Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8255150: Add utility methods to check long indexes and ranges #1003

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d9e4bc3
checkLongIndex
rwestrel Oct 14, 2020
88cbca7
Vladimir's comments
rwestrel Oct 15, 2020
57db4b5
Use overloads of method names.
PaulSandoz Oct 20, 2020
574c778
intrinsic
rwestrel Oct 21, 2020
e0309d1
c2 test case
rwestrel Oct 21, 2020
ca46960
non x86_64 arch support
rwestrel Oct 21, 2020
68ca5c2
move compiler test and add bug to test
rwestrel Oct 21, 2020
0162eab
Update headers and add intrinsic to Graal test ignore list
PaulSandoz Oct 22, 2020
4374433
Jorn's comments
rwestrel Nov 5, 2020
f974805
intrinsic comments
rwestrel Nov 6, 2020
692b429
CastLL should define carry_depency
rwestrel Nov 9, 2020
7ee2f29
checkLongIndex
rwestrel Oct 14, 2020
198fd99
Vladimir's comments
rwestrel Oct 15, 2020
ce1188c
Use overloads of method names.
PaulSandoz Oct 20, 2020
dcd4b2c
intrinsic
rwestrel Oct 21, 2020
f58e1af
c2 test case
rwestrel Oct 21, 2020
174d2c9
non x86_64 arch support
rwestrel Oct 21, 2020
15dc310
move compiler test and add bug to test
rwestrel Oct 21, 2020
db387ba
Update headers and add intrinsic to Graal test ignore list
PaulSandoz Oct 22, 2020
04ffefc
Jorn's comments
rwestrel Nov 5, 2020
8ef88cf
intrinsic comments
rwestrel Nov 6, 2020
efedb8e
CastLL should define carry_depency
rwestrel Nov 9, 2020
e3887a7
exclude compiler test when run with -Xcomp
rwestrel Nov 13, 2020
90493e6
Merge branch 'master' of https://git.openjdk.java.net/jdk into JDK-82…
rwestrel Nov 13, 2020
9c07df6
Merge branch 'master' into JDK-8255150
rwestrel Nov 16, 2020
4f31e7b
Merge branch 'master' into JDK-8255150
rwestrel Nov 16, 2020
feb3294
Merge branch 'master' of https://git.openjdk.java.net/jdk into JDK-82…
rwestrel Nov 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/hotspot/cpu/aarch64/aarch64.ad
Expand Up @@ -8860,6 +8860,17 @@ instruct castII(iRegI dst)
ins_pipe(pipe_class_empty);
%}

instruct castLL(iRegL dst)
%{
match(Set dst (CastLL dst));

size(0);
format %{ "# castLL of $dst" %}
ins_encode(/* empty encoding */);
ins_cost(0);
ins_pipe(pipe_class_empty);
%}

// ============================================================================
// Atomic operation instructions
//
Expand Down
8 changes: 8 additions & 0 deletions src/hotspot/cpu/arm/arm.ad
Expand Up @@ -5277,6 +5277,14 @@ instruct castII( iRegI dst ) %{
ins_pipe(empty);
%}

instruct castLL( iRegL dst ) %{
match(Set dst (CastLL dst));
format %{ "! castLL of $dst" %}
ins_encode( /*empty encoding*/ );
ins_cost(0);
ins_pipe(empty);
%}

//----------Arithmetic Instructions--------------------------------------------
// Addition Instructions
// Register Addition
Expand Down
8 changes: 8 additions & 0 deletions src/hotspot/cpu/ppc/ppc.ad
Expand Up @@ -10348,6 +10348,14 @@ instruct castII(iRegIdst dst) %{
ins_pipe(pipe_class_default);
%}

instruct castLL(iRegLdst dst) %{
match(Set dst (CastLL dst));
format %{ " -- \t// castLL of $dst" %}
size(0);
ins_encode( /*empty*/ );
ins_pipe(pipe_class_default);
%}

