CallContext.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746
  1. // Copyright (C) 2002, 2003, 2004 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.mapping;
  4. import gnu.math.*;
  5. import gnu.lists.*;
  6. import gnu.expr.Keyword; // FIXME - bad cross-package dependency
  7. import gnu.expr.Special;
  8. import gnu.kawa.util.HeapSort;
  9. /* #ifdef use:java.lang.invoke */
  10. import java.lang.invoke.*;
  11. /* #else */
  12. // import gnu.mapping.CallContext.MethodHandle;
  13. /* #endif */
  14. /** A procedure activation stack (when compiled with explicit stacks). */
  15. public class CallContext // implements Runnable
  16. // extends ValueStack ??? FIXME
  17. extends ArgListImpl implements ArgList, ArgListBuilder
  18. {
  19. static ThreadLocal currentContext = new ThreadLocal();
  20. public static void setInstance(CallContext ctx)
  21. {
  22. Thread thread = Thread.currentThread();
  23. currentContext.set(ctx);
  24. }
  25. /** Get but don't create a CallContext for the current thread. */
  26. public static CallContext getOnlyInstance()
  27. {
  28. return (CallContext) currentContext.get();
  29. }
  30. /** Get or create a CallContext for the current thread. */
  31. public static CallContext getInstance()
  32. {
  33. CallContext ctx = getOnlyInstance();
  34. if (ctx == null)
  35. {
  36. ctx = new CallContext();
  37. setInstance(ctx);
  38. }
  39. return ctx;
  40. }
  41. public/*private*/ MethodHandle applyMethod; // used for runUntilDone trampoline
  42. // FIXME is this redundant, given the Procedure parameter to the apply
  43. // methods? We probably don't need both.
  44. public /*private*/ Procedure proc; // mostly used for error reporting
  45. public final void setNextProcedure(Procedure proc, MethodHandle apply) {
  46. this.proc = proc;
  47. this.applyMethod = apply;
  48. }
  49. public final void setNextProcedure(Procedure proc) {
  50. this.proc = proc;
  51. this.applyMethod = proc == null ? null : proc.applyToConsumerMethod;
  52. }
  53. /* CPS:
  54. CallFrame frame;
  55. */
  56. /** Default place for function results.
  57. * In the future, function arguments will also use vstack. */
  58. private ValueStack vstack = new ValueStack();
  59. /** Function results are written to this Consumer.
  60. * This may point to vstack - or some other Consumer. */
  61. public Consumer consumer = vstack;
  62. /** Index of next argument.
  63. * This is used by methods like getNextArg, used by callees. */
  64. public int next;
  65. public Object getArgAsObject(int i)
  66. {
  67. /*
  68. if (i < 8)
  69. {
  70. switch ((this.where >> (4 * i)) & 15)
  71. {
  72. case ARG_IN_VALUE1: return value1;
  73. case ARG_IN_VALUE2: return value2;
  74. case ARG_IN_VALUE3: return value3;
  75. case ARG_IN_VALUE4: return value4;
  76. case ARG_IN_IVALUE1: return IntNum.make(ivalue1);
  77. case ARG_IN_IVALUE2: return IntNum.make(ivalue2);
  78. }
  79. }
  80. */
  81. return values[i];
  82. }
  83. /** Note state of matching - have we seen an error?
  84. * Either one of the NO_MATCH values defined in MethodProc, or
  85. * one of MATCH_THROW_ON_EXCEPTION, MATCH_CHECK, MATCH_CHECK_ONLY.
  86. */
  87. int matchState;
  88. /** Request to throw an exception on a match failure.
  89. * This is instead of setting matchState to an error value. */
  90. public static final int MATCH_THROW_ON_EXCEPTION = 0;
  91. /** Request to on failure return error code.
  92. * Error is indicated by check routine returning this CallContext.
  93. * Otherwise, execute actual function and return result (or null). */
  94. public static final int MATCH_CHECK = 1;
  95. /** Request to on failure return error code; on failure return 0.
  96. * Regardless, don't invoke body method. */
  97. public static final int MATCH_CHECK_ONLY = 2;
  98. public void rewind(int mode) {
  99. matchState = mode;
  100. rewind();
  101. }
  102. public void rewind() {
  103. next = 0;
  104. nextKeyword = 0;
  105. }
  106. public void reset() {
  107. super.clear();
  108. rewind(MATCH_THROW_ON_EXCEPTION);
  109. }
  110. public void shiftArgs(Procedure proc, int toDrop) {
  111. super.shiftArgs(toDrop);
  112. rewind();
  113. setNextProcedure(proc);
  114. }
  115. public int getMode() { return matchState; }
  116. //boolean throwOnMatchError;
  117. //boolean matchOnly;
  118. // Maybe:
  119. // int argState;
  120. // argState >= 0: number of args until first key arg (i.e. count-next)
  121. // argsStatc < 0: error code - subsumes matchState
  122. public void matchError(int code) {
  123. //new Error("matchError mp:"+proc+" code:"+Integer.toHexString(code)+" st:"+Integer.toHexString(matchState)).printStackTrace();
  124. if (throwOnException()) {
  125. int arg = (short) code;
  126. code &= 0xffff0000;
  127. if (code == MethodProc.NO_MATCH_TOO_FEW_ARGS
  128. || code == MethodProc.NO_MATCH_TOO_MANY_ARGS) {
  129. WrongArguments wr = new WrongArguments(proc, getArgCount()-numKeywords);
  130. //System.err.println("before WrongArgs code:"+Integer.toHexString(code)+" proc:"+proc+(proc==null?"":(" min:"+proc.minArgs()+" max:"+proc.maxArgs()))+" nargs:"+getArgCount()+" wr.m:"+wr.getMessage()+" wr:"+wr+" next:"+next+" count:"+count+" firstK:"+firstKeyword+" numK:"+numKeywords+" nextK:"+nextKeyword);
  131. throw wr;
  132. }
  133. if (code == MethodProc.NO_MATCH_UNUSED_KEYWORD) {
  134. StringBuilder mbuf = new StringBuilder();
  135. String pname = proc == null ? null : proc.getName();
  136. if (pname == null)
  137. mbuf.append("call has ");
  138. else {
  139. mbuf.append("call to ");
  140. mbuf.append(pname);
  141. mbuf.append(" has ");
  142. }
  143. if (keywords == null || numKeywords <= arg) {
  144. mbuf.append("unexpected keyword");
  145. }
  146. else {
  147. if (sortedKeywords != null && nextKeyword > 0
  148. && nextKeyword < sortedKeywords.length
  149. && arg == sortedKeywords[nextKeyword]
  150. && keywords[arg] == keywords[sortedKeywords[nextKeyword-1]])
  151. //if (arg+1 < numKeywords && keywords[arg] == keywords[arg+1])
  152. mbuf.append("duplicated keyword '");
  153. else
  154. mbuf.append("unexpected keyword '");
  155. mbuf.append(keywords[arg]);
  156. mbuf.append('\'');
  157. }
  158. throw new IllegalArgumentException(mbuf.toString());
  159. }
  160. if (code == MethodProc.NO_MATCH_GUARD_FALSE) {
  161. throw new IllegalArgumentException("guard evaluated to false");
  162. }
  163. throw new WrongType(proc, arg, arg >= 0 ? getArgAsObject(arg) : null);
  164. }
  165. if (matchState == MATCH_CHECK || matchState == MATCH_CHECK_ONLY)
  166. matchState = code;
  167. }
  168. public boolean throwOnException() {
  169. return matchState == MATCH_THROW_ON_EXCEPTION;
  170. }
  171. public boolean haveArg() {
  172. // If using argState: return argState > 0;
  173. return next < count && (next != firstKeyword || numKeywords == 0); // && matchState == 0;
  174. }
  175. /*
  176. public int checkOptionalDone() { // Or: doneWithArgs FIXME unused?
  177. if (next != count)
  178. matchError(MethodProc.NO_MATCH_TOO_MANY_ARGS|next);
  179. else if (matchState == MATCH_THROW_ON_EXCEPTION
  180. || matchState == MATCH_CHECK)
  181. return 0;
  182. return matchState;
  183. }
  184. */
  185. public void checkKeywordsDone() {
  186. if (numKeywords != 0 && next < firstKeyword)
  187. matchError(MethodProc.NO_MATCH_TOO_MANY_ARGS|next);
  188. if (nextKeyword < numKeywords) {
  189. short keywordIndex = sortedKeywords == null ? 0
  190. : sortedKeywords[nextKeyword];
  191. matchError(MethodProc.NO_MATCH_UNUSED_KEYWORD|keywordIndex);
  192. nextKeyword = numKeywords;
  193. }
  194. if (numKeywords > 0)
  195. next = firstKeyword + numKeywords;
  196. }
  197. public int checkDone() { // Or: doneWithArgs
  198. if (next == firstKeyword && numKeywords > 0)
  199. matchError(MethodProc.NO_MATCH_UNUSED_KEYWORD|firstKeyword);
  200. else if (next != count)
  201. matchError(MethodProc.NO_MATCH_TOO_MANY_ARGS|next);
  202. else if (matchState == MATCH_THROW_ON_EXCEPTION
  203. || matchState == MATCH_CHECK)
  204. return 0;
  205. return matchState;
  206. }
  207. public int getArgCount () { return count; }
  208. /** Get the next incoming argument.
  209. */
  210. public Object getNextArg() {
  211. if (next >= count || (next == firstKeyword && numKeywords != 0)) {
  212. matchError(MethodProc.NO_MATCH_TOO_FEW_ARGS|next);
  213. return null;
  214. } else
  215. return getArgAsObject(next++);
  216. }
  217. /** Get the next incoming argument.
  218. * Return defaultValue if there are no more arguments.
  219. */
  220. public Object getNextArg(Object defaultValue) {
  221. if (! haveArg())
  222. return defaultValue;
  223. return getArgAsObject(next++);
  224. }
  225. public final Object[] getRestPlainArray() {
  226. int numKeys = numKeywords();
  227. int firstKey = firstKeyword();
  228. if (next >= firstKey+numKeys || numKeys == 0)
  229. return getRestArgsArray();
  230. if (next <= firstKey) {
  231. Object[] args = new Object[firstKey-next];
  232. int i = 0;
  233. while (next < firstKey)
  234. args[i++] = getArgAsObject(next++);
  235. return args;
  236. }
  237. return new Object[0];
  238. }
  239. public final Object[] getRestArgsArray() {
  240. Object[] arr = getRestArgsArray(next);
  241. next = count;
  242. return arr;
  243. }
  244. /** Get remaining arguments as an array. */
  245. public final Object[] getRestArgsArray (int next)
  246. {
  247. int numKeys = numKeywords();
  248. int skipKeys = next - firstKeyword();
  249. if (skipKeys > 0 && skipKeys <= numKeys)
  250. numKeys -= skipKeys;
  251. int sz = count - next;
  252. Object[] args = new Object[count - next + numKeys];
  253. int i = 0;
  254. while (next < count)
  255. {
  256. String key = getKeyword(next);
  257. if (key != null)
  258. args[i++] = Keyword.make(key);
  259. args[i++] = getArgAsObject(next++);
  260. }
  261. return args;
  262. }
  263. public final LList peekRestArgsList() {
  264. return getRestArgsList(next);
  265. }
  266. public final ArgListVector getRestArgsVector() {
  267. ArgListVector args = getRestArgsVector(next);
  268. next = count;
  269. nextKeyword = numKeywords;
  270. return args;
  271. }
  272. public final LList getRestArgsList() {
  273. LList lst = getRestArgsList(next);
  274. next = count;
  275. nextKeyword = numKeywords;
  276. return lst;
  277. }
  278. /** Get remaining arguments as a list.
  279. * Used for Scheme and Lisp rest args. */
  280. public final LList getRestArgsList(int next) {
  281. if (numKeywords == 0)
  282. return getRestPlainList(next);
  283. else
  284. return ArgListPair.valueOf(getRestArgsVector(next));
  285. }
  286. public final LList getRestPlainList(int next) {
  287. if (false) // FIXME
  288. matchError(MethodProc.NO_MATCH_UNUSED_KEYWORD|firstKeyword);
  289. LList nil = LList.Empty;
  290. LList list = nil;
  291. Pair last = null;
  292. while (next < count)
  293. {
  294. Pair pair = new Pair(getArgAsObject(next++), nil);
  295. if (last == null)
  296. list = pair;
  297. else
  298. last.setCdr(pair);
  299. last = pair;
  300. }
  301. return list;
  302. }
  303. /** Get remaining arguments are an ArgListVector.
  304. * @param next The number of arguments that should be skipped.
  305. * Assume either no keywords have been processed, or they all have.
  306. */
  307. public ArgListVector getRestArgsVector(int next) {
  308. int size = count - next;
  309. if (next >= firstKeyword + numKeywords) {
  310. Object[] args = new Object[size];
  311. System.arraycopy(values, next, args, 0, size);
  312. return new ArgListVector(args, 0, 0);
  313. }
  314. size += numKeywords;
  315. Object[] args = new Object[size];
  316. int j = 0;
  317. for (int i = next; i < count; i++) {
  318. String key = getKeyword(i);
  319. if (key != null)
  320. args[j++] = Keyword.make(key);
  321. args[j++] = getArgAsObject(i);
  322. }
  323. return new ArgListVector(args, firstKeyword-next, numKeywords);
  324. }
  325. /** Note that we are done with the input arguments.
  326. * Throw WrongArguments if there are unprocessed arguments.
  327. */
  328. public void lastArg()
  329. {
  330. if (next < count)
  331. throw new WrongArguments(null, count);
  332. //values = null;
  333. }
  334. public Object[] getArgs()
  335. {
  336. Object[] args = new Object[count];
  337. System.arraycopy(values, 0, args, 0, count);
  338. return args;
  339. /*
  340. if (where == 0)
  341. return values;
  342. else
  343. {
  344. int n = count;
  345. next = 0;
  346. for (int i = 0; i < n; i++)
  347. args[i] = getNextArg();
  348. return args;
  349. }
  350. */
  351. }
  352. /*
  353. void resetArgCount(int size) {
  354. if (values.length < size) {
  355. int nsize = size > 32 ? size : 2 * size;
  356. values = new Object[nsize];
  357. } else {
  358. for (int i = size; i < count; i++)
  359. values[i] = null;
  360. }
  361. }
  362. */
  363. /* * A sorted list of keyword arguments.
  364. * (It might be a win to use a String instead of a short[],
  365. * because a String is cheaper to initialize.
  366. * {@code values[sortedKeywords[i]+firstKeyword]} is the {@code i}'th
  367. * keyword argument in lexicographic order.
  368. */
  369. public static short[] getSortedKeywords(String[] keywords, int nkeys) {
  370. short[] sorted = new short[nkeys];
  371. for (short i = (short) nkeys; --i >= 0; )
  372. sorted[i] = i;
  373. keywordSorter.heapSort(sorted, nkeys, keywords);
  374. return sorted;
  375. }
  376. static class KeywordSorter extends HeapSort<short[], String[]> {
  377. protected void swap(short[] a, int i, int j) {
  378. short t = a[i];
  379. a[i] = a[j];
  380. a[j] = t;
  381. }
  382. protected int compare(short[] a, int i, int j, String[] keywords) {
  383. int cmp = keywords[a[i]].compareTo(keywords[a[j]]);
  384. return cmp != 0 ? cmp : i > j ? 1 : i < j ? -1 : 0;
  385. }
  386. }
  387. static final KeywordSorter keywordSorter = new KeywordSorter();
  388. // Index in the sortedKeywords array. Initialized to 0.
  389. int nextKeyword;
  390. /** Return index of matching keyword argument.
  391. * Must be called with keywords in increasing lexicographic order.
  392. * @return {@code dfault} if no matching keyword argument,
  393. * or the corresponding keyword value.
  394. */
  395. public int nextKeyword(String keyword) {
  396. return nextKeywordIndex(keyword, false);
  397. }
  398. public int nextKeywordAllowOthers(String keyword) {
  399. return nextKeywordIndex(keyword, true);
  400. }
  401. public int nextKeywordIndex(String keyword, boolean allowOthers) {
  402. int klen = numKeywords;
  403. if (klen == 0)
  404. return -1;
  405. if (sortedKeywords == null)
  406. sortedKeywords = getSortedKeywords(keywords, klen);
  407. int i = nextKeyword;
  408. for (;; i++) {
  409. if (i >= klen) {
  410. nextKeyword = i;
  411. return -1;
  412. }
  413. short keywordIndex = sortedKeywords[i];
  414. String argkey = keywords[keywordIndex];
  415. // Assumes keyword strings are interned.
  416. if (argkey==keyword) {
  417. nextKeyword = i+1;
  418. return firstKeyword+keywordIndex;
  419. }
  420. if (allowOthers && argkey.compareTo(keyword) < 0)
  421. continue;
  422. // argkey > keyword
  423. nextKeyword = i;
  424. return -1;
  425. }
  426. }
  427. public Object nextKeyword(String keyword, Object dfault) {
  428. int index = nextKeywordIndex(keyword, false);
  429. return index >= 0 ? values[index] : dfault;
  430. }
  431. public Object nextKeywordAllowOthers(String keyword, Object dfault) {
  432. int index = nextKeywordIndex(keyword, true);
  433. return index >= 0 ? values[index] : dfault;
  434. }
  435. /*
  436. public static int compareForLookup(Keyword keyword1, Keyword keyword2) {
  437. // It might be faster to first compare hashCodes, and only
  438. // then do a compareTo.
  439. // That assumes String#hashCode is optimized by the VM.
  440. return keyword1.getName().compareTo(keyword2.getName());
  441. }
  442. */
  443. public void setupApply(Procedure proc) {
  444. setNextProcedure(proc);
  445. super.setArgs();
  446. rewind(MATCH_THROW_ON_EXCEPTION);
  447. }
  448. public void setupApply(Procedure proc, Object arg0) {
  449. setNextProcedure(proc);
  450. super.setArgs(arg0);
  451. rewind(MATCH_THROW_ON_EXCEPTION);
  452. }
  453. public void setupApply(Procedure proc, Object arg0, Object arg1) {
  454. setNextProcedure(proc);
  455. super.setArgs(arg0, arg1);
  456. rewind(MATCH_THROW_ON_EXCEPTION);
  457. }
  458. public void setupApply(Procedure proc, Object arg0, Object arg1,
  459. Object arg2) {
  460. setNextProcedure(proc);
  461. super.setArgs(arg0, arg1, arg2);
  462. rewind(MATCH_THROW_ON_EXCEPTION);
  463. }
  464. public void setupApply(Procedure proc, Object arg0, Object arg1,
  465. Object arg2, Object arg3) {
  466. setNextProcedure(proc);
  467. super.setArgs(arg0, arg1, arg2, arg3);
  468. rewind(MATCH_THROW_ON_EXCEPTION);
  469. }
  470. public void setupApplyAll(Procedure proc, Object[] args) {
  471. setNextProcedure(proc);
  472. super.setArgsAll(args);
  473. rewind(MATCH_THROW_ON_EXCEPTION);
  474. }
  475. public void setupApplyAll(Procedure proc, Object[] args,
  476. int fromIndex, int toIndex) {
  477. setNextProcedure(proc);
  478. super.setArgsAll(args, fromIndex, toIndex);
  479. rewind(MATCH_THROW_ON_EXCEPTION);
  480. }
  481. public void addArg(Object arg) {
  482. super.add(arg);
  483. }
  484. public void addArg(Object arg0, Object arg1, Object arg2, Object arg3) {
  485. super.add(arg0, arg1, arg2, arg3);
  486. }
  487. /*
  488. public void setArgs() {
  489. super.setArgs();
  490. next = 0;
  491. }
  492. public void setArgs(Object arg0) {
  493. super.setArgs(arg0);
  494. next = 0;
  495. }
  496. public void setArgs(Object arg0, Object arg1) {
  497. super.setArgs(arg0, arg1);
  498. next = 0;
  499. }
  500. public void setArgs(Object arg0, Object arg1, Object arg2) {
  501. super.setArgs(arg0, arg1, arg2);
  502. next = 0;
  503. }
  504. public void setArgs(Object arg0, Object arg1, Object arg2, Object arg3) {
  505. super.setArgs(arg0, arg1, arg2, arg3);
  506. next = 0;
  507. }
  508. public void setArgsAll(Object[] args) {
  509. super.setArgsAll(args);
  510. next = 0;
  511. }
  512. */
  513. public void runUntilDone() throws Throwable
  514. {
  515. for (;;)
  516. {
  517. MethodHandle handle = applyMethod;
  518. if (handle == null)
  519. break;
  520. this.applyMethod = null;
  521. rewind(MATCH_THROW_ON_EXCEPTION);
  522. Object ignored = handle.invokeExact(proc, this);
  523. }
  524. }
  525. /** Setup routine before calling a method that takes a CallContext.
  526. * The compiler emits a call to this before a call to a method that takes
  527. * a CallContext, when it wants the function result as an Object.
  528. * It pushes the CallContest state so it can uses the vstack for a
  529. * temporary, After the method, getFromContext extract the method's result
  530. * from the vstack and restores the state.
  531. */
  532. public final int startFromContext() {
  533. //System.err.println("startFromContext proc:"+proc+" gapS:"+vstack.gapStart +" onSt:"+vstack.gapStartOnPush+" cons:"+consumer.getClass().getName()+" last:"+vstack.lastObject);
  534. if (vstack.gapStart == vstack.gapStartOnPush
  535. && consumer == vstack
  536. && vstack.lastObject==vstack) { // Simple efficient case.
  537. return -1;
  538. } else {
  539. vstack.push();
  540. vstack.consumerOnPush = consumer;
  541. vstack.oindexOnPush = vstack.oindex;
  542. vstack.gapStartOnPush = vstack.gapStart;
  543. consumer = vstack;
  544. return vstack.gapStart;
  545. }
  546. }
  547. /** Routine to extract result and restore state after startFromContext.
  548. */
  549. public final Object getFromContext(int saved) throws Throwable {
  550. runUntilDone();
  551. //System.err.println("getFromContext proc:"+proc+" gapS:"+vstack.gapStart +" onSt:"+vstack.gapStartOnPush+" last:"+vstack.lastObject);
  552. Object result = ((ValueStack) consumer).getValue();
  553. cleanupFromContext(saved);
  554. return result;
  555. }
  556. /** Cleanup-only part of getFromContext.
  557. * This can be in an exception handler as an alternative
  558. * to getFromContext, which is called in the non-exception case.
  559. * (Alternatively, the compiler could call cleanupFromContext
  560. * from a finally clause but that is less efficient, partly
  561. * because the JVM stack must be empty before a finally subroutine.)
  562. */
  563. public final void cleanupFromContext(int saved) {
  564. vstack.gapStart = vstack.gapStartOnPush;
  565. int oindexOnPush = vstack.oindexOnPush;
  566. for (int i = vstack.oindex; --i >= oindexOnPush; )
  567. vstack.objects[i] = null;
  568. vstack.oindex = oindexOnPush;
  569. vstack.lastObject = vstack;
  570. if (saved >= 0) {
  571. consumer = vstack.consumerOnPush;
  572. vstack.pop(saved);
  573. }
  574. }
  575. /** Run until no more continuations, returning final result.
  576. * Assume that the current applyHandle is from proc. */
  577. public final Object runUntilValue() throws Throwable {
  578. // Functionally equivalent to the following, but more efficient.
  579. // int saved = startFromContext();
  580. // try {
  581. // return getFromContext(saved);
  582. // } catch (Throwable ex) {
  583. // cleanupFromContext(saved);
  584. // throw ex;
  585. // }
  586. if (proc != null && applyMethod == Procedure.applyToConsumerDefault) {
  587. applyMethod = null;
  588. return proc.applyToObjectMethod.invokeExact(proc, this);
  589. }
  590. Consumer consumerSave = consumer;
  591. ValueStack vst = vstack;
  592. consumer = vst;
  593. Object lastSave = vst.lastObject;
  594. vst.lastObject = vst;
  595. int dindexSave = vst.gapStart;
  596. int gapStartOnPushSave = vst.gapStartOnPush;
  597. vstack.gapStartOnPush = vst.gapStart;
  598. int oindexSave = vst.oindex;
  599. Object r;
  600. try {
  601. runUntilDone();
  602. return vst.getValue();
  603. } finally {
  604. consumer = consumerSave;
  605. vst.gapStart = dindexSave;
  606. vst.oindex = oindexSave;
  607. vst.gapStartOnPush = gapStartOnPushSave;
  608. vst.lastObject = lastSave;
  609. }
  610. }
  611. /** Run until no more continuations, sending result to a COnsumer. */
  612. public final void runUntilValue(Consumer out) throws Throwable
  613. {
  614. Consumer consumerSave = consumer;
  615. consumer = out;
  616. try
  617. {
  618. runUntilDone();
  619. }
  620. finally
  621. {
  622. consumer = consumerSave;
  623. }
  624. }
  625. /** Write values (of function result) to current consumer. */
  626. public void writeValue(Object value)
  627. {
  628. Values.writeValues(value, consumer);
  629. }
  630. /** Current stack of evaluation frames for interpreter. */
  631. public Object[][] evalFrames;
  632. int consumerOnPushArgState;
  633. public final void pushArgState() {
  634. vstack.pushArgState(this);
  635. }
  636. public final void popArgState() {
  637. vstack.popArgState(this);
  638. }
  639. /* #ifndef use:java.lang.invoke */
  640. // /** A fake "shim" for MethodHandle, as for Procedure application. */
  641. // public static abstract class MethodHandle {
  642. // public abstract Object invokeExact(Procedure proc, CallContext ctx) throws Throwable;
  643. // }
  644. // /** A implementation of "fake MethodHandle" using reflection. */
  645. // public static class ReflectMethodHandle extends MethodHandle {
  646. // java.lang.reflect.Method method;
  647. // public ReflectMethodHandle(java.lang.reflect.Method method) {
  648. // this.method = method;
  649. // }
  650. // public Object invokeExact(Procedure proc, CallContext ctx) throws Throwable {
  651. // try {
  652. // return method.invoke(null, proc, ctx);
  653. // } catch (java.lang.reflect.InvocationTargetException ex) {
  654. // throw ex.getCause();
  655. // }
  656. // }
  657. // }
  658. /* #endif */
  659. }
  660. /* CPS:
  661. class CallFrame
  662. {
  663. Procedure proc;
  664. CallFrame previous;
  665. int saveVstackLen;
  666. // Should probably be in sub-classes of ClassFrame:
  667. Object[] values;
  668. }
  669. */