[perl #32717] BeOS specific Updates
[p5sagit/p5-mst-13.2.git] / op.c
diff --git a/op.c b/op.c
index 9b33ff2..8a5c765 100644 (file)
--- a/op.c
+++ b/op.c
  * is made, called opmini.c.
  */
 
+/*
+Perl's compiler is essentially a 3-pass compiler with interleaved phases:
+
+    A bottom-up pass
+    A top-down pass
+    An execution-order pass
+
+The bottom-up pass is represented by all the "newOP" routines and
+the ck_ routines.  The bottom-upness is actually driven by yacc.
+So at the point that a ck_ routine fires, we have no idea what the
+context is, either upward in the syntax tree, or either forward or
+backward in the execution order.  (The bottom-up parser builds that
+part of the execution order it knows about, but if you follow the "next"
+links around, you'll find it's actually a closed loop through the
+top level node.
+
+Whenever the bottom-up parser gets to a node that supplies context to
+its components, it invokes that portion of the top-down pass that applies
+to that part of the subtree (and marks the top node as processed, so
+if a node further up supplies context, it doesn't have to take the
+plunge again).  As a particular subcase of this, as the new node is
+built, it takes all the closed execution loops of its subcomponents
+and links them into a new closed loop for the higher level node.  But
+it's still not the real execution order.
+
+The actual execution order is not known till we get a grammar reduction
+to a top-level unit like a subroutine or file that will be called by
+"name" rather than via a "next" pointer.  At that point, we can call
+into peep() to do that code's portion of the 3rd pass.  It has to be
+recursive, but it's recursive on basic blocks, not on tree nodes.
+*/
+
 #include "EXTERN.h"
 #define PERL_IN_OP_C
 #include "perl.h"
@@ -239,6 +271,7 @@ Perl_op_free(pTHX_ OP *o)
 {
     register OP *kid, *nextkid;
     OPCODE type;
+    PADOFFSET refcnt;
 
     if (!o || o->op_static)
        return;
@@ -252,11 +285,10 @@ Perl_op_free(pTHX_ OP *o)
        case OP_SCOPE:
        case OP_LEAVEWRITE:
            OP_REFCNT_LOCK;
-           if (OpREFCNT_dec(o)) {
-               OP_REFCNT_UNLOCK;
-               return;
-           }
+           refcnt = OpREFCNT_dec(o);
            OP_REFCNT_UNLOCK;
+           if (refcnt)
+               return;
            break;
        default:
            break;
@@ -442,6 +474,18 @@ Perl_op_null(pTHX_ OP *o)
     o->op_ppaddr = PL_ppaddr[OP_NULL];
 }
 
+void
+Perl_op_refcnt_lock(pTHX)
+{
+    OP_REFCNT_LOCK;
+}
+
+void
+Perl_op_refcnt_unlock(pTHX)
+{
+    OP_REFCNT_UNLOCK;
+}
+
 /* Contextualizers */
 
 #define LINKLIST(o) ((o)->op_next ? (o)->op_next : linklist((OP*)o))
@@ -4818,7 +4862,8 @@ Perl_newSVREF(pTHX_ OP *o)
     return newUNOP(OP_RV2SV, 0, scalar(o));
 }
 
-/* Check routines. */
+/* Check routines. See the comments at the top of this file for details
+ * on when these are called */
 
 OP *
 Perl_ck_anoncode(pTHX_ OP *o)
@@ -6403,7 +6448,9 @@ Perl_ck_substr(pTHX_ OP *o)
     return o;
 }
 
-/* A peephole optimizer.  We visit the ops in the order they're to execute. */
+/* A peephole optimizer.  We visit the ops in the order they're to execute.
+ * See the comments at the top of this file for more details about when
+ * peep() is called */
 
 void
 Perl_peep(pTHX_ register OP *o)