ccccccccc13


void TemplateTable::float_cmp(bool is_float, int unordered_result) {
  if (is_float) {
    __ fld_s(at_rsp());
  } else {
    __ fld_d(at_rsp());
    __ pop(rdx);
  }
  __ pop(rcx);
  __ fcmp2int(rax, unordered_result < 0);
}
void TemplateTable::branch(bool is_jsr, bool is_wide) {
  __ get_method(rcx);           // ECX holds method
  __ profile_taken_branch(rax,rbx); // EAX holds updated MDP, EBX holds bumped taken count
  const ByteSize be_offset = MethodCounters::backedge_counter_offset() +
                             InvocationCounter::counter_offset();
  const ByteSize inv_offset = MethodCounters::invocation_counter_offset() +
                              InvocationCounter::counter_offset();
  if (is_wide) {
    __ movl(rdx, at_bcp(1));
  } else {
    __ load_signed_short(rdx, at_bcp(1));
  }
  __ bswapl(rdx);
  if (!is_wide) __ sarl(rdx, 16);
  LP64_ONLY(__ movslq(rdx, rdx));
  if (is_jsr) {
    __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1, 0));
    __ lea(rax, at_bcp((is_wide ? 5 : 3) - in_bytes(ConstMethod::codes_offset())));
    __ subptr(rax, Address(rcx, Method::const_offset()));
    __ addptr(rsi, rdx);
    __ push_i(rax);
    __ dispatch_only_noverify(vtos);
    return;
  }
  __ addptr(rsi, rdx);
  assert(UseLoopCounter || !UseOnStackReplacement, "on-stack-replacement requires loop counters");
  Label backedge_counter_overflow;
  Label profile_method;
  Label dispatch;
  if (UseLoopCounter) {
    __ testl(rdx, rdx);             // check if forward or backward branch
    __ jcc(Assembler::positive, dispatch); // count only if backward branch
    Label has_counters;
    __ movptr(rax, Address(rcx, Method::method_counters_offset()));
    __ testptr(rax, rax);
    __ jcc(Assembler::notZero, has_counters);
    __ push(rdx);
    __ push(rcx);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters),
               rcx);
    __ pop(rcx);
    __ pop(rdx);
    __ movptr(rax, Address(rcx, Method::method_counters_offset()));
    __ testptr(rax, rax);
    __ jcc(Assembler::zero, dispatch);
    __ bind(has_counters);
    if (TieredCompilation) {
      Label no_mdo;
      int increment = InvocationCounter::count_increment;
      int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
      if (ProfileInterpreter) {
        __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
        __ testptr(rbx, rbx);
        __ jccb(Assembler::zero, no_mdo);
        const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
                                                in_bytes(InvocationCounter::counter_offset()));
        __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, rax, false, Assembler::zero,
                                   UseOnStackReplacement ? &backedge_counter_overflow : NULL);
        __ jmp(dispatch);
      }
      __ bind(no_mdo);
      __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
      __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
                                 rax, false, Assembler::zero,
                                 UseOnStackReplacement ? &backedge_counter_overflow : NULL);
    } else {
      __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
      __ movl(rax, Address(rcx, be_offset));        // load backedge counter
      __ incrementl(rax, InvocationCounter::count_increment); // increment counter
      __ movl(Address(rcx, be_offset), rax);        // store counter
      __ movl(rax, Address(rcx, inv_offset));    // load invocation counter
      __ andl(rax, InvocationCounter::count_mask_value);     // and the status bits
      __ addl(rax, Address(rcx, be_offset));        // add both counters
      if (ProfileInterpreter) {
        __ cmp32(rax,
                 ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
        __ jcc(Assembler::less, dispatch);
        __ test_method_data_pointer(rax, profile_method);
        if (UseOnStackReplacement) {
          __ cmp32(rbx,
                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
          __ jcc(Assembler::below, dispatch);
          const int overflow_frequency = 1024;
          __ andptr(rbx, overflow_frequency-1);
          __ jcc(Assembler::zero, backedge_counter_overflow);
        }
      } else {
        if (UseOnStackReplacement) {
          __ cmp32(rax,
                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
          __ jcc(Assembler::aboveEqual, backedge_counter_overflow);
        }
      }
    }
    __ bind(dispatch);
  }
  __ load_unsigned_byte(rbx, Address(rsi, 0));
  __ dispatch_only(vtos);
  if (UseLoopCounter) {
    if (ProfileInterpreter) {
      __ bind(profile_method);
      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
      __ load_unsigned_byte(rbx, Address(rsi, 0));  // restore target bytecode
      __ set_method_data_pointer_for_bcp();
      __ jmp(dispatch);
    }
    if (UseOnStackReplacement) {
      __ bind(backedge_counter_overflow);
      __ negptr(rdx);
      __ addptr(rdx, rsi);        // branch bcp
      call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::frequency_counter_overflow), rdx);
      __ load_unsigned_byte(rbx, Address(rsi, 0));  // restore target bytecode
      __ testptr(rax, rax);                      // test result
      __ jcc(Assembler::zero, dispatch);         // no osr if null
      __ movl(rcx, Address(rax, nmethod::entry_bci_offset()));
      __ cmpl(rcx, InvalidOSREntryBci);
      __ jcc(Assembler::equal, dispatch);
      __ mov(rbx, rax);                             // save the nmethod
      const Register thread = rcx;
      __ get_thread(thread);
      call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin));
      __ mov(rcx, rax);
      __ movptr(rdx, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp
      __ leave();                                // remove frame anchor
      __ pop(rdi);                               // get return address
      __ mov(rsp, rdx);                          // set sp to sender sp
      __ andptr(rsp, -(StackAlignmentInBytes));
      __ push(rdi);
      __ jmp(Address(rbx, nmethod::osr_entry_point_offset()));
    }
  }
}
void TemplateTable::if_0cmp(Condition cc) {
  transition(itos, vtos);
  Label not_taken;
  __ testl(rax, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::if_icmp(Condition cc) {
  transition(itos, vtos);
  Label not_taken;
  __ pop_i(rdx);
  __ cmpl(rdx, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::if_nullcmp(Condition cc) {
  transition(atos, vtos);
  Label not_taken;
  __ testptr(rax, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::if_acmp(Condition cc) {
  transition(atos, vtos);
  Label not_taken;
  __ pop_ptr(rdx);
  __ cmpptr(rdx, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::ret() {
  transition(vtos, vtos);
  locals_index(rbx);
  __ movptr(rbx, iaddress(rbx));                   // get return bci, compute return bcp
  __ profile_ret(rbx, rcx);
  __ get_method(rax);
  __ movptr(rsi, Address(rax, Method::const_offset()));
  __ lea(rsi, Address(rsi, rbx, Address::times_1,
                      ConstMethod::codes_offset()));
  __ dispatch_next(vtos);
}
void TemplateTable::wide_ret() {
  transition(vtos, vtos);
  locals_index_wide(rbx);
  __ movptr(rbx, iaddress(rbx));                   // get return bci, compute return bcp
  __ profile_ret(rbx, rcx);
  __ get_method(rax);
  __ movptr(rsi, Address(rax, Method::const_offset()));
  __ lea(rsi, Address(rsi, rbx, Address::times_1, ConstMethod::codes_offset()));
  __ dispatch_next(vtos);
}
void TemplateTable::tableswitch() {
  Label default_case, continue_execution;
  transition(itos, vtos);
  __ lea(rbx, at_bcp(wordSize));
  __ andptr(rbx, -wordSize);
  __ movl(rcx, Address(rbx, 1 * wordSize));
  __ movl(rdx, Address(rbx, 2 * wordSize));
  __ bswapl(rcx);
  __ bswapl(rdx);
  __ cmpl(rax, rcx);
  __ jccb(Assembler::less, default_case);
  __ cmpl(rax, rdx);
  __ jccb(Assembler::greater, default_case);
  __ subl(rax, rcx);
  __ movl(rdx, Address(rbx, rax, Address::times_4, 3 * BytesPerInt));
  __ profile_switch_case(rax, rbx, rcx);
  __ bind(continue_execution);
  __ bswapl(rdx);
  __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1));
  __ addptr(rsi, rdx);
  __ dispatch_only(vtos);
  __ bind(default_case);
  __ profile_switch_default(rax);
  __ movl(rdx, Address(rbx, 0));
  __ jmp(continue_execution);
}
void TemplateTable::lookupswitch() {
  transition(itos, itos);
  __ stop("lookupswitch bytecode should have been rewritten");
}
void TemplateTable::fast_linearswitch() {
  transition(itos, vtos);
  Label loop_entry, loop, found, continue_execution;
  __ bswapl(rax);
  __ lea(rbx, at_bcp(wordSize));                // btw: should be able to get rid of this instruction (change offsets below)
  __ andptr(rbx, -wordSize);
  __ movl(rcx, Address(rbx, wordSize));
  __ bswapl(rcx);
  __ jmpb(loop_entry);
  __ bind(loop);
  __ cmpl(rax, Address(rbx, rcx, Address::times_8, 2 * wordSize));
  __ jccb(Assembler::equal, found);
  __ bind(loop_entry);
  __ decrementl(rcx);
  __ jcc(Assembler::greaterEqual, loop);
  __ profile_switch_default(rax);
  __ movl(rdx, Address(rbx, 0));
  __ jmpb(continue_execution);
  __ bind(found);
  __ movl(rdx, Address(rbx, rcx, Address::times_8, 3 * wordSize));
  __ profile_switch_case(rcx, rax, rbx);
  __ bind(continue_execution);
  __ bswapl(rdx);
  __ load_unsigned_byte(rbx, Address(rsi, rdx, Address::times_1));
  __ addptr(rsi, rdx);
  __ dispatch_only(vtos);
}
void TemplateTable::fast_binaryswitch() {
  transition(itos, vtos);
  const Register key   = rax;                    // already set (tosca)
  const Register array = rbx;
  const Register i     = rcx;
  const Register j     = rdx;
  const Register h     = rdi;                    // needs to be restored
  const Register temp  = rsi;
  __ save_bcp();
  __ lea(array, at_bcp(3*wordSize));             // btw: should be able to get rid of this instruction (change offsets below)
  __ andptr(array, -wordSize);
  __ xorl(i, i);                                 // i = 0;
  __ movl(j, Address(array, -wordSize));         // j = length(array);
  __ bswapl(j);
  Label entry;
  __ jmp(entry);
  { Label loop;
    __ bind(loop);
    __ leal(h, Address(i, j, Address::times_1)); // h = i + j;
    __ sarl(h, 1);                               // h = (i + j) >> 1;
    __ movl(temp, Address(array, h, Address::times_8, 0*wordSize));
    __ bswapl(temp);
    __ cmpl(key, temp);
    __ cmov32(Assembler::less        , j, h);
    __ cmov32(Assembler::greaterEqual, i, h);
    __ bind(entry);
    __ leal(h, Address(i, 1));                   // i+1
    __ cmpl(h, j);                               // i+1 < j
    __ jcc(Assembler::less, loop);
  }
  Label default_case;
  __ movl(temp, Address(array, i, Address::times_8, 0*wordSize));
  __ bswapl(temp);
  __ cmpl(key, temp);
  __ jcc(Assembler::notEqual, default_case);
  __ movl(j , Address(array, i, Address::times_8, 1*wordSize));
  __ profile_switch_case(i, key, array);
  __ bswapl(j);
  LP64_ONLY(__ movslq(j, j));
  __ restore_bcp();
  __ restore_locals();                           // restore rdi
  __ load_unsigned_byte(rbx, Address(rsi, j, Address::times_1));
  __ addptr(rsi, j);
  __ dispatch_only(vtos);
  __ bind(default_case);
  __ profile_switch_default(i);
  __ movl(j, Address(array, -2*wordSize));
  __ bswapl(j);
  LP64_ONLY(__ movslq(j, j));
  __ restore_bcp();
  __ restore_locals();                           // restore rdi
  __ load_unsigned_byte(rbx, Address(rsi, j, Address::times_1));
  __ addptr(rsi, j);
  __ dispatch_only(vtos);
}
void TemplateTable::_return(TosState state) {
  transition(state, state);
  assert(_desc->calls_vm(), "inconsistent calls_vm information"); // call in remove_activation
  if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
    assert(state == vtos, "only valid state");
    __ movptr(rax, aaddress(0));
    __ load_klass(rdi, rax);
    __ movl(rdi, Address(rdi, Klass::access_flags_offset()));
    __ testl(rdi, JVM_ACC_HAS_FINALIZER);
    Label skip_register_finalizer;
    __ jcc(Assembler::zero, skip_register_finalizer);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), rax);
    __ bind(skip_register_finalizer);
  }
  if (state == itos) {
    __ narrow(rax);
  }
  __ remove_activation(state, rsi);
  __ jmp(rsi);
}
void TemplateTable::volatile_barrier(Assembler::Membar_mask_bits order_constraint ) {
  if( !os::is_MP() ) return;    // Not needed on single CPU
  __ membar(order_constraint);
}
void TemplateTable::resolve_cache_and_index(int byte_no,
                                            Register Rcache,
                                            Register index,
                                            size_t index_size) {
  const Register temp = rbx;
  assert_different_registers(Rcache, index, temp);
  Label resolved;
    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
    __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
    __ cmpl(temp, (int) bytecode());  // have we resolved this bytecode?
    __ jcc(Assembler::equal, resolved);
  address entry;
  switch (bytecode()) {
    case Bytecodes::_getstatic      : // fall through
    case Bytecodes::_putstatic      : // fall through
    case Bytecodes::_getfield       : // fall through
    case Bytecodes::_putfield       : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put);        break;
    case Bytecodes::_invokevirtual  : // fall through
    case Bytecodes::_invokespecial  : // fall through
    case Bytecodes::_invokestatic   : // fall through
    case Bytecodes::_invokeinterface: entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);         break;
    case Bytecodes::_invokehandle   : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);   break;
    case Bytecodes::_invokedynamic  : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);  break;
    default:
      fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
      break;
  }
  __ movl(temp, (int)bytecode());
  __ call_VM(noreg, entry, temp);
  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
  __ bind(resolved);
}
void TemplateTable::load_field_cp_cache_entry(Register obj,
                                              Register cache,
                                              Register index,
                                              Register off,
                                              Register flags,
                                              bool is_static = false) {
  assert_different_registers(cache, index, flags, off);
  ByteSize cp_base_offset = ConstantPoolCache::base_offset();
  __ movptr(off, Address(cache, index, Address::times_ptr,
                         in_bytes(cp_base_offset + ConstantPoolCacheEntry::f2_offset())));
  __ movl(flags, Address(cache, index, Address::times_ptr,
           in_bytes(cp_base_offset + ConstantPoolCacheEntry::flags_offset())));
  if (is_static) {
    __ movptr(obj, Address(cache, index, Address::times_ptr,
                           in_bytes(cp_base_offset + ConstantPoolCacheEntry::f1_offset())));
    const int mirror_offset = in_bytes(Klass::java_mirror_offset());
    __ movptr(obj, Address(obj, mirror_offset));
  }
}
void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
                                               Register method,
                                               Register itable_index,
                                               Register flags,
                                               bool is_invokevirtual,
                                               bool is_invokevfinal, /*unused*/
                                               bool is_invokedynamic) {
  const Register cache = rcx;
  const Register index = rdx;
  assert_different_registers(method, flags);
  assert_different_registers(method, cache, index);
  assert_different_registers(itable_index, flags);
  assert_different_registers(itable_index, cache, index);
  assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant");
  const int method_offset = in_bytes(
    ConstantPoolCache::base_offset() +
      ((byte_no == f2_byte)
       ? ConstantPoolCacheEntry::f2_offset()
       : ConstantPoolCacheEntry::f1_offset()));
  const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +
                                    ConstantPoolCacheEntry::flags_offset());
  const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
                                    ConstantPoolCacheEntry::f2_offset());
  size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
  resolve_cache_and_index(byte_no, cache, index, index_size);
    __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
  if (itable_index != noreg) {
    __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset));
  }
  __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
}
void TemplateTable::jvmti_post_field_access(Register cache,
                                            Register index,
                                            bool is_static,
                                            bool has_tos) {
  if (JvmtiExport::can_post_field_access()) {
    Label L1;
    assert_different_registers(cache, index, rax);
    __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr()));
    __ testl(rax,rax);
    __ jcc(Assembler::zero, L1);
    __ addptr(cache, in_bytes(ConstantPoolCache::base_offset()));
    __ shll(index, LogBytesPerWord);
    __ addptr(cache, index);
    if (is_static) {
      __ xorptr(rax, rax);      // NULL object reference
    } else {
      __ pop(atos);         // Get the object
      __ verify_oop(rax);
      __ push(atos);        // Restore stack state
    }
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access),
               rax, cache);
    __ get_cache_and_index_at_bcp(cache, index, 1);
    __ bind(L1);
  }
}
void TemplateTable::pop_and_check_object(Register r) {
  __ pop_ptr(r);
  __ null_check(r);  // for field access must check obj.
  __ verify_oop(r);
}
void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
  transition(vtos, vtos);
  const Register cache = rcx;
  const Register index = rdx;
  const Register obj   = rcx;
  const Register off   = rbx;
  const Register flags = rax;
  resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
  jvmti_post_field_access(cache, index, is_static, false);
  load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
  if (!is_static) pop_and_check_object(obj);
  const Address lo(obj, off, Address::times_1, 0*wordSize);
  const Address hi(obj, off, Address::times_1, 1*wordSize);
  Label Done, notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  assert(btos == 0, "change code, btos != 0");
  __ andptr(flags, ConstantPoolCacheEntry::tos_state_mask);
  __ jcc(Assembler::notZero, notByte);
  __ load_signed_byte(rax, lo );
  __ push(btos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_bgetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notByte);
  __ cmpl(flags, ztos);
  __ jcc(Assembler::notEqual, notBool);
  __ load_signed_byte(rax, lo);
  __ push(ztos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_bgetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notBool);
  __ cmpl(flags, itos );
  __ jcc(Assembler::notEqual, notInt);
  __ movl(rax, lo );
  __ push(itos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_igetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notInt);
  __ cmpl(flags, atos );
  __ jcc(Assembler::notEqual, notObj);
  __ movl(rax, lo );
  __ push(atos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_agetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notObj);
  __ cmpl(flags, ctos );
  __ jcc(Assembler::notEqual, notChar);
  __ load_unsigned_short(rax, lo );
  __ push(ctos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_cgetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notChar);
  __ cmpl(flags, stos );
  __ jcc(Assembler::notEqual, notShort);
  __ load_signed_short(rax, lo );
  __ push(stos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_sgetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notShort);
  __ cmpl(flags, ltos );
  __ jcc(Assembler::notEqual, notLong);
  __ fild_d(lo);                // Must load atomically
  __ subptr(rsp,2*wordSize);    // Make space for store
  __ fistp_d(Address(rsp,0));
  __ pop(rax);
  __ pop(rdx);
  __ push(ltos);
  __ jmp(Done);
  __ bind(notLong);
  __ cmpl(flags, ftos );
  __ jcc(Assembler::notEqual, notFloat);
  __ fld_s(lo);
  __ push(ftos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_fgetfield, rcx, rbx);
  }
  __ jmp(Done);
  __ bind(notFloat);
  __ cmpl(flags, dtos );
  __ jcc(Assembler::notEqual, notDouble);
  __ fld_d(lo);
  __ push(dtos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_dgetfield, rcx, rbx);
  }
  __ jmpb(Done);
  __ bind(notDouble);
  __ stop("Bad state");
  __ bind(Done);
}
void TemplateTable::getfield(int byte_no) {
  getfield_or_static(byte_no, false);
}
void TemplateTable::getstatic(int byte_no) {
  getfield_or_static(byte_no, true);
}
void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) {
  ByteSize cp_base_offset = ConstantPoolCache::base_offset();
  if (JvmtiExport::can_post_field_modification()) {
    Label L1;
    assert_different_registers(cache, index, rax);
    __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
    __ testl(rax, rax);
    __ jcc(Assembler::zero, L1);
    __ get_cache_and_index_at_bcp(rax, rdx, 1);
    if (is_static) {
      __ xorptr(rbx, rbx);
    } else {
      Label two_word, valsize_known;
      __ movl(rcx, Address(rax, rdx, Address::times_ptr, in_bytes(cp_base_offset +
                                   ConstantPoolCacheEntry::flags_offset())));
      __ mov(rbx, rsp);
      __ shrl(rcx, ConstantPoolCacheEntry::tos_state_shift);
      ConstantPoolCacheEntry::verify_tos_state_shift();
      __ cmpl(rcx, ltos);
      __ jccb(Assembler::equal, two_word);
      __ cmpl(rcx, dtos);
      __ jccb(Assembler::equal, two_word);
      __ addptr(rbx, Interpreter::expr_offset_in_bytes(1)); // one word jvalue (not ltos, dtos)
      __ jmpb(valsize_known);
      __ bind(two_word);
      __ addptr(rbx, Interpreter::expr_offset_in_bytes(2)); // two words jvalue
      __ bind(valsize_known);
      __ movptr(rbx, Address(rbx, 0));
    }
    __ addptr(rax, in_bytes(cp_base_offset));
    __ shll(rdx, LogBytesPerWord);
    __ addptr(rax, rdx);
    __ mov(rcx, rsp);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification),
               rbx, rax, rcx);
    __ get_cache_and_index_at_bcp(cache, index, 1);
    __ bind(L1);
  }
}
void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
  transition(vtos, vtos);
  const Register cache = rcx;
  const Register index = rdx;
  const Register obj   = rcx;
  const Register off   = rbx;
  const Register flags = rax;
  resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
  jvmti_post_field_mod(cache, index, is_static);
  load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
  Label notVolatile, Done;
  __ movl(rdx, flags);
  __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift);
  __ andl(rdx, 0x1);
  const Address lo(obj, off, Address::times_1, 0*wordSize);
  const Address hi(obj, off, Address::times_1, 1*wordSize);
  Label notByte, notBool, notInt, notShort, notChar, notLong, notFloat, notObj, notDouble;
  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  assert(btos == 0, "change code, btos != 0");
  __ andl(flags, ConstantPoolCacheEntry::tos_state_mask);
  __ jcc(Assembler::notZero, notByte);
  {
    __ pop(btos);
    if (!is_static) pop_and_check_object(obj);
    __ movb(lo, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_bputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notByte);
  __ cmpl(flags, ztos);
  __ jcc(Assembler::notEqual, notBool);
  {
    __ pop(ztos);
    if (!is_static) pop_and_check_object(obj);
    __ andl(rax, 0x1);
    __ movb(lo, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_zputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notBool);
  __ cmpl(flags, itos);
  __ jcc(Assembler::notEqual, notInt);
  {
    __ pop(itos);
    if (!is_static) pop_and_check_object(obj);
    __ movl(lo, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_iputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notInt);
  __ cmpl(flags, atos);
  __ jcc(Assembler::notEqual, notObj);
  {
    __ pop(atos);
    if (!is_static) pop_and_check_object(obj);
    do_oop_store(_masm, lo, rax, _bs->kind(), false);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notObj);
  __ cmpl(flags, ctos);
  __ jcc(Assembler::notEqual, notChar);
  {
    __ pop(ctos);
    if (!is_static) pop_and_check_object(obj);
    __ movw(lo, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_cputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notChar);
  __ cmpl(flags, stos);
  __ jcc(Assembler::notEqual, notShort);
  {
    __ pop(stos);
    if (!is_static) pop_and_check_object(obj);
    __ movw(lo, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_sputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notShort);
  __ cmpl(flags, ltos);
  __ jcc(Assembler::notEqual, notLong);
  {
    Label notVolatileLong;
    __ testl(rdx, rdx);
    __ jcc(Assembler::zero, notVolatileLong);
    __ pop(ltos);  // overwrites rdx, do this after testing volatile.
    if (!is_static) pop_and_check_object(obj);
    __ push(rdx);
    __ push(rax);                 // Must update atomically with FIST
    __ fild_d(Address(rsp,0));    // So load into FPU register
    __ fistp_d(lo);               // and put into memory atomically
    __ addptr(rsp, 2*wordSize);
    volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
                                                 Assembler::StoreStore));
    __ jmp(notVolatile);
    __ bind(notVolatileLong);
    __ pop(ltos);  // overwrites rdx
    if (!is_static) pop_and_check_object(obj);
    NOT_LP64(__ movptr(hi, rdx));
    __ movptr(lo, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_lputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(notVolatile);
  }
  __ bind(notLong);
  __ cmpl(flags, ftos);
  __ jcc(Assembler::notEqual, notFloat);
  {
    __ pop(ftos);
    if (!is_static) pop_and_check_object(obj);
    __ fstp_s(lo);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_fputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notFloat);
#ifdef ASSERT
  __ cmpl(flags, dtos);
  __ jcc(Assembler::notEqual, notDouble);
#endif
  {
    __ pop(dtos);
    if (!is_static) pop_and_check_object(obj);
    __ fstp_d(lo);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_dputfield, rcx, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
#ifdef ASSERT
  __ bind(notDouble);
  __ stop("Bad state");
#endif
  __ bind(Done);
  __ testl(rdx, rdx);
  __ jcc(Assembler::zero, notVolatile);
  volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
                                               Assembler::StoreStore));
  __ bind(notVolatile);
}
void TemplateTable::putfield(int byte_no) {
  putfield_or_static(byte_no, false);
}
void TemplateTable::putstatic(int byte_no) {
  putfield_or_static(byte_no, true);
}
void TemplateTable::jvmti_post_fast_field_mod() {
  if (JvmtiExport::can_post_field_modification()) {
    Label L2;
     __ mov32(rcx, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
     __ testl(rcx,rcx);
     __ jcc(Assembler::zero, L2);
     __ pop_ptr(rbx);               // copy the object pointer from tos
     __ verify_oop(rbx);
     __ push_ptr(rbx);              // put the object pointer back on tos
     switch (bytecode()) {          // load values into the jvalue object
     case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
     case Bytecodes::_fast_bputfield: // fall through
     case Bytecodes::_fast_zputfield: // fall through
     case Bytecodes::_fast_sputfield: // fall through
     case Bytecodes::_fast_cputfield: // fall through
     case Bytecodes::_fast_iputfield: __ push_i(rax); break;
     case Bytecodes::_fast_dputfield: __ push_d(); break;
     case Bytecodes::_fast_fputfield: __ push_f(); break;
     case Bytecodes::_fast_lputfield: __ push_l(rax); break;
     default:
       ShouldNotReachHere();
     }
     __ mov(rcx, rsp);              // points to jvalue on the stack
     __ get_cache_entry_pointer_at_bcp(rax, rdx, 1);
     __ verify_oop(rbx);
     __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_modification), rbx, rax, rcx);
     switch (bytecode()) {             // restore tos values
     case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
     case Bytecodes::_fast_bputfield: // fall through
     case Bytecodes::_fast_zputfield: // fall through
     case Bytecodes::_fast_sputfield: // fall through
     case Bytecodes::_fast_cputfield: // fall through
     case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
     case Bytecodes::_fast_dputfield: __ pop_d(); break;
     case Bytecodes::_fast_fputfield: __ pop_f(); break;
     case Bytecodes::_fast_lputfield: __ pop_l(rax); break;
     }
     __ bind(L2);
  }
}
void TemplateTable::fast_storefield(TosState state) {
  transition(state, vtos);
  ByteSize base = ConstantPoolCache::base_offset();
  jvmti_post_fast_field_mod();
  __ get_cache_and_index_at_bcp(rcx, rbx, 1);
  if (bytecode() == Bytecodes::_fast_lputfield) __ push(rdx);
  __ movl(rdx, Address(rcx, rbx, Address::times_ptr, in_bytes(base +
                       ConstantPoolCacheEntry::flags_offset())));
  __ movptr(rbx, Address(rcx, rbx, Address::times_ptr, in_bytes(base + ConstantPoolCacheEntry::f2_offset())));
  Label notVolatile, Done;
  __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift);
  __ andl(rdx, 0x1);
  __ testl(rdx, rdx);
  __ jcc(Assembler::zero, notVolatile);
  if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx);
  pop_and_check_object(rcx);
  const Address lo(rcx, rbx, Address::times_1, 0*wordSize);
  const Address hi(rcx, rbx, Address::times_1, 1*wordSize);
  switch (bytecode()) {
    case Bytecodes::_fast_zputfield: __ andl(rax, 0x1);  // boolean is true if LSB is 1
    case Bytecodes::_fast_bputfield: __ movb(lo, rax); break;
    case Bytecodes::_fast_sputfield: // fall through
    case Bytecodes::_fast_cputfield: __ movw(lo, rax); break;
    case Bytecodes::_fast_iputfield: __ movl(lo, rax); break;
    case Bytecodes::_fast_lputfield:
      NOT_LP64(__ movptr(hi, rdx));
      __ movptr(lo, rax);
      break;
    case Bytecodes::_fast_fputfield: __ fstp_s(lo); break;
    case Bytecodes::_fast_dputfield: __ fstp_d(lo); break;
    case Bytecodes::_fast_aputfield: {
      do_oop_store(_masm, lo, rax, _bs->kind(), false);
      break;
    }
    default:
      ShouldNotReachHere();
  }
  Label done;
  volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
                                               Assembler::StoreStore));
  __ jmp(done);
  __ bind(notVolatile);
  if (bytecode() == Bytecodes::_fast_lputfield) __ pop(rdx);
  pop_and_check_object(rcx);
  switch (bytecode()) {
    case Bytecodes::_fast_zputfield: __ andl(rax, 0x1);  // boolean is true if LSB is 1
    case Bytecodes::_fast_bputfield: __ movb(lo, rax); break;
    case Bytecodes::_fast_sputfield: // fall through
    case Bytecodes::_fast_cputfield: __ movw(lo, rax); break;
    case Bytecodes::_fast_iputfield: __ movl(lo, rax); break;
    case Bytecodes::_fast_lputfield:
      NOT_LP64(__ movptr(hi, rdx));
      __ movptr(lo, rax);
      break;
    case Bytecodes::_fast_fputfield: __ fstp_s(lo); break;
    case Bytecodes::_fast_dputfield: __ fstp_d(lo); break;
    case Bytecodes::_fast_aputfield: {
      do_oop_store(_masm, lo, rax, _bs->kind(), false);
      break;
    }
    default:
      ShouldNotReachHere();
  }
  __ bind(done);
}
void TemplateTable::fast_accessfield(TosState state) {
  transition(atos, state);
  if (JvmtiExport::can_post_field_access()) {
    Label L1;
    __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr()));
    __ testl(rcx,rcx);
    __ jcc(Assembler::zero, L1);
    __ get_cache_entry_pointer_at_bcp(rcx, rdx, 1);
    __ push_ptr(rax);  // save object pointer before call_VM() clobbers it
    __ verify_oop(rax);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::post_field_access), rax, rcx);
    __ pop_ptr(rax);   // restore object pointer
    __ bind(L1);
  }
  __ get_cache_and_index_at_bcp(rcx, rbx, 1);
  __ movptr(rbx, Address(rcx,
                         rbx,
                         Address::times_ptr,
                         in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())));
  __ verify_oop(rax);
  __ null_check(rax);
  const Address lo = Address(rax, rbx, Address::times_1, 0*wordSize);
  const Address hi = Address(rax, rbx, Address::times_1, 1*wordSize);
  switch (bytecode()) {
    case Bytecodes::_fast_bgetfield: __ movsbl(rax, lo );                 break;
    case Bytecodes::_fast_sgetfield: __ load_signed_short(rax, lo );      break;
    case Bytecodes::_fast_cgetfield: __ load_unsigned_short(rax, lo );    break;
    case Bytecodes::_fast_igetfield: __ movl(rax, lo);                    break;
    case Bytecodes::_fast_lgetfield: __ stop("should not be rewritten");  break;
    case Bytecodes::_fast_fgetfield: __ fld_s(lo);                        break;
    case Bytecodes::_fast_dgetfield: __ fld_d(lo);                        break;
    case Bytecodes::_fast_agetfield: __ movptr(rax, lo); __ verify_oop(rax); break;
    default:
      ShouldNotReachHere();
  }
}
void TemplateTable::fast_xaccess(TosState state) {
  transition(vtos, state);
  __ movptr(rax, aaddress(0));
  __ get_cache_and_index_at_bcp(rcx, rdx, 2);
  __ movptr(rbx, Address(rcx,
                         rdx,
                         Address::times_ptr,
                         in_bytes(ConstantPoolCache::base_offset() + ConstantPoolCacheEntry::f2_offset())));
  __ increment(rsi);
  __ null_check(rax);
  const Address lo = Address(rax, rbx, Address::times_1, 0*wordSize);
  if (state == itos) {
    __ movl(rax, lo);
  } else if (state == atos) {
    __ movptr(rax, lo);
    __ verify_oop(rax);
  } else if (state == ftos) {
    __ fld_s(lo);
  } else {
    ShouldNotReachHere();
  }
  __ decrement(rsi);
}
void TemplateTable::count_calls(Register method, Register temp) {
  ShouldNotReachHere();
}
void TemplateTable::prepare_invoke(int byte_no,
                                   Register method,  // linked method (or i-klass)
                                   Register index,   // itable index, MethodType, etc.
                                   Register recv,    // if caller wants to see it
                                   Register flags    // if caller wants to test it
                                   ) {
  const Bytecodes::Code code = bytecode();
  const bool is_invokeinterface  = code == Bytecodes::_invokeinterface;
  const bool is_invokedynamic    = code == Bytecodes::_invokedynamic;
  const bool is_invokehandle     = code == Bytecodes::_invokehandle;
  const bool is_invokevirtual    = code == Bytecodes::_invokevirtual;
  const bool is_invokespecial    = code == Bytecodes::_invokespecial;
  const bool load_receiver       = (recv  != noreg);
  const bool save_flags          = (flags != noreg);
  assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), "");
  assert(save_flags    == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");
  assert(flags == noreg || flags == rdx, "");
  assert(recv  == noreg || recv  == rcx, "");
  if (recv  == noreg)  recv  = rcx;
  if (flags == noreg)  flags = rdx;
  assert_different_registers(method, index, recv, flags);
  __ save_bcp();
  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
  if (is_invokedynamic || is_invokehandle) {
    Label L_no_push;
    __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift));
    __ jccb(Assembler::zero, L_no_push);
    __ push(rbx);
    __ mov(rbx, index);
    assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
    __ load_resolved_reference_at_index(index, rbx);
    __ pop(rbx);
    __ push(index);  // push appendix (MethodType, CallSite, etc.)
    __ bind(L_no_push);
  }
  if (load_receiver) {
    __ movl(recv, flags);
    __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);
    const int no_return_pc_pushed_yet = -1;  // argument slot correction before we push return address
    const int receiver_is_at_end      = -1;  // back off one slot to get receiver
    Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);
    __ movptr(recv, recv_addr);
    __ verify_oop(recv);
  }
  if (save_flags) {
    __ mov(rsi, flags);
  }
  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  ConstantPoolCacheEntry::verify_tos_state_shift();
  {
    const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
    ExternalAddress table(table_addr);
    __ movptr(flags, ArrayAddress(table, Address(noreg, flags, Address::times_ptr)));
  }
  __ push(flags);
  if (save_flags) {
    __ mov(flags, rsi);
    __ restore_bcp();
  }
}
void TemplateTable::invokevirtual_helper(Register index,
                                         Register recv,
                                         Register flags) {
  assert_different_registers(index, recv, rax, rdx);
  assert(index == rbx, "");
  assert(recv  == rcx, "");
  Label notFinal;
  __ movl(rax, flags);
  __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift));
  __ jcc(Assembler::zero, notFinal);
  const Register method = index;  // method must be rbx
  assert(method == rbx,
         "Method* must be rbx for interpreter calling convention");
  __ null_check(recv);
  __ profile_final_call(rax);
  __ profile_arguments_type(rax, method, rsi, true);
  __ jump_from_interpreted(method, rax);
  __ bind(notFinal);
  __ null_check(recv, oopDesc::klass_offset_in_bytes());
  __ load_klass(rax, recv);
  __ profile_virtual_call(rax, rdi, rdx);
  __ lookup_virtual_method(rax, index, method);
  __ profile_arguments_type(rdx, method, rsi, true);
  __ jump_from_interpreted(method, rdx);
}
void TemplateTable::invokevirtual(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f2_byte, "use this argument");
  prepare_invoke(byte_no,
                 rbx,    // method or vtable index
                 noreg,  // unused itable index
                 rcx, rdx); // recv, flags
  invokevirtual_helper(rbx, rcx, rdx);
}
void TemplateTable::invokespecial(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  prepare_invoke(byte_no, rbx, noreg,  // get f1 Method*
                 rcx);  // get receiver also for null check
  __ verify_oop(rcx);
  __ null_check(rcx);
  __ profile_call(rax);
  __ profile_arguments_type(rax, rbx, rsi, false);
  __ jump_from_interpreted(rbx, rax);
}
void TemplateTable::invokestatic(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  prepare_invoke(byte_no, rbx);  // get f1 Method*
  __ profile_call(rax);
  __ profile_arguments_type(rax, rbx, rsi, false);
  __ jump_from_interpreted(rbx, rax);
}
void TemplateTable::fast_invokevfinal(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f2_byte, "use this argument");
  __ stop("fast_invokevfinal not used on x86");
}
void TemplateTable::invokeinterface(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  prepare_invoke(byte_no, rax, rbx,  // get f1 Klass*, f2 Method*
                 rcx, rdx); // recv, flags
  Label notMethod;
  __ movl(rdi, rdx);
  __ andl(rdi, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift));
  __ jcc(Assembler::zero, notMethod);
  invokevirtual_helper(rbx, rcx, rdx);
  __ bind(notMethod);
  __ restore_locals();  // restore rdi
  __ null_check(rcx, oopDesc::klass_offset_in_bytes());
  __ load_klass(rdx, rcx);
  Label no_such_interface, no_such_method;
  __ lookup_interface_method(// inputs: rec. class, interface, itable index
                             rdx, rax, noreg,
                             rsi, rdi,
                             no_such_interface,
  __ restore_bcp(); // rbcp was destroyed by receiver type check
  __ profile_virtual_call(rdx, rsi, rdi);
  __ movptr(rax, Address(rbx, Method::const_offset()));
  __ movptr(rax, Address(rax, ConstMethod::constants_offset()));
  __ movptr(rax, Address(rax, ConstantPool::pool_holder_offset_in_bytes()));
  __ movl(rbx, Address(rbx, Method::itable_index_offset()));
  __ subl(rbx, Method::itable_index_max);
  __ negl(rbx);
  __ lookup_interface_method(// inputs: rec. class, interface, itable index
                             rdx, rax, rbx,
                             rbx, rsi,
                             no_such_interface);
  __ testptr(rbx, rbx);
  __ jcc(Assembler::zero, no_such_method);
  __ profile_arguments_type(rdx, rbx, rsi, true);
  __ jump_from_interpreted(rbx, rdx);
  __ should_not_reach_here();
  __ bind(no_such_method);
  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
  __ should_not_reach_here();
  __ bind(no_such_interface);
  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  __ restore_bcp();      // rsi must be correct for exception handler   (was destroyed)
  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                   InterpreterRuntime::throw_IncompatibleClassChangeError));
  __ should_not_reach_here();
}
void TemplateTable::invokehandle(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  const Register rbx_method = rbx;
  const Register rax_mtype  = rax;
  const Register rcx_recv   = rcx;
  const Register rdx_flags  = rdx;
  if (!EnableInvokeDynamic) {
    __ should_not_reach_here();
    return;
  }
  prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv);
  __ verify_method_ptr(rbx_method);
  __ verify_oop(rcx_recv);
  __ null_check(rcx_recv);
  __ profile_final_call(rax);
  __ profile_arguments_type(rdx, rbx_method, rsi, true);
  __ jump_from_interpreted(rbx_method, rdx);
}
void TemplateTable::invokedynamic(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  if (!EnableInvokeDynamic) {
    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                     InterpreterRuntime::throw_IncompatibleClassChangeError));
    __ should_not_reach_here();
    return;
  }
  const Register rbx_method   = rbx;
  const Register rax_callsite = rax;
  prepare_invoke(byte_no, rbx_method, rax_callsite);
  __ profile_call(rsi);
  __ profile_arguments_type(rdx, rbx, rsi, false);
  __ verify_oop(rax_callsite);
  __ jump_from_interpreted(rbx_method, rdx);
}
void TemplateTable::_new() {
  transition(vtos, atos);
  __ get_unsigned_2_byte_index_at_bcp(rdx, 1);
  Label slow_case;
  Label slow_case_no_pop;
  Label done;
  Label initialize_header;
  Label initialize_object;  // including clearing the fields
  Label allocate_shared;
  __ get_cpool_and_tags(rcx, rax);
  const int tags_offset = Array<u1>::base_offset_in_bytes();
  __ cmpb(Address(rax, rdx, Address::times_1, tags_offset), JVM_CONSTANT_Class);
  __ jcc(Assembler::notEqual, slow_case_no_pop);
  __ movptr(rcx, Address(rcx, rdx, Address::times_ptr, sizeof(ConstantPool)));
  __ push(rcx);  // save the contexts of klass for initializing the header
  __ cmpb(Address(rcx, InstanceKlass::init_state_offset()), InstanceKlass::fully_initialized);
  __ jcc(Assembler::notEqual, slow_case);
  __ movl(rdx, Address(rcx, Klass::layout_helper_offset()));
  __ testl(rdx, Klass::_lh_instance_slow_path_bit);
  __ jcc(Assembler::notZero, slow_case);
  const bool allow_shared_alloc =
    Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode;
  const Register thread = rcx;
  if (UseTLAB || allow_shared_alloc) {
    __ get_thread(thread);
  }
  if (UseTLAB) {
    __ movptr(rax, Address(thread, in_bytes(JavaThread::tlab_top_offset())));
    __ lea(rbx, Address(rax, rdx, Address::times_1));
    __ cmpptr(rbx, Address(thread, in_bytes(JavaThread::tlab_end_offset())));
    __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case);
    __ movptr(Address(thread, in_bytes(JavaThread::tlab_top_offset())), rbx);
    if (ZeroTLAB) {
      __ jmp(initialize_header);
    } else {
      __ jmp(initialize_object);
    }
  }
  if (allow_shared_alloc) {
    __ bind(allocate_shared);
    ExternalAddress heap_top((address)Universe::heap()->top_addr());
    Label retry;
    __ bind(retry);
    __ movptr(rax, heap_top);
    __ lea(rbx, Address(rax, rdx, Address::times_1));
    __ cmpptr(rbx, ExternalAddress((address)Universe::heap()->end_addr()));
    __ jcc(Assembler::above, slow_case);
    __ locked_cmpxchgptr(rbx, heap_top);
    __ jcc(Assembler::notEqual, retry);
    __ incr_allocated_bytes(thread, rdx, 0);
  }
  if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
    __ bind(initialize_object);
    __ decrement(rdx, sizeof(oopDesc));
    __ jcc(Assembler::zero, initialize_header);
    __ xorl(rcx, rcx);    // use zero reg to clear memory (shorter code)
    __ shrl(rdx, LogBytesPerLong); // divide by 2*oopSize and set carry flag if odd
#ifdef ASSERT
    Label L;
    __ jccb(Assembler::carryClear, L);
    __ stop("object size is not multiple of 2 - adjust this code");
    __ bind(L);
#endif
    { Label loop;
    __ bind(loop);
    __ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 1*oopSize), rcx);
    NOT_LP64(__ movptr(Address(rax, rdx, Address::times_8, sizeof(oopDesc) - 2*oopSize), rcx));
    __ decrement(rdx);
    __ jcc(Assembler::notZero, loop);
    }
    __ bind(initialize_header);
    if (UseBiasedLocking) {
      __ pop(rcx);   // get saved klass back in the register.
      __ movptr(rbx, Address(rcx, Klass::prototype_header_offset()));
      __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()), rbx);
    } else {
      __ movptr(Address(rax, oopDesc::mark_offset_in_bytes ()),
                (int32_t)markOopDesc::prototype()); // header
      __ pop(rcx);   // get saved klass back in the register.
    }
    __ store_klass(rax, rcx);  // klass
    {
      SkipIfEqual skip_if(_masm, &DTraceAllocProbes, 0);
      __ push(atos);
      __ call_VM_leaf(
           CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax);
      __ pop(atos);
    }
    __ jmp(done);
  }
  __ bind(slow_case);
  __ pop(rcx);   // restore stack pointer to what it was when we came in.
  __ bind(slow_case_no_pop);
  __ get_constant_pool(rax);
  __ get_unsigned_2_byte_index_at_bcp(rdx, 1);
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), rax, rdx);
  __ bind(done);
}
void TemplateTable::newarray() {
  transition(itos, atos);
  __ push_i(rax);                                 // make sure everything is on the stack
  __ load_unsigned_byte(rdx, at_bcp(1));
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray), rdx, rax);
  __ pop_i(rdx);                                  // discard size
}
void TemplateTable::anewarray() {
  transition(itos, atos);
  __ get_unsigned_2_byte_index_at_bcp(rdx, 1);
  __ get_constant_pool(rcx);
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray), rcx, rdx, rax);
}
void TemplateTable::arraylength() {
  transition(atos, itos);
  __ null_check(rax, arrayOopDesc::length_offset_in_bytes());
  __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes()));
}
void TemplateTable::checkcast() {
  transition(atos, atos);
  Label done, is_null, ok_is_subtype, quicked, resolved;
  __ testptr(rax, rax);   // Object is in EAX
  __ jcc(Assembler::zero, is_null);
  __ get_cpool_and_tags(rcx, rdx); // ECX=cpool, EDX=tags array
  __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // EBX=index
  __ cmpb(Address(rdx, rbx, Address::times_1, Array<u1>::base_offset_in_bytes()), JVM_CONSTANT_Class);
  __ jcc(Assembler::equal, quicked);
  __ push(atos);
  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
  __ get_thread(rdi);
  __ get_vm_result_2(rax, rdi);
  __ restore_locals();
  __ pop_ptr(rdx);
  __ jmpb(resolved);
  __ bind(quicked);
  __ mov(rdx, rax);          // Save object in EDX; EAX needed for subtype check
  __ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(ConstantPool)));
  __ bind(resolved);
  __ load_klass(rbx, rdx);
  __ gen_subtype_check( rbx, ok_is_subtype );
  __ push(rdx);
  __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry));
  __ bind(ok_is_subtype);
  __ mov(rax,rdx);           // Restore object in EDX
  if (ProfileInterpreter) {
    __ jmp(done);
    __ bind(is_null);
    __ profile_null_seen(rcx);
  } else {
    __ bind(is_null);   // same as 'done'
  }
  __ bind(done);
}
void TemplateTable::instanceof() {
  transition(atos, itos);
  Label done, is_null, ok_is_subtype, quicked, resolved;
  __ testptr(rax, rax);
  __ jcc(Assembler::zero, is_null);
  __ get_cpool_and_tags(rcx, rdx); // ECX=cpool, EDX=tags array
  __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // EBX=index
  __ cmpb(Address(rdx, rbx, Address::times_1, Array<u1>::base_offset_in_bytes()), JVM_CONSTANT_Class);
  __ jcc(Assembler::equal, quicked);
  __ push(atos);
  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc) );
  __ get_thread(rdi);
  __ get_vm_result_2(rax, rdi);
  __ restore_locals();
  __ pop_ptr(rdx);
  __ load_klass(rdx, rdx);
  __ jmp(resolved);
  __ bind(quicked);
  __ load_klass(rdx, rax);
  __ movptr(rax, Address(rcx, rbx, Address::times_ptr, sizeof(ConstantPool)));
  __ bind(resolved);
  __ gen_subtype_check( rdx, ok_is_subtype );
  __ xorl(rax,rax);
  __ jmpb(done);
  __ bind(ok_is_subtype);
  __ movl(rax, 1);
  if (ProfileInterpreter) {
    __ jmp(done);
    __ bind(is_null);
    __ profile_null_seen(rcx);
  } else {
    __ bind(is_null);   // same as 'done'
  }
  __ bind(done);
}
void TemplateTable::_breakpoint() {
  transition(vtos, vtos);
  __ get_method(rcx);
  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::get_original_bytecode_at), rcx, rsi);
  __ mov(rbx, rax);
  __ get_method(rcx);
  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint), rcx, rsi);
  __ dispatch_only_normal(vtos);
}
void TemplateTable::athrow() {
  transition(atos, vtos);
  __ null_check(rax);
  __ jump(ExternalAddress(Interpreter::throw_exception_entry()));
}
void TemplateTable::monitorenter() {
  transition(atos, vtos);
  __ null_check(rax);
  const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
  const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset        * wordSize);
  const int entry_size =         (     frame::interpreter_frame_monitor_size()           * wordSize);
  Label allocated;
  __ xorl(rdx, rdx);                             // points to free slot or NULL
  { Label entry, loop, exit;
    __ movptr(rcx, monitor_block_top);           // points to current entry, starting with top-most entry
    __ lea(rbx, monitor_block_bot);              // points to word before bottom of monitor block
    __ jmpb(entry);
    __ bind(loop);
    __ cmpptr(Address(rcx, BasicObjectLock::obj_offset_in_bytes()), (int32_t)NULL_WORD);  // check if current entry is used
    __ cmovptr(Assembler::equal, rdx, rcx);      // if not used then remember entry in rdx
    __ cmpptr(rax, Address(rcx, BasicObjectLock::obj_offset_in_bytes()));   // check if current entry is for same object
    __ jccb(Assembler::equal, exit);             // if same object then stop searching
    __ addptr(rcx, entry_size);                  // otherwise advance to next entry
    __ bind(entry);
    __ cmpptr(rcx, rbx);                         // check if bottom reached
    __ jcc(Assembler::notEqual, loop);           // if not at bottom then check this entry
    __ bind(exit);
  }
  __ testptr(rdx, rdx);                          // check if a slot has been found
  __ jccb(Assembler::notZero, allocated);        // if found, continue with that one
  { Label entry, loop;
    __ movptr(rdx, monitor_block_bot);           // rdx: old expression stack bottom
    __ subptr(rsp, entry_size);                  // move expression stack top
    __ subptr(rdx, entry_size);                  // move expression stack bottom
    __ mov(rcx, rsp);                            // set start value for copy loop
    __ movptr(monitor_block_bot, rdx);           // set new monitor block top
    __ jmp(entry);
    __ bind(loop);
    __ movptr(rbx, Address(rcx, entry_size));    // load expression stack word from old location
    __ movptr(Address(rcx, 0), rbx);             // and store it at new location
    __ addptr(rcx, wordSize);                    // advance to next word
    __ bind(entry);
    __ cmpptr(rcx, rdx);                         // check if bottom reached
    __ jcc(Assembler::notEqual, loop);           // if not at bottom then copy next word
  }
  __ bind(allocated);
  __ increment(rsi);
  __ movptr(Address(rdx, BasicObjectLock::obj_offset_in_bytes()), rax);     // store object
  __ lock_object(rdx);
  __ save_bcp();  // in case of exception
  __ generate_stack_overflow_check(0);
  __ dispatch_next(vtos);
}
void TemplateTable::monitorexit() {
  transition(atos, vtos);
  __ null_check(rax);
  const Address monitor_block_top(rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
  const Address monitor_block_bot(rbp, frame::interpreter_frame_initial_sp_offset        * wordSize);
  const int entry_size =         (     frame::interpreter_frame_monitor_size()           * wordSize);
  Label found;
  { Label entry, loop;
    __ movptr(rdx, monitor_block_top);           // points to current entry, starting with top-most entry
    __ lea(rbx, monitor_block_bot);             // points to word before bottom of monitor block
    __ jmpb(entry);
    __ bind(loop);
    __ cmpptr(rax, Address(rdx, BasicObjectLock::obj_offset_in_bytes()));   // check if current entry is for same object
    __ jcc(Assembler::equal, found);             // if same object then stop searching
    __ addptr(rdx, entry_size);                  // otherwise advance to next entry
    __ bind(entry);
    __ cmpptr(rdx, rbx);                         // check if bottom reached
    __ jcc(Assembler::notEqual, loop);           // if not at bottom then check this entry
  }
  Label end;
  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_illegal_monitor_state_exception));
  __ should_not_reach_here();
  __ bind(found);
  __ push_ptr(rax);                                 // make sure object is on stack (contract with oopMaps)
  __ unlock_object(rdx);
  __ pop_ptr(rax);                                  // discard object
  __ bind(end);
}
void TemplateTable::wide() {
  transition(vtos, vtos);
  __ load_unsigned_byte(rbx, at_bcp(1));
  ExternalAddress wtable((address)Interpreter::_wentry_point);
  __ jump(ArrayAddress(wtable, Address(noreg, rbx, Address::times_ptr)));
}
void TemplateTable::multianewarray() {
  transition(vtos, atos);
  __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions
  __ lea(  rax, Address(rsp, rax, Interpreter::stackElementScale(), -wordSize));
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray), rax);     // pass in rax,
  __ load_unsigned_byte(rbx, at_bcp(3));
  __ lea(rsp, Address(rsp, rbx, Interpreter::stackElementScale()));  // get rid of counts
}
#endif /* !CC_INTERP */
C:\hotspot-69087d08d473\src\cpu\x86\vm/templateTable_x86_32.hpp
#ifndef CPU_X86_VM_TEMPLATETABLE_X86_32_HPP
#define CPU_X86_VM_TEMPLATETABLE_X86_32_HPP
  static void prepare_invoke(int byte_no,
                             Register method,         // linked method (or i-klass)
                             Register index = noreg,  // itable index, MethodType, etc.
                             Register recv  = noreg,  // if caller wants to see it
                             Register flags = noreg   // if caller wants to test it
                             );
  static void invokevirtual_helper(Register index, Register recv,
                                   Register flags);
  static void volatile_barrier(Assembler::Membar_mask_bits order_constraint);
  static void index_check(Register array, Register index);
  static void index_check_without_pop(Register array, Register index);
#endif // CPU_X86_VM_TEMPLATETABLE_X86_32_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/templateTable_x86_64.cpp
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/interpreterRuntime.hpp"
#include "interpreter/templateTable.hpp"
#include "memory/universe.inline.hpp"
#include "oops/methodData.hpp"
#include "oops/objArrayKlass.hpp"
#include "oops/oop.inline.hpp"
#include "prims/methodHandles.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "runtime/synchronizer.hpp"
#include "utilities/macros.hpp"
#ifndef CC_INTERP
#define __ _masm->
void TemplateTable::pd_initialize() {
}
static inline Address iaddress(int n) {
  return Address(r14, Interpreter::local_offset_in_bytes(n));
}
static inline Address laddress(int n) {
  return iaddress(n + 1);
}
static inline Address faddress(int n) {
  return iaddress(n);
}
static inline Address daddress(int n) {
  return laddress(n);
}
static inline Address aaddress(int n) {
  return iaddress(n);
}
static inline Address iaddress(Register r) {
  return Address(r14, r, Address::times_8);
}
static inline Address laddress(Register r) {
  return Address(r14, r, Address::times_8, Interpreter::local_offset_in_bytes(1));
}
static inline Address faddress(Register r) {
  return iaddress(r);
}
static inline Address daddress(Register r) {
  return laddress(r);
}
static inline Address aaddress(Register r) {
  return iaddress(r);
}
static inline Address at_rsp() {
  return Address(rsp, 0);
}
static inline Address at_tos   () {
  return Address(rsp,  Interpreter::expr_offset_in_bytes(0));
}
static inline Address at_tos_p1() {
  return Address(rsp,  Interpreter::expr_offset_in_bytes(1));
}
static inline Address at_tos_p2() {
  return Address(rsp,  Interpreter::expr_offset_in_bytes(2));
}
static Assembler::Condition j_not(TemplateTable::Condition cc) {
  switch (cc) {
  case TemplateTable::equal        : return Assembler::notEqual;
  case TemplateTable::not_equal    : return Assembler::equal;
  case TemplateTable::less         : return Assembler::greaterEqual;
  case TemplateTable::less_equal   : return Assembler::greater;
  case TemplateTable::greater      : return Assembler::lessEqual;
  case TemplateTable::greater_equal: return Assembler::less;
  }
  ShouldNotReachHere();
  return Assembler::zero;
}
static void do_oop_store(InterpreterMacroAssembler* _masm,
                         Address obj,
                         Register val,
                         BarrierSet::Name barrier,
                         bool precise) {
  assert(val == noreg || val == rax, "parameter is just for looks");
  switch (barrier) {
#if INCLUDE_ALL_GCS
    case BarrierSet::G1SATBCT:
    case BarrierSet::G1SATBCTLogging:
      {
        if (obj.index() == noreg && obj.disp() == 0) {
          if (obj.base() != rdx) {
            __ movq(rdx, obj.base());
          }
        } else {
          __ leaq(rdx, obj);
        }
        __ g1_write_barrier_pre(rdx /* obj */,
                                rbx /* pre_val */,
                                r15_thread /* thread */,
                                r8  /* tmp */,
                                val != noreg /* tosca_live */,
                                false /* expand_call */);
        if (val == noreg) {
          __ store_heap_oop_null(Address(rdx, 0));
        } else {
          Register new_val = val;
          if (UseCompressedOops) {
            new_val = rbx;
            __ movptr(new_val, val);
          }
          __ store_heap_oop(Address(rdx, 0), val);
          __ g1_write_barrier_post(rdx /* store_adr */,
                                   new_val /* new_val */,
                                   r15_thread /* thread */,
                                   r8 /* tmp */,
                                   rbx /* tmp2 */);
        }
      }
      break;
#endif // INCLUDE_ALL_GCS
    case BarrierSet::CardTableModRef:
    case BarrierSet::CardTableExtension:
      {
        if (val == noreg) {
          __ store_heap_oop_null(obj);
        } else {
          __ store_heap_oop(obj, val);
          if (!precise || (obj.index() == noreg && obj.disp() == 0)) {
            __ store_check(obj.base());
          } else {
            __ leaq(rdx, obj);
            __ store_check(rdx);
          }
        }
      }
      break;
    case BarrierSet::ModRef:
    case BarrierSet::Other:
      if (val == noreg) {
        __ store_heap_oop_null(obj);
      } else {
        __ store_heap_oop(obj, val);
      }
      break;
    default      :
      ShouldNotReachHere();
  }
}
Address TemplateTable::at_bcp(int offset) {
  assert(_desc->uses_bcp(), "inconsistent uses_bcp information");
  return Address(r13, offset);
}
void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
                                   Register temp_reg, bool load_bc_into_bc_reg/*=true*/,
                                   int byte_no) {
  if (!RewriteBytecodes)  return;
  Label L_patch_done;
  switch (bc) {
  case Bytecodes::_fast_aputfield:
  case Bytecodes::_fast_bputfield:
  case Bytecodes::_fast_zputfield:
  case Bytecodes::_fast_cputfield:
  case Bytecodes::_fast_dputfield:
  case Bytecodes::_fast_fputfield:
  case Bytecodes::_fast_iputfield:
  case Bytecodes::_fast_lputfield:
  case Bytecodes::_fast_sputfield:
    {
      assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
      assert(load_bc_into_bc_reg, "we use bc_reg as temp");
      __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1);
      __ movl(bc_reg, bc);
      __ cmpl(temp_reg, (int) 0);
      __ jcc(Assembler::zero, L_patch_done);  // don't patch
    }
    break;
  default:
    assert(byte_no == -1, "sanity");
    if (load_bc_into_bc_reg) {
      __ movl(bc_reg, bc);
    }
  }
  if (JvmtiExport::can_post_breakpoint()) {
    Label L_fast_patch;
    __ movzbl(temp_reg, at_bcp(0));
    __ cmpl(temp_reg, Bytecodes::_breakpoint);
    __ jcc(Assembler::notEqual, L_fast_patch);
    __ get_method(temp_reg);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, r13, bc_reg);
#ifndef ASSERT
    __ jmpb(L_patch_done);
#else
    __ jmp(L_patch_done);
#endif
    __ bind(L_fast_patch);
  }
#ifdef ASSERT
  Label L_okay;
  __ load_unsigned_byte(temp_reg, at_bcp(0));
  __ cmpl(temp_reg, (int) Bytecodes::java_code(bc));
  __ jcc(Assembler::equal, L_okay);
  __ cmpl(temp_reg, bc_reg);
  __ jcc(Assembler::equal, L_okay);
  __ stop("patching the wrong bytecode");
  __ bind(L_okay);
#endif
  __ movb(at_bcp(0), bc_reg);
  __ bind(L_patch_done);
}
void TemplateTable::nop() {
  transition(vtos, vtos);
}
void TemplateTable::shouldnotreachhere() {
  transition(vtos, vtos);
  __ stop("shouldnotreachhere bytecode");
}
void TemplateTable::aconst_null() {
  transition(vtos, atos);
  __ xorl(rax, rax);
}
void TemplateTable::iconst(int value) {
  transition(vtos, itos);
  if (value == 0) {
    __ xorl(rax, rax);
  } else {
    __ movl(rax, value);
  }
}
void TemplateTable::lconst(int value) {
  transition(vtos, ltos);
  if (value == 0) {
    __ xorl(rax, rax);
  } else {
    __ movl(rax, value);
  }
}
void TemplateTable::fconst(int value) {
  transition(vtos, ftos);
  static float one = 1.0f, two = 2.0f;
  switch (value) {
  case 0:
    __ xorps(xmm0, xmm0);
    break;
  case 1:
    __ movflt(xmm0, ExternalAddress((address) &one));
    break;
  case 2:
    __ movflt(xmm0, ExternalAddress((address) &two));
    break;
  default:
    ShouldNotReachHere();
    break;
  }
}
void TemplateTable::dconst(int value) {
  transition(vtos, dtos);
  static double one = 1.0;
  switch (value) {
  case 0:
    __ xorpd(xmm0, xmm0);
    break;
  case 1:
    __ movdbl(xmm0, ExternalAddress((address) &one));
    break;
  default:
    ShouldNotReachHere();
    break;
  }
}
void TemplateTable::bipush() {
  transition(vtos, itos);
  __ load_signed_byte(rax, at_bcp(1));
}
void TemplateTable::sipush() {
  transition(vtos, itos);
  __ load_unsigned_short(rax, at_bcp(1));
  __ bswapl(rax);
  __ sarl(rax, 16);
}
void TemplateTable::ldc(bool wide) {
  transition(vtos, vtos);
  Label call_ldc, notFloat, notClass, Done;
  if (wide) {
    __ get_unsigned_2_byte_index_at_bcp(rbx, 1);
  } else {
    __ load_unsigned_byte(rbx, at_bcp(1));
  }
  __ get_cpool_and_tags(rcx, rax);
  const int base_offset = ConstantPool::header_size() * wordSize;
  const int tags_offset = Array<u1>::base_offset_in_bytes();
  __ movzbl(rdx, Address(rax, rbx, Address::times_1, tags_offset));
  __ cmpl(rdx, JVM_CONSTANT_UnresolvedClass);
  __ jccb(Assembler::equal, call_ldc);
  __ cmpl(rdx, JVM_CONSTANT_UnresolvedClassInError);
  __ jccb(Assembler::equal, call_ldc);
  __ cmpl(rdx, JVM_CONSTANT_Class);
  __ jcc(Assembler::notEqual, notClass);
  __ bind(call_ldc);
  __ movl(c_rarg1, wide);
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::ldc), c_rarg1);
  __ push_ptr(rax);
  __ verify_oop(rax);
  __ jmp(Done);
  __ bind(notClass);
  __ cmpl(rdx, JVM_CONSTANT_Float);
  __ jccb(Assembler::notEqual, notFloat);
  __ movflt(xmm0, Address(rcx, rbx, Address::times_8, base_offset));
  __ push_f();
  __ jmp(Done);
  __ bind(notFloat);
#ifdef ASSERT
  {
    Label L;
    __ cmpl(rdx, JVM_CONSTANT_Integer);
    __ jcc(Assembler::equal, L);
    __ stop("unexpected tag type in ldc");
    __ bind(L);
  }
#endif
  __ movl(rax, Address(rcx, rbx, Address::times_8, base_offset));
  __ push_i(rax);
  __ bind(Done);
}
void TemplateTable::fast_aldc(bool wide) {
  transition(vtos, atos);
  Register result = rax;
  Register tmp = rdx;
  int index_size = wide ? sizeof(u2) : sizeof(u1);
  Label resolved;
  assert_different_registers(result, tmp);
  __ get_cache_index_at_bcp(tmp, 1, index_size);
  __ load_resolved_reference_at_index(result, tmp);
  __ testl(result, result);
  __ jcc(Assembler::notZero, resolved);
  address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
  __ movl(tmp, (int)bytecode());
  __ call_VM(result, entry, tmp);
  __ bind(resolved);
  if (VerifyOops) {
    __ verify_oop(result);
  }
}
void TemplateTable::ldc2_w() {
  transition(vtos, vtos);
  Label Long, Done;
  __ get_unsigned_2_byte_index_at_bcp(rbx, 1);
  __ get_cpool_and_tags(rcx, rax);
  const int base_offset = ConstantPool::header_size() * wordSize;
  const int tags_offset = Array<u1>::base_offset_in_bytes();
  __ cmpb(Address(rax, rbx, Address::times_1, tags_offset),
          JVM_CONSTANT_Double);
  __ jccb(Assembler::notEqual, Long);
  __ movdbl(xmm0, Address(rcx, rbx, Address::times_8, base_offset));
  __ push_d();
  __ jmpb(Done);
  __ bind(Long);
  __ movq(rax, Address(rcx, rbx, Address::times_8, base_offset));
  __ push_l();
  __ bind(Done);
}
void TemplateTable::locals_index(Register reg, int offset) {
  __ load_unsigned_byte(reg, at_bcp(offset));
  __ negptr(reg);
}
void TemplateTable::iload() {
  transition(vtos, itos);
  if (RewriteFrequentPairs) {
    Label rewrite, done;
    const Register bc = c_rarg3;
    assert(rbx != bc, "register damaged");
    __ load_unsigned_byte(rbx,
                          at_bcp(Bytecodes::length_for(Bytecodes::_iload)));
    __ cmpl(rbx, Bytecodes::_iload);
    __ jcc(Assembler::equal, done);
    __ cmpl(rbx, Bytecodes::_fast_iload);
    __ movl(bc, Bytecodes::_fast_iload2);
    __ jccb(Assembler::equal, rewrite);
    __ cmpl(rbx, Bytecodes::_caload);
    __ movl(bc, Bytecodes::_fast_icaload);
    __ jccb(Assembler::equal, rewrite);
    __ movl(bc, Bytecodes::_fast_iload);
    __ bind(rewrite);
    patch_bytecode(Bytecodes::_iload, bc, rbx, false);
    __ bind(done);
  }
  locals_index(rbx);
  __ movl(rax, iaddress(rbx));
}
void TemplateTable::fast_iload2() {
  transition(vtos, itos);
  locals_index(rbx);
  __ movl(rax, iaddress(rbx));
  __ push(itos);
  locals_index(rbx, 3);
  __ movl(rax, iaddress(rbx));
}
void TemplateTable::fast_iload() {
  transition(vtos, itos);
  locals_index(rbx);
  __ movl(rax, iaddress(rbx));
}
void TemplateTable::lload() {
  transition(vtos, ltos);
  locals_index(rbx);
  __ movq(rax, laddress(rbx));
}
void TemplateTable::fload() {
  transition(vtos, ftos);
  locals_index(rbx);
  __ movflt(xmm0, faddress(rbx));
}
void TemplateTable::dload() {
  transition(vtos, dtos);
  locals_index(rbx);
  __ movdbl(xmm0, daddress(rbx));
}
void TemplateTable::aload() {
  transition(vtos, atos);
  locals_index(rbx);
  __ movptr(rax, aaddress(rbx));
}
void TemplateTable::locals_index_wide(Register reg) {
  __ load_unsigned_short(reg, at_bcp(2));
  __ bswapl(reg);
  __ shrl(reg, 16);
  __ negptr(reg);
}
void TemplateTable::wide_iload() {
  transition(vtos, itos);
  locals_index_wide(rbx);
  __ movl(rax, iaddress(rbx));
}
void TemplateTable::wide_lload() {
  transition(vtos, ltos);
  locals_index_wide(rbx);
  __ movq(rax, laddress(rbx));
}
void TemplateTable::wide_fload() {
  transition(vtos, ftos);
  locals_index_wide(rbx);
  __ movflt(xmm0, faddress(rbx));
}
void TemplateTable::wide_dload() {
  transition(vtos, dtos);
  locals_index_wide(rbx);
  __ movdbl(xmm0, daddress(rbx));
}
void TemplateTable::wide_aload() {
  transition(vtos, atos);
  locals_index_wide(rbx);
  __ movptr(rax, aaddress(rbx));
}
void TemplateTable::index_check(Register array, Register index) {
  __ null_check(array, arrayOopDesc::length_offset_in_bytes());
  __ movl2ptr(index, index);
  __ cmpl(index, Address(array, arrayOopDesc::length_offset_in_bytes()));
  if (index != rbx) {
    assert(rbx != array, "different registers");
    __ movl(rbx, index);
  }
  __ jump_cc(Assembler::aboveEqual,
             ExternalAddress(Interpreter::_throw_ArrayIndexOutOfBoundsException_entry));
}
void TemplateTable::iaload() {
  transition(itos, itos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ movl(rax, Address(rdx, rax,
                       Address::times_4,
                       arrayOopDesc::base_offset_in_bytes(T_INT)));
}
void TemplateTable::laload() {
  transition(itos, ltos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ movq(rax, Address(rdx, rbx,
                       Address::times_8,
                       arrayOopDesc::base_offset_in_bytes(T_LONG)));
}
void TemplateTable::faload() {
  transition(itos, ftos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ movflt(xmm0, Address(rdx, rax,
                         Address::times_4,
                         arrayOopDesc::base_offset_in_bytes(T_FLOAT)));
}
void TemplateTable::daload() {
  transition(itos, dtos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ movdbl(xmm0, Address(rdx, rax,
                          Address::times_8,
                          arrayOopDesc::base_offset_in_bytes(T_DOUBLE)));
}
void TemplateTable::aaload() {
  transition(itos, atos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ load_heap_oop(rax, Address(rdx, rax,
                                UseCompressedOops ? Address::times_4 : Address::times_8,
                                arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
}
void TemplateTable::baload() {
  transition(itos, itos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ load_signed_byte(rax,
                      Address(rdx, rax,
                              Address::times_1,
                              arrayOopDesc::base_offset_in_bytes(T_BYTE)));
}
void TemplateTable::caload() {
  transition(itos, itos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ load_unsigned_short(rax,
                         Address(rdx, rax,
                                 Address::times_2,
                                 arrayOopDesc::base_offset_in_bytes(T_CHAR)));
}
void TemplateTable::fast_icaload() {
  transition(vtos, itos);
  locals_index(rbx);
  __ movl(rax, iaddress(rbx));
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ load_unsigned_short(rax,
                         Address(rdx, rax,
                                 Address::times_2,
                                 arrayOopDesc::base_offset_in_bytes(T_CHAR)));
}
void TemplateTable::saload() {
  transition(itos, itos);
  __ pop_ptr(rdx);
  index_check(rdx, rax); // kills rbx
  __ load_signed_short(rax,
                       Address(rdx, rax,
                               Address::times_2,
                               arrayOopDesc::base_offset_in_bytes(T_SHORT)));
}
void TemplateTable::iload(int n) {
  transition(vtos, itos);
  __ movl(rax, iaddress(n));
}
void TemplateTable::lload(int n) {
  transition(vtos, ltos);
  __ movq(rax, laddress(n));
}
void TemplateTable::fload(int n) {
  transition(vtos, ftos);
  __ movflt(xmm0, faddress(n));
}
void TemplateTable::dload(int n) {
  transition(vtos, dtos);
  __ movdbl(xmm0, daddress(n));
}
void TemplateTable::aload(int n) {
  transition(vtos, atos);
  __ movptr(rax, aaddress(n));
}
void TemplateTable::aload_0() {
  transition(vtos, atos);
  if (RewriteFrequentPairs) {
    Label rewrite, done;
    const Register bc = c_rarg3;
    assert(rbx != bc, "register damaged");
    __ load_unsigned_byte(rbx,
                          at_bcp(Bytecodes::length_for(Bytecodes::_aload_0)));
    aload(0);
    __ cmpl(rbx, Bytecodes::_getfield);
    __ jcc(Assembler::equal, done);
    assert(Bytecodes::java_code(Bytecodes::_fast_iaccess_0) ==
           Bytecodes::_aload_0,
           "fix bytecode definition");
    __ cmpl(rbx, Bytecodes::_fast_igetfield);
    __ movl(bc, Bytecodes::_fast_iaccess_0);
    __ jccb(Assembler::equal, rewrite);
    assert(Bytecodes::java_code(Bytecodes::_fast_aaccess_0) ==
           Bytecodes::_aload_0,
           "fix bytecode definition");
    __ cmpl(rbx, Bytecodes::_fast_agetfield);
    __ movl(bc, Bytecodes::_fast_aaccess_0);
    __ jccb(Assembler::equal, rewrite);
    assert(Bytecodes::java_code(Bytecodes::_fast_faccess_0) ==
           Bytecodes::_aload_0,
           "fix bytecode definition");
    __ cmpl(rbx, Bytecodes::_fast_fgetfield);
    __ movl(bc, Bytecodes::_fast_faccess_0);
    __ jccb(Assembler::equal, rewrite);
    assert(Bytecodes::java_code(Bytecodes::_fast_aload_0) ==
           Bytecodes::_aload_0,
           "fix bytecode definition");
    __ movl(bc, Bytecodes::_fast_aload_0);
    __ bind(rewrite);
    patch_bytecode(Bytecodes::_aload_0, bc, rbx, false);
    __ bind(done);
  } else {
    aload(0);
  }
}
void TemplateTable::istore() {
  transition(itos, vtos);
  locals_index(rbx);
  __ movl(iaddress(rbx), rax);
}
void TemplateTable::lstore() {
  transition(ltos, vtos);
  locals_index(rbx);
  __ movq(laddress(rbx), rax);
}
void TemplateTable::fstore() {
  transition(ftos, vtos);
  locals_index(rbx);
  __ movflt(faddress(rbx), xmm0);
}
void TemplateTable::dstore() {
  transition(dtos, vtos);
  locals_index(rbx);
  __ movdbl(daddress(rbx), xmm0);
}
void TemplateTable::astore() {
  transition(vtos, vtos);
  __ pop_ptr(rax);
  locals_index(rbx);
  __ movptr(aaddress(rbx), rax);
}
void TemplateTable::wide_istore() {
  transition(vtos, vtos);
  __ pop_i();
  locals_index_wide(rbx);
  __ movl(iaddress(rbx), rax);
}
void TemplateTable::wide_lstore() {
  transition(vtos, vtos);
  __ pop_l();
  locals_index_wide(rbx);
  __ movq(laddress(rbx), rax);
}
void TemplateTable::wide_fstore() {
  transition(vtos, vtos);
  __ pop_f();
  locals_index_wide(rbx);
  __ movflt(faddress(rbx), xmm0);
}
void TemplateTable::wide_dstore() {
  transition(vtos, vtos);
  __ pop_d();
  locals_index_wide(rbx);
  __ movdbl(daddress(rbx), xmm0);
}
void TemplateTable::wide_astore() {
  transition(vtos, vtos);
  __ pop_ptr(rax);
  locals_index_wide(rbx);
  __ movptr(aaddress(rbx), rax);
}
void TemplateTable::iastore() {
  transition(itos, vtos);
  __ pop_i(rbx);
  __ pop_ptr(rdx);
  index_check(rdx, rbx); // prefer index in ebx
  __ movl(Address(rdx, rbx,
                  Address::times_4,
                  arrayOopDesc::base_offset_in_bytes(T_INT)),
          rax);
}
void TemplateTable::lastore() {
  transition(ltos, vtos);
  __ pop_i(rbx);
  __ pop_ptr(rdx);
  index_check(rdx, rbx); // prefer index in ebx
  __ movq(Address(rdx, rbx,
                  Address::times_8,
                  arrayOopDesc::base_offset_in_bytes(T_LONG)),
          rax);
}
void TemplateTable::fastore() {
  transition(ftos, vtos);
  __ pop_i(rbx);
  __ pop_ptr(rdx);
  index_check(rdx, rbx); // prefer index in ebx
  __ movflt(Address(rdx, rbx,
                   Address::times_4,
                   arrayOopDesc::base_offset_in_bytes(T_FLOAT)),
           xmm0);
}
void TemplateTable::dastore() {
  transition(dtos, vtos);
  __ pop_i(rbx);
  __ pop_ptr(rdx);
  index_check(rdx, rbx); // prefer index in ebx
  __ movdbl(Address(rdx, rbx,
                   Address::times_8,
                   arrayOopDesc::base_offset_in_bytes(T_DOUBLE)),
           xmm0);
}
void TemplateTable::aastore() {
  Label is_null, ok_is_subtype, done;
  transition(vtos, vtos);
  __ movptr(rax, at_tos());    // value
  __ movl(rcx, at_tos_p1()); // index
  __ movptr(rdx, at_tos_p2()); // array
  Address element_address(rdx, rcx,
                          UseCompressedOops? Address::times_4 : Address::times_8,
                          arrayOopDesc::base_offset_in_bytes(T_OBJECT));
  index_check(rdx, rcx);     // kills rbx
  __ testptr(rax, rax);
  __ jcc(Assembler::zero, is_null);
  __ load_klass(rbx, rax);
  __ load_klass(rax, rdx);
  __ movptr(rax, Address(rax,
                         ObjArrayKlass::element_klass_offset()));
  __ lea(rdx, element_address);
  __ gen_subtype_check(rbx, ok_is_subtype);
  __ jump(ExternalAddress(Interpreter::_throw_ArrayStoreException_entry));
  __ bind(ok_is_subtype);
  __ movptr(rax, at_tos());
  do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true);
  __ jmp(done);
  __ bind(is_null);
  __ profile_null_seen(rbx);
  do_oop_store(_masm, element_address, noreg, _bs->kind(), true);
  __ bind(done);
  __ addptr(rsp, 3 * Interpreter::stackElementSize);
}
void TemplateTable::bastore() {
  transition(itos, vtos);
  __ pop_i(rbx);
  __ pop_ptr(rdx);
  index_check(rdx, rbx); // prefer index in ebx
  __ load_klass(rcx, rdx);
  __ movl(rcx, Address(rcx, Klass::layout_helper_offset()));
  int diffbit = Klass::layout_helper_boolean_diffbit();
  __ testl(rcx, diffbit);
  Label L_skip;
  __ jccb(Assembler::zero, L_skip);
  __ andl(rax, 1);  // if it is a T_BOOLEAN array, mask the stored value to 0/1
  __ bind(L_skip);
  __ movb(Address(rdx, rbx,
                  Address::times_1,
                  arrayOopDesc::base_offset_in_bytes(T_BYTE)),
          rax);
}
void TemplateTable::castore() {
  transition(itos, vtos);
  __ pop_i(rbx);
  __ pop_ptr(rdx);
  index_check(rdx, rbx);  // prefer index in ebx
  __ movw(Address(rdx, rbx,
                  Address::times_2,
                  arrayOopDesc::base_offset_in_bytes(T_CHAR)),
          rax);
}
void TemplateTable::sastore() {
  castore();
}
void TemplateTable::istore(int n) {
  transition(itos, vtos);
  __ movl(iaddress(n), rax);
}
void TemplateTable::lstore(int n) {
  transition(ltos, vtos);
  __ movq(laddress(n), rax);
}
void TemplateTable::fstore(int n) {
  transition(ftos, vtos);
  __ movflt(faddress(n), xmm0);
}
void TemplateTable::dstore(int n) {
  transition(dtos, vtos);
  __ movdbl(daddress(n), xmm0);
}
void TemplateTable::astore(int n) {
  transition(vtos, vtos);
  __ pop_ptr(rax);
  __ movptr(aaddress(n), rax);
}
void TemplateTable::pop() {
  transition(vtos, vtos);
  __ addptr(rsp, Interpreter::stackElementSize);
}
void TemplateTable::pop2() {
  transition(vtos, vtos);
  __ addptr(rsp, 2 * Interpreter::stackElementSize);
}
void TemplateTable::dup() {
  transition(vtos, vtos);
  __ load_ptr(0, rax);
  __ push_ptr(rax);
}
void TemplateTable::dup_x1() {
  transition(vtos, vtos);
  __ load_ptr( 0, rax);  // load b
  __ load_ptr( 1, rcx);  // load a
  __ store_ptr(1, rax);  // store b
  __ store_ptr(0, rcx);  // store a
  __ push_ptr(rax);      // push b
}
void TemplateTable::dup_x2() {
  transition(vtos, vtos);
  __ load_ptr( 0, rax);  // load c
  __ load_ptr( 2, rcx);  // load a
  __ store_ptr(2, rax);  // store c in a
  __ push_ptr(rax);      // push c
  __ load_ptr( 2, rax);  // load b
  __ store_ptr(2, rcx);  // store a in b
  __ store_ptr(1, rax);  // store b in c
}
void TemplateTable::dup2() {
  transition(vtos, vtos);
  __ load_ptr(1, rax);  // load a
  __ push_ptr(rax);     // push a
  __ load_ptr(1, rax);  // load b
  __ push_ptr(rax);     // push b
}
void TemplateTable::dup2_x1() {
  transition(vtos, vtos);
  __ load_ptr( 0, rcx);  // load c
  __ load_ptr( 1, rax);  // load b
  __ push_ptr(rax);      // push b
  __ push_ptr(rcx);      // push c
  __ store_ptr(3, rcx);  // store c in b
  __ load_ptr( 4, rcx);  // load a
  __ store_ptr(2, rcx);  // store a in 2nd c
  __ store_ptr(4, rax);  // store b in a
}
void TemplateTable::dup2_x2() {
  transition(vtos, vtos);
  __ load_ptr( 0, rcx);  // load d
  __ load_ptr( 1, rax);  // load c
  __ push_ptr(rax);      // push c
  __ push_ptr(rcx);      // push d
  __ load_ptr( 4, rax);  // load b
  __ store_ptr(2, rax);  // store b in d
  __ store_ptr(4, rcx);  // store d in b
  __ load_ptr( 5, rcx);  // load a
  __ load_ptr( 3, rax);  // load c
  __ store_ptr(3, rcx);  // store a in c
  __ store_ptr(5, rax);  // store c in a
}
void TemplateTable::swap() {
  transition(vtos, vtos);
  __ load_ptr( 1, rcx);  // load a
  __ load_ptr( 0, rax);  // load b
  __ store_ptr(0, rcx);  // store a in b
  __ store_ptr(1, rax);  // store b in a
}
void TemplateTable::iop2(Operation op) {
  transition(itos, itos);
  switch (op) {
  case add  :                    __ pop_i(rdx); __ addl (rax, rdx); break;
  case sub  : __ movl(rdx, rax); __ pop_i(rax); __ subl (rax, rdx); break;
  case mul  :                    __ pop_i(rdx); __ imull(rax, rdx); break;
  case _and :                    __ pop_i(rdx); __ andl (rax, rdx); break;
  case _or  :                    __ pop_i(rdx); __ orl  (rax, rdx); break;
  case _xor :                    __ pop_i(rdx); __ xorl (rax, rdx); break;
  case shl  : __ movl(rcx, rax); __ pop_i(rax); __ shll (rax);      break;
  case shr  : __ movl(rcx, rax); __ pop_i(rax); __ sarl (rax);      break;
  case ushr : __ movl(rcx, rax); __ pop_i(rax); __ shrl (rax);      break;
  default   : ShouldNotReachHere();
  }
}
void TemplateTable::lop2(Operation op) {
  transition(ltos, ltos);
  switch (op) {
  case add  :                    __ pop_l(rdx); __ addptr(rax, rdx); break;
  case sub  : __ mov(rdx, rax);  __ pop_l(rax); __ subptr(rax, rdx); break;
  case _and :                    __ pop_l(rdx); __ andptr(rax, rdx); break;
  case _or  :                    __ pop_l(rdx); __ orptr (rax, rdx); break;
  case _xor :                    __ pop_l(rdx); __ xorptr(rax, rdx); break;
  default   : ShouldNotReachHere();
  }
}
void TemplateTable::idiv() {
  transition(itos, itos);
  __ movl(rcx, rax);
  __ pop_i(rax);
  __ corrected_idivl(rcx);
}
void TemplateTable::irem() {
  transition(itos, itos);
  __ movl(rcx, rax);
  __ pop_i(rax);
  __ corrected_idivl(rcx);
  __ movl(rax, rdx);
}
void TemplateTable::lmul() {
  transition(ltos, ltos);
  __ pop_l(rdx);
  __ imulq(rax, rdx);
}
void TemplateTable::ldiv() {
  transition(ltos, ltos);
  __ mov(rcx, rax);
  __ pop_l(rax);
  __ testq(rcx, rcx);
  __ jump_cc(Assembler::zero,
             ExternalAddress(Interpreter::_throw_ArithmeticException_entry));
  __ corrected_idivq(rcx); // kills rbx
}
void TemplateTable::lrem() {
  transition(ltos, ltos);
  __ mov(rcx, rax);
  __ pop_l(rax);
  __ testq(rcx, rcx);
  __ jump_cc(Assembler::zero,
             ExternalAddress(Interpreter::_throw_ArithmeticException_entry));
  __ corrected_idivq(rcx); // kills rbx
  __ mov(rax, rdx);
}
void TemplateTable::lshl() {
  transition(itos, ltos);
  __ movl(rcx, rax);                             // get shift count
  __ pop_l(rax);                                 // get shift value
  __ shlq(rax);
}
void TemplateTable::lshr() {
  transition(itos, ltos);
  __ movl(rcx, rax);                             // get shift count
  __ pop_l(rax);                                 // get shift value
  __ sarq(rax);
}
void TemplateTable::lushr() {
  transition(itos, ltos);
  __ movl(rcx, rax);                             // get shift count
  __ pop_l(rax);                                 // get shift value
  __ shrq(rax);
}
void TemplateTable::fop2(Operation op) {
  transition(ftos, ftos);
  switch (op) {
  case add:
    __ addss(xmm0, at_rsp());
    __ addptr(rsp, Interpreter::stackElementSize);
    break;
  case sub:
    __ movflt(xmm1, xmm0);
    __ pop_f(xmm0);
    __ subss(xmm0, xmm1);
    break;
  case mul:
    __ mulss(xmm0, at_rsp());
    __ addptr(rsp, Interpreter::stackElementSize);
    break;
  case div:
    __ movflt(xmm1, xmm0);
    __ pop_f(xmm0);
    __ divss(xmm0, xmm1);
    break;
  case rem:
    __ movflt(xmm1, xmm0);
    __ pop_f(xmm0);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::frem), 2);
    break;
  default:
    ShouldNotReachHere();
    break;
  }
}
void TemplateTable::dop2(Operation op) {
  transition(dtos, dtos);
  switch (op) {
  case add:
    __ addsd(xmm0, at_rsp());
    __ addptr(rsp, 2 * Interpreter::stackElementSize);
    break;
  case sub:
    __ movdbl(xmm1, xmm0);
    __ pop_d(xmm0);
    __ subsd(xmm0, xmm1);
    break;
  case mul:
    __ mulsd(xmm0, at_rsp());
    __ addptr(rsp, 2 * Interpreter::stackElementSize);
    break;
  case div:
    __ movdbl(xmm1, xmm0);
    __ pop_d(xmm0);
    __ divsd(xmm0, xmm1);
    break;
  case rem:
    __ movdbl(xmm1, xmm0);
    __ pop_d(xmm0);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::drem), 2);
    break;
  default:
    ShouldNotReachHere();
    break;
  }
}
void TemplateTable::ineg() {
  transition(itos, itos);
  __ negl(rax);
}
void TemplateTable::lneg() {
  transition(ltos, ltos);
  __ negq(rax);
}
static jlong* double_quadword(jlong *adr, jlong lo, jlong hi) {
  jlong *operand = (jlong*)(((intptr_t)adr)&((intptr_t)(~0xF)));
  operand[0] = lo;
  operand[1] = hi;
  return operand;
}
static jlong float_signflip_pool[2*2];
static jlong double_signflip_pool[2*2];
void TemplateTable::fneg() {
  transition(ftos, ftos);
  static jlong *float_signflip  = double_quadword(&float_signflip_pool[1], 0x8000000080000000, 0x8000000080000000);
  __ xorps(xmm0, ExternalAddress((address) float_signflip));
}
void TemplateTable::dneg() {
  transition(dtos, dtos);
  static jlong *double_signflip  = double_quadword(&double_signflip_pool[1], 0x8000000000000000, 0x8000000000000000);
  __ xorpd(xmm0, ExternalAddress((address) double_signflip));
}
void TemplateTable::iinc() {
  transition(vtos, vtos);
  __ load_signed_byte(rdx, at_bcp(2)); // get constant
  locals_index(rbx);
  __ addl(iaddress(rbx), rdx);
}
void TemplateTable::wide_iinc() {
  transition(vtos, vtos);
  __ movl(rdx, at_bcp(4)); // get constant
  locals_index_wide(rbx);
  __ bswapl(rdx); // swap bytes & sign-extend constant
  __ sarl(rdx, 16);
  __ addl(iaddress(rbx), rdx);
}
void TemplateTable::convert() {
#ifdef ASSERT
  {
    TosState tos_in  = ilgl;
    TosState tos_out = ilgl;
    switch (bytecode()) {
    case Bytecodes::_i2l: // fall through
    case Bytecodes::_i2f: // fall through
    case Bytecodes::_i2d: // fall through
    case Bytecodes::_i2b: // fall through
    case Bytecodes::_i2c: // fall through
    case Bytecodes::_i2s: tos_in = itos; break;
    case Bytecodes::_l2i: // fall through
    case Bytecodes::_l2f: // fall through
    case Bytecodes::_l2d: tos_in = ltos; break;
    case Bytecodes::_f2i: // fall through
    case Bytecodes::_f2l: // fall through
    case Bytecodes::_f2d: tos_in = ftos; break;
    case Bytecodes::_d2i: // fall through
    case Bytecodes::_d2l: // fall through
    case Bytecodes::_d2f: tos_in = dtos; break;
    default             : ShouldNotReachHere();
    }
    switch (bytecode()) {
    case Bytecodes::_l2i: // fall through
    case Bytecodes::_f2i: // fall through
    case Bytecodes::_d2i: // fall through
    case Bytecodes::_i2b: // fall through
    case Bytecodes::_i2c: // fall through
    case Bytecodes::_i2s: tos_out = itos; break;
    case Bytecodes::_i2l: // fall through
    case Bytecodes::_f2l: // fall through
    case Bytecodes::_d2l: tos_out = ltos; break;
    case Bytecodes::_i2f: // fall through
    case Bytecodes::_l2f: // fall through
    case Bytecodes::_d2f: tos_out = ftos; break;
    case Bytecodes::_i2d: // fall through
    case Bytecodes::_l2d: // fall through
    case Bytecodes::_f2d: tos_out = dtos; break;
    default             : ShouldNotReachHere();
    }
    transition(tos_in, tos_out);
  }
#endif // ASSERT
  static const int64_t is_nan = 0x8000000000000000L;
  switch (bytecode()) {
  case Bytecodes::_i2l:
    __ movslq(rax, rax);
    break;
  case Bytecodes::_i2f:
    __ cvtsi2ssl(xmm0, rax);
    break;
  case Bytecodes::_i2d:
    __ cvtsi2sdl(xmm0, rax);
    break;
  case Bytecodes::_i2b:
    __ movsbl(rax, rax);
    break;
  case Bytecodes::_i2c:
    __ movzwl(rax, rax);
    break;
  case Bytecodes::_i2s:
    __ movswl(rax, rax);
    break;
  case Bytecodes::_l2i:
    __ movl(rax, rax);
    break;
  case Bytecodes::_l2f:
    __ cvtsi2ssq(xmm0, rax);
    break;
  case Bytecodes::_l2d:
    __ cvtsi2sdq(xmm0, rax);
    break;
  case Bytecodes::_f2i:
  {
    Label L;
    __ cvttss2sil(rax, xmm0);
    __ cmpl(rax, 0x80000000); // NaN or overflow/underflow?
    __ jcc(Assembler::notEqual, L);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2i), 1);
    __ bind(L);
  }
    break;
  case Bytecodes::_f2l:
  {
    Label L;
    __ cvttss2siq(rax, xmm0);
    __ cmp64(rax, ExternalAddress((address) &is_nan));
    __ jcc(Assembler::notEqual, L);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::f2l), 1);
    __ bind(L);
  }
    break;
  case Bytecodes::_f2d:
    __ cvtss2sd(xmm0, xmm0);
    break;
  case Bytecodes::_d2i:
  {
    Label L;
    __ cvttsd2sil(rax, xmm0);
    __ cmpl(rax, 0x80000000); // NaN or overflow/underflow?
    __ jcc(Assembler::notEqual, L);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2i), 1);
    __ bind(L);
  }
    break;
  case Bytecodes::_d2l:
  {
    Label L;
    __ cvttsd2siq(rax, xmm0);
    __ cmp64(rax, ExternalAddress((address) &is_nan));
    __ jcc(Assembler::notEqual, L);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::d2l), 1);
    __ bind(L);
  }
    break;
  case Bytecodes::_d2f:
    __ cvtsd2ss(xmm0, xmm0);
    break;
  default:
    ShouldNotReachHere();
  }
}
void TemplateTable::lcmp() {
  transition(ltos, itos);
  Label done;
  __ pop_l(rdx);
  __ cmpq(rdx, rax);
  __ movl(rax, -1);
  __ jccb(Assembler::less, done);
  __ setb(Assembler::notEqual, rax);
  __ movzbl(rax, rax);
  __ bind(done);
}
void TemplateTable::float_cmp(bool is_float, int unordered_result) {
  Label done;
  if (is_float) {
    __ pop_f(xmm1);
    __ ucomiss(xmm1, xmm0);
  } else {
    __ pop_d(xmm1);
    __ ucomisd(xmm1, xmm0);
  }
  if (unordered_result < 0) {
    __ movl(rax, -1);
    __ jccb(Assembler::parity, done);
    __ jccb(Assembler::below, done);
    __ setb(Assembler::notEqual, rdx);
    __ movzbl(rax, rdx);
  } else {
    __ movl(rax, 1);
    __ jccb(Assembler::parity, done);
    __ jccb(Assembler::above, done);
    __ movl(rax, 0);
    __ jccb(Assembler::equal, done);
    __ decrementl(rax);
  }
  __ bind(done);
}
void TemplateTable::branch(bool is_jsr, bool is_wide) {
  __ get_method(rcx); // rcx holds method
  __ profile_taken_branch(rax, rbx); // rax holds updated MDP, rbx
  const ByteSize be_offset = MethodCounters::backedge_counter_offset() +
                             InvocationCounter::counter_offset();
  const ByteSize inv_offset = MethodCounters::invocation_counter_offset() +
                              InvocationCounter::counter_offset();
  if (is_wide) {
    __ movl(rdx, at_bcp(1));
  } else {
    __ load_signed_short(rdx, at_bcp(1));
  }
  __ bswapl(rdx);
  if (!is_wide) {
    __ sarl(rdx, 16);
  }
  __ movl2ptr(rdx, rdx);
  if (is_jsr) {
    __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1, 0));
    __ lea(rax, at_bcp((is_wide ? 5 : 3) -
                        in_bytes(ConstMethod::codes_offset())));
    __ subptr(rax, Address(rcx, Method::const_offset()));
    __ addptr(r13, rdx);
    __ push_i(rax);
    __ dispatch_only(vtos);
    return;
  }
  __ addptr(r13, rdx);
  assert(UseLoopCounter || !UseOnStackReplacement,
         "on-stack-replacement requires loop counters");
  Label backedge_counter_overflow;
  Label profile_method;
  Label dispatch;
  if (UseLoopCounter) {
    __ testl(rdx, rdx);             // check if forward or backward branch
    __ jcc(Assembler::positive, dispatch); // count only if backward branch
    Label has_counters;
    __ movptr(rax, Address(rcx, Method::method_counters_offset()));
    __ testptr(rax, rax);
    __ jcc(Assembler::notZero, has_counters);
    __ push(rdx);
    __ push(rcx);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters),
               rcx);
    __ pop(rcx);
    __ pop(rdx);
    __ movptr(rax, Address(rcx, Method::method_counters_offset()));
    __ jcc(Assembler::zero, dispatch);
    __ bind(has_counters);
    if (TieredCompilation) {
      Label no_mdo;
      int increment = InvocationCounter::count_increment;
      int mask = ((1 << Tier0BackedgeNotifyFreqLog) - 1) << InvocationCounter::count_shift;
      if (ProfileInterpreter) {
        __ movptr(rbx, Address(rcx, in_bytes(Method::method_data_offset())));
        __ testptr(rbx, rbx);
        __ jccb(Assembler::zero, no_mdo);
        const Address mdo_backedge_counter(rbx, in_bytes(MethodData::backedge_counter_offset()) +
                                           in_bytes(InvocationCounter::counter_offset()));
        __ increment_mask_and_jump(mdo_backedge_counter, increment, mask, rax, false, Assembler::zero,
                                   UseOnStackReplacement ? &backedge_counter_overflow : NULL);
        __ jmp(dispatch);
      }
      __ bind(no_mdo);
      __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
      __ increment_mask_and_jump(Address(rcx, be_offset), increment, mask,
                                 rax, false, Assembler::zero,
                                 UseOnStackReplacement ? &backedge_counter_overflow : NULL);
    } else {
      __ movptr(rcx, Address(rcx, Method::method_counters_offset()));
      __ movl(rax, Address(rcx, be_offset));        // load backedge counter
      __ incrementl(rax, InvocationCounter::count_increment); // increment counter
      __ movl(Address(rcx, be_offset), rax);        // store counter
      __ movl(rax, Address(rcx, inv_offset));    // load invocation counter
      __ andl(rax, InvocationCounter::count_mask_value); // and the status bits
      __ addl(rax, Address(rcx, be_offset));        // add both counters
      if (ProfileInterpreter) {
        __ cmp32(rax,
                 ExternalAddress((address) &InvocationCounter::InterpreterProfileLimit));
        __ jcc(Assembler::less, dispatch);
        __ test_method_data_pointer(rax, profile_method);
        if (UseOnStackReplacement) {
          __ cmp32(rbx,
                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
          __ jcc(Assembler::below, dispatch);
          const int overflow_frequency = 1024;
          __ andl(rbx, overflow_frequency - 1);
          __ jcc(Assembler::zero, backedge_counter_overflow);
        }
      } else {
        if (UseOnStackReplacement) {
          __ cmp32(rax,
                   ExternalAddress((address) &InvocationCounter::InterpreterBackwardBranchLimit));
          __ jcc(Assembler::aboveEqual, backedge_counter_overflow);
        }
      }
    }
    __ bind(dispatch);
  }
  __ load_unsigned_byte(rbx, Address(r13, 0));
  __ dispatch_only(vtos);
  if (UseLoopCounter) {
    if (ProfileInterpreter) {
      __ bind(profile_method);
      __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::profile_method));
      __ load_unsigned_byte(rbx, Address(r13, 0));  // restore target bytecode
      __ set_method_data_pointer_for_bcp();
      __ jmp(dispatch);
    }
    if (UseOnStackReplacement) {
      __ bind(backedge_counter_overflow);
      __ negptr(rdx);
      __ addptr(rdx, r13); // branch bcp
      __ call_VM(noreg,
                 CAST_FROM_FN_PTR(address,
                                  InterpreterRuntime::frequency_counter_overflow),
                 rdx);
      __ load_unsigned_byte(rbx, Address(r13, 0));  // restore target bytecode
      __ testptr(rax, rax);                        // test result
      __ jcc(Assembler::zero, dispatch);         // no osr if null
      __ movl(rcx, Address(rax, nmethod::entry_bci_offset()));
      __ cmpl(rcx, InvalidOSREntryBci);
      __ jcc(Assembler::equal, dispatch);
      __ mov(r13, rax);                             // save the nmethod
      call_VM(noreg, CAST_FROM_FN_PTR(address, SharedRuntime::OSR_migration_begin));
      __ mov(j_rarg0, rax);
      const Register retaddr = j_rarg2;
      const Register sender_sp = j_rarg1;
      __ movptr(sender_sp, Address(rbp, frame::interpreter_frame_sender_sp_offset * wordSize)); // get sender sp
      __ leave();                                // remove frame anchor
      __ pop(retaddr);                           // get return address
      __ mov(rsp, sender_sp);                   // set sp to sender sp
      __ andptr(rsp, -(StackAlignmentInBytes));
      __ push(retaddr);
      __ jmp(Address(r13, nmethod::osr_entry_point_offset()));
    }
  }
}
void TemplateTable::if_0cmp(Condition cc) {
  transition(itos, vtos);
  Label not_taken;
  __ testl(rax, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::if_icmp(Condition cc) {
  transition(itos, vtos);
  Label not_taken;
  __ pop_i(rdx);
  __ cmpl(rdx, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::if_nullcmp(Condition cc) {
  transition(atos, vtos);
  Label not_taken;
  __ testptr(rax, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::if_acmp(Condition cc) {
  transition(atos, vtos);
  Label not_taken;
  __ pop_ptr(rdx);
  __ cmpptr(rdx, rax);
  __ jcc(j_not(cc), not_taken);
  branch(false, false);
  __ bind(not_taken);
  __ profile_not_taken_branch(rax);
}
void TemplateTable::ret() {
  transition(vtos, vtos);
  locals_index(rbx);
  __ movslq(rbx, iaddress(rbx)); // get return bci, compute return bcp
  __ profile_ret(rbx, rcx);
  __ get_method(rax);
  __ movptr(r13, Address(rax, Method::const_offset()));
  __ lea(r13, Address(r13, rbx, Address::times_1,
                      ConstMethod::codes_offset()));
  __ dispatch_next(vtos);
}
void TemplateTable::wide_ret() {
  transition(vtos, vtos);
  locals_index_wide(rbx);
  __ movptr(rbx, aaddress(rbx)); // get return bci, compute return bcp
  __ profile_ret(rbx, rcx);
  __ get_method(rax);
  __ movptr(r13, Address(rax, Method::const_offset()));
  __ lea(r13, Address(r13, rbx, Address::times_1, ConstMethod::codes_offset()));
  __ dispatch_next(vtos);
}
void TemplateTable::tableswitch() {
  Label default_case, continue_execution;
  transition(itos, vtos);
  __ lea(rbx, at_bcp(BytesPerInt));
  __ andptr(rbx, -BytesPerInt);
  __ movl(rcx, Address(rbx, BytesPerInt));
  __ movl(rdx, Address(rbx, 2 * BytesPerInt));
  __ bswapl(rcx);
  __ bswapl(rdx);
  __ cmpl(rax, rcx);
  __ jcc(Assembler::less, default_case);
  __ cmpl(rax, rdx);
  __ jcc(Assembler::greater, default_case);
  __ subl(rax, rcx);
  __ movl(rdx, Address(rbx, rax, Address::times_4, 3 * BytesPerInt));
  __ profile_switch_case(rax, rbx, rcx);
  __ bind(continue_execution);
  __ bswapl(rdx);
  __ movl2ptr(rdx, rdx);
  __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1));
  __ addptr(r13, rdx);
  __ dispatch_only(vtos);
  __ bind(default_case);
  __ profile_switch_default(rax);
  __ movl(rdx, Address(rbx, 0));
  __ jmp(continue_execution);
}
void TemplateTable::lookupswitch() {
  transition(itos, itos);
  __ stop("lookupswitch bytecode should have been rewritten");
}
void TemplateTable::fast_linearswitch() {
  transition(itos, vtos);
  Label loop_entry, loop, found, continue_execution;
  __ bswapl(rax);
  __ lea(rbx, at_bcp(BytesPerInt)); // btw: should be able to get rid of
  __ andptr(rbx, -BytesPerInt);
  __ movl(rcx, Address(rbx, BytesPerInt));
  __ bswapl(rcx);
  __ jmpb(loop_entry);
  __ bind(loop);
  __ cmpl(rax, Address(rbx, rcx, Address::times_8, 2 * BytesPerInt));
  __ jcc(Assembler::equal, found);
  __ bind(loop_entry);
  __ decrementl(rcx);
  __ jcc(Assembler::greaterEqual, loop);
  __ profile_switch_default(rax);
  __ movl(rdx, Address(rbx, 0));
  __ jmp(continue_execution);
  __ bind(found);
  __ movl(rdx, Address(rbx, rcx, Address::times_8, 3 * BytesPerInt));
  __ profile_switch_case(rcx, rax, rbx);
  __ bind(continue_execution);
  __ bswapl(rdx);
  __ movl2ptr(rdx, rdx);
  __ load_unsigned_byte(rbx, Address(r13, rdx, Address::times_1));
  __ addptr(r13, rdx);
  __ dispatch_only(vtos);
}
void TemplateTable::fast_binaryswitch() {
  transition(itos, vtos);
  const Register key   = rax; // already set (tosca)
  const Register array = rbx;
  const Register i     = rcx;
  const Register j     = rdx;
  const Register h     = rdi;
  const Register temp  = rsi;
  __ lea(array, at_bcp(3 * BytesPerInt)); // btw: should be able to
  __ andptr(array, -BytesPerInt);
  __ xorl(i, i);                            // i = 0;
  __ movl(j, Address(array, -BytesPerInt)); // j = length(array);
  __ bswapl(j);
  Label entry;
  __ jmp(entry);
  {
    Label loop;
    __ bind(loop);
    __ leal(h, Address(i, j, Address::times_1)); // h = i + j;
    __ sarl(h, 1);                               // h = (i + j) >> 1;
    __ movl(temp, Address(array, h, Address::times_8));
    __ bswapl(temp);
    __ cmpl(key, temp);
    __ cmovl(Assembler::less, j, h);
    __ cmovl(Assembler::greaterEqual, i, h);
    __ bind(entry);
    __ leal(h, Address(i, 1)); // i+1
    __ cmpl(h, j);             // i+1 < j
    __ jcc(Assembler::less, loop);
  }
  Label default_case;
  __ movl(temp, Address(array, i, Address::times_8));
  __ bswapl(temp);
  __ cmpl(key, temp);
  __ jcc(Assembler::notEqual, default_case);
  __ movl(j , Address(array, i, Address::times_8, BytesPerInt));
  __ profile_switch_case(i, key, array);
  __ bswapl(j);
  __ movl2ptr(j, j);
  __ load_unsigned_byte(rbx, Address(r13, j, Address::times_1));
  __ addptr(r13, j);
  __ dispatch_only(vtos);
  __ bind(default_case);
  __ profile_switch_default(i);
  __ movl(j, Address(array, -2 * BytesPerInt));
  __ bswapl(j);
  __ movl2ptr(j, j);
  __ load_unsigned_byte(rbx, Address(r13, j, Address::times_1));
  __ addptr(r13, j);
  __ dispatch_only(vtos);
}
void TemplateTable::_return(TosState state) {
  transition(state, state);
  assert(_desc->calls_vm(),
         "inconsistent calls_vm information"); // call in remove_activation
  if (_desc->bytecode() == Bytecodes::_return_register_finalizer) {
    assert(state == vtos, "only valid state");
    __ movptr(c_rarg1, aaddress(0));
    __ load_klass(rdi, c_rarg1);
    __ movl(rdi, Address(rdi, Klass::access_flags_offset()));
    __ testl(rdi, JVM_ACC_HAS_FINALIZER);
    Label skip_register_finalizer;
    __ jcc(Assembler::zero, skip_register_finalizer);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::register_finalizer), c_rarg1);
    __ bind(skip_register_finalizer);
  }
  if (state == itos) {
    __ narrow(rax);
  }
  __ remove_activation(state, r13);
  __ jmp(r13);
}
void TemplateTable::volatile_barrier(AssemblerMembar_mask_bits
                                     order_constraint) {
  if (os::is_MP()) { // Not needed on single CPU
    __ membar(order_constraint);
  }
}
void TemplateTable::resolve_cache_and_index(int byte_no,
                                            Register Rcache,
                                            Register index,
                                            size_t index_size) {
  const Register temp = rbx;
  assert_different_registers(Rcache, index, temp);
  Label resolved;
    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
    __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
    __ cmpl(temp, (int) bytecode());  // have we resolved this bytecode?
    __ jcc(Assembler::equal, resolved);
  address entry;
  switch (bytecode()) {
  case Bytecodes::_getstatic:
  case Bytecodes::_putstatic:
  case Bytecodes::_getfield:
  case Bytecodes::_putfield:
    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_get_put);
    break;
  case Bytecodes::_invokevirtual:
  case Bytecodes::_invokespecial:
  case Bytecodes::_invokestatic:
  case Bytecodes::_invokeinterface:
    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invoke);
    break;
  case Bytecodes::_invokehandle:
    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);
    break;
  case Bytecodes::_invokedynamic:
    entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);
    break;
  default:
    fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
    break;
  }
  __ movl(temp, (int) bytecode());
  __ call_VM(noreg, entry, temp);
  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
  __ bind(resolved);
}
void TemplateTable::load_field_cp_cache_entry(Register obj,
                                              Register cache,
                                              Register index,
                                              Register off,
                                              Register flags,
                                              bool is_static = false) {
  assert_different_registers(cache, index, flags, off);
  ByteSize cp_base_offset = ConstantPoolCache::base_offset();
  __ movptr(off, Address(cache, index, Address::times_ptr,
                         in_bytes(cp_base_offset +
                                  ConstantPoolCacheEntry::f2_offset())));
  __ movl(flags, Address(cache, index, Address::times_ptr,
                         in_bytes(cp_base_offset +
                                  ConstantPoolCacheEntry::flags_offset())));
  if (is_static) {
    __ movptr(obj, Address(cache, index, Address::times_ptr,
                           in_bytes(cp_base_offset +
                                    ConstantPoolCacheEntry::f1_offset())));
    const int mirror_offset = in_bytes(Klass::java_mirror_offset());
    __ movptr(obj, Address(obj, mirror_offset));
  }
}
void TemplateTable::load_invoke_cp_cache_entry(int byte_no,
                                               Register method,
                                               Register itable_index,
                                               Register flags,
                                               bool is_invokevirtual,
                                               bool is_invokevfinal, /*unused*/
                                               bool is_invokedynamic) {
  const Register cache = rcx;
  const Register index = rdx;
  assert_different_registers(method, flags);
  assert_different_registers(method, cache, index);
  assert_different_registers(itable_index, flags);
  assert_different_registers(itable_index, cache, index);
  assert(is_invokevirtual == (byte_no == f2_byte), "is_invokevirtual flag redundant");
  const int method_offset = in_bytes(
    ConstantPoolCache::base_offset() +
      ((byte_no == f2_byte)
       ? ConstantPoolCacheEntry::f2_offset()
       : ConstantPoolCacheEntry::f1_offset()));
  const int flags_offset = in_bytes(ConstantPoolCache::base_offset() +
                                    ConstantPoolCacheEntry::flags_offset());
  const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
                                    ConstantPoolCacheEntry::f2_offset());
  size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
  resolve_cache_and_index(byte_no, cache, index, index_size);
    __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
  if (itable_index != noreg) {
    __ movptr(itable_index, Address(cache, index, Address::times_ptr, index_offset));
  }
  __ movl(flags, Address(cache, index, Address::times_ptr, flags_offset));
}
void TemplateTable::jvmti_post_field_access(Register cache, Register index,
                                            bool is_static, bool has_tos) {
  if (JvmtiExport::can_post_field_access()) {
    Label L1;
    assert_different_registers(cache, index, rax);
    __ mov32(rax, ExternalAddress((address) JvmtiExport::get_field_access_count_addr()));
    __ testl(rax, rax);
    __ jcc(Assembler::zero, L1);
    __ get_cache_and_index_at_bcp(c_rarg2, c_rarg3, 1);
    __ addptr(c_rarg2, in_bytes(ConstantPoolCache::base_offset()));
    __ shll(c_rarg3, LogBytesPerWord);
    __ addptr(c_rarg2, c_rarg3);
    if (is_static) {
      __ xorl(c_rarg1, c_rarg1); // NULL object reference
    } else {
      __ movptr(c_rarg1, at_tos()); // get object pointer without popping it
      __ verify_oop(c_rarg1);
    }
    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                                       InterpreterRuntime::post_field_access),
               c_rarg1, c_rarg2, c_rarg3);
    __ get_cache_and_index_at_bcp(cache, index, 1);
    __ bind(L1);
  }
}
void TemplateTable::pop_and_check_object(Register r) {
  __ pop_ptr(r);
  __ null_check(r);  // for field access must check obj.
  __ verify_oop(r);
}
void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
  transition(vtos, vtos);
  const Register cache = rcx;
  const Register index = rdx;
  const Register obj   = c_rarg3;
  const Register off   = rbx;
  const Register flags = rax;
  const Register bc = c_rarg3; // uses same reg as obj, so don't mix them
  resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
  jvmti_post_field_access(cache, index, is_static, false);
  load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
  if (!is_static) {
    pop_and_check_object(obj);
  }
  const Address field(obj, off, Address::times_1);
  Label Done, notByte, notBool, notInt, notShort, notChar,
              notLong, notFloat, notObj, notDouble;
  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  assert(btos == 0, "change code, btos != 0");
  __ andl(flags, ConstantPoolCacheEntry::tos_state_mask);
  __ jcc(Assembler::notZero, notByte);
  __ load_signed_byte(rax, field);
  __ push(btos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notByte);
  __ cmpl(flags, ztos);
  __ jcc(Assembler::notEqual, notBool);
  __ load_signed_byte(rax, field);
  __ push(ztos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notBool);
  __ cmpl(flags, atos);
  __ jcc(Assembler::notEqual, notObj);
  __ load_heap_oop(rax, field);
  __ push(atos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notObj);
  __ cmpl(flags, itos);
  __ jcc(Assembler::notEqual, notInt);
  __ movl(rax, field);
  __ push(itos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notInt);
  __ cmpl(flags, ctos);
  __ jcc(Assembler::notEqual, notChar);
  __ load_unsigned_short(rax, field);
  __ push(ctos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notChar);
  __ cmpl(flags, stos);
  __ jcc(Assembler::notEqual, notShort);
  __ load_signed_short(rax, field);
  __ push(stos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notShort);
  __ cmpl(flags, ltos);
  __ jcc(Assembler::notEqual, notLong);
  __ movq(rax, field);
  __ push(ltos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notLong);
  __ cmpl(flags, ftos);
  __ jcc(Assembler::notEqual, notFloat);
  __ movflt(xmm0, field);
  __ push(ftos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
  }
  __ jmp(Done);
  __ bind(notFloat);
#ifdef ASSERT
  __ cmpl(flags, dtos);
  __ jcc(Assembler::notEqual, notDouble);
#endif
  __ movdbl(xmm0, field);
  __ push(dtos);
  if (!is_static) {
    patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
  }
#ifdef ASSERT
  __ jmp(Done);
  __ bind(notDouble);
  __ stop("Bad state");
#endif
  __ bind(Done);
}
void TemplateTable::getfield(int byte_no) {
  getfield_or_static(byte_no, false);
}
void TemplateTable::getstatic(int byte_no) {
  getfield_or_static(byte_no, true);
}
void TemplateTable::jvmti_post_field_mod(Register cache, Register index, bool is_static) {
  transition(vtos, vtos);
  ByteSize cp_base_offset = ConstantPoolCache::base_offset();
  if (JvmtiExport::can_post_field_modification()) {
    Label L1;
    assert_different_registers(cache, index, rax);
    __ mov32(rax, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
    __ testl(rax, rax);
    __ jcc(Assembler::zero, L1);
    __ get_cache_and_index_at_bcp(c_rarg2, rscratch1, 1);
    if (is_static) {
      __ xorl(c_rarg1, c_rarg1);
    } else {
      __ movl(c_rarg3, Address(c_rarg2, rscratch1,
                           Address::times_8,
                           in_bytes(cp_base_offset +
                                     ConstantPoolCacheEntry::flags_offset())));
      __ shrl(c_rarg3, ConstantPoolCacheEntry::tos_state_shift);
      ConstantPoolCacheEntry::verify_tos_state_shift();
      __ movptr(c_rarg1, at_tos_p1());  // initially assume a one word jvalue
      __ cmpl(c_rarg3, ltos);
      __ cmovptr(Assembler::equal,
                 c_rarg1, at_tos_p2()); // ltos (two word jvalue)
      __ cmpl(c_rarg3, dtos);
      __ cmovptr(Assembler::equal,
                 c_rarg1, at_tos_p2()); // dtos (two word jvalue)
    }
    __ addptr(c_rarg2, in_bytes(cp_base_offset));
    __ shll(rscratch1, LogBytesPerWord);
    __ addptr(c_rarg2, rscratch1);
    __ mov(c_rarg3, rsp);
    __ call_VM(noreg,
               CAST_FROM_FN_PTR(address,
                                InterpreterRuntime::post_field_modification),
               c_rarg1, c_rarg2, c_rarg3);
    __ get_cache_and_index_at_bcp(cache, index, 1);
    __ bind(L1);
  }
}
void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
  transition(vtos, vtos);
  const Register cache = rcx;
  const Register index = rdx;
  const Register obj   = rcx;
  const Register off   = rbx;
  const Register flags = rax;
  const Register bc    = c_rarg3;
  resolve_cache_and_index(byte_no, cache, index, sizeof(u2));
  jvmti_post_field_mod(cache, index, is_static);
  load_field_cp_cache_entry(obj, cache, index, off, flags, is_static);
  Label notVolatile, Done;
  __ movl(rdx, flags);
  __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift);
  __ andl(rdx, 0x1);
  const Address field(obj, off, Address::times_1);
  Label notByte, notBool, notInt, notShort, notChar,
        notLong, notFloat, notObj, notDouble;
  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  assert(btos == 0, "change code, btos != 0");
  __ andl(flags, ConstantPoolCacheEntry::tos_state_mask);
  __ jcc(Assembler::notZero, notByte);
  {
    __ pop(btos);
    if (!is_static) pop_and_check_object(obj);
    __ movb(field, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notByte);
  __ cmpl(flags, ztos);
  __ jcc(Assembler::notEqual, notBool);
  {
    __ pop(ztos);
    if (!is_static) pop_and_check_object(obj);
    __ andl(rax, 0x1);
    __ movb(field, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_zputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notBool);
  __ cmpl(flags, atos);
  __ jcc(Assembler::notEqual, notObj);
  {
    __ pop(atos);
    if (!is_static) pop_and_check_object(obj);
    do_oop_store(_masm, field, rax, _bs->kind(), false);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notObj);
  __ cmpl(flags, itos);
  __ jcc(Assembler::notEqual, notInt);
  {
    __ pop(itos);
    if (!is_static) pop_and_check_object(obj);
    __ movl(field, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notInt);
  __ cmpl(flags, ctos);
  __ jcc(Assembler::notEqual, notChar);
  {
    __ pop(ctos);
    if (!is_static) pop_and_check_object(obj);
    __ movw(field, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notChar);
  __ cmpl(flags, stos);
  __ jcc(Assembler::notEqual, notShort);
  {
    __ pop(stos);
    if (!is_static) pop_and_check_object(obj);
    __ movw(field, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notShort);
  __ cmpl(flags, ltos);
  __ jcc(Assembler::notEqual, notLong);
  {
    __ pop(ltos);
    if (!is_static) pop_and_check_object(obj);
    __ movq(field, rax);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notLong);
  __ cmpl(flags, ftos);
  __ jcc(Assembler::notEqual, notFloat);
  {
    __ pop(ftos);
    if (!is_static) pop_and_check_object(obj);
    __ movflt(field, xmm0);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no);
    }
    __ jmp(Done);
  }
  __ bind(notFloat);
#ifdef ASSERT
  __ cmpl(flags, dtos);
  __ jcc(Assembler::notEqual, notDouble);
#endif
  {
    __ pop(dtos);
    if (!is_static) pop_and_check_object(obj);
    __ movdbl(field, xmm0);
    if (!is_static) {
      patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no);
    }
  }
#ifdef ASSERT
  __ jmp(Done);
  __ bind(notDouble);
  __ stop("Bad state");
#endif
  __ bind(Done);
  __ testl(rdx, rdx);
  __ jcc(Assembler::zero, notVolatile);
  volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
                                               Assembler::StoreStore));
  __ bind(notVolatile);
}
void TemplateTable::putfield(int byte_no) {
  putfield_or_static(byte_no, false);
}
void TemplateTable::putstatic(int byte_no) {
  putfield_or_static(byte_no, true);
}
void TemplateTable::jvmti_post_fast_field_mod() {
  if (JvmtiExport::can_post_field_modification()) {
    Label L2;
    __ mov32(c_rarg3, ExternalAddress((address)JvmtiExport::get_field_modification_count_addr()));
    __ testl(c_rarg3, c_rarg3);
    __ jcc(Assembler::zero, L2);
    __ pop_ptr(rbx);                  // copy the object pointer from tos
    __ verify_oop(rbx);
    __ push_ptr(rbx);                 // put the object pointer back on tos
    switch (bytecode()) {          // load values into the jvalue object
    case Bytecodes::_fast_aputfield: __ push_ptr(rax); break;
    case Bytecodes::_fast_bputfield: // fall through
    case Bytecodes::_fast_zputfield: // fall through
    case Bytecodes::_fast_sputfield: // fall through
    case Bytecodes::_fast_cputfield: // fall through
    case Bytecodes::_fast_iputfield: __ push_i(rax); break;
    case Bytecodes::_fast_dputfield: __ push_d(); break;
    case Bytecodes::_fast_fputfield: __ push_f(); break;
    case Bytecodes::_fast_lputfield: __ push_l(rax); break;
    default:
      ShouldNotReachHere();
    }
    __ mov(c_rarg3, rsp);             // points to jvalue on the stack
    __ get_cache_entry_pointer_at_bcp(c_rarg2, rax, 1);
    __ verify_oop(rbx);
    __ call_VM(noreg,
               CAST_FROM_FN_PTR(address,
                                InterpreterRuntime::post_field_modification),
               rbx, c_rarg2, c_rarg3);
    switch (bytecode()) {             // restore tos values
    case Bytecodes::_fast_aputfield: __ pop_ptr(rax); break;
    case Bytecodes::_fast_bputfield: // fall through
    case Bytecodes::_fast_zputfield: // fall through
    case Bytecodes::_fast_sputfield: // fall through
    case Bytecodes::_fast_cputfield: // fall through
    case Bytecodes::_fast_iputfield: __ pop_i(rax); break;
    case Bytecodes::_fast_dputfield: __ pop_d(); break;
    case Bytecodes::_fast_fputfield: __ pop_f(); break;
    case Bytecodes::_fast_lputfield: __ pop_l(rax); break;
    }
    __ bind(L2);
  }
}
void TemplateTable::fast_storefield(TosState state) {
  transition(state, vtos);
  ByteSize base = ConstantPoolCache::base_offset();
  jvmti_post_fast_field_mod();
  __ get_cache_and_index_at_bcp(rcx, rbx, 1);
  __ movl(rdx, Address(rcx, rbx, Address::times_8,
                       in_bytes(base +
                                ConstantPoolCacheEntry::flags_offset())));
  __ movptr(rbx, Address(rcx, rbx, Address::times_8,
                         in_bytes(base + ConstantPoolCacheEntry::f2_offset())));
  Label notVolatile;
  __ shrl(rdx, ConstantPoolCacheEntry::is_volatile_shift);
  __ andl(rdx, 0x1);
  pop_and_check_object(rcx);
  const Address field(rcx, rbx, Address::times_1);
  switch (bytecode()) {
  case Bytecodes::_fast_aputfield:
    do_oop_store(_masm, field, rax, _bs->kind(), false);
    break;
  case Bytecodes::_fast_lputfield:
    __ movq(field, rax);
    break;
  case Bytecodes::_fast_iputfield:
    __ movl(field, rax);
    break;
  case Bytecodes::_fast_zputfield:
    __ andl(rax, 0x1);  // boolean is true if LSB is 1
  case Bytecodes::_fast_bputfield:
    __ movb(field, rax);
    break;
  case Bytecodes::_fast_sputfield:
  case Bytecodes::_fast_cputfield:
    __ movw(field, rax);
    break;
  case Bytecodes::_fast_fputfield:
    __ movflt(field, xmm0);
    break;
  case Bytecodes::_fast_dputfield:
    __ movdbl(field, xmm0);
    break;
  default:
    ShouldNotReachHere();
  }
  __ testl(rdx, rdx);
  __ jcc(Assembler::zero, notVolatile);
  volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
                                               Assembler::StoreStore));
  __ bind(notVolatile);
}
void TemplateTable::fast_accessfield(TosState state) {
  transition(atos, state);
  if (JvmtiExport::can_post_field_access()) {
    Label L1;
    __ mov32(rcx, ExternalAddress((address) JvmtiExport::get_field_access_count_addr()));
    __ testl(rcx, rcx);
    __ jcc(Assembler::zero, L1);
    __ get_cache_entry_pointer_at_bcp(c_rarg2, rcx, 1);
    __ verify_oop(rax);
    __ push_ptr(rax);  // save object pointer before call_VM() clobbers it
    __ mov(c_rarg1, rax);
    __ call_VM(noreg,
               CAST_FROM_FN_PTR(address,
                                InterpreterRuntime::post_field_access),
               c_rarg1, c_rarg2);
    __ pop_ptr(rax); // restore object pointer
    __ bind(L1);
  }
  __ get_cache_and_index_at_bcp(rcx, rbx, 1);
  __ movptr(rbx, Address(rcx, rbx, Address::times_8,
                         in_bytes(ConstantPoolCache::base_offset() +
                                  ConstantPoolCacheEntry::f2_offset())));
  __ verify_oop(rax);
  __ null_check(rax);
  Address field(rax, rbx, Address::times_1);
  switch (bytecode()) {
  case Bytecodes::_fast_agetfield:
    __ load_heap_oop(rax, field);
    __ verify_oop(rax);
    break;
  case Bytecodes::_fast_lgetfield:
    __ movq(rax, field);
    break;
  case Bytecodes::_fast_igetfield:
    __ movl(rax, field);
    break;
  case Bytecodes::_fast_bgetfield:
    __ movsbl(rax, field);
    break;
  case Bytecodes::_fast_sgetfield:
    __ load_signed_short(rax, field);
    break;
  case Bytecodes::_fast_cgetfield:
    __ load_unsigned_short(rax, field);
    break;
  case Bytecodes::_fast_fgetfield:
    __ movflt(xmm0, field);
    break;
  case Bytecodes::_fast_dgetfield:
    __ movdbl(xmm0, field);
    break;
  default:
    ShouldNotReachHere();
  }
}
void TemplateTable::fast_xaccess(TosState state) {
  transition(vtos, state);
  __ movptr(rax, aaddress(0));
  __ get_cache_and_index_at_bcp(rcx, rdx, 2);
  __ movptr(rbx,
            Address(rcx, rdx, Address::times_8,
                    in_bytes(ConstantPoolCache::base_offset() +
                             ConstantPoolCacheEntry::f2_offset())));
  __ increment(r13);
  __ null_check(rax);
  switch (state) {
  case itos:
    __ movl(rax, Address(rax, rbx, Address::times_1));
    break;
  case atos:
    __ load_heap_oop(rax, Address(rax, rbx, Address::times_1));
    __ verify_oop(rax);
    break;
  case ftos:
    __ movflt(xmm0, Address(rax, rbx, Address::times_1));
    break;
  default:
    ShouldNotReachHere();
  }
  __ decrement(r13);
}
void TemplateTable::count_calls(Register method, Register temp) {
  ShouldNotReachHere();
}
void TemplateTable::prepare_invoke(int byte_no,
                                   Register method,  // linked method (or i-klass)
                                   Register index,   // itable index, MethodType, etc.
                                   Register recv,    // if caller wants to see it
                                   Register flags    // if caller wants to test it
                                   ) {
  const Bytecodes::Code code = bytecode();
  const bool is_invokeinterface  = code == Bytecodes::_invokeinterface;
  const bool is_invokedynamic    = code == Bytecodes::_invokedynamic;
  const bool is_invokehandle     = code == Bytecodes::_invokehandle;
  const bool is_invokevirtual    = code == Bytecodes::_invokevirtual;
  const bool is_invokespecial    = code == Bytecodes::_invokespecial;
  const bool load_receiver       = (recv  != noreg);
  const bool save_flags          = (flags != noreg);
  assert(load_receiver == (code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic), "");
  assert(save_flags    == (is_invokeinterface || is_invokevirtual), "need flags for vfinal");
  assert(flags == noreg || flags == rdx, "");
  assert(recv  == noreg || recv  == rcx, "");
  if (recv  == noreg)  recv  = rcx;
  if (flags == noreg)  flags = rdx;
  assert_different_registers(method, index, recv, flags);
  __ save_bcp();
  load_invoke_cp_cache_entry(byte_no, method, index, flags, is_invokevirtual, false, is_invokedynamic);
  if (is_invokedynamic || is_invokehandle) {
    Label L_no_push;
    __ testl(flags, (1 << ConstantPoolCacheEntry::has_appendix_shift));
    __ jcc(Assembler::zero, L_no_push);
    __ push(rbx);
    __ mov(rbx, index);
    assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
    __ load_resolved_reference_at_index(index, rbx);
    __ pop(rbx);
    __ push(index);  // push appendix (MethodType, CallSite, etc.)
    __ bind(L_no_push);
  }
  if (load_receiver) {
    __ movl(recv, flags);
    __ andl(recv, ConstantPoolCacheEntry::parameter_size_mask);
    const int no_return_pc_pushed_yet = -1;  // argument slot correction before we push return address
    const int receiver_is_at_end      = -1;  // back off one slot to get receiver
    Address recv_addr = __ argument_address(recv, no_return_pc_pushed_yet + receiver_is_at_end);
    __ movptr(recv, recv_addr);
    __ verify_oop(recv);
  }
  if (save_flags) {
    __ movl(r13, flags);
  }
  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
  ConstantPoolCacheEntry::verify_tos_state_shift();
  {
    const address table_addr = (address) Interpreter::invoke_return_entry_table_for(code);
    ExternalAddress table(table_addr);
    __ lea(rscratch1, table);
    __ movptr(flags, Address(rscratch1, flags, Address::times_ptr));
  }
  __ push(flags);
  if (save_flags) {
    __ movl(flags, r13);
    __ restore_bcp();
  }
}
void TemplateTable::invokevirtual_helper(Register index,
                                         Register recv,
                                         Register flags) {
  assert_different_registers(index, recv, rax, rdx);
  assert(index == rbx, "");
  assert(recv  == rcx, "");
  Label notFinal;
  __ movl(rax, flags);
  __ andl(rax, (1 << ConstantPoolCacheEntry::is_vfinal_shift));
  __ jcc(Assembler::zero, notFinal);
  const Register method = index;  // method must be rbx
  assert(method == rbx,
         "Method* must be rbx for interpreter calling convention");
  __ null_check(recv);
  __ profile_final_call(rax);
  __ profile_arguments_type(rax, method, r13, true);
  __ jump_from_interpreted(method, rax);
  __ bind(notFinal);
  __ null_check(recv, oopDesc::klass_offset_in_bytes());
  __ load_klass(rax, recv);
  __ profile_virtual_call(rax, r14, rdx);
  __ lookup_virtual_method(rax, index, method);
  __ profile_arguments_type(rdx, method, r13, true);
  __ jump_from_interpreted(method, rdx);
}
void TemplateTable::invokevirtual(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f2_byte, "use this argument");
  prepare_invoke(byte_no,
                 rbx,    // method or vtable index
                 noreg,  // unused itable index
                 rcx, rdx); // recv, flags
  invokevirtual_helper(rbx, rcx, rdx);
}
void TemplateTable::invokespecial(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  prepare_invoke(byte_no, rbx, noreg,  // get f1 Method*
                 rcx);  // get receiver also for null check
  __ verify_oop(rcx);
  __ null_check(rcx);
  __ profile_call(rax);
  __ profile_arguments_type(rax, rbx, r13, false);
  __ jump_from_interpreted(rbx, rax);
}
void TemplateTable::invokestatic(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  prepare_invoke(byte_no, rbx);  // get f1 Method*
  __ profile_call(rax);
  __ profile_arguments_type(rax, rbx, r13, false);
  __ jump_from_interpreted(rbx, rax);
}
void TemplateTable::fast_invokevfinal(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f2_byte, "use this argument");
  __ stop("fast_invokevfinal not used on amd64");
}
void TemplateTable::invokeinterface(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  prepare_invoke(byte_no, rax, rbx,  // get f1 Klass*, f2 Method*
                 rcx, rdx); // recv, flags
  Label notMethod;
  __ movl(r14, rdx);
  __ andl(r14, (1 << ConstantPoolCacheEntry::is_forced_virtual_shift));
  __ jcc(Assembler::zero, notMethod);
  invokevirtual_helper(rbx, rcx, rdx);
  __ bind(notMethod);
  __ restore_locals();  // restore r14
  __ null_check(rcx, oopDesc::klass_offset_in_bytes());
  __ load_klass(rdx, rcx);
  Label no_such_interface, no_such_method;
  __ lookup_interface_method(// inputs: rec. class, interface, itable index
                             rdx, rax, noreg,
                             r13, r14,
                             no_such_interface,
  __ restore_bcp(); // rbcp was destroyed by receiver type check
  __ profile_virtual_call(rdx, r13, r14);
  __ movptr(rax, Address(rbx, Method::const_offset()));
  __ movptr(rax, Address(rax, ConstMethod::constants_offset()));
  __ movptr(rax, Address(rax, ConstantPool::pool_holder_offset_in_bytes()));
  __ movl(rbx, Address(rbx, Method::itable_index_offset()));
  __ subl(rbx, Method::itable_index_max);
  __ negl(rbx);
  __ lookup_interface_method(// inputs: rec. class, interface, itable index
                             rdx, rax, rbx,
                             rbx, r13,
                             no_such_interface);
  __ testptr(rbx, rbx);
  __ jcc(Assembler::zero, no_such_method);
  __ profile_arguments_type(rdx, rbx, r13, true);
  __ jump_from_interpreted(rbx, rdx);
  __ should_not_reach_here();
  __ bind(no_such_method);
  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  __ restore_bcp();      // r13 must be correct for exception handler   (was destroyed)
  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::throw_AbstractMethodError));
  __ should_not_reach_here();
  __ bind(no_such_interface);
  __ pop(rbx);           // pop return address (pushed by prepare_invoke)
  __ restore_bcp();      // r13 must be correct for exception handler   (was destroyed)
  __ restore_locals();   // make sure locals pointer is correct as well (was destroyed)
  __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                   InterpreterRuntime::throw_IncompatibleClassChangeError));
  __ should_not_reach_here();
}
void TemplateTable::invokehandle(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  const Register rbx_method = rbx;
  const Register rax_mtype  = rax;
  const Register rcx_recv   = rcx;
  const Register rdx_flags  = rdx;
  if (!EnableInvokeDynamic) {
    __ should_not_reach_here();
    return;
  }
  prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv);
  __ verify_method_ptr(rbx_method);
  __ verify_oop(rcx_recv);
  __ null_check(rcx_recv);
  __ profile_final_call(rax);
  __ profile_arguments_type(rdx, rbx_method, r13, true);
  __ jump_from_interpreted(rbx_method, rdx);
}
void TemplateTable::invokedynamic(int byte_no) {
  transition(vtos, vtos);
  assert(byte_no == f1_byte, "use this argument");
  if (!EnableInvokeDynamic) {
    __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                     InterpreterRuntime::throw_IncompatibleClassChangeError));
    __ should_not_reach_here();
    return;
  }
  const Register rbx_method   = rbx;
  const Register rax_callsite = rax;
  prepare_invoke(byte_no, rbx_method, rax_callsite);
  __ profile_call(r13);
  __ profile_arguments_type(rdx, rbx_method, r13, false);
  __ verify_oop(rax_callsite);
  __ jump_from_interpreted(rbx_method, rdx);
}
void TemplateTable::_new() {
  transition(vtos, atos);
  __ get_unsigned_2_byte_index_at_bcp(rdx, 1);
  Label slow_case;
  Label done;
  Label initialize_header;
  Label initialize_object; // including clearing the fields
  Label allocate_shared;
  __ get_cpool_and_tags(rsi, rax);
  const int tags_offset = Array<u1>::base_offset_in_bytes();
  __ cmpb(Address(rax, rdx, Address::times_1, tags_offset),
          JVM_CONSTANT_Class);
  __ jcc(Assembler::notEqual, slow_case);
  __ movptr(rsi, Address(rsi, rdx,
            Address::times_8, sizeof(ConstantPool)));
  __ cmpb(Address(rsi,
                  InstanceKlass::init_state_offset()),
          InstanceKlass::fully_initialized);
  __ jcc(Assembler::notEqual, slow_case);
  __ movl(rdx,
          Address(rsi,
                  Klass::layout_helper_offset()));
  __ testl(rdx, Klass::_lh_instance_slow_path_bit);
  __ jcc(Assembler::notZero, slow_case);
  const bool allow_shared_alloc =
    Universe::heap()->supports_inline_contig_alloc() && !CMSIncrementalMode;
  if (UseTLAB) {
    __ movptr(rax, Address(r15_thread, in_bytes(JavaThread::tlab_top_offset())));
    __ lea(rbx, Address(rax, rdx, Address::times_1));
    __ cmpptr(rbx, Address(r15_thread, in_bytes(JavaThread::tlab_end_offset())));
    __ jcc(Assembler::above, allow_shared_alloc ? allocate_shared : slow_case);
    __ movptr(Address(r15_thread, in_bytes(JavaThread::tlab_top_offset())), rbx);
    if (ZeroTLAB) {
      __ jmp(initialize_header);
    } else {
      __ jmp(initialize_object);
    }
  }
  if (allow_shared_alloc) {
    __ bind(allocate_shared);
    ExternalAddress top((address)Universe::heap()->top_addr());
    ExternalAddress end((address)Universe::heap()->end_addr());
    const Register RtopAddr = rscratch1;
    const Register RendAddr = rscratch2;
    __ lea(RtopAddr, top);
    __ lea(RendAddr, end);
    __ movptr(rax, Address(RtopAddr, 0));
    Label retry;
    __ bind(retry);
    __ lea(rbx, Address(rax, rdx, Address::times_1));
    __ cmpptr(rbx, Address(RendAddr, 0));
    __ jcc(Assembler::above, slow_case);
    if (os::is_MP()) {
      __ lock();
    }
    __ cmpxchgptr(rbx, Address(RtopAddr, 0));
    __ jcc(Assembler::notEqual, retry);
    __ incr_allocated_bytes(r15_thread, rdx, 0);
  }
  if (UseTLAB || Universe::heap()->supports_inline_contig_alloc()) {
    __ bind(initialize_object);
    __ decrementl(rdx, sizeof(oopDesc));
    __ jcc(Assembler::zero, initialize_header);
    __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code)
    __ shrl(rdx, LogBytesPerLong);  // divide by oopSize to simplify the loop
    {
      Label loop;
      __ bind(loop);
      __ movq(Address(rax, rdx, Address::times_8,
                      sizeof(oopDesc) - oopSize),
              rcx);
      __ decrementl(rdx);
      __ jcc(Assembler::notZero, loop);
    }
    __ bind(initialize_header);
    if (UseBiasedLocking) {
      __ movptr(rscratch1, Address(rsi, Klass::prototype_header_offset()));
      __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()), rscratch1);
    } else {
      __ movptr(Address(rax, oopDesc::mark_offset_in_bytes()),
               (intptr_t) markOopDesc::prototype()); // header (address 0x1)
    }
    __ xorl(rcx, rcx); // use zero reg to clear memory (shorter code)
    __ store_klass_gap(rax, rcx);  // zero klass gap for compressed oops
    __ store_klass(rax, rsi);      // store klass last
    {
      SkipIfEqual skip(_masm, &DTraceAllocProbes, false);
      __ push(atos); // save the return value
      __ call_VM_leaf(
           CAST_FROM_FN_PTR(address, SharedRuntime::dtrace_object_alloc), rax);
      __ pop(atos); // restore the return value
    }
    __ jmp(done);
  }
  __ bind(slow_case);
  __ get_constant_pool(c_rarg1);
  __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1);
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::_new), c_rarg1, c_rarg2);
  __ verify_oop(rax);
  __ bind(done);
}
void TemplateTable::newarray() {
  transition(itos, atos);
  __ load_unsigned_byte(c_rarg1, at_bcp(1));
  __ movl(c_rarg2, rax);
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::newarray),
          c_rarg1, c_rarg2);
}
void TemplateTable::anewarray() {
  transition(itos, atos);
  __ get_unsigned_2_byte_index_at_bcp(c_rarg2, 1);
  __ get_constant_pool(c_rarg1);
  __ movl(c_rarg3, rax);
  call_VM(rax, CAST_FROM_FN_PTR(address, InterpreterRuntime::anewarray),
          c_rarg1, c_rarg2, c_rarg3);
}
void TemplateTable::arraylength() {
  transition(atos, itos);
  __ null_check(rax, arrayOopDesc::length_offset_in_bytes());
  __ movl(rax, Address(rax, arrayOopDesc::length_offset_in_bytes()));
}
void TemplateTable::checkcast() {
  transition(atos, atos);
  Label done, is_null, ok_is_subtype, quicked, resolved;
  __ testptr(rax, rax); // object is in rax
  __ jcc(Assembler::zero, is_null);
  __ get_cpool_and_tags(rcx, rdx); // rcx=cpool, rdx=tags array
  __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // rbx=index
  __ cmpb(Address(rdx, rbx,
                  Address::times_1,
                  Array<u1>::base_offset_in_bytes()),
          JVM_CONSTANT_Class);
  __ jcc(Assembler::equal, quicked);
  __ push(atos); // save receiver for result, and for GC
  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
  __ get_vm_result_2(rax, r15_thread);
  __ pop_ptr(rdx); // restore receiver
  __ jmpb(resolved);
  __ bind(quicked);
  __ mov(rdx, rax); // Save object in rdx; rax needed for subtype check
  __ movptr(rax, Address(rcx, rbx,
                       Address::times_8, sizeof(ConstantPool)));
  __ bind(resolved);
  __ load_klass(rbx, rdx);
  __ gen_subtype_check(rbx, ok_is_subtype);
  __ push_ptr(rdx);
  __ jump(ExternalAddress(Interpreter::_throw_ClassCastException_entry));
  __ bind(ok_is_subtype);
  __ mov(rax, rdx); // Restore object in rdx
  if (ProfileInterpreter) {
    __ jmp(done);
    __ bind(is_null);
    __ profile_null_seen(rcx);
  } else {
    __ bind(is_null);   // same as 'done'
  }
  __ bind(done);
}
void TemplateTable::instanceof() {
  transition(atos, itos);
  Label done, is_null, ok_is_subtype, quicked, resolved;
  __ testptr(rax, rax);
  __ jcc(Assembler::zero, is_null);
  __ get_cpool_and_tags(rcx, rdx); // rcx=cpool, rdx=tags array
  __ get_unsigned_2_byte_index_at_bcp(rbx, 1); // rbx=index
  __ cmpb(Address(rdx, rbx,
                  Address::times_1,
                  Array<u1>::base_offset_in_bytes()),
          JVM_CONSTANT_Class);
  __ jcc(Assembler::equal, quicked);
  __ push(atos); // save receiver for result, and for GC
  call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::quicken_io_cc));
  __ get_vm_result_2(rax, r15_thread);
  __ pop_ptr(rdx); // restore receiver
  __ verify_oop(rdx);
  __ load_klass(rdx, rdx);
  __ jmpb(resolved);
  __ bind(quicked);
  __ load_klass(rdx, rax);
  __ movptr(rax, Address(rcx, rbx,
                         Address::times_8, sizeof(ConstantPool)));
  __ bind(resolved);
  __ gen_subtype_check(rdx, ok_is_subtype);
  __ xorl(rax, rax);
  __ jmpb(done);
  __ bind(ok_is_subtype);
  __ movl(rax, 1);
  if (ProfileInterpreter) {
    __ jmp(done);
    __ bind(is_null);
    __ profile_null_seen(rcx);
  } else {
    __ bind(is_null);   // same as 'done'
  }
  __ bind(done);
}
void TemplateTable::_breakpoint() {
  transition(vtos, vtos);
  __ get_method(c_rarg1);
  __ call_VM(noreg,
             CAST_FROM_FN_PTR(address,
                              InterpreterRuntime::get_original_bytecode_at),
             c_rarg1, r13);
  __ mov(rbx, rax);
  __ get_method(c_rarg1);
  __ call_VM(noreg,
             CAST_FROM_FN_PTR(address, InterpreterRuntime::_breakpoint),
             c_rarg1, r13);
  __ dispatch_only_normal(vtos);
}
void TemplateTable::athrow() {
  transition(atos, vtos);
  __ null_check(rax);
  __ jump(ExternalAddress(Interpreter::throw_exception_entry()));
}
void TemplateTable::monitorenter() {
  transition(atos, vtos);
  __ null_check(rax);
  const Address monitor_block_top(
        rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
  const Address monitor_block_bot(
        rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
  const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
  Label allocated;
  __ xorl(c_rarg1, c_rarg1); // points to free slot or NULL
  {
    Label entry, loop, exit;
    __ movptr(c_rarg3, monitor_block_top); // points to current entry,
    __ lea(c_rarg2, monitor_block_bot); // points to word before bottom
    __ jmpb(entry);
    __ bind(loop);
    __ cmpptr(Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes()), (int32_t) NULL_WORD);
    __ cmov(Assembler::equal, c_rarg1, c_rarg3);
    __ cmpptr(rax, Address(c_rarg3, BasicObjectLock::obj_offset_in_bytes()));
    __ jccb(Assembler::equal, exit);
    __ addptr(c_rarg3, entry_size);
    __ bind(entry);
    __ cmpptr(c_rarg3, c_rarg2);
    __ jcc(Assembler::notEqual, loop);
    __ bind(exit);
  }
  __ testptr(c_rarg1, c_rarg1); // check if a slot has been found
  __ jcc(Assembler::notZero, allocated); // if found, continue with that one
  {
    Label entry, loop;
    __ movptr(c_rarg1, monitor_block_bot); // c_rarg1: old expression stack bottom
    __ subptr(rsp, entry_size);            // move expression stack top
    __ subptr(c_rarg1, entry_size);        // move expression stack bottom
    __ mov(c_rarg3, rsp);                  // set start value for copy loop
    __ movptr(monitor_block_bot, c_rarg1); // set new monitor block bottom
    __ jmp(entry);
    __ bind(loop);
    __ movptr(c_rarg2, Address(c_rarg3, entry_size)); // load expression stack
    __ movptr(Address(c_rarg3, 0), c_rarg2);          // and store it at new location
    __ addptr(c_rarg3, wordSize);                     // advance to next word
    __ bind(entry);
    __ cmpptr(c_rarg3, c_rarg1);            // check if bottom reached
    __ jcc(Assembler::notEqual, loop);      // if not at bottom then
  }
  __ bind(allocated);
  __ increment(r13);
  __ movptr(Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()), rax);
  __ lock_object(c_rarg1);
  __ save_bcp();  // in case of exception
  __ generate_stack_overflow_check(0);
  __ dispatch_next(vtos);
}
void TemplateTable::monitorexit() {
  transition(atos, vtos);
  __ null_check(rax);
  const Address monitor_block_top(
        rbp, frame::interpreter_frame_monitor_block_top_offset * wordSize);
  const Address monitor_block_bot(
        rbp, frame::interpreter_frame_initial_sp_offset * wordSize);
  const int entry_size = frame::interpreter_frame_monitor_size() * wordSize;
  Label found;
  {
    Label entry, loop;
    __ movptr(c_rarg1, monitor_block_top); // points to current entry,
    __ lea(c_rarg2, monitor_block_bot); // points to word before bottom
    __ jmpb(entry);
    __ bind(loop);
    __ cmpptr(rax, Address(c_rarg1, BasicObjectLock::obj_offset_in_bytes()));
    __ jcc(Assembler::equal, found);
    __ addptr(c_rarg1, entry_size);
    __ bind(entry);
    __ cmpptr(c_rarg1, c_rarg2);
    __ jcc(Assembler::notEqual, loop);
  }
  __ call_VM(noreg, CAST_FROM_FN_PTR(address,
                   InterpreterRuntime::throw_illegal_monitor_state_exception));
  __ should_not_reach_here();
  __ bind(found);
  __ push_ptr(rax); // make sure object is on stack (contract with oopMaps)
  __ unlock_object(c_rarg1);
  __ pop_ptr(rax); // discard object
}
void TemplateTable::wide() {
  transition(vtos, vtos);
  __ load_unsigned_byte(rbx, at_bcp(1));
  __ lea(rscratch1, ExternalAddress((address)Interpreter::_wentry_point));
  __ jmp(Address(rscratch1, rbx, Address::times_8));
}
void TemplateTable::multianewarray() {
  transition(vtos, atos);
  __ load_unsigned_byte(rax, at_bcp(3)); // get number of dimensions
  __ lea(c_rarg1, Address(rsp, rax, Address::times_8, -wordSize));
  call_VM(rax,
          CAST_FROM_FN_PTR(address, InterpreterRuntime::multianewarray),
          c_rarg1);
  __ load_unsigned_byte(rbx, at_bcp(3));
  __ lea(rsp, Address(rsp, rbx, Address::times_8));
}
#endif // !CC_INTERP
C:\hotspot-69087d08d473\src\cpu\x86\vm/templateTable_x86_64.hpp
#ifndef CPU_X86_VM_TEMPLATETABLE_X86_64_HPP
#define CPU_X86_VM_TEMPLATETABLE_X86_64_HPP
  static void prepare_invoke(int byte_no,
                             Register method,         // linked method (or i-klass)
                             Register index = noreg,  // itable index, MethodType, etc.
                             Register recv  = noreg,  // if caller wants to see it
                             Register flags = noreg   // if caller wants to test it
                             );
  static void invokevirtual_helper(Register index, Register recv,
                                   Register flags);
  static void volatile_barrier(Assembler::Membar_mask_bits order_constraint);
  static void index_check(Register array, Register index);
  static void index_check_without_pop(Register array, Register index);
#endif // CPU_X86_VM_TEMPLATETABLE_X86_64_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/vmreg_x86.cpp
#include "precompiled.hpp"
#include "asm/assembler.hpp"
#include "code/vmreg.hpp"
void VMRegImpl::set_regName() {
  Register reg = ::as_Register(0);
  int i;
  for (i = 0; i < ConcreteRegisterImpl::max_gpr ; ) {
    regName[i++] = reg->name();
#ifdef AMD64
    regName[i++] = reg->name();
#endif // AMD64
    reg = reg->successor();
  }
  FloatRegister freg = ::as_FloatRegister(0);
  for ( ; i < ConcreteRegisterImpl::max_fpr ; ) {
    regName[i++] = freg->name();
    regName[i++] = freg->name();
    freg = freg->successor();
  }
  XMMRegister xreg = ::as_XMMRegister(0);
  for ( ; i < ConcreteRegisterImpl::max_xmm ; ) {
    for (int j = 0 ; j < 8 ; j++) {
      regName[i++] = xreg->name();
    }
    xreg = xreg->successor();
  }
  for ( ; i < ConcreteRegisterImpl::number_of_registers ; i ++ ) {
    regName[i] = "NON-GPR-FPR-XMM";
  }
}
C:\hotspot-69087d08d473\src\cpu\x86\vm/vmreg_x86.hpp
#ifndef CPU_X86_VM_VMREG_X86_HPP
#define CPU_X86_VM_VMREG_X86_HPP
  bool is_Register();
  Register as_Register();
  bool is_FloatRegister();
  FloatRegister as_FloatRegister();
  bool is_XMMRegister();
  XMMRegister as_XMMRegister();
#endif // CPU_X86_VM_VMREG_X86_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/vmreg_x86.inline.hpp
#ifndef CPU_X86_VM_VMREG_X86_INLINE_HPP
#define CPU_X86_VM_VMREG_X86_INLINE_HPP
inline VMReg RegisterImpl::as_VMReg() {
  if( this==noreg ) return VMRegImpl::Bad();
#ifdef AMD64
  return VMRegImpl::as_VMReg(encoding() << 1 );
#else
  return VMRegImpl::as_VMReg(encoding() );
#endif // AMD64
}
inline VMReg FloatRegisterImpl::as_VMReg() {
  return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr);
}
inline VMReg XMMRegisterImpl::as_VMReg() {
  return VMRegImpl::as_VMReg((encoding() << 3) + ConcreteRegisterImpl::max_fpr);
}
inline bool VMRegImpl::is_Register() {
  return (unsigned int) value() < (unsigned int) ConcreteRegisterImpl::max_gpr;
}
inline bool VMRegImpl::is_FloatRegister() {
  return value() >= ConcreteRegisterImpl::max_gpr && value() < ConcreteRegisterImpl::max_fpr;
}
inline bool VMRegImpl::is_XMMRegister() {
  return value() >= ConcreteRegisterImpl::max_fpr && value() < ConcreteRegisterImpl::max_xmm;
}
inline Register VMRegImpl::as_Register() {
  assert( is_Register(), "must be");
#ifdef AMD64
  return ::as_Register(value() >> 1);
#else
  return ::as_Register(value());
#endif // AMD64
}
inline FloatRegister VMRegImpl::as_FloatRegister() {
  assert( is_FloatRegister() && is_even(value()), "must be" );
  return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1);
}
inline XMMRegister VMRegImpl::as_XMMRegister() {
  assert( is_XMMRegister() && is_even(value()), "must be" );
  return ::as_XMMRegister((value() - ConcreteRegisterImpl::max_fpr) >> 3);
}
inline   bool VMRegImpl::is_concrete() {
  assert(is_reg(), "must be");
#ifndef AMD64
  if (is_Register()) return true;
#endif // AMD64
  return is_even(value());
}
#endif // CPU_X86_VM_VMREG_X86_INLINE_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/vmStructs_x86.hpp
#ifndef CPU_X86_VM_VMSTRUCTS_X86_HPP
#define CPU_X86_VM_VMSTRUCTS_X86_HPP
#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field)            \
                                                                                                                                     \
  volatile_nonstatic_field(JavaFrameAnchor,     _last_Java_fp,                                    intptr_t*)
#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type, declare_c1_toplevel_type, declare_c2_type, declare_c2_toplevel_type)
#define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
#endif // CPU_X86_VM_VMSTRUCTS_X86_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/vm_version_ext_x86.cpp
#include "precompiled.hpp"
#include "jvm.h"
#include "utilities/macros.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_ext_x86.hpp"
typedef enum {
   CPU_FAMILY_8086_8088  = 0,
   CPU_FAMILY_INTEL_286  = 2,
   CPU_FAMILY_INTEL_386  = 3,
   CPU_FAMILY_INTEL_486  = 4,
   CPU_FAMILY_PENTIUM    = 5,
   CPU_FAMILY_PENTIUMPRO = 6,    // Same family several models
   CPU_FAMILY_PENTIUM_4  = 0xF
} FamilyFlag;
 typedef enum {
    RDTSCP_FLAG  = 0x08000000, // bit 27
    INTEL64_FLAG = 0x20000000  // bit 29
  } _featureExtendedEdxFlag;
#define CPUID_STANDARD_FN   0x0
#define CPUID_STANDARD_FN_1 0x1
#define CPUID_STANDARD_FN_4 0x4
#define CPUID_STANDARD_FN_B 0xb
#define CPUID_EXTENDED_FN   0x80000000
#define CPUID_EXTENDED_FN_1 0x80000001
#define CPUID_EXTENDED_FN_2 0x80000002
#define CPUID_EXTENDED_FN_3 0x80000003
#define CPUID_EXTENDED_FN_4 0x80000004
#define CPUID_EXTENDED_FN_7 0x80000007
#define CPUID_EXTENDED_FN_8 0x80000008
typedef enum {
   FPU_FLAG     = 0x00000001,
   VME_FLAG     = 0x00000002,
   DE_FLAG      = 0x00000004,
   PSE_FLAG     = 0x00000008,
   TSC_FLAG     = 0x00000010,
   MSR_FLAG     = 0x00000020,
   PAE_FLAG     = 0x00000040,
   MCE_FLAG     = 0x00000080,
   CX8_FLAG     = 0x00000100,
   APIC_FLAG    = 0x00000200,
   SEP_FLAG     = 0x00000800,
   MTRR_FLAG    = 0x00001000,
   PGE_FLAG     = 0x00002000,
   MCA_FLAG     = 0x00004000,
   CMOV_FLAG    = 0x00008000,
   PAT_FLAG     = 0x00010000,
   PSE36_FLAG   = 0x00020000,
   PSNUM_FLAG   = 0x00040000,
   CLFLUSH_FLAG = 0x00080000,
   DTS_FLAG     = 0x00200000,
   ACPI_FLAG    = 0x00400000,
   MMX_FLAG     = 0x00800000,
   FXSR_FLAG    = 0x01000000,
   SSE_FLAG     = 0x02000000,
   SSE2_FLAG    = 0x04000000,
   SS_FLAG      = 0x08000000,
   HTT_FLAG     = 0x10000000,
   TM_FLAG      = 0x20000000
} FeatureEdxFlag;
static BufferBlob* cpuid_brand_string_stub_blob;
static const int   cpuid_brand_string_stub_size = 550;
extern "C" {
  typedef void (*getCPUIDBrandString_stub_t)(void*);
}
static getCPUIDBrandString_stub_t getCPUIDBrandString_stub = NULL;
class VM_Version_Ext_StubGenerator: public StubCodeGenerator {
 public:
  VM_Version_Ext_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
  address generate_getCPUIDBrandString(void) {
    const uint32_t HS_EFL_AC           = 0x40000;
    const uint32_t HS_EFL_ID           = 0x200000;
    const int      CPU_FAMILY_SHIFT = 8;
    const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
    const uint32_t CPU_FAMILY_486   = (4 << CPU_FAMILY_SHIFT);
    Label detect_486, cpu486, detect_586, done, ext_cpuid;
    StubCodeMark mark(this, "VM_Version_Ext", "getCPUIDNameInfo_stub");
#   define __ _masm->
    address start = __ pc();
    __ push(rbp);
#ifdef _LP64
    __ mov(rbp, c_rarg0); // cpuid_info address
#else
    __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
#endif
    __ push(rbx);
    __ push(rsi);
    __ pushf();          // preserve rbx, and flags
    __ pop(rax);
    __ push(rax);
    __ mov(rcx, rax);
    __ xorl(rax, HS_EFL_AC);
    __ push(rax);
    __ popf();
    __ pushf();
    __ pop(rax);
    __ cmpptr(rax, rcx);
    __ jccb(Assembler::notEqual, detect_486);
    __ movl(rax, CPU_FAMILY_386);
    __ jmp(done);
    __ bind(detect_486);
    __ mov(rax, rcx);
    __ xorl(rax, HS_EFL_ID);
    __ push(rax);
    __ popf();
    __ pushf();
    __ pop(rax);
    __ cmpptr(rcx, rax);
    __ jccb(Assembler::notEqual, detect_586);
    __ bind(cpu486);
    __ movl(rax, CPU_FAMILY_486);
    __ jmp(done);
    __ bind(detect_586);
    __ xorl(rax, rax);
    __ cpuid();
    __ orl(rax, rax);
    __ jcc(Assembler::equal, cpu486);   // if cpuid doesn't support an input
    __ bind(ext_cpuid);
    __ movl(rax, CPUID_EXTENDED_FN);
    __ cpuid();
    __ cmpl(rax, CPUID_EXTENDED_FN_4);
    __ jcc(Assembler::below, done);
    __ movl(rax, CPUID_EXTENDED_FN_2);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_0_offset())));
    __ movl(Address(rsi, 0), rax);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_1_offset())));
    __ movl(Address(rsi, 0), rbx);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_2_offset())));
    __ movl(Address(rsi, 0), rcx);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_3_offset())));
    __ movl(Address(rsi,0), rdx);
    __ movl(rax, CPUID_EXTENDED_FN_3);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_4_offset())));
    __ movl(Address(rsi, 0), rax);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_5_offset())));
    __ movl(Address(rsi, 0), rbx);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_6_offset())));
    __ movl(Address(rsi, 0), rcx);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_7_offset())));
    __ movl(Address(rsi,0), rdx);
    __ movl(rax, CPUID_EXTENDED_FN_4);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_8_offset())));
    __ movl(Address(rsi, 0), rax);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_9_offset())));
    __ movl(Address(rsi, 0), rbx);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_10_offset())));
    __ movl(Address(rsi, 0), rcx);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version_Ext::proc_name_11_offset())));
    __ movl(Address(rsi,0), rdx);
    __ bind(done);
    __ popf();
    __ pop(rsi);
    __ pop(rbx);
    __ pop(rbp);
    __ ret(0);
#   undef __
    return start;
  };
};
const size_t VM_Version_Ext::VENDOR_LENGTH = 13;
const size_t VM_Version_Ext::CPU_EBS_MAX_LENGTH = (3 * 4 * 4 + 1);
const size_t VM_Version_Ext::CPU_TYPE_DESC_BUF_SIZE = 256;
const size_t VM_Version_Ext::CPU_DETAILED_DESC_BUF_SIZE = 4096;
char* VM_Version_Ext::_cpu_brand_string = NULL;
jlong VM_Version_Ext::_max_qualified_cpu_frequency = 0;
int VM_Version_Ext::_no_of_threads = 0;
int VM_Version_Ext::_no_of_cores = 0;
int VM_Version_Ext::_no_of_packages = 0;
void VM_Version_Ext::initialize(void) {
  ResourceMark rm;
  cpuid_brand_string_stub_blob = BufferBlob::create("getCPUIDBrandString_stub", cpuid_brand_string_stub_size);
  if (cpuid_brand_string_stub_blob == NULL) {
    vm_exit_during_initialization("Unable to allocate getCPUIDBrandString_stub");
  }
  CodeBuffer c(cpuid_brand_string_stub_blob);
  VM_Version_Ext_StubGenerator g(&c);
  getCPUIDBrandString_stub = CAST_TO_FN_PTR(getCPUIDBrandString_stub_t,
                                   g.generate_getCPUIDBrandString());
}
const char* VM_Version_Ext::cpu_model_description(void) {
  uint32_t cpu_family = extended_cpu_family();
  uint32_t cpu_model = extended_cpu_model();
  const char* model = NULL;
  if (cpu_family == CPU_FAMILY_PENTIUMPRO) {
    for (uint32_t i = 0; i <= cpu_model; i++) {
      model = _model_id_pentium_pro[i];
      if (model == NULL) {
        break;
      }
    }
  }
  return model;
}
const char* VM_Version_Ext::cpu_brand_string(void) {
  if (_cpu_brand_string == NULL) {
    _cpu_brand_string = NEW_C_HEAP_ARRAY_RETURN_NULL(char, CPU_EBS_MAX_LENGTH, mtInternal);
    if (NULL == _cpu_brand_string) {
      return NULL;
    }
    int ret_val = cpu_extended_brand_string(_cpu_brand_string, CPU_EBS_MAX_LENGTH);
    if (ret_val != OS_OK) {
      FREE_C_HEAP_ARRAY(char, _cpu_brand_string, mtInternal);
      _cpu_brand_string = NULL;
    }
  }
  return _cpu_brand_string;
}
const char* VM_Version_Ext::cpu_brand(void) {
  const char*  brand  = NULL;
  if ((_cpuid_info.std_cpuid1_ebx.value & 0xFF) > 0) {
    int brand_num = _cpuid_info.std_cpuid1_ebx.value & 0xFF;
    brand = _brand_id[0];
    for (int i = 0; brand != NULL && i <= brand_num; i += 1) {
      brand = _brand_id[i];
    }
  }
  return brand;
}
bool VM_Version_Ext::cpu_is_em64t(void) {
  return ((_cpuid_info.ext_cpuid1_edx.value & INTEL64_FLAG) == INTEL64_FLAG);
}
bool VM_Version_Ext::is_netburst(void) {
  return (is_intel() && (extended_cpu_family() == CPU_FAMILY_PENTIUM_4));
}
bool VM_Version_Ext::supports_tscinv_ext(void) {
  if (!supports_tscinv_bit()) {
    return false;
  }
  if (is_intel()) {
    return true;
  }
  if (is_amd()) {
    return !is_amd_Barcelona();
  }
  return false;
}
void VM_Version_Ext::resolve_cpu_information_details(void) {
  _no_of_threads = os::processor_count();
  int threads_per_package = threads_per_core() * cores_per_cpu();
  _no_of_packages = _no_of_threads / threads_per_package;
  if (0 == _no_of_packages) {
    _no_of_packages = 1;
  }
  _no_of_cores = cores_per_cpu() * _no_of_packages;
}
int VM_Version_Ext::number_of_threads(void) {
  if (_no_of_threads == 0) {
   resolve_cpu_information_details();
  }
  return _no_of_threads;
}
int VM_Version_Ext::number_of_cores(void) {
  if (_no_of_cores == 0) {
    resolve_cpu_information_details();
  }
  return _no_of_cores;
}
int VM_Version_Ext::number_of_sockets(void) {
  if (_no_of_packages == 0) {
    resolve_cpu_information_details();
  }
  return _no_of_packages;
}
const char* VM_Version_Ext::cpu_family_description(void) {
  int cpu_family_id = extended_cpu_family();
  if (is_amd()) {
    return _family_id_amd[cpu_family_id];
  }
  if (is_intel()) {
    if (cpu_family_id == CPU_FAMILY_PENTIUMPRO) {
      return cpu_model_description();
    }
    return _family_id_intel[cpu_family_id];
  }
  return "Unknown x86";
}
int VM_Version_Ext::cpu_type_description(char* const buf, size_t buf_len) {
  assert(buf != NULL, "buffer is NULL!");
  assert(buf_len >= CPU_TYPE_DESC_BUF_SIZE, "buffer len should at least be == CPU_TYPE_DESC_BUF_SIZE!");
  const char* cpu_type = NULL;
  const char* x64 = NULL;
  if (is_intel()) {
    cpu_type = "Intel";
    x64 = cpu_is_em64t() ? " Intel64" : "";
  } else if (is_amd()) {
    cpu_type = "AMD";
    x64 = cpu_is_em64t() ? " AMD64" : "";
  } else {
    cpu_type = "Unknown x86";
    x64 = cpu_is_em64t() ? " x86_64" : "";
  }
  jio_snprintf(buf, buf_len, "%s %s%s SSE SSE2%s%s%s%s%s%s%s%s",
    cpu_type,
    cpu_family_description(),
    supports_ht() ? " (HT)" : "",
    supports_sse3() ? " SSE3" : "",
    supports_ssse3() ? " SSSE3" : "",
    supports_sse4_1() ? " SSE4.1" : "",
    supports_sse4_2() ? " SSE4.2" : "",
    supports_sse4a() ? " SSE4A" : "",
    is_netburst() ? " Netburst" : "",
    is_intel_family_core() ? " Core" : "",
    x64);
  return OS_OK;
}
int VM_Version_Ext::cpu_extended_brand_string(char* const buf, size_t buf_len) {
  assert(buf != NULL, "buffer is NULL!");
  assert(buf_len >= CPU_EBS_MAX_LENGTH, "buffer len should at least be == CPU_EBS_MAX_LENGTH!");
  assert(getCPUIDBrandString_stub != NULL, "not initialized");
  getCPUIDBrandString_stub(&_cpuid_info);
  return OS_OK;
}
size_t VM_Version_Ext::cpu_write_support_string(char* const buf, size_t buf_len) {
  guarantee(buf != NULL, "buffer is NULL!");
  guarantee(buf_len > 0, "buffer len not enough!");
  unsigned int flag = 0;
  unsigned int fi = 0;
  size_t       written = 0;
  const char*  prefix = "";
#define WRITE_TO_BUF(string)                                                          \
  {                                                                                   \
    int res = jio_snprintf(&buf[written], buf_len - written, "%s%s", prefix, string); \
    if (res < 0) {                                                                    \
      return buf_len - 1;                                                             \
    }                                                                                 \
    written += res;                                                                   \
    if (prefix[0] == '\0') {                                                          \
      prefix = ", ";                                                                  \
    }                                                                                 \
  }
  for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
    if (flag == HTT_FLAG && (((_cpuid_info.std_cpuid1_ebx.value >> 16) & 0xff) <= 1)) {
      continue; /* no hyperthreading */
    } else if (flag == SEP_FLAG && (cpu_family() == CPU_FAMILY_PENTIUMPRO && ((_cpuid_info.std_cpuid1_eax.value & 0xff) < 0x33))) {
      continue; /* no fast system call */
    }
    if ((_cpuid_info.std_cpuid1_edx.value & flag) && strlen(_feature_edx_id[fi]) > 0) {
      WRITE_TO_BUF(_feature_edx_id[fi]);
    }
  }
  for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
    if ((_cpuid_info.std_cpuid1_ecx.value & flag) && strlen(_feature_ecx_id[fi]) > 0) {
      WRITE_TO_BUF(_feature_ecx_id[fi]);
    }
  }
  for (flag = 1, fi = 0; flag <= 0x20000000 ; flag <<= 1, fi++) {
    if ((_cpuid_info.ext_cpuid1_ecx.value & flag) && strlen(_feature_extended_ecx_id[fi]) > 0) {
      WRITE_TO_BUF(_feature_extended_ecx_id[fi]);
    }
  }
  for (flag = 1, fi = 0; flag <= 0x20000000; flag <<= 1, fi++) {
    if ((_cpuid_info.ext_cpuid1_edx.value & flag) && strlen(_feature_extended_edx_id[fi]) > 0) {
      WRITE_TO_BUF(_feature_extended_edx_id[fi]);
    }
  }
  if (supports_tscinv_bit()) {
      WRITE_TO_BUF("Invariant TSC");
  }
  return written;
}
int VM_Version_Ext::cpu_detailed_description(char* const buf, size_t buf_len) {
  assert(buf != NULL, "buffer is NULL!");
  assert(buf_len >= CPU_DETAILED_DESC_BUF_SIZE, "buffer len should at least be == CPU_DETAILED_DESC_BUF_SIZE!");
  static const char* unknown = "<unknown>";
  char               vendor_id[VENDOR_LENGTH];
  const char*        family = NULL;
  const char*        model = NULL;
  const char*        brand = NULL;
  int                outputLen = 0;
  family = cpu_family_description();
  if (family == NULL) {
    family = unknown;
  }
  model = cpu_model_description();
  if (model == NULL) {
    model = unknown;
  }
  brand = cpu_brand_string();
  if (brand == NULL) {
    brand = cpu_brand();
    if (brand == NULL) {
      brand = unknown;
    }
  }
  vendor_id[VENDOR_LENGTH-1] = '\0';
  outputLen = jio_snprintf(buf, buf_len, "Brand: %s, Vendor: %s\n"
    "Family: %s (0x%x), Model: %s (0x%x), Stepping: 0x%x\n"
    "Ext. family: 0x%x, Ext. model: 0x%x, Type: 0x%x, Signature: 0x%8.8x\n"
    "Features: ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
    "Ext. features: eax: 0x%8.8x, ebx: 0x%8.8x, ecx: 0x%8.8x, edx: 0x%8.8x\n"
    "Supports: ",
    brand,
    vendor_id,
    family,
    extended_cpu_family(),
    model,
    extended_cpu_model(),
    cpu_stepping(),
    _cpuid_info.std_cpuid1_eax.bits.ext_family,
    _cpuid_info.std_cpuid1_eax.bits.ext_model,
    _cpuid_info.std_cpuid1_eax.bits.proc_type,
    _cpuid_info.std_cpuid1_eax.value,
    _cpuid_info.std_cpuid1_ebx.value,
    _cpuid_info.std_cpuid1_ecx.value,
    _cpuid_info.std_cpuid1_edx.value,
    _cpuid_info.ext_cpuid1_eax,
    _cpuid_info.ext_cpuid1_ebx,
    _cpuid_info.ext_cpuid1_ecx,
    _cpuid_info.ext_cpuid1_edx);
  if (outputLen < 0 || (size_t) outputLen >= buf_len - 1) {
    if (buf_len > 0) { buf[buf_len-1] = '\0'; }
    return OS_ERR;
  }
  cpu_write_support_string(&buf[outputLen], buf_len - outputLen);
  return OS_OK;
}
const char* VM_Version_Ext::cpu_name(void) {
  char cpu_type_desc[CPU_TYPE_DESC_BUF_SIZE];
  size_t cpu_desc_len = sizeof(cpu_type_desc);
  cpu_type_description(cpu_type_desc, cpu_desc_len);
  char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_desc_len, mtTracing);
  if (NULL == tmp) {
    return NULL;
  }
  strncpy(tmp, cpu_type_desc, cpu_desc_len);
  return tmp;
}
const char* VM_Version_Ext::cpu_description(void) {
  char cpu_detailed_desc_buffer[CPU_DETAILED_DESC_BUF_SIZE];
  size_t cpu_detailed_desc_len = sizeof(cpu_detailed_desc_buffer);
  cpu_detailed_description(cpu_detailed_desc_buffer, cpu_detailed_desc_len);
  char* tmp = NEW_C_HEAP_ARRAY_RETURN_NULL(char, cpu_detailed_desc_len, mtTracing);
  if (NULL == tmp) {
    return NULL;
  }
  strncpy(tmp, cpu_detailed_desc_buffer, cpu_detailed_desc_len);
  return tmp;
}
jlong VM_Version_Ext::max_qualified_cpu_freq_from_brand_string(void) {
  const char* const brand_string = cpu_brand_string();
  if (brand_string == NULL) {
    return 0;
  }
  const u8 MEGA = 1000000;
  u8 multiplier = 0;
  jlong frequency = 0;
  const char* Hz_location = strchr(brand_string, 'H');
  if (Hz_location != NULL) {
    if (*(Hz_location + 1) == 'z') {
      switch(*(Hz_location - 1)) {
        case 'M' :
          multiplier = MEGA;
          break;
        case 'G' :
          multiplier = MEGA * 1000;
          break;
        case 'T' :
          multiplier = MEGA * 1000 * 1000;
          break;
      }
    }
  }
  if (multiplier > 0) {
    if (*(Hz_location - 4) == '.') { // if format is "x.xx"
      frequency =  (jlong)(*(Hz_location - 5) - '0') * (multiplier);
      frequency += (jlong)(*(Hz_location - 3) - '0') * (multiplier / 10);
      frequency += (jlong)(*(Hz_location - 2) - '0') * (multiplier / 100);
    } else { // format is "xxxx"
      frequency =  (jlong)(*(Hz_location - 5) - '0') * 1000;
      frequency += (jlong)(*(Hz_location - 4) - '0') * 100;
      frequency += (jlong)(*(Hz_location - 3) - '0') * 10;
      frequency += (jlong)(*(Hz_location - 2) - '0');
      frequency *= multiplier;
    }
  }
  return frequency;
}
jlong VM_Version_Ext::maximum_qualified_cpu_frequency(void) {
  if (_max_qualified_cpu_frequency == 0) {
    _max_qualified_cpu_frequency = max_qualified_cpu_freq_from_brand_string();
  }
  return _max_qualified_cpu_frequency;
}
const char* const VM_Version_Ext::_family_id_intel[] = {
  "8086/8088",
  "",
  "286",
  "386",
  "486",
  "Pentium",
  "Pentium Pro",   //or Pentium-M/Woodcrest depeding on model
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "Pentium 4"
};
const char* const VM_Version_Ext::_family_id_amd[] = {
  "",
  "",
  "",
  "",
  "5x86",
  "K5/K6",
  "Athlon/AthlonXP",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "Opteron/Athlon64",
  "Opteron QC/Phenom"  // Barcelona et.al.
};
const char* const VM_Version_Ext::_model_id_pentium_pro[] = {
  "",
  "Pentium Pro",
  "",
  "Pentium II model 3",
  "",
  "Pentium II model 5/Xeon/Celeron",
  "Celeron",
  "Pentium III/Pentium III Xeon",
  "Pentium III/Pentium III Xeon",
  "Pentium M model 9",    // Yonah
  "Pentium III, model A",
  "Pentium III, model B",
  "",
  "Pentium M model D",    // Dothan
  "",
  "Core 2",               // 0xf Woodcrest/Conroe/Merom/Kentsfield/Clovertown
  "",
  "",
  "",
  "",
  "",
  "",
  "Celeron",              // 0x16 Celeron 65nm
  "Core 2",               // 0x17 Penryn / Harpertown
  "",
  "",
  "Core i7",              // 0x1A CPU_MODEL_NEHALEM_EP
  "Atom",                 // 0x1B Z5xx series Silverthorn
  "",
  "Core 2",               // 0x1D Dunnington (6-core)
  "Nehalem",              // 0x1E CPU_MODEL_NEHALEM
  "",
  "",
  "",
  "",
  "",
  "",
  "Westmere",             // 0x25 CPU_MODEL_WESTMERE
  "",
  "",
  "",                     // 0x28
  "",
  "Sandy Bridge",         // 0x2a "2nd Generation Intel Core i7, i5, i3"
  "",
  "Westmere-EP",          // 0x2c CPU_MODEL_WESTMERE_EP
  "Sandy Bridge-EP",      // 0x2d CPU_MODEL_SANDYBRIDGE_EP
  "Nehalem-EX",           // 0x2e CPU_MODEL_NEHALEM_EX
  "Westmere-EX",          // 0x2f CPU_MODEL_WESTMERE_EX
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "Ivy Bridge",           // 0x3a
  "",
  "Haswell",              // 0x3c "4th Generation Intel Core Processor"
  "",                     // 0x3d "Next Generation Intel Core Processor"
  "Ivy Bridge-EP",        // 0x3e "Next Generation Intel Xeon Processor E7 Family"
  "",                     // 0x3f "Future Generation Intel Xeon Processor"
  "",
  "",
  "",
  "",
  "",
  "Haswell",              // 0x45 "4th Generation Intel Core Processor"
  "Haswell",              // 0x46 "4th Generation Intel Core Processor"
  NULL
};
const char* const VM_Version_Ext::_brand_id[] = {
  "",
  "Celeron processor",
  "Pentium III processor",
  "Intel Pentium III Xeon processor",
  "",
  "",
  "",
  "",
  "Intel Pentium 4 processor",
  NULL
};
const char* const VM_Version_Ext::_feature_edx_id[] = {
  "On-Chip FPU",
  "Virtual Mode Extensions",
  "Debugging Extensions",
  "Page Size Extensions",
  "Time Stamp Counter",
  "Model Specific Registers",
  "Physical Address Extension",
  "Machine Check Exceptions",
  "CMPXCHG8B Instruction",
  "On-Chip APIC",
  "",
  "Fast System Call",
  "Memory Type Range Registers",
  "Page Global Enable",
  "Machine Check Architecture",
  "Conditional Mov Instruction",
  "Page Attribute Table",
  "36-bit Page Size Extension",
  "Processor Serial Number",
  "CLFLUSH Instruction",
  "",
  "Debug Trace Store feature",
  "ACPI registers in MSR space",
  "Intel Architecture MMX Technology",
  "Fast Float Point Save and Restore",
  "Streaming SIMD extensions",
  "Streaming SIMD extensions 2",
  "Self-Snoop",
  "Hyper Threading",
  "Thermal Monitor",
  "",
  "Pending Break Enable"
};
const char* const VM_Version_Ext::_feature_extended_edx_id[] = {
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "SYSCALL/SYSRET",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "Execute Disable Bit",
  "",
  "",
  "",
  "",
  "",
  "",
  "RDTSCP",
  "",
  "Intel 64 Architecture",
  "",
  ""
};
const char* const VM_Version_Ext::_feature_ecx_id[] = {
  "Streaming SIMD Extensions 3",
  "PCLMULQDQ",
  "64-bit DS Area",
  "MONITOR/MWAIT instructions",
  "CPL Qualified Debug Store",
  "Virtual Machine Extensions",
  "Safer Mode Extensions",
  "Enhanced Intel SpeedStep technology",
  "Thermal Monitor 2",
  "Supplemental Streaming SIMD Extensions 3",
  "L1 Context ID",
  "",
  "Fused Multiply-Add",
  "CMPXCHG16B",
  "xTPR Update Control",
  "Perfmon and Debug Capability",
  "",
  "Process-context identifiers",
  "Direct Cache Access",
  "Streaming SIMD extensions 4.1",
  "Streaming SIMD extensions 4.2",
  "x2APIC",
  "MOVBE",
  "Popcount instruction",
  "TSC-Deadline",
  "AESNI",
  "XSAVE",
  "OSXSAVE",
  "AVX",
  "F16C",
  "RDRAND",
  ""
};
const char* const VM_Version_Ext::_feature_extended_ecx_id[] = {
  "LAHF/SAHF instruction support",
  "Core multi-processor leagacy mode",
  "",
  "",
  "",
  "Advanced Bit Manipulations: LZCNT",
  "SSE4A: MOVNTSS, MOVNTSD, EXTRQ, INSERTQ",
  "Misaligned SSE mode",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  "",
  ""
};
C:\hotspot-69087d08d473\src\cpu\x86\vm/vm_version_ext_x86.hpp
#ifndef CPU_X86_VM_VM_VERSION_EXT_X86_HPP
#define CPU_X86_VM_VM_VERSION_EXT_X86_HPP
#include "utilities/macros.hpp"
#include "vm_version_x86.hpp"
class VM_Version_Ext : public VM_Version {
 private:
  static const size_t      VENDOR_LENGTH;
  static const size_t      CPU_EBS_MAX_LENGTH;
  static const size_t      CPU_TYPE_DESC_BUF_SIZE;
  static const size_t      CPU_DETAILED_DESC_BUF_SIZE;
  static const char* const _family_id_intel[];
  static const char* const _family_id_amd[];
  static const char* const _brand_id[];
  static const char* const _model_id_pentium_pro[];
  static const char* const _feature_edx_id[];
  static const char* const _feature_extended_edx_id[];
  static const char* const _feature_ecx_id[];
  static const char* const _feature_extended_ecx_id[];
  static int               _no_of_threads;
  static int               _no_of_cores;
  static int               _no_of_packages;
  static char*             _cpu_brand_string;
  static jlong             _max_qualified_cpu_frequency;
  static const char* cpu_family_description(void);
  static const char* cpu_model_description(void);
  static const char* cpu_brand(void);
  static const char* cpu_brand_string(void);
  static int cpu_type_description(char* const buf, size_t buf_len);
  static int cpu_detailed_description(char* const buf, size_t buf_len);
  static int cpu_extended_brand_string(char* const buf, size_t buf_len);
  static bool cpu_is_em64t(void);
  static bool is_netburst(void);
  static size_t cpu_write_support_string(char* const buf, size_t buf_len);
  static void resolve_cpu_information_details(void);
  static jlong max_qualified_cpu_freq_from_brand_string(void);
 public:
  static ByteSize proc_name_0_offset() { return byte_offset_of(CpuidInfo, proc_name_0); }
  static ByteSize proc_name_1_offset() { return byte_offset_of(CpuidInfo, proc_name_1); }
  static ByteSize proc_name_2_offset() { return byte_offset_of(CpuidInfo, proc_name_2); }
  static ByteSize proc_name_3_offset() { return byte_offset_of(CpuidInfo, proc_name_3); }
  static ByteSize proc_name_4_offset() { return byte_offset_of(CpuidInfo, proc_name_4); }
  static ByteSize proc_name_5_offset() { return byte_offset_of(CpuidInfo, proc_name_5); }
  static ByteSize proc_name_6_offset() { return byte_offset_of(CpuidInfo, proc_name_6); }
  static ByteSize proc_name_7_offset() { return byte_offset_of(CpuidInfo, proc_name_7); }
  static ByteSize proc_name_8_offset() { return byte_offset_of(CpuidInfo, proc_name_8); }
  static ByteSize proc_name_9_offset() { return byte_offset_of(CpuidInfo, proc_name_9); }
  static ByteSize proc_name_10_offset() { return byte_offset_of(CpuidInfo, proc_name_10); }
  static ByteSize proc_name_11_offset() { return byte_offset_of(CpuidInfo, proc_name_11); }
  static int number_of_threads(void);
  static int number_of_cores(void);
  static int number_of_sockets(void);
  static jlong maximum_qualified_cpu_frequency(void);
  static bool supports_tscinv_ext(void);
  static const char* cpu_name(void);
  static const char* cpu_description(void);
  static void initialize();
};
#endif // CPU_X86_VM_VM_VERSION_EXT_X86_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/vm_version_x86.cpp
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "asm/macroAssembler.inline.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/java.hpp"
#include "runtime/stubCodeGenerator.hpp"
#include "vm_version_x86.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
int VM_Version::_cpu;
int VM_Version::_model;
int VM_Version::_stepping;
int VM_Version::_cpuFeatures;
const char*           VM_Version::_features_str = "";
VM_Version::CpuidInfo VM_Version::_cpuid_info   = { 0, };
address VM_Version::_cpuinfo_segv_addr = 0;
address VM_Version::_cpuinfo_cont_addr = 0;
static BufferBlob* stub_blob;
static const int stub_size = 600;
extern "C" {
  typedef void (*get_cpu_info_stub_t)(void*);
}
static get_cpu_info_stub_t get_cpu_info_stub = NULL;
class VM_Version_StubGenerator: public StubCodeGenerator {
 public:
  VM_Version_StubGenerator(CodeBuffer *c) : StubCodeGenerator(c) {}
  address generate_get_cpu_info() {
    const uint32_t HS_EFL_AC           = 0x40000;
    const uint32_t HS_EFL_ID           = 0x200000;
    const int      CPU_FAMILY_SHIFT = 8;
    const uint32_t CPU_FAMILY_386   = (3 << CPU_FAMILY_SHIFT);
    const uint32_t CPU_FAMILY_486   = (4 << CPU_FAMILY_SHIFT);
    Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4;
    Label sef_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7, done;
    StubCodeMark mark(this, "VM_Version", "get_cpu_info_stub");
#   define __ _masm->
    address start = __ pc();
    __ push(rbp);
#ifdef _LP64
    __ mov(rbp, c_rarg0); // cpuid_info address
#else
    __ movptr(rbp, Address(rsp, 8)); // cpuid_info address
#endif
    __ push(rbx);
    __ push(rsi);
    __ pushf();          // preserve rbx, and flags
    __ pop(rax);
    __ push(rax);
    __ mov(rcx, rax);
    __ xorl(rax, HS_EFL_AC);
    __ push(rax);
    __ popf();
    __ pushf();
    __ pop(rax);
    __ cmpptr(rax, rcx);
    __ jccb(Assembler::notEqual, detect_486);
    __ movl(rax, CPU_FAMILY_386);
    __ movl(Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())), rax);
    __ jmp(done);
    __ bind(detect_486);
    __ mov(rax, rcx);
    __ xorl(rax, HS_EFL_ID);
    __ push(rax);
    __ popf();
    __ pushf();
    __ pop(rax);
    __ cmpptr(rcx, rax);
    __ jccb(Assembler::notEqual, detect_586);
    __ bind(cpu486);
    __ movl(rax, CPU_FAMILY_486);
    __ movl(Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())), rax);
    __ jmp(done);
    __ bind(detect_586);
    __ xorl(rax, rax);
    __ cpuid();
    __ orl(rax, rax);
    __ jcc(Assembler::equal, cpu486);   // if cpuid doesn't support an input
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ cmpl(rax, 0xa);                  // Is cpuid(0xB) supported?
    __ jccb(Assembler::belowEqual, std_cpuid4);
    __ movl(rax, 0xb);
    __ xorl(rcx, rcx);   // Threads level
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB0_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ movl(rax, 0xb);
    __ movl(rcx, 1);     // Cores level
    __ cpuid();
    __ push(rax);
    __ andl(rax, 0x1f);  // Determine if valid topology level
    __ orl(rax, rbx);    // eax[4:0] | ebx[0:15] == 0 indicates invalid level
    __ andl(rax, 0xffff);
    __ pop(rax);
    __ jccb(Assembler::equal, std_cpuid4);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB1_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ movl(rax, 0xb);
    __ movl(rcx, 2);     // Packages level
    __ cpuid();
    __ push(rax);
    __ andl(rax, 0x1f);  // Determine if valid topology level
    __ orl(rax, rbx);    // eax[4:0] | ebx[0:15] == 0 indicates invalid level
    __ andl(rax, 0xffff);
    __ pop(rax);
    __ jccb(Assembler::equal, std_cpuid4);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::tpl_cpuidB2_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ bind(std_cpuid4);
    __ movl(rax, 4);
    __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x4) supported?
    __ jccb(Assembler::greater, std_cpuid1);
    __ xorl(rcx, rcx);   // L1 cache
    __ cpuid();
    __ push(rax);
    __ andl(rax, 0x1f);  // Determine if valid cache parameters used
    __ orl(rax, rax);    // eax[4:0] == 0 indicates invalid cache
    __ pop(rax);
    __ jccb(Assembler::equal, std_cpuid1);
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::dcp_cpuid4_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ bind(std_cpuid1);
    __ movl(rax, 1);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ andl(rcx, 0x18000000); // cpuid1 bits osxsave | avx
    __ cmpl(rcx, 0x18000000);
    __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
    __ xorl(rcx, rcx);   // zero for XCR0 register
    __ xgetbv();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rdx);
    __ andl(rax, 0x6); // xcr0 bits sse | ymm
    __ cmpl(rax, 0x6);
    __ jccb(Assembler::notEqual, sef_cpuid); // jump if AVX is not supported
    VM_Version::set_avx_cpuFeatures(); // Enable temporary to pass asserts
    intx saved_useavx = UseAVX;
    intx saved_usesse = UseSSE;
    UseAVX = 1;
    UseSSE = 2;
    __ movl(rcx, VM_Version::ymm_test_value());
    __ movdl(xmm0, rcx);
    __ pshufd(xmm0, xmm0, 0x00);
    __ vinsertf128h(xmm0, xmm0, xmm0);
    __ vmovdqu(xmm7, xmm0);
#ifdef _LP64
    __ vmovdqu(xmm8,  xmm0);
    __ vmovdqu(xmm15, xmm0);
#endif
    __ xorl(rsi, rsi);
    VM_Version::set_cpuinfo_segv_addr( __ pc() );
    __ movl(rax, Address(rsi, 0));
    VM_Version::set_cpuinfo_cont_addr( __ pc() );
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ymm_save_offset())));
    __ vmovdqu(Address(rsi,  0), xmm0);
    __ vmovdqu(Address(rsi, 32), xmm7);
#ifdef _LP64
    __ vmovdqu(Address(rsi, 64), xmm8);
    __ vmovdqu(Address(rsi, 96), xmm15);
