summaryrefslogtreecommitdiff
path: root/rts/StgMiscClosures.cmm
diff options
context:
space:
mode:
authorSimon Marlow <marlowsd@gmail.com>2012-10-03 09:30:56 +0100
committerSimon Marlow <marlowsd@gmail.com>2012-10-08 09:04:40 +0100
commita7c0387d20c1c9994d1100b14fbb8fb4e28a259e (patch)
treeb95d0a512f951a4a463f1aa5178b0cd5c4fdb410 /rts/StgMiscClosures.cmm
parentaed37acd4d157791381800d5de960a2461bcbef3 (diff)
downloadhaskell-a7c0387d20c1c9994d1100b14fbb8fb4e28a259e.tar.gz
Produce new-style Cmm from the Cmm parser
The main change here is that the Cmm parser now allows high-level cmm code with argument-passing and function calls. For example: foo ( gcptr a, bits32 b ) { if (b > 0) { // we can make tail calls passing arguments: jump stg_ap_0_fast(a); } return (x,y); } More details on the new cmm syntax are in Note [Syntax of .cmm files] in CmmParse.y. The old syntax is still more-or-less supported for those occasional code fragments that really need to explicitly manipulate the stack. However there are a couple of differences: it is now obligatory to give a list of live GlobalRegs on every jump, e.g. jump %ENTRY_CODE(Sp(0)) [R1]; Again, more details in Note [Syntax of .cmm files]. I have rewritten most of the .cmm files in the RTS into the new syntax, except for AutoApply.cmm which is generated by the genapply program: this file could be generated in the new syntax instead and would probably be better off for it, but I ran out of enthusiasm. Some other changes in this batch: - The PrimOp calling convention is gone, primops now use the ordinary NativeNodeCall convention. This means that primops and "foreign import prim" code must be written in high-level cmm, but they can now take more than 10 arguments. - CmmSink now does constant-folding (should fix #7219) - .cmm files now go through the cmmPipeline, and as a result we generate better code in many cases. All the object files generated for the RTS .cmm files are now smaller. Performance should be better too, but I haven't measured it yet. - RET_DYN frames are removed from the RTS, lots of code goes away - we now have some more canned GC points to cover unboxed-tuples with 2-4 pointers, which will reduce code size a little.
Diffstat (limited to 'rts/StgMiscClosures.cmm')
-rw-r--r--rts/StgMiscClosures.cmm126
1 files changed, 81 insertions, 45 deletions
diff --git a/rts/StgMiscClosures.cmm b/rts/StgMiscClosures.cmm
index b99126187a..2985982d64 100644
--- a/rts/StgMiscClosures.cmm
+++ b/rts/StgMiscClosures.cmm
@@ -22,30 +22,36 @@ import LeaveCriticalSection;
Stack underflow
------------------------------------------------------------------------- */
-INFO_TABLE_RET (stg_stack_underflow_frame, UNDERFLOW_FRAME, P_ unused)
+INFO_TABLE_RET (stg_stack_underflow_frame, UNDERFLOW_FRAME,
+ W_ info_ptr, P_ unused)
+ /* no args => explicit stack */
{
W_ new_tso;
W_ ret_off;
+ SAVE_STGREGS
+
SAVE_THREAD_STATE();
("ptr" ret_off) = foreign "C" threadStackUnderflow(MyCapability(),
CurrentTSO);
LOAD_THREAD_STATE();
- jump %ENTRY_CODE(Sp(ret_off));
+ RESTORE_STGREGS
+
+ jump %ENTRY_CODE(Sp(ret_off)) [*]; // NB. all registers live!
}
/* ----------------------------------------------------------------------------
Restore a saved cost centre
------------------------------------------------------------------------- */
-INFO_TABLE_RET (stg_restore_cccs, RET_SMALL, W_ cccs)
+INFO_TABLE_RET (stg_restore_cccs, RET_SMALL, W_ info_ptr, W_ cccs)
{
#if defined(PROFILING)
CCCS = Sp(1);
#endif
Sp_adj(2);
- jump %ENTRY_CODE(Sp(0));
+ jump %ENTRY_CODE(Sp(0)) [*]; // NB. all registers live!
}
/* ----------------------------------------------------------------------------
@@ -53,10 +59,9 @@ INFO_TABLE_RET (stg_restore_cccs, RET_SMALL, W_ cccs)
------------------------------------------------------------------------- */
/* 9 bits of return code for constructors created by the interpreter. */
-stg_interp_constr_entry
+stg_interp_constr_entry (P_ ret)
{
- /* R1 points at the constructor */
- jump %ENTRY_CODE(Sp(0));
+ return (ret);
}
/* Some info tables to be used when compiled code returns a value to
@@ -94,76 +99,83 @@ stg_interp_constr_entry
*/
INFO_TABLE_RET( stg_ctoi_R1p, RET_BCO)
+ /* explicit stack */
{
Sp_adj(-2);
Sp(1) = R1;
Sp(0) = stg_enter_info;
- jump stg_yield_to_interpreter;
+ jump stg_yield_to_interpreter [];
}
/*
* When the returned value is a pointer, but unlifted, in R1 ...
*/
INFO_TABLE_RET( stg_ctoi_R1unpt, RET_BCO )
+ /* explicit stack */
{
Sp_adj(-2);
Sp(1) = R1;
- Sp(0) = stg_gc_unpt_r1_info;
- jump stg_yield_to_interpreter;
+ Sp(0) = stg_ret_p_info;
+ jump stg_yield_to_interpreter [];
}
/*
* When the returned value is a non-pointer in R1 ...
*/
INFO_TABLE_RET( stg_ctoi_R1n, RET_BCO )
+ /* explicit stack */
{
Sp_adj(-2);
Sp(1) = R1;
- Sp(0) = stg_gc_unbx_r1_info;
- jump stg_yield_to_interpreter;
+ Sp(0) = stg_ret_p_info;
+ jump stg_yield_to_interpreter [];
}
/*
* When the returned value is in F1
*/
INFO_TABLE_RET( stg_ctoi_F1, RET_BCO )
+ /* explicit stack */
{
Sp_adj(-2);
F_[Sp + WDS(1)] = F1;
- Sp(0) = stg_gc_f1_info;
- jump stg_yield_to_interpreter;
+ Sp(0) = stg_ret_f_info;
+ jump stg_yield_to_interpreter [];
}
/*
* When the returned value is in D1
*/
INFO_TABLE_RET( stg_ctoi_D1, RET_BCO )
+ /* explicit stack */
{
Sp_adj(-1) - SIZEOF_DOUBLE;
D_[Sp + WDS(1)] = D1;
- Sp(0) = stg_gc_d1_info;
- jump stg_yield_to_interpreter;
+ Sp(0) = stg_ret_d_info;
+ jump stg_yield_to_interpreter [];
}
/*
* When the returned value is in L1
*/
INFO_TABLE_RET( stg_ctoi_L1, RET_BCO )
+ /* explicit stack */
{
Sp_adj(-1) - 8;
L_[Sp + WDS(1)] = L1;
- Sp(0) = stg_gc_l1_info;
- jump stg_yield_to_interpreter;
+ Sp(0) = stg_ret_l_info;
+ jump stg_yield_to_interpreter [];
}
/*
* When the returned value is a void
*/
INFO_TABLE_RET( stg_ctoi_V, RET_BCO )
+ /* explicit stack */
{
Sp_adj(-1);
- Sp(0) = stg_gc_void_info;
- jump stg_yield_to_interpreter;
+ Sp(0) = stg_ret_v_info;
+ jump stg_yield_to_interpreter [];
}
/*
@@ -172,9 +184,10 @@ INFO_TABLE_RET( stg_ctoi_V, RET_BCO )
* stack.
*/
INFO_TABLE_RET( stg_apply_interp, RET_BCO )
+ /* explicit stack */
{
/* Just in case we end up in here... (we shouldn't) */
- jump stg_yield_to_interpreter;
+ jump stg_yield_to_interpreter [];
}
/* ----------------------------------------------------------------------------
@@ -182,12 +195,13 @@ INFO_TABLE_RET( stg_apply_interp, RET_BCO )
------------------------------------------------------------------------- */
INFO_TABLE_FUN( stg_BCO, 4, 0, BCO, "BCO", "BCO", ARG_BCO )
+ /* explicit stack */
{
/* entering a BCO means "apply it", same as a function */
Sp_adj(-2);
Sp(1) = R1;
Sp(0) = stg_apply_interp_info;
- jump stg_yield_to_interpreter;
+ jump stg_yield_to_interpreter [];
}
/* ----------------------------------------------------------------------------
@@ -201,30 +215,48 @@ INFO_TABLE_FUN( stg_BCO, 4, 0, BCO, "BCO", "BCO", ARG_BCO )
------------------------------------------------------------------------- */
INFO_TABLE(stg_IND,1,0,IND,"IND","IND")
+#if 0
+/*
+ This version in high-level cmm generates slightly less good code
+ than the low-level version below it. (ToDo)
+*/
+ (P_ node)
+{
+ TICK_ENT_DYN_IND(); /* tick */
+ node = UNTAG(StgInd_indirectee(node));
+ TICK_ENT_VIA_NODE();
+ jump %GET_ENTRY(node) (node);
+}
+#else
+ /* explicit stack */
{
TICK_ENT_DYN_IND(); /* tick */
R1 = UNTAG(StgInd_indirectee(R1));
TICK_ENT_VIA_NODE();
- jump %GET_ENTRY(R1);
+ jump %GET_ENTRY(R1) [R1];
}
+#endif
INFO_TABLE(stg_IND_direct,1,0,IND,"IND","IND")
+ (P_ node)
{
TICK_ENT_DYN_IND(); /* tick */
- R1 = StgInd_indirectee(R1);
+ node = StgInd_indirectee(node);
TICK_ENT_VIA_NODE();
- jump %ENTRY_CODE(Sp(0));
+ jump %ENTRY_CODE(Sp(0)) (node);
}
INFO_TABLE(stg_IND_STATIC,1,0,IND_STATIC,"IND_STATIC","IND_STATIC")
+ /* explicit stack */
{
TICK_ENT_STATIC_IND(); /* tick */
R1 = UNTAG(StgInd_indirectee(R1));
TICK_ENT_VIA_NODE();
- jump %GET_ENTRY(R1);
+ jump %GET_ENTRY(R1) [R1];
}
INFO_TABLE(stg_IND_PERM,1,0,IND_PERM,"IND_PERM","IND_PERM")
+ /* explicit stack */
{
/* Don't add INDs to granularity cost */
@@ -259,7 +291,7 @@ INFO_TABLE(stg_IND_PERM,1,0,IND_PERM,"IND_PERM","IND_PERM")
TICK_ENT_VIA_NODE();
#endif
- jump %GET_ENTRY(R1);
+ jump %GET_ENTRY(R1) [R1];
}
/* ----------------------------------------------------------------------------
@@ -272,16 +304,17 @@ INFO_TABLE(stg_IND_PERM,1,0,IND_PERM,"IND_PERM","IND_PERM")
------------------------------------------------------------------------- */
INFO_TABLE(stg_BLACKHOLE,1,0,BLACKHOLE,"BLACKHOLE","BLACKHOLE")
+ (P_ node)
{
- W_ r, p, info, bq, msg, owner, bd;
+ W_ r, info, owner, bd;
+ P_ p, bq, msg;
TICK_ENT_DYN_IND(); /* tick */
retry:
- p = StgInd_indirectee(R1);
+ p = StgInd_indirectee(node);
if (GETTAG(p) != 0) {
- R1 = p;
- jump %ENTRY_CODE(Sp(0));
+ return (p);
}
info = StgHeader_info(p);
@@ -296,33 +329,33 @@ retry:
info == stg_BLOCKING_QUEUE_CLEAN_info ||
info == stg_BLOCKING_QUEUE_DIRTY_info)
{
- ("ptr" msg) = foreign "C" allocate(MyCapability() "ptr",
- BYTES_TO_WDS(SIZEOF_MessageBlackHole)) [R1];
+ ("ptr" msg) = ccall allocate(MyCapability() "ptr",
+ BYTES_TO_WDS(SIZEOF_MessageBlackHole));
SET_HDR(msg, stg_MSG_BLACKHOLE_info, CCS_SYSTEM);
MessageBlackHole_tso(msg) = CurrentTSO;
- MessageBlackHole_bh(msg) = R1;
+ MessageBlackHole_bh(msg) = node;
- (r) = foreign "C" messageBlackHole(MyCapability() "ptr", msg "ptr") [R1];
+ (r) = ccall messageBlackHole(MyCapability() "ptr", msg "ptr");
if (r == 0) {
goto retry;
} else {
StgTSO_why_blocked(CurrentTSO) = BlockedOnBlackHole::I16;
StgTSO_block_info(CurrentTSO) = msg;
- jump stg_block_blackhole;
+ jump stg_block_blackhole(node);
}
}
else
{
- R1 = p;
- ENTER();
+ ENTER(p);
}
}
INFO_TABLE(__stg_EAGER_BLACKHOLE,1,0,BLACKHOLE,"BLACKHOLE","BLACKHOLE")
+ (P_ node)
{
- jump ENTRY_LBL(stg_BLACKHOLE);
+ jump ENTRY_LBL(stg_BLACKHOLE) (node);
}
// CAF_BLACKHOLE is allocated when entering a CAF. The reason it is
@@ -332,8 +365,9 @@ INFO_TABLE(__stg_EAGER_BLACKHOLE,1,0,BLACKHOLE,"BLACKHOLE","BLACKHOLE")
// evaluation by another thread (a BLACKHOLE). See threadPaused().
//
INFO_TABLE(stg_CAF_BLACKHOLE,1,0,BLACKHOLE,"BLACKHOLE","BLACKHOLE")
+ (P_ node)
{
- jump ENTRY_LBL(stg_BLACKHOLE);
+ jump ENTRY_LBL(stg_BLACKHOLE) (node);
}
INFO_TABLE(stg_BLOCKING_QUEUE_CLEAN,4,0,BLOCKING_QUEUE,"BLOCKING_QUEUE","BLOCKING_QUEUE")
@@ -349,6 +383,7 @@ INFO_TABLE(stg_BLOCKING_QUEUE_DIRTY,4,0,BLOCKING_QUEUE,"BLOCKING_QUEUE","BLOCKIN
------------------------------------------------------------------------- */
INFO_TABLE(stg_WHITEHOLE, 0,0, WHITEHOLE, "WHITEHOLE", "WHITEHOLE")
+ (P_ node)
{
#if defined(THREADED_RTS)
W_ info, i;
@@ -356,18 +391,18 @@ INFO_TABLE(stg_WHITEHOLE, 0,0, WHITEHOLE, "WHITEHOLE", "WHITEHOLE")
i = 0;
loop:
// spin until the WHITEHOLE is updated
- info = StgHeader_info(R1);
+ info = StgHeader_info(node);
if (info == stg_WHITEHOLE_info) {
i = i + 1;
if (i == SPIN_COUNT) {
i = 0;
- foreign "C" yieldThread() [R1];
+ ccall yieldThread();
}
goto loop;
}
- jump %ENTRY_CODE(info);
+ jump %ENTRY_CODE(info) (node);
#else
- foreign "C" barf("WHITEHOLE object entered!") never returns;
+ ccall barf("WHITEHOLE object entered!") never returns;
#endif
}
@@ -556,8 +591,9 @@ INFO_TABLE(stg_MUT_VAR_DIRTY, 1, 0, MUT_VAR_DIRTY, "MUT_VAR_DIRTY", "MUT_VAR_DIR
* ------------------------------------------------------------------------- */
INFO_TABLE( stg_dummy_ret, 0, 0, CONSTR_NOCAF_STATIC, "DUMMY_RET", "DUMMY_RET")
+ ()
{
- jump %ENTRY_CODE(Sp(0));
+ return ();
}
CLOSURE(stg_dummy_ret_closure,stg_dummy_ret);