예제 #1
0
파일: mal_session.c 프로젝트: f7753/monetdb
/*
 * Determine the variables being used and clear non-used onces.
 */
void
MSresetVariables(Client cntxt, MalBlkPtr mb, MalStkPtr glb, int start)
{
	int i;
	bit *used = GDKzalloc(mb->vtop * sizeof(bit));
	if( used == NULL){
		GDKerror("MSresetVariables" MAL_MALLOC_FAIL);
		return;
	}

	for (i = 0; i < start && start < mb->vtop; i++)
		used[i] = 1;
	if (mb->errors == 0)
		for (i = start; i < mb->vtop; i++) {
			if (used[i] || !isTmpVar(mb, i)) {
				assert(!mb->var[i]->value.vtype || isVarConstant(mb, i));
				used[i] = 1;
			}
			if (glb && !used[i]) {
				if (isVarConstant(mb, i))
					garbageElement(cntxt, &glb->stk[i]);
				/* clean stack entry */
				glb->stk[i].vtype = TYPE_int;
				glb->stk[i].len = 0;
				glb->stk[i].val.pval = 0;
			}
		}

	if (mb->errors == 0)
		trimMalVariables_(mb, used, glb);
	GDKfree(used);
}
예제 #2
0
/* barrier blocks can only be dropped when they are fully excluded.  */
static int
OPTremoveUnusedBlocks(Client cntxt, MalBlkPtr mb)
{
	/* catch and remove constant bounded blocks */
	int i, j = 0, action = 0, block = 0, skip = 0, top =0, skiplist[10];
	InstrPtr p;

	for (i = 0; i < mb->stop; i++) {
		p = mb->stmt[i];
		if (blockStart(p)) {
			block++;
			if (p->argc == 2 && isVarConstant(mb, getArg(p, 1)) &&
					getArgType(mb, p, 1) == TYPE_bit &&
					getVarConstant(mb, getArg(p, 1)).val.btval == 0)
			{
				if (skip == 0)
					skip = block;
				action++;
			}
			// Try to remove the barrier statement itself (when true).
			if (p->argc == 2 && isVarConstant(mb, getArg(p, 1)) &&
					getArgType(mb, p, 1) == TYPE_bit &&
					getVarConstant(mb, getArg(p, 1)).val.btval == 1 && 
					top <10 && OPTsimpleflow(mb,i))
			{
				skiplist[top++]= getArg(p,0);
				freeInstruction(p);
				continue;
			}
		}
		if (blockExit(p)) {
			if (top > 0 && skiplist[top-1] == getArg(p,0) ){
				top--;
				freeInstruction(p);
				continue;
			} 
			if (skip )
				freeInstruction(p);
			else
				mb->stmt[j++] = p;
			if (skip == block)
				skip = 0;
			block--;
			if (block == 0)
				skip = 0;
		} else if (skip)
			freeInstruction(p);
		else
			mb->stmt[j++] = p;
	}
	mb->stop = j;
	for (; j < i; j++)
		mb->stmt[j] = NULL;
	if (action) {
		chkTypes(cntxt->fdout, cntxt->nspace, mb, TRUE);
		return mb->errors ? 0 : action;
	}
	return action;
}
예제 #3
0
/* barrier blocks can only be dropped when they are fully excluded.  */
static str
OPTremoveUnusedBlocks(Client cntxt, MalBlkPtr mb)
{
	/* catch and remove constant bounded blocks */
	int i, j = 0, action = 0, block = -1, skip = 0, multipass = 1;
	InstrPtr p;
	str msg = MAL_SUCCEED;

	while(multipass--){
		block = -1;
		skip = 0;
		j = 0;
		for (i = 0; i < mb->stop; i++) {
			p = mb->stmt[i];
			if (blockExit(p) && block == getArg(p,0) ){
					block = -1;
					skip = 0;
					freeInstruction(p);
					mb->stmt[i]= 0;
					continue;
			}
			if (p->argc == 2 && blockStart(p) && block < 0 && isVarConstant(mb, getArg(p, 1)) && getArgType(mb, p, 1) == TYPE_bit ){
				if( getVarConstant(mb, getArg(p, 1)).val.btval == 0)
				{
					block = getArg(p,0);
					skip ++;
					action++;
				}
				// Try to remove the barrier statement itself (when true).
				if ( getVarConstant(mb, getArg(p, 1)).val.btval == 1  && OPTsimpleflow(mb,i))
				{
					block = getArg(p,0);
					skip = 0;
					action++;
					freeInstruction(p);
					mb->stmt[i]= 0;
					continue;
				}
			} else 
			if( p->argc == 2 &&  blockStart(p) && block >= 0 && skip == 0 && isVarConstant(mb, getArg(p, 1)) && getArgType(mb, p, 1) == TYPE_bit && multipass == 0)
				multipass++;
			if (skip){
				freeInstruction(p);
				mb->stmt[i]= 0;
			} else
				mb->stmt[j++] = p;
		}
		mb->stop = j;
		for (; j < i; j++)
			mb->stmt[j] = NULL;
	}
	if (action)
		chkTypes(cntxt->usermodule, mb, TRUE);
	return msg;
}
예제 #4
0
str OPTsql_append(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){
	str modnme;
	str fcnnme;
	str msg= MAL_SUCCEED;
	Symbol s= NULL;
	lng t,clk= GDKusec();
	int actions = 0;

	if( p )
		removeInstruction(mb, p);
	OPTDEBUGsql_append mnstr_printf(cntxt->fdout,"=APPLY OPTIMIZER sql_append\n");
	if( p && p->argc > 1 ){
		if( getArgType(mb,p,1) != TYPE_str ||
			getArgType(mb,p,2) != TYPE_str ||
			!isVarConstant(mb,getArg(p,1)) ||
			!isVarConstant(mb,getArg(p,2))
		) {
			throw(MAL, "optimizer.sql_append", ILLARG_CONSTANTS);
		}
		if( stk != 0){
			modnme= *getArgReference_str(stk,p,1);
			fcnnme= *getArgReference_str(stk,p,2);
		} else {
			modnme= getArgDefault(mb,p,1);
			fcnnme= getArgDefault(mb,p,2);
		}
		s= findSymbol(cntxt->nspace, putName(modnme,strlen(modnme)),putName(fcnnme,strlen(fcnnme)));

		if( s == NULL) {
			char buf[1024];
			snprintf(buf,1024, "%s.%s",modnme,fcnnme);
			throw(MAL, "optimizer.sql_append", RUNTIME_OBJECT_UNDEFINED ":%s", buf);
		}
		mb = s->def;
		stk= 0;
	}
	if( mb->errors ){
		/* when we have errors, we still want to see them */
		addtoMalBlkHistory(mb,"sql_append");
		return MAL_SUCCEED;
	}
	actions= OPTsql_appendImplementation(cntxt, mb,stk,p);
	msg= optimizerCheck(cntxt, mb, "optimizer.sql_append", actions, t=(GDKusec() - clk));
	OPTDEBUGsql_append {
		mnstr_printf(cntxt->fdout,"=FINISHED sql_append %d\n",actions);
		printFunction(cntxt->fdout,mb,0,LIST_MAL_ALL );
	}
	DEBUGoptimizers
		mnstr_printf(cntxt->fdout,"#opt_reduce: " LLFMT " ms\n",t);
	QOTupdateStatistics("sql_append",actions,t);
	addtoMalBlkHistory(mb,"sql_append");
	return msg;
}
예제 #5
0
static int
OPTallConstant(Client cntxt, MalBlkPtr mb, InstrPtr p)
{
	int i;
	(void)cntxt;

	if ( !(p->token == ASSIGNsymbol ||
		   getModuleId(p) == calcRef ||
		   getModuleId(p) == strRef ||
		   getModuleId(p) == mtimeRef ||
		   getModuleId(p) == mmathRef))
		return FALSE;
	if (getModuleId(p) == mmathRef && strcmp(getFunctionId(p), "rand") == 0)
		return FALSE;

	for (i = p->retc; i < p->argc; i++)
		if (isVarConstant(mb, getArg(p, i)) == FALSE)
			return FALSE;
	for (i = 0; i < p->retc; i++) {
		if (isaBatType(getArgType(mb, p, i)))
			return FALSE;
		if ( mb->unsafeProp ) 
			return FALSE;
	}
	return TRUE;
}
예제 #6
0
/* the MAL beautifier is meant to simplify correlation of MAL variables and
 * the columns in the underlying database.
 * If the status is set, then we consider the instruction DONE and the result variables 
 * should be shown as well.
 */
