Hi,

here is a patch for the compiler to inline the ifNil: message,
it's interesting since we don't need to make a block closure
and to send the ifNil: message.

Gwen
>From 04373bc69c0d02c629f0007aa1e0a19203d7cede Mon Sep 17 00:00:00 2001
From: Gwenael Casaccio <[email protected]>
Date: Fri, 24 Jun 2011 06:48:32 +0200
Subject: [PATCH] ifNil: inlined

---
 libgst/comp.c |   61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 libgst/sym.c  |    2 +
 libgst/sym.h  |    1 +
 3 files changed, 64 insertions(+), 0 deletions(-)

diff --git a/libgst/comp.c b/libgst/comp.c
index 9cc5986..716256d 100644
--- a/libgst/comp.c
+++ b/libgst/comp.c
@@ -171,6 +171,9 @@ static mst_Boolean compile_and_or_statement (OOP selector,
 static mst_Boolean compile_if_true_false_statement (OOP selector,
 						    tree_node expr);
 
+static mst_Boolean compile_if_nil_statement (OOP selector,
+                                                    tree_node expr);
+
 /* Special case compilation of an infinite loop, given by the parse
    node in RECEIVER.  Returns true if byte codes were emitted, false
    if not.  If the last argument to the message is not a block
@@ -252,6 +255,12 @@ static bc_vector compile_sub_expression (tree_node expr);
 static bc_vector compile_sub_expression_and_jump (tree_node expr,
 						  int branchLen);
 
+/* Like compile_sub_expression, except that after compiling EXPR this
+   subexpression always ends with an unconditional branch past
+   BRANCHLEN bytecodes and POP the value on the stack.  */
+static bc_vector compile_pop_sub_expression_and_jump (tree_node expr,
+                                                  int branchLen);
+
 /* Compile a send with the given RECEIVER (used to check for sends to
    super), SELECTOR and number of arguments NUMARGS.  */
 static void compile_send (tree_node receiver,
@@ -1287,6 +1296,11 @@ compile_keyword_expr (tree_node expr,
 
       compile_expression (expr->v_expr.receiver);
 
+      if (selector == _gst_if_nil_symbol)
+        {
+          if (compile_if_nil_statement (selector, expr->v_expr.expression))
+            return;
+        }
       if (selector == _gst_if_true_symbol
           || selector == _gst_if_false_symbol)
         {
@@ -1722,6 +1736,53 @@ compile_if_statement (OOP selector,
   return (true);
 }
 
+bc_vector
+compile_pop_sub_expression_and_jump (tree_node expr,
+                                 int branchLen)
+{
+  bc_vector current_bytecodes, subExprByteCodes;
+  mst_Boolean returns;
+
+  current_bytecodes = _gst_save_bytecode_array ();
+
+  _gst_compile_byte (POP_STACK_TOP, 0);
+  //SUB_STACK_DEPTH (1);
+
+  returns = compile_statements (expr->v_block.statements, false);
+  if (returns)
+    INCR_STACK_DEPTH ();
+
+  if (!returns)
+    _gst_compile_byte (JUMP, branchLen);
+
+  subExprByteCodes = _gst_get_bytecodes ();
+  _gst_restore_bytecode_array (current_bytecodes);
+
+  return (subExprByteCodes);
+}
+
+mst_Boolean
+compile_if_nil_statement (OOP selector,
+                      tree_node expr)
+{
+  bc_vector nilByteCodes;
+  struct builtin_selector *bs = _gst_lookup_builtin_selector ("isNil", 5);
+
+  if (expr->v_list.value->nodeType != TREE_BLOCK_NODE
+      || HAS_PARAMS_OR_TEMPS (expr->v_list.value))
+    return (false);
+
+  _gst_compile_byte (DUP_STACK_TOP, 0);
+  INCR_STACK_DEPTH ();
+
+  _gst_compile_byte (bs->bytecode, 0);
+
+  nilByteCodes = compile_pop_sub_expression_and_jump (expr->v_list.value, 0);
+  compile_jump (_gst_bytecode_length (nilByteCodes), false);
+  _gst_compile_and_free_bytecodes (nilByteCodes);
+
+  return (true);
+}
 
 mst_Boolean
 compile_and_or_statement (OOP selector,
diff --git a/libgst/sym.c b/libgst/sym.c
index a3cfd65..27b9384 100644
--- a/libgst/sym.c
+++ b/libgst/sym.c
@@ -126,6 +126,7 @@ OOP _gst_if_false_if_true_symbol = NULL;
 OOP _gst_if_false_symbol = NULL;
 OOP _gst_if_true_if_false_symbol = NULL;
 OOP _gst_if_true_symbol = NULL;
+OOP _gst_if_nil_symbol = NULL;
 OOP _gst_int_symbol = NULL;
 OOP _gst_long_double_symbol = NULL;
 OOP _gst_long_symbol = NULL;
@@ -284,6 +285,7 @@ static const symbol_info sym_info[] = {
   {&_gst_if_false_symbol, "ifFalse:"},
   {&_gst_if_true_if_false_symbol, "ifTrue:ifFalse:"},
   {&_gst_if_true_symbol, "ifTrue:"},
+  {&_gst_if_nil_symbol, "ifNil:"},
   {&_gst_int_symbol, "int"},
   {&_gst_uint_symbol, "uInt"},
   {&_gst_long_double_symbol, "longDouble"},
diff --git a/libgst/sym.h b/libgst/sym.h
index 2288e38..b7d91a7 100644
--- a/libgst/sym.h
+++ b/libgst/sym.h
@@ -115,6 +115,7 @@ extern OOP _gst_if_false_if_true_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_false_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_true_if_false_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_if_true_symbol ATTRIBUTE_HIDDEN;
+extern OOP _gst_if_nil_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_int_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_long_double_symbol ATTRIBUTE_HIDDEN;
 extern OOP _gst_long_symbol ATTRIBUTE_HIDDEN;
-- 
1.7.4.1

_______________________________________________
help-smalltalk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-smalltalk

Reply via email to