2 * Global definitions for the LittleSmalltalk virtual machine
4 * ---------------------------------------------------------------
5 * Little Smalltalk, Version 5
7 * Copyright (C) 1987-2005 by Timothy A. Budd
8 * Copyright (C) 2007 by Charles R. Childers
9 * Copyright (C) 2005-2007 by Danny Reinhold
10 * Copyright (C) 2010 by Ketmar // Vampire Avalon
12 * ============================================================================
13 * This license applies to the virtual machine and to the initial image of
14 * the Little Smalltalk system and to all files in the Little Smalltalk
15 * packages except the files explicitly licensed with another license(s).
16 * ============================================================================
17 * Permission is hereby granted, free of charge, to any person obtaining a copy
18 * of this software and associated documentation files (the "Software"), to deal
19 * in the Software without restriction, including without limitation the rights
20 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21 * copies of the Software, and to permit persons to whom the Software is
22 * furnished to do so, subject to the following conditions:
24 * The above copyright notice and this permission notice shall be included in
25 * all copies or substantial portions of the Software.
27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
32 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
33 * DEALINGS IN THE SOFTWARE.
47 #define LST_IMAGE_VERSION 6
48 #define LST_IMAGE_SIGNATURE "LST5 Image File\x1a\x00"
50 #define LST_VERSION_STRING "Little Smalltalk version 5.2 (pre-beta)"
53 typedef uint32_t LstUInt
;
54 typedef int32_t LstInt
;
55 typedef int64_t LstLInt
;
56 typedef double LstFloat
;
59 #if defined(__MINGW32__) || defined(WINDOWS) || defined(WIN32) || defined(_WIN32)
60 # define LST_ON_WINDOWS 1
63 # define mkstemp mktemp
64 # define lstOSName "Windows"
68 # define lstOSName "GNU/Linux"
70 # define lstOSName "Unix"
75 extern unsigned int lstDebugFlag
; /* true if we are debugging */
77 extern unsigned int lstInfoCacheHit
;
78 extern unsigned int lstInfoCacheMiss
;
79 extern unsigned int lstInfoLiteralHit
;
80 extern unsigned int lstInfoIVarHit
;
82 extern unsigned int lstGCCount
;
85 /* symbolic definitions for the bytecodes */
87 lstBCExtended
, /* 0 */
88 lstBCPushInstance
, /* 1 */
89 lstBCPushArgument
, /* 2 */
90 lstBCPushTemporary
, /* 3 */
91 lstBCPushLiteral
, /* 4 */
92 lstBCPushConstant
, /* 5 */
93 lstBCAssignInstance
, /* 6 */
94 lstBCAssignArgument
, /* 7 */
95 lstBCAssignTemporary
, /* 8 */
96 lstBCMarkArguments
, /* 9 */
97 lstBCPushBlock
, /* 10 */
98 lstBCSendUnary
, /* 11 */
99 lstBCSendBinary
, /* 12 */
100 lstBCSendMessage
, /* 13 */
101 lstBCDoPrimitive
, /* 14 */
102 lstBCDoSpecial
/* 15 */
106 /* types of special instructions (opcode 15) */
108 lstBXBreakpoint
, /* 0 */
109 lstBXSelfReturn
, /* 1 */
110 lstBXStackReturn
, /* 2 */
111 lstBXBlockReturn
, /* 3 */
112 lstBXDuplicate
, /* 4 */
115 lstBXBranchIfTrue
, /* 7 */
116 lstBXBranchIfFalse
, /* 8 */
117 lstBXBranchIfNil
, /* 9 */
118 lstBXBranchIfNotNil
, /* 10 */
119 lstBXSendToSuper
, /* 11 */
120 lstBXThisContext
/* 12 */
124 /* special constants */
126 /* constants 0 to 9 are the integers 0 to 9 */
128 lstBLNilConst
, /* 0 */
129 lstBLTrueConst
, /* 1 */
130 lstBLFalseConst
/* 2 */
131 /* n-3: SmallInt constant */
135 /* Return values from doExecute: primitive */
137 lstReturnError
= 2, /* 2: error: called */
138 lstReturnBadMethod
, /* 3: Unknown method for object */
139 lstReturnReturned
, /* 4: Top level method returned */
140 lstReturnTimeExpired
, /* 5: Time quantum exhausted */
141 lstReturnBreak
, /* 6: lstBXBreakpoint instruction */
142 lstReturnYield
, /* 7: process yielded (can be continued) */
143 lstReturnAPISuspended
/* 8: suspended from C API; Smalltalk code will never see this */
147 /* The following are the objects with ``hard-wired'' field offsets */
149 /* A Process has two fields
150 * * a current context
151 * * status of process (running, waiting, etc)
154 lstIVcontextInProcess
,
155 lstIVstatusInProcess
,
156 lstIVresultInProcess
,
157 lstIVrunningInProcess
,
164 * * method (which has bytecode pointer)
165 * * bytecode offset (an integer)
167 * * temporaries and stack
171 lstIVmethodInContext
,
172 lstIVargumentsInContext
,
173 lstIVtemporariesInContext
,
175 lstIVbytePointerInContext
,
176 lstIVstackTopInContext
,
177 lstIVpreviousContextInContext
,
178 lstIVprocOwnerInContext
,
184 * A Block is subclassed from Context
185 * shares fields with creator, plus a couple new ones
188 lstIVmethodInBlock
= lstIVmethodInContext
,
189 lstIVargumentsInBlock
= lstIVargumentsInContext
,
190 lstIVtemporariesInBlock
= lstIVtemporariesInContext
,
191 lstIVstackInBlock
= lstIVstackInContext
,
192 lstIVstackTopInBlock
= lstIVstackTopInContext
,
193 lstIVpreviousContextInBlock
= lstIVpreviousContextInContext
,
194 lstIVprocOwnerInBlock
= lstIVprocOwnerInContext
,
195 lstIVargumentLocationInBlock
= lstContextSize
,
196 lstIVcreatingContextInBlock
,
197 /* the following are saved in different place so they don't get clobbered */
198 lstIVbytePointerInBlock
,
199 lstIVargCountInBlock
,
214 lstIVbyteCodesInMethod
,
215 lstIVliteralsInMethod
,
216 lstIVstackSizeInMethod
,
217 lstIVtemporarySizeInMethod
,
220 lstIVargCountInMethod
,
221 lstIVdebugInfoInMethod
,
222 lstIVargNamesInMethod
,
223 lstIVtempNamesInMethod
,
224 lstIVdbgDataInMethod
,
225 lstIVoptimDoneInMethod
,
227 lstIVcategoryInMethod
,
228 lstIVinvokeCountInMethod
,
235 * * pointer to parent class
236 * * pointer to tree of methods
240 lstIVparentClassInClass
,
242 lstIVinstanceSizeInClass
,
243 lstIVvariablesInClass
,
251 lstIVsymbolsInMetaSymbol
= lstClassSize
,
258 lstIVcharsInMetaChar
= lstClassSize
,
265 lstIVseedInMetaSmallInt
= lstClassSize
,
273 * * version (SmallInt)
274 * * requiremets (list of PackageRequirement objects)
277 lstIVclassesInPackage
, /* dictionary: symbol, class */
278 lstIVnameInPackage
, /* symbol */
279 lstIVversionInPackage
, /* smallint */
280 lstIVrequiresInPackage
, /* dictionary: symbol(pkgname), version(smallint)/nil(any) */
285 lstIVpackagesInMetaPackage
= lstClassSize
, /* dictionary: symbol, package instance */
286 lstIVcurrentInMetaPackage
,
291 /* PackageRequirement */
302 * A node in a tree has
315 /* misc iv defines */
318 lstIVreceiverInArguments
= 0,
323 * The fundamental data type is the object.
324 * The first field in an object is a size, the low order two
325 * bits being used to maintain:
326 * * binary flag, used if data is binary
327 * * indirection flag, used if object has been relocated
328 * The next data field is the class
329 * The following fields are either objects, or character values
331 * The initial image is loaded into static memory space --
332 * space which is never garbage collected
333 * This improves speed, as these items are not moved during GC
335 #define LST_OBJECT_HEADER \
337 lstObject *stclass; \
341 typedef struct lstObject lstObject
;
342 typedef struct LstFinLink LstFinLink
;
345 typedef void (*LstFinalizerFn
) (lstObject
*o
, void *udata
);
359 } __attribute__((__packed__
));
363 * byte objects are used to represent strings and symbols; bytes per word must be correct
365 typedef struct lstByteObject lstByteObject
;
366 struct lstByteObject
{
368 unsigned char bytes
[0];
369 } __attribute__((__packed__
));
372 #define LST_BYTES_PER_WORD (sizeof(lstObject *))
374 #define lstBytePtr(x) (((lstByteObject *)(x))->bytes)
378 * SmallInt objects are used to represent short integers.
379 * They are encoded as 31 bits, signed, with the low bit set to 1.
380 * This distinguishes them from all other objects, which are longword
381 * aligned and are proper C memory pointers.
384 # define LST_IS_SMALLINT(x) ((((int)(x)) & 0x01) != 0)
385 # define LST_FITS_SMALLINT(x) ((((int)(x)) >= INT_MIN/2) && (((int)(x)) <= INT_MAX/2))
386 # define LST_64FITS_SMALLINT(x) (((x) >= INT_MIN/2) && ((x) <= INT_MAX/2))
388 # define LST_IS_SMALLINT(x) ((((intptr_t)(x)) & 0x01) != 0)
389 # define LST_FITS_SMALLINT(x) ((((int)(x)) >= (-(__INT_MAX__))/2) && (((int)(x)) <= __INT_MAX__/2))
390 # define LST_64FITS_SMALLINT(x) (((x) >= (-(__INT_MAX__))/2) && ((x) <= __INT_MAX__/2))
392 #define LST_CLASS(x) (LST_IS_SMALLINT(x) ? lstSmallIntClass : ((x)->stclass))
395 * The "size" field is the top 30 bits; the bottom two are flags
397 #define LST_SIZE(op) ((op)->size >> 2)
398 #define LST_SETSIZE(op, val) ((op)->size = ((val) << 2))
399 #define LST_FLAG_GC_BHEART (0x01)
400 #define LST_FLAG_BIN (0x02)
401 #define LST_IS_BYTES(x) (((x)->size&LST_FLAG_BIN) != 0)
402 static inline int LST_IS_BYTES_EX (lstObject
*x
) { return !LST_IS_SMALLINT(x
) && LST_IS_BYTES(x
); }
406 * roots for the memory space
407 * these are traced down during memory management
408 * lstRootStack is the dynamic stack
409 * staticRoots are values in static memory that point to
412 #define LST_ROOTSTACK_LIMIT 550
413 extern lstObject
*lstRootStack
[];
414 extern LstUInt lstRootTop
;
415 extern void lstAddStaticRoot (lstObject
**);
418 #define LST_MAX_BIN_MSG 14
419 /* The following are roots for the file out */
420 extern lstObject
*lstNilObj
;
421 extern lstObject
*lstTrueObj
;
422 extern lstObject
*lstFalseObj
;
423 extern lstObject
*lstBooleanClass
;
424 extern lstObject
*lstSmallIntClass
;
425 extern lstObject
*lstCharClass
;
426 extern lstObject
*lstArrayClass
;
427 extern lstObject
*lstBlockClass
;
428 extern lstObject
*lstContextClass
;
429 extern lstObject
*lstProcessClass
;
430 extern lstObject
*lstStringClass
;
431 extern lstObject
*lstSymbolClass
;
432 extern lstObject
*lstByteArrayClass
;
433 extern lstObject
*lstByteCodeClass
;
434 extern lstObject
*lstMethodClass
;
435 extern lstObject
*lstGlobalObj
;
436 extern lstObject
*lstBinMsgs
[LST_MAX_BIN_MSG
]; /* '<'; '<='; '+', ... */
437 extern lstObject
*lstIntegerClass
;
438 extern lstObject
*lstFloatClass
;
439 extern lstObject
*lstBadMethodSym
; /* 'doesNotUnderstand:' */
440 /* Smalltalk entry points */
441 extern lstObject
*lstInitMethod
;
442 extern lstObject
*lstLoadMethod
;
443 extern lstObject
*lstDoStrMethod
;
444 extern lstObject
*lstReplMethod
;
445 extern lstObject
*lstNewSymMethod
;
446 extern lstObject
*lstSetGlobMethod
;
449 /* must be defined by the main program */
450 extern void lstFatal (const char *a
, unsigned int b
);
451 extern void lstBackTrace (lstObject
*aContext
);
455 extern void lstMemoryInit (int staticsz
, int dynamicsz
);
456 extern void lstMemoryDeinit (void);
458 extern int lstReadImage (FILE *fp
);
459 extern int lstWriteImage (FILE *fp
, int noSrc
);
461 extern void lstGC (void);
462 extern void lstShowCalledMethods (void);
464 extern lstObject
*lstStaticAlloc (int sz
);
465 extern lstByteObject
*lstStaticAllocBin (int sz
);
466 extern lstObject
*lstMemAlloc (int sz
);
467 extern lstByteObject
*lstMemAllocBin (int sz
);
469 /* internal functions for interpreter */
470 extern void lstSwapObjects (lstObject
*array1
, lstObject
*array2
, LstUInt size
);
471 extern int lstBulkReplace (lstObject
*dest
, lstObject
*start
, lstObject
*stop
, lstObject
*src
, lstObject
*repStart
);
473 /* do write, register static root if necessary */
474 extern void lstWriteBarrier (lstObject
**dest
, lstObject
*src
);
477 typedef lstObject
*(*LSTPrimitiveFn
) (int primitiveNumber
, lstObject
**args
, int argc
); /* return NULL if failed (not lstNilObj!) */
478 typedef void (*LSTPrimitiveClearFn
) (int primitiveNumber
);
480 extern const char *lstFindPrimitiveName (int idx
);
481 extern int lstFindPrimitiveIdx (const char *name
); /* -1: no such primitive */
483 extern int lstFindExtPrimitiveByName (const char *name
);
484 extern int lstRegisterExtPrimitive (const char *name
, LSTPrimitiveFn pfn
, LSTPrimitiveClearFn cfn
); /* -1: error; other: primitive index */
485 extern void lstClearExtPrimitives (void);
487 extern LSTPrimitiveFn
lstFindExtPrimitiveFn (int idx
);
489 extern void lstPrimitivesClear (void);
495 LSTPrimitiveClearFn cfn
;
496 } LSTExtPrimitiveTable
;
498 extern int lstRegisterExtPrimitiveTable (const LSTExtPrimitiveTable
*tbl
); /* return success flag */
502 #define lstIntValue(x) ((int)(((intptr_t)(x)) >> 1))
503 #define lstNewInt(x) ((lstObject *)((((intptr_t)(x)) << 1) | 0x01))
505 extern lstObject
*lstNewLongInt (LstLInt val
); /* create new Integer (64-bit) */
506 extern lstObject
*lstNewFloat (LstFloat val
);
508 #define lstNewInteger(x) (LST_64FITS_SMALLINT(x) ? lstNewInt(x) : lstNewLongInt(x))
510 static inline LstLInt
lstLIntValue (const lstObject
*o
) {
511 const LstLInt
*v
= (const LstLInt
*)o
->data
;
514 static inline LstFloat
lstFloatValue (const lstObject
*o
) {
515 const LstFloat
*v
= (const LstFloat
*)o
->data
;
519 #define lstLIntValue(o) (*((LstLInt *)lstConstPtr(o)))
520 #define lstFloatValue(o) (*((LstFloat *)lstConstPtr(o)))
523 extern lstObject
*lstNewString (const char *str
);
524 extern int lstGetString (char *buf
, int bufsize
, const lstObject
*str
); /* return 0 on ok or necessary buffer size */
525 extern lstObject
*lstNewBinary (const void *p
, LstUInt l
);
526 extern lstObject
*lstNewBCode (const void *p
, LstUInt l
);
527 extern lstObject
*lstNewArray (int size
);
529 extern lstObject
*lstAllocInstance (int size
, lstObject
*cl
);
531 extern lstObject
*lstDictFind (const lstObject
*dict
, const char *name
);
533 /* WARNING: this works only when obj is instance of something, and aclass is not! */
534 extern int lstIsKindOf (const lstObject
*obj
, const lstObject
*aclass
); /* returns true(!0) or false(0) */
536 extern lstObject
*lstFindGlobal (const char *name
);
538 /* WARNING: CAN'T BE CALLED FROM PRIMITIVE! */
539 extern lstObject
*lstNewSymbol (const char *name
);
541 /* WARNING: CAN'T BE CALLED FROM PRIMITIVE! */
542 extern int lstSetGlobal (const char *name
, lstObject
*val
);
544 extern lstObject
*lstFindMethod (lstObject
*stclass
, const char *method
);
546 extern void lstSetFinalizer (lstObject
*o
, LstFinalizerFn fn
, void *udata
);
547 extern void *lstGetUData (lstObject
*o
);
549 /* both returns lstReturnXXX */
550 extern int lstExecute (lstObject
*aProcess
, int ticks
, int locked
);
551 extern int lstResume (void);
552 extern int lstCanResume (void);
553 extern void lstResetResume (void);
555 /* arg==NULL: no argument
556 * result==NULL: don't need result
557 * remember, that result can be collected by GC on next allocation
559 extern int lstRunMethodWithArg (lstObject
*method
, lstObject
*inClass
, lstObject
*arg
, lstObject
**result
, int locked
);
562 /* types in image file */
574 extern void lstFlushMethodCache (void);
577 extern unsigned int lstImgReadWord (FILE *fp
);
578 extern void lstImgWriteWord (FILE *fp
, int i
);
580 extern int32_t lstImgReadDWord (FILE *fp
);
581 extern void lstImgWriteDWord (FILE *fp
, int32_t i
);
584 #define LST_FINALIZER(name) \
585 static void name (lstObject *obj, void *udata)
587 /* macro for primitives */
588 #define LST_PRIMFN(name) \
589 static lstObject *name (int primitiveNumber, lstObject **args, int argc)
591 #define LST_PRIMFN_NONSTATIC(name) \
592 lstObject *name (int primitiveNumber, lstObject **args, int argc)
594 #define LST_PRIMCLEARFN(name) \
595 static void name (int primitiveNumber)
597 #define LST_PRIMARGC (argc)
598 #define LST_PRIMARG(n) (args[n])
601 static inline void lstRootPush (lstObject
*o
) {
602 if (lstRootTop
>= LST_ROOTSTACK_LIMIT
) lstFatal("out of root stack", 0);
603 lstRootStack
[lstRootTop
++] = o
;
607 static inline lstObject
*lstRootPop (void) {
608 if (lstRootTop
< 1) lstFatal("root stack underflow", 0);
609 return lstRootStack
[--lstRootTop
];
613 #define LST_TS_LIMIT 512
614 extern lstObject
**lstTempStack
[LST_TS_LIMIT
];
615 extern int lstTempSP
;
617 #define LST_ENTER_BLOCK() int _lstCurTSP_ = lstTempSP
618 #define LST_LEAVE_BLOCK() lstTempSP = _lstCurTSP_
620 #define LST_NEW_TEMP(name) lstObject *name = NULL; lstTempStack[lstTempSP++] = &name
621 #define LST_TEMP(name) lstTempStack[lstTempSP++] = &name
624 typedef int (*LstEventCheckFn
) (int *ticksLeft
);
625 /* this must return eid (!0) to call callback */
626 extern LstEventCheckFn lstEventCheck
;
628 extern int lstEvtCheckLeft
; /* # of executed instructions before event check */
630 extern int lstExecUserBreak
; /* set this to non-zero to suspend current lstExecute() and return lstReturnAPISuspended */