home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
- *
- * Byte code array utility routines.
- *
- ***********************************************************************/
-
- /***********************************************************************
- *
- * Copyright (C) 1990, 1991 Free Software Foundation, Inc.
- * Written by Steve Byrne.
- *
- * This file is part of GNU Smalltalk.
- *
- * GNU Smalltalk is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 1, or (at your option) any later
- * version.
- *
- * GNU Smalltalk is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * GNU Smalltalk; see the file COPYING. If not, write to the Free Software
- * Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ***********************************************************************/
-
-
- /*
- * Change Log
- * ============================================================================
- * Author Date Change
- * sbyrne 20 Apr 90 Added initByteCodes to fix a robustness issue with
- * the compiler.
- *
- * sbyrne 27 Dec 88 created.
- *
- */
-
- #include "mst.h"
- #include "mstbyte.h"
-
- #define BYTE_CODE_CHUNK_SIZE 64
-
- struct ByteCodeArray {
- Byte *base; /* base of the byte code array */
- Byte *ptr; /* current byte+1 of byte code array */
- int maxLen; /* max allocated len of byte code array
- can be changed as byte code array grows,
- and is used to tell when to grow the byte
- code array. */
- };
-
- ByteCodes currentByteCodes = nil;
-
- static ByteCodes allocByteCodes();
- static void compileByteCodes(), reallocByteCodes();
-
-
- /* These are used to decode special send byte codes. */
- static char *mathMessageName[] = {
- "+",
- "-",
- "<",
- ">",
- "<=",
- ">=",
- "=",
- "~=",
- "*",
- "/",
- "\\",
- "@",
- "bitShift:",
- "//",
- "bitAnd:",
- "bitOr:"
- };
-
- /* These are the selectors for special case send bytecodes that the compiler
- generates. These are used only to print out the generated byte codes. */
- static char *specialMessageName[] = {
- "at:",
- "at:put:",
- "size",
- "next",
- "nextPut:",
- "atEnd",
- "==",
- "class",
- "blockCopy:",
- "value",
- "value:",
- "do:",
- "new",
- "new:",
- "x",
- "y"
- };
-
- void compileByte(byte)
- Byte byte;
- {
- if (currentByteCodes == nil) {
- currentByteCodes = allocByteCodes();
- }
-
- if ((currentByteCodes->ptr - currentByteCodes->base)
- >= currentByteCodes->maxLen) {
- reallocByteCodes(currentByteCodes);
- }
-
- *currentByteCodes->ptr++ = byte;
- }
-
- void compileAndFreeByteCodes(byteCodes)
- ByteCodes byteCodes;
- {
- compileByteCodes(byteCodes);
- freeByteCodes(byteCodes);
- }
-
- /*
- * void initByteCodes()
- *
- * Description
- *
- * Initialize the byte code system. Basically used to set the byte code
- * system to a known state, typically in preparation for compilation.
- *
- */
- void initByteCodes()
- {
- if (currentByteCodes) {
- free(currentByteCodes); /* ??? this might lose if trashed. */
- currentByteCodes = nil;
- }
- }
-
- /*
- * ByteCodes getByteCodes()
- *
- * Description
- *
- * Called when byte code compilation is complete, this routine returns the
- * set of byte codes that were compiled. Since compilation is complete,
- * this routine also resets the internal state of the byte code compiler
- * in preparation for next time.
- *
- * Outputs
- *
- * A pointer to a byte code array that contains the bytes for the current
- * compilation.
- */
- ByteCodes getByteCodes()
- {
- ByteCodes curByteCodes;
-
- curByteCodes = currentByteCodes;
- currentByteCodes = nil;
-
- return (curByteCodes);
- }
-
-
- /*
- * ByteCodes saveByteCodeArray()
- *
- * Description
- *
- * Called to save the set of byte codes currently being compiled and
- * prepare for a new compilation of byte codes. The current set of byte
- * codes being compiled is returned for the caller to keep and to later
- * use in a restoreByteCodeArray call.
- *
- * Outputs
- *
- * A byte code array pointer to the current byte codes.
- */
- ByteCodes saveByteCodeArray()
- {
- ByteCodes curByteCodes;
-
- curByteCodes = currentByteCodes;
- currentByteCodes = nil;
-
- return (curByteCodes);
- }
-
-
- /*
- * void restoreByteCodeArray(byteCodes)
- *
- * Description
- *
- * Restores the internal state of the byte code compiler so that it can
- * continue compiling byte codes into the byte code array "byteCodes",
- * which should have been returned at some previous point from
- * saveByteCodeArray().
- *
- * Inputs
- *
- * byteCodes:
- * The byte code array pointer to be restored. Should have come
- * from a saveByteCodeArray call.
- *
- */
- void restoreByteCodeArray(byteCodes)
- ByteCodes byteCodes;
- {
- currentByteCodes = byteCodes;
- }
-
- int byteCodeLength(byteCodes)
- ByteCodes byteCodes;
- {
- return (byteCodes->ptr - byteCodes->base);
- }
-
-
- /*
- * int currentByteCodeLength()
- *
- * Description
- *
- * Return the current number of byte codes that have been compiled.
- *
- * Outputs
- *
- * Number of byte codes present in the current byte code array right now.
- */
- int currentByteCodeLength()
- {
- if (currentByteCodes == nil) {
- return (0);
- }
-
- return (currentByteCodes->ptr - currentByteCodes->base);
- }
-
- int isSimpleReturn(byteCodes)
- ByteCodes byteCodes;
- {
- Byte *bytes;
- long byteCodeLen;
-
- if (byteCodes == nil) {
- return (0);
- }
-
- byteCodeLen = byteCodeLength(byteCodes);
- bytes = byteCodes->base;
-
- /* check for ^self */
- if (byteCodeLen == 1 && bytes[0] == (returnIndexed | receiverIndex)) {
- return (1);
- }
-
- /* check for ^instanceVariable */
- if (byteCodeLen == 2) {
- if ((bytes[0] & ~0x0F) == pushReceiverVariable
- && bytes[1] == returnMethodStackTop) {
- return (((bytes[0] & 0x0F) << 8) | 2);
- }
- } else if (byteCodeLen == 3) {
- if (bytes[0] == pushIndexed
- && (bytes[1] & locationMask) == receiverLocation
- && bytes[2] == returnMethodStackTop) {
- return (((bytes[1] & ~locationMask) << 8) | 2);
- }
- }
-
- return (0);
- }
-
- void copyByteCodes(dest, byteCodes)
- Byte *dest;
- ByteCodes byteCodes;
- {
- memcpy(dest, byteCodes->base, byteCodeLength(byteCodes));
- }
-
- /***********************************************************************
- *
- * Internal routines.
- *
- ***********************************************************************/
-
- static void compileByteCodes(byteCodes)
- register ByteCodes byteCodes;
- {
- register Byte *ptr;
-
- for (ptr = byteCodes->base; ptr < byteCodes->ptr; ptr++) {
- compileByte(*ptr);
- }
- }
-
- static ByteCodes allocByteCodes()
- {
- ByteCodes newByteCodes;
-
- newByteCodes = (ByteCodes)malloc(sizeof(struct ByteCodeArray));
- newByteCodes->base = (Byte *)malloc(BYTE_CODE_CHUNK_SIZE);
- newByteCodes->ptr = newByteCodes->base;
- newByteCodes->maxLen = BYTE_CODE_CHUNK_SIZE;
-
- return (newByteCodes);
- }
-
- static void reallocByteCodes(byteCodes)
- ByteCodes byteCodes;
- {
- Byte *newBytes;
- int newLen;
-
- if (byteCodes->maxLen != (byteCodes->ptr - byteCodes->base)) {
- errorf("reallocByteCodes called with maxLen != byteCode len");
- }
-
- newLen = byteCodes->maxLen + BYTE_CODE_CHUNK_SIZE;
- newBytes = (Byte *)malloc(newLen);
- memcpy(newBytes, byteCodes->base, byteCodes->maxLen);
- free(byteCodes->base);
-
- byteCodes->base = newBytes;
- byteCodes->ptr = newBytes + byteCodes->maxLen;
- byteCodes->maxLen = newLen;
- }
-
- void freeByteCodes(byteCodes)
- ByteCodes byteCodes;
- {
- if (byteCodes != nil) {
- free(byteCodes->base);
- free(byteCodes);
- }
- }
-
- void printByteCodes(byteCodes, literalVec)
- ByteCodes byteCodes;
- OOP literalVec[];
- {
- Byte *b, b1;
- int ip;
-
- if (byteCodes == nil) {
- return;
- }
-
- for (b = byteCodes->base; b < byteCodes->ptr; b++) {
- ip = b - byteCodes->base;
- printf("%5d:\t", ip);
- printByteCodeName(b, ip, literalVec);
- printf("\n");
- switch (*b) {
- case 0: case 1: case 2: case 3:
- case 4: case 5: case 6: case 7:
- case 8: case 9: case 10: case 11:
- case 12: case 13: case 14: case 15:
- break;
-
- case 16: case 17: case 18: case 19:
- case 20: case 21: case 22: case 23:
- case 24: case 25: case 26: case 27:
- case 28: case 29: case 30: case 31:
- break;
-
- case 32: case 33: case 34: case 35:
- case 36: case 37: case 38: case 39:
- case 40: case 41: case 42: case 43:
- case 44: case 45: case 46: case 47:
- case 48: case 49: case 50: case 51:
- case 52: case 53: case 54: case 55:
- case 56: case 57: case 58: case 59:
- case 60: case 61: case 62: case 63:
- break;
-
- case 64: case 65: case 66: case 67:
- case 68: case 69: case 70: case 71:
- case 72: case 73: case 74: case 75:
- case 76: case 77: case 78: case 79:
- case 80: case 81: case 82: case 83:
- case 84: case 85: case 86: case 87:
- case 88: case 89: case 90: case 91:
- case 92: case 93: case 94: case 95:
- break;
-
- case 96: case 97: case 98: case 99:
- case 100: case 101: case 102: case 103:
- break;
-
- case 104: case 105: case 106: case 107:
- case 108: case 109: case 110: case 111:
- break;
-
- case 112:
- break;
-
- case 113:
- break;
-
- case 114:
- break;
-
- case 115:
- break;
-
- case 116:
- break;
-
- case 117:
- break;
-
- case 118:
- break;
-
- case 119:
- break;
-
- case 120:
- break;
-
- case 121:
- break;
-
- case 122:
- break;
-
- case 123:
- break;
-
- case 124:
- break;
-
- case 125:
- break;
-
- case 126: case 127:
- break;
-
- case 128:
- b++;
- break;
-
- case 129:
- b++;
- break;
-
- case 130:
- b++;
- break;
-
- case 131:
- b++;
- break;
-
- case 132:
- b += 2;
- break;
-
- case 133:
- b++;
- break;
-
- case 134:
- b += 2;
- break;
-
- case 135:
- break;
-
- case 136:
- break;
-
- case 137:
- break;
-
- case 138: case 139: case 140: case 141:
- case 142: case 143:
- break;
-
- case 144: case 145: case 146: case 147:
- case 148: case 149: case 150: case 151:
- break;
-
- case 152: case 153: case 154: case 155:
- case 156: case 157: case 158: case 159:
- break;
-
- case 160: case 161: case 162: case 163:
- case 164: case 165: case 166: case 167:
- b++;
- break;
-
- case 168: case 169: case 170: case 171:
- b++;
- break;
-
- case 172: case 173: case 174: case 175:
- b++;
- break;
-
- case 176: case 177: case 178: case 179:
- case 180: case 181: case 182: case 183:
- case 184: case 185: case 186: case 187:
- case 188: case 189: case 190: case 191:
- break;
-
- case 192: case 193: case 194: case 195:
- case 196: case 197: case 198: case 199:
- case 200: case 201: case 202: case 203:
- case 204: case 205: case 206: case 207:
- break;
-
- case 208: case 209: case 210: case 211:
- case 212: case 213: case 214: case 215:
- case 216: case 217: case 218: case 219:
- case 220: case 221: case 222: case 223:
- break;
-
- case 224: case 225: case 226: case 227:
- case 228: case 229: case 230: case 231:
- case 232: case 233: case 234: case 235:
- case 236: case 237: case 238: case 239:
- break;
-
- case 240: case 241: case 242: case 243:
- case 244: case 245: case 246: case 247:
- case 248: case 249: case 250: case 251:
- case 252: case 253: case 254: case 255:
- break;
-
- default:
- break;
- }
- }
- printf("\n");
- }
-
- void printByteCodeName(bp, ip, literalVec)
- Byte bp[];
- int ip;
- OOP literalVec[];
- {
- switch (bp[0]) {
- case 0: case 1: case 2: case 3:
- case 4: case 5: case 6: case 7:
- case 8: case 9: case 10: case 11:
- case 12: case 13: case 14: case 15:
- printf("push Instance Variable[%d]", bp[0] & 15);
- break;
-
- case 16: case 17: case 18: case 19:
- case 20: case 21: case 22: case 23:
- case 24: case 25: case 26: case 27:
- case 28: case 29: case 30: case 31:
- printf("push Temporary[%d]", bp[0] & 15);
- break;
-
- case 32: case 33: case 34: case 35:
- case 36: case 37: case 38: case 39:
- case 40: case 41: case 42: case 43:
- case 44: case 45: case 46: case 47:
- case 48: case 49: case 50: case 51:
- case 52: case 53: case 54: case 55:
- case 56: case 57: case 58: case 59:
- case 60: case 61: case 62: case 63:
- printf("push Literal[%d]", bp[0] & 31);
- break;
-
- case 64: case 65: case 66: case 67:
- case 68: case 69: case 70: case 71:
- case 72: case 73: case 74: case 75:
- case 76: case 77: case 78: case 79:
- case 80: case 81: case 82: case 83:
- case 84: case 85: case 86: case 87:
- case 88: case 89: case 90: case 91:
- case 92: case 93: case 94: case 95:
- printf("push Global Variable[%d] = ", bp[0] & 31);
- printAssociationKey(literalVec[bp[0] & 31]);
- break;
-
- case 96: case 97: case 98: case 99:
- case 100: case 101: case 102: case 103:
- printf("pop and store Instance Variable[%d]", bp[0] & 7);
- break;
-
- case 104: case 105: case 106: case 107:
- case 108: case 109: case 110: case 111:
- printf("pop and store Temporary[%d]", bp[0] & 7);
- break;
-
- case 112:
- printf("push self");
- break;
-
- case 113:
- printf("push true");
- break;
-
- case 114:
- printf("push false");
- break;
-
- case 115:
- printf("push nil");
- break;
-
- case 116:
- printf("push -1");
- break;
-
- case 117:
- printf("push 0");
- break;
-
- case 118:
- printf("push 1");
- break;
-
- case 119:
- printf("push 2");
- break;
-
- case 120:
- printf("return self");
- break;
-
- case 121:
- printf("return true");
- break;
-
- case 122:
- printf("return false");
- break;
-
- case 123:
- printf("return nil");
- break;
-
- case 124:
- printf("return Message stack top");
- break;
-
- case 125:
- printf("return Block stack top");
- break;
-
- case 126: case 127:
- printf("Bytecode %d ILLEGAL!!!", bp[0]);
- break;
-
- case 128:
- switch (bp[1] >> 6) {
- case 0:
- printf("push Instance Variable[%d]", bp[1] & 63);
- break;
- case 1:
- printf("push Temporary[%d]", bp[1] & 63);
- break;
- case 2:
- printf("push Constant[%d]", bp[1] & 63);
- break;
- case 3:
- printf("push Global Variable[%d] = ", bp[1] & 63);
- printAssociationKey(literalVec[bp[1] & 63]);
- break;
- }
- break;
-
- case 129:
- switch (bp[1] >> 6) {
- case 0:
- printf("store Instance Variable[%d]", bp[1] & 63);
- break;
- case 1:
- printf("store Temporary[%d]", bp[1] & 63);
- break;
- case 2:
- printf("Illegal store into constant[%d]", bp[1] & 63);
- break;
- case 3:
- printf("store Global Variable[%d] = ", bp[1] & 63);
- printAssociationKey(literalVec[bp[1] & 63]);
- break;
- }
- break;
-
- case 130:
- switch (bp[1] >> 6) {
- case 0:
- printf("pop and store Instance Variable[%d]", bp[1] & 63);
- break;
- case 1:
- printf("pop and store Temporary[%d]", bp[1] & 63);
- break;
- case 2:
- printf("lllegal pop and store into constant[%d]", bp[1] & 63);
- break;
- case 3:
- printf("pop and store Global Variable[%d]", bp[1] & 63);
- printAssociationKey(literalVec[bp[1] & 63]);
- break;
- }
- break;
-
- case 131:
- printf("send selector %d, %d args = ", bp[1] & 31, bp[1] >> 5);
- printSymbol(literalVec[bp[1] & 31]);
- break;
-
- case 132:
- printf("send selector %d, %d args = ", bp[2], bp[1]);
- printSymbol(literalVec[bp[2]]);
- break;
-
- case 133:
- printf("send to super selector %d, %d args = ", bp[1] & 31, bp[1] >> 5);
- printSymbol(literalVec[bp[1] & 31]);
- break;
-
- case 134:
- printf("send to super selector %d, %d args = ", bp[2], bp[1]);
- printSymbol(literalVec[bp[2]]);
- break;
-
- case 135:
- printf("pop stack top");
- break;
-
- case 136:
- printf("duplicate stack top");
- break;
-
-
- case 137:
- printf("push current context");
- break;
-
- case 138: case 139: case 140: case 141:
- case 142: case 143:
- printf("Illegal bytecode %d!!!", bp[0]);
- break;
-
- case 144: case 145: case 146: case 147:
- case 148: case 149: case 150: case 151:
- printf("jump to %d", (bp[0] & 7) + ip + 1 + 1);
- break;
-
- case 152: case 153: case 154: case 155:
- case 156: case 157: case 158: case 159:
- printf("jump to %d if false", (bp[0] & 7) + ip + 1 + 1);
- break;
-
- case 160: case 161: case 162: case 163:
- case 164: case 165: case 166: case 167:
- printf("jump to %d", ((bp[0]&7)-4) * 256 + bp[1] + ip + 2);
- break;
-
- case 168: case 169: case 170: case 171:
- printf("pop and jump to %d if true", (bp[0]&3) * 256 + bp[1] + ip + 2);
- break;
-
- case 172: case 173: case 174: case 175:
- printf("pop and jump to %d if false", (bp[0]&3) * 256 + bp[1] + ip + 2);
- break;
-
- case 176: case 177: case 178: case 179:
- case 180: case 181: case 182: case 183:
- case 184: case 185: case 186: case 187:
- case 188: case 189: case 190: case 191:
- printf("send arithmetic message \"%s\"", mathMessageName[bp[0] & 15]);
- break;
-
- case 192: case 193: case 194: case 195:
- case 196: case 197: case 198: case 199:
- case 200: case 201: case 202: case 203:
- case 204: case 205: case 206: case 207:
- printf("send special message \"%s\"", specialMessageName[bp[0] & 15]);
- break;
-
- case 208: case 209: case 210: case 211:
- case 212: case 213: case 214: case 215:
- case 216: case 217: case 218: case 219:
- case 220: case 221: case 222: case 223:
- printf("send selector %d, 0 args = ", bp[0] & 15);
- printSymbol(literalVec[bp[0] & 15]);
- break;
-
- case 224: case 225: case 226: case 227:
- case 228: case 229: case 230: case 231:
- case 232: case 233: case 234: case 235:
- case 236: case 237: case 238: case 239:
- printf("send selector %d, 1 arg = ", bp[0] & 15);
- printSymbol(literalVec[bp[0] & 15]);
- break;
-
- case 240: case 241: case 242: case 243:
- case 244: case 245: case 246: case 247:
- case 248: case 249: case 250: case 251:
- case 252: case 253: case 254: case 255:
- printf("send selector %d, 2 args = ", bp[0] & 15);
- printSymbol(literalVec[bp[0] & 15]);
- break;
-
- default:
- printf("UNHANDLED BYTE CODE %d!!!", bp[0]);
- break;
- }
- }
-