#endif
    VM_Version::clean_cpuFeatures();
    UseAVX = saved_useavx;
    UseSSE = saved_usesse;
    __ bind(sef_cpuid);
    __ movl(rax, 7);
    __ cmpl(rax, Address(rbp, in_bytes(VM_Version::std_cpuid0_offset()))); // Is cpuid(0x7) supported?
    __ jccb(Assembler::greater, ext_cpuid);
    __ xorl(rcx, rcx);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ bind(ext_cpuid);
    __ movl(rax, 0x80000000);
    __ cpuid();
    __ cmpl(rax, 0x80000000);     // Is cpuid(0x80000001) supported?
    __ jcc(Assembler::belowEqual, done);
    __ cmpl(rax, 0x80000004);     // Is cpuid(0x80000005) supported?
    __ jccb(Assembler::belowEqual, ext_cpuid1);
    __ cmpl(rax, 0x80000006);     // Is cpuid(0x80000007) supported?
    __ jccb(Assembler::belowEqual, ext_cpuid5);
    __ cmpl(rax, 0x80000007);     // Is cpuid(0x80000008) supported?
    __ jccb(Assembler::belowEqual, ext_cpuid7);
    __ movl(rax, 0x80000008);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid8_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ bind(ext_cpuid7);
    __ movl(rax, 0x80000007);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid7_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ bind(ext_cpuid5);
    __ movl(rax, 0x80000005);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid5_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ bind(ext_cpuid1);
    __ movl(rax, 0x80000001);
    __ cpuid();
    __ lea(rsi, Address(rbp, in_bytes(VM_Version::ext_cpuid1_offset())));
    __ movl(Address(rsi, 0), rax);
    __ movl(Address(rsi, 4), rbx);
    __ movl(Address(rsi, 8), rcx);
    __ movl(Address(rsi,12), rdx);
    __ bind(done);
    __ popf();
    __ pop(rsi);
    __ pop(rbx);
    __ pop(rbp);
    __ ret(0);
#   undef __
    return start;
  };
};
void VM_Version::get_cpu_info_wrapper() {
  get_cpu_info_stub(&_cpuid_info);
}
#ifndef CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED
  #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f()
#endif
void VM_Version::get_processor_features() {
  _cpu = 4; // 486 by default
  _model = 0;
  _stepping = 0;
  _cpuFeatures = 0;
  _logical_processors_per_package = 1;
  _L1_data_cache_line_size = 16;
  if (!Use486InstrsOnly) {
    CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(get_cpu_info_wrapper);
    assert_is_initialized();
    _cpu = extended_cpu_family();
    _model = extended_cpu_model();
    _stepping = cpu_stepping();
    if (cpu_family() > 4) { // it supports CPUID
      _cpuFeatures = feature_flags();
      _logical_processors_per_package = logical_processor_count();
      _L1_data_cache_line_size = L1_line_size();
    }
  }
  _supports_cx8 = supports_cmpxchg8();
  _supports_atomic_getset4 = true;
  _supports_atomic_getadd4 = true;
  LP64_ONLY(_supports_atomic_getset8 = true);
  LP64_ONLY(_supports_atomic_getadd8 = true);
#ifdef _LP64
  if (!VM_Version::supports_sse2()) {
    vm_exit_during_initialization("Unknown x64 processor: SSE2 not supported");
  }
  if (UseSSE < 2) UseSSE = 2;
#endif
#ifdef AMD64
  guarantee(_cpuid_info.std_cpuid1_edx.bits.clflush != 0, "clflush is not supported");
  guarantee(_cpuid_info.std_cpuid1_ebx.bits.clflush_size == 8, "such clflush size is not supported");
#endif
  if (!os::supports_sse())
    _cpuFeatures &= ~(CPU_SSE|CPU_SSE2|CPU_SSE3|CPU_SSSE3|CPU_SSE4A|CPU_SSE4_1|CPU_SSE4_2);
  if (UseSSE < 4) {
    _cpuFeatures &= ~CPU_SSE4_1;
    _cpuFeatures &= ~CPU_SSE4_2;
  }
  if (UseSSE < 3) {
    _cpuFeatures &= ~CPU_SSE3;
    _cpuFeatures &= ~CPU_SSSE3;
    _cpuFeatures &= ~CPU_SSE4A;
  }
  if (UseSSE < 2)
    _cpuFeatures &= ~CPU_SSE2;
  if (UseSSE < 1)
    _cpuFeatures &= ~CPU_SSE;
  if (UseAVX < 2)
    _cpuFeatures &= ~CPU_AVX2;
  if (UseAVX < 1)
    _cpuFeatures &= ~CPU_AVX;
  if (!UseAES && !FLAG_IS_DEFAULT(UseAES))
    _cpuFeatures &= ~CPU_AES;
  if (logical_processors_per_package() == 1) {
    _cpuFeatures &= ~CPU_HT;
  }
  char buf[256];
  jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
               cores_per_cpu(), threads_per_core(),
               cpu_family(), _model, _stepping,
               (supports_cmov() ? ", cmov" : ""),
               (supports_cmpxchg8() ? ", cx8" : ""),
               (supports_fxsr() ? ", fxsr" : ""),
               (supports_mmx()  ? ", mmx"  : ""),
               (supports_sse()  ? ", sse"  : ""),
               (supports_sse2() ? ", sse2" : ""),
               (supports_sse3() ? ", sse3" : ""),
               (supports_ssse3()? ", ssse3": ""),
               (supports_sse4_1() ? ", sse4.1" : ""),
               (supports_sse4_2() ? ", sse4.2" : ""),
               (supports_popcnt() ? ", popcnt" : ""),
               (supports_avx()    ? ", avx" : ""),
               (supports_avx2()   ? ", avx2" : ""),
               (supports_aes()    ? ", aes" : ""),
               (supports_clmul()  ? ", clmul" : ""),
               (supports_erms()   ? ", erms" : ""),
               (supports_rtm()    ? ", rtm" : ""),
               (supports_mmx_ext() ? ", mmxext" : ""),
               (supports_3dnow_prefetch() ? ", 3dnowpref" : ""),
               (supports_lzcnt()   ? ", lzcnt": ""),
               (supports_sse4a()   ? ", sse4a": ""),
               (supports_ht() ? ", ht": ""),
               (supports_tsc() ? ", tsc": ""),
               (supports_tscinv_bit() ? ", tscinvbit": ""),
               (supports_tscinv() ? ", tscinv": ""),
               (supports_bmi1() ? ", bmi1" : ""),
               (supports_bmi2() ? ", bmi2" : ""),
               (supports_adx() ? ", adx" : ""));
  _features_str = strdup(buf);
  if (UseSSE > 4) UseSSE=4;
  if (UseSSE < 0) UseSSE=0;
  if (!supports_sse4_1()) // Drop to 3 if no SSE4 support
    UseSSE = MIN2((intx)3,UseSSE);
  if (!supports_sse3()) // Drop to 2 if no SSE3 support
    UseSSE = MIN2((intx)2,UseSSE);
  if (!supports_sse2()) // Drop to 1 if no SSE2 support
    UseSSE = MIN2((intx)1,UseSSE);
  if (!supports_sse ()) // Drop to 0 if no SSE  support
    UseSSE = 0;
  if (UseAVX > 2) UseAVX=2;
  if (UseAVX < 0) UseAVX=0;
  if (!supports_avx2()) // Drop to 1 if no AVX2 support
    UseAVX = MIN2((intx)1,UseAVX);
  if (!supports_avx ()) // Drop to 0 if no AVX  support
    UseAVX = 0;
  if (supports_aes()) {
    if (FLAG_IS_DEFAULT(UseAES)) {
      FLAG_SET_DEFAULT(UseAES, true);
    }
    if (!UseAES) {
      if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
        warning("AES intrinsics require UseAES flag to be enabled. Intrinsics will be disabled.");
      }
      FLAG_SET_DEFAULT(UseAESIntrinsics, false);
    } else {
      if (UseSSE > 2) {
        if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
          FLAG_SET_DEFAULT(UseAESIntrinsics, true);
        }
      } else {
        if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
          warning("X86 AES intrinsics require SSE3 instructions or higher. Intrinsics will be disabled.");
        }
        FLAG_SET_DEFAULT(UseAESIntrinsics, false);
      }
    }
  } else if (UseAES || UseAESIntrinsics) {
    if (UseAES && !FLAG_IS_DEFAULT(UseAES)) {
      warning("AES instructions are not available on this CPU");
      FLAG_SET_DEFAULT(UseAES, false);
    }
    if (UseAESIntrinsics && !FLAG_IS_DEFAULT(UseAESIntrinsics)) {
      warning("AES intrinsics are not available on this CPU");
      FLAG_SET_DEFAULT(UseAESIntrinsics, false);
    }
  }
  if (supports_clmul()) {
    if (FLAG_IS_DEFAULT(UseCLMUL)) {
      UseCLMUL = true;
    }
  } else if (UseCLMUL) {
    if (!FLAG_IS_DEFAULT(UseCLMUL))
      warning("CLMUL instructions not available on this CPU (AVX may also be required)");
    FLAG_SET_DEFAULT(UseCLMUL, false);
  }
  if (UseCLMUL && (UseSSE > 2)) {
    if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
      UseCRC32Intrinsics = true;
    }
  } else if (UseCRC32Intrinsics) {
    if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics))
      warning("CRC32 Intrinsics requires CLMUL instructions (not available on this CPU)");
    FLAG_SET_DEFAULT(UseCRC32Intrinsics, false);
  }
  if (UseCLMUL && (UseSSE > 2)) {
    if (FLAG_IS_DEFAULT(UseGHASHIntrinsics)) {
      UseGHASHIntrinsics = true;
    }
  } else if (UseGHASHIntrinsics) {
    if (!FLAG_IS_DEFAULT(UseGHASHIntrinsics))
      warning("GHASH intrinsic requires CLMUL and SSE2 instructions on this CPU");
    FLAG_SET_DEFAULT(UseGHASHIntrinsics, false);
  }
  if (UseSHA) {
    warning("SHA instructions are not available on this CPU");
    FLAG_SET_DEFAULT(UseSHA, false);
  }
  if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
    warning("SHA intrinsics are not available on this CPU");
    FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
    FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
    FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
  }
  if (!supports_rtm() && UseRTMLocking) {
    vm_exit_during_initialization("RTM instructions are not available on this CPU");
  }
#if INCLUDE_RTM_OPT
  if (UseRTMLocking) {
    if (is_intel_family_core()) {
      if ((_model == CPU_MODEL_HASWELL_E3) ||
          (_model == CPU_MODEL_HASWELL_E7 && _stepping < 3) ||
          (_model == CPU_MODEL_BROADWELL  && _stepping < 4)) {
        if (!UnlockExperimentalVMOptions) {
          vm_exit_during_initialization("UseRTMLocking is only available as experimental option on this platform. It must be enabled via -XX:+UnlockExperimentalVMOptions flag.");
        } else {
          warning("UseRTMLocking is only available as experimental option on this platform.");
        }
      }
    }
    if (!FLAG_IS_CMDLINE(UseRTMLocking)) {
      vm_exit_during_initialization("UseRTMLocking flag should be only set on command line");
    }
    if (!is_power_of_2(RTMTotalCountIncrRate)) {
      warning("RTMTotalCountIncrRate must be a power of 2, resetting it to 64");
      FLAG_SET_DEFAULT(RTMTotalCountIncrRate, 64);
    }
    if (RTMAbortRatio < 0 || RTMAbortRatio > 100) {
      warning("RTMAbortRatio must be in the range 0 to 100, resetting it to 50");
      FLAG_SET_DEFAULT(RTMAbortRatio, 50);
    }
  } else { // !UseRTMLocking
    if (UseRTMForStackLocks) {
      if (!FLAG_IS_DEFAULT(UseRTMForStackLocks)) {
        warning("UseRTMForStackLocks flag should be off when UseRTMLocking flag is off");
      }
      FLAG_SET_DEFAULT(UseRTMForStackLocks, false);
    }
    if (UseRTMDeopt) {
      FLAG_SET_DEFAULT(UseRTMDeopt, false);
    }
    if (PrintPreciseRTMLockingStatistics) {
      FLAG_SET_DEFAULT(PrintPreciseRTMLockingStatistics, false);
    }
  }
#else
  if (UseRTMLocking) {
    vm_exit_during_initialization("RTM locking optimization is not supported in this VM");
  }
#endif
#ifdef COMPILER2
  if (UseFPUForSpilling) {
    if (UseSSE < 2) {
      FLAG_SET_DEFAULT(UseFPUForSpilling, false);
    }
  }
  if (MaxVectorSize > 0) {
    if (!is_power_of_2(MaxVectorSize)) {
      warning("MaxVectorSize must be a power of 2");
      FLAG_SET_DEFAULT(MaxVectorSize, 32);
    }
    if (MaxVectorSize > 32) {
      FLAG_SET_DEFAULT(MaxVectorSize, 32);
    }
    if (MaxVectorSize > 16 && (UseAVX == 0 || !os_supports_avx_vectors())) {
      FLAG_SET_DEFAULT(MaxVectorSize, 16);
    }
    if (UseSSE < 2) {
      FLAG_SET_DEFAULT(MaxVectorSize, 0);
    }
#ifdef ASSERT
    if (supports_avx() && PrintMiscellaneous && Verbose && TraceNewVectors) {
      tty->print_cr("State of YMM registers after signal handle:");
      int nreg = 2 LP64_ONLY(+2);
      const char* ymm_name[4] = {"0", "7", "8", "15"};
      for (int i = 0; i < nreg; i++) {
        tty->print("YMM%s:", ymm_name[i]);
        for (int j = 7; j >=0; j--) {
          tty->print(" %x", _cpuid_info.ymm_save[i*8 + j]);
        }
        tty->cr();
      }
    }
#endif
  }
#ifdef _LP64
  if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
    UseMultiplyToLenIntrinsic = true;
  }
  if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
    UseSquareToLenIntrinsic = true;
  }
  if (FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
    UseMulAddIntrinsic = true;
  }
  if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
    UseMontgomeryMultiplyIntrinsic = true;
  }
  if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
    UseMontgomerySquareIntrinsic = true;
  }
#else
  if (UseMultiplyToLenIntrinsic) {
    if (!FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) {
      warning("multiplyToLen intrinsic is not available in 32-bit VM");
    }
    FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false);
  }
  if (UseSquareToLenIntrinsic) {
    if (!FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) {
      warning("squareToLen intrinsic is not available in 32-bit VM");
    }
    FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false);
  }
  if (UseMulAddIntrinsic) {
    if (!FLAG_IS_DEFAULT(UseMulAddIntrinsic)) {
      warning("mulAdd intrinsic is not available in 32-bit VM");
    }
    FLAG_SET_DEFAULT(UseMulAddIntrinsic, false);
  }
  if (UseMontgomeryMultiplyIntrinsic) {
    if (!FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) {
      warning("montgomeryMultiply intrinsic is not available in 32-bit VM");
    }
    FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false);
  }
  if (UseMontgomerySquareIntrinsic) {
    if (!FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) {
      warning("montgomerySquare intrinsic is not available in 32-bit VM");
    }
    FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false);
  }
#endif
#endif // COMPILER2
  if( is_amd() ) { // AMD cpus specific settings
    if( supports_sse2() && FLAG_IS_DEFAULT(UseAddressNop) ) {
      UseAddressNop = true;
    }
    if( supports_sse2() && FLAG_IS_DEFAULT(UseNewLongLShift) ) {
      UseNewLongLShift = true;
    }
    if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
      if( supports_sse4a() ) {
        UseXmmLoadAndClearUpper = true; // use movsd only on '10h' Opteron
      } else {
        UseXmmLoadAndClearUpper = false;
      }
    }
    if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
      if( supports_sse4a() ) {
        UseXmmRegToRegMoveAll = true; // use movaps, movapd only on '10h'
      } else {
        UseXmmRegToRegMoveAll = false;
      }
    }
    if( FLAG_IS_DEFAULT(UseXmmI2F) ) {
      if( supports_sse4a() ) {
        UseXmmI2F = true;
      } else {
        UseXmmI2F = false;
      }
    }
    if( FLAG_IS_DEFAULT(UseXmmI2D) ) {
      if( supports_sse4a() ) {
        UseXmmI2D = true;
      } else {
        UseXmmI2D = false;
      }
    }
    if( FLAG_IS_DEFAULT(UseSSE42Intrinsics) ) {
      if( supports_sse4_2() && UseSSE >= 4 ) {
        UseSSE42Intrinsics = true;
      }
    }
    if ( cpu_family() == 0x15 ) {
      if (FLAG_IS_DEFAULT(AllocatePrefetchStyle)) {
        AllocatePrefetchStyle = 0;
      }
      if (FLAG_IS_DEFAULT(AllocatePrefetchInstr)) {
        AllocatePrefetchInstr = 3;
      }
      if (supports_sse2() && FLAG_IS_DEFAULT(UseXMMForArrayCopy)) {
        UseXMMForArrayCopy = true;
      }
      if (supports_sse2() && FLAG_IS_DEFAULT(UseUnalignedLoadStores)) {
        UseUnalignedLoadStores = true;
      }
    }
#ifdef COMPILER2
    if (MaxVectorSize > 16) {
      FLAG_SET_DEFAULT(MaxVectorSize, 16);
    }
#endif // COMPILER2
  }
  if( is_intel() ) { // Intel cpus specific settings
    if( FLAG_IS_DEFAULT(UseStoreImmI16) ) {
      UseStoreImmI16 = false; // don't use it on Intel cpus
    }
    if( cpu_family() == 6 || cpu_family() == 15 ) {
      if( FLAG_IS_DEFAULT(UseAddressNop) ) {
        UseAddressNop = true;
      }
    }
    if( FLAG_IS_DEFAULT(UseXmmLoadAndClearUpper) ) {
      UseXmmLoadAndClearUpper = true; // use movsd on all Intel cpus
    }
    if( FLAG_IS_DEFAULT(UseXmmRegToRegMoveAll) ) {
      if( supports_sse3() ) {
        UseXmmRegToRegMoveAll = true; // use movaps, movapd on new Intel cpus
      } else {
        UseXmmRegToRegMoveAll = false;
      }
    }
    if( cpu_family() == 6 && supports_sse3() ) { // New Intel cpus
#ifdef COMPILER2
      if( FLAG_IS_DEFAULT(MaxLoopPad) ) {
        MaxLoopPad = 11;
      }
#endif // COMPILER2
      if (FLAG_IS_DEFAULT(UseXMMForArrayCopy)) {
        UseXMMForArrayCopy = true; // use SSE2 movq on new Intel cpus
      }
      if (supports_sse4_2() && supports_ht()) { // Newest Intel cpus
        if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) {
          UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
        }
      }
      if (supports_sse4_2() && UseSSE >= 4) {
        if (FLAG_IS_DEFAULT(UseSSE42Intrinsics)) {
          UseSSE42Intrinsics = true;
        }
      }
    }
    if ((cpu_family() == 0x06) &&
        ((extended_cpu_model() == 0x36) || // Centerton
         (extended_cpu_model() == 0x37) || // Silvermont
         (extended_cpu_model() == 0x4D))) {
#ifdef COMPILER2
      if (FLAG_IS_DEFAULT(OptoScheduling)) {
        OptoScheduling = true;
      }
#endif
      if (supports_sse4_2()) { // Silvermont
        if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) {
          UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
        }
      }
    }
    if(FLAG_IS_DEFAULT(AllocatePrefetchInstr) && supports_3dnow_prefetch()) {
      AllocatePrefetchInstr = 3;
    }
  }
  if (supports_lzcnt()) {
    if (FLAG_IS_DEFAULT(UseCountLeadingZerosInstruction)) {
      UseCountLeadingZerosInstruction = true;
    }
   } else if (UseCountLeadingZerosInstruction) {
    warning("lzcnt instruction is not available on this CPU");
    FLAG_SET_DEFAULT(UseCountLeadingZerosInstruction, false);
  }
  if (supports_bmi1()) {
    if (FLAG_IS_DEFAULT(UseCountTrailingZerosInstruction)) {
      if (!UseBMI1Instructions && !FLAG_IS_DEFAULT(UseBMI1Instructions)) {
        UseCountTrailingZerosInstruction = false;
      } else {
        UseCountTrailingZerosInstruction = true;
      }
    }
  } else if (UseCountTrailingZerosInstruction) {
    warning("tzcnt instruction is not available on this CPU");
    FLAG_SET_DEFAULT(UseCountTrailingZerosInstruction, false);
  }
  if (supports_bmi1() && supports_avx()) {
    if (FLAG_IS_DEFAULT(UseBMI1Instructions)) {
      UseBMI1Instructions = true;
    }
  } else if (UseBMI1Instructions) {
    warning("BMI1 instructions are not available on this CPU (AVX is also required)");
    FLAG_SET_DEFAULT(UseBMI1Instructions, false);
  }
  if (supports_bmi2() && supports_avx()) {
    if (FLAG_IS_DEFAULT(UseBMI2Instructions)) {
      UseBMI2Instructions = true;
    }
  } else if (UseBMI2Instructions) {
    warning("BMI2 instructions are not available on this CPU (AVX is also required)");
    FLAG_SET_DEFAULT(UseBMI2Instructions, false);
  }
  if (supports_popcnt()) {
    if (FLAG_IS_DEFAULT(UsePopCountInstruction)) {
      UsePopCountInstruction = true;
    }
  } else if (UsePopCountInstruction) {
    warning("POPCNT instruction is not available on this CPU");
    FLAG_SET_DEFAULT(UsePopCountInstruction, false);
  }
  if (supports_erms()) {
    if (FLAG_IS_DEFAULT(UseFastStosb)) {
      UseFastStosb = true;
    }
  } else if (UseFastStosb) {
    warning("fast-string operations are not available on this CPU");
    FLAG_SET_DEFAULT(UseFastStosb, false);
  }
#ifdef COMPILER2
  if (FLAG_IS_DEFAULT(AlignVector)) {
    AlignVector = !UseUnalignedLoadStores;
  }
#endif // COMPILER2
  assert(0 <= ReadPrefetchInstr && ReadPrefetchInstr <= 3, "invalid value");
  assert(0 <= AllocatePrefetchInstr && AllocatePrefetchInstr <= 3, "invalid value");
  if( ReadPrefetchInstr < 0 ) ReadPrefetchInstr = 0;
  if( ReadPrefetchInstr > 3 ) ReadPrefetchInstr = 3;
  if( ReadPrefetchInstr == 3 && !supports_3dnow_prefetch() ) ReadPrefetchInstr = 0;
  if( !supports_sse() && supports_3dnow_prefetch() ) ReadPrefetchInstr = 3;
  if( AllocatePrefetchInstr < 0 ) AllocatePrefetchInstr = 0;
  if( AllocatePrefetchInstr > 3 ) AllocatePrefetchInstr = 3;
  if( AllocatePrefetchInstr == 3 && !supports_3dnow_prefetch() ) AllocatePrefetchInstr=0;
  if( !supports_sse() && supports_3dnow_prefetch() ) AllocatePrefetchInstr = 3;
  intx cache_line_size = prefetch_data_size();
  if( cache_line_size > AllocatePrefetchStepSize )
    AllocatePrefetchStepSize = cache_line_size;
  assert(AllocatePrefetchLines > 0, "invalid value");
  if( AllocatePrefetchLines < 1 )     // set valid value in product VM
    AllocatePrefetchLines = 3;
  assert(AllocateInstancePrefetchLines > 0, "invalid value");
  if( AllocateInstancePrefetchLines < 1 ) // set valid value in product VM
    AllocateInstancePrefetchLines = 1;
  AllocatePrefetchDistance = allocate_prefetch_distance();
  AllocatePrefetchStyle    = allocate_prefetch_style();
  if (is_intel() && cpu_family() == 6 && supports_sse3()) {
    if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core
#ifdef _LP64
      AllocatePrefetchDistance = 384;
#else
      AllocatePrefetchDistance = 320;
#endif
    }
    if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus
      AllocatePrefetchDistance = 192;
      AllocatePrefetchLines = 4;
    }
#ifdef COMPILER2
    if (supports_sse4_2()) {
      if (FLAG_IS_DEFAULT(UseFPUForSpilling)) {
        FLAG_SET_DEFAULT(UseFPUForSpilling, true);
      }
    }
#endif
  }
  assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
#ifdef _LP64
  PrefetchCopyIntervalInBytes = prefetch_copy_interval_in_bytes();
  PrefetchScanIntervalInBytes = prefetch_scan_interval_in_bytes();
  PrefetchFieldsAhead         = prefetch_fields_ahead();
#endif
  if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
     (cache_line_size > ContendedPaddingWidth))
     ContendedPaddingWidth = cache_line_size;
#ifndef PRODUCT
  if (PrintMiscellaneous && Verbose) {
    tty->print_cr("Logical CPUs per core: %u",
                  logical_processors_per_package());
    tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size());
    tty->print("UseSSE=%d", (int) UseSSE);
    if (UseAVX > 0) {
      tty->print("  UseAVX=%d", (int) UseAVX);
    }
    if (UseAES) {
      tty->print("  UseAES=1");
    }
#ifdef COMPILER2
    if (MaxVectorSize > 0) {
      tty->print("  MaxVectorSize=%d", (int) MaxVectorSize);
    }
#endif
    tty->cr();
    tty->print("Allocation");
    if (AllocatePrefetchStyle <= 0 || UseSSE == 0 && !supports_3dnow_prefetch()) {
      tty->print_cr(": no prefetching");
    } else {
      tty->print(" prefetching: ");
      if (UseSSE == 0 && supports_3dnow_prefetch()) {
        tty->print("PREFETCHW");
      } else if (UseSSE >= 1) {
        if (AllocatePrefetchInstr == 0) {
          tty->print("PREFETCHNTA");
        } else if (AllocatePrefetchInstr == 1) {
          tty->print("PREFETCHT0");
        } else if (AllocatePrefetchInstr == 2) {
          tty->print("PREFETCHT2");
        } else if (AllocatePrefetchInstr == 3) {
          tty->print("PREFETCHW");
        }
      }
      if (AllocatePrefetchLines > 1) {
        tty->print_cr(" at distance %d, %d lines of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchLines, (int) AllocatePrefetchStepSize);
      } else {
        tty->print_cr(" at distance %d, one line of %d bytes", (int) AllocatePrefetchDistance, (int) AllocatePrefetchStepSize);
      }
    }
    if (PrefetchCopyIntervalInBytes > 0) {
      tty->print_cr("PrefetchCopyIntervalInBytes %d", (int) PrefetchCopyIntervalInBytes);
    }
    if (PrefetchScanIntervalInBytes > 0) {
      tty->print_cr("PrefetchScanIntervalInBytes %d", (int) PrefetchScanIntervalInBytes);
    }
    if (PrefetchFieldsAhead > 0) {
      tty->print_cr("PrefetchFieldsAhead %d", (int) PrefetchFieldsAhead);
    }
    if (ContendedPaddingWidth > 0) {
      tty->print_cr("ContendedPaddingWidth %d", (int) ContendedPaddingWidth);
    }
  }
