Skip to content

Commit

Permalink
Update JDK
Browse files Browse the repository at this point in the history
  • Loading branch information
dmlloyd committed Nov 4, 2024
1 parent eb626ab commit 15d9eb2
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 367 deletions.
2 changes: 1 addition & 1 deletion jdk
Submodule jdk updated 1471 files
Original file line number Diff line number Diff line change
Expand Up @@ -127,79 +127,102 @@ public static MethodTypeDesc methodTypeDesc(Class<?> returnType, Class<?>[] para
}

/**
* Validates the correctness of a binary class name. In particular checks for the presence of
* invalid characters in the name.
* Validates the correctness of a class or interface name or a package name.
* In particular checks for the presence of invalid characters,
* consecutive, leading, or trailing separator char, for both non-internal
* and internal forms, and the empty string for class or interface names.
*
* @param name the name
* @param slashSeparator {@code true} means {@code /} is the separator char
* (internal form); otherwise {@code .} is the separator char
* @param allowEmpty {@code true} means the empty string is a valid name
* @return the name passed if valid
* @throws IllegalArgumentException if the name is invalid
* @throws NullPointerException if name is {@code null}
*/
private static String validateClassOrPackageName(String name, boolean slashSeparator, boolean allowEmpty) {
int len = name.length(); // implicit null check
// empty name special rule
if (allowEmpty && len == 0)
return name;
// state variable for detection of illegal states of
// empty name, consecutive, leading, or trailing separators
int afterSeparator = 0;
for (int i = 0; i < len; i++) {
char ch = name.charAt(i);
// reject ';' or '['
if (ch == ';' || ch == '[')
throw invalidClassName(name);
// encounter a separator
boolean foundSlash = ch == '/';
if (foundSlash || ch == '.') {
// reject the other separator char
// reject consecutive or leading separators
if (foundSlash != slashSeparator || i == afterSeparator)
throw invalidClassName(name);
afterSeparator = i + 1;
}
}
// reject empty name or trailing separators
if (len == afterSeparator)
throw invalidClassName(name);
return name;
}

/**
* Validates the correctness of a binary class name.
* In particular checks for the presence of invalid characters, empty
* name, consecutive, leading, or trailing {@code .}.
*
* @param name the class name
* @return the class name passed if valid
* @throws IllegalArgumentException if the class name is invalid
* @throws NullPointerException if class name is {@code null}
*/
public static String validateBinaryClassName(String name) {
for (int i = 0; i < name.length(); i++) {
char ch = name.charAt(i);
if (ch == ';' || ch == '[' || ch == '/'
|| ch == '.' && (i == 0 || i + 1 == name.length() || name.charAt(i - 1) == '.'))
throw invalidClassName(name);
}
return name;
return validateClassOrPackageName(name, false, false);
}

/**
* Validates the correctness of an internal class name.
* In particular checks for the presence of invalid characters in the name.
* In particular checks for the presence of invalid characters, empty
* name, consecutive, leading, or trailing {@code /}.
*
* @param name the class name
* @return the class name passed if valid
* @throws IllegalArgumentException if the class name is invalid
* @throws NullPointerException if class name is {@code null}
*/
public static String validateInternalClassName(String name) {
for (int i = 0; i < name.length(); i++) {
char ch = name.charAt(i);
if (ch == ';' || ch == '[' || ch == '.'
|| ch == '/' && (i == 0 || i + 1 == name.length() || name.charAt(i - 1) == '/'))
throw invalidClassName(name);
}
return name;
return validateClassOrPackageName(name, true, false);
}

/**
* Validates the correctness of a binary package name.
* In particular checks for the presence of invalid characters in the name.
* Empty package name is allowed.
* In particular checks for the presence of invalid characters, consecutive,
* leading, or trailing {@code .}. Allows empty strings for the unnamed package.
*
* @param name the package name
* @return the package name passed if valid
* @throws IllegalArgumentException if the package name is invalid
* @throws NullPointerException if the package name is {@code null}
*/
public static String validateBinaryPackageName(String name) {
for (int i = 0; i < name.length(); i++) {
char ch = name.charAt(i);
if (ch == ';' || ch == '[' || ch == '/')
throw new IllegalArgumentException("Invalid package name: " + name);
}
return name;
return validateClassOrPackageName(name, false, true);
}

/**
* Validates the correctness of an internal package name.
* In particular checks for the presence of invalid characters in the name.
* Empty package name is allowed.
* In particular checks for the presence of invalid characters, consecutive,
* leading, or trailing {@code /}. Allows empty strings for the unnamed package.
*
* @param name the package name
* @return the package name passed if valid
* @throws IllegalArgumentException if the package name is invalid
* @throws NullPointerException if the package name is {@code null}
*/
public static String validateInternalPackageName(String name) {
for (int i = 0; i < name.length(); i++) {
char ch = name.charAt(i);
if (ch == ';' || ch == '[' || ch == '.')
throw new IllegalArgumentException("Invalid package name: " + name);
}
return name;
return validateClassOrPackageName(name, true, true);
}

