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); }