11/*
2- * Copyright (c) 2015, 2022 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2015, 2024 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
2323
2424package jdk .jfr .event .compiler ;
2525
26- import jdk .internal .org .objectweb .asm .*;
2726import jdk .jfr .Recording ;
2827import jdk .jfr .consumer .RecordedEvent ;
2928import jdk .jfr .consumer .RecordedMethod ;
3534import jdk .test .whitebox .WhiteBox ;
3635
3736import java .io .IOException ;
37+ import java .lang .classfile .ClassModel ;
38+ import java .lang .classfile .ClassFile ;
39+ import java .lang .classfile .Instruction ;
40+ import java .lang .classfile .instruction .InvokeInstruction ;
41+ import java .lang .constant .ClassDesc ;
42+ import java .lang .constant .MethodTypeDesc ;
3843import java .lang .reflect .Constructor ;
3944import java .lang .reflect .Executable ;
4045import java .lang .reflect .Method ;
4146import java .util .*;
4247import java .util .stream .IntStream ;
48+ import java .util .stream .Stream ;
4349
44- /**
50+ import static java .lang .constant .ConstantDescs .CD_Object ;
51+ import static java .lang .constant .ConstantDescs .CD_void ;
52+ import static java .lang .constant .ConstantDescs .INIT_NAME ;
53+
54+ /*
4555 * @test CompilerInliningTest
4656 * @bug 8073607
4757 * @key jfr
5060 *
5161 * @requires vm.opt.Inline == true | vm.opt.Inline == null
5262 * @library /test/lib
53- * @modules java.base/ jdk.internal.org.objectweb.asm
54- * jdk.jfr
63+ * @modules jdk.jfr
64+ * @enablePreview
5565 *
5666 * @build jdk.test.whitebox.WhiteBox
5767 * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox
@@ -64,7 +74,7 @@ public class TestCompilerInlining {
6474 private static final int LEVEL_SIMPLE = 1 ;
6575 private static final int LEVEL_FULL_OPTIMIZATION = 4 ;
6676 private static final Executable ENTRY_POINT = getConstructor (TestCase .class );
67- private static final String TEST_CASE_CLASS_NAME = TestCase .class .getName ().replace ( '.' , '/' );
77+ private static final ClassDesc CD_TestCase = TestCase .class .describeConstable ().orElseThrow ( );
6878
6979 public static void main (String [] args ) throws Exception {
7080 InlineCalls inlineCalls = new InlineCalls (TestCase .class );
@@ -100,8 +110,8 @@ private static void testLevel(Map<Call, Boolean> expectedResult, int level) thro
100110 MethodDesc caller = methodToMethodDesc (callerObject );
101111 MethodDesc callee = ciMethodToMethodDesc (calleeObject );
102112 // only TestCase.* -> TestCase.* OR TestCase.* -> Object.<init> are tested/filtered
103- if (caller .className .equals (TEST_CASE_CLASS_NAME ) && (callee .className .equals (TEST_CASE_CLASS_NAME )
104- || (callee .className .equals ("java/lang/Object" ) && callee .methodName .equals ("<init>" )))) {
113+ if (caller .className .equals (CD_TestCase ) && (callee .className .equals (CD_TestCase )
114+ || (callee .className .equals (CD_Object ) && callee .methodName .equals (INIT_NAME )))) {
105115 System .out .println (event );
106116 boolean succeeded = (boolean ) event .getValue ("succeeded" );
107117 int bci = Events .assertField (event , "bci" ).atLeast (0 ).getValue ();
@@ -132,17 +142,17 @@ private static int[] determineAvailableLevels() {
132142 }
133143
134144 private static MethodDesc methodToMethodDesc (RecordedMethod method ) {
135- String internalClassName = method .getType ().getName (). replace ( '.' , '/' );
145+ ClassDesc classDesc = ClassDesc . of ( method .getType ().getName ());
136146 String methodName = method .getValue ("name" );
137- String methodDescriptor = method .getValue ("descriptor" );
138- return new MethodDesc (internalClassName , methodName , methodDescriptor );
147+ MethodTypeDesc methodDescriptor = MethodTypeDesc . ofDescriptor ( method .getValue ("descriptor" ) );
148+ return new MethodDesc (classDesc , methodName , methodDescriptor );
139149 }
140150
141151 private static MethodDesc ciMethodToMethodDesc (RecordedObject ciMethod ) {
142- String internalClassName = ciMethod .getValue ("type" );
152+ ClassDesc classDesc = ClassDesc . ofInternalName ( ciMethod .getValue ("type" ) );
143153 String methodName = ciMethod .getValue ("name" );
144- String methodDescriptor = ciMethod .getValue ("descriptor" );
145- return new MethodDesc (internalClassName , methodName , methodDescriptor );
154+ MethodTypeDesc methodDescriptor = MethodTypeDesc . ofDescriptor ( ciMethod .getValue ("descriptor" ) );
155+ return new MethodDesc (classDesc , methodName , methodDescriptor );
146156 }
147157
148158 private static Method getMethod (Class <?> aClass , String name , Class <?>... params ) {
@@ -246,35 +256,33 @@ public String toString() {
246256 * data structure for method description
247257 */
248258class MethodDesc {
249- public final String className ;
259+ public final ClassDesc className ;
250260 public final String methodName ;
251- public final String descriptor ;
252-
253- public MethodDesc (Class <?> aClass , String methodName , String descriptor ) {
254- this (aClass .getName ().replace ('.' , '/' ), methodName , descriptor );
255- }
261+ public final MethodTypeDesc descriptor ;
256262
257- public MethodDesc (String className , String methodName , String descriptor ) {
263+ public MethodDesc (ClassDesc className , String methodName , MethodTypeDesc descriptor ) {
258264 Objects .requireNonNull (className );
259265 Objects .requireNonNull (methodName );
260266 Objects .requireNonNull (descriptor );
261- this .className = className . replace ( '.' , '/' ) ;
267+ this .className = className ;
262268 this .methodName = methodName ;
263269 this .descriptor = descriptor ;
264270 }
265271
266272 public MethodDesc (Executable executable ) {
267- Class <?> aClass = executable .getDeclaringClass ();
268- className = Type . getInternalName ( aClass ). replace ( '.' , '/' ) ;
273+ className = executable .getDeclaringClass (). describeConstable (). orElseThrow ();
274+ ClassDesc retType ;
269275
270- if (executable instanceof Constructor <?>) {
271- methodName = "<init>" ;
272- descriptor = Type .getConstructorDescriptor ((Constructor <?>) executable );
273- } else {
276+ if (executable instanceof Method method ) {
274277 methodName = executable .getName ();
275- descriptor = Type .getMethodDescriptor ((Method ) executable );
278+ retType = method .getReturnType ().describeConstable ().orElseThrow ();
279+ } else {
280+ methodName = INIT_NAME ;
281+ retType = CD_void ;
276282 }
277283
284+ descriptor = MethodTypeDesc .of (retType , Stream .of (executable .getParameterTypes ())
285+ .map (c -> c .describeConstable ().orElseThrow ()).toArray (ClassDesc []::new ));
278286 }
279287
280288 @ Override
@@ -361,43 +369,41 @@ public void forceInline(Executable executable) {
361369
362370 private static Collection <Call > getCalls (Class <?> aClass ) {
363371 List <Call > calls = new ArrayList <>();
364- ClassWriter cw ;
365- ClassReader cr ;
372+ ClassModel clm ;
366373 try {
367- cr = new ClassReader (aClass .getName ());
374+ var stream = ClassLoader .getSystemResourceAsStream (aClass .getName ()
375+ .replace ('.' , '/' ) + ".class" );
376+ if (stream == null ) {
377+ throw new IOException ("Cannot find class file for " + aClass .getName ());
378+ }
379+ clm = ClassFile .of ().parse (stream .readAllBytes ());
368380 } catch (IOException e ) {
369381 throw new Error ("TESTBUG : unexpected IOE during class reading" , e );
370382 }
371- cw = new ClassWriter (cr , 0 );
372- ClassVisitor cv = new ClassVisitor (Opcodes .ASM7 , cw ) {
373- @ Override
374- public MethodVisitor visitMethod (int access , String name , String desc , String descriptor , String [] exceptions ) {
375- System .out .println ("Method: " +name );
376- MethodVisitor mv = super .visitMethod (access , name , desc , descriptor , exceptions );
377- return new CallTracer (aClass , name , desc , mv , calls );
378- }
379- };
380- cr .accept (cv , 0 );
381383
384+ clm .methods ().forEach (mm -> {
385+ System .out .println ("Method: " + mm .methodName ().stringValue ());
386+ mm .code ().ifPresent (com -> {
387+ MethodDesc caller = new MethodDesc (
388+ clm .thisClass ().asSymbol (),
389+ mm .methodName ().stringValue (),
390+ mm .methodTypeSymbol ()
391+ );
392+ int offset = 0 ;
393+ for (var ce : com .elements ()) {
394+ if (ce instanceof Instruction ins ) {
395+ if (ins instanceof InvokeInstruction inv ) {
396+ calls .add (new Call (caller , new MethodDesc (
397+ inv .owner ().asSymbol (),
398+ inv .name ().stringValue (),
399+ inv .typeSymbol ()
400+ ), offset ));
401+ }
402+ offset += ins .sizeInBytes ();
403+ }
404+ }
405+ });
406+ });
382407 return calls ;
383408 }
384-
385- private static class CallTracer extends MethodVisitor {
386- private final MethodDesc caller ;
387- private Collection <Call > calls ;
388-
389- public CallTracer (Class <?> aClass , String name , String desc , MethodVisitor mv , Collection <Call > calls ) {
390- super (Opcodes .ASM7 , mv );
391- caller = new MethodDesc (aClass .getName (), name , desc );
392- this .calls = calls ;
393- }
394-
395- @ Override
396- public void visitMethodInsn (int opcode , String owner , String name , String desc , boolean itf ) {
397- Label label = new Label ();
398- visitLabel (label );
399- super .visitMethodInsn (opcode , owner , name , desc , itf );
400- calls .add (new Call (caller , new MethodDesc (owner , name , desc ), label .getOffset ()));
401- }
402- }
403409}
0 commit comments