codeobject.c 27.6 KB
Newer Older
1 2
#include <stdbool.h>

Jeremy Hylton's avatar
Jeremy Hylton committed
3 4 5 6 7
#include "Python.h"
#include "code.h"
#include "structmember.h"

#define NAME_CHARS \
8
    "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
Jeremy Hylton's avatar
Jeremy Hylton committed
9

10 11 12 13 14 15
/* Holder for co_extra information */
typedef struct {
    Py_ssize_t ce_size;
    void **ce_extras;
} _PyCodeObjectExtra;

Jeremy Hylton's avatar
Jeremy Hylton committed
16 17 18
/* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */

static int
Martin v. Löwis's avatar
Martin v. Löwis committed
19
all_name_chars(PyObject *o)
Jeremy Hylton's avatar
Jeremy Hylton committed
20
{
21
    static char ok_name_char[256];
22 23
    static const unsigned char *name_chars = (unsigned char *)NAME_CHARS;
    const unsigned char *s, *e;
Martin v. Löwis's avatar
Martin v. Löwis committed
24

25
    if (!PyUnicode_IS_ASCII(o))
Martin v. Löwis's avatar
Martin v. Löwis committed
26
        return 0;
27 28

    if (ok_name_char[*name_chars] == 0) {
29
        const unsigned char *p;
30 31 32
        for (p = name_chars; *p; p++)
            ok_name_char[*p] = 1;
    }
33 34 35
    s = PyUnicode_1BYTE_DATA(o);
    e = s + PyUnicode_GET_LENGTH(o);
    while (s != e) {
36 37 38 39
        if (ok_name_char[*s++] == 0)
            return 0;
    }
    return 1;
Jeremy Hylton's avatar
Jeremy Hylton committed
40 41 42 43 44
}

static void
intern_strings(PyObject *tuple)
{
45 46 47 48 49 50 51 52 53
    Py_ssize_t i;

    for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
        PyObject *v = PyTuple_GET_ITEM(tuple, i);
        if (v == NULL || !PyUnicode_CheckExact(v)) {
            Py_FatalError("non-string found in code slot");
        }
        PyUnicode_InternInPlace(&PyTuple_GET_ITEM(tuple, i));
    }
Jeremy Hylton's avatar
Jeremy Hylton committed
54 55
}

56 57 58 59 60 61 62 63 64 65
/* Intern selected string constants */
static int
intern_string_constants(PyObject *tuple)
{
    int modified = 0;
    Py_ssize_t i;

    for (i = PyTuple_GET_SIZE(tuple); --i >= 0; ) {
        PyObject *v = PyTuple_GET_ITEM(tuple, i);
        if (PyUnicode_CheckExact(v)) {
66 67 68 69
            if (PyUnicode_READY(v) == -1) {
                PyErr_Clear();
                continue;
            }
70 71 72 73 74 75 76 77 78 79 80 81 82
            if (all_name_chars(v)) {
                PyObject *w = v;
                PyUnicode_InternInPlace(&v);
                if (w != v) {
                    PyTuple_SET_ITEM(tuple, i, v);
                    modified = 1;
                }
            }
        }
        else if (PyTuple_CheckExact(v)) {
            intern_string_constants(v);
        }
        else if (PyFrozenSet_CheckExact(v)) {
83
            PyObject *w = v;
84 85 86 87 88 89 90 91 92 93 94 95
            PyObject *tmp = PySequence_Tuple(v);
            if (tmp == NULL) {
                PyErr_Clear();
                continue;
            }
            if (intern_string_constants(tmp)) {
                v = PyFrozenSet_New(tmp);
                if (v == NULL) {
                    PyErr_Clear();
                }
                else {
                    PyTuple_SET_ITEM(tuple, i, v);
96
                    Py_DECREF(w);
97 98 99 100 101 102 103 104 105
                    modified = 1;
                }
            }
            Py_DECREF(tmp);
        }
    }
    return modified;
}

Jeremy Hylton's avatar
Jeremy Hylton committed
106 107

PyCodeObject *
108
PyCode_New(int argcount, int kwonlyargcount,
109 110 111 112 113
           int nlocals, int stacksize, int flags,
           PyObject *code, PyObject *consts, PyObject *names,
           PyObject *varnames, PyObject *freevars, PyObject *cellvars,
           PyObject *filename, PyObject *name, int firstlineno,
           PyObject *lnotab)
Jeremy Hylton's avatar
Jeremy Hylton committed
114
{
115
    PyCodeObject *co;
116 117
    unsigned char *cell2arg = NULL;
    Py_ssize_t i, n_cellvars;
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

    /* Check argument types */
    if (argcount < 0 || kwonlyargcount < 0 || nlocals < 0 ||
        code == NULL ||
        consts == NULL || !PyTuple_Check(consts) ||
        names == NULL || !PyTuple_Check(names) ||
        varnames == NULL || !PyTuple_Check(varnames) ||
        freevars == NULL || !PyTuple_Check(freevars) ||
        cellvars == NULL || !PyTuple_Check(cellvars) ||
        name == NULL || !PyUnicode_Check(name) ||
        filename == NULL || !PyUnicode_Check(filename) ||
        lnotab == NULL || !PyBytes_Check(lnotab) ||
        !PyObject_CheckReadBuffer(code)) {
        PyErr_BadInternalCall();
        return NULL;
    }
134 135 136 137 138

    /* Ensure that the filename is a ready Unicode string */
    if (PyUnicode_READY(filename) < 0)
        return NULL;

139 140 141 142
    intern_strings(names);
    intern_strings(varnames);
    intern_strings(freevars);
    intern_strings(cellvars);
143
    intern_string_constants(consts);
144 145 146 147 148 149 150 151 152

    /* Check for any inner or outer closure references */
    n_cellvars = PyTuple_GET_SIZE(cellvars);
    if (!n_cellvars && !PyTuple_GET_SIZE(freevars)) {
        flags |= CO_NOFREE;
    } else {
        flags &= ~CO_NOFREE;
    }

153 154 155 156 157
    /* Create mapping between cells and arguments if needed. */
    if (n_cellvars) {
        Py_ssize_t total_args = argcount + kwonlyargcount +
            ((flags & CO_VARARGS) != 0) + ((flags & CO_VARKEYWORDS) != 0);
        Py_ssize_t alloc_size = sizeof(unsigned char) * n_cellvars;
158
        bool used_cell2arg = false;
159 160 161 162 163 164 165 166 167 168 169 170
        cell2arg = PyMem_MALLOC(alloc_size);
        if (cell2arg == NULL)
            return NULL;
        memset(cell2arg, CO_CELL_NOT_AN_ARG, alloc_size);
        /* Find cells which are also arguments. */
        for (i = 0; i < n_cellvars; i++) {
            Py_ssize_t j;
            PyObject *cell = PyTuple_GET_ITEM(cellvars, i);
            for (j = 0; j < total_args; j++) {
                PyObject *arg = PyTuple_GET_ITEM(varnames, j);
                if (!PyUnicode_Compare(cell, arg)) {
                    cell2arg[i] = j;
171
                    used_cell2arg = true;
172 173 174 175 176 177 178 179 180
                    break;
                }
            }
        }
        if (!used_cell2arg) {
            PyMem_FREE(cell2arg);
            cell2arg = NULL;
        }
    }
181
    co = PyObject_NEW(PyCodeObject, &PyCode_Type);
182 183 184 185
    if (co == NULL) {
        if (cell2arg)
            PyMem_FREE(cell2arg);
        return NULL;
186
    }
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
    co->co_argcount = argcount;
    co->co_kwonlyargcount = kwonlyargcount;
    co->co_nlocals = nlocals;
    co->co_stacksize = stacksize;
    co->co_flags = flags;
    Py_INCREF(code);
    co->co_code = code;
    Py_INCREF(consts);
    co->co_consts = consts;
    Py_INCREF(names);
    co->co_names = names;
    Py_INCREF(varnames);
    co->co_varnames = varnames;
    Py_INCREF(freevars);
    co->co_freevars = freevars;
    Py_INCREF(cellvars);
    co->co_cellvars = cellvars;
    co->co_cell2arg = cell2arg;
    Py_INCREF(filename);
    co->co_filename = filename;
    Py_INCREF(name);
    co->co_name = name;
    co->co_firstlineno = firstlineno;
    Py_INCREF(lnotab);
    co->co_lnotab = lnotab;
    co->co_zombieframe = NULL;
    co->co_weakreflist = NULL;
214
    co->co_extra = NULL;
215
    return co;
Jeremy Hylton's avatar
Jeremy Hylton committed
216 217
}

