Mercurial > hg > truffle
annotate graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/stubs/DeoptimizationStub.java @ 21708:6df25b1418be
moved com.oracle.asm.** to jvmci-util.jar (JBS:GRAAL-53)
author | Doug Simon <doug.simon@oracle.com> |
---|---|
date | Wed, 03 Jun 2015 18:06:44 +0200 |
parents | 48c1ebd24120 |
children | d915361cc3a1 |
rev | line source |
---|---|
15104 | 1 /* |
2 * Copyright (c) 2013, 2014, 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 com.oracle.graal.hotspot.stubs; | |
24 | |
21708
6df25b1418be
moved com.oracle.asm.** to jvmci-util.jar (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21556
diff
changeset
|
25 import com.oracle.jvmci.asm.*; |
21556
48c1ebd24120
renamed com.oracle.graal.api[meta|code] modules to com.oracle.jvmci.[meta|code] (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21551
diff
changeset
|
26 import com.oracle.jvmci.code.Register; |
48c1ebd24120
renamed com.oracle.graal.api[meta|code] modules to com.oracle.jvmci.[meta|code] (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21551
diff
changeset
|
27 import com.oracle.jvmci.code.TargetDescription; |
48c1ebd24120
renamed com.oracle.graal.api[meta|code] modules to com.oracle.jvmci.[meta|code] (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21551
diff
changeset
|
28 import com.oracle.jvmci.meta.ForeignCallDescriptor; |
21708
6df25b1418be
moved com.oracle.asm.** to jvmci-util.jar (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21556
diff
changeset
|
29 |
15968
42eaa579e134
more improvements to runtime initialization:
Doug Simon <doug.simon@oracle.com>
parents:
15926
diff
changeset
|
30 import static com.oracle.graal.hotspot.HotSpotBackend.*; |
19462
33a783b15758
made use of Graal stubs instead of equivalent HotSpot stubs optional and off by default
Doug Simon <doug.simon@oracle.com>
parents:
18669
diff
changeset
|
31 import static com.oracle.graal.hotspot.HotSpotBackend.Options.*; |
15968
42eaa579e134
more improvements to runtime initialization:
Doug Simon <doug.simon@oracle.com>
parents:
15926
diff
changeset
|
32 import static com.oracle.graal.hotspot.nodes.DeoptimizationFetchUnrollInfoCallNode.*; |
15104 | 33 import static com.oracle.graal.hotspot.replacements.HotSpotReplacementsUtil.*; |
19462
33a783b15758
made use of Graal stubs instead of equivalent HotSpot stubs optional and off by default
Doug Simon <doug.simon@oracle.com>
parents:
18669
diff
changeset
|
34 import static com.oracle.graal.hotspot.stubs.UncommonTrapStub.*; |
15104 | 35 |
18370
6713fef8c859
Make the @Fold annotation a top-level interface in the api project. It is not tied to the Snippet class where it was located before.
Christian Wimmer <christian.wimmer@oracle.com>
parents:
16441
diff
changeset
|
36 import com.oracle.graal.api.replacements.*; |
15104 | 37 import com.oracle.graal.graph.Node.ConstantNodeParameter; |
38 import com.oracle.graal.graph.Node.NodeIntrinsic; | |
39 import com.oracle.graal.hotspot.*; | |
40 import com.oracle.graal.hotspot.meta.*; | |
41 import com.oracle.graal.hotspot.nodes.*; | |
42 import com.oracle.graal.replacements.*; | |
15926
af0e42dad358
reduced time to initialize ForeignCallProviders by avoiding triggering class initialization of Node subclasses as well as making annotation parsing lazy in SnippetInfo
Doug Simon <doug.simon@oracle.com>
parents:
15456
diff
changeset
|
43 import com.oracle.graal.replacements.Snippet.ConstantParameter; |
15104 | 44 import com.oracle.graal.word.*; |
21543
93c50cefb9e8
moved GraalInternalError to com.oracle.jvmci.common and renamed it to JVMCIError (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21526
diff
changeset
|
45 import com.oracle.jvmci.common.*; |
21551
5324104ac4f3
moved com.oracle.graal.hotspot.jvmci classes to com.oracle.jvmci.hotspot module (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21543
diff
changeset
|
46 import com.oracle.jvmci.hotspot.*; |
15104 | 47 |
48 /** | |
49 * Deoptimization stub. | |
50 * | |
51 * This is the entry point for code which is returning to a de-optimized frame. | |
52 * | |
53 * The steps taken by this frame are as follows: | |
54 * | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
55 * <li>push a dummy "register_save" and save the return values (O0, O1, F0/F1, G1) and all |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
56 * potentially live registers (at a pollpoint many registers can be live). |
15104 | 57 * |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
58 * <li>call the C routine: Deoptimization::fetch_unroll_info (this function returns information |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
59 * about the number and size of interpreter frames which are equivalent to the frame which is being |
15104 | 60 * deoptimized) |
61 * | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
62 * <li>deallocate the unpack frame, restoring only results values. Other volatile registers will now |
15104 | 63 * be captured in the vframeArray as needed. |
64 * | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
65 * <li>deallocate the deoptimization frame |
15104 | 66 * |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
67 * <li>in a loop using the information returned in the previous step push new interpreter frames |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
68 * (take care to propagate the return values through each new frame pushed) |
15104 | 69 * |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
70 * <li>create a dummy "unpack_frame" and save the return values (O0, O1, F0) |
15104 | 71 * |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
72 * <li>call the C routine: Deoptimization::unpack_frames (this function lays out values on the |
15104 | 73 * interpreter frame which was just created) |
74 * | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
75 * <li>deallocate the dummy unpack_frame |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
76 * |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
77 * <li>ensure that all the return values are correctly set and then do a return to the interpreter |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
78 * entry point |
15104 | 79 * |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
80 * <p> |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
81 * <b>ATTENTION: We cannot do any complicated operations e.g. logging via printf in this snippet |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
82 * because we change the current stack layout and so the code is very sensitive to register |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
83 * allocation.</b> |
15104 | 84 */ |
85 public class DeoptimizationStub extends SnippetStub { | |
86 | |
87 private final TargetDescription target; | |
88 | |
89 public DeoptimizationStub(HotSpotProviders providers, TargetDescription target, HotSpotForeignCallLinkage linkage) { | |
19791
14e703edb2ab
use GraphBuilderPlugins for method substitutions, intrinsics and snippets (GRAAL-982)
Doug Simon <doug.simon@oracle.com>
parents:
19507
diff
changeset
|
90 super(DeoptimizationStub.class, "deoptimizationHandler", providers, linkage); |
15104 | 91 this.target = target; |
19462
33a783b15758
made use of Graal stubs instead of equivalent HotSpot stubs optional and off by default
Doug Simon <doug.simon@oracle.com>
parents:
18669
diff
changeset
|
92 assert PreferGraalStubs.getValue(); |
15104 | 93 } |
94 | |
95 @Override | |
96 public boolean preservesRegisters() { | |
97 return false; | |
98 } | |
99 | |
100 @Override | |
101 protected Object getConstantParameterValue(int index, String name) { | |
102 switch (index) { | |
103 case 0: | |
104 return providers.getRegisters().getThreadRegister(); | |
105 case 1: | |
106 return providers.getRegisters().getStackPointerRegister(); | |
107 default: | |
21543
93c50cefb9e8
moved GraalInternalError to com.oracle.jvmci.common and renamed it to JVMCIError (JBS:GRAAL-53)
Doug Simon <doug.simon@oracle.com>
parents:
21526
diff
changeset
|
108 throw JVMCIError.shouldNotReachHere("unknown parameter " + name + " at index " + index); |
15104 | 109 } |
110 } | |
111 | |
112 /** | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
113 * Deoptimization handler for normal deoptimization |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
114 * {@link HotSpotVMConfig#deoptimizationUnpackDeopt}. |
15104 | 115 */ |
116 @Snippet | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
117 private static void deoptimizationHandler(@ConstantParameter Register threadRegister, @ConstantParameter Register stackPointerRegister) { |
15104 | 118 final Word thread = registerAsWord(threadRegister); |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
119 final long registerSaver = SaveAllRegistersNode.saveAllRegisters(); |
15104 | 120 |
15968
42eaa579e134
more improvements to runtime initialization:
Doug Simon <doug.simon@oracle.com>
parents:
15926
diff
changeset
|
121 final Word unrollBlock = fetchUnrollInfo(registerSaver); |
15104 | 122 |
123 // Pop all the frames we must move/replace. | |
124 // | |
125 // Frame picture (youngest to oldest) | |
15345 | 126 // 1: self-frame |
127 // 2: deoptimizing frame | |
15104 | 128 // 3: caller of deoptimizing frame (could be compiled/interpreted). |
129 | |
130 // Pop self-frame. | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
131 LeaveCurrentStackFrameNode.leaveCurrentStackFrame(registerSaver); |
15104 | 132 |
133 // Load the initial info we should save (e.g. frame pointer). | |
134 final Word initialInfo = unrollBlock.readWord(deoptimizationUnrollBlockInitialInfoOffset()); | |
135 | |
15345 | 136 // Pop deoptimized frame. |
15104 | 137 final int sizeOfDeoptimizedFrame = unrollBlock.readInt(deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset()); |
138 LeaveDeoptimizedStackFrameNode.leaveDeoptimizedStackFrame(sizeOfDeoptimizedFrame, initialInfo); | |
139 | |
140 /* | |
141 * Stack bang to make sure there's enough room for the interpreter frames. Bang stack for | |
142 * total size of the interpreter frames plus shadow page size. Bang one page at a time | |
143 * because large sizes can bang beyond yellow and red zones. | |
19507
1cde96b96673
Fixed code format issues.
Roland Schatz <roland.schatz@oracle.com>
parents:
19462
diff
changeset
|
144 * |
15345 | 145 * @deprecated This code should go away as soon as JDK-8032410 hits the Graal repository. |
15104 | 146 */ |
147 final int totalFrameSizes = unrollBlock.readInt(deoptimizationUnrollBlockTotalFrameSizesOffset()); | |
148 final int bangPages = NumUtil.roundUp(totalFrameSizes, pageSize()) / pageSize() + stackShadowPages(); | |
149 Word stackPointer = readRegister(stackPointerRegister); | |
150 | |
151 for (int i = 1; i < bangPages; i++) { | |
19462
33a783b15758
made use of Graal stubs instead of equivalent HotSpot stubs optional and off by default
Doug Simon <doug.simon@oracle.com>
parents:
18669
diff
changeset
|
152 stackPointer.writeInt((-i * pageSize()) + stackBias(), 0, STACK_BANG_LOCATION); |
15104 | 153 } |
154 | |
155 // Load number of interpreter frames. | |
156 final int numberOfFrames = unrollBlock.readInt(deoptimizationUnrollBlockNumberOfFramesOffset()); | |
157 | |
158 // Load address of array of frame sizes. | |
159 final Word frameSizes = unrollBlock.readWord(deoptimizationUnrollBlockFrameSizesOffset()); | |
160 | |
161 // Load address of array of frame PCs. | |
162 final Word framePcs = unrollBlock.readWord(deoptimizationUnrollBlockFramePcsOffset()); | |
163 | |
164 /* | |
165 * Get the current stack pointer (sender's original SP) before adjustment so that we can | |
166 * save it in the skeletal interpreter frame. | |
167 */ | |
168 Word senderSp = readRegister(stackPointerRegister); | |
169 | |
170 // Adjust old interpreter frame to make space for new frame's extra Java locals. | |
171 final int callerAdjustment = unrollBlock.readInt(deoptimizationUnrollBlockCallerAdjustmentOffset()); | |
172 writeRegister(stackPointerRegister, readRegister(stackPointerRegister).subtract(callerAdjustment)); | |
173 | |
174 for (int i = 0; i < numberOfFrames; i++) { | |
175 final Word frameSize = frameSizes.readWord(i * wordSize()); | |
176 final Word framePc = framePcs.readWord(i * wordSize()); | |
177 | |
178 // Push an interpreter frame onto the stack. | |
179 PushInterpreterFrameNode.pushInterpreterFrame(frameSize, framePc, senderSp, initialInfo); | |
180 | |
181 // Get the current stack pointer (sender SP) and pass it to next frame. | |
182 senderSp = readRegister(stackPointerRegister); | |
183 } | |
184 | |
185 // Get final return address. | |
186 final Word framePc = framePcs.readWord(numberOfFrames * wordSize()); | |
187 | |
188 /* | |
189 * Enter a frame to call out to unpack frames. Since we changed the stack pointer to an | |
190 * unknown alignment we need to align it here before calling C++ code. | |
191 */ | |
192 final Word senderFp = initialInfo; | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
193 EnterUnpackFramesStackFrameNode.enterUnpackFramesStackFrame(framePc, senderSp, senderFp, registerSaver); |
15104 | 194 |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
195 // Pass unpack deopt mode to unpack frames. |
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
196 final int mode = deoptimizationUnpackDeopt(); |
15104 | 197 unpackFrames(UNPACK_FRAMES, thread, mode); |
198 | |
15456
bb97b75d1d65
AMD64: implemented DeoptimizationStub.deoptimizationHandler
twisti
parents:
15345
diff
changeset
|
199 LeaveUnpackFramesStackFrameNode.leaveUnpackFramesStackFrame(registerSaver); |
15104 | 200 } |
201 | |
202 /** | |
203 * Reads the value of the passed register as a Word. | |
204 */ | |
205 private static Word readRegister(Register register) { | |
206 return registerAsWord(register, false, false); | |
207 } | |
208 | |
209 /** | |
210 * Writes the value of the passed register. | |
211 * | |
212 * @param value value the register should be set to | |
213 */ | |
214 private static void writeRegister(Register register, Word value) { | |
215 writeRegisterAsWord(register, value); | |
216 } | |
217 | |
218 @Fold | |
219 private static int stackShadowPages() { | |
220 return config().useStackBanging ? config().stackShadowPages : 0; | |
221 } | |
222 | |
15345 | 223 /** |
224 * Returns the stack bias for the host architecture. | |
225 * | |
226 * @deprecated This method should go away as soon as JDK-8032410 hits the Graal repository. | |
227 * | |
228 * @return stack bias | |
229 */ | |
230 @Deprecated | |
231 @Fold | |
232 private static int stackBias() { | |
233 return config().stackBias; | |
234 } | |
235 | |
15104 | 236 @Fold |
237 private static int deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset() { | |
238 return config().deoptimizationUnrollBlockSizeOfDeoptimizedFrameOffset; | |
239 } | |
240 | |
241 @Fold | |
242 private static int deoptimizationUnrollBlockCallerAdjustmentOffset() { | |
243 return config().deoptimizationUnrollBlockCallerAdjustmentOffset; | |
244 } | |
245 | |
246 @Fold | |
247 private static int deoptimizationUnrollBlockNumberOfFramesOffset() { | |
248 return config().deoptimizationUnrollBlockNumberOfFramesOffset; | |
249 } | |
250 | |
251 @Fold | |
252 private static int deoptimizationUnrollBlockTotalFrameSizesOffset() { | |
253 return config().deoptimizationUnrollBlockTotalFrameSizesOffset; | |
254 } | |
255 | |
256 @Fold | |
257 private static int deoptimizationUnrollBlockFrameSizesOffset() { | |
258 return config().deoptimizationUnrollBlockFrameSizesOffset; | |
259 } | |
260 | |
261 @Fold | |
262 private static int deoptimizationUnrollBlockFramePcsOffset() { | |
263 return config().deoptimizationUnrollBlockFramePcsOffset; | |
264 } | |
265 | |
266 @Fold | |
267 private static int deoptimizationUnrollBlockInitialInfoOffset() { | |
268 return config().deoptimizationUnrollBlockInitialInfoOffset; | |
269 } | |
270 | |
271 @Fold | |
272 private static int deoptimizationUnpackDeopt() { | |
273 return config().deoptimizationUnpackDeopt; | |
274 } | |
275 | |
276 @Fold | |
277 private static int deoptimizationUnpackUncommonTrap() { | |
278 return config().deoptimizationUnpackUncommonTrap; | |
279 } | |
280 | |
281 @NodeIntrinsic(value = StubForeignCallNode.class, setStampFromReturnType = true) | |
282 public static native int unpackFrames(@ConstantNodeParameter ForeignCallDescriptor unpackFrames, Word thread, int mode); | |
283 } |