< prev index next >

src/hotspot/share/opto/parse3.cpp

Print this page

        

*** 25,54 **** --- 25,65 ---- #include "precompiled.hpp" #include "compiler/compileLog.hpp" #include "interpreter/linkResolver.hpp" #include "memory/universe.hpp" #include "oops/objArrayKlass.hpp" + #include "oops/valueArrayKlass.hpp" #include "opto/addnode.hpp" #include "opto/castnode.hpp" #include "opto/memnode.hpp" #include "opto/parse.hpp" #include "opto/rootnode.hpp" #include "opto/runtime.hpp" #include "opto/subnode.hpp" + #include "opto/valuetypenode.hpp" #include "runtime/deoptimization.hpp" #include "runtime/handles.inline.hpp" //============================================================================= // Helper methods for _get* and _put* bytecodes //============================================================================= + void Parse::do_field_access(bool is_get, bool is_field) { bool will_link; ciField* field = iter().get_field(will_link); assert(will_link, "getfield: typeflow responsibility"); ciInstanceKlass* field_holder = field->holder(); + if (is_field && field_holder->is_valuetype() && peek()->is_ValueType()) { + assert(is_get, "value type field store not supported"); + ValueTypeNode* vt = pop()->as_ValueType(); + Node* value = vt->field_value_by_offset(field->offset()); + push_node(field->layout_type(), value); + return; + } + if (is_field == field->is_static()) { // Interpreter will throw java_lang_IncompatibleClassChangeError // Check this before allowing <clinit> methods to access static fields uncommon_trap(Deoptimization::Reason_unhandled, Deoptimization::Action_none);
*** 85,112 **** assert(_gvn.type(obj)->higher_equal(tjp), "cast_up is no longer needed"); #endif if (is_get) { (void) pop(); // pop receiver before getting ! do_get_xxx(obj, field, is_field); } else { do_put_xxx(obj, field, is_field); (void) pop(); // pop receiver after putting } } else { const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror()); obj = _gvn.makecon(tip); if (is_get) { ! do_get_xxx(obj, field, is_field); } else { do_put_xxx(obj, field, is_field); } } } ! ! void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { BasicType bt = field->layout_type(); // Does this field have a constant value? If so, just push the value. if (field->is_constant() && // Keep consistent with types found by ciTypeFlow: for an --- 96,125 ---- assert(_gvn.type(obj)->higher_equal(tjp), "cast_up is no longer needed"); #endif if (is_get) { (void) pop(); // pop receiver before getting ! do_get_xxx(obj, field); } else { do_put_xxx(obj, field, is_field); + if (stopped()) { + return; + } (void) pop(); // pop receiver after putting } } else { const TypeInstPtr* tip = TypeInstPtr::make(field_holder->java_mirror()); obj = _gvn.makecon(tip); if (is_get) { ! do_get_xxx(obj, field); } else { do_put_xxx(obj, field, is_field); } } } ! void Parse::do_get_xxx(Node* obj, ciField* field) { BasicType bt = field->layout_type(); // Does this field have a constant value? If so, just push the value. if (field->is_constant() && // Keep consistent with types found by ciTypeFlow: for an
*** 123,132 **** --- 136,147 ---- } } ciType* field_klass = field->type(); bool is_vol = field->is_volatile(); + bool flattened = field->is_flattened(); + bool flattenable = field->is_flattenable(); // Compute address and memory type. int offset = field->offset_in_bytes(); const TypePtr* adr_type = C->alias_type(field)->adr_type(); Node *adr = basic_plus_adr(obj, obj, offset);
*** 134,149 **** // Build the resultant type of the load const Type *type; bool must_assert_null = false; ! DecoratorSet decorators = IN_HEAP; ! decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED; ! ! bool is_obj = bt == T_OBJECT || bt == T_ARRAY; ! ! if (is_obj) { if (!field->type()->is_loaded()) { type = TypeInstPtr::BOTTOM; must_assert_null = true; } else if (field->is_static_constant()) { // This can happen if the constant oop is non-perm. --- 149,159 ---- // Build the resultant type of the load const Type *type; bool must_assert_null = false; ! if (bt == T_OBJECT || bt == T_ARRAY || bt == T_VALUETYPE) { if (!field->type()->is_loaded()) { type = TypeInstPtr::BOTTOM; must_assert_null = true; } else if (field->is_static_constant()) { // This can happen if the constant oop is non-perm.
*** 156,171 **** type = TypeOopPtr::make_from_constant(con)->isa_oopptr(); } assert(type != NULL, "field singleton type must be consistent"); } else { type = TypeOopPtr::make_from_klass(field_klass->as_klass()); } } else { type = Type::get_const_basic_type(bt); } ! Node* ld = access_load_at(obj, adr, adr_type, type, bt, decorators); // Adjust Java stack if (type2size[bt] == 1) push(ld); else --- 166,206 ---- type = TypeOopPtr::make_from_constant(con)->isa_oopptr(); } assert(type != NULL, "field singleton type must be consistent"); } else { type = TypeOopPtr::make_from_klass(field_klass->as_klass()); + if (bt == T_VALUETYPE && field->is_static() && flattenable) { + // Check if static value type field is already initialized + assert(!flattened, "static fields should not be flattened"); + ciInstance* mirror = field->holder()->java_mirror(); + ciObject* val = mirror->field_value(field).as_object(); + if (!val->is_null_object()) { + type = type->join_speculative(TypePtr::NOTNULL); + } + } } } else { type = Type::get_const_basic_type(bt); } ! Node* ld = NULL; ! if (flattened) { ! // Load flattened value type ! ld = ValueTypeNode::make_from_flattened(this, field_klass->as_value_klass(), obj, obj, field->holder(), offset); ! } else { ! DecoratorSet decorators = IN_HEAP; ! decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED; ! ld = access_load_at(obj, adr, adr_type, type, bt, decorators); ! if (flattenable) { ! // Load a non-flattened but flattenable value type from memory ! if (field_klass->as_value_klass()->is_scalarizable()) { ! ld = ValueTypeNode::make_from_oop(this, ld, field_klass->as_value_klass()); ! } else { ! ld = null2default(ld, field_klass->as_value_klass()); ! } ! } ! } // Adjust Java stack if (type2size[bt] == 1) push(ld); else
*** 208,231 **** Node* val = type2size[bt] == 1 ? pop() : pop_pair(); DecoratorSet decorators = IN_HEAP; decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED; - bool is_obj = bt == T_OBJECT || bt == T_ARRAY; - // Store the value. const Type* field_type; if (!field->type()->is_loaded()) { field_type = TypeInstPtr::BOTTOM; } else { ! if (is_obj) { field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); } else { field_type = Type::BOTTOM; } } ! access_store_at(obj, adr, adr_type, val, field_type, bt, decorators); if (is_field) { // Remember we wrote a volatile field. // For not multiple copy atomic cpu (ppc64) a barrier should be issued // in constructors which have such stores. See do_exits() in parse1.cpp. --- 243,281 ---- Node* val = type2size[bt] == 1 ? pop() : pop_pair(); DecoratorSet decorators = IN_HEAP; decorators |= is_vol ? MO_SEQ_CST : MO_UNORDERED; // Store the value. const Type* field_type; if (!field->type()->is_loaded()) { field_type = TypeInstPtr::BOTTOM; } else { ! if (bt == T_OBJECT || bt == T_ARRAY || bt == T_VALUETYPE) { field_type = TypeOopPtr::make_from_klass(field->type()->as_klass()); } else { field_type = Type::BOTTOM; } } ! ! if (field->is_flattenable() && !val->is_ValueType()) { ! inc_sp(1); ! val = null_check(val); ! dec_sp(1); ! if (stopped()) return; ! } ! ! if (field->is_flattened()) { ! // Store flattened value type to a non-static field ! if (!val->is_ValueType()) { ! assert(!gvn().type(val)->maybe_null(), "should never be null"); ! val = ValueTypeNode::make_from_oop(this, val, field->type()->as_value_klass()); ! } ! val->as_ValueType()->store_flattened(this, obj, obj, field->holder(), offset); ! } else { ! access_store_at(obj, adr, adr_type, val, field_type, bt, decorators); ! } if (is_field) { // Remember we wrote a volatile field. // For not multiple copy atomic cpu (ppc64) a barrier should be issued // in constructors which have such stores. See do_exits() in parse1.cpp.
*** 253,279 **** } } } //============================================================================= ! void Parse::do_anewarray() { bool will_link; ciKlass* klass = iter().get_klass(will_link); // Uncommon Trap when class that array contains is not loaded // we need the loaded class for the rest of graph; do not // initialize the container class (see Java spec)!!! ! assert(will_link, "anewarray: typeflow responsibility"); - ciObjArrayKlass* array_klass = ciObjArrayKlass::make(klass); // Check that array_klass object is loaded if (!array_klass->is_loaded()) { // Generate uncommon_trap for unloaded array_class uncommon_trap(Deoptimization::Reason_unloaded, Deoptimization::Action_reinterpret, array_klass); return; } kill_dead_locals(); const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass); --- 303,339 ---- } } } //============================================================================= ! ! void Parse::do_newarray() { bool will_link; ciKlass* klass = iter().get_klass(will_link); + bool never_null = iter().is_klass_never_null(); // Uncommon Trap when class that array contains is not loaded // we need the loaded class for the rest of graph; do not // initialize the container class (see Java spec)!!! ! assert(will_link, "newarray: typeflow responsibility"); ! ! ciArrayKlass* array_klass = ciArrayKlass::make(klass, never_null); // Check that array_klass object is loaded if (!array_klass->is_loaded()) { // Generate uncommon_trap for unloaded array_class uncommon_trap(Deoptimization::Reason_unloaded, Deoptimization::Action_reinterpret, array_klass); return; + } else if (array_klass->element_klass() != NULL && + array_klass->element_klass()->is_valuetype() && + !array_klass->element_klass()->as_value_klass()->is_initialized()) { + uncommon_trap(Deoptimization::Reason_uninitialized, + Deoptimization::Action_reinterpret, + NULL); + return; } kill_dead_locals(); const TypeKlassPtr* array_klass_type = TypeKlassPtr::make(array_klass);
< prev index next >