1 /******************************** -*- C -*- ****************************
2 *
3 * Byte code array utility routines.
4 *
5 *
6 ***********************************************************************/
7
8 /***********************************************************************
9 *
10 * Copyright 1988,89,90,91,92,94,95,99,2000,2001,2002,2003,2006,2008,2009
11 * Free Software Foundation, Inc.
12 * Written by Steve Byrne.
13 *
14 * This file is part of GNU Smalltalk.
15 *
16 * GNU Smalltalk is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the Free
18 * Software Foundation; either version 2, or (at your option) any later
19 * version.
20 *
21 * Linking GNU Smalltalk statically or dynamically with other modules is
22 * making a combined work based on GNU Smalltalk. Thus, the terms and
23 * conditions of the GNU General Public License cover the whole
24 * combination.
25 *
26 * In addition, as a special exception, the Free Software Foundation
27 * give you permission to combine GNU Smalltalk with free software
28 * programs or libraries that are released under the GNU LGPL and with
29 * independent programs running under the GNU Smalltalk virtual machine.
30 *
31 * You may copy and distribute such a system following the terms of the
32 * GNU GPL for GNU Smalltalk and the licenses of the other code
33 * concerned, provided that you include the source code of that other
34 * code when and as the GNU GPL requires distribution of source code.
35 *
36 * Note that people who make modified versions of GNU Smalltalk are not
37 * obligated to grant this special exception for their modified
38 * versions; it is their choice whether to do so. The GNU General
39 * Public License gives permission to release a modified version without
40 * this exception; this exception also makes it possible to release a
41 * modified version which carries forward this exception.
42 *
43 * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
44 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
46 * more details.
47 *
48 * You should have received a copy of the GNU General Public License along with
49 * GNU Smalltalk; see the file COPYING. If not, write to the Free Software
50 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
51 *
52 ***********************************************************************/
53
54 #include "gstpriv.h"
55 #include "match.h"
56
57 #define BYTECODE_CHUNK_SIZE 64
58
59 /* Where the compiled bytecodes go. */
60 bc_vector _gst_cur_bytecodes;
61
62 /* Reallocate an array of bytecodes, leaving space for DELTA more
63 bytes. */
64 static void realloc_bytecodes (bc_vector bytecodes,
65 int delta);
66
67
68
69
70 bc_vector
_gst_extract_bytecodes(OOP byteArrayOOP)71 _gst_extract_bytecodes (OOP byteArrayOOP)
72 {
73 bc_vector result;
74 int len;
75 gst_byte_array byteArray;
76
77 byteArray = (gst_byte_array) OOP_TO_OBJ (byteArrayOOP);
78 len = oop_num_fields (byteArrayOOP);
79 result = (bc_vector) xmalloc (sizeof (struct bytecode_array));
80
81 result->base = (gst_uchar *) xmalloc (len);
82 result->ptr = result->base + len;
83 result->maxLen = len;
84 memcpy (result->base, byteArray->bytes, len);
85 return (result);
86 }
87
88 static int next_line_number;
89
90 static void
compile_byte(gst_uchar byte,int arg)91 compile_byte (gst_uchar byte, int arg)
92 {
93 int num_bytes;
94 long n;
95
96 for (num_bytes = 2, n = arg; n > 255; n >>= 8)
97 num_bytes += 2;
98
99 assert (_gst_cur_bytecodes);
100
101 if ((_gst_cur_bytecodes->ptr - _gst_cur_bytecodes->base) >
102 _gst_cur_bytecodes->maxLen - num_bytes)
103
104 realloc_bytecodes (_gst_cur_bytecodes, BYTECODE_CHUNK_SIZE);
105
106
107 while (num_bytes > 2)
108 {
109 num_bytes -= 2;
110 *_gst_cur_bytecodes->ptr++ = EXT_BYTE;
111 *_gst_cur_bytecodes->ptr++ = (arg >> (num_bytes * 4)) & 255;
112 }
113
114 *_gst_cur_bytecodes->ptr++ = byte;
115 *_gst_cur_bytecodes->ptr++ = arg & 255;
116 }
117
118 void
_gst_line_number(int n,int flags)119 _gst_line_number (int n, int flags)
120 {
121 static int prev_line;
122 static int line_offset;
123
124 if (n > 65535)
125 n = 65535;
126
127 if (flags & LN_RESET)
128 {
129 assert (!(flags & LN_FORCE));
130 assert (n > 0);
131 if (flags & LN_ABSOLUTE)
132 {
133 compile_byte (LINE_NUMBER_BYTECODE, n);
134 prev_line = n;
135 }
136 line_offset = n - 1;
137 next_line_number = -1;
138 }
139 else
140 {
141 assert (!(flags & LN_ABSOLUTE));
142 if (n == -1)
143 {
144 prev_line = -1;
145 next_line_number = -1;
146 }
147 else
148 {
149 assert (n > line_offset);
150 if ((flags & LN_FORCE) || n != prev_line)
151 {
152 prev_line = n;
153 next_line_number = n - line_offset;
154 }
155 }
156 }
157 }
158
159 void
_gst_compile_byte(gst_uchar byte,int arg)160 _gst_compile_byte (gst_uchar byte, int arg)
161 {
162 if (next_line_number != -1)
163 {
164 compile_byte (LINE_NUMBER_BYTECODE, next_line_number);
165 next_line_number = -1;
166 }
167
168 compile_byte (byte, arg);
169 }
170
171 void
_gst_free_bytecodes(bc_vector bytecodes)172 _gst_free_bytecodes (bc_vector bytecodes)
173 {
174 if (bytecodes != NULL)
175 {
176 xfree (bytecodes->base);
177 xfree (bytecodes);
178 }
179 }
180
181 void
_gst_compile_and_free_bytecodes(bc_vector bytecodes)182 _gst_compile_and_free_bytecodes (bc_vector bytecodes)
183 {
184 _gst_compile_bytecodes (bytecodes->base, bytecodes->ptr);
185
186 /* First add the worst case, then leave the net effect. */
187 ADD_STACK_DEPTH (bytecodes->max_stack_depth);
188 SUB_STACK_DEPTH (bytecodes->max_stack_depth - bytecodes->stack_depth);
189
190 _gst_free_bytecodes (bytecodes);
191 }
192
193 bc_vector
_gst_get_bytecodes(void)194 _gst_get_bytecodes (void)
195 {
196 bc_vector curBytecodes;
197
198 curBytecodes = _gst_cur_bytecodes;
199 _gst_cur_bytecodes = NULL;
200
201 return (curBytecodes);
202 }
203
204
205 bc_vector
_gst_save_bytecode_array()206 _gst_save_bytecode_array ()
207 {
208 bc_vector curBytecodes;
209
210 curBytecodes = _gst_cur_bytecodes;
211 _gst_alloc_bytecodes ();
212
213 return (curBytecodes);
214 }
215
216
217 void
_gst_restore_bytecode_array(bc_vector bytecodes)218 _gst_restore_bytecode_array (bc_vector bytecodes)
219 {
220 _gst_cur_bytecodes = bytecodes;
221 }
222
223 int
_gst_bytecode_length(bc_vector bytecodes)224 _gst_bytecode_length (bc_vector bytecodes)
225 {
226 if (bytecodes == NULL)
227 return (0);
228
229 return (bytecodes->ptr - bytecodes->base);
230 }
231
232
233 int
_gst_current_bytecode_length(void)234 _gst_current_bytecode_length (void)
235 {
236 if (_gst_cur_bytecodes == NULL)
237 return (0);
238
239 return (_gst_cur_bytecodes->ptr - _gst_cur_bytecodes->base);
240 }
241
242 void
_gst_copy_bytecodes(gst_uchar * dest,bc_vector bytecodes)243 _gst_copy_bytecodes (gst_uchar * dest,
244 bc_vector bytecodes)
245 {
246 memcpy (dest, bytecodes->base, _gst_bytecode_length (bytecodes));
247 }
248
249 void
_gst_truncate_bytecodes(gst_uchar * here,bc_vector bytecodes)250 _gst_truncate_bytecodes (gst_uchar * here,
251 bc_vector bytecodes)
252 {
253 bytecodes->ptr = here;
254 }
255
256
257
258 void
_gst_print_bytecodes(bc_vector bytecodes,OOP * literal_vec)259 _gst_print_bytecodes (bc_vector bytecodes,
260 OOP * literal_vec)
261 {
262 gst_uchar *b;
263 int ip;
264
265 if (bytecodes == NULL)
266 return;
267
268 for (b = bytecodes->base; b < bytecodes->ptr; )
269 {
270 ip = b - bytecodes->base;
271 printf ("%5d:", ip);
272 b = _gst_print_bytecode_name (b, ip, literal_vec, "");
273 }
274 printf ("\n");
275 }
276
277 gst_uchar *
_gst_print_bytecode_name(gst_uchar * bp,int ip,OOP * literal_vec,const char * pref)278 _gst_print_bytecode_name (gst_uchar * bp,
279 int ip,
280 OOP * literal_vec,
281 const char *pref)
282 {
283 const char *prefix = "";
284 gst_uchar b = *bp;
285
286 MATCH_BYTECODES (PRINT_BYTECODE_NAME, bp, (
287 PUSH_RECEIVER_VARIABLE {
288 printf ("%s\tpush Instance Variable[%d]\n", prefix, n);
289 prefix = pref;
290 }
291
292 PUSH_TEMPORARY_VARIABLE {
293 printf ("%s\tpush Temporary Variable[%d]\n", prefix, n);
294 prefix = pref;
295 }
296
297 PUSH_LIT_CONSTANT {
298 printf ("%s\tpush Literal[%d]", prefix, n);
299 if (literal_vec)
300 printf (" = %O", literal_vec[n]);
301 printf ("\n");
302 prefix = pref;
303 }
304
305 PUSH_LIT_VARIABLE {
306 printf ("%s\tpush Global Variable[%d]", prefix, n);
307 if (literal_vec)
308 printf (" = %+O", literal_vec[n]);
309 printf ("\n");
310 prefix = pref;
311 }
312
313 PUSH_SELF {
314 printf ("%s\tpush self\n", prefix);
315 prefix = pref;
316 }
317 PUSH_SPECIAL {
318 switch (n) {
319 case TRUE_INDEX: printf ("%s\tpush true\n", prefix); break;
320 case FALSE_INDEX: printf ("%s\tpush false\n", prefix); break;
321 case NIL_INDEX: printf ("%s\tpush nil\n", prefix); break;
322 }
323 prefix = pref;
324 }
325 PUSH_INTEGER {
326 printf ("%s\tpush %d\n", prefix, n);
327 prefix = pref;
328 }
329
330 RETURN_METHOD_STACK_TOP {
331 printf ("%s\treturn explicitly from method\n", prefix);
332 prefix = pref;
333 }
334 RETURN_CONTEXT_STACK_TOP {
335 printf ("%s\treturn stack top\n", prefix);
336 prefix = pref;
337 }
338
339 LINE_NUMBER_BYTECODE {
340 printf ("%s\tsource line %d\n", prefix, n);
341 prefix = pref;
342 }
343
344 STORE_RECEIVER_VARIABLE {
345 printf ("%s\tstore into Instance Variable[%d]\n", prefix, n);
346 prefix = pref;
347 }
348 STORE_TEMPORARY_VARIABLE {
349 printf ("%s\tstore into Temporary Variable[%d]\n", prefix, n);
350 prefix = pref;
351 }
352 STORE_LIT_VARIABLE {
353 printf ("%s\tstore into Global Variable[%d]", prefix, n);
354 if (literal_vec)
355 printf (" = %+O", literal_vec[n]);
356 printf ("\n");
357 prefix = pref;
358 }
359
360 SEND {
361 printf ("%s\tsend selector %d%s, %d args", prefix, n, super ? " to super" : "", num_args);
362 if (literal_vec)
363 printf (" = %O", literal_vec[n]);
364 printf ("\n");
365 prefix = pref;
366 }
367
368 POP_INTO_NEW_STACKTOP {
369 printf ("%s\tpop and store into Instance Variable[%d] of new stack top\n", prefix, n);
370 prefix = pref;
371 }
372
373 POP_STACK_TOP {
374 printf ("%s\tpop stack top\n", prefix);
375 prefix = pref;
376 }
377 DUP_STACK_TOP {
378 printf ("%s\tduplicate stack top\n", prefix);
379 prefix = pref;
380 }
381
382 PUSH_OUTER_TEMP {
383 printf ("%s\tpush outer var scopes = %d varIndex = %d\n", prefix, scopes, n);
384 prefix = pref;
385 }
386 STORE_OUTER_TEMP {
387 printf ("%s\tstore outer var scopes = %d varIndex = %d\n", prefix, scopes, n);
388 prefix = pref;
389 }
390
391 EXIT_INTERPRETER {
392 printf ("%s\tterminate interpreter\n", prefix);
393 prefix = pref;
394 }
395
396 JUMP {
397 printf ("%s\tjump to %d\n", prefix, ip + ofs);
398 prefix = pref;
399 }
400 POP_JUMP_TRUE {
401 printf ("%s\tpop and jump to %d if true\n", prefix, ip + ofs);
402 prefix = pref;
403 }
404 POP_JUMP_FALSE {
405 printf ("%s\tpop and jump to %d if false\n", prefix, ip + ofs);
406 prefix = pref;
407 }
408
409 SEND_ARITH {
410 printf ("%s\tsend arithmetic message %O\n", prefix,
411 _gst_builtin_selectors[n].symbol);
412 prefix = pref;
413 }
414 SEND_SPECIAL {
415 printf ("%s\tsend special message %O\n", prefix,
416 _gst_builtin_selectors[n + 16].symbol);
417 prefix = pref;
418 }
419
420 MAKE_DIRTY_BLOCK {
421 printf ("%s\tmake dirty block\n", prefix);
422 prefix = pref;
423 }
424
425 SEND_IMMEDIATE {
426 printf ("%s\tsend special message %O%s\n", prefix,
427 _gst_builtin_selectors[n].symbol,
428 super ? " to super" : "");
429 prefix = pref;
430 }
431
432 INVALID {
433 printf ("%s\tINVALID BYTECODE %d(%d)\n", prefix, b, arg);
434 prefix = pref;
435 }
436 ));
437 return bp;
438 }
439
440 void
_gst_compile_bytecodes(gst_uchar * from,gst_uchar * to)441 _gst_compile_bytecodes (gst_uchar * from,
442 gst_uchar * to)
443 {
444 int free;
445 assert (_gst_cur_bytecodes);
446
447 free = _gst_cur_bytecodes->maxLen -
448 (_gst_cur_bytecodes->ptr - _gst_cur_bytecodes->base);
449
450 if (free < (to - from))
451 {
452 memcpy (_gst_cur_bytecodes->ptr, from, free);
453 _gst_cur_bytecodes->ptr += free;
454 from += free;
455 realloc_bytecodes (_gst_cur_bytecodes,
456 BYTECODE_CHUNK_SIZE + (to - from));
457 }
458
459 memcpy (_gst_cur_bytecodes->ptr, from, to - from);
460 _gst_cur_bytecodes->ptr += to - from;
461 }
462
463 void
_gst_alloc_bytecodes()464 _gst_alloc_bytecodes ()
465 {
466 bc_vector newBytecodes;
467
468 newBytecodes = (bc_vector) xmalloc (sizeof (struct bytecode_array));
469 newBytecodes->base = (gst_uchar *) xmalloc (BYTECODE_CHUNK_SIZE);
470 newBytecodes->ptr = newBytecodes->base;
471 newBytecodes->maxLen = BYTECODE_CHUNK_SIZE;
472
473 newBytecodes->stack_depth = 0;
474 newBytecodes->max_stack_depth = 0;
475
476 _gst_cur_bytecodes = newBytecodes;
477 }
478
479 void
realloc_bytecodes(bc_vector bytecodes,int delta)480 realloc_bytecodes (bc_vector bytecodes,
481 int delta)
482 {
483 int size;
484
485 size = bytecodes->ptr - bytecodes->base;
486
487 bytecodes->base =
488 (gst_uchar *) xrealloc (bytecodes->base, bytecodes->maxLen + delta);
489 bytecodes->ptr = bytecodes->base + size;
490 bytecodes->maxLen += delta;
491 }
492