OSDN Git Service

* libjava.jni/throwit.java: New file.
[pf3gnuchains/gcc-fork.git] / libjava / defineclass.cc
index 09f8f47..215fc23 100644 (file)
@@ -1,6 +1,6 @@
 // defineclass.cc - defining a class from .class format.
 
-/* Copyright (C) 1999  Cygnus Solutions
+/* Copyright (C) 1999, 2000  Red Hat, Inc.
 
    This file is part of libgcj.
 
@@ -18,12 +18,14 @@ details.  */
    currently being ignored ("InnerClasses", "LineNumber", etc...).  
 */
 
+#include <config.h>
+
 #include <java-interp.h>
 
 #ifdef INTERPRETER
 
 #include <java-cpool.h>
-#include <cni.h>
+#include <gcj/cni.h>
 
 #include <java/lang/Class.h>
 #include <java/lang/Float.h>
@@ -36,11 +38,10 @@ details.  */
 #include <java/lang/ClassCircularityError.h>
 #include <java/lang/ClassNotFoundException.h>
 #include <java/lang/IncompatibleClassChangeError.h>
+#include <java/lang/reflect/Modifier.h>
 
 #define ClassClass _CL_Q34java4lang5Class
 extern java::lang::Class ClassClass;
-#define StringClass _CL_Q34java4lang6String
-extern java::lang::Class StringClass;
 #define ClassObject _CL_Q34java4lang6Object
 extern java::lang::Class ClassObject;
 
@@ -246,20 +247,6 @@ struct _Jv_ClassReader {
    * could be implemented in prims.cc (_Jv_makeUtf8Const), since it
    * computes the hash value anyway.
    */
-
-  static const int PUBLIC       = 0x001;
-  static const int PRIVATE      = 0x002;
-  static const int PROTECTED    = 0x004;
-  static const int STATIC       = 0x008;
-  static const int FINAL        = 0x010;
-  static const int SYNCHRONIZED = 0x020;
-  static const int VOLATILE     = 0x040;
-  static const int TRANSIENT    = 0x080;
-  static const int NATIVE       = 0x100;
-  static const int INTERFACE    = 0x200;
-  static const int ABSTRACT     = 0x400;
-  static const int ALL_FLAGS    = 0x7FF; 
-
 };
 
 /* This is used for the isJavaIdentifierStart & isJavaIdentifierPart
@@ -614,7 +601,8 @@ void _Jv_ClassReader::handleConstantPool ()
 
   // the pool is scanned explicitly by the collector
   jbyte *pool_tags = (jbyte*) _Jv_AllocBytesChecked (pool_count);
-  void **pool_data = (void**) _Jv_AllocBytesChecked (pool_count * sizeof (void*));
+  _Jv_word *pool_data
+    = (_Jv_word*) _Jv_AllocBytesChecked (pool_count * sizeof (_Jv_word));
   
   def->constants.tags = pool_tags;
   def->constants.data = pool_data;
@@ -634,7 +622,7 @@ void _Jv_ClassReader::handleConstantPool ()
          check_tag (utf_index, JV_CONSTANT_Utf8);
          unsigned char *utf_data = bytes + offsets[utf_index];
          int len = get2u (utf_data);
-         pool_data[i] = (void*)_Jv_makeUtf8Const ((char*)(utf_data+2), len);
+         pool_data[i].utf8 = _Jv_makeUtf8Const ((char*)(utf_data+2), len);
          pool_tags[i] = JV_CONSTANT_String;
        }
       else
@@ -671,7 +659,7 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
      structure we are currently defining */
 
   unsigned char *pool_tags = (unsigned char*) def->constants.tags;
-  void         **pool_data = (void**) def->constants.data;
+  _Jv_word      *pool_data = def->constants.data;
 
   /* this entry was already prepared */
   if (pool_tags[index] == this_tag)
@@ -703,7 +691,7 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
              buffer[i] = (char) s[i];
          }
        
-       pool_data[index] = (void*)_Jv_makeUtf8Const (buffer, len);
+       pool_data[index].utf8 = _Jv_makeUtf8Const (buffer, len);
        pool_tags[index] = JV_CONSTANT_Utf8;
       }
       break;
