1 /*
2 * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package org.openjdk.bench.jdk.classfile;
24
25 import java.io.IOException;
26 import java.lang.classfile.Attributes;
27 import java.lang.constant.ClassDesc;
28 import java.net.URI;
29 import java.nio.file.FileSystems;
30 import java.nio.file.Files;
31 import java.util.ArrayList;
32 import java.util.List;
33 import java.lang.classfile.ClassFile;
34 import java.lang.classfile.ClassReader;
35 import java.lang.classfile.constantpool.ConstantPoolBuilder;
36 import java.lang.constant.MethodTypeDesc;
37 import jdk.internal.classfile.impl.AbstractPseudoInstruction;
38 import jdk.internal.classfile.impl.LabelContext;
39 import jdk.internal.classfile.impl.ClassFileImpl;
40 import jdk.internal.classfile.impl.RawBytecodeHelper;
41 import jdk.internal.classfile.impl.SplitConstantPool;
42 import jdk.internal.classfile.impl.StackCounter;
43 import jdk.internal.classfile.impl.StackMapGenerator;
44 import jdk.internal.classfile.impl.WritableField;
45 import org.openjdk.jmh.annotations.Benchmark;
46 import org.openjdk.jmh.annotations.BenchmarkMode;
47 import org.openjdk.jmh.annotations.Fork;
48 import org.openjdk.jmh.annotations.Level;
49 import org.openjdk.jmh.annotations.Measurement;
50 import org.openjdk.jmh.annotations.Mode;
51 import org.openjdk.jmh.annotations.Scope;
52 import org.openjdk.jmh.annotations.Setup;
53 import org.openjdk.jmh.annotations.State;
54 import org.openjdk.jmh.annotations.Warmup;
55 import org.openjdk.jmh.infra.Blackhole;
56
57 @BenchmarkMode(Mode.Throughput)
58 @State(Scope.Benchmark)
59 @Fork(value = 1, jvmArgs = {
60 "--add-exports", "java.base/jdk.internal.classfile.impl=ALL-UNNAMED"})
61 @Warmup(iterations = 2)
62 @Measurement(iterations = 8)
63 public class CodeAttributeTools {
64
65 record GenData(LabelContext labelContext,
66 ClassDesc thisClass,
67 String methodName,
68 MethodTypeDesc methodDesc,
69 boolean isStatic,
70 RawBytecodeHelper.CodeRange bytecode,
71 ConstantPoolBuilder constantPool,
72 List<AbstractPseudoInstruction.ExceptionCatchImpl> handlers) {}
73
74 List<GenData> data;
75
76 @Setup(Level.Invocation)
77 public void setup() throws IOException {
78 data = new ArrayList<>();
79 Files.walk(FileSystems.getFileSystem(URI.create("jrt:/")).getPath("modules/java.base/java")).forEach(p -> {
80 if (Files.isRegularFile(p) && p.toString().endsWith(".class")) try {
81 var clm = ClassFile.of().parse(p);
82 var thisCls = clm.thisClass().asSymbol();
83 var cp = new SplitConstantPool((ClassReader)clm.constantPool());
84 for (var m : clm.methods()) {
85 m.findAttribute(Attributes.code()).ifPresent(com -> {
86 data.add(new GenData(
87 (LabelContext)com,
88 thisCls,
89 m.methodName().stringValue(),
90 m.methodTypeSymbol(),
91 (m.flags().flagsMask() & ClassFile.ACC_STATIC) != 0,
92 RawBytecodeHelper.of(com.codeArray()),
93 cp,
94 com.exceptionHandlers().stream().map(eh -> (AbstractPseudoInstruction.ExceptionCatchImpl)eh).toList()));
95 });
96 }
97 } catch (IOException e) {
98 throw new RuntimeException(e);
99 }
100 });
101 }
102
103 @Benchmark
104 public void benchmarkStackMapsGenerator(Blackhole bh) {
105 for (var d : data) bh.consume(new StackMapGenerator(
106 d.labelContext(),
107 d.thisClass(),
108 d.methodName(),
109 d.methodDesc(),
110 d.isStatic(),
111 d.bytecode(),
112 (SplitConstantPool)d.constantPool(),
113 (ClassFileImpl)ClassFile.of(),
114 WritableField.UnsetField.EMPTY_ARRAY,
115 d.handlers()));
116 }
117
118 @Benchmark
119 public void benchmarkStackCounter(Blackhole bh) {
120 for (var d : data) bh.consume(new StackCounter(
121 d.labelContext(),
122 null,
123 d.thisClass(),
124 d.methodName(),
125 d.methodDesc(),
126 d.isStatic(),
127 d.bytecode(),
128 (SplitConstantPool)d.constantPool(),
129 d.handlers()));
130 }
131 }