From: jzhou Date: Thu, 12 Nov 2009 00:48:18 +0000 (+0000) Subject: bug fix in scheduling and multicore support for tags X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2302c9f524785546125e51b4768dc207eb13ea7a;p=IRC.git bug fix in scheduling and multicore support for tags --- diff --git a/Robust/src/Analysis/Scheduling/MCImplSynthesis.java b/Robust/src/Analysis/Scheduling/MCImplSynthesis.java index 65f0ea6c..544f29cd 100644 --- a/Robust/src/Analysis/Scheduling/MCImplSynthesis.java +++ b/Robust/src/Analysis/Scheduling/MCImplSynthesis.java @@ -1085,7 +1085,7 @@ public class MCImplSynthesis { generateScheduling(Vector scheduleGraph, Hashtable td2maincd) { Hashtable> td2cores = - new Hashtable>(); // multiparam tasks reside on which cores + new Hashtable>(); // tasks reside on which cores Vector scheduling = new Vector(scheduleGraph.size()); // for each ScheduleNode create a schedule node representing a core Hashtable sn2coreNum = @@ -1093,7 +1093,10 @@ public class MCImplSynthesis { Hashtable td2maincore = new Hashtable(); Hashtable> td2allycores = - new Hashtable>(); + new Hashtable>(); // multiparam tasks -- + // ally cores which might have parameters + // for the task + int j = 0; for(j = 0; j < scheduleGraph.size(); j++) { sn2coreNum.put(scheduleGraph.elementAt(j), j); @@ -1121,6 +1124,7 @@ public class MCImplSynthesis { if(td.numParameters() > 1) { // td is a multi-param task, check if this core contains the // main cd of it + ClassDescriptor cd1 = td2maincd.get(td); if(td2maincd.get(td).equals(cd)) { contain = true; td2maincore.put(td, tmpSchedule.getCoreNum()); @@ -1183,15 +1187,23 @@ public class MCImplSynthesis { while(it.hasNext()) { TaskDescriptor td = ((FEdge)it.next()).getTask(); if(td.numParameters() > 1) { - tmpSchedule.addFState4TD(td, fs); // TODO + tmpSchedule.addFState4TD(td, fs); // TODO + // add this core as a allycore of td + if(!td2allycores.containsKey(td)) { + td2allycores.put(td, new Vector()); + } + Vector allycores = td2allycores.get(td); + if(!allycores.contains(tmpSchedule)) { + allycores.addElement(tmpSchedule); + } } else { canTriggerSTask = true; } } - for(int k = 0; k < se.getNewRate(); k++) { - if(canTriggerSTask) { - // Only transfer the obj when it can trigger some single-parm task - // TODO: ensure that multi-param tasks have these objects + if(canTriggerSTask) { + // Only transfer the obj when it can trigger some single-parm task + // TODO: ensure that multi-param tasks have these objects + for(int k = 0; k < se.getNewRate(); k++) { tmpSchedule.addTargetCore(fs, targetcore); } } @@ -1213,6 +1225,14 @@ public class MCImplSynthesis { TaskDescriptor td = ((FEdge)it.next()).getTask(); if(td.numParameters() > 1) { tmpSchedule.addFState4TD(td, fs); + // add this core as a allycore of td + if(!td2allycores.containsKey(td)) { + td2allycores.put(td, new Vector()); + } + Vector allycores = td2allycores.get(td); + if(!allycores.contains(tmpSchedule)) { + allycores.addElement(tmpSchedule); + } } } break; @@ -1235,13 +1255,21 @@ public class MCImplSynthesis { while(it.hasNext()) { TaskDescriptor td = ((FEdge)it.next()).getTask(); if(td.numParameters() > 1) { - tmpSchedule.addFState4TD(td, fs); // TODO + tmpSchedule.addFState4TD(td, fs); // TODO + // add this core as a allycore of td + if(!td2allycores.containsKey(td)) { + td2allycores.put(td, new Vector()); + } + Vector allycores = td2allycores.get(td); + if(!allycores.contains(tmpSchedule)) { + allycores.addElement(tmpSchedule); + } } else { canTriggerSTask = true; } } - for(int k = 0; k < se.getNewRate(); k++) { - if(canTriggerSTask) { + if(canTriggerSTask) { + for(int k = 0; k < se.getNewRate(); k++) { tmpSchedule.addTargetCore(se.getFstate(), j); } } @@ -1253,6 +1281,26 @@ public class MCImplSynthesis { tmpSchedule.addTargetCore(se.getFstate(), j, se.getTargetFState()); + // check if missed some FlagState associated with some + // multi-parameter task, which has been cloned when + // splitting a ClassNode + FlagState fs = se.getSourceFState(); + FlagState tfs = se.getTargetFState(); + Iterator it = tfs.edges(); + while(it.hasNext()) { + TaskDescriptor td = ((FEdge)it.next()).getTask(); + if(td.numParameters() > 1) { + tmpSchedule.addFState4TD(td, fs); + // add this core as a allycore of td + if(!td2allycores.containsKey(td)) { + td2allycores.put(td, new Vector()); + } + Vector allycores = td2allycores.get(td); + if(!allycores.contains(tmpSchedule)) { + allycores.addElement(tmpSchedule); + } + } + } break; } } @@ -1267,7 +1315,6 @@ public class MCImplSynthesis { } Iterator it_mptds = td2maincd.keySet().iterator(); - // set up all the associate ally cores while(it_mptds.hasNext()) { TaskDescriptor td = it_mptds.next(); Vector fes = (Vector) this.taskAnalysis.getFEdgesFromTD(td); @@ -1290,6 +1337,7 @@ public class MCImplSynthesis { TaskDescriptor tmptd = ((FEdge)it_edges.next()).getTask(); if(!tmptds.contains(tmptd)) { tmptds.add(tmptd); + // only multiparam task will be processed here!!! TODO Vector tmpcores = td2cores.get(tmptd); for(int m = 0; m < tmpcores.size(); ++m) { Schedule target = tmpcores.elementAt(m); diff --git a/Robust/src/Analysis/Scheduling/ScheduleAnalysis.java b/Robust/src/Analysis/Scheduling/ScheduleAnalysis.java index 413a54fb..181296f3 100644 --- a/Robust/src/Analysis/Scheduling/ScheduleAnalysis.java +++ b/Robust/src/Analysis/Scheduling/ScheduleAnalysis.java @@ -71,6 +71,14 @@ public class ScheduleAnalysis { } public Hashtable getTd2maincd() { + // TODO, for test + /*Iterator key = td2maincd.keySet().iterator(); + while(key.hasNext()) { + TaskDescriptor td = key.next(); + System.err.println(td.getSymbol() + ", maincd: " + + this.td2maincd.get(td).getSymbol()); + }*/ + return td2maincd; } @@ -164,9 +172,14 @@ public class ScheduleAnalysis { while(it_edges.hasNext()) { FEdge edge = (FEdge)it_edges.next(); TaskInfo taskinfo = taskinfos.get(edge.getTask().getSymbol()); - tint = taskinfo.m_exetime[edge.getTaskExitIndex()]; + double idouble = 0.0; + if(edge.getTaskExitIndex() >= taskinfo.m_exetime.length) { + tint = 0; + } else { + tint = taskinfo.m_exetime[edge.getTaskExitIndex()]; + idouble = taskinfo.m_probability[edge.getTaskExitIndex()]; + } edge.setExeTime(tint); - double idouble = taskinfo.m_probability[edge.getTaskExitIndex()]; edge.setProbability(idouble); if(taskinfo.m_byObj != -1) { ((FlagState)edge.getSource()).setByObj(taskinfo.m_byObj); @@ -395,11 +408,17 @@ public class ScheduleAnalysis { (cdname.equals("Fractal")) || (cdname.equals("KMeans")) || (cdname.equals("ZTransform")) || - (cdname.equals("TestRunner")) || - (cdname.equals("LinkList"))) { + (cdname.equals("TestRunner")) || + (cdname.equals("LinkList"))) { newRate = this.coreNum; } else if(cdname.equals("SentenceParser")) { newRate = 4; + } else if(cdname.equals("BlurPiece")){ + newRate = 4; + } else if(cdname.equals("ImageX")){ + newRate = 2 * 2; + } else if(cdname.equals("ImageY")){ + newRate = 1 * 4; } //do { // tint = r.nextInt()%100; @@ -509,12 +528,10 @@ public class ScheduleAnalysis { } // Create 'new' edges between the ScheduleNodes. - Vector singleCDs = new Vector(); for(i = 0; i < classNodes.size(); i++) { ClassNode cNode = classNodes.elementAt(i); ClassDescriptor cd = cNode.getClassDescriptor(); Vector rootnodes = taskanalysis.getRootNodes(cd); - boolean isSingle = false; if(rootnodes != null) { for(int h = 0; h < rootnodes.size(); h++) { FlagState root=(FlagState)rootnodes.elementAt(h); @@ -535,9 +552,6 @@ public class ScheduleAnalysis { // 'new' edge continue; } - if(noi.getNewRate() == 1) { - isSingle = true; - } if(noi.getRoot() == null) { // set root FlagState noi.setRoot(root); @@ -567,9 +581,6 @@ public class ScheduleAnalysis { } allocatingTasks = null; } - if(isSingle) { - singleCDs.add(cd); - } } rootnodes = null; } @@ -578,15 +589,13 @@ public class ScheduleAnalysis { for(i = 0; i < multiparamtds.size(); i++) { TaskDescriptor td = multiparamtds.elementAt(i); - for(int j = 0; j < td.numParameters(); j++) { - ClassDescriptor cd = td.getParamType(j).getClassDesc(); - if(singleCDs.contains(cd)) { - // set the first parameter which has single creation rate as main cd - // TODO: may have bug when cd has multiple new flag states - this.td2maincd.put(td, cd); - break; - } - } + ClassDescriptor cd = td.getParamType(0).getClassDesc(); + // set the first parameter as main cd + // NOTE: programmer should write in such a style that + // for all multi-param tasks, the main class should be + // the first parameter + // TODO: may have bug when cd has multiple new flag states + this.td2maincd.put(td, cd); } return startupNode; @@ -649,16 +658,39 @@ public class ScheduleAnalysis { this.state.outputdir + "scheduling_ori.dot", this.scheduleNodes); } } + + private void handleDescenSEs(Vector ses) { + ScheduleEdge tempse = ses.elementAt(0); + long temptime = tempse.getListExeTime(); + // find out the ScheduleEdge with least exeTime + for(int k = 1; k < ses.size(); k++) { + long ttemp = ses.elementAt(k).getListExeTime(); + if(ttemp < temptime) { + tempse = ses.elementAt(k); + temptime = ttemp; + } // if(ttemp < temptime) + } // for(int k = 1; k < ses.size(); k++) + // handle the tempse + handleScheduleEdge(tempse, true); + ses.removeElement(tempse); + // handle other ScheduleEdges + for(int k = 0; k < ses.size(); k++) { + handleScheduleEdge(ses.elementAt(k), false); + } // for(int k = 0; k < ses.size(); k++) + } private void CFSTGTransform() { // First iteration int i = 0; - //Access the ScheduleEdges in reverse topology order + + // table of all schedule edges associated to one fedge Hashtable> fe2ses = new Hashtable>(); + // table of all fedges associated to one schedule node Hashtable> sn2fes = new Hashtable>(); ScheduleNode preSNode = null; + // Access the ScheduleEdges in reverse topology order for(i = scheduleEdges.size(); i > 0; i--) { ScheduleEdge se = (ScheduleEdge)scheduleEdges.elementAt(i-1); if(ScheduleEdge.NEWEDGE == se.getType()) { @@ -669,34 +701,45 @@ public class ScheduleAnalysis { boolean split = false; FEdge fe = se.getFEdge(); if(fe.getSource() == fe.getTarget()) { - // back edge + // the associated start fe is a back edge try { + // check the number of newly created objs int repeat = (int)Math.ceil(se.getNewRate()*se.getProbability()/100); int rate = 0; - if(repeat > 1) { + /*if(repeat > 1) { + // more than one new objs, expand the new edge for(int j = 1; j< repeat; j++ ) { cloneSNodeList(se, true); - } + } // for(int j = 1; j< repeat; j++ ) se.setNewRate(1); se.setProbability(100); - } + } // if(repeat > 1)*/ try { + // match the rates of obj creation and new obj consumption rate = (int)Math.ceil( se.getListExeTime()/calInExeTime(se.getSourceFState())); } catch (Exception e) { e.printStackTrace(); - } - for(int j = rate - 1; j > 0; j--) { + } // try-catch {} + repeat = (rate > repeat)? rate : repeat; + // expand the new edge + for(int j = 1; j< repeat; j++ ) { + cloneSNodeList(se, true); + } // for(int j = 1; j< repeat; j++ ) + se.setNewRate(1); + se.setProbability(100); + /*for(int j = rate - 1; j > 0; j--) { for(int k = repeat; k > 0; k--) { cloneSNodeList(se, true); - } - } + } // for(int k = repeat; k > 0; k--) + } // for(int j = rate - 1; j > 0; j--)*/ } catch (Exception e) { e.printStackTrace(); System.exit(-1); - } - } else { - // if preSNode is not the same as se's source ScheduleNode + } // try-catch{} + } else { // if(fe.getSource() == fe.getTarget()) + // the associated start fe is not a back edge + // Note: if preSNode is not the same as se's source ScheduleNode // handle any ScheduleEdges previously put into fe2ses whose source // ScheduleNode is preSNode boolean same = (preSNode == se.getSource()); @@ -708,39 +751,32 @@ public class ScheduleAnalysis { for(int j = 0; j < fes.size(); j++) { FEdge tempfe = fes.elementAt(j); Vector ses = fe2ses.get(tempfe); - ScheduleEdge tempse = ses.elementAt(0); - long temptime = tempse.getListExeTime(); - // find out the ScheduleEdge with least exeTime - for(int k = 1; k < ses.size(); k++) { - long ttemp = ses.elementAt(k).getListExeTime(); - if(ttemp < temptime) { - tempse = ses.elementAt(k); - temptime = ttemp; - } - } - // handle the tempse - handleScheduleEdge(tempse, true); - ses.removeElement(tempse); - // handle other ScheduleEdges - for(int k = 0; k < ses.size(); k++) { - handleScheduleEdge(ses.elementAt(k), false); - } + this.handleDescenSEs(ses); ses = null; fe2ses.remove(tempfe); - } + } // for(int j = 0; j < fes.size(); j++) fes = null; - } - } + } + } preSNode = (ScheduleNode)se.getSource(); - } - - // if fe is the last task inside this ClassNode, delay the expanding - // and merging until we find all such 'new' edges - // associated with a last task inside this ClassNode - if(!fe.getTarget().edges().hasNext()) { + } // if(!same) + + if(fe.getTarget().edges().hasNext()) { + // not associated with the last task, check if to split the snode + if((!(se.getTransTime() < this.transThreshold)) + && (se.getSourceCNode().getTransTime() < se.getTransTime())) { + // it's better to transfer the other obj with preSnode + split = true; + splitSNode(se, true); + } + } // if(!fe.getTarget().edges().hasNext()) + + if(!split) { + // delay the expanding and merging until we find all such 'new' + // edges associated with a last task inside this ClassNode if(fe2ses.get(fe) == null) { fe2ses.put(fe, new Vector()); - } + } if(sn2fes.get((ScheduleNode)se.getSource()) == null) { sn2fes.put((ScheduleNode)se.getSource(), new Vector()); } @@ -750,72 +786,17 @@ public class ScheduleAnalysis { if(!sn2fes.get((ScheduleNode)se.getSource()).contains(fe)) { sn2fes.get((ScheduleNode)se.getSource()).add(fe); } - } else { - // As this is not a last task, first handle available ScheduleEdges - // previously put into fe2ses - if((same) && (sn2fes.containsKey(preSNode))) { - Vector fes = sn2fes.remove(preSNode); - for(int j = 0; j < fes.size(); j++) { - FEdge tempfe = fes.elementAt(j); - Vector ses = fe2ses.get(tempfe); - ScheduleEdge tempse = ses.elementAt(0); - long temptime = tempse.getListExeTime(); - // find out the ScheduleEdge with least exeTime - for(int k = 1; k < ses.size(); k++) { - long ttemp = ses.elementAt(k).getListExeTime(); - if(ttemp < temptime) { - tempse = ses.elementAt(k); - temptime = ttemp; - } - } - // handle the tempse - handleScheduleEdge(tempse, true); - ses.removeElement(tempse); - // handle other ScheduleEdges - for(int k = 0; k < ses.size(); k++) { - handleScheduleEdge(ses.elementAt(k), false); - } - ses = null; - fe2ses.remove(tempfe); - } - fes = null; - } - - if((!(se.getTransTime() < this.transThreshold)) - && (se.getSourceCNode().getTransTime() < se.getTransTime())) { - split = true; - splitSNode(se, true); - } else { - // handle this ScheduleEdge - handleScheduleEdge(se, true); - } - } - } - } - } + } // if(!split) + } // if(fe.getSource() == fe.getTarget()) + } // if(ScheduleEdge.NEWEDGE == se.getType()) + } // for(i = scheduleEdges.size(); i > 0; i--) if(!fe2ses.isEmpty()) { Set keys = fe2ses.keySet(); Iterator it_keys = keys.iterator(); while(it_keys.hasNext()) { FEdge tempfe = (FEdge)it_keys.next(); Vector ses = fe2ses.get(tempfe); - ScheduleEdge tempse = ses.elementAt(0); - long temptime = tempse.getListExeTime(); - // find out the ScheduleEdge with least exeTime - for(int k = 1; k < ses.size(); k++) { - long ttemp = ses.elementAt(k).getListExeTime(); - if(ttemp < temptime) { - tempse = ses.elementAt(k); - temptime = ttemp; - } - } - // handle the tempse - handleScheduleEdge(tempse, true); - ses.removeElement(tempse); - // handle other ScheduleEdges - for(int k = 0; k < ses.size(); k++) { - handleScheduleEdge(ses.elementAt(k), false); - } + this.handleDescenSEs(ses); ses = null; } keys = null; @@ -833,7 +814,7 @@ public class ScheduleAnalysis { } private void handleScheduleEdge(ScheduleEdge se, - boolean merge) { + boolean merge) { try { int rate = 0; int repeat = (int)Math.ceil(se.getNewRate() * se.getProbability() / 100); @@ -1043,7 +1024,7 @@ public class ScheduleAnalysis { } private ScheduleNode splitSNode(ScheduleEdge se, - boolean copy) { + boolean copy) { assert(ScheduleEdge.NEWEDGE == se.getType()); FEdge fe = se.getFEdge(); diff --git a/Robust/src/Analysis/Scheduling/ScheduleSimulator.java b/Robust/src/Analysis/Scheduling/ScheduleSimulator.java index f2eb6733..48b82a09 100644 --- a/Robust/src/Analysis/Scheduling/ScheduleSimulator.java +++ b/Robust/src/Analysis/Scheduling/ScheduleSimulator.java @@ -92,6 +92,7 @@ public class ScheduleSimulator { simexegraph = null; } } else {*/ + // TODO Iterator it_scheduling = schedulings.iterator(); int index = 0; while(it_scheduling.hasNext()) { diff --git a/Robust/src/Analysis/Scheduling/TaskSimulator.java b/Robust/src/Analysis/Scheduling/TaskSimulator.java index a1de20ee..9e1044f8 100644 --- a/Robust/src/Analysis/Scheduling/TaskSimulator.java +++ b/Robust/src/Analysis/Scheduling/TaskSimulator.java @@ -215,6 +215,20 @@ public class TaskSimulator { // For shared objects, need to first grab the lock and also check if the version is right for(int i = 0; i < paraQueues.size(); i++) { ObjectSimulator tpara = paraQueues.elementAt(i).peek(); + if(tpara == null) { + // the parameter is already removed, delete this task too + finishTime = 800; + this.currentRun.setFinishTime(finishTime); + this.currentRun.setExetype(2); + for(int j = 0; j < i; ++j) { + tpara = this.paraQueues.elementAt(j).poll(); + if(tpara.isShared() && tpara.isHold()) { + tpara.setHold(false); + } + this.paraQueues.elementAt(j).add(tpara); + } + return; + } if(tpara.isShared()) { if(tpara.isHold()) { // shared object held by other tasks diff --git a/Robust/src/ClassLibrary/Math.java b/Robust/src/ClassLibrary/Math.java index 6f16dee7..7e6a59f6 100644 --- a/Robust/src/ClassLibrary/Math.java +++ b/Robust/src/ClassLibrary/Math.java @@ -132,4 +132,5 @@ public class Math { public static native float sqrtf(float a); public static native float logf(float a); public static native float powf(float a, float b); + public static native float ceilf(float a); } diff --git a/Robust/src/Runtime/math.c b/Robust/src/Runtime/math.c index 183fb6b8..0bd678e8 100644 --- a/Robust/src/Runtime/math.c +++ b/Robust/src/Runtime/math.c @@ -77,3 +77,7 @@ float CALL11(___Math______logf____F, float ___a___, float ___a___) { float CALL22(___Math______powf____F_F, float ___a___, float ___b___, float ___a___, float ___b___) { return powf(___a___,___b___); } + +float CALL11(___Math______ceilf____F, float ___a___, float ___a___) { + return ceilf(___a___); +} diff --git a/Robust/src/Runtime/multicoreruntime.h b/Robust/src/Runtime/multicoreruntime.h index 14ed7921..7610b519 100644 --- a/Robust/src/Runtime/multicoreruntime.h +++ b/Robust/src/Runtime/multicoreruntime.h @@ -217,11 +217,11 @@ struct Queue * totransobjqueue; // queue to hold objs to be transferred #define BAMBOO_BASE_VA 0xd000000 #ifdef GC_DEBUG #include "structdefs.h" -#define BAMBOO_NUM_PAGES (NUMCORES*(2+3)+5) -#define BAMBOO_PAGE_SIZE (16 * 16) +#define BAMBOO_NUM_PAGES (NUMCORES*(2+1)+3) +#define BAMBOO_PAGE_SIZE (64 * 64) #define BAMBOO_SMEM_SIZE (BAMBOO_PAGE_SIZE) #else -#define BAMBOO_NUM_PAGES (1024 * 512) +#define BAMBOO_NUM_PAGES (1024 * 512 * 4) #define BAMBOO_PAGE_SIZE (4096) #define BAMBOO_SMEM_SIZE (16 * BAMBOO_PAGE_SIZE) #endif diff --git a/Robust/src/Runtime/multicoretask.c b/Robust/src/Runtime/multicoretask.c index d3d62bc3..6447caf5 100644 --- a/Robust/src/Runtime/multicoretask.c +++ b/Robust/src/Runtime/multicoretask.c @@ -769,7 +769,7 @@ void tagset(struct ___Object___ * obj, ao=(struct ArrayObject *)tagd->flagptr; #else struct ArrayObject * aonew= - allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL); + allocate_newarray(OBJECTARRAYTYPE,OBJECTARRAYINTERVAL+ao->___length___); #endif aonew->___cachedCode___=ao->___cachedCode___+1; for(i=0; i___length___; i++) { @@ -1181,6 +1181,7 @@ inline void addNewObjInfo(void * nobj) { } #endif +#ifdef MULTICORE_GC struct freeMemItem * findFreeMemChunk(int coren, int isize, int * tofindb) { @@ -1334,6 +1335,7 @@ void * globalmalloc(int isize, freemem->size -= *allocsize; return mem; } // void * globalmalloc(int, struct freeMemItem *, int *) +#endif // malloc from the shared memory void * smemalloc(int coren, @@ -1400,7 +1402,7 @@ void * smemalloc(int coren, #endif } return mem; -} +} // void * smemalloc(int, int, int) // receive object transferred from other cores // or the terminate message from other cores @@ -3081,12 +3083,14 @@ int containstag(struct ___Object___ *ptr, if (objptr->type==OBJECTARRAYTYPE) { struct ArrayObject *ao=(struct ArrayObject *)objptr; for(j=0; j___cachedCode___; j++) { - if (ptr==ARRAYGET(ao, struct ___Object___*, j)) + if (ptr==ARRAYGET(ao, struct ___Object___*, j)) { return 1; + } } return 0; - } else + } else { return objptr==ptr; + } } void toiNext(struct tagobjectiterator *it, diff --git a/Robust/src/buildscript b/Robust/src/buildscript index ca925aa2..1c2ff449 100755 --- a/Robust/src/buildscript +++ b/Robust/src/buildscript @@ -481,7 +481,7 @@ fi if $MULTICOREFLAG then -if ! ${ROBUSTROOT}/ourjava -Xms50m -Xmx1500m $JAVAFORWARDOPTS -classpath $ROBUSTROOT/../cup/:$ROBUSTROOT Main.Main -classlibrary \ +if ! ${ROBUSTROOT}/ourjava -Xms50m -Xmx2500m $JAVAFORWARDOPTS -classpath $ROBUSTROOT/../cup/:$ROBUSTROOT Main.Main -classlibrary \ $ROBUSTROOT/ClassLibrary/ -classlibrary $ROBUSTROOT/ClassLibrary/gnu/ \ -dir $BUILDDIR $JAVAOPTS $SRCFILES then exit $?