Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
theaoqi committed Oct 17, 2024
2 parents d6a27b9 + 618917e commit 5fb709b
Show file tree
Hide file tree
Showing 47 changed files with 2,678 additions and 193 deletions.
24 changes: 10 additions & 14 deletions hotspot/src/share/vm/c1/c1_Canonicalizer.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2019, 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
Expand Down Expand Up @@ -303,24 +303,20 @@ void Canonicalizer::do_ShiftOp (ShiftOp* x) {
}
if (t2->is_constant()) {
if (t->tag() == intTag) {
int value = t->as_IntConstant()->value();
int shift = t2->as_IntConstant()->value() & 31;
jint mask = ~(~0 << (32 - shift));
if (shift == 0) mask = ~0;
jint value = t->as_IntConstant()->value();
jint shift = t2->as_IntConstant()->value();
switch (x->op()) {
case Bytecodes::_ishl: set_constant(value << shift); return;
case Bytecodes::_ishr: set_constant(value >> shift); return;
case Bytecodes::_iushr: set_constant((value >> shift) & mask); return;
case Bytecodes::_ishl: set_constant(java_shift_left(value, shift)); return;
case Bytecodes::_ishr: set_constant(java_shift_right(value, shift)); return;
case Bytecodes::_iushr: set_constant(java_shift_right_unsigned(value, shift)); return;
}
} else if (t->tag() == longTag) {
jlong value = t->as_LongConstant()->value();
int shift = t2->as_IntConstant()->value() & 63;
jlong mask = ~(~jlong_cast(0) << (64 - shift));
if (shift == 0) mask = ~jlong_cast(0);
jint shift = t2->as_IntConstant()->value();
switch (x->op()) {
case Bytecodes::_lshl: set_constant(value << shift); return;
case Bytecodes::_lshr: set_constant(value >> shift); return;
case Bytecodes::_lushr: set_constant((value >> shift) & mask); return;
case Bytecodes::_lshl: set_constant(java_shift_left(value, shift)); return;
case Bytecodes::_lshr: set_constant(java_shift_right(value, shift)); return;
case Bytecodes::_lushr: set_constant(java_shift_right_unsigned(value, shift)); return;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions hotspot/src/share/vm/opto/doCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
tty->print_cr(" Catching every inline exception bci:%d -> handler_bci:%d", bci(), handler_bci);
}
#endif
// If this is a backwards branch in the bytecodes, add safepoint
maybe_add_safepoint(handler_bci);
merge_exception(handler_bci); // jump to handler
return; // No more handling to be done here!
}
Expand Down Expand Up @@ -925,6 +927,8 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
tty->cr();
}
#endif
// If this is a backwards branch in the bytecodes, add safepoint
maybe_add_safepoint(handler_bci);
merge_exception(handler_bci);
}
set_control(not_subtype_ctrl);
Expand Down
6 changes: 3 additions & 3 deletions hotspot/src/share/vm/opto/loopnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1220,7 +1220,7 @@ Node *LoopLimitNode::Ideal(PhaseGVN *phase, bool can_reshape) {

const TypeInt* init_t = phase->type(in(Init) )->is_int();
const TypeInt* limit_t = phase->type(in(Limit))->is_int();
int stride_p;
jlong stride_p;
jlong lim, ini;
julong max;
if (stride_con > 0) {
Expand All @@ -1229,10 +1229,10 @@ Node *LoopLimitNode::Ideal(PhaseGVN *phase, bool can_reshape) {
ini = init_t->_lo;
max = (julong)max_jint;
} else {
stride_p = -stride_con;
stride_p = -(jlong)stride_con;
lim = init_t->_hi;
ini = limit_t->_lo;
max = (julong)min_jint;
max = (julong)(juint)min_jint; // double cast to get 0x0000000080000000, not 0xffffffff80000000
}
julong range = lim - ini + stride_p;
if (range <= max) {
Expand Down
530 changes: 514 additions & 16 deletions hotspot/src/share/vm/opto/superword.cpp

Large diffs are not rendered by default.

91 changes: 89 additions & 2 deletions hotspot/src/share/vm/opto/superword.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,18 +452,63 @@ class SuperWord : public ResourceObj {

//------------------------------SWPointer---------------------------
// Information about an address for dependence checking and vector alignment
//
// We parse and represent pointers of the simple form:
//
// pointer = adr + offset + invar + scale * ConvI2L(iv)
//
// Where:
//
// adr: the base address of an array (base = adr)
// OR
// some address to off-heap memory (base = TOP)
//
// offset: a constant offset
// invar: a runtime variable, which is invariant during the loop
// scale: scaling factor
// iv: loop induction variable
//
// But more precisely, we parse the composite-long-int form:
//
// pointer = adr + long_offset + long_invar + long_scale * ConvI2L(int_offset + inv_invar + int_scale * iv)
//
// pointer = adr + long_offset + long_invar + long_scale * ConvI2L(int_index)
// int_index = int_offset + int_invar + int_scale * iv
//
// However, for aliasing and adjacency checks (e.g. SWPointer::cmp()) we always use the simple form to make
// decisions. Hence, we must make sure to only create a "valid" SWPointer if the optimisations based on the
// simple form produce the same result as the compound-long-int form would. Intuitively, this depends on
// if the int_index overflows, but the precise conditions are given in SWPointer::is_safe_to_use_as_simple_form().
//
// ConvI2L(int_index) = ConvI2L(int_offset + int_invar + int_scale * iv)
// = Convi2L(int_offset) + ConvI2L(int_invar) + ConvI2L(int_scale) * ConvI2L(iv)
//
// scale = long_scale * ConvI2L(int_scale)
// offset = long_offset + long_scale * ConvI2L(int_offset)
// invar = long_invar + long_scale * ConvI2L(int_invar)
//
// pointer = adr + offset + invar + scale * ConvI2L(iv)
//
class SWPointer VALUE_OBJ_CLASS_SPEC {
protected:
MemNode* _mem; // My memory reference node
SuperWord* _slp; // SuperWord class

Node* _base; // NULL if unsafe nonheap reference
Node* _adr; // address pointer
// Components of the simple form:
Node* _base; // Base address of an array OR NULL if some off-heap memory.
Node* _adr; // Same as _base if an array pointer OR some off-heap memory pointer.
jint _scale; // multiplier for iv (in bytes), 0 if no loop iv
jint _offset; // constant offset (in bytes)
Node* _invar; // invariant offset (in bytes), NULL if none
bool _negate_invar; // if true then use: (0 - _invar)

// The int_index components of the compound-long-int form. Used to decide if it is safe to use the
// simple form rather than the compound-long-int form that was parsed.
bool _has_int_index_after_convI2L;
int _int_index_after_convI2L_offset;
Node* _int_index_after_convI2L_invar;
int _int_index_after_convI2L_scale;

PhaseIdealLoop* phase() { return _slp->phase(); }
IdealLoopTree* lpt() { return _slp->lpt(); }
PhiNode* iv() { return _slp->iv(); } // Induction var
Expand All @@ -480,6 +525,8 @@ class SWPointer VALUE_OBJ_CLASS_SPEC {
// Match: offset is (k [+/- invariant])
bool offset_plus_k(Node* n, bool negate = false);

bool is_safe_to_use_as_simple_form(Node* base, Node* adr) const;

public:
enum CMP {
Less = 1,
Expand Down Expand Up @@ -507,12 +554,45 @@ class SWPointer VALUE_OBJ_CLASS_SPEC {
int memory_size() { return _mem->memory_size(); }

// Comparable?
// We compute if and how two SWPointers can alias at runtime, i.e. if the two addressed regions of memory can
// ever overlap. There are essentially 3 relevant return states:
// - NotComparable: Synonymous to "unknown aliasing".
// We have no information about how the two SWPointers can alias. They could overlap, refer
// to another location in the same memory object, or point to a completely different object.
// -> Memory edge required. Aliasing unlikely but possible.
//
// - Less / Greater: Synonymous to "never aliasing".
// The two SWPointers may point into the same memory object, but be non-aliasing (i.e. we
// know both address regions inside the same memory object, but these regions are non-
// overlapping), or the SWPointers point to entirely different objects.
// -> No memory edge required. Aliasing impossible.
//
// - Equal: Synonymous to "overlap, or point to different memory objects".
// The two SWPointers either overlap on the same memory object, or point to two different
// memory objects.
// -> Memory edge required. Aliasing likely.
//
// In a future refactoring, we can simplify to two states:
// - NeverAlias: instead of Less / Greater
// - MayAlias: instead of Equal / NotComparable
//
// Two SWPointer are "comparable" (Less / Greater / Equal), iff all of these conditions apply:
// 1) Both are valid, i.e. expressible in the compound-long-int or simple form.
// 2) The adr are identical, or both are array bases of different arrays.
// 3) They have identical scale.
// 4) They have identical invar.
// 5) The difference in offsets is limited: abs(offset0 - offset1) < 2^31.
int cmp(SWPointer& q) {
if (valid() && q.valid() &&
(_adr == q._adr || _base == _adr && q._base == q._adr) &&
_scale == q._scale &&
_invar == q._invar &&
_negate_invar == q._negate_invar) {
jlong difference = abs(java_subtract((jlong)_offset, (jlong)q._offset));
jlong max_diff = (jlong)1 << 31;
if (difference >= max_diff) {
return NotComparable;
}
bool overlap = q._offset < _offset + memory_size() &&
_offset < q._offset + q.memory_size();
return overlap ? Equal : (_offset < q._offset ? Less : Greater);
Expand All @@ -529,6 +609,13 @@ class SWPointer VALUE_OBJ_CLASS_SPEC {
static bool comparable(int cmp) { return cmp < NotComparable; }

void print();

static bool try_AddI_no_overflow(jint offset1, jint offset2, jint& result);
static bool try_SubI_no_overflow(jint offset1, jint offset2, jint& result);
static bool try_AddSubI_no_overflow(jint offset1, jint offset2, bool is_sub, jint& result);
static bool try_LShiftI_no_overflow(jint offset1, int offset2, jint& result);
static bool try_MulI_no_overflow(jint offset1, jint offset2, jint& result);

};

#endif // SHARE_VM_OPTO_SUPERWORD_HPP
36 changes: 36 additions & 0 deletions hotspot/src/share/vm/utilities/globalDefinitions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1292,6 +1292,42 @@ inline intx byte_size(void* from, void* to) {
return (address)to - (address)from;
}

#ifdef ASSERT
#define RHS_MASK_ASSERT(rhs_mask) \
if (rhs_mask != 31 && rhs_mask != 63) { \
basic_fatal("rhs_mask assertion failed."); \
}
#else
#define RHS_MASK_ASSERT(rhs_mask)
#endif

// Provide integer shift operations with Java semantics. No overflow
// issues - left shifts simply discard shifted out bits. No undefined
// behavior for large or negative shift quantities; instead the actual
// shift distance is the argument modulo the lhs value's size in bits.
// No undefined or implementation defined behavior for shifting negative
// values; left shift discards bits, right shift sign extends. We use
// the same safe conversion technique as above for java_add and friends.
#define JAVA_INTEGER_SHIFT_OP(OP, NAME, TYPE, XTYPE) \
inline TYPE NAME (TYPE lhs, jint rhs) { \
const uint rhs_mask = (sizeof(TYPE) * 8) - 1; \
RHS_MASK_ASSERT(rhs_mask) \
XTYPE xres = static_cast<XTYPE>(lhs); \
xres OP ## = (rhs & rhs_mask); \
return reinterpret_cast<TYPE&>(xres); \
}

JAVA_INTEGER_SHIFT_OP(<<, java_shift_left, jint, juint)
JAVA_INTEGER_SHIFT_OP(<<, java_shift_left, jlong, julong)
// For signed shift right, assume C++ implementation >> sign extends.
JAVA_INTEGER_SHIFT_OP(>>, java_shift_right, jint, jint)
JAVA_INTEGER_SHIFT_OP(>>, java_shift_right, jlong, jlong)
// For >>> use C++ unsigned >>.
JAVA_INTEGER_SHIFT_OP(>>, java_shift_right_unsigned, jint, juint)
JAVA_INTEGER_SHIFT_OP(>>, java_shift_right_unsigned, jlong, julong)

#undef JAVA_INTEGER_SHIFT_OP

//----------------------------------------------------------------------------------------------------
// Avoid non-portable casts with these routines (DEPRECATED)

Expand Down
111 changes: 111 additions & 0 deletions hotspot/test/compiler/parsing/MissingSafepointOnTryCatch.jasm
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

public class MissingSafepointOnTryCatch version 52:0 {

static Method m:"()V" {
return;
}

static Method test1:"()V" stack 1 {
try t;
invokestatic m:"()V";
return;

catch t java/lang/Throwable;
stack_map class java/lang/Throwable;
athrow;
endtry t;
}

static Method test2:"()V" stack 1 {
try t0;
try t1;
invokestatic m:"()V";
endtry t1;
return;

catch t1 java/lang/Exception;
stack_map class java/lang/Exception;
return;

catch t0 java/lang/Throwable;
stack_map class java/lang/Throwable;
athrow;
endtry t0;
}

public static Method th:"()V"
throws java/lang/Exception
stack 2 locals 0
{
new class java/lang/Exception;
dup;
invokespecial Method java/lang/Exception."<init>":"()V";
athrow;
}

static Method test3:"()V" stack 1 locals 2 {
try t;
invokestatic m:"()V";
iconst_1;
istore_0;
iconst_0;
istore_1;
return;
catch t java/lang/Throwable;
stack_map class java/lang/Throwable;
invokestatic th:"()V";
return;
endtry t;
}

static Method test4:"()V" stack 2 locals 2 {
try t;
invokestatic m:"()V";
iconst_1;
istore_0;
iconst_0;
istore_1;
return;
catch t java/lang/Throwable;
stack_map class java/lang/Throwable;
iconst_1;
istore_0;
invokestatic th:"()V";
return;
endtry t;
}

static Method testInfinite:"()V" stack 1 {
try t;
invokestatic th:"()V";
return;

catch t java/lang/Throwable;
stack_map class java/lang/Throwable;
athrow;
endtry t;
}

} // end Class MissingSafepointOnTryCatch
Loading

0 comments on commit 5fb709b

Please sign in to comment.