1 /* |
1 /* |
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * Copyright 2012, 2013 SAP AG. All rights reserved. |
3 * Copyright 2012, 2014 SAP AG. All rights reserved. |
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
5 * |
5 * |
6 * This code is free software; you can redistribute it and/or modify it |
6 * This code is free software; you can redistribute it and/or modify it |
7 * under the terms of the GNU General Public License version 2 only, as |
7 * under the terms of the GNU General Public License version 2 only, as |
8 * published by the Free Software Foundation. |
8 * published by the Free Software Foundation. |
22 * questions. |
22 * questions. |
23 * |
23 * |
24 */ |
24 */ |
25 |
25 |
26 #include "precompiled.hpp" |
26 #include "precompiled.hpp" |
27 #include "asm/assembler.hpp" |
|
28 #include "asm/assembler.inline.hpp" |
|
29 #include "asm/macroAssembler.inline.hpp" |
27 #include "asm/macroAssembler.inline.hpp" |
30 #include "compiler/disassembler.hpp" |
28 #include "compiler/disassembler.hpp" |
31 #include "gc_interface/collectedHeap.inline.hpp" |
29 #include "gc_interface/collectedHeap.inline.hpp" |
32 #include "interpreter/interpreter.hpp" |
30 #include "interpreter/interpreter.hpp" |
33 #include "memory/cardTableModRefBS.hpp" |
31 #include "memory/cardTableModRefBS.hpp" |
1118 bl64_patchable(fd->entry(), rt); |
1116 bl64_patchable(fd->entry(), rt); |
1119 _last_calls_return_pc = pc(); |
1117 _last_calls_return_pc = pc(); |
1120 } |
1118 } |
1121 return _last_calls_return_pc; |
1119 return _last_calls_return_pc; |
1122 } |
1120 } |
1123 #endif |
1121 #endif // ABI_ELFv2 |
1124 |
1122 |
1125 void MacroAssembler::call_VM_base(Register oop_result, |
1123 void MacroAssembler::call_VM_base(Register oop_result, |
1126 Register last_java_sp, |
1124 Register last_java_sp, |
1127 address entry_point, |
1125 address entry_point, |
1128 bool check_exceptions) { |
1126 bool check_exceptions) { |
1792 |
1790 |
1793 andi(temp_reg, mark_reg, markOopDesc::biased_lock_mask_in_place); |
1791 andi(temp_reg, mark_reg, markOopDesc::biased_lock_mask_in_place); |
1794 cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern); |
1792 cmpwi(cr_reg, temp_reg, markOopDesc::biased_lock_pattern); |
1795 bne(cr_reg, cas_label); |
1793 bne(cr_reg, cas_label); |
1796 |
1794 |
1797 load_klass_with_trap_null_check(temp_reg, obj_reg); |
1795 load_klass(temp_reg, obj_reg); |
1798 |
1796 |
1799 load_const_optimized(temp2_reg, ~((int) markOopDesc::age_mask_in_place)); |
1797 load_const_optimized(temp2_reg, ~((int) markOopDesc::age_mask_in_place)); |
1800 ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); |
1798 ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); |
1801 orr(temp_reg, R16_thread, temp_reg); |
1799 orr(temp_reg, R16_thread, temp_reg); |
1802 xorr(temp_reg, mark_reg, temp_reg); |
1800 xorr(temp_reg, mark_reg, temp_reg); |
1889 // value as the comparison value when doing the cas to acquire the |
1887 // value as the comparison value when doing the cas to acquire the |
1890 // bias in the current epoch. In other words, we allow transfer of |
1888 // bias in the current epoch. In other words, we allow transfer of |
1891 // the bias from one thread to another directly in this situation. |
1889 // the bias from one thread to another directly in this situation. |
1892 andi(temp_reg, mark_reg, markOopDesc::age_mask_in_place); |
1890 andi(temp_reg, mark_reg, markOopDesc::age_mask_in_place); |
1893 orr(temp_reg, R16_thread, temp_reg); |
1891 orr(temp_reg, R16_thread, temp_reg); |
1894 load_klass_with_trap_null_check(temp2_reg, obj_reg); |
1892 load_klass(temp2_reg, obj_reg); |
1895 ld(temp2_reg, in_bytes(Klass::prototype_header_offset()), temp2_reg); |
1893 ld(temp2_reg, in_bytes(Klass::prototype_header_offset()), temp2_reg); |
1896 orr(temp_reg, temp_reg, temp2_reg); |
1894 orr(temp_reg, temp_reg, temp2_reg); |
1897 |
1895 |
1898 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); |
1896 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); |
1899 |
1897 |
1925 // this object to the prototype value and fall through to the |
1923 // this object to the prototype value and fall through to the |
1926 // CAS-based locking scheme. Note that if our CAS fails, it means |
1924 // CAS-based locking scheme. Note that if our CAS fails, it means |
1927 // that another thread raced us for the privilege of revoking the |
1925 // that another thread raced us for the privilege of revoking the |
1928 // bias of this particular object, so it's okay to continue in the |
1926 // bias of this particular object, so it's okay to continue in the |
1929 // normal locking code. |
1927 // normal locking code. |
1930 load_klass_with_trap_null_check(temp_reg, obj_reg); |
1928 load_klass(temp_reg, obj_reg); |
1931 ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); |
1929 ld(temp_reg, in_bytes(Klass::prototype_header_offset()), temp_reg); |
1932 andi(temp2_reg, mark_reg, markOopDesc::age_mask_in_place); |
1930 andi(temp2_reg, mark_reg, markOopDesc::age_mask_in_place); |
1933 orr(temp_reg, temp_reg, temp2_reg); |
1931 orr(temp_reg, temp_reg, temp2_reg); |
1934 |
1932 |
1935 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); |
1933 assert(oopDesc::mark_offset_in_bytes() == 0, "offset of _mark is not 0"); |
2211 li(R0, 0); // dirty |
2209 li(R0, 0); // dirty |
2212 if (UseConcMarkSweepGC) membar(Assembler::StoreStore); |
2210 if (UseConcMarkSweepGC) membar(Assembler::StoreStore); |
2213 stbx(R0, Rtmp, Robj); |
2211 stbx(R0, Rtmp, Robj); |
2214 } |
2212 } |
2215 |
2213 |
2216 #ifndef SERIALGC |
2214 #if INCLUDE_ALL_GCS |
2217 |
|
2218 // General G1 pre-barrier generator. |
2215 // General G1 pre-barrier generator. |
2219 // Goal: record the previous value if it is not null. |
2216 // Goal: record the previous value if it is not null. |
2220 void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, |
2217 void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val, |
2221 Register Rtmp1, Register Rtmp2, bool needs_frame) { |
2218 Register Rtmp1, Register Rtmp2, bool needs_frame) { |
2222 Label runtime, filtered; |
2219 Label runtime, filtered; |
2326 |
2323 |
2327 srdi(Rcard_addr, Rstore_addr, CardTableModRefBS::card_shift); |
2324 srdi(Rcard_addr, Rstore_addr, CardTableModRefBS::card_shift); |
2328 |
2325 |
2329 // Get the address of the card. |
2326 // Get the address of the card. |
2330 lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); |
2327 lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); |
2331 |
2328 cmpwi(CCR0, Rtmp3, (int)G1SATBCardTableModRefBS::g1_young_card_val()); |
2332 assert(CardTableModRefBS::dirty_card_val() == 0, "otherwise check this code"); |
2329 beq(CCR0, filtered); |
2333 cmpwi(CCR0, Rtmp3 /* card value */, 0); |
2330 |
|
2331 membar(Assembler::StoreLoad); |
|
2332 lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr); // Reload after membar. |
|
2333 cmpwi(CCR0, Rtmp3 /* card value */, CardTableModRefBS::dirty_card_val()); |
2334 beq(CCR0, filtered); |
2334 beq(CCR0, filtered); |
2335 |
2335 |
2336 // Storing a region crossing, non-NULL oop, card is clean. |
2336 // Storing a region crossing, non-NULL oop, card is clean. |
2337 // Dirty card and log. |
2337 // Dirty card and log. |
2338 li(Rtmp3, 0); // dirty |
2338 li(Rtmp3, CardTableModRefBS::dirty_card_val()); |
2339 //release(); // G1: oops are allowed to get visible after dirty marking. |
2339 //release(); // G1: oops are allowed to get visible after dirty marking. |
2340 stbx(Rtmp3, Rbase, Rcard_addr); |
2340 stbx(Rtmp3, Rbase, Rcard_addr); |
2341 |
2341 |
2342 add(Rcard_addr, Rbase, Rcard_addr); // This is the address which needs to get enqueued. |
2342 add(Rcard_addr, Rbase, Rcard_addr); // This is the address which needs to get enqueued. |
2343 Rbase = noreg; // end of lifetime |
2343 Rbase = noreg; // end of lifetime |
2360 // Save the live input values. |
2360 // Save the live input values. |
2361 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, R16_thread); |
2361 call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, R16_thread); |
2362 |
2362 |
2363 bind(filtered_int); |
2363 bind(filtered_int); |
2364 } |
2364 } |
2365 #endif // SERIALGC |
2365 #endif // INCLUDE_ALL_GCS |
2366 |
2366 |
2367 // Values for last_Java_pc, and last_Java_sp must comply to the rules |
2367 // Values for last_Java_pc, and last_Java_sp must comply to the rules |
2368 // in frame_ppc64.hpp. |
2368 // in frame_ppc64.hpp. |
2369 void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) { |
2369 void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) { |
2370 // Always set last_Java_pc and flags first because once last_Java_sp |
2370 // Always set last_Java_pc and flags first because once last_Java_sp |
2451 |
2451 |
2452 |
2452 |
2453 void MacroAssembler::encode_klass_not_null(Register dst, Register src) { |
2453 void MacroAssembler::encode_klass_not_null(Register dst, Register src) { |
2454 Register current = (src != noreg) ? src : dst; // Klass is in dst if no src provided. |
2454 Register current = (src != noreg) ? src : dst; // Klass is in dst if no src provided. |
2455 if (Universe::narrow_klass_base() != 0) { |
2455 if (Universe::narrow_klass_base() != 0) { |
2456 load_const(R0, Universe::narrow_klass_base(), (dst != current) ? dst : noreg); // Use dst as temp if it is free. |
2456 // Use dst as temp if it is free. |
|
2457 load_const(R0, Universe::narrow_klass_base(), (dst != current && dst != R0) ? dst : noreg); |
2457 sub(dst, current, R0); |
2458 sub(dst, current, R0); |
2458 current = dst; |
2459 current = dst; |
2459 } |
2460 } |
2460 if (Universe::narrow_klass_shift() != 0) { |
2461 if (Universe::narrow_klass_shift() != 0) { |
2461 srdi(dst, current, Universe::narrow_klass_shift()); |
2462 srdi(dst, current, Universe::narrow_klass_shift()); |