Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1)

Delta Between Two Patch Sets: Objects/codeobject.c

Issue 25843: lambdas on the same line may incorrectly share code objects
Left Patch Set: Created 4 years, 2 months ago
Right Patch Set: Created 4 years, 1 month ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/test/test_compile.py ('k') | Python/compile.c » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 #include "Python.h" 1 #include "Python.h"
2 #include "code.h" 2 #include "code.h"
3 #include "structmember.h" 3 #include "structmember.h"
4 4
5 #define NAME_CHARS \ 5 #define NAME_CHARS \
6 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz" 6 "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz"
7 7
8 /* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */ 8 /* all_name_chars(s): true iff all chars in s are valid NAME_CHARS */
9 9
10 static int 10 static int
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 if (co->co_weakreflist != NULL) 377 if (co->co_weakreflist != NULL)
378 PyObject_ClearWeakRefs((PyObject*)co); 378 PyObject_ClearWeakRefs((PyObject*)co);
379 PyObject_DEL(co); 379 PyObject_DEL(co);
380 } 380 }
381 381
382 static PyObject * 382 static PyObject *
383 code_sizeof(PyCodeObject *co, void *unused) 383 code_sizeof(PyCodeObject *co, void *unused)
384 { 384 {
385 Py_ssize_t res; 385 Py_ssize_t res;
386 386
387 res = sizeof(PyCodeObject); 387 res = _PyObject_SIZE(Py_TYPE(co));
388 if (co->co_cell2arg != NULL && co->co_cellvars != NULL) 388 if (co->co_cell2arg != NULL && co->co_cellvars != NULL)
389 res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char); 389 res += PyTuple_GET_SIZE(co->co_cellvars) * sizeof(unsigned char);
390 return PyLong_FromSsize_t(res); 390 return PyLong_FromSsize_t(res);
391 } 391 }
392 392
393 static PyObject * 393 static PyObject *
394 code_repr(PyCodeObject *co) 394 code_repr(PyCodeObject *co)
395 { 395 {
396 int lineno; 396 int lineno;
397 if (co->co_firstlineno != 0) 397 if (co->co_firstlineno != 0)
398 lineno = co->co_firstlineno; 398 lineno = co->co_firstlineno;
399 else 399 else
400 lineno = -1; 400 lineno = -1;
401 if (co->co_filename && PyUnicode_Check(co->co_filename)) { 401 if (co->co_filename && PyUnicode_Check(co->co_filename)) {
402 return PyUnicode_FromFormat( 402 return PyUnicode_FromFormat(
403 "<code object %U at %p, file \"%U\", line %d>", 403 "<code object %U at %p, file \"%U\", line %d>",
404 co->co_name, co, co->co_filename, lineno); 404 co->co_name, co, co->co_filename, lineno);
405 } else { 405 } else {
406 return PyUnicode_FromFormat( 406 return PyUnicode_FromFormat(
407 "<code object %U at %p, file ???, line %d>", 407 "<code object %U at %p, file ???, line %d>",
408 co->co_name, co, lineno); 408 co->co_name, co, lineno);
409 } 409 }
410 } 410 }
411 411
412 PyObject* 412 PyObject*
413 _PyCode_ConstantKey(PyObject *o) 413 _PyCode_ConstantKey(PyObject *op)
414 { 414 {
415 PyObject *key; 415 PyObject *key;
416 416
417 /* necessary to make sure types aren't coerced (e.g., float and complex) */ 417 /* Py_None and Py_Ellipsis are singleton */
418 /* _and_ to distinguish 0.0 from -0.0 e.g. on IEEE platforms */ 418 if (op == Py_None || op == Py_Ellipsis
419 if (PyFloat_Check(o)) { 419 || PyLong_CheckExact(op)
420 double d = PyFloat_AS_DOUBLE(o); 420 || PyBool_Check(op)
421 || PyBytes_CheckExact(op)
422 || PyUnicode_CheckExact(op)
423 /* code_richcompare() uses _PyCode_ConstantKey() internally */
424 || PyCode_Check(op)) {
425 key = PyTuple_Pack(2, Py_TYPE(op), op);
426 }
427 else if (PyFloat_CheckExact(op)) {
428 double d = PyFloat_AS_DOUBLE(op);
421 /* all we need is to make the tuple different in either the 0.0 429 /* all we need is to make the tuple different in either the 0.0
422 * or -0.0 case from all others, just to avoid the "coercion". 430 * or -0.0 case from all others, just to avoid the "coercion".
423 */ 431 */
424 if (d == 0.0 && copysign(1.0, d) < 0.0) 432 if (d == 0.0 && copysign(1.0, d) < 0.0)
425 key = PyTuple_Pack(3, o, o->ob_type, Py_None); 433 key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
426 else 434 else
427 key = PyTuple_Pack(2, o, o->ob_type); 435 key = PyTuple_Pack(2, Py_TYPE(op), op);
428 } 436 }
429 else if (PyComplex_Check(o)) { 437 else if (PyComplex_CheckExact(op)) {
430 Py_complex z; 438 Py_complex z;
431 int real_negzero, imag_negzero; 439 int real_negzero, imag_negzero;
432 /* For the complex case we must make complex(x, 0.) 440 /* For the complex case we must make complex(x, 0.)
433 different from complex(x, -0.) and complex(0., y) 441 different from complex(x, -0.) and complex(0., y)
434 different from complex(-0., y), for any x and y. 442 different from complex(-0., y), for any x and y.
435 All four complex zeros must be distinguished.*/ 443 All four complex zeros must be distinguished.*/
436 z = PyComplex_AsCComplex(o); 444 z = PyComplex_AsCComplex(op);
437 real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0; 445 real_negzero = z.real == 0.0 && copysign(1.0, z.real) < 0.0;
438 imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0; 446 imag_negzero = z.imag == 0.0 && copysign(1.0, z.imag) < 0.0;
447 /* use True, False and None singleton as tags for the real and imag
448 * sign, to make tuples different */
439 if (real_negzero && imag_negzero) { 449 if (real_negzero && imag_negzero) {
440 key = PyTuple_Pack(5, o, o->ob_type, 450 key = PyTuple_Pack(3, Py_TYPE(op), op, Py_True);
441 Py_None, Py_None, Py_None);
442 } 451 }
443 else if (imag_negzero) { 452 else if (imag_negzero) {
444 key = PyTuple_Pack(4, o, o->ob_type, Py_None, Py_None); 453 key = PyTuple_Pack(3, Py_TYPE(op), op, Py_False);
445 } 454 }
446 else if (real_negzero) { 455 else if (real_negzero) {
447 key = PyTuple_Pack(3, o, o->ob_type, Py_None); 456 key = PyTuple_Pack(3, Py_TYPE(op), op, Py_None);
448 } 457 }
449 else { 458 else {
450 key = PyTuple_Pack(2, o, o->ob_type); 459 key = PyTuple_Pack(2, Py_TYPE(op), op);
451 } 460 }
452 } 461 }
453 else if (PyTuple_Check(o)) { 462 else if (PyTuple_CheckExact(op)) {
454 Py_ssize_t i, len; 463 Py_ssize_t i, len;
455 PyObject *keys; 464 PyObject *tuple;
456 465
457 len = PyTuple_GET_SIZE(o); 466 len = PyTuple_GET_SIZE(op);
458 keys = PyTuple_New(len); 467 tuple = PyTuple_New(len);
459 if (keys == NULL) 468 if (tuple == NULL)
460 return NULL; 469 return NULL;
461 470
462 for (i=0; i < len; i++) { 471 for (i=0; i < len; i++) {
463 PyObject *item, *item_key; 472 PyObject *item, *item_key;
464 473
465 item = PyTuple_GET_ITEM(o, i); 474 item = PyTuple_GET_ITEM(op, i);
466 item_key = _PyCode_ConstantKey(item); 475 item_key = _PyCode_ConstantKey(item);
467 if (item_key == NULL) { 476 if (item_key == NULL) {
468 Py_DECREF(keys); 477 Py_DECREF(tuple);
469 return NULL; 478 return NULL;
470 } 479 }
471 480
472 PyTuple_SET_ITEM(keys, i, item_key); 481 PyTuple_SET_ITEM(tuple, i, item_key);
473 } 482 }
474 483
475 key = PyTuple_Pack(2, o, keys); 484 key = PyTuple_Pack(3, Py_TYPE(op), op, tuple);
476 } 485 Py_DECREF(tuple);
477 else if (PyAnySet_CheckExact(o)) { 486 }
487 else if (PyFrozenSet_CheckExact(op)) {
478 Py_ssize_t pos = 0; 488 Py_ssize_t pos = 0;
479 PyObject *item; 489 PyObject *item;
480 Py_hash_t hash; 490 Py_hash_t hash;
481 Py_ssize_t i, len; 491 Py_ssize_t i, len;
482 PyObject *keys; 492 PyObject *tuple, *set;
483 493
484 len = PySet_GET_SIZE(o); 494 len = PySet_GET_SIZE(op);
485 keys = PyTuple_New(len); 495 tuple = PyTuple_New(len);
486 if (keys == NULL) 496 if (tuple == NULL)
487 return NULL; 497 return NULL;
488 498
489 i = 0; 499 i = 0;
490 while (_PySet_NextEntry(o, &pos, &item, &hash)) { 500 while (_PySet_NextEntry(op, &pos, &item, &hash)) {
491 PyObject *item_key; 501 PyObject *item_key;
492 502
493 item_key = _PyCode_ConstantKey(item); 503 item_key = _PyCode_ConstantKey(item);
494 if (item_key == NULL) { 504 if (item_key == NULL) {
495 Py_DECREF(keys); 505 Py_DECREF(tuple);
496 return NULL; 506 return NULL;
497 } 507 }
498 508
499 PyTuple_SET_ITEM(keys, i, item_key); 509 assert(i < len);
510 PyTuple_SET_ITEM(tuple, i, item_key);
500 i++; 511 i++;
501 if (i >= len) { 512 }
502 /* set size changed during iteration, ignore */ 513 set = PyFrozenSet_New(tuple);
storchaka 2015/12/14 20:29:30 Is it ever possible? If yes, we have more serious
haypo 2016/01/22 12:24:14 Ok, I replaced it with an assertion.
503 break; 514 Py_DECREF(tuple);
504 } 515 if (set == NULL)
505 } 516 return NULL;
506 return keys; 517
storchaka 2015/12/14 20:29:30 Just keys? Not wrap it in a tuple? And note that
haypo 2016/01/22 12:24:14 Ok, I will wrap the set inside a tuple, as other t
518 key = PyTuple_Pack(3, Py_TYPE(op), op, set);
519 Py_DECREF(set);
520 return key;
507 } 521 }
508 else { 522 else {
509 key = PyTuple_Pack(2, o, o->ob_type); 523 /* for other types, use the identifier to *not* merge them
524 * even if they are equal */
525 PyObject *obj_id = PyLong_FromVoidPtr(op);
526 if (obj_id == NULL)
527 return NULL;
528
529 key = PyTuple_Pack(3, Py_TYPE(op), op, obj_id);
530 Py_DECREF(obj_id);
510 } 531 }
511 return key; 532 return key;
512 } 533 }
513 534
514 static PyObject * 535 static PyObject *
515 code_richcompare(PyObject *self, PyObject *other, int op) 536 code_richcompare(PyObject *self, PyObject *other, int op)
516 { 537 {
517 PyCodeObject *co, *cp; 538 PyCodeObject *co, *cp;
518 int eq; 539 int eq;
519 PyObject *consts1, *consts2; 540 PyObject *consts1, *consts2;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
666 PyCode_Addr2Line(PyCodeObject *co, int addrq) 687 PyCode_Addr2Line(PyCodeObject *co, int addrq)
667 { 688 {
668 Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2; 689 Py_ssize_t size = PyBytes_Size(co->co_lnotab) / 2;
669 unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab); 690 unsigned char *p = (unsigned char*)PyBytes_AsString(co->co_lnotab);
670 int line = co->co_firstlineno; 691 int line = co->co_firstlineno;
671 int addr = 0; 692 int addr = 0;
672 while (--size >= 0) { 693 while (--size >= 0) {
673 addr += *p++; 694 addr += *p++;
674 if (addr > addrq) 695 if (addr > addrq)
675 break; 696 break;
676 line += *p++; 697 line += (signed char)*p;
698 p++;
677 } 699 }
678 return line; 700 return line;
679 } 701 }
680 702
681 /* Update *bounds to describe the first and one-past-the-last instructions in 703 /* Update *bounds to describe the first and one-past-the-last instructions in
682 the same line as lasti. Return the number of that line. */ 704 the same line as lasti. Return the number of that line. */
683 int 705 int
684 _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds) 706 _PyCode_CheckLineNumber(PyCodeObject* co, int lasti, PyAddrPair *bounds)
685 { 707 {
686 Py_ssize_t size; 708 Py_ssize_t size;
(...skipping 14 matching lines...) Expand all
701 723
702 /* See lnotab_notes.txt for the description of 724 /* See lnotab_notes.txt for the description of
703 co_lnotab. A point to remember: increments to p 725 co_lnotab. A point to remember: increments to p
704 come in (addr, line) pairs. */ 726 come in (addr, line) pairs. */
705 727
706 bounds->ap_lower = 0; 728 bounds->ap_lower = 0;
707 while (size > 0) { 729 while (size > 0) {
708 if (addr + *p > lasti) 730 if (addr + *p > lasti)
709 break; 731 break;
710 addr += *p++; 732 addr += *p++;
711 if (*p) 733 if ((signed char)*p)
712 bounds->ap_lower = addr; 734 bounds->ap_lower = addr;
713 line += *p++; 735 line += (signed char)*p;
736 p++;
714 --size; 737 --size;
715 } 738 }
716 739
717 if (size > 0) { 740 if (size > 0) {
718 while (--size >= 0) { 741 while (--size >= 0) {
719 addr += *p++; 742 addr += *p++;
720 if (*p++) 743 if ((signed char)*p)
721 break; 744 break;
745 p++;
722 } 746 }
723 bounds->ap_upper = addr; 747 bounds->ap_upper = addr;
724 } 748 }
725 else { 749 else {
726 bounds->ap_upper = INT_MAX; 750 bounds->ap_upper = INT_MAX;
727 } 751 }
728 752
729 return line; 753 return line;
730 } 754 }
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld 894c83f36cb7+