Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r83937 - in trunk/tools/build/v2: engine engine/modules test/core-language
From: steven_at_[hidden]
Date: 2013-04-16 19:54:56


Author: steven_watanabe
Date: 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
New Revision: 83937
URL: http://svn.boost.org/trac/boost/changeset/83937

Log:
Optimize member function calls to use less string manipulation.
Text files modified:
   trunk/tools/build/v2/engine/compile.c | 29 +++-----
   trunk/tools/build/v2/engine/compile.h | 3
   trunk/tools/build/v2/engine/function.c | 142 ++++++++++++++++++++++++++++++++++++++-
   trunk/tools/build/v2/engine/headers.c | 3
   trunk/tools/build/v2/engine/make1.c | 6 +
   trunk/tools/build/v2/engine/modules/sequence.c | 3
   trunk/tools/build/v2/engine/search.c | 5 +
   trunk/tools/build/v2/test/core-language/test.jam | 21 +++++
   8 files changed, 181 insertions(+), 31 deletions(-)

Modified: trunk/tools/build/v2/engine/compile.c
==============================================================================
--- trunk/tools/build/v2/engine/compile.c (original)
+++ trunk/tools/build/v2/engine/compile.c 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -54,35 +54,28 @@
  * evaluate_rule() - execute a rule invocation
  */
 
-LIST * evaluate_rule( OBJECT * rulename, FRAME * frame )
+LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * frame )
 {
     LIST * result = L0;
- RULE * rule;
     profile_frame prof[ 1 ];
     module_t * prev_module = frame->module;
 
- rule = bindrule( rulename, frame->module );
-
     if ( DEBUG_COMPILE )
     {
         /* Try hard to indicate in which module the rule is going to execute. */
- if ( rule->module != frame->module && rule->procedure && !object_equal(
- rulename, function_rulename( rule->procedure ) ) )
+ char buf[ 256 ] = "";
+ if ( rule->module->name )
         {
- char buf[ 256 ] = "";
- if ( rule->module->name )
+ strncat( buf, object_str( rule->module->name ), sizeof( buf ) -
+ 1 );
+ strncat( buf, ".", sizeof( buf ) - 1 );
+ if ( strncmp( buf, object_str( rule->name ), strlen( buf ) ) == 0 )
             {
- strncat( buf, object_str( rule->module->name ), sizeof( buf ) -
- 1 );
- strncat( buf, ".", sizeof( buf ) - 1 );
+ buf[ 0 ] = 0;
             }
- strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 );
- debug_compile( 1, buf, frame );
- }
- else
- {
- debug_compile( 1, object_str( rulename ), frame );
         }
+ strncat( buf, object_str( rule->name ), sizeof( buf ) - 1 );
+ debug_compile( 1, buf, frame );
 
         lol_print( frame->args );
         printf( "\n" );
@@ -238,7 +231,7 @@
     }
     va_end( va );
 
- result = evaluate_rule( rulename, inner );
+ result = evaluate_rule( bindrule( rulename, inner->module ), rulename, inner );
 
     frame_free( inner );
 

Modified: trunk/tools/build/v2/engine/compile.h
==============================================================================
--- trunk/tools/build/v2/engine/compile.h (original)
+++ trunk/tools/build/v2/engine/compile.h 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -20,10 +20,11 @@
 #include "frames.h"
 #include "lists.h"
 #include "object.h"
+#include "rules.h"
 
 void compile_builtins();
 
-LIST * evaluate_rule( OBJECT * rulename, FRAME * );
+LIST * evaluate_rule( RULE * rule, OBJECT * rulename, FRAME * );
 LIST * call_rule( OBJECT * rulename, FRAME * caller_frame, ... );
 
 /* Flags for compile_set(), etc */

Modified: trunk/tools/build/v2/engine/function.c
==============================================================================
--- trunk/tools/build/v2/engine/function.c (original)
+++ trunk/tools/build/v2/engine/function.c 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -96,6 +96,7 @@
 #define INSTR_GET_ON 65
 
 #define INSTR_CALL_RULE 39
