< prev index next >
src/hotspot/share/opto/parse3.cpp
Print this page
*** 25,41 ****
--- 25,43 ----
#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
*** 78,87 ****
--- 80,97 ----
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);
*** 125,134 ****
--- 135,147 ----
if (is_get) {
(void) pop(); // pop receiver before getting
do_get_xxx(obj, field, is_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);
*** 138,148 ****
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() &&
--- 151,160 ----
*** 160,169 ****
--- 172,183 ----
}
}
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);
*** 171,186 ****
// 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.
--- 185,195 ----
// 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.
*** 193,208 ****
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
--- 202,242 ----
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()) {
+ // 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
*** 245,268 ****
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.
--- 279,317 ----
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.
*** 290,316 ****
}
}
}
//=============================================================================
! 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);
--- 339,373 ----
}
}
}
//=============================================================================
!
! void Parse::do_newarray() {
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, "newarray: typeflow responsibility");
! ciArrayKlass* array_klass = ciArrayKlass::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;
+ } 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 >