Commit a286e145 by Bryce McKinlay Committed by Bryce McKinlay

Class.h (_Jv_IDispatchTable): Make it a struct.

2006-02-09  Bryce McKinlay  <mckinlay@redhat.com>

	* java/lang/Class.h (_Jv_IDispatchTable): Make it a struct. Put 
	'itable' inline, instead of as a pointer.
	(java::lang::Class): Put 'idt' in anonymous union with 'ioffsets'.
	* link.cc (null_idt): Update definition.
	(_Jv_Linker::prepare_constant_time_tables): Allocate klass->idt
	as a single struct. Use _Jv_AllocBytes, not _Jv_AllocRawObj.
	(_Jv_Linker::generate_itable): Update to use 'ioffsets'.
	(_Jv_Linker::find_iindex): Likewise. Update comment.
	* java/lang/natClass.cc	(_Jv_LookupInterfaceMethodIdx): Update for
	_Jv_IDispatchTable change.
	(_Jv_IsAssignableFrom): Likewise.

From-SVN: r110818
parent c4bbc105
2006-02-09 Bryce McKinlay <mckinlay@redhat.com>
* java/lang/Class.h (_Jv_IDispatchTable): Make it a struct. Put
'itable' inline, instead of as a pointer.
(java::lang::Class): Put 'idt' in anonymous union with 'ioffsets'.
* link.cc (null_idt): Update definition.
(_Jv_Linker::prepare_constant_time_tables): Allocate klass->idt
as a single struct. Use _Jv_AllocBytes, not _Jv_AllocRawObj.
(_Jv_Linker::generate_itable): Update to use 'ioffsets'.
(_Jv_Linker::find_iindex): Likewise. Update comment.
* java/lang/natClass.cc (_Jv_LookupInterfaceMethodIdx): Update for
_Jv_IDispatchTable change.
(_Jv_IsAssignableFrom): Likewise.
2006-02-08 Bryce McKinlay <mckinlay@redhat.com> 2006-02-08 Bryce McKinlay <mckinlay@redhat.com>
PR libgcj/25187: PR libgcj/25187:
......
...@@ -120,23 +120,14 @@ struct _Jv_Method ...@@ -120,23 +120,14 @@ struct _Jv_Method
{ return this + 1; } { return this + 1; }
}; };
// Interface Dispatch Tables // The table used to resolve interface calls.
union _Jv_IDispatchTable struct _Jv_IDispatchTable
{ {
struct
{
// Index into interface's ioffsets. // Index into interface's ioffsets.
jshort iindex; jshort iindex;
jshort itable_length; jshort itable_length;
// Class Interface dispatch table. // Class Interface dispatch table.
void **itable; void *itable[0];
} cls;
struct
{
// Offsets into implementation class itables.
jshort *ioffsets;
} iface;
}; };
// Used by _Jv_Linker::get_interfaces () // Used by _Jv_Linker::get_interfaces ()
...@@ -600,8 +591,13 @@ private: ...@@ -600,8 +591,13 @@ private:
jshort depth; jshort depth;
// Vector of this class's superclasses, ordered by decreasing depth. // Vector of this class's superclasses, ordered by decreasing depth.
jclass *ancestors; jclass *ancestors;
// Interface Dispatch Table. // In a regular class, this field points to the Class Interface Dispatch
// Table. In an interface, it points to the ioffsets table.
union
{
_Jv_IDispatchTable *idt; _Jv_IDispatchTable *idt;
jshort *ioffsets;
};
// Pointer to the class that represents an array of this class. // Pointer to the class that represents an array of this class.
jclass arrayclass; jclass arrayclass;
// Security Domain to which this class belongs (or null). // Security Domain to which this class belongs (or null).
......
...@@ -985,8 +985,8 @@ void * ...@@ -985,8 +985,8 @@ void *
_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx) _Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx)
{ {
_Jv_IDispatchTable *cldt = klass->idt; _Jv_IDispatchTable *cldt = klass->idt;
int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx; int idx = iface->ioffsets[cldt->iindex] + method_idx;
return cldt->cls.itable[idx]; return cldt->itable[idx];
} }
jboolean jboolean
...@@ -1013,16 +1013,15 @@ _Jv_IsAssignableFrom (jclass source, jclass target) ...@@ -1013,16 +1013,15 @@ _Jv_IsAssignableFrom (jclass source, jclass target)
return _Jv_InterfaceAssignableFrom (source, target); return _Jv_InterfaceAssignableFrom (source, target);
_Jv_IDispatchTable *cl_idt = source->idt; _Jv_IDispatchTable *cl_idt = source->idt;
_Jv_IDispatchTable *if_idt = target->idt;
if (__builtin_expect ((if_idt == NULL), false)) if (__builtin_expect ((target->ioffsets == NULL), false))
return false; // No class implementing TARGET has been loaded. return false; // No class implementing TARGET has been loaded.
jshort cl_iindex = cl_idt->cls.iindex; jshort cl_iindex = cl_idt->iindex;
if (cl_iindex < if_idt->iface.ioffsets[0]) if (cl_iindex < target->ioffsets[0])
{ {
jshort offset = if_idt->iface.ioffsets[cl_iindex]; jshort offset = target->ioffsets[cl_iindex];
if (offset != -1 && offset < cl_idt->cls.itable_length if (offset != -1 && offset < cl_idt->itable_length
&& cl_idt->cls.itable[offset] == target) && cl_idt->itable[offset] == target)
return true; return true;
} }
return false; return false;
......
...@@ -552,7 +552,7 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass, ...@@ -552,7 +552,7 @@ _Jv_Linker::search_method_in_class (jclass cls, jclass klass,
#define INITIAL_IOFFSETS_LEN 4 #define INITIAL_IOFFSETS_LEN 4
#define INITIAL_IFACES_LEN 4 #define INITIAL_IFACES_LEN 4
static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} }; static _Jv_IDispatchTable null_idt = {SHRT_MAX, 0, {}};
// Generate tables for constant-time assignment testing and interface // Generate tables for constant-time assignment testing and interface
// method lookup. This implements the technique described by Per Bothner // method lookup. This implements the technique described by Per Bothner
...@@ -611,9 +611,6 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) ...@@ -611,9 +611,6 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass)
return; return;
} }
klass->idt =
(_Jv_IDispatchTable *) _Jv_AllocRawObj (sizeof (_Jv_IDispatchTable));
_Jv_ifaces ifaces; _Jv_ifaces ifaces;
ifaces.count = 0; ifaces.count = 0;
ifaces.len = INITIAL_IFACES_LEN; ifaces.len = INITIAL_IFACES_LEN;
...@@ -625,9 +622,10 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) ...@@ -625,9 +622,10 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass)
{ {
// The classes pointed to by the itable will always be reachable // The classes pointed to by the itable will always be reachable
// via other paths. // via other paths.
klass->idt->cls.itable = int idt_bytes = sizeof (_Jv_IDispatchTable) + (itable_size
(void **) _Jv_AllocBytes (itable_size * sizeof (void *)); * sizeof (void *));
klass->idt->cls.itable_length = itable_size; klass->idt = (_Jv_IDispatchTable *) _Jv_AllocBytes (idt_bytes);
klass->idt->itable_length = itable_size;
jshort *itable_offsets = jshort *itable_offsets =
(jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort)); (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort));
...@@ -639,18 +637,17 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass) ...@@ -639,18 +637,17 @@ _Jv_Linker::prepare_constant_time_tables (jclass klass)
for (int i = 0; i < ifaces.count; i++) for (int i = 0; i < ifaces.count; i++)
{ {
ifaces.list[i]->idt->iface.ioffsets[cls_iindex] = ifaces.list[i]->ioffsets[cls_iindex] = itable_offsets[i];
itable_offsets[i];
} }
klass->idt->cls.iindex = cls_iindex; klass->idt->iindex = cls_iindex;
_Jv_Free (ifaces.list); _Jv_Free (ifaces.list);
_Jv_Free (itable_offsets); _Jv_Free (itable_offsets);
} }
else else
{ {
klass->idt->cls.iindex = SHRT_MAX; klass->idt->iindex = SHRT_MAX;
} }
} }
...@@ -713,7 +710,7 @@ void ...@@ -713,7 +710,7 @@ void
_Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces,
jshort *itable_offsets) jshort *itable_offsets)
{ {
void **itable = klass->idt->cls.itable; void **itable = klass->idt->itable;
jshort itable_pos = 0; jshort itable_pos = 0;
for (int i = 0; i < ifaces->count; i++) for (int i = 0; i < ifaces->count; i++)
...@@ -722,12 +719,9 @@ _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, ...@@ -722,12 +719,9 @@ _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces,
itable_offsets[i] = itable_pos; itable_offsets[i] = itable_pos;
itable_pos = append_partial_itable (klass, iface, itable, itable_pos); itable_pos = append_partial_itable (klass, iface, itable, itable_pos);
/* Create interface dispatch table for iface */ /* Create ioffsets table for iface */
if (iface->idt == NULL) if (iface->ioffsets == NULL)
{ {
iface->idt
= (_Jv_IDispatchTable *) _Jv_AllocRawObj (sizeof (_Jv_IDispatchTable));
// The first element of ioffsets is its length (itself included). // The first element of ioffsets is its length (itself included).
jshort *ioffsets = (jshort *) _Jv_AllocBytes (INITIAL_IOFFSETS_LEN jshort *ioffsets = (jshort *) _Jv_AllocBytes (INITIAL_IOFFSETS_LEN
* sizeof (jshort)); * sizeof (jshort));
...@@ -735,7 +729,7 @@ _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces, ...@@ -735,7 +729,7 @@ _Jv_Linker::generate_itable (jclass klass, _Jv_ifaces *ifaces,
for (int i = 1; i < INITIAL_IOFFSETS_LEN; i++) for (int i = 1; i < INITIAL_IOFFSETS_LEN; i++)
ioffsets[i] = -1; ioffsets[i] = -1;
iface->idt->iface.ioffsets = ioffsets; iface->ioffsets = ioffsets;
} }
} }
} }
...@@ -881,8 +875,8 @@ static bool iindex_mutex_initialized = false; ...@@ -881,8 +875,8 @@ static bool iindex_mutex_initialized = false;
// Interface Dispatch Table, we just compare the first element to see if it // Interface Dispatch Table, we just compare the first element to see if it
// matches the desired interface. So how can we find the correct offset? // matches the desired interface. So how can we find the correct offset?
// Our solution is to keep a vector of candiate offsets in each interface // Our solution is to keep a vector of candiate offsets in each interface
// (idt->iface.ioffsets), and in each class we have an index // (ioffsets), and in each class we have an index (idt->iindex) used to
// (idt->cls.iindex) used to select the correct offset from ioffsets. // select the correct offset from ioffsets.
// //
// Calculate and return iindex for a new class. // Calculate and return iindex for a new class.
// ifaces is a vector of num interfaces that the class implements. // ifaces is a vector of num interfaces that the class implements.
...@@ -913,9 +907,9 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) ...@@ -913,9 +907,9 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num)
{ {
if (j >= num) if (j >= num)
goto found; goto found;
if (i >= ifaces[j]->idt->iface.ioffsets[0]) if (i >= ifaces[j]->ioffsets[0])
continue; continue;
int ioffset = ifaces[j]->idt->iface.ioffsets[i]; int ioffset = ifaces[j]->ioffsets[i];
/* We can potentially share this position with another class. */ /* We can potentially share this position with another class. */
if (ioffset >= 0 && ioffset != offsets[j]) if (ioffset >= 0 && ioffset != offsets[j])
break; /* Nope. Try next i. */ break; /* Nope. Try next i. */
...@@ -924,14 +918,15 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) ...@@ -924,14 +918,15 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num)
found: found:
for (j = 0; j < num; j++) for (j = 0; j < num; j++)
{ {
int len = ifaces[j]->idt->iface.ioffsets[0]; int len = ifaces[j]->ioffsets[0];
if (i >= len) if (i >= len)
{ {
// Resize ioffsets. // Resize ioffsets.
int newlen = 2 * len; int newlen = 2 * len;
if (i >= newlen) if (i >= newlen)
newlen = i + 3; newlen = i + 3;
jshort *old_ioffsets = ifaces[j]->idt->iface.ioffsets;
jshort *old_ioffsets = ifaces[j]->ioffsets;
jshort *new_ioffsets = (jshort *) _Jv_AllocBytes (newlen jshort *new_ioffsets = (jshort *) _Jv_AllocBytes (newlen
* sizeof(jshort)); * sizeof(jshort));
memcpy (&new_ioffsets[1], &old_ioffsets[1], memcpy (&new_ioffsets[1], &old_ioffsets[1],
...@@ -941,9 +936,9 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num) ...@@ -941,9 +936,9 @@ _Jv_Linker::find_iindex (jclass *ifaces, jshort *offsets, jshort num)
while (len < newlen) while (len < newlen)
new_ioffsets[len++] = -1; new_ioffsets[len++] = -1;
ifaces[j]->idt->iface.ioffsets = new_ioffsets; ifaces[j]->ioffsets = new_ioffsets;
} }
ifaces[j]->idt->iface.ioffsets[i] = offsets[j]; ifaces[j]->ioffsets[i] = offsets[j];
} }
_Jv_MutexUnlock (&iindex_mutex); _Jv_MutexUnlock (&iindex_mutex);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment