There are canned sequences for 'n' pointer values in registers.
-------------------------------------------------------------------------- */
-INFO_TABLE_RET( stg_enter, 1/*framesize*/, 0/*bitmap*/, RET_SMALL)
+INFO_TABLE_RET( stg_enter, RET_SMALL, "ptr" W_ unused)
{
R1 = Sp(1);
Sp_adj(2);
/*-- void return ------------------------------------------------------------ */
-INFO_TABLE_RET( stg_gc_void, 0/*framesize*/, 0/*bitmap*/, RET_SMALL)
+INFO_TABLE_RET( stg_gc_void, RET_SMALL)
{
Sp_adj(1);
jump %ENTRY_CODE(Sp(0));
/*-- R1 is boxed/unpointed -------------------------------------------------- */
-INFO_TABLE_RET( stg_gc_unpt_r1, 1/*framesize*/, 0/*bitmap*/, RET_SMALL)
+INFO_TABLE_RET( stg_gc_unpt_r1, RET_SMALL, "ptr" W_ unused)
{
R1 = Sp(1);
Sp_adj(2);
/*-- R1 is unboxed -------------------------------------------------- */
/* the 1 is a bitmap - i.e. 1 non-pointer word on the stack. */
-INFO_TABLE_RET( stg_gc_unbx_r1, 1/*framesize*/, 1/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_gc_unbx_r1, RET_SMALL, W_ unused )
{
R1 = Sp(1);
Sp_adj(2);
/*-- F1 contains a float ------------------------------------------------- */
-INFO_TABLE_RET( stg_gc_f1, 1/*framesize*/, 1/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_gc_f1, RET_SMALL, F_ unused )
{
F1 = F_[Sp+WDS(1)];
Sp_adj(2);
/*-- D1 contains a double ------------------------------------------------- */
-/* we support doubles of either 1 or 2 words in size */
-
-#if SIZEOF_DOUBLE == SIZEOF_VOID_P
-# define DBL_BITMAP 1
-# define DBL_WORDS 1
-#else
-# define DBL_BITMAP 3
-# define DBL_WORDS 2
-#endif
-
-INFO_TABLE_RET( stg_gc_d1, DBL_WORDS/*framesize*/, DBL_BITMAP/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_gc_d1, RET_SMALL, D_ unused )
{
D1 = D_[Sp + WDS(1)];
Sp = Sp + WDS(1) + SIZEOF_StgDouble;
/*-- L1 contains an int64 ------------------------------------------------- */
-/* we support int64s of either 1 or 2 words in size */
-
-#if SIZEOF_VOID_P == 8
-# define LLI_BITMAP 1
-# define LLI_WORDS 1
-#else
-# define LLI_BITMAP 3
-# define LLI_WORDS 2
-#endif
-
-INFO_TABLE_RET( stg_gc_l1, LLI_WORDS/*framesize*/, LLI_BITMAP/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_gc_l1, RET_SMALL, L_ unused )
{
L1 = L_[Sp + WDS(1)];
Sp_adj(1) + SIZEOF_StgWord64;
/*-- Unboxed tuple return, one pointer (unregisterised build only) ---------- */
-INFO_TABLE_RET( stg_ut_1_0_unreg, 1/*size*/, 0/*BITMAP*/, RET_SMALL )
+INFO_TABLE_RET( stg_ut_1_0_unreg, RET_SMALL, "ptr" W_ unused )
{
Sp_adj(1);
// one ptr is on the stack (Sp(0))
+---------------------+
| f_closure |
+---------------------+
+ | tag |
+ +- - - - - - - - - - -+
| size |
+---------------------+
| stg_gc_fun_info |
W_ size;
W_ info;
W_ type;
+ W_ tag;
+ W_ ret_fun;
- info = %GET_FUN_INFO(R1);
+ tag = GETTAG(R1);
+ info = %GET_FUN_INFO(UNTAG(R1));
// cache the size
type = TO_W_(StgFunInfoExtra_fun_type(info));
#ifdef TABLES_NEXT_TO_CODE
// bitmap field holds an offset
size = StgLargeBitmap_size( StgFunInfoExtra_bitmap(info)
- + %GET_ENTRY(R1) /* ### */ );
+ + %GET_ENTRY(UNTAG(R1)) /* ### */ );
#else
size = StgLargeBitmap_size( StgFunInfoExtra_bitmap(info) );
#endif
#ifdef NO_ARG_REGS
// we don't have to save any registers away
Sp_adj(-3);
- Sp(2) = R1;
- Sp(1) = size;
Sp(0) = stg_gc_fun_info;
+ ret_fun = Sp;
+ StgRetFun_size(ret_fun) = HALF_W_(size);
+ StgRetFun_tag(ret_fun) = HALF_W_(tag);
+ StgRetFun_fun(ret_fun) = R1;
GC_GENERIC
#else
W_ type;
if (type == ARG_GEN || type == ARG_GEN_BIG) {
// regs already saved by the heap check code
Sp_adj(-3);
- Sp(2) = R1;
- Sp(1) = size;
Sp(0) = stg_gc_fun_info;
+ ret_fun = Sp;
+ StgRetFun_size(ret_fun) = HALF_W_(size);
+ StgRetFun_tag(ret_fun) = HALF_W_(tag);
+ StgRetFun_fun(ret_fun) = R1;
// DEBUG_ONLY(foreign "C" debugBelch("stg_fun_gc_gen(ARG_GEN)"););
GC_GENERIC
} else {
appropriately. The stack layout is given above.
-------------------------------------------------------------------------- */
-INFO_TABLE_RET( stg_gc_fun, 0/*framesize*/, 0/*bitmap*/, RET_FUN )
+INFO_TABLE_RET( stg_gc_fun, RET_FUN )
{
- R1 = Sp(2);
+ // Grab the fun, but remember to add in the tag. The GC doesn't
+ // guarantee to retain the tag on the pointer, so we have to do
+ // it manually, because the function entry code assumes it.
+ W_ ret_fun;
+ ret_fun = Sp;
+ R1 = StgRetFun_fun(ret_fun) | TO_W_(StgRetFun_tag(ret_fun));
Sp_adj(3);
#ifdef NO_ARG_REGS
// Minor optimisation: there are no argument registers to load up,
// so we can just jump straight to the function's entry point.
- jump %GET_ENTRY(R1);
+ jump %GET_ENTRY(UNTAG(R1));
#else
W_ info;
W_ type;
- info = %GET_FUN_INFO(R1);
+ info = %GET_FUN_INFO(UNTAG(R1));
type = TO_W_(StgFunInfoExtra_fun_type(info));
if (type == ARG_GEN || type == ARG_GEN_BIG) {
jump StgFunInfoExtra_slow_apply(info);
Sp(1) = R9; /* liveness mask */ \
Sp(0) = stg_gc_gen_info;
-INFO_TABLE_RET( stg_gc_gen, 0/*framesize*/, 0/*bitmap*/, RET_DYN )
+INFO_TABLE_RET( stg_gc_gen, RET_DYN )
/* bitmap in the above info table is unused, the real one is on the stack. */
{
RESTORE_EVERYTHING;
*
* -------------------------------------------------------------------------- */
-INFO_TABLE_RET( stg_block_takemvar, 1/*framesize*/, 0/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_block_takemvar, RET_SMALL, "ptr" W_ unused )
{
R1 = Sp(1);
Sp_adj(2);
stg_block_takemvar_finally
{
#ifdef THREADED_RTS
- foreign "C" unlockClosure(R3 "ptr", stg_EMPTY_MVAR_info);
+ unlockClosure(R3, stg_EMPTY_MVAR_info);
#endif
jump StgReturn;
}
BLOCK_BUT_FIRST(stg_block_takemvar_finally);
}
-INFO_TABLE_RET( stg_block_putmvar, 2/*framesize*/, 0/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_block_putmvar, RET_SMALL, "ptr" W_ unused1, "ptr" W_ unused2 )
{
R2 = Sp(2);
R1 = Sp(1);
stg_block_putmvar_finally
{
#ifdef THREADED_RTS
- foreign "C" unlockClosure(R3 "ptr", stg_FULL_MVAR_info);
+ unlockClosure(R3, stg_FULL_MVAR_info);
#endif
jump StgReturn;
}
BLOCK_BUT_FIRST(stg_block_blackhole_finally);
}
+INFO_TABLE_RET( stg_block_throwto, RET_SMALL, "ptr" W_ unused, "ptr" W_ unused )
+{
+ R2 = Sp(2);
+ R1 = Sp(1);
+ Sp_adj(3);
+ jump killThreadzh_fast;
+}
+
+stg_block_throwto_finally
+{
+#ifdef THREADED_RTS
+ foreign "C" throwToReleaseTarget (R3 "ptr");
+#endif
+ jump StgReturn;
+}
+
+stg_block_throwto
+{
+ Sp_adj(-3);
+ Sp(2) = R2;
+ Sp(1) = R1;
+ Sp(0) = stg_block_throwto_info;
+ BLOCK_BUT_FIRST(stg_block_throwto_finally);
+}
+
#ifdef mingw32_HOST_OS
-INFO_TABLE_RET( stg_block_async, 0/*framesize*/, 0/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_block_async, RET_SMALL )
{
W_ ares;
W_ len, errC;
/* Used by threadDelay implementation; it would be desirable to get rid of
* this free()'ing void return continuation.
*/
-INFO_TABLE_RET( stg_block_async_void, 0/*framesize*/, 0/*bitmap*/, RET_SMALL )
+INFO_TABLE_RET( stg_block_async_void, RET_SMALL )
{
W_ ares;