Commit 18fa3240 by Alexandre Oliva Committed by Alexandre Oliva

ffi.h.in (ffi_closure_alloc, [...]): New.

libffi/ChangeLog:
* include/ffi.h.in (ffi_closure_alloc, ffi_closure_free): New.
(ffi_prep_closure_loc): New.
(ffi_prep_raw_closure_loc): New.
(ffi_prep_java_raw_closure_loc): New.
* src/closures.c: New file.
* src/dlmalloc.c [FFI_MMAP_EXEC_WRIT] (struct malloc_segment):
Replace sflags with exec_offset.
[FFI_MMAP_EXEC_WRIT] (mmap_exec_offset, add_segment_exec_offset,
sub_segment_exec_offset): New macros.
(get_segment_flags, set_segment_flags, check_segment_merge): New
macros.
(is_mmapped_segment, is_extern_segment): Use get_segment_flags.
(add_segment, sys_alloc, create_mspace, create_mspace_with_base,
destroy_mspace): Use new macros.
(sys_alloc): Silence warning.
* Makefile.am (libffi_la_SOURCES): Add src/closures.c.
* Makefile.in: Rebuilt.
* src/prep_cif [FFI_CLOSURES] (ffi_prep_closure): Implement in
terms of ffi_prep_closure_loc.
* src/raw_api.c (ffi_prep_raw_closure_loc): Renamed and adjusted
from...
(ffi_prep_raw_closure): ... this.  Re-implement in terms of the
renamed version.
* src/java_raw_api (ffi_prep_java_raw_closure_loc): Renamed and
adjusted from...
(ffi_prep_java_raw_closure): ... this.  Re-implement in terms of
the renamed version.
* src/alpha/ffi.c (ffi_prep_closure_loc): Renamed from
(ffi_prep_closure): ... this.
* src/pa/ffi.c: Likewise.
* src/cris/ffi.c: Likewise.  Adjust.
* src/frv/ffi.c: Likewise.
* src/ia64/ffi.c: Likewise.
* src/mips/ffi.c: Likewise.
* src/powerpc/ffi_darwin.c: Likewise.
* src/s390/ffi.c: Likewise.
* src/sh/ffi.c: Likewise.
* src/sh64/ffi.c: Likewise.
* src/sparc/ffi.c: Likewise.
* src/x86/ffi64.c: Likewise.
* src/x86/ffi.c: Likewise.
(FFI_INIT_TRAMPOLINE): Adjust.
(ffi_prep_raw_closure_loc): Renamed and adjusted from...
(ffi_prep_raw_closure): ... this.
* src/powerpc/ffi.c (ffi_prep_closure_loc): Renamed from
(ffi_prep_closure): ... this.
(flush_icache): Adjust.
boehm-gc/ChangeLog:
* include/gc.h (GC_REGISTER_FINALIZER_UNREACHABLE): New.
(GC_register_finalizer_unreachable): Declare.
(GC_debug_register_finalizer_unreachable): Declare.
* finalize.c (GC_unreachable_finalize_mark_proc): New.
(GC_register_finalizer_unreachable): New.
(GC_finalize): Handle it.
* dbg_mlc.c (GC_debug_register_finalizer_unreachable): New.
(GC_debug_register_finalizer_no_order): Fix whitespace.
libjava/ChangeLog:
* include/jvm.h (_Jv_ClosureListFinalizer): New.
(_Jv_Linker::create_error_method): Adjust.
* boehm.cc (_Jv_ClosureListFinalizer): New.
* nogc.cc (_Jv_ClosureListFinalizer): New.
* java/lang/Class.h (class _Jv_ClosureList): New.
(class java::lang::Class): Declare it as friend.
* java/lang/natClass.cc (_Jv_ClosureList::releaseClosures): New.
(_Jv_ClosureList::registerClousure): New.
* include/execution.h (_Jv_ExecutionEngine): Add get_closure_list.
(_Jv_CompiledEngine::do_get_closure_list): New.
(_Jv_CompiledEngine::_Jv_CompiledEngine): Use it.
(_Jv_IndirectCompiledClass): Add closures.
(_Jv_IndirectCompiledEngine::get_aux_info): New.
(_Jv_IndirectCompiledEngine::do_allocate_field_initializers): Use
it.
(_Jv_IndirectCompiledEngine::do_get_closure_list): New.
(_Jv_IndirectCompiledEngine::_Jv_IndirectCompiledEngine): Use it.
(_Jv_InterpreterEngine::do_get_closure_list): Declare.
(_Jv_InterpreterEngine::_Jv_InterpreterEngine): Use it.
* interpret.cc (FFI_PREP_RAW_CLOSURE): Use _loc variants.
(node_closure): Add closure list.
(_Jv_InterpMethod::ncode): Add jclass argument.  Use
ffi_closure_alloc and the separate code pointer.  Register the
closure for finalization.
(_Jv_JNIMethod::ncode): Likewise.
(_Jv_InterpreterEngine::do_create_ncode): Pass klass to ncode.
(_Jv_InterpreterEngine::do_get_closure_list): New.
* include/java-interp.h (_Jv_InterpMethod::ncode): Adjust.
(_Jv_InterpClass): Add closures field.
(_Jv_JNIMethod::ncode): Adjust.
* defineclass.cc (_Jv_ClassReader::handleCodeAttribute): Adjust.
(_Jv_ClassReader::handleMethodsEnd): Likewise.
* link.cc (struct method_closure): Add closure list.
(_Jv_Linker::create_error_method): Add jclass argument.  Use
ffi_closure_alloc and the separate code pointer.  Register the
closure for finalization.
(_Jv_Linker::link_symbol_table): Remove outdated comment about
sharing of otable and atable.  Adjust.
* java/lang/reflect/natVMProxy.cc (ncode_closure): Add closure
list.
(ncode): Add jclass argument.  Use ffi_closure_alloc and the
separate code pointer.  Register the closure for finalization.
(java::lang::reflect::VMProxy::generateProxyClass): Adjust.
* testsuite/libjava.jar/TestClosureGC.java: New.
* testsuite/libjava.jar/TestClosureGC.out: New.
* testsuite/libjava.jar/TestClosureGC.xfail: New.
* testsuite/libjava.jar/TestClosureGC.jar: New.

From-SVN: r122652
parent dd778331
2007-03-07 Alexandre Oliva <aoliva@redhat.com>
* include/gc.h (GC_REGISTER_FINALIZER_UNREACHABLE): New.
(GC_register_finalizer_unreachable): Declare.
(GC_debug_register_finalizer_unreachable): Declare.
* finalize.c (GC_unreachable_finalize_mark_proc): New.
(GC_register_finalizer_unreachable): New.
(GC_finalize): Handle it.
* dbg_mlc.c (GC_debug_register_finalizer_unreachable): New.
(GC_debug_register_finalizer_no_order): Fix whitespace.
2007-03-01 Brooks Moses <brooks.moses@codesourcery.com> 2007-03-01 Brooks Moses <brooks.moses@codesourcery.com>
* Makefile.am: Add dummy install-pdf target. * Makefile.am: Add dummy install-pdf target.
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright (c) 1997 by Silicon Graphics. All rights reserved. * Copyright (c) 1997 by Silicon Graphics. All rights reserved.
* Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P. * Copyright (c) 1999-2004 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2007 Free Software Foundation, Inc
* *
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
...@@ -1129,7 +1130,41 @@ GC_PTR *ocd; ...@@ -1129,7 +1130,41 @@ GC_PTR *ocd;
&my_old_cd); &my_old_cd);
} }
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd); store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
# ifdef __STDC__
void GC_debug_register_finalizer_unreachable
(GC_PTR obj, GC_finalization_proc fn,
GC_PTR cd, GC_finalization_proc *ofn,
GC_PTR *ocd)
# else
void GC_debug_register_finalizer_unreachable
(obj, fn, cd, ofn, ocd)
GC_PTR obj;
GC_finalization_proc fn;
GC_PTR cd;
GC_finalization_proc *ofn;
GC_PTR *ocd;
# endif
{
GC_finalization_proc my_old_fn;
GC_PTR my_old_cd;
ptr_t base = GC_base(obj);
if (0 == base) return;
if ((ptr_t)obj - base != sizeof(oh)) {
GC_err_printf1(
"GC_debug_register_finalizer_unreachable called with non-base-pointer 0x%lx\n",
obj);
} }
if (0 == fn) {
GC_register_finalizer_unreachable(base, 0, 0, &my_old_fn, &my_old_cd);
} else {
GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer,
GC_make_closure(fn,cd), &my_old_fn,
&my_old_cd);
}
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
# ifdef __STDC__ # ifdef __STDC__
void GC_debug_register_finalizer_ignore_self void GC_debug_register_finalizer_ignore_self
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
* Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers * Copyright 1988, 1989 Hans-J. Boehm, Alan J. Demers
* Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved. * Copyright (c) 1991-1996 by Xerox Corporation. All rights reserved.
* Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved. * Copyright (c) 1996-1999 by Silicon Graphics. All rights reserved.
* Copyright (C) 2007 Free Software Foundation, Inc
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
...@@ -315,6 +316,14 @@ ptr_t p; ...@@ -315,6 +316,14 @@ ptr_t p;
{ {
} }
/* Possible finalization_marker procedures. Note that mark stack */
/* overflow is handled by the caller, and is not a disaster. */
GC_API void GC_unreachable_finalize_mark_proc(p)
ptr_t p;
{
return GC_normal_finalize_mark_proc(p);
}
/* Register a finalization function. See gc.h for details. */ /* Register a finalization function. See gc.h for details. */
...@@ -511,6 +520,23 @@ finalization_mark_proc * mp; ...@@ -511,6 +520,23 @@ finalization_mark_proc * mp;
ocd, GC_null_finalize_mark_proc); ocd, GC_null_finalize_mark_proc);
} }
# if defined(__STDC__)
void GC_register_finalizer_unreachable(void * obj,
GC_finalization_proc fn, void * cd,
GC_finalization_proc *ofn, void ** ocd)
# else
void GC_register_finalizer_unreachable(obj, fn, cd, ofn, ocd)
GC_PTR obj;
GC_finalization_proc fn;
GC_PTR cd;
GC_finalization_proc * ofn;
GC_PTR * ocd;
# endif
{
GC_register_finalizer_inner(obj, fn, cd, ofn,
ocd, GC_unreachable_finalize_mark_proc);
}
#ifndef NO_DEBUGGING #ifndef NO_DEBUGGING
void GC_dump_finalization() void GC_dump_finalization()
{ {
...@@ -638,8 +664,43 @@ void GC_finalize() ...@@ -638,8 +664,43 @@ void GC_finalize()
if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) { if (curr_fo -> fo_mark_proc == GC_null_finalize_mark_proc) {
GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc); GC_MARK_FO(real_ptr, GC_normal_finalize_mark_proc);
} }
if (curr_fo -> fo_mark_proc != GC_unreachable_finalize_mark_proc) {
GC_set_mark_bit(real_ptr);
}
}
}
/* now revive finalize-when-unreachable objects reachable from
other finalizable objects */
curr_fo = GC_finalize_now;
prev_fo = 0;
while (curr_fo != 0) {
next_fo = fo_next(curr_fo);
if (curr_fo -> fo_mark_proc == GC_unreachable_finalize_mark_proc) {
real_ptr = (ptr_t)curr_fo -> fo_hidden_base;
if (!GC_is_marked(real_ptr)) {
GC_set_mark_bit(real_ptr); GC_set_mark_bit(real_ptr);
} else {
if (prev_fo == 0)
GC_finalize_now = next_fo;
else
fo_set_next(prev_fo, next_fo);
curr_fo -> fo_hidden_base =
(word) HIDE_POINTER(curr_fo -> fo_hidden_base);
GC_words_finalized -=
ALIGNED_WORDS(curr_fo -> fo_object_size)
+ ALIGNED_WORDS(sizeof(struct finalizable_object));
i = HASH2(real_ptr, log_fo_table_size);
fo_set_next (curr_fo, fo_head[i]);
GC_fo_entries++;
fo_head[i] = curr_fo;
curr_fo = prev_fo;
}
} }
prev_fo = curr_fo;
curr_fo = next_fo;
} }
} }
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved. * Copyright (c) 1991-1995 by Xerox Corporation. All rights reserved.
* Copyright 1996-1999 by Silicon Graphics. All rights reserved. * Copyright 1996-1999 by Silicon Graphics. All rights reserved.
* Copyright 1999 by Hewlett-Packard Company. All rights reserved. * Copyright 1999 by Hewlett-Packard Company. All rights reserved.
* Copyright (C) 2007 Free Software Foundation, Inc
* *
* THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED * THIS MATERIAL IS PROVIDED AS IS, WITH ABSOLUTELY NO WARRANTY EXPRESSED
* OR IMPLIED. ANY USE IS AT YOUR OWN RISK. * OR IMPLIED. ANY USE IS AT YOUR OWN RISK.
...@@ -602,6 +603,8 @@ GC_API GC_PTR GC_debug_realloc_replacement ...@@ -602,6 +603,8 @@ GC_API GC_PTR GC_debug_realloc_replacement
GC_debug_register_finalizer_ignore_self(p, f, d, of, od) GC_debug_register_finalizer_ignore_self(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \ # define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
GC_debug_register_finalizer_no_order(p, f, d, of, od) GC_debug_register_finalizer_no_order(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
GC_debug_register_finalizer_unreachable(p, f, d, of, od)
# define GC_MALLOC_STUBBORN(sz) GC_debug_malloc_stubborn(sz, GC_EXTRAS); # define GC_MALLOC_STUBBORN(sz) GC_debug_malloc_stubborn(sz, GC_EXTRAS);
# define GC_CHANGE_STUBBORN(p) GC_debug_change_stubborn(p) # define GC_CHANGE_STUBBORN(p) GC_debug_change_stubborn(p)
# define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p) # define GC_END_STUBBORN_CHANGE(p) GC_debug_end_stubborn_change(p)
...@@ -624,6 +627,8 @@ GC_API GC_PTR GC_debug_realloc_replacement ...@@ -624,6 +627,8 @@ GC_API GC_PTR GC_debug_realloc_replacement
GC_register_finalizer_ignore_self(p, f, d, of, od) GC_register_finalizer_ignore_self(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \ # define GC_REGISTER_FINALIZER_NO_ORDER(p, f, d, of, od) \
GC_register_finalizer_no_order(p, f, d, of, od) GC_register_finalizer_no_order(p, f, d, of, od)
# define GC_REGISTER_FINALIZER_UNREACHABLE(p, f, d, of, od) \
GC_register_finalizer_unreachable(p, f, d, of, od)
# define GC_MALLOC_STUBBORN(sz) GC_malloc_stubborn(sz) # define GC_MALLOC_STUBBORN(sz) GC_malloc_stubborn(sz)
# define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p) # define GC_CHANGE_STUBBORN(p) GC_change_stubborn(p)
# define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p) # define GC_END_STUBBORN_CHANGE(p) GC_end_stubborn_change(p)
...@@ -716,6 +721,19 @@ GC_API void GC_debug_register_finalizer_no_order ...@@ -716,6 +721,19 @@ GC_API void GC_debug_register_finalizer_no_order
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd, GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd)); GC_finalization_proc *ofn, GC_PTR *ocd));
/* This is a special finalizer that is useful when an object's */
/* finalizer must be run when the object is known to be no */
/* longer reachable, not even from other finalizable objects. */
/* This can be used in combination with finalizer_no_order so */
/* as to release resources that must not be released while an */
/* object can still be brought back to life by other */
/* finalizers. */
GC_API void GC_register_finalizer_unreachable
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
GC_API void GC_debug_register_finalizer_unreachable
GC_PROTO((GC_PTR obj, GC_finalization_proc fn, GC_PTR cd,
GC_finalization_proc *ofn, GC_PTR *ocd));
/* The following routine may be used to break cycles between */ /* The following routine may be used to break cycles between */
/* finalizable objects, thus causing cyclic finalizable */ /* finalizable objects, thus causing cyclic finalizable */
......
2007-03-07 Alexandre Oliva <aoliva@redhat.com> 2007-03-07 Alexandre Oliva <aoliva@redhat.com>
* include/ffi.h.in (ffi_closure_alloc, ffi_closure_free): New.
(ffi_prep_closure_loc): New.
(ffi_prep_raw_closure_loc): New.
(ffi_prep_java_raw_closure_loc): New.
* src/closures.c: New file.
* src/dlmalloc.c [FFI_MMAP_EXEC_WRIT] (struct malloc_segment):
Replace sflags with exec_offset.
[FFI_MMAP_EXEC_WRIT] (mmap_exec_offset, add_segment_exec_offset,
sub_segment_exec_offset): New macros.
(get_segment_flags, set_segment_flags, check_segment_merge): New
macros.
(is_mmapped_segment, is_extern_segment): Use get_segment_flags.
(add_segment, sys_alloc, create_mspace, create_mspace_with_base,
destroy_mspace): Use new macros.
(sys_alloc): Silence warning.
* Makefile.am (libffi_la_SOURCES): Add src/closures.c.
* Makefile.in: Rebuilt.
* src/prep_cif [FFI_CLOSURES] (ffi_prep_closure): Implement in
terms of ffi_prep_closure_loc.
* src/raw_api.c (ffi_prep_raw_closure_loc): Renamed and adjusted
from...
(ffi_prep_raw_closure): ... this. Re-implement in terms of the
renamed version.
* src/java_raw_api (ffi_prep_java_raw_closure_loc): Renamed and
adjusted from...
(ffi_prep_java_raw_closure): ... this. Re-implement in terms of
the renamed version.
* src/alpha/ffi.c (ffi_prep_closure_loc): Renamed from
(ffi_prep_closure): ... this.
* src/pa/ffi.c: Likewise.
* src/cris/ffi.c: Likewise. Adjust.
* src/frv/ffi.c: Likewise.
* src/ia64/ffi.c: Likewise.
* src/mips/ffi.c: Likewise.
* src/powerpc/ffi_darwin.c: Likewise.
* src/s390/ffi.c: Likewise.
* src/sh/ffi.c: Likewise.
* src/sh64/ffi.c: Likewise.
* src/sparc/ffi.c: Likewise.
* src/x86/ffi64.c: Likewise.
* src/x86/ffi.c: Likewise.
(FFI_INIT_TRAMPOLINE): Adjust.
(ffi_prep_raw_closure_loc): Renamed and adjusted from...
(ffi_prep_raw_closure): ... this.
* src/powerpc/ffi.c (ffi_prep_closure_loc): Renamed from
(ffi_prep_closure): ... this.
(flush_icache): Adjust.
2007-03-07 Alexandre Oliva <aoliva@redhat.com>
* src/dlmalloc.c: New file, imported version 2.8.3 of Doug * src/dlmalloc.c: New file, imported version 2.8.3 of Doug
Lea's malloc. Lea's malloc.
......
...@@ -78,7 +78,7 @@ toolexeclib_LTLIBRARIES = libffi.la ...@@ -78,7 +78,7 @@ toolexeclib_LTLIBRARIES = libffi.la
noinst_LTLIBRARIES = libffi_convenience.la noinst_LTLIBRARIES = libffi_convenience.la
libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \ libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \
src/raw_api.c src/java_raw_api.c src/raw_api.c src/java_raw_api.c src/closures.c
nodist_libffi_la_SOURCES = nodist_libffi_la_SOURCES =
......
...@@ -92,7 +92,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES) ...@@ -92,7 +92,7 @@ LTLIBRARIES = $(noinst_LTLIBRARIES) $(toolexeclib_LTLIBRARIES)
libffi_la_LIBADD = libffi_la_LIBADD =
am__dirstamp = $(am__leading_dot)dirstamp am__dirstamp = $(am__leading_dot)dirstamp
am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \ am_libffi_la_OBJECTS = src/debug.lo src/prep_cif.lo src/types.lo \
src/raw_api.lo src/java_raw_api.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo
@MIPS_IRIX_TRUE@am__objects_1 = src/mips/ffi.lo src/mips/o32.lo \ @MIPS_IRIX_TRUE@am__objects_1 = src/mips/ffi.lo src/mips/o32.lo \
@MIPS_IRIX_TRUE@ src/mips/n32.lo @MIPS_IRIX_TRUE@ src/mips/n32.lo
@MIPS_LINUX_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo @MIPS_LINUX_TRUE@am__objects_2 = src/mips/ffi.lo src/mips/o32.lo
...@@ -141,7 +141,7 @@ libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \ ...@@ -141,7 +141,7 @@ libffi_la_OBJECTS = $(am_libffi_la_OBJECTS) \
$(nodist_libffi_la_OBJECTS) $(nodist_libffi_la_OBJECTS)
libffi_convenience_la_LIBADD = libffi_convenience_la_LIBADD =
am__objects_24 = src/debug.lo src/prep_cif.lo src/types.lo \ am__objects_24 = src/debug.lo src/prep_cif.lo src/types.lo \
src/raw_api.lo src/java_raw_api.lo src/raw_api.lo src/java_raw_api.lo src/closures.lo
am_libffi_convenience_la_OBJECTS = $(am__objects_24) am_libffi_convenience_la_OBJECTS = $(am__objects_24)
am__objects_25 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \ am__objects_25 = $(am__objects_1) $(am__objects_2) $(am__objects_3) \
$(am__objects_4) $(am__objects_5) $(am__objects_6) \ $(am__objects_4) $(am__objects_5) $(am__objects_6) \
...@@ -416,7 +416,7 @@ MAKEOVERRIDES = ...@@ -416,7 +416,7 @@ MAKEOVERRIDES =
toolexeclib_LTLIBRARIES = libffi.la toolexeclib_LTLIBRARIES = libffi.la
noinst_LTLIBRARIES = libffi_convenience.la noinst_LTLIBRARIES = libffi_convenience.la
libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \ libffi_la_SOURCES = src/debug.c src/prep_cif.c src/types.c \
src/raw_api.c src/java_raw_api.c src/raw_api.c src/java_raw_api.c src/closures.c
nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \ nodist_libffi_la_SOURCES = $(am__append_1) $(am__append_2) \
$(am__append_3) $(am__append_4) $(am__append_5) \ $(am__append_3) $(am__append_4) $(am__append_5) \
...@@ -534,6 +534,7 @@ src/prep_cif.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) ...@@ -534,6 +534,7 @@ src/prep_cif.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/types.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/java_raw_api.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/closures.lo: src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
src/mips/$(am__dirstamp): src/mips/$(am__dirstamp):
@$(mkdir_p) src/mips @$(mkdir_p) src/mips
@: > src/mips/$(am__dirstamp) @: > src/mips/$(am__dirstamp)
...@@ -729,6 +730,8 @@ mostlyclean-compile: ...@@ -729,6 +730,8 @@ mostlyclean-compile:
-rm -f src/arm/ffi.lo -rm -f src/arm/ffi.lo
-rm -f src/arm/sysv.$(OBJEXT) -rm -f src/arm/sysv.$(OBJEXT)
-rm -f src/arm/sysv.lo -rm -f src/arm/sysv.lo
-rm -f src/closures.$(OBJEXT)
-rm -f src/closures.lo
-rm -f src/cris/ffi.$(OBJEXT) -rm -f src/cris/ffi.$(OBJEXT)
-rm -f src/cris/ffi.lo -rm -f src/cris/ffi.lo
-rm -f src/cris/sysv.$(OBJEXT) -rm -f src/cris/sysv.$(OBJEXT)
...@@ -827,6 +830,7 @@ mostlyclean-compile: ...@@ -827,6 +830,7 @@ mostlyclean-compile:
distclean-compile: distclean-compile:
-rm -f *.tab.c -rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/closures.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/debug.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/java_raw_api.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/prep_cif.Plo@am__quote@
......
/* -----------------------------------------------------------------*-C-*- /* -----------------------------------------------------------------*-C-*-
libffi @VERSION@ - Copyright (c) 1996-2003 Red Hat, Inc. libffi @VERSION@ - Copyright (c) 1996-2003, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
...@@ -228,12 +228,22 @@ typedef struct { ...@@ -228,12 +228,22 @@ typedef struct {
void *user_data; void *user_data;
} ffi_closure __attribute__((aligned (8))); } ffi_closure __attribute__((aligned (8)));
void *ffi_closure_alloc (size_t size, void **code);
void ffi_closure_free (void *);
ffi_status ffi_status
ffi_prep_closure (ffi_closure*, ffi_prep_closure (ffi_closure*,
ffi_cif *, ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*), void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data); void *user_data);
ffi_status
ffi_prep_closure_loc (ffi_closure*,
ffi_cif *,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data,
void*codeloc);
typedef struct { typedef struct {
char tramp[FFI_TRAMPOLINE_SIZE]; char tramp[FFI_TRAMPOLINE_SIZE];
...@@ -262,11 +272,25 @@ ffi_prep_raw_closure (ffi_raw_closure*, ...@@ -262,11 +272,25 @@ ffi_prep_raw_closure (ffi_raw_closure*,
void *user_data); void *user_data);
ffi_status ffi_status
ffi_prep_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
ffi_status
ffi_prep_java_raw_closure (ffi_raw_closure*, ffi_prep_java_raw_closure (ffi_raw_closure*,
ffi_cif *cif, ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data); void *user_data);
ffi_status
ffi_prep_java_raw_closure_loc (ffi_raw_closure*,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data,
void *codeloc);
#endif /* FFI_CLOSURES */ #endif /* FFI_CLOSURES */
/* ---- Public interface definition -------------------------------------- */ /* ---- Public interface definition -------------------------------------- */
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998, 2001 Red Hat, Inc. ffi.c - Copyright (c) 1998, 2001, 2007 Red Hat, Inc.
Alpha Foreign Function Interface Alpha Foreign Function Interface
...@@ -146,10 +146,11 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) ...@@ -146,10 +146,11 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp; unsigned int *tramp;
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
ffi.c - Copyright (c) 1998 Cygnus Solutions ffi.c - Copyright (c) 1998 Cygnus Solutions
Copyright (c) 2004 Simon Posnjak Copyright (c) 2004 Simon Posnjak
Copyright (c) 2005 Axis Communications AB Copyright (c) 2005 Axis Communications AB
Copyright (C) 2007 Free Software Foundation, Inc.
CRIS Foreign Function Interface CRIS Foreign Function Interface
...@@ -360,10 +361,11 @@ ffi_prep_closure_inner (void **params, ffi_closure* closure) ...@@ -360,10 +361,11 @@ ffi_prep_closure_inner (void **params, ffi_closure* closure)
/* API function: Prepare the trampoline. */ /* API function: Prepare the trampoline. */
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif *, void *, void **, void*), void (*fun)(ffi_cif *, void *, void **, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
void *innerfn = ffi_prep_closure_inner; void *innerfn = ffi_prep_closure_inner;
FFI_ASSERT (cif->abi == FFI_SYSV); FFI_ASSERT (cif->abi == FFI_SYSV);
...@@ -375,7 +377,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -375,7 +377,7 @@ ffi_prep_closure (ffi_closure* closure,
memcpy (closure->tramp + ffi_cris_trampoline_fn_offset, memcpy (closure->tramp + ffi_cris_trampoline_fn_offset,
&innerfn, sizeof (void *)); &innerfn, sizeof (void *));
memcpy (closure->tramp + ffi_cris_trampoline_closure_offset, memcpy (closure->tramp + ffi_cris_trampoline_closure_offset,
&closure, sizeof (void *)); &codeloc, sizeof (void *));
return FFI_OK; return FFI_OK;
} }
...@@ -1879,11 +1879,47 @@ struct malloc_segment { ...@@ -1879,11 +1879,47 @@ struct malloc_segment {
char* base; /* base address */ char* base; /* base address */
size_t size; /* allocated size */ size_t size; /* allocated size */
struct malloc_segment* next; /* ptr to next segment */ struct malloc_segment* next; /* ptr to next segment */
#if FFI_MMAP_EXEC_WRIT
/* The mmap magic is supposed to store the address of the executable
segment at the very end of the requested block. */
# define mmap_exec_offset(b,s) (*(ptrdiff_t*)((b)+(s)-sizeof(ptrdiff_t)))
/* We can only merge segments if their corresponding executable
segments are at identical offsets. */
# define check_segment_merge(S,b,s) \
(mmap_exec_offset((b),(s)) == (S)->exec_offset)
# define add_segment_exec_offset(p,S) ((char*)(p) + (S)->exec_offset)
# define sub_segment_exec_offset(p,S) ((char*)(p) - (S)->exec_offset)
/* The removal of sflags only works with HAVE_MORECORE == 0. */
# define get_segment_flags(S) (IS_MMAPPED_BIT)
# define set_segment_flags(S,v) \
(((v) != IS_MMAPPED_BIT) ? (ABORT, (v)) : \
(((S)->exec_offset = \
mmap_exec_offset((S)->base, (S)->size)), \
(mmap_exec_offset((S)->base + (S)->exec_offset, (S)->size) != \
(S)->exec_offset) ? (ABORT, (v)) : \
(mmap_exec_offset((S)->base, (S)->size) = 0), (v)))
/* We use an offset here, instead of a pointer, because then, when
base changes, we don't have to modify this. On architectures
with segmented addresses, this might not work. */
ptrdiff_t exec_offset;
#else
# define get_segment_flags(S) ((S)->sflags)
# define set_segment_flags(S,v) ((S)->sflags = (v))
# define check_segment_merge(S,b,s) (1)
flag_t sflags; /* mmap and extern flag */ flag_t sflags; /* mmap and extern flag */
#endif
}; };
#define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT) #define is_mmapped_segment(S) (get_segment_flags(S) & IS_MMAPPED_BIT)
#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) #define is_extern_segment(S) (get_segment_flags(S) & EXTERN_BIT)
typedef struct malloc_segment msegment; typedef struct malloc_segment msegment;
typedef struct malloc_segment* msegmentptr; typedef struct malloc_segment* msegmentptr;
...@@ -3290,7 +3326,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { ...@@ -3290,7 +3326,7 @@ static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) {
*ss = m->seg; /* Push current record */ *ss = m->seg; /* Push current record */
m->seg.base = tbase; m->seg.base = tbase;
m->seg.size = tsize; m->seg.size = tsize;
m->seg.sflags = mmapped; set_segment_flags(&m->seg, mmapped);
m->seg.next = ss; m->seg.next = ss;
/* Insert trailing fenceposts */ /* Insert trailing fenceposts */
...@@ -3393,7 +3429,7 @@ static void* sys_alloc(mstate m, size_t nb) { ...@@ -3393,7 +3429,7 @@ static void* sys_alloc(mstate m, size_t nb) {
if (end != CMFAIL) if (end != CMFAIL)
asize += esize; asize += esize;
else { /* Can't use; try to release */ else { /* Can't use; try to release */
CALL_MORECORE(-asize); (void)CALL_MORECORE(-asize);
br = CMFAIL; br = CMFAIL;
} }
} }
...@@ -3450,7 +3486,7 @@ static void* sys_alloc(mstate m, size_t nb) { ...@@ -3450,7 +3486,7 @@ static void* sys_alloc(mstate m, size_t nb) {
if (!is_initialized(m)) { /* first-time initialization */ if (!is_initialized(m)) { /* first-time initialization */
m->seg.base = m->least_addr = tbase; m->seg.base = m->least_addr = tbase;
m->seg.size = tsize; m->seg.size = tsize;
m->seg.sflags = mmap_flag; set_segment_flags(&m->seg, mmap_flag);
m->magic = mparams.magic; m->magic = mparams.magic;
init_bins(m); init_bins(m);
if (is_global(m)) if (is_global(m))
...@@ -3469,7 +3505,8 @@ static void* sys_alloc(mstate m, size_t nb) { ...@@ -3469,7 +3505,8 @@ static void* sys_alloc(mstate m, size_t nb) {
sp = sp->next; sp = sp->next;
if (sp != 0 && if (sp != 0 &&
!is_extern_segment(sp) && !is_extern_segment(sp) &&
(sp->sflags & IS_MMAPPED_BIT) == mmap_flag && check_segment_merge(sp, tbase, tsize) &&
(get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag &&
segment_holds(sp, m->top)) { /* append */ segment_holds(sp, m->top)) { /* append */
sp->size += tsize; sp->size += tsize;
init_top(m, m->top, m->topsize + tsize); init_top(m, m->top, m->topsize + tsize);
...@@ -3482,7 +3519,8 @@ static void* sys_alloc(mstate m, size_t nb) { ...@@ -3482,7 +3519,8 @@ static void* sys_alloc(mstate m, size_t nb) {
sp = sp->next; sp = sp->next;
if (sp != 0 && if (sp != 0 &&
!is_extern_segment(sp) && !is_extern_segment(sp) &&
(sp->sflags & IS_MMAPPED_BIT) == mmap_flag) { check_segment_merge(sp, tbase, tsize) &&
(get_segment_flags(sp) & IS_MMAPPED_BIT) == mmap_flag) {
char* oldbase = sp->base; char* oldbase = sp->base;
sp->base = tbase; sp->base = tbase;
sp->size += tsize; sp->size += tsize;
...@@ -4397,7 +4435,7 @@ mspace create_mspace(size_t capacity, int locked) { ...@@ -4397,7 +4435,7 @@ mspace create_mspace(size_t capacity, int locked) {
char* tbase = (char*)(CALL_MMAP(tsize)); char* tbase = (char*)(CALL_MMAP(tsize));
if (tbase != CMFAIL) { if (tbase != CMFAIL) {
m = init_user_mstate(tbase, tsize); m = init_user_mstate(tbase, tsize);
m->seg.sflags = IS_MMAPPED_BIT; set_segment_flags(&m->seg, IS_MMAPPED_BIT);
set_lock(m, locked); set_lock(m, locked);
} }
} }
...@@ -4412,7 +4450,7 @@ mspace create_mspace_with_base(void* base, size_t capacity, int locked) { ...@@ -4412,7 +4450,7 @@ mspace create_mspace_with_base(void* base, size_t capacity, int locked) {
if (capacity > msize + TOP_FOOT_SIZE && if (capacity > msize + TOP_FOOT_SIZE &&
capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) {
m = init_user_mstate((char*)base, capacity); m = init_user_mstate((char*)base, capacity);
m->seg.sflags = EXTERN_BIT; set_segment_flags(&m->seg, EXTERN_BIT);
set_lock(m, locked); set_lock(m, locked);
} }
return (mspace)m; return (mspace)m;
...@@ -4426,7 +4464,7 @@ size_t destroy_mspace(mspace msp) { ...@@ -4426,7 +4464,7 @@ size_t destroy_mspace(mspace msp) {
while (sp != 0) { while (sp != 0) {
char* base = sp->base; char* base = sp->base;
size_t size = sp->size; size_t size = sp->size;
flag_t flag = sp->sflags; flag_t flag = get_segment_flags(sp);
sp = sp->next; sp = sp->next;
if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) && if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) &&
CALL_MUNMAP(base, size) == 0) CALL_MUNMAP(base, size) == 0)
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2004 Anthony Green ffi.c - Copyright (c) 2004 Anthony Green
Copyright (C) 2007 Free Software Foundation, Inc.
FR-V Foreign Function Interface FR-V Foreign Function Interface
...@@ -243,14 +244,15 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3, ...@@ -243,14 +244,15 @@ void ffi_closure_eabi (unsigned arg1, unsigned arg2, unsigned arg3,
} }
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp = (unsigned int *) &closure->tramp[0]; unsigned int *tramp = (unsigned int *) &closure->tramp[0];
unsigned long fn = (long) ffi_closure_eabi; unsigned long fn = (long) ffi_closure_eabi;
unsigned long cls = (long) closure; unsigned long cls = (long) codeloc;
#ifdef __FRV_FDPIC__ #ifdef __FRV_FDPIC__
register void *got __asm__("gr15"); register void *got __asm__("gr15");
#endif #endif
...@@ -259,7 +261,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -259,7 +261,7 @@ ffi_prep_closure (ffi_closure* closure,
fn = (unsigned long) ffi_closure_eabi; fn = (unsigned long) ffi_closure_eabi;
#ifdef __FRV_FDPIC__ #ifdef __FRV_FDPIC__
tramp[0] = &tramp[2]; tramp[0] = &((unsigned int *)codeloc)[2];
tramp[1] = got; tramp[1] = got;
tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */ tramp[2] = 0x8cfc0000 + (fn & 0xffff); /* setlos lo(fn), gr6 */
tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */ tramp[3] = 0x8efc0000 + (cls & 0xffff); /* setlos lo(cls), gr7 */
...@@ -281,7 +283,8 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -281,7 +283,8 @@ ffi_prep_closure (ffi_closure* closure,
/* Cache flushing. */ /* Cache flushing. */
for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++) for (i = 0; i < FFI_TRAMPOLINE_SIZE; i++)
__asm__ volatile ("dcf @(%0,%1)\n\tici @(%0,%1)" :: "r" (tramp), "r" (i)); __asm__ volatile ("dcf @(%0,%1)\n\tici @(%2,%1)" :: "r" (tramp), "r" (i),
"r" (codeloc));
return FFI_OK; return FFI_OK;
} }
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998 Red Hat, Inc. ffi.c - Copyright (c) 1998, 2007 Red Hat, Inc.
Copyright (c) 2000 Hewlett Packard Company Copyright (c) 2000 Hewlett Packard Company
IA64 Foreign Function Interface IA64 Foreign Function Interface
...@@ -400,10 +400,11 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) ...@@ -400,10 +400,11 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
extern void ffi_closure_unix (); extern void ffi_closure_unix ();
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*), void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
/* The layout of a function descriptor. A C function pointer really /* The layout of a function descriptor. A C function pointer really
points to one of these. */ points to one of these. */
...@@ -430,7 +431,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -430,7 +431,7 @@ ffi_prep_closure (ffi_closure* closure,
tramp->code_pointer = fd->code_pointer; tramp->code_pointer = fd->code_pointer;
tramp->real_gp = fd->gp; tramp->real_gp = fd->gp;
tramp->fake_gp = (UINT64)(PTR64)closure; tramp->fake_gp = (UINT64)(PTR64)codeloc;
closure->cif = cif; closure->cif = cif;
closure->user_data = user_data; closure->user_data = user_data;
closure->fun = fun; closure->fun = fun;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
java_raw_api.c - Copyright (c) 1999 Red Hat, Inc. java_raw_api.c - Copyright (c) 1999, 2007 Red Hat, Inc.
Cloned from raw_api.c Cloned from raw_api.c
...@@ -307,22 +307,20 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue, ...@@ -307,22 +307,20 @@ ffi_java_translate_args (ffi_cif *cif, void *rvalue,
ffi_java_raw_to_rvalue (cif, rvalue); ffi_java_raw_to_rvalue (cif, rvalue);
} }
/* Again, here is the generic version of ffi_prep_raw_closure, which
* will install an intermediate "hub" for translation of arguments from
* the pointer-array format, to the raw format */
ffi_status ffi_status
ffi_prep_java_raw_closure (ffi_raw_closure* cl, ffi_prep_java_raw_closure_loc (ffi_raw_closure* cl,
ffi_cif *cif, ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
ffi_status status; ffi_status status;
status = ffi_prep_closure ((ffi_closure*) cl, status = ffi_prep_closure_loc ((ffi_closure*) cl,
cif, cif,
&ffi_java_translate_args, &ffi_java_translate_args,
(void*)cl); codeloc,
codeloc);
if (status == FFI_OK) if (status == FFI_OK)
{ {
cl->fun = fun; cl->fun = fun;
...@@ -332,6 +330,19 @@ ffi_prep_java_raw_closure (ffi_raw_closure* cl, ...@@ -332,6 +330,19 @@ ffi_prep_java_raw_closure (ffi_raw_closure* cl,
return status; return status;
} }
/* Again, here is the generic version of ffi_prep_raw_closure, which
* will install an intermediate "hub" for translation of arguments from
* the pointer-array format, to the raw format */
ffi_status
ffi_prep_java_raw_closure (ffi_raw_closure* cl,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data)
{
return ffi_prep_java_raw_closure_loc (cl, cif, fun, user_data, cl);
}
#endif /* FFI_CLOSURES */ #endif /* FFI_CLOSURES */
#endif /* !FFI_NATIVE_RAW_API */ #endif /* !FFI_NATIVE_RAW_API */
#endif /* !FFI_NO_RAW_API */ #endif /* !FFI_NO_RAW_API */
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996 Red Hat, Inc. ffi.c - Copyright (c) 1996, 2007 Red Hat, Inc.
MIPS Foreign Function Interface MIPS Foreign Function Interface
...@@ -497,14 +497,15 @@ extern void ffi_closure_O32(void); ...@@ -497,14 +497,15 @@ extern void ffi_closure_O32(void);
#endif /* FFI_MIPS_O32 */ #endif /* FFI_MIPS_O32 */
ffi_status ffi_status
ffi_prep_closure (ffi_closure *closure, ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif *cif, ffi_cif *cif,
void (*fun)(ffi_cif*,void*,void**,void*), void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp = (unsigned int *) &closure->tramp[0]; unsigned int *tramp = (unsigned int *) &closure->tramp[0];
unsigned int fn; unsigned int fn;
unsigned int ctx = (unsigned int) closure; unsigned int ctx = (unsigned int) codeloc;
#if defined(FFI_MIPS_O32) #if defined(FFI_MIPS_O32)
FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT); FFI_ASSERT(cif->abi == FFI_O32 || cif->abi == FFI_O32_SOFT_FLOAT);
...@@ -525,7 +526,7 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -525,7 +526,7 @@ ffi_prep_closure (ffi_closure *closure,
closure->user_data = user_data; closure->user_data = user_data;
/* XXX this is available on Linux, but anything else? */ /* XXX this is available on Linux, but anything else? */
cacheflush (tramp, FFI_TRAMPOLINE_SIZE, ICACHE); cacheflush (codeloc, FFI_TRAMPOLINE_SIZE, ICACHE);
return FFI_OK; return FFI_OK;
} }
......
...@@ -613,10 +613,11 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack) ...@@ -613,10 +613,11 @@ ffi_status ffi_closure_inner_pa32(ffi_closure *closure, UINT32 *stack)
extern void ffi_closure_pa32(void); extern void ffi_closure_pa32(void);
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*), void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
UINT32 *tramp = (UINT32 *)(closure->tramp); UINT32 *tramp = (UINT32 *)(closure->tramp);
#ifdef PA_HPUX #ifdef PA_HPUX
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1998 Geoffrey Keating ffi.c - Copyright (c) 1998 Geoffrey Keating
Copyright (C) 2007 Free Software Foundation, Inc
PowerPC Foreign Function Interface PowerPC Foreign Function Interface
...@@ -834,27 +835,27 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) ...@@ -834,27 +835,27 @@ ffi_call(ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
#define MIN_CACHE_LINE_SIZE 8 #define MIN_CACHE_LINE_SIZE 8
static void static void
flush_icache (char *addr1, int size) flush_icache (char *wraddr, char *xaddr, int size)
{ {
int i; int i;
char * addr;
for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE) for (i = 0; i < size; i += MIN_CACHE_LINE_SIZE)
{ {
addr = addr1 + i; addr = addr1 + i;
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;"
: : "r" (addr) : "memory"); : : "r" (xaddr + i), "r" (wraddr + i) : "memory");
} }
addr = addr1 + size - 1; __asm__ volatile ("icbi 0,%0;" "dcbf 0,%1;" "sync;" "isync;"
__asm__ volatile ("icbi 0,%0;" "dcbf 0,%0;" "sync;" "isync;" : : "r"(xaddr + size - 1), "r"(wraddr + size - 1)
: : "r"(addr) : "memory"); : "memory");
} }
#endif #endif
ffi_status ffi_status
ffi_prep_closure (ffi_closure *closure, ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif *cif, ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *), void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data) void *user_data,
void *codeloc)
{ {
#ifdef POWERPC64 #ifdef POWERPC64
void **tramp = (void **) &closure->tramp[0]; void **tramp = (void **) &closure->tramp[0];
...@@ -862,7 +863,7 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -862,7 +863,7 @@ ffi_prep_closure (ffi_closure *closure,
FFI_ASSERT (cif->abi == FFI_LINUX64); FFI_ASSERT (cif->abi == FFI_LINUX64);
/* Copy function address and TOC from ffi_closure_LINUX64. */ /* Copy function address and TOC from ffi_closure_LINUX64. */
memcpy (tramp, (char *) ffi_closure_LINUX64, 16); memcpy (tramp, (char *) ffi_closure_LINUX64, 16);
tramp[2] = (void *) closure; tramp[2] = (void *) codeloc;
#else #else
unsigned int *tramp; unsigned int *tramp;
...@@ -878,10 +879,10 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -878,10 +879,10 @@ ffi_prep_closure (ffi_closure *closure,
tramp[8] = 0x7c0903a6; /* mtctr r0 */ tramp[8] = 0x7c0903a6; /* mtctr r0 */
tramp[9] = 0x4e800420; /* bctr */ tramp[9] = 0x4e800420; /* bctr */
*(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */ *(void **) &tramp[2] = (void *) ffi_closure_SYSV; /* function */
*(void **) &tramp[3] = (void *) closure; /* context */ *(void **) &tramp[3] = (void *) codeloc; /* context */
/* Flush the icache. */ /* Flush the icache. */
flush_icache (&closure->tramp[0],FFI_TRAMPOLINE_SIZE); flush_icache (tramp, codeloc, FFI_TRAMPOLINE_SIZE);
#endif #endif
closure->cif = cif; closure->cif = cif;
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
Copyright (C) 1998 Geoffrey Keating Copyright (C) 1998 Geoffrey Keating
Copyright (C) 2001 John Hornkvist Copyright (C) 2001 John Hornkvist
Copyright (C) 2002, 2006 Free Software Foundation, Inc. Copyright (C) 2002, 2006, 2007 Free Software Foundation, Inc.
FFI support for Darwin and AIX. FFI support for Darwin and AIX.
...@@ -528,10 +528,11 @@ SP current --> +---------------------------------------+ 176 <- parent frame ...@@ -528,10 +528,11 @@ SP current --> +---------------------------------------+ 176 <- parent frame
*/ */
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp; unsigned int *tramp;
struct ffi_aix_trampoline_struct *tramp_aix; struct ffi_aix_trampoline_struct *tramp_aix;
...@@ -553,14 +554,14 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -553,14 +554,14 @@ ffi_prep_closure (ffi_closure* closure,
tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */ tramp[8] = 0x816b0004; /* lwz r11,4(r11) static chain */
tramp[9] = 0x4e800420; /* bctr */ tramp[9] = 0x4e800420; /* bctr */
tramp[2] = (unsigned long) ffi_closure_ASM; /* function */ tramp[2] = (unsigned long) ffi_closure_ASM; /* function */
tramp[3] = (unsigned long) closure; /* context */ tramp[3] = (unsigned long) codeloc; /* context */
closure->cif = cif; closure->cif = cif;
closure->fun = fun; closure->fun = fun;
closure->user_data = user_data; closure->user_data = user_data;
/* Flush the icache. Only necessary on Darwin. */ /* Flush the icache. Only necessary on Darwin. */
flush_range(&closure->tramp[0],FFI_TRAMPOLINE_SIZE); flush_range(codeloc, FFI_TRAMPOLINE_SIZE);
break; break;
...@@ -573,7 +574,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -573,7 +574,7 @@ ffi_prep_closure (ffi_closure* closure,
tramp_aix->code_pointer = fd->code_pointer; tramp_aix->code_pointer = fd->code_pointer;
tramp_aix->toc = fd->toc; tramp_aix->toc = fd->toc;
tramp_aix->static_chain = closure; tramp_aix->static_chain = codeloc;
closure->cif = cif; closure->cif = cif;
closure->fun = fun; closure->fun = fun;
closure->user_data = user_data; closure->user_data = user_data;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
prep_cif.c - Copyright (c) 1996, 1998 Red Hat, Inc. prep_cif.c - Copyright (c) 1996, 1998, 2007 Red Hat, Inc.
Permission is hereby granted, free of charge, to any person obtaining Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the a copy of this software and associated documentation files (the
...@@ -158,3 +158,16 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs, ...@@ -158,3 +158,16 @@ ffi_status ffi_prep_cif(ffi_cif *cif, ffi_abi abi, unsigned int nargs,
return ffi_prep_cif_machdep(cif); return ffi_prep_cif_machdep(cif);
} }
#endif /* not __CRIS__ */ #endif /* not __CRIS__ */
#if FFI_CLOSURES
ffi_status
ffi_prep_closure (ffi_closure* closure,
ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data)
{
return ffi_prep_closure_loc (closure, cif, fun, user_data, closure);
}
#endif
...@@ -209,22 +209,20 @@ ffi_translate_args (ffi_cif *cif, void *rvalue, ...@@ -209,22 +209,20 @@ ffi_translate_args (ffi_cif *cif, void *rvalue,
(*cl->fun) (cif, rvalue, raw, cl->user_data); (*cl->fun) (cif, rvalue, raw, cl->user_data);
} }
/* Again, here is the generic version of ffi_prep_raw_closure, which
* will install an intermediate "hub" for translation of arguments from
* the pointer-array format, to the raw format */
ffi_status ffi_status
ffi_prep_raw_closure (ffi_raw_closure* cl, ffi_prep_raw_closure_loc (ffi_raw_closure* cl,
ffi_cif *cif, ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
ffi_status status; ffi_status status;
status = ffi_prep_closure ((ffi_closure*) cl, status = ffi_prep_closure_loc ((ffi_closure*) cl,
cif, cif,
&ffi_translate_args, &ffi_translate_args,
(void*)cl); codeloc,
codeloc);
if (status == FFI_OK) if (status == FFI_OK)
{ {
cl->fun = fun; cl->fun = fun;
...@@ -236,4 +234,22 @@ ffi_prep_raw_closure (ffi_raw_closure* cl, ...@@ -236,4 +234,22 @@ ffi_prep_raw_closure (ffi_raw_closure* cl,
#endif /* FFI_CLOSURES */ #endif /* FFI_CLOSURES */
#endif /* !FFI_NATIVE_RAW_API */ #endif /* !FFI_NATIVE_RAW_API */
#if FFI_CLOSURES
/* Again, here is the generic version of ffi_prep_raw_closure, which
* will install an intermediate "hub" for translation of arguments from
* the pointer-array format, to the raw format */
ffi_status
ffi_prep_raw_closure (ffi_raw_closure* cl,
ffi_cif *cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data)
{
return ffi_prep_raw_closure_loc (cl, cif, fun, user_data, cl);
}
#endif /* FFI_CLOSURES */
#endif /* !FFI_NO_RAW_API */ #endif /* !FFI_NO_RAW_API */
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2000 Software AG ffi.c - Copyright (c) 2000, 2007 Software AG
S390 Foreign Function Interface S390 Foreign Function Interface
...@@ -736,17 +736,18 @@ ffi_closure_helper_SYSV (ffi_closure *closure, ...@@ -736,17 +736,18 @@ ffi_closure_helper_SYSV (ffi_closure *closure,
/*====================================================================*/ /*====================================================================*/
/* */ /* */
/* Name - ffi_prep_closure. */ /* Name - ffi_prep_closure_loc. */
/* */ /* */
/* Function - Prepare a FFI closure. */ /* Function - Prepare a FFI closure. */
/* */ /* */
/*====================================================================*/ /*====================================================================*/
ffi_status ffi_status
ffi_prep_closure (ffi_closure *closure, ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif *cif, ffi_cif *cif,
void (*fun) (ffi_cif *, void *, void **, void *), void (*fun) (ffi_cif *, void *, void **, void *),
void *user_data) void *user_data,
void *codeloc)
{ {
FFI_ASSERT (cif->abi == FFI_SYSV); FFI_ASSERT (cif->abi == FFI_SYSV);
...@@ -755,7 +756,7 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -755,7 +756,7 @@ ffi_prep_closure (ffi_closure *closure,
*(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */ *(short *)&closure->tramp [2] = 0x9801; /* lm %r0,%r1,6(%r1) */
*(short *)&closure->tramp [4] = 0x1006; *(short *)&closure->tramp [4] = 0x1006;
*(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */ *(short *)&closure->tramp [6] = 0x07f1; /* br %r1 */
*(long *)&closure->tramp [8] = (long)closure; *(long *)&closure->tramp [8] = (long)codeloc;
*(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV; *(long *)&closure->tramp[12] = (long)&ffi_closure_SYSV;
#else #else
*(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */ *(short *)&closure->tramp [0] = 0x0d10; /* basr %r1,0 */
...@@ -763,7 +764,7 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -763,7 +764,7 @@ ffi_prep_closure (ffi_closure *closure,
*(short *)&closure->tramp [4] = 0x100e; *(short *)&closure->tramp [4] = 0x100e;
*(short *)&closure->tramp [6] = 0x0004; *(short *)&closure->tramp [6] = 0x0004;
*(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */ *(short *)&closure->tramp [8] = 0x07f1; /* br %r1 */
*(long *)&closure->tramp[16] = (long)closure; *(long *)&closure->tramp[16] = (long)codeloc;
*(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV; *(long *)&closure->tramp[24] = (long)&ffi_closure_SYSV;
#endif #endif
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006 Kaz Kojima ffi.c - Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007 Kaz Kojima
SuperH Foreign Function Interface SuperH Foreign Function Interface
...@@ -452,10 +452,11 @@ extern void __ic_invalidate (void *line); ...@@ -452,10 +452,11 @@ extern void __ic_invalidate (void *line);
#endif #endif
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp; unsigned int *tramp;
unsigned short insn; unsigned short insn;
...@@ -475,7 +476,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -475,7 +476,7 @@ ffi_prep_closure (ffi_closure* closure,
tramp[0] = 0xd102d301; tramp[0] = 0xd102d301;
tramp[1] = 0x412b0000 | insn; tramp[1] = 0x412b0000 | insn;
#endif #endif
*(void **) &tramp[2] = (void *)closure; /* ctx */ *(void **) &tramp[2] = (void *)codeloc; /* ctx */
*(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */ *(void **) &tramp[3] = (void *)ffi_closure_SYSV; /* funaddr */
closure->cif = cif; closure->cif = cif;
...@@ -484,7 +485,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -484,7 +485,7 @@ ffi_prep_closure (ffi_closure* closure,
#if defined(__SH4__) #if defined(__SH4__)
/* Flush the icache. */ /* Flush the icache. */
__ic_invalidate(&closure->tramp[0]); __ic_invalidate(codeloc);
#endif #endif
return FFI_OK; return FFI_OK;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2003, 2004, 2006 Kaz Kojima ffi.c - Copyright (c) 2003, 2004, 2006, 2007 Kaz Kojima
SuperH SHmedia Foreign Function Interface SuperH SHmedia Foreign Function Interface
...@@ -283,10 +283,11 @@ extern void ffi_closure_SYSV (void); ...@@ -283,10 +283,11 @@ extern void ffi_closure_SYSV (void);
extern void __ic_invalidate (void *line); extern void __ic_invalidate (void *line);
ffi_status ffi_status
ffi_prep_closure (ffi_closure *closure, ffi_prep_closure_loc (ffi_closure *closure,
ffi_cif *cif, ffi_cif *cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp; unsigned int *tramp;
...@@ -310,8 +311,8 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -310,8 +311,8 @@ ffi_prep_closure (ffi_closure *closure,
tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10; tramp[2] = 0xcc000010 | (((UINT32) ffi_closure_SYSV) >> 16) << 10;
tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10; tramp[3] = 0xc8000010 | (((UINT32) ffi_closure_SYSV) & 0xffff) << 10;
tramp[4] = 0x6bf10600; tramp[4] = 0x6bf10600;
tramp[5] = 0xcc000010 | (((UINT32) closure) >> 16) << 10; tramp[5] = 0xcc000010 | (((UINT32) codeloc) >> 16) << 10;
tramp[6] = 0xc8000010 | (((UINT32) closure) & 0xffff) << 10; tramp[6] = 0xc8000010 | (((UINT32) codeloc) & 0xffff) << 10;
tramp[7] = 0x4401fff0; tramp[7] = 0x4401fff0;
closure->cif = cif; closure->cif = cif;
...@@ -319,7 +320,8 @@ ffi_prep_closure (ffi_closure *closure, ...@@ -319,7 +320,8 @@ ffi_prep_closure (ffi_closure *closure,
closure->user_data = user_data; closure->user_data = user_data;
/* Flush the icache. */ /* Flush the icache. */
asm volatile ("ocbwb %0,0; synco; icbi %0,0; synci" : : "r" (tramp)); asm volatile ("ocbwb %0,0; synco; icbi %1,0; synci" : : "r" (tramp),
"r"(codeloc));
return FFI_OK; return FFI_OK;
} }
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 2003, 2004 Red Hat, Inc. ffi.c - Copyright (c) 1996, 2003, 2004, 2007 Red Hat, Inc.
SPARC Foreign Function Interface SPARC Foreign Function Interface
...@@ -425,10 +425,11 @@ extern void ffi_closure_v8(void); ...@@ -425,10 +425,11 @@ extern void ffi_closure_v8(void);
#endif #endif
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
unsigned int *tramp = (unsigned int *) &closure->tramp[0]; unsigned int *tramp = (unsigned int *) &closure->tramp[0];
unsigned long fn; unsigned long fn;
...@@ -443,7 +444,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -443,7 +444,7 @@ ffi_prep_closure (ffi_closure* closure,
tramp[3] = 0x01000000; /* nop */ tramp[3] = 0x01000000; /* nop */
*((unsigned long *) &tramp[4]) = fn; *((unsigned long *) &tramp[4]) = fn;
#else #else
unsigned long ctx = (unsigned long) closure; unsigned long ctx = (unsigned long) codeloc;
FFI_ASSERT (cif->abi == FFI_V8); FFI_ASSERT (cif->abi == FFI_V8);
fn = (unsigned long) ffi_closure_v8; fn = (unsigned long) ffi_closure_v8;
tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */ tramp[0] = 0x03000000 | fn >> 10; /* sethi %hi(fn), %g1 */
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 1996, 1998, 1999, 2001 Red Hat, Inc. ffi.c - Copyright (c) 1996, 1998, 1999, 2001, 2007 Red Hat, Inc.
Copyright (c) 2002 Ranjit Mathew Copyright (c) 2002 Ranjit Mathew
Copyright (c) 2002 Bo Thorsen Copyright (c) 2002 Bo Thorsen
Copyright (c) 2002 Roger Sayle Copyright (c) 2002 Roger Sayle
...@@ -302,7 +302,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, ...@@ -302,7 +302,7 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
({ unsigned char *__tramp = (unsigned char*)(TRAMP); \ ({ unsigned char *__tramp = (unsigned char*)(TRAMP); \
unsigned int __fun = (unsigned int)(FUN); \ unsigned int __fun = (unsigned int)(FUN); \
unsigned int __ctx = (unsigned int)(CTX); \ unsigned int __ctx = (unsigned int)(CTX); \
unsigned int __dis = __fun - ((unsigned int) __tramp + FFI_TRAMPOLINE_SIZE); \ unsigned int __dis = __fun - (__ctx + FFI_TRAMPOLINE_SIZE); \
*(unsigned char*) &__tramp[0] = 0xb8; \ *(unsigned char*) &__tramp[0] = 0xb8; \
*(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \ *(unsigned int*) &__tramp[1] = __ctx; /* movl __ctx, %eax */ \
*(unsigned char *) &__tramp[5] = 0xe9; \ *(unsigned char *) &__tramp[5] = 0xe9; \
...@@ -313,16 +313,17 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue, ...@@ -313,16 +313,17 @@ ffi_prep_incoming_args_SYSV(char *stack, void **rvalue, void **avalue,
/* the cif must already be prep'ed */ /* the cif must already be prep'ed */
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*,void*,void**,void*), void (*fun)(ffi_cif*,void*,void**,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
FFI_ASSERT (cif->abi == FFI_SYSV); FFI_ASSERT (cif->abi == FFI_SYSV);
FFI_INIT_TRAMPOLINE (&closure->tramp[0], \ FFI_INIT_TRAMPOLINE (&closure->tramp[0], \
&ffi_closure_SYSV, \ &ffi_closure_SYSV, \
(void*)closure); codeloc);
closure->cif = cif; closure->cif = cif;
closure->user_data = user_data; closure->user_data = user_data;
...@@ -336,10 +337,11 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -336,10 +337,11 @@ ffi_prep_closure (ffi_closure* closure,
#if !FFI_NO_RAW_API #if !FFI_NO_RAW_API
ffi_status ffi_status
ffi_prep_raw_closure (ffi_raw_closure* closure, ffi_prep_raw_closure_loc (ffi_raw_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*,void*,ffi_raw*,void*), void (*fun)(ffi_cif*,void*,ffi_raw*,void*),
void *user_data) void *user_data,
void *codeloc)
{ {
int i; int i;
...@@ -358,7 +360,7 @@ ffi_prep_raw_closure (ffi_raw_closure* closure, ...@@ -358,7 +360,7 @@ ffi_prep_raw_closure (ffi_raw_closure* closure,
FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV, FFI_INIT_TRAMPOLINE (&closure->tramp[0], &ffi_closure_raw_SYSV,
(void*)closure); codeloc);
closure->cif = cif; closure->cif = cif;
closure->user_data = user_data; closure->user_data = user_data;
......
/* ----------------------------------------------------------------------- /* -----------------------------------------------------------------------
ffi.c - Copyright (c) 2002 Bo Thorsen <bo@suse.de> ffi.c - Copyright (c) 2002, 2007 Bo Thorsen <bo@suse.de>
x86-64 Foreign Function Interface x86-64 Foreign Function Interface
...@@ -433,10 +433,11 @@ ffi_call (ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue) ...@@ -433,10 +433,11 @@ ffi_call (ffi_cif *cif, void (*fn)(), void *rvalue, void **avalue)
extern void ffi_closure_unix64(void); extern void ffi_closure_unix64(void);
ffi_status ffi_status
ffi_prep_closure (ffi_closure* closure, ffi_prep_closure_loc (ffi_closure* closure,
ffi_cif* cif, ffi_cif* cif,
void (*fun)(ffi_cif*, void*, void**, void*), void (*fun)(ffi_cif*, void*, void**, void*),
void *user_data) void *user_data,
void *codeloc)
{ {
volatile unsigned short *tramp; volatile unsigned short *tramp;
...@@ -445,7 +446,7 @@ ffi_prep_closure (ffi_closure* closure, ...@@ -445,7 +446,7 @@ ffi_prep_closure (ffi_closure* closure,
tramp[0] = 0xbb49; /* mov <code>, %r11 */ tramp[0] = 0xbb49; /* mov <code>, %r11 */
*(void * volatile *) &tramp[1] = ffi_closure_unix64; *(void * volatile *) &tramp[1] = ffi_closure_unix64;
tramp[5] = 0xba49; /* mov <data>, %r10 */ tramp[5] = 0xba49; /* mov <data>, %r10 */
*(void * volatile *) &tramp[6] = closure; *(void * volatile *) &tramp[6] = codeloc;
/* Set the carry bit iff the function uses any sse registers. /* Set the carry bit iff the function uses any sse registers.
This is clc or stc, together with the first byte of the jmp. */ This is clc or stc, together with the first byte of the jmp. */
......
2007-03-07 Alexandre Oliva <aoliva@redhat.com>
* include/jvm.h (_Jv_ClosureListFinalizer): New.
(_Jv_Linker::create_error_method): Adjust.
* boehm.cc (_Jv_ClosureListFinalizer): New.
* nogc.cc (_Jv_ClosureListFinalizer): New.
* java/lang/Class.h (class _Jv_ClosureList): New.
(class java::lang::Class): Declare it as friend.
* java/lang/natClass.cc (_Jv_ClosureList::releaseClosures): New.
(_Jv_ClosureList::registerClousure): New.
* include/execution.h (_Jv_ExecutionEngine): Add get_closure_list.
(_Jv_CompiledEngine::do_get_closure_list): New.
(_Jv_CompiledEngine::_Jv_CompiledEngine): Use it.
(_Jv_IndirectCompiledClass): Add closures.
(_Jv_IndirectCompiledEngine::get_aux_info): New.
(_Jv_IndirectCompiledEngine::do_allocate_field_initializers): Use
it.
(_Jv_IndirectCompiledEngine::do_get_closure_list): New.
(_Jv_IndirectCompiledEngine::_Jv_IndirectCompiledEngine): Use it.
(_Jv_InterpreterEngine::do_get_closure_list): Declare.
(_Jv_InterpreterEngine::_Jv_InterpreterEngine): Use it.
* interpret.cc (FFI_PREP_RAW_CLOSURE): Use _loc variants.
(node_closure): Add closure list.
(_Jv_InterpMethod::ncode): Add jclass argument. Use
ffi_closure_alloc and the separate code pointer. Register the
closure for finalization.
(_Jv_JNIMethod::ncode): Likewise.
(_Jv_InterpreterEngine::do_create_ncode): Pass klass to ncode.
(_Jv_InterpreterEngine::do_get_closure_list): New.
* include/java-interp.h (_Jv_InterpMethod::ncode): Adjust.
(_Jv_InterpClass): Add closures field.
(_Jv_JNIMethod::ncode): Adjust.
* defineclass.cc (_Jv_ClassReader::handleCodeAttribute): Adjust.
(_Jv_ClassReader::handleMethodsEnd): Likewise.
* link.cc (struct method_closure): Add closure list.
(_Jv_Linker::create_error_method): Add jclass argument. Use
ffi_closure_alloc and the separate code pointer. Register the
closure for finalization.
(_Jv_Linker::link_symbol_table): Remove outdated comment about
sharing of otable and atable. Adjust.
* java/lang/reflect/natVMProxy.cc (ncode_closure): Add closure
list.
(ncode): Add jclass argument. Use ffi_closure_alloc and the
separate code pointer. Register the closure for finalization.
(java::lang::reflect::VMProxy::generateProxyClass): Adjust.
* testsuite/libjava.jar/TestClosureGC.java: New.
* testsuite/libjava.jar/TestClosureGC.out: New.
* testsuite/libjava.jar/TestClosureGC.xfail: New.
* testsuite/libjava.jar/TestClosureGC.jar: New.
2007-03-06 Kyle Galloway <kgallowa@redhat.com> 2007-03-06 Kyle Galloway <kgallowa@redhat.com>
* classpath/gnu/classpath/jdwp/exception/AbsentInformationException.java: New file. * classpath/gnu/classpath/jdwp/exception/AbsentInformationException.java: New file.
......
// boehm.cc - interface between libjava and Boehm GC. // boehm.cc - interface between libjava and Boehm GC.
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -380,6 +380,29 @@ _Jv_AllocRawObj (jsize size) ...@@ -380,6 +380,29 @@ _Jv_AllocRawObj (jsize size)
return (void *) GC_MALLOC (size ? size : 1); return (void *) GC_MALLOC (size ? size : 1);
} }
typedef _Jv_ClosureList *closure_list_pointer;
/* Release closures in a _Jv_ClosureList. */
static void
finalize_closure_list (GC_PTR obj, GC_PTR)
{
_Jv_ClosureList **clpp = (_Jv_ClosureList **)obj;
_Jv_ClosureList::releaseClosures (clpp);
}
/* Allocate a double-indirect pointer to a _Jv_ClosureList that will
get garbage-collected after this double-indirect pointer becomes
unreachable by any other objects, including finalizable ones. */
_Jv_ClosureList **
_Jv_ClosureListFinalizer ()
{
_Jv_ClosureList **clpp;
clpp = (_Jv_ClosureList **)_Jv_AllocBytes (sizeof (*clpp));
GC_REGISTER_FINALIZER_UNREACHABLE (clpp, finalize_closure_list,
NULL, NULL, NULL);
return clpp;
}
static void static void
call_finalizer (GC_PTR obj, GC_PTR client_data) call_finalizer (GC_PTR obj, GC_PTR client_data)
{ {
......
// defineclass.cc - defining a class from .class format. // defineclass.cc - defining a class from .class format.
/* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation /* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -1695,7 +1696,7 @@ void _Jv_ClassReader::handleCodeAttribute ...@@ -1695,7 +1696,7 @@ void _Jv_ClassReader::handleCodeAttribute
// call a static method of an interpreted class from precompiled // call a static method of an interpreted class from precompiled
// code without first resolving the class (that will happen // code without first resolving the class (that will happen
// during class initialization instead). // during class initialization instead).
method->self->ncode = method->ncode (); method->self->ncode = method->ncode (def);
} }
} }
...@@ -1740,7 +1741,7 @@ void _Jv_ClassReader::handleMethodsEnd () ...@@ -1740,7 +1741,7 @@ void _Jv_ClassReader::handleMethodsEnd ()
// interpreted class from precompiled code without // interpreted class from precompiled code without
// first resolving the class (that will happen // first resolving the class (that will happen
// during class initialization instead). // during class initialization instead).
method->ncode = m->ncode (); method->ncode = m->ncode (def);
} }
} }
} }
......
// execution.h - Execution engines. -*- c++ -*- // execution.h - Execution engines. -*- c++ -*-
/* Copyright (C) 2004, 2006 Free Software Foundation /* Copyright (C) 2004, 2006, 2007 Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -29,6 +29,7 @@ struct _Jv_ExecutionEngine ...@@ -29,6 +29,7 @@ struct _Jv_ExecutionEngine
_Jv_ResolvedMethod *(*resolve_method) (_Jv_Method *, jclass, _Jv_ResolvedMethod *(*resolve_method) (_Jv_Method *, jclass,
jboolean); jboolean);
void (*post_miranda_hook) (jclass); void (*post_miranda_hook) (jclass);
_Jv_ClosureList **(*get_closure_list) (jclass);
}; };
// This handles gcj-compiled code except that compiled with // This handles gcj-compiled code except that compiled with
...@@ -77,6 +78,11 @@ struct _Jv_CompiledEngine : public _Jv_ExecutionEngine ...@@ -77,6 +78,11 @@ struct _Jv_CompiledEngine : public _Jv_ExecutionEngine
// Not needed. // Not needed.
} }
static _Jv_ClosureList **do_get_closure_list (jclass)
{
return NULL;
}
_Jv_CompiledEngine () _Jv_CompiledEngine ()
{ {
unregister = do_unregister; unregister = do_unregister;
...@@ -87,6 +93,7 @@ struct _Jv_CompiledEngine : public _Jv_ExecutionEngine ...@@ -87,6 +93,7 @@ struct _Jv_CompiledEngine : public _Jv_ExecutionEngine
create_ncode = do_create_ncode; create_ncode = do_create_ncode;
resolve_method = do_resolve_method; resolve_method = do_resolve_method;
post_miranda_hook = do_post_miranda_hook; post_miranda_hook = do_post_miranda_hook;
get_closure_list = do_get_closure_list;
} }
// These operators make it so we don't have to link in libstdc++. // These operators make it so we don't have to link in libstdc++.
...@@ -105,6 +112,7 @@ class _Jv_IndirectCompiledClass ...@@ -105,6 +112,7 @@ class _Jv_IndirectCompiledClass
{ {
public: public:
void **field_initializers; void **field_initializers;
_Jv_ClosureList **closures;
}; };
// This handles gcj-compiled code compiled with -findirect-classes. // This handles gcj-compiled code compiled with -findirect-classes.
...@@ -114,14 +122,32 @@ struct _Jv_IndirectCompiledEngine : public _Jv_CompiledEngine ...@@ -114,14 +122,32 @@ struct _Jv_IndirectCompiledEngine : public _Jv_CompiledEngine
{ {
allocate_static_fields = do_allocate_static_fields; allocate_static_fields = do_allocate_static_fields;
allocate_field_initializers = do_allocate_field_initializers; allocate_field_initializers = do_allocate_field_initializers;
get_closure_list = do_get_closure_list;
}
static _Jv_IndirectCompiledClass *get_aux_info (jclass klass)
{
_Jv_IndirectCompiledClass *aux =
(_Jv_IndirectCompiledClass*)klass->aux_info;
if (!aux)
{
aux = (_Jv_IndirectCompiledClass*)
_Jv_AllocRawObj (sizeof (_Jv_IndirectCompiledClass));
klass->aux_info = aux;
}
return aux;
} }
static void do_allocate_field_initializers (jclass klass) static void do_allocate_field_initializers (jclass klass)
{ {
_Jv_IndirectCompiledClass *aux _Jv_IndirectCompiledClass *aux = get_aux_info (klass);
= (_Jv_IndirectCompiledClass*) if (!aux)
{
aux = (_Jv_IndirectCompiledClass*)
_Jv_AllocRawObj (sizeof (_Jv_IndirectCompiledClass)); _Jv_AllocRawObj (sizeof (_Jv_IndirectCompiledClass));
klass->aux_info = aux; klass->aux_info = aux;
}
aux->field_initializers = (void **)_Jv_Malloc (klass->field_count aux->field_initializers = (void **)_Jv_Malloc (klass->field_count
* sizeof (void*)); * sizeof (void*));
...@@ -172,6 +198,16 @@ struct _Jv_IndirectCompiledEngine : public _Jv_CompiledEngine ...@@ -172,6 +198,16 @@ struct _Jv_IndirectCompiledEngine : public _Jv_CompiledEngine
} }
_Jv_Free (aux->field_initializers); _Jv_Free (aux->field_initializers);
} }
static _Jv_ClosureList **do_get_closure_list (jclass klass)
{
_Jv_IndirectCompiledClass *aux = get_aux_info (klass);
if (!aux->closures)
aux->closures = _Jv_ClosureListFinalizer ();
return aux->closures;
}
}; };
...@@ -203,6 +239,8 @@ class _Jv_InterpreterEngine : public _Jv_ExecutionEngine ...@@ -203,6 +239,8 @@ class _Jv_InterpreterEngine : public _Jv_ExecutionEngine
static void do_post_miranda_hook (jclass); static void do_post_miranda_hook (jclass);
static _Jv_ClosureList **do_get_closure_list (jclass klass);
_Jv_InterpreterEngine () _Jv_InterpreterEngine ()
{ {
unregister = do_unregister; unregister = do_unregister;
...@@ -213,6 +251,7 @@ class _Jv_InterpreterEngine : public _Jv_ExecutionEngine ...@@ -213,6 +251,7 @@ class _Jv_InterpreterEngine : public _Jv_ExecutionEngine
create_ncode = do_create_ncode; create_ncode = do_create_ncode;
resolve_method = do_resolve_method; resolve_method = do_resolve_method;
post_miranda_hook = do_post_miranda_hook; post_miranda_hook = do_post_miranda_hook;
get_closure_list = do_get_closure_list;
} }
// These operators make it so we don't have to link in libstdc++. // These operators make it so we don't have to link in libstdc++.
......
...@@ -202,7 +202,7 @@ class _Jv_InterpMethod : public _Jv_MethodBase ...@@ -202,7 +202,7 @@ class _Jv_InterpMethod : public _Jv_MethodBase
} }
// return the method's invocation pointer (a stub). // return the method's invocation pointer (a stub).
void *ncode (); void *ncode (jclass);
void compile (const void * const *); void compile (const void * const *);
static void run_normal (ffi_cif*, void*, ffi_raw*, void*); static void run_normal (ffi_cif*, void*, ffi_raw*, void*);
...@@ -293,6 +293,7 @@ class _Jv_InterpClass ...@@ -293,6 +293,7 @@ class _Jv_InterpClass
_Jv_MethodBase **interpreted_methods; _Jv_MethodBase **interpreted_methods;
_Jv_ushort *field_initializers; _Jv_ushort *field_initializers;
jstring source_file_name; jstring source_file_name;
_Jv_ClosureList **closures;
friend class _Jv_ClassReader; friend class _Jv_ClassReader;
friend class _Jv_InterpMethod; friend class _Jv_InterpMethod;
...@@ -341,7 +342,7 @@ class _Jv_JNIMethod : public _Jv_MethodBase ...@@ -341,7 +342,7 @@ class _Jv_JNIMethod : public _Jv_MethodBase
// This function is used when making a JNI call from the interpreter. // This function is used when making a JNI call from the interpreter.
static void call (ffi_cif *, void *, ffi_raw *, void *); static void call (ffi_cif *, void *, ffi_raw *, void *);
void *ncode (); void *ncode (jclass);
friend class _Jv_ClassReader; friend class _Jv_ClassReader;
friend class _Jv_InterpreterEngine; friend class _Jv_InterpreterEngine;
......
...@@ -288,7 +288,7 @@ private: ...@@ -288,7 +288,7 @@ private:
_Jv_Utf8Const *method_signature, _Jv_Utf8Const *method_signature,
jclass *found_class, jclass *found_class,
bool check_perms = true); bool check_perms = true);
static void *create_error_method(_Jv_Utf8Const *); static void *create_error_method(_Jv_Utf8Const *, jclass);
/* The least significant bit of the signature pointer in a symbol /* The least significant bit of the signature pointer in a symbol
table is set to 1 by the compiler if the reference is "special", table is set to 1 by the compiler if the reference is "special",
...@@ -341,6 +341,10 @@ void *_Jv_AllocBytes (jsize size) __attribute__((__malloc__)); ...@@ -341,6 +341,10 @@ void *_Jv_AllocBytes (jsize size) __attribute__((__malloc__));
/* Allocate space for a new non-Java object, which does not have the usual /* Allocate space for a new non-Java object, which does not have the usual
Java object header but may contain pointers to other GC'ed objects. */ Java object header but may contain pointers to other GC'ed objects. */
void *_Jv_AllocRawObj (jsize size) __attribute__((__malloc__)); void *_Jv_AllocRawObj (jsize size) __attribute__((__malloc__));
/* Allocate a double-indirect pointer to a _Jv_ClosureList such that
the _Jv_ClosureList gets automatically finalized when it is no
longer reachable, not even by other finalizable objects. */
_Jv_ClosureList **_Jv_ClosureListFinalizer (void) __attribute__((__malloc__));
/* Explicitly throw an out-of-memory exception. */ /* Explicitly throw an out-of-memory exception. */
void _Jv_ThrowNoMemory() __attribute__((__noreturn__)); void _Jv_ThrowNoMemory() __attribute__((__noreturn__));
/* Allocate an object with a single pointer. The first word is reserved /* Allocate an object with a single pointer. The first word is reserved
......
...@@ -1255,10 +1255,10 @@ _Jv_init_cif (_Jv_Utf8Const* signature, ...@@ -1255,10 +1255,10 @@ _Jv_init_cif (_Jv_Utf8Const* signature,
} }
#if FFI_NATIVE_RAW_API #if FFI_NATIVE_RAW_API
# define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure # define FFI_PREP_RAW_CLOSURE ffi_prep_raw_closure_loc
# define FFI_RAW_SIZE ffi_raw_size # define FFI_RAW_SIZE ffi_raw_size
#else #else
# define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure # define FFI_PREP_RAW_CLOSURE ffi_prep_java_raw_closure_loc
# define FFI_RAW_SIZE ffi_java_raw_size # define FFI_RAW_SIZE ffi_java_raw_size
#endif #endif
...@@ -1269,6 +1269,7 @@ _Jv_init_cif (_Jv_Utf8Const* signature, ...@@ -1269,6 +1269,7 @@ _Jv_init_cif (_Jv_Utf8Const* signature,
typedef struct { typedef struct {
ffi_raw_closure closure; ffi_raw_closure closure;
_Jv_ClosureList list;
ffi_cif cif; ffi_cif cif;
ffi_type *arg_types[0]; ffi_type *arg_types[0];
} ncode_closure; } ncode_closure;
...@@ -1276,7 +1277,7 @@ typedef struct { ...@@ -1276,7 +1277,7 @@ typedef struct {
typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*); typedef void (*ffi_closure_fun) (ffi_cif*,void*,ffi_raw*,void*);
void * void *
_Jv_InterpMethod::ncode () _Jv_InterpMethod::ncode (jclass klass)
{ {
using namespace java::lang::reflect; using namespace java::lang::reflect;
...@@ -1286,9 +1287,12 @@ _Jv_InterpMethod::ncode () ...@@ -1286,9 +1287,12 @@ _Jv_InterpMethod::ncode ()
jboolean staticp = (self->accflags & Modifier::STATIC) != 0; jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
int arg_count = _Jv_count_arguments (self->signature, staticp); int arg_count = _Jv_count_arguments (self->signature, staticp);
void *code;
ncode_closure *closure = ncode_closure *closure =
(ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure)
+ arg_count * sizeof (ffi_type*)); + arg_count * sizeof (ffi_type*),
&code);
closure->list.registerClosure (klass, closure);
_Jv_init_cif (self->signature, _Jv_init_cif (self->signature,
arg_count, arg_count,
...@@ -1341,9 +1345,11 @@ _Jv_InterpMethod::ncode () ...@@ -1341,9 +1345,11 @@ _Jv_InterpMethod::ncode ()
FFI_PREP_RAW_CLOSURE (&closure->closure, FFI_PREP_RAW_CLOSURE (&closure->closure,
&closure->cif, &closure->cif,
fun, fun,
(void*)this); (void*)this,
code);
self->ncode = code;
self->ncode = (void*)closure;
return self->ncode; return self->ncode;
} }
...@@ -1540,7 +1546,7 @@ _Jv_InterpMethod::set_insn (jlong index, pc_t insn) ...@@ -1540,7 +1546,7 @@ _Jv_InterpMethod::set_insn (jlong index, pc_t insn)
} }
void * void *
_Jv_JNIMethod::ncode () _Jv_JNIMethod::ncode (jclass klass)
{ {
using namespace java::lang::reflect; using namespace java::lang::reflect;
...@@ -1550,9 +1556,12 @@ _Jv_JNIMethod::ncode () ...@@ -1550,9 +1556,12 @@ _Jv_JNIMethod::ncode ()
jboolean staticp = (self->accflags & Modifier::STATIC) != 0; jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
int arg_count = _Jv_count_arguments (self->signature, staticp); int arg_count = _Jv_count_arguments (self->signature, staticp);
void *code;
ncode_closure *closure = ncode_closure *closure =
(ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure)
+ arg_count * sizeof (ffi_type*)); + arg_count * sizeof (ffi_type*),
&code);
closure->list.registerClosure (klass, closure);
ffi_type *rtype; ffi_type *rtype;
_Jv_init_cif (self->signature, _Jv_init_cif (self->signature,
...@@ -1594,9 +1603,10 @@ _Jv_JNIMethod::ncode () ...@@ -1594,9 +1603,10 @@ _Jv_JNIMethod::ncode ()
FFI_PREP_RAW_CLOSURE (&closure->closure, FFI_PREP_RAW_CLOSURE (&closure->closure,
&closure->cif, &closure->cif,
fun, fun,
(void*) this); (void*) this,
code);
self->ncode = (void *) closure; self->ncode = code;
return self->ncode; return self->ncode;
} }
...@@ -1657,16 +1667,27 @@ _Jv_InterpreterEngine::do_create_ncode (jclass klass) ...@@ -1657,16 +1667,27 @@ _Jv_InterpreterEngine::do_create_ncode (jclass klass)
// cases. Well, we can't, because we don't allocate these // cases. Well, we can't, because we don't allocate these
// objects using `new', and thus they don't get a vtable. // objects using `new', and thus they don't get a vtable.
_Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth); _Jv_JNIMethod *jnim = reinterpret_cast<_Jv_JNIMethod *> (imeth);
klass->methods[i].ncode = jnim->ncode (); klass->methods[i].ncode = jnim->ncode (klass);
} }
else if (imeth != 0) // it could be abstract else if (imeth != 0) // it could be abstract
{ {
_Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth); _Jv_InterpMethod *im = reinterpret_cast<_Jv_InterpMethod *> (imeth);
klass->methods[i].ncode = im->ncode (); klass->methods[i].ncode = im->ncode (klass);
} }
} }
} }
_Jv_ClosureList **
_Jv_InterpreterEngine::do_get_closure_list (jclass klass)
{
_Jv_InterpClass *iclass = (_Jv_InterpClass *) klass->aux_info;
if (!iclass->closures)
iclass->closures = _Jv_ClosureListFinalizer ();
return iclass->closures;
}
void void
_Jv_InterpreterEngine::do_allocate_static_fields (jclass klass, _Jv_InterpreterEngine::do_allocate_static_fields (jclass klass,
int pointer_size, int pointer_size,
......
...@@ -105,6 +105,15 @@ class _Jv_InterpClass; ...@@ -105,6 +105,15 @@ class _Jv_InterpClass;
class _Jv_InterpMethod; class _Jv_InterpMethod;
#endif #endif
class _Jv_ClosureList
{
_Jv_ClosureList *next;
void *ptr;
public:
void registerClosure (jclass klass, void *ptr);
static void releaseClosures (_Jv_ClosureList **closures);
};
struct _Jv_Constants struct _Jv_Constants
{ {
jint size; jint size;
...@@ -632,6 +641,7 @@ private: ...@@ -632,6 +641,7 @@ private:
friend class ::_Jv_CompiledEngine; friend class ::_Jv_CompiledEngine;
friend class ::_Jv_IndirectCompiledEngine; friend class ::_Jv_IndirectCompiledEngine;
friend class ::_Jv_InterpreterEngine; friend class ::_Jv_InterpreterEngine;
friend class ::_Jv_ClosureList;
friend void ::_Jv_sharedlib_register_hook (jclass klass); friend void ::_Jv_sharedlib_register_hook (jclass klass);
......
...@@ -670,6 +670,28 @@ java::lang::Class::finalize (void) ...@@ -670,6 +670,28 @@ java::lang::Class::finalize (void)
engine->unregister(this); engine->unregister(this);
} }
void
_Jv_ClosureList::releaseClosures (_Jv_ClosureList **closures)
{
if (!closures)
return;
while (_Jv_ClosureList *current = *closures)
{
*closures = current->next;
ffi_closure_free (current->ptr);
}
}
void
_Jv_ClosureList::registerClosure (jclass klass, void *ptr)
{
_Jv_ClosureList **closures = klass->engine->get_closure_list (klass);
this->ptr = ptr;
this->next = *closures;
*closures = this;
}
// This implements the initialization process for a class. From Spec // This implements the initialization process for a class. From Spec
// section 12.4.2. // section 12.4.2.
void void
......
// natVMProxy.cc -- Implementation of VMProxy methods. // natVMProxy.cc -- Implementation of VMProxy methods.
/* Copyright (C) 2006 /* Copyright (C) 2006, 2007
Free Software Foundation Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -66,7 +66,7 @@ using namespace java::lang::reflect; ...@@ -66,7 +66,7 @@ using namespace java::lang::reflect;
using namespace java::lang; using namespace java::lang;
typedef void (*closure_fun) (ffi_cif*, void*, void**, void*); typedef void (*closure_fun) (ffi_cif*, void*, void**, void*);
static void *ncode (_Jv_Method *self, closure_fun fun); static void *ncode (jclass klass, _Jv_Method *self, closure_fun fun);
static void run_proxy (ffi_cif*, void*, void**, void*); static void run_proxy (ffi_cif*, void*, void**, void*);
typedef jobject invoke_t (jobject, Proxy *, Method *, JArray< jobject > *); typedef jobject invoke_t (jobject, Proxy *, Method *, JArray< jobject > *);
...@@ -165,7 +165,7 @@ java::lang::reflect::VMProxy::generateProxyClass ...@@ -165,7 +165,7 @@ java::lang::reflect::VMProxy::generateProxyClass
// the interfaces of which it is a proxy will also be reachable, // the interfaces of which it is a proxy will also be reachable,
// so this is safe. // so this is safe.
method = imethod; method = imethod;
method.ncode = ncode (&method, run_proxy); method.ncode = ncode (klass, &method, run_proxy);
method.accflags &= ~Modifier::ABSTRACT; method.accflags &= ~Modifier::ABSTRACT;
} }
...@@ -289,6 +289,7 @@ unbox (jobject o, jclass klass, void *rvalue, FFI_TYPE type) ...@@ -289,6 +289,7 @@ unbox (jobject o, jclass klass, void *rvalue, FFI_TYPE type)
typedef struct { typedef struct {
ffi_closure closure; ffi_closure closure;
_Jv_ClosureList list;
ffi_cif cif; ffi_cif cif;
_Jv_Method *self; _Jv_Method *self;
ffi_type *arg_types[0]; ffi_type *arg_types[0];
...@@ -366,16 +367,19 @@ run_proxy (ffi_cif *cif, ...@@ -366,16 +367,19 @@ run_proxy (ffi_cif *cif,
// the address of its closure. // the address of its closure.
static void * static void *
ncode (_Jv_Method *self, closure_fun fun) ncode (jclass klass, _Jv_Method *self, closure_fun fun)
{ {
using namespace java::lang::reflect; using namespace java::lang::reflect;
jboolean staticp = (self->accflags & Modifier::STATIC) != 0; jboolean staticp = (self->accflags & Modifier::STATIC) != 0;
int arg_count = _Jv_count_arguments (self->signature, staticp); int arg_count = _Jv_count_arguments (self->signature, staticp);
void *code;
ncode_closure *closure = ncode_closure *closure =
(ncode_closure*)_Jv_AllocBytes (sizeof (ncode_closure) (ncode_closure*)ffi_closure_alloc (sizeof (ncode_closure)
+ arg_count * sizeof (ffi_type*)); + arg_count * sizeof (ffi_type*),
&code);
closure->list.registerClosure (klass, closure);
_Jv_init_cif (self->signature, _Jv_init_cif (self->signature,
arg_count, arg_count,
...@@ -387,11 +391,12 @@ ncode (_Jv_Method *self, closure_fun fun) ...@@ -387,11 +391,12 @@ ncode (_Jv_Method *self, closure_fun fun)
JvAssert ((self->accflags & Modifier::NATIVE) == 0); JvAssert ((self->accflags & Modifier::NATIVE) == 0);
ffi_prep_closure (&closure->closure, ffi_prep_closure_loc (&closure->closure,
&closure->cif, &closure->cif,
fun, fun,
(void*)closure); code,
code);
self->ncode = (void*)closure; self->ncode = code;
return self->ncode; return self->ncode;
} }
...@@ -1022,15 +1022,17 @@ struct method_closure ...@@ -1022,15 +1022,17 @@ struct method_closure
// be the same as the address of the overall structure. This is due // be the same as the address of the overall structure. This is due
// to disabling interior pointers in the GC. // to disabling interior pointers in the GC.
ffi_closure closure; ffi_closure closure;
_Jv_ClosureList list;
ffi_cif cif; ffi_cif cif;
ffi_type *arg_types[1]; ffi_type *arg_types[1];
}; };
void * void *
_Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name, jclass klass)
{ {
void *code;
method_closure *closure method_closure *closure
= (method_closure *) _Jv_AllocBytes(sizeof (method_closure)); = (method_closure *)ffi_closure_alloc (sizeof (method_closure), &code);
closure->arg_types[0] = &ffi_type_void; closure->arg_types[0] = &ffi_type_void;
...@@ -1042,13 +1044,18 @@ _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) ...@@ -1042,13 +1044,18 @@ _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name)
1, 1,
&ffi_type_void, &ffi_type_void,
closure->arg_types) == FFI_OK closure->arg_types) == FFI_OK
&& ffi_prep_closure (&closure->closure, && ffi_prep_closure_loc (&closure->closure,
&closure->cif, &closure->cif,
_Jv_ThrowNoClassDefFoundErrorTrampoline, _Jv_ThrowNoClassDefFoundErrorTrampoline,
class_name) == FFI_OK) class_name,
return &closure->closure; code) == FFI_OK)
{
closure->list.registerClosure (klass, closure);
return code;
}
else else
{ {
ffi_closure_free (closure);
java::lang::StringBuffer *buffer = new java::lang::StringBuffer(); java::lang::StringBuffer *buffer = new java::lang::StringBuffer();
buffer->append(JvNewStringLatin1("Error setting up FFI closure" buffer->append(JvNewStringLatin1("Error setting up FFI closure"
" for static method of" " for static method of"
...@@ -1059,7 +1066,7 @@ _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name) ...@@ -1059,7 +1066,7 @@ _Jv_Linker::create_error_method (_Jv_Utf8Const *class_name)
} }
#else #else
void * void *
_Jv_Linker::create_error_method (_Jv_Utf8Const *) _Jv_Linker::create_error_method (_Jv_Utf8Const *, jclass)
{ {
// Codepath for platforms which do not support (or want) libffi. // Codepath for platforms which do not support (or want) libffi.
// You have to accept that it is impossible to provide the name // You have to accept that it is impossible to provide the name
...@@ -1090,8 +1097,6 @@ static bool debug_link = false; ...@@ -1090,8 +1097,6 @@ static bool debug_link = false;
// at the corresponding position in the virtual method offset table // at the corresponding position in the virtual method offset table
// (klass->otable). // (klass->otable).
// The same otable and atable may be shared by many classes.
// This must be called while holding the class lock. // This must be called while holding the class lock.
void void
...@@ -1242,13 +1247,15 @@ _Jv_Linker::link_symbol_table (jclass klass) ...@@ -1242,13 +1247,15 @@ _Jv_Linker::link_symbol_table (jclass klass)
// NullPointerException // NullPointerException
klass->atable->addresses[index] = NULL; klass->atable->addresses[index] = NULL;
bool use_error_method = false;
// If the target class is missing we prepare a function call // If the target class is missing we prepare a function call
// that throws a NoClassDefFoundError and store the address of // that throws a NoClassDefFoundError and store the address of
// that newly prepared method in the atable. The user can run // that newly prepared method in the atable. The user can run
// code in classes where the missing class is part of the // code in classes where the missing class is part of the
// execution environment as long as it is never referenced. // execution environment as long as it is never referenced.
if (target_class == NULL) if (target_class == NULL)
klass->atable->addresses[index] = create_error_method(sym.class_name); use_error_method = true;
// We're looking for a static field or a static method, and we // We're looking for a static field or a static method, and we
// can tell which is needed by looking at the signature. // can tell which is needed by looking at the signature.
else if (signature->first() == '(' && signature->len() >= 2) else if (signature->first() == '(' && signature->len() >= 2)
...@@ -1296,12 +1303,16 @@ _Jv_Linker::link_symbol_table (jclass klass) ...@@ -1296,12 +1303,16 @@ _Jv_Linker::link_symbol_table (jclass klass)
} }
} }
else else
use_error_method = true;
if (use_error_method)
klass->atable->addresses[index] klass->atable->addresses[index]
= create_error_method(sym.class_name); = create_error_method(sym.class_name, klass);
continue; continue;
} }
// Try fields only if the target class exists. // Try fields only if the target class exists.
if (target_class != NULL) if (target_class != NULL)
{ {
......
// nogc.cc - Implement null garbage collector. // nogc.cc - Implement null garbage collector.
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006 Free Software Foundation /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2006, 2007
Free Software Foundation
This file is part of libgcj. This file is part of libgcj.
...@@ -71,6 +72,14 @@ _Jv_AllocRawObj (jsize size) ...@@ -71,6 +72,14 @@ _Jv_AllocRawObj (jsize size)
return calloc (size, 1); return calloc (size, 1);
} }
_Jv_ClosureList **
_Jv_ClosureListFinalizer ()
{
_Jv_ClosureList **clpp;
clpp = (_Jv_ClosureList **)_Jv_AllocBytes (sizeof (*clpp));
return clpp;
}
void void
_Jv_RegisterFinalizer (void *, _Jv_FinalizerFunc *) _Jv_RegisterFinalizer (void *, _Jv_FinalizerFunc *)
{ {
......
/* Verify that libffi closures aren't deallocated too early.
Copyright (C) 2007 Free Software Foundation, Inc
Contributed by Alexandre Oliva <aoliva@redhat.com>
If libffi closures are released too early, we lose.
*/
import java.util.HashSet;
public class TestClosureGC {
public static String objId (Object obj) {
return obj + "/"
+ Integer.toHexString(obj.getClass().getClassLoader().hashCode());
}
public static class cld extends java.net.URLClassLoader {
static final Object obj = new cl0();
public cld () throws Exception {
super(new java.net.URL[] { });
/* System.out.println (objId (this) + " created"); */
}
public void finalize () {
/* System.out.println (objId (this) + " finalized"); */
}
public String toString () {
return this.getClass().getName() + "@"
+ Integer.toHexString (hashCode ());
}
public Class loadClass (String name) throws ClassNotFoundException {
try {
java.io.InputStream IS = getSystemResourceAsStream
(name + ".class");
int maxsz = 1024, readsz = 0;
byte buf[] = new byte[maxsz];
for(;;) {
int readnow = IS.read (buf, readsz, maxsz - readsz);
if (readnow <= 0)
break;
readsz += readnow;
if (readsz == maxsz) {
byte newbuf[] = new byte[maxsz *= 2];
System.arraycopy (buf, 0, newbuf, 0, readsz);
buf = newbuf;
}
}
return defineClass (name, buf, 0, readsz);
} catch (Exception e) {
return super.loadClass (name);
}
}
}
public static class cl0 {
public cl0 () {
/* System.out.println (objId (this) + " created"); */
}
public void finalize () {
/* System.out.println (objId (this) + " finalized"); */
}
}
public static class cl1 {
final HashSet hs;
static final Object obj = new cl0();
public cl1 (final HashSet hs) {
this.hs = hs;
/* System.out.println (objId (this) + " created"); */
}
public void finalize () {
/* System.out.println (objId (this) + " finalized"); */
}
}
public static class cl2 {
final HashSet hs;
static final Object obj = new cl0();
public cl2 (final HashSet hs) {
this.hs = hs;
/* System.out.println (objId (this) + " created"); */
}
public void finalize () {
/* System.out.println (objId (this) + " finalized"); */
hs.add(this);
hs.add(new cl0());
}
}
static final HashSet hs = new HashSet();
static final Object obj = new cl0();
public static void main(String[] argv) throws Exception {
{
Class[] hscs = { HashSet.class };
Object[] hsos = { hs };
new cld().loadClass ("TestClosureGC$cl1").
getConstructor (hscs).newInstance (hsos);
new cld().loadClass ("TestClosureGC$cl2").
getConstructor (hscs).newInstance (hsos);
new cld().loadClass ("TestClosureGC$cl1").
getConstructor (hscs).newInstance (hsos);
new cld().loadClass ("TestClosureGC$cl1").
getConstructor (hscs).newInstance (hsos);
}
for (int i = 1; i <= 5; i++) {
/* System.out.println ("Will run GC and finalization " + i); */
System.gc ();
Thread.sleep (100);
System.runFinalization ();
Thread.sleep (100);
if (hs.isEmpty ())
continue;
java.util.Iterator it = hs.iterator ();
while (it.hasNext ()) {
Object obj = it.next();
/* System.out.println (objId (obj) + " in ht, removing"); */
it.remove ();
}
}
System.out.println ("ok");
}
}
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