diff options
-rw-r--r-- | libjava/ChangeLog | 9 | ||||
-rw-r--r-- | libjava/include/jvm.h | 1 | ||||
-rw-r--r-- | libjava/link.cc | 12 | ||||
-rw-r--r-- | libjava/verify.cc | 49 |
4 files changed, 59 insertions, 12 deletions
diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 051484c35a5..a81a389ff19 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,12 @@ +2005-02-18 Tom Tromey <tromey@redhat.com> + + PR java/20056: + * include/jvm.h (_Jv_Linker::has_field_p): Declare. + * link.cc (has_field_p): New function. + * verify.cc (check_field_constant): Added 'putfield' argument. + (verify_instructions_0): Updated. + (type::equals): New method. + 2005-02-18 Anthony Green <green@redhat.com> * NEWS: Draft of libgcj NEWS for 4.0. diff --git a/libjava/include/jvm.h b/libjava/include/jvm.h index 235c8ed21cc..61e426f2e66 100644 --- a/libjava/include/jvm.h +++ b/libjava/include/jvm.h @@ -278,6 +278,7 @@ private: public: + static bool has_field_p (jclass, _Jv_Utf8Const *); static void print_class_loaded (jclass); static void resolve_class_ref (jclass, jclass *); static void wait_for_state(jclass, int); diff --git a/libjava/link.cc b/libjava/link.cc index 8dd809b8687..cfaa3cd363d 100644 --- a/libjava/link.cc +++ b/libjava/link.cc @@ -131,6 +131,18 @@ _Jv_Linker::find_field_helper (jclass search, _Jv_Utf8Const *name, return NULL; } +bool +_Jv_Linker::has_field_p (jclass search, _Jv_Utf8Const *field_name) +{ + for (int i = 0; i < search->field_count; ++i) + { + _Jv_Field *field = &search->fields[i]; + if (_Jv_equalUtf8Consts (field->name, field_name)) + return true; + } + return false; +} + // Find a field. // KLASS is the class that is requesting the field. // OWNER is the class in which the field should be found. diff --git a/libjava/verify.cc b/libjava/verify.cc index 988b5aab67e..9df031634fa 100644 --- a/libjava/verify.cc +++ b/libjava/verify.cc @@ -1,6 +1,6 @@ // verify.cc - verify bytecode -/* Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation +/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation This file is part of libgcj. @@ -751,6 +751,20 @@ private: return klass->compatible(k.klass, verifier); } + bool equals (const type &other, _Jv_BytecodeVerifier *vfy) + { + // Only works for reference types. + if (key != reference_type + || key != uninitialized_reference_type + || other.key != reference_type + || other.key != uninitialized_reference_type) + return false; + // Only for single-valued types. + if (klass->ref_next || other.klass->ref_next) + return false; + return klass->equals (other.klass, vfy); + } + bool isvoid () const { return key == void_type; @@ -1963,7 +1977,9 @@ private: } // Return field's type, compute class' type if requested. - type check_field_constant (int index, type *class_type = NULL) + // If PUTFIELD is true, use the special 'putfield' semantics. + type check_field_constant (int index, type *class_type = NULL, + bool putfield = false) { _Jv_Utf8Const *name, *field_type; type ct = handle_field_or_method (index, @@ -1971,9 +1987,25 @@ private: &name, &field_type); if (class_type) *class_type = ct; + type result; if (field_type->first() == '[' || field_type->first() == 'L') - return type (field_type, this); - return get_type_val_for_signature (field_type->first()); + result = type (field_type, this); + else + result = get_type_val_for_signature (field_type->first()); + + // We have an obscure special case here: we can use `putfield' on + // a field declared in this class, even if `this' has not yet been + // initialized. + if (putfield + && ! current_state->this_type.isinitialized () + && current_state->this_type.pc == type::SELF + && current_state->this_type.equals (ct, this) + // We don't look at the signature, figuring that if it is + // wrong we will fail during linking. FIXME? + && _Jv_Linker::has_field_p (current_class, name)) + class_type->set_uninitialized (type::SELF, this); + + return result; } type check_method_constant (int index, bool is_interface, @@ -2783,15 +2815,8 @@ private: case op_putfield: { type klass; - type field = check_field_constant (get_ushort (), &klass); + type field = check_field_constant (get_ushort (), &klass, true); pop_type (field); - - // We have an obscure special case here: we can use - // `putfield' on a field declared in this class, even if - // `this' has not yet been initialized. - if (! current_state->this_type.isinitialized () - && current_state->this_type.pc == type::SELF) - klass.set_uninitialized (type::SELF, this); pop_type (klass); } break; |