| 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 | /* |
| 10 | * @f run_adder |
| 11 | * @a The ROX Team |
| 12 | * @+ Dynamic Statement Generation Example |
| 13 | * |
| 14 | * we have a function: adder.generate(target, batch) |
| 15 | * that is recognized by this scheduler. |
| 16 | * @example |
| 17 | * x := 0; |
| 18 | * x := adder.generate(10,2) |
| 19 | * io.print(x); |
| 20 | * @end example |
| 21 | * should produce on first iteration |
| 22 | * @example |
| 23 | * x := 0; |
| 24 | * x := calc.+(x,1); |
| 25 | * x := calc.+(x,1); |
| 26 | * x := adder.generate(8,2) |
| 27 | * io.print(x); |
| 28 | * @end example |
| 29 | * next when generate() is found: |
| 30 | * @example |
| 31 | * x := calc.+(x,1); |
| 32 | * x := calc.+(x,1); |
| 33 | * x := adder.generate(6,2) |
| 34 | * io.print(x); |
| 35 | * @end example |
| 36 | * etc, until x = base |
| 37 | * |
| 38 | */ |
| 39 | /* |
| 40 | * @+ Adder implementation |
| 41 | * The code below is a mixture of generic routines and |
| 42 | * sample implementations to run the tests. |
| 43 | */ |
| 44 | #include "monetdb_config.h" |
| 45 | #include "mal_builder.h" |
| 46 | #include "opt_prelude.h" |
| 47 | #include "run_adder.h" |
| 48 | |
| 49 | /* |
| 50 | * @- |
| 51 | * THe choice operator first searches the next one to identify |
| 52 | * the fragment to be optimized and to gain access to the variables |
| 53 | * without the need to declare them upfront. |
| 54 | */ |
| 55 | /* helper routine that at runtime propagates values to the stack */ |
| 56 | static void adder_addval(MalBlkPtr mb, MalStkPtr stk, int i) { |
| 57 | ValPtr rhs, lhs = &stk->stk[i]; |
| 58 | if (isVarConstant(mb,i) > 0 ){ |
| 59 | rhs = &getVarConstant(mb,i); |
| 60 | VALcopy(lhs,rhs); |
| 61 | } else { |
| 62 | lhs->vtype = getVarGDKType(mb,i); |
| 63 | lhs->val.pval = 0; |
| 64 | lhs->len = 0; |
| 65 | } |
| 66 | } |
| 67 | |
| 68 | str |
| 69 | RUNadder(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p) |
| 70 | { |
| 71 | int total; |
| 72 | int batch; |
| 73 | int size; |
| 74 | int i,pc; |
| 75 | InstrPtr q, *old; |
| 76 | int oldtop; |
| 77 | |
| 78 | (void) cntxt; |
| 79 | pc = getPC(mb,p); |
| 80 | total = *getArgReference_int(stk,p,1); |
| 81 | batch = *getArgReference_int(stk,p,2); |
| 82 | if (total == 0) return MAL_SUCCEED; |
| 83 | |
| 84 | old = mb->stmt; |
| 85 | oldtop= mb->stop; |
| 86 | size = ((mb->stop+batch) < mb->ssize)? mb->ssize:(mb->stop+batch); |
| 87 | mb->stmt = (InstrPtr *) GDKzalloc(size * sizeof(InstrPtr)); |
| 88 | if (mb->stmt == NULL) { |
| 89 | mb->stmt = old; |
| 90 | throw(MAL, "adder.generate" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 91 | } |
| 92 | mb->ssize = size; |
| 93 | memcpy( mb->stmt, old, sizeof(InstrPtr)*(pc+1)); |
| 94 | mb->stop = pc+1; |
| 95 | |
| 96 | if (batch > total) total = batch; |
| 97 | for (i=0; i<batch; i++) { |
| 98 | /* tmp := calc.+(x,1) */ |
| 99 | q = newStmt(mb, calcRef, plusRef); |
| 100 | getArg(q,0) = getArg(p,0); |
| 101 | q = pushArgument(mb, q, getArg(p, 0)); |
| 102 | q = pushInt(mb, q, 1); |
| 103 | adder_addval(mb, stk, getArg(q,2)); |
| 104 | } |
| 105 | total -= batch; |
| 106 | *getArgReference_int(stk,p,1) = total; |
| 107 | getVar(mb,getArg(p,1))->value.val.ival = total; /* also set in symbol table */ |
| 108 | if (total > 0) { |
| 109 | if ((q = copyInstruction(p)) == NULL) { |
| 110 | for(i=0; i<mb->stop; i++) |
| 111 | if( mb->stmt[i]) |
| 112 | freeInstruction(mb->stmt[i]); |
| 113 | GDKfree(mb->stmt); |
| 114 | mb->stmt = old; |
| 115 | throw(MAL, "adder.generate" , SQLSTATE(HY001) MAL_MALLOC_FAIL); |
| 116 | } |
| 117 | pushInstruction(mb, q); |
| 118 | } |
| 119 | memcpy(mb->stmt+mb->stop, old+pc+1, sizeof(InstrPtr) * (oldtop-pc)-1); |
| 120 | mb->stop += (oldtop-pc)-1; |
| 121 | |
| 122 | /* check new statments for sanity */ |
| 123 | chkTypes(cntxt->usermodule, mb, FALSE); |
| 124 | chkFlow(mb); |
| 125 | chkDeclarations(mb); |
| 126 | |
| 127 | GDKfree(old); |
| 128 | return MAL_SUCCEED; |
| 129 | } |
| 130 | |