LCOV - code coverage report
Current view: top level - monetdb5/optimizer - opt_evaluate.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 120 126 95.2 %
Date: 2021-10-13 02:24:04 Functions: 4 4 100.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             : #include "monetdb_config.h"
      10             : #include "opt_evaluate.h"
      11             : #include "opt_aliases.h"
      12             : 
      13             : static int
      14    18639438 : OPTallConstant(Client cntxt, MalBlkPtr mb, InstrPtr p)
      15             : {
      16             :         int i;
      17             :         (void)cntxt;
      18             : 
      19    18639438 :         if ( !(p->token == ASSIGNsymbol ||
      20    18638457 :                    getModuleId(p) == calcRef ||
      21    18537210 :                    getModuleId(p) == strRef ||
      22    18536907 :                    getModuleId(p) == mtimeRef ||
      23    18536611 :                    getModuleId(p) == mmathRef))
      24             :                 return FALSE;
      25      103051 :         if (getModuleId(p) == mmathRef && strcmp(getFunctionId(p), "rand") == 0)
      26             :                 return FALSE;
      27             : 
      28      233392 :         for (i = p->retc; i < p->argc; i++)
      29      163963 :                 if (isVarConstant(mb, getArg(p, i)) == FALSE)
      30             :                         return FALSE;
      31      138834 :         for (i = 0; i < p->retc; i++) {
      32       69429 :                 if (isaBatType(getArgType(mb, p, i)))
      33             :                         return FALSE;
      34       69429 :                 if ( mb->unsafeProp )
      35             :                         return FALSE;
      36             :         }
      37             :         return TRUE;
      38             : }
      39             : 
      40         133 : static int OPTsimpleflow(MalBlkPtr mb, int pc)
      41             : {
      42             :         int i, block =0, simple= TRUE;
      43             :         InstrPtr p;
      44             : 
      45         703 :         for ( i= pc; i< mb->stop; i++){
      46         703 :                 p =getInstrPtr(mb,i);
      47         703 :                 if (blockStart(p))
      48         148 :                         block++;
      49         703 :                 if ( blockExit(p))
      50         148 :                         block--;
      51         703 :                 if ( blockCntrl(p))
      52             :                         simple= FALSE;
      53         703 :                 if ( block == 0){
      54         133 :                         return simple;
      55             :                 }
      56             :         }
      57             :         return FALSE;
      58             : }
      59             : 
      60             : /* barrier blocks can only be dropped when they are fully excluded.  */
      61             : static str
      62         233 : OPTremoveUnusedBlocks(Client cntxt, MalBlkPtr mb)
      63             : {
      64             :         /* catch and remove constant bounded blocks */
      65             :         int i, j = 0, action = 0, block = -1, skip = 0, multipass = 1;
      66             :         InstrPtr p;
      67             :         str msg = MAL_SUCCEED;
      68             : 
      69         469 :         while(multipass--){
      70             :                 block = -1;
      71             :                 skip = 0;
      72             :                 j = 0;
      73       21328 :                 for (i = 0; i < mb->stop; i++) {
      74       21092 :                         p = mb->stmt[i];
      75       21092 :                         if (blockExit(p) && block == getArg(p,0) ){
      76             :                                         block = -1;
      77             :                                         skip = 0;
      78         304 :                                         freeInstruction(p);
      79         304 :                                         mb->stmt[i]= 0;
      80         304 :                                         continue;
      81             :                         }
      82       20788 :                         if (p->argc == 2 && blockStart(p) && block < 0 && isVarConstant(mb, getArg(p, 1)) && getArgType(mb, p, 1) == TYPE_bit ){
      83         330 :                                 if( getVarConstant(mb, getArg(p, 1)).val.btval == 0)
      84             :                                 {
      85         184 :                                         block = getArg(p,0);
      86         184 :                                         skip ++;
      87         184 :                                         action++;
      88             :                                 }
      89             :                                 // Try to remove the barrier statement itself (when true).
      90         330 :                                 if ( getVarConstant(mb, getArg(p, 1)).val.btval == 1  && OPTsimpleflow(mb,i))
      91             :                                 {
      92         120 :                                         block = getArg(p,0);
      93             :                                         skip = 0;
      94         120 :                                         action++;
      95         120 :                                         freeInstruction(p);
      96         120 :                                         mb->stmt[i]= 0;
      97         120 :                                         continue;
      98             :                                 }
      99             :                         } else
     100       20458 :                         if( p->argc == 2 &&  blockStart(p) && block >= 0 && skip == 0 && isVarConstant(mb, getArg(p, 1)) && getArgType(mb, p, 1) == TYPE_bit && multipass == 0)
     101             :                                 multipass++;
     102       20668 :                         if (skip){
     103         568 :                                 freeInstruction(p);
     104         568 :                                 mb->stmt[i]= 0;
     105             :                         } else
     106       20100 :                                 mb->stmt[j++] = p;
     107             :                 }
     108         236 :                 mb->stop = j;
     109        1228 :                 for (; j < i; j++)
     110         992 :                         mb->stmt[j] = NULL;
     111             :         }
     112         233 :         if (action)
     113          98 :                 msg = chkTypes(cntxt->usermodule, mb, TRUE);
     114         233 :         return msg;
     115             : }
     116             : 
     117             : str
     118      353101 : OPTevaluateImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
     119             : {
     120             :         InstrPtr p;
     121             :         int i, k, limit, *alias = 0, barrier;
     122             :         MalStkPtr env = NULL;
     123      353101 :         int debugstate = cntxt->itrace, actions = 0, constantblock = 0;
     124             :         int *assigned = 0, use;
     125             :         str msg = MAL_SUCCEED;
     126             : 
     127             :         (void)stk;
     128             : 
     129      353101 :         if ( mb->inlineProp )
     130             :                 return MAL_SUCCEED;
     131             : 
     132      353101 :         cntxt->itrace = 0;
     133             : 
     134      353101 :         assigned = (int*) GDKzalloc(sizeof(int) * mb->vtop);
     135      353101 :         if (assigned == NULL)
     136           0 :                 throw(MAL,"optimzier.evaluate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     137             : 
     138      353101 :         alias = (int*)GDKzalloc(mb->vsize * sizeof(int) * 2); /* we introduce more */
     139      353101 :         if (alias == NULL){
     140           0 :                 GDKfree(assigned);
     141           0 :                 throw(MAL,"optimzier.evaluate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     142             :         }
     143             : 
     144             :         // arguments are implicitly assigned by context
     145      353101 :         p = getInstrPtr(mb, 0);
     146      353919 :         for ( k =p->retc;  k < p->argc; k++)
     147         818 :                 assigned[getArg(p,k)]++;
     148      353101 :         limit = mb->stop;
     149    20101113 :         for (i = 1; i < limit; i++) {
     150    19748012 :                 p = getInstrPtr(mb, i);
     151             :                 // The double count emerging from a barrier exit is ignored.
     152    19748012 :                 if (! blockExit(p) || (blockExit(p) && p->retc != p->argc))
     153    39973966 :                 for ( k =0;  k < p->retc; k++)
     154    20226935 :                 if ( p->retc != p->argc || p->token != ASSIGNsymbol )
     155    20226676 :                         assigned[getArg(p,k)]++;
     156             :         }
     157             : 
     158    20101063 :         for (i = 1; i < limit && cntxt->mode != FINISHCLIENT; i++) {
     159    19747962 :                 p = getInstrPtr(mb, i);
     160             :                 // to avoid management of duplicate assignments over multiple blocks
     161             :                 // we limit ourselves to evaluation of the first assignment only.
     162    19747962 :                 use = assigned[getArg(p,0)] == 1 && !(p->argc == p->retc && blockExit(p));
     163    50373623 :                 for (k = p->retc; k < p->argc; k++)
     164    30625661 :                         if (alias[getArg(p, k)])
     165       69292 :                                 getArg(p, k) = alias[getArg(p, k)];
     166             :                 /* be aware that you only assign once to a variable */
     167    19747962 :                 if (use && p->retc == 1 && getFunctionId(p) && OPTallConstant(cntxt, mb, p) && !isUnsafeFunction(p)) {
     168       68814 :                         barrier = p->barrier;
     169       68814 :                         p->barrier = 0;
     170       68814 :                         if ( env == NULL) {
     171        8653 :                                 env = prepareMALstack(mb,  2 * mb->vsize);
     172        8653 :                                 if (!env) {
     173           0 :                                         msg = createException(MAL,"optimizer.evaluate", SQLSTATE(HY013) MAL_MALLOC_FAIL);
     174           0 :                                         goto wrapup;
     175             :                                 }
     176        8653 :                                 env->keepAlive = TRUE;
     177             :                         }
     178       68814 :                         msg = reenterMAL(cntxt, mb, i, i + 1, env);
     179       68814 :                         p->barrier = barrier;
     180       68814 :                         if (msg == MAL_SUCCEED) {
     181             :                                 int nvar;
     182             :                                 ValRecord cst;
     183             : 
     184       68283 :                                 actions++;
     185       68283 :                                 cst.vtype = 0;
     186       68283 :                                 VALcopy(&cst, &env->stk[getArg(p, 0)]);
     187             :                                 /* You may not overwrite constants.  They may be used by
     188             :                                  * other instructions */
     189       68283 :                                 nvar = defConstant(mb, getArgType(mb, p, 0), &cst);
     190       68283 :                                 if( nvar >= 0)
     191       68283 :                                         getArg(p,1) = nvar;
     192       68283 :                                 if (nvar >= env->stktop) {
     193       17892 :                                         VALcopy(&env->stk[getArg(p, 1)], &getVarConstant(mb, getArg(p, 1)));
     194       17892 :                                         env->stktop = getArg(p, 1) + 1;
     195             :                                 }
     196       68283 :                                 alias[getArg(p, 0)] = getArg(p, 1);
     197       68283 :                                 p->argc = 2;
     198       68283 :                                 p->token = ASSIGNsymbol;
     199       68283 :                                 clrFunction(p);
     200       68283 :                                 p->barrier = barrier;
     201             :                                 /* freeze the type */
     202       68283 :                                 setVarFixed(mb,getArg(p,1));
     203             :                         } else {
     204             :                                 /* if there is an error, we should postpone message handling,
     205             :                                         as the actual error (eg. division by zero ) may not happen) */
     206         531 :                                 freeException(msg);
     207             :                                 msg= MAL_SUCCEED;
     208         531 :                                 mb->errors = 0;
     209             :                         }
     210             :                 }
     211    19748352 :                 constantblock +=  blockStart(p) && OPTallConstant(cntxt, mb, p);        /* default */
     212             :         }
     213             :         // produces errors in SQL when enabled
     214      353101 :         if ( constantblock)
     215         233 :                 msg = OPTremoveUnusedBlocks(cntxt, mb);
     216      353101 :         cntxt->itrace = debugstate;
     217             : 
     218             :                 /* Defense line against incorrect plans */
     219             :         /* Plan is unaffected */
     220      353101 :         if (!msg)
     221      353101 :                 msg = chkTypes(cntxt->usermodule, mb, FALSE);
     222      353101 :         if (!msg)
     223      353101 :                 msg = chkFlow(mb);
     224      353101 :         if (!msg)
     225      353101 :                 msg = chkDeclarations(mb);
     226             :                 /* keep all actions taken as a post block comment */
     227             : 
     228           0 : wrapup:
     229             :         /* keep actions taken as a fake argument*/
     230      353101 :         (void) pushInt(mb, pci, actions);
     231             : 
     232      353101 :         if (env) {
     233        8653 :                 assert(env->stktop < env->stksize);
     234        8653 :                 freeStack(env);
     235             :         }
     236             :         if (assigned)
     237      353101 :                 GDKfree(assigned);
     238             :         if (alias)
     239      353101 :                 GDKfree(alias);
     240      353101 :         return msg;
     241             : }

Generated by: LCOV version 1.14