Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -147,7 +149,7 @@ public int rawNext() {
if (bci + 1 >= endBci) {
code = ILLEGAL;
} else {
code = bytecode.get(bci + 1) & 0xff;
code = getIndexU1();
isWide = true;
}
}
Expand All @@ -166,6 +168,6 @@ public int getIndexU2() {
}

public int getIndexU2Raw(int bci) {
return bytecode.getShort(bci) & 0xffff;
return Short.toUnsignedInt(bytecode.getShort(bci));
}
}
38 changes: 35 additions & 3 deletions src/java.base/share/classes/jdk/internal/classfile/impl/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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
Expand All @@ -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++) {
Expand Down