hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
Print this page
rev 611 : Merge
@@ -1,10 +1,7 @@
-#ifdef USE_PRAGMA_IDENT_SRC
-#pragma ident "@(#)templateTable_sparc.cpp 1.262 07/08/29 13:42:19 JVM"
-#endif
/*
- * Copyright 1997-2007 Sun Microsystems, Inc. All Rights Reserved.
+ * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -29,10 +26,83 @@
#include "incls/_templateTable_sparc.cpp.incl"
#ifndef CC_INTERP
#define __ _masm->
+// Misc helpers
+
+// Do an oop store like *(base + index + offset) = val
+// index can be noreg,
+static void do_oop_store(InterpreterMacroAssembler* _masm,
+ Register base,
+ Register index,
+ int offset,
+ Register val,
+ Register tmp,
+ BarrierSet::Name barrier,
+ bool precise) {
+ assert(tmp != val && tmp != base && tmp != index, "register collision");
+ assert(index == noreg || offset == 0, "only one offset");
+ switch (barrier) {
+#ifndef SERIALGC
+ case BarrierSet::G1SATBCT:
+ case BarrierSet::G1SATBCTLogging:
+ {
+ __ g1_write_barrier_pre( base, index, offset, tmp, /*preserve_o_regs*/true);
+ if (index == noreg ) {
+ assert(Assembler::is_simm13(offset), "fix this code");
+ __ store_heap_oop(val, base, offset);
+ } else {
+ __ store_heap_oop(val, base, index);
+ }
+
+ // No need for post barrier if storing NULL
+ if (val != G0) {
+ if (precise) {
+ if (index == noreg) {
+ __ add(base, offset, base);
+ } else {
+ __ add(base, index, base);
+ }
+ }
+ __ g1_write_barrier_post(base, val, tmp);
+ }
+ }
+ break;
+#endif // SERIALGC
+ case BarrierSet::CardTableModRef:
+ case BarrierSet::CardTableExtension:
+ {
+ if (index == noreg ) {
+ assert(Assembler::is_simm13(offset), "fix this code");
+ __ store_heap_oop(val, base, offset);
+ } else {
+ __ store_heap_oop(val, base, index);
+ }
+ // No need for post barrier if storing NULL
+ if (val != G0) {
+ if (precise) {
+ if (index == noreg) {
+ __ add(base, offset, base);
+ } else {
+ __ add(base, index, base);
+ }
+ }
+ __ card_write_barrier_post(base, val, tmp);
+ }
+ }
+ break;
+ case BarrierSet::ModRef:
+ case BarrierSet::Other:
+ ShouldNotReachHere();
+ break;
+ default :
+ ShouldNotReachHere();
+
+ }
+}
+
//----------------------------------------------------------------------------------------------------
// Platform-dependent initialization
void TemplateTable::pd_initialize() {
@@ -463,12 +533,12 @@
void TemplateTable::aaload() {
transition(itos, atos);
// Otos_i: index
// tos: array
- __ index_check(O2, Otos_i, LogBytesPerWord, G3_scratch, O3);
- __ ld_ptr(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i);
+ __ index_check(O2, Otos_i, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O3);
+ __ load_heap_oop(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i);
__ verify_oop(Otos_i);
}
void TemplateTable::baload() {
@@ -737,19 +807,20 @@
__ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(2), O3); // get array
// Otos_i: val
// O2: index
// O3: array
__ verify_oop(Otos_i);
- __ index_check_without_pop(O3, O2, LogBytesPerWord, G3_scratch, O1);
+ __ index_check_without_pop(O3, O2, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O1);
// do array store check - check for NULL value first
__ br_null( Otos_i, false, Assembler::pn, is_null );
- __ delayed()->
- ld_ptr(O3, oopDesc::klass_offset_in_bytes(), O4); // get array klass
+ __ delayed()->nop();
+
+ __ load_klass(O3, O4); // get array klass
+ __ load_klass(Otos_i, O5); // get value klass
// do fast instanceof cache test
- __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), O5); // get value klass
__ ld_ptr(O4, sizeof(oopDesc) + objArrayKlass::element_klass_offset_in_bytes(), O4);
assert(Otos_i == O0, "just checking");
@@ -758,31 +829,29 @@
// O2: index
// O3: array
// O4: array element klass
// O5: value klass
+ // Address element(O1, 0, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
+
// Generate a fast subtype check. Branch to store_ok if no
// failure. Throw if failure.
__ gen_subtype_check( O5, O4, G3_scratch, G4_scratch, G1_scratch, store_ok );
// Not a subtype; so must throw exception
__ throw_if_not_x( Assembler::never, Interpreter::_throw_ArrayStoreException_entry, G3_scratch );
// Store is OK.
__ bind(store_ok);
- __ st_ptr(Otos_i, O1, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
- // Quote from rememberedSet.hpp: For objArrays, the precise card
- // corresponding to the pointer store is dirtied so we don't need to
- // scavenge the entire array.
- Address element(O1, 0, arrayOopDesc::base_offset_in_bytes(T_OBJECT));
- __ add(element, O1); // address the element precisely
- __ store_check(G3_scratch, O1);
+ do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, _bs->kind(), true);
+
__ ba(false,done);
__ delayed()->inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value)
__ bind(is_null);
- __ st_ptr(Otos_i, element);
+ do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, _bs->kind(), true);
+
__ profile_null_seen(G3_scratch);
__ inc(Lesp, 3* Interpreter::stackElementSize()); // adj sp (pops array, index and value)
__ bind(done);
}
@@ -1834,11 +1903,11 @@
if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
assert(state == vtos, "only valid state");
__ mov(G0, G3_scratch);
__ access_local_ptr(G3_scratch, Otos_i);
- __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), O2);
+ __ load_klass(Otos_i, O2);
__ set(JVM_ACC_HAS_FINALIZER, G3);
__ ld(O2, Klass::access_flags_offset_in_bytes() + sizeof(oopDesc), O2);
__ andcc(G3, O2, G0);
Label skip_register_finalizer;
__ br(Assembler::zero, false, Assembler::pn, skip_register_finalizer);
@@ -2014,11 +2083,11 @@
if (is_static) {
__ clr(Otos_i);
} else {
if (has_tos) {
// save object pointer before call_VM() clobbers it
- __ mov(Otos_i, Lscratch);
+ __ push_ptr(Otos_i); // put object on tos where GC wants it.
} else {
// Load top of stack (do not pop the value off the stack);
__ ld_ptr(Lesp, Interpreter::expr_offset_in_bytes(0), Otos_i);
}
__ verify_oop(Otos_i);
@@ -2026,11 +2095,11 @@
// Otos_i: object pointer or NULL if static
// Rcache: cache entry pointer
__ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access),
Otos_i, Rcache);
if (!is_static && has_tos) {
- __ mov(Lscratch, Otos_i); // restore object pointer
+ __ pop_ptr(Otos_i); // restore object pointer
__ verify_oop(Otos_i);
}
__ get_cache_and_index_at_bcp(Rcache, index, 1);
__ bind(Label1);
}
@@ -2079,11 +2148,11 @@
__ cmp(Rflags, atos);
__ br(Assembler::notEqual, false, Assembler::pt, notObj);
__ delayed() ->cmp(Rflags, itos);
// atos
- __ ld_ptr(Rclass, Roffset, Otos_i);
+ __ load_heap_oop(Rclass, Roffset, Otos_i);
__ verify_oop(Otos_i);
__ push(atos);
if (!is_static) {
patch_bytecode(Bytecodes::_fast_agetfield, G3_scratch, G4_scratch);
}
@@ -2260,11 +2329,11 @@
break;
case Bytecodes::_fast_dgetfield:
__ ldf(FloatRegisterImpl::D, Otos_i, Roffset, Ftos_d);
break;
case Bytecodes::_fast_agetfield:
- __ ld_ptr(Otos_i, Roffset, Otos_i);
+ __ load_heap_oop(Otos_i, Roffset, Otos_i);
break;
default:
ShouldNotReachHere();
}
@@ -2449,12 +2518,13 @@
__ delayed() ->cmp(Rflags, itos );
// atos
__ pop_ptr();
__ verify_oop(Otos_i);
- __ st_ptr(Otos_i, Rclass, Roffset);
- __ store_check(G1_scratch, Rclass, Roffset);
+
+ do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+
__ ba(false, checkVolatile);
__ delayed()->tst(Lscratch);
__ bind(notObj);
@@ -2491,12 +2561,13 @@
// atos
__ pop_ptr();
pop_and_check_object(Rclass);
__ verify_oop(Otos_i);
- __ st_ptr(Otos_i, Rclass, Roffset);
- __ store_check(G1_scratch, Rclass, Roffset);
+
+ do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+
patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch);
__ ba(false, checkVolatile);
__ delayed()->tst(Lscratch);
__ bind(notObj);
@@ -2646,12 +2717,11 @@
break;
case Bytecodes::_fast_dputfield:
__ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
break;
case Bytecodes::_fast_aputfield:
- __ st_ptr(Otos_i, Rclass, Roffset);
- __ store_check(G1_scratch, Rclass, Roffset);
+ do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
break;
default:
ShouldNotReachHere();
}
@@ -2689,11 +2759,11 @@
__ add(Lbcp, 1, Lbcp); // needed to report exception at the correct bcp
__ verify_oop(Rreceiver);
__ null_check(Rreceiver);
if (state == atos) {
- __ ld_ptr(Rreceiver, Roffset, Otos_i);
+ __ load_heap_oop(Rreceiver, Roffset, Otos_i);
} else if (state == itos) {
__ ld (Rreceiver, Roffset, Otos_i) ;
} else if (state == ftos) {
__ ldf(FloatRegisterImpl::S, Rreceiver, Roffset, Ftos_f);
} else {
@@ -2791,11 +2861,11 @@
__ sll(Rret, LogBytesPerWord, Rret);
__ ld_ptr(Rtemp, Rret, Rret); // get return address
// get receiver klass
__ null_check(O0, oopDesc::klass_offset_in_bytes());
- __ ld_ptr(Address(O0, 0, oopDesc::klass_offset_in_bytes()), Rrecv);
+ __ load_klass(O0, Rrecv);
__ verify_oop(Rrecv);
__ profile_virtual_call(Rrecv, O4);
generate_vtable_call(Rrecv, Rscratch, Rret);
@@ -2959,11 +3029,11 @@
__ sll(Rret, LogBytesPerWord, Rret);
__ ld_ptr(Rscratch, Rret, Rret); // get return address
// get receiver klass
__ null_check(O0, oopDesc::klass_offset_in_bytes());
- __ ld_ptr(O0, oopDesc::klass_offset_in_bytes(), RklassOop);
+ __ load_klass(O0, RklassOop);
__ verify_oop(RklassOop);
// Special case of invokeinterface called for virtual method of
// java.lang.Object. See cpCacheOop.cpp for details.
// This code isn't produced by javac, but could be produced by
@@ -3222,11 +3292,12 @@
__ ld_ptr(RinstanceKlass, Klass::prototype_header_offset_in_bytes() + sizeof(oopDesc), G4_scratch);
} else {
__ set((intptr_t)markOopDesc::prototype(), G4_scratch);
}
__ st_ptr(G4_scratch, RallocatedObject, oopDesc::mark_offset_in_bytes()); // mark
- __ st_ptr(RinstanceKlass, RallocatedObject, oopDesc::klass_offset_in_bytes()); // klass
+ __ store_klass_gap(G0, RallocatedObject); // klass gap if compressed
+ __ store_klass(RinstanceKlass, RallocatedObject); // klass (last for cms)
{
SkipIfEqual skip_if(
_masm, G4_scratch, &DTraceAllocProbes, Assembler::zero);
// Trigger dtrace event
@@ -3278,11 +3349,11 @@
// Check for casting a NULL
__ br_null(Otos_i, false, Assembler::pn, is_null);
__ delayed()->nop();
// Get value klass in RobjKlass
- __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
+ __ load_klass(Otos_i, RobjKlass); // get value klass
// Get constant pool tag
__ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
// See if the checkcast has been quickened
@@ -3296,17 +3367,18 @@
__ push_ptr(); // save receiver for result, and for GC
call_VM(RspecifiedKlass, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
__ pop_ptr(Otos_i, G3_scratch); // restore receiver
__ br(Assembler::always, false, Assembler::pt, resolved);
- __ delayed()->ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
+ __ delayed()->nop();
// Extract target class from constant pool
__ bind(quicked);
__ add(Roffset, sizeof(constantPoolOopDesc), Roffset);
__ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
__ bind(resolved);
+ __ load_klass(Otos_i, RobjKlass); // get value klass
// Generate a fast subtype check. Branch to cast_ok if no
// failure. Throw exception if failure.
__ gen_subtype_check( RobjKlass, RspecifiedKlass, G3_scratch, G4_scratch, G1_scratch, cast_ok );
@@ -3335,11 +3407,11 @@
// Check for casting a NULL
__ br_null(Otos_i, false, Assembler::pt, is_null);
__ delayed()->nop();
// Get value klass in RobjKlass
- __ ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
+ __ load_klass(Otos_i, RobjKlass); // get value klass
// Get constant pool tag
__ get_2_byte_integer_at_bcp(1, Lscratch, Roffset, InterpreterMacroAssembler::Unsigned);
// See if the checkcast has been quickened
@@ -3353,19 +3425,20 @@
__ push_ptr(); // save receiver for result, and for GC
call_VM(RspecifiedKlass, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
__ pop_ptr(Otos_i, G3_scratch); // restore receiver
__ br(Assembler::always, false, Assembler::pt, resolved);
- __ delayed()->ld_ptr(Otos_i, oopDesc::klass_offset_in_bytes(), RobjKlass); // get value klass
+ __ delayed()->nop();
// Extract target class from constant pool
__ bind(quicked);
__ add(Roffset, sizeof(constantPoolOopDesc), Roffset);
__ get_constant_pool(Lscratch);
__ ld_ptr(Lscratch, Roffset, RspecifiedKlass);
__ bind(resolved);
+ __ load_klass(Otos_i, RobjKlass); // get value klass
// Generate a fast subtype check. Branch to cast_ok if no
// failure. Return 0 if failure.
__ or3(G0, 1, Otos_i); // set result assuming quick tests succeed
__ gen_subtype_check( RobjKlass, RspecifiedKlass, G3_scratch, G4_scratch, G1_scratch, done );