218 219 220
PyCodeObject *
PyCode_NewEmpty(const char *filename, const char *funcname, int firstlineno)
{
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
    static PyObject *emptystring = NULL;
    static PyObject *nulltuple = NULL;
    PyObject *filename_ob = NULL;
    PyObject *funcname_ob = NULL;
    PyCodeObject *result = NULL;
    if (emptystring == NULL) {
        emptystring = PyBytes_FromString("");
        if (emptystring == NULL)
            goto failed;
    }
    if (nulltuple == NULL) {
        nulltuple = PyTuple_New(0);
        if (nulltuple == NULL)
            goto failed;
    }
    funcname_ob = PyUnicode_FromString(funcname);
    if (funcname_ob == NULL)
        goto failed;
    filename_ob = PyUnicode_DecodeFSDefault(filename);
    if (filename_ob == NULL)
        goto failed;

    result = PyCode_New(0,                      /* argcount */
                0,                              /* kwonlyargcount */
                0,                              /* nlocals */
                0,                              /* stacksize */
                0,                              /* flags */
                emptystring,                    /* code */
                nulltuple,                      /* consts */
                nulltuple,                      /* names */
                nulltuple,                      /* varnames */
                nulltuple,                      /* freevars */
                nulltuple,                      /* cellvars */
                filename_ob,                    /* filename */
                funcname_ob,                    /* name */
                firstlineno,                    /* firstlineno */
                emptystring                     /* lnotab */
                );
259 260

failed:
261 262 263
    Py_XDECREF(funcname_ob);
    Py_XDECREF(filename_ob);
    return result;
264
}
Jeremy Hylton's avatar
Jeremy Hylton committed
265 266 267 268

#define OFF(x) offsetof(PyCodeObject, x)

static PyMemberDef code_memberlist[] = {
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
    {"co_argcount",     T_INT,          OFF(co_argcount),       READONLY},
    {"co_kwonlyargcount",       T_INT,  OFF(co_kwonlyargcount), READONLY},
    {"co_nlocals",      T_INT,          OFF(co_nlocals),        READONLY},
    {"co_stacksize",T_INT,              OFF(co_stacksize),      READONLY},
    {"co_flags",        T_INT,          OFF(co_flags),          READONLY},
    {"co_code",         T_OBJECT,       OFF(co_code),           READONLY},
    {"co_consts",       T_OBJECT,       OFF(co_consts),         READONLY},
    {"co_names",        T_OBJECT,       OFF(co_names),          READONLY},
    {"co_varnames",     T_OBJECT,       OFF(co_varnames),       READONLY},
    {"co_freevars",     T_OBJECT,       OFF(co_freevars),       READONLY},
    {"co_cellvars",     T_OBJECT,       OFF(co_cellvars),       READONLY},
    {"co_filename",     T_OBJECT,       OFF(co_filename),       READONLY},
    {"co_name",         T_OBJECT,       OFF(co_name),           READONLY},
    {"co_firstlineno", T_INT,           OFF(co_firstlineno),    READONLY},
    {"co_lnotab",       T_OBJECT,       OFF(co_lnotab),         READONLY},
    {NULL}      /* Sentinel */
Jeremy Hylton's avatar
Jeremy Hylton committed
285 286 287 288 289 290 291 292
};

/* Helper for code_new: return a shallow copy of a tuple that is
   guaranteed to contain exact strings, by converting string subclasses
   to exact strings and complaining if a non-string is found. */
static PyObject*
validate_and_copy_tuple(PyObject *tup)
{
293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
    PyObject *newtuple;
    PyObject *item;
    Py_ssize_t i, len;

    len = PyTuple_GET_SIZE(tup);
    newtuple = PyTuple_New(len);
    if (newtuple == NULL)
        return NULL;

    for (i = 0; i < len; i++) {
        item = PyTuple_GET_ITEM(tup, i);
        if (PyUnicode_CheckExact(item)) {
            Py_INCREF(item);
        }
        else if (!PyUnicode_Check(item)) {
            PyErr_Format(
                PyExc_TypeError,
                "name tuples must contain only "
                "strings, not '%.500s'",
                item->ob_type->tp_name);
            Py_DECREF(newtuple);
            return NULL;
        }
        else {
317
            item = _PyUnicode_Copy(item);
318 319 320 321 322 323 324 325 326
            if (item == NULL) {
                Py_DECREF(newtuple);
                return NULL;
            }
        }
        PyTuple_SET_ITEM(newtuple, i, item);
    }

    return newtuple;
Jeremy Hylton's avatar
Jeremy Hylton committed
327 328 329
}

