aoqi@0: /* aoqi@0: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #include "precompiled.hpp" aoqi@0: #include "classfile/systemDictionary.hpp" aoqi@0: #include "classfile/vmSymbols.hpp" aoqi@0: #include "memory/resourceArea.hpp" aoqi@0: #include "memory/universe.inline.hpp" aoqi@0: #include "oops/annotations.hpp" aoqi@0: #include "oops/instanceKlass.hpp" aoqi@0: #include "oops/fieldStreams.hpp" aoqi@0: #include "runtime/fieldDescriptor.hpp" aoqi@0: #include "runtime/handles.inline.hpp" aoqi@0: #include "runtime/signature.hpp" aoqi@0: aoqi@0: aoqi@0: oop fieldDescriptor::loader() const { aoqi@0: return _cp->pool_holder()->class_loader(); aoqi@0: } aoqi@0: aoqi@0: Symbol* fieldDescriptor::generic_signature() const { aoqi@0: if (!has_generic_signature()) { aoqi@0: return NULL; aoqi@0: } aoqi@0: aoqi@0: int idx = 0; aoqi@0: InstanceKlass* ik = field_holder(); aoqi@0: for (AllFieldStream fs(ik); !fs.done(); fs.next()) { aoqi@0: if (idx == _index) { aoqi@0: return fs.generic_signature(); aoqi@0: } else { aoqi@0: idx ++; aoqi@0: } aoqi@0: } aoqi@0: assert(false, "should never happen"); aoqi@0: return NULL; aoqi@0: } aoqi@0: aoqi@0: AnnotationArray* fieldDescriptor::annotations() const { aoqi@0: InstanceKlass* ik = field_holder(); aoqi@0: Array* md = ik->fields_annotations(); aoqi@0: if (md == NULL) aoqi@0: return NULL; aoqi@0: return md->at(index()); aoqi@0: } aoqi@0: aoqi@0: AnnotationArray* fieldDescriptor::type_annotations() const { aoqi@0: InstanceKlass* ik = field_holder(); aoqi@0: Array* type_annos = ik->fields_type_annotations(); aoqi@0: if (type_annos == NULL) aoqi@0: return NULL; aoqi@0: return type_annos->at(index()); aoqi@0: } aoqi@0: aoqi@0: constantTag fieldDescriptor::initial_value_tag() const { aoqi@0: return constants()->tag_at(initial_value_index()); aoqi@0: } aoqi@0: aoqi@0: jint fieldDescriptor::int_initial_value() const { aoqi@0: return constants()->int_at(initial_value_index()); aoqi@0: } aoqi@0: aoqi@0: jlong fieldDescriptor::long_initial_value() const { aoqi@0: return constants()->long_at(initial_value_index()); aoqi@0: } aoqi@0: aoqi@0: jfloat fieldDescriptor::float_initial_value() const { aoqi@0: return constants()->float_at(initial_value_index()); aoqi@0: } aoqi@0: aoqi@0: jdouble fieldDescriptor::double_initial_value() const { aoqi@0: return constants()->double_at(initial_value_index()); aoqi@0: } aoqi@0: aoqi@0: oop fieldDescriptor::string_initial_value(TRAPS) const { aoqi@0: return constants()->uncached_string_at(initial_value_index(), CHECK_0); aoqi@0: } aoqi@0: aoqi@0: void fieldDescriptor::reinitialize(InstanceKlass* ik, int index) { aoqi@0: if (_cp.is_null() || field_holder() != ik) { aoqi@0: _cp = constantPoolHandle(Thread::current(), ik->constants()); aoqi@0: // _cp should now reference ik's constant pool; i.e., ik is now field_holder. aoqi@0: assert(field_holder() == ik, "must be already initialized to this class"); aoqi@0: } aoqi@0: FieldInfo* f = ik->field(index); aoqi@0: assert(!f->is_internal(), "regular Java fields only"); aoqi@0: aoqi@0: _access_flags = accessFlags_from(f->access_flags()); aoqi@0: guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor"); aoqi@0: _index = index; aoqi@0: verify(); aoqi@0: } aoqi@0: aoqi@0: #ifndef PRODUCT aoqi@0: aoqi@0: void fieldDescriptor::verify() const { aoqi@0: if (_cp.is_null()) { aoqi@0: assert(_index == badInt, "constructor must be called"); // see constructor aoqi@0: } else { aoqi@0: assert(_index >= 0, "good index"); aoqi@0: assert(_index < field_holder()->java_fields_count(), "oob"); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void fieldDescriptor::print_on(outputStream* st) const { aoqi@0: access_flags().print_on(st); aoqi@0: name()->print_value_on(st); aoqi@0: st->print(" "); aoqi@0: signature()->print_value_on(st); aoqi@0: st->print(" @%d ", offset()); aoqi@0: if (WizardMode && has_initial_value()) { aoqi@0: st->print("(initval "); aoqi@0: constantTag t = initial_value_tag(); aoqi@0: if (t.is_int()) { aoqi@0: st->print("int %d)", int_initial_value()); aoqi@0: } else if (t.is_long()){ aoqi@0: st->print_jlong(long_initial_value()); aoqi@0: } else if (t.is_float()){ aoqi@0: st->print("float %f)", float_initial_value()); aoqi@0: } else if (t.is_double()){ aoqi@0: st->print("double %lf)", double_initial_value()); aoqi@0: } aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: void fieldDescriptor::print_on_for(outputStream* st, oop obj) { aoqi@0: print_on(st); aoqi@0: BasicType ft = field_type(); aoqi@0: jint as_int = 0; aoqi@0: switch (ft) { aoqi@0: case T_BYTE: aoqi@0: as_int = (jint)obj->byte_field(offset()); aoqi@0: st->print(" %d", obj->byte_field(offset())); aoqi@0: break; aoqi@0: case T_CHAR: aoqi@0: as_int = (jint)obj->char_field(offset()); aoqi@0: { aoqi@0: jchar c = obj->char_field(offset()); aoqi@0: as_int = c; aoqi@0: st->print(" %c %d", isprint(c) ? c : ' ', c); aoqi@0: } aoqi@0: break; aoqi@0: case T_DOUBLE: aoqi@0: st->print(" %lf", obj->double_field(offset())); aoqi@0: break; aoqi@0: case T_FLOAT: aoqi@0: as_int = obj->int_field(offset()); aoqi@0: st->print(" %f", obj->float_field(offset())); aoqi@0: break; aoqi@0: case T_INT: aoqi@0: as_int = obj->int_field(offset()); aoqi@0: st->print(" %d", obj->int_field(offset())); aoqi@0: break; aoqi@0: case T_LONG: aoqi@0: st->print(" "); aoqi@0: st->print_jlong(obj->long_field(offset())); aoqi@0: break; aoqi@0: case T_SHORT: aoqi@0: as_int = obj->short_field(offset()); aoqi@0: st->print(" %d", obj->short_field(offset())); aoqi@0: break; aoqi@0: case T_BOOLEAN: aoqi@0: as_int = obj->bool_field(offset()); aoqi@0: st->print(" %s", obj->bool_field(offset()) ? "true" : "false"); aoqi@0: break; aoqi@0: case T_ARRAY: aoqi@0: st->print(" "); aoqi@0: NOT_LP64(as_int = obj->int_field(offset())); aoqi@0: obj->obj_field(offset())->print_value_on(st); aoqi@0: break; aoqi@0: case T_OBJECT: aoqi@0: st->print(" "); aoqi@0: NOT_LP64(as_int = obj->int_field(offset())); aoqi@0: obj->obj_field(offset())->print_value_on(st); aoqi@0: break; aoqi@0: default: aoqi@0: ShouldNotReachHere(); aoqi@0: break; aoqi@0: } aoqi@0: // Print a hint as to the underlying integer representation. This can be wrong for aoqi@0: // pointers on an LP64 machine aoqi@0: if (ft == T_LONG || ft == T_DOUBLE LP64_ONLY(|| !is_java_primitive(ft)) ) { aoqi@0: st->print(" (%x %x)", obj->int_field(offset()), obj->int_field(offset()+sizeof(jint))); aoqi@0: } else if (as_int < 0 || as_int > 9) { aoqi@0: st->print(" (%x)", as_int); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: #endif /* PRODUCT */