@@ -715,9 +703,9 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
        prepare_pool_entry (utf_index, JV_CONSTANT_Utf8);
 
        if (verify)
-         _Jv_VerifyClassName ((_Jv_Utf8Const*)pool_data[utf_index]);
+         _Jv_VerifyClassName (pool_data[utf_index].utf8);
                
-       pool_data[index] = pool_data[utf_index];
+       pool_data[index].utf8 = pool_data[utf_index].utf8;
        pool_tags[index] = JV_CONSTANT_Class;
       }
       break;
@@ -743,24 +731,22 @@ _Jv_ClassReader::prepare_pool_entry (int index, unsigned char this_tag)
        if (verify)
        {
          _Jv_ushort name_index, type_index;
-         _Jv_loadIndexes ((const void**)&pool_data[nat_index],
+         _Jv_loadIndexes (&pool_data[nat_index],
                           name_index, type_index);
 
          if (this_tag == JV_CONSTANT_Fieldref)
-           _Jv_VerifyFieldSignature
-             ((_Jv_Utf8Const*)pool_data[type_index]);
+           _Jv_VerifyFieldSignature (pool_data[type_index].utf8);
          else
-           _Jv_VerifyMethodSignature
-             ((_Jv_Utf8Const*)pool_data[type_index]);
+           _Jv_VerifyMethodSignature (pool_data[type_index].utf8);
 
-         _Jv_Utf8Const* name = (_Jv_Utf8Const*)pool_data[name_index];
+         _Jv_Utf8Const* name = pool_data[name_index].utf8;
 
          if (this_tag != JV_CONSTANT_Fieldref
              && (   _Jv_equalUtf8Consts (name, clinit_name)
                  || _Jv_equalUtf8Consts (name, init_name)))
            /* ignore */;
          else
-           _Jv_VerifyIdentifier ((_Jv_Utf8Const*)pool_data[name_index]);
+           _Jv_VerifyIdentifier (pool_data[name_index].utf8);
        }
            
        _Jv_storeIndexes (&pool_data[index], class_index, nat_index);
@@ -826,11 +812,13 @@ void
 _Jv_ClassReader::handleClassBegin
   (int access_flags, int this_class, int super_class)
 {
+  using namespace java::lang::reflect;
+
   unsigned char *pool_tags = (unsigned char*) def->constants.tags;
-  void         **pool_data = (void**) def->constants.data;
+  _Jv_word      *pool_data = def->constants.data;
 
   check_tag (this_class, JV_CONSTANT_Class);
-  _Jv_Utf8Const *loadedName = (_Jv_Utf8Const*)pool_data[this_class];
+  _Jv_Utf8Const *loadedName = pool_data[this_class].utf8;
 
   // was ClassLoader.defineClass called with an expected class name?
   if (def->name == 0)
@@ -865,13 +853,13 @@ _Jv_ClassReader::handleClassBegin
     }
 
   def->accflags = access_flags;
-  pool_data[this_class] = (void*)def;
+  pool_data[this_class].clazz = def;
   pool_tags[this_class] = JV_CONSTANT_ResolvedClass;
 
   if (super_class == 0)
     {
       // interfaces have java.lang.Object as super.
-      if (access_flags & INTERFACE)
+      if (access_flags & Modifier::INTERFACE)
        {
          def->superclass = (jclass)&ClassObject;
        }
@@ -894,8 +882,7 @@ _Jv_ClassReader::handleClassBegin
     {
       // load the super class
       check_tag (super_class, JV_CONSTANT_Class);
-      _Jv_Utf8Const* super_name =
-       (_Jv_Utf8Const*)pool_data[super_class]; 
+      _Jv_Utf8Const* super_name = pool_data[super_class].utf8; 
 
       // load the super class using our defining loader
       jclass the_super = _Jv_FindClass (super_name,
@@ -906,7 +893,7 @@ _Jv_ClassReader::handleClassBegin
       checkExtends (def, the_super);
 
       def->superclass = the_super;
-      pool_data[super_class] = (void*) the_super;
+      pool_data[super_class].clazz = the_super;
       pool_tags[super_class] = JV_CONSTANT_ResolvedClass;
     }
            
@@ -921,14 +908,16 @@ _Jv_ClassReader::handleClassBegin
 void
 _Jv_ClassReader::checkExtends (jclass sub, jclass super)
 {
+  using namespace java::lang::reflect;
+
   // having an interface or a final class as a superclass is no good
-  if ((super->accflags & (INTERFACE | FINAL)) != 0)
+  if ((super->accflags & (Modifier::INTERFACE | Modifier::FINAL)) != 0)
     {
       throw_incompatible_class_change_error (sub->getName ());
     }
 
   // if the super class is not public, we need to check some more
-  if ((super->accflags & PUBLIC) == 0)
+  if ((super->accflags & Modifier::PUBLIC) == 0)
     {
       // With package scope, the classes must have the same
       // class loader.
@@ -956,19 +945,19 @@ void _Jv_ClassReader::handleInterfacesBegin (int count)
 
 void _Jv_ClassReader::handleInterface (int if_number, int offset)
 {
-  void          ** pool_data = def->constants.data;
+  _Jv_word       * pool_data = def->constants.data;
   unsigned char  * pool_tags = (unsigned char*) def->constants.tags;
 
   jclass the_interface;
 
   if (pool_tags[offset] == JV_CONSTANT_Class)
     {
-      _Jv_Utf8Const* name = (_Jv_Utf8Const*) pool_data[offset];
+      _Jv_Utf8Const* name = pool_data[offset].utf8;
       the_interface =  _Jv_FindClass (name, def->loader);
     }
   else if (pool_tags[offset] == JV_CONSTANT_ResolvedClass)
     {
-      the_interface = (jclass)pool_data[offset];
+      the_interface = pool_data[offset].clazz;
     }
   else
     {
@@ -979,7 +968,7 @@ void _Jv_ClassReader::handleInterface (int if_number, int offset)
   // allowed to implement that interface.
   checkImplements (def, the_interface);
   
-  pool_data[offset] = (void*)the_interface;
+  pool_data[offset].clazz = the_interface;
   pool_tags[offset] = JV_CONSTANT_ResolvedClass;
   
   def->interfaces[if_number] = the_interface;
@@ -988,15 +977,17 @@ void _Jv_ClassReader::handleInterface (int if_number, int offset)
 void
 _Jv_ClassReader::checkImplements (jclass sub, jclass super)
 {
+  using namespace java::lang::reflect;
+
   // well, it *must* be an interface
-  if ((super->accflags & INTERFACE) == 0)
+  if ((super->accflags & Modifier::INTERFACE) == 0)
     {
       throw_incompatible_class_change_error (sub->getName ());
     }
 
   // if it has package scope, it must also be defined by the 
   // same loader.
-  if ((super->accflags & PUBLIC) == 0)
+  if ((super->accflags & Modifier::PUBLIC) == 0)
     {
       if (    sub->loader != super->loader
          || !_Jv_ClassNameSamePackage (sub->name, super->name))
@@ -1028,10 +1019,12 @@ void _Jv_ClassReader::handleField (int field_no,
                                   int name,
                                   int desc)
 {
-  void **const pool_data = def->constants.data;
+  using namespace java::lang::reflect;
+
+  _Jv_word *pool_data = def->constants.data;
 
   _Jv_Field *field = &def->fields[field_no];
-  _Jv_Utf8Const *field_name = (_Jv_Utf8Const*) pool_data[name];
+  _Jv_Utf8Const *field_name = pool_data[name].utf8;
 
 #ifndef COMPACT_FIELDS
   field->name      = field_name;
@@ -1043,20 +1036,23 @@ void _Jv_ClassReader::handleField (int field_no,
     _Jv_VerifyIdentifier (field_name);
 
   // ignore flags we don't know about.  
-  field->flags = flags & ALL_FLAGS;
+  field->flags = flags & Modifier::ALL_FLAGS;
 
   if (verify)
     {
-      if (field->flags & (SYNCHRONIZED|NATIVE|INTERFACE|ABSTRACT))
+      if (field->flags & (Modifier::SYNCHRONIZED
+                         | Modifier::NATIVE
+                         | Modifier::INTERFACE
+                         | Modifier::ABSTRACT))
        throw_class_format_error ("erroneous field access flags");
       
-      if (1 < ( ((field->flags & PUBLIC) ? 1 : 0)
-               +((field->flags & PRIVATE) ? 1 : 0)
-               +((field->flags & PROTECTED) ? 1 : 0)))
+      if (1 < ( ((field->flags & Modifier::PUBLIC) ? 1 : 0)
+               +((field->flags & Modifier::PRIVATE) ? 1 : 0)
+               +((field->flags & Modifier::PROTECTED) ? 1 : 0)))
        throw_class_format_error ("erroneous field access flags");
     }
 
-  _Jv_Utf8Const* sig = (_Jv_Utf8Const*) pool_data[desc];
+  _Jv_Utf8Const* sig = pool_data[desc].utf8;
 
   if (verify)
     _Jv_VerifyFieldSignature (sig);
@@ -1072,9 +1068,13 @@ void _Jv_ClassReader::handleField (int field_no,
 void _Jv_ClassReader::handleConstantValueAttribute (int field_index, 
                                                    int value)
 {
+  using namespace java::lang::reflect;
+
   _Jv_Field *field = &def->fields[field_index];
 
-  if ((field->flags & (STATIC|FINAL|PRIVATE)) == 0)
+  if ((field->flags & (Modifier::STATIC
+                      | Modifier::FINAL
+                      | Modifier::PRIVATE)) == 0)
     {
       // Ignore, as per vmspec #4.7.2
       return;
@@ -1097,6 +1097,8 @@ void _Jv_ClassReader::handleConstantValueAttribute (int field_index,
 
 void _Jv_ClassReader::handleFieldsEnd ()
 {
+  using namespace java::lang::reflect;
+
   // We need to reorganize the fields so that the static ones are first,
   // to conform to GCJ class layout.
 
@@ -1109,11 +1111,11 @@ void _Jv_ClassReader::handleFieldsEnd ()
   while (low < high)
     {
       // go forward on low, while it's a static
-      while (low < high && (fields[low].flags & STATIC) != 0)
+      while (low < high && (fields[low].flags & Modifier::STATIC) != 0)
        low++;
       
       // go backwards on high, while it's a non-static
-      while (low < high && (fields[high].flags & STATIC) == 0)
+      while (low < high && (fields[high].flags & Modifier::STATIC) == 0)
        high--;
 
       if (low==high)
@@ -1132,7 +1134,7 @@ void _Jv_ClassReader::handleFieldsEnd ()
       low  += 1;
     }
   
-  if ((fields[low].flags & STATIC) != 0) 
+  if ((fields[low].flags & Modifier::STATIC) != 0) 
     low += 1;
 
   def->static_field_count = low;
@@ -1140,13 +1142,15 @@ void _Jv_ClassReader::handleFieldsEnd ()
 
 
 
-void _Jv_ClassReader::handleMethodsBegin (int count)
+void
+_Jv_ClassReader::handleMethodsBegin (int count)
 {
   def->methods = (_Jv_Method*)
     _Jv_AllocBytesChecked (sizeof (_Jv_Method)*count);
 
-  def->interpreted_methods = (_Jv_InterpMethod**)
-    _Jv_AllocBytesChecked (sizeof (_Jv_InterpMethod*) * count);
+  def->interpreted_methods
+    = (_Jv_MethodBase **) _Jv_AllocBytesChecked (sizeof (_Jv_MethodBase *)
+                                                * count);
 
   for (int i = 0; i < count; i++)
     def->interpreted_methods[i] = 0;
@@ -1158,19 +1162,21 @@ void _Jv_ClassReader::handleMethodsBegin (int count)
 void _Jv_ClassReader::handleMethod 
     (int mth_index, int accflags, int name, int desc)
 { 
-  void **const pool_data = def->constants.data;
+  using namespace java::lang::reflect;
+
+  _Jv_word *pool_data = def->constants.data;
   _Jv_Method *method = &def->methods[mth_index];
 
   check_tag (name, JV_CONSTANT_Utf8);
   prepare_pool_entry (name, JV_CONSTANT_Utf8);
-  method->name = (_Jv_Utf8Const*)pool_data[name];
+  method->name = pool_data[name].utf8;
 
   check_tag (desc, JV_CONSTANT_Utf8);
   prepare_pool_entry (desc, JV_CONSTANT_Utf8);
-  method->signature = (_Jv_Utf8Const*)pool_data[desc];
+  method->signature = pool_data[desc].utf8;
 
   // ignore unknown flags
-  method->accflags = accflags & ALL_FLAGS;
+  method->accflags = accflags & Modifier::ALL_FLAGS;
 
   // intialize...
   method->ncode = 0;
@@ -1185,12 +1191,14 @@ void _Jv_ClassReader::handleMethod
 
       _Jv_VerifyMethodSignature (method->signature);
 
-      if (method->accflags & (VOLATILE|TRANSIENT|INTERFACE))
+      if (method->accflags & (Modifier::VOLATILE
+                             | Modifier::TRANSIENT
+                             | Modifier::INTERFACE))
        throw_class_format_error ("erroneous method access flags");
       
-      if (1 < ( ((method->accflags & PUBLIC) ? 1 : 0)
-               +((method->accflags & PRIVATE) ? 1 : 0)
-               +((method->accflags & PROTECTED) ? 1 : 0)))
+      if (1 < ( ((method->accflags & Modifier::PUBLIC) ? 1 : 0)
+               +((method->accflags & Modifier::PRIVATE) ? 1 : 0)
+               +((method->accflags & Modifier::PROTECTED) ? 1 : 0)))
        throw_class_format_error ("erroneous method access flags");
     }
 }
@@ -1224,7 +1232,8 @@ void _Jv_ClassReader::handleExceptionTableEntry
   (int method_index, int exc_index, 
    int start_pc, int end_pc, int handler_pc, int catch_type)
 {
-  _Jv_InterpMethod *method = def->interpreted_methods[method_index];
+  _Jv_InterpMethod *method = reinterpret_cast<_Jv_InterpMethod *>
+    (def->interpreted_methods[method_index]);
   _Jv_InterpException *exc = method->exceptions ();
 
   exc[exc_index].start_pc     = start_pc;
@@ -1235,20 +1244,34 @@ void _Jv_ClassReader::handleExceptionTableEntry
 
 void _Jv_ClassReader::handleMethodsEnd ()
 {
+  using namespace java::lang::reflect;
+
   for (int i = 0; i < def->method_count; i++)
     {
       _Jv_Method *method = &def->methods[i];
-      if (method->accflags & (NATIVE|ABSTRACT))
+      if ((method->accflags & Modifier::NATIVE) != 0)
        {
          if (def->interpreted_methods[i] != 0)
-           throw_class_format_error ("code provided "
-                                     "for abstract or native method");
+           throw_class_format_error ("code provided for native method");
+         else
+           {
+             _Jv_JNIMethod *m = (_Jv_JNIMethod *)
+               _Jv_AllocBytesChecked (sizeof (_Jv_JNIMethod));
+             m->defining_class = def;
+             m->self = method;
+             m->function = NULL;
+             def->interpreted_methods[i] = m;
+           }
+       }
+      else if ((method->accflags & Modifier::ABSTRACT) != 0)
+       {
+         if (def->interpreted_methods[i] != 0)
+           throw_class_format_error ("code provided for abstract method");
        }
       else
        {
          if (def->interpreted_methods[i] == 0)
-           throw_class_format_error ("abstract or native method "
-                                     "with no code");
+           throw_class_format_error ("method with no code");
        }
     }
 
@@ -1414,6 +1437,14 @@ _Jv_VerifyClassName (unsigned char* ptr, _Jv_ushort length)
   unsigned char *limit = ptr+length;
   int ch;
 
+  if ('[' == UTF8_PEEK (ptr, limit))
+    {
+      if (! _Jv_VerifyOne (++ptr, limit, false))
+        throw_class_format_error ("erroneous class name");
+      else
+        return;
+    }
+
  next_level:
   do {
     if ((ch = UTF8_GET (ptr, limit))==-1)