--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp Tue Apr 19 20:40:20 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp Wed Apr 20 20:32:45 2011 -0700
@@ -6902,26 +6902,39 @@
#ifndef SERIALGC
void MacroAssembler::g1_write_barrier_pre(Register obj,
-#ifndef _LP64
+ Register pre_val,
Register thread,
-#endif
Register tmp,
- Register tmp2,
- bool tosca_live) {
- LP64_ONLY(Register thread = r15_thread;)
+ bool tosca_live,
+ bool expand_call) {
+
+ // If expand_call is true then we expand the call_VM_leaf macro
+ // directly to skip generating the check by
+ // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
+
+#ifdef _LP64
+ assert(thread == r15_thread, "must be");
+#endif // _LP64
+
+ Label done;
+ Label runtime;
+
+ assert(pre_val != noreg, "check this code");
+
+ if (obj != noreg) {
+ assert_different_registers(obj, pre_val, tmp);
+ assert(pre_val != rax, "check this code");
+ }
+
Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_active()));
-
Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
PtrQueue::byte_offset_of_buf()));
- Label done;
- Label runtime;
-
- // if (!marking_in_progress) goto done;
+ // Is marking active?
if (in_bytes(PtrQueue::byte_width_of_active()) == 4) {
cmpl(in_progress, 0);
} else {
@@ -6930,65 +6943,92 @@
}
jcc(Assembler::equal, done);
- // if (x.f == NULL) goto done;
-#ifdef _LP64
- load_heap_oop(tmp2, Address(obj, 0));
-#else
- movptr(tmp2, Address(obj, 0));
-#endif
- cmpptr(tmp2, (int32_t) NULL_WORD);
+ // Do we need to load the previous value?
+ if (obj != noreg) {
+ load_heap_oop(pre_val, Address(obj, 0));
+ }
+
+ // Is the previous value null?
+ cmpptr(pre_val, (int32_t) NULL_WORD);
jcc(Assembler::equal, done);
// Can we store original value in the thread's buffer?
-
-#ifdef _LP64
- movslq(tmp, index);
- cmpq(tmp, 0);
-#else
- cmpl(index, 0);
-#endif
- jcc(Assembler::equal, runtime);
-#ifdef _LP64
- subq(tmp, wordSize);
- movl(index, tmp);
- addq(tmp, buffer);
-#else
- subl(index, wordSize);
- movl(tmp, buffer);
- addl(tmp, index);
-#endif
- movptr(Address(tmp, 0), tmp2);
+ // Is index == 0?
+ // (The index field is typed as size_t.)
+
+ movptr(tmp, index); // tmp := *index_adr
+ cmpptr(tmp, 0); // tmp == 0?
+ jcc(Assembler::equal, runtime); // If yes, goto runtime
+
+ subptr(tmp, wordSize); // tmp := tmp - wordSize
+ movptr(index, tmp); // *index_adr := tmp
+ addptr(tmp, buffer); // tmp := tmp + *buffer_adr
+
+ // Record the previous value
+ movptr(Address(tmp, 0), pre_val);
jmp(done);
+
bind(runtime);
// save the live input values
if(tosca_live) push(rax);
- push(obj);
-#ifdef _LP64
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, r15_thread);
-#else
- push(thread);
- call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), tmp2, thread);
- pop(thread);
-#endif
- pop(obj);
+
+ if (obj != noreg && obj != rax)
+ push(obj);
+
+ if (pre_val != rax)
+ push(pre_val);
+
+ // Calling the runtime using the regular call_VM_leaf mechanism generates
+ // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
+ // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
+ //
+ // If we care generating the pre-barrier without a frame (e.g. in the
+ // intrinsified Reference.get() routine) then ebp might be pointing to
+ // the caller frame and so this check will most likely fail at runtime.
+ //
+ // Expanding the call directly bypasses the generation of the check.
+ // So when we do not have have a full interpreter frame on the stack
+ // expand_call should be passed true.
+
+ NOT_LP64( push(thread); )
+
+ if (expand_call) {
+ LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
+ pass_arg1(this, thread);
+ pass_arg0(this, pre_val);
+ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2);
+ } else {
+ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
+ }
+
+ NOT_LP64( pop(thread); )
+
+ // save the live input values
+ if (pre_val != rax)
+ pop(pre_val);
+
+ if (obj != noreg && obj != rax)
+ pop(obj);
+
if(tosca_live) pop(rax);
+
bind(done);
-
}
void MacroAssembler::g1_write_barrier_post(Register store_addr,
Register new_val,
-#ifndef _LP64
Register thread,
-#endif
Register tmp,
Register tmp2) {
-
- LP64_ONLY(Register thread = r15_thread;)
+#ifdef _LP64
+ assert(thread == r15_thread, "must be");
+#endif // _LP64
+
Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
PtrQueue::byte_offset_of_index()));
Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
PtrQueue::byte_offset_of_buf()));
+
BarrierSet* bs = Universe::heap()->barrier_set();
CardTableModRefBS* ct = (CardTableModRefBS*)bs;
Label done;
@@ -7067,7 +7107,6 @@
pop(store_addr);
bind(done);
-
}
#endif // SERIALGC