This commit is contained in:
Jesper Wilhelmsson 2021-06-17 01:05:54 +00:00
commit 3637e50b30
33 changed files with 538 additions and 209 deletions

View file

@ -10,7 +10,7 @@ on:
platforms: platforms:
description: "Platform(s) to execute on" description: "Platform(s) to execute on"
required: true required: true
default: "Linux additional (hotspot only), Linux x64, Linux x86, Windows aarch64, Windows x64, macOS x64" default: "Linux additional (hotspot only), Linux x64, Linux x86, Windows x64, macOS x64"
jobs: jobs:
prerequisites: prerequisites:
@ -22,7 +22,6 @@ jobs:
platform_linux_additional: ${{ steps.check_platforms.outputs.platform_linux_additional }} platform_linux_additional: ${{ steps.check_platforms.outputs.platform_linux_additional }}
platform_linux_x64: ${{ steps.check_platforms.outputs.platform_linux_x64 }} platform_linux_x64: ${{ steps.check_platforms.outputs.platform_linux_x64 }}
platform_linux_x86: ${{ steps.check_platforms.outputs.platform_linux_x86 }} platform_linux_x86: ${{ steps.check_platforms.outputs.platform_linux_x86 }}
platform_windows_aarch64: ${{ steps.check_platforms.outputs.platform_windows_aarch64 }}
platform_windows_x64: ${{ steps.check_platforms.outputs.platform_windows_x64 }} platform_windows_x64: ${{ steps.check_platforms.outputs.platform_windows_x64 }}
platform_macos_x64: ${{ steps.check_platforms.outputs.platform_macos_x64 }} platform_macos_x64: ${{ steps.check_platforms.outputs.platform_macos_x64 }}
platform_macos_aarch64: ${{ steps.check_platforms.outputs.platform_macos_aarch64 }} platform_macos_aarch64: ${{ steps.check_platforms.outputs.platform_macos_aarch64 }}
@ -39,7 +38,6 @@ jobs:
echo "::set-output name=platform_linux_additional::${{ contains(github.event.inputs.platforms, 'linux additional (hotspot only)') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux additional (hotspot only)'))) }}" echo "::set-output name=platform_linux_additional::${{ contains(github.event.inputs.platforms, 'linux additional (hotspot only)') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux additional (hotspot only)'))) }}"
echo "::set-output name=platform_linux_x64::${{ contains(github.event.inputs.platforms, 'linux x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x64'))) }}" echo "::set-output name=platform_linux_x64::${{ contains(github.event.inputs.platforms, 'linux x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x64'))) }}"
echo "::set-output name=platform_linux_x86::${{ contains(github.event.inputs.platforms, 'linux x86') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x86'))) }}" echo "::set-output name=platform_linux_x86::${{ contains(github.event.inputs.platforms, 'linux x86') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'linux x86'))) }}"
echo "::set-output name=platform_windows_aarch64::${{ contains(github.event.inputs.platforms, 'windows aarch64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'windows aarch64'))) }}"
echo "::set-output name=platform_windows_x64::${{ contains(github.event.inputs.platforms, 'windows x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'windows x64'))) }}" echo "::set-output name=platform_windows_x64::${{ contains(github.event.inputs.platforms, 'windows x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'windows x64'))) }}"
echo "::set-output name=platform_macos_x64::${{ contains(github.event.inputs.platforms, 'macos x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos x64'))) }}" echo "::set-output name=platform_macos_x64::${{ contains(github.event.inputs.platforms, 'macos x64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos x64'))) }}"
echo "::set-output name=platform_macos_aarch64::${{ contains(github.event.inputs.platforms, 'macos aarch64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos aarch64'))) }}" echo "::set-output name=platform_macos_aarch64::${{ contains(github.event.inputs.platforms, 'macos aarch64') || (github.event.inputs.platforms == '' && (secrets.JDK_SUBMIT_PLATFORMS == '' || contains(secrets.JDK_SUBMIT_PLATFORMS, 'macos aarch64'))) }}"
@ -849,94 +847,6 @@ jobs:
path: ~/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip path: ~/linux-x86${{ matrix.artifact }}_testsupport_${{ env.logsuffix }}.zip
continue-on-error: true continue-on-error: true
windows_aarch64_build:
name: Windows aarch64
runs-on: "windows-2019"
needs: prerequisites
if: needs.prerequisites.outputs.should_run != 'false' && needs.prerequisites.outputs.platform_windows_aarch64 != 'false'
strategy:
fail-fast: false
matrix:
flavor:
- build debug
include:
- flavor: build debug
flags: --enable-debug
artifact: -debug
env:
JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).DEFAULT_VERSION_FEATURE }}"
BOOT_JDK_VERSION: "${{ fromJson(needs.prerequisites.outputs.dependencies).BOOT_JDK_VERSION }}"
BOOT_JDK_FILENAME: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_FILENAME }}"
BOOT_JDK_URL: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_URL }}"
BOOT_JDK_SHA256: "${{ fromJson(needs.prerequisites.outputs.dependencies).WINDOWS_X64_BOOT_JDK_SHA256 }}"
steps:
- name: Restore cygwin packages from cache
id: cygwin
uses: actions/cache@v2
with:
path: ~/cygwin/packages
key: cygwin-packages-${{ runner.os }}-v1
- name: Install cygwin
run: |
New-Item -Force -ItemType directory -Path "$HOME\cygwin"
& curl -L "https://www.cygwin.com/setup-x86_64.exe" -o "$HOME/cygwin/setup-x86_64.exe"
Start-Process -FilePath "$HOME\cygwin\setup-x86_64.exe" -ArgumentList "--quiet-mode --packages autoconf,make,zip,unzip --root $HOME\cygwin\cygwin64 --local-package-dir $HOME\cygwin\packages --site http://mirrors.kernel.org/sourceware/cygwin --no-desktop --no-shortcuts --no-startmenu --no-admin" -Wait -NoNewWindow
- name: Checkout the source
uses: actions/checkout@v2
with:
path: jdk
- name: Restore boot JDK from cache
id: bootjdk
uses: actions/cache@v2
with:
path: ~/bootjdk/${{ env.BOOT_JDK_VERSION }}
key: bootjdk-${{ runner.os }}-${{ env.BOOT_JDK_VERSION }}-${{ env.BOOT_JDK_SHA256 }}-v1
- name: Download boot JDK
run: |
mkdir -p "$HOME\bootjdk\$env:BOOT_JDK_VERSION"
& curl -L "$env:BOOT_JDK_URL" -o "$HOME/bootjdk/$env:BOOT_JDK_FILENAME"
$FileHash = Get-FileHash -Algorithm SHA256 "$HOME/bootjdk/$env:BOOT_JDK_FILENAME"
$FileHash.Hash -eq $env:BOOT_JDK_SHA256
& tar -xf "$HOME/bootjdk/$env:BOOT_JDK_FILENAME" -C "$HOME/bootjdk/$env:BOOT_JDK_VERSION"
Get-ChildItem "$HOME\bootjdk\$env:BOOT_JDK_VERSION\*\*" | Move-Item -Destination "$HOME\bootjdk\$env:BOOT_JDK_VERSION"
if: steps.bootjdk.outputs.cache-hit != 'true'
- name: Ensure a specific version of MSVC is installed
run: >
Start-Process -FilePath 'C:\Program Files (x86)\Microsoft Visual Studio\Installer\vs_installer.exe' -Wait -NoNewWindow -ArgumentList
'modify --installPath "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise" --quiet
--add Microsoft.VisualStudio.Component.VC.14.28.arm64'
- name: Configure
run: >
$env:Path = "$HOME\cygwin\cygwin64\bin;$HOME\cygwin\cygwin64\bin;$env:Path" ;
$env:Path = $env:Path -split ";" -match "C:\\Windows|PowerShell|cygwin" -join ";" ;
$env:BOOT_JDK = cygpath "$HOME/bootjdk/$env:BOOT_JDK_VERSION" ;
& bash configure
--with-conf-name=windows-aarch64
--with-msvc-toolset-version=14.28
--openjdk-target=aarch64-unknown-cygwin
${{ matrix.flags }}
--with-version-opt="$env:GITHUB_ACTOR-$env:GITHUB_SHA"
--with-version-build=0
--with-boot-jdk="$env:BOOT_JDK"
--with-default-make-target="hotspot"
working-directory: jdk
- name: Build
run: |
$env:Path = "$HOME\cygwin\cygwin64\bin;$HOME\cygwin\cygwin64\bin;$env:Path" ;
$env:Path = $env:Path -split ";" -match "C:\\Windows|PowerShell|cygwin" -join ";" ;
& make CONF_NAME=windows-aarch64
working-directory: jdk
windows_x64_build: windows_x64_build:
name: Windows x64 name: Windows x64
runs-on: "windows-2019" runs-on: "windows-2019"
@ -1661,7 +1571,6 @@ jobs:
needs: needs:
- prerequisites - prerequisites
- linux_additional_build - linux_additional_build
- windows_aarch64_build
- linux_x64_test - linux_x64_test
- linux_x86_test - linux_x86_test
- windows_x64_test - windows_x64_test

