Skip to content

Commit

Permalink
Merge master HEAD into openj9-staging
Browse files Browse the repository at this point in the history
Signed-off-by: J9 Build <[email protected]>
  • Loading branch information
j9build committed Sep 21, 2024
2 parents 2b2db5a + 1ebbf85 commit 75c5309
Show file tree
Hide file tree
Showing 32 changed files with 2,213 additions and 201 deletions.
1 change: 1 addition & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ jobs:
- build-windows-aarch64
- test-linux-x64
- test-macos-x64
- test-macos-aarch64
- test-windows-x64

steps:
Expand Down
54 changes: 40 additions & 14 deletions src/java.base/share/classes/java/io/DataInputStream.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, Alibaba Group Holding Limited. 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 All @@ -25,8 +26,11 @@

package java.io;

import jdk.internal.access.JavaLangAccess;
import jdk.internal.access.SharedSecrets;
import jdk.internal.util.ByteArray;

import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
Expand All @@ -45,6 +49,7 @@
* @since 1.0
*/
public class DataInputStream extends FilterInputStream implements DataInput {
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();

private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
private static final char[] EMPTY_CHAR_ARRAY = new char[0];
Expand Down Expand Up @@ -573,31 +578,52 @@ public final String readUTF() throws IOException {
*/
public static final String readUTF(DataInput in) throws IOException {
int utflen = in.readUnsignedShort();
byte[] bytearr;
char[] chararr;
byte[] bytearr = null;
if (in instanceof DataInputStream dis) {
if (dis.bytearr.length < utflen) {
dis.bytearr = new byte[utflen*2];
dis.chararr = new char[utflen*2];
if (dis.bytearr.length >= utflen) {
bytearr = dis.bytearr;
}
chararr = dis.chararr;
bytearr = dis.bytearr;
} else {
}
boolean trusted = false;
if (bytearr == null) {
bytearr = new byte[utflen];
chararr = new char[utflen];
trusted = true;
}

int c, char2, char3;
int count = 0;
int chararr_count=0;

in.readFully(bytearr, 0, utflen);
int ascii = JLA.countPositives(bytearr, 0, utflen);
if (ascii == utflen) {
String str;
if (trusted) {
str = JLA.newStringNoRepl(bytearr, StandardCharsets.ISO_8859_1);
} else {
str = new String(bytearr, 0, utflen, StandardCharsets.ISO_8859_1);
}
return str;
}
if (trusted && in instanceof DataInputStream dis) {
dis.bytearr = bytearr;
trusted = false;
}

while (count < utflen) {
c = (int) bytearr[count] & 0xff;
if (c > 127) break;
count++;
chararr[chararr_count++]=(char)c;
char[] chararr;
if (in instanceof DataInputStream dis) {
if (dis.chararr.length < (utflen << 1)) {
dis.chararr = new char[utflen << 1];
}
chararr = dis.chararr;
} else {
chararr = new char[utflen];
}

if (ascii != 0) {
JLA.inflateBytesToChars(bytearr, 0, chararr, 0, ascii);
count += ascii;
chararr_count += ascii;
}

while (count < utflen) {
Expand Down
93 changes: 67 additions & 26 deletions src/java.base/share/classes/java/lang/classfile/CodeBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -615,36 +615,77 @@ default CodeBuilder loadConstant(ConstantDesc value) {
if (value == null || value == ConstantDescs.NULL)
return aconst_null();
if (value instanceof Number) {
if (value instanceof Integer iVal)
return switch (iVal) {
case -1 -> iconst_m1();
case 0 -> iconst_0();
case 1 -> iconst_1();
case 2 -> iconst_2();
case 3 -> iconst_3();
case 4 -> iconst_4();
case 5 -> iconst_5();
default -> (iVal >= Byte.MIN_VALUE && iVal <= Byte.MAX_VALUE) ? bipush(iVal)
: (iVal >= Short.MIN_VALUE && iVal <= Short.MAX_VALUE) ? sipush(iVal)
: ldc(constantPool().intEntry(iVal));
};
if (value instanceof Long lVal)
return lVal == 0L ? lconst_0()
: lVal == 1L ? lconst_1()
: ldc(constantPool().longEntry(lVal));
if (value instanceof Float fVal)
return Float.floatToRawIntBits(fVal) == 0 ? fconst_0()
: fVal == 1.0f ? fconst_1()
: fVal == 2.0f ? fconst_2()
: ldc(constantPool().floatEntry(fVal));
if (value instanceof Double dVal)
return Double.doubleToRawLongBits(dVal) == 0L ? dconst_0()
: dVal == 1.0d ? dconst_1()
: ldc(constantPool().doubleEntry(dVal));
if (value instanceof Integer) return loadConstant((int) value);
if (value instanceof Long ) return loadConstant((long) value);
if (value instanceof Float ) return loadConstant((float) value);
if (value instanceof Double ) return loadConstant((double) value);
}
return ldc(value);
}


/**
* Generate an instruction pushing a constant int value onto the operand stack.
* This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Integer.valueOf(value))}.
* @param value the int value
* @return this builder
* @since 24
*/
default CodeBuilder loadConstant(int value) {
return switch (value) {
case -1 -> iconst_m1();
case 0 -> iconst_0();
case 1 -> iconst_1();
case 2 -> iconst_2();
case 3 -> iconst_3();
case 4 -> iconst_4();
case 5 -> iconst_5();
default -> (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE ) ? bipush(value)
: (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) ? sipush(value)
: ldc(constantPool().intEntry(value));
};
}

/**
* Generate an instruction pushing a constant long value onto the operand stack.
* This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Long.valueOf(value))}.
* @param value the long value
* @return this builder
* @since 24
*/
default CodeBuilder loadConstant(long value) {
return value == 0l ? lconst_0()
: value == 1l ? lconst_1()
: ldc(constantPool().longEntry(value));
}

/**
* Generate an instruction pushing a constant float value onto the operand stack.
* This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Float.valueOf(value))}.
* @param value the float value
* @return this builder
* @since 24
*/
default CodeBuilder loadConstant(float value) {
return Float.floatToRawIntBits(value) == 0 ? fconst_0()
: value == 1.0f ? fconst_1()
: value == 2.0f ? fconst_2()
: ldc(constantPool().floatEntry(value));
}

/**
* Generate an instruction pushing a constant double value onto the operand stack.
* This is identical to {@link #loadConstant(ConstantDesc) loadConstant(Double.valueOf(value))}.
* @param value the double value
* @return this builder
* @since 24
*/
default CodeBuilder loadConstant(double value) {
return Double.doubleToRawLongBits(value) == 0l ? dconst_0()
: value == 1.0d ? dconst_1()
: ldc(constantPool().doubleEntry(value));
}

/**
* Generate a do nothing instruction
* @return this builder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1645,7 +1645,7 @@ private void bogusMethod(ClassBuilder clb, Object os) {
clb.withMethodBody("dummy", MTD_void, ACC_STATIC, new Consumer<>() {
@Override
public void accept(CodeBuilder cob) {
cob.loadConstant(os.toString());
cob.ldc(os.toString());
cob.pop();
cob.return_();
}
Expand Down
52 changes: 33 additions & 19 deletions src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,18 @@ final class ProxyGenerator {
private static final Method OBJECT_EQUALS_METHOD;
private static final Method OBJECT_TO_STRING_METHOD;

private static final String OBJECT_HASH_CODE_SIG;
private static final String OBJECT_EQUALS_SIG;
private static final String OBJECT_TO_STRING_SIG;

static {
try {
OBJECT_HASH_CODE_METHOD = Object.class.getMethod("hashCode");
OBJECT_HASH_CODE_SIG = OBJECT_HASH_CODE_METHOD.toShortSignature();
OBJECT_EQUALS_METHOD = Object.class.getMethod("equals", Object.class);
OBJECT_EQUALS_SIG = OBJECT_EQUALS_METHOD.toShortSignature();
OBJECT_TO_STRING_METHOD = Object.class.getMethod("toString");
OBJECT_TO_STRING_SIG = OBJECT_TO_STRING_METHOD.toShortSignature();
} catch (NoSuchMethodException e) {
throw new NoSuchMethodError(e.getMessage());
}
Expand Down Expand Up @@ -446,9 +453,9 @@ private byte[] generateClassFile() {
* java.lang.Object take precedence over duplicate methods in the
* proxy interfaces.
*/
addProxyMethod(new ProxyMethod(OBJECT_HASH_CODE_METHOD, "m0"));
addProxyMethod(new ProxyMethod(OBJECT_EQUALS_METHOD, "m1"));
addProxyMethod(new ProxyMethod(OBJECT_TO_STRING_METHOD, "m2"));
addProxyMethod(new ProxyMethod(OBJECT_HASH_CODE_METHOD, OBJECT_HASH_CODE_SIG, "m0"));
addProxyMethod(new ProxyMethod(OBJECT_EQUALS_METHOD, OBJECT_EQUALS_SIG, "m1"));
addProxyMethod(new ProxyMethod(OBJECT_TO_STRING_METHOD, OBJECT_TO_STRING_SIG, "m2"));

/*
* Accumulate all of the methods from the proxy interfaces.
Expand Down Expand Up @@ -526,7 +533,7 @@ private void addProxyMethod(Method m, Class<?> fromClass) {
return;
}
}
sigmethods.add(new ProxyMethod(m, sig, m.getSharedParameterTypes(), returnType,
sigmethods.add(new ProxyMethod(m, sig, returnType,
exceptionTypes, fromClass, "m" + proxyMethodCount++));
}

Expand Down Expand Up @@ -617,19 +624,19 @@ private void generateLookupAccessor(ClassBuilder clb) {
Label failLabel = cob.newLabel();
ClassEntry mhl = cp.classEntry(CD_MethodHandles_Lookup);
ClassEntry iae = cp.classEntry(CD_IllegalAccessException);
cob.aload(cob.parameterSlot(0))
cob.aload(0)
.invokevirtual(cp.methodRefEntry(mhl, cp.nameAndTypeEntry("lookupClass", MTD_Class)))
.ldc(proxyCE)
.if_acmpne(failLabel)
.aload(cob.parameterSlot(0))
.aload(0)
.invokevirtual(cp.methodRefEntry(mhl, cp.nameAndTypeEntry("hasFullPrivilegeAccess", MTD_boolean)))
.ifeq(failLabel)
.invokestatic(CD_MethodHandles, "lookup", MTD_MethodHandles$Lookup)
.areturn()
.labelBinding(failLabel)
.new_(iae)
.dup()
.aload(cob.parameterSlot(0))
.aload(0)
.invokevirtual(cp.methodRefEntry(mhl, cp.nameAndTypeEntry("toString", MTD_String)))
.invokespecial(cp.methodRefEntry(iae, exInit))
.athrow()
Expand All @@ -650,18 +657,16 @@ private class ProxyMethod {
private final Method method;
private final String shortSignature;
private final Class<?> fromClass;
private final Class<?>[] parameterTypes;
private final Class<?> returnType;
private final String methodFieldName;
private Class<?>[] exceptionTypes;
private final FieldRefEntry methodField;

private ProxyMethod(Method method, String sig, Class<?>[] parameterTypes,
private ProxyMethod(Method method, String sig,
Class<?> returnType, Class<?>[] exceptionTypes,
Class<?> fromClass, String methodFieldName) {
this.method = method;
this.shortSignature = sig;
this.parameterTypes = parameterTypes;
this.returnType = returnType;
this.exceptionTypes = exceptionTypes;
this.fromClass = fromClass;
Expand All @@ -670,32 +675,36 @@ private ProxyMethod(Method method, String sig, Class<?>[] parameterTypes,
cp.nameAndTypeEntry(methodFieldName, CD_Method));
}

private Class<?>[] parameterTypes() {
return method.getSharedParameterTypes();
}

/**
* Create a new specific ProxyMethod with a specific field name
*
* @param method The method for which to create a proxy
*/
private ProxyMethod(Method method, String methodFieldName) {
this(method, method.toShortSignature(),
method.getSharedParameterTypes(), method.getReturnType(),
private ProxyMethod(Method method, String sig, String methodFieldName) {
this(method, sig, method.getReturnType(),
method.getSharedExceptionTypes(), method.getDeclaringClass(), methodFieldName);
}

/**
* Generate this method, including the code and exception table entry.
*/
private void generateMethod(ClassBuilder clb) {
var desc = methodTypeDesc(returnType, parameterTypes);
var desc = methodTypeDesc(returnType, parameterTypes());
int accessFlags = (method.isVarArgs()) ? ACC_VARARGS | ACC_PUBLIC | ACC_FINAL
: ACC_PUBLIC | ACC_FINAL;
var catchList = computeUniqueCatchList(exceptionTypes);
clb.withMethod(method.getName(), desc, accessFlags, mb ->
mb.with(ExceptionsAttribute.of(toClassEntries(cp, List.of(exceptionTypes))))
.withCode(cob -> {
var catchList = computeUniqueCatchList(exceptionTypes);
cob.aload(cob.receiverSlot())
.getfield(handlerField)
.aload(cob.receiverSlot())
.getstatic(methodField);
Class<?>[] parameterTypes = parameterTypes();
if (parameterTypes.length > 0) {
// Create an array and fill with the parameters converting primitives to wrappers
cob.loadConstant(parameterTypes.length)
Expand Down Expand Up @@ -784,6 +793,7 @@ private void codeFieldInitialization(CodeBuilder cob) {
var cp = cob.constantPool();
codeClassForName(cob, fromClass);

Class<?>[] parameterTypes = parameterTypes();
cob.ldc(method.getName())
.loadConstant(parameterTypes.length)
.anewarray(classCE);
Expand Down Expand Up @@ -817,10 +827,14 @@ private void codeFieldInitialization(CodeBuilder cob) {
* loader is anticipated at local variable index 0.
*/
private void codeClassForName(CodeBuilder cob, Class<?> cl) {
cob.ldc(cl.getName())
.iconst_0() // false
.aload(0)// classLoader
.invokestatic(classForName);
if (cl == Object.class) {
cob.ldc(objectCE);
} else {
cob.ldc(cl.getName())
.iconst_0() // false
.aload(0)// classLoader
.invokestatic(classForName);
}
}

@Override
Expand Down
2 changes: 1 addition & 1 deletion src/java.base/share/classes/java/util/jar/JarFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
* <p> If the {@code verify} flag is on when opening a signed jar file, the content
* of the jar entry is verified against the signature embedded inside the manifest
* that is associated with its {@link JarEntry#getRealName() path name}. For a
* multi-release jar file, the content of a versioned entry is verfieid against
* multi-release jar file, the content of a versioned entry is verified against
* its own signature and {@link JarEntry#getCodeSigners()} returns its own signers.
*
* Please note that the verification process does not include validating the
Expand Down
Loading

0 comments on commit 75c5309

Please sign in to comment.