Mercurial > hg > truffle
comparison src/cpu/x86/vm/frame_x86.cpp @ 10405:f2110083203d
8005849: JEP 167: Event-Based JVM Tracing
Reviewed-by: acorn, coleenp, sla
Contributed-by: Karen Kinnear <karen.kinnear@oracle.com>, Bengt Rutisson <bengt.rutisson@oracle.com>, Calvin Cheung <calvin.cheung@oracle.com>, Erik Gahlin <erik.gahlin@oracle.com>, Erik Helin <erik.helin@oracle.com>, Jesper Wilhelmsson <jesper.wilhelmsson@oracle.com>, Keith McGuigan <keith.mcguigan@oracle.com>, Mattias Tobiasson <mattias.tobiasson@oracle.com>, Markus Gronlund <markus.gronlund@oracle.com>, Mikael Auno <mikael.auno@oracle.com>, Nils Eliasson <nils.eliasson@oracle.com>, Nils Loodin <nils.loodin@oracle.com>, Rickard Backman <rickard.backman@oracle.com>, Staffan Larsen <staffan.larsen@oracle.com>, Stefan Karlsson <stefan.karlsson@oracle.com>, Yekaterina Kantserova <yekaterina.kantserova@oracle.com>
author | sla |
---|---|
date | Mon, 10 Jun 2013 11:30:51 +0200 |
parents | 47bc9800972c |
children | 836a62f43af9 e0c9a1d29eb4 |
comparison
equal
deleted
inserted
replaced
10404:d0add7016434 | 10405:f2110083203d |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
31 #include "prims/methodHandles.hpp" | 31 #include "prims/methodHandles.hpp" |
32 #include "runtime/frame.inline.hpp" | 32 #include "runtime/frame.inline.hpp" |
33 #include "runtime/handles.inline.hpp" | 33 #include "runtime/handles.inline.hpp" |
34 #include "runtime/javaCalls.hpp" | 34 #include "runtime/javaCalls.hpp" |
35 #include "runtime/monitorChunk.hpp" | 35 #include "runtime/monitorChunk.hpp" |
36 #include "runtime/os.hpp" | |
36 #include "runtime/signature.hpp" | 37 #include "runtime/signature.hpp" |
37 #include "runtime/stubCodeGenerator.hpp" | 38 #include "runtime/stubCodeGenerator.hpp" |
38 #include "runtime/stubRoutines.hpp" | 39 #include "runtime/stubRoutines.hpp" |
39 #include "vmreg_x86.inline.hpp" | 40 #include "vmreg_x86.inline.hpp" |
40 #ifdef COMPILER1 | 41 #ifdef COMPILER1 |
52 | 53 |
53 bool frame::safe_for_sender(JavaThread *thread) { | 54 bool frame::safe_for_sender(JavaThread *thread) { |
54 address sp = (address)_sp; | 55 address sp = (address)_sp; |
55 address fp = (address)_fp; | 56 address fp = (address)_fp; |
56 address unextended_sp = (address)_unextended_sp; | 57 address unextended_sp = (address)_unextended_sp; |
57 // sp must be within the stack | 58 |
58 bool sp_safe = (sp <= thread->stack_base()) && | 59 // consider stack guards when trying to determine "safe" stack pointers |
59 (sp >= thread->stack_base() - thread->stack_size()); | 60 static size_t stack_guard_size = os::uses_stack_guard_pages() ? (StackYellowPages + StackRedPages) * os::vm_page_size() : 0; |
61 size_t usable_stack_size = thread->stack_size() - stack_guard_size; | |
62 | |
63 // sp must be within the usable part of the stack (not in guards) | |
64 bool sp_safe = (sp < thread->stack_base()) && | |
65 (sp >= thread->stack_base() - usable_stack_size); | |
66 | |
60 | 67 |
61 if (!sp_safe) { | 68 if (!sp_safe) { |
62 return false; | 69 return false; |
63 } | 70 } |
64 | 71 |
65 // unextended sp must be within the stack and above or equal sp | 72 // unextended sp must be within the stack and above or equal sp |
66 bool unextended_sp_safe = (unextended_sp <= thread->stack_base()) && | 73 bool unextended_sp_safe = (unextended_sp < thread->stack_base()) && |
67 (unextended_sp >= sp); | 74 (unextended_sp >= sp); |
68 | 75 |
69 if (!unextended_sp_safe) { | 76 if (!unextended_sp_safe) { |
70 return false; | 77 return false; |
71 } | 78 } |
72 | 79 |
73 // an fp must be within the stack and above (but not equal) sp | 80 // an fp must be within the stack and above (but not equal) sp |
74 bool fp_safe = (fp <= thread->stack_base()) && (fp > sp); | 81 // second evaluation on fp+ is added to handle situation where fp is -1 |
82 bool fp_safe = (fp < thread->stack_base() && (fp > sp) && (((fp + (return_addr_offset * sizeof(void*))) < thread->stack_base()))); | |
75 | 83 |
76 // We know sp/unextended_sp are safe only fp is questionable here | 84 // We know sp/unextended_sp are safe only fp is questionable here |
77 | 85 |
78 // If the current frame is known to the code cache then we can attempt to | 86 // If the current frame is known to the code cache then we can attempt to |
79 // to construct the sender and do some validation of it. This goes a long way | 87 // to construct the sender and do some validation of it. This goes a long way |
84 // First check if frame is complete and tester is reliable | 92 // First check if frame is complete and tester is reliable |
85 // Unfortunately we can only check frame complete for runtime stubs and nmethod | 93 // Unfortunately we can only check frame complete for runtime stubs and nmethod |
86 // other generic buffer blobs are more problematic so we just assume they are | 94 // other generic buffer blobs are more problematic so we just assume they are |
87 // ok. adapter blobs never have a frame complete and are never ok. | 95 // ok. adapter blobs never have a frame complete and are never ok. |
88 | 96 |
97 // check for a valid frame_size, otherwise we are unlikely to get a valid sender_pc | |
98 | |
99 if (!Interpreter::contains(_pc) && _cb->frame_size() <= 0) { | |
100 //assert(0, "Invalid frame_size"); | |
101 return false; | |
102 } | |
103 | |
89 if (!_cb->is_frame_complete_at(_pc)) { | 104 if (!_cb->is_frame_complete_at(_pc)) { |
90 if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { | 105 if (_cb->is_nmethod() || _cb->is_adapter_blob() || _cb->is_runtime_stub()) { |
91 return false; | 106 return false; |
92 } | 107 } |
93 } | 108 } |
105 | 120 |
106 // Validate the JavaCallWrapper an entry frame must have | 121 // Validate the JavaCallWrapper an entry frame must have |
107 | 122 |
108 address jcw = (address)entry_frame_call_wrapper(); | 123 address jcw = (address)entry_frame_call_wrapper(); |
109 | 124 |
110 bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > fp); | 125 bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > fp); |
111 | 126 |
112 return jcw_safe; | 127 return jcw_safe; |
113 | 128 |
114 } | 129 } |
115 | 130 |
132 sender_sp = _unextended_sp + _cb->frame_size(); | 147 sender_sp = _unextended_sp + _cb->frame_size(); |
133 // On Intel the return_address is always the word on the stack | 148 // On Intel the return_address is always the word on the stack |
134 sender_pc = (address) *(sender_sp-1); | 149 sender_pc = (address) *(sender_sp-1); |
135 } | 150 } |
136 | 151 |
152 | |
153 // If the potential sender is the interpreter then we can do some more checking | |
154 if (Interpreter::contains(sender_pc)) { | |
155 | |
156 // ebp is always saved in a recognizable place in any code we generate. However | |
157 // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved ebp | |
158 // is really a frame pointer. | |
159 | |
160 intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); | |
161 bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); | |
162 | |
163 if (!saved_fp_safe) { | |
164 return false; | |
165 } | |
166 | |
167 // construct the potential sender | |
168 | |
169 frame sender(sender_sp, saved_fp, sender_pc); | |
170 | |
171 return sender.is_interpreted_frame_valid(thread); | |
172 | |
173 } | |
174 | |
137 // We must always be able to find a recognizable pc | 175 // We must always be able to find a recognizable pc |
138 CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); | 176 CodeBlob* sender_blob = CodeCache::find_blob_unsafe(sender_pc); |
139 if (sender_pc == NULL || sender_blob == NULL) { | 177 if (sender_pc == NULL || sender_blob == NULL) { |
140 return false; | 178 return false; |
141 } | 179 } |
142 | 180 |
143 | 181 // Could be a zombie method |
144 // If the potential sender is the interpreter then we can do some more checking | 182 if (sender_blob->is_zombie() || sender_blob->is_unloaded()) { |
145 if (Interpreter::contains(sender_pc)) { | 183 return false; |
146 | 184 } |
147 // ebp is always saved in a recognizable place in any code we generate. However | 185 |
148 // only if the sender is interpreted/call_stub (c1 too?) are we certain that the saved ebp | 186 // Could just be some random pointer within the codeBlob |
149 // is really a frame pointer. | 187 if (!sender_blob->code_contains(sender_pc)) { |
150 | 188 return false; |
189 } | |
190 | |
191 // We should never be able to see an adapter if the current frame is something from code cache | |
192 if (sender_blob->is_adapter_blob()) { | |
193 return false; | |
194 } | |
195 | |
196 // Could be the call_stub | |
197 if (StubRoutines::returns_to_call_stub(sender_pc)) { | |
151 intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); | 198 intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); |
152 bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); | 199 bool saved_fp_safe = ((address)saved_fp < thread->stack_base()) && (saved_fp > sender_sp); |
153 | 200 |
154 if (!saved_fp_safe) { | 201 if (!saved_fp_safe) { |
155 return false; | 202 return false; |
156 } | 203 } |
157 | 204 |
158 // construct the potential sender | 205 // construct the potential sender |
159 | 206 |
160 frame sender(sender_sp, saved_fp, sender_pc); | 207 frame sender(sender_sp, saved_fp, sender_pc); |
161 | 208 |
162 return sender.is_interpreted_frame_valid(thread); | |
163 | |
164 } | |
165 | |
166 // Could just be some random pointer within the codeBlob | |
167 if (!sender_blob->code_contains(sender_pc)) { | |
168 return false; | |
169 } | |
170 | |
171 // We should never be able to see an adapter if the current frame is something from code cache | |
172 if (sender_blob->is_adapter_blob()) { | |
173 return false; | |
174 } | |
175 | |
176 // Could be the call_stub | |
177 | |
178 if (StubRoutines::returns_to_call_stub(sender_pc)) { | |
179 intptr_t *saved_fp = (intptr_t*)*(sender_sp - frame::sender_sp_offset); | |
180 bool saved_fp_safe = ((address)saved_fp <= thread->stack_base()) && (saved_fp > sender_sp); | |
181 | |
182 if (!saved_fp_safe) { | |
183 return false; | |
184 } | |
185 | |
186 // construct the potential sender | |
187 | |
188 frame sender(sender_sp, saved_fp, sender_pc); | |
189 | |
190 // Validate the JavaCallWrapper an entry frame must have | 209 // Validate the JavaCallWrapper an entry frame must have |
191 address jcw = (address)sender.entry_frame_call_wrapper(); | 210 address jcw = (address)sender.entry_frame_call_wrapper(); |
192 | 211 |
193 bool jcw_safe = (jcw <= thread->stack_base()) && ( jcw > (address)sender.fp()); | 212 bool jcw_safe = (jcw < thread->stack_base()) && ( jcw > (address)sender.fp()); |
194 | 213 |
195 return jcw_safe; | 214 return jcw_safe; |
196 } | 215 } |
197 | 216 |
198 // If the frame size is 0 something is bad because every nmethod has a non-zero frame size | 217 if (sender_blob->is_nmethod()) { |
218 nmethod* nm = sender_blob->as_nmethod_or_null(); | |
219 if (nm != NULL) { | |
220 if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc)) { | |
221 return false; | |
222 } | |
223 } | |
224 } | |
225 | |
226 // If the frame size is 0 something (or less) is bad because every nmethod has a non-zero frame size | |
199 // because the return address counts against the callee's frame. | 227 // because the return address counts against the callee's frame. |
200 | 228 |
201 if (sender_blob->frame_size() == 0) { | 229 if (sender_blob->frame_size() <= 0) { |
202 assert(!sender_blob->is_nmethod(), "should count return address at least"); | 230 assert(!sender_blob->is_nmethod(), "should count return address at least"); |
203 return false; | 231 return false; |
204 } | 232 } |
205 | 233 |
206 // We should never be able to see anything here except an nmethod. If something in the | 234 // We should never be able to see anything here except an nmethod. If something in the |
207 // code cache (current frame) is called by an entity within the code cache that entity | 235 // code cache (current frame) is called by an entity within the code cache that entity |
208 // should not be anything but the call stub (already covered), the interpreter (already covered) | 236 // should not be anything but the call stub (already covered), the interpreter (already covered) |
209 // or an nmethod. | 237 // or an nmethod. |
210 | 238 |
211 assert(sender_blob->is_nmethod(), "Impossible call chain"); | 239 if (!sender_blob->is_nmethod()) { |
240 return false; | |
241 } | |
212 | 242 |
213 // Could put some more validation for the potential non-interpreted sender | 243 // Could put some more validation for the potential non-interpreted sender |
214 // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... | 244 // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... |
215 | 245 |
216 // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb | 246 // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb |