Ejemplo n.º 1
0
void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
  assert(x->is_pinned(),"");
  bool needs_range_check = true;
  bool use_length = x->length() != NULL;
  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
                                         !get_jobject_constant(x->value())->is_null_object());

  LIRItem array(x->array(), this);
  LIRItem index(x->index(), this);
  LIRItem value(x->value(), this);
  LIRItem length(this);

  array.load_item();
  index.load_nonconstant();

  if (use_length) {
    needs_range_check = x->compute_needs_range_check();
    if (needs_range_check) {
      length.set_instruction(x->length());
      length.load_item();
    }
  }
  if (needs_store_check) {
    value.load_item();
  } else {
    value.load_for_store(x->elt_type());
  }

  set_no_result(x);

  // the CodeEmitInfo must be duplicated for each different
  // LIR-instruction because spilling can occur anywhere between two
  // instructions and so the debug information must be different
  CodeEmitInfo* range_check_info = state_for(x);
  CodeEmitInfo* null_check_info = NULL;
  if (x->needs_null_check()) {
    null_check_info = new CodeEmitInfo(range_check_info);
  }

  // emit array address setup early so it schedules better
  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);

  if (GenerateRangeChecks && needs_range_check) {
    if (use_length) {
      __ cmp(lir_cond_belowEqual, length.result(), index.result());
      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
    } else {
      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
      // range_check also does the null check
      null_check_info = NULL;
    }
  }

  if (GenerateArrayStoreCheck && needs_store_check) {
    LIR_Opr tmp1 = new_register(objectType);
    LIR_Opr tmp2 = new_register(objectType);
    LIR_Opr tmp3 = new_register(objectType);

    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
    __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info);
  }

  if (obj_store) {
    // Needs GC write barriers.
    pre_barrier(LIR_OprFact::address(array_addr), false, NULL);
    __ move(value.result(), array_addr, null_check_info);
    // Seems to be a precise
    post_barrier(LIR_OprFact::address(array_addr), value.result());
  } else {
    __ move(value.result(), array_addr, null_check_info);
  }
}
void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
  assert(x->is_root(),"");
  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
  LIRItem array(x->array(), this);
  LIRItem index(x->index(), this);
  LIRItem value(x->value(), this);
  if (obj_store) {
    array.set_destroys_register();
  }
  value.handle_float_kind();
  array.load_item();
  index.load_nonconstant();

  bool must_load = true;
  if (x->elt_type() == T_SHORT || x->elt_type() == T_CHAR) {
    // there is no immediate move of word values in asembler_i486.?pp
    must_load = true;
  } else {
    if (obj_store && value.is_constant() && !get_jobject_constant(x->value())->is_loaded()) {
      // do nothing; do not load (NULL object)
      must_load = false;
    } else if (value.is_constant() && !obj_store) {
      // array store check needs a register, otherwise do not load a constant
      must_load = false;
    }
  }
  if (must_load) {
    // for T_BYTE element type, we must have a byte register free
    if (x->elt_type() == T_BYTE || x->elt_type() == T_BOOLEAN) {
      value.load_byte_item();
    } else {
      value.load_item();
    }
  }
  set_no_result(x);

  CodeEmitInfo* range_check_info = state_for(x);
  CodeEmitInfo* null_check_info = NULL;
  bool needs_null_check = x->needs_null_check();
  if (needs_null_check) {
    null_check_info = range_check_info;
  }

  if (GenerateRangeChecks) {
    emit()->array_range_check(array.result(), index.result(), null_check_info, range_check_info);
    // range_check also does the null check
    needs_null_check = false;
  }

  if (obj_store) {
    if (value.is_constant() && !get_jobject_constant(x->value())->is_loaded()) {
      // skip store check
    } else if (GenerateArrayStoreCheck) {
      RInfo tmp1 = new_register(objectType)->rinfo();
      RInfo tmp2 = new_register(objectType)->rinfo();
      RInfo tmp3 = new_register(objectType)->rinfo();

      emit()->array_store_check(array.result(), value.result(), tmp1, tmp2, tmp3, range_check_info);
    }
  }
  emit()->indexed_store(x->elt_type(), array.result(), index.result(), value.result(), norinfo, null_check_info);
}