X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FStgStdThunks.cmm;h=be859995981d18236975aa8301f790a3d6b2a525;hb=d8334d807812e40f67770ffc37608c0ce66f96b2;hp=db9c2542338ef4a63f418f29ee60c9132911a9c0;hpb=d31dfb32ea936c22628b508c28a36c12e631430a;p=ghc-hetmet.git diff --git a/rts/StgStdThunks.cmm b/rts/StgStdThunks.cmm index db9c254..be85999 100644 --- a/rts/StgStdThunks.cmm +++ b/rts/StgStdThunks.cmm @@ -39,10 +39,38 @@ #define RET_PARAMS #endif -#define SELECTOR_CODE_UPD(offset) \ +/* + * TODO: On return, we can use a more efficient + * untagging (we know the constructor tag). + * + * When entering stg_sel_#_upd, we know R1 points to its closure, + * so it's untagged. + * The payload might be a thunk or a constructor, + * so we enter it. + * + * When returning, we know for sure it is a constructor, + * so we untag it before accessing the field. + * + */ +#ifdef PROFILING +// 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); +#else +#define SEL_ENTER(offset) \ + if (GETTAG(R1) != 0) { \ + jump RET_LBL(stg_sel_ret_##offset##_upd); \ + } \ + jump %GET_ENTRY(R1); +#endif + +#define SELECTOR_CODE_UPD(offset) \ INFO_TABLE_RET(stg_sel_ret_##offset##_upd, RET_SMALL, RET_PARAMS) \ { \ - R1 = StgClosure_payload(R1,offset); \ + R1 = StgClosure_payload(UNTAG(R1),offset); \ GET_SAVED_CCCS; \ Sp = Sp + SIZEOF_StgHeader; \ ENTER(); \ @@ -58,9 +86,9 @@ ENTER_CCS_THUNK(R1); \ SAVE_CCCS(WITHUPD_FRAME_SIZE); \ W_[Sp-WITHUPD_FRAME_SIZE] = stg_sel_ret_##offset##_upd_info; \ - R1 = StgThunk_payload(R1,0); \ Sp = Sp - WITHUPD_FRAME_SIZE; \ - jump %GET_ENTRY(R1); \ + R1 = StgThunk_payload(R1,0); \ + SEL_ENTER(offset); \ } /* 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. */ @@ -85,10 +113,10 @@ SELECTOR_CODE_UPD(15) #define SELECTOR_CODE_NOUPD(offset) \ INFO_TABLE_RET(stg_sel_ret_##offset##_noupd, RET_SMALL, RET_PARAMS) \ { \ - R1 = StgClosure_payload(R1,offset); \ + R1 = StgClosure_payload(UNTAG(R1),offset); \ GET_SAVED_CCCS; \ Sp = Sp + SIZEOF_StgHeader; \ - jump %GET_ENTRY(R1); \ + ENTER(); \ } \ \ INFO_TABLE_SELECTOR(stg_sel_##offset##_noupd, offset, THUNK_SELECTOR, "stg_sel_noupd", "stg_sel_noupd")\ @@ -101,8 +129,11 @@ SELECTOR_CODE_UPD(15) ENTER_CCS_THUNK(R1); \ SAVE_CCCS(NOUPD_FRAME_SIZE); \ W_[Sp-NOUPD_FRAME_SIZE] = stg_sel_ret_##offset##_noupd_info; \ - R1 = StgThunk_payload(R1,0); \ Sp = Sp - NOUPD_FRAME_SIZE; \ + R1 = StgThunk_payload(R1,0); \ + if (GETTAG(R1) != 0) { \ + jump RET_LBL(stg_sel_ret_##offset##_noupd); \ + } \ jump %GET_ENTRY(R1); \ } @@ -141,7 +172,7 @@ SELECTOR_CODE_NOUPD(15) * in the compiler that means stg_ap_1 is generated occasionally (ToDo) */ -INFO_TABLE(stg_ap_1_upd,1,1,THUNK_1_0,"stg_ap_1_upd_info","stg_ap_1_upd_info") +INFO_TABLE(stg_ap_1_upd,1,0,THUNK_1_0,"stg_ap_1_upd_info","stg_ap_1_upd_info") { TICK_ENT_DYN_THK(); STK_CHK_NP(SIZEOF_StgUpdateFrame+WDS(1));