static str
shortRenderingTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx)
{
	str s, nme;
	BAT *b;
	ValRecord *val;
	char *cv =0;
	int varid = getArg(p,idx);
	size_t len = BUFSIZ;

	s= GDKmalloc(len);
	if( s == NULL)
		return NULL;
	*s = 0;

	if( isVarConstant(mb,varid) ){
		val =&getVarConstant(mb, varid);
		if ((cv = VALformat(val)) == NULL) {
			GDKfree(s);
			return NULL;
		}
		if (strlen(cv) >= len) {
			char *nbuf;
			len = strlen(cv);
			nbuf = GDKrealloc(s, len + 1);
			if (nbuf == NULL) {
				GDKfree(s);
				GDKfree(cv);
				return NULL;
			}
			s = nbuf;
		}
		snprintf(s,len + 1,"%s",cv);
	} else {
		val = &stk->stk[varid];
		if ((cv = VALformat(val)) == NULL) {
			GDKfree(s);
			return NULL;
		}
		nme = getVarName(mb, varid);
		if ( isaBatType(getArgType(mb,p,idx))){
			b = BBPquickdesc(stk->stk[varid].val.bval, true);
			snprintf(s,BUFSIZ,"%s["BUNFMT"]" ,nme, b?BATcount(b):0);
		} else
			snprintf(s,BUFSIZ,"%s=%s ",nme,cv);
	}
	GDKfree(cv);
	return s;
}
예제 #7
0
static int
OPTallConstant(Client cntxt, MalBlkPtr mb, InstrPtr p)
{
	int i;
	(void)cntxt;

	if ( !( p->token == ASSIGNsymbol ||
			getModuleId(p) == calcRef ||
		   getModuleId(p) == strRef ||
		   getModuleId(p) == mmathRef ))
		return FALSE;

	for (i = p->retc; i < p->argc; i++)
		if (isVarConstant(mb, getArg(p, i)) == FALSE)
			return FALSE;
	for (i = 0; i < p->retc; i++)
		if (isaBatType(getArgType(mb, p, i)))
			return FALSE;
	return p->argc != p->retc;
}
예제 #8
0
파일: mal_listing.c 프로젝트: f7753/monetdb
/* the MAL beautifier is meant to simplify correlation of MAL variables and
 * the columns in the underlying database.
 * If the status is set, then we consider the instruction DONE and the result variables 
 * should be shown as well.
 */
static str
shortRenderingTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx)
{
	str s, nme;
	BAT *b;
	ValRecord *val;
	char *cv =0;
	int varid = getArg(p,idx);

	s= GDKmalloc(BUFSIZ);
	if( s == NULL)
		return NULL;
	*s = 0;

	if( isVarConstant(mb,varid) ){
		val =&getVarConstant(mb, varid);
		VALformat(&cv, val);
		snprintf(s,BUFSIZ,"%s",cv);
	} else {
		val = &stk->stk[varid];
		VALformat(&cv, val);
		nme = getSTC(mb, varid);
		if( nme == NULL) 
			nme = getVarName(mb, varid);
		if ( isaBatType(getArgType(mb,p,idx))){
			b = BBPquickdesc(abs(stk->stk[varid].val.ival),TRUE);
			snprintf(s,BUFSIZ,"%s["BUNFMT"]" ,nme, b?BATcount(b):0);
		} else
		if( cv)
			snprintf(s,BUFSIZ,"%s=%s ",nme,cv);
		else
			snprintf(s,BUFSIZ,"%s ",nme);
	}
	GDKfree(cv);
	return s;
}
예제 #9
0
str
runFactory(Client cntxt, MalBlkPtr mb, MalBlkPtr mbcaller, MalStkPtr stk, InstrPtr pci)
{
	Plant pl=0;
	int firstcall= TRUE, i, k;
	InstrPtr psig = getInstrPtr(mb, 0);
	ValPtr lhs, rhs;
	char cmd;
	str msg;

#ifdef DEBUG_MAL_FACTORY
	fprintf(stderr, "#factoryMgr called\n");
#endif
	/* the lookup can be largely avoided by handing out the index
	   upon factory definition. todo
		Alternative is to move them to the front
	 */
	for(i=0; i< lastPlant; i++)
	if( plants[i].factory == mb){
		if(i > 0 && i< lastPlant ){
			PlantRecord prec= plants[i-1];
			plants[i-1] = plants[i];
			plants[i]= prec;
			i--;
		}
		pl= plants+i;
		firstcall= FALSE;
		break;
	}
	if (pl == 0) {
		/* compress the plant table*/
		for(k=i=0;i<=lastPlant; i++)
		if( plants[i].inuse)
			plants[k++]= plants[i];
		lastPlant = k;
		/* initialize a new plant using the owner policy */
		pl = newPlant(mb);
		if (pl == NULL)
			throw(MAL, "factory.new", SQLSTATE(HY001) MAL_MALLOC_FAIL);
	}
	/*
	 * We have found a factory to process the request.
	 * Let's call it as a synchronous action, without concern on parallelism.
	 */
	/* remember context */
	pl->client = cntxt;
	pl->caller = mbcaller;
	pl->env = stk;
	pl->pci = pci;
	pl->inuse = 1;
	/* inherit debugging */
	cmd = stk->cmd;
	if ( pl->stk == NULL)
		throw(MAL, "factory.new", "internal error, stack frame missing");

	/* copy the calling arguments onto the stack
	   of the factory */
	i = psig->retc;
	for (k = pci->retc; i < pci->argc; i++, k++) {
		lhs = &pl->stk->stk[psig->argv[k]];
		/* variable arguments ? */
		if (k == psig->argc - 1)
			k--;

		rhs = &pl->env->stk[getArg(pci, i)];
		if (VALcopy(lhs, rhs) == NULL)
			throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		if( lhs->vtype == TYPE_bat )
			BBPretain(lhs->val.bval);
	}
	if (mb->errors)
		throw(MAL, "factory.call", PROGRAM_GENERAL);
	if (firstcall ){
		/* initialize the stack */
		for(i= psig->argc; i< mb->vtop; i++) {
			lhs = &pl->stk->stk[i];
			if( isVarConstant(mb,i) > 0 ){
				if( !isVarDisabled(mb,i)){
					rhs = &getVarConstant(mb,i);
					if (VALcopy(lhs,rhs) == NULL)
						throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
				}
			} else{
				lhs->vtype = getVarGDKType(mb,i);
				lhs->val.pval = 0;
				lhs->len = 0;
			}
		}
		pl->stk->stkbot= mb->vtop;	/* stack already initialized */
		msg = runMAL(cntxt, mb, 0, pl->stk);
	 } else {
		msg = reenterMAL(cntxt, mb, pl->pc, -1, pl->stk);
	}
	/* propagate change in debugging status */
	if (cmd && pl->stk && pl->stk->cmd != cmd && cmd != 'x')
		for (; stk; stk = stk->up)
			stk->cmd = pl->stk->cmd;
	return msg;
}
예제 #10
0
파일: opt_wrapper.c 프로젝트: f7753/monetdb
str OPTwrapper (Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p){
	str modnme = "(NONE)";
	str fcnnme = 0;
	str msg= MAL_SUCCEED;
	Symbol s= NULL;
	lng t,clk= GDKusec();
	int i, actions = 0;
	char optimizer[256];
	InstrPtr q;

	if( p == NULL)
		throw(MAL, "opt_wrapper", "missing optimizer statement");
	snprintf(optimizer,256,"%s", fcnnme = getFunctionId(p));
	q= copyInstruction(p);
	OPTIMIZERDEBUG 
		mnstr_printf(cntxt->fdout,"=APPLY OPTIMIZER %s\n",fcnnme);
	if( p && p->argc > 1 ){
		if( getArgType(mb,p,1) != TYPE_str ||
			getArgType(mb,p,2) != TYPE_str ||
			!isVarConstant(mb,getArg(p,1)) ||
			!isVarConstant(mb,getArg(p,2))
			) {
			freeInstruction(q);
			throw(MAL, optimizer, ILLARG_CONSTANTS);
		}

		if( stk != 0){
			modnme= *getArgReference_str(stk,p,1);
			fcnnme= *getArgReference_str(stk,p,2);
		} else {
			modnme= getArgDefault(mb,p,1);
			fcnnme= getArgDefault(mb,p,2);
		}
		removeInstruction(mb, p);
		s= findSymbol(cntxt->nspace, putName(modnme,strlen(modnme)),putName(fcnnme,strlen(fcnnme)));

		if( s == NULL) {
			freeInstruction(q);
			throw(MAL, optimizer, RUNTIME_OBJECT_UNDEFINED ":%s.%s", modnme, fcnnme);
		}
		mb = s->def;
		stk= 0;
	} else if( p ) 
		removeInstruction(mb, p);
	if( mb->errors ){
		/* when we have errors, we still want to see them */
		addtoMalBlkHistory(mb,getModuleId(q));
		freeInstruction(q);
		return MAL_SUCCEED;
	}


	for ( i=0; codes[i].nme; i++)
		if ( strcmp(codes[i].nme, optimizer)== 0 ){
			actions = (int)(*(codes[i].fcn))(cntxt, mb, stk,0);
			break;	
		}
	if ( codes[i].nme == 0){
		freeInstruction(q);
		throw(MAL, optimizer, RUNTIME_OBJECT_UNDEFINED ":%s.%s", modnme, fcnnme);
	}

	msg= optimizerCheck(cntxt, mb, optimizer, actions, t=(GDKusec() - clk));
	OPTIMIZERDEBUG {
		mnstr_printf(cntxt->fdout,"=FINISHED %s  %d\n",optimizer, actions);
		printFunction(cntxt->fdout,mb,0,LIST_MAL_DEBUG );
	}
	DEBUGoptimizers
		mnstr_printf(cntxt->fdout,"#optimizer %-11s %3d actions %5d MAL instructions ("SZFMT" K) " LLFMT" usec\n", optimizer, actions, mb->stop, 
		((sizeof( MalBlkRecord) +mb->ssize * offsetof(InstrRecord, argv)+ mb->vtop * sizeof(int) /* argv estimate */ +mb->vtop* sizeof(VarRecord) + mb->vsize*sizeof(VarPtr)+1023)/1024),
		t);
	QOTupdateStatistics(getModuleId(q),actions,t);
	addtoMalBlkHistory(mb,getModuleId(q));
	freeInstruction(q);
	return msg;
}
예제 #11
0
int
inlineMALblock(MalBlkPtr mb, int pc, MalBlkPtr mc)
{
	int i, k, l, n;
	InstrPtr *ns, p,q;
	int *nv, *np = NULL;

	p = getInstrPtr(mb, pc);
	q = getInstrPtr(mc, 0);
	ns = GDKzalloc((l = (mb->ssize + mc->ssize + p->retc - 3)) * sizeof(InstrPtr));
	if (ns == NULL)
		return -1;
	if ( mc->ptop > 0){
		np = (int*) GDKmalloc(mc->ptop * sizeof(int));
		if (np == 0){
			GDKfree(ns);
			return -1;
		}
	}
	nv = (int*) GDKmalloc(mc->vtop * sizeof(int));
	if (nv == 0){
		GDKfree(ns);
		if( np)
			GDKfree(np);
		return -1;
	}

	/* add all properties of the new block to the target environment */
	for (n = 0; n < mc->ptop; n++) {
		int propid = newProperty(mb);

		if (propid < 0) {
			assert(0);
			return -1;
		}
		np[n] = propid; 
		mb->prps[propid].idx = mc->prps[n].idx;
		mb->prps[propid].op = mc->prps[n].op;
		mb->prps[propid].var = mc->prps[n].var; /* fixed later */
	}

	/* add all variables of the new block to the target environment */
	for (n = 0; n < mc->vtop; n++) {
		VarPtr ov, v;

		if (isExceptionVariable(mc->var[n]->name)) {
			nv[n] = newVariable(mb,GDKstrdup(mc->var[n]->name),TYPE_str);
			if (isVarUDFtype(mc,n))
				setVarUDFtype(mb,nv[n]);
			if (isVarUsed(mc,n))
				setVarUsed(mb,nv[n]);
		} else if (isVarTypedef(mc,n)) {
			nv[n] = newTypeVariable(mb,getVarType(mc,n));
		} else if (isVarConstant(mc,n)) {
			nv[n] = cpyConstant(mb,getVar(mc,n));
		} else {
			nv[n] = newTmpVariable(mb, getVarType(mc, n));
			if (isVarUDFtype(mc,n))
				setVarUDFtype(mb,nv[n]);
			if (isVarUsed(mc,n))
				setVarUsed(mb,nv[n]);
		}
		/* remap the properties */
		ov = getVar(mc, n);
		v = getVar(mb, nv[n]);
		if (ov->propc > v->maxprop) {
			int size = sizeof(VarRecord);
        		VarPtr vnew = (VarPtr) GDKzalloc(size + ov->propc * sizeof(int));
			memcpy((char*) vnew, (char*) v, size);
			vnew->maxprop = ov->propc;
			mb->var[nv[n]] = vnew;
			GDKfree(v);
			v = getVar(mb, nv[n]);
		}
		for (i = 0; i < ov->propc; i++) 
			v->prps[i] = np[ov->prps[i]];
		v->propc = ov->propc;
	}

	/* change the property variables to the new context */
	for (n = 0; n < mc->ptop; n++) {
		if (mc->prps[n].var)
			mb->prps[np[n]].var = nv[mc->prps[n].var];
		assert( mb->prps[np[n]].var >= 0);
	}

	/* use an alias mapping to keep track of the actual arguments */
	for (n = p->retc; n < p->argc; n++)
		nv[getArg(q,n)] = getArg(p, n);

	k = 0;
	/* find the return statement of the inline function */
	for (i = 1; i < mc->stop - 1; i++) {
		q = mc->stmt[i];
		if( q->barrier== RETURNsymbol || q->barrier== YIELDsymbol){
			/* add the mapping of the return variables */
			for(n=0; n<p->retc; n++)
				nv[getArg(q,n)] = getArg(p,n);
		}
	}

	/* copy the stable part */
	for (i = 0; i < pc; i++)
		ns[k++] = mb->stmt[i];

	for (i = 1; i < mc->stop - 1; i++) {
		q = mc->stmt[i];
		if( q->token == ENDsymbol)
			break;

		/* copy the instruction and fix variable references */
		ns[k] = copyInstruction(q);
		for (n = 0; n < q->argc; n++)
			getArg(ns[k], n) = nv[getArg(q, n)];

		if (q->barrier == RETURNsymbol || q->barrier == YIELDsymbol) {
			for(n=0; n<q->retc; n++)
				clrVarFixed(mb,getArg(ns[k],n)); /* for typing */
			setModuleId(ns[k],getModuleId(q));
			setFunctionId(ns[k],getFunctionId(q));
			ns[k]->barrier = 0;
			ns[k]->token = ASSIGNsymbol;
		}
		k++;
	} 

	/* copy the remainder of the stable part */
	freeInstruction(p);
	for (i = pc + 1; i < mb->stop; i++){
		ns[k++] = mb->stmt[i];
	}
	/* remove any free instruction */
	for(; i<mb->ssize; i++)
	if( mb->stmt[i]){
		freeInstruction(mb->stmt[i]);
		mb->stmt[i]= 0;
	}
	GDKfree(mb->stmt);
	mb->stmt = ns;

	mb->ssize = l;
	mb->stop = k;
	GDKfree(np);
	GDKfree(nv);
	return pc;
}
예제 #12
0
int
OPTpushrangesImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i,j, limit,actions=0;
	InstrPtr p, *old;
	int x,y,z;
	Range range;

	if( mb->errors) 
		return 0;

	range= (Range) GDKzalloc(mb->vtop * sizeof(RangeRec));
	if (range == NULL)
		return 0;
	OPTDEBUGpushranges
		mnstr_printf(cntxt->fdout,"#Range select optimizer started\n");
	(void) stk;
	(void) pci;
	
	limit = mb->stop;
	old = mb->stmt;
	/*
	 * In phase I we collect information about constants
	 */
	for (i = 0; i < limit; i++) {
		p = old[i];
		if( p->barrier) 
			break; /* end of optimizer */
		for(j=p->retc; j< p->argc; j++)
			range[getArg(p,j)].used++;
		for(j=0; j<p->retc; j++){
			range[getArg(p,j)].lastupdate= i;
			if( range[getArg(p,j)].lastrange == 0)
				range[getArg(p,j)].lastrange= i;
		} 
		if( getModuleId(p)== algebraRef && 
			( getFunctionId(p)== selectRef || getFunctionId(p)== uselectRef) ){
			/*
			 * The operation X:= algebra.select(Y,L,H,Li,Hi) is analysed.
			 * First, we attempt to propagate the range known for Y onto the
			 * requested range of X. This may lead to smaller range of
			 * even the conclusion that X is necessarily empty.
			 * Of course, only under the condition that Y has not been changed by a
			 * side-effect since it was bound to X.
			 */
			x= getArg(p,1);
			y= getArg(p,2);
			if( range[x].lcst && isVarConstant(mb,y) ){
				/* merge lowerbound */
				if( ATOMcmp( getVarGDKType(mb,y), 
						VALptr( &getVarConstant(mb,range[x].lcst)), 
						VALptr( &getVarConstant(mb,y)) ) > 0){
					getArg(p,2)= range[x].lcst;
					z= range[x].srcvar;
					if( getArg(p,1) == x && 
						range[z].lastupdate == range[z].lastrange){
						getArg(p,1) = z;
						actions++;
					}
				}
				y= getArg(p,3);
				/* merge higherbound */
				if( ATOMcmp( getVarGDKType(mb,y), 
						VALptr( &getVarConstant(mb,range[x].hcst)), 
						VALptr( &getVarConstant(mb,y)) ) < 0 ||
					ATOMcmp( getVarGDKType(mb,y),
						VALptr( &getVarConstant(mb,y)),
						 ATOMnilptr(getVarType(mb,y)) ) == 0){
					getArg(p,3)= range[x].hcst;
					z= range[x].srcvar;
					if( getArg(p,1) == x && range[z].lastupdate == range[z].lastrange){
						getArg(p,1) = z;
						actions++;
					}
				}
			}
			/*
			 * The second step is to assign the result of this exercise to the
			 * result variable.
			 */
			x= getArg(p,0);
			if( isVarConstant(mb, getArg(p,2)) ){
				range[x].lcst = getArg(p,2);
				range[x].srcvar= getArg(p,1);
				range[x].lastupdate= range[x].lastrange = i;
			}
			if( isVarConstant(mb, getArg(p,3)) ){
				range[x].hcst = getArg(p,3);
				range[x].srcvar= getArg(p,1);
				range[x].lastupdate= range[x].lastrange = i;
			}
			/*
			 * If both range bounds are constant, we can also detect empty results.
			 * It is empty if L> H or when L=H and the bounds are !(true,true).
			 */
			x= getArg(p,2);
			y= getArg(p,3);
			if( isVarConstant(mb, x)  &&
				isVarConstant(mb, y)  ){
				z =ATOMcmp( getVarGDKType(mb,y),
                        VALptr( &getVarConstant(mb,x)),
                        VALptr( &getVarConstant(mb,y)));
				x=  p->argc > 4;
				x= x && isVarConstant(mb,getArg(p,4));
				x= x && isVarConstant(mb,getArg(p,5));
				x= x && getVarConstant(mb,getArg(p,4)).val.btval;
				x= x && getVarConstant(mb,getArg(p,5)).val.btval;
				if( z > 0 || (z==0 && p->argc>4 && !x)) {
					int var = getArg(p, 0);
					wrd zero = 0;
					ValRecord v, *vp;

					vp = VALset(&v, TYPE_wrd, &zero);
					varSetProp(mb, var, rowsProp, op_eq, vp);
					/* create an empty replacement */
					x = getArgType(mb, p, 1);
					p->argc=1;
					getModuleId(p)= batRef;
					getFunctionId(p)= newRef;
					p= pushArgument(mb,p, newTypeVariable(mb, getHeadType(x)));
					(void) pushArgument(mb,p, newTypeVariable(mb, getTailType(x)));
					actions++;
				}
			}
		}
	}
	OPTDEBUGpushranges
		for(j=0; j< mb->vtop; j++)
		if( range[j].used )
			printRange(cntxt, mb,range,j);
	/*
	 * Phase II, if we succeeded in pushing constants around and
	 * changing instructions, we might as well try once more to perform
	 * aliasRemoval, constantExpression, and pushranges.
	 */
	GDKfree(range);
	return actions;
}
예제 #13
0
파일: opt_qep.c 프로젝트: f7753/monetdb
static QEP
QEPbuild(MalBlkPtr mb){
	QEP qroot= NULL, q= NULL, *vq;
	InstrPtr p;
	int i, j, k, *status;

	vq= (QEP*) GDKmalloc( mb->vtop * sizeof(QEP));
	if (vq == NULL)
		return NULL;
	status= (int*) GDKmalloc( mb->vtop * sizeof(int));
	if (status == NULL){
		GDKfree(vq);
		return NULL;
	}
	for(i=0; i<mb->vtop; i++) {
		status[i]= 0;
		vq[i] = 0;
	}

	for(i=1; i< mb->stop-1; i++){
		p= getInstrPtr(mb,i);
		q= QEPnewNode(mb,p);
		if( q == NULL)
			continue;
		for( k=p->retc; k<p->argc; k++) 
		if( ! isVarConstant(mb, getArg(p,k)) ){
			status[getArg(p,k)]= LEAFNODE;
			if( vq[getArg(p,k)] )
				QEPappend(q, vq[getArg(p,k)]);
		}
		for( k=0; k<p->retc; k++){
			if(	vq[getArg(p,k)] == 0)
				vq[getArg(p,k)] = q;
			status[getArg(p,k)]= TOPNODE;
		}

	}
/* We may end up with multiple variables not yet bound to a QEP. */

	qroot= QEPnew(MAXPARENT,mb->stop);
	if( qroot)
	for(i=1; i< mb->stop-1; i++){
		p= getInstrPtr(mb,i);
	
		k=0;
		if( p->barrier){
			k++;
			q= QEPnewNode(mb,p);
		} else
		for( j=0; j< p->retc; j++)
		if( status[getArg(p,j)] == TOPNODE){
			q= vq[getArg(p,j)];
			k++;
			break;
		}
		if(q && k)
			QEPappend(qroot,q);
	}
	GDKfree(vq);
	GDKfree(status);
	return qroot;
}
예제 #14
0
int
OPTrecyclerImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p)
{
	int i, j, cnt, tp, c, actions = 0, marks = 0, delta = 0;
	Lifespan span;
	InstrPtr *old, q;
	int limit, updstmt = 0;
	char *recycled;
	short app_sc = -1, in = 0;
	ValRecord cst;

	(void) cntxt;
	(void) stk;

	limit = mb->stop;
	old = mb->stmt;

	for (i = 1; i < limit; i++) {
		p = old[i];
		if (getModuleId(p) == sqlRef &&
				(getFunctionId(p) == affectedRowsRef ||
				 getFunctionId(p) == exportOperationRef ||
				 getFunctionId(p) == appendRef ||
				 getFunctionId(p) == updateRef ||
				 getFunctionId(p) == deleteRef))
			updstmt = 1;
	}

	span = setLifespan(mb);
	if (span == NULL)
		return 0;

	/* watch out, newly created instructions may introduce new variables */
	recycled = GDKzalloc(sizeof(char) * mb->vtop * 2);
	if (recycled == NULL)
		return 0;
	if (newMalBlkStmt(mb, mb->ssize) < 0) {
		GDKfree(recycled);
		return 0;
	}
	pushInstruction(mb, old[0]);
	mb->recid = recycleSeq++;

	/* create a handle for recycler */
	(void) newFcnCall(mb, "recycle", "prelude");
	in = 1;
	for (i = 1; i < limit; i++) {
		p = old[i];
		if (hasSideEffects(p, TRUE) || isUpdateInstruction(p) || isUnsafeFunction(p)) {
			if (getModuleId(p) == recycleRef) { /*don't inline recycle instr. */
				freeInstruction(p);
				continue;
			}
			pushInstruction(mb, p);
			/*  update instructions are not recycled but monitored*/
			if (isUpdateInstruction(p)) {
				if (getModuleId(p) == batRef &&
					(getArgType(mb, p, 1) == TYPE_bat
					 || isaBatType(getArgType(mb, p, 1)))) {
					recycled[getArg(p, 1)] = 0;
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, getArg(p, 1));
					actions++;
				}
				if (getModuleId(p) == sqlRef) {
					if (getFunctionId(p) == appendRef) {
						if (app_sc >= 0)
							continue;
						else
							app_sc = getArg(p, 2);
					}
					VALset(&cst, TYPE_int, &delta);
					c = defConstant(mb, TYPE_int, &cst);
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, c);
					pushArgument(mb, q, getArg(p, 2));
					pushArgument(mb, q, getArg(p, 3));
					if (getFunctionId(p) == updateRef)
						pushArgument(mb, q, getArg(p, 4));
					actions++;
				}
			}
			/* take care of SQL catalog update instructions */
			if (getModuleId(p) == sqlRef && getFunctionId(p) == catalogRef) {
				tp = *(int *) getVarValue(mb, getArg(p, 1));
				if (tp == 22 || tp == 25) {
					delta = 2;
					VALset(&cst, TYPE_int, &delta);
					c = defConstant(mb, TYPE_int, &cst);
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, c);
					pushArgument(mb, q, getArg(p, 2));
					if (tp == 25)
						pushArgument(mb, q, getArg(p, 3));
					actions++;
				}
			}
			continue;
		}
		if (p->token == ENDsymbol || p->barrier == RETURNsymbol) {
			if (in) {
				/*
				if (updstmt && app_sc >= 0) {
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, app_sc);
					pushArgument(mb, q, app_tbl);
				}
				 */
				(void) newFcnCall(mb, "recycle", "epilogue");
				in = 0;
			}
			pushInstruction(mb, p);
			continue;
		}

		if (p->barrier && p->token != CMDcall) {
			/* never save a barrier unless it is a command and side-effect free */
			pushInstruction(mb, p);
			continue;
		}

		/* don't change instructions in update statements */
		if (updstmt) {
			pushInstruction(mb, p);
			continue;
		}

		/* skip simple assignments */
		if (p->token == ASSIGNsymbol) {
			pushInstruction(mb, p);
			continue;
		}

		if (getModuleId(p) == octopusRef &&
			(getFunctionId(p) == bindRef || getFunctionId(p) == bindidxRef)) {
			recycled[getArg(p, 0)] = 1;
			p->recycle = recycleMaxInterest;
			marks++;
		}
		/* During base table recycling skip marking instructions other than octopus.bind */
		if (baseTableMode) {
			pushInstruction(mb, p);
			continue;
		}

		/* general rule: all arguments are constants or recycled,
		   ignore C pointer arguments from mvc */
		cnt = 0;
		for (j = p->retc; j < p->argc; j++)
			if (recycled[getArg(p, j)] || isVarConstant(mb, getArg(p, j))
					|| ignoreVar(mb, getArg(p, j)))
				cnt++;
		if (cnt == p->argc - p->retc) {
			OPTDEBUGrecycle {
				mnstr_printf(cntxt->fdout, "#recycle instruction\n");
				printInstruction(cntxt->fdout, mb, 0, p, LIST_MAL_ALL);
			}
			marks++;
			p->recycle = recycleMaxInterest; /* this instruction is to be monitored */
			for (j = 0; j < p->retc; j++)
				if (getLastUpdate(span, getArg(p, j)) == i)
					recycled[getArg(p, j)] = 1;
		}
		/*
		 * The expected gain is largest if we can re-use selections
		 * on the base tables in SQL. These, however, are marked as
		 * uselect() calls, which only produce the oid head.
		 * For cheap types we preselect using select() and re-map uselect() back
		 * over this temporary.
		 * For the time being for all possible selects encountered
		 * are marked for re-use.
		 */
		/* take care of semantic driven recyling */
		/* for selections check the bat argument only
		   the range is often template parameter*/
		if ((getFunctionId(p) == selectRef ||
					getFunctionId(p) == antiuselectRef ||
					getFunctionId(p) == likeselectRef ||
					getFunctionId(p) == likeRef ||
					getFunctionId(p) == thetaselectRef) &&
				recycled[getArg(p, 1)])
		{
			p->recycle = recycleMaxInterest;
			marks++;
			if (getLastUpdate(span, getArg(p, 0)) == i)
				recycled[getArg(p, 0)] = 1;
		}
		if ((getFunctionId(p) == uselectRef || getFunctionId(p) == thetauselectRef)
				&& recycled[getArg(p, 1)])
		{
			if (!ATOMvarsized(getGDKType(getArgType(mb, p, 2)))) {
				q = copyInstruction(p);
				getArg(q, 0) = newTmpVariable(mb, TYPE_any);
				if (getFunctionId(p) == uselectRef)
					setFunctionId(q, selectRef);
				else
					setFunctionId(q, thetaselectRef);
				q->recycle = recycleMaxInterest;
				marks++;
				recycled[getArg(q, 0)] = 1;
				pushInstruction(mb, q);
				getArg(p, 1) = getArg(q, 0);
				setFunctionId(p, projectRef);
				p->argc = 2;
			}
			p->recycle = recycleMaxInterest;
			marks++;
			if (getLastUpdate(span, getArg(p, 0)) == i)
				recycled[getArg(p, 0)] = 1;
		}

		if (getModuleId(p) == pcreRef) {
			if ((getFunctionId(p) == selectRef && recycled[getArg(p, 2)]) ||
				(getFunctionId(p) == uselectRef && recycled[getArg(p, 2)])) {
				p->recycle = recycleMaxInterest;
				marks++;
				if (getLastUpdate(span, getArg(p, 0)) == i)
					recycled[getArg(p, 0)] = 1;
			} else if (getFunctionId(p) == likeuselectRef && recycled[getArg(p, 1)]) {
				q = copyInstruction(p);
				getArg(q, 0) = newTmpVariable(mb, TYPE_any);
				setFunctionId(q, likeselectRef);
				q->recycle = recycleMaxInterest;
				recycled[getArg(q, 0)] = 1;
				pushInstruction(mb, q);
				getArg(p, 1) = getArg(q, 0);
				setFunctionId(p, projectRef);
				setModuleId(p, algebraRef);
				p->argc = 2;
				p->recycle = recycleMaxInterest;
				marks += 2;
				if (getLastUpdate(span, getArg(p, 0)) == i)
					recycled[getArg(p, 0)] = 1;
			}
		}

		/*
		 * The sql.bind instructions should be handled carefully
		 * The delete and update BATs should not be recycled,
		 * because they may lead to view dependencies that later interferes
		 * with the transaction commits.
		 */
		/* enable recycling of delta-bats
		if (getModuleId(p) == sqlRef &&
				(((getFunctionId(p) == bindRef || getFunctionId(p) == putName("bind_idxbat", 11)) &&
				  getVarConstant(mb, getArg(p, 5)).val.ival != 0) ||
				 getFunctionId(p) == binddbatRef)) {
			recycled[getArg(p, 0)] = 0;
			p->recycle = REC_NO_INTEREST;
		}
		*/

/*
 * The sql.bind instructions should be handled carefully
 * The delete and update BATs should not be recycled,
 * because they may lead to view dependencies that later interferes
 * with the transaction commits.
 */
/* enable recycling of delta-bats
		if (getModuleId(p)== sqlRef && 
			(((getFunctionId(p)==bindRef || getFunctionId(p) == putName("bind_idxbat",11)) && 
				getVarConstant(mb, getArg(p,5)).val.ival != 0) ||
				getFunctionId(p)== binddbatRef) ) {
				recycled[getArg(p,0)]=0;
				p->recycle = REC_NO_INTEREST; 
			}
*/

		pushInstruction(mb, p);
	}
예제 #15
0
int
OPTrecyclerImplementation(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i, j, cnt, cand, actions = 1, marks = 0;
	InstrPtr *old, q,p;
	int limit;
	char *recycled;

	(void) cntxt;
	(void) stk;
	(void) pci;

	limit = mb->stop;
	old = mb->stmt;

	/* watch out, newly created instructions may introduce new variables */
	recycled = GDKzalloc(sizeof(char) * mb->vtop * 2);
	if (recycled == NULL)
		return 0;
	if (newMalBlkStmt(mb, mb->ssize) < 0) {
		GDKfree(recycled);
		return 0;
	}
	pushInstruction(mb, old[0]);
	for (i = 1; i < limit; i++) {
		p = old[i];
		if (p->token == ENDsymbol )
			break;
		/* the first non-dataflow barrier breaks the recycler code*/
		if (blockStart(p) && !(getFunctionId(p) && getFunctionId(p) == dataflowRef) )
			break;

		if ( isUpdateInstruction(p) || hasSideEffects(p,TRUE)){
			/*  update instructions are not recycled but monitored*/
			pushInstruction(mb, p);
			if (isUpdateInstruction(p)) {
				if (getModuleId(p) == batRef && isaBatType(getArgType(mb, p, 1))) {
					q = newFcnCall(mb, "recycle", "reset");
					pushArgument(mb, q, getArg(p, 1));
					actions++;
				}
				if (getModuleId(p) == sqlRef) {
					q= copyInstruction(p);
					getModuleId(q) = recycleRef;
					actions++;
				}
			}
			continue;
		}
		// Not all instruction may be recycled. In particular, we should avoid
		// MAL function with implicit/recursive side effects. 
		// This can not always be detected easily. Likewise, we ignore cheap operations
		// Therefore, we use a safe subset to start with
		if ( ! (getModuleId(p) == sqlRef || getModuleId(p)== batRef || 
				getModuleId(p) == algebraRef || getModuleId(p)==batcalcRef ||
				getModuleId(p)== aggrRef || getModuleId(p)== groupRef ||
				getModuleId(p)== batstrRef || getModuleId(p)== batmmathRef ||
				getModuleId(p)== arrayRef || getModuleId(p)== batmtimeRef ||
				getModuleId(p)== batcalcRef || getModuleId(p)== pcreRef ||
				getModuleId(p)== mtimeRef || getModuleId(p) == calcRef  ||
				getModuleId(p)== dateRef || getModuleId(p) == timestampRef  ||
				getModuleId(p)== matRef )
			){
			pushInstruction(mb,p);
			continue;
		}

		/* general rule: all arguments should be constants or recycled*/
		cnt = 0;
		for (j = p->retc; j < p->argc; j++)
			if (recycled[getArg(p, j)] || isVarConstant(mb, getArg(p, j)) || isFunctionArgument(mb,getArg(p,j)) )
				cnt++;
		cand = 0;
		for (j =0; j< p->retc; j++)
			if (recycled[getArg(p, j)] ==0)
				cand++;
		if (cnt == p->argc - p->retc && cand == p->retc) {
			marks++;
			p->recycle = RECYCLING; /* this instruction is to be monitored */
			for (j = 0; j < p->retc; j++)
				recycled[getArg(p, j)] = 1;
		}
		pushInstruction(mb, p);
	}
	for (; i < limit; i++) 
		pushInstruction(mb, old[i]);
	GDKfree(old);
	GDKfree(recycled);
	mb->recycle = marks > 0;
	OPTDEBUGrecycle {
		mnstr_printf(cntxt->fdout, "#recycle optimizer: ");
		printFunction(cntxt->fdout,mb, 0, LIST_MAL_ALL);
	}
	return actions + marks;
}
예제 #16
0
static str
renderTerm(MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int idx, int flg)
{
	char *buf =0;
	char *nme =0;
	int nameused = 0;
	size_t len = 0, maxlen = BUFSIZ;
	ValRecord *val = 0;
	char *cv =0;
	str tpe;
	int showtype = 0, closequote=0;
	int varid = getArg(p,idx);

	buf = GDKzalloc(maxlen);
	if( buf == NULL) {
		addMalException(mb, "renderTerm:Failed to allocate");
		return NULL;
	}
	// show the name when required or is used
	if ((flg & LIST_MAL_NAME) && !isVarConstant(mb,varid) && !isVarTypedef(mb,varid)) {
		nme = getVarName(mb,varid);
		len +=snprintf(buf, maxlen, "%s", nme);
		nameused =1;
	} 
	// show the value when required or being a constant
	if( ((flg & LIST_MAL_VALUE) && stk != 0) || isVarConstant(mb,varid) ){
		if (nameused){
			strcat(buf + len,"=");
			len++;
		}

		// locate value record
		if (isVarConstant(mb,varid)){
			val = &getVarConstant(mb, varid);
			showtype= getVarType(mb,varid) != TYPE_str && getVarType(mb,varid) != TYPE_bit;
		} else if( stk)
			val = &stk->stk[varid];

		if ((cv = VALformat(val)) == NULL) {
			addMalException(mb, "renderTerm:Failed to allocate");
			GDKfree(buf);
			return NULL;
		}
		if (len + strlen(cv) >= maxlen) {
			char *nbuf= GDKrealloc(buf, maxlen =len + strlen(cv) + BUFSIZ);

			if( nbuf == 0){
				GDKfree(buf);
				GDKfree(cv);
				addMalException(mb,"renderTerm:Failed to allocate");
				return NULL;
			}
			buf = nbuf;
		}

		if( strcmp(cv,"nil") == 0){
			strcat(buf+len,cv);
			len += strlen(buf+len);
			GDKfree(cv);
			showtype = showtype || getBatType(getVarType(mb,varid)) > TYPE_str || 
				((isVarUDFtype(mb,varid) || isVarTypedef(mb,varid)) && isVarConstant(mb,varid)) || isaBatType(getVarType(mb,varid)); 
		} else{
			if ( !isaBatType(getVarType(mb,varid)) && getBatType(getVarType(mb,varid)) > TYPE_str ){
				closequote = 1;
				strcat(buf+len,"\"");
				len++;
			}
			strcat(buf+len,cv);
			len += strlen(buf+len);
			GDKfree(cv);

			if( closequote ){
				strcat(buf+len,"\"");
				len++;
			}
			showtype = showtype || closequote > TYPE_str || ((isVarUDFtype(mb,varid) || isVarTypedef(mb,varid) || (flg & (LIST_MAL_REMOTE | LIST_MAL_TYPE))) && isVarConstant(mb,varid)) ||
				(isaBatType(getVarType(mb,varid)) && idx < p->retc);

			if (stk && isaBatType(getVarType(mb,varid)) && stk->stk[varid].val.bval ){
				BAT *d= BBPquickdesc(stk->stk[varid].val.bval, true);
				if( d)
					len += snprintf(buf+len,maxlen-len,"[" BUNFMT "]", BATcount(d));
			}
		}
	}

	// show the type when required or frozen by the user
	// special care should be taken with constants, they may have been casted
	if ((flg & LIST_MAL_TYPE) || (isVarUDFtype(mb, varid) && idx < p->retc) || isVarTypedef(mb,varid) || showtype){
		strcat(buf + len,":");
		len++;
		tpe = getTypeName(getVarType(mb, varid));
		len += snprintf(buf+len,maxlen-len,"%s",tpe);
		GDKfree(tpe);
	}

	if( len >= maxlen)
		addMalException(mb,"renderTerm:Value representation too large");
	return buf;
}
예제 #17
0
/*
 * The shortcut operator for factory calls assumes that the user is
 * not interested in the results produced.
 */