PyDoc_STRVAR(code_doc,
330
"code(argcount, kwonlyargcount, nlocals, stacksize, flags, codestring,\n\
331 332
      constants, names, varnames, filename, name, firstlineno,\n\
      lnotab[, freevars[, cellvars]])\n\
Jeremy Hylton's avatar
Jeremy Hylton committed
333 334 335 336 337 338
\n\
Create a code object.  Not for the faint of heart.");

static PyObject *
code_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
    int argcount;
    int kwonlyargcount;
    int nlocals;
    int stacksize;
    int flags;
    PyObject *co = NULL;
    PyObject *code;
    PyObject *consts;
    PyObject *names, *ournames = NULL;
    PyObject *varnames, *ourvarnames = NULL;
    PyObject *freevars = NULL, *ourfreevars = NULL;
    PyObject *cellvars = NULL, *ourcellvars = NULL;
    PyObject *filename;
    PyObject *name;
    int firstlineno;
    PyObject *lnotab;

    if (!PyArg_ParseTuple(args, "iiiiiSO!O!O!UUiS|O!O!:code",
                          &argcount, &kwonlyargcount,
                              &nlocals, &stacksize, &flags,
                          &code,
                          &PyTuple_Type, &consts,
                          &PyTuple_Type, &names,
                          &PyTuple_Type, &varnames,
                          &filename, &name,
                          &firstlineno, &lnotab,
                          &PyTuple_Type, &freevars,
                          &PyTuple_Type, &cellvars))
        return NULL;

    if (argcount < 0) {
        PyErr_SetString(
            PyExc_ValueError,
            "code: argcount must not be negative");
        goto cleanup;
    }

    if (kwonlyargcount < 0) {
        PyErr_SetString(
            PyExc_ValueError,
            "code: kwonlyargcount must not be negative");
        goto cleanup;
    }
    if (nlocals < 0) {
        PyErr_SetString(
            PyExc_ValueError,
            "code: nlocals must not be negative");
        goto cleanup;
    }

    ournames = validate_and_copy_tuple(names);
    if (ournames == NULL)
        goto cleanup;
    ourvarnames = validate_and_copy_tuple(varnames);
    if (ourvarnames == NULL)
        goto cleanup;
    if (freevars)
        ourfreevars = validate_and_copy_tuple(freevars);
    else
        ourfreevars = PyTuple_New(0);
    if (ourfreevars == NULL)
        goto cleanup;
    if (cellvars)
        ourcellvars = validate_and_copy_tuple(cellvars);
    else
        ourcellvars = PyTuple_New(0);
    if (ourcellvars == NULL)
        goto cleanup;

    co = (PyObject *)PyCode_New(argcount, kwonlyargcount,
                                nlocals, stacksize, flags,
                                code, consts, ournames, ourvarnames,
                                ourfreevars, ourcellvars, filename,
                                name, firstlineno, lnotab);
Jeremy Hylton's avatar
Jeremy Hylton committed
413
  cleanup:
414 415 416 417 418
    Py_XDECREF(ournames);
    Py_XDECREF(ourvarnames);
    Py_XDECREF(ourfreevars);
    Py_XDECREF(ourcellvars);
    return co;
Jeremy Hylton's avatar
Jeremy Hylton committed
419 420 421 422 423
}

static void
code_dealloc(PyCodeObject *co)
{
424
    if (co->co_extra != NULL) {
425
        __PyCodeExtraState *state = __PyCodeExtraState_Get();
426
        _PyCodeObjectExtra *co_extra = co->co_extra;
427

428
        for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
429
            freefunc free_extra = state->co_extra_freefuncs[i];
430 431

            if (free_extra != NULL) {
432
                free_extra(co_extra->ce_extras[i]);
433 434 435
            }
        }

436 437
        PyMem_Free(co_extra->ce_extras);
        PyMem_Free(co_extra);
438 439
    }

