Example #1
0
/*
 * The routine VALconvert transforms a value for interpretation in a
 * certain type. It uses some standard cast conventions to do this.
 * The result, a pointer to a value, is returned. If there are illegal
 * values, or type combinations involved, it gives up with an
 * ILLEGALVALUE.
 */
ptr
VALconvert(int typ, ValPtr t)
{
	int src_tpe = t->vtype;
	ValRecord dst;

	dst.vtype = typ;
	/* use base types for user types */
	if (src_tpe > TYPE_str)
		src_tpe = ATOMstorage(src_tpe);
	if (dst.vtype > TYPE_str)
		dst.vtype = ATOMstorage(dst.vtype);
	else if (dst.vtype == TYPE_void)
		dst.vtype = TYPE_oid;

	/* first convert into a new location */
	if (VARconvert(&dst, t, 0) == GDK_FAIL)
		return ILLEGALVALUE;

	/* then maybe free the old */
	if (src_tpe != dst.vtype &&
	    t->vtype != typ &&
	    dst.vtype != TYPE_void &&
	    (src_tpe >= TYPE_str || dst.vtype >= TYPE_str))
		VALclear(t);
	/* and finally copy the result */
	*t = dst;
	/* make sure we return the correct type (not the storage type) */
	t->vtype = typ;
	return VALget(t);
}
Example #2
0
void
clearStack(MalStkPtr s)
{
	ValPtr v;
	int i;

	if (!s) return;
	
	i = s->stktop;

	for (v = s->stk; i >= 0; i--, v++)
		if (ATOMextern(v->vtype) && v->val.pval) {
			GDKfree(v->val.pval);
			v->vtype = 0;
			v->val.pval = NULL;
		} else if (BATatoms[v->vtype].atomUnfix) {
			BATatoms[v->vtype].atomUnfix(VALget(v));
			v->vtype = 0;
			v->val.pval = NULL;
		}
	s->stkbot = 0;
}
Example #3
0
/* Convert (cast) the value in T to the type TYP, do this in place.
 * Return a pointer to the converted value, or NULL if the conversion
 * didn't succeed.  If the conversion didn't succeed, the original
 * value is not modified.  Also see VARconvert. */
ptr
VALconvert(int typ, ValPtr t)
{
	int src_tpe = t->vtype;
	ValRecord dst;

	dst.vtype = typ;

	/* first convert into a new location */
	if (VARconvert(&dst, t, 0) != GDK_SUCCEED)
		return NULL;

	/* then maybe free the old */
	if (src_tpe != dst.vtype &&
	    t->vtype != typ &&
	    dst.vtype != TYPE_void &&
	    (src_tpe >= TYPE_str || dst.vtype >= TYPE_str))
		VALclear(t);
	/* and finally copy the result */
	*t = dst;
	/* make sure we return the correct type (not the storage type) */
	t->vtype = typ;
	return VALget(t);
}
Example #4
0
/*
 * The generic solution to the multiplex operators is to translate
 * them to a MAL loop.
 * The call optimizer.multiplex(MOD,FCN,A1,...An) introduces the following code
 * structure:
 *
 * @verbatim
 *  A1rev:=bat.reverse(A1);
 * 	resB:= bat.new(A1);
 * barrier (h,t):= iterator.new(A1);
 * 	$1:= algebra.fetch(A1,h);
 * 	$2:= A2;	# in case of constant?
 * 	...
 * 	cr:= MOD.FCN($1,...,$n);
 *  y:=algebra.fetch(A1rev,h);
 * 	bat.insert(resB,y,cr);
 * 	redo (h,t):= iterator.next(A1);
 * end h;
 * @end verbatim
 *
 * The algorithm consists of two phases: phase one deals with
 * collecting the relevant information, phase two is the actual
 * code construction.
 */
