Changeset: bbab2d7ad02d for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=bbab2d7ad02d
Modified Files:
monetdb5/modules/mal/language.c
monetdb5/modules/mal/language.h
monetdb5/modules/mal/language.mal
monetdb5/optimizer/opt_dataflow.c
monetdb5/optimizer/opt_prelude.c
monetdb5/optimizer/opt_prelude.h
Branch: Feb2013
Log Message:
Improve release of temporaries
The sink() operation ensures we handle proper execution of variables used
repeatedly at the cost of retaining the temporaries too long.
Using the pass() operation turns it into a cheap dataflow dependency.
Cheap instruction to disgard storage while retaining the dataflow dependency.
diffs (282 lines):
diff --git a/monetdb5/modules/mal/language.c b/monetdb5/modules/mal/language.c
--- a/monetdb5/modules/mal/language.c
+++ b/monetdb5/modules/mal/language.c
@@ -152,6 +152,16 @@ MALgarbagesink( Client cntxt, MalBlkPtr
return MAL_SUCCEED;
}
+str
+MALpass( Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
+{
+ (void) cntxt;
+ (void) mb;
+ (void) stk;
+ (void) pci;
+ return MAL_SUCCEED;
+}
+
str
CMDregisterFunction(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
diff --git a/monetdb5/modules/mal/language.h b/monetdb5/modules/mal/language.h
--- a/monetdb5/modules/mal/language.h
+++ b/monetdb5/modules/mal/language.h
@@ -47,6 +47,7 @@ language_export str MALassertSht(int *re
language_export str MALassertInt(int *ret, int *val, str *msg);
language_export str MALassertLng(int *ret, lng *val, str *msg);
language_export str MALstartDataflow( Client cntxt, MalBlkPtr mb, MalStkPtr
stk, InstrPtr pci);
+language_export str MALpass( Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
language_export str MALgarbagesink( Client cntxt, MalBlkPtr mb, MalStkPtr stk,
InstrPtr pci);
language_export str CMDregisterFunction(Client cntxt, MalBlkPtr mb, MalStkPtr
stk, InstrPtr pci);
language_export str CMDsetMemoryTrace(Client cntxt, MalBlkPtr mb, MalStkPtr
stk, InstrPtr pci);
diff --git a/monetdb5/modules/mal/language.mal
b/monetdb5/modules/mal/language.mal
--- a/monetdb5/modules/mal/language.mal
+++ b/monetdb5/modules/mal/language.mal
@@ -39,6 +39,10 @@ address MALgarbagesink
comment "Variables to be considered together when triggering garbage
collection.
Used in the dataflow blocks to avoid early release of values.";
+pattern pass(v:any_1):any_1
+address MALpass
+comment "Cheap instruction to disgard storage while retaining the dataflow
dependency";
+
pattern register(m:str,f:str,code:str,help:str):void
address CMDregisterFunction
comment"Compile the code string to MAL and register it as a function.";
diff --git a/monetdb5/optimizer/opt_dataflow.c
b/monetdb5/optimizer/opt_dataflow.c
--- a/monetdb5/optimizer/opt_dataflow.c
+++ b/monetdb5/optimizer/opt_dataflow.c
@@ -132,34 +132,44 @@ dflowInstruction(InstrPtr p) {
return FALSE;
}
-static InstrPtr
-dflowGarbagesink(MalBlkPtr mb, InstrPtr *old, int start, int last, int var,
int *usage){
- InstrPtr p, sink;
+static int
+dflowGarbagesink(MalBlkPtr mb, InstrPtr *old, int start, int last, int var,
InstrPtr *sink, int top){
+ InstrPtr p, q, r;
int j,k;
- if ( usage[var] == 0 || isVarConstant(mb, var) )
- return NULL;
- sink= newInstruction(mb,ASSIGNsymbol);
- getModuleId(sink) = languageRef;
- getFunctionId(sink) = sinkRef;
- getArg(sink,0)= newTmpVariable(mb,TYPE_void);
- sink= pushArgument(mb, sink, var);
+
+ q= newInstruction(NULL,ASSIGNsymbol);
+ getModuleId(q) = languageRef;
+ getFunctionId(q) = sinkRef;
+ getArg(q,0)= newTmpVariable(mb,TYPE_void);
+ q= pushArgument(mb, q, var);
for ( j= start; j< last; j++){
+ assert(top <mb->vsize);
p = old[j];
if ( p )
for (k = p->retc; k< p->argc; k++)
- if ( getArg(p,k)== var)
- sink= pushArgument(mb,sink, getArg(p,0));
+ if ( getArg(p,k)== var) {
+ r = newInstruction(NULL,ASSIGNsymbol);
+ getModuleId(r) = languageRef;
+ getFunctionId(r) = passRef;
+ getArg(r,0) =
newTmpVariable(mb,getArgType(mb,p,0));
+ r= pushArgument(mb,r, getArg(p,0));
+ sink[top++] = r;
+ q= pushArgument(mb,q, getArg(r,0));
+ break;
+ }
}
- return sink;
+ assert(top <mb->vsize);
+ sink[top++] = q;
+ return top;
}
int
OPTdataflowImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr
p)
{
- int i,j,k, cnt, start=1,entries=0, actions=0;
+ int i,j,k, var, cnt, start=1,entries=0, actions=0;
int flowblock= 0, dumbcopy=0;
InstrPtr *sink, *old, q;
- int limit, slimit, top = 0;
+ int limit, slimit, size, top = 0;
Lifespan span;
char *init;
int *usage;
@@ -187,18 +197,18 @@ OPTdataflowImplementation(Client cntxt,
GDKfree(init);
return 0;
}
- sink= (InstrPtr*) GDKzalloc(mb->stop * sizeof(InstrPtr));
- if ( usage == NULL){
+ sink= (InstrPtr*) GDKzalloc(size = mb->vsize * sizeof(InstrPtr));
+ if ( sink == NULL){
GDKfree(span);
GDKfree(init);
- GDKfree(sink);
+ GDKfree(usage);
return 0;
}
limit= mb->stop;
slimit= mb->ssize;
old = mb->stmt;
- if ( newMalBlkStmt(mb, mb->ssize+20) <0 ){
+ if ( newMalBlkStmt(mb, mb->ssize+mb->vtop) <0 ){
GDKfree(span);
GDKfree(init);
GDKfree(usage);
@@ -222,6 +232,7 @@ OPTdataflowImplementation(Client cntxt,
/* close old flow block */
if (flowblock){
int sf = simpleFlow(old,start,i);
+ top = 0;
if (!sf && entries > 1){
for( j=start ; j<i; j++)
if (old[j]) {
@@ -234,13 +245,12 @@ OPTdataflowImplementation(Client cntxt,
}
/* collect variables garbage
collected within the block */
for( k=old[j]->retc;
k<old[j]->argc; k++)
- if(
getEndLifespan(span,getArg(old[j],k)) == j) {
- sink[top] =
dflowGarbagesink(mb,old, start, i, getArg(old[j],k), usage);
- top += sink[top] !=
NULL;
- }
- else
- if(
getEndLifespan(span,getArg(old[j],k)) < i)
-
usage[getArg(old[j],k)]++;
+ if(
getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]==1 &&
!isVarConstant(mb, var) )
+ top =
dflowGarbagesink(mb,old, start, i, getArg(old[j],k), sink,top);
+ else
+ if(
getEndLifespan(span,getArg(old[j],k)) < i && !isVarConstant(mb, var) )
+
usage[getArg(old[j],k)]++;
+ assert(top <mb->vsize);
}
q=
newFcnCall(mb,languageRef,dataflowRef);
q->barrier= BARRIERsymbol;
@@ -254,10 +264,6 @@ OPTdataflowImplementation(Client cntxt,
pushInstruction(mb,old[j]);
for( j=0; j<top; j++)
pushInstruction(mb,sink[j]);
- if ( top ) {
- top = 0;
- memset( (char*) sink, 0, limit *
sizeof(InstrPtr));
- }
if (!sf && entries>1){
q= newAssignment(mb);
q->barrier= EXITsymbol;
@@ -278,6 +284,7 @@ OPTdataflowImplementation(Client cntxt,
/* close old flow block */
if (flowblock){
int sf = simpleFlow(old,start,i);
+ top = 0;
if (!sf && entries > 1){
for( j=start ; j<i; j++)
if (old[j]) {
@@ -290,13 +297,11 @@ OPTdataflowImplementation(Client cntxt,
}
/* collect variables
garbagecollected in the block */
for( k=old[j]->retc;
k<old[j]->argc; k++)
- if(
getEndLifespan(span,getArg(old[j],k)) == i) {
-
sink[top] = dflowGarbagesink(mb, old, start, i, getArg(old[j],k), usage);
- top +=
sink[top] != NULL;
- }
- else
- if(
getEndLifespan(span,getArg(old[j],k)) < i)
-
usage[getArg(old[j],k)]++;
+ if(
getEndLifespan(span, var = getArg(old[j],k)) == j && usage[var]==1 &&
!isVarConstant(mb, var) )
+ top =
dflowGarbagesink(mb,old, start, i, getArg(old[j],k), sink,top);
+ else
+ if(
getEndLifespan(span,getArg(old[j],k)) < i && !isVarConstant(mb, var) )
+
usage[getArg(old[j],k)]++;
}
q=
newFcnCall(mb,languageRef,dataflowRef);
q->barrier= BARRIERsymbol;
@@ -308,13 +313,10 @@ OPTdataflowImplementation(Client cntxt,
for( j=start ; j<i; j++)
if (old[j])
pushInstruction(mb,old[j]);
- /* inject the optional garbage
sink statement */
- for( j=0; j<top; j++)
-
pushInstruction(mb,sink[j]);
- if ( top) {
- top = 0;
- memset( (char*) sink,
0, mb->stop * sizeof(InstrPtr));
- }
+ assert(top <mb->vsize);
+ /* inject the optional garbage sink
statement */
+ for( j=0; j<top; j++)
+
pushInstruction(mb,sink[j]);
if (!sf && entries>1){
q= newAssignment(mb);
q->barrier= EXITsymbol;
@@ -357,9 +359,10 @@ OPTdataflowImplementation(Client cntxt,
/* close old flow block */
if (flowblock){
int sf = simpleFlow(old,start,i);
+ top = 0;
if (!sf && entries > 1){
for( j=start ; j<i; j++)
- if (old[j])
+ if (old[j]) {
for( k=0; k<old[j]->retc; k++)
if( getBeginLifespan(span,getArg(old[j],k)) >
start && getEndLifespan(span,getArg(old[j],k)) >= i &&
init[getArg(old[j],k)]==0){
InstrPtr r= newAssignment(mb);
@@ -367,6 +370,13 @@ OPTdataflowImplementation(Client cntxt,
pushNil(mb,r,getArgType(mb,old[j],k));
init[getArg(old[j],k)]=1;
}
+ for( k=old[j]->retc; k<old[j]->argc; k++)
+ if( getEndLifespan(span, var =
getArg(old[j],k)) == j && usage[var]==1 && !isVarConstant(mb, var) )
+ top = dflowGarbagesink(mb,old, start,
i, getArg(old[j],k), sink,top);
+ else
+ if( getEndLifespan(span,getArg(old[j],k)) < i
&& !isVarConstant(mb, var) )
+ usage[getArg(old[j],k)]++;
+ }
q= newFcnCall(mb,languageRef,dataflowRef);
q->barrier= BARRIERsymbol;
getArg(q,0)= flowblock;
@@ -377,6 +387,10 @@ OPTdataflowImplementation(Client cntxt,
for( j=start ; j<i; j++)
if (old[j])
pushInstruction(mb,old[j]);
+ assert(top <mb->vsize);
+ /* inject the optional garbage sink statement */
+ for( j=0; j<top; j++)
+ pushInstruction(mb,sink[j]);
if (!sf && entries>1){
q= newAssignment(mb);
q->barrier= EXITsymbol;
diff --git a/monetdb5/optimizer/opt_prelude.c b/monetdb5/optimizer/opt_prelude.c
--- a/monetdb5/optimizer/opt_prelude.c
+++ b/monetdb5/optimizer/opt_prelude.c
@@ -167,6 +167,7 @@ str openRef;
str optimizerRef;
str packRef;
str pack2Ref;
+str passRef;
str partitionRef;
str pcreRef;
str pinRef;
@@ -423,6 +424,7 @@ void optimizerInit(void){
openRef = putName("open",4);
packRef = putName("pack",4);
pack2Ref = putName("pack2",5);
+ passRef = putName("pass",4);
partitionRef = putName("partition",9);
pcreRef = putName("pcre",4);
pinRef = putName("pin",3);
diff --git a/monetdb5/optimizer/opt_prelude.h b/monetdb5/optimizer/opt_prelude.h
--- a/monetdb5/optimizer/opt_prelude.h
+++ b/monetdb5/optimizer/opt_prelude.h
@@ -166,6 +166,7 @@ opt_export str openRef;
opt_export str optimizerRef;
opt_export str packRef;
opt_export str pack2Ref;
+opt_export str passRef;
opt_export str partitionRef;
opt_export str pcreRef;
opt_export str pinRef;
_______________________________________________
checkin-list mailing list
[email protected]
http://mail.monetdb.org/mailman/listinfo/checkin-list