示例#1
0
void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
  assert(x->number_of_arguments() == 3, "wrong type");
  LIRItem obj       (x->argument_at(0), this);  // AtomicLong object
  LIRItem cmp_value (x->argument_at(1), this);  // value to compare with field
  LIRItem new_value (x->argument_at(2), this);  // replace field with new_value if it matches cmp_value

  // compare value must be in rdx,eax (hi,lo); may be destroyed by cmpxchg8 instruction
  cmp_value.load_item_force(FrameMap::long0_opr);

  // new value must be in rcx,ebx (hi,lo)
  new_value.load_item_force(FrameMap::long1_opr);

  // object pointer register is overwritten with field address
  obj.load_item();

  // generate compare-and-swap; produces zero condition if swap occurs
  int value_offset = sun_misc_AtomicLongCSImpl::value_offset();
  LIR_Opr addr = new_pointer_register();
  __ leal(LIR_OprFact::address(new LIR_Address(obj.result(), value_offset, T_LONG)), addr);
  LIR_Opr t1 = LIR_OprFact::illegalOpr;  // no temp needed
  LIR_Opr t2 = LIR_OprFact::illegalOpr;  // no temp needed
  __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2);

  // generate conditional move of boolean result
  LIR_Opr result = rlock_result(x);
  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result, T_LONG);
}
void LIRGenerator::do_NewMultiArray(NewMultiArray* x) {
  // make sure registers are spilled
  spill_values_on_stack(x->state());
  if (x->state_before() != NULL) {
    spill_values_on_stack(x->state_before());
  }
  Values* dims = x->dims();
  int i = dims->length();
  LIRItemList* items = new LIRItemList();
  while (i-- > 0) {
    LIRItem* size = new LIRItem(dims->at(i), this);
    items->at_put(i, size);
    assert(!size->is_register() || x->state_before() == NULL, "shouldn't be since it was spilled above");
  }

  // need to get the info before, as the items may become invalid through item_free

  CodeEmitInfo* patching_info = NULL;
  if (!x->klass()->is_loaded() || PatchALot) {
    patching_info = state_for(x, x->state_before());
  }
  i = dims->length();
  while (i-- > 0) {
    LIRItem* size = items->at(i);
    size->load_item();

    emit()->store_stack_parameter(size->result(), i);
  }
  RInfo reg = set_with_result_register(x)->rinfo();

  CodeEmitInfo* info = state_for(x, x->state());
  emit()->new_multi_array(reg, x->klass(), x->rank(), norinfo, info, patching_info);
}
void LIRGenerator::do_NewMultiArray(NewMultiArray* x) {
  Values* dims = x->dims();
  int i = dims->length();
  LIRItemList* items = new LIRItemList(dims->length(), NULL);
  while (i-- > 0) {
    LIRItem* size = new LIRItem(dims->at(i), this);
    items->at_put(i, size);
  }

  // need to get the info before, as the items may become invalid through item_free
  CodeEmitInfo* patching_info = NULL;
  if (!x->klass()->is_loaded() || PatchALot) {
    patching_info = state_for(x, x->state_before());

    // cannot re-use same xhandlers for multiple CodeEmitInfos, so
    // clone all handlers
    x->set_exception_handlers(new XHandlers(x->exception_handlers()));
  }

  i = dims->length();
  while (i-- > 0) {
    LIRItem* size = items->at(i);
    // if a patching_info was generated above then debug information for the state before
    // the call is going to be emitted.  The LIRGenerator calls above may have left some values
    // in registers and that's been recorded in the CodeEmitInfo.  In that case the items
    // for those values can't simply be freed if they are registers because the values
    // might be destroyed by store_stack_parameter.  So in the case of patching, delay the
    // freeing of the items that already were in registers
    size->load_item();
    store_stack_parameter (size->result(),
                           in_ByteSize(STACK_BIAS +
                                       frame::memory_parameter_word_sp_offset * wordSize +
                                       i * sizeof(jint)));
  }

  // This instruction can be deoptimized in the slow path : use
  // O0 as result register.
  const LIR_Opr reg = result_register_for(x->type());
  CodeEmitInfo* info = state_for(x, x->state());

  jobject2reg_with_patching(reg, x->klass(), patching_info);
  LIR_Opr rank = FrameMap::O1_opr;
  __ move(LIR_OprFact::intConst(x->rank()), rank);
  LIR_Opr varargs = FrameMap::as_pointer_opr(O2);
  int offset_from_sp = (frame::memory_parameter_word_sp_offset * wordSize) + STACK_BIAS;
  __ add(FrameMap::SP_opr,
         LIR_OprFact::intptrConst(offset_from_sp),
         varargs);
  LIR_OprList* args = new LIR_OprList(3);
  args->append(reg);
  args->append(rank);
  args->append(varargs);
  __ call_runtime(Runtime1::entry_for(Runtime1::new_multi_array_id),
                  LIR_OprFact::illegalOpr,
                  reg, args, info);

  LIR_Opr result = rlock_result(x);
  __ move(reg, result);
}
void LIRGenerator::do_ArrayCopy(Intrinsic* x) {
  assert(x->number_of_arguments() == 5, "wrong type");
  // Note: spill caller save before setting the item
  LIRItem src     (x->argument_at(0), this);
  LIRItem src_pos (x->argument_at(1), this);
  LIRItem dst     (x->argument_at(2), this);
  LIRItem dst_pos (x->argument_at(3), this);
  LIRItem length  (x->argument_at(4), this);
  // load all values in callee_save_registers, as this makes the
  // parameter passing to the fast case simpler
  src.load_item_force     (rlock_callee_saved(T_OBJECT));
  src_pos.load_item_force (rlock_callee_saved(T_INT));
  dst.load_item_force     (rlock_callee_saved(T_OBJECT));
  dst_pos.load_item_force (rlock_callee_saved(T_INT));
  length.load_item_force  (rlock_callee_saved(T_INT));

  int flags;
  ciArrayKlass* expected_type;
  arraycopy_helper(x, &flags, &expected_type);

  CodeEmitInfo* info = state_for(x, x->state());
  __ arraycopy(src.result(), src_pos.result(), dst.result(), dst_pos.result(),
               length.result(), rlock_callee_saved(T_INT),
               expected_type, flags, info);
  set_no_result(x);
}
示例#5
0
void LIRGenerator::do_NewMultiArray(NewMultiArray* x) {
  Values* dims = x->dims();
  int i = dims->length();
  LIRItemList* items = new LIRItemList(dims->length(), NULL);
  while (i-- > 0) {
    LIRItem* size = new LIRItem(dims->at(i), this);
    items->at_put(i, size);
  }

  // Evaluate state_for early since it may emit code.
  CodeEmitInfo* patching_info = NULL;
  if (!x->klass()->is_loaded() || PatchALot) {
    patching_info = state_for(x, x->state_before());

    // cannot re-use same xhandlers for multiple CodeEmitInfos, so
    // clone all handlers.  This is handled transparently in other
    // places by the CodeEmitInfo cloning logic but is handled
    // specially here because a stub isn't being used.
    x->set_exception_handlers(new XHandlers(x->exception_handlers()));
  }
  CodeEmitInfo* info = state_for(x, x->state());

  i = dims->length();
  while (i-- > 0) {
    LIRItem* size = items->at(i);
    size->load_nonconstant();

    store_stack_parameter(size->result(), in_ByteSize(i*4));
  }

  LIR_Opr reg = result_register_for(x->type());
  jobject2reg_with_patching(reg, x->klass(), patching_info);

  LIR_Opr rank = FrameMap::rbx_opr;
  __ move(LIR_OprFact::intConst(x->rank()), rank);
  LIR_Opr varargs = FrameMap::rcx_opr;
  __ move(FrameMap::rsp_opr, varargs);
  LIR_OprList* args = new LIR_OprList(3);
  args->append(reg);
  args->append(rank);
  args->append(varargs);
  __ call_runtime(Runtime1::entry_for(Runtime1::new_multi_array_id),
                  LIR_OprFact::illegalOpr,
                  reg, args, info);

  LIR_Opr result = rlock_result(x);
  __ move(reg, result);
}
void LIRGenerator::do_AttemptUpdate(Intrinsic* x) {
  assert(x->number_of_arguments() == 3, "wrong type");
  LIRItem obj       (x->argument_at(0), this);  // AtomicLong object
  LIRItem cmp_value (x->argument_at(1), this);  // value to compare with field
  LIRItem new_value (x->argument_at(2), this);  // replace field with new_value if it matches cmp_value

  obj.load_item();
  cmp_value.load_item();
  new_value.load_item();

  // generate compare-and-swap and produce zero condition if swap occurs
  int value_offset = sun_misc_AtomicLongCSImpl::value_offset();
  LIR_Opr addr = FrameMap::O7_opr;
  __ add(obj.result(), LIR_OprFact::intConst(value_offset), addr);
  LIR_Opr t1 = FrameMap::G1_opr;  // temp for 64-bit value
  LIR_Opr t2 = FrameMap::G3_opr;  // temp for 64-bit value
  __ cas_long(addr, cmp_value.result(), new_value.result(), t1, t2);

  // generate conditional move of boolean result
  LIR_Opr result = rlock_result(x);
  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result);
}
void LIRGenerator::invoke_load_arguments(Invoke* x, LIRItemList* args, CallingConvention* unused) {
  // we need to lock a register so that we can transport values on stack
  int offset_from_esp_in_words = x->size_of_arguments() - 1;
  if (x->has_receiver()) {
    --offset_from_esp_in_words; // the receiver has been pushed already
  }
  for (int i = 0; i < x->number_of_arguments(); i++) {
    LIRItem* param = args->at(i);
    param->handle_float_kind();
    if (!param->is_constant()) {
      param->load_item();
    }

    emit()->store_stack_parameter(param->result(), offset_from_esp_in_words);

    offset_from_esp_in_words -= param->result()->is_double_word() ? 2 : 1;
  }
}
示例#8
0
void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
  assert(x->number_of_arguments() == 4, "wrong type");
  LIRItem obj   (x->argument_at(0), this);  // object
  LIRItem offset(x->argument_at(1), this);  // offset of field
  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp

  assert(obj.type()->tag() == objectTag, "invalid type");

  // In 64bit the type can be long, sparc doesn't have this assert
  // assert(offset.type()->tag() == intTag, "invalid type");

  assert(cmp.type()->tag() == type->tag(), "invalid type");
  assert(val.type()->tag() == type->tag(), "invalid type");

  // get address of field
  obj.load_item();
  offset.load_nonconstant();

  if (type == objectType) {
    cmp.load_item_force(FrameMap::rax_oop_opr);
    val.load_item();
  } else if (type == intType) {
    cmp.load_item_force(FrameMap::rax_opr);
    val.load_item();
  } else if (type == longType) {
    cmp.load_item_force(FrameMap::long0_opr);
    val.load_item_force(FrameMap::long1_opr);
  } else {
    ShouldNotReachHere();
  }

  LIR_Opr addr = new_pointer_register();
  LIR_Address* a;
  if(offset.result()->is_constant()) {
    a = new LIR_Address(obj.result(),
                        NOT_LP64(offset.result()->as_constant_ptr()->as_jint()) LP64_ONLY((int)offset.result()->as_constant_ptr()->as_jlong()),
                        as_BasicType(type));
  } else {
    a = new LIR_Address(obj.result(),
                        offset.result(),
                        LIR_Address::times_1,
                        0,
                        as_BasicType(type));
  }
  __ leal(LIR_OprFact::address(a), addr);

  if (type == objectType) {  // Write-barrier needed for Object fields.
    // Do the pre-write barrier, if any.
    pre_barrier(addr, false, NULL);
  }

  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
  if (type == objectType)
    __ cas_obj(addr, cmp.result(), val.result(), ill, ill);
  else if (type == intType)
    __ cas_int(addr, cmp.result(), val.result(), ill, ill);
  else if (type == longType)
    __ cas_long(addr, cmp.result(), val.result(), ill, ill);
  else {
    ShouldNotReachHere();
  }

  // generate conditional move of boolean result
  LIR_Opr result = rlock_result(x);
  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
           result, as_BasicType(type));
  if (type == objectType) {   // Write-barrier needed for Object fields.
    // Seems to be precise
    post_barrier(addr, val.result());
  }
}
示例#9
0
void LIRGenerator::do_If(If* x) {
  assert(x->number_of_sux() == 2, "inconsistency");
  ValueTag tag = x->x()->type()->tag();
  bool is_safepoint = x->is_safepoint();

  If::Condition cond = x->cond();

  LIRItem xitem(x->x(), this);
  LIRItem yitem(x->y(), this);
  LIRItem* xin = &xitem;
  LIRItem* yin = &yitem;

  if (tag == longTag) {
    // for longs, only conditions "eql", "neq", "lss", "geq" are valid;
    // mirror for other conditions
    if (cond == If::gtr || cond == If::leq) {
      cond = Instruction::mirror(cond);
      xin = &yitem;
      yin = &xitem;
    }
    xin->set_destroys_register();
  }
  xin->load_item();
  if (tag == longTag && yin->is_constant() && yin->get_jlong_constant() == 0 && (cond == If::eql || cond == If::neq)) {
    // inline long zero
    yin->dont_load_item();
  } else if (tag == longTag || tag == floatTag || tag == doubleTag) {
    // longs cannot handle constants at right side
    yin->load_item();
  } else {
    yin->dont_load_item();
  }

  // add safepoint before generating condition code so it can be recomputed
  if (x->is_safepoint()) {
    // increment backedge counter if needed
    increment_backedge_counter(state_for(x, x->state_before()), x->profiled_bci());
    __ safepoint(LIR_OprFact::illegalOpr, state_for(x, x->state_before()));
  }
  set_no_result(x);

  LIR_Opr left = xin->result();
  LIR_Opr right = yin->result();
  __ cmp(lir_cond(cond), left, right);
  // Generate branch profiling. Profiling code doesn't kill flags.
  profile_branch(x, cond);
  move_to_phi(x->state());
  if (x->x()->type()->is_float_kind()) {
    __ branch(lir_cond(cond), right->type(), x->tsux(), x->usux());
  } else {
    __ branch(lir_cond(cond), right->type(), x->tsux());
  }
  assert(x->default_sux() == x->fsux(), "wrong destination above");
  __ jump(x->default_sux());
}
// _i2l, _i2f, _i2d, _l2i, _l2f, _l2d, _f2i, _f2l, _f2d, _d2i, _d2l, _d2f
// _i2b, _i2c, _i2s
void LIRGenerator::do_Convert(Convert* x) {

  switch (x->op()) {
    case Bytecodes::_f2l:
    case Bytecodes::_d2l:
    case Bytecodes::_d2i:
    case Bytecodes::_l2f:
    case Bytecodes::_l2d: {

      address entry;
      switch (x->op()) {
      case Bytecodes::_l2f:
        entry = CAST_FROM_FN_PTR(address, SharedRuntime::l2f);
        break;
      case Bytecodes::_l2d:
        entry = CAST_FROM_FN_PTR(address, SharedRuntime::l2d);
        break;
      case Bytecodes::_f2l:
        entry = CAST_FROM_FN_PTR(address, SharedRuntime::f2l);
        break;
      case Bytecodes::_d2l:
        entry = CAST_FROM_FN_PTR(address, SharedRuntime::d2l);
        break;
      case Bytecodes::_d2i:
        entry = CAST_FROM_FN_PTR(address, SharedRuntime::d2i);
        break;
      default:
        ShouldNotReachHere();
      }
      LIR_Opr result = call_runtime(x->value(), entry, x->type(), NULL);
      set_result(x, result);
      break;
    }

    case Bytecodes::_i2f:
    case Bytecodes::_i2d: {
      LIRItem value(x->value(), this);

      LIR_Opr reg = rlock_result(x);
      // To convert an int to double, we need to load the 32-bit int
      // from memory into a single precision floating point register
      // (even numbered). Then the sparc fitod instruction takes care
      // of the conversion. This is a bit ugly, but is the best way to
      // get the int value in a single precision floating point register
      value.load_item();
      LIR_Opr tmp = force_to_spill(value.result(), T_FLOAT);
      __ convert(x->op(), tmp, reg);
      break;
    }
    break;

    case Bytecodes::_i2l:
    case Bytecodes::_i2b:
    case Bytecodes::_i2c:
    case Bytecodes::_i2s:
    case Bytecodes::_l2i:
    case Bytecodes::_f2d:
    case Bytecodes::_d2f: { // inline code
      LIRItem value(x->value(), this);

      value.load_item();
      LIR_Opr reg = rlock_result(x);
      __ convert(x->op(), value.result(), reg, false);
    }
    break;

    case Bytecodes::_f2i: {
      LIRItem value (x->value(), this);
      value.set_destroys_register();
      value.load_item();
      LIR_Opr reg = rlock_result(x);
      set_vreg_flag(reg, must_start_in_memory);
      __ convert(x->op(), value.result(), reg, false);
    }
    break;

    default: ShouldNotReachHere();
  }
}
void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
  assert(x->number_of_arguments() == 4, "wrong type");
  LIRItem obj   (x->argument_at(0), this);  // object
  LIRItem offset(x->argument_at(1), this);  // offset of field
  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp

  // Use temps to avoid kills
  LIR_Opr t1 = FrameMap::G1_opr;
  LIR_Opr t2 = FrameMap::G3_opr;
  LIR_Opr addr = new_pointer_register();

  // get address of field
  obj.load_item();
  offset.load_item();
  cmp.load_item();
  val.load_item();

  __ add(obj.result(), offset.result(), addr);

  if (type == objectType) {  // Write-barrier needed for Object fields.
    pre_barrier(obj.result(), false, NULL);
  }

  if (type == objectType)
    __ cas_obj(addr, cmp.result(), val.result(), t1, t2);
  else if (type == intType)
    __ cas_int(addr, cmp.result(), val.result(), t1, t2);
  else if (type == longType)
    __ cas_long(addr, cmp.result(), val.result(), t1, t2);
  else {
    ShouldNotReachHere();
  }

  // generate conditional move of boolean result
  LIR_Opr result = rlock_result(x);
  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0), result);
  if (type == objectType) {  // Write-barrier needed for Object fields.
#ifdef PRECISE_CARDMARK
    post_barrier(addr, val.result());
#else
    post_barrier(obj.result(), val.result());
#endif // PRECISE_CARDMARK
  }
}
void LIRGenerator::do_If(If* x) {
  assert(x->number_of_sux() == 2, "inconsistency");
  ValueTag tag = x->x()->type()->tag();
  LIRItem xitem(x->x(), this);
  LIRItem yitem(x->y(), this);
  LIRItem* xin = &xitem;
  LIRItem* yin = &yitem;
  If::Condition cond = x->cond();

  if (tag == longTag) {
    // for longs, only conditions "eql", "neq", "lss", "geq" are valid;
    // mirror for other conditions
    if (cond == If::gtr || cond == If::leq) {
      // swap inputs
      cond = Instruction::mirror(cond);
      xin = &yitem;
      yin = &xitem;
    }
    xin->set_destroys_register();
  }

  LIR_Opr left = LIR_OprFact::illegalOpr;
  LIR_Opr right = LIR_OprFact::illegalOpr;

  xin->load_item();
  left = xin->result();

  if (is_simm13(yin->result())) {
    // inline int constants which are small enough to be immediate operands
    right = LIR_OprFact::value_type(yin->value()->type());
  } else if (tag == longTag && yin->is_constant() && yin->get_jlong_constant() == 0 &&
             (cond == If::eql || cond == If::neq)) {
    // inline long zero
    right = LIR_OprFact::value_type(yin->value()->type());
  } else if (tag == objectTag && yin->is_constant() && (yin->get_jobject_constant()->is_null_object())) {
    right = LIR_OprFact::value_type(yin->value()->type());
  } else {
    yin->load_item();
    right = yin->result();
  }
  set_no_result(x);

  // add safepoint before generating condition code so it can be recomputed
  if (x->is_safepoint()) {
    // increment backedge counter if needed
    increment_backedge_counter(state_for(x, x->state_before()));

    __ safepoint(new_register(T_INT), state_for(x, x->state_before()));
  }

  __ cmp(lir_cond(cond), left, right);
  profile_branch(x, cond);
  move_to_phi(x->state());
  if (x->x()->type()->is_float_kind()) {
    __ branch(lir_cond(cond), right->type(), x->tsux(), x->usux());
  } else {
    __ branch(lir_cond(cond), right->type(), x->tsux());
  }
  assert(x->default_sux() == x->fsux(), "wrong destination above");
  __ jump(x->default_sux());
}
void LIRGenerator::do_If(If* x) {
  assert(x->number_of_sux() == 2, "inconsistency");
  ValueTag tag = x->x()->type()->tag();
  bool is_safepoint = x->is_safepoint();

  If::Condition cond = x->cond();

  LIRItem xitem(x->x(), this);
  LIRItem yitem(x->y(), this);
  LIRItem* xin = &xitem;
  LIRItem* yin = &yitem;

  if (tag == longTag) {
    // for longs, only conditions "eql", "neq", "lss", "geq" are valid;
    // mirror for other conditions
    if (cond == If::gtr || cond == If::leq) {
      cond = Instruction::mirror(cond);
      xin = &yitem;
      yin = &xitem;
    }
    xin->set_destroys_register();
  } if (tag == floatTag || tag == doubleTag) {
    xin->set_destroys_register();
    yin->set_destroys_register();
  }
  xin->load_item();
  if (tag == longTag && yin->is_constant() && yin->get_jlong_constant() == 0 && (cond == If::eql || cond == If::neq)) {
    // inline long zero
    yin->dont_load_item();
  } else if (tag == longTag || tag == floatTag || tag == doubleTag) {
    // longs cannot handle constants at right side
    yin->load_item();
  } else {
    yin->dont_load_item();
  }

  // note that the condition test must happen before the
  // moves into Phi area happen, and that the control flow
  // jump must happen after the moves into the phi area

  set_no_result(x);

  if (x->is_safepoint()) {
    CodeEmitInfo* info_before = state_for(x, x->state_before());
    emit()->safepoint_nop(info_before);
  }

  emit()->if_op(1, cond, xin->result(), yin->result(), x->tsux(), x->fsux(), x->usux());
  move_to_phi(x->state());
  emit()->if_op(2, cond, xin->result(), yin->result(), x->tsux(), x->fsux(), x->usux());

  goto_default_successor(x);
}