#endif // !PRODUCT
}
bool VM_Version::use_biased_locking() {
#if INCLUDE_RTM_OPT
  if (UseRTMLocking && UseBiasedLocking) {
    if (FLAG_IS_DEFAULT(UseBiasedLocking)) {
      FLAG_SET_DEFAULT(UseBiasedLocking, false);
    } else {
      warning("Biased locking is not supported with RTM locking; ignoring UseBiasedLocking flag." );
      UseBiasedLocking = false;
    }
  }
#endif
  return UseBiasedLocking;
}
void VM_Version::initialize() {
  ResourceMark rm;
  stub_blob = BufferBlob::create("get_cpu_info_stub", stub_size);
  if (stub_blob == NULL) {
    vm_exit_during_initialization("Unable to allocate get_cpu_info_stub");
  }
  CodeBuffer c(stub_blob);
  VM_Version_StubGenerator g(&c);
  get_cpu_info_stub = CAST_TO_FN_PTR(get_cpu_info_stub_t,
                                     g.generate_get_cpu_info());
  get_processor_features();
}
C:\hotspot-69087d08d473\src\cpu\x86\vm/vm_version_x86.hpp
#ifndef CPU_X86_VM_VM_VERSION_X86_HPP
#define CPU_X86_VM_VM_VERSION_X86_HPP
#include "runtime/globals_extension.hpp"
#include "runtime/vm_version.hpp"
class VM_Version : public Abstract_VM_Version {
public:
  union StdCpuid1Eax {
    uint32_t value;
    struct {
      uint32_t stepping   : 4,
               model      : 4,
               family     : 4,
               proc_type  : 2,
                          : 2,
               ext_model  : 4,
               ext_family : 8,
                          : 4;
    } bits;
  };
  union StdCpuid1Ebx { // example, unused
    uint32_t value;
    struct {
      uint32_t brand_id         : 8,
               clflush_size     : 8,
               threads_per_cpu  : 8,
               apic_id          : 8;
    } bits;
  };
  union StdCpuid1Ecx {
    uint32_t value;
    struct {
      uint32_t sse3     : 1,
               clmul    : 1,
                        : 1,
               monitor  : 1,
                        : 1,
               vmx      : 1,
                        : 1,
               est      : 1,
                        : 1,
               ssse3    : 1,
               cid      : 1,
                        : 2,
               cmpxchg16: 1,
                        : 4,
               dca      : 1,
               sse4_1   : 1,
               sse4_2   : 1,
                        : 2,
               popcnt   : 1,
                        : 1,
               aes      : 1,
                        : 1,
               osxsave  : 1,
               avx      : 1,
                        : 3;
    } bits;
  };
  union StdCpuid1Edx {
    uint32_t value;
    struct {
      uint32_t          : 4,
               tsc      : 1,
                        : 3,
               cmpxchg8 : 1,
                        : 6,
               cmov     : 1,
                        : 3,
               clflush  : 1,
                        : 3,
               mmx      : 1,
               fxsr     : 1,
               sse      : 1,
               sse2     : 1,
                        : 1,
               ht       : 1,
                        : 3;
    } bits;
  };
  union DcpCpuid4Eax {
    uint32_t value;
    struct {
      uint32_t cache_type    : 5,
                             : 21,
               cores_per_cpu : 6;
    } bits;
  };
  union DcpCpuid4Ebx {
    uint32_t value;
    struct {
      uint32_t L1_line_size  : 12,
               partitions    : 10,
               associativity : 10;
    } bits;
  };
  union TplCpuidBEbx {
    uint32_t value;
    struct {
      uint32_t logical_cpus : 16,
                            : 16;
    } bits;
  };
  union ExtCpuid1Ecx {
    uint32_t value;
    struct {
      uint32_t LahfSahf     : 1,
               CmpLegacy    : 1,
                            : 3,
               lzcnt_intel  : 1,
               lzcnt        : 1,
               sse4a        : 1,
               misalignsse  : 1,
               prefetchw    : 1,
                            : 22;
    } bits;
  };
  union ExtCpuid1Edx {
    uint32_t value;
    struct {
      uint32_t           : 22,
               mmx_amd   : 1,
               mmx       : 1,
               fxsr      : 1,
                         : 4,
               long_mode : 1,
               tdnow2    : 1,
               tdnow     : 1;
    } bits;
  };
  union ExtCpuid5Ex {
    uint32_t value;
    struct {
      uint32_t L1_line_size : 8,
               L1_tag_lines : 8,
               L1_assoc     : 8,
               L1_size      : 8;
    } bits;
  };
  union ExtCpuid7Edx {
    uint32_t value;
    struct {
      uint32_t               : 8,
              tsc_invariance : 1,
                             : 23;
    } bits;
  };
  union ExtCpuid8Ecx {
    uint32_t value;
    struct {
      uint32_t cores_per_cpu : 8,
                             : 24;
    } bits;
  };
  union SefCpuid7Eax {
    uint32_t value;
  };
  union SefCpuid7Ebx {
    uint32_t value;
    struct {
      uint32_t fsgsbase : 1,
                        : 2,
                   bmi1 : 1,
                        : 1,
                   avx2 : 1,
                        : 2,
                   bmi2 : 1,
                   erms : 1,
                        : 1,
                   rtm  : 1,
                        : 7,
                   adx  : 1,
                        : 12;
    } bits;
  };
  union XemXcr0Eax {
    uint32_t value;
    struct {
      uint32_t x87 : 1,
               sse : 1,
               ymm : 1,
                   : 29;
    } bits;
  };
protected:
  static int _cpu;
  static int _model;
  static int _stepping;
  static int _cpuFeatures;     // features returned by the "cpuid" instruction
  static const char* _features_str;
  static address   _cpuinfo_segv_addr; // address of instruction which causes SEGV
  static address   _cpuinfo_cont_addr; // address of instruction after the one which causes SEGV
  enum {
    CPU_CX8    = (1 << 0), // next bits are from cpuid 1 (EDX)
    CPU_CMOV   = (1 << 1),
    CPU_FXSR   = (1 << 2),
    CPU_HT     = (1 << 3),
    CPU_MMX    = (1 << 4),
    CPU_3DNOW_PREFETCH  = (1 << 5), // Processor supports 3dnow prefetch and prefetchw instructions
    CPU_SSE    = (1 << 6),
    CPU_SSE2   = (1 << 7),
    CPU_SSE3   = (1 << 8), // SSE3 comes from cpuid 1 (ECX)
    CPU_SSSE3  = (1 << 9),
    CPU_SSE4A  = (1 << 10),
    CPU_SSE4_1 = (1 << 11),
    CPU_SSE4_2 = (1 << 12),
    CPU_POPCNT = (1 << 13),
    CPU_LZCNT  = (1 << 14),
    CPU_TSC    = (1 << 15),
    CPU_TSCINV = (1 << 16),
    CPU_AVX    = (1 << 17),
    CPU_AVX2   = (1 << 18),
    CPU_AES    = (1 << 19),
    CPU_ERMS   = (1 << 20), // enhanced 'rep movsb/stosb' instructions
    CPU_CLMUL  = (1 << 21), // carryless multiply for CRC
    CPU_BMI1   = (1 << 22),
    CPU_BMI2   = (1 << 23),
    CPU_RTM    = (1 << 24),  // Restricted Transactional Memory instructions
    CPU_ADX    = (1 << 25)
  } cpuFeatureFlags;
  enum {
    CPU_FAMILY_AMD_11H       = 0x11,
    CPU_FAMILY_INTEL_CORE    = 6,
    CPU_MODEL_NEHALEM        = 0x1e,
    CPU_MODEL_NEHALEM_EP     = 0x1a,
    CPU_MODEL_NEHALEM_EX     = 0x2e,
    CPU_MODEL_WESTMERE       = 0x25,
    CPU_MODEL_WESTMERE_EP    = 0x2c,
    CPU_MODEL_WESTMERE_EX    = 0x2f,
    CPU_MODEL_SANDYBRIDGE    = 0x2a,
    CPU_MODEL_SANDYBRIDGE_EP = 0x2d,
    CPU_MODEL_IVYBRIDGE_EP   = 0x3a,
    CPU_MODEL_HASWELL_E3     = 0x3c,
    CPU_MODEL_HASWELL_E7     = 0x3f,
    CPU_MODEL_BROADWELL      = 0x3d
  } cpuExtendedFamily;
  struct CpuidInfo {
    uint32_t std_max_function;
    uint32_t std_vendor_name_0;
    uint32_t std_vendor_name_1;
    uint32_t std_vendor_name_2;
    StdCpuid1Eax std_cpuid1_eax;
    StdCpuid1Ebx std_cpuid1_ebx;
    StdCpuid1Ecx std_cpuid1_ecx;
    StdCpuid1Edx std_cpuid1_edx;
    DcpCpuid4Eax dcp_cpuid4_eax;
    DcpCpuid4Ebx dcp_cpuid4_ebx;
    uint32_t     dcp_cpuid4_ecx; // unused currently
    uint32_t     dcp_cpuid4_edx; // unused currently
    SefCpuid7Eax sef_cpuid7_eax;
    SefCpuid7Ebx sef_cpuid7_ebx;
    uint32_t     sef_cpuid7_ecx; // unused currently
    uint32_t     sef_cpuid7_edx; // unused currently
    uint32_t     tpl_cpuidB0_eax;
    TplCpuidBEbx tpl_cpuidB0_ebx;
    uint32_t     tpl_cpuidB0_ecx; // unused currently
    uint32_t     tpl_cpuidB0_edx; // unused currently
    uint32_t     tpl_cpuidB1_eax;
    TplCpuidBEbx tpl_cpuidB1_ebx;
    uint32_t     tpl_cpuidB1_ecx; // unused currently
    uint32_t     tpl_cpuidB1_edx; // unused currently
    uint32_t     tpl_cpuidB2_eax;
    TplCpuidBEbx tpl_cpuidB2_ebx;
    uint32_t     tpl_cpuidB2_ecx; // unused currently
    uint32_t     tpl_cpuidB2_edx; // unused currently
    uint32_t ext_max_function;
    uint32_t ext_vendor_name_0;
    uint32_t ext_vendor_name_1;
    uint32_t ext_vendor_name_2;
    uint32_t     ext_cpuid1_eax; // reserved
    uint32_t     ext_cpuid1_ebx; // reserved
    ExtCpuid1Ecx ext_cpuid1_ecx;
    ExtCpuid1Edx ext_cpuid1_edx;
    uint32_t proc_name_0, proc_name_1, proc_name_2, proc_name_3;
    uint32_t proc_name_4, proc_name_5, proc_name_6, proc_name_7;
    uint32_t proc_name_8, proc_name_9, proc_name_10,proc_name_11;
    uint32_t     ext_cpuid5_eax; // unused currently
    uint32_t     ext_cpuid5_ebx; // reserved
    ExtCpuid5Ex  ext_cpuid5_ecx; // L1 data cache info (AMD)
    ExtCpuid5Ex  ext_cpuid5_edx; // L1 instruction cache info (AMD)
    uint32_t     ext_cpuid7_eax; // reserved
    uint32_t     ext_cpuid7_ebx; // reserved
    uint32_t     ext_cpuid7_ecx; // reserved
    ExtCpuid7Edx ext_cpuid7_edx; // tscinv
    uint32_t     ext_cpuid8_eax; // unused currently
    uint32_t     ext_cpuid8_ebx; // reserved
    ExtCpuid8Ecx ext_cpuid8_ecx;
    uint32_t     ext_cpuid8_edx; // reserved
    XemXcr0Eax   xem_xcr0_eax;
    uint32_t     xem_xcr0_edx; // reserved
    int          ymm_save[8*4]; // Save ymm0, ymm7, ymm8, ymm15
  };
  static CpuidInfo _cpuid_info;
  static uint32_t extended_cpu_family() {
    uint32_t result = _cpuid_info.std_cpuid1_eax.bits.family;
    result += _cpuid_info.std_cpuid1_eax.bits.ext_family;
    return result;
  }
  static uint32_t extended_cpu_model() {
    uint32_t result = _cpuid_info.std_cpuid1_eax.bits.model;
    result |= _cpuid_info.std_cpuid1_eax.bits.ext_model << 4;
    return result;
  }
  static uint32_t cpu_stepping() {
    uint32_t result = _cpuid_info.std_cpuid1_eax.bits.stepping;
    return result;
  }
  static uint logical_processor_count() {
    uint result = threads_per_core();
    return result;
  }
  static uint32_t feature_flags() {
    uint32_t result = 0;
    if (_cpuid_info.std_cpuid1_edx.bits.cmpxchg8 != 0)
      result |= CPU_CX8;
    if (_cpuid_info.std_cpuid1_edx.bits.cmov != 0)
      result |= CPU_CMOV;
    if (_cpuid_info.std_cpuid1_edx.bits.fxsr != 0 || (is_amd() &&
        _cpuid_info.ext_cpuid1_edx.bits.fxsr != 0))
      result |= CPU_FXSR;
    if (threads_per_core() > 1)
      result |= CPU_HT;
    if (_cpuid_info.std_cpuid1_edx.bits.mmx != 0 || (is_amd() &&
        _cpuid_info.ext_cpuid1_edx.bits.mmx != 0))
      result |= CPU_MMX;
    if (_cpuid_info.std_cpuid1_edx.bits.sse != 0)
      result |= CPU_SSE;
    if (_cpuid_info.std_cpuid1_edx.bits.sse2 != 0)
      result |= CPU_SSE2;
    if (_cpuid_info.std_cpuid1_ecx.bits.sse3 != 0)
      result |= CPU_SSE3;
    if (_cpuid_info.std_cpuid1_ecx.bits.ssse3 != 0)
      result |= CPU_SSSE3;
    if (_cpuid_info.std_cpuid1_ecx.bits.sse4_1 != 0)
      result |= CPU_SSE4_1;
    if (_cpuid_info.std_cpuid1_ecx.bits.sse4_2 != 0)
      result |= CPU_SSE4_2;
    if (_cpuid_info.std_cpuid1_ecx.bits.popcnt != 0)
      result |= CPU_POPCNT;
    if (_cpuid_info.std_cpuid1_ecx.bits.avx != 0 &&
        _cpuid_info.std_cpuid1_ecx.bits.osxsave != 0 &&
        _cpuid_info.xem_xcr0_eax.bits.sse != 0 &&
        _cpuid_info.xem_xcr0_eax.bits.ymm != 0) {
      result |= CPU_AVX;
      if (_cpuid_info.sef_cpuid7_ebx.bits.avx2 != 0)
        result |= CPU_AVX2;
    }
    if(_cpuid_info.sef_cpuid7_ebx.bits.bmi1 != 0)
      result |= CPU_BMI1;
    if (_cpuid_info.std_cpuid1_edx.bits.tsc != 0)
      result |= CPU_TSC;
    if (_cpuid_info.ext_cpuid7_edx.bits.tsc_invariance != 0)
      result |= CPU_TSCINV;
    if (_cpuid_info.std_cpuid1_ecx.bits.aes != 0)
      result |= CPU_AES;
    if (_cpuid_info.sef_cpuid7_ebx.bits.erms != 0)
      result |= CPU_ERMS;
    if (_cpuid_info.std_cpuid1_ecx.bits.clmul != 0)
      result |= CPU_CLMUL;
    if (_cpuid_info.sef_cpuid7_ebx.bits.rtm != 0)
      result |= CPU_RTM;
    if (is_amd()) {
      if ((_cpuid_info.ext_cpuid1_edx.bits.tdnow != 0) ||
          (_cpuid_info.ext_cpuid1_ecx.bits.prefetchw != 0))
        result |= CPU_3DNOW_PREFETCH;
      if (_cpuid_info.ext_cpuid1_ecx.bits.lzcnt != 0)
        result |= CPU_LZCNT;
      if (_cpuid_info.ext_cpuid1_ecx.bits.sse4a != 0)
        result |= CPU_SSE4A;
    }
    if(is_intel()) {
      if(_cpuid_info.sef_cpuid7_ebx.bits.adx != 0)
         result |= CPU_ADX;
      if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0)
        result |= CPU_BMI2;
      if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0)
        result |= CPU_LZCNT;
      if (_cpuid_info.ext_cpuid1_ecx.bits.misalignsse != 0) {
        result |= CPU_3DNOW_PREFETCH;
      }
    }
    return result;
  }
  static bool os_supports_avx_vectors() {
    if (!supports_avx()) {
      return false;
    }
    int nreg = 2 LP64_ONLY(+2);
    for (int i = 0; i < 8 * nreg; i++) { // 32 bytes per ymm register
      if (_cpuid_info.ymm_save[i] != ymm_test_value()) {
        return false;
      }
    }
    return true;
  }
  static void get_processor_features();
public:
  static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); }
  static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); }
  static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); }
  static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); }
  static ByteSize ext_cpuid1_offset() { return byte_offset_of(CpuidInfo, ext_cpuid1_eax); }
  static ByteSize ext_cpuid5_offset() { return byte_offset_of(CpuidInfo, ext_cpuid5_eax); }
  static ByteSize ext_cpuid7_offset() { return byte_offset_of(CpuidInfo, ext_cpuid7_eax); }
  static ByteSize ext_cpuid8_offset() { return byte_offset_of(CpuidInfo, ext_cpuid8_eax); }
  static ByteSize tpl_cpuidB0_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB0_eax); }
  static ByteSize tpl_cpuidB1_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB1_eax); }
  static ByteSize tpl_cpuidB2_offset() { return byte_offset_of(CpuidInfo, tpl_cpuidB2_eax); }
  static ByteSize xem_xcr0_offset() { return byte_offset_of(CpuidInfo, xem_xcr0_eax); }
  static ByteSize ymm_save_offset() { return byte_offset_of(CpuidInfo, ymm_save); }
  static int ymm_test_value()    { return 0xCAFEBABE; }
  static void get_cpu_info_wrapper();
  static void set_cpuinfo_segv_addr(address pc) { _cpuinfo_segv_addr = pc; }
  static bool  is_cpuinfo_segv_addr(address pc) { return _cpuinfo_segv_addr == pc; }
  static void set_cpuinfo_cont_addr(address pc) { _cpuinfo_cont_addr = pc; }
  static address  cpuinfo_cont_addr()           { return _cpuinfo_cont_addr; }
  static void clean_cpuFeatures()   { _cpuFeatures = 0; }
  static void set_avx_cpuFeatures() { _cpuFeatures = (CPU_SSE | CPU_SSE2 | CPU_AVX); }
  static void initialize();
  static bool use_biased_locking();
  static void assert_is_initialized() {
    assert(_cpuid_info.std_cpuid1_eax.bits.family != 0, "VM_Version not initialized");
  }
  static int  cpu_family()        { return _cpu;}
  static bool is_P6()             { return cpu_family() >= 6; }
  static bool is_amd()            { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
  static bool is_intel()          { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x756e6547; } // 'uneG'
  static bool supports_processor_topology() {
    return (_cpuid_info.std_max_function >= 0xB) &&
           (((_cpuid_info.tpl_cpuidB0_eax & 0x1f) | _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus) != 0);
  }
  static uint cores_per_cpu()  {
    uint result = 1;
    if (is_intel()) {
      bool supports_topology = supports_processor_topology();
      if (supports_topology) {
        result = _cpuid_info.tpl_cpuidB1_ebx.bits.logical_cpus /
                 _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
      }
      if (!supports_topology || result == 0) {
        result = (_cpuid_info.dcp_cpuid4_eax.bits.cores_per_cpu + 1);
      }
    } else if (is_amd()) {
      result = (_cpuid_info.ext_cpuid8_ecx.bits.cores_per_cpu + 1);
    }
    return result;
  }
  static uint threads_per_core()  {
    uint result = 1;
    if (is_intel() && supports_processor_topology()) {
      result = _cpuid_info.tpl_cpuidB0_ebx.bits.logical_cpus;
    } else if (_cpuid_info.std_cpuid1_edx.bits.ht != 0) {
      result = _cpuid_info.std_cpuid1_ebx.bits.threads_per_cpu /
               cores_per_cpu();
    }
    return (result == 0 ? 1 : result);
  }
  static intx L1_line_size()  {
    intx result = 0;
    if (is_intel()) {
      result = (_cpuid_info.dcp_cpuid4_ebx.bits.L1_line_size + 1);
    } else if (is_amd()) {
      result = _cpuid_info.ext_cpuid5_ecx.bits.L1_line_size;
    }
    if (result < 32) // not defined ?
      result = 32;   // 32 bytes by default on x86 and other x64
    return result;
  }
  static intx prefetch_data_size()  {
    return L1_line_size();
  }
  static bool supports_cpuid()    { return _cpuFeatures  != 0; }
  static bool supports_cmpxchg8() { return (_cpuFeatures & CPU_CX8) != 0; }
  static bool supports_cmov()     { return (_cpuFeatures & CPU_CMOV) != 0; }
  static bool supports_fxsr()     { return (_cpuFeatures & CPU_FXSR) != 0; }
  static bool supports_ht()       { return (_cpuFeatures & CPU_HT) != 0; }
  static bool supports_mmx()      { return (_cpuFeatures & CPU_MMX) != 0; }
  static bool supports_sse()      { return (_cpuFeatures & CPU_SSE) != 0; }
  static bool supports_sse2()     { return (_cpuFeatures & CPU_SSE2) != 0; }
  static bool supports_sse3()     { return (_cpuFeatures & CPU_SSE3) != 0; }
  static bool supports_ssse3()    { return (_cpuFeatures & CPU_SSSE3)!= 0; }
  static bool supports_sse4_1()   { return (_cpuFeatures & CPU_SSE4_1) != 0; }
  static bool supports_sse4_2()   { return (_cpuFeatures & CPU_SSE4_2) != 0; }
  static bool supports_popcnt()   { return (_cpuFeatures & CPU_POPCNT) != 0; }
  static bool supports_avx()      { return (_cpuFeatures & CPU_AVX) != 0; }
  static bool supports_avx2()     { return (_cpuFeatures & CPU_AVX2) != 0; }
  static bool supports_tsc()      { return (_cpuFeatures & CPU_TSC)    != 0; }
  static bool supports_aes()      { return (_cpuFeatures & CPU_AES) != 0; }
  static bool supports_erms()     { return (_cpuFeatures & CPU_ERMS) != 0; }
  static bool supports_clmul()    { return (_cpuFeatures & CPU_CLMUL) != 0; }
  static bool supports_rtm()      { return (_cpuFeatures & CPU_RTM) != 0; }
  static bool supports_bmi1()     { return (_cpuFeatures & CPU_BMI1) != 0; }
  static bool supports_bmi2()     { return (_cpuFeatures & CPU_BMI2) != 0; }
  static bool supports_adx()     { return (_cpuFeatures & CPU_ADX) != 0; }
  static bool is_intel_family_core() { return is_intel() &&
                                       extended_cpu_family() == CPU_FAMILY_INTEL_CORE; }
  static bool is_intel_tsc_synched_at_init()  {
    if (is_intel_family_core()) {
      uint32_t ext_model = extended_cpu_model();
      if (ext_model == CPU_MODEL_NEHALEM_EP     ||
          ext_model == CPU_MODEL_WESTMERE_EP    ||
          ext_model == CPU_MODEL_SANDYBRIDGE_EP ||
          ext_model == CPU_MODEL_IVYBRIDGE_EP) {
        return true;
      }
    }
    return false;
  }
  static bool supports_3dnow_prefetch()    { return (_cpuFeatures & CPU_3DNOW_PREFETCH) != 0; }
  static bool supports_mmx_ext()  { return is_amd() && _cpuid_info.ext_cpuid1_edx.bits.mmx_amd != 0; }
  static bool supports_lzcnt()    { return (_cpuFeatures & CPU_LZCNT) != 0; }
  static bool supports_sse4a()    { return (_cpuFeatures & CPU_SSE4A) != 0; }
  static bool is_amd_Barcelona()  { return is_amd() &&
                                           extended_cpu_family() == CPU_FAMILY_AMD_11H; }
  static bool supports_tscinv_bit() {
    return (_cpuFeatures & CPU_TSCINV) != 0;
  }
  static bool supports_tscinv() {
    return supports_tscinv_bit() &&
           ( (is_amd() && !is_amd_Barcelona()) ||
             is_intel_tsc_synched_at_init() );
  }
  static bool has_fast_idiv()     { return is_intel() && cpu_family() == 6 &&
                                           supports_sse3() && _model != 0x1C; }
  static bool supports_compare_and_exchange() { return true; }
  static const char* cpu_features()           { return _features_str; }
  static intx allocate_prefetch_distance() {
    intx count = AllocatePrefetchDistance;
    if (count < 0) {   // default ?
      if (is_amd()) {  // AMD
        if (supports_sse2())
          count = 256; // Opteron
        else
          count = 128; // Athlon
      } else {         // Intel
        if (supports_sse2())
          if (cpu_family() == 6) {
            count = 256; // Pentium M, Core, Core2
          } else {
            count = 512; // Pentium 4
          }
        else
          count = 128; // Pentium 3 (and all other old CPUs)
      }
    }
    return count;
  }
  static intx allocate_prefetch_style() {
    assert(AllocatePrefetchStyle >= 0, "AllocatePrefetchStyle should be positive");
    return AllocatePrefetchDistance > 0 ? AllocatePrefetchStyle : 0;
  }
  static intx prefetch_copy_interval_in_bytes() {
    intx interval = PrefetchCopyIntervalInBytes;
    return interval >= 0 ? interval : 576;
  }
  static intx prefetch_scan_interval_in_bytes() {
    intx interval = PrefetchScanIntervalInBytes;
    return interval >= 0 ? interval : 576;
  }
  static intx prefetch_fields_ahead() {
    intx count = PrefetchFieldsAhead;
    return count >= 0 ? count : 1;
  }
#ifdef __APPLE__
  static bool is_cpu_emulated();
#endif
};
#endif // CPU_X86_VM_VM_VERSION_X86_HPP
C:\hotspot-69087d08d473\src\cpu\x86\vm/vtableStubs_x86_32.cpp
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
#include "vmreg_x86.inline.hpp"
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
#define __ masm->
#ifndef PRODUCT
extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int index);
#endif
VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
  const int i486_code_length = VtableStub::pd_code_size_limit(true);
  VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index);
  if (s == NULL) {
    return NULL;
  }
  ResourceMark rm;
  CodeBuffer cb(s->entry_point(), i486_code_length);
  MacroAssembler* masm = new MacroAssembler(&cb);
#ifndef PRODUCT
  if (CountCompiledCalls) {
    __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
  }
#endif /* PRODUCT */
  assert(VtableStub::receiver_location() == rcx->as_VMReg(), "receiver expected in rcx");
  address npe_addr = __ pc();
  __ movptr(rax, Address(rcx, oopDesc::klass_offset_in_bytes()));
#ifndef PRODUCT
  if (DebugVtables) {
    Label L;
    __ cmpl(Address(rax, InstanceKlass::vtable_length_offset()*wordSize), vtable_index*vtableEntry::size());
    __ jcc(Assembler::greater, L);
    __ movl(rbx, vtable_index);
    __ call_VM(noreg, CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), rcx, rbx);
    __ bind(L);
  }
#endif // PRODUCT
  const Register method = rbx;
  __ lookup_virtual_method(rax, vtable_index, method);
  if (DebugVtables) {
    Label L;
    __ cmpptr(method, (int32_t)NULL_WORD);
    __ jcc(Assembler::equal, L);
    __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD);
    __ jcc(Assembler::notZero, L);
    __ stop("Vtable entry is NULL");
    __ bind(L);
  }
  address ame_addr = __ pc();
  __ jmp( Address(method, Method::from_compiled_offset()));
  masm->flush();
  if (PrintMiscellaneous && (WizardMode || Verbose)) {
    tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d",
                  vtable_index, p2i(s->entry_point()),
                  (int)(s->code_end() - s->entry_point()),
                  (int)(s->code_end() - __ pc()));
  }
  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
  int slop = 3;  // 32-bit offset is this much larger than an 8-bit one
  assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
  s->set_exception_points(npe_addr, ame_addr);
  return s;
}
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
  const int i486_code_length = VtableStub::pd_code_size_limit(false);
  VtableStub* s = new(i486_code_length) VtableStub(false, itable_index);
  if (s == NULL) {
    return NULL;
  }
  ResourceMark rm;
  CodeBuffer cb(s->entry_point(), i486_code_length);
  MacroAssembler* masm = new MacroAssembler(&cb);
#ifndef PRODUCT
  if (CountCompiledCalls) {
    __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
  }
#endif /* PRODUCT */
  const Register recv_klass_reg     = rsi;
  const Register holder_klass_reg   = rax; // declaring interface klass (DECC)
  const Register resolved_klass_reg = rbx; // resolved interface klass (REFC)
  const Register temp_reg           = rdi;
  const Register icholder_reg = rax;
  __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
  __ movptr(holder_klass_reg,   Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
  Label L_no_such_interface;
  address npe_addr = __ pc();
  assert(VtableStub::receiver_location() ==  rcx->as_VMReg(), "receiver expected in  rcx");
  __ load_klass(recv_klass_reg, rcx);
  __ lookup_interface_method(// inputs: rec. class, interface
                             recv_klass_reg, resolved_klass_reg, noreg,
                             recv_klass_reg, temp_reg,
                             L_no_such_interface,
  const Register method = rbx;
  __ load_klass(recv_klass_reg, rcx); // restore recv_klass_reg
  __ lookup_interface_method(// inputs: rec. class, interface, itable index
                             recv_klass_reg, holder_klass_reg, itable_index,
                             method, temp_reg,
                             L_no_such_interface);
#ifdef ASSERT
  if (DebugVtables) {
      Label L1;
      __ cmpptr(method, (int32_t)NULL_WORD);
      __ jcc(Assembler::equal, L1);
      __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD);
      __ jcc(Assembler::notZero, L1);
      __ stop("Method* is null");
      __ bind(L1);
    }
#endif // ASSERT
  address ame_addr = __ pc();
  __ jmp(Address(method, Method::from_compiled_offset()));
  __ bind(L_no_such_interface);
  __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
  __ flush();
  if (PrintMiscellaneous && (WizardMode || Verbose)) {
    tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d",
                  itable_index, p2i(s->entry_point()),
                  (int)(s->code_end() - s->entry_point()),
                  (int)(s->code_end() - __ pc()));
  }
  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
  int slop = 3;  // 32-bit offset is this much larger than an 8-bit one
  assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
  s->set_exception_points(npe_addr, ame_addr);
  return s;
}
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
  if (is_vtable_stub) {
    return (DebugVtables ? 210 : 16) + (CountCompiledCalls ? 6 : 0);
  } else {
    return (DebugVtables ? 256 : 116) + (CountCompiledCalls ? 6 : 0);
  }
}
int VtableStub::pd_code_alignment() {
  return wordSize;
}
C:\hotspot-69087d08d473\src\cpu\x86\vm/vtableStubs_x86_64.cpp
#include "precompiled.hpp"
#include "asm/macroAssembler.hpp"
#include "code/vtableStubs.hpp"
#include "interp_masm_x86.hpp"
#include "memory/resourceArea.hpp"
#include "oops/compiledICHolder.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klassVtable.hpp"
#include "runtime/sharedRuntime.hpp"
#include "vmreg_x86.inline.hpp"
#ifdef COMPILER2
#include "opto/runtime.hpp"
#endif
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#define __ masm->
#ifndef PRODUCT
extern "C" void bad_compiled_vtable_index(JavaThread* thread,
                                          oop receiver,
                                          int index);
#endif
VtableStub* VtableStubs::create_vtable_stub(int vtable_index) {
  const int amd64_code_length = VtableStub::pd_code_size_limit(true);
  VtableStub* s = new(amd64_code_length) VtableStub(true, vtable_index);
  if (s == NULL) {
    return NULL;
  }
  ResourceMark rm;
  CodeBuffer cb(s->entry_point(), amd64_code_length);
  MacroAssembler* masm = new MacroAssembler(&cb);
#ifndef PRODUCT
  if (CountCompiledCalls) {
    __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
  }
#endif
  assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
  address npe_addr = __ pc();
  __ load_klass(rax, j_rarg0);
#ifndef PRODUCT
  if (DebugVtables) {
    Label L;
    __ cmpl(Address(rax, InstanceKlass::vtable_length_offset() * wordSize),
            vtable_index * vtableEntry::size());
    __ jcc(Assembler::greater, L);
    __ movl(rbx, vtable_index);
    __ call_VM(noreg,
               CAST_FROM_FN_PTR(address, bad_compiled_vtable_index), j_rarg0, rbx);
    __ bind(L);
  }
#endif // PRODUCT
  const Register method = rbx;
  __ lookup_virtual_method(rax, vtable_index, method);
  if (DebugVtables) {
    Label L;
    __ cmpptr(method, (int32_t)NULL_WORD);
    __ jcc(Assembler::equal, L);
    __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD);
    __ jcc(Assembler::notZero, L);
    __ stop("Vtable entry is NULL");
    __ bind(L);
  }
  address ame_addr = __ pc();
  __ jmp( Address(rbx, Method::from_compiled_offset()));
  __ flush();
  if (PrintMiscellaneous && (WizardMode || Verbose)) {
    tty->print_cr("vtable #%d at " PTR_FORMAT "[%d] left over: %d",
                  vtable_index, s->entry_point(),
                  (int)(s->code_end() - s->entry_point()),
                  (int)(s->code_end() - __ pc()));
  }
  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
  int slop = 3;  // 32-bit offset is this much larger than an 8-bit one
  assert(vtable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
  s->set_exception_points(npe_addr, ame_addr);
  return s;
}
VtableStub* VtableStubs::create_itable_stub(int itable_index) {
  const int amd64_code_length = VtableStub::pd_code_size_limit(false);
  VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index);
  if (s == NULL) {
    return NULL;
  }
  ResourceMark rm;
  CodeBuffer cb(s->entry_point(), amd64_code_length);
  MacroAssembler* masm = new MacroAssembler(&cb);
#ifndef PRODUCT
  if (CountCompiledCalls) {
    __ incrementl(ExternalAddress((address) SharedRuntime::nof_megamorphic_calls_addr()));
  }
#endif
  const Register recv_klass_reg     = r10;
  const Register holder_klass_reg   = rax; // declaring interface klass (DECC)
  const Register resolved_klass_reg = rbx; // resolved interface klass (REFC)
  const Register temp_reg           = r11;
  Label L_no_such_interface;
  const Register icholder_reg = rax;
  __ movptr(resolved_klass_reg, Address(icholder_reg, CompiledICHolder::holder_klass_offset()));
  __ movptr(holder_klass_reg,   Address(icholder_reg, CompiledICHolder::holder_metadata_offset()));
  assert(VtableStub::receiver_location() == j_rarg0->as_VMReg(), "receiver expected in j_rarg0");
  address npe_addr = __ pc();
  __ load_klass(recv_klass_reg, j_rarg0);
  __ lookup_interface_method(// inputs: rec. class, interface
                             recv_klass_reg, resolved_klass_reg, noreg,
                             recv_klass_reg, temp_reg,
                             L_no_such_interface,
  const Register method = rbx;
  __ load_klass(recv_klass_reg, j_rarg0);   // restore recv_klass_reg
  __ lookup_interface_method(// inputs: rec. class, interface, itable index
                       recv_klass_reg, holder_klass_reg, itable_index,
                       method, temp_reg,
                       L_no_such_interface);
#ifdef ASSERT
  if (DebugVtables) {
    Label L2;
    __ cmpptr(method, (int32_t)NULL_WORD);
    __ jcc(Assembler::equal, L2);
    __ cmpptr(Address(method, Method::from_compiled_offset()), (int32_t)NULL_WORD);
    __ jcc(Assembler::notZero, L2);
    __ stop("compiler entrypoint is null");
    __ bind(L2);
  }
#endif // ASSERT
  address ame_addr = __ pc();
  __ jmp(Address(method, Method::from_compiled_offset()));
  __ bind(L_no_such_interface);
  __ jump(RuntimeAddress(StubRoutines::throw_IncompatibleClassChangeError_entry()));
  __ flush();
  if (PrintMiscellaneous && (WizardMode || Verbose)) {
    tty->print_cr("itable #%d at " PTR_FORMAT "[%d] left over: %d",
                  itable_index, s->entry_point(),
                  (int)(s->code_end() - s->entry_point()),
                  (int)(s->code_end() - __ pc()));
  }
  guarantee(__ pc() <= s->code_end(), "overflowed buffer");
  int slop = 3;  // 32-bit offset is this much larger than an 8-bit one
  assert(itable_index > 10 || __ pc() + slop <= s->code_end(), "room for 32-bit offset");
  s->set_exception_points(npe_addr, ame_addr);
  return s;
}
int VtableStub::pd_code_size_limit(bool is_vtable_stub) {
  if (is_vtable_stub) {
    return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0) +
           (UseCompressedClassPointers ?  MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
  } else {
    return (DebugVtables ? 512 : 140) + (CountCompiledCalls ? 13 : 0) +
           (UseCompressedClassPointers ? 2 * MacroAssembler::instr_size_for_decode_klass_not_null() : 0);
  }
}
int VtableStub::pd_code_alignment() {
  return wordSize;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值