From bc4a6c3d4ee3d7c01bfcc96463da14e8f92adae0 Mon Sep 17 00:00:00 2001 From: Rene Rivera Date: Sat, 2 Apr 2022 11:35:47 -0500 Subject: [PATCH] Fix orphan items in function eval stack. --- src/engine/function.cpp | 50 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/src/engine/function.cpp b/src/engine/function.cpp index 51349a9aa..ee94bcca2 100644 --- a/src/engine/function.cpp +++ b/src/engine/function.cpp @@ -36,6 +36,7 @@ #include #include #include +#include /* #define FUNCTION_DEBUG_PROFILE @@ -289,6 +290,20 @@ struct _stack void done() { + if ( cleanups.size() > 0 ) + { + // err_printf( "STACK: %d, ITEMS: %d\n", (char*)end - (char*)data, cleanups.size() ); + // err_flush(); + while ( cleanups.size() > 0 ) + { + std::get<0>(cleanups.back())( + std::get<1>(cleanups.back()), + std::get<2>(cleanups.back()) ); + cleanups.pop_back(); + } + // err_printf( "STACK: %d, ITEMS: %d\n", (char*)end - (char*)data, cleanups.size() ); + // err_flush(); + } BJAM_FREE( start ); start = end = data = nullptr; } @@ -318,6 +333,7 @@ struct _stack check_alignment(); data = (char *)data - sizeof(U); check_alignment(); + cleanups.push_back(std::make_tuple(&_stack::cleanup_item, this, 1)); return top() = v; } @@ -331,6 +347,7 @@ struct _stack data = (char *)data - ( n * sizeof(U) ); check_alignment(); std::uninitialized_fill_n( reinterpret_cast( data ), n, v ); + cleanups.push_back(std::make_tuple(&_stack::cleanup_item, this, n)); return reinterpret_cast( data ); } @@ -343,6 +360,7 @@ struct _stack check_alignment(); data = (char *)data + sizeof(U); check_alignment(); + cleanups.pop_back(); return result; } @@ -353,6 +371,7 @@ struct _stack check_alignment(); data = (char *)data + ( n * sizeof(remove_cref_t) ); check_alignment(); + cleanups.pop_back(); } private: @@ -360,6 +379,11 @@ struct _stack void * start = nullptr; void * end = nullptr; void * data = nullptr; + using cleanup_f = void(*)( _stack*, int32_t ); + std::vector> cleanups; + + template + void do_cleanup(int32_t) {} struct list_alignment_helper { @@ -405,8 +429,26 @@ struct _stack + sum_advance_size::value - advance_size< select_last_t >::value; } + + template + static void cleanup_item(_stack * s, int32_t n) + { + s->data = (char *)s->data + ( n * sizeof(remove_cref_t) ); + s->check_alignment(); + } }; +template <> +void _stack::cleanup_item(_stack * s, int32_t n) +{ + for (int32_t i = 0; i < n; ++i) + { + list_free( s->top(i) ); + } + s->data = (char *)s->data + ( n * sizeof(remove_cref_t) ); + s->check_alignment(); +} + STACK * stack_global() { static STACK result; @@ -3344,7 +3386,6 @@ static void type_check_range( OBJECT * type_name, LISTITER iter, LISTITER end, for ( ; iter != end; iter = list_next( iter ) ) { - LIST * error; FRAME frame[ 1 ]; frame_init( frame ); frame->module = typecheck; @@ -3355,10 +3396,11 @@ static void type_check_range( OBJECT * type_name, LISTITER iter, LISTITER end, /* Prepare the argument list */ lol_add( frame->args, list_new( object_copy( list_item( iter ) ) ) ); - error = evaluate_rule( bindrule( type_name, frame->module ), type_name, frame ); + b2::jam::list error( evaluate_rule( + bindrule( type_name, frame->module ), type_name, frame ) ); - if ( !list_empty( error ) ) - argument_error( object_str( list_front( error ) ), called, caller, + if ( !error.empty() ) + argument_error( object_str( *error.begin() ), called, caller, arg_name ); frame_free( frame );