LCOV - code coverage report
Current view: top level - monetdb5/mal - mal_stack.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 36 36 100.0 %
Date: 2024-12-19 23:10:26 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.14