src/cpu/sparc/vm/frame_sparc.hpp

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2314
f95d63e2154a
child 3099
c124e2e7463e
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

duke@435 1 /*
twisti@2142 2 * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
duke@435 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435 4 *
duke@435 5 * This code is free software; you can redistribute it and/or modify it
duke@435 6 * under the terms of the GNU General Public License version 2 only, as
duke@435 7 * published by the Free Software Foundation.
duke@435 8 *
duke@435 9 * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435 12 * version 2 for more details (a copy is included in the LICENSE file that
duke@435 13 * accompanied this code).
duke@435 14 *
duke@435 15 * You should have received a copy of the GNU General Public License version
duke@435 16 * 2 along with this work; if not, write to the Free Software Foundation,
duke@435 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
duke@435 22 *
duke@435 23 */
duke@435 24
stefank@2314 25 #ifndef CPU_SPARC_VM_FRAME_SPARC_HPP
stefank@2314 26 #define CPU_SPARC_VM_FRAME_SPARC_HPP
stefank@2314 27
stefank@2314 28 #include "runtime/synchronizer.hpp"
stefank@2314 29 #include "utilities/top.hpp"
stefank@2314 30
duke@435 31 // A frame represents a physical stack frame (an activation). Frames can be
duke@435 32 // C or Java frames, and the Java frames can be interpreted or compiled.
duke@435 33 // In contrast, vframes represent source-level activations, so that one physical frame
duke@435 34 // can correspond to multiple source level frames because of inlining.
duke@435 35 // A frame is comprised of {pc, sp, younger_sp}
duke@435 36
duke@435 37
duke@435 38 // Layout of asm interpreter frame:
duke@435 39 //
duke@435 40 // 0xfffffff
duke@435 41 // ......
duke@435 42 // [last extra incoming arg, (local # Nargs > 6 ? Nargs-1 : undef)]
duke@435 43 // .. Note: incoming args are copied to local frame area upon entry
duke@435 44 // [first extra incoming arg, (local # Nargs > 6 ? 6 : undef)]
duke@435 45 // [6 words for C-arg storage (unused)] Are this and next one really needed?
duke@435 46 // [C-aggregate-word (unused)] Yes, if want extra params to be in same place as C convention
duke@435 47 // [16 words for register saving] <--- FP
duke@435 48 // [interpreter_frame_vm_locals ] (see below)
duke@435 49
duke@435 50 // Note: Llocals is always double-word aligned
duke@435 51 // [first local i.e. local # 0] <-- Llocals
duke@435 52 // ...
duke@435 53 // [last local, i.e. local # Nlocals-1]
duke@435 54
duke@435 55 // [monitors ]
duke@435 56 // ....
duke@435 57 // [monitors ] <-- Lmonitors (same as Llocals + 6*4 if none)
duke@435 58 // (must be double-word aligned because
duke@435 59 // monitor element size is constrained to
duke@435 60 // doubleword)
duke@435 61 //
duke@435 62 // <-- Lesp (points 1 past TOS)
duke@435 63 // [bottom word used for stack ]
duke@435 64 // ...
duke@435 65 // [top word used for stack] (first word of stack is double-word aligned)
duke@435 66
duke@435 67 // [space for outgoing args (conservatively allocated as max_stack - 6 + interpreter_frame_extra_outgoing_argument_words)]
duke@435 68 // [6 words for C-arg storage]
duke@435 69 // [C-aggregate-word (unused)]
duke@435 70 // [16 words for register saving] <--- SP
duke@435 71 // ...
duke@435 72 // 0x0000000
duke@435 73 //
duke@435 74 // The in registers and local registers are preserved in a block at SP.
duke@435 75 //
duke@435 76 // The first six in registers (I0..I5) hold the first six locals.
duke@435 77 // The locals are used as follows:
duke@435 78 // Lesp first free element of expression stack
duke@435 79 // (which grows towards __higher__ addresses)
duke@435 80 // Lbcp is set to address of bytecode to execute
duke@435 81 // It is accessed in the frame under the name "bcx".
duke@435 82 // It may at times (during GC) be an index instead.
duke@435 83 // Lmethod the method being interpreted
duke@435 84 // Llocals the base pointer for accessing the locals array
duke@435 85 // (lower-numbered locals have lower addresses)
duke@435 86 // Lmonitors the base pointer for accessing active monitors
duke@435 87 // Lcache a saved pointer to the method's constant pool cache
duke@435 88 //
duke@435 89 //
duke@435 90 // When calling out to another method,
duke@435 91 // G5_method is set to method to call, G5_inline_cache_klass may be set,
duke@435 92 // parameters are put in O registers, and also extra parameters
duke@435 93 // must be cleverly copied from the top of stack to the outgoing param area in the frame,
duke@435 94 // ------------------------------ C++ interpreter ----------------------------------------
duke@435 95 // Layout of C++ interpreter frame:
duke@435 96 //
duke@435 97
duke@435 98
duke@435 99
duke@435 100 // All frames:
duke@435 101
duke@435 102 public:
duke@435 103
duke@435 104 enum {
duke@435 105 // normal return address is 2 words past PC
duke@435 106 pc_return_offset = 2 * BytesPerInstWord,
duke@435 107
duke@435 108 // size of each block, in order of increasing address:
duke@435 109 register_save_words = 16,
duke@435 110 #ifdef _LP64
duke@435 111 callee_aggregate_return_pointer_words = 0,
duke@435 112 #else
duke@435 113 callee_aggregate_return_pointer_words = 1,
duke@435 114 #endif
duke@435 115 callee_register_argument_save_area_words = 6,
duke@435 116 // memory_parameter_words = <arbitrary>,
duke@435 117
duke@435 118 // offset of each block, in order of increasing address:
duke@435 119 // (note: callee_register_argument_save_area_words == Assembler::n_register_parameters)
duke@435 120 register_save_words_sp_offset = 0,
duke@435 121 callee_aggregate_return_pointer_sp_offset = register_save_words_sp_offset + register_save_words,
duke@435 122 callee_register_argument_save_area_sp_offset = callee_aggregate_return_pointer_sp_offset + callee_aggregate_return_pointer_words,
duke@435 123 memory_parameter_word_sp_offset = callee_register_argument_save_area_sp_offset + callee_register_argument_save_area_words,
duke@435 124 varargs_offset = memory_parameter_word_sp_offset
duke@435 125 };
duke@435 126
duke@435 127 private:
duke@435 128 intptr_t* _younger_sp; // optional SP of callee (used to locate O7)
duke@435 129 int _sp_adjustment_by_callee; // adjustment in words to SP by callee for making locals contiguous
duke@435 130
duke@435 131 // Note: On SPARC, unlike Intel, the saved PC for a stack frame
duke@435 132 // is stored at a __variable__ distance from that frame's SP.
duke@435 133 // (In fact, it may be in the register save area of the callee frame,
duke@435 134 // but that fact need not bother us.) Thus, we must store the
duke@435 135 // address of that saved PC explicitly. On the other hand, SPARC
duke@435 136 // stores the FP for a frame at a fixed offset from the frame's SP,
duke@435 137 // so there is no need for a separate "frame::_fp" field.
duke@435 138
duke@435 139 public:
duke@435 140 // Accessors
duke@435 141
duke@435 142 intptr_t* younger_sp() const {
duke@435 143 assert(_younger_sp != NULL, "frame must possess a younger_sp");
duke@435 144 return _younger_sp;
duke@435 145 }
duke@435 146
duke@435 147 int callee_sp_adjustment() const { return _sp_adjustment_by_callee; }
duke@435 148 void set_sp_adjustment_by_callee(int number_of_words) { _sp_adjustment_by_callee = number_of_words; }
duke@435 149
duke@435 150 // Constructors
duke@435 151
duke@435 152 // This constructor relies on the fact that the creator of a frame
duke@435 153 // has flushed register windows which the frame will refer to, and
duke@435 154 // that those register windows will not be reloaded until the frame is
duke@435 155 // done reading and writing the stack. Moreover, if the "younger_sp"
duke@435 156 // argument points into the register save area of the next younger
duke@435 157 // frame (though it need not), the register window for that next
duke@435 158 // younger frame must also stay flushed. (The caller is responsible
duke@435 159 // for ensuring this.)
duke@435 160
duke@435 161 frame(intptr_t* sp, intptr_t* younger_sp, bool younger_frame_adjusted_stack = false);
duke@435 162
duke@435 163 // make a deficient frame which doesn't know where its PC is:
duke@435 164 enum unpatchable_t { unpatchable };
duke@435 165 frame(intptr_t* sp, unpatchable_t, address pc = NULL, CodeBlob* cb = NULL);
duke@435 166
duke@435 167 // Walk from sp outward looking for old_sp, and return old_sp's predecessor
duke@435 168 // (i.e. return the sp from the frame where old_sp is the fp).
duke@435 169 // Register windows are assumed to be flushed for the stack in question.
duke@435 170
duke@435 171 static intptr_t* next_younger_sp_or_null(intptr_t* old_sp, intptr_t* sp);
duke@435 172
duke@435 173 // Return true if sp is a younger sp in the stack described by valid_sp.
duke@435 174 static bool is_valid_stack_pointer(intptr_t* valid_sp, intptr_t* sp);
duke@435 175
duke@435 176 public:
duke@435 177 // accessors for the instance variables
duke@435 178 intptr_t* fp() const { return (intptr_t*) ((intptr_t)(sp()[FP->sp_offset_in_saved_window()]) + STACK_BIAS ); }
duke@435 179
duke@435 180 // All frames
duke@435 181
duke@435 182 intptr_t* fp_addr_at(int index) const { return &fp()[index]; }
duke@435 183 intptr_t* sp_addr_at(int index) const { return &sp()[index]; }
duke@435 184 intptr_t fp_at( int index) const { return *fp_addr_at(index); }
duke@435 185 intptr_t sp_at( int index) const { return *sp_addr_at(index); }
duke@435 186
duke@435 187 private:
duke@435 188 inline address* I7_addr() const;
duke@435 189 inline address* O7_addr() const;
duke@435 190
duke@435 191 inline address* I0_addr() const;
duke@435 192 inline address* O0_addr() const;
duke@435 193 intptr_t* younger_sp_addr_at(int index) const { return &younger_sp()[index]; }
duke@435 194
duke@435 195 public:
duke@435 196 // access to SPARC arguments and argument registers
duke@435 197
duke@435 198 // Assumes reg is an in/local register
duke@435 199 intptr_t* register_addr(Register reg) const {
duke@435 200 return sp_addr_at(reg->sp_offset_in_saved_window());
duke@435 201 }
duke@435 202
duke@435 203 // Assumes reg is an out register
duke@435 204 intptr_t* out_register_addr(Register reg) const {
duke@435 205 return younger_sp_addr_at(reg->after_save()->sp_offset_in_saved_window());
duke@435 206 }
duke@435 207 intptr_t* memory_param_addr(int param_ix, bool is_in) const {
duke@435 208 int offset = callee_register_argument_save_area_sp_offset + param_ix;
duke@435 209 if (is_in)
duke@435 210 return fp_addr_at(offset);
duke@435 211 else
duke@435 212 return sp_addr_at(offset);
duke@435 213 }
duke@435 214 intptr_t* param_addr(int param_ix, bool is_in) const {
duke@435 215 if (param_ix >= callee_register_argument_save_area_words)
duke@435 216 return memory_param_addr(param_ix, is_in);
duke@435 217 else if (is_in)
duke@435 218 return register_addr(Argument(param_ix, true).as_register());
duke@435 219 else {
duke@435 220 // the registers are stored in the next younger frame
duke@435 221 // %%% is this really necessary?
duke@435 222 ShouldNotReachHere();
duke@435 223 return NULL;
duke@435 224 }
duke@435 225 }
duke@435 226
duke@435 227
duke@435 228 // Interpreter frames
duke@435 229
duke@435 230 public:
duke@435 231 // Asm interpreter
duke@435 232 #ifndef CC_INTERP
duke@435 233 enum interpreter_frame_vm_locals {
duke@435 234 // 2 words, also used to save float regs across calls to C
duke@435 235 interpreter_frame_d_scratch_fp_offset = -2,
duke@435 236 interpreter_frame_l_scratch_fp_offset = -4,
duke@435 237 interpreter_frame_padding_offset = -5, // for native calls only
duke@435 238 interpreter_frame_oop_temp_offset = -6, // for native calls only
duke@435 239 interpreter_frame_vm_locals_fp_offset = -6, // should be same as above, and should be zero mod 8
duke@435 240
duke@435 241 interpreter_frame_vm_local_words = -interpreter_frame_vm_locals_fp_offset,
duke@435 242
duke@435 243
duke@435 244 // interpreter frame set-up needs to save 2 extra words in outgoing param area
duke@435 245 // for class and jnienv arguments for native stubs (see nativeStubGen_sparc.cpp_
duke@435 246
duke@435 247 interpreter_frame_extra_outgoing_argument_words = 2
duke@435 248 };
duke@435 249 #else
duke@435 250 enum interpreter_frame_vm_locals {
duke@435 251 // 2 words, also used to save float regs across calls to C
duke@435 252 interpreter_state_ptr_offset = 0, // Is in L0 (Lstate) in save area
duke@435 253 interpreter_frame_mirror_offset = 1, // Is in L1 (Lmirror) in save area (for native calls only)
duke@435 254
duke@435 255 // interpreter frame set-up needs to save 2 extra words in outgoing param area
duke@435 256 // for class and jnienv arguments for native stubs (see nativeStubGen_sparc.cpp_
duke@435 257
duke@435 258 interpreter_frame_extra_outgoing_argument_words = 2
duke@435 259 };
duke@435 260 #endif /* CC_INTERP */
duke@435 261
duke@435 262 // the compiler frame has many of the same fields as the interpreter frame
duke@435 263 // %%%%% factor out declarations of the shared fields
duke@435 264 enum compiler_frame_fixed_locals {
duke@435 265 compiler_frame_d_scratch_fp_offset = -2,
duke@435 266 compiler_frame_vm_locals_fp_offset = -2, // should be same as above
duke@435 267
duke@435 268 compiler_frame_vm_local_words = -compiler_frame_vm_locals_fp_offset
duke@435 269 };
duke@435 270
duke@435 271 private:
twisti@2142 272 constantPoolCacheOop* interpreter_frame_cpoolcache_addr() const;
duke@435 273
duke@435 274 #ifndef CC_INTERP
duke@435 275
duke@435 276 // where Lmonitors is saved:
duke@435 277 BasicObjectLock** interpreter_frame_monitors_addr() const {
duke@435 278 return (BasicObjectLock**) sp_addr_at(Lmonitors->sp_offset_in_saved_window());
duke@435 279 }
duke@435 280 intptr_t** interpreter_frame_esp_addr() const {
duke@435 281 return (intptr_t**)sp_addr_at(Lesp->sp_offset_in_saved_window());
duke@435 282 }
duke@435 283
duke@435 284 inline void interpreter_frame_set_tos_address(intptr_t* x);
duke@435 285
duke@435 286
duke@435 287 // %%%%% Another idea: instead of defining 3 fns per item, just define one returning a ref
duke@435 288
duke@435 289 // monitors:
duke@435 290
duke@435 291 // next two fns read and write Lmonitors value,
duke@435 292 private:
duke@435 293 BasicObjectLock* interpreter_frame_monitors() const { return *interpreter_frame_monitors_addr(); }
duke@435 294 void interpreter_frame_set_monitors(BasicObjectLock* monitors) { *interpreter_frame_monitors_addr() = monitors; }
duke@435 295 #else
duke@435 296 public:
duke@435 297 inline interpreterState get_interpreterState() const {
duke@435 298 return ((interpreterState)sp_at(interpreter_state_ptr_offset));
duke@435 299 }
duke@435 300
duke@435 301
duke@435 302 #endif /* CC_INTERP */
duke@435 303
duke@435 304
duke@435 305
duke@435 306 // Compiled frames
duke@435 307
duke@435 308 public:
duke@435 309 // Tells if this register can hold 64 bits on V9 (really, V8+).
duke@435 310 static bool holds_a_doubleword(Register reg) {
duke@435 311 #ifdef _LP64
duke@435 312 // return true;
duke@435 313 return reg->is_out() || reg->is_global();
duke@435 314 #else
duke@435 315 return reg->is_out() || reg->is_global();
duke@435 316 #endif
duke@435 317 }
stefank@2314 318
stefank@2314 319 #endif // CPU_SPARC_VM_FRAME_SPARC_HPP

mercurial