< prev index next >
src/hotspot/share/c1/c1_Instruction.cpp
Print this page
*** 1,7 ****
/*
! * Copyright (c) 1999, 2017, 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.
--- 1,7 ----
/*
! * 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,36 ****
--- 27,38 ----
#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,120 ****
--- 113,187 ----
}
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,204 ****
--- 262,281 ----
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,216 ****
ciType* NewTypeArray::exact_type() const {
return ciTypeArrayKlass::make(elt_type());
}
ciType* NewObjectArray::exact_type() const {
! return ciObjArrayKlass::make(klass());
}
ciType* NewArray::declared_type() const {
return exact_type();
}
--- 283,302 ----
ciType* NewTypeArray::exact_type() const {
return ciTypeArrayKlass::make(elt_type());
}
ciType* NewObjectArray::exact_type() const {
! 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,230 ****
--- 307,333 ----
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,340 ****
// Implementation of Invoke
Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
! int vtable_index, ciMethod* target, ValueStack* state_before)
: 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());
assert(args != NULL, "args must exist");
#ifdef ASSERT
AssertValues assert_value;
values_do(&assert_value);
--- 423,444 ----
// Implementation of Invoke
Invoke::Invoke(Bytecodes::Code code, ValueType* result_type, Value recv, Values* args,
! 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,808 ****
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);
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);
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));
}
}
}
--- 893,912 ----
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, 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, 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,867 ****
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);
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
--- 961,971 ----
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_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,881 ****
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);
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));
}
}
}
--- 975,985 ----
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_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 >