summaryrefslogtreecommitdiff
path: root/rts/StgStdThunks.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/StgStdThunks.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/StgStdThunks.cmm')
-rw-r--r--rts/StgStdThunks.cmm302
1 files changed, 138 insertions, 164 deletions
diff --git a/rts/StgStdThunks.cmm b/rts/StgStdThunks.cmm
index 171ab52b96..0b69a9a279 100644
--- a/rts/StgStdThunks.cmm
+++ b/rts/StgStdThunks.cmm
@@ -11,6 +11,7 @@
* ---------------------------------------------------------------------------*/
#include "Cmm.h"
+#include "Updates.h"
/* -----------------------------------------------------------------------------
The code for a thunk that simply extracts a field from a
@@ -26,17 +27,15 @@
matching.
-------------------------------------------------------------------------- */
-#define WITHUPD_FRAME_SIZE (SIZEOF_StgUpdateFrame + SIZEOF_StgHeader)
-#define NOUPD_FRAME_SIZE (SIZEOF_StgHeader)
-
#ifdef PROFILING
-#define SAVE_CCCS(fs) StgHeader_ccs(Sp-fs) = CCCS
-#define GET_SAVED_CCCS CCCS = StgHeader_ccs(Sp)
-#define RET_PARAMS W_ unused1, W_ unused2
+#define RET_FIELDS(w_,info_ptr,ccs) \
+ w_ info_ptr, \
+ w_ ccs
+#define GET_SAVED_CCCS CCCS = ccs
#else
-#define SAVE_CCCS(fs) /* empty */
+#define RET_FIELDS(w_,info_ptr,ccs) \
+ w_ info_ptr
#define GET_SAVED_CCCS /* empty */
-#define RET_PARAMS
#endif
/*
@@ -56,42 +55,34 @@
// When profiling, we cannot shortcut by checking the tag,
// because LDV profiling relies on entering closures to mark them as
// "used".
-#define SEL_ENTER(offset) \
- R1 = UNTAG(R1); \
- jump %GET_ENTRY(R1);
+#define NEED_EVAL(__x__) 1
#else
-#define SEL_ENTER(offset) \
- if (GETTAG(R1) != 0) { \
- jump RET_LBL(stg_sel_ret_##offset##_upd); \
- } \
- jump %GET_ENTRY(R1);
+#define NEED_EVAL(__x__) GETTAG(__x__) == 0
#endif
#define SELECTOR_CODE_UPD(offset) \
- INFO_TABLE_RET(stg_sel_ret_##offset##_upd, RET_SMALL, RET_PARAMS) \
- { \
- R1 = StgClosure_payload(UNTAG(R1),offset); \
- GET_SAVED_CCCS; \
- Sp = Sp + SIZEOF_StgHeader; \
- ENTER(); \
- } \
- \
INFO_TABLE_SELECTOR(stg_sel_##offset##_upd, offset, THUNK_SELECTOR, "stg_sel_upd", "stg_sel_upd") \
- { \
- TICK_ENT_DYN_THK(); \
- STK_CHK_NP(WITHUPD_FRAME_SIZE); \
- UPD_BH_UPDATABLE(); \
- LDV_ENTER(R1); \
- PUSH_UPD_FRAME(Sp - SIZEOF_StgUpdateFrame, R1); \
- ENTER_CCS_THUNK(R1); \
- SAVE_CCCS(WITHUPD_FRAME_SIZE); \
- W_[Sp-WITHUPD_FRAME_SIZE] = stg_sel_ret_##offset##_upd_info; \
- Sp = Sp - WITHUPD_FRAME_SIZE; \
- R1 = StgThunk_payload(R1,0); \
- SEL_ENTER(offset); \
+ (P_ node) \
+ { \
+ P_ selectee, field; \
+ TICK_ENT_DYN_THK(); \
+ STK_CHK_NP(node); \
+ UPD_BH_UPDATABLE(node); \
+ LDV_ENTER(node); \
+ ENTER_CCS_THUNK(node); \
+ selectee = StgThunk_payload(node,0); \
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info,node)) { \
+ if (NEED_EVAL(selectee)) { \
+ (P_ constr) = call %GET_ENTRY(selectee) (selectee); \
+ selectee = constr; \
+ } \
+ field = StgClosure_payload(UNTAG(selectee),offset); \
+ jump stg_ap_0_fast(field); \
+ } \
}
- /* NOTE: no need to ENTER() here, we know the closure cannot evaluate to a function,
- because we're going to do a field selection on the result. */
+ /* NOTE: no need to ENTER() here, we know the closure cannot
+ evaluate to a function, because we're going to do a field
+ selection on the result. */
SELECTOR_CODE_UPD(0)
SELECTOR_CODE_UPD(1)
@@ -110,33 +101,27 @@ SELECTOR_CODE_UPD(13)
SELECTOR_CODE_UPD(14)
SELECTOR_CODE_UPD(15)
-#define SELECTOR_CODE_NOUPD(offset) \
- INFO_TABLE_RET(stg_sel_ret_##offset##_noupd, RET_SMALL, RET_PARAMS) \
- { \
- R1 = StgClosure_payload(UNTAG(R1),offset); \
- GET_SAVED_CCCS; \
- Sp = Sp + SIZEOF_StgHeader; \
- ENTER(); \
- } \
- \
- INFO_TABLE_SELECTOR(stg_sel_##offset##_noupd, offset, THUNK_SELECTOR, "stg_sel_noupd", "stg_sel_noupd")\
- { \
- TICK_ENT_DYN_THK(); \
- STK_CHK_NP(NOUPD_FRAME_SIZE); \
- UPD_BH_SINGLE_ENTRY(); \
- LDV_ENTER(R1); \
- TICK_UPDF_OMITTED(); \
- ENTER_CCS_THUNK(R1); \
- SAVE_CCCS(NOUPD_FRAME_SIZE); \
- W_[Sp-NOUPD_FRAME_SIZE] = stg_sel_ret_##offset##_noupd_info; \
- Sp = Sp - NOUPD_FRAME_SIZE; \
- R1 = StgThunk_payload(R1,0); \
- if (GETTAG(R1) != 0) { \
- jump RET_LBL(stg_sel_ret_##offset##_noupd); \
+
+#define SELECTOR_CODE_NOUPD(offset) \
+ INFO_TABLE_SELECTOR(stg_sel_##offset##_noupd, offset, THUNK_SELECTOR, "stg_sel_noupd", "stg_sel_noupd") \
+ (P_ node) \
+ { \
+ P_ selectee, field; \
+ TICK_ENT_DYN_THK(); \
+ STK_CHK_NP(node); \
+ UPD_BH_UPDATABLE(node); \
+ LDV_ENTER(node); \
+ ENTER_CCS_THUNK(node); \
+ selectee = StgThunk_payload(node,0); \
+ if (NEED_EVAL(selectee)) { \
+ (P_ constr) = call %GET_ENTRY(selectee) (selectee); \
+ selectee = constr; \
} \
- jump %GET_ENTRY(R1); \
+ field = StgClosure_payload(UNTAG(selectee),offset); \
+ jump stg_ap_0_fast(field); \
}
+
SELECTOR_CODE_NOUPD(0)
SELECTOR_CODE_NOUPD(1)
SELECTOR_CODE_NOUPD(2)
@@ -173,131 +158,120 @@ SELECTOR_CODE_NOUPD(15)
*/
INFO_TABLE(stg_ap_1_upd,1,0,THUNK_1_0,"stg_ap_1_upd_info","stg_ap_1_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(1));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame;
- jump stg_ap_0_fast;
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_0_fast
+ (StgThunk_payload(node,0));
+ }
}
INFO_TABLE(stg_ap_2_upd,2,0,THUNK_2_0,"stg_ap_2_upd_info","stg_ap_2_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(2));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(1)] = StgThunk_payload(R1,1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame - WDS(1);
- Sp_adj(-1); // for stg_ap_*_ret
- TICK_UNKNOWN_CALL();
- TICK_SLOW_CALL_p();
- jump RET_LBL(stg_ap_p);
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_p_fast
+ (StgThunk_payload(node,0),
+ StgThunk_payload(node,1));
+ }
}
INFO_TABLE(stg_ap_3_upd,3,0,THUNK,"stg_ap_3_upd_info","stg_ap_3_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(3));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(1)] = StgThunk_payload(R1,2);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(2)] = StgThunk_payload(R1,1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame - WDS(2);
- Sp_adj(-1); // for stg_ap_*_ret
- TICK_UNKNOWN_CALL();
- TICK_SLOW_CALL_pp();
- jump RET_LBL(stg_ap_pp);
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_pp_fast
+ (StgThunk_payload(node,0),
+ StgThunk_payload(node,1),
+ StgThunk_payload(node,2));
+ }
}
INFO_TABLE(stg_ap_4_upd,4,0,THUNK,"stg_ap_4_upd_info","stg_ap_4_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(4));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(1)] = StgThunk_payload(R1,3);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(2)] = StgThunk_payload(R1,2);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(3)] = StgThunk_payload(R1,1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame - WDS(3);
- Sp_adj(-1); // for stg_ap_*_ret
- TICK_UNKNOWN_CALL();
- TICK_SLOW_CALL_ppp();
- jump RET_LBL(stg_ap_ppp);
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_ppp_fast
+ (StgThunk_payload(node,0),
+ StgThunk_payload(node,1),
+ StgThunk_payload(node,2),
+ StgThunk_payload(node,3));
+ }
}
INFO_TABLE(stg_ap_5_upd,5,0,THUNK,"stg_ap_5_upd_info","stg_ap_5_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(5));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(1)] = StgThunk_payload(R1,4);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(2)] = StgThunk_payload(R1,3);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(3)] = StgThunk_payload(R1,2);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(4)] = StgThunk_payload(R1,1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame - WDS(4);
- Sp_adj(-1); // for stg_ap_*_ret
- TICK_UNKNOWN_CALL();
- TICK_SLOW_CALL_pppp();
- jump RET_LBL(stg_ap_pppp);
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_pppp_fast
+ (StgThunk_payload(node,0),
+ StgThunk_payload(node,1),
+ StgThunk_payload(node,2),
+ StgThunk_payload(node,3),
+ StgThunk_payload(node,4));
+ }
}
INFO_TABLE(stg_ap_6_upd,6,0,THUNK,"stg_ap_6_upd_info","stg_ap_6_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(6));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(1)] = StgThunk_payload(R1,5);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(2)] = StgThunk_payload(R1,4);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(3)] = StgThunk_payload(R1,3);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(4)] = StgThunk_payload(R1,2);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(5)] = StgThunk_payload(R1,1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame - WDS(5);
- Sp_adj(-1); // for stg_ap_*_ret
- TICK_UNKNOWN_CALL();
- TICK_SLOW_CALL_ppppp();
- jump RET_LBL(stg_ap_ppppp);
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_ppppp_fast
+ (StgThunk_payload(node,0),
+ StgThunk_payload(node,1),
+ StgThunk_payload(node,2),
+ StgThunk_payload(node,3),
+ StgThunk_payload(node,4),
+ StgThunk_payload(node,5));
+ }
}
INFO_TABLE(stg_ap_7_upd,7,0,THUNK,"stg_ap_7_upd_info","stg_ap_7_upd_info")
+ (P_ node)
{
- TICK_ENT_DYN_THK();
- STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(7));
- UPD_BH_UPDATABLE();
- LDV_ENTER(R1);
- ENTER_CCS_THUNK(R1);
- PUSH_UPD_FRAME(Sp-SIZEOF_StgUpdateFrame,R1);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(1)] = StgThunk_payload(R1,6);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(2)] = StgThunk_payload(R1,5);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(3)] = StgThunk_payload(R1,4);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(4)] = StgThunk_payload(R1,3);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(5)] = StgThunk_payload(R1,2);
- W_[Sp-SIZEOF_StgUpdateFrame-WDS(6)] = StgThunk_payload(R1,1);
- R1 = StgThunk_payload(R1,0);
- Sp = Sp - SIZEOF_StgUpdateFrame - WDS(6);
- Sp_adj(-1); // for stg_ap_*_ret
- TICK_UNKNOWN_CALL();
- TICK_SLOW_CALL_pppppp();
- jump RET_LBL(stg_ap_pppppp);
+ TICK_ENT_DYN_THK();
+ STK_CHK_NP(node);
+ UPD_BH_UPDATABLE(node);
+ LDV_ENTER(node);
+ ENTER_CCS_THUNK(node);
+ push (UPDATE_FRAME_FIELDS(,,stg_upd_frame_info, node)) {
+ jump stg_ap_pppppp_fast
+ (StgThunk_payload(node,0),
+ StgThunk_payload(node,1),
+ StgThunk_payload(node,2),
+ StgThunk_payload(node,3),
+ StgThunk_payload(node,4),
+ StgThunk_payload(node,5),
+ StgThunk_payload(node,6));
+ }
}