< prev index next >

src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp

Print this page

 24 
 25 #include "precompiled.hpp"
 26 #include "c1/c1_MacroAssembler.hpp"
 27 #include "c1/c1_Runtime1.hpp"
 28 #include "code/compiledIC.hpp"
 29 #include "compiler/compilerDefinitions.inline.hpp"
 30 #include "gc/shared/barrierSet.hpp"
 31 #include "gc/shared/barrierSetAssembler.hpp"
 32 #include "gc/shared/collectedHeap.hpp"
 33 #include "gc/shared/tlab_globals.hpp"
 34 #include "interpreter/interpreter.hpp"
 35 #include "oops/arrayOop.hpp"
 36 #include "oops/markWord.hpp"
 37 #include "runtime/basicLock.hpp"
 38 #include "runtime/globals.hpp"
 39 #include "runtime/os.hpp"
 40 #include "runtime/sharedRuntime.hpp"
 41 #include "runtime/stubRoutines.hpp"
 42 #include "utilities/checkedCast.hpp"
 43 #include "utilities/globalDefinitions.hpp"

 44 
 45 int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
 46   const int aligned_mask = BytesPerWord -1;
 47   const int hdr_offset = oopDesc::mark_offset_in_bytes();
 48   assert(hdr == rax, "hdr must be rax, for the cmpxchg instruction");
 49   assert_different_registers(hdr, obj, disp_hdr, tmp);
 50   int null_check_offset = -1;
 51 
 52   verify_oop(obj);
 53 
 54   // save object being locked into the BasicObjectLock
 55   movptr(Address(disp_hdr, BasicObjectLock::obj_offset()), obj);
 56 
 57   null_check_offset = offset();
 58 
 59   if (DiagnoseSyncOnValueBasedClasses != 0) {
 60     load_klass(hdr, obj, rscratch1);
 61     movl(hdr, Address(hdr, Klass::access_flags_offset()));
 62     testl(hdr, JVM_ACC_IS_VALUE_BASED_CLASS);
 63     jcc(Assembler::notZero, slow_case);
 64   }
 65 
 66   if (LockingMode == LM_LIGHTWEIGHT) {
 67 #ifdef _LP64
 68     const Register thread = r15_thread;

 69 #else
 70     const Register thread = disp_hdr;
 71     get_thread(thread);


 72 #endif
 73     lightweight_lock(obj, hdr, thread, tmp, slow_case);
 74   } else  if (LockingMode == LM_LEGACY) {
 75     Label done;
 76     // Load object header
 77     movptr(hdr, Address(obj, hdr_offset));
 78     // and mark it as unlocked
 79     orptr(hdr, markWord::unlocked_value);
 80     // save unlocked object header into the displaced header location on the stack
 81     movptr(Address(disp_hdr, 0), hdr);
 82     // test if object header is still the same (i.e. unlocked), and if so, store the
 83     // displaced header address in the object header - if it is not the same, get the
 84     // object header instead
 85     MacroAssembler::lock(); // must be immediately before cmpxchg!
 86     cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
 87     // if the object header was the same, we're done
 88     jcc(Assembler::equal, done);
 89     // if the object header was not the same, it is now in the hdr register
 90     // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
 91     //
 92     // 1) (hdr & aligned_mask) == 0
 93     // 2) rsp <= hdr

154     // we do unlocking via runtime call
155     jcc(Assembler::notEqual, slow_case);
156     // done
157   }
158   bind(done);
159   dec_held_monitor_count();
160 }
161 
162 
163 // Defines obj, preserves var_size_in_bytes
164 void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {
165   if (UseTLAB) {
166     tlab_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
167   } else {
168     jmp(slow_case);
169   }
170 }
171 
172 
173 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
174   assert_different_registers(obj, klass, len);
175   movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
176 #ifdef _LP64
177   if (UseCompressedClassPointers) { // Take care not to kill klass




178     movptr(t1, klass);
179     encode_klass_not_null(t1, rscratch1);
180     movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
181   } else
182 #endif
183   {

184     movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
185   }
186 
187   if (len->is_valid()) {
188     movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
189 #ifdef _LP64
190     int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
191     if (!is_aligned(base_offset, BytesPerWord)) {
192       assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
193       // Clear gap/first 4 bytes following the length field.
194       xorl(t1, t1);
195       movl(Address(obj, base_offset), t1);
196     }
197 #endif
198   }
199 #ifdef _LP64
200   else if (UseCompressedClassPointers) {
201     xorptr(t1, t1);
202     store_klass_gap(obj, t1);
203   }
204 #endif
205 }
206 
207 
208 // preserves obj, destroys len_in_bytes
209 void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {
210   assert(hdr_size_in_bytes >= 0, "header size must be positive or 0");
211   Label done;
212 
213   // len_in_bytes is positive and ptr sized
214   subptr(len_in_bytes, hdr_size_in_bytes);
215   zero_memory(obj, len_in_bytes, hdr_size_in_bytes, t1);
216   bind(done);
217 }
218 
219 
220 void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {
221   assert(obj == rax, "obj must be in rax, for cmpxchg");
222   assert_different_registers(obj, t1, t2); // XXX really?
223   assert(header_size >= 0 && object_size >= header_size, "illegal sizes");
224 
225   try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);
226 
227   initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2, UseTLAB);
228 }
229 
230 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) {
231   assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
232          "con_size_in_bytes is not multiple of alignment");
233   const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
234 