str
callFactory(Client cntxt, MalBlkPtr mb, ValPtr argv[], char flag){
	Plant pl;
	InstrPtr psig = getInstrPtr(mb, 0);
	int i;
	ValPtr lhs,rhs;
	MalStkPtr stk;
	str ret;

	i= findPlant(mb);
	if( i< 0) {
		/* first call? prepare the factory */
		pl = newPlant(mb);
		if (pl == NULL)
			throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		/* remember context, which does not exist. */
		pl->client = cntxt;
		pl->caller = 0;
		pl->env = 0;
		pl->pci = 0;
		pl->inuse = 1;
		stk = pl->stk;
		/* initialize the stack */
		stk->stktop= mb->vtop;
		stk->stksize= mb->vsize;
		stk->blk= mb;
		stk->up = 0;
		stk->cmd= flag;
		/* initialize the stack */
		for(i= psig->argc; i< mb->vtop; i++)
		if( isVarConstant(mb,i) > 0 ){
			lhs = &stk->stk[i];
			rhs = &getVarConstant(mb,i);
			if (VALcopy(lhs,rhs) == NULL)
				throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		} else {
			lhs = &stk->stk[i];
			lhs->vtype = getVarGDKType(mb,i);
		}
		pl->stk= stk;
	} else  {
		pl= plants+i;
		/*
		 * When you re-enter the factory the old arguments should be
		 * released to make room for the new ones.
		 */
		for (i = psig->retc; i < psig->argc; i++) {
			lhs = &pl->stk->stk[psig->argv[i]];
			if( lhs->vtype == TYPE_bat )
				BBPrelease(lhs->val.bval);
		}
	}
	/* copy the calling arguments onto the stack of the factory */
	i = psig->retc;
	for (i = psig->retc; i < psig->argc; i++) {
		lhs = &pl->stk->stk[psig->argv[i]];
		if (VALcopy(lhs, argv[i]) == NULL)
			throw(MAL, "factory.call", SQLSTATE(HY001) MAL_MALLOC_FAIL);
		if( lhs->vtype == TYPE_bat )
			BBPretain(lhs->val.bval);
	}
	ret=  reenterMAL(cntxt, mb, pl->pc, -1, pl->stk);
	/* garbage collect the string arguments, these positions
	   will simply be overwritten the next time.
	for (i = psig->retc; i < psig->argc; i++)
		garbageElement(lhs = &pl->stk->stk[psig->argv[i]]);
	*/
	return ret;
}
예제 #18
0
/*
 * The dataflow administration is based on administration of
 * how many variables are still missing before it can be executed.
 * For each instruction we keep a list of instructions whose
 * blocking counter should be decremented upon finishing it.
 */
