--- old/src/hotspot/share/c1/c1_Instruction.cpp 2018-12-03 15:48:55.656359503 -0800 +++ new/src/hotspot/share/c1/c1_Instruction.cpp 2018-12-03 15:48:55.512354004 -0800 @@ -827,7 +827,7 @@ TRACE_PHI(tty->print_cr("loop header block, initializing phi functions")); for_each_stack_value(new_state, index, new_value) { - new_state->setup_phi_for_stack(this, index); + new_state->setup_phi_for_stack(this, index, NULL, new_value); TRACE_PHI(tty->print_cr("creating phi-function %c%d for stack %d", new_state->stack_at(index)->type()->tchar(), new_state->stack_at(index)->id(), index)); } @@ -836,7 +836,7 @@ for_each_local_value(new_state, index, new_value) { bool requires_phi = requires_phi_function.at(index) || (new_value->type()->is_double_word() && requires_phi_function.at(index + 1)); if (requires_phi || !SelectivePhiFunctions) { - new_state->setup_phi_for_local(this, index); + new_state->setup_phi_for_local(this, index, NULL, new_value); TRACE_PHI(tty->print_cr("creating phi-function %c%d for local %d", new_state->local_at(index)->type()->tchar(), new_state->local_at(index)->id(), index)); } } @@ -888,7 +888,7 @@ Phi* existing_phi = existing_value->as_Phi(); if (new_value != existing_value && (existing_phi == NULL || existing_phi->block() != this)) { - existing_state->setup_phi_for_stack(this, index); + existing_state->setup_phi_for_stack(this, index, existing_value, new_value); TRACE_PHI(tty->print_cr("creating phi-function %c%d for stack %d", existing_state->stack_at(index)->type()->tchar(), existing_state->stack_at(index)->id(), index)); } } @@ -902,7 +902,7 @@ existing_state->invalidate_local(index); TRACE_PHI(tty->print_cr("invalidating local %d because of type mismatch", index)); } else if (new_value != existing_value && (existing_phi == NULL || existing_phi->block() != this)) { - existing_state->setup_phi_for_local(this, index); + existing_state->setup_phi_for_local(this, index, existing_value, new_value); TRACE_PHI(tty->print_cr("creating phi-function %c%d for local %d", existing_state->local_at(index)->type()->tchar(), existing_state->local_at(index)->id(), index)); } } --- old/src/hotspot/share/c1/c1_Instruction.hpp 2018-12-03 15:48:56.184379669 -0800 +++ new/src/hotspot/share/c1/c1_Instruction.hpp 2018-12-03 15:48:56.040374169 -0800 @@ -649,12 +649,14 @@ private: int _pf_flags; // the flags of the phi function int _index; // to value on operand stack (index < 0) or to local + ciType* _exact_type; // preserve type information for flattened arrays. public: // creation - Phi(ValueType* type, BlockBegin* b, int index) + Phi(ValueType* type, BlockBegin* b, int index, ciType* exact_type) : Instruction(type->base()) , _pf_flags(0) , _index(index) + , _exact_type(exact_type) { _block = b; NOT_PRODUCT(set_printable_bci(Value(b)->printable_bci())); @@ -663,6 +665,14 @@ } } + virtual ciType* exact_type() const { + return _exact_type; + } + + virtual ciType* declared_type() const { + return _exact_type; + } + // flags enum Flag { no_flag = 0, --- old/src/hotspot/share/c1/c1_ValueStack.cpp 2018-12-03 15:48:56.720400141 -0800 +++ new/src/hotspot/share/c1/c1_ValueStack.cpp 2018-12-03 15:48:56.576394641 -0800 @@ -172,22 +172,47 @@ return total_locks_size(); } +// When we merge two object slots, we usually lose the type information. +// However, for aaload/aastore to work with flattened arrays, we need to preserve +// the type info (because the aaload/aastore bytecode themselves don't carry the +// type info). +ciType* ValueStack::merge_if_flattened_array_types(Value existing_value, Value new_value) { + assert(new_value != NULL, "must be"); + assert(existing_value != new_value, "must be"); + + if (existing_value == NULL) { + if (new_value->is_flattened_array()) { + return new_value->exact_type(); + } else { + return NULL; + } + } + + if (existing_value->is_flattened_array() && new_value->is_flattened_array()) { + // The merged block should be able to access this value as a flattened array. + assert(existing_value->exact_type() == new_value->exact_type(), "must be guaranteed by verifier"); + return existing_value->exact_type(); + } else { + // The merged block cannot access value as a flattened array without first doing a type cast. + return NULL; + } +} -void ValueStack::setup_phi_for_stack(BlockBegin* b, int index) { +void ValueStack::setup_phi_for_stack(BlockBegin* b, int index, Value existing_value, Value new_value) { assert(stack_at(index)->as_Phi() == NULL || stack_at(index)->as_Phi()->block() != b, "phi function already created"); ValueType* t = stack_at(index)->type(); - Value phi = new Phi(t, b, -index - 1); + Value phi = new Phi(t, b, -index - 1, merge_if_flattened_array_types(existing_value, new_value)); _stack.at_put(index, phi); assert(!t->is_double_word() || _stack.at(index + 1) == NULL, "hi-word of doubleword value must be NULL"); } -void ValueStack::setup_phi_for_local(BlockBegin* b, int index) { +void ValueStack::setup_phi_for_local(BlockBegin* b, int index, Value existing_value, Value new_value) { assert(local_at(index)->as_Phi() == NULL || local_at(index)->as_Phi()->block() != b, "phi function already created"); ValueType* t = local_at(index)->type(); - Value phi = new Phi(t, b, index); + Value phi = new Phi(t, b, index, merge_if_flattened_array_types(existing_value, new_value)); store_local(index, phi); } --- old/src/hotspot/share/c1/c1_ValueStack.hpp 2018-12-03 15:48:57.244420154 -0800 +++ new/src/hotspot/share/c1/c1_ValueStack.hpp 2018-12-03 15:48:57.092414348 -0800 @@ -204,8 +204,10 @@ Value lock_at(int i) const { return _locks.at(i); } // SSA form IR support - void setup_phi_for_stack(BlockBegin* b, int index); - void setup_phi_for_local(BlockBegin* b, int index); + void setup_phi_for_stack(BlockBegin* b, int index, Value existing_value, Value new_value); + void setup_phi_for_local(BlockBegin* b, int index, Value existing_value, Value new_value); + + ciType* merge_if_flattened_array_types(Value existing_value, Value new_value); // debugging void print() PRODUCT_RETURN;