Skip to content

Commit

Permalink
Merge
Browse files Browse the repository at this point in the history
  • Loading branch information
theaoqi committed Jul 26, 2024
2 parents 00ca185 + 833f65e commit 0389c6c
Show file tree
Hide file tree
Showing 22 changed files with 458 additions and 146 deletions.
4 changes: 2 additions & 2 deletions make/conf/version-numbers.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2024, 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 @@ -39,4 +39,4 @@ DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="16 17"
DEFAULT_JDK_SOURCE_TARGET_VERSION=17
DEFAULT_PROMOTED_VERSION_PRE=ea
DEFAULT_PROMOTED_VERSION_PRE=
14 changes: 7 additions & 7 deletions src/hotspot/share/c1/c1_RangeCheckElimination.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2024, 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 @@ -466,14 +466,14 @@ void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList

if (c) {
jint value = c->type()->as_IntConstant()->value();
if (value != min_jint) {
if (ao->op() == Bytecodes::_isub) {
value = -value;
}
if (ao->op() == Bytecodes::_iadd) {
base = java_add(base, value);
last_integer = base;
last_instruction = other;
} else {
assert(ao->op() == Bytecodes::_isub, "unexpected bytecode");
base = java_subtract(base, value);
}
last_integer = base;
last_instruction = other;
index = other;
} else {
break;
Expand Down
22 changes: 20 additions & 2 deletions src/hotspot/share/classfile/symbolTable.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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 @@ -338,7 +338,23 @@ Symbol* SymbolTable::lookup_common(const char* name,
return sym;
}

// Symbols should represent entities from the constant pool that are
// limited to <64K in length, but usage errors creep in allowing Symbols
// to be used for arbitrary strings. For debug builds we will assert if
// a string is too long, whereas product builds will truncate it.
static int check_length(const char* name, int len) {
assert(len <= Symbol::max_length(),
"String length %d exceeds the maximum Symbol length of %d", len, Symbol::max_length());
if (len > Symbol::max_length()) {
warning("A string \"%.80s ... %.80s\" exceeds the maximum Symbol "
"length of %d and has been truncated", name, (name + len - 80), Symbol::max_length());
len = Symbol::max_length();
}
return len;
}

Symbol* SymbolTable::new_symbol(const char* name, int len) {
len = check_length(name, len);
unsigned int hash = hash_symbol(name, len, _alt_hash);
Symbol* sym = lookup_common(name, len, hash);
if (sym == NULL) {
Expand Down Expand Up @@ -472,6 +488,7 @@ void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHa
for (int i = 0; i < names_count; i++) {
const char *name = names[i];
int len = lengths[i];
assert(len <= Symbol::max_length(), "must be - these come from the constant pool");
unsigned int hash = hashValues[i];
assert(lookup_shared(name, len, hash) == NULL, "must have checked already");
Symbol* sym = do_add_if_needed(name, len, hash, c_heap);
Expand All @@ -481,6 +498,7 @@ void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHa
}

Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool heap) {
assert(len <= Symbol::max_length(), "caller should have ensured this");
SymbolTableLookup lookup(name, len, hash);
SymbolTableGet stg;
bool clean_hint = false;
Expand Down Expand Up @@ -515,7 +533,7 @@ Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, boo

Symbol* SymbolTable::new_permanent_symbol(const char* name) {
unsigned int hash = 0;
int len = (int)strlen(name);
int len = check_length(name, (int)strlen(name));
Symbol* sym = SymbolTable::lookup_only(name, len, hash);
if (sym == NULL) {
sym = do_add_if_needed(name, len, hash, false);
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/oops/symbol.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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 @@ -53,6 +53,7 @@ uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) {
}

Symbol::Symbol(const u1* name, int length, int refcount) {
assert(length <= max_length(), "SymbolTable should have caught this!");
_hash_and_refcount = pack_hash_and_refcount((short)os::random(), refcount);
_length = length;
// _body[0..1] are allocated in the header just by coincidence in the current
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/oops/symbol.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, 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 @@ -130,6 +130,7 @@ class Symbol : public MetaspaceObj {
return (int)heap_word_size(byte_size(length));
}

// Constructor is private for use only by SymbolTable.
Symbol(const u1* name, int length, int refcount);
void* operator new(size_t size, int len) throw();
void* operator new(size_t size, int len, Arena* arena) throw();
Expand Down
132 changes: 132 additions & 0 deletions src/hotspot/share/opto/addnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,138 @@ const Type *MinINode::add_ring( const Type *t0, const Type *t1 ) const {
return TypeInt::make( MIN2(r0->_lo,r1->_lo), MIN2(r0->_hi,r1->_hi), MAX2(r0->_widen,r1->_widen) );
}

// Collapse the "addition with overflow-protection" pattern, and the symmetrical
// "subtraction with underflow-protection" pattern. These are created during the
// unrolling, when we have to adjust the limit by subtracting the stride, but want
// to protect against underflow: MaxL(SubL(limit, stride), min_jint).
// If we have more than one of those in a sequence:
//
// x con2
// | |
// AddL clamp2
// | |
// Max/MinL con1
// | |
// AddL clamp1
// | |
// Max/MinL (n)
//
// We want to collapse it to:
//
// x con1 con2
// | | |
// | AddLNode (new_con)
// | |
// AddLNode clamp1
// | |
// Max/MinL (n)
//
// Note: we assume that SubL was already replaced by an AddL, and that the stride
// has its sign flipped: SubL(limit, stride) -> AddL(limit, -stride).
Node* fold_subI_no_underflow_pattern(Node* n, PhaseGVN* phase) {
assert(n->Opcode() == Op_MaxL || n->Opcode() == Op_MinL, "sanity");
// Check that the two clamps have the correct values.
jlong clamp = (n->Opcode() == Op_MaxL) ? min_jint : max_jint;
auto is_clamp = [&](Node* c) {
const TypeLong* t = phase->type(c)->isa_long();
return t != nullptr && t->is_con() &&
t->get_con() == clamp;
};
// Check that the constants are negative if MaxL, and positive if MinL.
auto is_sub_con = [&](Node* c) {
const TypeLong* t = phase->type(c)->isa_long();
return t != nullptr && t->is_con() &&
t->get_con() < max_jint && t->get_con() > min_jint &&
(t->get_con() < 0) == (n->Opcode() == Op_MaxL);
};
// Verify the graph level by level:
Node* add1 = n->in(1);
Node* clamp1 = n->in(2);
if (add1->Opcode() == Op_AddL && is_clamp(clamp1)) {
Node* max2 = add1->in(1);
Node* con1 = add1->in(2);
if (max2->Opcode() == n->Opcode() && is_sub_con(con1)) {
Node* add2 = max2->in(1);
Node* clamp2 = max2->in(2);
if (add2->Opcode() == Op_AddL && is_clamp(clamp2)) {
Node* x = add2->in(1);
Node* con2 = add2->in(2);
if (is_sub_con(con2)) {
Node* new_con = phase->transform(new AddLNode(con1, con2));
Node* new_sub = phase->transform(new AddLNode(x, new_con));
n->set_req_X(1, new_sub, phase);
return n;
}
}
}
}
return nullptr;
}

const Type* MaxLNode::add_ring(const Type* t0, const Type* t1) const {
const TypeLong* r0 = t0->is_long();
const TypeLong* r1 = t1->is_long();

return TypeLong::make(MAX2(r0->_lo, r1->_lo), MAX2(r0->_hi, r1->_hi), MAX2(r0->_widen, r1->_widen));
}

Node* MaxLNode::Identity(PhaseGVN* phase) {
const TypeLong* t1 = phase->type(in(1))->is_long();
const TypeLong* t2 = phase->type(in(2))->is_long();

// Can we determine maximum statically?
if (t1->_lo >= t2->_hi) {
return in(1);
} else if (t2->_lo >= t1->_hi) {
return in(2);
}

return MaxNode::Identity(phase);
}

Node* MaxLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
Node* n = AddNode::Ideal(phase, can_reshape);
if (n != nullptr) {
return n;
}
if (can_reshape) {
return fold_subI_no_underflow_pattern(this, phase);
}
return nullptr;
}

const Type* MinLNode::add_ring(const Type* t0, const Type* t1) const {
const TypeLong* r0 = t0->is_long();
const TypeLong* r1 = t1->is_long();

return TypeLong::make(MIN2(r0->_lo, r1->_lo), MIN2(r0->_hi, r1->_hi), MIN2(r0->_widen, r1->_widen));
}

Node* MinLNode::Identity(PhaseGVN* phase) {
const TypeLong* t1 = phase->type(in(1))->is_long();
const TypeLong* t2 = phase->type(in(2))->is_long();

// Can we determine minimum statically?
if (t1->_lo >= t2->_hi) {
return in(2);
} else if (t2->_lo >= t1->_hi) {
return in(1);
}

return MaxNode::Identity(phase);
}

Node* MinLNode::Ideal(PhaseGVN* phase, bool can_reshape) {
Node* n = AddNode::Ideal(phase, can_reshape);
if (n != nullptr) {
return n;
}
if (can_reshape) {
return fold_subI_no_underflow_pattern(this, phase);
}
return nullptr;
}

//------------------------------add_ring---------------------------------------
const Type *MinFNode::add_ring( const Type *t0, const Type *t1 ) const {
const TypeF *r0 = t0->is_float_constant();
Expand Down
26 changes: 18 additions & 8 deletions src/hotspot/share/opto/addnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,28 +330,38 @@ class MinINode : public MaxNode {
// MAXimum of 2 longs.
class MaxLNode : public MaxNode {
public:
MaxLNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
MaxLNode(Compile* C, Node* in1, Node* in2) : MaxNode(in1, in2) {
init_flags(Flag_is_macro);
C->add_macro_node(this);
}
virtual int Opcode() const;
virtual const Type *add_ring(const Type*, const Type*) const { return TypeLong::LONG; }
virtual const Type *add_id() const { return TypeLong::make(min_jlong); }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
virtual const Type* add_ring(const Type* t0, const Type* t1) const;
virtual const Type* add_id() const { return TypeLong::make(min_jlong); }
virtual const Type* bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
virtual Node* Identity(PhaseGVN* phase);
virtual Node* Ideal(PhaseGVN *phase, bool can_reshape);
};

//------------------------------MinLNode---------------------------------------
// MINimum of 2 longs.
class MinLNode : public MaxNode {
public:
MinLNode(Node *in1, Node *in2) : MaxNode(in1, in2) {}
MinLNode(Compile* C, Node* in1, Node* in2) : MaxNode(in1, in2) {
init_flags(Flag_is_macro);
C->add_macro_node(this);
}
virtual int Opcode() const;
virtual const Type *add_ring(const Type*, const Type*) const { return TypeLong::LONG; }
virtual const Type *add_id() const { return TypeLong::make(max_jlong); }
virtual const Type *bottom_type() const { return TypeLong::LONG; }
virtual const Type* add_ring(const Type* t0, const Type* t1) const;
virtual const Type* add_id() const { return TypeLong::make(max_jlong); }
virtual const Type* bottom_type() const { return TypeLong::LONG; }
virtual uint ideal_reg() const { return Op_RegL; }
int max_opcode() const { return Op_MaxL; }
int min_opcode() const { return Op_MinL; }
virtual Node* Identity(PhaseGVN* phase);
virtual Node* Ideal(PhaseGVN* phase, bool can_reshape);
};

//------------------------------MaxFNode---------------------------------------
Expand Down
14 changes: 14 additions & 0 deletions src/hotspot/share/opto/convertnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,20 @@ const Type* ConvI2LNode::Value(PhaseGVN* phase) const {
return tl;
}

Node* ConvI2LNode::Identity(PhaseGVN* phase) {
// If type is in "int" sub-range, we can
// convert I2L(L2I(x)) => x
// since the conversions have no effect.
if (in(1)->Opcode() == Op_ConvL2I) {
Node* x = in(1)->in(1);
const TypeLong* t = phase->type(x)->isa_long();
if (t != nullptr && t->_lo >= min_jint && t->_hi <= max_jint) {
return x;
}
}
return this;
}

static inline bool long_ranges_overlap(jlong lo1, jlong hi1,
jlong lo2, jlong hi2) {
// Two ranges overlap iff one range's low point falls in the other range.
Expand Down
1 change: 1 addition & 0 deletions src/hotspot/share/opto/convertnode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class ConvI2LNode : public TypeNode {
virtual int Opcode() const;
virtual const Type* Value(PhaseGVN* phase) const;
virtual Node *Ideal(PhaseGVN *phase, bool can_reshape);
virtual Node* Identity(PhaseGVN* phase);
virtual uint ideal_reg() const { return Op_RegL; }
};

Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/opto/ifnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,7 @@ bool IfNode::cmpi_folds(PhaseIterGVN* igvn, bool fold_ne) {
bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) {
return ctrl != nullptr &&
ctrl->is_Proj() &&
ctrl->outcnt() == 1 && // No side-effects
ctrl->in(0) != nullptr &&
ctrl->in(0)->Opcode() == Op_If &&
ctrl->in(0)->outcnt() == 2 &&
Expand Down Expand Up @@ -1307,7 +1308,7 @@ Node* IfNode::fold_compares(PhaseIterGVN* igvn) {

if (cmpi_folds(igvn)) {
Node* ctrl = in(0);
if (is_ctrl_folds(ctrl, igvn) && ctrl->outcnt() == 1) {
if (is_ctrl_folds(ctrl, igvn)) {
// A integer comparison immediately dominated by another integer
// comparison
ProjNode* success = nullptr;
Expand Down
Loading

0 comments on commit 0389c6c

Please sign in to comment.