@@ -81,6 +81,7 @@ static int cmp_member PROTO((object *, object *));
8181static object * cmp_outcome PROTO ((int , object * , object * ));
8282static int import_from PROTO ((object * , object * , object * ) );
8383static object * build_class PROTO ((object * , object * ) );
84+ static void locals_2_fast PROTO ((frameobject * , int ) );
8485
8586
8687/* Pointer to current frame, used to link new frames to */
@@ -994,19 +995,51 @@ eval_code(co, globals, locals, arg)
994995 break ;
995996
996997 case RESERVE_FAST :
997- if (oparg > 0 ) {
998- XDECREF (fastlocals );
999- x = newlistobject (oparg );
1000- fastlocals = (listobject * ) x ;
998+ x = GETCONST (oparg );
999+ if (x == None )
1000+ break ;
1001+ if (x == NULL || !is_dictobject (x )) {
1002+ fatal ("bad RESERVE_FAST" );
1003+ err_setstr (SystemError , "bad RESERVE_FAST" );
1004+ x = NULL ;
1005+ break ;
10011006 }
1007+ XDECREF (f -> f_fastlocals );
1008+ XDECREF (f -> f_localmap );
1009+ INCREF (x );
1010+ f -> f_localmap = x ;
1011+ f -> f_fastlocals = x = newlistobject (
1012+ x -> ob_type -> tp_as_mapping -> mp_length (x ));
1013+ fastlocals = (listobject * ) x ;
10021014 break ;
10031015
10041016 case LOAD_FAST :
1005- /* NYI */
1017+ x = GETLISTITEM (fastlocals , oparg );
1018+ if (x == NULL ) {
1019+ err_setstr (NameError ,
1020+ "undefined local variable" );
1021+ break ;
1022+ }
1023+ INCREF (x );
1024+ PUSH (x );
10061025 break ;
10071026
10081027 case STORE_FAST :
1009- /* NYI */
1028+ w = GETLISTITEM (fastlocals , oparg );
1029+ XDECREF (w );
1030+ w = POP ();
1031+ GETLISTITEM (fastlocals , oparg ) = w ;
1032+ break ;
1033+
1034+ case DELETE_FAST :
1035+ x = GETLISTITEM (fastlocals , oparg );
1036+ if (x == NULL ) {
1037+ err_setstr (NameError ,
1038+ "undefined local variable" );
1039+ break ;
1040+ }
1041+ DECREF (x );
1042+ GETLISTITEM (fastlocals , oparg ) = NULL ;
10101043 break ;
10111044
10121045 case BUILD_TUPLE :
@@ -1068,6 +1101,7 @@ eval_code(co, globals, locals, arg)
10681101 w = GETNAMEV (oparg );
10691102 v = TOP ();
10701103 err = import_from (f -> f_locals , v , w );
1104+ locals_2_fast (f , 0 );
10711105 break ;
10721106
10731107 case JUMP_FORWARD :
@@ -1299,8 +1333,6 @@ eval_code(co, globals, locals, arg)
12991333
13001334 current_frame = f -> f_back ;
13011335 DECREF (f );
1302-
1303- XDECREF (fastlocals );
13041336
13051337 return retval ;
13061338}
@@ -1418,10 +1450,92 @@ call_trace(p_trace, p_newtrace, f, msg, arg)
14181450object *
14191451getlocals ()
14201452{
1421- if (current_frame == NULL )
1453+ /* Merge f->f_fastlocals into f->f_locals, then return the latter */
1454+ frameobject * f ;
1455+ object * locals , * fast , * map ;
1456+ int i ;
1457+ f = current_frame ;
1458+ if (f == NULL )
14221459 return NULL ;
1423- else
1424- return current_frame -> f_locals ;
1460+ locals = f -> f_locals ;
1461+ fast = f -> f_fastlocals ;
1462+ map = f -> f_localmap ;
1463+ if (locals == NULL || fast == NULL || map == NULL )
1464+ return locals ;
1465+ if (!is_dictobject (locals ) || !is_listobject (fast ) ||
1466+ !is_dictobject (map ))
1467+ return locals ;
1468+ i = getdictsize (map );
1469+ while (-- i >= 0 ) {
1470+ object * key ;
1471+ object * value ;
1472+ int j ;
1473+ key = getdict2key (map , i );
1474+ if (key == NULL )
1475+ continue ;
1476+ value = dict2lookup (map , key );
1477+ if (value == NULL || !is_intobject (value ))
1478+ continue ;
1479+ j = getintvalue (value );
1480+ value = getlistitem (fast , j );
1481+ if (value == NULL ) {
1482+ err_clear ();
1483+ if (dict2remove (locals , key ) != 0 )
1484+ err_clear ();
1485+ }
1486+ else {
1487+ if (dict2insert (locals , key , value ) != 0 )
1488+ err_clear ();
1489+ }
1490+ }
1491+ return locals ;
1492+ }
1493+
1494+ static void
1495+ locals_2_fast (f , clear )
1496+ frameobject * f ;
1497+ int clear ;
1498+ {
1499+ /* Merge f->f_locals into f->f_fastlocals */
1500+ object * locals , * fast , * map ;
1501+ int i ;
1502+ if (f == NULL )
1503+ return ;
1504+ locals = f -> f_locals ;
1505+ fast = f -> f_fastlocals ;
1506+ map = f -> f_localmap ;
1507+ if (locals == NULL || fast == NULL || map == NULL )
1508+ return ;
1509+ if (!is_dictobject (locals ) || !is_listobject (fast ) ||
1510+ !is_dictobject (map ))
1511+ return ;
1512+ i = getdictsize (map );
1513+ while (-- i >= 0 ) {
1514+ object * key ;
1515+ object * value ;
1516+ int j ;
1517+ key = getdict2key (map , i );
1518+ if (key == NULL )
1519+ continue ;
1520+ value = dict2lookup (map , key );
1521+ if (value == NULL || !is_intobject (value ))
1522+ continue ;
1523+ j = getintvalue (value );
1524+ value = dict2lookup (locals , key );
1525+ if (value == NULL )
1526+ err_clear ();
1527+ else
1528+ INCREF (value );
1529+ if (value != NULL || clear )
1530+ if (setlistitem (fast , j , value ) != 0 )
1531+ err_clear ();
1532+ }
1533+ }
1534+
1535+ void
1536+ mergelocals ()
1537+ {
1538+ locals_2_fast (current_frame , 1 );
14251539}
14261540
14271541object *
0 commit comments