diff Python/compile.c @ 14147:21ec69a56228 legacy-trunk

Charles G. Waldman <cgw@fnal.gov>: Add the EXTENDED_ARG opcode to the virtual machine, allowing 32-bit arguments to opcodes instead of being forced to stick to the 16-bit limit. This is especially useful for machine-generated code, which can be too long for the SET_LINENO parameter to fit into 16 bits. This closes the implementation portion of SourceForge patch #100893.
author Fred Drake <fdrake@acm.org>
date Thu, 24 Aug 2000 00:32:09 +0000
parents ac8809959d01
children 1b9fd0cbd914
line wrap: on
line diff
--- a/Python/compile.c	Wed Aug 23 23:31:34 2000 +0000
+++ b/Python/compile.c	Thu Aug 24 00:32:09 2000 +0000
@@ -36,6 +36,9 @@
 #ifdef HAVE_LIMITS_H
 #include <limits.h>
 #endif
+#ifndef INT_MAX
+#define INT_MAX 2147483647
+#endif
 
 /* Three symbols from graminit.h are also defined in Python.h, with
    Py_ prefixes to their names.  Python.h can't include graminit.h
@@ -572,11 +575,17 @@
 static void
 com_addoparg(struct compiling *c, int op, int arg)
 {
+	int extended_arg = arg >> 16;
 	if (op == SET_LINENO) {
 		com_set_lineno(c, arg);
 		if (Py_OptimizeFlag)
 			return;
 	}
+	if (extended_arg){
+		com_addbyte(c, EXTENDED_ARG);
+		com_addint(c, extended_arg);
+		arg &= 0xffff;
+	}
 	com_addbyte(c, op);
 	com_addint(c, arg);
 }
@@ -606,7 +615,14 @@
 		prev = code[anchor] + (code[anchor+1] << 8);
 		dist = target - (anchor+2);
 		code[anchor] = dist & 0xff;
-		code[anchor+1] = dist >> 8;
+		dist >>= 8;
+		code[anchor+1] = dist;
+		dist >>= 8;
+		if (dist) {
+			com_error(c, PyExc_SystemError,
+				  "com_backpatch: offset too large");
+			break;
+		}
 		if (!prev)
 			break;
 		anchor -= prev;
@@ -3364,6 +3380,7 @@
 			break;
 		if (HAS_ARG(opcode))
 			oparg = NEXTARG();
+	  dispatch_opcode1:
 		switch (opcode) {
 		case STORE_NAME:
 		case DELETE_NAME:
@@ -3374,6 +3391,11 @@
 		case EXEC_STMT:
 			c->c_flags &= ~CO_OPTIMIZED;
 			break;
+		case EXTENDED_ARG:
+			opcode = NEXTOP();
+			oparg = oparg<<16 | NEXTARG();
+			goto dispatch_opcode1;
+			break;
 		}
 	}
 	
@@ -3389,6 +3411,7 @@
 			break;
 		if (HAS_ARG(opcode))
 			oparg = NEXTARG();
+	  dispatch_opcode2:
 		if (opcode == LOAD_NAME ||
 		    opcode == STORE_NAME ||
 		    opcode == DELETE_NAME) {
@@ -3403,13 +3426,20 @@
 				continue;
 			}
 			i = PyInt_AsLong(v);
+			if (i >> 16) /* too big for 2 bytes */
+				continue;
 			switch (opcode) {
 			case LOAD_NAME: cur_instr[0] = LOAD_FAST; break;
 			case STORE_NAME: cur_instr[0] = STORE_FAST; break;
 			case DELETE_NAME: cur_instr[0] = DELETE_FAST; break;
 			}
 			cur_instr[1] = i & 0xff;
-			cur_instr[2] = (i>>8) & 0xff;
+			cur_instr[2] = i >> 8;
+		}
+		if (opcode == EXTENDED_ARG) {
+			opcode = NEXTOP();
+			oparg = oparg<<16 | NEXTARG();
+			goto dispatch_opcode2;
 		}
 	}