235   initialize_header(obj, klass, noreg, t1, t2);
236 
237   if (!(UseTLAB && ZeroTLAB && is_tlab_allocated)) {
238     // clear rest of allocated space
239     const Register t1_zero = t1;
240     const Register index = t2;
241     const int threshold = 6 * BytesPerWord;   // approximate break even point for code size (see comments below)
242     if (var_size_in_bytes != noreg) {
243       mov(index, var_size_in_bytes);
244       initialize_body(obj, index, hdr_size_in_bytes, t1_zero);
245     } else if (con_size_in_bytes <= threshold) {
246       // use explicit null stores
247       // code size = 2 + 3*n bytes (n = number of fields to clear)
248       xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code)
249       for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord)
250         movptr(Address(obj, i), t1_zero);
251     } else if (con_size_in_bytes > hdr_size_in_bytes) {
252       // use loop to null out the fields
253       // code size = 16 bytes for even n (n = number of fields to clear)
254       // initialize last object field first if odd number of fields

 24 
 25 #include "precompiled.hpp"
 26 #include "c1/c1_MacroAssembler.hpp"
 27 #include "c1/c1_Runtime1.hpp"
 28 #include "code/compiledIC.hpp"
 29 #include "compiler/compilerDefinitions.inline.hpp"
 30 #include "gc/shared/barrierSet.hpp"
 31 #include "gc/shared/barrierSetAssembler.hpp"
 32 #include "gc/shared/collectedHeap.hpp"
 33 #include "gc/shared/tlab_globals.hpp"
 34 #include "interpreter/interpreter.hpp"
 35 #include "oops/arrayOop.hpp"
 36 #include "oops/markWord.hpp"
 37 #include "runtime/basicLock.hpp"
 38 #include "runtime/globals.hpp"
 39 #include "runtime/os.hpp"
 40 #include "runtime/sharedRuntime.hpp"
 41 #include "runtime/stubRoutines.hpp"
 42 #include "utilities/checkedCast.hpp"
 43 #include "utilities/globalDefinitions.hpp"
 44 #include "utilities/macros.hpp"
 45 
 46 int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register tmp, Label& slow_case) {
 47   const int aligned_mask = BytesPerWord -1;
 48   const int hdr_offset = oopDesc::mark_offset_in_bytes();
 49   assert(hdr == rax, "hdr must be rax, for the cmpxchg instruction");
 50   assert_different_registers(hdr, obj, disp_hdr, tmp);
 51   int null_check_offset = -1;
 52 
 53   verify_oop(obj);
 54 
 55   // save object being locked into the BasicObjectLock
 56   movptr(Address(disp_hdr, BasicObjectLock::obj_offset()), obj);
 57 
 58   null_check_offset = offset();
 59 
 60   if (DiagnoseSyncOnValueBasedClasses != 0) {
 61     load_klass(hdr, obj, rscratch1);
 62     movl(hdr, Address(hdr, Klass::access_flags_offset()));
 63     testl(hdr, JVM_ACC_IS_VALUE_BASED_CLASS);
 64     jcc(Assembler::notZero, slow_case);
 65   }
 66 
 67   if (LockingMode == LM_LIGHTWEIGHT) {
 68 #ifdef _LP64
 69     const Register thread = r15_thread;
 70     lightweight_lock(disp_hdr, obj, hdr, thread, tmp, slow_case);
 71 #else
 72     // Implicit null check.
 73     movptr(hdr, Address(obj, oopDesc::mark_offset_in_bytes()));
 74     // Lacking registers and thread on x86_32. Always take slow path.
 75     jmp(slow_case);
 76 #endif

 77   } else  if (LockingMode == LM_LEGACY) {
 78     Label done;
 79     // Load object header
 80     movptr(hdr, Address(obj, hdr_offset));
 81     // and mark it as unlocked
 82     orptr(hdr, markWord::unlocked_value);
 83     // save unlocked object header into the displaced header location on the stack
 84     movptr(Address(disp_hdr, 0), hdr);
 85     // test if object header is still the same (i.e. unlocked), and if so, store the
 86     // displaced header address in the object header - if it is not the same, get the
 87     // object header instead
 88     MacroAssembler::lock(); // must be immediately before cmpxchg!
 89     cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
 90     // if the object header was the same, we're done
 91     jcc(Assembler::equal, done);
 92     // if the object header was not the same, it is now in the hdr register
 93     // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
 94     //
 95     // 1) (hdr & aligned_mask) == 0
 96     // 2) rsp <= hdr

157     // we do unlocking via runtime call
158     jcc(Assembler::notEqual, slow_case);
159     // done
160   }
161   bind(done);
162   dec_held_monitor_count();
163 }
164 
165 
166 // Defines obj, preserves var_size_in_bytes
167 void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {
168   if (UseTLAB) {
169     tlab_allocate(noreg, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
170   } else {
171     jmp(slow_case);
172   }
173 }
174 
175 
176 void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
177   assert_different_registers(obj, klass, len, t1, t2);

178 #ifdef _LP64
179   if (UseCompactObjectHeaders) {
180     movptr(t1, Address(klass, Klass::prototype_header_offset()));
181     movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1);
182   } else if (UseCompressedClassPointers) { // Take care not to kill klass
183     movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
184     movptr(t1, klass);
185     encode_klass_not_null(t1, rscratch1);
186     movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1);
187   } else
188 #endif
189   {
190     movptr(Address(obj, oopDesc::mark_offset_in_bytes()), checked_cast<int32_t>(markWord::prototype().value()));
191     movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
192   }
193 
194   if (len->is_valid()) {
195     movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
196 #ifdef _LP64
197     int base_offset = arrayOopDesc::length_offset_in_bytes() + BytesPerInt;
198     if (!is_aligned(base_offset, BytesPerWord)) {
199       assert(is_aligned(base_offset, BytesPerInt), "must be 4-byte aligned");
200       // Clear gap/first 4 bytes following the length field.
201       xorl(t1, t1);
202       movl(Address(obj, base_offset), t1);
203     }
204 #endif
205   }
206 #ifdef _LP64
207   else if (UseCompressedClassPointers && !UseCompactObjectHeaders) {
208     xorptr(t1, t1);
209     store_klass_gap(obj, t1);
210   }
211 #endif
212 }
213 
214 
215 // preserves obj, destroys len_in_bytes
216 void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {
217   assert(hdr_size_in_bytes >= 0, "header size must be positive or 0");
218   Label done;
219 
220   // len_in_bytes is positive and ptr sized
221   subptr(len_in_bytes, hdr_size_in_bytes);
222   zero_memory(obj, len_in_bytes, hdr_size_in_bytes, t1);
223   bind(done);
224 }
225 
226 
227 void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {
228   assert(obj == rax, "obj must be in rax, for cmpxchg");
229   assert_different_registers(obj, t1, t2); // XXX really?
230   assert(header_size >= 0 && object_size >= header_size, "illegal sizes");
231 
232   try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);
233 
234   initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2, UseTLAB);
235 }
236 
237 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) {
238   assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
239          "con_size_in_bytes is not multiple of alignment");
240   const int hdr_size_in_bytes = instanceOopDesc::header_size() * HeapWordSize;
241   if (UseCompactObjectHeaders) {
242     assert(hdr_size_in_bytes == 8, "check object headers size");
243   }
244   initialize_header(obj, klass, noreg, t1, t2);
245 
246   if (!(UseTLAB && ZeroTLAB && is_tlab_allocated)) {
247     // clear rest of allocated space
248     const Register t1_zero = t1;
249     const Register index = t2;
250     const int threshold = 6 * BytesPerWord;   // approximate break even point for code size (see comments below)
251     if (var_size_in_bytes != noreg) {
252       mov(index, var_size_in_bytes);
253       initialize_body(obj, index, hdr_size_in_bytes, t1_zero);
254     } else if (con_size_in_bytes <= threshold) {
255       // use explicit null stores
256       // code size = 2 + 3*n bytes (n = number of fields to clear)
257       xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code)
258       for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord)
259         movptr(Address(obj, i), t1_zero);
260     } else if (con_size_in_bytes > hdr_size_in_bytes) {
261       // use loop to null out the fields
262       // code size = 16 bytes for even n (n = number of fields to clear)
263       // initialize last object field first if odd number of fields
< prev index next >