Skip to content

Commit

Permalink
Use inlined representation for class initializer, loop initialization…
Browse files Browse the repository at this point in the history
… too costly
  • Loading branch information
liach committed Sep 4, 2024
1 parent ceb3db0 commit 3b92745
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
*/
package jdk.internal.classfile.impl;

import java.lang.classfile.Opcode;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
Expand All @@ -34,11 +32,7 @@
import jdk.internal.util.Preconditions;
import jdk.internal.vm.annotation.Stable;

import static java.lang.classfile.ClassFile.ASTORE_3;
import static java.lang.classfile.ClassFile.ISTORE;
import static java.lang.classfile.ClassFile.LOOKUPSWITCH;
import static java.lang.classfile.ClassFile.TABLESWITCH;
import static java.lang.classfile.ClassFile.WIDE;
import static java.lang.classfile.ClassFile.*;

public final class RawBytecodeHelper {

Expand All @@ -58,22 +52,42 @@ public RawBytecodeHelper start() {

public static final int ILLEGAL = -1;

private static final @Stable byte[] LENGTHS;

static {
var lengths = new byte[0x100];
Arrays.fill(lengths, (byte) -1);
for (var op : Opcode.values()) {
if (!op.isWide()) {
lengths[op.bytecode()] = (byte) op.sizeIfFixed();
} else {
// Wide pseudo-opcodes have double the length as normal variants
// Must match logic in checkSpecialInstruction()
assert lengths[op.bytecode() & 0xFF] * 2 == op.sizeIfFixed();
}
}
LENGTHS = lengths;
}
/**
* The length of opcodes, 0 for
* This is generated as if:
* {@snippet lang=java :
* var lengths = new byte[0x100];
* Arrays.fill(lengths, (byte) -1);
* for (var op : Opcode.values()) {
* if (!op.isWide()) {
* lengths[op.bytecode()] = (byte) op.sizeIfFixed();
* } else {
* // Wide pseudo-opcodes have double the length as normal variants
* // Must match logic in checkSpecialInstruction()
* assert lengths[op.bytecode() & 0xFF] * 2 == op.sizeIfFixed();
* }
* }
* }
* Tested in UtilTest.
*/
public 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, 2, 2, 2, 2, 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, 2, 2, 2, 2, 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, 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, -1, -1, 1, 1, 1, 1,
1, 1, 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 2, 3, 1, 1,
3, 3, 1, 1, -1, 4, 3, 3, 5, 5, -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,
};

public static boolean isStoreIntoLocal(int code) {
return (ISTORE <= code && code <= ASTORE_3);
Expand Down Expand Up @@ -232,11 +246,12 @@ public void next() {
int len = LENGTHS[code];
opcode = code;
isWide = false;
if (len < 0) {
// Consider using 0 vs -1 to represent invalid vs special
if (len <= 0) {
len = checkSpecialInstruction(code);
}

if (len < 0 || (nextBci += len) > endBci()) {
if (len <= 0 || (nextBci += len) > endBci()) {
opcode = ILLEGAL;
}
}
Expand Down
26 changes: 25 additions & 1 deletion test/jdk/jdk/classfile/UtilTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2022, 2024, 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 All @@ -26,7 +26,14 @@
* @summary Testing ClassFile Util.
* @run junit UtilTest
*/
import java.lang.classfile.ClassFile;
import java.lang.classfile.Opcode;
import java.lang.constant.MethodTypeDesc;
import java.lang.invoke.MethodHandles;
import java.util.Arrays;
import java.util.BitSet;

import jdk.internal.classfile.impl.RawBytecodeHelper;
import jdk.internal.classfile.impl.Util;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
Expand Down Expand Up @@ -76,4 +83,21 @@ void testParameterSlots() {
private void assertSlots(String methodDesc, int slots) {
assertEquals(Util.parameterSlots(MethodTypeDesc.ofDescriptor(methodDesc)), slots);
}

@Test
void testOpcodeLengthTable() {
var lengths = new byte[0x100];
Arrays.fill(lengths, (byte) -1);
for (var op : Opcode.values()) {
if (!op.isWide()) {
lengths[op.bytecode()] = (byte) op.sizeIfFixed();
} else {
// Wide pseudo-opcodes have double the length as normal variants
// Must match logic in checkSpecialInstruction()
assertEquals(op.sizeIfFixed(), lengths[op.bytecode() & 0xFF] * 2, op + " size");
}
}

assertArrayEquals(lengths, RawBytecodeHelper.LENGTHS);
}
}

0 comments on commit 3b92745

Please sign in to comment.