Scale columns in cost-centre-stack report to their contents
[ghc.git] / rts / Apply.cmm
index 0498f00..f9ac3b3 100644 (file)
@@ -30,9 +30,7 @@ stg_ap_0_fast
        foreign "C" printClosure(R1 "ptr") [R1]);
 
     IF_DEBUG(sanity,
-       foreign "C" checkStackChunk(Sp "ptr",
-                                   CurrentTSO + TSO_OFFSET_StgTSO_stack +
-                                   WDS(TO_W_(StgTSO_stack_size(CurrentTSO))) "ptr") [R1]);
+       foreign "C" checkStackFrame(Sp "ptr") [R1]);
 
     ENTER();
 }
@@ -223,6 +221,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.
 
@@ -282,3 +350,56 @@ for:
 
   ENTER();
 }
+
+/* -----------------------------------------------------------------------------
+   AP_STACK_NOUPD - exactly like AP_STACK, but doesn't push an update frame.
+   -------------------------------------------------------------------------- */
+
+INFO_TABLE(stg_AP_STACK_NOUPD,/*special layout*/0,0,AP_STACK,
+                                        "AP_STACK_NOUPD","AP_STACK_NOUPD")
+{
+  W_ Words;
+  W_ ap;
+
+  ap = R1;
+  
+  Words = StgAP_STACK_size(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) + WDS(AP_STACK_SPLIM));
+  /* ensure there is at least AP_STACK_SPLIM words of headroom available
+   * after unpacking the AP_STACK. See bug #1466 */
+
+  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_STACK_payload;
+  i = 0;
+for:
+  if (i < Words) {
+    Sp(i) = W_[p];
+    p = p + WDS(1);
+    i = i + 1;
+    goto for;
+  }
+
+  // Off we go!
+  TICK_ENT_VIA_NODE();
+
+  R1 = StgAP_STACK_fun(ap);
+
+  ENTER();
+}