duke@435: /* twisti@1730: * Copyright 1999-2010 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: class CodeEmitInfo; duke@435: class LIR_Assembler; duke@435: class LIR_OpVisitState; duke@435: duke@435: // CodeStubs are little 'out-of-line' pieces of code that duke@435: // usually handle slow cases of operations. All code stubs duke@435: // are collected and code is emitted at the end of the duke@435: // nmethod. duke@435: duke@435: class CodeStub: public CompilationResourceObj { duke@435: protected: duke@435: Label _entry; // label at the stub entry point duke@435: Label _continuation; // label where stub continues, if any duke@435: duke@435: public: duke@435: CodeStub() {} duke@435: duke@435: // code generation duke@435: void assert_no_unbound_labels() { assert(!_entry.is_unbound() && !_continuation.is_unbound(), "unbound label"); } duke@435: virtual void emit_code(LIR_Assembler* e) = 0; duke@435: virtual CodeEmitInfo* info() const { return NULL; } duke@435: virtual bool is_exception_throw_stub() const { return false; } duke@435: virtual bool is_range_check_stub() const { return false; } duke@435: virtual bool is_divbyzero_stub() const { return false; } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const = 0; duke@435: #endif duke@435: duke@435: // label access duke@435: Label* entry() { return &_entry; } duke@435: Label* continuation() { return &_continuation; } duke@435: // for LIR duke@435: virtual void visit(LIR_OpVisitState* visit) { duke@435: #ifndef PRODUCT duke@435: if (LIRTracePeephole && Verbose) { duke@435: tty->print("no visitor for "); duke@435: print_name(tty); duke@435: tty->cr(); duke@435: } duke@435: #endif duke@435: } duke@435: }; duke@435: duke@435: duke@435: define_array(CodeStubArray, CodeStub*) duke@435: define_stack(_CodeStubList, CodeStubArray) duke@435: duke@435: class CodeStubList: public _CodeStubList { duke@435: public: duke@435: CodeStubList(): _CodeStubList() {} duke@435: duke@435: void append(CodeStub* stub) { duke@435: if (!contains(stub)) { duke@435: _CodeStubList::append(stub); duke@435: } duke@435: } duke@435: }; duke@435: duke@435: #ifdef TIERED duke@435: class CounterOverflowStub: public CodeStub { duke@435: private: duke@435: CodeEmitInfo* _info; duke@435: int _bci; duke@435: duke@435: public: duke@435: CounterOverflowStub(CodeEmitInfo* info, int bci) : _info(info), _bci(bci) { duke@435: } duke@435: duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("CounterOverflowStub"); } duke@435: #endif // PRODUCT duke@435: duke@435: }; duke@435: #endif // TIERED duke@435: duke@435: class ConversionStub: public CodeStub { duke@435: private: duke@435: Bytecodes::Code _bytecode; duke@435: LIR_Opr _input; duke@435: LIR_Opr _result; duke@435: duke@435: static float float_zero; duke@435: static double double_zero; duke@435: public: duke@435: ConversionStub(Bytecodes::Code bytecode, LIR_Opr input, LIR_Opr result) duke@435: : _bytecode(bytecode), _input(input), _result(result) { duke@435: } duke@435: duke@435: Bytecodes::Code bytecode() { return _bytecode; } duke@435: LIR_Opr input() { return _input; } duke@435: LIR_Opr result() { return _result; } duke@435: duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(); duke@435: visitor->do_input(_input); duke@435: visitor->do_output(_result); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("ConversionStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: // Throws ArrayIndexOutOfBoundsException by default but can be duke@435: // configured to throw IndexOutOfBoundsException in constructor duke@435: class RangeCheckStub: public CodeStub { duke@435: private: duke@435: CodeEmitInfo* _info; duke@435: LIR_Opr _index; duke@435: bool _throw_index_out_of_bounds_exception; duke@435: duke@435: public: duke@435: RangeCheckStub(CodeEmitInfo* info, LIR_Opr index, bool throw_index_out_of_bounds_exception = false); duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual bool is_exception_throw_stub() const { return true; } duke@435: virtual bool is_range_check_stub() const { return true; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: visitor->do_input(_index); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("RangeCheckStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class DivByZeroStub: public CodeStub { duke@435: private: duke@435: CodeEmitInfo* _info; duke@435: int _offset; duke@435: duke@435: public: duke@435: DivByZeroStub(CodeEmitInfo* info) duke@435: : _info(info), _offset(-1) { duke@435: } duke@435: DivByZeroStub(int offset, CodeEmitInfo* info) duke@435: : _info(info), _offset(offset) { duke@435: } duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual bool is_exception_throw_stub() const { return true; } duke@435: virtual bool is_divbyzero_stub() const { return true; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("DivByZeroStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class ImplicitNullCheckStub: public CodeStub { duke@435: private: duke@435: CodeEmitInfo* _info; duke@435: int _offset; duke@435: duke@435: public: duke@435: ImplicitNullCheckStub(int offset, CodeEmitInfo* info) duke@435: : _offset(offset), _info(info) { duke@435: } duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual bool is_exception_throw_stub() const { return true; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("ImplicitNullCheckStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class NewInstanceStub: public CodeStub { duke@435: private: duke@435: ciInstanceKlass* _klass; duke@435: LIR_Opr _klass_reg; duke@435: LIR_Opr _result; duke@435: CodeEmitInfo* _info; duke@435: Runtime1::StubID _stub_id; duke@435: duke@435: public: duke@435: NewInstanceStub(LIR_Opr klass_reg, LIR_Opr result, ciInstanceKlass* klass, CodeEmitInfo* info, Runtime1::StubID stub_id); duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: visitor->do_input(_klass_reg); duke@435: visitor->do_output(_result); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("NewInstanceStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class NewTypeArrayStub: public CodeStub { duke@435: private: duke@435: LIR_Opr _klass_reg; duke@435: LIR_Opr _length; duke@435: LIR_Opr _result; duke@435: CodeEmitInfo* _info; duke@435: duke@435: public: duke@435: NewTypeArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info); duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: visitor->do_input(_klass_reg); duke@435: visitor->do_input(_length); duke@435: assert(_result->is_valid(), "must be valid"); visitor->do_output(_result); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("NewTypeArrayStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class NewObjectArrayStub: public CodeStub { duke@435: private: duke@435: LIR_Opr _klass_reg; duke@435: LIR_Opr _length; duke@435: LIR_Opr _result; duke@435: CodeEmitInfo* _info; duke@435: duke@435: public: duke@435: NewObjectArrayStub(LIR_Opr klass_reg, LIR_Opr length, LIR_Opr result, CodeEmitInfo* info); duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: visitor->do_input(_klass_reg); duke@435: visitor->do_input(_length); duke@435: assert(_result->is_valid(), "must be valid"); visitor->do_output(_result); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("NewObjectArrayStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class MonitorAccessStub: public CodeStub { duke@435: protected: duke@435: LIR_Opr _obj_reg; duke@435: LIR_Opr _lock_reg; duke@435: duke@435: public: duke@435: MonitorAccessStub(LIR_Opr obj_reg, LIR_Opr lock_reg) { duke@435: _obj_reg = obj_reg; duke@435: _lock_reg = lock_reg; duke@435: } duke@435: duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("MonitorAccessStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class MonitorEnterStub: public MonitorAccessStub { duke@435: private: duke@435: CodeEmitInfo* _info; duke@435: duke@435: public: duke@435: MonitorEnterStub(LIR_Opr obj_reg, LIR_Opr lock_reg, CodeEmitInfo* info); duke@435: duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_input(_obj_reg); duke@435: visitor->do_input(_lock_reg); duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("MonitorEnterStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class MonitorExitStub: public MonitorAccessStub { duke@435: private: duke@435: bool _compute_lock; duke@435: int _monitor_ix; duke@435: duke@435: public: duke@435: MonitorExitStub(LIR_Opr lock_reg, bool compute_lock, int monitor_ix) duke@435: : MonitorAccessStub(LIR_OprFact::illegalOpr, lock_reg), duke@435: _compute_lock(compute_lock), _monitor_ix(monitor_ix) { } duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: assert(_obj_reg->is_illegal(), "unused"); duke@435: if (_compute_lock) { duke@435: visitor->do_temp(_lock_reg); duke@435: } else { duke@435: visitor->do_input(_lock_reg); duke@435: } duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("MonitorExitStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class PatchingStub: public CodeStub { duke@435: public: duke@435: enum PatchID { duke@435: access_field_id, duke@435: load_klass_id duke@435: }; duke@435: enum constants { duke@435: patch_info_size = 3 duke@435: }; duke@435: private: duke@435: PatchID _id; duke@435: address _pc_start; duke@435: int _bytes_to_copy; duke@435: Label _patched_code_entry; duke@435: Label _patch_site_entry; duke@435: Label _patch_site_continuation; duke@435: Register _obj; duke@435: CodeEmitInfo* _info; duke@435: int _oop_index; // index of the patchable oop in nmethod oop table if needed duke@435: static int _patch_info_offset; duke@435: duke@435: void align_patch_site(MacroAssembler* masm); duke@435: duke@435: public: duke@435: static int patch_info_offset() { return _patch_info_offset; } duke@435: duke@435: PatchingStub(MacroAssembler* masm, PatchID id, int oop_index = -1): duke@435: _id(id) duke@435: , _info(NULL) duke@435: , _oop_index(oop_index) { duke@435: if (os::is_MP()) { duke@435: // force alignment of patch sites on MP hardware so we duke@435: // can guarantee atomic writes to the patch site. duke@435: align_patch_site(masm); duke@435: } duke@435: _pc_start = masm->pc(); duke@435: masm->bind(_patch_site_entry); duke@435: } duke@435: duke@435: void install(MacroAssembler* masm, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) { duke@435: _info = info; duke@435: _obj = obj; duke@435: masm->bind(_patch_site_continuation); duke@435: _bytes_to_copy = masm->pc() - pc_start(); duke@435: if (_id == PatchingStub::access_field_id) { duke@435: // embed a fixed offset to handle long patches which need to be offset by a word. duke@435: // the patching code will just add the field offset field to this offset so duke@435: // that we can refernce either the high or low word of a double word field. duke@435: int field_offset = 0; duke@435: switch (patch_code) { duke@435: case lir_patch_low: field_offset = lo_word_offset_in_bytes; break; duke@435: case lir_patch_high: field_offset = hi_word_offset_in_bytes; break; duke@435: case lir_patch_normal: field_offset = 0; break; duke@435: default: ShouldNotReachHere(); duke@435: } duke@435: NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start()); duke@435: n_move->set_offset(field_offset); duke@435: } else if (_id == load_klass_id) { duke@435: assert(_obj != noreg, "must have register object for load_klass"); duke@435: #ifdef ASSERT duke@435: // verify that we're pointing at a NativeMovConstReg duke@435: nativeMovConstReg_at(pc_start()); duke@435: #endif duke@435: } else { duke@435: ShouldNotReachHere(); duke@435: } duke@435: assert(_bytes_to_copy <= (masm->pc() - pc_start()), "not enough bytes"); duke@435: } duke@435: duke@435: address pc_start() const { return _pc_start; } duke@435: PatchID id() const { return _id; } duke@435: duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("PatchingStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: twisti@1730: //------------------------------------------------------------------------------ twisti@1730: // DeoptimizeStub twisti@1730: // twisti@1730: class DeoptimizeStub : public CodeStub { twisti@1730: private: twisti@1730: CodeEmitInfo* _info; twisti@1730: twisti@1730: public: twisti@1730: DeoptimizeStub(CodeEmitInfo* info) : _info(new CodeEmitInfo(info)) {} twisti@1730: twisti@1730: virtual void emit_code(LIR_Assembler* e); twisti@1730: virtual CodeEmitInfo* info() const { return _info; } twisti@1730: virtual bool is_exception_throw_stub() const { return true; } twisti@1730: virtual void visit(LIR_OpVisitState* visitor) { twisti@1730: visitor->do_slow_case(_info); twisti@1730: } twisti@1730: #ifndef PRODUCT twisti@1730: virtual void print_name(outputStream* out) const { out->print("DeoptimizeStub"); } twisti@1730: #endif // PRODUCT twisti@1730: }; twisti@1730: twisti@1730: duke@435: class SimpleExceptionStub: public CodeStub { duke@435: private: duke@435: LIR_Opr _obj; duke@435: Runtime1::StubID _stub; duke@435: CodeEmitInfo* _info; duke@435: duke@435: public: duke@435: SimpleExceptionStub(Runtime1::StubID stub, LIR_Opr obj, CodeEmitInfo* info): duke@435: _obj(obj), _info(info), _stub(stub) { duke@435: } duke@435: duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual bool is_exception_throw_stub() const { return true; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: if (_obj->is_valid()) visitor->do_input(_obj); duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("SimpleExceptionStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: duke@435: class ArrayStoreExceptionStub: public CodeStub { duke@435: private: duke@435: CodeEmitInfo* _info; duke@435: duke@435: public: duke@435: ArrayStoreExceptionStub(CodeEmitInfo* info); duke@435: virtual void emit_code(LIR_Assembler* emit); duke@435: virtual CodeEmitInfo* info() const { return _info; } duke@435: virtual bool is_exception_throw_stub() const { return true; } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: visitor->do_slow_case(_info); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("ArrayStoreExceptionStub"); } duke@435: #endif // PRODUCT duke@435: }; duke@435: duke@435: duke@435: class ArrayCopyStub: public CodeStub { duke@435: private: duke@435: LIR_OpArrayCopy* _op; duke@435: duke@435: public: duke@435: ArrayCopyStub(LIR_OpArrayCopy* op): _op(op) { } duke@435: duke@435: LIR_Opr src() const { return _op->src(); } duke@435: LIR_Opr src_pos() const { return _op->src_pos(); } duke@435: LIR_Opr dst() const { return _op->dst(); } duke@435: LIR_Opr dst_pos() const { return _op->dst_pos(); } duke@435: LIR_Opr length() const { return _op->length(); } duke@435: LIR_Opr tmp() const { return _op->tmp(); } duke@435: duke@435: virtual void emit_code(LIR_Assembler* e); duke@435: virtual CodeEmitInfo* info() const { return _op->info(); } duke@435: virtual void visit(LIR_OpVisitState* visitor) { duke@435: // don't pass in the code emit info since it's processed in the fast path duke@435: visitor->do_slow_case(); duke@435: } duke@435: #ifndef PRODUCT duke@435: virtual void print_name(outputStream* out) const { out->print("ArrayCopyStub"); } duke@435: #endif // PRODUCT duke@435: }; ysr@777: ysr@777: ////////////////////////////////////////////////////////////////////////////////////////// ysr@777: #ifndef SERIALGC ysr@777: ysr@777: // Code stubs for Garbage-First barriers. ysr@777: class G1PreBarrierStub: public CodeStub { ysr@777: private: ysr@777: LIR_Opr _addr; ysr@777: LIR_Opr _pre_val; ysr@777: LIR_PatchCode _patch_code; ysr@777: CodeEmitInfo* _info; ysr@777: ysr@777: public: ysr@777: // pre_val (a temporary register) must be a register; ysr@777: // addr (the address of the field to be read) must be a LIR_Address ysr@777: G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) : ysr@777: _addr(addr), _pre_val(pre_val), _patch_code(patch_code), _info(info) ysr@777: { ysr@777: assert(_pre_val->is_register(), "should be temporary register"); ysr@777: assert(_addr->is_address(), "should be the address of the field"); ysr@777: } ysr@777: ysr@777: LIR_Opr addr() const { return _addr; } ysr@777: LIR_Opr pre_val() const { return _pre_val; } ysr@777: LIR_PatchCode patch_code() const { return _patch_code; } ysr@777: CodeEmitInfo* info() const { return _info; } ysr@777: ysr@777: virtual void emit_code(LIR_Assembler* e); ysr@777: virtual void visit(LIR_OpVisitState* visitor) { ysr@777: // don't pass in the code emit info since it's processed in the fast ysr@777: // path ysr@777: if (_info != NULL) ysr@777: visitor->do_slow_case(_info); ysr@777: else ysr@777: visitor->do_slow_case(); ysr@777: visitor->do_input(_addr); ysr@777: visitor->do_temp(_pre_val); ysr@777: } ysr@777: #ifndef PRODUCT ysr@777: virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); } ysr@777: #endif // PRODUCT ysr@777: }; ysr@777: ysr@777: class G1PostBarrierStub: public CodeStub { ysr@777: private: ysr@777: LIR_Opr _addr; ysr@777: LIR_Opr _new_val; ysr@777: ysr@777: static jbyte* _byte_map_base; ysr@777: static jbyte* byte_map_base_slow(); ysr@777: static jbyte* byte_map_base() { ysr@777: if (_byte_map_base == NULL) { ysr@777: _byte_map_base = byte_map_base_slow(); ysr@777: } ysr@777: return _byte_map_base; ysr@777: } ysr@777: ysr@777: public: ysr@777: // addr (the address of the object head) and new_val must be registers. ysr@777: G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { } ysr@777: ysr@777: LIR_Opr addr() const { return _addr; } ysr@777: LIR_Opr new_val() const { return _new_val; } ysr@777: ysr@777: virtual void emit_code(LIR_Assembler* e); ysr@777: virtual void visit(LIR_OpVisitState* visitor) { ysr@777: // don't pass in the code emit info since it's processed in the fast path ysr@777: visitor->do_slow_case(); ysr@777: visitor->do_input(_addr); ysr@777: visitor->do_input(_new_val); ysr@777: } ysr@777: #ifndef PRODUCT ysr@777: virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); } ysr@777: #endif // PRODUCT ysr@777: }; ysr@777: ysr@777: #endif // SERIALGC ysr@777: //////////////////////////////////////////////////////////////////////////////////////////