static str
DFLOWinitBlk(DataFlow flow, MalBlkPtr mb, int size)
{
	int pc, i, j, k, l, n, etop = 0;
	int *assign;
	InstrPtr p;

	if (flow == NULL)
		throw(MAL, "dataflow", "DFLOWinitBlk(): Called with flow == NULL");
	if (mb == NULL)
		throw(MAL, "dataflow", "DFLOWinitBlk(): Called with mb == NULL");
	PARDEBUG fprintf(stderr, "#Initialize dflow block\n");
	assign = (int *) GDKzalloc(mb->vtop * sizeof(int));
	if (assign == NULL)
		throw(MAL, "dataflow", "DFLOWinitBlk(): Failed to allocate assign");
	etop = flow->stop - flow->start;
	for (n = 0, pc = flow->start; pc < flow->stop; pc++, n++) {
		p = getInstrPtr(mb, pc);
		if (p == NULL) {
			GDKfree(assign);
			throw(MAL, "dataflow", "DFLOWinitBlk(): getInstrPtr() returned NULL");
		}

		/* initial state, ie everything can run */
		flow->status[n].flow = flow;
		flow->status[n].pc = pc;
		flow->status[n].state = DFLOWpending;
		flow->status[n].cost = -1;
		flow->status[n].flow->error = NULL;

		/* administer flow dependencies */
		for (j = p->retc; j < p->argc; j++) {
			/* list of instructions that wake n-th instruction up */
			if (!isVarConstant(mb, getArg(p, j)) && (k = assign[getArg(p, j)])) {
				assert(k < pc); /* only dependencies on earlier instructions */
				/* add edge to the target instruction for wakeup call */
				k -= flow->start;
				if (flow->nodes[k]) {
					/* add wakeup to tail of list */
					for (i = k; flow->edges[i] > 0; i = flow->edges[i])
						;
					flow->nodes[etop] = n;
					flow->edges[etop] = -1;
					flow->edges[i] = etop;
					etop++;
					(void) size;
					if( etop == size){
						flow->nodes = (int*) GDKrealloc(flow->nodes, sizeof(int) * 2 * size);
						flow->edges = (int*) GDKrealloc(flow->edges, sizeof(int) * 2 * size);
						size *=2;
					}
				} else {
					flow->nodes[k] = n;
					flow->edges[k] = -1;
				}

				flow->status[n].blocks++;
			}

			/* list of instructions to be woken up explicitly */
			if (!isVarConstant(mb, getArg(p, j))) {
				/* be careful, watch out for garbage collection interference */
				/* those should be scheduled after all its other uses */
				l = getEndOfLife(mb, getArg(p, j));
				if (l != pc && l < flow->stop && l > flow->start) {
					/* add edge to the target instruction for wakeup call */
					PARDEBUG fprintf(stderr, "#endoflife for %s is %d -> %d\n", getVarName(mb, getArg(p, j)), n + flow->start, l);
					assert(pc < l); /* only dependencies on earlier instructions */
					l -= flow->start;
					if (flow->nodes[n]) {
						/* add wakeup to tail of list */
						for (i = n; flow->edges[i] > 0; i = flow->edges[i])
							;
						flow->nodes[etop] = l;
						flow->edges[etop] = -1;
						flow->edges[i] = etop;
						etop++;
						if( etop == size){
							flow->nodes = (int*) GDKrealloc(flow->nodes, sizeof(int) * 2 * size);
							flow->edges = (int*) GDKrealloc(flow->edges, sizeof(int) * 2 * size);
							size *=2;
						}
					} else {
						flow->nodes[n] = l;
						flow->edges[n] = -1;
					}
					flow->status[l].blocks++;
				}
			}
		}

		for (j = 0; j < p->retc; j++)
			assign[getArg(p, j)] = pc;  /* ensure recognition of dependency on first instruction and constant */
	}
	GDKfree(assign);
	PARDEBUG {
		for (n = 0; n < flow->stop - flow->start; n++) {
			mnstr_printf(GDKstdout, "#[%d] %d: ", flow->start + n, n);
			printInstruction(GDKstdout, mb, 0, getInstrPtr(mb, n + flow->start), LIST_MAL_STMT | LIST_MAPI);
			mnstr_printf(GDKstdout, "#[%d]Dependents block count %d wakeup", flow->start + n, flow->status[n].blocks);
			for (j = n; flow->edges[j]; j = flow->edges[j]) {
				mnstr_printf(GDKstdout, "%d ", flow->start + flow->nodes[j]);
				if (flow->edges[j] == -1)
					break;
			}
			mnstr_printf(GDKstdout, "\n");
		}
	}
#ifdef USE_MAL_ADMISSION
	memorypool = memoryclaims = 0;
#endif
	return MAL_SUCCEED;
}