Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/openjdk/jdk into docs/cf-…
Browse files Browse the repository at this point in the history
…instruction
  • Loading branch information
liach committed Dec 4, 2024
2 parents ecda715 + 79eb77b commit cda30b1
Show file tree
Hide file tree
Showing 33 changed files with 54 additions and 158 deletions.
1 change: 1 addition & 0 deletions make/test/BuildMicrobenchmark.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
SRC := $(MICROBENCHMARK_SRC), \
BIN := $(MICROBENCHMARK_CLASSES), \
JAVAC_FLAGS := \
--add-exports java.base/jdk.internal.classfile.components=ALL-UNNAMED \
--add-exports java.base/jdk.internal.classfile.impl=ALL-UNNAMED \
--add-exports java.base/jdk.internal.event=ALL-UNNAMED \
--add-exports java.base/jdk.internal.foreign=ALL-UNNAMED \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,12 +60,7 @@
* its state must be reset for each traversal; this will happen automatically if
* the transform is created with {@link ClassTransform#ofStateful(Supplier)} (or
* corresponding methods for other classfile locations.)
* <p>
* Class transformation sample where code transformation is stateful:
* {@snippet lang="java" class="PackageSnippets" region="codeRelabeling"}
* <p>
* Complex class instrumentation sample chaining multiple transformations:
* {@snippet lang="java" class="PackageSnippets" region="classInstrumentation"}
*
* @param <C> the transform type
* @param <E> the element type
* @param <B> the builder type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,13 @@
package java.lang.classfile.snippets;

import java.lang.classfile.*;
import java.lang.classfile.components.ClassRemapper;
import java.lang.classfile.components.CodeLocalsShifter;
import java.lang.classfile.components.CodeRelabeler;
import java.lang.classfile.instruction.*;
import java.lang.constant.ClassDesc;
import java.lang.constant.ConstantDescs;
import java.lang.constant.MethodTypeDesc;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.AccessFlag;
import java.util.ArrayDeque;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static java.util.stream.Collectors.toSet;
Expand Down Expand Up @@ -326,82 +318,6 @@ void fooToBarUnrolled(ClassModel classModel) {
// @end
}

void codeRelabeling(ClassModel classModel) {
// @start region="codeRelabeling"
byte[] newBytes = ClassFile.of().transformClass(classModel,
ClassTransform.transformingMethodBodies(
CodeTransform.ofStateful(CodeRelabeler::of)));
// @end
}

// @start region="classInstrumentation"
byte[] classInstrumentation(ClassModel target, ClassModel instrumentor, Predicate<MethodModel> instrumentedMethodsFilter) {
var instrumentorCodeMap = instrumentor.methods().stream()
.filter(instrumentedMethodsFilter)
.collect(Collectors.toMap(mm -> mm.methodName().stringValue() + mm.methodType().stringValue(), mm -> mm.code().orElseThrow()));
var targetFieldNames = target.fields().stream().map(f -> f.fieldName().stringValue()).collect(Collectors.toSet());
var targetMethods = target.methods().stream().map(m -> m.methodName().stringValue() + m.methodType().stringValue()).collect(Collectors.toSet());
var instrumentorClassRemapper = ClassRemapper.of(Map.of(instrumentor.thisClass().asSymbol(), target.thisClass().asSymbol()));
return ClassFile.of().transformClass(target,
ClassTransform.transformingMethods(
instrumentedMethodsFilter,
(mb, me) -> {
if (me instanceof CodeModel targetCodeModel) {
var mm = targetCodeModel.parent().get();
//instrumented methods code is taken from instrumentor
mb.transformCode(instrumentorCodeMap.get(mm.methodName().stringValue() + mm.methodType().stringValue()),
//all references to the instrumentor class are remapped to target class
instrumentorClassRemapper.asCodeTransform()
.andThen((codeBuilder, instrumentorCodeElement) -> {
//all invocations of target methods from instrumentor are inlined
if (instrumentorCodeElement instanceof InvokeInstruction inv
&& target.thisClass().asInternalName().equals(inv.owner().asInternalName())
&& mm.methodName().stringValue().equals(inv.name().stringValue())
&& mm.methodType().stringValue().equals(inv.type().stringValue())) {

//store stacked method parameters into locals
var storeStack = new ArrayDeque<StoreInstruction>();
int slot = 0;
if (!mm.flags().has(AccessFlag.STATIC))
storeStack.push(StoreInstruction.of(TypeKind.REFERENCE, slot++));
for (var pt : mm.methodTypeSymbol().parameterList()) {
var tk = TypeKind.from(pt);
storeStack.push(StoreInstruction.of(tk, slot));
slot += tk.slotSize();
}
storeStack.forEach(codeBuilder::with);

//inlined target locals must be shifted based on the actual instrumentor locals
codeBuilder.block(inlinedBlockBuilder -> inlinedBlockBuilder
.transform(targetCodeModel, CodeLocalsShifter.of(mm.flags(), mm.methodTypeSymbol())
.andThen(CodeRelabeler.of())
.andThen((innerBuilder, shiftedTargetCode) -> {
//returns must be replaced with jump to the end of the inlined method
if (shiftedTargetCode instanceof ReturnInstruction)
innerBuilder.goto_(inlinedBlockBuilder.breakLabel());
else
innerBuilder.with(shiftedTargetCode);
})));
} else
codeBuilder.with(instrumentorCodeElement);
}));
} else
mb.with(me);
})
.andThen(ClassTransform.endHandler(clb ->
//remaining instrumentor fields and methods are injected at the end
clb.transform(instrumentor,
ClassTransform.dropping(cle ->
!(cle instanceof FieldModel fm
&& !targetFieldNames.contains(fm.fieldName().stringValue()))
&& !(cle instanceof MethodModel mm
&& !ConstantDescs.INIT_NAME.equals(mm.methodName().stringValue())
&& !targetMethods.contains(mm.methodName().stringValue() + mm.methodType().stringValue())))
//and instrumentor class references remapped to target class
.andThen(instrumentorClassRemapper)))));
}
// @end

