From d9a93b6e559f2ea0acf1a51ed8670937ed53e51c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Sun, 1 Jul 2001 21:09:50 -0700
Subject: [PATCH] more debug, more optimizations, new efuns: int2char, basetype
 new opcodes: F_CALL_BUILTIN1, F_CALL_BUILTIN1_AND_POP,
 F_BRANCH_IF_TYPE_IS_NOT

Rev: src/builtin.cmod:1.53
Rev: src/builtin_functions.c:1.388
Rev: src/constants.c:1.31
Rev: src/constants.h:1.18
Rev: src/docode.c:1.124
Rev: src/interpret.c:1.211
Rev: src/interpret_functions.h:1.66
Rev: src/lex.c:1.91
Rev: src/modules/sprintf/sprintf.c:1.79
Rev: src/peep.c:1.49
Rev: src/peep.in:1.56
---
 src/builtin.cmod              | 102 +++++++++++++++++++++++++++++++++-
 src/builtin_functions.c       |  35 ++++--------
 src/constants.c               |  23 +++++++-
 src/constants.h               |   4 +-
 src/docode.c                  |  27 ++++++---
 src/interpret.c               |   3 +-
 src/interpret_functions.h     |  39 ++++++++++++-
 src/lex.c                     |   5 +-
 src/modules/sprintf/sprintf.c |  44 ++++++++++++++-
 src/peep.c                    |  10 ++--
 src/peep.in                   |  16 +++++-
 11 files changed, 260 insertions(+), 48 deletions(-)

diff --git a/src/builtin.cmod b/src/builtin.cmod
index a570fbe277..d42372d8b0 100644
--- a/src/builtin.cmod
+++ b/src/builtin.cmod
@@ -1,5 +1,5 @@
 /* -*- c -*-
- * $Id: builtin.cmod,v 1.52 2001/07/01 15:39:16 grubba Exp $
+ * $Id: builtin.cmod,v 1.53 2001/07/02 04:09:46 hubbe Exp $
  */
 
 #include "global.h"
@@ -28,6 +28,106 @@
 #include "builtin_functions.h"
 #include "fsort.h"
 
+
+/*! @decl string basetype(mixed x)
+ *!
+ *! Same as sprintf("%t",x);
+ *!
+ *! @seealso
+ *! @[sprintf()]
+ */
+PIKEFUN string basetype(mixed x)
+  efun;
+  optflags OPT_TRY_OPTIMIZE;
+{
+  int t=x->type;
+  if(x->type == T_OBJECT && x->u.object->prog)
+  {
+    ptrdiff_t fun=FIND_LFUN(x->u.object->prog, LFUN__SPRINTF);
+    if(fun != -1)
+    {
+      push_int('t');
+      f_aggregate_mapping(0);
+      apply_low(x->u.object, fun, 2);
+      if(Pike_sp[-1].type == T_STRING)
+      {
+	stack_swap();
+	pop_stack();
+	return;
+      }
+      error("Non-string returned from _sprintf()\n");
+    }
+  }
+  pop_stack();
+  switch(t)
+  {
+    case T_ARRAY: push_constant_text("array"); break;
+    case T_FLOAT: push_constant_text("float"); break;
+    case T_FUNCTION: push_constant_text("function"); break;
+    case T_INT: push_constant_text("int"); break;
+    case T_LVALUE: push_constant_text("lvalue"); break;
+    case T_MAPPING: push_constant_text("mapping"); break;
+    case T_MULTISET: push_constant_text("multiset"); break;
+    case T_OBJECT: push_constant_text("object"); break;
+    case T_PROGRAM: push_constant_text("program"); break;
+    case T_STRING: push_constant_text("string"); break;
+    case T_TYPE: push_constant_text("type"); break;
+    case T_ZERO: push_constant_text("zero"); break;
+    case T_VOID: push_constant_text("void"); break;
+    case T_MAPPING_DATA: push_constant_text("mapping_data"); break;
+    default: push_constant_text("unknown"); break;
+  }
+}
+
+
+/*! @decl string int2char(int x)
+ *!
+ *! Same as sprintf("%c",x);
+ *!
+ *! @seealso
+ *! @[sprintf()]
+ */
+PIKEFUN string int2char(int|object x)
+  efun;
+  optflags OPT_TRY_OPTIMIZE;
+{
+  int c;
+  if(x->type == T_OBJECT && x->u.object->prog)
+  {
+    ptrdiff_t fun=FIND_LFUN(x->u.object->prog, LFUN__SPRINTF);
+    if(fun != -1)
+    {
+      push_int('c');
+      f_aggregate_mapping(0);
+      apply_low(x->u.object, fun, 2);
+      if(Pike_sp[-1].type == T_STRING)
+      {
+	stack_swap();
+	pop_stack();
+	return;
+      }
+      error("Non-string returned from _sprintf()\n");
+    }
+  }
+  if(x->type != T_INT)
+    error("Bad argument 1 to int2char.\n");
+
+  c=x->u.integer;
+
+  if(c>=0 && c<256)
+  {
+    struct pike_string *s;
+    s=begin_shared_string(1);
+    s->str[0]=c;
+    RETURN end_shared_string(s);
+  }else{
+    struct string_builder tmp;
+    init_string_builder(&tmp,0);
+    string_builder_putchar(&tmp, c);
+    RETURN finish_string_builder(&tmp);
+  }
+}
+
 /*! @decl array column(array data, mixed index)
  *!
  *! Extract a column from a two-dimensional array.
diff --git a/src/builtin_functions.c b/src/builtin_functions.c
index 34d7dc305e..aa59700f32 100644
--- a/src/builtin_functions.c
+++ b/src/builtin_functions.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: builtin_functions.c,v 1.387 2001/06/29 10:47:37 grubba Exp $");
+RCSID("$Id: builtin_functions.c,v 1.388 2001/07/02 04:09:47 hubbe Exp $");
 #include "interpret.h"
 #include "svalue.h"
 #include "pike_macros.h"
@@ -2050,6 +2050,14 @@ void f__exit(INT32 args)
   if(Pike_sp[-args].type != T_INT)
     SIMPLE_BAD_ARG_ERROR("_exit", 1, "int");
 
+#ifdef PIKE_DEBUG
+  {
+    /* This will allow -p to work with _exit -Hubbe */
+    extern void exit_lex(void);
+    exit_lex();
+  }
+#endif
+
   exit(Pike_sp[-args].u.integer);
 }
 
@@ -3506,10 +3514,6 @@ void f_gc(INT32 args)
 #undef TYPEP
 #endif
 
-#ifdef AUTO_BIGNUM
-/* This should probably be here whether AUTO_BIGNUM is defined or not,
- * but it can wait a little. /Hubbe
- */
 
 #define TYPEP(ID,NAME,TYPE,TYPE_NAME)				\
 PMOD_EXPORT void ID(INT32 args)						\
@@ -3532,17 +3536,6 @@ PMOD_EXPORT void ID(INT32 args)						\
   pop_n_elems(args);						\
   push_int(t);							\
 }
-#else
-#define TYPEP(ID,NAME,TYPE) \
-void ID(INT32 args) \
-{ \
-  int t; \
-  if(args<1) SIMPLE_TOO_FEW_ARGS_ERROR(NAME, 1); \
-  t=Pike_sp[-args].type == TYPE; \
-  pop_n_elems(args); \
-  push_int(t); \
-}
-#endif /* AUTO_BIGNUM */
 
 
 /*! @decl int programp(mixed arg)
@@ -3632,21 +3625,13 @@ PMOD_EXPORT void f_programp(INT32 args)
  *!   @[mappingp()], @[stringp()], @[functionp()]
  */
 
-#ifdef AUTO_BIGNUM
+
 TYPEP(f_intp, "intp", T_INT, "int")
 TYPEP(f_mappingp, "mappingp", T_MAPPING, "mapping")
 TYPEP(f_arrayp, "arrayp", T_ARRAY, "array")
 TYPEP(f_multisetp, "multisetp", T_MULTISET, "multiset")
 TYPEP(f_stringp, "stringp", T_STRING, "string")
 TYPEP(f_floatp, "floatp", T_FLOAT, "float")
