< prev index next > src/hotspot/share/c1/c1_Instruction.cpp
Print this page
#include "precompiled.hpp"
#include "c1/c1_IR.hpp"
#include "c1/c1_Instruction.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_ValueStack.hpp"
+ #include "ci/ciFlatArrayKlass.hpp"
+ #include "ci/ciInlineKlass.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciTypeArrayKlass.hpp"
#include "utilities/bitMap.inline.hpp"
exception_state()->values_do(f);
}
}
ciType* Instruction::exact_type() const {
- ciType* t = declared_type();
+ ciType* t = declared_type();
if (t != NULL && t->is_klass()) {
return t->as_klass()->exact_klass();
}
return NULL;
}
+ ciKlass* Instruction::as_loaded_klass_or_null() const {
+ ciType* type = declared_type();
+ if (type != NULL && type->is_klass()) {
+ ciKlass* klass = type->as_klass();
+ if (klass->is_loaded()) {
+ return klass;
+ }
+ }
+ return NULL;
+ }
+
+ bool Instruction::is_loaded_flattened_array() const {
+ if (UseFlatArray) {
+ ciType* type = declared_type();
+ return type != NULL && type->is_flat_array_klass();
+ }
+ return false;
+ }
+
+ bool Instruction::maybe_flattened_array() {
+ if (UseFlatArray) {
+ ciType* type = declared_type();
+ if (type != NULL) {
+ if (type->is_obj_array_klass() && !type->as_obj_array_klass()->is_elem_null_free()) {
+ // The runtime type of [LMyValue might be [QMyValue due to [QMyValue <: [LMyValue.
+ ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+ if (element_klass->can_be_inline_klass() && (!element_klass->is_inlinetype() || element_klass->as_inline_klass()->flatten_array())) {
+ return true;
+ }
+ } else if (type->is_flat_array_klass()) {
+ return true;
+ } else if (type->is_klass() && type->as_klass()->is_java_lang_Object()) {
+ // This can happen as a parameter to System.arraycopy()
+ return true;
+ }
+ } else {
+ // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a
+ // flattened array, so we should do a runtime check.
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool Instruction::maybe_null_free_array() {
+ ciType* type = declared_type();
+ if (type != NULL) {
+ if (type->is_obj_array_klass()) {
+ // Due to array covariance, the runtime type might be a null-free array.
+ if (type->as_obj_array_klass()->can_be_inline_array_klass()) {
+ return true;
+ }
+ }
+ } else {
+ // Type info gets lost during Phi merging (Phi, IfOp, etc), but we might be storing into a
+ // null-free array, so we should do a runtime check.
+ return true;
+ }
+ return false;
+ }
#ifndef PRODUCT
void Instruction::check_state(ValueStack* state) {
if (state != NULL) {
state->verify();
return NULL;
}
ciType* LoadIndexed::exact_type() const {
ciType* array_type = array()->exact_type();
- if (array_type != NULL) {
+ if (delayed() == NULL && array_type != NULL) {
assert(array_type->is_array_klass(), "what else?");
ciArrayKlass* ak = (ciArrayKlass*)array_type;
if (ak->element_type()->is_instance_klass()) {
ciInstanceKlass* ik = (ciInstanceKlass*)ak->element_type();
}
}
return Instruction::exact_type();
}
-
ciType* LoadIndexed::declared_type() const {
+ if (delayed() != NULL) {
+ return delayed()->field()->type();
+ }
ciType* array_type = array()->declared_type();
if (array_type == NULL || !array_type->is_loaded()) {
return NULL;
}
assert(array_type->is_array_klass(), "what else?");
ciArrayKlass* ak = (ciArrayKlass*)array_type;
return ak->element_type();
}
+ bool StoreIndexed::is_exact_flattened_array_store() const {
+ if (array()->is_loaded_flattened_array() && value()->as_Constant() == NULL && value()->declared_type() != NULL) {
+ ciKlass* element_klass = array()->declared_type()->as_flat_array_klass()->element_klass();
+ ciKlass* actual_klass = value()->declared_type()->as_klass();
+
+ // The following check can fail with inlining:
+ // void test45_inline(Object[] oa, Object o, int index) { oa[index] = o; }
+ // void test45(MyValue1[] va, int index, MyValue2 v) { test45_inline(va, v, index); }
+ if (element_klass == actual_klass) {
+ return true;
+ }
+ }
+ return false;
+ }
ciType* LoadField::declared_type() const {
return field()->type();
}
ciType* NewTypeArray::exact_type() const {
return ciTypeArrayKlass::make(elt_type());
}
ciType* NewObjectArray::exact_type() const {
- return ciObjArrayKlass::make(klass());
+ return ciArrayKlass::make(klass(), is_null_free());
+ }
+
+ ciType* NewMultiArray::exact_type() const {
+ return _klass;
}
ciType* NewArray::declared_type() const {
return exact_type();
}
ciType* NewInstance::declared_type() const {
return exact_type();
}
+ ciType* NewInlineTypeInstance::exact_type() const {
+ return klass();
+ }
+
+ ciType* NewInlineTypeInstance::declared_type() const {
+ return exact_type();
+ }
+
ciType* CheckCast::declared_type() const {
return klass();
}
// Implementation of ArithmeticOp
}
}
}
+ StoreField::StoreField(Value obj, int offset, ciField* field, Value value, bool is_static,
+ ValueStack* state_before, bool needs_patching)
+ : AccessField(obj, offset, field, is_static, state_before, needs_patching)
+ , _value(value)
+ , _enclosing_field(NULL)
+ {
+ set_flag(NeedsWriteBarrierFlag, as_ValueType(field_type())->is_object());
+ #ifdef ASSERT
+ AssertValues assert_value;
+ values_do(&assert_value);
+ #endif
+ pin();
+ if (value->as_NewInlineTypeInstance() != NULL) {
+ value->as_NewInlineTypeInstance()->set_not_larva_anymore();
+ }
+ }
+
+ StoreIndexed::StoreIndexed(Value array, Value index, Value length, BasicType elt_type, Value value,
+ ValueStack* state_before, bool check_boolean, bool mismatched)
+ : AccessIndexed(array, index, length, elt_type, state_before, mismatched)
+ , _value(value), _check_boolean(check_boolean)
+ {
+ set_flag(NeedsWriteBarrierFlag, (as_ValueType(elt_type)->is_object()));
+ set_flag(NeedsStoreCheckFlag, (as_ValueType(elt_type)->is_object()));
+ #ifdef ASSERT
+ AssertValues assert_value;
+ values_do(&assert_value);
+ #endif
+ pin();
+ if (value->as_NewInlineTypeInstance() != NULL) {
+ value->as_NewInlineTypeInstance()->set_not_larva_anymore();
+ }
+ }
+
+
// Implementation of Invoke
Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
- ciMethod* target, ValueStack* state_before)
+ ciMethod* target, ValueStack* state_before, bool null_free)
: StateSplit(result_type, state_before)
, _code(code)
, _recv(recv)
, _args(args)
, _target(target)
{
set_flag(TargetIsLoadedFlag, target->is_loaded());
set_flag(TargetIsFinalFlag, target_is_loaded() && target->is_final_method());
+ set_null_free(null_free);
assert(args != NULL, "args must exist");
#ifdef ASSERT
AssertValues assert_value;
values_do(&assert_value);
// provide an initial guess of signature size.
_signature = new BasicTypeList(number_of_arguments() + (has_receiver() ? 1 : 0));
if (has_receiver()) {
_signature->append(as_BasicType(receiver()->type()));
+ if (receiver()->as_NewInlineTypeInstance() != NULL) {
+ receiver()->as_NewInlineTypeInstance()->set_not_larva_anymore();
+ }
}
for (int i = 0; i < number_of_arguments(); i++) {
- ValueType* t = argument_at(i)->type();
+ Value v = argument_at(i);
+ ValueType* t = v->type();
BasicType bt = as_BasicType(t);
_signature->append(bt);
+ if (v->as_NewInlineTypeInstance() != NULL) {
+ v->as_NewInlineTypeInstance()->set_not_larva_anymore();
+ }
}
}
void Invoke::state_values_do(ValueVisitor* f) {
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);
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));
+ if (new_value->as_NewInlineTypeInstance() != NULL) {new_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
+ if (existing_value->as_NewInlineTypeInstance() != NULL) {existing_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
}
}
// create necessary phi functions for locals
for_each_local_value(existing_state, index, existing_value) {
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);
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));
+ if (new_value->as_NewInlineTypeInstance() != NULL) {new_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
+ if (existing_value->as_NewInlineTypeInstance() != NULL) {existing_value->as_NewInlineTypeInstance()->set_not_larva_anymore(); }
}
}
}
assert(existing_state->caller_state() == new_state->caller_state(), "caller states must be equal");
}
void ProfileInvoke::state_values_do(ValueVisitor* f) {
if (state() != NULL) state()->values_do(f);
}
+
< prev index next >