/**
Expand Down Expand Up @@ -360,26 +383,22 @@ static int skipOverFieldSignature(String descriptor, int start, int end) {
case JVM_SIGNATURE_DOUBLE:
return index - start;
case JVM_SIGNATURE_CLASS:
// state variable for detection of illegal states, such as:
// empty unqualified name, '//', leading '/', or trailing '/'
boolean legal = false;
// state variable for detection of illegal states of
// empty name, '//', leading '/', or trailing '/'
int afterSeparator = index + 1; // start of internal name
while (index < end) {
switch (descriptor.charAt(index++)) {
case ';' -> {
// illegal state on parser exit indicates empty unqualified name or trailing '/'
return legal ? index - start : 0;
}
case '.', '[' -> {
// do not permit '.' or '['
ch = descriptor.charAt(index++);
if (ch == ';')
// reject empty name or trailing '/'
return index == afterSeparator ? 0 : index - start;
// reject '.' or '['
if (ch == '.' || ch == '[')
return 0;
if (ch == '/') {
// reject '//' or leading '/'
if (index == afterSeparator)
return 0;
}
case '/' -> {
// illegal state when received '/' indicates '//' or leading '/'
if (!legal) return 0;
legal = false;
}
default ->
legal = true;
afterSeparator = index + 1;
}
}
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public sealed interface PackageDesc
* @see PackageDesc#ofInternalName(String)
*/
static PackageDesc of(String name) {
ConstantUtils.validateBinaryPackageName(requireNonNull(name));
ConstantUtils.validateBinaryPackageName(name);
return new PackageDescImpl(ConstantUtils.binaryToInternal(name));
}

Expand All @@ -72,7 +72,7 @@ static PackageDesc of(String name) {
* @see PackageDesc#of(String)
*/
static PackageDesc ofInternalName(String name) {
ConstantUtils.validateInternalPackageName(requireNonNull(name));
ConstantUtils.validateInternalPackageName(name);
return new PackageDescImpl(name);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,8 @@ public void writeTo(DirectCodeBuilder writer) {
if (writer.canWriteDirect(code.constantPool()))
super.writeTo(writer);
else
writer.writeLoadConstant(op, constantEntry());
// We have writer.canWriteDirect(constantEntry().constantPool()) == false
writer.writeAdaptLoadConstant(op, constantEntry());
}

@Override
Expand Down Expand Up @@ -1346,7 +1347,12 @@ public ConstantDesc constantValue() {

@Override
public void writeTo(DirectCodeBuilder writer) {
writer.writeLoadConstant(op, constant);
var constant = this.constant;
if (writer.canWriteDirect(constant.constantPool()))
// Allows writing ldc_w small index constants upon user request
writer.writeDirectLoadConstant(op, constant);
else
writer.writeAdaptLoadConstant(op, constant);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -670,16 +670,22 @@ public void writeArgumentConstant(Opcode opcode, int value) {
}
}

public void writeLoadConstant(Opcode opcode, LoadableConstantEntry value) {
// Make sure Long and Double have LDC2_W and
// rewrite to _W if index is >= 256
int index = AbstractPoolEntry.maybeClone(constantPool, value).index();
if (value instanceof LongEntry || value instanceof DoubleEntry) {
opcode = Opcode.LDC2_W;
} else if (index >= 256)
opcode = Opcode.LDC_W;
// value may not be writable to this constant pool
public void writeAdaptLoadConstant(Opcode opcode, LoadableConstantEntry value) {
var pe = AbstractPoolEntry.maybeClone(constantPool, value);
int index = pe.index();
if (pe != value && opcode != Opcode.LDC2_W) {
// rewrite ldc/ldc_w if external entry; ldc2_w never needs rewrites
opcode = index <= 0xFF ? Opcode.LDC : Opcode.LDC_W;
}

assert !opcode.isWide();
writeDirectLoadConstant(opcode, pe);
}

// the loadable entry is writable to this constant pool
public void writeDirectLoadConstant(Opcode opcode, LoadableConstantEntry pe) {
assert !opcode.isWide() && canWriteDirect(pe.constantPool());
int index = pe.index();
if (opcode.sizeIfFixed() == 3) {
bytecodesBufWriter.writeU1U2(opcode.bytecode(), index);
} else {
Expand Down Expand Up @@ -1654,7 +1660,8 @@ public CodeBuilder lconst_1() {

@Override
public CodeBuilder ldc(LoadableConstantEntry entry) {
writeLoadConstant(BytecodeHelpers.ldcOpcode(entry), entry);
var direct = AbstractPoolEntry.maybeClone(constantPool, entry);
writeDirectLoadConstant(BytecodeHelpers.ldcOpcode(direct), direct);
return this;
}

Expand Down
Loading

0 comments on commit 15d9eb2

Please sign in to comment.