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 - 2019 MonetDB B.V.
7 */
8
9#include "monetdb_config.h"
10#include "opt_garbageCollector.h"
11#include "mal_interpreter.h"
12#include "mal_builder.h"
13#include "mal_function.h"
14#include "opt_prelude.h"
15
16/* The garbage collector is focused on removing temporary BATs only.
17 * Leaving some garbage on the stack is an issue.
18 *
19 * The end-of-life of a BAT may lay within block bracket. This calls
20 * for care, as the block may trigger a loop and then the BATs should
21 * still be there.
22 *
23 * The life time of such BATs is forcefully terminated after the block exit.
24 */
25str
26OPTgarbageCollectorImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
27{
28 int i, limit;
29 InstrPtr p;
30 int actions = 0;
31 char buf[256];
32 lng usec = GDKusec();
33 str msg = MAL_SUCCEED;
34 char *used;
35
36 (void) pci;
37 (void) stk;
38 if ( mb->inlineProp)
39 return 0;
40
41 used = (char*) GDKzalloc(sizeof(char) * mb->vtop);
42 if ( used == NULL)
43 throw(MAL, "optimizer.garbagecollector", SQLSTATE(HY001) MAL_MALLOC_FAIL);
44
45 limit = mb->stop;
46
47 /* variables get their name from the position */
48 /* rename all temporaries used for ease of variable table interpretation */
49 /* this code should not be necessary is variables always keep their position */
50 for( i = 0; i < mb->vtop; i++){
51 //strcpy(buf, getVarName(mb,i));
52 if (getVarName(mb,i)[0] == 'X' && getVarName(mb,i)[1] == '_')
53 snprintf(getVarName(mb,i),IDLENGTH,"X_%d",i);
54 else
55 if (getVarName(mb,i)[0] == 'C' && getVarName(mb,i)[1] == '_')
56 snprintf(getVarName(mb,i),IDLENGTH,"C_%d",i);
57 //if(strcmp(buf, getVarName(mb,i)) )
58 //fprintf(stderr, "non-matching name/entry %s %s\n", buf, getVarName(mb,i));
59 }
60
61 // move SQL query definition to the front for event profiling tools
62 p = NULL;
63 for(i = 0; i < limit; i++)
64 if(mb->stmt[i] && getModuleId(mb->stmt[i]) == querylogRef && getFunctionId(mb->stmt[i]) == defineRef ){
65 p = getInstrPtr(mb,i);
66 break;
67 }
68
69 if( p != NULL){
70 for( ; i > 1; i--)
71 mb->stmt[i] = mb->stmt[i-1];
72 mb->stmt[1] = p;
73 actions =1;
74 }
75
76 // Actual garbage collection stuff, just mark them for re-assessment
77 p = NULL;
78 for (i = 0; i < limit; i++) {
79 p = getInstrPtr(mb, i);
80 p->gc &= ~GARBAGECONTROL;
81 p->typechk = TYPE_UNKNOWN;
82 /* Set the program counter to ease profiling */
83 p->pc = i;
84 if ( p->token == ENDsymbol)
85 break;
86 }
87 /* A good MAL plan should end with an END instruction */
88 if( p && p->token != ENDsymbol){
89 throw(MAL, "optimizer.garbagecollector", SQLSTATE(42000) "Incorrect MAL plan encountered");
90 }
91 getInstrPtr(mb,0)->gc |= GARBAGECONTROL;
92 GDKfree(used);
93 if( OPTdebug & OPTgarbagecollector)
94 { int k;
95 fprintf(stderr, "#Garbage collected BAT variables \n");
96 for ( k =0; k < mb->vtop; k++)
97 fprintf(stderr,"%10s eolife %3d begin %3d lastupd %3d end %3d\n",
98 getVarName(mb,k), getVarEolife(mb,k),
99 getBeginScope(mb,k), getLastUpdate(mb,k), getEndScope(mb,k));
100 chkFlow(mb);
101 if ( mb->errors != MAL_SUCCEED ){
102 fprintf(stderr,"%s\n",mb->errors);
103 freeException(mb->errors);
104 mb->errors = MAL_SUCCEED;
105 }
106 fprintFunction(stderr,mb, 0, LIST_MAL_ALL);
107 fprintf(stderr, "End of GCoptimizer\n");
108 }
109
110 /* leave a consistent scope admin behind */
111 setVariableScope(mb);
112 /* Defense line against incorrect plans */
113 if( actions > 0){
114 chkTypes(cntxt->usermodule, mb, FALSE);
115 chkFlow(mb);
116 chkDeclarations(mb);
117 }
118
119 /* keep all actions taken as a post block comment */
120 usec = GDKusec()- usec;
121 snprintf(buf,256,"%-20s actions=%2d time=" LLFMT " usec","garbagecollector",actions, usec);
122 newComment(mb,buf);
123 if( actions >= 0)
124 addtoMalBlkHistory(mb);
125
126 if( OPTdebug & OPTgarbagecollector){
127 fprintf(stderr, "#GARBAGECOLLECTOR optimizer exit\n");
128 fprintFunction(stderr, mb, 0, LIST_MAL_ALL);
129 }
130 return msg;
131}
132
133