-#else
-TYPEP(f_intp, "intp", T_INT)
-TYPEP(f_mappingp, "mappingp", T_MAPPING)
-TYPEP(f_arrayp, "arrayp", T_ARRAY)
-TYPEP(f_multisetp, "multisetp", T_MULTISET)
-TYPEP(f_stringp, "stringp", T_STRING)
-TYPEP(f_floatp, "floatp", T_FLOAT)
-#endif /* AUTO_BIGNUM */
 
 /*! @decl array sort(array(mixed) index, array(mixed) ... data)
  *!
diff --git a/src/constants.c b/src/constants.c
index 4defadce16..d076dc15e9 100644
--- a/src/constants.c
+++ b/src/constants.c
@@ -17,7 +17,7 @@
 #include "security.h"
 #include "block_alloc.h"
 
-RCSID("$Id: constants.c,v 1.30 2001/04/13 19:56:49 grubba Exp $");
+RCSID("$Id: constants.c,v 1.31 2001/07/02 04:09:47 hubbe Exp $");
 
 struct mapping *builtin_constants = 0;
 
@@ -69,6 +69,7 @@ PMOD_EXPORT void add_global_program(char *name, struct program *p)
 #define EXIT_BLOCK(X) do {		\
   free_type(X->type);			\
   free_string(X->name);			\
+  X->name=0;				\
   EXIT_PIKE_MEMOBJ(X);                  \
 }while(0)
 BLOCK_ALLOC(callable,128)
@@ -96,6 +97,8 @@ PMOD_EXPORT struct callable *low_make_callable(c_fun fun,
     if(!z) fatal("Gnapp!\n");
     free_type(z);
   }
+  f->runs=0;
+  f->compiles=0;
 #endif
   return f;
 }
@@ -168,6 +171,24 @@ PMOD_EXPORT struct callable *quick_add_efun(char *name, ptrdiff_t name_length,
   return ret;
 }
 
+#ifdef PIKE_DEBUG
+void present_constant_profiling(void)
+{
+  struct callable_block *b;
+  int e;
+  for(b=callable_blocks;b;b=b->next)
+  {
+    for(e=0;e<NELEM(b->x);e++)
+    {
+      if(b->x[e].name)
+      {
+	fprintf(stderr,"%010d @E@: %s\n",b->x[e].runs, b->x[e].name->str);
+      }
+    }
+  }
+}
+#endif
+
 void cleanup_added_efuns(void)
 {
 #ifdef DO_PIKE_CLEANUP
diff --git a/src/constants.h b/src/constants.h
index 5bae6091a2..fffa9b3108 100644
--- a/src/constants.h
+++ b/src/constants.h
@@ -5,7 +5,7 @@
 \*/
 
 /*
- * $Id: constants.h,v 1.17 2001/04/07 07:38:24 hubbe Exp $
+ * $Id: constants.h,v 1.18 2001/07/02 04:09:47 hubbe Exp $
  */
 #ifndef ADD_EFUN_H
 #define ADD_EFUN_H
@@ -27,6 +27,8 @@ struct callable
   INT16 flags;
 #ifdef PIKE_DEBUG
   INT8 may_return_void;
+  long compiles;
+  long runs;
 #endif
   optimize_fun optimize;
   docode_fun docode;
diff --git a/src/docode.c b/src/docode.c
index fac76b113d..573831836d 100644
--- a/src/docode.c
+++ b/src/docode.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: docode.c,v 1.123 2001/06/29 19:48:22 hubbe Exp $");
+RCSID("$Id: docode.c,v 1.124 2001/07/02 04:09:48 hubbe Exp $");
 #include "las.h"
 #include "program.h"
 #include "pike_types.h"
