Skip to content

Commit 50e91e7

Browse files
[GR-55562] Merge in jdk-23+32 (24.1)
PullRequest: labsjdk-ce/97
2 parents f9518e2 + 2122bac commit 50e91e7

File tree

70 files changed

+1439
-365
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+1439
-365
lines changed

make/jdk/src/classes/build/tools/taglet/SealedGraph.java

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -107,7 +107,7 @@ public String toString(List<? extends DocTree> tags, Element element) {
107107
throw new RuntimeException(e);
108108
}
109109

110-
String simpleTypeName = element.getSimpleName().toString();
110+
String simpleTypeName = packagelessCanonicalName(typeElement).replace('.', '/');
111111
String imageFile = simpleTypeName + "-sealed-graph.svg";
112112
int thumbnailHeight = 100; // also appears in the stylesheet
113113
String hoverImage = "<span>"
@@ -315,14 +315,14 @@ private static Optional<String> packageName(TypeElement element) {
315315
case MEMBER -> packageName((TypeElement) element.getEnclosingElement());
316316
};
317317
}
318+
}
318319

319-
private static String packagelessCanonicalName(TypeElement element) {
320-
String result = element.getSimpleName().toString();
321-
while (element.getNestingKind() == NestingKind.MEMBER) {
322-
element = (TypeElement) element.getEnclosingElement();
323-
result = element.getSimpleName().toString() + '.' + result;
324-
}
325-
return result;
320+
private static String packagelessCanonicalName(TypeElement element) {
321+
String result = element.getSimpleName().toString();
322+
while (element.getNestingKind() == NestingKind.MEMBER) {
323+
element = (TypeElement) element.getEnclosingElement();
324+
result = element.getSimpleName().toString() + '.' + result;
326325
}
326+
return result;
327327
}
328328
}

src/hotspot/share/c1/c1_RangeCheckElimination.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -483,14 +483,14 @@ void RangeCheckEliminator::in_block_motion(BlockBegin *block, AccessIndexedList
483483

484484
if (c) {
485485
jint value = c->type()->as_IntConstant()->value();
486-
if (value != min_jint) {
487-
if (ao->op() == Bytecodes::_isub) {
488-
value = -value;
489-
}
486+
if (ao->op() == Bytecodes::_iadd) {
490487
base = java_add(base, value);
491-
last_integer = base;
492-
last_instruction = other;
488+
} else {
489+
assert(ao->op() == Bytecodes::_isub, "unexpected bytecode");
490+
base = java_subtract(base, value);
493491
}
492+
last_integer = base;
493+
last_instruction = other;
494494
index = other;
495495
} else {
496496
break;

src/hotspot/share/classfile/symbolTable.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,23 @@ Symbol* SymbolTable::lookup_common(const char* name,
344344
return sym;
345345
}
346346

347+
// Symbols should represent entities from the constant pool that are
348+
// limited to <64K in length, but usage errors creep in allowing Symbols
349+
// to be used for arbitrary strings. For debug builds we will assert if
350+
// a string is too long, whereas product builds will truncate it.
351+
static int check_length(const char* name, int len) {
352+
assert(len <= Symbol::max_length(),
353+
"String length %d exceeds the maximum Symbol length of %d", len, Symbol::max_length());
354+
if (len > Symbol::max_length()) {
355+
warning("A string \"%.80s ... %.80s\" exceeds the maximum Symbol "
356+
"length of %d and has been truncated", name, (name + len - 80), Symbol::max_length());
357+
len = Symbol::max_length();
358+
}
359+
return len;
360+
}
361+
347362
Symbol* SymbolTable::new_symbol(const char* name, int len) {
348-
assert(len <= Symbol::max_length(), "sanity");
363+
len = check_length(name, len);
349364
unsigned int hash = hash_symbol(name, len, _alt_hash);
350365
Symbol* sym = lookup_common(name, len, hash);
351366
if (sym == nullptr) {
@@ -485,6 +500,7 @@ void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHa
485500
for (int i = 0; i < names_count; i++) {
486501
const char *name = names[i];
487502
int len = lengths[i];
503+
assert(len <= Symbol::max_length(), "must be - these come from the constant pool");
488504
unsigned int hash = hashValues[i];
489505
assert(lookup_shared(name, len, hash) == nullptr, "must have checked already");
490506
Symbol* sym = do_add_if_needed(name, len, hash, is_permanent);
@@ -494,6 +510,7 @@ void SymbolTable::new_symbols(ClassLoaderData* loader_data, const constantPoolHa
494510
}
495511

496512
Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, bool is_permanent) {
513+
assert(len <= Symbol::max_length(), "caller should have ensured this");
497514
SymbolTableLookup lookup(name, len, hash);
498515
SymbolTableGet stg;
499516
bool clean_hint = false;
@@ -542,7 +559,7 @@ Symbol* SymbolTable::do_add_if_needed(const char* name, int len, uintx hash, boo
542559

543560
Symbol* SymbolTable::new_permanent_symbol(const char* name) {
544561
unsigned int hash = 0;
545-
int len = (int)strlen(name);
562+
int len = check_length(name, (int)strlen(name));
546563
Symbol* sym = SymbolTable::lookup_only(name, len, hash);
547564
if (sym == nullptr) {
548565
sym = do_add_if_needed(name, len, hash, /* is_permanent */ true);

src/hotspot/share/interpreter/oopMapCache.cpp

Lines changed: 24 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,6 @@ class OopMapCacheEntry: private InterpreterOopMap {
6666
public:
6767
OopMapCacheEntry() : InterpreterOopMap() {
6868
_next = nullptr;
69-
#ifdef ASSERT
70-
_resource_allocate_bit_mask = false;
71-
#endif
7269
}
7370
};
7471

@@ -177,9 +174,13 @@ class VerifyClosure : public OffsetClosure {
177174

178175
InterpreterOopMap::InterpreterOopMap() {
179176
initialize();
180-
#ifdef ASSERT
181-
_resource_allocate_bit_mask = true;
182-
#endif
177+
}
178+
179+
InterpreterOopMap::~InterpreterOopMap() {
180+
if (has_valid_mask() && mask_size() > small_mask_limit) {
181+
assert(_bit_mask[0] != 0, "should have pointer to C heap");
182+
FREE_C_HEAP_ARRAY(uintptr_t, _bit_mask[0]);
183+
}
183184
}
184185

185186
bool InterpreterOopMap::is_empty() const {
@@ -399,37 +400,24 @@ void OopMapCacheEntry::deallocate(OopMapCacheEntry* const entry) {
399400

400401
// Implementation of OopMapCache
401402

402-
void InterpreterOopMap::resource_copy(OopMapCacheEntry* from) {
403-
assert(_resource_allocate_bit_mask,
404-
"Should not resource allocate the _bit_mask");
405-
assert(from->has_valid_mask(),
406-
"Cannot copy entry with an invalid mask");
403+
void InterpreterOopMap::copy_from(const OopMapCacheEntry* src) {
404+
// The expectation is that this InterpreterOopMap is recently created
405+
// and empty. It is used to get a copy of a cached entry.
406+
assert(!has_valid_mask(), "InterpreterOopMap object can only be filled once");
407+
assert(src->has_valid_mask(), "Cannot copy entry with an invalid mask");
407408

408-
set_method(from->method());
409-
set_bci(from->bci());
410-
set_mask_size(from->mask_size());
411-
set_expression_stack_size(from->expression_stack_size());
412-
_num_oops = from->num_oops();
409+
set_method(src->method());
410+
set_bci(src->bci());
411+
set_mask_size(src->mask_size());
412+
set_expression_stack_size(src->expression_stack_size());
413+
_num_oops = src->num_oops();
413414

414415
// Is the bit mask contained in the entry?
415-
if (from->mask_size() <= small_mask_limit) {
416-
memcpy((void *)_bit_mask, (void *)from->_bit_mask,
417-
mask_word_size() * BytesPerWord);
416+
if (src->mask_size() <= small_mask_limit) {
417+
memcpy(_bit_mask, src->_bit_mask, mask_word_size() * BytesPerWord);
418418
} else {
419-
// The expectation is that this InterpreterOopMap is a recently created
420-
// and empty. It is used to get a copy of a cached entry.
421-
// If the bit mask has a value, it should be in the
422-
// resource area.
423-
assert(_bit_mask[0] == 0 ||
424-
Thread::current()->resource_area()->contains((void*)_bit_mask[0]),
425-
"The bit mask should have been allocated from a resource area");
426-
// Allocate the bit_mask from a Resource area for performance. Allocating
427-
// from the C heap as is done for OopMapCache has a significant
428-
// performance impact.
429-
_bit_mask[0] = (uintptr_t) NEW_RESOURCE_ARRAY(uintptr_t, mask_word_size());
430-
assert(_bit_mask[0] != 0, "bit mask was not allocated");
431-
memcpy((void*) _bit_mask[0], (void*) from->_bit_mask[0],
432-
mask_word_size() * BytesPerWord);
419+
_bit_mask[0] = (uintptr_t) NEW_C_HEAP_ARRAY(uintptr_t, mask_word_size(), mtClass);
420+
memcpy((void*) _bit_mask[0], (void*) src->_bit_mask[0], mask_word_size() * BytesPerWord);
433421
}
434422
}
435423

@@ -516,7 +504,7 @@ void OopMapCache::lookup(const methodHandle& method,
516504
for (int i = 0; i < _probe_depth; i++) {
517505
OopMapCacheEntry *entry = entry_at(probe + i);
518506
if (entry != nullptr && !entry->is_empty() && entry->match(method, bci)) {
519-
entry_for->resource_copy(entry);
507+
entry_for->copy_from(entry);
520508
assert(!entry_for->is_empty(), "A non-empty oop map should be returned");
521509
log_debug(interpreter, oopmap)("- found at hash %d", probe + i);
522510
return;
@@ -530,7 +518,7 @@ void OopMapCache::lookup(const methodHandle& method,
530518
OopMapCacheEntry* tmp = NEW_C_HEAP_OBJ(OopMapCacheEntry, mtClass);
531519
tmp->initialize();
532520
tmp->fill(method, bci);
533-
entry_for->resource_copy(tmp);
521+
entry_for->copy_from(tmp);
534522

535523
if (method->should_not_be_cached()) {
536524
// It is either not safe or not a good idea to cache this Method*
@@ -631,7 +619,7 @@ void OopMapCache::compute_one_oop_map(const methodHandle& method, int bci, Inter
631619
tmp->initialize();
632620
tmp->fill(method, bci);
633621
if (tmp->has_valid_mask()) {
634-
entry->resource_copy(tmp);
622+
entry->copy_from(tmp);
635623
}
636624
OopMapCacheEntry::deallocate(tmp);
637625
}

src/hotspot/share/interpreter/oopMapCache.hpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,14 @@
3636
// OopMapCache's are allocated lazily per InstanceKlass.
3737

3838
// The oopMap (InterpreterOopMap) is stored as a bit mask. If the
39-
// bit_mask can fit into two words it is stored in
39+
// bit_mask can fit into four words it is stored in
4040
// the _bit_mask array, otherwise it is allocated on the heap.
4141
// For OopMapCacheEntry the bit_mask is allocated in the C heap
4242
// because these entries persist between garbage collections.
43-
// For InterpreterOopMap the bit_mask is allocated in
44-
// a resource area for better performance. InterpreterOopMap
45-
// should only be created and deleted during same garbage collection.
43+
// For InterpreterOopMap the bit_mask is allocated in the C heap
44+
// to avoid issues with allocations from the resource area that have
45+
// to live accross the oop closure. InterpreterOopMap should only be
46+
// created and deleted during the same garbage collection.
4647
//
4748
// If ENABBLE_ZAP_DEAD_LOCALS is defined, two bits are used
4849
// per entry instead of one. In all cases,
@@ -95,9 +96,6 @@ class InterpreterOopMap: ResourceObj {
9596
// access it without using trickery in
9697
// method bit_mask().
9798
int _num_oops;
98-
#ifdef ASSERT
99-
bool _resource_allocate_bit_mask;
100-
#endif
10199

102100
// access methods
103101
Method* method() const { return _method; }
@@ -128,12 +126,13 @@ class InterpreterOopMap: ResourceObj {
128126

129127
public:
130128
InterpreterOopMap();
129+
~InterpreterOopMap();
131130

132-
// Copy the OopMapCacheEntry in parameter "from" into this
133-
// InterpreterOopMap. If the _bit_mask[0] in "from" points to
134-
// allocated space (i.e., the bit mask was to large to hold
135-
// in-line), allocate the space from a Resource area.
136-
void resource_copy(OopMapCacheEntry* from);
131+
// Copy the OopMapCacheEntry in parameter "src" into this
132+
// InterpreterOopMap. If the _bit_mask[0] in "src" points to
133+
// allocated space (i.e., the bit mask was too large to hold
134+
// in-line), allocate the space from the C heap.
135+
void copy_from(const OopMapCacheEntry* src);
137136

138137
void iterate_oop(OffsetClosure* oop_closure) const;
139138
void print() const;

src/hotspot/share/oops/symbol.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ uint32_t Symbol::pack_hash_and_refcount(short hash, int refcount) {
5454
}
5555

5656
Symbol::Symbol(const u1* name, int length, int refcount) {
57+
assert(length <= max_length(), "SymbolTable should have caught this!");
5758
_hash_and_refcount = pack_hash_and_refcount((short)os::random(), refcount);
5859
_length = (u2)length;
5960
// _body[0..1] are allocated in the header just by coincidence in the current

src/hotspot/share/oops/symbol.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,7 @@ class Symbol : public MetaspaceObj {
130130
return (int)heap_word_size(byte_size(length));
131131
}
132132

133+
// Constructor is private for use only by SymbolTable.
133134
Symbol(const u1* name, int length, int refcount);
134135

135136
static short extract_hash(uint32_t value) { return (short)(value >> 16); }

src/hotspot/share/opto/ifnode.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ bool IfNode::cmpi_folds(PhaseIterGVN* igvn, bool fold_ne) {
755755
bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) {
756756
return ctrl != nullptr &&
757757
ctrl->is_Proj() &&
758+
ctrl->outcnt() == 1 && // No side-effects
758759
ctrl->in(0) != nullptr &&
759760
ctrl->in(0)->Opcode() == Op_If &&
760761
ctrl->in(0)->outcnt() == 2 &&
@@ -1328,7 +1329,7 @@ Node* IfNode::fold_compares(PhaseIterGVN* igvn) {
13281329

13291330
if (cmpi_folds(igvn)) {
13301331
Node* ctrl = in(0);
1331-
if (is_ctrl_folds(ctrl, igvn) && ctrl->outcnt() == 1) {
1332+
if (is_ctrl_folds(ctrl, igvn)) {
13321333
// A integer comparison immediately dominated by another integer
13331334
// comparison
13341335
ProjNode* success = nullptr;

src/hotspot/share/opto/machnode.hpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,10 @@ class MachSafePointNode : public MachReturnNode {
870870
assert(verify_jvms(jvms), "jvms must match");
871871
return in(_jvmadj + jvms->monitor_box_offset(idx));
872872
}
873+
Node* scalarized_obj(const JVMState* jvms, uint idx) const {
874+
assert(verify_jvms(jvms), "jvms must match");
875+
return in(_jvmadj + jvms->scloff() + idx);
876+
}
873877
void set_local(const JVMState* jvms, uint idx, Node *c) {
874878
assert(verify_jvms(jvms), "jvms must match");
875879
set_req(_jvmadj + jvms->locoff() + idx, c);

src/hotspot/share/opto/output.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,27 @@ bool PhaseOutput::contains_as_owner(GrowableArray<MonitorValue*> *monarray, Obje
974974
return false;
975975
}
976976

977+
// Determine if there is a scalar replaced object description represented by 'ov'.
978+
bool PhaseOutput::contains_as_scalarized_obj(JVMState* jvms, MachSafePointNode* sfn,
979+
GrowableArray<ScopeValue*>* objs,
980+
ObjectValue* ov) const {
981+
for (int i = 0; i < jvms->scl_size(); i++) {
982+
Node* n = sfn->scalarized_obj(jvms, i);
983+
// Other kinds of nodes that we may encounter here, for instance constants
984+
// representing values of fields of objects scalarized, aren't relevant for
985+
// us, since they don't map to ObjectValue.
986+
if (!n->is_SafePointScalarObject()) {
987+
continue;
988+
}
989+
990+
ObjectValue* other = (ObjectValue*) sv_for_node_id(objs, n->_idx);
991+
if (ov == other) {
992+
return true;
993+
}
994+
}
995+
return false;
996+
}
997+
977998
//--------------------------Process_OopMap_Node--------------------------------
978999
void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
9791000
// Handle special safepoint nodes for synchronization
@@ -1137,7 +1158,10 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) {
11371158

11381159
for (int j = 0; j< merge->possible_objects()->length(); j++) {
11391160
ObjectValue* ov = merge->possible_objects()->at(j)->as_ObjectValue();
1140-
bool is_root = locarray->contains(ov) || exparray->contains(ov) || contains_as_owner(monarray, ov);
1161+
bool is_root = locarray->contains(ov) ||
1162+
exparray->contains(ov) ||
1163+
contains_as_owner(monarray, ov) ||
1164+
contains_as_scalarized_obj(jvms, sfn, objs, ov);
11411165
ov->set_root(is_root);
11421166
}
11431167
}

0 commit comments

Comments
 (0)