+#define INSTR_CALL_MEMBER_RULE 66
 
 #define INSTR_APPLY_MODIFIERS 40
 #define INSTR_APPLY_INDEX 41
@@ -472,12 +473,111 @@
         }
     }
 
- result = evaluate_rule( rulename, inner );
+ result = evaluate_rule( bindrule( rulename, inner->module ), rulename, inner );
     frame_free( inner );
     object_free( rulename );
     return result;
 }
 
+static LIST * function_call_member_rule( JAM_FUNCTION * function, FRAME * frame, STACK * s, int n_args, OBJECT * rulename, OBJECT * file, int line )
+{
+ FRAME inner[ 1 ];
+ int i;
+ LIST * first = stack_pop( s );
+ LIST * result = L0;
+ LIST * trailing;
+ RULE * rule;
+ module_t * module;
+ OBJECT * real_rulename = 0;
+
+ frame->file = file;
+ frame->line = line;
+
+ if ( list_empty( first ) )
+ {
+ backtrace_line( frame );
+ printf( "warning: object is empty\n" );
+ backtrace( frame );
+
+ list_free( first );
+
+ for( i = 0; i < n_args; ++i )
+ {
+ list_free( stack_pop( s ) );
+ }
+
+ return result;
+ }
+
+ /* FIXME: handle generic case */
+ assert( list_length( first ) == 1 );
+
+ module = bindmodule( list_front( first ) );
+ if ( module->class_module )
+ {
+ rule = bindrule( rulename, module );
+ real_rulename = object_copy( function_rulename( rule->procedure ) );
+ }
+ else
+ {
+ string buf[ 1 ];
+ string_new( buf );
+ string_append( buf, object_str( list_front( first ) ) );
+ string_push_back( buf, '.' );
+ string_append( buf, object_str( rulename ) );
+ real_rulename = object_new( buf->value );
+ string_free( buf );
+ rule = bindrule( real_rulename, frame->module );
+ }
+
+ frame_init( inner );
+
+ inner->prev = frame;
+ inner->prev_user = frame->module->user_module ? frame : frame->prev_user;
+ inner->module = frame->module; /* This gets fixed up in evaluate_rule(), below. */
+
+ for( i = 0; i < n_args; ++i )
+ {
+ lol_add( inner->args, stack_at( s, n_args - i - 1 ) );
+ }
+
+ for( i = 0; i < n_args; ++i )
+ {
+ stack_pop( s );
+ }
+
+ if ( list_length( first ) > 1 )
+ {
+ string buf[ 1 ];
+ LIST * trailing = L0;
+ LISTITER iter = list_begin( first ), end = list_end( first );
+ iter = list_next( iter );
+ string_new( buf );
+ for ( ; iter != end; iter = list_next( iter ) )
+ {
+ string_append( buf, object_str( list_item( iter ) ) );
+ string_push_back( buf, '.' );
+ string_append( buf, object_str( rulename ) );
+ trailing = list_push_back( trailing, object_new( buf->value ) );
+ string_truncate( buf, 0 );
+ }
+ string_free( buf );
+ if ( inner->args->count == 0 )
+ lol_add( inner->args, trailing );
+ else
+ {
+ LIST * * const l = &inner->args->list[ 0 ];
+ *l = list_append( trailing, *l );
+ }
+ }
+
+ result = evaluate_rule( rule, real_rulename, inner );
+ frame_free( inner );
+ object_free( rulename );
+ object_free( real_rulename );
+ return result;
+}
+
 
 /* Variable expansion */
 
@@ -2557,11 +2657,29 @@
         current_file = object_str( parse->file );
         current_line = parse->line;
         group = parse_expansion( &s );
