Skip to content

Commit

Permalink
Merge branch 'master' into JDK-8256020
Browse files Browse the repository at this point in the history
  • Loading branch information
Roman Kennke committed Nov 11, 2020
2 parents 0726034 + 432c387 commit 527f90a
Show file tree
Hide file tree
Showing 9 changed files with 429 additions and 104 deletions.
6 changes: 4 additions & 2 deletions src/hotspot/cpu/aarch64/aarch64.ad
Expand Up @@ -1753,7 +1753,9 @@ int MachCallDynamicJavaNode::ret_addr_offset()

int MachCallRuntimeNode::ret_addr_offset() {
// for generated stubs the call will be
// far_call(addr)
// bl(addr)
// or with far branches
// bl(trampoline_stub)
// for real runtime callouts it will be six instructions
// see aarch64_enc_java_to_runtime
// adr(rscratch2, retaddr)
Expand All @@ -1762,7 +1764,7 @@ int MachCallRuntimeNode::ret_addr_offset() {
// blr(rscratch1)
CodeBlob *cb = CodeCache::find_blob(_entry_point);
if (cb) {
return MacroAssembler::far_branch_size();
return 1 * NativeInstruction::instruction_size;
} else {
return 6 * NativeInstruction::instruction_size;
}
Expand Down
32 changes: 22 additions & 10 deletions src/hotspot/share/opto/convertnode.cpp
Expand Up @@ -258,14 +258,30 @@ static inline bool long_ranges_overlap(jlong lo1, jlong hi1,
// Two ranges overlap iff one range's low point falls in the other range.
return (lo2 <= lo1 && lo1 <= hi2) || (lo1 <= lo2 && lo2 <= hi1);
}

// If there is an existing ConvI2L node with the given parent and type, return
// it. Otherwise, create and return a new one. Both reusing existing ConvI2L
// nodes and postponing the idealization of new ones are needed to avoid an
// explosion of recursive Ideal() calls when compiling long AddI chains.
static Node* find_or_make_convI2L(PhaseIterGVN* igvn, Node* parent,
const TypeLong* type) {
Node* n = new ConvI2LNode(parent, type);
Node* existing = igvn->hash_find_insert(n);
if (existing != NULL) {
n->destruct(igvn);
return existing;
}
return igvn->register_new_node_with_optimizer(n);
}
#endif

//------------------------------Ideal------------------------------------------
Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
PhaseIterGVN *igvn = phase->is_IterGVN();
const TypeLong* this_type = this->type()->is_long();
Node* this_changed = NULL;

if (can_reshape) {
if (igvn != NULL) {
// Do NOT remove this node's type assertion until no more loop ops can happen.
if (phase->C->post_loop_opts_phase()) {
const TypeInt* in_type = phase->type(in(1))->isa_int();
Expand Down Expand Up @@ -334,10 +350,9 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
Node* z = in(1);
int op = z->Opcode();
if (op == Op_AddI || op == Op_SubI) {
if (!can_reshape) {
// Postpone this optimization to after parsing because with deep AddNode
// chains a large amount of dead ConvI2L nodes might be created that are
// not removed during parsing. As a result, we might hit the node limit.
if (igvn == NULL) {
// Postpone this optimization to iterative GVN, where we can handle deep
// AddI chains without an exponential number of recursive Ideal() calls.
phase->record_for_igvn(this);
return this_changed;
}
Expand Down Expand Up @@ -399,11 +414,8 @@ Node *ConvI2LNode::Ideal(PhaseGVN *phase, bool can_reshape) {
}
assert(rxlo == (int)rxlo && rxhi == (int)rxhi, "x should not overflow");
assert(rylo == (int)rylo && ryhi == (int)ryhi, "y should not overflow");
Node* cx = phase->C->constrained_convI2L(phase, x, TypeInt::make(rxlo, rxhi, widen), NULL);
Node *hook = new Node(1);
hook->init_req(0, cx); // Add a use to cx to prevent him from dying
Node* cy = phase->C->constrained_convI2L(phase, y, TypeInt::make(rylo, ryhi, widen), NULL);
hook->destruct(phase);
Node* cx = find_or_make_convI2L(igvn, x, TypeLong::make(rxlo, rxhi, widen));
Node* cy = find_or_make_convI2L(igvn, y, TypeLong::make(rylo, ryhi, widen));
switch (op) {
case Op_AddI: return new AddLNode(cx, cy);
case Op_SubI: return new SubLNode(cx, cy);
Expand Down
Expand Up @@ -500,38 +500,44 @@ private byte[] transform(Data dereferencedData,
}

boolean secVal = Utils.secureValidation(context);
xi.setSecureValidation(secVal);
if (context instanceof XMLSignContext && c14n11
&& !xi.isOctetStream() && !xi.isOutputStreamSet()) {
TransformService spi = null;
if (provider == null) {
spi = TransformService.getInstance(c14nalg, "DOM");
} else {
try {
spi = TransformService.getInstance(c14nalg, "DOM", provider);
} catch (NoSuchAlgorithmException nsae) {
try {
xi.setSecureValidation(secVal);
if (context instanceof XMLSignContext && c14n11
&& !xi.isOctetStream() && !xi.isOutputStreamSet()) {
TransformService spi = null;
if (provider == null) {
spi = TransformService.getInstance(c14nalg, "DOM");
} else {
try {
spi = TransformService.getInstance(c14nalg, "DOM", provider);
} catch (NoSuchAlgorithmException nsae) {
spi = TransformService.getInstance(c14nalg, "DOM");
}
}
}

DOMTransform t = new DOMTransform(spi);
Element transformsElem = null;
String dsPrefix = DOMUtils.getSignaturePrefix(context);
if (allTransforms.isEmpty()) {
transformsElem = DOMUtils.createElement(
refElem.getOwnerDocument(),
"Transforms", XMLSignature.XMLNS, dsPrefix);
refElem.insertBefore(transformsElem,
DOMUtils.getFirstChildElement(refElem));
DOMTransform t = new DOMTransform(spi);
Element transformsElem = null;
String dsPrefix = DOMUtils.getSignaturePrefix(context);
if (allTransforms.isEmpty()) {
transformsElem = DOMUtils.createElement(
refElem.getOwnerDocument(),
"Transforms", XMLSignature.XMLNS, dsPrefix);
refElem.insertBefore(transformsElem,
DOMUtils.getFirstChildElement(refElem));
} else {
transformsElem = DOMUtils.getFirstChildElement(refElem);
}
t.marshal(transformsElem, dsPrefix,
(DOMCryptoContext) context);
allTransforms.add(t);
xi.updateOutputStream(os, true);
} else {
transformsElem = DOMUtils.getFirstChildElement(refElem);
xi.updateOutputStream(os);
}
} finally {
if(xi.getOctetStreamReal() != null) {
xi.getOctetStreamReal().close();
}
t.marshal(transformsElem, dsPrefix,
(DOMCryptoContext)context);
allTransforms.add(t);
xi.updateOutputStream(os, true);
} else {
xi.updateOutputStream(os);
}
}
os.flush();
Expand Down
Expand Up @@ -2577,10 +2577,12 @@ private void readClassBuffer(ClassSymbol c) throws IOException {
majorVersion = nextChar();
int maxMajor = Version.MAX().major;
int maxMinor = Version.MAX().minor;
boolean previewClassFile =
minorVersion == ClassFile.PREVIEW_MINOR_VERSION;
if (majorVersion > maxMajor ||
majorVersion * 1000 + minorVersion <
Version.MIN().major * 1000 + Version.MIN().minor) {
if (majorVersion == (maxMajor + 1))
if (majorVersion == (maxMajor + 1) && !previewClassFile)
log.warning(Warnings.BigMajorVersion(currentClassFile,
majorVersion,
maxMajor));
Expand All @@ -2592,7 +2594,7 @@ private void readClassBuffer(ClassSymbol c) throws IOException {
Integer.toString(maxMinor));
}

if (minorVersion == ClassFile.PREVIEW_MINOR_VERSION) {
if (previewClassFile) {
if (!preview.isEnabled()) {
log.error(preview.disabledError(currentClassFile, majorVersion));
} else {
Expand Down
@@ -0,0 +1,164 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

package compiler.conversions;

import java.util.Random;
import jdk.test.lib.Asserts;

/*
* @test
* @bug 8254317
* @requires vm.compiler2.enabled
* @summary Exercises the optimization that moves integer-to-long conversions
* upwards through different shapes of integer addition
* subgraphs. Contains three small functional tests and two stress
* tests that resulted in a compilation time and memory explosion
* before fixing bug 8254317. The stress tests run with -Xbatch to wait
* for C2, so that a timeout or an out-of-memory error is triggered if
* there was an explosion. These tests use a timeout of 30s to catch
* the explosion earlier.
* @library /test/lib /
* @run main/othervm
* compiler.conversions.TestMoveConvI2LThroughAddIs functional
* @run main/othervm/timeout=30 -Xbatch
* compiler.conversions.TestMoveConvI2LThroughAddIs stress1
* @run main/othervm/timeout=30 -Xbatch
* compiler.conversions.TestMoveConvI2LThroughAddIs stress2
*/

public class TestMoveConvI2LThroughAddIs {

// Number of repetitions of each test. Should be sufficiently large for the
// method under test to be compiled with C2.
static final int N = 100_000;

// Chain-shaped functional test.
static long testChain(boolean cnd) {
int a = cnd ? 1 : 2;
int b = a + a;
int c = b + b;
int d = c + c;
return d;
}

// Tree-shaped functional test.
static long testTree(boolean cnd) {
int a0 = cnd ? 1 : 2;
int a1 = cnd ? 1 : 2;
int a2 = cnd ? 1 : 2;
int a3 = cnd ? 1 : 2;
int a4 = cnd ? 1 : 2;
int a5 = cnd ? 1 : 2;
int a6 = cnd ? 1 : 2;
int a7 = cnd ? 1 : 2;
int b0 = a0 + a1;
int b1 = a2 + a3;
int b2 = a4 + a5;
int b3 = a6 + a7;
int c0 = b0 + b1;
int c1 = b2 + b3;
int d = c0 + c1;
return d;
}

// DAG-shaped functional test.
static long testDAG(boolean cnd) {
int a0 = cnd ? 1 : 2;
int a1 = cnd ? 1 : 2;
int a2 = cnd ? 1 : 2;
int a3 = cnd ? 1 : 2;
int b0 = a0 + a1;
int b1 = a1 + a2;
int b2 = a2 + a3;
int c0 = b0 + b1;
int c1 = b1 + b2;
int d = c0 + c1;
return d;
}

// Chain-shaped stress test. Before fixing bug 8254317, this test would
// result in an out-of-memory error after minutes running.
static long testStress1(boolean cnd) {
// C2 infers a finite, small value range for a. Note that there are
// different ways to achieve this, for example a might take the value of
// the induction variable in an outer counted loop.
int a = cnd ? 1 : 2;
// C2 fully unrolls this loop, creating a long chain of AddIs.
for (int i = 0; i < 28; i++) {
a = a + a;
}
// C2 places a ConvI2L at the end of the AddI chain.
return a;
}

// DAG-shaped stress test. Before fixing bug 8254317, this test would result
// in an out-of-memory error after minutes running.
static long testStress2(boolean cnd) {
int a = cnd ? 1 : 2;
int b = a;
int c = a + a;
for (int i = 0; i < 20; i++) {
b = b + c;
c = b + c;
}
int d = b + c;
return d;
}

public static void main(String[] args) {
// We use a random number generator to avoid constant propagation in C2
// and produce a variable ("a" in the different tests) with a finite,
// small value range.
Random rnd = new Random();
switch(args[0]) {
case "functional":
// Small, functional tests.
for (int i = 0; i < N; i++) {
boolean cnd = rnd.nextBoolean();
Asserts.assertEQ(testChain(cnd), cnd ? 8L : 16L);
Asserts.assertEQ(testTree(cnd), cnd ? 8L : 16L);
Asserts.assertEQ(testDAG(cnd), cnd ? 8L : 16L);
}
break;
case "stress1":
// Chain-shaped stress test.
for (int i = 0; i < N; i++) {
boolean cnd = rnd.nextBoolean();
Asserts.assertEQ(testStress1(cnd),
cnd ? 268435456L : 536870912L);
}
break;
case "stress2":
// DAG-shaped stress test.
for (int i = 0; i < N; i++) {
boolean cnd = rnd.nextBoolean();
Asserts.assertEQ(testStress2(cnd),
cnd ? 701408733L : 1402817466L);
}
break;
default:
System.out.println("invalid mode");
}
}
}
1 change: 0 additions & 1 deletion test/jdk/ProblemList.txt
Expand Up @@ -730,7 +730,6 @@ javax/sound/midi/Sequencer/MetaCallback.java 8178698 linux-all
javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all

javax/swing/border/TestTitledBorderLeak.java 8213531 linux-all
javax/swing/JComponent/7154030/bug7154030.java 7190978 generic-all
javax/swing/JComponent/6683775/bug6683775.java 8172337 generic-all
javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java 8233582 linux-all
javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java 8233582 linux-all
Expand Down

0 comments on commit 527f90a

Please sign in to comment.