vm-i-system.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. /* Copyright (C) 2001,2008,2009,2010,2011,2012,2013 Free Software Foundation, Inc.
  2. *
  3. * This library is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU Lesser General Public License
  5. * as published by the Free Software Foundation; either version 3 of
  6. * the License, or (at your option) any later version.
  7. *
  8. * This library is distributed in the hope that it will be useful, but
  9. * WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. *
  13. * You should have received a copy of the GNU Lesser General Public
  14. * License along with this library; if not, write to the Free Software
  15. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  16. * 02110-1301 USA
  17. */
  18. /* This file is included in vm_engine.c */
  19. /*
  20. * Basic operations
  21. */
  22. VM_DEFINE_INSTRUCTION (0, nop, "nop", 0, 0, 0)
  23. {
  24. NEXT;
  25. }
  26. VM_DEFINE_INSTRUCTION (1, halt, "halt", 0, 0, 0)
  27. {
  28. SCM ret;
  29. nvalues = SCM_I_INUM (*sp--);
  30. NULLSTACK (1);
  31. if (nvalues == 1)
  32. POP (ret);
  33. else
  34. {
  35. SYNC_REGISTER ();
  36. sp -= nvalues;
  37. CHECK_UNDERFLOW ();
  38. ret = scm_c_values (sp + 1, nvalues);
  39. NULLSTACK (nvalues);
  40. }
  41. {
  42. #ifdef VM_ENABLE_STACK_NULLING
  43. SCM *old_sp = sp;
  44. #endif
  45. /* Restore registers */
  46. sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
  47. /* Setting the ip here doesn't actually affect control flow, as the calling
  48. code will restore its own registers, but it does help when walking the
  49. stack */
  50. ip = SCM_FRAME_RETURN_ADDRESS (fp);
  51. fp = SCM_FRAME_DYNAMIC_LINK (fp);
  52. NULLSTACK (old_sp - sp);
  53. }
  54. SYNC_ALL ();
  55. return ret;
  56. }
  57. VM_DEFINE_INSTRUCTION (2, drop, "drop", 0, 1, 0)
  58. {
  59. DROP ();
  60. NEXT;
  61. }
  62. VM_DEFINE_INSTRUCTION (3, dup, "dup", 0, 0, 1)
  63. {
  64. SCM x = *sp;
  65. PUSH (x);
  66. NEXT;
  67. }
  68. /*
  69. * Object creation
  70. */
  71. VM_DEFINE_INSTRUCTION (4, void, "void", 0, 0, 1)
  72. {
  73. PUSH (SCM_UNSPECIFIED);
  74. NEXT;
  75. }
  76. VM_DEFINE_INSTRUCTION (5, make_true, "make-true", 0, 0, 1)
  77. {
  78. PUSH (SCM_BOOL_T);
  79. NEXT;
  80. }
  81. VM_DEFINE_INSTRUCTION (6, make_false, "make-false", 0, 0, 1)
  82. {
  83. PUSH (SCM_BOOL_F);
  84. NEXT;
  85. }
  86. VM_DEFINE_INSTRUCTION (7, make_nil, "make-nil", 0, 0, 1)
  87. {
  88. PUSH (SCM_ELISP_NIL);
  89. NEXT;
  90. }
  91. VM_DEFINE_INSTRUCTION (8, make_eol, "make-eol", 0, 0, 1)
  92. {
  93. PUSH (SCM_EOL);
  94. NEXT;
  95. }
  96. VM_DEFINE_INSTRUCTION (9, make_int8, "make-int8", 1, 0, 1)
  97. {
  98. PUSH (SCM_I_MAKINUM ((signed char) FETCH ()));
  99. NEXT;
  100. }
  101. VM_DEFINE_INSTRUCTION (10, make_int8_0, "make-int8:0", 0, 0, 1)
  102. {
  103. PUSH (SCM_INUM0);
  104. NEXT;
  105. }
  106. VM_DEFINE_INSTRUCTION (11, make_int8_1, "make-int8:1", 0, 0, 1)
  107. {
  108. PUSH (SCM_I_MAKINUM (1));
  109. NEXT;
  110. }
  111. VM_DEFINE_INSTRUCTION (12, make_int16, "make-int16", 2, 0, 1)
  112. {
  113. int h = FETCH ();
  114. int l = FETCH ();
  115. PUSH (SCM_I_MAKINUM ((signed short) (h << 8) + l));
  116. NEXT;
  117. }
  118. VM_DEFINE_INSTRUCTION (13, make_int64, "make-int64", 8, 0, 1)
  119. {
  120. scm_t_uint64 v = 0;
  121. v += FETCH ();
  122. v <<= 8; v += FETCH ();
  123. v <<= 8; v += FETCH ();
  124. v <<= 8; v += FETCH ();
  125. v <<= 8; v += FETCH ();
  126. v <<= 8; v += FETCH ();
  127. v <<= 8; v += FETCH ();
  128. v <<= 8; v += FETCH ();
  129. PUSH (scm_from_int64 ((scm_t_int64) v));
  130. NEXT;
  131. }
  132. VM_DEFINE_INSTRUCTION (14, make_uint64, "make-uint64", 8, 0, 1)
  133. {
  134. scm_t_uint64 v = 0;
  135. v += FETCH ();
  136. v <<= 8; v += FETCH ();
  137. v <<= 8; v += FETCH ();
  138. v <<= 8; v += FETCH ();
  139. v <<= 8; v += FETCH ();
  140. v <<= 8; v += FETCH ();
  141. v <<= 8; v += FETCH ();
  142. v <<= 8; v += FETCH ();
  143. PUSH (scm_from_uint64 (v));
  144. NEXT;
  145. }
  146. VM_DEFINE_INSTRUCTION (15, make_char8, "make-char8", 1, 0, 1)
  147. {
  148. scm_t_uint8 v = 0;
  149. v = FETCH ();
  150. PUSH (SCM_MAKE_CHAR (v));
  151. /* Don't simplify this to PUSH (SCM_MAKE_CHAR (FETCH ())). The
  152. contents of SCM_MAKE_CHAR may be evaluated more than once,
  153. resulting in a double fetch. */
  154. NEXT;
  155. }
  156. VM_DEFINE_INSTRUCTION (16, make_char32, "make-char32", 4, 0, 1)
  157. {
  158. scm_t_wchar v = 0;
  159. v += FETCH ();
  160. v <<= 8; v += FETCH ();
  161. v <<= 8; v += FETCH ();
  162. v <<= 8; v += FETCH ();
  163. PUSH (SCM_MAKE_CHAR (v));
  164. NEXT;
  165. }
  166. VM_DEFINE_INSTRUCTION (17, list, "list", 2, -1, 1)
  167. {
  168. unsigned h = FETCH ();
  169. unsigned l = FETCH ();
  170. unsigned len = ((h << 8) + l);
  171. POP_LIST (len);
  172. NEXT;
  173. }
  174. VM_DEFINE_INSTRUCTION (18, vector, "vector", 2, -1, 1)
  175. {
  176. unsigned h = FETCH ();
  177. unsigned l = FETCH ();
  178. unsigned len = ((h << 8) + l);
  179. SCM vect;
  180. SYNC_REGISTER ();
  181. sp++; sp -= len;
  182. CHECK_UNDERFLOW ();
  183. vect = scm_make_vector (scm_from_uint (len), SCM_BOOL_F);
  184. memcpy (SCM_I_VECTOR_WELTS(vect), sp, sizeof(SCM) * len);
  185. NULLSTACK (len);
  186. *sp = vect;
  187. NEXT;
  188. }
  189. /*
  190. * Variable access
  191. */
  192. #define OBJECT_REF(i) objects[i]
  193. #define OBJECT_SET(i,o) objects[i] = o
  194. #define LOCAL_REF(i) SCM_FRAME_VARIABLE (fp, i)
  195. #define LOCAL_SET(i,o) SCM_FRAME_VARIABLE (fp, i) = o
  196. /* For the variable operations, we _must_ obviously avoid function calls to
  197. `scm_variable_ref ()', `scm_variable_bound_p ()' and friends which do
  198. nothing more than the corresponding macros. */
  199. #define VARIABLE_REF(v) SCM_VARIABLE_REF (v)
  200. #define VARIABLE_SET(v,o) SCM_VARIABLE_SET (v, o)
  201. #define VARIABLE_BOUNDP(v) (!scm_is_eq (VARIABLE_REF (v), SCM_UNDEFINED))
  202. #define FREE_VARIABLE_REF(i) SCM_PROGRAM_FREE_VARIABLE_REF (program, i)
  203. /* ref */
  204. VM_DEFINE_INSTRUCTION (19, object_ref, "object-ref", 1, 0, 1)
  205. {
  206. register unsigned objnum = FETCH ();
  207. CHECK_OBJECT (objnum);
  208. PUSH (OBJECT_REF (objnum));
  209. NEXT;
  210. }
  211. /* FIXME: necessary? elt 255 of the vector could be a vector... */
  212. VM_DEFINE_INSTRUCTION (20, long_object_ref, "long-object-ref", 2, 0, 1)
  213. {
  214. unsigned int objnum = FETCH ();
  215. objnum <<= 8;
  216. objnum += FETCH ();
  217. CHECK_OBJECT (objnum);
  218. PUSH (OBJECT_REF (objnum));
  219. NEXT;
  220. }
  221. VM_DEFINE_INSTRUCTION (21, local_ref, "local-ref", 1, 0, 1)
  222. {
  223. PUSH (LOCAL_REF (FETCH ()));
  224. ASSERT_BOUND (*sp);
  225. NEXT;
  226. }
  227. VM_DEFINE_INSTRUCTION (22, long_local_ref, "long-local-ref", 2, 0, 1)
  228. {
  229. unsigned int i = FETCH ();
  230. i <<= 8;
  231. i += FETCH ();
  232. PUSH (LOCAL_REF (i));
  233. ASSERT_BOUND (*sp);
  234. NEXT;
  235. }
  236. VM_DEFINE_INSTRUCTION (23, local_bound, "local-bound?", 1, 0, 1)
  237. {
  238. PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (FETCH ()), SCM_UNDEFINED)));
  239. NEXT;
  240. }
  241. VM_DEFINE_INSTRUCTION (24, long_local_bound, "long-local-bound?", 2, 0, 1)
  242. {
  243. unsigned int i = FETCH ();
  244. i <<= 8;
  245. i += FETCH ();
  246. PUSH (scm_from_bool (!scm_is_eq (LOCAL_REF (i), SCM_UNDEFINED)));
  247. NEXT;
  248. }
  249. VM_DEFINE_INSTRUCTION (25, variable_ref, "variable-ref", 0, 1, 1)
  250. {
  251. SCM x = *sp;
  252. /* We don't use ASSERT_VARIABLE or ASSERT_BOUND_VARIABLE here because,
  253. unlike in top-variable-ref, it really isn't an internal assertion
  254. that can be optimized out -- the variable could be coming directly
  255. from the user. */
  256. VM_ASSERT (SCM_VARIABLEP (x),
  257. vm_error_not_a_variable ("variable-ref", x));
  258. if (SCM_UNLIKELY (!VARIABLE_BOUNDP (x)))
  259. {
  260. SCM var_name;
  261. SYNC_ALL ();
  262. /* Attempt to provide the variable name in the error message. */
  263. var_name = scm_module_reverse_lookup (scm_current_module (), x);
  264. vm_error_unbound (program, scm_is_true (var_name) ? var_name : x);
  265. }
  266. else
  267. {
  268. SCM o = VARIABLE_REF (x);
  269. *sp = o;
  270. }
  271. NEXT;
  272. }
  273. VM_DEFINE_INSTRUCTION (26, variable_bound, "variable-bound?", 0, 1, 1)
  274. {
  275. SCM x = *sp;
  276. VM_ASSERT (SCM_VARIABLEP (x),
  277. vm_error_not_a_variable ("variable-bound?", x));
  278. *sp = scm_from_bool (VARIABLE_BOUNDP (x));
  279. NEXT;
  280. }
  281. VM_DEFINE_INSTRUCTION (27, toplevel_ref, "toplevel-ref", 1, 0, 1)
  282. {
  283. unsigned objnum = FETCH ();
  284. SCM what, resolved;
  285. CHECK_OBJECT (objnum);
  286. what = OBJECT_REF (objnum);
  287. if (!SCM_VARIABLEP (what))
  288. {
  289. SYNC_REGISTER ();
  290. resolved = resolve_variable (what, scm_program_module (program));
  291. VM_ASSERT (VARIABLE_BOUNDP (resolved), vm_error_unbound (program, what));
  292. what = resolved;
  293. OBJECT_SET (objnum, what);
  294. }
  295. PUSH (VARIABLE_REF (what));
  296. NEXT;
  297. }
  298. VM_DEFINE_INSTRUCTION (28, long_toplevel_ref, "long-toplevel-ref", 2, 0, 1)
  299. {
  300. SCM what, resolved;
  301. unsigned int objnum = FETCH ();
  302. objnum <<= 8;
  303. objnum += FETCH ();
  304. CHECK_OBJECT (objnum);
  305. what = OBJECT_REF (objnum);
  306. if (!SCM_VARIABLEP (what))
  307. {
  308. SYNC_REGISTER ();
  309. resolved = resolve_variable (what, scm_program_module (program));
  310. VM_ASSERT (VARIABLE_BOUNDP (resolved),
  311. vm_error_unbound (program, what));
  312. what = resolved;
  313. OBJECT_SET (objnum, what);
  314. }
  315. PUSH (VARIABLE_REF (what));
  316. NEXT;
  317. }
  318. /* set */
  319. VM_DEFINE_INSTRUCTION (29, local_set, "local-set", 1, 1, 0)
  320. {
  321. SCM x;
  322. POP (x);
  323. LOCAL_SET (FETCH (), x);
  324. NEXT;
  325. }
  326. VM_DEFINE_INSTRUCTION (30, long_local_set, "long-local-set", 2, 1, 0)
  327. {
  328. SCM x;
  329. unsigned int i = FETCH ();
  330. i <<= 8;
  331. i += FETCH ();
  332. POP (x);
  333. LOCAL_SET (i, x);
  334. NEXT;
  335. }
  336. VM_DEFINE_INSTRUCTION (31, variable_set, "variable-set", 0, 2, 0)
  337. {
  338. VM_ASSERT (SCM_VARIABLEP (sp[0]),
  339. vm_error_not_a_variable ("variable-set!", sp[0]));
  340. VARIABLE_SET (sp[0], sp[-1]);
  341. DROPN (2);
  342. NEXT;
  343. }
  344. VM_DEFINE_INSTRUCTION (32, toplevel_set, "toplevel-set", 1, 1, 0)
  345. {
  346. unsigned objnum = FETCH ();
  347. SCM what;
  348. CHECK_OBJECT (objnum);
  349. what = OBJECT_REF (objnum);
  350. if (!SCM_VARIABLEP (what))
  351. {
  352. SYNC_BEFORE_GC ();
  353. what = resolve_variable (what, scm_program_module (program));
  354. OBJECT_SET (objnum, what);
  355. }
  356. VARIABLE_SET (what, *sp);
  357. DROP ();
  358. NEXT;
  359. }
  360. VM_DEFINE_INSTRUCTION (33, long_toplevel_set, "long-toplevel-set", 2, 1, 0)
  361. {
  362. SCM what;
  363. unsigned int objnum = FETCH ();
  364. objnum <<= 8;
  365. objnum += FETCH ();
  366. CHECK_OBJECT (objnum);
  367. what = OBJECT_REF (objnum);
  368. if (!SCM_VARIABLEP (what))
  369. {
  370. SYNC_BEFORE_GC ();
  371. what = resolve_variable (what, scm_program_module (program));
  372. OBJECT_SET (objnum, what);
  373. }
  374. VARIABLE_SET (what, *sp);
  375. DROP ();
  376. NEXT;
  377. }
  378. /*
  379. * branch and jump
  380. */
  381. /* offset must be at least 24 bits wide, and signed */
  382. #define FETCH_OFFSET(offset) \
  383. { \
  384. offset = FETCH () << 16; \
  385. offset += FETCH () << 8; \
  386. offset += FETCH (); \
  387. offset -= (offset & (1<<23)) << 1; \
  388. }
  389. #define BR(p) \
  390. { \
  391. scm_t_int32 offset; \
  392. FETCH_OFFSET (offset); \
  393. if (p) \
  394. ip += offset; \
  395. if (offset < 0) \
  396. VM_HANDLE_INTERRUPTS; \
  397. NEXT; \
  398. }
  399. VM_DEFINE_INSTRUCTION (34, br, "br", 3, 0, 0)
  400. {
  401. scm_t_int32 offset;
  402. FETCH_OFFSET (offset);
  403. ip += offset;
  404. if (offset < 0)
  405. VM_HANDLE_INTERRUPTS;
  406. NEXT;
  407. }
  408. VM_DEFINE_INSTRUCTION (35, br_if, "br-if", 3, 0, 0)
  409. {
  410. SCM x;
  411. POP (x);
  412. BR (scm_is_true (x));
  413. }
  414. VM_DEFINE_INSTRUCTION (36, br_if_not, "br-if-not", 3, 0, 0)
  415. {
  416. SCM x;
  417. POP (x);
  418. BR (scm_is_false (x));
  419. }
  420. VM_DEFINE_INSTRUCTION (37, br_if_eq, "br-if-eq", 3, 0, 0)
  421. {
  422. SCM x, y;
  423. POP2 (y, x);
  424. BR (scm_is_eq (x, y));
  425. }
  426. VM_DEFINE_INSTRUCTION (38, br_if_not_eq, "br-if-not-eq", 3, 0, 0)
  427. {
  428. SCM x, y;
  429. POP2 (y, x);
  430. BR (!scm_is_eq (x, y));
  431. }
  432. VM_DEFINE_INSTRUCTION (39, br_if_null, "br-if-null", 3, 0, 0)
  433. {
  434. SCM x;
  435. POP (x);
  436. BR (scm_is_null (x));
  437. }
  438. VM_DEFINE_INSTRUCTION (40, br_if_not_null, "br-if-not-null", 3, 0, 0)
  439. {
  440. SCM x;
  441. POP (x);
  442. BR (!scm_is_null (x));
  443. }
  444. VM_DEFINE_INSTRUCTION (41, br_if_nil, "br-if-nil", 3, 0, 0)
  445. {
  446. SCM x;
  447. POP (x);
  448. BR (scm_is_lisp_false (x));
  449. }
  450. VM_DEFINE_INSTRUCTION (42, br_if_not_nil, "br-if-not-nil", 3, 0, 0)
  451. {
  452. SCM x;
  453. POP (x);
  454. BR (!scm_is_lisp_false (x));
  455. }
  456. #undef BR
  457. /*
  458. * Subprogram call
  459. */
  460. VM_DEFINE_INSTRUCTION (43, br_if_nargs_ne, "br-if-nargs-ne", 5, 0, 0)
  461. {
  462. scm_t_ptrdiff n;
  463. scm_t_int32 offset;
  464. n = FETCH () << 8;
  465. n += FETCH ();
  466. FETCH_OFFSET (offset);
  467. if (sp - (fp - 1) != n)
  468. ip += offset;
  469. NEXT;
  470. }
  471. VM_DEFINE_INSTRUCTION (44, br_if_nargs_lt, "br-if-nargs-lt", 5, 0, 0)
  472. {
  473. scm_t_ptrdiff n;
  474. scm_t_int32 offset;
  475. n = FETCH () << 8;
  476. n += FETCH ();
  477. FETCH_OFFSET (offset);
  478. if (sp - (fp - 1) < n)
  479. ip += offset;
  480. NEXT;
  481. }
  482. VM_DEFINE_INSTRUCTION (45, br_if_nargs_gt, "br-if-nargs-gt", 5, 0, 0)
  483. {
  484. scm_t_ptrdiff n;
  485. scm_t_int32 offset;
  486. n = FETCH () << 8;
  487. n += FETCH ();
  488. FETCH_OFFSET (offset);
  489. if (sp - (fp - 1) > n)
  490. ip += offset;
  491. NEXT;
  492. }
  493. VM_DEFINE_INSTRUCTION (46, assert_nargs_ee, "assert-nargs-ee", 2, 0, 0)
  494. {
  495. scm_t_ptrdiff n;
  496. n = FETCH () << 8;
  497. n += FETCH ();
  498. VM_ASSERT (sp - (fp - 1) == n,
  499. vm_error_wrong_num_args (program));
  500. NEXT;
  501. }
  502. VM_DEFINE_INSTRUCTION (47, assert_nargs_ge, "assert-nargs-ge", 2, 0, 0)
  503. {
  504. scm_t_ptrdiff n;
  505. n = FETCH () << 8;
  506. n += FETCH ();
  507. VM_ASSERT (sp - (fp - 1) >= n,
  508. vm_error_wrong_num_args (program));
  509. NEXT;
  510. }
  511. VM_DEFINE_INSTRUCTION (48, bind_optionals, "bind-optionals", 2, -1, -1)
  512. {
  513. scm_t_ptrdiff n;
  514. n = FETCH () << 8;
  515. n += FETCH ();
  516. while (sp - (fp - 1) < n)
  517. PUSH (SCM_UNDEFINED);
  518. NEXT;
  519. }
  520. VM_DEFINE_INSTRUCTION (49, bind_optionals_shuffle, "bind-optionals/shuffle", 6, -1, -1)
  521. {
  522. SCM *walk;
  523. scm_t_ptrdiff nreq, nreq_and_opt, ntotal;
  524. nreq = FETCH () << 8;
  525. nreq += FETCH ();
  526. nreq_and_opt = FETCH () << 8;
  527. nreq_and_opt += FETCH ();
  528. ntotal = FETCH () << 8;
  529. ntotal += FETCH ();
  530. /* look in optionals for first keyword or last positional */
  531. /* starting after the last required positional arg */
  532. walk = fp + nreq;
  533. while (/* while we have args */
  534. walk <= sp
  535. /* and we still have positionals to fill */
  536. && walk - fp < nreq_and_opt
  537. /* and we haven't reached a keyword yet */
  538. && !scm_is_keyword (*walk))
  539. /* bind this optional arg (by leaving it in place) */
  540. walk++;
  541. /* now shuffle up, from walk to ntotal */
  542. {
  543. scm_t_ptrdiff nshuf = sp - walk + 1, i;
  544. sp = (fp - 1) + ntotal + nshuf;
  545. CHECK_OVERFLOW ();
  546. for (i = 0; i < nshuf; i++)
  547. sp[-i] = walk[nshuf-i-1];
  548. }
  549. /* and fill optionals & keyword args with SCM_UNDEFINED */
  550. while (walk <= (fp - 1) + ntotal)
  551. *walk++ = SCM_UNDEFINED;
  552. NEXT;
  553. }
  554. /* See also bind-optionals/shuffle-or-br below. */
  555. /* Flags that determine whether other keywords are allowed, and whether a
  556. rest argument is expected. These values must match those used by the
  557. glil->assembly compiler. */
  558. #define F_ALLOW_OTHER_KEYS 1
  559. #define F_REST 2
  560. VM_DEFINE_INSTRUCTION (50, bind_kwargs, "bind-kwargs", 5, 0, 0)
  561. {
  562. scm_t_uint16 idx;
  563. scm_t_ptrdiff nkw;
  564. int kw_and_rest_flags;
  565. SCM kw;
  566. idx = FETCH () << 8;
  567. idx += FETCH ();
  568. /* XXX: We don't actually use NKW. */
  569. nkw = FETCH () << 8;
  570. nkw += FETCH ();
  571. kw_and_rest_flags = FETCH ();
  572. VM_ASSERT ((kw_and_rest_flags & F_REST)
  573. || ((sp - (fp - 1) - nkw) % 2) == 0,
  574. vm_error_kwargs_length_not_even (program))
  575. CHECK_OBJECT (idx);
  576. kw = OBJECT_REF (idx);
  577. /* Switch NKW to be a negative index below SP. */
  578. for (nkw = -(sp - (fp - 1) - nkw) + 1; nkw < 0; nkw++)
  579. {
  580. SCM walk;
  581. if (scm_is_keyword (sp[nkw]))
  582. {
  583. for (walk = kw; scm_is_pair (walk); walk = SCM_CDR (walk))
  584. {
  585. if (scm_is_eq (SCM_CAAR (walk), sp[nkw]))
  586. {
  587. SCM si = SCM_CDAR (walk);
  588. LOCAL_SET (SCM_I_INUMP (si) ? SCM_I_INUM (si) : scm_to_long (si),
  589. sp[nkw + 1]);
  590. break;
  591. }
  592. }
  593. VM_ASSERT (scm_is_pair (walk)
  594. || (kw_and_rest_flags & F_ALLOW_OTHER_KEYS),
  595. vm_error_kwargs_unrecognized_keyword (program, sp[nkw]));
  596. nkw++;
  597. }
  598. else
  599. VM_ASSERT (kw_and_rest_flags & F_REST,
  600. vm_error_kwargs_invalid_keyword (program, sp[nkw]));
  601. }
  602. NEXT;
  603. }
  604. #undef F_ALLOW_OTHER_KEYS
  605. #undef F_REST
  606. VM_DEFINE_INSTRUCTION (51, push_rest, "push-rest", 2, -1, -1)
  607. {
  608. scm_t_ptrdiff n;
  609. SCM rest = SCM_EOL;
  610. n = FETCH () << 8;
  611. n += FETCH ();
  612. SYNC_BEFORE_GC ();
  613. while (sp - (fp - 1) > n)
  614. /* No need to check for underflow. */
  615. rest = scm_cons (*sp--, rest);
  616. PUSH (rest);
  617. NEXT;
  618. }
  619. VM_DEFINE_INSTRUCTION (52, bind_rest, "bind-rest", 4, -1, -1)
  620. {
  621. scm_t_ptrdiff n;
  622. scm_t_uint32 i;
  623. SCM rest = SCM_EOL;
  624. n = FETCH () << 8;
  625. n += FETCH ();
  626. i = FETCH () << 8;
  627. i += FETCH ();
  628. SYNC_BEFORE_GC ();
  629. while (sp - (fp - 1) > n)
  630. /* No need to check for underflow. */
  631. rest = scm_cons (*sp--, rest);
  632. LOCAL_SET (i, rest);
  633. NEXT;
  634. }
  635. VM_DEFINE_INSTRUCTION (53, reserve_locals, "reserve-locals", 2, -1, -1)
  636. {
  637. SCM *old_sp;
  638. scm_t_int32 n;
  639. n = FETCH () << 8;
  640. n += FETCH ();
  641. old_sp = sp;
  642. sp = (fp - 1) + n;
  643. if (old_sp < sp)
  644. {
  645. CHECK_OVERFLOW ();
  646. while (old_sp < sp)
  647. *++old_sp = SCM_UNDEFINED;
  648. }
  649. else
  650. NULLSTACK (old_sp - sp);
  651. NEXT;
  652. }
  653. VM_DEFINE_INSTRUCTION (54, new_frame, "new-frame", 0, 0, 3)
  654. {
  655. /* NB: if you change this, see frames.c:vm-frame-num-locals */
  656. /* and frames.h, vm-engine.c, etc of course */
  657. /* We don't initialize the dynamic link here because we don't actually
  658. know that this frame will point to the current fp: it could be
  659. placed elsewhere on the stack if captured in a partial
  660. continuation, and invoked from some other context. */
  661. PUSH (SCM_PACK (0)); /* dynamic link */
  662. PUSH (SCM_PACK (0)); /* mvra */
  663. PUSH (SCM_PACK (0)); /* ra */
  664. NEXT;
  665. }
  666. VM_DEFINE_INSTRUCTION (55, call, "call", 1, -1, 1)
  667. {
  668. nargs = FETCH ();
  669. vm_call:
  670. VM_HANDLE_INTERRUPTS;
  671. {
  672. SCM *old_fp = fp;
  673. fp = sp - nargs + 1;
  674. ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
  675. ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
  676. ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
  677. SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
  678. SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
  679. SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, 0);
  680. }
  681. PUSH_CONTINUATION_HOOK ();
  682. program = fp[-1];
  683. if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
  684. goto apply;
  685. CACHE_PROGRAM ();
  686. ip = SCM_C_OBJCODE_BASE (bp);
  687. APPLY_HOOK ();
  688. NEXT;
  689. }
  690. VM_DEFINE_INSTRUCTION (56, tail_call, "tail-call", 1, -1, 1)
  691. {
  692. nargs = FETCH ();
  693. vm_tail_call:
  694. VM_HANDLE_INTERRUPTS;
  695. {
  696. int i;
  697. #ifdef VM_ENABLE_STACK_NULLING
  698. SCM *old_sp = sp;
  699. CHECK_STACK_LEAK ();
  700. #endif
  701. /* shuffle down the program and the arguments */
  702. for (i = -1, sp = sp - nargs + 1; i < nargs; i++)
  703. SCM_FRAME_STACK_ADDRESS (fp)[i] = sp[i];
  704. sp = fp + i - 1;
  705. NULLSTACK (old_sp - sp);
  706. }
  707. program = fp[-1];
  708. if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
  709. goto apply;
  710. CACHE_PROGRAM ();
  711. ip = SCM_C_OBJCODE_BASE (bp);
  712. APPLY_HOOK ();
  713. NEXT;
  714. }
  715. VM_DEFINE_INSTRUCTION (57, subr_call, "subr-call", 1, -1, -1)
  716. {
  717. SCM pointer, ret;
  718. SCM (*subr)();
  719. nargs = FETCH ();
  720. POP (pointer);
  721. subr = SCM_POINTER_VALUE (pointer);
  722. VM_HANDLE_INTERRUPTS;
  723. SYNC_REGISTER ();
  724. switch (nargs)
  725. {
  726. case 0:
  727. ret = subr ();
  728. break;
  729. case 1:
  730. ret = subr (sp[0]);
  731. break;
  732. case 2:
  733. ret = subr (sp[-1], sp[0]);
  734. break;
  735. case 3:
  736. ret = subr (sp[-2], sp[-1], sp[0]);
  737. break;
  738. case 4:
  739. ret = subr (sp[-3], sp[-2], sp[-1], sp[0]);
  740. break;
  741. case 5:
  742. ret = subr (sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
  743. break;
  744. case 6:
  745. ret = subr (sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
  746. break;
  747. case 7:
  748. ret = subr (sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
  749. break;
  750. case 8:
  751. ret = subr (sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
  752. break;
  753. case 9:
  754. ret = subr (sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
  755. break;
  756. case 10:
  757. ret = subr (sp[-9], sp[-8], sp[-7], sp[-6], sp[-5], sp[-4], sp[-3], sp[-2], sp[-1], sp[0]);
  758. break;
  759. default:
  760. abort ();
  761. }
  762. NULLSTACK_FOR_NONLOCAL_EXIT ();
  763. if (SCM_UNLIKELY (SCM_VALUESP (ret)))
  764. {
  765. /* multiple values returned to continuation */
  766. ret = scm_struct_ref (ret, SCM_INUM0);
  767. nvalues = scm_ilength (ret);
  768. PUSH_LIST (ret, scm_is_null);
  769. goto vm_return_values;
  770. }
  771. else
  772. {
  773. PUSH (ret);
  774. goto vm_return;
  775. }
  776. }
  777. /* Instruction 58 used to be smob-call. */
  778. VM_DEFINE_INSTRUCTION (59, foreign_call, "foreign-call", 1, -1, -1)
  779. {
  780. SCM foreign, ret;
  781. nargs = FETCH ();
  782. POP (foreign);
  783. VM_HANDLE_INTERRUPTS;
  784. SYNC_REGISTER ();
  785. ret = scm_i_foreign_call (foreign, sp - nargs + 1);
  786. NULLSTACK_FOR_NONLOCAL_EXIT ();
  787. if (SCM_UNLIKELY (SCM_VALUESP (ret)))
  788. {
  789. /* multiple values returned to continuation */
  790. ret = scm_struct_ref (ret, SCM_INUM0);
  791. nvalues = scm_ilength (ret);
  792. PUSH_LIST (ret, scm_is_null);
  793. goto vm_return_values;
  794. }
  795. else
  796. {
  797. PUSH (ret);
  798. goto vm_return;
  799. }
  800. }
  801. VM_DEFINE_INSTRUCTION (60, continuation_call, "continuation-call", 0, -1, 0)
  802. {
  803. SCM contregs;
  804. POP (contregs);
  805. SYNC_ALL ();
  806. scm_i_check_continuation (contregs);
  807. vm_return_to_continuation (scm_i_contregs_vm (contregs),
  808. scm_i_contregs_vm_cont (contregs),
  809. sp - (fp - 1), fp);
  810. scm_i_reinstate_continuation (contregs);
  811. /* no NEXT */
  812. abort ();
  813. }
  814. VM_DEFINE_INSTRUCTION (61, partial_cont_call, "partial-cont-call", 0, -1, 0)
  815. {
  816. SCM vmcont;
  817. POP (vmcont);
  818. SYNC_REGISTER ();
  819. VM_ASSERT (SCM_VM_CONT_REWINDABLE_P (vmcont),
  820. vm_error_continuation_not_rewindable (vmcont));
  821. vm_reinstate_partial_continuation (vm, vmcont, sp + 1 - fp, fp,
  822. &current_thread->dynstack,
  823. &registers);
  824. CACHE_REGISTER ();
  825. program = SCM_FRAME_PROGRAM (fp);
  826. CACHE_PROGRAM ();
  827. NEXT;
  828. }
  829. VM_DEFINE_INSTRUCTION (62, tail_call_nargs, "tail-call/nargs", 0, 0, 1)
  830. {
  831. SCM x;
  832. POP (x);
  833. nargs = scm_to_int (x);
  834. /* FIXME: should truncate values? */
  835. goto vm_tail_call;
  836. }
  837. VM_DEFINE_INSTRUCTION (63, call_nargs, "call/nargs", 0, 0, 1)
  838. {
  839. SCM x;
  840. POP (x);
  841. nargs = scm_to_int (x);
  842. /* FIXME: should truncate values? */
  843. goto vm_call;
  844. }
  845. VM_DEFINE_INSTRUCTION (64, mv_call, "mv-call", 4, -1, 1)
  846. {
  847. scm_t_int32 offset;
  848. scm_t_uint8 *mvra;
  849. SCM *old_fp = fp;
  850. nargs = FETCH ();
  851. FETCH_OFFSET (offset);
  852. mvra = ip + offset;
  853. VM_HANDLE_INTERRUPTS;
  854. fp = sp - nargs + 1;
  855. ASSERT (SCM_FRAME_DYNAMIC_LINK (fp) == 0);
  856. ASSERT (SCM_FRAME_RETURN_ADDRESS (fp) == 0);
  857. ASSERT (SCM_FRAME_MV_RETURN_ADDRESS (fp) == 0);
  858. SCM_FRAME_SET_DYNAMIC_LINK (fp, old_fp);
  859. SCM_FRAME_SET_RETURN_ADDRESS (fp, ip);
  860. SCM_FRAME_SET_MV_RETURN_ADDRESS (fp, mvra);
  861. PUSH_CONTINUATION_HOOK ();
  862. program = fp[-1];
  863. if (SCM_UNLIKELY (!SCM_PROGRAM_P (program)))
  864. goto apply;
  865. CACHE_PROGRAM ();
  866. ip = SCM_C_OBJCODE_BASE (bp);
  867. APPLY_HOOK ();
  868. NEXT;
  869. }
  870. VM_DEFINE_INSTRUCTION (65, apply, "apply", 1, -1, 1)
  871. {
  872. int len;
  873. SCM ls;
  874. POP (ls);
  875. nargs = FETCH ();
  876. ASSERT (nargs >= 2);
  877. len = scm_ilength (ls);
  878. VM_ASSERT (len >= 0,
  879. vm_error_apply_to_non_list (ls));
  880. PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
  881. nargs += len - 2;
  882. goto vm_call;
  883. }
  884. VM_DEFINE_INSTRUCTION (66, tail_apply, "tail-apply", 1, -1, 1)
  885. {
  886. int len;
  887. SCM ls;
  888. POP (ls);
  889. nargs = FETCH ();
  890. ASSERT (nargs >= 2);
  891. len = scm_ilength (ls);
  892. VM_ASSERT (len >= 0,
  893. vm_error_apply_to_non_list (ls));
  894. PUSH_LIST (ls, SCM_NULL_OR_NIL_P);
  895. nargs += len - 2;
  896. goto vm_tail_call;
  897. }
  898. VM_DEFINE_INSTRUCTION (67, call_cc, "call/cc", 0, 1, 1)
  899. {
  900. int first;
  901. SCM proc, vm_cont, cont;
  902. scm_t_dynstack *dynstack;
  903. POP (proc);
  904. SYNC_ALL ();
  905. dynstack = scm_dynstack_capture_all (&current_thread->dynstack);
  906. vm_cont = scm_i_vm_capture_stack (vp->stack_base, fp, sp, ip, NULL,
  907. dynstack, 0);
  908. cont = scm_i_make_continuation (&first, vm, vm_cont);
  909. if (first)
  910. {
  911. PUSH (SCM_PACK (0)); /* dynamic link */
  912. PUSH (SCM_PACK (0)); /* mvra */
  913. PUSH (SCM_PACK (0)); /* ra */
  914. PUSH (proc);
  915. PUSH (cont);
  916. nargs = 1;
  917. goto vm_call;
  918. }
  919. else
  920. {
  921. /* Otherwise, the vm continuation was reinstated, and
  922. vm_return_to_continuation pushed on one value. We know only one
  923. value was returned because we are in value context -- the
  924. previous block jumped to vm_call, not vm_mv_call, after all.
  925. So, pull our regs back down from the vp, and march on to the
  926. next instruction. */
  927. CACHE_REGISTER ();
  928. program = SCM_FRAME_PROGRAM (fp);
  929. CACHE_PROGRAM ();
  930. RESTORE_CONTINUATION_HOOK ();
  931. NEXT;
  932. }
  933. }
  934. VM_DEFINE_INSTRUCTION (68, tail_call_cc, "tail-call/cc", 0, 1, 1)
  935. {
  936. int first;
  937. SCM proc, vm_cont, cont;
  938. scm_t_dynstack *dynstack;
  939. POP (proc);
  940. SYNC_ALL ();
  941. /* In contrast to call/cc, tail-call/cc captures the continuation without the
  942. stack frame. */
  943. dynstack = scm_dynstack_capture_all (&current_thread->dynstack);
  944. vm_cont = scm_i_vm_capture_stack (vp->stack_base,
  945. SCM_FRAME_DYNAMIC_LINK (fp),
  946. SCM_FRAME_LOWER_ADDRESS (fp) - 1,
  947. SCM_FRAME_RETURN_ADDRESS (fp),
  948. SCM_FRAME_MV_RETURN_ADDRESS (fp),
  949. dynstack,
  950. 0);
  951. cont = scm_i_make_continuation (&first, vm, vm_cont);
  952. if (first)
  953. {
  954. PUSH (proc);
  955. PUSH (cont);
  956. nargs = 1;
  957. goto vm_tail_call;
  958. }
  959. else
  960. {
  961. /* Otherwise, cache regs and NEXT, as above. Invoking the continuation
  962. does a return from the frame, either to the RA or
  963. MVRA. */
  964. CACHE_REGISTER ();
  965. program = SCM_FRAME_PROGRAM (fp);
  966. CACHE_PROGRAM ();
  967. /* Unfortunately we don't know whether we are at the RA, and thus
  968. have one value without an nvalues marker, or we are at the
  969. MVRA and thus have multiple values and the nvalues
  970. marker. Instead of adding heuristics here, we will let hook
  971. client code do that. */
  972. RESTORE_CONTINUATION_HOOK ();
  973. NEXT;
  974. }
  975. }
  976. VM_DEFINE_INSTRUCTION (69, return, "return", 0, 1, 1)
  977. {
  978. vm_return:
  979. POP_CONTINUATION_HOOK (sp, 1);
  980. VM_HANDLE_INTERRUPTS;
  981. {
  982. SCM ret;
  983. POP (ret);
  984. #ifdef VM_ENABLE_STACK_NULLING
  985. SCM *old_sp = sp;
  986. #endif
  987. /* Restore registers */
  988. sp = SCM_FRAME_LOWER_ADDRESS (fp);
  989. ip = SCM_FRAME_RETURN_ADDRESS (fp);
  990. fp = SCM_FRAME_DYNAMIC_LINK (fp);
  991. #ifdef VM_ENABLE_STACK_NULLING
  992. NULLSTACK (old_sp - sp);
  993. #endif
  994. /* Set return value (sp is already pushed) */
  995. *sp = ret;
  996. }
  997. /* Restore the last program */
  998. program = SCM_FRAME_PROGRAM (fp);
  999. CACHE_PROGRAM ();
  1000. CHECK_IP ();
  1001. NEXT;
  1002. }
  1003. VM_DEFINE_INSTRUCTION (70, return_values, "return/values", 1, -1, -1)
  1004. {
  1005. /* nvalues declared at top level, because for some reason gcc seems to think
  1006. that perhaps it might be used without declaration. Fooey to that, I say. */
  1007. nvalues = FETCH ();
  1008. vm_return_values:
  1009. POP_CONTINUATION_HOOK (sp + 1 - nvalues, nvalues);
  1010. VM_HANDLE_INTERRUPTS;
  1011. if (nvalues != 1 && SCM_FRAME_MV_RETURN_ADDRESS (fp))
  1012. {
  1013. /* A multiply-valued continuation */
  1014. SCM *vals = sp - nvalues;
  1015. int i;
  1016. /* Restore registers */
  1017. sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
  1018. ip = SCM_FRAME_MV_RETURN_ADDRESS (fp);
  1019. fp = SCM_FRAME_DYNAMIC_LINK (fp);
  1020. /* Push return values, and the number of values */
  1021. for (i = 0; i < nvalues; i++)
  1022. *++sp = vals[i+1];
  1023. *++sp = SCM_I_MAKINUM (nvalues);
  1024. /* Finally null the end of the stack */
  1025. NULLSTACK (vals + nvalues - sp);
  1026. }
  1027. else if (nvalues >= 1)
  1028. {
  1029. /* Multiple values for a single-valued continuation -- here's where I
  1030. break with guile tradition and try and do something sensible. (Also,
  1031. this block handles the single-valued return to an mv
  1032. continuation.) */
  1033. SCM *vals = sp - nvalues;
  1034. /* Restore registers */
  1035. sp = SCM_FRAME_LOWER_ADDRESS (fp) - 1;
  1036. ip = SCM_FRAME_RETURN_ADDRESS (fp);
  1037. fp = SCM_FRAME_DYNAMIC_LINK (fp);
  1038. /* Push first value */
  1039. *++sp = vals[1];
  1040. /* Finally null the end of the stack */
  1041. NULLSTACK (vals + nvalues - sp);
  1042. }
  1043. else
  1044. {
  1045. SYNC_ALL ();
  1046. vm_error_no_values ();
  1047. }
  1048. /* Restore the last program */
  1049. program = SCM_FRAME_PROGRAM (fp);
  1050. CACHE_PROGRAM ();
  1051. CHECK_IP ();
  1052. NEXT;
  1053. }
  1054. VM_DEFINE_INSTRUCTION (71, return_values_star, "return/values*", 1, -1, -1)
  1055. {
  1056. SCM l;
  1057. nvalues = FETCH ();
  1058. ASSERT (nvalues >= 1);
  1059. nvalues--;
  1060. POP (l);
  1061. while (scm_is_pair (l))
  1062. {
  1063. PUSH (SCM_CAR (l));
  1064. l = SCM_CDR (l);
  1065. nvalues++;
  1066. }
  1067. VM_ASSERT (SCM_NULL_OR_NIL_P (l), vm_error_improper_list (l));
  1068. goto vm_return_values;
  1069. }
  1070. VM_DEFINE_INSTRUCTION (72, return_nvalues, "return/nvalues", 0, 1, -1)
  1071. {
  1072. SCM n;
  1073. POP (n);
  1074. nvalues = scm_to_int (n);
  1075. ASSERT (nvalues >= 0);
  1076. goto vm_return_values;
  1077. }
  1078. VM_DEFINE_INSTRUCTION (73, truncate_values, "truncate-values", 2, -1, -1)
  1079. {
  1080. SCM x;
  1081. int nbinds, rest;
  1082. POP (x);
  1083. nvalues = scm_to_int (x);
  1084. nbinds = FETCH ();
  1085. rest = FETCH ();
  1086. if (rest)
  1087. nbinds--;
  1088. VM_ASSERT (nvalues >= nbinds, vm_error_not_enough_values ());
  1089. if (rest)
  1090. POP_LIST (nvalues - nbinds);
  1091. else
  1092. DROPN (nvalues - nbinds);
  1093. NEXT;
  1094. }
  1095. VM_DEFINE_INSTRUCTION (74, box, "box", 1, 1, 0)
  1096. {
  1097. SCM val;
  1098. POP (val);
  1099. SYNC_BEFORE_GC ();
  1100. LOCAL_SET (FETCH (), scm_cell (scm_tc7_variable, SCM_UNPACK (val)));
  1101. NEXT;
  1102. }
  1103. /* for letrec:
  1104. (let ((a *undef*) (b *undef*) ...)
  1105. (set! a (lambda () (b ...)))
  1106. ...)
  1107. */
  1108. VM_DEFINE_INSTRUCTION (75, empty_box, "empty-box", 1, 0, 0)
  1109. {
  1110. SYNC_BEFORE_GC ();
  1111. LOCAL_SET (FETCH (),
  1112. scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
  1113. NEXT;
  1114. }
  1115. VM_DEFINE_INSTRUCTION (76, local_boxed_ref, "local-boxed-ref", 1, 0, 1)
  1116. {
  1117. SCM v = LOCAL_REF (FETCH ());
  1118. ASSERT_BOUND_VARIABLE (v);
  1119. PUSH (VARIABLE_REF (v));
  1120. NEXT;
  1121. }
  1122. VM_DEFINE_INSTRUCTION (77, local_boxed_set, "local-boxed-set", 1, 1, 0)
  1123. {
  1124. SCM v, val;
  1125. v = LOCAL_REF (FETCH ());
  1126. POP (val);
  1127. ASSERT_VARIABLE (v);
  1128. VARIABLE_SET (v, val);
  1129. NEXT;
  1130. }
  1131. VM_DEFINE_INSTRUCTION (78, free_ref, "free-ref", 1, 0, 1)
  1132. {
  1133. scm_t_uint8 idx = FETCH ();
  1134. CHECK_FREE_VARIABLE (idx);
  1135. PUSH (FREE_VARIABLE_REF (idx));
  1136. NEXT;
  1137. }
  1138. /* no free-set -- if a var is assigned, it should be in a box */
  1139. VM_DEFINE_INSTRUCTION (79, free_boxed_ref, "free-boxed-ref", 1, 0, 1)
  1140. {
  1141. SCM v;
  1142. scm_t_uint8 idx = FETCH ();
  1143. CHECK_FREE_VARIABLE (idx);
  1144. v = FREE_VARIABLE_REF (idx);
  1145. ASSERT_BOUND_VARIABLE (v);
  1146. PUSH (VARIABLE_REF (v));
  1147. NEXT;
  1148. }
  1149. VM_DEFINE_INSTRUCTION (80, free_boxed_set, "free-boxed-set", 1, 1, 0)
  1150. {
  1151. SCM v, val;
  1152. scm_t_uint8 idx = FETCH ();
  1153. POP (val);
  1154. CHECK_FREE_VARIABLE (idx);
  1155. v = FREE_VARIABLE_REF (idx);
  1156. ASSERT_BOUND_VARIABLE (v);
  1157. VARIABLE_SET (v, val);
  1158. NEXT;
  1159. }
  1160. VM_DEFINE_INSTRUCTION (81, make_closure, "make-closure", 2, -1, 1)
  1161. {
  1162. size_t n, len;
  1163. SCM closure;
  1164. len = FETCH ();
  1165. len <<= 8;
  1166. len += FETCH ();
  1167. SYNC_BEFORE_GC ();
  1168. closure = scm_words (scm_tc7_program | (len<<16), len + 3);
  1169. SCM_SET_CELL_OBJECT_1 (closure, SCM_PROGRAM_OBJCODE (sp[-len]));
  1170. SCM_SET_CELL_OBJECT_2 (closure, SCM_PROGRAM_OBJTABLE (sp[-len]));
  1171. sp[-len] = closure;
  1172. for (n = 0; n < len; n++)
  1173. SCM_PROGRAM_FREE_VARIABLE_SET (closure, n, sp[-len + 1 + n]);
  1174. DROPN (len);
  1175. NEXT;
  1176. }
  1177. VM_DEFINE_INSTRUCTION (82, make_variable, "make-variable", 0, 0, 1)
  1178. {
  1179. SYNC_BEFORE_GC ();
  1180. /* fixme underflow */
  1181. PUSH (scm_cell (scm_tc7_variable, SCM_UNPACK (SCM_UNDEFINED)));
  1182. NEXT;
  1183. }
  1184. VM_DEFINE_INSTRUCTION (83, fix_closure, "fix-closure", 2, -1, 0)
  1185. {
  1186. SCM x;
  1187. unsigned int i = FETCH ();
  1188. size_t n, len;
  1189. i <<= 8;
  1190. i += FETCH ();
  1191. /* FIXME CHECK_LOCAL (i) */
  1192. x = LOCAL_REF (i);
  1193. /* FIXME ASSERT_PROGRAM (x); */
  1194. len = SCM_PROGRAM_NUM_FREE_VARIABLES (x);
  1195. for (n = 0; n < len; n++)
  1196. SCM_PROGRAM_FREE_VARIABLE_SET (x, n, sp[-len + 1 + n]);
  1197. DROPN (len);
  1198. NEXT;
  1199. }
  1200. VM_DEFINE_INSTRUCTION (84, define, "define", 0, 0, 2)
  1201. {
  1202. SCM sym, val;
  1203. POP2 (sym, val);
  1204. SYNC_REGISTER ();
  1205. scm_define (sym, val);
  1206. NEXT;
  1207. }
  1208. VM_DEFINE_INSTRUCTION (85, make_keyword, "make-keyword", 0, 1, 1)
  1209. {
  1210. CHECK_UNDERFLOW ();
  1211. SYNC_REGISTER ();
  1212. *sp = scm_symbol_to_keyword (*sp);
  1213. NEXT;
  1214. }
  1215. VM_DEFINE_INSTRUCTION (86, make_symbol, "make-symbol", 0, 1, 1)
  1216. {
  1217. CHECK_UNDERFLOW ();
  1218. SYNC_REGISTER ();
  1219. *sp = scm_string_to_symbol (*sp);
  1220. NEXT;
  1221. }
  1222. VM_DEFINE_INSTRUCTION (87, prompt, "prompt", 4, 2, 0)
  1223. {
  1224. scm_t_int32 offset;
  1225. scm_t_uint8 escape_only_p;
  1226. SCM k;
  1227. scm_t_dynstack_prompt_flags flags;
  1228. escape_only_p = FETCH ();
  1229. FETCH_OFFSET (offset);
  1230. POP (k);
  1231. SYNC_REGISTER ();
  1232. /* Push the prompt onto the dynamic stack. */
  1233. flags = escape_only_p ? SCM_F_DYNSTACK_PROMPT_ESCAPE_ONLY : 0;
  1234. scm_dynstack_push_prompt (&current_thread->dynstack, flags, k,
  1235. fp, sp, ip + offset, &registers);
  1236. NEXT;
  1237. }
  1238. VM_DEFINE_INSTRUCTION (88, wind, "wind", 0, 2, 0)
  1239. {
  1240. SCM wind, unwind;
  1241. POP2 (unwind, wind);
  1242. SYNC_REGISTER ();
  1243. /* Push wind and unwind procedures onto the dynamic stack. Note that neither
  1244. are actually called; the compiler should emit calls to wind and unwind for
  1245. the normal dynamic-wind control flow. Also note that the compiler
  1246. should have inserted checks that they wind and unwind procs are
  1247. thunks, if it could not prove that to be the case. */
  1248. scm_dynstack_push_dynwind (&current_thread->dynstack, wind, unwind);
  1249. NEXT;
  1250. }
  1251. VM_DEFINE_INSTRUCTION (89, abort, "abort", 1, -1, -1)
  1252. {
  1253. unsigned n = FETCH ();
  1254. SYNC_REGISTER ();
  1255. PRE_CHECK_UNDERFLOW (n + 2);
  1256. vm_abort (vm, n, &registers);
  1257. /* vm_abort should not return */
  1258. abort ();
  1259. }
  1260. VM_DEFINE_INSTRUCTION (90, unwind, "unwind", 0, 0, 0)
  1261. {
  1262. /* A normal exit from the dynamic extent of an expression. Pop the top entry
  1263. off of the dynamic stack. */
  1264. scm_dynstack_pop (&current_thread->dynstack);
  1265. NEXT;
  1266. }
  1267. VM_DEFINE_INSTRUCTION (91, push_fluid, "push-fluid", 0, 2, 0)
  1268. {
  1269. SCM fluid, val;
  1270. POP2 (val, fluid);
  1271. SYNC_REGISTER ();
  1272. scm_dynstack_push_fluid (&current_thread->dynstack, fluid, val,
  1273. current_thread->dynamic_state);
  1274. NEXT;
  1275. }
  1276. VM_DEFINE_INSTRUCTION (92, pop_fluid, "pop-fluid", 0, 0, 0)
  1277. {
  1278. /* This function must not allocate. */
  1279. scm_dynstack_unwind_fluid (&current_thread->dynstack,
  1280. current_thread->dynamic_state);
  1281. NEXT;
  1282. }
  1283. VM_DEFINE_INSTRUCTION (93, fluid_ref, "fluid-ref", 0, 1, 1)
  1284. {
  1285. size_t num;
  1286. SCM fluids;
  1287. CHECK_UNDERFLOW ();
  1288. fluids = SCM_I_DYNAMIC_STATE_FLUIDS (current_thread->dynamic_state);
  1289. if (SCM_UNLIKELY (!SCM_FLUID_P (*sp))
  1290. || ((num = SCM_I_FLUID_NUM (*sp)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
  1291. {
  1292. /* Punt dynstate expansion and error handling to the C proc. */
  1293. SYNC_REGISTER ();
  1294. *sp = scm_fluid_ref (*sp);
  1295. }
  1296. else
  1297. {
  1298. SCM val = SCM_SIMPLE_VECTOR_REF (fluids, num);
  1299. if (scm_is_eq (val, SCM_UNDEFINED))
  1300. val = SCM_I_FLUID_DEFAULT (*sp);
  1301. VM_ASSERT (!scm_is_eq (val, SCM_UNDEFINED),
  1302. vm_error_unbound_fluid (program, *sp));
  1303. *sp = val;
  1304. }
  1305. NEXT;
  1306. }
  1307. VM_DEFINE_INSTRUCTION (94, fluid_set, "fluid-set", 0, 2, 0)
  1308. {
  1309. size_t num;
  1310. SCM val, fluid, fluids;
  1311. POP2 (val, fluid);
  1312. fluids = SCM_I_DYNAMIC_STATE_FLUIDS (current_thread->dynamic_state);
  1313. if (SCM_UNLIKELY (!SCM_FLUID_P (fluid))
  1314. || ((num = SCM_I_FLUID_NUM (fluid)) >= SCM_SIMPLE_VECTOR_LENGTH (fluids)))
  1315. {
  1316. /* Punt dynstate expansion and error handling to the C proc. */
  1317. SYNC_REGISTER ();
  1318. scm_fluid_set_x (fluid, val);
  1319. }
  1320. else
  1321. SCM_SIMPLE_VECTOR_SET (fluids, num, val);
  1322. NEXT;
  1323. }
  1324. VM_DEFINE_INSTRUCTION (95, assert_nargs_ee_locals, "assert-nargs-ee/locals", 1, 0, 0)
  1325. {
  1326. scm_t_ptrdiff n;
  1327. SCM *old_sp;
  1328. /* nargs = n & 0x7, nlocs = nargs + (n >> 3) */
  1329. n = FETCH ();
  1330. VM_ASSERT (sp - (fp - 1) == (n & 0x7),
  1331. vm_error_wrong_num_args (program));
  1332. old_sp = sp;
  1333. sp += (n >> 3);
  1334. CHECK_OVERFLOW ();
  1335. while (old_sp < sp)
  1336. *++old_sp = SCM_UNDEFINED;
  1337. NEXT;
  1338. }
  1339. /* Like bind-optionals/shuffle, but if there are too many positional
  1340. arguments, jumps to the next case-lambda clause. */
  1341. VM_DEFINE_INSTRUCTION (96, bind_optionals_shuffle_or_br, "bind-optionals/shuffle-or-br", 9, -1, -1)
  1342. {
  1343. SCM *walk;
  1344. scm_t_ptrdiff nreq, nreq_and_opt, ntotal;
  1345. scm_t_int32 offset;
  1346. nreq = FETCH () << 8;
  1347. nreq += FETCH ();
  1348. nreq_and_opt = FETCH () << 8;
  1349. nreq_and_opt += FETCH ();
  1350. ntotal = FETCH () << 8;
  1351. ntotal += FETCH ();
  1352. FETCH_OFFSET (offset);
  1353. /* look in optionals for first keyword or last positional */
  1354. /* starting after the last required positional arg */
  1355. walk = fp + nreq;
  1356. while (/* while we have args */
  1357. walk <= sp
  1358. /* and we still have positionals to fill */
  1359. && walk - fp < nreq_and_opt
  1360. /* and we haven't reached a keyword yet */
  1361. && !scm_is_keyword (*walk))
  1362. /* bind this optional arg (by leaving it in place) */
  1363. walk++;
  1364. if (/* If we have filled all the positionals */
  1365. walk - fp == nreq_and_opt
  1366. /* and there are still more arguments */
  1367. && walk <= sp
  1368. /* and the next argument is not a keyword, */
  1369. && !scm_is_keyword (*walk))
  1370. {
  1371. /* Jump to the next case-lambda* clause. */
  1372. ip += offset;
  1373. }
  1374. else
  1375. {
  1376. /* Otherwise, finish as in bind-optionals/shuffle: shuffle up,
  1377. from walk to ntotal */
  1378. scm_t_ptrdiff nshuf = sp - walk + 1, i;
  1379. sp = (fp - 1) + ntotal + nshuf;
  1380. CHECK_OVERFLOW ();
  1381. for (i = 0; i < nshuf; i++)
  1382. sp[-i] = walk[nshuf-i-1];
  1383. /* and fill optionals & keyword args with SCM_UNDEFINED */
  1384. while (walk <= (fp - 1) + ntotal)
  1385. *walk++ = SCM_UNDEFINED;
  1386. }
  1387. NEXT;
  1388. }
  1389. /*
  1390. (defun renumber-ops ()
  1391. "start from top of buffer and renumber 'VM_DEFINE_FOO (\n' sequences"
  1392. (interactive "")
  1393. (save-excursion
  1394. (let ((counter -1)) (goto-char (point-min))
  1395. (while (re-search-forward "^VM_DEFINE_[^ ]+ (\\([^,]+\\)," (point-max) t)
  1396. (replace-match
  1397. (number-to-string (setq counter (1+ counter)))
  1398. t t nil 1)))))
  1399. (renumber-ops)
  1400. */
  1401. /*
  1402. Local Variables:
  1403. c-file-style: "gnu"
  1404. End:
  1405. */