< prev index next >
src/hotspot/share/c1/c1_Instruction.cpp
Print this page
@@ -1,7 +1,7 @@
/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
@@ -27,10 +27,12 @@
#include "c1/c1_Instruction.hpp"
#include "c1/c1_InstructionPrinter.hpp"
#include "c1/c1_ValueStack.hpp"
#include "ci/ciObjArrayKlass.hpp"
#include "ci/ciTypeArrayKlass.hpp"
+#include "ci/ciValueArrayKlass.hpp"
+#include "ci/ciValueKlass.hpp"
// Implementation of Instruction
@@ -111,10 +113,75 @@
}
return NULL;
}
+// FIXME -- this is used by ValueStack::merge_types only. We should remove this function
+// and use a better way for handling phi nodes.
+bool Instruction::is_flattened_array() const {
+ if (ValueArrayFlatten) {
+ ciType* type = declared_type();
+ if (type != NULL && type->is_value_array_klass()) {
+ ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass();
+ assert(element_klass->is_loaded(), "ciValueKlasses are always loaded");
+ if (element_klass->flatten_array()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Instruction::is_loaded_flattened_array() const {
+ if (ValueArrayFlatten) {
+ ciType* type = declared_type();
+ if (type != NULL && type->is_value_array_klass()) {
+ ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass();
+ assert(element_klass->is_loaded(), "ciValueKlasses are always loaded");
+ if (element_klass->flatten_array()) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+bool Instruction::maybe_flattened_array() {
+ if (ValueArrayFlatten) {
+ ciType* type = declared_type();
+ if (type != NULL) {
+ if (type->is_value_array_klass()) {
+ ciValueKlass* element_klass = type->as_value_array_klass()->element_klass()->as_value_klass();
+ assert(element_klass->is_loaded(), "ciValueKlasses are always loaded");
+ if (element_klass->flatten_array()) {
+ return true;
+ }
+ } else if (type->is_obj_array_klass()) {
+ ciKlass* element_klass = type->as_obj_array_klass()->element_klass();
+ if (!element_klass->is_loaded() || element_klass->is_java_lang_Object() || element_klass->is_interface()) {
+ // Array covariance:
+ // (ValueType[] <: Object[])
+ // (ValueType[] <: <any interface>[])
+ // We will add a runtime check for flat-ness.
+ 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 if (as_Phi() != NULL) {
+ // Type info gets lost during Phi merging, but we might be storing into a
+ // flattened 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();
}
@@ -195,10 +262,20 @@
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) {
+ ciKlass* element_klass = array()->declared_type()->as_value_array_klass()->element_klass();
+ ciKlass* actual_klass = value()->declared_type()->as_klass();
+ if (element_klass == actual_klass) {
+ return true;
+ }
+ }
+ return false;
+}
ciType* LoadField::declared_type() const {
return field()->type();
}
@@ -206,11 +283,20 @@
ciType* NewTypeArray::exact_type() const {
return ciTypeArrayKlass::make(elt_type());
}
ciType* NewObjectArray::exact_type() const {
- return ciObjArrayKlass::make(klass());
+ ciKlass* element_klass = klass();
+ if (element_klass->is_valuetype()) {
+ return ciValueArrayKlass::make(element_klass);
+ } else {
+ return ciObjArrayKlass::make(element_klass);
+ }
+}
+
+ciType* NewMultiArray::exact_type() const {
+ return _klass;
}
ciType* NewArray::declared_type() const {
return exact_type();
}
@@ -221,10 +307,27 @@
ciType* NewInstance::declared_type() const {
return exact_type();
}
+Value NewValueTypeInstance::depends_on() {
+ if (_depends_on != this) {
+ if (_depends_on->as_NewValueTypeInstance() != NULL) {
+ return _depends_on->as_NewValueTypeInstance()->depends_on();
+ }
+ }
+ return _depends_on;
+}
+
+ciType* NewValueTypeInstance::exact_type() const {
+ return klass();
+}
+
+ciType* NewValueTypeInstance::declared_type() const {
+ return exact_type();
+}
+
ciType* CheckCast::declared_type() const {
return klass();
}
// Implementation of ArithmeticOp
@@ -320,21 +423,22 @@
// Implementation of Invoke
Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
- int vtable_index, ciMethod* target, ValueStack* state_before)
+ int vtable_index, ciMethod* target, ValueStack* state_before, bool never_null)
: StateSplit(result_type, state_before)
, _code(code)
, _recv(recv)
, _args(args)
, _vtable_index(vtable_index)
, _target(target)
{
set_flag(TargetIsLoadedFlag, target->is_loaded());
set_flag(TargetIsFinalFlag, target_is_loaded() && target->is_final_method());
set_flag(TargetIsStrictfpFlag, target_is_loaded() && target->is_strict());
+ set_never_null(never_null);
assert(args != NULL, "args must exist");
#ifdef ASSERT
AssertValues assert_value;
values_do(&assert_value);
@@ -789,20 +893,20 @@
if (is_set(BlockBegin::parser_loop_header_flag)) {
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));
}
BitMap& requires_phi_function = new_state->scope()->requires_phi_function();
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));
}
}
}
@@ -857,11 +961,11 @@
for_each_stack_value(existing_state, index, existing_value) {
Value new_value = new_state->stack_at(index);
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));
}
}
// create necessary phi functions for locals
@@ -871,11 +975,11 @@
if (new_value == NULL || new_value->type()->tag() != existing_value->type()->tag()) {
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));
}
}
}
< prev index next >