diff --git a/boehm-gc/ChangeLog b/boehm-gc/ChangeLog index 1b5c92d878b..50a0802d9d8 100644 --- a/boehm-gc/ChangeLog +++ b/boehm-gc/ChangeLog @@ -1,3 +1,11 @@ +2014-05-13 Bernd Edlinger + + Fix current cygwin-64 build problems. + * include/gc_config_macros.h (GC_PTHREADS): Use __CYGWIN__ instead + of __CYGWIN32__ here. + * win32_threads.c (GC_push_all_stacks): Push all X86_64 registers. + (GC_get_thread_stack_base): Get the stack base for X86_64. + 2014-04-22 Jakub Jelinek PR other/43620 diff --git a/boehm-gc/include/gc_config_macros.h b/boehm-gc/include/gc_config_macros.h index fd3006c1789..a01da4a1342 100644 --- a/boehm-gc/include/gc_config_macros.h +++ b/boehm-gc/include/gc_config_macros.h @@ -23,7 +23,7 @@ defined(GC_HPUX_THREADS) || defined(GC_OSF1_THREADS) || \ defined(GC_DGUX386_THREADS) || defined(GC_DARWIN_THREADS) || \ defined(GC_AIX_THREADS) || \ - (defined(GC_WIN32_THREADS) && defined(__CYGWIN32__)) + (defined(GC_WIN32_THREADS) && defined(__CYGWIN__)) # define GC_PTHREADS # endif diff --git a/boehm-gc/win32_threads.c b/boehm-gc/win32_threads.c index ffb34e0a8b1..2de1c6953b8 100644 --- a/boehm-gc/win32_threads.c +++ b/boehm-gc/win32_threads.c @@ -365,7 +365,11 @@ void GC_push_all_stacks() # define PUSH1(reg) GC_push_one((word)context.reg) # define PUSH2(r1,r2) PUSH1(r1), PUSH1(r2) # define PUSH4(r1,r2,r3,r4) PUSH2(r1,r2), PUSH2(r3,r4) -# if defined(I386) +# if defined(__x86_64__) + PUSH4(Rdi,Rsi,Rbx,Rdx), PUSH2(Rcx,Rax), PUSH1(Rbp); + PUSH4(R8,R9,R10,R11), PUSH4(R12,R13,R14,R15); + sp = (ptr_t)context.Rsp; +# elif defined(I386) PUSH4(Edi,Esi,Ebx,Edx), PUSH2(Ecx,Eax), PUSH1(Ebp); sp = (ptr_t)context.Esp; # elif defined(ARM32) @@ -755,8 +759,12 @@ int GC_pthread_detach(pthread_t thread) GC_PTR GC_get_thread_stack_base() { +#ifdef __x86_64__ + return ((NT_TIB*)NtCurrentTeb())->StackBase; +#else extern GC_PTR _tlsbase __asm__ ("%fs:4"); return _tlsbase; +#endif } #else /* !CYGWIN32 */ diff --git a/libffi/ChangeLog b/libffi/ChangeLog index 75bfd8036a0..9ca95562fbd 100644 --- a/libffi/ChangeLog +++ b/libffi/ChangeLog @@ -1,3 +1,12 @@ +2014-05-13 Bernd Edlinger + + Fix current cygwin-64 build problems. + * src/java_raw_api.c: Remove if !defined(FFI_NO_RAW_API). + * src/x86/ffi.c: Add if defined(__CYGWIN__). + * src/x86/win64.S (ffi_closure_win64, ffi_call_win64): Added + handling for FFI_TYPE_UINT64, FFI_TYPE_POINTER and FFI_TYPE_INT. + Added SEH information. Fixed formatting. + 2014-04-22 Jakub Jelinek PR other/43620 diff --git a/libffi/src/java_raw_api.c b/libffi/src/java_raw_api.c index 522c8bfd67e..d8e79ea1d45 100644 --- a/libffi/src/java_raw_api.c +++ b/libffi/src/java_raw_api.c @@ -39,7 +39,7 @@ #include #include -#if !defined(NO_JAVA_RAW_API) && !defined(FFI_NO_RAW_API) +#if !defined(NO_JAVA_RAW_API) size_t ffi_java_raw_size (ffi_cif *cif) @@ -353,4 +353,4 @@ ffi_prep_java_raw_closure (ffi_java_raw_closure* cl, #endif /* FFI_CLOSURES */ #endif /* !FFI_NATIVE_RAW_API */ -#endif /* !FFI_NO_RAW_API */ +#endif /* !NO_JAVA_RAW_API */ diff --git a/libffi/src/x86/ffi.c b/libffi/src/x86/ffi.c index 611e2219716..6338de2a0f2 100644 --- a/libffi/src/x86/ffi.c +++ b/libffi/src/x86/ffi.c @@ -28,7 +28,7 @@ DEALINGS IN THE SOFTWARE. ----------------------------------------------------------------------- */ -#if !defined(__x86_64__) || defined(_WIN64) +#if !defined(__x86_64__) || defined(_WIN64) || defined(__CYGWIN__) #ifdef _WIN64 #include diff --git a/libffi/src/x86/win64.S b/libffi/src/x86/win64.S index 1394cf177b6..687f97c451d 100644 --- a/libffi/src/x86/win64.S +++ b/libffi/src/x86/win64.S @@ -1,8 +1,8 @@ #define LIBFFI_ASM #include #include - -/* Constants for ffi_call_win64 */ + +/* Constants for ffi_call_win64 */ #define STACK 0 #define PREP_ARGS_FN 32 #define ECIF 40 @@ -12,8 +12,8 @@ #define FN 72 /* ffi_call_win64 (void (*prep_args_fn)(char *, extended_cif *), - extended_cif *ecif, unsigned bytes, unsigned flags, - unsigned *rvalue, void (*fn)()); + extended_cif *ecif, unsigned bytes, unsigned flags, + unsigned *rvalue, void (*fn)()); */ #ifdef _MSC_VER @@ -31,11 +31,11 @@ _TEXT SEGMENT ;;; ;;; It must move the parameters passed in registers to their stack location, ;;; call ffi_closure_win64_inner for the actual work, then return the result. -;;; +;;; ffi_closure_win64 PROC FRAME ;; copy register arguments onto stack test r11, 1 - jne first_is_float + jne first_is_float mov QWORD PTR [rsp+8], rcx jmp second first_is_float: @@ -43,7 +43,7 @@ first_is_float: second: test r11, 2 - jne second_is_float + jne second_is_float mov QWORD PTR [rsp+16], rdx jmp third second_is_float: @@ -51,7 +51,7 @@ second_is_float: third: test r11, 4 - jne third_is_float + jne third_is_float mov QWORD PTR [rsp+24], r8 jmp fourth third_is_float: @@ -59,16 +59,16 @@ third_is_float: fourth: test r11, 8 - jne fourth_is_float + jne fourth_is_float mov QWORD PTR [rsp+32], r9 jmp done fourth_is_float: movlpd QWORD PTR [rsp+32], xmm3 done: - .ALLOCSTACK 40 + .ALLOCSTACK 40 sub rsp, 40 - .ENDPROLOG + .ENDPROLOG mov rcx, rax ; context is first parameter mov rdx, rsp ; stack is second parameter add rdx, 48 ; point to start of arguments @@ -76,23 +76,23 @@ done: call rax ; call the real closure function add rsp, 40 movd xmm0, rax ; If the closure returned a float, - ; ffi_closure_win64_inner wrote it to rax + ; ffi_closure_win64_inner wrote it to rax ret 0 ffi_closure_win64 ENDP ffi_call_win64 PROC FRAME - ;; copy registers onto stack + ;; copy registers onto stack mov QWORD PTR [rsp+32], r9 mov QWORD PTR [rsp+24], r8 mov QWORD PTR [rsp+16], rdx mov QWORD PTR [rsp+8], rcx - .PUSHREG rbp + .PUSHREG rbp push rbp - .ALLOCSTACK 48 + .ALLOCSTACK 48 sub rsp, 48 ; 00000030H - .SETFRAME rbp, 32 + .SETFRAME rbp, 32 lea rbp, QWORD PTR [rsp+32] - .ENDPROLOG + .ENDPROLOG mov eax, DWORD PTR CIF_BYTES[rbp] add rax, 15 @@ -209,20 +209,45 @@ ret_float$: ret_double$: cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_DOUBLE - jne SHORT ret_sint64$ + jne SHORT ret_uint64$ mov rax, QWORD PTR RVALUE[rbp] movlpd QWORD PTR [rax], xmm0 jmp SHORT ret_void$ -ret_sint64$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 - jne ret_void$ +ret_uint64$: + cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT64 + jne SHORT ret_sint64$ mov rcx, QWORD PTR RVALUE[rbp] mov QWORD PTR [rcx], rax jmp SHORT ret_void$ - + +ret_sint64$: + cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT64 + jne SHORT ret_pointer$ + + mov rcx, QWORD PTR RVALUE[rbp] + mov QWORD PTR [rcx], rax + jmp SHORT ret_void$ + +ret_pointer$: + cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_POINTER + jne SHORT ret_int$ + + mov rcx, QWORD PTR RVALUE[rbp] + mov QWORD PTR [rcx], rax + jmp SHORT ret_void$ + +ret_int$: + cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_INT + jne SHORT ret_void$ + + mov rcx, QWORD PTR RVALUE[rbp] + cdqe + mov QWORD PTR [rcx], rax + jmp SHORT ret_void$ + ret_void$: xor rax, rax @@ -252,13 +277,14 @@ END # # It must move the parameters passed in registers to their stack location, # call ffi_closure_win64_inner for the actual work, then return the result. -# +# .balign 16 - .globl SYMBOL_NAME(ffi_closure_win64) + .globl SYMBOL_NAME(ffi_closure_win64) + .seh_proc SYMBOL_NAME(ffi_closure_win64) SYMBOL_NAME(ffi_closure_win64): # copy register arguments onto stack test $1,%r11 - jne .Lfirst_is_float + jne .Lfirst_is_float mov %rcx, 8(%rsp) jmp .Lsecond .Lfirst_is_float: @@ -266,7 +292,7 @@ SYMBOL_NAME(ffi_closure_win64): .Lsecond: test $2, %r11 - jne .Lsecond_is_float + jne .Lsecond_is_float mov %rdx, 16(%rsp) jmp .Lthird .Lsecond_is_float: @@ -274,7 +300,7 @@ SYMBOL_NAME(ffi_closure_win64): .Lthird: test $4, %r11 - jne .Lthird_is_float + jne .Lthird_is_float mov %r8,24(%rsp) jmp .Lfourth .Lthird_is_float: @@ -282,16 +308,16 @@ SYMBOL_NAME(ffi_closure_win64): .Lfourth: test $8, %r11 - jne .Lfourth_is_float + jne .Lfourth_is_float mov %r9, 32(%rsp) jmp .Ldone .Lfourth_is_float: movlpd %xmm3, 32(%rsp) .Ldone: -#.ALLOCSTACK 40 + .seh_stackalloc 40 sub $40, %rsp -#.ENDPROLOG + .seh_endprologue mov %rax, %rcx # context is first parameter mov %rsp, %rdx # stack is second parameter add $48, %rdx # point to start of arguments @@ -299,25 +325,26 @@ SYMBOL_NAME(ffi_closure_win64): callq *%rax # call the real closure function add $40, %rsp movq %rax, %xmm0 # If the closure returned a float, - # ffi_closure_win64_inner wrote it to rax + # ffi_closure_win64_inner wrote it to rax retq -.ffi_closure_win64_end: + .seh_endproc .balign 16 - .globl SYMBOL_NAME(ffi_call_win64) + .globl SYMBOL_NAME(ffi_call_win64) + .seh_proc SYMBOL_NAME(ffi_call_win64) SYMBOL_NAME(ffi_call_win64): - # copy registers onto stack + # copy registers onto stack mov %r9,32(%rsp) mov %r8,24(%rsp) mov %rdx,16(%rsp) mov %rcx,8(%rsp) - #.PUSHREG rbp + .seh_pushreg rbp push %rbp - #.ALLOCSTACK 48 + .seh_stackalloc 48 sub $48,%rsp - #.SETFRAME rbp, 32 + .seh_setframe rbp, 32 lea 32(%rsp),%rbp - #.ENDPROLOG + .seh_endprologue mov CIF_BYTES(%rbp),%eax add $15, %rax @@ -366,15 +393,15 @@ Lch_done: .Lret_struct2b: cmpl $FFI_TYPE_SMALL_STRUCT_2B, CIF_FLAGS(%rbp) jne .Lret_struct1b - + mov RVALUE(%rbp), %rcx mov %ax, (%rcx) jmp .Lret_void - + .Lret_struct1b: cmpl $FFI_TYPE_SMALL_STRUCT_1B, CIF_FLAGS(%rbp) jne .Lret_uint8 - + mov RVALUE(%rbp), %rcx mov %al, (%rcx) jmp .Lret_void @@ -382,45 +409,45 @@ Lch_done: .Lret_uint8: cmpl $FFI_TYPE_UINT8, CIF_FLAGS(%rbp) jne .Lret_sint8 - - mov RVALUE(%rbp), %rcx - movzbq %al, %rax + + mov RVALUE(%rbp), %rcx + movzbq %al, %rax movq %rax, (%rcx) jmp .Lret_void .Lret_sint8: cmpl $FFI_TYPE_SINT8, CIF_FLAGS(%rbp) jne .Lret_uint16 - - mov RVALUE(%rbp), %rcx - movsbq %al, %rax + + mov RVALUE(%rbp), %rcx + movsbq %al, %rax movq %rax, (%rcx) jmp .Lret_void .Lret_uint16: cmpl $FFI_TYPE_UINT16, CIF_FLAGS(%rbp) jne .Lret_sint16 - - mov RVALUE(%rbp), %rcx - movzwq %ax, %rax + + mov RVALUE(%rbp), %rcx + movzwq %ax, %rax movq %rax, (%rcx) jmp .Lret_void .Lret_sint16: cmpl $FFI_TYPE_SINT16, CIF_FLAGS(%rbp) jne .Lret_uint32 - - mov RVALUE(%rbp), %rcx - movswq %ax, %rax + + mov RVALUE(%rbp), %rcx + movswq %ax, %rax movq %rax, (%rcx) jmp .Lret_void .Lret_uint32: cmpl $FFI_TYPE_UINT32, CIF_FLAGS(%rbp) jne .Lret_sint32 - - mov RVALUE(%rbp), %rcx - movl %eax, %eax + + mov RVALUE(%rbp), %rcx + movl %eax, %eax movq %rax, (%rcx) jmp .Lret_void @@ -443,26 +470,51 @@ Lch_done: .Lret_double: cmpl $FFI_TYPE_DOUBLE, CIF_FLAGS(%rbp) - jne .Lret_sint64 + jne .Lret_uint64 mov RVALUE(%rbp), %rax movlpd %xmm0, (%rax) jmp .Lret_void -.Lret_sint64: - cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp) - jne .Lret_void +.Lret_uint64: + cmpl $FFI_TYPE_UINT64, CIF_FLAGS(%rbp) + jne .Lret_sint64 mov RVALUE(%rbp), %rcx mov %rax, (%rcx) jmp .Lret_void - + +.Lret_sint64: + cmpl $FFI_TYPE_SINT64, CIF_FLAGS(%rbp) + jne .Lret_pointer + + mov RVALUE(%rbp), %rcx + mov %rax, (%rcx) + jmp .Lret_void + +.Lret_pointer: + cmpl $FFI_TYPE_POINTER, CIF_FLAGS(%rbp) + jne .Lret_int + + mov RVALUE(%rbp), %rcx + mov %rax, (%rcx) + jmp .Lret_void + +.Lret_int: + cmpl $FFI_TYPE_INT, CIF_FLAGS(%rbp) + jne .Lret_void + + mov RVALUE(%rbp), %rcx + cltq + movq %rax, (%rcx) + jmp .Lret_void + .Lret_void: xor %rax, %rax lea 16(%rbp), %rsp pop %rbp retq -.ffi_call_win64_end: + .seh_endproc #endif /* !_MSC_VER */ diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index dd908743091..13036945556 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,8 @@ +2014-05-13 Bernd Edlinger + + * unwind-seh.c (_Unwind_Backtrace): Uncommented, finished + implementation. + 2014-05-12 Georg-Johann Lay * config/arm/bpabi-lib.h (License): Add GCC Runtime Library Exception. diff --git a/libgcc/unwind-seh.c b/libgcc/unwind-seh.c index b4a3ca1e34b..c8187b37a16 100644 --- a/libgcc/unwind-seh.c +++ b/libgcc/unwind-seh.c @@ -431,43 +431,40 @@ _Unwind_DeleteException (struct _Unwind_Exception *exc) /* Perform stack backtrace through unwind data. */ _Unwind_Reason_Code -_Unwind_Backtrace(_Unwind_Trace_Fn trace ATTRIBUTE_UNUSED, - void *trace_argument ATTRIBUTE_UNUSED) +_Unwind_Backtrace(_Unwind_Trace_Fn trace, + void *trace_argument) { -#if 0 UNWIND_HISTORY_TABLE ms_history; CONTEXT ms_context; struct _Unwind_Context gcc_context; + DISPATCHER_CONTEXT disp_context; memset (&ms_history, 0, sizeof(ms_history)); memset (&gcc_context, 0, sizeof(gcc_context)); + memset (&disp_context, 0, sizeof(disp_context)); ms_context.ContextFlags = CONTEXT_ALL; RtlCaptureContext (&ms_context); - gcc_context.disp.ContextRecord = &ms_context; - gcc_context.disp.HistoryTable = &ms_history; + gcc_context.disp = &disp_context; + gcc_context.disp->ContextRecord = &ms_context; + gcc_context.disp->HistoryTable = &ms_history; while (1) { - gcc_context.disp.ControlPc = ms_context.Rip; - gcc_context.disp.FunctionEntry - = RtlLookupFunctionEntry (ms_context.Rip, &gcc_context.disp.ImageBase, + gcc_context.disp->ControlPc = ms_context.Rip; + gcc_context.disp->FunctionEntry + = RtlLookupFunctionEntry (ms_context.Rip, &gcc_context.disp->ImageBase, &ms_history); - if (gcc_context.disp.FunctionEntry) - { - gcc_context.disp.LanguageHandler - = RtlVirtualUnwind (0, gcc_context.disp.ImageBase, ms_context.Rip, - gcc_context.disp.FunctionEntry, &ms_context, - &gcc_context.disp.HandlerData, - &gcc_context.disp.EstablisherFrame, NULL); - } - else - { - ms_context.Rip = *(ULONG_PTR *)ms_context.Rsp; - ms_context.Rsp += 8; - } + if (!gcc_context.disp->FunctionEntry) + return _URC_END_OF_STACK; + + gcc_context.disp->LanguageHandler + = RtlVirtualUnwind (0, gcc_context.disp->ImageBase, ms_context.Rip, + gcc_context.disp->FunctionEntry, &ms_context, + &gcc_context.disp->HandlerData, + &gcc_context.disp->EstablisherFrame, NULL); /* Call trace function. */ if (trace (&gcc_context, trace_argument) != _URC_NO_REASON) @@ -477,8 +474,5 @@ _Unwind_Backtrace(_Unwind_Trace_Fn trace ATTRIBUTE_UNUSED, if (ms_context.Rip == 0) return _URC_END_OF_STACK; } -#else - return _URC_END_OF_STACK; -#endif } #endif /* __SEH__ && !defined (__USING_SJLJ_EXCEPTIONS__) */ diff --git a/libjava/ChangeLog b/libjava/ChangeLog index 661bb7a30c1..0bedfed271d 100644 --- a/libjava/ChangeLog +++ b/libjava/ChangeLog @@ -1,3 +1,12 @@ +2014-05-13 Bernd Edlinger + + Fix current cygwin-64 build problems. + * configure.host: Added handling for x86_64-*-cygwin/mingw. + * boehm.cc (_Jv_GCAttachThread, _Jv_GCDetachThread): Don't compile if + GC_WIN32_THREADS is defined. + * java/lang/natClass.cc (_Jv_InterfaceAssignableFrom): Rename interface + to source_interface. + 2014-04-22 Rainer Orth * configure.ac (THREADLIBS, THREADSPEC): Remove *-*-solaris2.9 diff --git a/libjava/boehm.cc b/libjava/boehm.cc index 855d23cb024..043fd0030ca 100644 --- a/libjava/boehm.cc +++ b/libjava/boehm.cc @@ -747,7 +747,8 @@ _Jv_GCAttachThread () // The registration interface is only defined on posixy systems and // only actually works if pthread_getattr_np is defined. // FIXME: until gc7 it is simpler to disable this on solaris. -#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) +#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) \ + && !defined(GC_WIN32_THREADS) GC_register_my_thread (); #endif } @@ -755,7 +756,8 @@ _Jv_GCAttachThread () void _Jv_GCDetachThread () { -#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) +#if defined(HAVE_PTHREAD_GETATTR_NP) && !defined(GC_SOLARIS_THREADS) \ + && !defined(GC_WIN32_THREADS) GC_unregister_my_thread (); #endif } diff --git a/libjava/classpath/ChangeLog b/libjava/classpath/ChangeLog index 4d9f1a6e49c..4389fc05507 100644 --- a/libjava/classpath/ChangeLog +++ b/libjava/classpath/ChangeLog @@ -1,3 +1,9 @@ +2014-05-13 Bernd Edlinger + + Fix current cygwin-64 build problems. + * native/fdlibm/mprec.c (_REENT_CHECK_MP, _REENT_MP_FREELIST, + _REENT_MP_P5S, __ULong, __Long): Undefine previous definitions. + 2013-09-20 Alan Modra * configure: Regenerate. diff --git a/libjava/classpath/native/fdlibm/mprec.c b/libjava/classpath/native/fdlibm/mprec.c index 8a7cdc03968..460c301054d 100644 --- a/libjava/classpath/native/fdlibm/mprec.c +++ b/libjava/classpath/native/fdlibm/mprec.c @@ -93,12 +93,17 @@ #define _reent _Jv_reent #define _Bigint _Jv_Bigint +#undef _REENT_CHECK_MP #define _REENT_CHECK_MP(x) +#undef _REENT_MP_FREELIST #define _REENT_MP_FREELIST(x) ((x)->_freelist) +#undef _REENT_MP_P5S #define _REENT_MP_P5S(x) ((x)->_p5s) -typedef unsigned long __ULong; -typedef long __Long; +#undef __ULong +#define __ULong unsigned long +#undef __Long +#define __Long long static void * mprec_calloc (void *ignore, size_t x1, size_t x2) diff --git a/libjava/configure.host b/libjava/configure.host index f2d1bb5ed3b..c6f359c5492 100644 --- a/libjava/configure.host +++ b/libjava/configure.host @@ -365,6 +365,13 @@ EOF esac case "${host}" in + x86_64-*-cygwin* | x86_64-*-mingw*) + # Win32 DLLs are limited to 64k exported symbols each. + enable_libgcj_sublibs_default=yes + libgcj_sublib_ltflags='$(lt_host_flags) \ + -Wl,-u,_ZN3org4ietf4jgss10GSSManagerC1Ev,-L..,-lgcj-noncore-dummy' + libgcj_sublib_core_extra_deps=libgcj-noncore-dummy.dll.a + ;; *-cygwin* | *-mingw*) fallback_backtrace_h=sysdep/i386/backtrace.h # We need a frame pointer on Windows, so override BACKTRACESPEC diff --git a/libjava/java/lang/natClass.cc b/libjava/java/lang/natClass.cc index b5ad91f2252..00766d0b102 100644 --- a/libjava/java/lang/natClass.cc +++ b/libjava/java/lang/natClass.cc @@ -1870,9 +1870,9 @@ _Jv_InterfaceAssignableFrom (jclass source, jclass iface) { for (int i = 0; i < source->interface_count; i++) { - jclass interface = source->interfaces[i]; - if (iface == interface - || _Jv_InterfaceAssignableFrom (interface, iface)) + jclass source_interface = source->interfaces[i]; + if (iface == source_interface + || _Jv_InterfaceAssignableFrom (source_interface, iface)) return true; }