- var_parse_group_compile( group, c );
- var_parse_group_free( group );
- compile_emit( c, INSTR_CALL_RULE, n );
- compile_emit( c, compile_emit_constant( c, parse->string ), parse->line
- );
+
+ if ( group->elems->size == 2 &&
+ dynamic_array_at( VAR_PARSE *, group->elems, 0 )->type == VAR_PARSE_TYPE_VAR &&
+ dynamic_array_at( VAR_PARSE *, group->elems, 1 )->type == VAR_PARSE_TYPE_STRING &&
+ ( object_str( ( (VAR_PARSE_STRING *)dynamic_array_at( VAR_PARSE *, group->elems, 1 ) )->s )[ 0 ] == '.' ) )
+ {
+ VAR_PARSE_STRING * access = (VAR_PARSE_STRING *)dynamic_array_at( VAR_PARSE *, group->elems, 1 );
+ OBJECT * member = object_new( object_str( access->s ) + 1 );
+ /* Emit the object */
+ var_parse_var_compile( (VAR_PARSE_VAR *)dynamic_array_at( VAR_PARSE *, group->elems, 0 ), c );
+ var_parse_group_free( group );
+ compile_emit( c, INSTR_CALL_MEMBER_RULE, n );
+ compile_emit( c, compile_emit_constant( c, member ), parse->line );
+ object_free( member );
+ }
+ else
+ {
+ var_parse_group_compile( group, c );
+ var_parse_group_free( group );
+ compile_emit( c, INSTR_CALL_RULE, n );
+ compile_emit( c, compile_emit_constant( c, parse->string ), parse->line );
+ }
+
         adjust_result( c, RESULT_STACK, result_location );
     }
     else if ( parse->type == PARSE_RULES )
@@ -2840,7 +2958,7 @@
 
         /* Prepare the argument list */
         lol_add( frame->args, list_new( object_copy( list_item( iter ) ) ) );
- error = evaluate_rule( type_name, frame );
+ error = evaluate_rule( bindrule( type_name, frame->module ), type_name, frame );
 
         if ( !list_empty( error ) )
             argument_error( object_str( list_front( error ) ), called, caller,
@@ -3396,6 +3514,7 @@
             case INSTR_APPEND: op_code = INSTR_APPEND_FIXED; break;
             case INSTR_DEFAULT: op_code = INSTR_DEFAULT_FIXED; break;
             case INSTR_RETURN: return (FUNCTION *)new_func;
+ case INSTR_CALL_MEMBER_RULE:
             case INSTR_CALL_RULE: ++i; continue;
             case INSTR_PUSH_MODULE:
                 {
@@ -4114,6 +4233,15 @@
             break;
         }
 
+ case INSTR_CALL_MEMBER_RULE:
+ {
+ OBJECT * rule_name = function_get_constant( function, code[1].op_code );
+ LIST * result = function_call_member_rule( function, frame, s, code->arg, rule_name, function->file, code[1].arg );
+ stack_push( s, result );
+ ++code;
+ break;
+ }
+
         case INSTR_RULE:
             function_set_rule( function, frame, s, code->arg );
             break;

Modified: trunk/tools/build/v2/engine/headers.c
==============================================================================
--- trunk/tools/build/v2/engine/headers.c (original)
+++ trunk/tools/build/v2/engine/headers.c 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -96,9 +96,10 @@
 
         if ( lol_get( frame->args, 1 ) )
         {
+ OBJECT * rulename = list_front( hdrrule );
             /* The third argument to HDRRULE is the bound name of $(<). */
             lol_add( frame->args, list_new( object_copy( t->boundname ) ) );
- list_free( evaluate_rule( list_front( hdrrule ), frame ) );
+ list_free( evaluate_rule( bindrule( rulename, frame->module ), rulename, frame ) );
         }
 
         /* Clean up. */

Modified: trunk/tools/build/v2/engine/make1.c
==============================================================================
--- trunk/tools/build/v2/engine/make1.c (original)
+++ trunk/tools/build/v2/engine/make1.c 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -739,6 +739,7 @@
 
         /* Prepare the argument list. */
         FRAME frame[ 1 ];
+ OBJECT * rulename = list_front( timing_rule );
         frame_init( frame );
 
         /* args * :: $(__TIMING_RULE__[2-]) */
@@ -756,7 +757,7 @@
             outf_double( time->system ) ) );
 
         /* Call the rule. */