View file

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://###MODULE_DIR###/###MODULE_CONTENT###">
###SOURCE_DIRS###
</content>
<orderEntry type="sourceFolder" forTests="false" />
###DEPENDENCIES###
<orderEntry type="inheritedJdk" />
</component>
</module>

View file

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://###MODULE_DIR###/test/jdk"></content>
<orderEntry type="sourceFolder" forTests="true" />
###TEST_MODULE_DEPENDENCIES###
<orderEntry type="inheritedJdk" />
</component>
</module>

View file

@ -1406,7 +1406,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) {
} }
if (addr->Opcode() == Op_AddP) { if (addr->Opcode() == Op_AddP) {
Node* orig_base = addr->in(AddPNode::Base); Node* orig_base = addr->in(AddPNode::Base);
Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), true); Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), ConstraintCastNode::StrongDependency);
phase->register_new_node(base, ctrl); phase->register_new_node(base, ctrl);
if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) { if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) {
// Field access // Field access

View file

@ -39,7 +39,7 @@ Node* ConstraintCastNode::Identity(PhaseGVN* phase) {
if (dom != NULL) { if (dom != NULL) {
return dom; return dom;
} }
if (_carry_dependency) { if (_dependency != RegularDependency) {
return this; return this;
} }
return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this; return phase->type(in(1))->higher_equal_speculative(_type) ? in(1) : this;
@ -82,46 +82,46 @@ Node *ConstraintCastNode::Ideal(PhaseGVN *phase, bool can_reshape) {
} }
bool ConstraintCastNode::cmp(const Node &n) const { bool ConstraintCastNode::cmp(const Node &n) const {
return TypeNode::cmp(n) && ((ConstraintCastNode&)n)._carry_dependency == _carry_dependency; return TypeNode::cmp(n) && ((ConstraintCastNode&)n)._dependency == _dependency;
} }
uint ConstraintCastNode::size_of() const { uint ConstraintCastNode::size_of() const {
return sizeof(*this); return sizeof(*this);
} }
Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t, bool carry_dependency) { Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t, DependencyType dependency) {
switch(opcode) { switch(opcode) {
case Op_CastII: { case Op_CastII: {
Node* cast = new CastIINode(n, t, carry_dependency); Node* cast = new CastIINode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastLL: { case Op_CastLL: {
Node* cast = new CastLLNode(n, t, carry_dependency); Node* cast = new CastLLNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastPP: { case Op_CastPP: {
Node* cast = new CastPPNode(n, t, carry_dependency); Node* cast = new CastPPNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastFF: { case Op_CastFF: {
Node* cast = new CastFFNode(n, t, carry_dependency); Node* cast = new CastFFNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastDD: { case Op_CastDD: {
Node* cast = new CastDDNode(n, t, carry_dependency); Node* cast = new CastDDNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CastVV: { case Op_CastVV: {
Node* cast = new CastVVNode(n, t, carry_dependency); Node* cast = new CastVVNode(n, t, dependency);
cast->set_req(0, c); cast->set_req(0, c);
return cast; return cast;
} }
case Op_CheckCastPP: return new CheckCastPPNode(c, n, t, carry_dependency); case Op_CheckCastPP: return new CheckCastPPNode(c, n, t, dependency);
default: default:
fatal("Bad opcode %d", opcode); fatal("Bad opcode %d", opcode);
} }
@ -131,10 +131,10 @@ Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t,
Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) { Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) {
switch(bt) { switch(bt) {
case T_INT: { case T_INT: {
return make_cast(Op_CastII, c, n, t, false); return make_cast(Op_CastII, c, n, t, RegularDependency);
} }
case T_LONG: { case T_LONG: {
return make_cast(Op_CastLL, c, n, t, false); return make_cast(Op_CastLL, c, n, t, RegularDependency);
} }
default: default:
fatal("Bad basic type %s", type2name(bt)); fatal("Bad basic type %s", type2name(bt));
@ -143,6 +143,9 @@ Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) {
} }
TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const { TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const {
if (_dependency == UnconditionalDependency) {
return NULL;
}
Node* val = in(1); Node* val = in(1);
Node* ctl = in(0); Node* ctl = in(0);
int opc = Opcode(); int opc = Opcode();
@ -183,8 +186,8 @@ TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt)
#ifndef PRODUCT #ifndef PRODUCT
void ConstraintCastNode::dump_spec(outputStream *st) const { void ConstraintCastNode::dump_spec(outputStream *st) const {
TypeNode::dump_spec(st); TypeNode::dump_spec(st);
if (_carry_dependency) { if (_dependency != RegularDependency) {
st->print(" carry dependency"); st->print(" %s dependency", _dependency == StrongDependency ? "strong" : "unconditional");
} }
} }
#endif #endif
@ -194,7 +197,7 @@ const Type* CastIINode::Value(PhaseGVN* phase) const {
// Try to improve the type of the CastII if we recognize a CmpI/If // Try to improve the type of the CastII if we recognize a CmpI/If
// pattern. // pattern.
if (_carry_dependency) { if (_dependency != RegularDependency) {
if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) { if (in(0) != NULL && in(0)->in(0) != NULL && in(0)->in(0)->is_If()) {
assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj"); assert(in(0)->is_IfFalse() || in(0)->is_IfTrue(), "should be If proj");
Node* proj = in(0); Node* proj = in(0);
@ -255,8 +258,8 @@ const Type* CastIINode::Value(PhaseGVN* phase) const {
return res; return res;
} }
static Node* find_or_make_CastII(PhaseIterGVN* igvn, Node* parent, Node* control, const TypeInt* type, bool carry_dependency) { static Node* find_or_make_CastII(PhaseIterGVN* igvn, Node* parent, Node* control, const TypeInt* type, ConstraintCastNode::DependencyType dependency) {
Node* n = new CastIINode(parent, type, carry_dependency); Node* n = new CastIINode(parent, type, dependency);
n->set_req(0, control); n->set_req(0, control);
Node* existing = igvn->hash_find_insert(n); Node* existing = igvn->hash_find_insert(n);
if (existing != NULL) { if (existing != NULL) {
@ -289,8 +292,8 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* x = z->in(1); Node* x = z->in(1);
Node* y = z->in(2); Node* y = z->in(2);
Node* cx = find_or_make_CastII(igvn, x, in(0), rx->is_int(), _carry_dependency); Node* cx = find_or_make_CastII(igvn, x, in(0), rx->is_int(), _dependency);
Node* cy = find_or_make_CastII(igvn, y, in(0), ry->is_int(), _carry_dependency); Node* cy = find_or_make_CastII(igvn, y, in(0), ry->is_int(), _dependency);
switch (op) { switch (op) {
case Op_AddI: return new AddINode(cx, cy); case Op_AddI: return new AddINode(cx, cy);
case Op_SubI: return new SubINode(cx, cy); case Op_SubI: return new SubINode(cx, cy);
@ -377,7 +380,7 @@ Node* CheckCastPPNode::Identity(PhaseGVN* phase) {
if (dom != NULL) { if (dom != NULL) {
return dom; return dom;
} }
if (_carry_dependency) { if (_dependency != RegularDependency) {
return this; return this;
} }
const Type* t = phase->type(in(1)); const Type* t = phase->type(in(1));
@ -573,20 +576,20 @@ Node* CastP2XNode::Identity(PhaseGVN* phase) {
return this; return this;
} }
Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type) { Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency) {
Node* cast= NULL; Node* cast= NULL;
if (type->isa_int()) { if (type->isa_int()) {
cast = make_cast(Op_CastII, c, in, type, true); cast = make_cast(Op_CastII, c, in, type, dependency);
} else if (type->isa_long()) { } else if (type->isa_long()) {
cast = make_cast(Op_CastLL, c, in, type, true); cast = make_cast(Op_CastLL, c, in, type, dependency);
} else if (type->isa_float()) { } else if (type->isa_float()) {
cast = make_cast(Op_CastFF, c, in, type, true); cast = make_cast(Op_CastFF, c, in, type, dependency);
} else if (type->isa_double()) { } else if (type->isa_double()) {
cast = make_cast(Op_CastDD, c, in, type, true); cast = make_cast(Op_CastDD, c, in, type, dependency);
} else if (type->isa_vect()) { } else if (type->isa_vect()) {
cast = make_cast(Op_CastVV, c, in, type, true); cast = make_cast(Op_CastVV, c, in, type, dependency);
} else if (type->isa_ptr()) { } else if (type->isa_ptr()) {
cast = make_cast(Op_CastPP, c, in, type, true); cast = make_cast(Op_CastPP, c, in, type, dependency);
} }
return cast; return cast;
} }

View file

@ -32,15 +32,21 @@
//------------------------------ConstraintCastNode----------------------------- //------------------------------ConstraintCastNode-----------------------------
// cast to a different range // cast to a different range
class ConstraintCastNode: public TypeNode { class ConstraintCastNode: public TypeNode {
public:
enum DependencyType {
RegularDependency, // if cast doesn't improve input type, cast can be removed
StrongDependency, // leave cast in even if _type doesn't improve input type, can be replaced by stricter dominating cast if one exist
UnconditionalDependency // leave cast in unconditionally
};
protected: protected:
// Can this node be removed post CCP or does it carry a required dependency? const DependencyType _dependency;
const bool _carry_dependency;
virtual bool cmp( const Node &n ) const; virtual bool cmp( const Node &n ) const;
virtual uint size_of() const; virtual uint size_of() const;
public: public:
ConstraintCastNode(Node *n, const Type *t, bool carry_dependency) ConstraintCastNode(Node *n, const Type *t, DependencyType dependency)
: TypeNode(t,2), _carry_dependency(carry_dependency) { : TypeNode(t,2), _dependency(dependency) {
init_class_id(Class_ConstraintCast); init_class_id(Class_ConstraintCast);
init_req(1, n); init_req(1, n);
} }
@ -49,10 +55,10 @@ class ConstraintCastNode: public TypeNode {
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual int Opcode() const; virtual int Opcode() const;
virtual uint ideal_reg() const = 0; virtual uint ideal_reg() const = 0;
virtual bool depends_only_on_test() const { return !_carry_dependency; } virtual bool depends_only_on_test() const { return _dependency == RegularDependency; }
bool carry_dependency() const { return _carry_dependency; } bool carry_dependency() const { return _dependency != RegularDependency; }
TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const; TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const;
static Node* make_cast(int opcode, Node* c, Node *n, const Type *t, bool carry_dependency); static Node* make_cast(int opcode, Node* c, Node *n, const Type *t, DependencyType dependency);
static Node* make(Node* c, Node *n, const Type *t, BasicType bt); static Node* make(Node* c, Node *n, const Type *t, BasicType bt);
virtual bool operates_on(BasicType bt, bool signed_int) const { virtual bool operates_on(BasicType bt, bool signed_int) const {
assert(bt == T_INT || bt == T_LONG, "unsupported"); assert(bt == T_INT || bt == T_LONG, "unsupported");
@ -63,7 +69,7 @@ class ConstraintCastNode: public TypeNode {
virtual void dump_spec(outputStream *st) const; virtual void dump_spec(outputStream *st) const;
#endif #endif
static Node* make_cast_for_type(Node* c, Node* in, const Type* type); static Node* make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency);
}; };
//------------------------------CastIINode------------------------------------- //------------------------------CastIINode-------------------------------------
@ -76,12 +82,12 @@ class CastIINode: public ConstraintCastNode {
virtual uint size_of() const; virtual uint size_of() const;
public: public:
CastIINode(Node* n, const Type* t, bool carry_dependency = false, bool range_check_dependency = false) CastIINode(Node* n, const Type* t, DependencyType dependency = RegularDependency, bool range_check_dependency = false)
: ConstraintCastNode(n, t, carry_dependency), _range_check_dependency(range_check_dependency) { : ConstraintCastNode(n, t, dependency), _range_check_dependency(range_check_dependency) {
init_class_id(Class_CastII); init_class_id(Class_CastII);
} }
CastIINode(Node* ctrl, Node* n, const Type* t, bool carry_dependency = false, bool range_check_dependency = false) CastIINode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, bool range_check_dependency = false)
: ConstraintCastNode(n, t, carry_dependency), _range_check_dependency(range_check_dependency) { : ConstraintCastNode(n, t, dependency), _range_check_dependency(range_check_dependency) {
init_class_id(Class_CastII); init_class_id(Class_CastII);
init_req(0, ctrl); init_req(0, ctrl);
} }
@ -110,13 +116,13 @@ class CastIINode: public ConstraintCastNode {
class CastLLNode: public ConstraintCastNode { class CastLLNode: public ConstraintCastNode {
public: public:
CastLLNode(Node* ctrl, Node* n, const Type* t, bool carry_dependency = false) CastLLNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency) { : ConstraintCastNode(n, t, dependency) {
init_class_id(Class_CastLL); init_class_id(Class_CastLL);
init_req(0, ctrl); init_req(0, ctrl);
} }
CastLLNode(Node* n, const Type* t, bool carry_dependency = false) CastLLNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastLL); init_class_id(Class_CastLL);
} }
virtual bool operates_on(BasicType bt, bool signed_int) const { virtual bool operates_on(BasicType bt, bool signed_int) const {
@ -129,8 +135,8 @@ public:
class CastFFNode: public ConstraintCastNode { class CastFFNode: public ConstraintCastNode {
public: public:
CastFFNode(Node* n, const Type* t, bool carry_dependency = false) CastFFNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastFF); init_class_id(Class_CastFF);
} }
virtual int Opcode() const; virtual int Opcode() const;
@ -139,8 +145,8 @@ public:
class CastDDNode: public ConstraintCastNode { class CastDDNode: public ConstraintCastNode {
public: public:
CastDDNode(Node* n, const Type* t, bool carry_dependency = false) CastDDNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastDD); init_class_id(Class_CastDD);
} }
virtual int Opcode() const; virtual int Opcode() const;
@ -149,8 +155,8 @@ public:
class CastVVNode: public ConstraintCastNode { class CastVVNode: public ConstraintCastNode {
public: public:
CastVVNode(Node* n, const Type* t, bool carry_dependency = false) CastVVNode(Node* n, const Type* t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency){ : ConstraintCastNode(n, t, dependency){
init_class_id(Class_CastVV); init_class_id(Class_CastVV);
} }
virtual int Opcode() const; virtual int Opcode() const;
@ -162,8 +168,8 @@ public:
// cast pointer to pointer (different type) // cast pointer to pointer (different type)
class CastPPNode: public ConstraintCastNode { class CastPPNode: public ConstraintCastNode {
public: public:
CastPPNode (Node *n, const Type *t, bool carry_dependency = false) CastPPNode (Node *n, const Type *t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency) { : ConstraintCastNode(n, t, dependency) {
} }
virtual int Opcode() const; virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegP; } virtual uint ideal_reg() const { return Op_RegP; }
@ -173,8 +179,8 @@ class CastPPNode: public ConstraintCastNode {
// for _checkcast, cast pointer to pointer (different type), without JOIN, // for _checkcast, cast pointer to pointer (different type), without JOIN,
class CheckCastPPNode: public ConstraintCastNode { class CheckCastPPNode: public ConstraintCastNode {
public: public:
CheckCastPPNode(Node *c, Node *n, const Type *t, bool carry_dependency = false) CheckCastPPNode(Node *c, Node *n, const Type *t, DependencyType dependency = RegularDependency)
: ConstraintCastNode(n, t, carry_dependency) { : ConstraintCastNode(n, t, dependency) {
init_class_id(Class_CheckCastPP); init_class_id(Class_CheckCastPP);
init_req(0, c); init_req(0, c);
} }

View file

@ -1975,7 +1975,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
if (phi_type->isa_ptr()) { if (phi_type->isa_ptr()) {
const Type* uin_type = phase->type(uin); const Type* uin_type = phase->type(uin);
if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) { if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) {
cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, true); cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, ConstraintCastNode::StrongDependency);
} else { } else {
// Use a CastPP for a cast to not null and a CheckCastPP for // Use a CastPP for a cast to not null and a CheckCastPP for
// a cast to a new klass (and both if both null-ness and // a cast to a new klass (and both if both null-ness and
@ -1985,7 +1985,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// null, uin's type must be casted to not null // null, uin's type must be casted to not null
if (phi_type->join(TypePtr::NOTNULL) == phi_type->remove_speculative() && if (phi_type->join(TypePtr::NOTNULL) == phi_type->remove_speculative() &&
uin_type->join(TypePtr::NOTNULL) != uin_type->remove_speculative()) { uin_type->join(TypePtr::NOTNULL) != uin_type->remove_speculative()) {
cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, TypePtr::NOTNULL, true); cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, TypePtr::NOTNULL, ConstraintCastNode::StrongDependency);
} }
// If the type of phi and uin, both casted to not null, // If the type of phi and uin, both casted to not null,
@ -1997,14 +1997,14 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
cast = phase->transform(cast); cast = phase->transform(cast);
n = cast; n = cast;
} }
cast = ConstraintCastNode::make_cast(Op_CheckCastPP, r, n, phi_type, true); cast = ConstraintCastNode::make_cast(Op_CheckCastPP, r, n, phi_type, ConstraintCastNode::StrongDependency);
} }
if (cast == NULL) { if (cast == NULL) {
cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, true); cast = ConstraintCastNode::make_cast(Op_CastPP, r, uin, phi_type, ConstraintCastNode::StrongDependency);
} }
} }
} else { } else {
cast = ConstraintCastNode::make_cast_for_type(r, uin, phi_type); cast = ConstraintCastNode::make_cast_for_type(r, uin, phi_type, ConstraintCastNode::StrongDependency);
} }
assert(cast != NULL, "cast should be set"); assert(cast != NULL, "cast should be set");
cast = phase->transform(cast); cast = phase->transform(cast);

View file

@ -4135,7 +4135,7 @@ Node* Compile::conv_I2X_index(PhaseGVN* phase, Node* idx, const TypeInt* sizetyp
Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl, bool carry_dependency) { Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* itype, Node* ctrl, bool carry_dependency) {
if (ctrl != NULL) { if (ctrl != NULL) {
// Express control dependency by a CastII node with a narrow type. // Express control dependency by a CastII node with a narrow type.
value = new CastIINode(value, itype, carry_dependency, true /* range check dependency */); value = new CastIINode(value, itype, carry_dependency ? ConstraintCastNode::StrongDependency : ConstraintCastNode::RegularDependency, true /* range check dependency */);
// Make the CastII node dependent on the control input to prevent the narrowed ConvI2L // Make the CastII node dependent on the control input to prevent the narrowed ConvI2L
// node from floating above the range check during loop optimizations. Otherwise, the // node from floating above the range check during loop optimizations. Otherwise, the
// ConvI2L node may be eliminated independently of the range check, causing the data path // ConvI2L node may be eliminated independently of the range check, causing the data path

View file

@ -1193,7 +1193,7 @@ Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctr
} }
Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) { Node* PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, Node* loop) {
Node* castii = new CastIINode(incr, TypeInt::INT, true); Node* castii = new CastIINode(incr, TypeInt::INT, ConstraintCastNode::StrongDependency);
castii->set_req(0, ctrl); castii->set_req(0, ctrl);
register_new_node(castii, ctrl); register_new_node(castii, ctrl);
for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) { for (DUIterator_Fast imax, i = incr->fast_outs(imax); i < imax; i++) {

View file

@ -1503,7 +1503,15 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
assert(!n_loop->is_member(get_loop(x_ctrl)), "should have moved out of loop"); assert(!n_loop->is_member(get_loop(x_ctrl)), "should have moved out of loop");
register_new_node(x, x_ctrl); register_new_node(x, x_ctrl);
if (x->in(0) == NULL && !x->is_DecodeNarrowPtr()) { // Chain of AddP: (AddP base (AddP base )) must keep the same base after sinking so:
// 1- We don't add a CastPP here when the first one is sunk so if the second one is not, their bases remain
// the same.
// (see 2- below)
assert(!x->is_AddP() || !x->in(AddPNode::Address)->is_AddP() ||
x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base) ||
!x->in(AddPNode::Address)->in(AddPNode::Base)->eqv_uncast(x->in(AddPNode::Base)), "unexpected AddP shape");
if (x->in(0) == NULL && !x->is_DecodeNarrowPtr() &&
!(x->is_AddP() && x->in(AddPNode::Address)->is_AddP() && x->in(AddPNode::Address)->in(AddPNode::Base) == x->in(AddPNode::Base))) {
assert(!x->is_Load(), "load should be pinned"); assert(!x->is_Load(), "load should be pinned");
// Use a cast node to pin clone out of loop // Use a cast node to pin clone out of loop
Node* cast = NULL; Node* cast = NULL;
@ -1511,11 +1519,22 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) {
Node* in = x->in(k); Node* in = x->in(k);
if (in != NULL && n_loop->is_member(get_loop(get_ctrl(in)))) { if (in != NULL && n_loop->is_member(get_loop(get_ctrl(in)))) {
const Type* in_t = _igvn.type(in); const Type* in_t = _igvn.type(in);
cast = ConstraintCastNode::make_cast_for_type(x_ctrl, in, in_t); cast = ConstraintCastNode::make_cast_for_type(x_ctrl, in, in_t, ConstraintCastNode::UnconditionalDependency);
} }
if (cast != NULL) { if (cast != NULL) {
register_new_node(cast, x_ctrl); register_new_node(cast, x_ctrl);
x->replace_edge(in, cast); x->replace_edge(in, cast);
// Chain of AddP:
// 2- A CastPP of the base is only added now that both AddP nodes are sunk
if (x->is_AddP() && k == AddPNode::Base) {
for (DUIterator_Fast imax, i = x->fast_outs(imax); i < imax; i++) {
Node* u = x->fast_out(i);
if (u->is_AddP() && u->in(AddPNode::Base) == n->in(AddPNode::Base)) {
_igvn.replace_input_of(u, AddPNode::Base, cast);
assert(u->find_out_with(Op_AddP) == NULL, "more than 2 chained AddP nodes?");
}
}
}
break; break;
} }
} }
@ -2800,6 +2819,12 @@ int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, No
worklist.push(use); worklist.push(use);
} }
} }
if (C->check_node_count(worklist.size() + NodeLimitFudgeFactor,
"Too many clones required in clone_for_use_outside_loop in partial peeling")) {
return -1;
}
while( worklist.size() ) { while( worklist.size() ) {
Node *use = worklist.pop(); Node *use = worklist.pop();
if (!has_node(use) || use->in(0) == C->top()) continue; if (!has_node(use) || use->in(0) == C->top()) continue;
@ -3352,6 +3377,7 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
#endif #endif
// Evacuate nodes in peel region into the not_peeled region if possible // Evacuate nodes in peel region into the not_peeled region if possible
bool too_many_clones = false;
uint new_phi_cnt = 0; uint new_phi_cnt = 0;
uint cloned_for_outside_use = 0; uint cloned_for_outside_use = 0;
for (uint i = 0; i < peel_list.size();) { for (uint i = 0; i < peel_list.size();) {
@ -3368,7 +3394,12 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
// if not pinned and not a load (which maybe anti-dependent on a store) // if not pinned and not a load (which maybe anti-dependent on a store)
// and not a CMove (Matcher expects only bool->cmove). // and not a CMove (Matcher expects only bool->cmove).
if (n->in(0) == NULL && !n->is_Load() && !n->is_CMove()) { if (n->in(0) == NULL && !n->is_Load() && !n->is_CMove()) {
cloned_for_outside_use += clone_for_use_outside_loop(loop, n, worklist); int new_clones = clone_for_use_outside_loop(loop, n, worklist);
if (new_clones == -1) {
too_many_clones = true;
break;
}
cloned_for_outside_use += new_clones;
sink_list.push(n); sink_list.push(n);
peel.remove(n->_idx); peel.remove(n->_idx);
not_peel.set(n->_idx); not_peel.set(n->_idx);
@ -3396,9 +3427,9 @@ bool PhaseIdealLoop::partial_peel( IdealLoopTree *loop, Node_List &old_new ) {
bool exceed_node_budget = !may_require_nodes(estimate); bool exceed_node_budget = !may_require_nodes(estimate);
bool exceed_phi_limit = new_phi_cnt > old_phi_cnt + PartialPeelNewPhiDelta; bool exceed_phi_limit = new_phi_cnt > old_phi_cnt + PartialPeelNewPhiDelta;
if (exceed_node_budget || exceed_phi_limit) { if (too_many_clones || exceed_node_budget || exceed_phi_limit) {
#ifndef PRODUCT #ifndef PRODUCT
if (TracePartialPeeling) { if (TracePartialPeeling && exceed_phi_limit) {
tty->print_cr("\nToo many new phis: %d old %d new cmpi: %c", tty->print_cr("\nToo many new phis: %d old %d new cmpi: %c",
new_phi_cnt, old_phi_cnt, new_peel_if != NULL?'T':'F'); new_phi_cnt, old_phi_cnt, new_peel_if != NULL?'T':'F');
} }

View file

@ -794,13 +794,69 @@ list.
.TP .TP
.B \f[CB]\-Xcheck:jni\f[R] .B \f[CB]\-Xcheck:jni\f[R]
Performs additional checks for Java Native Interface (JNI) functions. Performs additional checks for Java Native Interface (JNI) functions.
Specifically, it validates the parameters passed to the JNI function and
the runtime environment data before processing the JNI request.
It also checks for pending exceptions between JNI calls.
Any invalid data encountered indicates a problem in the native code, and
the JVM terminates with an irrecoverable error in such cases.
Expect a performance degradation when this option is used.
.RS .RS
.PP
The following checks are considered indicative of significant problems
with the native code, and the JVM terminates with an irrecoverable error
in such cases:
.IP \[bu] 2
The thread doing the call is not attached to the JVM.
.IP \[bu] 2
The thread doing the call is using the \f[CB]JNIEnv\f[R] belonging to
another thread.
.IP \[bu] 2
A parameter validation check fails:
.RS 2
.IP \[bu] 2
A \f[CB]jfieldID\f[R], or \f[CB]jmethodID\f[R], is detected as being
invalid.
For example:
.RS 2
.IP \[bu] 2
Of the wrong type
.IP \[bu] 2
Associated with the wrong class
.RE
.IP \[bu] 2
A parameter of the wrong type is detected.
.IP \[bu] 2
An invalid parameter value is detected.
For example:
.RS 2
.IP \[bu] 2
NULL where not permitted
.IP \[bu] 2
An out\-of\-bounds array index, or frame capacity
.IP \[bu] 2
A non\-UTF\-8 string
.IP \[bu] 2
An invalid JNI reference
.IP \[bu] 2
An attempt to use a \f[CB]ReleaseXXX\f[R] function on a parameter not
produced by the corresponding \f[CB]GetXXX\f[R] function
.RE
.RE
.PP
The following checks only result in warnings being printed:
.IP \[bu] 2
A JNI call was made without checking for a pending exception from a
previous JNI call, and the current call is not safe when an exception
may be pending.
.IP \[bu] 2
The number of JNI local references existing when a JNI function
terminates exceeds the number guaranteed to be available.
See the \f[CB]EnsureLocalcapacity\f[R] function.
.IP \[bu] 2
A class descriptor is in decorated format (\f[CB]Lname;\f[R]) when it
should not be.
.IP \[bu] 2
A \f[CB]NULL\f[R] parameter is allowed, but its use is questionable.
.IP \[bu] 2
Calling other JNI functions in the scope of
\f[CB]Get/ReleasePrimitiveArrayCritical\f[R] or
\f[CB]Get/ReleaseStringCritical\f[R]
.PP
Expect a performance degradation when this option is used.
.RE .RE
.TP .TP
.B \f[CB]\-Xdebug\f[R] .B \f[CB]\-Xdebug\f[R]

View file

@ -560,7 +560,8 @@ public class Start {
// We're done. // We're done.
if (options.verbose()) { if (options.verbose()) {
long elapsedMillis = (System.nanoTime() - startNanos) / 1_000_000; long elapsedMillis = (System.nanoTime() - startNanos) / 1_000_000;
log.noticeUsingKey("main.done_in", Long.toString(elapsedMillis)); JavadocLog.printRawLines(log.getDiagnosticWriter(),
log.getText("main.done_in", Long.toString(elapsedMillis)));
} }
return returnStatus; return returnStatus;

View file

@ -199,7 +199,7 @@ public class ToolEnvironment {
if (quiet) { if (quiet) {
return; return;
} }
log.noticeUsingKey(key); JavadocLog.printRawLines(log.getDiagnosticWriter(), log.getText(key));
} }
/** /**
@ -212,7 +212,7 @@ public class ToolEnvironment {
if (quiet) { if (quiet) {
return; return;
} }
log.noticeUsingKey(key, a1); JavadocLog.printRawLines(log.getDiagnosticWriter(), log.getText(key, a1));
} }
TreePath getTreePath(JCCompilationUnit tree) { TreePath getTreePath(JCCompilationUnit tree) {

View file

@ -39,4 +39,8 @@ serviceability/sa/ClhsdbFindPC.java#id3 8268722 macosx-x
serviceability/sa/ClhsdbPmap.java#id1 8268722 macosx-x64 serviceability/sa/ClhsdbPmap.java#id1 8268722 macosx-x64
serviceability/sa/ClhsdbPstack.java#id1 8268722 macosx-x64 serviceability/sa/ClhsdbPstack.java#id1 8268722 macosx-x64
serviceability/sa/TestJmapCore.java 8268722,8268283 macosx-x64,linux-aarch64 serviceability/sa/TestJmapCore.java 8268722,8268283 macosx-x64,linux-aarch64
serviceability/sa/TestJmapCoreMetaspace.java 8268722 macosx-x64 serviceability/sa/TestJmapCoreMetaspace.java 8268722,8268636 macosx-x64,linux-x64
serviceability/dcmd/framework/HelpTest.java 8268433 windows-x64
serviceability/dcmd/framework/InvalidCommandTest.java 8268433 windows-x64
serviceability/dcmd/framework/VMVersionTest.java 8268433 windows-x64

View file

@ -0,0 +1,57 @@
/*
* Copyright (c) 2021, Red Hat, Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8267988
* @summary C2: assert(!addp->is_AddP() || addp->in(AddPNode::Base)->is_top() || addp->in(AddPNode::Base) == n->in(AddPNode::Base)) failed: Base pointers must match (addp 1301)
*
* @run main/othervm -Xcomp -XX:CompileOnly=TestAddPChainWithDifferentBase TestAddPChainWithDifferentBase
*
*/
public class TestAddPChainWithDifferentBase {
static int x;
static int iArrFld[] = new int[400];
public static void main(String[] strArr) {
test();
}
static void test() {
int i6, i7 = 9, i8, i9 = 138;
for (i6 = 7; i6 > 1; i6 -= 3) {
for (i8 = i6; i8 < 4; i8++) {
try {
iArrFld[i8] = (52691 / i8);
i7 = (iArrFld[i8 + 1] % i9);
i7 = (412419036 / iArrFld[i8]);
} catch (ArithmeticException a_e) {
}
i9 += 13;
}
}
x = i7;
}
}

View file

@ -0,0 +1,73 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @bug 8256934
* @summary Sinking of nodes in partial peeling creates too many clones resulting in a live node limit exceeded assertion failure.
* @requires vm.compiler2.enabled
* @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileCommand=compileonly,compiler.loopopts.TestPartialPeelingSinkNodes::test
* compiler.loopopts.TestPartialPeelingSinkNodes
*/
package compiler.loopopts;
public class TestPartialPeelingSinkNodes {
static int i5 = 168, iFld = 2, x, y;
static boolean b = false, b2 = false;
public static void main(String[] strArr) {
test();
}
// The algorithm in partial peeling creates ~90000 nodes for this method which triggers the assertion failure.
public static void test() {
for (int i = 0; i < 2480; i++) {
int i2 = -37052, i3 = 39651, i4 = -37052;
int i5 = 168, i6 = -133, i7 = 1, i8 = -10;
double d = -20.82293;
float fArr[] = new float[400];
for (int j = 0; j < 400; j++) {
fArr[j] = (j % 2 == 0) ? 0.300F + j : 0.300F - j;
}
while (--i5 > 0) {
i6 = 1;
do {
i4 += (((i6 * i2) + i3) - i3);
i2 += i4;
} while (++i6 < 9);
i3 -= i4;
for (i7 = 1; i7 < 18; i7++) {
i4 = i5;
d -= i4;
i2 -= i8;
i2 = i8;
}
}
}
}
}

View file

@ -122,11 +122,12 @@ public class TestNewRatioFlag {
public static void verifyDefNewNewRatio(int expectedRatio) { public static void verifyDefNewNewRatio(int expectedRatio) {
long initEden = HeapRegionUsageTool.getEdenUsage().getInit(); long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit(); long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
long initOld = HeapRegionUsageTool.getOldUsage().getInit(); long initHeap = HeapRegionUsageTool.getHeapUsage().getInit();
long newSize = initEden + 2 * initSurv; long newSize = initEden + 2 * initSurv;
long expectedNewSize = HeapRegionUsageTool.alignDown(initOld / expectedRatio, // See GenArguments::scale_by_NewRatio_aligned for calculation in the JVM.
long expectedNewSize = HeapRegionUsageTool.alignDown(initHeap / (expectedRatio + 1),
wb.getHeapSpaceAlignment()); wb.getHeapSpaceAlignment());
if (expectedNewSize != newSize) { if (expectedNewSize != newSize) {
@ -143,11 +144,12 @@ public class TestNewRatioFlag {
public static void verifyPSNewRatio(int expectedRatio) { public static void verifyPSNewRatio(int expectedRatio) {
long initEden = HeapRegionUsageTool.getEdenUsage().getInit(); long initEden = HeapRegionUsageTool.getEdenUsage().getInit();
long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit(); long initSurv = HeapRegionUsageTool.getSurvivorUsage().getInit();
long initOld = HeapRegionUsageTool.getOldUsage().getInit(); long initHeap = HeapRegionUsageTool.getHeapUsage().getInit();
long newSize = initEden + 2 * initSurv; long newSize = initEden + 2 * initSurv;
long alignedDownNewSize = HeapRegionUsageTool.alignDown(initOld / expectedRatio, // See GenArguments::scale_by_NewRatio_aligned for calculation in the JVM.
long alignedDownNewSize = HeapRegionUsageTool.alignDown(initHeap / (expectedRatio + 1),
wb.getHeapSpaceAlignment()); wb.getHeapSpaceAlignment());
long expectedNewSize = HeapRegionUsageTool.alignUp(alignedDownNewSize, long expectedNewSize = HeapRegionUsageTool.alignUp(alignedDownNewSize,
wb.psVirtualSpaceAlignment()); wb.psVirtualSpaceAlignment());

View file

@ -822,6 +822,8 @@ jdk/jfr/event/compiler/TestCodeSweeper.java 8225209 gener
jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all jdk/jfr/event/os/TestThreadContextSwitches.java 8247776 windows-all
jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64
jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64
jdk/jfr/event/gc/detailed/TestEvacuationFailedEvent.java 8263461 linux-x64
jdk/jfr/api/consumer/streaming/TestLatestEvent.java 8268297 windows-x64
############################################################################ ############################################################################

View file

@ -278,6 +278,7 @@ public class ISO_8859_1_Test implements HttpServerAdapters {
@Test(dataProvider = "variants") @Test(dataProvider = "variants")
public void test(String uri, boolean sameClient) throws Exception { public void test(String uri, boolean sameClient) throws Exception {
checkSkip();
System.out.println("Request to " + uri); System.out.println("Request to " + uri);
HttpClient client = newHttpClient(sameClient); HttpClient client = newHttpClient(sameClient);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -150,7 +150,7 @@ public class DummyWebSocketServer implements Closeable {
err.println("Error in connection: " + channel + ", " + e); err.println("Error in connection: " + channel + ", " + e);
} finally { } finally {
err.println("Closed: " + channel); err.println("Closed: " + channel);
close(channel); closeChannel(channel);
readReady.countDown(); readReady.countDown();
} }
} }
@ -184,6 +184,10 @@ public class DummyWebSocketServer implements Closeable {
} }
} }
protected void closeChannel(SocketChannel channel) {
close(channel);
}
protected void write(SocketChannel ch) throws IOException { } protected void write(SocketChannel ch) throws IOException { }
protected final void serve(SocketChannel channel) protected final void serve(SocketChannel channel)

View file

@ -25,6 +25,7 @@
* @test * @test
* @build DummyWebSocketServer * @build DummyWebSocketServer
* @run testng/othervm * @run testng/othervm
* -Djdk.httpclient.sendBufferSize=8192
* -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.debug=true
* -Djdk.internal.httpclient.websocket.debug=true * -Djdk.internal.httpclient.websocket.debug=true
* PendingBinaryPingClose * PendingBinaryPingClose
@ -48,6 +49,7 @@ public class PendingBinaryPingClose extends PendingOperations {
public void pendingBinaryPingClose(boolean last) throws Exception { public void pendingBinaryPingClose(boolean last) throws Exception {
repeatable(() -> { repeatable(() -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -25,6 +25,7 @@
* @test * @test
* @build DummyWebSocketServer * @build DummyWebSocketServer
* @run testng/othervm * @run testng/othervm
* -Djdk.httpclient.sendBufferSize=8192
* -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.debug=true
* -Djdk.internal.httpclient.websocket.debug=true * -Djdk.internal.httpclient.websocket.debug=true
* PendingBinaryPongClose * PendingBinaryPongClose
@ -50,6 +51,7 @@ public class PendingBinaryPongClose extends PendingOperations {
public void pendingBinaryPongClose(boolean last) throws Exception { public void pendingBinaryPongClose(boolean last) throws Exception {
repeatable(() -> { repeatable(() -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -25,6 +25,7 @@
* @test * @test
* @build DummyWebSocketServer * @build DummyWebSocketServer
* @run testng/othervm * @run testng/othervm
* -Djdk.httpclient.sendBufferSize=8192
* PendingPingBinaryClose * PendingPingBinaryClose
*/ */
@ -50,6 +51,7 @@ public class PendingPingBinaryClose extends PendingOperations {
public void pendingPingBinaryClose(boolean last) throws Exception { public void pendingPingBinaryClose(boolean last) throws Exception {
repeatable( () -> { repeatable( () -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -25,6 +25,7 @@
* @test * @test
* @build DummyWebSocketServer * @build DummyWebSocketServer
* @run testng/othervm * @run testng/othervm
* -Djdk.httpclient.sendBufferSize=8192
* PendingPingTextClose * PendingPingTextClose
*/ */
@ -52,6 +53,7 @@ public class PendingPingTextClose extends PendingOperations {
try { try {
repeatable(() -> { repeatable(() -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -25,6 +25,7 @@
* @test * @test
* @build DummyWebSocketServer * @build DummyWebSocketServer
* @run testng/othervm * @run testng/othervm
* -Djdk.httpclient.sendBufferSize=8192
* PendingPongBinaryClose * PendingPongBinaryClose
*/ */
@ -50,6 +51,7 @@ public class PendingPongBinaryClose extends PendingOperations {
public void pendingPongBinaryClose(boolean last) throws Exception { public void pendingPongBinaryClose(boolean last) throws Exception {
repeatable( () -> { repeatable( () -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -25,6 +25,7 @@
* @test * @test
* @build DummyWebSocketServer * @build DummyWebSocketServer
* @run testng/othervm * @run testng/othervm
* -Djdk.httpclient.sendBufferSize=8192
* PendingPongTextClose * PendingPongTextClose
*/ */
@ -50,6 +51,7 @@ public class PendingPongTextClose extends PendingOperations {
public void pendingPongTextClose(boolean last) throws Exception { public void pendingPongTextClose(boolean last) throws Exception {
repeatable( () -> { repeatable( () -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -27,6 +27,7 @@
* @run testng/othervm * @run testng/othervm
* -Djdk.internal.httpclient.debug=true * -Djdk.internal.httpclient.debug=true
* -Djdk.internal.httpclient.websocket.debug=true * -Djdk.internal.httpclient.websocket.debug=true
* -Djdk.httpclient.sendBufferSize=8192
* PendingTextPongClose * PendingTextPongClose
*/ */
@ -49,6 +50,7 @@ public class PendingTextPongClose extends PendingOperations {
public void pendingTextPongClose(boolean last) throws Exception { public void pendingTextPongClose(boolean last) throws Exception {
repeatable(() -> { repeatable(() -> {
server = Support.notReadingServer(); server = Support.notReadingServer();
server.setReceiveBufferSize(1024);
server.open(); server.open();
webSocket = httpClient().newWebSocketBuilder() webSocket = httpClient().newWebSocketBuilder()
.buildAsync(server.getURI(), new WebSocket.Listener() { }) .buildAsync(server.getURI(), new WebSocket.Listener() { })

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -136,17 +136,65 @@ public class Support {
*/ */
public static DummyWebSocketServer notReadingServer() { public static DummyWebSocketServer notReadingServer() {
return new DummyWebSocketServer() { return new DummyWebSocketServer() {
volatile Thread reader;
@Override @Override
protected void read(SocketChannel ch) throws IOException { protected void read(SocketChannel ch) throws IOException {
reader = Thread.currentThread();
try { try {
System.out.println("Not reading server waiting");
Thread.sleep(Long.MAX_VALUE); Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) { } catch (InterruptedException e) {
throw new IOException(e); throw new IOException(e);
} }
} }
@Override
protected void closeChannel(SocketChannel channel) {
try {
long read = drain(channel);
System.out.printf("Not reading server drained %s bytes%n", read);
} catch (IOException io) {
System.out.println("Not reading server failed to drain channel: " + io);
}
super.closeChannel(channel);
}
@Override
public void close() {
super.close();
Thread thread = reader;
if (thread != null && thread.isAlive() && thread != Thread.currentThread()) {
try {
thread.join();
System.out.println("Not reading server: closed");
} catch (InterruptedException x) {
System.out.println("Not reading server: close interrupted: " + x);
}
}
}
}; };
} }
static long drain(SocketChannel channel) throws IOException {
System.out.println("Not reading server: draining socket");
var blocking = channel.isBlocking();
if (blocking) channel.configureBlocking(false);
long count = 0;
try {
ByteBuffer buffer = ByteBuffer.allocateDirect(8 * 1024);
int read;
while ((read = channel.read(buffer)) > 0) {
count += read;
buffer.clear();
}
return count;
} finally {
if (blocking != channel.isBlocking()) {
channel.configureBlocking(blocking);
}
}
}
public static DummyWebSocketServer writingServer(int... data) { public static DummyWebSocketServer writingServer(int... data) {
byte[] copy = new byte[data.length]; byte[] copy = new byte[data.length];
for (int i = 0; i < data.length; i++) { for (int i = 0; i < data.length; i++) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -76,8 +76,9 @@ public class WSHandshakeExceptionTest {
String httpsURI; String httpsURI;
String httpNonUtf8URI; String httpNonUtf8URI;
String httpsNonUtf8URI; String httpsNonUtf8URI;
HttpClient sharedClient;
static final int ITERATION_COUNT = 10; static final int ITERATION_COUNT = 4;
// a shared executor helps reduce the amount of threads created by the test // a shared executor helps reduce the amount of threads created by the test
static final ExecutorService executor = Executors.newCachedThreadPool(); static final ExecutorService executor = Executors.newCachedThreadPool();
@ -106,11 +107,16 @@ public class WSHandshakeExceptionTest {
@Test(dataProvider = "variants") @Test(dataProvider = "variants")
public void test(String uri, boolean sameClient) { public void test(String uri, boolean sameClient) {
HttpClient client = null; HttpClient client = sharedClient;
boolean pause;
for (int i = 0; i < ITERATION_COUNT; i++) { for (int i = 0; i < ITERATION_COUNT; i++) {
System.out.printf("iteration %s%n", i); System.out.printf("iteration %s%n", i);
if (!sameClient || client == null) if (!sameClient || client == null) {
pause = client != null;
client = newHttpClient(); client = newHttpClient();
if (pause) gc(10); // give some time to gc
}
if (sharedClient == null) sharedClient = client;
try { try {
client.newWebSocketBuilder() client.newWebSocketBuilder()
@ -143,6 +149,15 @@ public class WSHandshakeExceptionTest {
} }
} }
static void gc(long ms) {
System.gc();
try {
Thread.sleep(ms);
} catch (InterruptedException x) {
// OK
}
}
@BeforeTest @BeforeTest
public void setup() throws Exception { public void setup() throws Exception {
sslContext = new SimpleSSLContext().get(); sslContext = new SimpleSSLContext().get();
@ -168,6 +183,8 @@ public class WSHandshakeExceptionTest {
@AfterTest @AfterTest
public void teardown() { public void teardown() {
sharedClient = null;
gc(100);
httpTestServer.stop(0); httpTestServer.stop(0);
httpsTestServer.stop(0); httpsTestServer.stop(0);
executor.shutdownNow(); executor.shutdownNow();

View file

@ -404,6 +404,8 @@ public class WebSocketProxyTest {
@BeforeMethod @BeforeMethod
public void breakBetweenTests() { public void breakBetweenTests() {
System.gc();
try {Thread.sleep(100); } catch (InterruptedException x) { /* OK */ }
System.out.println("\n-------\n"); System.out.println("\n-------\n");
} }
} }

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -123,7 +123,7 @@ public class ToolProviderTest extends TestRunner {
String out = swOut.toString(); String out = swOut.toString();
String err = swErr.toString(); String err = swErr.toString();
if (!out.contains("Loading")) { if (!err.contains("Loading")) {
error("stdout: unexpected output"); error("stdout: unexpected output");
} }
if (!err.contains("illegal character")) { if (!err.contains("illegal character")) {

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -155,22 +155,22 @@ public class TestLocaleOption extends TestRunner {
private void testHelloWorld(Path base, Locale defaultLocale, Locale localeOption) throws Exception { private void testHelloWorld(Path base, Locale defaultLocale, Locale localeOption) throws Exception {
Path apiDir = base.resolve("api"); Path apiDir = base.resolve("api");
String stdOut = javadoc(defaultLocale, String stdErr = javadoc(defaultLocale,
localeOption, localeOption,
"-sourcepath", srcDir.toString(), "-sourcepath", srcDir.toString(),
"-d", apiDir.toString(), "-d", apiDir.toString(),
"p") "p")
.writeAll() .writeAll()
.getOutput(Task.OutputKind.STDOUT); .getOutput(Task.OutputKind.STDERR);
// check console messages // check console messages
if (Objects.equals(defaultLocale, ALLCAPS)) { if (Objects.equals(defaultLocale, ALLCAPS)) {
checkContains(stdOut, checkContains(stdErr,
""" """
LOADING SOURCE FILES FOR PACKAGE p... LOADING SOURCE FILES FOR PACKAGE p...
CONSTRUCTING JAVADOC INFORMATION..."""); CONSTRUCTING JAVADOC INFORMATION...""");
} else { } else {
checkContains(stdOut, checkContains(stdErr,
""" """
Loading source files for package p... Loading source files for package p...
Constructing Javadoc information..."""); Constructing Javadoc information...""");

View file

@ -0,0 +1,122 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8268774
* @summary Residual logging output written to STDOUT, not STDERR
* @library /tools/lib ../../lib
* @modules jdk.javadoc/jdk.javadoc.internal.tool
* @build toolbox.ToolBox javadoc.tester.*
* @run main TestToolStreams
*/
import java.io.IOException;
import java.nio.file.Path;
import javadoc.tester.JavadocTester;
import toolbox.ToolBox;
// See also TestReporterStreams for testing doclet/reporter use of streams
public class TestToolStreams extends JavadocTester {
public static void main(String... args) throws Exception {
TestToolStreams tester = new TestToolStreams();
tester.runTests(m -> new Object[]{Path.of(m.getName())});
}
ToolBox tb = new ToolBox();
TestToolStreams() throws IOException {
tb.writeJavaFiles(Path.of("src"),
"""
package p1;
/** Comment 1. */
public class C1 { }""",
"""
package p2;
/** Comment 2. */
public class C2 { }""");
}
/**
* Tests the entry point used by the DocumentationTool API and JavadocTester, in which
* all output is written to a single specified writer.
*/
@Test
public void testSingleStream(Path base) {
test(base, false, Output.OUT, Output.OUT);
}
/**
* Tests the entry point used by the launcher, in which output is written to
* writers that wrap {@code System.out} and {@code System.err}.
*/
@Test
public void testStandardStreams(Path base) {
test(base, true, Output.STDOUT, Output.STDERR);
}
void test(Path base, boolean useStdStreams, Output stdOut, Output stdErr) {
setOutputDirectoryCheck(DirectoryCheck.NONE);
setUseStandardStreams(useStdStreams);
javadoc("--help");
checkExit(Exit.OK);
if (stdOut != stdErr) {
checkIsEmpty(stdErr);
}
checkOutput(stdOut, true,
"Usage:");
javadoc("-d", base.resolve("out").toString(),
"-sourcepath", "src",
"-verbose", // Note: triggers lots of javac messages as well as the javadoc time-taken message
"p1",
Path.of("src").resolve("p2").resolve("C2.java").toString());
checkExit(Exit.OK);
if (stdOut != stdErr) {
checkIsEmpty(stdOut);
}
checkOutput(stdErr, true,
"Loading source file src/p2/C2.java...".replace("/", FS),
"Loading source files for package p1...",
"Constructing Javadoc information",
"[done in ", " ms]"
);
}
void checkIsEmpty(Output out) {
checking("no output to " + out);
String s = getOutput(out);
if (s.isEmpty()) {
passed("no output written to " + out);
} else {
failed(out + " is not empty");
}
}
}