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 org.openjdk.jmh.annotations.Benchmark;
45 import org.openjdk.jmh.annotations.BenchmarkMode;
46 import org.openjdk.jmh.annotations.Fork;
47 import org.openjdk.jmh.annotations.Level;
48 import org.openjdk.jmh.annotations.Measurement;
49 import org.openjdk.jmh.annotations.Mode;
50 import org.openjdk.jmh.annotations.Scope;
51 import org.openjdk.jmh.annotations.Setup;
52 import org.openjdk.jmh.annotations.State;
53 import org.openjdk.jmh.annotations.Warmup;
54 import org.openjdk.jmh.infra.Blackhole;
55
56 @BenchmarkMode(Mode.Throughput)
57 @State(Scope.Benchmark)
58 @Fork(value = 1, jvmArgs = {
59 "--add-exports", "java.base/jdk.internal.classfile.impl=ALL-UNNAMED"})
60 @Warmup(iterations = 2)
61 @Measurement(iterations = 8)
62 public class CodeAttributeTools {
63
64 record GenData(LabelContext labelContext,
65 ClassDesc thisClass,
66 String methodName,
67 MethodTypeDesc methodDesc,
68 boolean isStatic,
69 RawBytecodeHelper.CodeRange bytecode,
70 ConstantPoolBuilder constantPool,
71 List<AbstractPseudoInstruction.ExceptionCatchImpl> handlers) {}
72
73 List<GenData> data;
74
75 @Setup(Level.Invocation)
76 public void setup() throws IOException {
77 data = new ArrayList<>();
78 Files.walk(FileSystems.getFileSystem(URI.create("jrt:/")).getPath("modules/java.base/java")).forEach(p -> {
79 if (Files.isRegularFile(p) && p.toString().endsWith(".class")) try {
80 var clm = ClassFile.of().parse(p);
81 var thisCls = clm.thisClass().asSymbol();
82 var cp = new SplitConstantPool((ClassReader)clm.constantPool());
83 for (var m : clm.methods()) {
84 m.findAttribute(Attributes.code()).ifPresent(com -> {
85 data.add(new GenData(
86 (LabelContext)com,
87 thisCls,
88 m.methodName().stringValue(),
89 m.methodTypeSymbol(),
90 (m.flags().flagsMask() & ClassFile.ACC_STATIC) != 0,
91 RawBytecodeHelper.of(com.codeArray()),
92 cp,
93 com.exceptionHandlers().stream().map(eh -> (AbstractPseudoInstruction.ExceptionCatchImpl)eh).toList()));
94 });
95 }
96 } catch (IOException e) {
97 throw new RuntimeException(e);
98 }
99 });
100 }
101
102 @Benchmark
103 public void benchmarkStackMapsGenerator(Blackhole bh) {
104 for (var d : data) bh.consume(new StackMapGenerator(
105 d.labelContext(),
106 d.thisClass(),
107 d.methodName(),
108 d.methodDesc(),
109 d.isStatic(),
110 d.bytecode(),
111 (SplitConstantPool)d.constantPool(),
112 (ClassFileImpl)ClassFile.of(),
113 d.handlers()));
114 }
115
116 @Benchmark
117 public void benchmarkStackCounter(Blackhole bh) {
118 for (var d : data) bh.consume(new StackCounter(
119 d.labelContext(),
120 null,
121 d.thisClass(),
122 d.methodName(),
123 d.methodDesc(),
124 d.isStatic(),
125 d.bytecode(),
126 (SplitConstantPool)d.constantPool(),
127 d.handlers()));
128 }
129 }
--- EOF ---