- evaluate_rule( list_front( timing_rule ), frame );
+ evaluate_rule( bindrule( rulename , root_module() ), rulename, frame );
 
         /* Clean up. */
         frame_free( frame );
@@ -795,6 +796,7 @@
 
         /* Prepare the argument list. */
         FRAME frame[ 1 ];
+ OBJECT * rulename = list_front( action_rule );
         frame_init( frame );
 
         /* args * :: $(__ACTION_RULE__[2-]) */
@@ -822,7 +824,7 @@
             lol_add( frame->args, L0 );
 
         /* Call the rule. */
- evaluate_rule( list_front( action_rule ), frame );
+ evaluate_rule( bindrule( rulename, root_module() ), rulename, frame );
 
         /* Clean up. */
         frame_free( frame );

Modified: trunk/tools/build/v2/engine/modules/sequence.c
==============================================================================
--- trunk/tools/build/v2/engine/modules/sequence.c (original)
+++ trunk/tools/build/v2/engine/modules/sequence.c 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -62,6 +62,7 @@
     OBJECT * function_name = list_front( function );
     LISTITER args_begin = list_next( list_begin( function ) ), args_end = list_end( function );
     LISTITER iter = list_begin( sequence ), end = list_end( sequence );
+ RULE * rule = bindrule( function_name, frame->prev->module );
 
     for ( ; iter != end; iter = list_next( iter ) )
     {
@@ -73,7 +74,7 @@
         inner->module = frame->prev->module;
 
         lol_add( inner->args, list_push_back( list_copy_range( function, args_begin, args_end ), object_copy( list_item( iter ) ) ) );
- result = list_append( result, evaluate_rule( function_name, inner ) );
+ result = list_append( result, evaluate_rule( rule, function_name, inner ) );
 
         frame_free( inner );
     }

Modified: trunk/tools/build/v2/engine/search.c
==============================================================================
--- trunk/tools/build/v2/engine/search.c (original)
+++ trunk/tools/build/v2/engine/search.c 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -54,7 +54,10 @@
 
             lol_add( frame->args, list_new( boundname ) );
             if ( lol_get( frame->args, 1 ) )
- list_free( evaluate_rule( list_front( bind_rule ), frame ) );
+ {
+ OBJECT * rulename = list_front( bind_rule );
+ list_free( evaluate_rule( bindrule( rulename, root_module() ), rulename, frame ) );
+ }
 
             /* Clean up */
             frame_free( frame );

Modified: trunk/tools/build/v2/test/core-language/test.jam
==============================================================================
--- trunk/tools/build/v2/test/core-language/test.jam (original)
+++ trunk/tools/build/v2/test/core-language/test.jam 2013-04-16 19:54:54 EDT (Tue, 16 Apr 2013)
@@ -250,6 +250,27 @@
 $(x)-x [ mark-order r1 : [ reset-x reset ] ] : [ mark-order r2 ] ;
 check-order rule-order : r1 r2 ;
 
+# Cases that look like member calls
+rule looks.like-a-member ( args * )
+{
+ return $(args) ;
+}
+
+rule call-non-member ( rule + )
+{
+ return [ $(rule).like-a-member ] ;
+}
+
+rule call-non-member-with-args ( rule + )
+{
+ return [ $(rule).like-a-member a2 ] ;
+}
+
+check-equal rule-non-member : [ call-non-member looks ] : ;
+#check-equal rule-non-member-a1 : [ call-non-member looks a1 ] : looks.a1 ;
+check-equal rule-non-member-args : [ call-non-member-with-args looks ] : a2 ;
+#check-equal rule-non-member-args-a1 : [ call-non-member-with-args looks a1 ] : looks.a1 a2 ;
+
 }
 
 # Check append


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk