< prev index next >
src/hotspot/share/opto/parse3.cpp
Print this page
@@ -25,17 +25,19 @@
#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,10 +80,18 @@
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,10 +135,13 @@
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,11 +151,10 @@
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() &&
@@ -160,10 +172,12 @@
}
}
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,16 +185,11 @@
// 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 (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,16 +202,41 @@
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 = access_load_at(obj, adr, adr_type, type, bt, decorators);
+ 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,24 +279,39 @@
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) {
+ 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,27 +339,35 @@
}
}
}
//=============================================================================
-void Parse::do_anewarray() {
+
+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, "anewarray: typeflow responsibility");
+ assert(will_link, "newarray: typeflow responsibility");
- ciObjArrayKlass* array_klass = ciObjArrayKlass::make(klass);
+ 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 >