440 441 442 443 444 445 446 447 448
    Py_XDECREF(co->co_code);
    Py_XDECREF(co->co_consts);
    Py_XDECREF(co->co_names);
    Py_XDECREF(co->co_varnames);
    Py_XDECREF(co->co_freevars);
    Py_XDECREF(co->co_cellvars);
    Py_XDECREF(co->co_filename);
    Py_XDECREF(co->co_name);
    Py_XDECREF(co->co_lnotab);
449 450
    if (co->co_cell2arg != NULL)
        PyMem_FREE(co->co_cell2arg);
451 452 453 454 455
    if (co->co_zombieframe != NULL)
        PyObject_GC_Del(co->co_zombieframe);
    if (co->co_weakreflist != NULL)
        PyObject_ClearWeakRefs((PyObject*)co);
    PyObject_DEL(co);
Jeremy Hylton's avatar
Jeremy Hylton committed
456 457
}

458 459 460
static PyObject *
code_sizeof(PyCodeObject *co, void *unused)
{
461 462
    Py_ssize_t res = _PyObject_SIZE(Py_TYPE(co));
    _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) co->co_extra;
463 464

    if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
465 466 467 468 469
        res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(Py_ssize_t);

    if (co_extra != NULL)
        res += co_extra->ce_size * sizeof(co_extra->ce_extras[0]);

470 471 472
    return PyLong_FromSsize_t(res);
}

Jeremy Hylton's avatar
Jeremy Hylton committed
473 474 475
static PyObject *
code_repr(PyCodeObject *co)
{
476 477 478 479 480 481 482
    int lineno;
    if (co->co_firstlineno != 0)
        lineno = co->co_firstlineno;
    else
        lineno = -1;
    if (co->co_filename && PyUnicode_Check(co->co_filename)) {
        return PyUnicode_FromFormat(
483
            "<code object %U at %p, file \"%U\", line %d>",
484 485 486
            co->co_name, co, co->co_filename, lineno);
    } else {
        return PyUnicode_FromFormat(
487
            "<code object %U at %p, file ???, line %d>",
488 489
            co->co_name, co, lineno);
    }
Jeremy Hylton's avatar
Jeremy Hylton committed
490 491
}

492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563
PyObject*
_PyCode_ConstantKey(PyObject *op)
{
    PyObject *key;

    /* Py_None and Py_Ellipsis are singleton */
    if (op == Py_None || op == Py_Ellipsis
       || PyLong_CheckExact(op)
       || PyBool_Check(op)
       || PyBytes_CheckExact(op)
       || PyUnicode_CheckExact(op)
          /* code_richcompare() uses _PyCode_ConstantKey() internally */
       || PyCode_Check(op)) {
        key = PyTuple_Pack(2, Py_TYPE(op), op);
    }
    else if (PyFloat_CheckExact(op)) {
        double d = PyFloat_AS_DOUBLE(op);
        /* all we need is to make the tuple different in either the 0.0
         * or -0.0 case from all others, just to avoid the "coercion".
         */
        if (d == 0.0 && copysign(1.0, d) < 0.0)
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
        else
            key = PyTuple_Pack(2, Py_TYPE(op), op);
    }
    else if (PyComplex_CheckExact(op)) {
        Py_complex z;
        int real_negzero, imag_negzero;
        /* For the complex case we must make complex(x, 0.)
           different from complex(x, -0.) and complex(0., y)
           different from complex(-0., y), for any x and y.
           All four complex zeros must be distinguished.*/
        z = PyComplex_AsCComplex(op);
        real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
        imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
        /* use True, False and None singleton as tags for the real and imag
         * sign, to make tuples different */
        if (real_negzero && imag_negzero) {
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True);
        }
        else if (imag_negzero) {
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False);
        }
        else if (real_negzero) {
            key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
        }
        else {
            key = PyTuple_Pack(2, Py_TYPE(op), op);
        }
    }
    else if (PyTuple_CheckExact(op)) {
        Py_ssize_t i, len;
        PyObject *tuple;

        len = PyTuple_GET_SIZE(op);
        tuple = PyTuple_New(len);
        if (tuple == NULL)
            return NULL;

        for (i=0; i < len; i++) {
            PyObject *item, *item_key;

            item = PyTuple_GET_ITEM(op, i);
            item_key = _PyCode_ConstantKey(item);
            if (item_key == NULL) {
                Py_DECREF(tuple);
                return NULL;
            }

            PyTuple_SET_ITEM(tuple, i, item_key);
        }

564
        key = PyTuple_Pack(2, tuple, op);
565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597
        Py_DECREF(tuple);
    }
    else if (PyFrozenSet_CheckExact(op)) {
        Py_ssize_t pos = 0;
        PyObject *item;
        Py_hash_t hash;
        Py_ssize_t i, len;
        PyObject *tuple, *set;

        len = PySet_GET_SIZE(op);
        tuple = PyTuple_New(len);
        if (tuple == NULL)
            return NULL;

        i = 0;
        while (_PySet_NextEntry(op, &pos, &item, &hash)) {
            PyObject *item_key;

            item_key = _PyCode_ConstantKey(item);
            if (item_key == NULL) {
                Py_DECREF(tuple);
                return NULL;
            }

            assert(i < len);
            PyTuple_SET_ITEM(tuple, i, item_key);
            i++;
        }
        set = PyFrozenSet_New(tuple);
        Py_DECREF(tuple);
        if (set == NULL)
            return NULL;

598
        key = PyTuple_Pack(2, set, op);
599 600 601 602
        Py_DECREF(set);
        return key;
    }
    else {
603
        /* for other types, use the object identifier as a unique identifier
604 605 606 607 608
         * to ensure that they are seen as unequal. */
        PyObject *obj_id = PyLong_FromVoidPtr(op);
        if (obj_id == NULL)
            return NULL;

609
        key = PyTuple_Pack(2, obj_id, op);
610 611 612 613 614
        Py_DECREF(obj_id);
    }
    return key;
}

