aoqi@1: /* aoqi@1: * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@1: * Copyright (c) 2015, 2016, Loongson Technology. All rights reserved. aoqi@1: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@1: * aoqi@1: * This code is free software; you can redistribute it and/or modify it aoqi@1: * under the terms of the GNU General Public License version 2 only, as aoqi@1: * published by the Free Software Foundation. aoqi@1: * aoqi@1: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@1: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@1: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@1: * version 2 for more details (a copy is included in the LICENSE file that aoqi@1: * accompanied this code). aoqi@1: * aoqi@1: * You should have received a copy of the GNU General Public License version aoqi@1: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@1: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@1: * aoqi@1: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@1: * or visit www.oracle.com if you need additional information or have any aoqi@1: * questions. aoqi@1: * aoqi@1: */ aoqi@1: aoqi@1: #include "precompiled.hpp" aoqi@1: #include "c1/c1_MacroAssembler.hpp" aoqi@1: #include "c1/c1_Runtime1.hpp" aoqi@1: #include "classfile/systemDictionary.hpp" aoqi@1: #include "gc_interface/collectedHeap.hpp" aoqi@1: #include "interpreter/interpreter.hpp" aoqi@1: #include "oops/arrayOop.hpp" aoqi@1: #include "oops/markOop.hpp" aoqi@1: #include "runtime/basicLock.hpp" aoqi@1: #include "runtime/biasedLocking.hpp" aoqi@1: #include "runtime/os.hpp" aoqi@1: #include "runtime/stubRoutines.hpp" aoqi@1: aoqi@1: int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr,Register scratch, Label& slow_case) { aoqi@1: const int aligned_mask = BytesPerWord -1; aoqi@1: const int hdr_offset = oopDesc::mark_offset_in_bytes(); aoqi@1: aoqi@1: // hdr is just a temperary register, it cannot be AT, however aoqi@1: if ( hdr == NOREG ) { aoqi@1: hdr = T8; aoqi@1: } aoqi@1: aoqi@1: assert_different_registers(hdr, obj, disp_hdr); aoqi@1: Label done; aoqi@1: // The following move must be the first instruction of emitted since debug aoqi@1: // information may be generated for it. aoqi@1: // Load object header aoqi@1: int null_check_offset = -1; aoqi@1: verify_oop(obj); aoqi@1: aoqi@1: // save object being locked into the BasicObjectLock aoqi@1: st_ptr(obj, disp_hdr, BasicObjectLock::obj_offset_in_bytes()); aoqi@1: if (UseBiasedLocking) { aoqi@1: assert(scratch != noreg, "should have scratch register at this point"); aoqi@1: null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, aoqi@1: done, &slow_case); aoqi@1: } else { aoqi@1: null_check_offset = offset(); aoqi@1: } aoqi@1: aoqi@1: // Load object header aoqi@1: ld_ptr(hdr, obj, hdr_offset); aoqi@1: // and mark it as unlocked aoqi@1: ori(hdr, hdr, markOopDesc::unlocked_value); aoqi@1: // save unlocked object header into the displaced header location on the stack aoqi@1: sd(hdr, disp_hdr, 0); aoqi@1: aoqi@1: // test if object header is still the same (i.e. unlocked), and if so, store the aoqi@1: // displaced header address in the object header - if it is not the same, get the aoqi@1: // object header instead aoqi@1: //if (os::is_MP()) MacroAssembler::lock(); // must be immediately before cmpxchg! aoqi@1: cmpxchg(disp_hdr, Address(obj, hdr_offset), hdr); aoqi@1: // if the object header was the same, we're done aoqi@1: if (PrintBiasedLockingStatistics) { aoqi@29: Label L; aoqi@29: beq(AT, R0, L); aoqi@29: delayed()->nop(); aoqi@29: push(T0); aoqi@29: push(T1); aoqi@29: li(T0, (address) BiasedLocking::fast_path_entry_count_addr()); aoqi@29: lw(T1, T0, 0); aoqi@29: addi(T1, T1, 1); aoqi@29: sw(T1, T0, 0); aoqi@29: pop(T1); aoqi@29: pop(T0); aoqi@29: bind(L); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: bne(AT, R0, done); aoqi@1: delayed()->nop(); aoqi@1: // if the object header was not the same, it is now in the hdr register aoqi@1: // => test if it is a stack pointer into the same stack (recursive locking), i.e.: aoqi@1: // aoqi@1: // 1) (hdr & aligned_mask) == 0 aoqi@1: // 2) SP <= hdr aoqi@1: // 3) hdr <= SP + page_size aoqi@1: // aoqi@1: // these 3 tests can be done by evaluating the following expression: aoqi@1: // aoqi@1: // (hdr - SP) & (aligned_mask - page_size) aoqi@1: // aoqi@1: // assuming both the stack pointer and page_size have their least aoqi@1: // significant 2 bits cleared and page_size is a power of 2 aoqi@1: sub(hdr, hdr, SP); aoqi@1: move(AT, aligned_mask - os::vm_page_size()); aoqi@1: andr(hdr, hdr, AT); aoqi@1: // for recursive locking, the result is zero => save it in the displaced header aoqi@1: // location (NULL in the displaced hdr location indicates recursive locking) aoqi@1: st_ptr(hdr, disp_hdr, 0); aoqi@1: // otherwise we don't care about the result and handle locking via runtime call aoqi@1: bne_far(hdr, R0, slow_case); aoqi@1: delayed()->nop(); aoqi@1: // done aoqi@1: bind(done); aoqi@1: return null_check_offset; aoqi@1: } aoqi@1: aoqi@1: aoqi@1: void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) { aoqi@1: const int aligned_mask = BytesPerWord -1; aoqi@1: const int hdr_offset = oopDesc::mark_offset_in_bytes(); aoqi@1: aoqi@1: // hdr is just a temparay register, however, it cannot be AT aoqi@1: if ( hdr == NOREG ) { aoqi@1: hdr = T8; aoqi@1: } aoqi@1: aoqi@1: assert_different_registers(hdr, obj, disp_hdr); aoqi@1: assert(BytesPerWord == 8, "adjust aligned_mask and code"); aoqi@1: Label done; aoqi@1: if (UseBiasedLocking) { aoqi@1: // load object aoqi@1: ld_ptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes())); aoqi@1: biased_locking_exit(obj, hdr, done); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: aoqi@1: // load displaced header aoqi@1: ld_ptr(hdr, disp_hdr, 0); aoqi@1: // if the loaded hdr is NULL we had recursive locking aoqi@1: // if we had recursive locking, we are done aoqi@1: beq(hdr, R0, done); aoqi@1: delayed()->nop(); aoqi@1: // load object aoqi@1: if(!UseBiasedLocking){ aoqi@1: ld_ptr(obj, disp_hdr, BasicObjectLock::obj_offset_in_bytes()); aoqi@1: } aoqi@1: aoqi@1: verify_oop(obj); aoqi@1: // test if object header is pointing to the displaced header, and if so, restore aoqi@1: // the displaced header in the object - if the object header is not pointing to aoqi@1: // the displaced header, get the object header instead aoqi@1: //if (os::is_MP()) MacroAssembler::lock(); // must be immediately before cmpxchg! aoqi@1: cmpxchg(hdr, Address(obj, hdr_offset), disp_hdr); aoqi@1: // if the object header was not pointing to the displaced header, aoqi@1: // we do unlocking via runtime call aoqi@1: beq_far(AT, R0, slow_case); aoqi@1: delayed()->nop(); aoqi@1: // done aoqi@1: bind(done); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: aoqi@1: // Defines obj, preserves var_size_in_bytes aoqi@1: void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) { aoqi@1: if (UseTLAB) { aoqi@1: tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); aoqi@1: } else { aoqi@1: eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); aoqi@1: } aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1 , Register t2) { aoqi@1: assert_different_registers(obj, klass, len, AT); aoqi@1: aoqi@1: if (UseBiasedLocking && !len->is_valid()) { aoqi@1: assert_different_registers(obj, klass, len, t1, t2); aoqi@1: ld_ptr(t1, klass, in_bytes(Klass::prototype_header_offset())); aoqi@1: st_ptr(t1, obj, oopDesc::mark_offset_in_bytes()); aoqi@1: } else { aoqi@1: li(AT, (intptr_t)markOopDesc::prototype()); aoqi@1: st_ptr(AT, obj, oopDesc::mark_offset_in_bytes()); aoqi@1: } aoqi@1: //st_ptr(klass, obj, oopDesc::klass_offset_in_bytes()); aoqi@1: #ifdef _LP64 aoqi@1: if (UseCompressedOops) { aoqi@1: move(AT, klass); aoqi@1: store_klass(obj, AT); aoqi@1: } else aoqi@1: #endif aoqi@1: { aoqi@1: st_ptr(klass, obj, oopDesc::klass_offset_in_bytes()); aoqi@1: } aoqi@1: aoqi@1: if (len->is_valid()) { aoqi@1: sw(len, obj, arrayOopDesc::length_offset_in_bytes()); aoqi@1: } aoqi@1: #ifdef _LP64 aoqi@1: else if (UseCompressedOops) { aoqi@1: store_klass_gap(obj, R0); aoqi@1: } aoqi@1: aoqi@1: #endif aoqi@1: } aoqi@1: aoqi@1: // preserves obj, destroys len_in_bytes aoqi@1: void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) { aoqi@1: Label done; aoqi@1: Register ptr = t1; aoqi@1: assert_different_registers(obj, ptr, len_in_bytes); aoqi@1: assert((hdr_size_in_bytes & (BytesPerWord - 1)) == 0, aoqi@1: "header size is not a multiple of BytesPerWord"); aoqi@1: Register index = len_in_bytes; aoqi@1: aoqi@1: //tty->print_cr("C1_MacroAssembler::initialize_body LEN=0x%x, hdr_size=0x%x", len_in_bytes, hdr_size_in_bytes); aoqi@1: assert(is_simm16(hdr_size_in_bytes), "change this code"); aoqi@1: addi(index, index, - hdr_size_in_bytes); aoqi@1: beq(index, R0, done); aoqi@1: delayed(); aoqi@1: aoqi@1: // initialize topmost word, divide index by 2, check if odd and test if zero aoqi@1: // note: for the remaining code to work, index must be a multiple of BytesPerWord aoqi@1: #ifdef ASSERT aoqi@1: { aoqi@1: Label L; aoqi@1: andi(AT, index, BytesPerWord - 1); aoqi@1: beq(AT, R0, L); aoqi@1: delayed()->nop(); aoqi@1: stop("index is not a multiple of BytesPerWord"); aoqi@1: bind(L); aoqi@1: } aoqi@1: #endif aoqi@1: // index could have been not a multiple of 8 (i.e., bit 2 was set) aoqi@1: { aoqi@1: Label even; aoqi@1: // note: if index was a multiple of 8, than it cannot aoqi@1: // be 0 now otherwise it must have been 0 before aoqi@1: // => if it is even, we don't need to check for 0 again aoqi@1: #ifdef _LP64 aoqi@1: andi(AT, index, 8); aoqi@1: shr(index, 4); aoqi@1: shl(index, 4); aoqi@1: #else aoqi@1: andi(AT, index, 4); aoqi@1: shr(index, 3); aoqi@1: shl(index, 3); aoqi@1: #endif aoqi@1: beq(AT, R0, even); aoqi@1: delayed()->add(ptr, obj, index); aoqi@1: // clear topmost word (no jump needed if conditional assignment would work here) aoqi@1: st_ptr(R0, ptr, hdr_size_in_bytes); aoqi@1: // index could be 0 now, need to check again aoqi@1: beq(index, R0, done); aoqi@1: delayed()->nop(); aoqi@1: bind(even); aoqi@1: } aoqi@1: // initialize remaining object fields: edx is a multiple of 2 now aoqi@1: { aoqi@1: Label loop; aoqi@1: bind(loop); aoqi@1: st_ptr(R0, ptr, hdr_size_in_bytes - 1*BytesPerWord); aoqi@1: st_ptr(R0, ptr, hdr_size_in_bytes - 2*BytesPerWord); aoqi@1: aoqi@1: addi(index, index, - 2 * wordSize); aoqi@1: bne(index, R0, loop); aoqi@1: delayed()->addi(ptr, ptr, - 2 * wordSize); aoqi@1: } aoqi@1: aoqi@1: // done aoqi@1: bind(done); aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) { aoqi@1: //assert(obj == rax, "obj must be in rax, for cmpxchg"); aoqi@1: assert(obj != t1 && obj != t2 && t1 != t2, "registers must be different"); // XXX really? aoqi@1: assert(header_size >= 0 && object_size >= header_size, "illegal sizes"); aoqi@1: aoqi@1: try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case); aoqi@1: aoqi@1: initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2); aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) { aoqi@1: assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, aoqi@1: "con_size_in_bytes is not multiple of alignment"); aoqi@1: //Merged from b25 aoqi@1: const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; aoqi@1: aoqi@1: // initialize_header(obj, klass, NOREG); aoqi@1: initialize_header(obj, klass, NOREG,t1,t2); aoqi@1: aoqi@1: // clear rest of allocated space aoqi@1: const Register index = t2; aoqi@1: //FIXME, x86 changed the value in jdk6 aoqi@1: // const int threshold = hdr_size_in_bytes + 36; aoqi@1: // // approximate break even point for code size (see comments below) aoqi@1: const int threshold = 6 * BytesPerWord; aoqi@1: // approximate break even point for code size (see comments below) aoqi@1: if (var_size_in_bytes != NOREG) { aoqi@1: move(index, var_size_in_bytes); aoqi@1: initialize_body(obj, index, hdr_size_in_bytes, t1); aoqi@1: } else if (con_size_in_bytes <= threshold) { aoqi@1: // use explicit null stores aoqi@1: // code size = 4*n bytes (n = number of fields to clear) aoqi@1: aoqi@1: for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord) { aoqi@1: st_ptr(R0, obj, i); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: aoqi@1: } else if(con_size_in_bytes > hdr_size_in_bytes) { aoqi@1: // use loop to null out the fields aoqi@1: // code size = 32 bytes for even n (n = number of fields to clear) aoqi@1: // initialize last object field first if odd number of fields aoqi@1: assert( ((con_size_in_bytes - hdr_size_in_bytes) >> 3)!=0, "change code here"); aoqi@1: aoqi@1: #ifdef _LP64 aoqi@1: move(index, (con_size_in_bytes - hdr_size_in_bytes) >> 4); aoqi@1: sll(t1, index, 4); aoqi@1: #else aoqi@1: move(index, (con_size_in_bytes - hdr_size_in_bytes) >> 3); aoqi@1: sll(t1, index, 3); aoqi@1: #endif aoqi@1: add(t1, obj, t1); aoqi@1: aoqi@1: // initialize last object field if constant size is odd aoqi@1: #ifdef _LP64 aoqi@1: if (! UseCompressedOops) aoqi@1: { aoqi@1: if (((con_size_in_bytes - hdr_size_in_bytes) & 8) != 0) { aoqi@1: sd(R0, t1, hdr_size_in_bytes); aoqi@1: } aoqi@1: } else if (UseCompressedOops) { aoqi@1: int extra = (con_size_in_bytes - hdr_size_in_bytes) % 16; aoqi@1: while (extra != 0) { aoqi@1: sw(R0, t1, hdr_size_in_bytes + extra - 4); aoqi@1: extra -= 4; aoqi@1: } aoqi@1: } aoqi@1: #else aoqi@1: if (((con_size_in_bytes - hdr_size_in_bytes) & 4) != 0) { aoqi@1: sw(R0, t1, hdr_size_in_bytes); aoqi@1: } aoqi@1: #endif aoqi@1: // initialize remaining object fields: edx is a multiple of 2 aoqi@1: { aoqi@1: Label loop; aoqi@1: bind(loop); aoqi@1: st_ptr(R0, t1, hdr_size_in_bytes - (1*BytesPerWord)); aoqi@1: st_ptr(R0, t1, hdr_size_in_bytes - (2*BytesPerWord)); aoqi@1: addi(index, index, -1); aoqi@1: bne(index, R0, loop); aoqi@1: delayed()->addi(t1, t1, - 2 * wordSize); aoqi@1: } aoqi@1: } aoqi@1: aoqi@1: if (DTraceAllocProbes) { aoqi@1: //assert(obj == eax, "must be"); aoqi@1: call(CAST_FROM_FN_PTR(address, aoqi@1: Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), relocInfo::runtime_call_type); aoqi@1: delayed()->nop(); aoqi@1: } aoqi@1: verify_oop(obj); aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, Register t3,int header_size, aoqi@1: int scale, Register klass, Label& slow_case) { aoqi@1: assert(obj == V0, "obj must be in V0 for cmpxchg"); aoqi@1: assert_different_registers(obj, len, t1, t2, t3,klass, AT); aoqi@1: aoqi@1: // determine alignment mask aoqi@1: assert(BytesPerWord == 8, "must be a multiple of 2 for masking code to work"); aoqi@1: aoqi@1: // check for negative or excessive length aoqi@1: //const int max_length = 0x00FFFFFF; aoqi@1: // move(AT, max_length); aoqi@1: move(AT, max_array_allocation_length); aoqi@1: sltu(AT, AT, len); aoqi@1: bne_far(AT, R0, slow_case); aoqi@1: delayed()->nop(); aoqi@1: aoqi@1: const Register arr_size = t3; aoqi@1: // align object end aoqi@1: move(arr_size, header_size * BytesPerWord + MinObjAlignmentInBytesMask); aoqi@1: sll(AT, len, scale); aoqi@1: add(arr_size, arr_size, AT); aoqi@1: move(AT, ~MinObjAlignmentInBytesMask); aoqi@1: andr(arr_size, arr_size, AT); aoqi@1: aoqi@1: try_allocate(obj, arr_size, 0, t1, t2, slow_case); aoqi@1: aoqi@1: initialize_header(obj, klass, len,t1,t2); aoqi@1: aoqi@1: // clear rest of allocated space aoqi@1: const Register len_zero = len; aoqi@1: initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero); aoqi@1: if (DTraceAllocProbes) { aoqi@1: // assert(obj == eax, "must be"); aoqi@1: call(CAST_FROM_FN_PTR(address, aoqi@1: Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), aoqi@1: relocInfo::runtime_call_type); aoqi@1: delayed()->nop(); aoqi@1: } aoqi@1: aoqi@1: verify_oop(obj); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { aoqi@1: verify_oop(receiver); aoqi@1: // explicit NULL check not needed since load from [klass_offset] causes a trap aoqi@1: // check against inline cache aoqi@1: assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); aoqi@1: ///cmpl(iCache, Address(receiver, oopDesc::klass_offset_in_bytes())); aoqi@1: // if icache check fails, then jump to runtime routine aoqi@1: // Note: RECEIVER must still contain the receiver! aoqi@1: Label L; aoqi@1: #ifdef _LP64 aoqi@1: //ld_ptr(AT, receiver, oopDesc::klass_offset_in_bytes()); aoqi@1: //add for compressedoops aoqi@1: load_klass(AT, receiver); aoqi@1: #else aoqi@1: lw(AT, receiver, oopDesc::klass_offset_in_bytes()); aoqi@1: #endif aoqi@1: beq(AT, iCache, L); aoqi@1: delayed()->nop(); aoqi@1: // jmp(Runtime1::entry_for(Runtime1::handle_ic_miss_id), relocInfo::runtime_call_type); aoqi@1: jmp(SharedRuntime::get_ic_miss_stub(), relocInfo::runtime_call_type); aoqi@1: delayed()->nop(); aoqi@1: bind(L); aoqi@1: // assert(UseCompressedOops, "check alignment in emit_method_entry"); aoqi@1: } aoqi@1: /* aoqi@1: void C1_MacroAssembler::method_exit(bool restore_frame) { aoqi@1: if (restore_frame) { aoqi@1: leave(); aoqi@1: } aoqi@1: jr(RA); aoqi@1: delayed()->nop(); aoqi@1: }*/ aoqi@1: aoqi@1: aoqi@1: void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) { aoqi@1: // Make sure there is enough stack space for this method's activation. aoqi@1: // Note that we do this before doing an enter(). This matches the aoqi@1: // ordering of C2's stack overflow check / esp decrement and allows aoqi@1: // the SharedRuntime stack overflow handling to be consistent aoqi@1: // between the two compilers. aoqi@1: generate_stack_overflow_check(frame_size_in_bytes); aoqi@1: aoqi@1: enter(); aoqi@1: //FIXME aoqi@1: #ifdef TIERED aoqi@1: // c2 leaves fpu stack dirty. Clean it on entry aoqi@1: // if (UseSSE < 2 ) { aoqi@1: empty_FPU_stack(); aoqi@1: // } aoqi@1: #endif // TIERED aoqi@1: aoqi@1: decrement(SP, frame_size_in_bytes); // does not emit code for frame_size == 0 aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) { aoqi@1: if (C1Breakpoint) int3(); aoqi@1: inline_cache_check(receiver, ic_klass); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: void C1_MacroAssembler::verified_entry() { aoqi@1: if (C1Breakpoint)int3(); aoqi@1: // build frame aoqi@1: verify_FPU(0, "method_entry"); aoqi@1: } aoqi@1: aoqi@1: aoqi@1: #ifndef PRODUCT aoqi@1: void C1_MacroAssembler::verify_stack_oop(int stack_offset) { aoqi@1: if (!VerifyOops) return; aoqi@1: // verify_oop_addr(Address(esp, stack_offset)); aoqi@1: verify_oop_addr(Address(SP, stack_offset)); aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::verify_not_null_oop(Register r) { aoqi@1: if (!VerifyOops) return; aoqi@1: Label not_null; aoqi@1: // testl(r, r); aoqi@1: //jcc(Assembler::notZero, not_null); aoqi@1: bne(r,R0,not_null); aoqi@1: delayed()->nop(); aoqi@1: stop("non-null oop required"); aoqi@1: bind(not_null); aoqi@1: verify_oop(r); aoqi@1: } aoqi@1: aoqi@1: void C1_MacroAssembler::invalidate_registers(bool inv_v0, bool inv_v1, bool inv_t3, bool inv_t7, bool inv_s0, bool inv_s7) { aoqi@1: #ifdef ASSERT aoqi@1: /* if (inv_eax) movl(eax, 0xDEAD); aoqi@1: if (inv_ebx) movl(ebx, 0xDEAD); aoqi@1: if (inv_ecx) movl(ecx, 0xDEAD); aoqi@1: if (inv_edx) movl(edx, 0xDEAD); aoqi@1: if (inv_esi) movl(esi, 0xDEAD); aoqi@1: if (inv_edi) movl(edi, 0xDEAD); aoqi@1: */ aoqi@1: //if (inv_v0) move(V0, 0xDEAD); aoqi@1: //if (inv_v1) move(V1, 0xDEAD); aoqi@1: //if (inv_t3) move(T3, 0xDEAD); aoqi@1: //if (inv_t7) move(T7, 0xDEAD); aoqi@1: //if (inv_s0) move(S0, 0xDEAD); aoqi@1: //if (inv_s7) move(S7, 0xDEAD); aoqi@1: #endif aoqi@1: } aoqi@1: #endif // ifndef PRODUCT aoqi@1: aoqi@1: