summaryrefslogtreecommitdiff
path: root/rts/Apply.cmm
diff options
context:
space:
mode:
authorSimon Marlow <simonmar@microsoft.com>2007-10-10 09:32:41 +0000
committerSimon Marlow <simonmar@microsoft.com>2007-10-10 09:32:41 +0000
commit2777940384ce4740954062bedd0f6813698fc72a (patch)
treee73a8c5e4a1d35057527a68676bc7d13b3fff30d /rts/Apply.cmm
parent70f308087c2291a3114bfedaa7ae915b1a1ac70a (diff)
downloadhaskell-2777940384ce4740954062bedd0f6813698fc72a.tar.gz
GHCi: use non-updatable thunks for breakpoints
The extra safe points introduced for breakpoints were previously compiled as normal updatable thunks, but they are guaranteed single-entry, so we can use non-updatable thunks here. This restores the tail-call property where it was lost in some cases (although stack squeezing probably often recovered it), and should improve performance.
Diffstat (limited to 'rts/Apply.cmm')
-rw-r--r--rts/Apply.cmm70
1 files changed, 70 insertions, 0 deletions
diff --git a/rts/Apply.cmm b/rts/Apply.cmm
index 0498f009b8..a98edeef91 100644
--- a/rts/Apply.cmm
+++ b/rts/Apply.cmm
@@ -223,6 +223,76 @@ for:
#endif
}
+/* AP_NOUPD is exactly like AP, except that no update frame is pushed.
+ Use for thunks that are guaranteed to be entered once only, such as
+ those generated by the byte-code compiler for inserting breakpoints. */
+
+INFO_TABLE(stg_AP_NOUPD,/*special layout*/0,0,AP,"AP_NOUPD","AP_NOUPD")
+{
+ W_ Words;
+ W_ ap;
+
+ ap = R1;
+
+ Words = TO_W_(StgAP_n_args(ap));
+
+ /*
+ * Check for stack overflow. IMPORTANT: use a _NP check here,
+ * because if the check fails, we might end up blackholing this very
+ * closure, in which case we must enter the blackhole on return rather
+ * than continuing to evaluate the now-defunct closure.
+ */
+ STK_CHK_NP(WDS(Words));
+ Sp = Sp - WDS(Words);
+
+ TICK_ENT_AP();
+ LDV_ENTER(ap);
+
+ // Enter PAP cost centre
+ ENTER_CCS_PAP_CL(ap); // ToDo: ENTER_CC_AP_CL
+
+ // Reload the stack
+ W_ i;
+ W_ p;
+ p = ap + SIZEOF_StgHeader + OFFSET_StgAP_payload;
+ i = 0;
+for:
+ if (i < Words) {
+ Sp(i) = W_[p];
+ p = p + WDS(1);
+ i = i + 1;
+ goto for;
+ }
+
+ R1 = StgAP_fun(ap);
+
+ // Off we go!
+ TICK_ENT_VIA_NODE();
+
+#ifdef NO_ARG_REGS
+ jump %GET_ENTRY(UNTAG(R1));
+#else
+ W_ info;
+ info = %GET_FUN_INFO(UNTAG(R1));
+ W_ type;
+ type = TO_W_(StgFunInfoExtra_fun_type(info));
+ if (type == ARG_GEN) {
+ jump StgFunInfoExtra_slow_apply(info);
+ }
+ if (type == ARG_GEN_BIG) {
+ jump StgFunInfoExtra_slow_apply(info);
+ }
+ if (type == ARG_BCO) {
+ Sp_adj(-2);
+ Sp(1) = R1;
+ Sp(0) = stg_apply_interp_info;
+ jump stg_yield_to_interpreter;
+ }
+ jump W_[stg_ap_stack_entries +
+ WDS(TO_W_(StgFunInfoExtra_fun_type(info)))];
+#endif
+}
+
/* -----------------------------------------------------------------------------
Entry Code for an AP_STACK.