615 616
static PyObject *
code_richcompare(PyObject *self, PyObject *other, int op)
Jeremy Hylton's avatar
Jeremy Hylton committed
617
{
618 619
    PyCodeObject *co, *cp;
    int eq;
620
    PyObject *consts1, *consts2;
621 622 623 624 625
    PyObject *res;

    if ((op != Py_EQ && op != Py_NE) ||
        !PyCode_Check(self) ||
        !PyCode_Check(other)) {
626
        Py_RETURN_NOTIMPLEMENTED;
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
    }

    co = (PyCodeObject *)self;
    cp = (PyCodeObject *)other;

    eq = PyObject_RichCompareBool(co->co_name, cp->co_name, Py_EQ);
    if (eq <= 0) goto unequal;
    eq = co->co_argcount == cp->co_argcount;
    if (!eq) goto unequal;
    eq = co->co_kwonlyargcount == cp->co_kwonlyargcount;
    if (!eq) goto unequal;
    eq = co->co_nlocals == cp->co_nlocals;
    if (!eq) goto unequal;
    eq = co->co_flags == cp->co_flags;
    if (!eq) goto unequal;
    eq = co->co_firstlineno == cp->co_firstlineno;
    if (!eq) goto unequal;
    eq = PyObject_RichCompareBool(co->co_code, cp->co_code, Py_EQ);
    if (eq <= 0) goto unequal;
646 647 648 649 650 651 652 653 654 655 656 657 658

    /* compare constants */
    consts1 = _PyCode_ConstantKey(co->co_consts);
    if (!consts1)
        return NULL;
    consts2 = _PyCode_ConstantKey(cp->co_consts);
    if (!consts2) {
        Py_DECREF(consts1);
        return NULL;
    }
    eq = PyObject_RichCompareBool(consts1, consts2, Py_EQ);
    Py_DECREF(consts1);
    Py_DECREF(consts2);
659
    if (eq <= 0) goto unequal;
660

661 662 663 664 665 666 667 668 669 670 671 672 673 674
    eq = PyObject_RichCompareBool(co->co_names, cp->co_names, Py_EQ);
    if (eq <= 0) goto unequal;
    eq = PyObject_RichCompareBool(co->co_varnames, cp->co_varnames, Py_EQ);
    if (eq <= 0) goto unequal;
    eq = PyObject_RichCompareBool(co->co_freevars, cp->co_freevars, Py_EQ);
    if (eq <= 0) goto unequal;
    eq = PyObject_RichCompareBool(co->co_cellvars, cp->co_cellvars, Py_EQ);
    if (eq <= 0) goto unequal;

    if (op == Py_EQ)
        res = Py_True;
    else
        res = Py_False;
    goto done;
675 676

  unequal:
677 678 679 680 681 682
    if (eq < 0)
        return NULL;
    if (op == Py_NE)
        res = Py_True;
    else
        res = Py_False;
683 684

  done:
685 686
    Py_INCREF(res);
    return res;
Jeremy Hylton's avatar
Jeremy Hylton committed
687 688
}

689
static Py_hash_t
Jeremy Hylton's avatar
Jeremy Hylton committed
690 691
code_hash(PyCodeObject *co)
{
692
    Py_hash_t h, h0, h1, h2, h3, h4, h5, h6;
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
    h0 = PyObject_Hash(co->co_name);
    if (h0 == -1) return -1;
    h1 = PyObject_Hash(co->co_code);
    if (h1 == -1) return -1;
    h2 = PyObject_Hash(co->co_consts);
    if (h2 == -1) return -1;
    h3 = PyObject_Hash(co->co_names);
    if (h3 == -1) return -1;
    h4 = PyObject_Hash(co->co_varnames);
    if (h4 == -1) return -1;
    h5 = PyObject_Hash(co->co_freevars);
    if (h5 == -1) return -1;
    h6 = PyObject_Hash(co->co_cellvars);
    if (h6 == -1) return -1;
    h = h0 ^ h1 ^ h2 ^ h3 ^ h4 ^ h5 ^ h6 ^
        co->co_argcount ^ co->co_kwonlyargcount ^
        co->co_nlocals ^ co->co_flags;
    if (h == -1) h = -2;
    return h;
Jeremy Hylton's avatar
Jeremy Hylton committed
712 713 714 715
}

/* XXX code objects need to participate in GC? */

716 717 718 719 720
static struct PyMethodDef code_methods[] = {
    {"__sizeof__", (PyCFunction)code_sizeof, METH_NOARGS},
    {NULL, NULL}                /* sentinel */
};

Jeremy Hylton's avatar
Jeremy Hylton committed
721
PyTypeObject PyCode_Type = {
722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
    "code",
    sizeof(PyCodeObject),
    0,
    (destructor)code_dealloc,           /* tp_dealloc */
    0,                                  /* tp_print */
    0,                                  /* tp_getattr */
    0,                                  /* tp_setattr */
    0,                                  /* tp_reserved */
    (reprfunc)code_repr,                /* tp_repr */
    0,                                  /* tp_as_number */
    0,                                  /* tp_as_sequence */
    0,                                  /* tp_as_mapping */
    (hashfunc)code_hash,                /* tp_hash */
    0,                                  /* tp_call */
    0,                                  /* tp_str */
    PyObject_GenericGetAttr,            /* tp_getattro */
    0,                                  /* tp_setattro */
    0,                                  /* tp_as_buffer */
    Py_TPFLAGS_DEFAULT,                 /* tp_flags */
    code_doc,                           /* tp_doc */
    0,                                  /* tp_traverse */
    0,                                  /* tp_clear */
    code_richcompare,                   /* tp_richcompare */
    offsetof(PyCodeObject, co_weakreflist),     /* tp_weaklistoffset */
    0,                                  /* tp_iter */
    0,                                  /* tp_iternext */
749
    code_methods,                       /* tp_methods */
750 751 752 753 754 755 756 757 758 759
    code_memberlist,                    /* tp_members */
    0,                                  /* tp_getset */
    0,                                  /* tp_base */
    0,                                  /* tp_dict */
    0,                                  /* tp_descr_get */
    0,                                  /* tp_descr_set */
    0,                                  /* tp_dictoffset */
    0,                                  /* tp_init */
    0,                                  /* tp_alloc */
    code_new,                           /* tp_new */
Jeremy Hylton's avatar
Jeremy Hylton committed
760 761
};

762 763
/* Use co_lnotab to compute the line number from a bytecode index, addrq.  See
   lnotab_notes.txt for the details of the lnotab representation.
Jeremy Hylton's avatar
Jeremy Hylton committed
764 765 766 767 768
*/

int
PyCode_Addr2Line(PyCodeObject *co, int addrq)
{
769
    Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2;
770 771 772 773 774 775 776
    unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab);
    int line = co->co_firstlineno;
    int addr = 0;
    while (--size >= 0) {
        addr += *p++;
        if (addr > addrq)
            break;
777 778
        line += (signed char)*p;
        p++;
779 780
    }
    return line;
Jeremy Hylton's avatar
Jeremy Hylton committed
781
}
782

783 784 785 786
/* Update *bounds to describe the first and one-past-the-last instructions in
   the same line as lasti.  Return the number of that line. */
int
_PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
787
{
788 789
    Py_ssize_t size;
    int addr, line;
790 791 792 793 794 795 796 797 798 799 800 801
    unsigned char* p;

    p = (unsigned char*)PyBytes_AS_STRING(co->co_lnotab);
    size = PyBytes_GET_SIZE(co->co_lnotab) / 2;

    addr = 0;
    line = co->co_firstlineno;
    assert(line > 0);

    /* possible optimization: if f->f_lasti == instr_ub
       (likely to be a common case) then we already know
       instr_lb -- if we stored the matching value of p
802
       somewhere we could skip the first while loop. */
803 804 805 806 807 808 809 810 811 812

    /* See lnotab_notes.txt for the description of
       co_lnotab.  A point to remember: increments to p
       come in (addr, line) pairs. */

    bounds->ap_lower = 0;
    while (size > 0) {
        if (addr + *p > lasti)
            break;
        addr += *p++;
813
        if ((signed char)*p)
814
            bounds->ap_lower = addr;
815 816
        line += (signed char)*p;
        p++;
817 818 819 820 821 822
        --size;
    }

    if (size > 0) {
        while (--size >= 0) {
            addr += *p++;
823
            if ((signed char)*p)
824
                break;
825
            p++;
826
        }
827 828 829 830 831
        bounds->ap_upper = addr;
    }
    else {
        bounds->ap_upper = INT_MAX;
    }
832

833
    return line;
834
}
835 836 837 838 839 840 841


int
_PyCode_GetExtra(PyObject *code, Py_ssize_t index, void **extra)
{
    if (!PyCode_Check(code)) {
        PyErr_BadInternalCall();
842
        return -1;
843 844
    }

845 846 847
    PyCodeObject *o = (PyCodeObject*) code;
    _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra*) o->co_extra;

848

849
    if (co_extra == NULL || co_extra->ce_size <= index) {
850
        *extra = NULL;
851 852 853
        return 0;
    }

854
    *extra = co_extra->ce_extras[index];
855 856 857 858 859 860 861
    return 0;
}


int
_PyCode_SetExtra(PyObject *code, Py_ssize_t index, void *extra)
{
862
    __PyCodeExtraState *state = __PyCodeExtraState_Get();
863 864

    if (!PyCode_Check(code) || index < 0 ||
865
            index >= state->co_extra_user_count) {
866
        PyErr_BadInternalCall();
867
        return -1;
868 869
    }

870 871
    PyCodeObject *o = (PyCodeObject*) code;
    _PyCodeObjectExtra *co_extra = (_PyCodeObjectExtra *) o->co_extra;
872

873
    if (co_extra == NULL) {
874 875
        co_extra = PyMem_Malloc(sizeof(_PyCodeObjectExtra));
        if (co_extra == NULL) {
876
            return -1;
877 878
        }

879
        co_extra->ce_extras = PyMem_Malloc(
880
            state->co_extra_user_count * sizeof(void*));
881
        if (co_extra->ce_extras == NULL) {
882
            PyMem_Free(co_extra);
883
            return -1;
884 885
        }

886
        co_extra->ce_size = state->co_extra_user_count;
887

888 889
        for (Py_ssize_t i = 0; i < co_extra->ce_size; i++) {
            co_extra->ce_extras[i] = NULL;
890
        }
891 892

        o->co_extra = co_extra;
893
    }
894
    else if (co_extra->ce_size <= index) {
895
        void** ce_extras = PyMem_Realloc(
896
            co_extra->ce_extras, state->co_extra_user_count * sizeof(void*));
897

898
        if (ce_extras == NULL) {
899
            return -1;
900 901
        }

902
        for (Py_ssize_t i = co_extra->ce_size;
903
             i < state->co_extra_user_count;
904 905
             i++) {
            ce_extras[i] = NULL;
906
        }
907 908

        co_extra->ce_extras = ce_extras;
909 910 911 912 913 914 915 916
        co_extra->ce_size = state->co_extra_user_count;
    }

    if (co_extra->ce_extras[index] != NULL) {
        freefunc free = state->co_extra_freefuncs[index];
        if (free != NULL) {
            free(co_extra->ce_extras[index]);
        }
917 918
    }

919
    co_extra->ce_extras[index] = extra;
920 921
    return 0;
}