instruct checkCastPP(iRegPdst dst) %{
match(Set dst (CheckCastPP dst));
format %{ " -- \t// checkcastPP of $dst" %}
Expand Down
7 changes: 7 additions & 0 deletions src/hotspot/cpu/s390/s390.ad
Expand Up @@ -5345,6 +5345,13 @@ instruct castII(iRegI dst) %{
ins_pipe(pipe_class_dummy);
%}

instruct castLL(iRegL dst) %{
match(Set dst (CastLL dst));
size(0);
format %{ "# castLL of $dst" %}
ins_encode(/*empty*/);
ins_pipe(pipe_class_dummy);
%}

//----------Conditional_store--------------------------------------------------
// Conditional-store of the updated heap-top.
Expand Down
8 changes: 8 additions & 0 deletions src/hotspot/cpu/x86/x86_32.ad
Expand Up @@ -7147,6 +7147,14 @@ instruct castII( rRegI dst ) %{
ins_pipe( empty );
%}

instruct castLL( eRegL dst ) %{
match(Set dst (CastLL dst));
format %{ "#castLL of $dst" %}
ins_encode( /*empty encoding*/ );
ins_cost(0);
ins_pipe( empty );
%}

// Load-locked - same as a regular pointer load when used with compare-swap
instruct loadPLocked(eRegP dst, memory mem) %{
match(Set dst (LoadPLocked mem));
Expand Down
11 changes: 11 additions & 0 deletions src/hotspot/cpu/x86/x86_64.ad
Expand Up @@ -7445,6 +7445,17 @@ instruct castII(rRegI dst)
ins_pipe(empty);
%}

instruct castLL(rRegL dst)
%{
match(Set dst (CastLL dst));

size(0);
format %{ "# castLL of $dst" %}
ins_encode(/* empty encoding */);
ins_cost(0);
ins_pipe(empty);
%}

// LoadP-locked same as a regular LoadP when used with compare-swap
instruct loadPLocked(rRegP dst, memory mem)
%{
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/classfile/vmIntrinsics.hpp
Expand Up @@ -337,6 +337,8 @@ class methodHandle;
\
do_intrinsic(_Preconditions_checkIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkIndex_signature, F_S) \
do_signature(Preconditions_checkIndex_signature, "(IILjava/util/function/BiFunction;)I") \
do_intrinsic(_Preconditions_checkLongIndex, jdk_internal_util_Preconditions, checkIndex_name, Preconditions_checkLongIndex_signature, F_S) \
do_signature(Preconditions_checkLongIndex_signature, "(JJLjava/util/function/BiFunction;)J") \
\
do_class(java_nio_Buffer, "java/nio/Buffer") \
do_intrinsic(_checkIndex, java_nio_Buffer, checkIndex_name, int_int_signature, F_R) \
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/c2compiler.cpp
Expand Up @@ -649,6 +649,7 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt
case vmIntrinsics::_profileBoolean:
case vmIntrinsics::_isCompileConstant:
case vmIntrinsics::_Preconditions_checkIndex:
case vmIntrinsics::_Preconditions_checkLongIndex:
case vmIntrinsics::_getObjectSize:
break;

Expand Down
19 changes: 19 additions & 0 deletions src/hotspot/share/opto/castnode.cpp
Expand Up @@ -96,6 +96,11 @@ Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t,
cast->set_req(0, c);
return cast;
}
case Op_CastLL: {
Node* cast = new CastLLNode(n, t, carry_dependency);
cast->set_req(0, c);
return cast;
}
case Op_CastPP: {
Node* cast = new CastPPNode(n, t, carry_dependency);
cast->set_req(0, c);
Expand All @@ -108,6 +113,20 @@ Node* ConstraintCastNode::make_cast(int opcode, Node* c, Node *n, const Type *t,
return NULL;
}

Node* ConstraintCastNode::make(Node* c, Node *n, const Type *t, BasicType bt) {
switch(bt) {
case T_INT: {
return make_cast(Op_CastII, c, n, t, false);
}
case T_LONG: {
return make_cast(Op_CastLL, c, n, t, false);
}
default:
fatal("Bad basic type %s", type2name(bt));
}
return NULL;
}

TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const {
Node* val = in(1);
Node* ctl = in(0);
Expand Down
11 changes: 11 additions & 0 deletions src/hotspot/share/opto/castnode.hpp
Expand Up @@ -53,6 +53,7 @@ class ConstraintCastNode: public TypeNode {
bool carry_dependency() const { return _carry_dependency; }
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(Node* c, Node *n, const Type *t, BasicType bt);

#ifndef PRODUCT
virtual void dump_spec(outputStream *st) const;
Expand Down Expand Up @@ -92,6 +93,16 @@ class CastIINode: public ConstraintCastNode {
#endif
};

class CastLLNode: public ConstraintCastNode {
public:
CastLLNode(Node* n, const Type* t, bool carry_dependency = false)
: ConstraintCastNode(n, t, carry_dependency){
init_class_id(Class_CastLL);
}
virtual int Opcode() const;
virtual uint ideal_reg() const { return Op_RegL; }
};

//------------------------------CastPPNode-------------------------------------
// cast pointer to pointer (different type)
class CastPPNode: public ConstraintCastNode {
Expand Down
4 changes: 3 additions & 1 deletion src/hotspot/share/opto/cfgnode.cpp
Expand Up @@ -1970,12 +1970,14 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) {
// Wait until after parsing for the type information to propagate from the casts.
assert(can_reshape, "Invalid during parsing");
const Type* phi_type = bottom_type();
assert(phi_type->isa_int() || phi_type->isa_ptr(), "bad phi type");
assert(phi_type->isa_int() || phi_type->isa_ptr() || phi_type->isa_long(), "bad phi type");
// Add casts to carry the control dependency of the Phi that is
// going away
Node* cast = NULL;
if (phi_type->isa_int()) {
cast = ConstraintCastNode::make_cast(Op_CastII, r, uin, phi_type, true);
} else if (phi_type->isa_long()) {
cast = ConstraintCastNode::make_cast(Op_CastLL, r, uin, phi_type, true);
} else {
const Type* uin_type = phase->type(uin);
if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) {
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/classes.hpp
Expand Up @@ -61,6 +61,7 @@ macro(CallLeafNoFP)
macro(CallRuntime)
macro(CallStaticJava)
macro(CastII)
macro(CastLL)
macro(CastX2P)
macro(CastP2X)
macro(CastPP)
Expand Down
7 changes: 7 additions & 0 deletions src/hotspot/share/opto/graphKit.hpp
Expand Up @@ -103,6 +103,13 @@ class GraphKit : public Phase {
// Create or find a constant node
Node* intcon(jint con) const { return _gvn.intcon(con); }
Node* longcon(jlong con) const { return _gvn.longcon(con); }
Node* integercon(jlong con, BasicType bt) const {
if (bt == T_INT) {
return intcon(checked_cast<jint>(con));
}
assert(bt == T_LONG, "basic type not an int or long");
return longcon(con);
rwestrel marked this conversation as resolved.
Show resolved Hide resolved
}
Node* makecon(const Type *t) const { return _gvn.makecon(t); }
Node* zerocon(BasicType bt) const { return _gvn.zerocon(bt); }
// (See also macro MakeConX in type.hpp, which uses intcon or longcon.)
Expand Down
24 changes: 17 additions & 7 deletions src/hotspot/share/opto/library_call.cpp
Expand Up @@ -483,7 +483,8 @@ bool LibraryCallKit::try_to_inline(int predicate) {
case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true);
case vmIntrinsics::_equalsB: return inline_array_equals(StrIntrinsicNode::LL);
case vmIntrinsics::_equalsC: return inline_array_equals(StrIntrinsicNode::UU);
case vmIntrinsics::_Preconditions_checkIndex: return inline_preconditions_checkIndex();
case vmIntrinsics::_Preconditions_checkIndex: return inline_preconditions_checkIndex(T_INT);
case vmIntrinsics::_Preconditions_checkLongIndex: return inline_preconditions_checkIndex(T_LONG);
case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual());

case vmIntrinsics::_allocateUninitializedArray: return inline_unsafe_newArray(true);
Expand Down Expand Up @@ -1001,14 +1002,15 @@ bool LibraryCallKit::inline_hasNegatives() {
return true;
}

bool LibraryCallKit::inline_preconditions_checkIndex() {
bool LibraryCallKit::inline_preconditions_checkIndex(BasicType bt) {
Node* index = argument(0);
Node* length = argument(1);
Node* length = bt == T_INT ? argument(1) : argument(2);
if (too_many_traps(Deoptimization::Reason_intrinsic) || too_many_traps(Deoptimization::Reason_range_check)) {
return false;
}

Node* len_pos_cmp = _gvn.transform(new CmpINode(length, intcon(0)));
// check that length is positive
Node* len_pos_cmp = _gvn.transform(CmpNode::make(length, integercon(0, bt), bt));
Node* len_pos_bol = _gvn.transform(new BoolNode(len_pos_cmp, BoolTest::ge));

{
Expand All @@ -1017,11 +1019,19 @@ bool LibraryCallKit::inline_preconditions_checkIndex() {
Deoptimization::Action_make_not_entrant);
}

rwestrel marked this conversation as resolved.
Show resolved Hide resolved
// length is now known postive, add a cast node to make this explicit
jlong upper_bound = _gvn.type(length)->is_integer(bt)->hi_as_long();
Node* casted_length = ConstraintCastNode::make(control(), length, TypeInteger::make(0, upper_bound, Type::WidenMax, bt), bt);
casted_length = _gvn.transform(casted_length);
replace_in_map(length, casted_length);
length = casted_length;

if (stopped()) {
return false;
}

Node* rc_cmp = _gvn.transform(new CmpUNode(index, length));
// Use an unsigned comparison for the range check itself
Node* rc_cmp = _gvn.transform(CmpNode::make(index, length, bt, true));
BoolTest::mask btest = BoolTest::lt;
Node* rc_bool = _gvn.transform(new BoolNode(rc_cmp, btest));
RangeCheckNode* rc = new RangeCheckNode(control(), rc_bool, PROB_MAX, COUNT_UNKNOWN);
Expand All @@ -1041,8 +1051,8 @@ bool LibraryCallKit::inline_preconditions_checkIndex() {
return false;
}

Node* result = new CastIINode(index, TypeInt::make(0, _gvn.type(length)->is_int()->_hi, Type::WidenMax));
result->set_req(0, control());
// index is now known to be >= 0 and < length, cast it
Node* result = ConstraintCastNode::make(control(), index, TypeInteger::make(0, upper_bound, Type::WidenMax, bt), bt);
result = _gvn.transform(result);
set_result(result);
replace_in_map(index, result);
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/opto/library_call.hpp
Expand Up @@ -241,7 +241,7 @@ class LibraryCallKit : public GraphKit {
bool inline_native_getLength();
bool inline_array_copyOf(bool is_copyOfRange);
bool inline_array_equals(StrIntrinsicNode::ArgEnc ae);
bool inline_preconditions_checkIndex();
bool inline_preconditions_checkIndex(BasicType bt);
void copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, bool is_array);
bool inline_native_clone(bool is_virtual);
bool inline_native_Reflection_getCallerClass();
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/opto/node.hpp
Expand Up @@ -52,6 +52,7 @@ class CallNode;
class CallRuntimeNode;
class CallStaticJavaNode;
class CastIINode;
class CastLLNode;
class CatchNode;
class CatchProjNode;
class CheckCastPPNode;
Expand Down Expand Up @@ -671,6 +672,7 @@ class Node {
DEFINE_CLASS_ID(ConstraintCast, Type, 1)
DEFINE_CLASS_ID(CastII, ConstraintCast, 0)
DEFINE_CLASS_ID(CheckCastPP, ConstraintCast, 1)
DEFINE_CLASS_ID(CastLL, ConstraintCast, 2)
DEFINE_CLASS_ID(CMove, Type, 3)
DEFINE_CLASS_ID(SafePointScalarObject, Type, 4)
DEFINE_CLASS_ID(DecodeNarrowPtr, Type, 5)
Expand Down Expand Up @@ -819,6 +821,7 @@ class Node {
DEFINE_CLASS_QUERY(CatchProj)
DEFINE_CLASS_QUERY(CheckCastPP)
DEFINE_CLASS_QUERY(CastII)
DEFINE_CLASS_QUERY(CastLL)
DEFINE_CLASS_QUERY(ConstraintCast)
DEFINE_CLASS_QUERY(ClearArray)
DEFINE_CLASS_QUERY(CMove)
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/phaseX.hpp
Expand Up @@ -274,6 +274,7 @@ class PhaseTransform : public Phase {
// Fast int or long constant. Same as TypeInt::make(i) or TypeLong::make(l).
ConINode* intcon(jint i);
ConLNode* longcon(jlong l);
ConNode* integercon(jlong l, BasicType bt);

// Fast zero or null constant. Same as makecon(Type::get_zero_type(bt)).
ConNode* zerocon(BasicType bt);
Expand Down
19 changes: 19 additions & 0 deletions src/hotspot/share/opto/subnode.cpp
Expand Up @@ -563,8 +563,27 @@ void CmpNode::related(GrowableArray<Node*> *in_rel, GrowableArray<Node*> *out_re
}
}
}

#endif

CmpNode *CmpNode::make(Node *in1, Node *in2, BasicType bt, bool unsigned_comp) {
switch (bt) {
case T_INT:
if (unsigned_comp) {
return new CmpUNode(in1, in2);
}
return new CmpINode(in1, in2);
case T_LONG:
if (unsigned_comp) {
return new CmpULNode(in1, in2);
}
return new CmpLNode(in1, in2);
default:
fatal("Not implemented for %s", type2name(bt));
}
return NULL;
}

//=============================================================================
//------------------------------cmp--------------------------------------------
// Simplify a CmpI (compare 2 integers) node, based on local information.
Expand Down
2 changes: 2 additions & 0 deletions src/hotspot/share/opto/subnode.hpp
Expand Up @@ -140,6 +140,8 @@ class CmpNode : public SubNode {
const Type *bottom_type() const { return TypeInt::CC; }
virtual uint ideal_reg() const { return Op_RegFlags; }

static CmpNode *make(Node *in1, Node *in2, BasicType bt, bool unsigned_comp = false);

#ifndef PRODUCT
// CmpNode and subclasses include all data inputs (until hitting a control
// boundary) in their related node set, as well as all outputs until and
Expand Down
12 changes: 10 additions & 2 deletions src/hotspot/share/opto/type.cpp
Expand Up @@ -1338,6 +1338,14 @@ bool TypeD::empty(void) const {
return false; // always exactly a singleton
}

const TypeInteger* TypeInteger::make(jlong lo, jlong hi, int w, BasicType bt) {
if (bt == T_INT) {
return TypeInt::make(checked_cast<jint>(lo), checked_cast<jint>(hi), w);
}
assert(bt == T_LONG, "basic type not an int or long");
return TypeLong::make(lo, hi, w);
}

//=============================================================================
// Convience common pre-built types.
const TypeInt *TypeInt::MAX; // INT_MAX
Expand All @@ -1363,7 +1371,7 @@ const TypeInt *TypeInt::SYMINT; // symmetric range [-max_jint..max_jint]
const TypeInt *TypeInt::TYPE_DOMAIN; // alias for TypeInt::INT

//------------------------------TypeInt----------------------------------------
TypeInt::TypeInt( jint lo, jint hi, int w ) : Type(Int), _lo(lo), _hi(hi), _widen(w) {
TypeInt::TypeInt( jint lo, jint hi, int w ) : TypeInteger(Int), _lo(lo), _hi(hi), _widen(w) {
}

//------------------------------make-------------------------------------------
Expand Down Expand Up @@ -1623,7 +1631,7 @@ const TypeLong *TypeLong::UINT; // 32-bit unsigned subrange
const TypeLong *TypeLong::TYPE_DOMAIN; // alias for TypeLong::LONG

//------------------------------TypeLong---------------------------------------
TypeLong::TypeLong( jlong lo, jlong hi, int w ) : Type(Long), _lo(lo), _hi(hi), _widen(w) {
TypeLong::TypeLong(jlong lo, jlong hi, int w) : TypeInteger(Long), _lo(lo), _hi(hi), _widen(w) {
}

//------------------------------make-------------------------------------------
Expand Down