frame_sparc.cpp revision 3101
1472N/A * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. 100N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 100N/A * This code is free software; you can redistribute it and/or modify it 100N/A * under the terms of the GNU General Public License version 2 only, as 100N/A * published by the Free Software Foundation. 100N/A * This code is distributed in the hope that it will be useful, but WITHOUT 100N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 100N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 100N/A * version 2 for more details (a copy is included in the LICENSE file that 100N/A * accompanied this code). 100N/A * You should have received a copy of the GNU General Public License version 100N/A * 2 along with this work; if not, write to the Free Software Foundation, 100N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1472N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 100N/A// Unified register numbering scheme: each 32-bits counts as a register 100N/A// number, so all the V9 registers take 2 slots. 100N/Aconst static int R_L_nums[] = {0+0
40,
2+0
40,
4+0
40,
6+0
40,
8+0
40,
10+0
40,
12+0
40,
14+0
40};
100N/Aconst static int R_I_nums[] = {0+0
60,
2+0
60,
4+0
60,
6+0
60,
8+0
60,
10+0
60,
12+0
60,
14+0
60};
100N/Aconst static int R_O_nums[] = {0+0
20,
2+0
20,
4+0
20,
6+0
20,
8+0
20,
10+0
20,
12+0
20,
14+0
20};
const static int R_G_nums[] = {0+000,
2+000,
4+000,
6+000,
8+000,
10+000,
12+000,
14+000};
for (i = 0; i <
8; i++) {
for (i = 0; i <
8; i++) {
// Only the GPRs get handled this way // don't talk about bad registers // 32-bit registers for in, out and local // HMM ought to return NULL for any non-concrete (odd) vmreg // this all tied up in the fact we put out double oopMaps for // register locations. When that is fixed we'd will return NULL // Only the window'd GPRs get handled this way; not the globals. // We are shifting windows. That means we are moving all %i to %o, // getting rid of all current %l, and keeping all %g. This is only // complicated if any of the location pointers for these are valid. // The normal case is that everything is in its standard register window // home, and _location_valid[0] is zero. In that case, this routine if (!
update_map())
return;
// this only applies to maps with locations // if we cleared some non-%g locations, we may have to do some shifting // copy %i0-%i5 to %o0-%o5, if they have special locations // This can happen in within stubs which spill argument registers // around a dynamic link operation, such as resolve_opt_virtual_call. for (
int i = 0; i <
8; i++) {
// sp must be within the stack // unextended sp must be within the stack and above or equal sp // an fp must be within the stack and above (but not equal) sp // If the current frame is known to the code cache then we can attempt to // to construct the sender and do some validation of it. This goes a long way // toward eliminating issues when we get in frame construction code // First check if frame is complete and tester is reliable // Unfortunately we can only check frame complete for runtime stubs and nmethod // other generic buffer blobs are more problematic so we just assume they are // ok. adapter blobs never have a frame complete and are never ok. // an entry frame must have a valid fp. // Validate the JavaCallWrapper an entry frame must have // We must always be able to find a recognizable pc // It should be safe to construct the sender though it might not be valid // Do we have a valid fp? // an fp must be within the stack and above (but not equal) current frame's _FP // If the potential sender is the interpreter then we can do some more checking // Could just be some random pointer within the codeBlob // We should never be able to see an adapter if the current frame is something from code cache // Validate the JavaCallWrapper an entry frame must have // If the frame size is 0 something is bad because every nmethod has a non-zero frame size // because you must allocate window space // The sender should positively be an nmethod or call_stub. On sparc we might in fact see something else. // The cause of this is because at a save instruction the O7 we get is a leftover from an earlier // window use. So if a runtime stub creates two frames (common in fastdebug/jvmg) then we see the // stale pc. So if the sender blob is not something we'd expect we have little choice but to declare // the stack unwalkable. pd_get_top_frame_for_signal_handler tries to recover from this by unwinding // that initial frame and retrying. // Could put some more validation for the potential non-interpreted sender // frame we'd create by calling sender if I could think of any. Wait for next crash in forte... // One idea is seeing if the sender_pc we have is one that we'd expect to call to current cb // We've validated the potential sender that would be created // Must be native-compiled frame. Since sender will try and use fp to find // linkages it must be safe // could try and do some more potential verification of native frame if we could think of some... // Construct an unpatchable, deficient frame // Without a valid unextended_sp() we can't convert the pc to "original" // make a deficient frame which doesn't know where its PC is // Any frame we ever build should always "safe" therefore we should not have to call // In case of native stubs, the pc retrieved here might be // wrong. (the _last_native_pc will have the right value) // So do not put add any asserts on the _pc here. // Check for MethodHandle call sites. // The SP is already adjusted by this MH call site, don't // overwrite this value with the wrong interpreter value. // compute adjustment to this frame's SP made by its interpreted callee // It is important that the frame is fully constructed when we do // this lookup as get_deopt_original_pc() needs a correct value for // unextended_sp() which uses _sp_adjustment_by_callee. for(
int i = 0; i < n; ++i)
printf(
"deoptimized frame 1\n");
// Java frame called from C; skip all C frames and return top C // frame of that chunk as the sender // Since we are walking the stack now this nested anchor is obviously walkable // even if it wasn't when it was stacked. // Capture _last_Java_pc (if needed) and mark anchor walkable. // Default is not to follow arguments; update it accordingly below // Note: The version of this operation on any platform with callee-save // registers must update the register map (if not null). // In order to do this correctly, the various subtypes of // of frame (interpreted, compiled, glue, native), // must be distinguished. There is no need on SPARC for // such distinctions, because all callee-save registers are // preserved for all frames via SPARC-specific mechanisms. // *** HOWEVER, *** if and when we make any floating-point // registers callee-saved, then we will have to copy over // the RegisterMap update logic from the Intel code. // The constructor of the sender must know whether this frame is interpreted so it can set the // sender's _sp_adjustment_by_callee field. An osr adapter frame was originally // interpreted but its pc is in the code cache (for c1 -> osr_frame_return_id stub), so it must be // explicitly recognized. // Update the locations of implicitly saved registers to be their // addresses in the register save area. // For %o registers, the addresses of %i registers in the next younger // Tell GC to use argument oopmaps for some runtime stubs that need it. // For C1, the runtime stub might not have oop maps, so set this flag // outside of update_register_map. // QQQ this assert is invalid (or too strong anyway) sice _pc could // be original pc and frame could have the deopt pc. // assert(_pc == *O7_addr() + pc_return_offset, "frame has wrong pc"); Find the (biased) sp that is just younger than old_sp starting at sp. If not found return NULL. Register windows are assumed to be flushed. // too many frames have gone by; invalid parameters given to this function Determine if "sp" is a valid stack pointer. "sp" is assumed to be younger than "valid_sp". So if "sp" is valid itself then it should be possible to walk frames from "sp" to "valid_sp". The assumption is that the registers windows for the thread stack in question are flushed. // set constant pool cache entry for interpreter // Is there anything to do? // These are reasonable sanity checks // These are hacks to keep us out of trouble. // The problem with these is that they mask other problems if (
fp() <=
sp()) {
// this attempts to deal with unsigned comparison above // do some validation of frame elements // validate the method we'd find in this potential sender // stack frames shouldn't be much larger than max_stack elements // validate constantPoolCacheOop // We'd have to be pretty unlucky to be mislead at this point // Windows have been flushed on entry (but not marked). Capture the pc that // is the return address to the frame that contains "sp" as its stack pointer. // This pc resides in the called of the frame corresponding to "sp". // As a side effect we mark this JavaFrameAnchor as having flushed the windows. // This side effect lets us mark stacked JavaFrameAnchors (stacked in the // call_helper) as flushed when we have flushed the windows for the most // recent (i.e. current) JavaFrameAnchor. This saves useless flushing calls // and lets us find the pc just once rather than multiple times as it did // in the bad old _post_Java_state days. // try and find the sp just younger than _last_Java_sp // Really this should never fail otherwise VM call must have non-standard // frame linkage (bad) or stack is not properly flushed (worse). // Eventually make an assert // We always flush in case the profiler wants it but we won't mark // the windows as flushed unless we have a last_Java_frame // convert offset to index to deal with tsi // Prior to notifying the runtime of the method_exit the possible result // value is saved to l_scratch and d_scratch. // On 64-bit the result for 1/8/16/32-bit result types is in the other case T_VOID :
/* Nothing to do */ break;
case T_VOID :
/* Nothing to do */ break;
// Lesp pointer is one word lower than the top item on the stack. // esp, according to Lesp (e.g. not depending on bci), if seems valid err_msg(
"callee_register_argument_save_area_words %d", w));
// unused... but returns fp() to minimize changes introduced by 7087445