LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_stack.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 23 32 71.9 %
Date: 2021-09-14 22:17:06 Functions: 3 4 75.0 %

          Line data    Source code
       1             : /*
       2             :  * This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0.  If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       5             :  *
       6             :  * Copyright 1997 - July 2008 CWI, August 2008 - 2021 MonetDB B.V.
       7             :  */
       8             : 
       9             : /*
      10             :  * (author) M. L. Kersten
      11             :  * @node Stack Management, The MAL Optimizer, Garbage Collection, The MAL Interpreter
      12             :  * @+ MAL runtime stack
      13             :  * The runtime context of a MAL procedure is allocated on the runtime stack
      14             :  * of the corresponding interpreter.
      15             :  * Access to the elements in the stack are through index offsets,
      16             :  * determined during MAL procedure parsing.
      17             :  *
      18             :  * The scope administration for MAL procedures is
      19             :  * decoupled from their actual runtime behavior. This means we are
      20             :  * more relaxed on space allocation, because the size is determined
      21             :  * by the number of MAL procedure definitions instead of the runtime
      22             :  * calling behavior. (See mal_interpreter for details on value stack
      23             :  * management)
      24             :  *
      25             :  * The variable names and types are kept in the stack to ease debugging.
      26             :  * The underlying string value need not be garbage collected.
      27             :  * Runtime storage for variables are allocated on the stack of the
      28             :  * interpreter thread. The physical stack is often limited in size,
      29             :  * which calls for safeguarding their value and garbage collection before returning.
      30             :  * A malicious procedure or implementation will lead to memory leakage.
      31             :  *
      32             :  * A system command (linked C-routine) may be interested in extending the
      33             :  * stack. This is precluded, because it could interfere with the recursive
      34             :  * calling sequence of procedures. To accommodate the (rare) case, the routine
      35             :  * should issue an exception to be handled by the interpreter before retrying.
      36             :  * All other errors are turned into an exception, followed by continuing
      37             :  * at the exception handling block of the MAL procedure.
      38             :  *
      39             :  * The interpreter should be protected against physical stack overflow.
      40             :  * The solution chosen is to maintain an incremental depth size.
      41             :  * Once it exceeds a threshold, we call upon the kernel to
      42             :  * ensure we are still within safe bounds.
      43             :  */
      44             : #include "monetdb_config.h"
      45             : #include "mal_stack.h"
      46             : #include "mal_exception.h"
      47             : 
      48             : /* #define DEBUG_MAL_STACK*/
      49             : 
      50             : MalStkPtr
      51      411440 : newGlobalStack(int size)
      52             : {
      53             :         MalStkPtr s;
      54             : 
      55      411440 :         s = (MalStkPtr) GDKzalloc(stackSize(size));
      56      411445 :         if (!s)
      57             :                 return NULL;
      58      411445 :         s->stksize = size;
      59      411445 :         return s;
      60             : }
      61             : 
      62             : MalStkPtr
      63           0 : reallocGlobalStack(MalStkPtr old, int cnt)
      64             : {
      65             :         int k;
      66             :         MalStkPtr s;
      67             : 
      68           0 :         if (old->stksize > cnt)
      69             :                 return old;
      70           0 :         k = ((cnt / STACKINCR) + 1) * STACKINCR;
      71           0 :         s = newGlobalStack(k);
      72           0 :         if (!s) {
      73             :                 return NULL;
      74             :         }
      75           0 :         memcpy(s, old, stackSize(old->stksize));
      76           0 :         s->stksize = k;
      77           0 :         GDKfree(old);
      78           0 :         return s;
      79             : }
      80             : /*
      81             :  * The clearStack operation throws away any space occupied by variables
      82             :  * Freeing the stack itself is automatic upon return from the interpreter
      83             :  * context. Since the stack is allocated and zeroed on the calling stack,
      84             :  * it may happen that entries are never set to a real value.
      85             :  * This can be recognized by the vtype component
      86             :  */
      87             : static void
      88      372638 : clearStack(MalStkPtr s)
      89             : {
      90             :         ValPtr v;
      91             :         int i;
      92             : 
      93      372638 :         if (!s) return;
      94             : 
      95      372638 :         i = s->stktop;
      96    61576318 :         for (v = s->stk; i > 0; i--, v++)
      97    61203680 :                 if (ATOMextern(v->vtype) && v->val.pval) {
      98      206924 :                         GDKfree(v->val.pval);
      99      206924 :                         v->vtype = 0;
     100      206924 :                         v->val.pval = NULL;
     101    60996756 :                 } else if (BATatoms[v->vtype].atomUnfix) {
     102      346182 :                         (void) BATatoms[v->vtype].atomUnfix(VALget(v));
     103      346182 :                         v->vtype = 0;
     104      346182 :                         v->val.pval = NULL;
     105             :                 }
     106      372638 :         s->stkbot = 0;
     107             : }
     108             : 
     109             : /*
     110             :  * When you add a value to the stack, you should ensure that
     111             :  * there is space left. It should only be used for global
     112             :  * stack frames, because the others are allocated in the
     113             :  * runtime stack.
     114             :  */
     115             : void
     116      372638 : freeStack(MalStkPtr stk)
     117             : {
     118      372638 :         if (stk != NULL) {
     119      372638 :                 clearStack(stk);
     120      372638 :                 GDKfree(stk);
     121             :         }
     122      372638 : }
     123             : 

Generated by: LCOV version 1.14