c1_MacroAssembler_x86.cpp 14.7 KB
Newer Older
D
duke 已提交
1
/*
X
xdono 已提交
2
 * Copyright 1999-2008 Sun Microsystems, Inc.  All Rights Reserved.
D
duke 已提交
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 *
 */

#include "incls/_precompiled.incl"
#include "incls/_c1_MacroAssembler_x86.cpp.incl"

int C1_MacroAssembler::lock_object(Register hdr, Register obj, Register disp_hdr, Register scratch, Label& slow_case) {
29
  const int aligned_mask = BytesPerWord -1;
D
duke 已提交
30 31 32 33 34 35 36 37 38
  const int hdr_offset = oopDesc::mark_offset_in_bytes();
  assert(hdr == rax, "hdr must be rax, for the cmpxchg instruction");
  assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");
  Label done;
  int null_check_offset = -1;

  verify_oop(obj);

  // save object being locked into the BasicObjectLock
39
  movptr(Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()), obj);
D
duke 已提交
40 41 42 43 44 45 46 47 48

  if (UseBiasedLocking) {
    assert(scratch != noreg, "should have scratch register at this point");
    null_check_offset = biased_locking_enter(disp_hdr, obj, hdr, scratch, false, done, &slow_case);
  } else {
    null_check_offset = offset();
  }

  // Load object header
49
  movptr(hdr, Address(obj, hdr_offset));
D
duke 已提交
50
  // and mark it as unlocked
51
  orptr(hdr, markOopDesc::unlocked_value);
D
duke 已提交
52
  // save unlocked object header into the displaced header location on the stack
53
  movptr(Address(disp_hdr, 0), hdr);
D
duke 已提交
54 55 56 57
  // test if object header is still the same (i.e. unlocked), and if so, store the
  // displaced header address in the object header - if it is not the same, get the
  // object header instead
  if (os::is_MP()) MacroAssembler::lock(); // must be immediately before cmpxchg!
58
  cmpxchgptr(disp_hdr, Address(obj, hdr_offset));
D
duke 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
  // if the object header was the same, we're done
  if (PrintBiasedLockingStatistics) {
    cond_inc32(Assembler::equal,
               ExternalAddress((address)BiasedLocking::fast_path_entry_count_addr()));
  }
  jcc(Assembler::equal, done);
  // if the object header was not the same, it is now in the hdr register
  // => test if it is a stack pointer into the same stack (recursive locking), i.e.:
  //
  // 1) (hdr & aligned_mask) == 0
  // 2) rsp <= hdr
  // 3) hdr <= rsp + page_size
  //
  // these 3 tests can be done by evaluating the following expression:
  //
  // (hdr - rsp) & (aligned_mask - page_size)
  //
  // assuming both the stack pointer and page_size have their least
  // significant 2 bits cleared and page_size is a power of 2
78 79
  subptr(hdr, rsp);
  andptr(hdr, aligned_mask - os::vm_page_size());
D
duke 已提交
80 81
  // for recursive locking, the result is zero => save it in the displaced header
  // location (NULL in the displaced hdr location indicates recursive locking)
82
  movptr(Address(disp_hdr, 0), hdr);
D
duke 已提交
83 84 85 86 87 88 89 90 91
  // otherwise we don't care about the result and handle locking via runtime call
  jcc(Assembler::notZero, slow_case);
  // done
  bind(done);
  return null_check_offset;
}


void C1_MacroAssembler::unlock_object(Register hdr, Register obj, Register disp_hdr, Label& slow_case) {
92
  const int aligned_mask = BytesPerWord -1;
D
duke 已提交
93 94 95 96 97 98 99
  const int hdr_offset = oopDesc::mark_offset_in_bytes();
  assert(disp_hdr == rax, "disp_hdr must be rax, for the cmpxchg instruction");
  assert(hdr != obj && hdr != disp_hdr && obj != disp_hdr, "registers must be different");
  Label done;

  if (UseBiasedLocking) {
    // load object
100
    movptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));
D
duke 已提交
101 102 103 104
    biased_locking_exit(obj, hdr, done);
  }

  // load displaced header
105
  movptr(hdr, Address(disp_hdr, 0));
D
duke 已提交
106
  // if the loaded hdr is NULL we had recursive locking
107
  testptr(hdr, hdr);
D
duke 已提交
108 109 110 111
  // if we had recursive locking, we are done
  jcc(Assembler::zero, done);
  if (!UseBiasedLocking) {
    // load object
112
    movptr(obj, Address(disp_hdr, BasicObjectLock::obj_offset_in_bytes()));
D
duke 已提交
113 114 115 116 117 118
  }
  verify_oop(obj);
  // test if object header is pointing to the displaced header, and if so, restore
  // the displaced header in the object - if the object header is not pointing to
  // the displaced header, get the object header instead
  if (os::is_MP()) MacroAssembler::lock(); // must be immediately before cmpxchg!
119
  cmpxchgptr(hdr, Address(obj, hdr_offset));
D
duke 已提交
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
  // if the object header was not pointing to the displaced header,
  // we do unlocking via runtime call
  jcc(Assembler::notEqual, slow_case);
  // done
  bind(done);
}


// Defines obj, preserves var_size_in_bytes
void C1_MacroAssembler::try_allocate(Register obj, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2, Label& slow_case) {
  if (UseTLAB) {
    tlab_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case);
  } else {
    eden_allocate(obj, var_size_in_bytes, con_size_in_bytes, t1, slow_case);
  }
}


void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register len, Register t1, Register t2) {
  assert_different_registers(obj, klass, len);
  if (UseBiasedLocking && !len->is_valid()) {
    assert_different_registers(obj, klass, len, t1, t2);
142 143
    movptr(t1, Address(klass, Klass::prototype_header_offset_in_bytes() + klassOopDesc::klass_part_offset_in_bytes()));
    movptr(Address(obj, oopDesc::mark_offset_in_bytes()), t1);
D
duke 已提交
144
  } else {
145 146
    // This assumes that all prototype bits fit in an int32_t
    movptr(Address(obj, oopDesc::mark_offset_in_bytes ()), (int32_t)(intptr_t)markOopDesc::prototype());
D
duke 已提交
147 148
  }

149
  movptr(Address(obj, oopDesc::klass_offset_in_bytes()), klass);
D
duke 已提交
150 151 152 153 154 155 156 157 158 159 160 161
  if (len->is_valid()) {
    movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len);
  }
}


// preserves obj, destroys len_in_bytes
void C1_MacroAssembler::initialize_body(Register obj, Register len_in_bytes, int hdr_size_in_bytes, Register t1) {
  Label done;
  assert(obj != len_in_bytes && obj != t1 && t1 != len_in_bytes, "registers must be different");
  assert((hdr_size_in_bytes & (BytesPerWord - 1)) == 0, "header size is not a multiple of BytesPerWord");
  Register index = len_in_bytes;
162 163
  // index is positive and ptr sized
  subptr(index, hdr_size_in_bytes);
D
duke 已提交
164 165 166 167 168
  jcc(Assembler::zero, done);
  // initialize topmost word, divide index by 2, check if odd and test if zero
  // note: for the remaining code to work, index must be a multiple of BytesPerWord
#ifdef ASSERT
  { Label L;
169
    testptr(index, BytesPerWord - 1);
D
duke 已提交
170 171 172 173 174
    jcc(Assembler::zero, L);
    stop("index is not a multiple of BytesPerWord");
    bind(L);
  }
#endif
175
  xorptr(t1, t1);    // use _zero reg to clear memory (shorter code)
D
duke 已提交
176
  if (UseIncDec) {
177
    shrptr(index, 3);  // divide by 8/16 and set carry flag if bit 2 was set
D
duke 已提交
178
  } else {
179 180
    shrptr(index, 2);  // use 2 instructions to avoid partial flag stall
    shrptr(index, 1);
D
duke 已提交
181
  }
182
#ifndef _LP64
D
duke 已提交
183 184 185 186 187 188 189
  // index could have been not a multiple of 8 (i.e., bit 2 was set)
  { Label even;
    // note: if index was a multiple of 8, than it cannot
    //       be 0 now otherwise it must have been 0 before
    //       => if it is even, we don't need to check for 0 again
    jcc(Assembler::carryClear, even);
    // clear topmost word (no jump needed if conditional assignment would work here)
190
    movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - 0*BytesPerWord), t1);
D
duke 已提交
191 192 193 194
    // index could be 0 now, need to check again
    jcc(Assembler::zero, done);
    bind(even);
  }
195
#endif // !_LP64
D
duke 已提交
196 197 198
  // initialize remaining object fields: rdx is a multiple of 2 now
  { Label loop;
    bind(loop);
199 200
    movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - 1*BytesPerWord), t1);
    NOT_LP64(movptr(Address(obj, index, Address::times_8, hdr_size_in_bytes - 2*BytesPerWord), t1);)
D
duke 已提交
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
    decrement(index);
    jcc(Assembler::notZero, loop);
  }

  // done
  bind(done);
}


void C1_MacroAssembler::allocate_object(Register obj, Register t1, Register t2, int header_size, int object_size, Register klass, Label& slow_case) {
  assert(obj == rax, "obj must be in rax, for cmpxchg");
  assert(obj != t1 && obj != t2 && t1 != t2, "registers must be different"); // XXX really?
  assert(header_size >= 0 && object_size >= header_size, "illegal sizes");

  try_allocate(obj, noreg, object_size * BytesPerWord, t1, t2, slow_case);

  initialize_object(obj, klass, noreg, object_size * HeapWordSize, t1, t2);
}

void C1_MacroAssembler::initialize_object(Register obj, Register klass, Register var_size_in_bytes, int con_size_in_bytes, Register t1, Register t2) {
  assert((con_size_in_bytes & MinObjAlignmentInBytesMask) == 0,
         "con_size_in_bytes is not multiple of alignment");
223
  const int hdr_size_in_bytes = instanceOopDesc::base_offset_in_bytes();
D
duke 已提交
224 225 226 227 228 229 230 231

  initialize_header(obj, klass, noreg, t1, t2);

  // 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) {
232
    mov(index, var_size_in_bytes);
D
duke 已提交
233 234 235 236
    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)
237
    xorptr(t1_zero, t1_zero); // use t1_zero reg to clear memory (shorter code)
D
duke 已提交
238
    for (int i = hdr_size_in_bytes; i < con_size_in_bytes; i += BytesPerWord)
239
      movptr(Address(obj, i), t1_zero);
D
duke 已提交
240 241 242 243
  } 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
244 245
    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);
D
duke 已提交
246 247
    // initialize last object field if constant size is odd
    if (((con_size_in_bytes - hdr_size_in_bytes) & 4) != 0)
248
      movptr(Address(obj, con_size_in_bytes - (1*BytesPerWord)), t1_zero);
D
duke 已提交
249 250 251
    // initialize remaining object fields: rdx is a multiple of 2
    { Label loop;
      bind(loop);
252 253 254 255
      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);)
D
duke 已提交
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
      decrement(index);
      jcc(Assembler::notZero, loop);
    }
  }

  if (DTraceAllocProbes) {
    assert(obj == rax, "must be");
    call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
  }

  verify_oop(obj);
}

void C1_MacroAssembler::allocate_array(Register obj, Register len, Register t1, Register t2, int header_size, Address::ScaleFactor f, Register klass, Label& slow_case) {
  assert(obj == rax, "obj must be in rax, for cmpxchg");
  assert_different_registers(obj, len, t1, t2, klass);

  // determine alignment mask
274
  assert(!(BytesPerWord & 1), "must be a multiple of 2 for masking code to work");
D
duke 已提交
275 276

  // check for negative or excessive length
277
  cmpptr(len, (int32_t)max_array_allocation_length);
D
duke 已提交
278 279 280 281
  jcc(Assembler::above, slow_case);

  const Register arr_size = t2; // okay to be the same
  // align object end
282 283 284
  movptr(arr_size, (int32_t)header_size * BytesPerWord + MinObjAlignmentInBytesMask);
  lea(arr_size, Address(arr_size, len, f));
  andptr(arr_size, ~MinObjAlignmentInBytesMask);
D
duke 已提交
285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309

  try_allocate(obj, arr_size, 0, t1, t2, slow_case);

  initialize_header(obj, klass, len, t1, t2);

  // clear rest of allocated space
  const Register len_zero = len;
  initialize_body(obj, arr_size, header_size * BytesPerWord, len_zero);

  if (DTraceAllocProbes) {
    assert(obj == rax, "must be");
    call(RuntimeAddress(Runtime1::entry_for(Runtime1::dtrace_object_alloc_id)));
  }

  verify_oop(obj);
}



void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) {
  verify_oop(receiver);
  // explicit NULL check not needed since load from [klass_offset] causes a trap
  // check against inline cache
  assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check");
  int start_offset = offset();
310
  cmpptr(iCache, Address(receiver, oopDesc::klass_offset_in_bytes()));
D
duke 已提交
311 312 313 314
  // if icache check fails, then jump to runtime routine
  // Note: RECEIVER must still contain the receiver!
  jump_cc(Assembler::notEqual,
          RuntimeAddress(SharedRuntime::get_ic_miss_stub()));
315 316
  const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9);
  assert(offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry");
D
duke 已提交
317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369
}


void C1_MacroAssembler::method_exit(bool restore_frame) {
  if (restore_frame) {
    leave();
  }
  ret(0);
}


void C1_MacroAssembler::build_frame(int frame_size_in_bytes) {
  // Make sure there is enough stack space for this method's activation.
  // Note that we do this before doing an enter(). This matches the
  // ordering of C2's stack overflow check / rsp decrement and allows
  // the SharedRuntime stack overflow handling to be consistent
  // between the two compilers.
  generate_stack_overflow_check(frame_size_in_bytes);

  enter();
#ifdef TIERED
  // c2 leaves fpu stack dirty. Clean it on entry
  if (UseSSE < 2 ) {
    empty_FPU_stack();
  }
#endif // TIERED
  decrement(rsp, frame_size_in_bytes); // does not emit code for frame_size == 0
}


void C1_MacroAssembler::unverified_entry(Register receiver, Register ic_klass) {
  if (C1Breakpoint) int3();
  inline_cache_check(receiver, ic_klass);
}


void C1_MacroAssembler::verified_entry() {
  if (C1Breakpoint)int3();
  // build frame
  verify_FPU(0, "method_entry");
}


#ifndef PRODUCT

void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
  if (!VerifyOops) return;
  verify_oop_addr(Address(rsp, stack_offset));
}

void C1_MacroAssembler::verify_not_null_oop(Register r) {
  if (!VerifyOops) return;
  Label not_null;
370
  testptr(r, r);
D
duke 已提交
371 372 373 374 375 376 377 378
  jcc(Assembler::notZero, not_null);
  stop("non-null oop required");
  bind(not_null);
  verify_oop(r);
}

void C1_MacroAssembler::invalidate_registers(bool inv_rax, bool inv_rbx, bool inv_rcx, bool inv_rdx, bool inv_rsi, bool inv_rdi) {
#ifdef ASSERT
379 380 381 382 383 384
  if (inv_rax) movptr(rax, 0xDEAD);
  if (inv_rbx) movptr(rbx, 0xDEAD);
  if (inv_rcx) movptr(rcx, 0xDEAD);
  if (inv_rdx) movptr(rdx, 0xDEAD);
  if (inv_rsi) movptr(rsi, 0xDEAD);
  if (inv_rdi) movptr(rdi, 0xDEAD);
D
duke 已提交
385 386 387 388
#endif
}

#endif // ifndef PRODUCT