static str
OPTexpandMultiplex(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i = 2, resB, iter = 0, cr;
	int hvar, tvar;
	int x, y;
	str mod, fcn;
	int *alias;
	InstrPtr q;
	int ht, tt;

	(void) cntxt;
	(void) stk;

	ht = getHeadType(getArgType(mb, pci, 0));
	if (ht != TYPE_oid)
		throw(MAL, "optimizer.multiplex", "Target head type is missing");
	tt = getTailType(getArgType(mb, pci, 0));
	if (tt== TYPE_any)
		throw(MAL, "optimizer.multiplex", "Target tail type is missing");
	if (isAnyExpression(getArgType(mb, pci, 0)))
		throw(MAL, "optimizer.multiplex", "Target type is missing");

	mod = VALget(&getVar(mb, getArg(pci, 1))->value);
	mod = putName(mod,strlen(mod));
	fcn = VALget(&getVar(mb, getArg(pci, 2))->value);
	fcn = putName(fcn,strlen(fcn));

	/* search the iterator bat */
	for (i = 3; i < pci->argc; i++)
		if (isaBatType(getArgType(mb, pci, i))) {
			iter = getArg(pci, i);
			if (getHeadType(getVarType(mb,iter)) != TYPE_oid)
				throw(MAL, "optimizer.multiplex", "Iterator BAT is not OID-headed");
			break;
		}
	if( i == pci->argc)
		throw(MAL, "optimizer.multiplex", "Iterator BAT type is missing");

	OPTDEBUGmultiplex {
		mnstr_printf(cntxt->fdout,"#calling the optimize multiplex script routine\n");
		printFunction(cntxt->fdout,mb, 0, LIST_MAL_ALL );
		mnstr_printf(cntxt->fdout,"#multiplex against operator %d %s\n",iter, getTypeName(getVarType(mb,iter)));
		printInstruction(cntxt->fdout,mb, 0, pci,LIST_MAL_ALL);
	}
	/*
	 * Beware, the operator constant (arg=1) is passed along as well,
	 * because in the end we issue a recursive function call that should
	 * find the actual arguments at the proper place of the callee.
	 */

	alias= (int*) GDKmalloc(sizeof(int) * pci->maxarg);
	if (alias == NULL)
		return NULL;

	/* x := bat.reverse(A1); */
	x = newTmpVariable(mb, newBatType(getTailType(getVarType(mb,iter)),
									  getHeadType(getVarType(mb,iter))));
	q = newFcnCall(mb, batRef, reverseRef);
	getArg(q, 0) = x;
	q = pushArgument(mb, q, iter);

	/* resB := new(refBat) */
	q = newFcnCall(mb, batRef, newRef);
	resB = getArg(q, 0);

	setVarType(mb, getArg(q, 0), newBatType(ht, tt));
	q = pushType(mb, q, ht);
	q = pushType(mb, q, tt);
	/* barrier (h,r) := iterator.new(refBat); */
	q = newFcnCall(mb, iteratorRef, newRef);
	q->barrier = BARRIERsymbol;
	hvar = newTmpVariable(mb, TYPE_any);
	getArg(q,0) = hvar;
	tvar = newTmpVariable(mb, TYPE_any);
	q= pushReturn(mb, q, tvar);
	(void) pushArgument(mb,q,iter);

	/* $1:= algebra.fetch(Ai,h) or constant */
	alias[i] = tvar;

	for (i++; i < pci->argc; i++)
		if (isaBatType(getArgType(mb, pci, i))) {
			q = newFcnCall(mb, algebraRef, "fetch");
			alias[i] = newTmpVariable(mb, getTailType(getArgType(mb, pci, i)));
			getArg(q, 0) = alias[i];
			q= pushArgument(mb, q, getArg(pci, i));
			(void) pushArgument(mb, q, hvar);
		}

	/* cr:= mod.CMD($1,...,$n); */
	q = newFcnCall(mb, mod, fcn);
	cr = getArg(q, 0) = newTmpVariable(mb, TYPE_any);

	for (i = 3; i < pci->argc; i++)
		if (isaBatType(getArgType(mb, pci, i))) {
			q= pushArgument(mb, q, alias[i]);
		} else {
			q = pushArgument(mb, q, getArg(pci, i));
		}

	/* y := algebra.fetch(x,h); */
	y = newTmpVariable(mb, getHeadType(getVarType(mb,iter)));
	q = newFcnCall(mb, algebraRef, "fetch");
	getArg(q, 0) = y;
	q = pushArgument(mb, q, x);
	q = pushArgument(mb, q, hvar);

	/* insert(resB,h,cr);
	   not append(resB, cr); the head type (oid) may dynamically change */

	q = newFcnCall(mb, batRef, insertRef);
	q= pushArgument(mb, q, resB);
	q= pushArgument(mb, q, y);
	(void) pushArgument(mb, q, cr);

/* redo (h,r):= iterator.next(refBat); */
	q = newFcnCall(mb, iteratorRef, nextRef);
	q->barrier = REDOsymbol;
	getArg(q,0) = hvar;
	q= pushReturn(mb, q, tvar);
	(void) pushArgument(mb,q,iter);

	q = newAssignment(mb);
	q->barrier = EXITsymbol;
	getArg(q,0) = hvar;
	(void) pushReturn(mb, q, tvar);

	q = newAssignment(mb);
	getArg(q, 0) = getArg(pci, 0);
	(void) pushArgument(mb, q, resB);
	GDKfree(alias);
	return MAL_SUCCEED;
}
Example #5
0
/*
 * The generic solution to the multiplex operators is to translate
 * them to a MAL loop.
 * The call optimizer.multiplex(MOD,FCN,A1,...An) introduces the following code
 * structure:
 *
 * 	resB:= bat.new(A1);
 * barrier (h,t1):= iterator.new(A1);
 * 	t2:= algebra.fetch(A2,h)
 * 	...
 * 	cr:= MOD.FCN(t1,...,tn);
 * 	bat.append(resB,cr);
 * 	redo (h,t):= iterator.next(A1);
 * end h;
 *
 * The algorithm consists of two phases: phase one deals with
 * collecting the relevant information, phase two is the actual
 * code construction.
 */
static str
OPTexpandMultiplex(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci)
{
	int i = 2, iter = 0;
	int hvar, tvar;
	str mod, fcn;
	int *alias, *resB;
	InstrPtr q;
	int tt;
	int bat = (getModuleId(pci) == batmalRef) ;

	//if ( optimizerIsApplied(mb,"multiplex"))
		//return 0;
	(void) cntxt;
	(void) stk;
	for (i = 0; i < pci->retc; i++) {
		tt = getBatType(getArgType(mb, pci, i));
		if (tt== TYPE_any)
			throw(MAL, "optimizer.multiplex", SQLSTATE(HY002) "Target tail type is missing");
		if (isAnyExpression(getArgType(mb, pci, i)))
			throw(MAL, "optimizer.multiplex", SQLSTATE(HY002) "Target type is missing");
	}

	mod = VALget(&getVar(mb, getArg(pci, pci->retc))->value);
	mod = putName(mod);
	fcn = VALget(&getVar(mb, getArg(pci, pci->retc+1))->value);
	fcn = putName(fcn);
	if(mod == NULL || fcn == NULL)
		throw(MAL, "optimizer.multiplex", SQLSTATE(HY001) MAL_MALLOC_FAIL);
#ifndef NDEBUG
	fprintf(stderr,"#WARNING To speedup %s.%s a bulk operator implementation is needed\n#", mod,fcn);
	fprintInstruction(stderr, mb, stk, pci, LIST_MAL_DEBUG);
#endif

	/* search the iterator bat */
	for (i = pci->retc+2; i < pci->argc; i++)
		if (isaBatType(getArgType(mb, pci, i))) {
			iter = getArg(pci, i);
			break;
		}
	if( i == pci->argc)
		throw(MAL, "optimizer.multiplex", SQLSTATE(HY002) "Iterator BAT type is missing");

#ifdef DEBUG_OPT_MULTIPLEX
	{	char *tpenme;
		fprintf(stderr,"#calling the optimize multiplex script routine\n");
		fprintFunction(stderr,mb, 0, LIST_MAL_ALL );
		tpenme = getTypeName(getVarType(mb,iter));
		fprintf(stderr,"#multiplex against operator %d %s\n",iter, tpenme);
		GDKfree(tpenme);
		fprintInstruction(stderr,mb, 0, pci,LIST_MAL_ALL);
	}
#endif
	/*
	 * Beware, the operator constant (arg=1) is passed along as well,
	 * because in the end we issue a recursive function call that should
	 * find the actual arguments at the proper place of the callee.
	 */

	alias= (int*) GDKmalloc(sizeof(int) * pci->maxarg);
	resB = (int*) GDKmalloc(sizeof(int) * pci->retc);
	if (alias == NULL || resB == NULL)  {
		GDKfree(alias);
		GDKfree(resB);
		return NULL;
	}

	/* resB := new(refBat) */
	for (i = 0; i < pci->retc; i++) {
		q = newFcnCall(mb, batRef, newRef);
		resB[i] = getArg(q, 0);

		tt = getBatType(getArgType(mb, pci, i));

		setVarType(mb, getArg(q, 0), newBatType(tt));
		q = pushType(mb, q, tt);
	}

	/* barrier (h,r) := iterator.new(refBat); */
	q = newFcnCall(mb, iteratorRef, newRef);
	q->barrier = BARRIERsymbol;
	hvar = newTmpVariable(mb, TYPE_any);
	getArg(q,0) = hvar;
	tvar = newTmpVariable(mb, TYPE_any);
	q= pushReturn(mb, q, tvar);
	(void) pushArgument(mb,q,iter);

	/* $1:= algebra.fetch(Ai,h) or constant */
	for (i = pci->retc+2; i < pci->argc; i++) {
		if (getArg(pci, i) != iter && isaBatType(getArgType(mb, pci, i))) {
			q = newFcnCall(mb, algebraRef, "fetch");
			alias[i] = newTmpVariable(mb, getBatType(getArgType(mb, pci, i)));
			getArg(q, 0) = alias[i];
			q= pushArgument(mb, q, getArg(pci, i));
			(void) pushArgument(mb, q, hvar);
		}
	}

	/* cr:= mod.CMD($1,...,$n); */
	q = newFcnCall(mb, mod, fcn);
	for (i = 0; i < pci->retc; i++) {
		int nvar = 0;
		if (bat) {
			tt = getBatType(getArgType(mb, pci, i));
			nvar = newTmpVariable(mb, newBatType(tt));
		} else {
			nvar = newTmpVariable(mb, TYPE_any);
		}
		if (i)
			q = pushReturn(mb, q, nvar);
		else
			getArg(q, 0) = nvar;
	}

	for (i = pci->retc+2; i < pci->argc; i++) {
		if (getArg(pci, i) == iter) {
			q = pushArgument(mb, q, tvar);
		} else if (isaBatType(getArgType(mb, pci, i))) {
			q = pushArgument(mb, q, alias[i]);
		} else {
			q = pushArgument(mb, q, getArg(pci, i));
		}
	}

	for (i = 0; i < pci->retc; i++) {
		InstrPtr a = newFcnCall(mb, batRef, appendRef);
		a = pushArgument(mb, a, resB[i]);
		(void) pushArgument(mb, a, getArg(q,i));
	}

/* redo (h,r):= iterator.next(refBat); */
	q = newFcnCall(mb, iteratorRef, nextRef);
	q->barrier = REDOsymbol;
	getArg(q,0) = hvar;
	q= pushReturn(mb, q, tvar);
	(void) pushArgument(mb,q,iter);

	q = newAssignment(mb);
	q->barrier = EXITsymbol;
	getArg(q,0) = hvar;
	(void) pushReturn(mb, q, tvar);

	for (i = 0; i < pci->retc; i++) {
		q = newAssignment(mb);
		getArg(q, 0) = getArg(pci, i);
		(void) pushArgument(mb, q, resB[i]);
	}
	GDKfree(alias);
	GDKfree(resB);
	return MAL_SUCCEED;
}