From eed0cf6cc39f1ed7d35922ead2fbfbb06379c883 Mon Sep 17 00:00:00 2001
From: Rene Rivera
Date: Mon, 3 Oct 2005 00:47:36 +0000
Subject: [PATCH] Variety of performance improvements. * bjam; bump to version
3.1.12 * bjam; make it possible to build in MinGW/MSYS shell * bjam; move
profile code to debug.h/c to make it available for use everywhere * bjam;
cache all filesystem query operations, Unix and Windows only, include PWD and
scanning * bjam; add memory profile info, and sprinkle throught code * bbv2;
rewrite some while() loops into for() loops to reduce time and memory * bbv2;
keep a single instance counter instead of one per type to reduce memory use *
bjam+bbv2; change NORMALIZE_PATH builtin to join path parts to reduce memory
use
[SVN r31177]
---
src/build/generators.jam | 14 +--
src/build/toolset.jam | 21 ++--
src/engine/boost-jam.spec | 3 +-
src/engine/build.bat | 2 +-
src/engine/build.jam | 8 +-
src/engine/build.sh | 19 ++-
src/engine/builtins.c | 24 +++-
src/engine/command.c | 7 ++
src/engine/compile.c | 95 +--------------
src/engine/compile.h | 2 -
src/engine/debian/changelog | 6 +
src/engine/debian/copyright | 1 +
src/engine/debug.c | 127 ++++++++++++++++++++
src/engine/debug.h | 53 +++++++++
src/engine/execnt.c | 11 ++
src/engine/execunix.c | 4 +
src/engine/filent.c | 225 ++++++++++++++++++++++--------------
src/engine/filesys.c | 31 +++++
src/engine/filesys.h | 18 +++
src/engine/fileunix.c | 154 +++++++++++++++---------
src/engine/hash.c | 38 +++++-
src/engine/hash.h | 5 +
src/engine/index.html | 4 +-
src/engine/jam.c | 24 ++--
src/engine/lists.c | 5 +-
src/engine/make1.c | 2 +
src/engine/modules.c | 17 ++-
src/engine/modules/order.c | 7 ++
src/engine/newstr.c | 21 ++++
src/engine/parse.c | 3 +
src/engine/patchlevel.h | 8 +-
src/engine/pwd.c | 28 +++--
src/engine/regexp.c | 3 +
src/engine/rules.c | 15 +++
src/engine/scan.c | 3 +
src/engine/strings.c | 3 +
src/engine/timestamp.c | 10 +-
src/kernel/class.jam | 12 +-
src/util/path.jam | 2 +-
src/util/print.jam | 7 +-
40 files changed, 738 insertions(+), 304 deletions(-)
create mode 100644 src/engine/debug.c
create mode 100644 src/engine/debug.h
diff --git a/src/build/generators.jam b/src/build/generators.jam
index 6b3be2f5b..219a3c58c 100644
--- a/src/build/generators.jam
+++ b/src/build/generators.jam
@@ -541,28 +541,20 @@ class generator
{
# We process each source one-by-one, trying to convert it to
# a usable type.
- local failed ;
- while $(sources) && ! $(failed)
+ for local source in $(sources)
{
local _c ;
local _b ;
# TODO: need to check for failure on each source.
convert-to-consumable-types $(project) : $(property-set)
- : $(sources[1]) : true : _c _b ;
+ : $(source) : true : _c _b ;
if ! $(_c)
{
- generators.dout [ indent ] " failed to convert " $(sources[1]) ;
- # failed = true ;
+ generators.dout [ indent ] " failed to convert " $(source) ;
}
$(consumed-var) += $(_c) ;
$(bypassed-var) += $(_b) ;
- sources = $(sources[2-]) ;
}
- if $(failed)
- {
- $(consumed-var) = ;
- $(bypassed-var) = ;
- }
}
rule consume-directly ( source : consumed-var : missing-types-var )
diff --git a/src/build/toolset.jam b/src/build/toolset.jam
index aa81a1f32..0841b0fe1 100644
--- a/src/build/toolset.jam
+++ b/src/build/toolset.jam
@@ -293,17 +293,22 @@ rule set-target-variables ( rule-or-module targets + : property-set )
}
.stv.$(key) = $(settings) ;
}
-
+
if $(settings) != none
{
- while $(settings)
+ local var-name = ;
+ for local name-or-value in $(settings)
{
- # Here, $(settings[1]) is the name of variable to assign
- # and $(settings[2]) is the value.
-
- $(settings[1]) on $(targets) += $(settings[2]) ;
- settings = $(settings[3-]) ;
- }
+ if $(var-name)
+ {
+ $(var-name) on $(targets) += $(name-or-value) ;
+ var-name = ;
+ }
+ else
+ {
+ var-name = $(name-or-value) ;
+ }
+ }
}
}
diff --git a/src/engine/boost-jam.spec b/src/engine/boost-jam.spec
index 2cdbc20aa..80549d1fc 100644
--- a/src/engine/boost-jam.spec
+++ b/src/engine/boost-jam.spec
@@ -1,5 +1,5 @@
Name: boost-jam
-Version: 3.1.11
+Version: 3.1.12
Summary: Build tool
Release: 1
Source: %{name}-%{version}.tgz
@@ -33,6 +33,7 @@ Copyright:
Also:
Copyright 2001-2004 David Abrahams.
Copyright 2002-2005 Rene Rivera.
+ Copyright 2003-2005 Vladimir Prus.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/engine/build.bat b/src/engine/build.bat
index 71fb25ae7..28d978b24 100644
--- a/src/engine/build.bat
+++ b/src/engine/build.bat
@@ -312,7 +312,7 @@ echo ###
set YYACC_SOURCES=yyacc.c
set MKJAMBASE_SOURCES=mkjambase.c
set BJAM_SOURCES=
-set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c execnt.c expand.c filent.c glob.c hash.c
+set BJAM_SOURCES=%BJAM_SOURCES% command.c compile.c debug.c execnt.c expand.c filent.c glob.c hash.c
set BJAM_SOURCES=%BJAM_SOURCES% hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c
set BJAM_SOURCES=%BJAM_SOURCES% newstr.c option.c parse.c pathunix.c regexp.c
set BJAM_SOURCES=%BJAM_SOURCES% rules.c scan.c search.c subst.c timestamp.c variable.c modules.c
diff --git a/src/engine/build.jam b/src/engine/build.jam
index 8a28a4674..3a7001ae7 100644
--- a/src/engine/build.jam
+++ b/src/engine/build.jam
@@ -13,7 +13,7 @@ else { . = "." ; }
# Info about what we are building.
NAME = boost-jam ;
-VERSION = 3$(.)1$(.)11 ;
+VERSION = 3$(.)1$(.)12 ;
RELEASE = 1 ;
LICENSE = 1_0 ;
@@ -98,10 +98,10 @@ toolset darwin cc : "-o " : -D
:
[ opt --release : -Wl,-x -O3 -finline-functions ]
[ opt --debug : -g -O0 -fno-inline -pg ] ;
-## GCC 2.x, 3.x
+## GCC 2.x, 3.x, 4.x
toolset gcc gcc : "-o " : -D
: -pedantic
- [ opt --release : [ opt --symbols : -g : -s ] -O3 -finline-functions ]
+ [ opt --release : [ opt --symbols : -g : -s ] -O3 ]
[ opt --debug : -g -O0 -fno-inline ] ;
## GCC 2.x, 3.x on CYGWIN but without cygwin1.dll
toolset gcc-nocygwin gcc : "-o " : -D
@@ -277,7 +277,7 @@ else
# We have some different files for UNIX, VMS, and NT.
jam.source =
- command.c compile.c expand.c glob.c
+ command.c compile.c debug.c expand.c glob.c
hash.c hcache.c headers.c hdrmacro.c
jam.c jambase.c jamgram.c
lists.c make.c make1.c newstr.c
diff --git a/src/engine/build.sh b/src/engine/build.sh
index 048080ed0..732d7985e 100755
--- a/src/engine/build.sh
+++ b/src/engine/build.sh
@@ -30,7 +30,7 @@ error_exit ()
echo "###"
echo "### Toolsets supported by this script are:"
echo "### acc, como, darwin, gcc, intel-linux, kcc, kylix, mipspro,"
- echo "### sunpro, tru64cxx, vacpp"
+ echo "### sunpro, tru64cxx, vacpp, mingw(msys)"
echo "###"
echo "### A special toolset; cc, is available which is used as a fallback"
echo "### when a more specific toolset is not found and the cc command is"
@@ -61,7 +61,10 @@ test_uname ()
# Try and guess the toolset to bootstrap the build with...
Guess_Toolset ()
{
- if test_uname Darwin ; then BOOST_JAM_TOOLSET=darwin
+ if test -r /mingw/bin/gcc ; then
+ BOOST_JAM_TOOLSET=mingw
+ BOOST_JAM_TOOLSET_ROOT=/mingw/
+ elif test_uname Darwin ; then BOOST_JAM_TOOLSET=darwin
elif test_uname IRIX ; then BOOST_JAM_TOOLSET=mipspro
elif test_uname IRIX64 ; then BOOST_JAM_TOOLSET=mipspro
elif test_uname OSF1 ; then BOOST_JAM_TOOLSET=tru64cxx
@@ -108,6 +111,13 @@ BOOST_JAM_OPT_JAM="-o bootstrap/jam0"
BOOST_JAM_OPT_MKJAMBASE="-o bootstrap/mkjambase0"
BOOST_JAM_OPT_YYACC="-o bootstrap/yyacc0"
case $BOOST_JAM_TOOLSET in
+ mingw)
+ if test -r ${BOOST_JAM_TOOLSET_ROOT}bin/gcc -r ; then
+ export PATH=${BOOST_JAM_TOOLSET_ROOT}bin:$PATH
+ fi
+ BOOST_JAM_CC="gcc -DNT"
+ ;;
+
gcc)
BOOST_JAM_CC=gcc
;;
@@ -188,13 +198,14 @@ echo "###"
YYACC_SOURCES="yyacc.c"
MKJAMBASE_SOURCES="mkjambase.c"
BJAM_SOURCES="\
- command.c compile.c execunix.c expand.c fileunix.c glob.c hash.c\
+ command.c compile.c debug.c execunix.c expand.c fileunix.c glob.c hash.c\
hdrmacro.c headers.c jam.c jambase.c jamgram.c lists.c make.c make1.c\
newstr.c option.c parse.c pathunix.c pathvms.c regexp.c\
rules.c scan.c search.c subst.c timestamp.c variable.c modules.c\
strings.c filesys.c builtins.c pwd.c class.c native.c w32_getreg.c\
modules/set.c modules/path.c modules/regex.c modules/property-set.c\
- modules/sequence.c modules/order.c"
+ modules/sequence.c modules/order.c\
+ execnt.c filent.c"
BJAM_UPDATE=
if test "$1" = "--update" -o "$2" = "--update" -o "$3" = "--update" -o "$4" = "--update" ; then
diff --git a/src/engine/builtins.c b/src/engine/builtins.c
index 5f392ff3c..a0c39f5aa 100644
--- a/src/engine/builtins.c
+++ b/src/engine/builtins.c
@@ -5,6 +5,7 @@
*/
# include "jam.h"
+# include "debug.h"
# include "lists.h"
# include "parse.h"
@@ -266,7 +267,7 @@ load_builtins()
}
{
- char * args[] = { "path", 0 };
+ char * args[] = { "path_parts", "*", 0 };
bind_builtin( "NORMALIZE_PATH",
builtin_normalize_path, 0, args );
}
@@ -547,11 +548,13 @@ builtin_glob_back(
int status,
time_t time )
{
+ PROFILE_ENTER(BUILTIN_GLOB_BACK);
+
struct globbing *globbing = (struct globbing *)closure;
LIST *l;
PATHNAME f;
string buf[1];
-
+
/* Null out directory for matching. */
/* We wish we had file_dirscan() pass up a PATHNAME. */
@@ -565,7 +568,10 @@ builtin_glob_back(
"." and ".." won't work anywhere.
*/
if (strcmp(f.f_base.ptr, ".") == 0 || strcmp(f.f_base.ptr, "..") == 0)
+ {
+ PROFILE_EXIT(BUILTIN_GLOB_BACK);
return;
+ }
string_new( buf );
path_build( &f, buf, 0 );
@@ -584,6 +590,8 @@ builtin_glob_back(
}
string_free( buf );
+
+ PROFILE_EXIT(BUILTIN_GLOB_BACK);
}
static LIST* downcase_list( LIST *in )
@@ -1263,7 +1271,7 @@ builtin_sort( PARSE *parse, FRAME *frame )
LIST *builtin_normalize_path( PARSE *parse, FRAME *frame )
{
- LIST* arg1 = lol_get( frame->args, 0 );
+ LIST* arg = lol_get( frame->args, 0 );
/* First, we iterate over all '/'-separated elements, starting from
the end of string. If we see '..', we remove previous path elements.
@@ -1276,14 +1284,20 @@ LIST *builtin_normalize_path( PARSE *parse, FRAME *frame )
char* end; /* Last character of the part of string still to be processed. */
char* current; /* Working pointer. */
int dotdots = 0; /* Number of '..' elements seen and not processed yet. */
- int rooted = arg1->string[0] == '/';
+ int rooted = arg->string[0] == '/';
char* result;
/* Make a copy of input: we should not change it. */
string_new(in);
if (!rooted)
string_push_back(in, '/');
- string_append(in, arg1->string);
+ while (arg)
+ {
+ string_append(in, arg->string);
+ arg = list_next(arg);
+ if (arg)
+ string_append(in, "/");
+ }
end = in->value + in->size - 1;
diff --git a/src/engine/command.c b/src/engine/command.c
index bcb7fcbc9..727a3278c 100644
--- a/src/engine/command.c
+++ b/src/engine/command.c
@@ -20,6 +20,7 @@
# include "parse.h"
# include "variable.h"
# include "rules.h"
+# include "debug.h"
# include "command.h"
# include
@@ -42,6 +43,9 @@ cmd_new(
int max_line = MAXLINE;
int allocated = -1;
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( CMD ) );
+
cmd->rule = rule;
cmd->shell = shell;
cmd->next = 0;
@@ -56,6 +60,9 @@ cmd_new(
free(cmd->buf); /* free any buffer from previous iteration */
cmd->buf = (char*)malloc(max_line + 1);
+
+ if ( DEBUG_PROFILE )
+ profile_memory( max_line + 1 );
if (cmd->buf == 0)
break;
diff --git a/src/engine/compile.c b/src/engine/compile.c
index 8bea9b5c7..75464cf75 100644
--- a/src/engine/compile.c
+++ b/src/engine/compile.c
@@ -11,6 +11,7 @@
*/
# include "jam.h"
+# include "debug.h"
# include "lists.h"
# include "parse.h"
@@ -28,7 +29,6 @@
# include "builtins.h"
# include "class.h"
-# include
# include
# include
# include
@@ -799,96 +799,6 @@ collect_arguments( RULE* rule, FRAME* frame )
return locals;
}
-struct profile_info
-{
- char* name; /* name of rule being called */
- clock_t cumulative; /* cumulative time spent in rule */
- clock_t net; /* time spent in rule proper */
- unsigned long num_entries; /* number of time rule was entered */
- unsigned long stack_count; /* number of the times this function is present in stack */
-};
-typedef struct profile_info profile_info;
-
-struct profile_frame
-{
- profile_info* info; /* permanent storage where data accumulates */
- clock_t overhead; /* overhead for profiling in this call */
- clock_t entry_time; /* time of last entry to rule */
- struct profile_frame* caller; /* stack frame of caller */
- clock_t subrules; /* time spent in subrules */
-};
-typedef struct profile_frame profile_frame;
-
-static profile_frame* profile_stack = 0;
-static struct hash* profile_hash = 0;
-
-static void profile_enter( char* rulename, profile_frame* frame )
-{
- clock_t start = clock();
- profile_info info, *p = &info;
-
- if ( !profile_hash )
- profile_hash = hashinit(sizeof(profile_info), "profile");
-
- info.name = rulename;
-
- if ( hashenter( profile_hash, (HASHDATA **)&p ) )
- p->cumulative = p->net = p->num_entries = p->stack_count = 0;
-
- ++(p->num_entries);
- ++(p->stack_count);
-
- frame->info = p;
-
- frame->caller = profile_stack;
- profile_stack = frame;
-
- frame->entry_time = clock();
- frame->overhead = 0;
- frame->subrules = 0;
-
- /* caller pays for the time it takes to play with the hash table */
- if ( frame->caller )
- frame->caller->overhead += frame->entry_time - start;
-}
-
-static void profile_exit(profile_frame* frame)
-{
- /* cumulative time for this call */
- clock_t t = clock() - frame->entry_time - frame->overhead;
- /* If this rule is already present on the stack, don't add the time for
- this instance. */
- if (frame->info->stack_count == 1)
- frame->info->cumulative += t;
- /* Net time does not depend on presense of the same rule in call stack. */
- frame->info->net += t - frame->subrules;
-
- if (frame->caller)
- {
- /* caller's cumulative time must account for this overhead */
- frame->caller->overhead += frame->overhead;
- frame->caller->subrules += t;
- }
- /* pop this stack frame */
- --frame->info->stack_count;
- profile_stack = frame->caller;
-}
-
-static void dump_profile_entry(void* p_, void* ignored)
-{
- profile_info* p = (profile_info*)p_;
- printf("%10d %10d %10d %s\n", p->cumulative, p->net, p->num_entries, p->name);
-}
-
-void profile_dump()
-{
- if ( profile_hash )
- {
- printf("%10s %10s %10s %s\n", "gross", "net", "# entries", "name");
- hashenumerate( profile_hash, dump_profile_entry, 0 );
- }
-}
-
static int python_instance_number = 0;
RULE *
@@ -1100,6 +1010,9 @@ evaluate_rule(
action = (ACTION *)malloc( sizeof( ACTION ) );
memset( (char *)action, '\0', sizeof( *action ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( ACTION ) );
+
action->rule = rule;
action->targets = targetlist( (TARGETS *)0, lol_get( frame->args, 0 ) );
action->sources = targetlist( (TARGETS *)0, lol_get( frame->args, 1 ) );
diff --git a/src/engine/compile.h b/src/engine/compile.h
index eb548bde3..f44e51ef4 100644
--- a/src/engine/compile.h
+++ b/src/engine/compile.h
@@ -48,8 +48,6 @@ LIST *call_rule( char *rulename, FRAME* caller_frame, ...);
regexp* regex_compile( const char* pattern );
-void profile_dump();
-
/* Flags for compile_set(), etc */
# define ASSIGN_SET 0x00 /* = assign variable */
diff --git a/src/engine/debian/changelog b/src/engine/debian/changelog
index 4bea9bdb5..29084289c 100644
--- a/src/engine/debian/changelog
+++ b/src/engine/debian/changelog
@@ -1,3 +1,9 @@
+bjam (3.1.12-1) unstable; urgency=low
+
+ * New upstream release.
+
+ -- Rene Rivera Sat, 01 Oct 2005 00:00:00 +0000
+
bjam (3.1.11-1) unstable; urgency=low
* New upstream release.
diff --git a/src/engine/debian/copyright b/src/engine/debian/copyright
index af42cefb7..4b4dcbfc8 100644
--- a/src/engine/debian/copyright
+++ b/src/engine/debian/copyright
@@ -19,6 +19,7 @@ Some portions are also:
Copyright 2001-2004 David Abrahams.
Copyright 2002-2005 Rene Rivera.
+ Copyright 2003-2005 Vladimir Prus.
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
diff --git a/src/engine/debug.c b/src/engine/debug.c
new file mode 100644
index 000000000..d3f5ef04f
--- /dev/null
+++ b/src/engine/debug.c
@@ -0,0 +1,127 @@
+/*
+ Copyright Rene Rivera 2005.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+
+# include "jam.h"
+# include "debug.h"
+
+# include "hash.h"
+
+# include
+# include
+
+static profile_frame* profile_stack = 0;
+static struct hash* profile_hash = 0;
+static profile_info profile_other = { "[OTHER]", 0, 0, 0, 0, 0 };
+static profile_info profile_total = { "[TOTAL]", 0, 0, 0, 0, 0 };
+
+profile_frame* profile_init( char* rulename, profile_frame* frame )
+{
+ if ( DEBUG_PROFILE ) profile_enter(rulename,frame);
+ return frame;
+}
+
+void profile_enter( char* rulename, profile_frame* frame )
+{
+ if ( DEBUG_PROFILE )
+ {
+ clock_t start = clock();
+ profile_info info, *p = &info;
+
+ if ( !rulename ) p = &profile_other;
+
+ if ( !profile_hash )
+ {
+ if ( rulename ) profile_hash = hashinit(sizeof(profile_info), "profile");
+ }
+
+ info.name = rulename;
+
+ if ( rulename && hashenter( profile_hash, (HASHDATA **)&p ) )
+ p->cumulative = p->net = p->num_entries = p->stack_count = p->memory = 0;
+
+ ++(p->num_entries);
+ ++(p->stack_count);
+
+ frame->info = p;
+
+ frame->caller = profile_stack;
+ profile_stack = frame;
+
+ frame->entry_time = clock();
+ frame->overhead = 0;
+ frame->subrules = 0;
+
+ /* caller pays for the time it takes to play with the hash table */
+ if ( frame->caller )
+ frame->caller->overhead += frame->entry_time - start;
+ }
+}
+
+void profile_memory( long mem )
+{
+ if ( DEBUG_PROFILE )
+ {
+ if ( profile_stack && profile_stack->info )
+ {
+ profile_stack->info->memory += mem;
+ }
+ }
+}
+
+void profile_exit(profile_frame* frame)
+{
+ if ( DEBUG_PROFILE )
+ {
+ /* cumulative time for this call */
+ clock_t t = clock() - frame->entry_time - frame->overhead;
+ /* If this rule is already present on the stack, don't add the time for
+ this instance. */
+ if (frame->info->stack_count == 1)
+ frame->info->cumulative += t;
+ /* Net time does not depend on presense of the same rule in call stack. */
+ frame->info->net += t - frame->subrules;
+
+ if (frame->caller)
+ {
+ /* caller's cumulative time must account for this overhead */
+ frame->caller->overhead += frame->overhead;
+ frame->caller->subrules += t;
+ }
+ /* pop this stack frame */
+ --frame->info->stack_count;
+ profile_stack = frame->caller;
+ }
+}
+
+static void dump_profile_entry(void* p_, void* ignored)
+{
+ profile_info* p = (profile_info*)p_;
+ unsigned long mem_each = (p->memory/(p->num_entries ? p->num_entries : 1));
+ double q = p->net; q /= (p->num_entries ? p->num_entries : 1);
+ if (!ignored)
+ {
+ profile_total.cumulative += p->net;
+ profile_total.memory += p->memory;
+ }
+ printf("%10d %10d %10d %12.6f %10d %10d %s\n",
+ p->num_entries, p->cumulative, p->net, q,
+ p->memory, mem_each,
+ p->name);
+}
+
+void profile_dump()
+{
+ if ( profile_hash )
+ {
+ printf("%10s %10s %10s %12s %10s %10s %s\n",
+ "--count--", "--gross--", "--net--", "--each--",
+ "--mem--", "--each--",
+ "--name--");
+ hashenumerate( profile_hash, dump_profile_entry, 0 );
+ dump_profile_entry(&profile_other,0);
+ dump_profile_entry(&profile_total,(void*)1);
+ }
+}
diff --git a/src/engine/debug.h b/src/engine/debug.h
new file mode 100644
index 000000000..b417c1618
--- /dev/null
+++ b/src/engine/debug.h
@@ -0,0 +1,53 @@
+/*
+ Copyright Rene Rivera 2005.
+ Distributed under the Boost Software License, Version 1.0.
+ (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
+*/
+#ifndef BJAM_DEBUG_H
+#define BJAM_DEBUG_H
+
+# include "jam.h"
+# include
+
+struct profile_info
+{
+ /* name of rule being called */
+ char* name;
+ /* cumulative time spent in rule */
+ clock_t cumulative;
+ /* time spent in rule proper */
+ clock_t net;
+ /* number of time rule was entered */
+ unsigned long num_entries;
+ /* number of the times this function is present in stack */
+ unsigned long stack_count;
+ /* bytes of memory allocated by the call */
+ unsigned long memory;
+};
+typedef struct profile_info profile_info;
+
+struct profile_frame
+{
+ /* permanent storage where data accumulates */
+ profile_info* info;
+ /* overhead for profiling in this call */
+ clock_t overhead;
+ /* time of last entry to rule */
+ clock_t entry_time;
+ /* stack frame of caller */
+ struct profile_frame* caller;
+ /* time spent in subrules */
+ clock_t subrules;
+};
+typedef struct profile_frame profile_frame;
+
+profile_frame * profile_init( char* rulename, profile_frame* frame );
+void profile_enter( char* rulename, profile_frame* frame );
+void profile_memory( long mem );
+void profile_exit(profile_frame* frame);
+void profile_dump();
+
+#define PROFILE_ENTER(scope) profile_frame PROF_ ## scope, *PROF_ ## scope ## _p = profile_init(#scope,&PROF_ ## scope)
+#define PROFILE_EXIT(scope) profile_exit(PROF_ ## scope ## _p)
+
+#endif
diff --git a/src/engine/execnt.c b/src/engine/execnt.c
index 639bf1987..27f962f72 100644
--- a/src/engine/execnt.c
+++ b/src/engine/execnt.c
@@ -13,6 +13,7 @@
# include "jam.h"
# include "lists.h"
# include "execcmd.h"
+# include "debug.h"
# include
# include
# include
@@ -149,6 +150,9 @@ string_to_args( const char* string )
if (!line)
return 0;
+ if ( DEBUG_PROFILE )
+ profile_memory( src_len+1 );
+
/* allocate the argv array.
* element 0: stores the path to the executable
* element 1: stores the command-line arguments to the executable
@@ -160,6 +164,9 @@ string_to_args( const char* string )
free( line );
return 0;
}
+
+ if ( DEBUG_PROFILE )
+ profile_memory( 3 * sizeof(char*) );
/* Strip quotes from the first command-line argument and find
* where it ends. Quotes are illegal in Win32 pathnames, so we
@@ -279,6 +286,8 @@ process_del( char* command )
line = (char*)malloc( len+4+1 );
if (!line)
return 1;
+ if ( DEBUG_PROFILE )
+ profile_memory( len+4+1 );
strncpy( line, "del ", 4 );
strncpy( line+4, q, len );
@@ -572,6 +581,8 @@ execcmd(
/* SVA - allocate 64 other just to be safe */
cmdtab[ slot ].tempfile = malloc( strlen( tempdir ) + 64 );
+ if ( DEBUG_PROFILE )
+ profile_memory( strlen( tempdir ) + 64 );
procID = GetCurrentProcessId();
diff --git a/src/engine/execunix.c b/src/engine/execunix.c
index 592f22835..af2a52b87 100644
--- a/src/engine/execunix.c
+++ b/src/engine/execunix.c
@@ -255,7 +255,11 @@ my_wait( int *status )
static HANDLE *active_handles = 0;
if (!active_handles)
+ {
active_handles = (HANDLE *)malloc(globs.jobs * sizeof(HANDLE) );
+ if ( DEBUG_PROFILE )
+ profile_memory( globs.jobs * sizeof(HANDLE) );
+ }
/* first see if any non-waited-for processes are dead,
* and return if so.
diff --git a/src/engine/filent.c b/src/engine/filent.c
index 53d507f82..170a992d4 100644
--- a/src/engine/filent.c
+++ b/src/engine/filent.c
@@ -6,14 +6,18 @@
/* This file is ALSO:
* Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Rene Rivera.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
+# include "debug.h"
+
# include "filesys.h"
# include "pathsys.h"
# include "strings.h"
+# include "newstr.h"
# ifdef OS_NT
@@ -59,89 +63,152 @@ file_dirscan(
scanback func,
void *closure )
{
- PATHNAME f;
- string filespec[1];
- string filename[1];
- long handle;
- int ret;
- struct _finddata_t finfo[1];
+ PROFILE_ENTER(FILE_DIRSCAN);
+
+ file_info_t * d = 0;
dir = short_path_to_long_path( dir );
/* First enter directory itself */
- memset( (char *)&f, '\0', sizeof( f ) );
+ d = file_query( dir );
+
+ if ( ! d || ! d->is_dir )
+ {
+ PROFILE_EXIT(FILE_DIRSCAN);
+ return;
+ }
- f.f_dir.ptr = dir;
- f.f_dir.len = strlen(dir);
+ if ( ! d->files )
+ {
+ PATHNAME f;
+ string filespec[1];
+ string filename[1];
+ long handle;
+ int ret;
+ struct _finddata_t finfo[1];
+ LIST* files = L0;
- dir = *dir ? dir : ".";
+ memset( (char *)&f, '\0', sizeof( f ) );
+
+ f.f_dir.ptr = d->name;
+ f.f_dir.len = strlen(d->name);
+
+ /* Now enter contents of directory */
+
+ string_copy( filespec, *d->name ? d->name : "." );
+ string_append( filespec, "/*" );
+
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
+
+ # if defined(__BORLANDC__) && __BORLANDC__ < 0x550
+ if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
+ {
+ string_free( filespec );
+ PROFILE_EXIT(FILE_DIRSCAN);
+ return;
+ }
+
+ string_new( filename );
+ while( !ret )
+ {
+ file_info_t * ff = 0;
+
+ f.f_base.ptr = finfo->ff_name;
+ f.f_base.len = strlen( finfo->ff_name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename );
+
+ files = list_new( files, newstr(filename->value) );
+ ff = file_info( filename->value );
+ ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1;
+ ff->is_dir = finfo->ff_attrib & FA_DIREC ? 1 : 0;
+ ff->size = finfo->ff_fsize;
+ ff->time = (finfo->ff_ftime << 16) | finfo->ff_ftime;
+
+ ret = findnext( finfo );
+ }
+ # else
+ handle = _findfirst( filespec->value, finfo );
+
+ if( ret = ( handle < 0L ) )
+ {
+ string_free( filespec );
+ PROFILE_EXIT(FILE_DIRSCAN);
+ return;
+ }
+
+ string_new( filename );
+ while( !ret )
+ {
+ file_info_t * ff = 0;
+
+ f.f_base.ptr = finfo->name;
+ f.f_base.len = strlen( finfo->name );
+
+ string_truncate( filename, 0 );
+ path_build( &f, filename, 0 );
+
+ files = list_new( files, newstr(filename->value) );
+ ff = file_info( filename->value );
+ ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1;
+ ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0;
+ ff->size = finfo->size;
+ ff->time = finfo->time_write;
+
+ ret = _findnext( handle, finfo );
+ }
+
+ _findclose( handle );
+ # endif
+ string_free( filename );
+ string_free( filespec );
+
+ d->files = files;
+ }
/* Special case \ or d:\ : enter it */
-
- if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' )
- (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
- else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' )
- (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ {
+ unsigned long len = strlen(d->name);
+ if( len == 1 && d->name[0] == '\\' )
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ else if( len == 3 && d->name[1] == ':' )
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ }
/* Now enter contents of directory */
-
- string_copy( filespec, dir );
- string_append( filespec, "/*" );
-
- if( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
-
-# if defined(__BORLANDC__) && __BORLANDC__ < 0x550
- if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) )
+ if ( d->files )
{
- string_free( filespec );
- return;
+ LIST * files = d->files;
+ while ( files )
+ {
+ file_info_t * ff = file_info( files->string );
+ (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
+ files = list_next( files );
+ }
}
+
+ PROFILE_EXIT(FILE_DIRSCAN);
+}
- string_new( filename );
- while( !ret )
+file_info_t * file_query( char * filename )
+{
+ file_info_t * ff = file_info( filename );
+ if ( ! ff->time )
{
- time_t time_write = finfo->ff_fdate;
+ struct stat statbuf;
- time_write = (time_write << 16) | finfo->ff_ftime;
- f.f_base.ptr = finfo->ff_name;
- f.f_base.len = strlen( finfo->ff_name );
+ if( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ return 0;
- string_truncate( filename, 0 );
- path_build( &f, filename );
-
- (*func)( closure, filename->value, 1 /* stat()'ed */, time_write );
-
- ret = findnext( finfo );
+ ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
+ ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
+ ff->size = statbuf.st_size;
+ ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
}
-# else
- handle = _findfirst( filespec->value, finfo );
-
- if( ret = ( handle < 0L ) )
- {
- string_free( filespec );
- return;
- }
-
- string_new( filename );
- while( !ret )
- {
- f.f_base.ptr = finfo->name;
- f.f_base.len = strlen( finfo->name );
-
- string_truncate( filename, 0 );
- path_build( &f, filename, 0 );
-
- (*func)( closure, filename->value, 1 /* stat()'ed */, finfo->time_write );
-
- ret = _findnext( handle, finfo );
- }
-
- _findclose( handle );
-# endif
- string_free( filename );
- string_free( filespec );
+ return ff;
}
/*
@@ -153,29 +220,17 @@ file_time(
char *filename,
time_t *time )
{
- /* On NT this is called only for C:/ */
-
- struct stat statbuf;
-
- if( stat( filename, &statbuf ) < 0 )
- return -1;
-
- *time = statbuf.st_mtime;
-
- return 0;
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ *time = ff->time;
+ return 0;
}
int file_is_file(char* filename)
{
- struct stat statbuf;
-
- if( stat( filename, &statbuf ) < 0 )
- return -1;
-
- if (statbuf.st_mode & S_IFREG)
- return 1;
- else
- return 0;
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ return ff->is_file;
}
@@ -252,6 +307,8 @@ file_archscan(
*/
string_table = malloc(lar_size+1);
+ if ( DEBUG_PROFILE )
+ profile_memory( lar_size+1 );
if (read(fd, string_table, lar_size) != lar_size)
printf("error reading string table\n");
string_table[lar_size] = '\0';
diff --git a/src/engine/filesys.c b/src/engine/filesys.c
index 597aa98bd..bec1d8fc3 100644
--- a/src/engine/filesys.c
+++ b/src/engine/filesys.c
@@ -1,6 +1,8 @@
# include "jam.h"
# include "pathsys.h"
# include "strings.h"
+# include "newstr.h"
+# include "filesys.h"
void
file_build1(
@@ -31,3 +33,32 @@ file_build1(
string_push_back( file, '>' );
}
}
+
+static struct hash * filecache_hash = 0;
+
+file_info_t * file_info(char * filename)
+{
+ file_info_t finfo_, *finfo = &finfo_;
+
+ if ( !filecache_hash )
+ filecache_hash = hashinit( sizeof( file_info_t ), "file_info" );
+
+ finfo->name = filename;
+ if ( hashenter( filecache_hash, (HASHDATA**)&finfo ) )
+ {
+ /* printf( "file_info: %s\n", filename ); */
+ finfo->name = newstr( finfo->name );
+ finfo->is_file = 0;
+ finfo->is_dir = 0;
+ finfo->size = 0;
+ finfo->time = 0;
+ finfo->files = 0;
+ }
+
+ return finfo;
+}
+
+void file_done()
+{
+ hashdone( filecache_hash );
+}
diff --git a/src/engine/filesys.h b/src/engine/filesys.h
index 91f077b82..c48b28bf4 100644
--- a/src/engine/filesys.h
+++ b/src/engine/filesys.h
@@ -18,6 +18,8 @@
# define FILESYS_DWA20011025_H
# include "pathsys.h"
+#include "hash.h"
+#include "lists.h"
typedef void (*scanback)( void *closure, char *file, int found, time_t t );
@@ -29,4 +31,20 @@ int file_time( char *filename, time_t *time );
void file_build1(PATHNAME *f, string* file) ;
int file_is_file(char* filename);
+struct file_info_t {
+ char * name;
+ short is_file;
+ short is_dir;
+ unsigned long size;
+ time_t time;
+ LIST * files;
+} ;
+typedef struct file_info_t file_info_t ;
+
+file_info_t * file_info(char * filename);
+
+file_info_t * file_query(char * filename);
+
+void file_done();
+
#endif
diff --git a/src/engine/fileunix.c b/src/engine/fileunix.c
index 69bf0f17d..a57e830ca 100644
--- a/src/engine/fileunix.c
+++ b/src/engine/fileunix.c
@@ -6,14 +6,17 @@
/* This file is ALSO:
* Copyright 2001-2004 David Abrahams.
+ * Copyright 2005 Rene Rivera.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
# include "jam.h"
+# include "debug.h"
# include "filesys.h"
# include "strings.h"
# include "pathsys.h"
+# include "newstr.h"
# include
#if defined(sun) || defined(__sun)
@@ -127,52 +130,110 @@ file_dirscan(
scanback func,
void *closure )
{
- PATHNAME f;
- DIR *d;
- STRUCT_DIRENT *dirent;
+ PROFILE_ENTER(FILE_DIRSCAN);
+
+ file_info_t * d = 0;
+
+ d = file_query( dir );
+
+ if ( ! d || ! d->is_dir )
+ {
+ PROFILE_EXIT(FILE_DIRSCAN);
+ return;
+ }
+
+ if ( ! d->files )
+ {
+ LIST* files = L0;
+ PATHNAME f;
+ DIR *dd;
+ STRUCT_DIRENT *dirent;
string filename[1];
- /* First enter directory itself */
+ /* First enter directory itself */
- memset( (char *)&f, '\0', sizeof( f ) );
+ memset( (char *)&f, '\0', sizeof( f ) );
- f.f_dir.ptr = dir;
- f.f_dir.len = strlen(dir);
+ f.f_dir.ptr = dir;
+ f.f_dir.len = strlen(dir);
- dir = *dir ? dir : ".";
+ dir = *dir ? dir : ".";
- /* Special case / : enter it */
+ /* Now enter contents of directory */
- if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' )
- (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 );
+ if( !( dd = opendir( dir ) ) )
+ {
+ PROFILE_EXIT(FILE_DIRSCAN);
+ return;
+ }
- /* Now enter contents of directory */
-
- if( !( d = opendir( dir ) ) )
- return;
-
- if( DEBUG_BINDSCAN )
- printf( "scan directory %s\n", dir );
+ if( DEBUG_BINDSCAN )
+ printf( "scan directory %s\n", dir );
string_new( filename );
- while( dirent = readdir( d ) )
- {
-# ifdef old_sinix
- /* Broken structure definition on sinix. */
- f.f_base.ptr = dirent->d_name - 2;
-# else
- f.f_base.ptr = dirent->d_name;
-# endif
- f.f_base.len = strlen( f.f_base.ptr );
+ while( dirent = readdir( dd ) )
+ {
+ file_info_t * ff = 0;
+
+ # ifdef old_sinix
+ /* Broken structure definition on sinix. */
+ f.f_base.ptr = dirent->d_name - 2;
+ # else
+ f.f_base.ptr = dirent->d_name;
+ # endif
+ f.f_base.len = strlen( f.f_base.ptr );
string_truncate( filename, 0 );
- path_build( &f, filename, 0 );
+ path_build( &f, filename, 0 );
- (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 );
- }
+ files = list_new( files, newstr(filename->value) );
+ file_query( filename->value );
+ }
string_free( filename );
- closedir( d );
+ closedir( dd );
+
+ d->files = files;
+ }
+
+ /* Special case / : enter it */
+ {
+ unsigned long len = strlen(d->name);
+ if( len == 1 && d->name[0] == '/' )
+ (*func)( closure, d->name, 1 /* stat()'ed */, d->time );
+ }
+
+ /* Now enter contents of directory */
+ if ( d->files )
+ {
+ LIST * files = d->files;
+ while ( files )
+ {
+ file_info_t * ff = file_info( files->string );
+ (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time );
+ files = list_next( files );
+ }
+ }
+
+ PROFILE_EXIT(FILE_DIRSCAN);
+}
+
+file_info_t * file_query( char * filename )
+{
+ file_info_t * ff = file_info( filename );
+ if ( ! ff->time )
+ {
+ struct stat statbuf;
+
+ if( stat( *filename ? filename : ".", &statbuf ) < 0 )
+ return 0;
+
+ ff->is_file = statbuf.st_mode & S_IFREG ? 1 : 0;
+ ff->is_dir = statbuf.st_mode & S_IFDIR ? 1 : 0;
+ ff->size = statbuf.st_size;
+ ff->time = statbuf.st_mtime ? statbuf.st_mtime : 1;
+ }
+ return ff;
}
/*
@@ -184,32 +245,17 @@ file_time(
char *filename,
time_t *time )
{
- struct stat statbuf;
-
- if( stat( filename, &statbuf ) < 0 )
- return -1;
-
- /* Technically, existing files can have 0 as statbuf.st_mtime
- --- in particular, the /cygdrive directory under cygwin. However,
- though all the code jam assumes that timestamp of 0 means
- "does not exist" and will try to create the "missing" target, causing
- problems. Work around this problem by chanding 0 to 1.
- */
- *time = statbuf.st_mtime ? statbuf.st_mtime : 1 ;
- return 0;
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ *time = ff->time;
+ return 0;
}
int file_is_file(char* filename)
{
- struct stat statbuf;
-
- if( stat( filename, &statbuf ) < 0 )
- return -1;
-
- if (S_ISREG(statbuf.st_mode))
- return 1;
- else
- return 0;
+ file_info_t * ff = file_query( filename );
+ if ( !ff ) return -1;
+ return ff->is_file;
}
@@ -281,6 +327,8 @@ file_archscan(
*/
string_table = (char *)malloc(lar_size);
+ if ( DEBUG_PROFILE )
+ profile_memory( lar_size );
lseek(fd, offset + SARHDR, 0);
if (read(fd, string_table, lar_size) != lar_size)
printf("error reading string table\n");
diff --git a/src/engine/hash.c b/src/engine/hash.c
index 50572f6f4..dda649381 100644
--- a/src/engine/hash.c
+++ b/src/engine/hash.c
@@ -6,6 +6,8 @@
# include "jam.h"
# include "hash.h"
+# include "compile.h"
+#include "debug.h"
# include
/*
@@ -24,6 +26,10 @@
* 4/29/93 - ensure ITEM's are aligned
*/
+/* */
+#define HASH_DEBUG_PROFILE 1
+/* */
+
char *hashsccssid="@(#)hash.c 1.14 () 6/20/88";
/* Header attached to all data items entered into a hash table. */
@@ -144,12 +150,24 @@ hashitem(
register ITEM *i;
unsigned char *b = (unsigned char*)(*data)->key;
unsigned int keyval;
+
+ #ifdef HASH_DEBUG_PROFILE
+ profile_frame prof[1];
+ if ( DEBUG_PROFILE )
+ profile_enter( 0, prof );
+ #endif
if( enter && !hp->items.more )
hashrehash( hp );
if( !enter && !hp->items.nel )
+ {
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
+ #endif
return 0;
+ }
keyval = *b;
@@ -163,6 +181,10 @@ hashitem(
!strcmp( i->data.key, (*data)->key ) )
{
*data = &i->data;
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
+ #endif
return !0;
}
@@ -188,6 +210,10 @@ hashitem(
*data = &i->data;
}
+ #ifdef HASH_DEBUG_PROFILE
+ if ( DEBUG_PROFILE )
+ profile_exit( prof );
+ #endif
return 0;
}
@@ -198,10 +224,12 @@ hashitem(
static void hashrehash( register struct hash *hp )
{
int i = ++hp->items.list;
-
hp->items.more = i ? 2 * hp->items.nel : hp->inel;
hp->items.next = (char *)malloc( hp->items.more * hp->items.size );
hp->items.free = 0;
+
+ if ( DEBUG_PROFILE )
+ profile_memory( hp->items.more * hp->items.size );
hp->items.lists[i].nel = hp->items.more;
hp->items.lists[i].base = hp->items.next;
@@ -213,6 +241,9 @@ static void hashrehash( register struct hash *hp )
hp->tab.nel = hp->items.nel * hp->bloat;
hp->tab.base = (ITEM **)malloc( hp->tab.nel * sizeof(ITEM **) );
+ if ( DEBUG_PROFILE )
+ profile_memory( hp->tab.nel * sizeof(ITEM **) );
+
memset( (char *)hp->tab.base, '\0', hp->tab.nel * sizeof( ITEM * ) );
for( i = 0; i < hp->items.list; i++ )
@@ -268,6 +299,9 @@ hashinit(
{
struct hash *hp = (struct hash *)malloc( sizeof( *hp ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( *hp ) );
+
hp->bloat = 3;
hp->tab.nel = 0;
hp->tab.base = (ITEM **)0;
@@ -277,7 +311,7 @@ hashinit(
hp->items.size = sizeof( struct hashhdr ) + ALIGNED( datalen );
hp->items.list = -1;
hp->items.nel = 0;
- hp->inel = 11;
+ hp->inel = /* */ 11 /*/ 47 /* */;
hp->name = name;
return hp;
diff --git a/src/engine/hash.h b/src/engine/hash.h
index ad43abbb2..11f0e7b3c 100644
--- a/src/engine/hash.h
+++ b/src/engine/hash.h
@@ -7,6 +7,9 @@
/*
* hash.h - simple in-memory hashing routines
*/
+
+#ifndef BOOST_JAM_HASH_H
+#define BOOST_JAM_HASH_H
typedef struct hashdata HASHDATA;
@@ -18,3 +21,5 @@ int hash_free( struct hash *hp, HASHDATA *data);
# define hashenter( hp, data ) (!hashitem( hp, data, !0 ))
# define hashcheck( hp, data ) hashitem( hp, data, 0 )
+
+#endif
diff --git a/src/engine/index.html b/src/engine/index.html
index 9b300b03f..417f9d6f5 100644
--- a/src/engine/index.html
+++ b/src/engine/index.html
@@ -138,7 +138,7 @@
facilitate its use in the Boost Build System, but should be backward
compatible with Perforce Jam.
- This is version 3.1.10 of BJam and is based on version 2.4 of
+
This is version 3.1.12 of BJam and is based on version 2.4 of
Jam/MR:
/+\
@@ -1254,7 +1254,7 @@ if $(MESSAGE) { ECHO The message is: $(MESSAGE) ; }
18 November, 2004
- Copyright 2003-2004 Rene Rivera, David Abrahams, Vladimir Prus.
+ Copyright 2003-2005 Rene Rivera, David Abrahams, Vladimir Prus.
Distributed under the Boost Software License, Version 1.0. (See
accompanying file LICENSE_1_0.txt or string;
@@ -485,9 +488,13 @@ int main( int argc, char **argv, char **arg_environ )
status |= make( targets_count, targets2, anyhow );
free(targets);
}
+
+ PROFILE_EXIT(MAIN_MAKE);
}
+ PROFILE_EXIT(MAIN); }
+
if ( DEBUG_PROFILE )
profile_dump();
@@ -497,6 +504,7 @@ int main( int argc, char **argv, char **arg_environ )
donerules();
donestamps();
donestr();
+ file_done();
/* close cmdout */
diff --git a/src/engine/lists.c b/src/engine/lists.c
index 2b527c396..92440288c 100644
--- a/src/engine/lists.c
+++ b/src/engine/lists.c
@@ -7,6 +7,7 @@
# include "jam.h"
# include "newstr.h"
# include "lists.h"
+# include "debug.h"
/*
* lists.c - maintain lists of strings
@@ -80,7 +81,9 @@ list_new(
}
else
{
- l = (LIST *)malloc( sizeof( *l ) );
+ l = (LIST *)malloc( sizeof( LIST ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( LIST ) );
}
/* If first on chain, head points here. */
diff --git a/src/engine/make1.c b/src/engine/make1.c
index 91ee208cb..030009e78 100644
--- a/src/engine/make1.c
+++ b/src/engine/make1.c
@@ -127,6 +127,8 @@ static state *alloc_state()
}
else
{
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof(state) );
return (state *)malloc(sizeof(state));
}
}
diff --git a/src/engine/modules.c b/src/engine/modules.c
index aa8f2c8d9..ea874b640 100644
--- a/src/engine/modules.c
+++ b/src/engine/modules.c
@@ -3,8 +3,10 @@
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
*/
-#include "modules.h"
#include "jam.h"
+#include "debug.h"
+
+#include "modules.h"
#include "string.h"
#include "hash.h"
#include "newstr.h"
@@ -30,6 +32,8 @@ static char* new_module_str( module_t* m, char* suffix )
module_t* bindmodule( char* name )
{
+ PROFILE_ENTER(BINDMODULE);
+
string s;
module_t m_, *m = &m_;
@@ -56,6 +60,9 @@ module_t* bindmodule( char* name )
m->user_module = 0;
}
string_free( &s );
+
+ PROFILE_EXIT(BINDMODULE);
+
return m;
}
@@ -115,9 +122,11 @@ void exit_module( module_t* m )
}
void import_module(LIST* module_names, module_t* target_module)
-{
+{
+ PROFILE_ENTER(IMPORT_MODULE);
+
struct hash* h;
-
+
if (!target_module->imported_modules)
target_module->imported_modules = hashinit( sizeof(char*), "imported");
h = target_module->imported_modules;
@@ -129,6 +138,8 @@ void import_module(LIST* module_names, module_t* target_module)
hashenter(h, (HASHDATA**)&ss);
}
+
+ PROFILE_EXIT(IMPORT_MODULE);
}
static void add_module_name( void* r_, void* result_ )
diff --git a/src/engine/modules/order.c b/src/engine/modules/order.c
index a435d9cc5..848c35ee1 100644
--- a/src/engine/modules/order.c
+++ b/src/engine/modules/order.c
@@ -7,6 +7,7 @@
#include "../strings.h"
#include "../newstr.h"
#include "../variable.h"
+#include "../debug.h"
/* Use quite klugy approach: when we add order dependency from 'a' to 'b',
@@ -62,6 +63,8 @@ void topological_sort(int** graph, int num_vertices, int* result)
{
int i;
int* colors = (int*)calloc(num_vertices, sizeof(int));
+ if ( DEBUG_PROFILE )
+ profile_memory( num_vertices*sizeof(int) );
for (i = 0; i < num_vertices; ++i)
colors[i] = white;
@@ -86,6 +89,8 @@ LIST *order( PARSE *parse, FRAME *frame )
int length = list_length(arg);
int** graph = (int**)calloc(length, sizeof(int*));
int* order = (int*)malloc((length+1)*sizeof(int));
+ if ( DEBUG_PROFILE )
+ profile_memory( length*sizeof(int*) + (length+1)*sizeof(int) );
for(tmp = arg, src = 0; tmp; tmp = tmp->next, ++src) {
/* For all object this one depend upon, add elements
@@ -94,6 +99,8 @@ LIST *order( PARSE *parse, FRAME *frame )
int index = 0;
graph[src] = (int*)calloc(list_length(dependencies)+1, sizeof(int));
+ if ( DEBUG_PROFILE )
+ profile_memory( (list_length(dependencies)+1)*sizeof(int) );
for(; dependencies; dependencies = dependencies->next) {
int dst = list_index(arg, dependencies->string);
if (dst != -1)
diff --git a/src/engine/newstr.c b/src/engine/newstr.c
index 117dfb9ab..670cee504 100644
--- a/src/engine/newstr.c
+++ b/src/engine/newstr.c
@@ -7,6 +7,7 @@
# include "jam.h"
# include "newstr.h"
# include "hash.h"
+# include "compile.h"
# include
# include
@@ -34,6 +35,8 @@ typedef char *STRING;
static struct hash *strhash = 0;
static int strtotal = 0;
+static int strcount_in = 0;
+static int strcount_out = 0;
/*
* Immortal string allocator implementation speeds string allocation
@@ -53,11 +56,20 @@ static strblock* strblock_chain = 0;
static char* storage_start = 0;
static char* storage_finish = 0;
+/* */
+#define SIMPLE_ALLOC 0
+/*/
+#define SIMPLE_ALLOC 1
+/* */
+
/*
* allocate() - Allocate n bytes of immortal string storage
*/
static char* allocate(size_t n)
{
+ #if SIMPLE_ALLOC
+ return (char*)malloc(n);
+ #else
/* See if we can grab storage from an existing block */
size_t remaining = storage_finish - storage_start;
if ( remaining >= n )
@@ -88,6 +100,7 @@ static char* allocate(size_t n)
}
return new_block->data;
}
+ #endif
}
/*
@@ -112,8 +125,12 @@ newstr( char *string )
strtotal += l + 1;
memcpy( m, string, l + 1 );
*s = m;
+
+ if ( DEBUG_PROFILE )
+ profile_memory( l+1 );
}
+ strcount_in += 1;
return *s;
}
@@ -124,6 +141,7 @@ newstr( char *string )
char *
copystr( char *s )
{
+ strcount_in += 1;
return s;
}
@@ -134,6 +152,7 @@ copystr( char *s )
void
freestr( char *s )
{
+ strcount_out += 1;
}
/*
@@ -155,4 +174,6 @@ donestr()
if( DEBUG_MEM )
printf( "%dK in strings\n", strtotal / 1024 );
+
+ /* printf( "--- %d strings of %d dangling\n", strcount_in-strcount_out, strcount_in ); */
}
diff --git a/src/engine/parse.c b/src/engine/parse.c
index c630ee77a..606112ec8 100644
--- a/src/engine/parse.c
+++ b/src/engine/parse.c
@@ -17,6 +17,7 @@
# include "newstr.h"
# include "modules.h"
# include "frames.h"
+# include "debug.h"
/*
* parse.c - make and destroy parse trees as driven by the parser
@@ -78,6 +79,8 @@ parse_make(
int num )
{
PARSE *p = (PARSE *)malloc( sizeof( PARSE ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( PARSE ) );
p->func = func;
p->left = left;
diff --git a/src/engine/patchlevel.h b/src/engine/patchlevel.h
index f93eb2a3f..a1a6df001 100644
--- a/src/engine/patchlevel.h
+++ b/src/engine/patchlevel.h
@@ -7,5 +7,11 @@
/* Keep JAMVERSYM in sync with VERSION. */
/* It can be accessed as $(JAMVERSION) in the Jamfile. */
-#define VERSION "3.1.11"
+#define VERSION_MAJOR 3
+#define VERSION_MINOR 1
+#define VERSION_PATCH 12
+#define VERSION_MAJOR_SYM "03"
+#define VERSION_MINOR_SYM "1"
+#define VERSION_PATCH_SYM "12"
+#define VERSION "3.1.12"
#define JAMVERSYM "JAMVERSION=3.1"
diff --git a/src/engine/pwd.c b/src/engine/pwd.c
index 7bf8c5c31..896524820 100644
--- a/src/engine/pwd.c
+++ b/src/engine/pwd.c
@@ -1,4 +1,4 @@
-/* Copyright Vladimir Prus 2002. Distributed under the Boost */
+/* Copyright Vladimir Prus 2002, Rene Rivera 2005. Distributed under the Boost */
/* Software License, Version 1.0. (See accompanying */
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
@@ -21,24 +21,32 @@
#endif
#endif
+/* The current directory can't change in bjam, so optimize this to cache
+** the result.
+*/
+static char pwd_buffer[PATH_MAX];
+static char * pwd_result = NULL;
LIST*
pwd(void)
{
- char buffer[PATH_MAX];
- if (getcwd(buffer, sizeof(buffer)) == NULL)
- {
- perror("can not get current directory");
- return L0;
- }
- else
+ if (!pwd_result)
{
+ if (getcwd(pwd_buffer, sizeof(pwd_buffer)) == NULL)
+ {
+ perror("can not get current directory");
+ return L0;
+ }
+ else
+ {
#ifdef NT
- return list_new(L0, short_path_to_long_path(buffer));
+ pwd_result = short_path_to_long_path(pwd_buffer);
#else
- return list_new(L0, newstr(buffer));
+ pwd_result = newstr(pwd_buffer);
#endif
+ }
}
+ return list_new(L0, pwd_result);
}
diff --git a/src/engine/regexp.c b/src/engine/regexp.c
index 92ee8efd8..33cd9f968 100644
--- a/src/engine/regexp.c
+++ b/src/engine/regexp.c
@@ -42,6 +42,7 @@
* regular-expression syntax might require a total rethink.
*/
#include "regexp.h"
+#include "debug.h"
#include
#include
#ifndef ultrix
@@ -241,6 +242,8 @@ regcomp( char *exp )
r = (regexp *)malloc(sizeof(regexp) + (unsigned)regsize);
if (r == NULL)
FAIL("out of space");
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof(regexp) + (unsigned)regsize );
/* Second pass: emit code. */
regparse = (char *)exp;
diff --git a/src/engine/rules.c b/src/engine/rules.c
index 69bb56734..2902995c3 100644
--- a/src/engine/rules.c
+++ b/src/engine/rules.c
@@ -16,6 +16,7 @@
# include "lists.h"
# include "pathsys.h"
# include "timestamp.h"
+# include "debug.h"
/* This file is ALSO:
* Copyright 2001-2004 David Abrahams.
@@ -265,6 +266,8 @@ copytarget( const TARGET *ot )
TARGET *t;
t = (TARGET *)malloc( sizeof( *t ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( *t ) );
memset( (char *)t, '\0', sizeof( *t ) );
t->name = copystr( ot->name );
t->boundname = t->name;
@@ -319,6 +322,8 @@ targetentry(
TARGETS *c;
c = (TARGETS *)malloc( sizeof( TARGETS ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( TARGETS ) );
c->target = target;
if( !chain ) chain = c;
@@ -365,6 +370,8 @@ actionlist(
ACTION *action )
{
ACTIONS *actions = (ACTIONS *)malloc( sizeof( ACTIONS ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( ACTIONS ) );
actions->action = action;
@@ -413,7 +420,11 @@ addsettings(
if ( v )
settings_freelist = v->next;
else
+ {
v = (SETTINGS *)malloc( sizeof( *v ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( *v ) );
+ }
v->symbol = newstr( symbol );
v->value = value;
@@ -553,6 +564,8 @@ donerules()
argument_list* args_new()
{
argument_list* r = (argument_list*)malloc( sizeof(argument_list) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof(argument_list) );
r->reference_count = 0;
lol_init(r->data);
return r;
@@ -690,6 +703,8 @@ static void set_rule_actions( RULE* rule, rule_actions* actions )
static rule_actions* actions_new( char* command, LIST* bindlist, int flags )
{
rule_actions* result = (rule_actions*)malloc(sizeof(rule_actions));
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof(rule_actions) );
result->command = copystr( command );
result->bindlist = bindlist;
result->flags = flags;
diff --git a/src/engine/scan.c b/src/engine/scan.c
index b6943228c..1145ac858 100644
--- a/src/engine/scan.c
+++ b/src/engine/scan.c
@@ -11,6 +11,7 @@
# include "jamgram.h"
# include "jambase.h"
# include "newstr.h"
+# include "debug.h"
/*
* scan.c - the jam yacc scanner
@@ -82,6 +83,8 @@ void
yyfparse( char *s )
{
struct include *i = (struct include *)malloc( sizeof( *i ) );
+ if ( DEBUG_PROFILE )
+ profile_memory( sizeof( *i ) );
/* Push this onto the incp chain. */
diff --git a/src/engine/strings.c b/src/engine/strings.c
index b578c7901..6c093c6b7 100644
--- a/src/engine/strings.c
+++ b/src/engine/strings.c
@@ -3,6 +3,7 @@
/* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) */
#include "strings.h"
+#include "debug.h"
#include
#include
#include
@@ -55,6 +56,8 @@ static void string_reserve_internal( string* self, size_t capacity )
if ( self->value == self->opt )
{
self->value = (char*)malloc( capacity + JAM_STRING_MAGIC_SIZE );
+ if ( DEBUG_PROFILE )
+ profile_memory( capacity + JAM_STRING_MAGIC_SIZE );
self->value[0] = 0;
strncat( self->value, self->opt, sizeof(self->opt) );
assert( strlen( self->value ) <= self->capacity ); /* This is a regression test */
diff --git a/src/engine/timestamp.c b/src/engine/timestamp.c
index f7c412808..3c5643108 100644
--- a/src/engine/timestamp.c
+++ b/src/engine/timestamp.c
@@ -11,6 +11,8 @@
*/
# include "jam.h"
+# include "debug.h"
+
# include "hash.h"
# include "filesys.h"
# include "pathsys.h"
@@ -69,13 +71,15 @@ timestamp(
char *target,
time_t *time )
{
+ PROFILE_ENTER(timestamp);
+
PATHNAME f1, f2;
BINDING binding, *b = &binding;
string buf[1];
+ string path;
+ char *p;
# ifdef DOWNSHIFT_PATHS
- string path;
- char *p;
string_copy( &path, target );
p = path.value;
@@ -181,6 +185,8 @@ timestamp(
# ifdef DOWNSHIFT_PATHS
string_free( &path );
#endif
+
+ PROFILE_EXIT(timestamp);
}
static void
diff --git a/src/kernel/class.jam b/src/kernel/class.jam
index 188f0e8ff..92b970ad8 100644
--- a/src/kernel/class.jam
+++ b/src/kernel/class.jam
@@ -82,17 +82,17 @@ rule xinit ( instance : class )
rule new ( class args * : * )
{
- .next-instance.$(class) ?= 1 ;
- local id = object($(class))@$(.next-instance.$(class)) ;
+ .next-instance ?= 1 ;
+ local id = object($(class))@$(.next-instance) ;
+
+ xinit $(id) : $(class) ;
- xinit $(id) : $(class) ;
-
INSTANCE $(id) : class@$(class) ;
IMPORT_MODULE $(id) : ;
$(id).__init__ $(args) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
-
+
# bump the next unique object name
- .next-instance.$(class) = [ numbers.increment $(.next-instance.$(class)) ] ;
+ .next-instance = [ numbers.increment $(.next-instance) ] ;
# Return the name of the new instance.
return $(id) ;
diff --git a/src/util/path.jam b/src/util/path.jam
index 6fe0dad1f..5d1c0c546 100644
--- a/src/util/path.jam
+++ b/src/util/path.jam
@@ -140,7 +140,7 @@ rule reverse ( path )
#
local rule join-imp ( elements + )
{
- return [ NORMALIZE_PATH $(elements:J="/") ] ;
+ return [ NORMALIZE_PATH $(elements) ] ;
}
#
diff --git a/src/util/print.jam b/src/util/print.jam
index 0ef4ca3c0..e776beffb 100644
--- a/src/util/print.jam
+++ b/src/util/print.jam
@@ -342,7 +342,7 @@ rule text (
text-body on $(output-target) = ;
text-suffix on $(output-target) = ;
text-action $(output-target) ;
- text-front-section.$(soutput-target) = ;
+ text-front-section.$(output-target) = ;
}
if $(overwrite)
{
@@ -368,10 +368,9 @@ rule text (
text-front-section.$(output-target) = $(prefix-body-suffix) ;
strings = $(strings[2-]) ;
}
- while $(strings)
+ for local string-n in $(strings)
{
- text-$(prefix-body-suffix) on $(output-target) += [ echo-cmd $(strings[1]) ] ;
- strings = $(strings[2-]) ;
+ text-$(prefix-body-suffix) on $(output-target) += [ echo-cmd $(string-n) ] ;
}
}
}