@@ -1159,14 +1159,23 @@ static int do_docode2(node *n, INT16 flags)
 	  if(!CAR(n)->u.sval.u.efun->docode || 
 	     !CAR(n)->u.sval.u.efun->docode(n))
 	  {
-	    emit0(F_MARK);
-	    PUSH_CLEANUP_FRAME(do_pop_mark, 0);
-	    do_docode(CDR(n),0);
-	    tmp1=store_constant(& CAR(n)->u.sval,
-				!(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
-				CAR(n)->name);
-	    emit1(F_CALL_BUILTIN, DO_NOT_WARN((INT32)tmp1));
-	    POP_AND_DONT_CLEANUP;
+	    if(count_args(CDR(n))==1)
+	    {
+	      do_docode(CDR(n),0);
+	      tmp1=store_constant(& CAR(n)->u.sval,
+				  !(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
+				  CAR(n)->name);
+	      emit1(F_CALL_BUILTIN1, DO_NOT_WARN((INT32)tmp1));
+	    }else{
+	      emit0(F_MARK);
+	      PUSH_CLEANUP_FRAME(do_pop_mark, 0);
+	      do_docode(CDR(n),0);
+	      tmp1=store_constant(& CAR(n)->u.sval,
+				  !(CAR(n)->tree_info & OPT_EXTERNAL_DEPEND),
+				  CAR(n)->name);
+	      emit1(F_CALL_BUILTIN, DO_NOT_WARN((INT32)tmp1));
+	      POP_AND_DONT_CLEANUP;
+	    }
 	  }
 	  if(n->type == void_type_string)
 	    return 0;
diff --git a/src/interpret.c b/src/interpret.c
index 1f81d55d9c..1947a0e008 100644
--- a/src/interpret.c
+++ b/src/interpret.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: interpret.c,v 1.210 2001/07/01 22:29:41 mast Exp $");
+RCSID("$Id: interpret.c,v 1.211 2001/07/02 04:09:48 hubbe Exp $");
 #include "interpret.h"
 #include "object.h"
 #include "program.h"
@@ -982,6 +982,7 @@ int low_mega_apply(enum apply_type type, INT32 args, void *arg1, void *arg2)
 	(*(s->u.efun->function))(args);
 
 #ifdef PIKE_DEBUG
+	s->u.efun->runs++;
 	if(Pike_sp != expected_stack + !s->u.efun->may_return_void)
 	{
 	  if(Pike_sp < expected_stack)
diff --git a/src/interpret_functions.h b/src/interpret_functions.h
index 1c1ac074d5..984079e18a 100644
--- a/src/interpret_functions.h
+++ b/src/interpret_functions.h
@@ -1,5 +1,5 @@
 /*
- * $Id: interpret_functions.h,v 1.65 2001/06/29 19:48:49 hubbe Exp $
+ * $Id: interpret_functions.h,v 1.66 2001/07/02 04:09:48 hubbe Exp $
  *
  * Opcode definitions for the interpreter.
  */
@@ -862,6 +862,30 @@ OPCODE0_JUMP(F_BRANCH_WHEN_NON_ZERO,"branch if not zero")
   pop_stack();
 BREAK
 
+OPCODE1_JUMP(F_BRANCH_IF_TYPE_IS_NOT,"branch if type is !=")
+/*  fprintf(stderr,"******BRANCH IF TYPE IS NOT***** %s\n",get_name_of_type(arg1)); */
+  if(Pike_sp[-1].type == T_OBJECT &&
+     Pike_sp[-1].u.object->prog)
+  {
+    int fun=FIND_LFUN(Pike_sp[-1].u.object->prog, LFUN__IS_TYPE);
+    if(fun != -1)
+    {
+/*      fprintf(stderr,"******OBJECT OVERLOAD IN TYPEP***** %s\n",get_name_of_type(arg1)); */
+      push_text(get_name_of_type(arg1));
+      apply_low(Pike_sp[-2].u.object, fun, 1);
+      arg1=IS_ZERO(Pike_sp-1) ? T_FLOAT : T_OBJECT ;
+      pop_stack();
+    }
+  }
+  if(Pike_sp[-1].type == arg1)
+  {
+    SKIPJUMP();
+  }else{
+    DOJUMP();
+  }
+  pop_stack();
+BREAK
+
 OPCODE1_JUMP(F_BRANCH_IF_LOCAL,"branch if local")
   if(IS_ZERO(Pike_fp->locals + arg1))
   {
@@ -1659,6 +1683,7 @@ MKAPPLY(OPCODE0,CALL_FUNCTION,"call function",APPLY_STACK, 0,0);
     do_trace_call(args);						 \
   }									 \
   (*(s->u.efun->function))(args);					 \
+  s->u.efun->runs++;                                                     \
   if(Pike_sp != expected_stack + !s->u.efun->may_return_void)		 \
   {									 \
     if(Pike_sp < expected_stack)					 \
@@ -1725,6 +1750,18 @@ OPCODE1(F_MARK_CALL_BUILTIN_AND_RETURN,"mark, call builtin & return")
 BREAK;
 
 
+OPCODE1(F_CALL_BUILTIN1,"call builtin 1")
+{
+  DO_CALL_BUILTIN(1);
+}
+BREAK;
+
+OPCODE1(F_CALL_BUILTIN1_AND_POP,"call builtin1 & pop")
+{
+  DO_CALL_BUILTIN(1);
+  pop_stack();
+}
+BREAK;
 
 /* Assume that the number of arguments is correct */
 OPCODE1_JUMP(F_COND_RECUR,"recur if not overloaded")
diff --git a/src/lex.c b/src/lex.c
index 091a161108..c6620d3abc 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -5,7 +5,7 @@
 \*/
 /**/
 #include "global.h"
-RCSID("$Id: lex.c,v 1.90 2001/06/29 18:19:30 hubbe Exp $");
+RCSID("$Id: lex.c,v 1.91 2001/07/02 04:09:49 hubbe Exp $");
 #include "language.h"
 #include "array.h"
 #include "lex.h"
@@ -120,7 +120,10 @@ void exit_lex(void)
 #ifdef PIKE_DEBUG
   if(p_flag)
   {
+    extern void present_constant_profiling(void);
     int e;
+    present_constant_profiling();
+
     fprintf(stderr,"Opcode compiles: (opcode, compiled)\n");
     for(e=0;e<F_MAX_OPCODE-F_OFFSET;e++)
     {
diff --git a/src/modules/sprintf/sprintf.c b/src/modules/sprintf/sprintf.c
index 6e02b9b49e..1c5efeb277 100644
--- a/src/modules/sprintf/sprintf.c
+++ b/src/modules/sprintf/sprintf.c
@@ -103,7 +103,7 @@
 */
 
 #include "global.h"
-RCSID("$Id: sprintf.c,v 1.78 2001/03/05 00:41:35 hubbe Exp $");
+RCSID("$Id: sprintf.c,v 1.79 2001/07/02 04:09:50 hubbe Exp $");
 #include "pike_error.h"
 #include "array.h"
 #include "svalue.h"
@@ -1474,6 +1474,7 @@ void f_sprintf(INT32 num_arg)
       Pike_error("Bad argument 1 to sprintf.\n");
     }
   }
+/*  fprintf(stderr,"SPRINTF: %s\n",argp->u.string->str); */
 
   init_string_builder(&r,0);
   SET_ONERROR(err_format_stack, free_sprintf_strings, &fs);
@@ -1493,11 +1494,48 @@ void f_sprintf(INT32 num_arg)
   push_string(ret);
 }
 
+static node *optimize_sprintf(node *n)
+{
+  node **arg0 = my_get_arg(&_CDR(n), 0);
+  node **arg1 = my_get_arg(&_CDR(n), 1);
+  node *ret;
+  int num_args=count_args(CDR(n));
+  if(arg0 && arg1 && num_args == 2 &&
+     (*arg0)->token == F_CONSTANT &&
+     (*arg0)->u.sval.type == T_STRING &&
+     (*arg0)->u.sval.u.string->size_shift == 0 &&
+     (*arg0)->u.sval.u.string->len == 2 &&
+     STR0((*arg0)->u.sval.u.string)[0]=='%')
+  {
+    switch(STR0((*arg0)->u.sval.u.string)[1])
+    {
+      case 'c':
+	ADD_NODE_REF2(*arg1,
+		      ret = mkefuncallnode("int2char",*arg1);
+	  );
+	return ret;
+
+      case 't':
+	ADD_NODE_REF2(*arg1,
+		      ret = mkefuncallnode("basetype",*arg1);
+	  );
+	return ret;
+
+      default: break;
+    }
+  }
+  return 0;
+}
+
 void pike_module_init(void)
 {
   /* function(string|object, mixed ... : string) */
-  ADD_EFUN("sprintf", f_sprintf, tFuncV(tOr(tStr, tObj), tMix, tStr),
-	   OPT_TRY_OPTIMIZE);
+  ADD_EFUN2("sprintf", 
+	    f_sprintf,
+	    tFuncV(tOr(tStr, tObj), tMix, tStr),
+	    OPT_TRY_OPTIMIZE,
+	    optimize_sprintf,
+	    0);
 }
 
 void pike_module_exit(void)
diff --git a/src/peep.c b/src/peep.c
index 68dac35ce1..127335c1ce 100644
--- a/src/peep.c
+++ b/src/peep.c
@@ -14,8 +14,10 @@
 #include "stuff.h"
 #include "bignum.h"
 #include "opcodes.h"
+#include "builtin_functions.h"
+#include "constants.h"
 
-RCSID("$Id: peep.c,v 1.48 2001/06/30 07:05:55 hubbe Exp $");
+RCSID("$Id: peep.c,v 1.49 2001/07/02 04:09:49 hubbe Exp $");
 
 static void asm_opt(void);
 
@@ -454,7 +456,7 @@ static INLINE ptrdiff_t insopt2(int f, INT32 a, INT32 b,
 
 #ifdef PIKE_DEBUG
   if(!hasarg2(f) && b)
-    fatal("hasarg(%d) is wrong!\n",f);
+    fatal("hasarg2(%d /*%s */) is wrong!\n",f,get_f_name(f));
 #endif
 
   p=(p_instr *)low_make_buf_space(sizeof(p_instr), &instrbuf);
@@ -483,7 +485,7 @@ static INLINE ptrdiff_t insopt1(int f, INT32 a, int cl, struct pike_string *cf)
 {
 #ifdef PIKE_DEBUG
   if(!hasarg(f) && a)
-    fatal("hasarg(%d) is wrong!\n",f);
+    fatal("hasarg(%d /* %s */) is wrong!\n",f,get_f_name(f));
 #endif
 
   return insopt2(f,a,0,cl, cf);
@@ -493,7 +495,7 @@ static INLINE ptrdiff_t insopt0(int f, int cl, struct pike_string *cf)
 {
 #ifdef PIKE_DEBUG
   if(hasarg(f))
-    fatal("hasarg(%d) is wrong!\n",f);
+    fatal("hasarg(%d /* %s */) is wrong!\n",f,get_f_name(f));
 #endif
   return insopt2(f,0,0,cl, cf);
 }
diff --git a/src/peep.in b/src/peep.in
index 26dca99cca..7e4e175d3f 100644
--- a/src/peep.in
+++ b/src/peep.in
@@ -1,5 +1,5 @@
 //
-// $Id: peep.in,v 1.55 2001/06/29 19:48:49 hubbe Exp $
+// $Id: peep.in,v 1.56 2001/07/02 04:09:49 hubbe Exp $
 //
 
 NOP :
@@ -389,3 +389,17 @@ MKCALLOPTS(CALL_FUNCTION)
 MKCALLOPTS(CALL_LFUN)
 MKCALLOPTS(CALL_BUILTIN)
 
+CALL_BUILTIN1 POP_VALUE : CALL_BUILTIN1_AND_POP ($1a)
+
+#define OPT_TYPEP(X,Y) \
+ CALL_BUILTIN1 [ Pike_compiler->new_program->constants[$1a].sval.u.efun->function == X ] BRANCH_WHEN_ZERO : BRANCH_IF_TYPE_IS_NOT(Y) POINTER($2a);
+
+#if 1
+OPT_TYPEP(f_intp, T_INT)
+OPT_TYPEP(f_stringp, T_STRING)
+OPT_TYPEP(f_arrayp, T_ARRAY)
+OPT_TYPEP(f_floatp, T_FLOAT)
+OPT_TYPEP(f_mappingp, T_MAPPING)
+OPT_TYPEP(f_multisetp, T_MULTISET)
+#endif
+
-- 
GitLab