void C1_MacroAssembler::allocate_array( Register obj, // result: Pointer to array after successful allocation. Register len, // array length Register t1, // temp register Register t2, // temp register int hdr_size, // object header size in words int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // Continuation point if fast allocation fails. ) { assert_different_registers(obj, len, t1, t2, klass); // Determine alignment mask. assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work"); // Check for negative or excessive length. compareU64_and_branch(len, (int32_t)max_array_allocation_length, bcondHigh, slow_case); // Compute array size. // Note: If 0 <= len <= max_length, len*elt_size + header + alignment is // smaller or equal to the largest integer. Also, since top is always // aligned, we can do the alignment here instead of at the end address // computation. const Register arr_size = t2; switch (elt_size) { case 1: lgr_if_needed(arr_size, len); break; case 2: z_sllg(arr_size, len, 1); break; case 4: z_sllg(arr_size, len, 2); break; case 8: z_sllg(arr_size, len, 3); break; default: ShouldNotReachHere(); } add2reg(arr_size, hdr_size * wordSize + MinObjAlignmentInBytesMask); // Add space for header & alignment. z_nill(arr_size, (~MinObjAlignmentInBytesMask) & 0xffff); // Align array size. try_allocate(obj, arr_size, 0, t1, slow_case); initialize_header(obj, klass, len, noreg, t1); // Clear rest of allocated space. Label done; Register object_fields = t1; Register Rzero = Z_R1_scratch; z_aghi(arr_size, -(hdr_size * BytesPerWord)); z_bre(done); // Jump if size of fields is zero. z_la(object_fields, hdr_size * BytesPerWord, obj); z_xgr(Rzero, Rzero); initialize_body(object_fields, arr_size, Rzero); bind(done); // Dtrace support is unimplemented. // if (CURRENT_ENV->dtrace_alloc_probes()) { // assert(obj == rax, "must be"); // call(RuntimeAddress(Runtime1::entry_for (Runtime1::dtrace_object_alloc_id))); // } verify_oop(obj); }
void C1_MacroAssembler::initialize_object( Register obj, // result: pointer to object after successful allocation Register klass, // object klass Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise int con_size_in_bytes, // object size in bytes if known at compile time Register t1, // temp register Register t2 // temp register ) { const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; initialize_header(obj, klass, noreg, t1, t2); #ifdef ASSERT { lwz(t1, in_bytes(Klass::layout_helper_offset()), klass); if (var_size_in_bytes != noreg) { cmpw(CCR0, t1, var_size_in_bytes); } else { cmpwi(CCR0, t1, con_size_in_bytes); } asm_assert_eq("bad size in initialize_object", 0x753); } #endif // Initialize body. if (var_size_in_bytes != noreg) { // Use a loop. addi(t1, obj, hdr_size_in_bytes); // Compute address of first element. addi(t2, var_size_in_bytes, -hdr_size_in_bytes); // Compute size of body. initialize_body(t1, t2); } else if (con_size_in_bytes > hdr_size_in_bytes) { // Use a loop. initialize_body(obj, t1, t2, con_size_in_bytes, hdr_size_in_bytes); } if (CURRENT_ENV->dtrace_alloc_probes()) { Unimplemented(); // assert(obj == O0, "must be"); // call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), // relocInfo::runtime_call_type); } verify_oop(obj); }
void C1_MacroAssembler::initialize_object( Register obj, // result: Pointer to object after successful allocation. Register klass, // object klass Register var_size_in_bytes, // Object size in bytes if unknown at compile time; invalid otherwise. int con_size_in_bytes, // Object size in bytes if known at compile time. Register t1, // temp register Register t2 // temp register ) { assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "con_size_in_bytes is not multiple of alignment"); assert(var_size_in_bytes == noreg, "not implemented"); const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; const Register Rzero = t2; z_xgr(Rzero, Rzero); initialize_header(obj, klass, noreg, Rzero, t1); // Clear rest of allocated space. const int threshold = 4 * BytesPerWord; if (con_size_in_bytes <= threshold) { // Use explicit null stores. // code size = 6*n bytes (n = number of fields to clear) for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord) z_stg(Rzero, Address(obj, i)); } else { // Code size generated by initialize_body() is 16. Register object_fields = Z_R0_scratch; Register len_in_bytes = Z_R1_scratch; z_la(object_fields, hdr_size_in_bytes, obj); load_const_optimized(len_in_bytes, con_size_in_bytes - hdr_size_in_bytes); initialize_body(object_fields, len_in_bytes, Rzero); } // Dtrace support is unimplemented. // if (CURRENT_ENV->dtrace_alloc_probes()) { // assert(obj == rax, "must be"); // call(RuntimeAddress(Runtime1::entry_for (Runtime1::dtrace_object_alloc_id))); // } verify_oop(obj); }
void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, bool is_tlab_allocated) { assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0, "con_size_in_bytes is not multiple of alignment"); const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; initialize_header(obj, klass, noreg, t1, t2); if (!(UseTLAB && ZeroTLAB && is_tlab_allocated)) { // clear rest of allocated space const Register t1_zero = t1; const Register index = t2; const int threshold = 6 * BytesPerWord; // approximate break even point for code size (see comments below) if (var_size_in_bytes != noreg) { mov(index, var_size_in_bytes); initialize_body(obj, index, hdr_size_in_bytes, t1_zero); } else if (con_size_in_bytes <= threshold) { // use explicit null stores // code size = 2 + 3*n bytes (n = number of fields to clear) xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code) for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord) movptr(Address(obj, i), t1_zero); } else if (con_size_in_bytes > hdr_size_in_bytes) { // use loop to null out the fields // code size = 16 bytes for even n (n = number of fields to clear) // initialize last object field first if odd number of fields xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code) movptr(index, (con_size_in_bytes - hdr_size_in_bytes) >> 3); // initialize last object field if constant size is odd if (((con_size_in_bytes - hdr_size_in_bytes) & 4) != 0) movptr(Address(obj, con_size_in_bytes - (1*BytesPerWord)), t1_zero); // initialize remaining object fields: rdx is a multiple of 2 { Label loop; bind(loop); movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (1*BytesPerWord)), t1_zero); NOT_LP64(movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - (2*BytesPerWord)), t1_zero);) decrement(index); jcc(Assembler::notZero, loop); } }
void C1_MacroAssembler::allocate_array( Register obj, // result: pointer to array after successful allocation Register len, // array length Register t1, // temp register Register t2, // temp register Register t3, // temp register int hdr_size, // object header size in words int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // continuation point if fast allocation fails ) { assert_different_registers(obj, len, t1, t2, t3, klass); assert(klass == G5, "must be G5"); assert(t1 == G1, "must be G1"); // determine alignment mask assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work"); // check for negative or excessive length // note: the maximum length allowed is chosen so that arrays of any // element size with this length are always smaller or equal // to the largest integer (i.e., array size computation will // not overflow) set(max_array_allocation_length, t1); cmp(len, t1); br(Assembler::greaterUnsigned, false, Assembler::pn, slow_case); // compute array size // note: if 0 <= len <= max_length, len*elt_size + header + alignment is // smaller or equal to the largest integer; also, since top is always // aligned, we can do the alignment here instead of at the end address // computation const Register arr_size = t1; switch (elt_size) { case 1: delayed()->mov(len, arr_size); break; case 2: delayed()->sll(len, 1, arr_size); break; case 4: delayed()->sll(len, 2, arr_size); break; case 8: delayed()->sll(len, 3, arr_size); break; default: ShouldNotReachHere(); } add(arr_size, hdr_size * wordSize + MinObjAlignmentInBytesMask, arr_size); // add space for header & alignment and3(arr_size, ~MinObjAlignmentInBytesMask, arr_size); // align array size // allocate space & initialize header if (UseTLAB) { tlab_allocate(obj, arr_size, 0, t2, slow_case); } else { eden_allocate(obj, arr_size, 0, t2, t3, slow_case); } initialize_header(obj, klass, len, t2, t3); // initialize body const Register base = t2; const Register index = t3; add(obj, hdr_size * wordSize, base); // compute address of first element sub(arr_size, hdr_size * wordSize, index); // compute index = number of words to clear initialize_body(base, index); if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == O0, "must be"); call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), relocInfo::runtime_call_type); delayed()->nop(); } verify_oop(obj); }
void C1_MacroAssembler::initialize_object( Register obj, // result: pointer to object after successful allocation Register klass, // object klass Register var_size_in_bytes, // object size in bytes if unknown at compile time; invalid otherwise int con_size_in_bytes, // object size in bytes if known at compile time Register t1, // temp register Register t2 // temp register ) { const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize; initialize_header(obj, klass, noreg, t1, t2); #ifdef ASSERT { Label ok; ld(klass, in_bytes(Klass::layout_helper_offset()), t1); if (var_size_in_bytes != noreg) { cmp_and_brx_short(t1, var_size_in_bytes, Assembler::equal, Assembler::pt, ok); } else { cmp_and_brx_short(t1, con_size_in_bytes, Assembler::equal, Assembler::pt, ok); } stop("bad size in initialize_object"); should_not_reach_here(); bind(ok); } #endif // initialize body const int threshold = 5 * HeapWordSize; // approximate break even point for code size if (var_size_in_bytes != noreg) { // use a loop add(obj, hdr_size_in_bytes, t1); // compute address of first element sub(var_size_in_bytes, hdr_size_in_bytes, t2); // compute size of body initialize_body(t1, t2); #ifndef _LP64 } else if (con_size_in_bytes < threshold * 2) { // on v9 we can do double word stores to fill twice as much space. assert(hdr_size_in_bytes % 8 == 0, "double word aligned"); assert(con_size_in_bytes % 8 == 0, "double word aligned"); for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += 2 * HeapWordSize) stx(G0, obj, i); #endif } else if (con_size_in_bytes <= threshold) { // use explicit NULL stores for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += HeapWordSize) st_ptr(G0, obj, i); } else if (con_size_in_bytes > hdr_size_in_bytes) { // use a loop const Register base = t1; const Register index = t2; add(obj, hdr_size_in_bytes, base); // compute address of first element // compute index = number of words to clear set(con_size_in_bytes - hdr_size_in_bytes, index); initialize_body(base, index); } if (CURRENT_ENV->dtrace_alloc_probes()) { assert(obj == O0, "must be"); call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), relocInfo::runtime_call_type); delayed()->nop(); } verify_oop(obj); }
OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { OopMapSet* oop_maps = NULL; // for better readability const bool must_gc_arguments = true; const bool dont_gc_arguments = false; // stub code & info for the different stubs switch (id) { case forward_exception_id: { oop_maps = generate_handle_exception(id, sasm); } break; case new_instance_id: case fast_new_instance_id: case fast_new_instance_init_check_id: { Register G5_klass = G5; // Incoming Register O0_obj = O0; // Outgoing if (id == new_instance_id) { __ set_info("new_instance", dont_gc_arguments); } else if (id == fast_new_instance_id) { __ set_info("fast new_instance", dont_gc_arguments); } else { assert(id == fast_new_instance_init_check_id, "bad StubID"); __ set_info("fast new_instance init check", dont_gc_arguments); } if ((id == fast_new_instance_id || id == fast_new_instance_init_check_id) && UseTLAB && FastTLABRefill) { Label slow_path; Register G1_obj_size = G1; Register G3_t1 = G3; Register G4_t2 = G4; assert_different_registers(G5_klass, G1_obj_size, G3_t1, G4_t2); // Push a frame since we may do dtrace notification for the // allocation which requires calling out and we don't want // to stomp the real return address. __ save_frame(0); if (id == fast_new_instance_init_check_id) { // make sure the klass is initialized __ ldub(G5_klass, in_bytes(InstanceKlass::init_state_offset()), G3_t1); __ cmp_and_br_short(G3_t1, InstanceKlass::fully_initialized, Assembler::notEqual, Assembler::pn, slow_path); } #ifdef ASSERT // assert object can be fast path allocated { Label ok, not_ok; __ ld(G5_klass, in_bytes(Klass::layout_helper_offset()), G1_obj_size); // make sure it's an instance (LH > 0) __ cmp_and_br_short(G1_obj_size, 0, Assembler::lessEqual, Assembler::pn, not_ok); __ btst(Klass::_lh_instance_slow_path_bit, G1_obj_size); __ br(Assembler::zero, false, Assembler::pn, ok); __ delayed()->nop(); __ bind(not_ok); __ stop("assert(can be fast path allocated)"); __ should_not_reach_here(); __ bind(ok); } #endif // ASSERT // if we got here then the TLAB allocation failed, so try // refilling the TLAB or allocating directly from eden. Label retry_tlab, try_eden; __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G5_klass __ bind(retry_tlab); // get the instance size __ ld(G5_klass, in_bytes(Klass::layout_helper_offset()), G1_obj_size); __ tlab_allocate(O0_obj, G1_obj_size, 0, G3_t1, slow_path); __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ verify_oop(O0_obj); __ mov(O0, I0); __ ret(); __ delayed()->restore(); __ bind(try_eden); // get the instance size __ ld(G5_klass, in_bytes(Klass::layout_helper_offset()), G1_obj_size); __ eden_allocate(O0_obj, G1_obj_size, 0, G3_t1, G4_t2, slow_path); __ incr_allocated_bytes(G1_obj_size, G3_t1, G4_t2); __ initialize_object(O0_obj, G5_klass, G1_obj_size, 0, G3_t1, G4_t2); __ verify_oop(O0_obj); __ mov(O0, I0); __ ret(); __ delayed()->restore(); __ bind(slow_path); // pop this frame so generate_stub_call can push it's own __ restore(); } oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_instance), G5_klass); // I0->O0: new instance } break; case counter_overflow_id: // G4 contains bci, G5 contains method oop_maps = generate_stub_call(sasm, noreg, CAST_FROM_FN_PTR(address, counter_overflow), G4, G5); break; case new_type_array_id: case new_object_array_id: { Register G5_klass = G5; // Incoming Register G4_length = G4; // Incoming Register O0_obj = O0; // Outgoing Address klass_lh(G5_klass, Klass::layout_helper_offset()); assert(Klass::_lh_header_size_shift % BitsPerByte == 0, "bytewise"); assert(Klass::_lh_header_size_mask == 0xFF, "bytewise"); // Use this offset to pick out an individual byte of the layout_helper: const int klass_lh_header_size_offset = ((BytesPerInt - 1) // 3 - 2 selects byte {0,1,0,0} - Klass::_lh_header_size_shift / BitsPerByte); if (id == new_type_array_id) { __ set_info("new_type_array", dont_gc_arguments); } else { __ set_info("new_object_array", dont_gc_arguments); } #ifdef ASSERT // assert object type is really an array of the proper kind { Label ok; Register G3_t1 = G3; __ ld(klass_lh, G3_t1); __ sra(G3_t1, Klass::_lh_array_tag_shift, G3_t1); int tag = ((id == new_type_array_id) ? Klass::_lh_array_tag_type_value : Klass::_lh_array_tag_obj_value); __ cmp_and_brx_short(G3_t1, tag, Assembler::equal, Assembler::pt, ok); __ stop("assert(is an array klass)"); __ should_not_reach_here(); __ bind(ok); } #endif // ASSERT if (UseTLAB && FastTLABRefill) { Label slow_path; Register G1_arr_size = G1; Register G3_t1 = G3; Register O1_t2 = O1; assert_different_registers(G5_klass, G4_length, G1_arr_size, G3_t1, O1_t2); // check that array length is small enough for fast path __ set(C1_MacroAssembler::max_array_allocation_length, G3_t1); __ cmp_and_br_short(G4_length, G3_t1, Assembler::greaterUnsigned, Assembler::pn, slow_path); // if we got here then the TLAB allocation failed, so try // refilling the TLAB or allocating directly from eden. Label retry_tlab, try_eden; __ tlab_refill(retry_tlab, try_eden, slow_path); // preserves G4_length and G5_klass __ bind(retry_tlab); // get the allocation size: (length << (layout_helper & 0x1F)) + header_size __ ld(klass_lh, G3_t1); __ sll(G4_length, G3_t1, G1_arr_size); __ srl(G3_t1, Klass::_lh_header_size_shift, G3_t1); __ and3(G3_t1, Klass::_lh_header_size_mask, G3_t1); __ add(G1_arr_size, G3_t1, G1_arr_size); __ add(G1_arr_size, MinObjAlignmentInBytesMask, G1_arr_size); // align up __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); __ tlab_allocate(O0_obj, G1_arr_size, 0, G3_t1, slow_path); // preserves G1_arr_size __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); __ sub(G1_arr_size, G3_t1, O1_t2); // body length __ add(O0_obj, G3_t1, G3_t1); // body start __ initialize_body(G3_t1, O1_t2); __ verify_oop(O0_obj); __ retl(); __ delayed()->nop(); __ bind(try_eden); // get the allocation size: (length << (layout_helper & 0x1F)) + header_size __ ld(klass_lh, G3_t1); __ sll(G4_length, G3_t1, G1_arr_size); __ srl(G3_t1, Klass::_lh_header_size_shift, G3_t1); __ and3(G3_t1, Klass::_lh_header_size_mask, G3_t1); __ add(G1_arr_size, G3_t1, G1_arr_size); __ add(G1_arr_size, MinObjAlignmentInBytesMask, G1_arr_size); __ and3(G1_arr_size, ~MinObjAlignmentInBytesMask, G1_arr_size); __ eden_allocate(O0_obj, G1_arr_size, 0, G3_t1, O1_t2, slow_path); // preserves G1_arr_size __ incr_allocated_bytes(G1_arr_size, G3_t1, O1_t2); __ initialize_header(O0_obj, G5_klass, G4_length, G3_t1, O1_t2); __ ldub(klass_lh, G3_t1, klass_lh_header_size_offset); __ sub(G1_arr_size, G3_t1, O1_t2); // body length __ add(O0_obj, G3_t1, G3_t1); // body start __ initialize_body(G3_t1, O1_t2); __ verify_oop(O0_obj); __ retl(); __ delayed()->nop(); __ bind(slow_path); } if (id == new_type_array_id) { oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_type_array), G5_klass, G4_length); } else { oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_object_array), G5_klass, G4_length); } // I0 -> O0: new array } break; case new_multi_array_id: { // O0: klass // O1: rank // O2: address of 1st dimension __ set_info("new_multi_array", dont_gc_arguments); oop_maps = generate_stub_call(sasm, I0, CAST_FROM_FN_PTR(address, new_multi_array), I0, I1, I2); // I0 -> O0: new multi array } break; case register_finalizer_id: { __ set_info("register_finalizer", dont_gc_arguments); // load the klass and check the has finalizer flag Label register_finalizer; Register t = O1; __ load_klass(O0, t); __ ld(t, in_bytes(Klass::access_flags_offset()), t); __ set(JVM_ACC_HAS_FINALIZER, G3); __ andcc(G3, t, G0); __ br(Assembler::notZero, false, Assembler::pt, register_finalizer); __ delayed()->nop(); // do a leaf return __ retl(); __ delayed()->nop(); __ bind(register_finalizer); OopMap* oop_map = save_live_registers(sasm); int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, SharedRuntime::register_finalizer), I0); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, oop_map); // Now restore all the live registers restore_live_registers(sasm); __ ret(); __ delayed()->restore(); } break; case throw_range_check_failed_id: { __ set_info("range_check_failed", dont_gc_arguments); // arguments will be discarded // G4: index oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_range_check_exception), true); } break; case throw_index_exception_id: { __ set_info("index_range_check_failed", dont_gc_arguments); // arguments will be discarded // G4: index oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_index_exception), true); } break; case throw_div0_exception_id: { __ set_info("throw_div0_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_div0_exception), false); } break; case throw_null_pointer_exception_id: { __ set_info("throw_null_pointer_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_null_pointer_exception), false); } break; case handle_exception_id: { __ set_info("handle_exception", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; case handle_exception_from_callee_id: { __ set_info("handle_exception_from_callee", dont_gc_arguments); oop_maps = generate_handle_exception(id, sasm); } break; case unwind_exception_id: { // O0: exception // I7: address of call to this method __ set_info("unwind_exception", dont_gc_arguments); __ mov(Oexception, Oexception->after_save()); __ add(I7, frame::pc_return_offset, Oissuing_pc->after_save()); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SharedRuntime::exception_handler_for_return_address), G2_thread, Oissuing_pc->after_save()); __ verify_not_null_oop(Oexception->after_save()); // Restore SP from L7 if the exception PC is a method handle call site. __ mov(O0, G5); // Save the target address. __ lduw(Address(G2_thread, JavaThread::is_method_handle_return_offset()), L0); __ tst(L0); // Condition codes are preserved over the restore. __ restore(); __ jmp(G5, 0); __ delayed()->movcc(Assembler::notZero, false, Assembler::icc, L7_mh_SP_save, SP); // Restore SP if required. } break; case throw_array_store_exception_id: { __ set_info("throw_array_store_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_array_store_exception), true); } break; case throw_class_cast_exception_id: { // G4: object __ set_info("throw_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_class_cast_exception), true); } break; case throw_incompatible_class_change_error_id: { __ set_info("throw_incompatible_class_cast_exception", dont_gc_arguments); oop_maps = generate_exception_throw(sasm, CAST_FROM_FN_PTR(address, throw_incompatible_class_change_error), false); } break; case slow_subtype_check_id: { // Support for uint StubRoutine::partial_subtype_check( Klass sub, Klass super ); // Arguments : // // ret : G3 // sub : G3, argument, destroyed // super: G1, argument, not changed // raddr: O7, blown by call Label miss; __ save_frame(0); // Blow no registers! __ check_klass_subtype_slow_path(G3, G1, L0, L1, L2, L4, NULL, &miss); __ mov(1, G3); __ ret(); // Result in G5 is 'true' __ delayed()->restore(); // free copy or add can go here __ bind(miss); __ mov(0, G3); __ ret(); // Result in G5 is 'false' __ delayed()->restore(); // free copy or add can go here } case monitorenter_nofpu_id: case monitorenter_id: { // G4: object // G5: lock address __ set_info("monitorenter", dont_gc_arguments); int save_fpu_registers = (id == monitorenter_id); // make a frame and preserve the caller's caller-save registers OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorenter), G4, G5); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm, save_fpu_registers); __ ret(); __ delayed()->restore(); } break; case monitorexit_nofpu_id: case monitorexit_id: { // G4: lock address // note: really a leaf routine but must setup last java sp // => use call_RT for now (speed can be improved by // doing last java sp setup manually) __ set_info("monitorexit", dont_gc_arguments); int save_fpu_registers = (id == monitorexit_id); // make a frame and preserve the caller's caller-save registers OopMap* oop_map = save_live_registers(sasm, save_fpu_registers); int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, monitorexit), G4); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm, save_fpu_registers); __ ret(); __ delayed()->restore(); } break; case deoptimize_id: { __ set_info("deoptimize", dont_gc_arguments); OopMap* oop_map = save_live_registers(sasm); int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, deoptimize)); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, oop_map); restore_live_registers(sasm); DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); assert(deopt_blob != NULL, "deoptimization blob must have been created"); AddressLiteral dest(deopt_blob->unpack_with_reexecution()); __ jump_to(dest, O0); __ delayed()->restore(); } break; case access_field_patching_id: { __ set_info("access_field_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, access_field_patching)); } break; case load_klass_patching_id: { __ set_info("load_klass_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_klass_patching)); } break; case load_mirror_patching_id: { __ set_info("load_mirror_patching", dont_gc_arguments); oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_mirror_patching)); } break; case dtrace_object_alloc_id: { // O0: object __ set_info("dtrace_object_alloc", dont_gc_arguments); // we can't gc here so skip the oopmap but make sure that all // the live registers get saved. save_live_registers(sasm); __ save_thread(L7_thread_cache); __ call(CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), relocInfo::runtime_call_type); __ delayed()->mov(I0, O0); __ restore_thread(L7_thread_cache); restore_live_registers(sasm); __ ret(); __ delayed()->restore(); } break; #if INCLUDE_ALL_GCS case g1_pre_barrier_slow_id: { // G4: previous value of memory BarrierSet* bs = Universe::heap()->barrier_set(); if (bs->kind() != BarrierSet::G1SATBCTLogging) { __ save_frame(0); __ set((int)id, O1); __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); __ should_not_reach_here(); break; } __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments); Register pre_val = G4; Register tmp = G1_scratch; Register tmp2 = G3_scratch; Label refill, restart; bool with_frame = false; // I don't know if we can do with-frame. int satb_q_index_byte_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_index()); int satb_q_buf_byte_offset = in_bytes(JavaThread::satb_mark_queue_offset() + PtrQueue::byte_offset_of_buf()); __ bind(restart); // Load the index into the SATB buffer. PtrQueue::_index is a // size_t so ld_ptr is appropriate __ ld_ptr(G2_thread, satb_q_index_byte_offset, tmp); // index == 0? __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill); __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2); __ sub(tmp, oopSize, tmp); __ st_ptr(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card> // Use return-from-leaf __ retl(); __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset); __ bind(refill); __ save_frame(0); __ mov(pre_val, L0); __ mov(tmp, L1); __ mov(tmp2, L2); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, SATBMarkQueueSet::handle_zero_index_for_thread), G2_thread); __ mov(L0, pre_val); __ mov(L1, tmp); __ mov(L2, tmp2); __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); __ delayed()->restore(); } break; case g1_post_barrier_slow_id: { BarrierSet* bs = Universe::heap()->barrier_set(); if (bs->kind() != BarrierSet::G1SATBCTLogging) { __ save_frame(0); __ set((int)id, O1); __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0); __ should_not_reach_here(); break; } __ set_info("g1_post_barrier_slow_id", dont_gc_arguments); Register addr = G4; Register cardtable = G5; Register tmp = G1_scratch; Register tmp2 = G3_scratch; jbyte* byte_map_base = ((CardTableModRefBS*)bs)->byte_map_base; Label not_already_dirty, restart, refill; #ifdef _LP64 __ srlx(addr, CardTableModRefBS::card_shift, addr); #else __ srl(addr, CardTableModRefBS::card_shift, addr); #endif AddressLiteral rs(byte_map_base); __ set(rs, cardtable); // cardtable := <card table base> __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable] assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, not_already_dirty); // We didn't take the branch, so we're already dirty: return. // Use return-from-leaf __ retl(); __ delayed()->nop(); // Not dirty. __ bind(not_already_dirty); // Get cardtable + tmp into a reg by itself __ add(addr, cardtable, tmp2); // First, dirty it. __ stb(G0, tmp2, 0); // [cardPtr] := 0 (i.e., dirty). Register tmp3 = cardtable; Register tmp4 = tmp; // these registers are now dead addr = cardtable = tmp = noreg; int dirty_card_q_index_byte_offset = in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_index()); int dirty_card_q_buf_byte_offset = in_bytes(JavaThread::dirty_card_queue_offset() + PtrQueue::byte_offset_of_buf()); __ bind(restart); // Get the index into the update buffer. PtrQueue::_index is // a size_t so ld_ptr is appropriate here. __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, tmp3); // index == 0? __ cmp_and_brx_short(tmp3, G0, Assembler::equal, Assembler::pn, refill); __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4); __ sub(tmp3, oopSize, tmp3); __ st_ptr(tmp2, tmp4, tmp3); // [_buf + index] := <address_of_card> // Use return-from-leaf __ retl(); __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset); __ bind(refill); __ save_frame(0); __ mov(tmp2, L0); __ mov(tmp3, L1); __ mov(tmp4, L2); __ call_VM_leaf(L7_thread_cache, CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread), G2_thread); __ mov(L0, tmp2); __ mov(L1, tmp3); __ mov(L2, tmp4); __ br(Assembler::always, /*annul*/false, Assembler::pt, restart); __ delayed()->restore(); } break; #endif // INCLUDE_ALL_GCS case predicate_failed_trap_id: { __ set_info("predicate_failed_trap", dont_gc_arguments); OopMap* oop_map = save_live_registers(sasm); int call_offset = __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, predicate_failed_trap)); oop_maps = new OopMapSet(); oop_maps->add_gc_map(call_offset, oop_map); DeoptimizationBlob* deopt_blob = SharedRuntime::deopt_blob(); assert(deopt_blob != NULL, "deoptimization blob must have been created"); restore_live_registers(sasm); AddressLiteral dest(deopt_blob->unpack_with_reexecution()); __ jump_to(dest, O0); __ delayed()->restore(); } break; default: { __ set_info("unimplemented entry", dont_gc_arguments); __ save_frame(0); __ set((int)id, O1); __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), O1); __ should_not_reach_here(); } break; } return oop_maps; }
int main(int argc, char **argv) { SegyReel reel; SegyHead *header; char *dbin; char *outfile; FILE *fp; Pf *pf; Arr *channels; /* channel order list */ Arr *table_list; /* array of valid tables */ int nchan; char *stest; float **traces; char reel1[3200]; Dbptr db, trdb, dbj; Dbptr trdbss; int nsamp0; double time0, endtime0, samprate0; long int nsamp; double samprate; int i,j; char stime[30],etime[30]; char s[128]; double tlength; double phi, theta; char *newchan_standard[3]={"X1","X2","X3"}; char *trsubset="chan=~/X./"; char *newchan[3]={"R","T","Z"}; Tbl *sortkeys=newtbl(0); char sta[10],chan[10]; double lat, lon, elev, dnorth, deast, edepth; char refsta[10]; int total_traces=0; char *time_str; long int evid,shotid=1; int rotate=0; long int ntraces; int ichan; int map_to_cdp; /* logical switch to output data like cdp stacked data */ char *fmt="%Y %j %H %M %S %s"; char *pfname; int Verbose=0; /* New features added 2009 */ /* this is a boolean. If true (nonzero) it is assumed stdin will contain four numbers: time,lat, lon, elev. If false, only the time field is read and remainder of any input on each line is dropped.*/ int input_source_coordinates; /* scale factor for source coordinates. Needed because segy uses an int to store source coordinates. Sensible choices are 3600 for arc seconds and 10000 for a pseudodecimal. Note this parameter is ignored unless input_source_coordinates is true.*/ int coordScale; /* If true use passcal 32 bit extension num_samps as record length. SEGY standard uses a 16 bit entry that easily overflows with large shots at long offset. In this ase assume the 16 bit quantity is meaningless. */ int use_32bit_nsamp; /* This is switched on by argument switch. When set to a nonzero (default) the reel headers are written. When 0 ` the reel heades will not be written -- used by seismic unix r and passcal*/ int write_reel_headers=1; char *substr=NULL; if(argc < 3) usage(); dbin = argv[1]; outfile = argv[2]; pfname = NULL; for(i=3;i<argc;++i) { if(!strcmp(argv[i],"-pf")) { ++i; pfname = argv[i]; } else if(!strcmp(argv[i],"-SU")) { write_reel_headers=0; } else if(!strcmp(argv[i],"-v")) { Verbose=1; } else if(!strcmp(argv[i],"-ss")) { ++i; substr=argv[i]; } else { usage(); } } if(pfname == NULL) pfname = strdup("db2segy"); elog_init(argc, argv); if(pfread(pfname,&pf)) elog_die(0,"pfread error for pf file %s.pf\n",argv[0]); /* rotation parameters */ rotate=pfget_boolean(pf,"rotate"); if(rotate) { phi = pfget_double(pf,"phi"); theta = pfget_double(pf,"theta"); } /* This function creates the channel order list keyed by station channel names */ channels = build_stachan_list(pf,&nchan,Verbose); map_to_cdp = pfget_boolean(pf,"map_to_cdp"); if(map_to_cdp && Verbose) fprintf(stdout,"Casting data as CDP stacked section\n"); if(dbopen(dbin,"r",&db) == dbINVALID) { fprintf(stderr,"Cannot open db %s\n", dbin); usage(); } /* We grab the sample rate and trace length (in seconds) and use this to define global sample rates for the data. segy REQUIRES fixed length records and sample rates, so irregular sample rates will cause this program to die. One could add a decimate/interpolate function, but this is not currently implemented */ samprate0 = pfget_double(pf,"sample_rate"); tlength = pfget_double(pf,"trace_length"); nsamp0 = (int)(tlength*samprate0); use_32bit_nsamp=pfget_boolean(pf,"use_32bit_nsamp"); /* nsamp in segy is a 16 bit field. Handling depends on setting of use_32bit_nsamp boolean */ if(nsamp0 > 32767) { if(use_32bit_nsamp) { elog_notify(0,"Warning: segy ues a 16 bit entity to store number of samples\nThat field is garbage. Using the 32 bit extension field.\n"); } else { elog_complain(0, "Warning: segy uses a 16 bit entity to store number of samples\nRequested %d samples per trace. Trucated to 32767\n",nsamp0); nsamp0 = 32767; } } input_source_coordinates=pfget_boolean(pf,"input_source_coordinates"); if(input_source_coordinates) { coordScale=pfget_int(pf,"coordinate_scale_factor"); } else { coordScale=1; } /* boolean. When nonzero set coordinates as geographic arc seconds values */ int use_geo_coordinates=pfget_boolean(pf,"use_geo_coordinates"); /* check list of tables defined in pf. Return array of logicals that define which tables are valid and join tables. */ table_list = check_tables(db,pf); check_for_required_tables(table_list); dbj = join_tables(db,pf,table_list); if(dbj.record == dbINVALID) elog_die(0,"dbjoin error\n"); if(substr!=NULL) dbj=dbsubset(dbj,substr,0); long int ndbrows; dbquery(dbj,dbRECORD_COUNT,&ndbrows); if(ndbrows<=0) { fprintf(stderr,"Working database view is empty\n"); if(substr!=NULL) fprintf(stderr,"Subset condtion =%s a likely problem\n", substr); usage(); } fp = fopen(outfile,"w"); if(fp == NULL) { fprintf(stderr,"Cannot open output file %s\n",outfile); usage(); } /* These are needed for sort below */ pushtbl(sortkeys,"sta"); pushtbl(sortkeys,"chan"); /*The reel1 header in true blue segy is ebcdic. We are goingto just fill it with nulls and hope for the best */ for(i=0;i<3200;i++) reel1[i] = '\0'; /* Just blindly write this turkey. Bad form, but tough*/ if(write_reel_headers) fwrite(reel1,1,3200,fp); /* memory allocation for trace data. This is a large matrix that is cleared for each event. This model works because of segy's fixed length format. This routine is a descendent of numerical recipes routine found in libgenloc. This is not the most efficient way to do this, but it simplifies the algorithm a lot. */ traces = matrix(0,nchan,0,nsamp0); if(traces == NULL) elog_die(0,"Cannot alloc trace data matrix work space of size %d by %d\n", nchan, nsamp0); header = (SegyHead *)calloc((size_t)nchan,sizeof(SegyHead)); if(header == NULL) elog_die(0,"Cannot alloc memory for %d segy header workspace\n",nchan); if(write_reel_headers) { /* now fill in the binary reel header and write it */ reel.kjob = 1; reel.kline = 1; reel.kreel = 1; reel.kntr = (int16_t)nchan; reel.knaux = 0; reel.sr = (int16_t)(1000000.0/samprate0); reel.kfldsr = reel.sr; reel.knsamp = (int16_t)nsamp0; reel.kfsamp = (int16_t)nsamp0; reel.dsfc=5; /* This is ieee floats*/ reel.kmfold = 0; if(map_to_cdp) reel.ksort = 2; else reel.ksort = 1; reel.kunits = 1; /* This sets units to always be meters */ for(i=0;i<344;++i)reel.unused2[i]='\0'; if(fwrite((void *)(&reel),sizeof(SegyReel),1,fp) != 1) { fprintf(stderr,"Write error for binary reel header\n"); exit(-2); } } /* Now we enter a loop over stdin reading start times. Program will blindly ask for data from each start time to time+tlength. The trace buffer will be initialized to zeros at the top of the loop always. If nothing is found only zeros will be written to output. */ while((stest=fgets(s,80,stdin)) != NULL) { double slat,slon,selev; /* Used when reading source location*/ if(Verbose) fprintf(stdout,"Processing: %s\n",s); for(i=0;i<nchan;++i) { initialize_header(&(header[i])); header[i].lineSeq = total_traces + i + 1; header[i].reelSeq = header[i].lineSeq; if(map_to_cdp) { header[i].cdpEns = i + 1; header[i].traceInEnsemble = 1; /* 1 trace per cdp faked */ } else { header[i].channel_number = i + 1; } header[i].event_number = shotid; header[i].energySourcePt=shotid; for(j=0;j<nsamp0;++j) traces[i][j] = (Trsample)0.0; } if(input_source_coordinates) { char stmp[40]; sscanf(s,"%s%ld%lf%lf%lf",stmp,&shotid,&slon,&slat,&selev); time0=str2epoch(stmp); } else { time0 = str2epoch(s); } endtime0 = time0 + tlength; sprintf(stime,"%20.4f",time0); sprintf(etime,"%20.4f",endtime0); trdb.database = -1; if(trload_css(dbj,stime,etime,&trdb,0, 0) < 0) { if(Verbose) { fprintf(stdout,"trload_css failed for shotid=%ld",shotid); fprintf(stdout," No data in time range %s to %s\n", strtime(time0),strtime(endtime0) ); fprintf(stdout,"No data written for this shotid block."); fprintf(stdout," Handle this carefully in geometry definitions.\n"); } continue; } /* This does gap processing */ repair_gaps(trdb); trapply_calib(trdb); if(rotate) { if(rotate_to_standard(trdb,newchan_standard)) elog_notify(0,"Data loss in rotate_to_standard for event %s to %s\n", stime, etime); /* This is need to prevent collisions of channel names */ trdbss = dbsubset(trdb,trsubset,0); if(trrotate(trdbss,phi,theta,newchan)) elog_notify(0,"Data loss in trrotate for event %s to %s\n", stime, etime); } if(Verbose) fprintf(stdout,"Station chan_name chan_number seq_number shotid evid\n"); trdb = dbsort(trdb,sortkeys,0,0); dbquery(trdb,dbRECORD_COUNT,&ntraces); if(Verbose) fprintf(stdout,"Read %ld traces for event at time%s\n", ntraces,strtime(time0)); for(trdb.record=0;trdb.record<ntraces;++trdb.record) { Trsample *trdata; if(dbgetv(trdb,0, "evid",&evid, "sta",sta, "chan",chan, "nsamp", &nsamp, "samprate",&samprate, "data",&trdata, "lat", &lat, "lon", &lon, "elev",&elev, "refsta",refsta, "dnorth",&dnorth, "deast",&deast, "edepth",&edepth, NULL) == dbINVALID) { elog_complain(0," dbgetv error reading record %ld\nTrace will be skipped for station %s and channel %s\n", trdb.record,sta,chan); continue; } /* Allow 1 percent samprate error before killing */ double fsrskew=fabs((samprate-samprate0)/samprate0); double frskewcut=0.01; if(fsrskew>frskewcut) { elog_complain(0,"%s:%s sample rate %f is significantly different from base sample rate of %f\nTrace skipped -- segy requires fixed sample rates\n", sta,chan,samprate,samprate0); continue; } if(nsamp > nsamp0) { elog_complain(0,"%s:%s trace has extra samples=%ld\nTruncated to length %d\n", sta, chan, nsamp, nsamp0); nsamp = nsamp0; } else if(nsamp < nsamp0) { elog_complain(0,"%s:%s trace is shorter than expected %d samples\nZero padded after sample %ld\n", sta, chan, nsamp0, nsamp); } ichan = get_channel_index(channels,sta,chan); if(ichan > nchan) elog_die(0,"Channel index %d outside limit of %d\nCannot continue\n", ichan, nchan); if(ichan >= 0) { if(Verbose) fprintf(stdout,"%s:%s\t%-d\t%-d\t%-ld\t%-ld\n", sta,chan,ichan+1, header[ichan].reelSeq, shotid, evid); header[ichan].traceID = 1; for(j=0;j<nsamp;++j) traces[ichan][j] = (float)trdata[j]; /* header fields coming from trace table */ header[ichan].samp_rate = (int32_t) (1000000.0/samprate0); if(!use_geo_coordinates && ( coordScale==1)) { header[ichan].recLongOrX = (int32_t)(deast*1000.0); header[ichan].recLatOrY = (int32_t)(dnorth*1000.0); } else { /* Note negative here. This is a oddity of segy that - means divide by this to get actual. Always make this negative in case user inputs a negative number. */ header[ichan].coordScale=-abs(coordScale); /* Force 2 = geographic coordinates. Standard says when this is so units are arc seconds, hence we multiply deg by 3600*coordScale */ if(use_geo_coordinates) { header[ichan].coordUnits=2; header[ichan].recLongOrX =(int32_t)(lon*3600.0*(double)coordScale); header[ichan].recLatOrY =(int32_t)(lat*3600.0*(double)coordScale); } else { header[ichan].recLongOrX =(int32_t)(lon*(double)coordScale); header[ichan].recLatOrY =(int32_t)(lat*(double)coordScale); } } header[ichan].recElevation = (int32_t)(elev*1000.0); header[ichan].deltaSample = (int16_t) (1000000.0/samprate0); header[ichan].sampleLength = (int16_t)nsamp0; header[ichan].num_samps = (int32_t)nsamp0; /* This cracks the time fields */ time_str = epoch2str(time0,fmt); sscanf(time_str,"%hd %hd %hd %hd %hd %hd", &header[ichan].year, &header[ichan].day, &header[ichan].hour, &header[ichan].minute, &header[ichan].second, &header[ichan].m_secs); /* These are PASSCAL extensions, but we'll go ahead and set them anyway.*/ header[ichan].trigyear = header[ichan].year; header[ichan].trigday = header[ichan].day; header[ichan].trighour = header[ichan].hour; header[ichan].trigminute = header[ichan].minute; header[ichan].trigsecond = header[ichan].second; free(time_str); if(input_source_coordinates) { if(use_geo_coordinates) { slat*=3600.0; slon*=3600.0; } header[ichan].sourceLongOrX =(int32_t)(slon*(double)coordScale); header[ichan].sourceLatOrY =(int32_t)(slat*(double)coordScale); header[ichan].sourceSurfaceElevation =(int32_t)selev; /* No easy way to specify both elev and depth*/ header[ichan].sourceDepth=0; } else if(map_to_cdp) { /* When faking CDP data we make this look like a zero offset, single fold data set */ header[ichan].sourceLongOrX = header[ichan].recLongOrX; header[ichan].sourceLatOrY = header[ichan].recLatOrY; header[ichan].sourceSurfaceElevation = header[ichan].recElevation; header[ichan].sourceDepth = 0; header[ichan].sourceToRecDist = 0; } else { /* This is the mechanism for adding other information with added tables. The one table currently supported is a "shot" table that holds shot coordinates. If other tables were added new functions could be added with a similar calling sequence. This procedure silently does nothing if a shot table is not present.*/ set_shot_variable(db,table_list, evid,&header[ichan]); } } else { if(Verbose) fprintf(stdout,"Station %s and channel %s skipped\n", sta,chan); } } /* Now we write the data */ for(i=0;i<nchan;++i) { if(fwrite((void *)(&(header[i])),sizeof(SegyHead),1,fp) != 1) elog_die(0,"Write error on header for trace %d\n",total_traces+i); if(fwrite((void *)traces[i],sizeof(float), (size_t)nsamp0,fp) != nsamp0) elog_die(0,"Write error while writing data for trace %d\n", total_traces+i); } total_traces += nchan; trdestroy(&trdb); if(!input_source_coordinates) ++shotid; } return 0 ; }
void C1_MacroAssembler::allocate_array( Register obj, // result: pointer to array after successful allocation Register len, // array length Register t1, // temp register Register t2, // temp register Register t3, // temp register int hdr_size, // object header size in words int elt_size, // element size in bytes Register klass, // object klass Label& slow_case // continuation point if fast allocation fails ) { assert_different_registers(obj, len, t1, t2, t3, klass); // Determine alignment mask. assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work"); int log2_elt_size = exact_log2(elt_size); // Check for negative or excessive length. size_t max_length = max_array_allocation_length >> log2_elt_size; if (UseTLAB) { size_t max_tlab = align_size_up(ThreadLocalAllocBuffer::max_size() >> log2_elt_size, 64*K); if (max_tlab < max_length) { max_length = max_tlab; } } load_const_optimized(t1, max_length); cmpld(CCR0, len, t1); bc_far_optimized(Assembler::bcondCRbiIs1, bi0(CCR0, Assembler::greater), slow_case); // compute array size // note: If 0 <= len <= max_length, len*elt_size + header + alignment is // smaller or equal to the largest integer; also, since top is always // aligned, we can do the alignment here instead of at the end address // computation. const Register arr_size = t1; Register arr_len_in_bytes = len; if (elt_size != 1) { sldi(t1, len, log2_elt_size); arr_len_in_bytes = t1; } addi(arr_size, arr_len_in_bytes, hdr_size * wordSize + MinObjAlignmentInBytesMask); // Add space for header & alignment. clrrdi(arr_size, arr_size, LogMinObjAlignmentInBytes); // Align array size. // Allocate space & initialize header. if (UseTLAB) { tlab_allocate(obj, arr_size, 0, t2, slow_case); } else { eden_allocate(obj, arr_size, 0, t2, t3, slow_case); } initialize_header(obj, klass, len, t2, t3); // Initialize body. const Register base = t2; const Register index = t3; addi(base, obj, hdr_size * wordSize); // compute address of first element addi(index, arr_size, -(hdr_size * wordSize)); // compute index = number of bytes to clear initialize_body(base, index); if (CURRENT_ENV->dtrace_alloc_probes()) { Unimplemented(); //assert(obj == O0, "must be"); //call(CAST_FROM_FN_PTR(address, Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)), // relocInfo::runtime_call_type); } verify_oop(obj); }