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 1e63782 + dfcd8d2 commit 1e9bfdb
Show file tree
Hide file tree
Showing 67 changed files with 2,691 additions and 453 deletions.
2 changes: 1 addition & 1 deletion make/conf/version-numbers.conf
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ DEFAULT_VERSION_CLASSFILE_MINOR=0
DEFAULT_VERSION_DOCS_API_SINCE=11
DEFAULT_ACCEPTABLE_BOOT_VERSIONS="20 21"
DEFAULT_JDK_SOURCE_TARGET_VERSION=21
DEFAULT_PROMOTED_VERSION_PRE=ea
DEFAULT_PROMOTED_VERSION_PRE=
6 changes: 6 additions & 0 deletions src/hotspot/share/classfile/verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "classfile/stackMapTableFormat.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verifier.hpp"
#include "classfile/vmClasses.hpp"
#include "classfile/vmSymbols.hpp"
Expand Down Expand Up @@ -211,6 +212,11 @@ bool Verifier::verify(InstanceKlass* klass, bool should_verify_class, TRAPS) {
exception_name == vmSymbols::java_lang_ClassFormatError())) {
log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
// Exclude any classes that fail over during dynamic dumping
if (CDS_ONLY(DynamicDumpSharedSpaces) NOT_CDS(false)) {
SystemDictionaryShared::warn_excluded(klass, "Failed over class verification while dynamic dumping");
SystemDictionaryShared::set_excluded(klass);
}
message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
exception_message = message_buffer;
exception_name = inference_verify(
Expand Down
6 changes: 3 additions & 3 deletions src/hotspot/share/opto/loopnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2540,7 +2540,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 @@ -2549,10 +2549,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
538 changes: 526 additions & 12 deletions src/hotspot/share/opto/superword.cpp

Large diffs are not rendered by default.

90 changes: 88 additions & 2 deletions src/hotspot/share/opto/superword.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -640,13 +640,51 @@ 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 : public ArenaObj {
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.
int _scale; // multiplier for iv (in bytes), 0 if no loop iv
int _offset; // constant offset (in bytes)

Expand All @@ -657,6 +695,13 @@ class SWPointer : public ArenaObj {
Node* _debug_invar_scale; // multiplier for invariant
#endif

// 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;

Node_Stack* _nstack; // stack used to record a swpointer trace of variants
bool _analyze_only; // Used in loop unrolling only for swpointer trace
uint _stack_idx; // Used in loop unrolling only for swpointer trace
Expand All @@ -675,6 +720,8 @@ class SWPointer : public ArenaObj {
// 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 @@ -710,10 +757,43 @@ class SWPointer : public ArenaObj {
return _invar == q._invar;
}

// 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_equals(q)) {
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 Down Expand Up @@ -821,6 +901,12 @@ class SWPointer : public ArenaObj {

void maybe_add_to_invar(Node* new_invar, bool negate);

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

Node* register_if_new(Node* n) const;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,15 @@ <H2>Misc HTTP URL stream protocol handler properties</H2>
</OL>
<P>The channel binding tokens generated are of the type "tls-server-end-point" as defined in
RFC 5929.</P>

<LI><P><B>{@systemProperty jdk.http.maxHeaderSize}</B> (default: 393216 or 384kB)<BR>
This is the maximum header field section size that a client is prepared to accept.
This is computed as the sum of the size of the uncompressed header name, plus
the size of the uncompressed header value, plus an overhead of 32 bytes for
each field section line. If a peer sends a field section that exceeds this
size a {@link java.net.ProtocolException ProtocolException} will be raised.
This applies to all versions of the HTTP protocol. A value of zero or a negative
value means no limit. If left unspecified, the default value is 393216 bytes.
</UL>
<P>All these properties are checked only once at startup.</P>
<a id="AddressCache"></a>
Expand Down
60 changes: 50 additions & 10 deletions src/java.base/share/classes/java/text/MessageFormat.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.io.InvalidObjectException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -1008,6 +1009,8 @@ public Object[] parse(String source, ParsePosition pos) {
maximumArgumentNumber = argumentNumbers[i];
}
}

// Constructors/applyPattern ensure that resultArray.length < MAX_ARGUMENT_INDEX
Object[] resultArray = new Object[maximumArgumentNumber + 1];

int patternOffset = 0;
Expand Down Expand Up @@ -1260,6 +1263,9 @@ protected Object readResolve() throws InvalidObjectException {
* @serial
*/
private int[] argumentNumbers = new int[INITIAL_FORMATS];
// Implementation limit for ArgumentIndex pattern element. Valid indices must
// be less than this value
private static final int MAX_ARGUMENT_INDEX = 10000;

/**
* One less than the number of entries in {@code offsets}. Can also be thought of
Expand Down Expand Up @@ -1484,6 +1490,11 @@ private void makeFormat(int position, int offsetNumber,
+ argumentNumber);
}

if (argumentNumber >= MAX_ARGUMENT_INDEX) {
throw new IllegalArgumentException(
argumentNumber + " exceeds the ArgumentIndex implementation limit");
}

// resize format information arrays if necessary
if (offsetNumber >= formats.length) {
int newLength = formats.length * 2;
Expand Down Expand Up @@ -1631,24 +1642,53 @@ private static final void copyAndFixQuotes(String source, int start, int end,
*/
@java.io.Serial
private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
in.defaultReadObject();
boolean isValid = maxOffset >= -1
&& formats.length > maxOffset
&& offsets.length > maxOffset
&& argumentNumbers.length > maxOffset;
ObjectInputStream.GetField fields = in.readFields();
if (fields.defaulted("argumentNumbers") || fields.defaulted("offsets")
|| fields.defaulted("formats") || fields.defaulted("locale")
|| fields.defaulted("pattern") || fields.defaulted("maxOffset")){
throw new InvalidObjectException("Stream has missing data");
}

locale = (Locale) fields.get("locale", null);
String patt = (String) fields.get("pattern", null);
int maxOff = fields.get("maxOffset", -2);
int[] argNums = ((int[]) fields.get("argumentNumbers", null)).clone();
int[] offs = ((int[]) fields.get("offsets", null)).clone();
Format[] fmts = ((Format[]) fields.get("formats", null)).clone();

// Check arrays/maxOffset have correct value/length
boolean isValid = maxOff >= -1 && argNums.length > maxOff
&& offs.length > maxOff && fmts.length > maxOff;

// Check the correctness of arguments and offsets
if (isValid) {
int lastOffset = pattern.length() + 1;
for (int i = maxOffset; i >= 0; --i) {
if ((offsets[i] < 0) || (offsets[i] > lastOffset)) {
int lastOffset = patt.length() + 1;
for (int i = maxOff; i >= 0; --i) {
if (argNums[i] < 0 || argNums[i] >= MAX_ARGUMENT_INDEX
|| offs[i] < 0 || offs[i] > lastOffset) {
isValid = false;
break;
} else {
lastOffset = offsets[i];
lastOffset = offs[i];
}
}
}

if (!isValid) {
throw new InvalidObjectException("Could not reconstruct MessageFormat from corrupt stream.");
throw new InvalidObjectException("Stream has invalid data");
}
maxOffset = maxOff;
pattern = patt;
offsets = offs;
formats = fmts;
argumentNumbers = argNums;
}

/**
* Serialization without data not supported for this class.
*/
@java.io.Serial
private void readObjectNoData() throws ObjectStreamException {
throw new InvalidObjectException("Deserialized MessageFormat objects need data");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -981,7 +981,9 @@ public final ForkJoinWorkerThread newThread(ForkJoinPool pool) {
boolean isCommon = (pool.workerNamePrefix == null);
@SuppressWarnings("removal")
SecurityManager sm = System.getSecurityManager();
if (sm != null && isCommon)
if (sm == null)
return new ForkJoinWorkerThread(null, pool, true, false);
else if (isCommon)
return newCommonWithACC(pool);
else
return newRegularWithACC(pool);
Expand Down
Loading

0 comments on commit 1e9bfdb

Please sign in to comment.