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 | */ |
25 | str |
26 | OPTgarbageCollectorImplementation(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 | |