📄 natclass.cc
字号:
for (; klass; klass = klass->getSuperclass()) { _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature); if (meth) return meth; } return NULL;}// NOTE: MCACHE_SIZE should be a power of 2 minus one.#define MCACHE_SIZE 1023struct _Jv_mcache{ jclass klass; _Jv_Method *method;};static _Jv_mcache method_cache[MCACHE_SIZE + 1];static void *_Jv_FindMethodInCache (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature){ int index = name->hash & MCACHE_SIZE; _Jv_mcache *mc = method_cache + index; _Jv_Method *m = mc->method; if (mc->klass == klass && m != NULL // thread safe check && _Jv_equalUtf8Consts (m->name, name) && _Jv_equalUtf8Consts (m->signature, signature)) return mc->method->ncode; return NULL;}static void_Jv_AddMethodToCache (jclass klass, _Jv_Method *method){ _Jv_MonitorEnter (&java::lang::Class::class$); int index = method->name->hash & MCACHE_SIZE; method_cache[index].method = method; method_cache[index].klass = klass; _Jv_MonitorExit (&java::lang::Class::class$);}void *_Jv_LookupInterfaceMethod (jclass klass, _Jv_Utf8Const *name, _Jv_Utf8Const *signature){ using namespace java::lang::reflect; void *ncode = _Jv_FindMethodInCache (klass, name, signature); if (ncode != 0) return ncode; for (; klass; klass = klass->getSuperclass()) { _Jv_Method *meth = _Jv_GetMethodLocal (klass, name, signature); if (! meth) continue; if (Modifier::isStatic(meth->accflags)) throw new java::lang::IncompatibleClassChangeError (_Jv_GetMethodString (klass, meth->name)); if (Modifier::isAbstract(meth->accflags)) throw new java::lang::AbstractMethodError (_Jv_GetMethodString (klass, meth->name)); if (! Modifier::isPublic(meth->accflags)) throw new java::lang::IllegalAccessError (_Jv_GetMethodString (klass, meth->name)); _Jv_AddMethodToCache (klass, meth); return meth->ncode; } throw new java::lang::IncompatibleClassChangeError;}// Fast interface method lookup by index.void *_Jv_LookupInterfaceMethodIdx (jclass klass, jclass iface, int method_idx){ _Jv_IDispatchTable *cldt = klass->idt; int idx = iface->idt->iface.ioffsets[cldt->cls.iindex] + method_idx; return cldt->cls.itable[idx];}jboolean_Jv_IsAssignableFrom (jclass target, jclass source){ if (source == target) return true; // If target is array, so must source be. while (target->isArray ()) { if (! source->isArray()) return false; target = target->getComponentType(); source = source->getComponentType(); } if (target->isInterface()) { // Abstract classes have no IDT, and IDTs provide no way to check // two interfaces for assignability. if (__builtin_expect (source->idt == NULL || source->isInterface(), false)) return _Jv_InterfaceAssignableFrom (target, source); _Jv_IDispatchTable *cl_idt = source->idt; _Jv_IDispatchTable *if_idt = target->idt; if (__builtin_expect ((if_idt == NULL), false)) return false; // No class implementing TARGET has been loaded. jshort cl_iindex = cl_idt->cls.iindex; if (cl_iindex < if_idt->iface.ioffsets[0]) { jshort offset = if_idt->iface.ioffsets[cl_iindex]; if (offset != -1 && offset < cl_idt->cls.itable_length && cl_idt->cls.itable[offset] == target) return true; } return false; } // Primitive TYPE classes are only assignable to themselves. if (__builtin_expect (target->isPrimitive() || source->isPrimitive(), false)) return false; if (target == &java::lang::Object::class$) return true; else if (source->ancestors == NULL || target->ancestors == NULL) { // We need this case when either SOURCE or TARGET has not has // its constant-time tables prepared. // At this point we know that TARGET can't be Object, so it is // safe to use that as the termination point. while (source && source != &java::lang::Object::class$) { if (source == target) return true; source = source->getSuperclass(); } } else if (source->depth >= target->depth && source->ancestors[source->depth - target->depth] == target) return true; return false;}// Interface type checking, the slow way. Returns TRUE if IFACE is a // superinterface of SOURCE. This is used when SOURCE is also an interface,// or a class with no interface dispatch table.jboolean_Jv_InterfaceAssignableFrom (jclass iface, jclass source){ for (int i = 0; i < source->interface_count; i++) { jclass interface = source->interfaces[i]; if (iface == interface || _Jv_InterfaceAssignableFrom (iface, interface)) return true; } if (!source->isInterface() && source->superclass && _Jv_InterfaceAssignableFrom (iface, source->superclass)) return true; return false;}jboolean_Jv_IsInstanceOf(jobject obj, jclass cl){ if (__builtin_expect (!obj, false)) return false; return (_Jv_IsAssignableFrom (cl, JV_CLASS (obj)));}void *_Jv_CheckCast (jclass c, jobject obj){ if (__builtin_expect (obj != NULL && ! _Jv_IsAssignableFrom(c, JV_CLASS (obj)), false)) throw new java::lang::ClassCastException ((new java::lang::StringBuffer (obj->getClass()->getName()))->append (JvNewStringUTF(" cannot be cast to "))->append (c->getName())->toString()); return obj;}void_Jv_CheckArrayStore (jobject arr, jobject obj){ if (obj) { JvAssert (arr != NULL); jclass elt_class = (JV_CLASS (arr))->getComponentType(); if (elt_class == &java::lang::Object::class$) return; jclass obj_class = JV_CLASS (obj); if (__builtin_expect (! _Jv_IsAssignableFrom (elt_class, obj_class), false)) throw new java::lang::ArrayStoreException ((new java::lang::StringBuffer (JvNewStringUTF("Cannot store ")))->append (obj_class->getName())->append (JvNewStringUTF(" in array of type "))->append (elt_class->getName())->toString()); }}#define INITIAL_IOFFSETS_LEN 4#define INITIAL_IFACES_LEN 4static _Jv_IDispatchTable null_idt = { {SHRT_MAX, 0, NULL} };// Generate tables for constant-time assignment testing and interface// method lookup. This implements the technique described by Per Bothner// <per@bothner.com> on the java-discuss mailing list on 1999-09-02:// http://gcc.gnu.org/ml/java/1999-q3/msg00377.htmlvoid _Jv_PrepareConstantTimeTables (jclass klass){ if (klass->isPrimitive () || klass->isInterface ()) return; // Short-circuit in case we've been called already. if ((klass->idt != NULL) || klass->depth != 0) return; // Calculate the class depth and ancestor table. The depth of a class // is how many "extends" it is removed from Object. Thus the depth of // java.lang.Object is 0, but the depth of java.io.FilterOutputStream // is 2. Depth is defined for all regular and array classes, but not // interfaces or primitive types. jclass klass0 = klass; jboolean has_interfaces = 0; while (klass0 != &java::lang::Object::class$) { has_interfaces += klass0->interface_count; klass0 = klass0->superclass; klass->depth++; } // We do class member testing in constant time by using a small table // of all the ancestor classes within each class. The first element is // a pointer to the current class, and the rest are pointers to the // classes ancestors, ordered from the current class down by decreasing // depth. We do not include java.lang.Object in the table of ancestors, // since it is redundant. klass->ancestors = (jclass *) _Jv_Malloc (klass->depth * sizeof (jclass)); klass0 = klass; for (int index = 0; index < klass->depth; index++) { klass->ancestors[index] = klass0; klass0 = klass0->superclass; } if (java::lang::reflect::Modifier::isAbstract (klass->accflags)) return; // Optimization: If class implements no interfaces, use a common // predefined interface table. if (!has_interfaces) { klass->idt = &null_idt; return; } klass->idt = (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); _Jv_ifaces ifaces; ifaces.count = 0; ifaces.len = INITIAL_IFACES_LEN; ifaces.list = (jclass *) _Jv_Malloc (ifaces.len * sizeof (jclass *)); int itable_size = _Jv_GetInterfaces (klass, &ifaces); if (ifaces.count > 0) { klass->idt->cls.itable = (void **) _Jv_Malloc (itable_size * sizeof (void *)); klass->idt->cls.itable_length = itable_size; jshort *itable_offsets = (jshort *) _Jv_Malloc (ifaces.count * sizeof (jshort)); _Jv_GenerateITable (klass, &ifaces, itable_offsets); jshort cls_iindex = _Jv_FindIIndex (ifaces.list, itable_offsets, ifaces.count); for (int i=0; i < ifaces.count; i++) { ifaces.list[i]->idt->iface.ioffsets[cls_iindex] = itable_offsets[i]; } klass->idt->cls.iindex = cls_iindex; _Jv_Free (ifaces.list); _Jv_Free (itable_offsets); } else { klass->idt->cls.iindex = SHRT_MAX; }}// Return index of item in list, or -1 if item is not present.inline jshort_Jv_IndexOf (void *item, void **list, jshort list_len){ for (int i=0; i < list_len; i++) { if (list[i] == item) return i; } return -1;}// Find all unique interfaces directly or indirectly implemented by klass.// Returns the size of the interface dispatch table (itable) for klass, which // is the number of unique interfaces plus the total number of methods that // those interfaces declare. May extend ifaces if required.jshort_Jv_GetInterfaces (jclass klass, _Jv_ifaces *ifaces){ jshort result = 0; for (int i=0; i < klass->interface_count; i++) { jclass iface = klass->interfaces[i]; if (_Jv_IndexOf (iface, (void **) ifaces->list, ifaces->count) == -1) { if (ifaces->count + 1 >= ifaces->len) { /* Resize ifaces list */ ifaces->len = ifaces->len * 2; ifaces->list = (jclass *) _Jv_Realloc (ifaces->list, ifaces->len * sizeof(jclass)); } ifaces->list[ifaces->count] = iface; ifaces->count++; result += _Jv_GetInterfaces (klass->interfaces[i], ifaces); } } if (klass->isInterface()) { result += klass->method_count + 1; } else { if (klass->superclass) { result += _Jv_GetInterfaces (klass->superclass, ifaces); } } return result;}// Fill out itable in klass, resolving method declarations in each ifaces.// itable_offsets is filled out with the position of each iface in itable,// such that itable[itable_offsets[n]] == ifaces.list[n].void_Jv_GenerateITable (jclass klass, _Jv_ifaces *ifaces, jshort *itable_offsets){ void **itable = klass->idt->cls.itable; jshort itable_pos = 0; for (int i=0; i < ifaces->count; i++) { jclass iface = ifaces->list[i]; itable_offsets[i] = itable_pos; itable_pos = _Jv_AppendPartialITable (klass, iface, itable, itable_pos); /* Create interface dispatch table for iface */ if (iface->idt == NULL) { iface->idt = (_Jv_IDispatchTable *) _Jv_Malloc (sizeof (_Jv_IDispatchTable)); // The first element of ioffsets is its length (itself included). jshort *ioffsets = (jshort *) _Jv_Malloc (INITIAL_IOFFSETS_LEN * sizeof (jshort)); ioffsets[0] = INITIAL_IOFFSETS_LEN; for (int i=1; i < INITIAL_IOFFSETS_LEN; i++) ioffsets[i] = -1; iface->idt->iface.ioffsets = ioffsets; } }}// Format method name for use in error messages.jstring_Jv_GetMethodString (jclass klass, _Jv_Utf8Const *name){ jstring r = JvNewStringUTF (klass->name->data); r = r->concat (JvNewStringUTF (".")); r = r->concat (JvNewStringUTF (name->data)); return r;}void _Jv_ThrowNoSuchMethodError (){ throw new java::lang::NoSuchMethodError;}// Each superinterface of a class (i.e. each interface that the class// directly or indirectly implements) has a corresponding "Partial
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -