/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "ci/ciField.hpp"
#include "ci/ciInstanceKlass.hpp"
#include "ci/ciUtilities.hpp"
#include "classfile/systemDictionary.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/linkResolver.hpp"
#include "memory/universe.inline.hpp"
#include "oops/oop.inline.hpp"
#include "oops/oop.inline2.hpp"
#include "runtime/fieldDescriptor.hpp"
// ciField
//
// This class represents the result of a field lookup in the VM.
// The lookup may not succeed, in which case the information in
// the ciField will be incomplete.
// The ciObjectFactory cannot create circular data structures in one query.
// To avoid vicious circularities, we initialize ciField::_type to NULL
// for reference types and derive it lazily from the ciField::_signature.
// Primitive types are eagerly initialized, and basic layout queries
// can succeed without initialization, using only the BasicType of the field.
// Notes on bootstrapping and shared CI objects: A field is shared if and
// only if it is (a) non-static and (b) declared by a shared instance klass.
// This allows non-static field lists to be cached on shared types.
// Because the _type field is lazily initialized, however, there is a
// special restriction that a shared field cannot cache an unshared type.
// This puts a small performance penalty on shared fields with unshared
// types, such as StackTraceElement[] Throwable.stackTrace.
// (Throwable is shared because ClassCastException is shared, but
// StackTraceElement is not presently shared.)
// It is not a vicious circularity for a ciField to recursively create
// the ciSymbols necessary to represent its name and signature.
// Therefore, these items are created eagerly, and the name and signature
// of a shared field are themselves shared symbols. This somewhat
// pollutes the set of shared CI objects: It grows from 50 to 93 items,
// with all of the additional 43 being uninteresting shared ciSymbols.
// This adds at most one step to the binary search, an amount which
// decreases for complex compilation tasks.
// ------------------------------------------------------------------
// ciField::ciField
ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with_put(NULL), _known_to_link_with_get(NULL) {
// Get the field's name, signature, and type.
// If the field is a pointer type, get the klass of the
// field.
bool ignore;
// This is not really a class reference; the index always refers to the
// field's type signature, as a symbol. Linkage checks do not apply.
} else {
}
// Get the field's declared holder.
//
// Note: we actually create a ciInstanceKlass for this klass,
// even though we may not need to.
bool holder_is_accessible;
klass)->as_instance_klass();
// The declared holder of this field may not have been loaded.
// Bail out with partial field information.
if (!holder_is_accessible) {
// _cp_index and _type have already been set.
// The default values for _flags and _constant_value will suffice.
// We need values for _holder, _offset, and _is_constant,
_offset = -1;
_is_constant = false;
return;
}
// Perform the field lookup.
if (canonical_holder == NULL) {
// Field lookup failed. Will be detected by will_link.
_offset = -1;
_is_constant = false;
return;
}
}
ciField::ciField(fieldDescriptor *fd): _known_to_link_with_put(NULL), _known_to_link_with_get(NULL) {
_cp_index = -1;
// Get the field's name, signature, and type.
// If the field is a pointer type, get the klass of the
// field.
} else {
}
// Either (a) it is marked shared, or else (b) we are done bootstrapping.
"bootstrap classes must not create & cache unshared fields");
}
return false;
// Never trust strangely unstable finals: System.out, etc.
return false;
// Even if general trusting is disabled, trust system-built closures in these packages.
return true;
return TrustFinalNonStaticFields;
}
// Get the flags, offset, and canonical holder of the field.
// Check to see if the field is constant.
if (!this->is_static()) {
// A field can be constant if it's a final static field or if
// it's a final non-static field of a trusted class (classes in
// java.lang.invoke and sun.invoke packages and subpackages).
if (trust_final_non_static_fields(_holder)) {
_is_constant = true;
return;
}
_is_constant = false;
return;
}
// This field just may be constant. The only cases where it will
// not be constant are:
//
// 1. The field holds a non-perm-space oop. The field is, strictly
// speaking, constant but we cannot embed non-perm-space oops into
// generated code. For the time being we need to consider the
// field to be not constant.
// 2. The field is a *special* static&final field whose value
// may change. The three examples are java.lang.System.in,
// java.lang.System.out, and java.lang.System.err.
if( k() == SystemDictionary::System_klass() ) {
// Check offsets for case 2: System.in, System.out, or System.err
_is_constant = false;
return;
}
}
_is_constant = true;
switch(type()->basic_type()) {
case T_BYTE:
break;
case T_CHAR:
break;
case T_SHORT:
break;
case T_BOOLEAN:
break;
case T_INT:
break;
case T_FLOAT:
break;
case T_DOUBLE:
break;
case T_LONG:
break;
case T_OBJECT:
case T_ARRAY:
{
// A field will be "constant" if it is known always to be
// a non-null reference to an instance of a particular class,
// or to a particular array. This can happen even if the instance
// or array is not perm. In such a case, an "unloaded" ciArray
// or ciInstance is created. The compiler may be able to use
// information about the object's class (which is exact) or length.
if (o == NULL) {
} else {
}
}
}
} else {
_is_constant = false;
}
}
// ------------------------------------------------------------------
// ciField::compute_type
//
// Lazily compute the type, if it is an instance klass.
GUARDED_VM_ENTRY(return compute_type_impl();)
}
ciKlass* type = CURRENT_ENV->get_klass_by_name_impl(_holder, constantPoolHandle(), _signature, false);
// We must not cache a pointer to an unshared type, in a shared field.
bool type_is_also_shared = false;
if (type->is_type_array_klass()) {
type_is_also_shared = true; // int[] etc. are explicitly bootstrapped
} else if (type->is_instance_klass()) {
} else {
// Currently there is no 'shared' query for array types.
}
if (!type_is_also_shared)
return type; // Bummer.
}
return type;
}
// ------------------------------------------------------------------
// ciField::will_link
//
// Can a specific access to this field be made without causing
// link errors?
"unexpected bytecode");
if (_offset == -1) {
// at creation we couldn't link to our holder so we need to
// maintain that stance, otherwise there's no safe way to use this
// ciField.
return false;
}
return false;
}
// Get and put can have different accessibility rules
if (is_put) {
if (_known_to_link_with_put == accessing_klass) {
return true;
}
} else {
if (_known_to_link_with_get == accessing_klass) {
return true;
}
}
true, false, KILL_COMPILE_ON_FATAL_(false));
// update the hit-cache, unless there is a problem with memory scoping:
if (is_put) {
} else {
}
}
return true;
}
// ------------------------------------------------------------------
// ciField::print
_holder->print_name();
_name->print_symbol();
if (_is_constant && is_static()) {
}
}
// ------------------------------------------------------------------
// ciField::print_name_on
//
// Print the name of this field
}