diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java index 8873d965402bf..171dcb0d9711a 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/BufWriterImpl.java @@ -87,17 +87,23 @@ public int getMajorVersion() { @Override public void writeU1(int x) { - writeIntBytes(1, x); + reserveSpace(Byte.BYTES); + elems[offset] = (byte) (x & 0xFF); + offset += Byte.BYTES; } @Override public void writeU2(int x) { - writeIntBytes(2, x); + reserveSpace(Short.BYTES); + Util.putShort(elems, offset, (short) (x & 0xFFFF)); + offset += Short.BYTES; } @Override public void writeInt(int x) { - writeIntBytes(4, x); + reserveSpace(Integer.BYTES); + Util.putInt(elems, offset, x); + offset += Integer.BYTES; } @Override @@ -107,7 +113,9 @@ public void writeFloat(float x) { @Override public void writeLong(long x) { - writeIntBytes(8, x); + reserveSpace(Long.BYTES); + Util.putLong(elems, offset, x); + offset += Long.BYTES; } @Override @@ -143,9 +151,17 @@ public void patchInt(int offset, int size, int value) { @Override public void writeIntBytes(int intSize, long intValue) { - reserveSpace(intSize); - for (int i = 0; i < intSize; i++) { - elems[offset++] = (byte) ((intValue >> 8 * (intSize - i - 1)) & 0xFF); + switch (intSize) { + case 1 -> writeU1((int) (intValue & 0xFFL)); + case 2 -> writeU2((int) (intValue & 0xFFFFL)); + case 4 -> writeInt((int) (intValue & 0xFFFFFFFFL)); + case 8 -> writeLong(intValue); + default -> { + reserveSpace(intSize); + for (int i = 0; i < intSize; i++) { + elems[offset++] = (byte) ((intValue >> 8 * (intSize - i - 1)) & 0xFF); + } + } } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java index fe91e674bab9f..bbad70968af27 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/ClassReaderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, 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 @@ -43,6 +43,7 @@ import jdk.internal.classfile.constantpool.PackageEntry; import jdk.internal.classfile.constantpool.PoolEntry; import jdk.internal.classfile.constantpool.Utf8Entry; +import jdk.internal.misc.Unsafe; import static jdk.internal.classfile.Classfile.TAG_CLASS; import static jdk.internal.classfile.Classfile.TAG_CONSTANTDYNAMIC; @@ -65,6 +66,8 @@ public final class ClassReaderImpl implements ClassReader { static final int CP_ITEM_START = 10; + // Cannot use VarHandle as it depends on bytecode generation + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private final byte[] buffer; private final int metadataStart; @@ -194,14 +197,12 @@ public BootstrapMethodEntryImpl bootstrapMethodEntry(int index) { @Override public int readU1(int p) { - return buffer[p] & 0xFF; + return Byte.toUnsignedInt(buffer[p]); } @Override public int readU2(int p) { - int b1 = buffer[p] & 0xFF; - int b2 = buffer[p + 1] & 0xFF; - return (b1 << 8) + b2; + return Short.toUnsignedInt(Util.getShort(buffer, p)); } @Override @@ -211,26 +212,17 @@ public int readS1(int p) { @Override public int readS2(int p) { - int b1 = buffer[p]; - int b2 = buffer[p + 1] & 0xFF; - return (b1 << 8) + b2; + return Util.getShort(buffer, p); } @Override public int readInt(int p) { - int ch1 = buffer[p] & 0xFF; - int ch2 = buffer[p + 1] & 0xFF; - int ch3 = buffer[p + 2] & 0xFF; - int ch4 = buffer[p + 3] & 0xFF; - return (ch1 << 24) + (ch2 << 16) + (ch3 << 8) + ch4; + return Util.getInt(buffer, p); } @Override public long readLong(int p) { - return ((long) buffer[p + 0] << 56) + ((long) (buffer[p + 1] & 255) << 48) + - ((long) (buffer[p + 2] & 255) << 40) + ((long) (buffer[p + 3] & 255) << 32) + - ((long) (buffer[p + 4] & 255) << 24) + ((buffer[p + 5] & 255) << 16) + ((buffer[p + 6] & 255) << 8) + - (buffer[p + 7] & 255); + return Util.getLong(buffer, p); } @Override diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java b/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java index 223f04d591822..73722764cee23 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/RawBytecodeHelper.java @@ -24,6 +24,8 @@ */ package jdk.internal.classfile.impl; +import jdk.internal.vm.annotation.Stable; + import java.nio.ByteBuffer; import static jdk.internal.classfile.Classfile.ASTORE_3; import static jdk.internal.classfile.Classfile.ISTORE; @@ -35,7 +37,7 @@ public final class RawBytecodeHelper { public static final int ILLEGAL = -1; - private static final byte[] LENGTHS = new byte[] { + private static final @Stable byte[] LENGTHS = new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 2, 3, 3, 2 | (4 << 4), 2 | (4 << 4), 2 | (4 << 4), 2 | (4 << 4), 2 | (4 << 4), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2 | (4 << 4), 2 | (4 << 4), 2 | (4 << 4), 2 | (4 << 4), 2 | (4 << 4), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3 | (6 << 4), 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2 | (4 << 4), 0, 0, 1, 1, 1, @@ -84,11 +86,11 @@ public int destW() { } public int getIndexU1() { - return bytecode.get(bci + 1) & 0xff; + return getU1(bci + 1); } public int getU1(int bci) { - return bytecode.get(bci) & 0xff; + return Byte.toUnsignedInt(bytecode.get(bci)); } public int rawNext(int jumpTo) { @@ -98,7 +100,7 @@ public int rawNext(int jumpTo) { public int rawNext() { bci = nextBci; - int code = bytecode.get(bci) & 0xff; + int code = getU1(bci); int len = LENGTHS[code] & 0xf; if (len > 0 && (bci <= endBci - len)) { isWide = false; @@ -109,12 +111,12 @@ public int rawNext() { rawCode = code; return code; } else { - len = switch (bytecode.get(bci) & 0xff) { + len = switch (getU1(bci)) { case WIDE -> { if (bci + 1 >= endBci) { yield -1; } - yield LENGTHS[bytecode.get(bci + 1) & 0xff] >> 4; + yield LENGTHS[getIndexU1()] >> 4; } case TABLESWITCH -> { int aligned_bci = align(bci + 1); @@ -147,7 +149,7 @@ public int rawNext() { if (bci + 1 >= endBci) { code = ILLEGAL; } else { - code = bytecode.get(bci + 1) & 0xff; + code = getIndexU1(); isWide = true; } } @@ -166,6 +168,6 @@ public int getIndexU2() { } public int getIndexU2Raw(int bci) { - return bytecode.getShort(bci) & 0xffff; + return Short.toUnsignedInt(bytecode.getShort(bci)); } } diff --git a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java index b757749b4980b..b29603594beba 100644 --- a/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java +++ b/src/java.base/share/classes/jdk/internal/classfile/impl/Util.java @@ -27,9 +27,7 @@ import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.AbstractList; -import java.util.BitSet; import java.util.Collection; -import java.util.Iterator; import java.util.List; import java.util.function.Function; @@ -38,11 +36,13 @@ import jdk.internal.classfile.constantpool.ModuleEntry; import jdk.internal.classfile.constantpool.NameAndTypeEntry; import java.lang.constant.ModuleDesc; -import jdk.internal.classfile.impl.TemporaryConstantPool; import java.lang.reflect.AccessFlag; import static jdk.internal.classfile.Classfile.ACC_STATIC; import jdk.internal.access.SharedSecrets; +import jdk.internal.misc.Unsafe; +import jdk.internal.util.Preconditions; +import jdk.internal.vm.annotation.ForceInline; /** * Helper to create and manipulate type descriptors, where type descriptors are @@ -54,6 +54,38 @@ public class Util { private Util() { } + // Utilities to speed up reading/writing from arrays, before VarHandle is available + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); + + @ForceInline + public static long checkByteArrayIndex(byte[] array, int index, int bytes) { + return Unsafe.ARRAY_BYTE_BASE_OFFSET + Preconditions.checkIndex(index, array.length - bytes + 1, Preconditions.AIOOBE_FORMATTER); + } + + public static short getShort(byte[] array, int index) { + return UNSAFE.getShortUnaligned(array, checkByteArrayIndex(array, index, Short.BYTES), true); + } + + public static int getInt(byte[] array, int index) { + return UNSAFE.getIntUnaligned(array, checkByteArrayIndex(array, index, Integer.BYTES), true); + } + + public static long getLong(byte[] array, int index) { + return UNSAFE.getLongUnaligned(array, checkByteArrayIndex(array, index, Long.BYTES), true); + } + + public static void putShort(byte[] array, int index, short value) { + UNSAFE.putShortUnaligned(array, checkByteArrayIndex(array, index, Short.BYTES), value, true); + } + + public static void putInt(byte[] array, int index, int value) { + UNSAFE.putIntUnaligned(array, checkByteArrayIndex(array, index, Integer.BYTES), value, true); + } + + public static void putLong(byte[] array, int index, long value) { + UNSAFE.putLongUnaligned(array, checkByteArrayIndex(array, index, Long.BYTES), value, true); + } + public static int parameterSlots(MethodTypeDesc mDesc) { int count = 0; for (int i = 0; i < mDesc.parameterCount(); i++) {