< prev index next >

src/hotspot/share/c1/c1_LIRGenerator.cpp

Print this page

*** 32,41 **** --- 32,43 ---- #include "c1/c1_ValueStack.hpp" #include "ci/ciArrayKlass.hpp" #include "ci/ciInstance.hpp" #include "ci/ciObjArray.hpp" #include "ci/ciUtilities.hpp" + #include "ci/ciValueArrayKlass.hpp" + #include "ci/ciValueKlass.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/c1/barrierSetC1.hpp" #include "runtime/arguments.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp"
*** 1546,1561 **** access_store_at(decorators, field_type, object, LIR_OprFact::intConst(x->offset()), value.result(), info != NULL ? new CodeEmitInfo(info) : NULL, info); } void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { assert(x->is_pinned(),""); bool needs_range_check = x->compute_needs_range_check(); 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() || x->should_profile()); LIRItem array(x->array(), this); LIRItem index(x->index(), this); --- 1548,1636 ---- access_store_at(decorators, field_type, object, LIR_OprFact::intConst(x->offset()), value.result(), info != NULL ? new CodeEmitInfo(info) : NULL, info); } + // FIXME -- I can't find any other way to pass an address to access_load_at(). + class TempResolvedAddress: public Instruction { + public: + TempResolvedAddress(ValueType* type, LIR_Opr addr) : Instruction(type) { + set_operand(addr); + } + virtual void input_values_do(ValueVisitor*) {} + virtual void visit(InstructionVisitor* v) {} + virtual const char* name() const { return "TempResolvedAddress"; } + }; + + void LIRGenerator::access_flattened_array(bool is_load, LIRItem& array, LIRItem& index, LIRItem& obj_item) { + // Find the starting address of the source (inside the array) + ciType* array_type = array.value()->declared_type(); + ciValueArrayKlass* value_array_klass = array_type->as_value_array_klass(); + ciValueKlass* elem_klass = value_array_klass->element_klass()->as_value_klass(); + int array_header_size = value_array_klass->array_header_in_bytes(); + + #ifndef _LP64 + LIR_Opr index_op = index.result(); + #else + LIR_Opr index_op = new_register(T_LONG); + __ convert(Bytecodes::_i2l, index.result(), index_op); + #endif + // Need to shift manually, as LIR_Address can scale only up to 3. + __ shift_left(index_op, value_array_klass->log2_element_size(), index_op); + + LIR_Opr elm_op = new_pointer_register(); + LIR_Address* elm_address = new LIR_Address(array.result(), index_op, array_header_size, T_ADDRESS); + __ leal(LIR_OprFact::address(elm_address), elm_op); + + for (int i = 0; i < elem_klass->nof_nonstatic_fields(); i++) { + ciField* inner_field = elem_klass->nonstatic_field_at(i); + int obj_offset = inner_field->offset(); + int elm_offset = obj_offset - elem_klass->first_field_offset(); // object header is not stored in array. + + BasicType field_type = inner_field->type()->basic_type(); + switch (field_type) { + case T_BYTE: + case T_BOOLEAN: + case T_SHORT: + case T_CHAR: + field_type = T_INT; + break; + default: + break; + } + + LIR_Opr temp = new_register(field_type); + TempResolvedAddress* elm_resolved_addr = new TempResolvedAddress(as_ValueType(field_type), elm_op); + LIRItem elm_item(elm_resolved_addr, this); + + DecoratorSet decorators = IN_HEAP; + if (is_load) { + access_load_at(decorators, field_type, + elm_item, LIR_OprFact::intConst(elm_offset), temp, + NULL, NULL); + access_store_at(decorators, field_type, + obj_item, LIR_OprFact::intConst(obj_offset), temp, + NULL, NULL); + } else { + access_load_at(decorators, field_type, + obj_item, LIR_OprFact::intConst(obj_offset), temp, + NULL, NULL); + access_store_at(decorators, field_type, + elm_item, LIR_OprFact::intConst(elm_offset), temp, + NULL, NULL); + } + } + } + void LIRGenerator::do_StoreIndexed(StoreIndexed* x) { assert(x->is_pinned(),""); + bool is_flattened = x->array()->is_flattened_array(); bool needs_range_check = x->compute_needs_range_check(); 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 && !is_flattened && ! (x->value()->as_Constant() == NULL || !get_jobject_constant(x->value())->is_null_object() || x->should_profile()); LIRItem array(x->array(), this); LIRItem index(x->index(), this);
*** 1568,1578 **** if (use_length && needs_range_check) { length.set_instruction(x->length()); length.load_item(); } ! if (needs_store_check || x->check_boolean()) { value.load_item(); } else { value.load_for_store(x->elt_type()); } --- 1643,1654 ---- if (use_length && needs_range_check) { length.set_instruction(x->length()); length.load_item(); } ! ! if (needs_store_check || x->check_boolean() || is_flattened) { value.load_item(); } else { value.load_for_store(x->elt_type()); }
*** 1601,1617 **** --- 1677,1698 ---- if (GenerateArrayStoreCheck && needs_store_check) { CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info); array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci()); } + if (is_flattened) { + index.load_item(); + access_flattened_array(false, array, index, value); + } else { DecoratorSet decorators = IN_HEAP | IS_ARRAY; if (x->check_boolean()) { decorators |= C1_MASK_BOOLEAN; } access_store_at(decorators, x->elt_type(), array, index.result(), value.result(), NULL, null_check_info); + } } void LIRGenerator::access_load_at(DecoratorSet decorators, BasicType type, LIRItem& base, LIR_Opr offset, LIR_Opr result, CodeEmitInfo* patch_info, CodeEmitInfo* load_emit_info) {
*** 1868,1883 **** // The range check performs the null check, so clear it out for the load null_check_info = NULL; } } ! DecoratorSet decorators = IN_HEAP | IS_ARRAY; LIR_Opr result = rlock_result(x, x->elt_type()); access_load_at(decorators, x->elt_type(), array, index.result(), result, NULL, null_check_info); } void LIRGenerator::do_NullCheck(NullCheck* x) { if (x->can_trap()) { --- 1949,1972 ---- // The range check performs the null check, so clear it out for the load null_check_info = NULL; } } ! if (x->array()->is_flattened_array()) { ! // Find the destination address (of the NewValueTypeInstance) ! LIR_Opr obj = x->vt()->operand(); ! LIRItem obj_item(x->vt(), this); + access_flattened_array(true, array, index, obj_item); + set_no_result(x); + } else { + DecoratorSet decorators = IN_HEAP | IS_ARRAY; LIR_Opr result = rlock_result(x, x->elt_type()); access_load_at(decorators, x->elt_type(), array, index.result(), result, NULL, null_check_info); + } } void LIRGenerator::do_NullCheck(NullCheck* x) { if (x->can_trap()) {
*** 2733,2742 **** --- 2822,2832 ---- if (loc->is_register()) { param->load_item_force(loc); } else { LIR_Address* addr = loc->as_address_ptr(); param->load_for_store(addr->type()); + assert(addr->type() != T_VALUETYPE, "not supported yet"); if (addr->type() == T_OBJECT) { __ move_wide(param->result(), addr); } else if (addr->type() == T_LONG || addr->type() == T_DOUBLE) { __ unaligned_move(param->result(), addr);
< prev index next >