< prev index next >
src/hotspot/share/c1/c1_GraphBuilder.cpp
Print this page
*** 1644,1653 ****
--- 1644,1666 ----
default:
return new Constant(value);
}
}
+ void GraphBuilder::copy_value_content(ciValueKlass* vk, Value src, int src_off, Value dest, int dest_off,
+ ValueStack* state_before, bool needs_patching) {
+ for (int i = 0; i < vk->nof_nonstatic_fields(); i++) {
+ ciField* inner_field = vk->nonstatic_field_at(i);
+ assert(!inner_field->is_flattened(), "the iteration over nested fields is handled by the loop itself");
+ int off = inner_field->offset() - vk->first_field_offset();
+ LoadField* load = new LoadField(src, src_off + off, inner_field, false, state_before, needs_patching);
+ Value replacement = append(load);
+ StoreField* store = new StoreField(dest, dest_off + off, inner_field, replacement, false, state_before, needs_patching);
+ append(store);
+ }
+ }
+
void GraphBuilder::access_field(Bytecodes::Code code) {
bool will_link;
ciField* field = stream()->get_field(will_link);
ciInstanceKlass* holder = field->holder();
BasicType field_type = field->type()->basic_type();
*** 1745,1782 ****
push(type, append(constant));
} else {
if (state_before == NULL) {
state_before = copy_state_for_exception();
}
! // Pb with test below, is_flattened() can return true for fields that are not value types
! // (initialization issue of ciField?)
! if (!(field->type()->is_valuetype() && field->is_flattened())) {
LoadField* load = new LoadField(obj, offset, field, false, state_before, needs_patching);
Value replacement = !needs_patching ? _memory->load(load) : load;
if (replacement != load) {
assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked");
push(type, replacement);
} else {
push(type, append(load));
}
} else { // flattened field, not optimized solution: re-instantiate the flattened value
ciValueKlass* value_klass = field->type()->as_value_klass();
int flattening_offset = field->offset() - value_klass->first_field_offset();
assert(field->type()->is_valuetype(), "Sanity check");
scope()->set_wrote_final();
scope()->set_wrote_fields();
NewValueTypeInstance* new_instance = new NewValueTypeInstance(value_klass, state_before, false);
_memory->new_instance(new_instance);
apush(append_split(new_instance));
! for (int i = 0; i < holder->nof_nonstatic_fields(); i++) {
! ciField* inner_field = holder->nonstatic_field_at(i);
! int off = inner_field->offset();
! LoadField* load = new LoadField(obj, off + flattening_offset, inner_field, false, state_before, needs_patching);
! Value replacement = append(load);
! StoreField* store = new StoreField(new_instance, off, inner_field, replacement, false, state_before, needs_patching);
! append(store);
! }
}
}
break;
}
case Bytecodes::_putfield: {
--- 1758,1789 ----
push(type, append(constant));
} else {
if (state_before == NULL) {
state_before = copy_state_for_exception();
}
!
! if (!field->is_flattened()) {
LoadField* load = new LoadField(obj, offset, field, false, state_before, needs_patching);
Value replacement = !needs_patching ? _memory->load(load) : load;
if (replacement != load) {
assert(replacement->is_linked() || !replacement->can_be_linked(), "should already by linked");
push(type, replacement);
} else {
push(type, append(load));
}
} else { // flattened field, not optimized solution: re-instantiate the flattened value
+ assert(field->type()->is_valuetype(), "Sanity check");
ciValueKlass* value_klass = field->type()->as_value_klass();
int flattening_offset = field->offset() - value_klass->first_field_offset();
assert(field->type()->is_valuetype(), "Sanity check");
scope()->set_wrote_final();
scope()->set_wrote_fields();
NewValueTypeInstance* new_instance = new NewValueTypeInstance(value_klass, state_before, false);
_memory->new_instance(new_instance);
apush(append_split(new_instance));
! copy_value_content(value_klass, obj, field->offset() , new_instance, value_klass->first_field_offset(),
! state_before, needs_patching);
}
}
break;
}
case Bytecodes::_putfield: {
*** 1787,1815 ****
}
if (field->type()->basic_type() == T_BOOLEAN) {
Value mask = append(new Constant(new IntConstant(1)));
val = append(new LogicOp(Bytecodes::_iand, val, mask));
}
! // Pb with test below, is_flattened() can return true for fields that are not value types
! // (initialization issue of ciField?) <---- FIXME
! if (!(field->type()->is_valuetype() && field->is_flattened())) {
StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching);
if (!needs_patching) store = _memory->store(store);
if (store != NULL) {
append(store);
}
} else {
ciValueKlass* value_klass = field->type()->as_value_klass();
int flattening_offset = field->offset() - value_klass->first_field_offset();
! for (int i = 0; i < holder->nof_nonstatic_fields(); i++) {
! ciField* inner_field = holder->nonstatic_field_at(i);
! int off = inner_field->offset();
! LoadField* load = new LoadField(val, off, inner_field, false, state_before, needs_patching);
! Value replacement = append(load);
! StoreField* store = new StoreField(obj, off + flattening_offset, inner_field, replacement, false, state_before, needs_patching);
! append(store);
! }
}
break;
}
default:
ShouldNotReachHere();
--- 1794,1816 ----
}
if (field->type()->basic_type() == T_BOOLEAN) {
Value mask = append(new Constant(new IntConstant(1)));
val = append(new LogicOp(Bytecodes::_iand, val, mask));
}
!
! if (!field->is_flattened()) {
StoreField* store = new StoreField(obj, offset, field, val, false, state_before, needs_patching);
if (!needs_patching) store = _memory->store(store);
if (store != NULL) {
append(store);
}
} else {
+ assert(field->type()->is_valuetype(), "Sanity check");
ciValueKlass* value_klass = field->type()->as_value_klass();
int flattening_offset = field->offset() - value_klass->first_field_offset();
! copy_value_content(value_klass, val, value_klass->first_field_offset(), obj, field->offset(),
! state_before, needs_patching);
}
break;
}
default:
ShouldNotReachHere();
*** 1849,1874 ****
for (int i = 0; i < holder->nof_nonstatic_fields(); i++) {
ciField* field = holder->nonstatic_field_at(i);
int off = field->offset();
if (field->offset() != offset) {
// Only load those fields who are not modified
LoadField* load = new LoadField(obj, off, field, false, state_before, needs_patching);
Value replacement = append(load);
-
StoreField* store = new StoreField(new_instance, off, field, replacement, false, state_before, needs_patching);
append(store);
}
}
// Field to modify
if (field_modify->type()->basic_type() == T_BOOLEAN) {
Value mask = append(new Constant(new IntConstant(1)));
val = append(new LogicOp(Bytecodes::_iand, val, mask));
}
StoreField* store = new StoreField(new_instance, offset, field_modify, val, false, state_before, needs_patching);
append(store);
}
Dependencies* GraphBuilder::dependency_recorder() const {
assert(DeoptC1, "need debug information");
return compilation()->dependency_recorder();
--- 1850,1887 ----
for (int i = 0; i < holder->nof_nonstatic_fields(); i++) {
ciField* field = holder->nonstatic_field_at(i);
int off = field->offset();
if (field->offset() != offset) {
+ if (field->is_flattened()) {
+ assert(field->type()->is_valuetype(), "Sanity check");
+ assert(field->type()->is_valuetype(), "Only value types can be flattened");
+ ciValueKlass* vk = field->type()->as_value_klass();
+ copy_value_content(vk, obj, off, new_instance, vk->first_field_offset(), state_before, needs_patching);
+ } else {
// Only load those fields who are not modified
LoadField* load = new LoadField(obj, off, field, false, state_before, needs_patching);
Value replacement = append(load);
StoreField* store = new StoreField(new_instance, off, field, replacement, false, state_before, needs_patching);
append(store);
}
}
+ }
// Field to modify
if (field_modify->type()->basic_type() == T_BOOLEAN) {
Value mask = append(new Constant(new IntConstant(1)));
val = append(new LogicOp(Bytecodes::_iand, val, mask));
}
+ if (field_modify->is_flattened()) {
+ assert(field_modify->type()->is_valuetype(), "Only value types can be flattened");
+ ciValueKlass* vk = field_modify->type()->as_value_klass();
+ copy_value_content(vk, val, vk->first_field_offset(), new_instance, field_modify->offset(), state_before, needs_patching);
+ } else {
StoreField* store = new StoreField(new_instance, offset, field_modify, val, false, state_before, needs_patching);
append(store);
+ }
}
Dependencies* GraphBuilder::dependency_recorder() const {
assert(DeoptC1, "need debug information");
return compilation()->dependency_recorder();
< prev index next >