1 /*
2  * Copyright (c) 2016, 2018, 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 
24 
25 
26 package jdk.tools.jaotc;
27 
28 import jdk.tools.jaotc.binformat.BinaryContainer;
29 import jdk.tools.jaotc.binformat.Relocation;
30 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
31 
32 import jdk.vm.ci.code.BytecodePosition;
33 import jdk.vm.ci.code.VirtualObject;
34 import jdk.vm.ci.code.site.Call;
35 import jdk.vm.ci.code.site.Infopoint;
36 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
37 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
38 import jdk.vm.ci.meta.InvokeTarget;
39 
40 final class InfopointProcessor {
41 
42     private final DataBuilder dataBuilder;
43 
44     private final BinaryContainer binaryContainer;
45 
InfopointProcessor(DataBuilder dataBuilder)46     InfopointProcessor(DataBuilder dataBuilder) {
47         this.dataBuilder = dataBuilder;
48         this.binaryContainer = dataBuilder.getBinaryContainer();
49     }
50 
51     /**
52      * Parse an {@link Infopoint} generated by the compiler and create all needed binary section
53      * constructs.
54      *
55      * @param methodInfo compiled method info
56      * @param info info point being processed
57      */
process(CompiledMethodInfo methodInfo, Infopoint info)58     void process(CompiledMethodInfo methodInfo, Infopoint info) {
59         switch (info.reason) {
60             case CALL:
61                 // All calls in compiled code need a symbol and relocation entry.
62                 processCallInfoPoint(methodInfo, (Call) info);
63                 break;
64             case SAFEPOINT:
65             case IMPLICIT_EXCEPTION:
66             case METHOD_START:
67             case METHOD_END:
68             case BYTECODE_POSITION:
69                 break;
70             default:
71                 throw new InternalError("Unknown info point reason: " + info.reason);
72         }
73         if (info.debugInfo == null) {
74             return;
75         }
76         BytecodePosition bcp = info.debugInfo.getBytecodePosition();
77         if (bcp == null) {
78             return;
79         }
80         recordScopeKlasses(methodInfo, bcp, info.debugInfo.getVirtualObjectMapping());
81     }
82 
recordScopeKlasses(CompiledMethodInfo methodInfo, BytecodePosition bcp, VirtualObject[] vos)83     private void recordScopeKlasses(CompiledMethodInfo methodInfo, BytecodePosition bcp, VirtualObject[] vos) {
84         BytecodePosition caller = bcp.getCaller();
85         if (caller != null) {
86             recordScopeKlasses(methodInfo, caller, vos);
87         }
88 
89         HotSpotResolvedJavaMethod m = (HotSpotResolvedJavaMethod) bcp.getMethod();
90         HotSpotResolvedObjectType klass = m.getDeclaringClass();
91         methodInfo.addDependentKlassData(binaryContainer, klass);
92 
93         if (vos == null) {
94             return;
95         }
96         for (VirtualObject vo : vos) {
97             HotSpotResolvedObjectType vk = (HotSpotResolvedObjectType) vo.getType();
98             methodInfo.addDependentKlassData(binaryContainer, vk);
99         }
100 
101     }
102 
103     /**
104      * Process Call info points in Graal generated compilation result. We want to create one of the
105      * following relocations: .text -> .hotspot.plt.linkage - Java method to Java method call .text
106      * -> .text - Java method / Graal stub to Graal stub call .text -> .plt - Java method / Graal
107      * stub to VM method call.
108      *
109      * @param methodInfo compiled method info
110      * @param call call
111      */
processCallInfoPoint(CompiledMethodInfo methodInfo, Call call)112     private void processCallInfoPoint(CompiledMethodInfo methodInfo, Call call) {
113         CallSiteRelocationInfo callSiteRelocation = getCallSiteRelocationInfo(call);
114         CallSiteRelocationSymbol callSiteRelocationSymbol = getCallSiteRelocationSymbol(methodInfo, call, callSiteRelocation);
115 
116         Relocation relocation = new Relocation(methodInfo.getTextSectionOffset() + call.pcOffset, callSiteRelocation.type, call.size, binaryContainer.getCodeContainer(),
117                         callSiteRelocationSymbol.symbol);
118         binaryContainer.addRelocation(relocation);
119     }
120 
121     /**
122      * Get information about the call site. Name of the callee and relocation call type.
123      */
getCallSiteRelocationInfo(Call call)124     private static CallSiteRelocationInfo getCallSiteRelocationInfo(Call call) {
125         InvokeTarget callTarget = call.target;
126         if (callTarget instanceof HotSpotResolvedJavaMethod) {
127             return new JavaCallSiteRelocationInfo(call, (HotSpotResolvedJavaMethod) callTarget);
128         } else if (callTarget instanceof HotSpotForeignCallLinkage) {
129             return new ForeignCallSiteRelocationInfo(call, (HotSpotForeignCallLinkage) callTarget);
130         } else {
131             throw new InternalError("Unhandled call type found in infopoint: " + callTarget);
132         }
133     }
134 
135     /**
136      * Return a relocation symbol for the given call site.
137      */
getCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation)138     private CallSiteRelocationSymbol getCallSiteRelocationSymbol(CompiledMethodInfo mi, Call call, CallSiteRelocationInfo callSiteRelocation) {
139         switch (callSiteRelocation.type) {
140             case STUB_CALL_DIRECT:
141                 return new StubDirectCallSiteRelocationSymbol(callSiteRelocation, binaryContainer);
142             case FOREIGN_CALL_INDIRECT_GOT:
143                 return new ForeignGotCallSiteRelocationSymbol(mi, call, callSiteRelocation, dataBuilder);
144             default:
145                 return new JavaCallSiteRelocationSymbol(mi, call, callSiteRelocation, binaryContainer);
146         }
147     }
148 
149 }
150