void resolverExample() {
// @start region="lookup-class-hierarchy-resolver"
MethodHandles.Lookup lookup = MethodHandles.lookup(); // @replace regex="MethodHandles\.lookup\(\)" replacement="..."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.classfile.components;
package jdk.internal.classfile.components;

import java.lang.classfile.ClassModel;
import java.lang.classfile.CodeModel;
Expand Down Expand Up @@ -58,8 +58,6 @@
* <p>
* Another use case for {@link ClassPrinter} is to simplify writing of automated tests:
* {@snippet lang="java" class="PackageSnippets" region="printNodesInTest"}
*
* @since 24
*/
public final class ClassPrinter {

Expand All @@ -68,8 +66,6 @@ private ClassPrinter() {

/**
* Level of detail to print or export.
*
* @since 24
*/
public enum Verbosity {

Expand Down Expand Up @@ -102,8 +98,6 @@ public enum Verbosity {

/**
* Named, traversable, and printable node parent.
*
* @since 24
*/
public sealed interface Node {

Expand Down Expand Up @@ -146,8 +140,6 @@ default void toYaml(Consumer<String> out) {

/**
* A leaf node holding single printable value.
*
* @since 24
*/
public sealed interface LeafNode extends Node
permits ClassPrinterImpl.LeafNodeImpl {
Expand All @@ -161,8 +153,6 @@ public sealed interface LeafNode extends Node

/**
* A tree node holding {@link List} of nested nodes.
*
* @since 24
*/
public sealed interface ListNode extends Node, List<Node>
permits ClassPrinterImpl.ListNodeImpl {
Expand All @@ -172,8 +162,6 @@ public sealed interface ListNode extends Node, List<Node>
* A tree node holding {@link Map} of nested nodes.
* <p>
* Each {@link Map.Entry#getKey()} == {@link Map.Entry#getValue()}.{@link #name()}.
*
* @since 24
*/
public sealed interface MapNode extends Node, Map<ConstantDesc, Node>
permits ClassPrinterImpl.MapNodeImpl {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.classfile.components;
package jdk.internal.classfile.components;

import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassModel;
Expand Down Expand Up @@ -53,8 +53,6 @@
* <p>
* Arrays of reference types are always decomposed, mapped as the base reference
* types and composed back to arrays.
*
* @since 24
*/
public sealed interface ClassRemapper extends ClassTransform permits ClassRemapperImpl {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.classfile.components;
package jdk.internal.classfile.components;

import java.lang.classfile.AccessFlags;
import java.lang.classfile.CodeTransform;
Expand All @@ -37,8 +37,6 @@
* newly allocated positions to avoid conflicts during code injection.
* Locals pointing to the receiver or to method arguments slots are never shifted.
* All locals pointing beyond the method arguments are re-indexed in order of appearance.
*
* @since 24
*/
public sealed interface CodeLocalsShifter extends CodeTransform permits CodeLocalsShifterImpl {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.classfile.components;
package jdk.internal.classfile.components;

import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeTransform;
Expand All @@ -44,8 +44,6 @@
* Primary purpose of CodeRelabeler is for repeated injections of the same code blocks.
* Repeated injection of the same code block must be relabeled, so each instance of
* {@link java.lang.classfile.Label} is bound in the target bytecode exactly once.
*
* @since 24
*/
public sealed interface CodeRelabeler extends CodeTransform permits CodeRelabelerImpl {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.lang.classfile.components;
package jdk.internal.classfile.components;

import java.lang.classfile.CodeTransform;
import java.lang.classfile.Label;
Expand All @@ -49,8 +49,6 @@
* int maxStack = stackTracker.maxStackSize().get();
* });
* }
*
* @since 24
*/
public sealed interface CodeStackTracker extends CodeTransform permits CodeStackTrackerImpl {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,6 @@
* CodeLocalsShifter} and {@link CodeRelabeler} into fully functional class
* instrumenting transformation:
* {@snippet lang="java" class="PackageSnippets" region="classInstrumentation"}
*
* @since 24
*/
package java.lang.classfile.components;
package jdk.internal.classfile.components;

Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@
package java.lang.classfile.components.snippets;

import java.lang.classfile.*;
import java.lang.classfile.components.ClassPrinter;
import java.lang.classfile.components.ClassRemapper;
import java.lang.classfile.components.CodeLocalsShifter;
import java.lang.classfile.components.CodeRelabeler;
import jdk.internal.classfile.components.ClassPrinter;
import jdk.internal.classfile.components.ClassRemapper;
import jdk.internal.classfile.components.CodeLocalsShifter;
import jdk.internal.classfile.components.CodeRelabeler;
import java.lang.classfile.instruction.InvokeInstruction;
import java.lang.classfile.instruction.ReturnInstruction;
import java.lang.classfile.instruction.StoreInstruction;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@
import java.lang.classfile.attribute.StackMapFrameInfo.SimpleVerificationTypeInfo;
import java.lang.classfile.attribute.StackMapFrameInfo.UninitializedVerificationTypeInfo;
import java.lang.classfile.attribute.StackMapFrameInfo.VerificationTypeInfo;
import java.lang.classfile.components.ClassPrinter.LeafNode;
import java.lang.classfile.components.ClassPrinter.ListNode;
import java.lang.classfile.components.ClassPrinter.MapNode;
import java.lang.classfile.components.ClassPrinter.Node;
import java.lang.classfile.components.ClassPrinter.Verbosity;
import jdk.internal.classfile.components.ClassPrinter.LeafNode;
import jdk.internal.classfile.components.ClassPrinter.ListNode;
import jdk.internal.classfile.components.ClassPrinter.MapNode;
import jdk.internal.classfile.components.ClassPrinter.Node;
import jdk.internal.classfile.components.ClassPrinter.Verbosity;
import java.lang.classfile.constantpool.*;
import java.lang.classfile.instruction.*;
import java.lang.constant.ConstantDesc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import java.lang.classfile.*;
import java.lang.classfile.attribute.*;
import java.lang.classfile.components.ClassRemapper;
import jdk.internal.classfile.components.ClassRemapper;
import java.lang.classfile.constantpool.Utf8Entry;
import java.lang.classfile.instruction.ConstantInstruction.LoadConstantInstruction;
import java.lang.classfile.instruction.*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import java.lang.classfile.CodeElement;
import java.lang.classfile.Signature;
import java.lang.classfile.TypeKind;
import java.lang.classfile.components.CodeLocalsShifter;
import jdk.internal.classfile.components.CodeLocalsShifter;
import java.lang.classfile.instruction.IncrementInstruction;
import java.lang.classfile.instruction.LoadInstruction;
import java.lang.classfile.instruction.LocalVariable;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.CodeElement;
import java.lang.classfile.Label;
import java.lang.classfile.components.CodeRelabeler;
import jdk.internal.classfile.components.CodeRelabeler;
import java.lang.classfile.instruction.*;
import java.util.function.BiFunction;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import java.lang.classfile.Label;
import java.lang.classfile.Opcode;
import java.lang.classfile.TypeKind;
import java.lang.classfile.components.CodeStackTracker;
import jdk.internal.classfile.components.CodeStackTracker;
import java.lang.classfile.instruction.*;
import java.util.*;
import java.util.function.Consumer;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import java.lang.classfile.*;
import java.lang.classfile.attribute.CodeAttribute;
import java.lang.classfile.components.ClassPrinter;
import jdk.internal.classfile.components.ClassPrinter;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.classfile.constantpool.ModuleEntry;
import java.lang.classfile.constantpool.PoolEntry;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

import java.lang.classfile.ClassHierarchyResolver;
import java.lang.classfile.ClassModel;
import java.lang.classfile.components.ClassPrinter;
import jdk.internal.classfile.components.ClassPrinter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
Expand Down
3 changes: 2 additions & 1 deletion src/java.base/share/classes/module-info.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@
exports java.lang.annotation;
exports java.lang.classfile;
exports java.lang.classfile.attribute;
exports java.lang.classfile.components;
exports java.lang.classfile.constantpool;
exports java.lang.classfile.instruction;
exports java.lang.constant;
Expand Down Expand Up @@ -177,6 +176,8 @@
jdk.net,
jdk.sctp,
jdk.crypto.cryptoki;
exports jdk.internal.classfile.components to
jdk.jfr;
exports jdk.internal.foreign to
jdk.incubator.vector;
exports jdk.internal.event to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
import java.lang.classfile.CodeBuilder;
import java.lang.classfile.ClassModel;
import java.lang.classfile.ClassFile;
import java.lang.classfile.components.ClassPrinter;
import jdk.internal.classfile.components.ClassPrinter;

/**
* Helper class when working with bytecode.
Expand Down
Loading

0 comments on commit cda30b1

Please sign in to comment.