@@ -2340,16 +2340,6 @@ dict_update_common(PyObject *self, PyObject *args, PyObject *kwds,
2340
2340
return result ;
2341
2341
}
2342
2342
2343
- /* Note: dict.update() uses the METH_VARARGS|METH_KEYWORDS calling convention.
2344
- Using METH_FASTCALL|METH_KEYWORDS would make dict.update(**dict2) calls
2345
- slower, see the issue #29312. */
2346
- static PyObject *
2347
- dict_update (PyObject * self , PyObject * args , PyObject * kwds )
2348
- {
2349
- if (dict_update_common (self , args , kwds , "update" ) != -1 )
2350
- Py_RETURN_NONE ;
2351
- return NULL ;
2352
- }
2353
2343
2354
2344
/* Update unconditionally replaces existing items.
2355
2345
Merge has a 3rd argument 'override'; if set, it acts like Update,
@@ -2591,6 +2581,100 @@ dict_merge(PyObject *a, PyObject *b, int override)
2591
2581
return 0 ;
2592
2582
}
2593
2583
2584
+ /* Implementation of d.update(obj). There are two cases:
2585
+ * - if obj has a "keys" method, assume that it is a mapping
2586
+ * - otherwise, obj must be an iterable of (key, value) pairs
2587
+ */
2588
+ static int
2589
+ dict_merge_from_any (PyObject * self , PyObject * obj )
2590
+ {
2591
+ /* Fast path for dict subclasses */
2592
+ if (PyDict_Check (obj )) {
2593
+ return dict_merge (self , obj , 1 );
2594
+ }
2595
+
2596
+ _Py_IDENTIFIER (keys );
2597
+ PyObject * func ;
2598
+ if (_PyObject_LookupAttrId (obj , & PyId_keys , & func ) < 0 ) {
2599
+ return -1 ;
2600
+ }
2601
+ if (func != NULL ) {
2602
+ Py_DECREF (func );
2603
+ return dict_merge (self , obj , 1 );
2604
+ }
2605
+ else {
2606
+ return PyDict_MergeFromSeq2 (self , obj , 1 );
2607
+ }
2608
+ }
2609
+
2610
+ /* Insert the key:value pairs from the arrays keys and values (of length n).
2611
+ * Return 0 if successful, -1 if an exception was raised */
2612
+ static int
2613
+ dict_merge_from_arrays (PyDictObject * mp , PyObject * const * keys , PyObject * const * values , Py_ssize_t n )
2614
+ {
2615
+ /* Do one big resize at the start, rather than
2616
+ * incrementally resizing as we insert new items. Expect
2617
+ * that there will be no (or few) overlapping keys.
2618
+ */
2619
+ if (USABLE_FRACTION (mp -> ma_keys -> dk_size ) < n ) {
2620
+ if (dictresize (mp , ESTIMATE_SIZE (mp -> ma_used + n ))) {
2621
+ return -1 ;
2622
+ }
2623
+ }
2624
+
2625
+ for (Py_ssize_t i = 0 ; i < n ; i ++ ) {
2626
+ PyObject * key = keys [i ];
2627
+ PyObject * value = values [i ];
2628
+ assert (PyUnicode_Check (key ));
2629
+ Py_hash_t hash = ((PyASCIIObject * )key )-> hash ;
2630
+ if (hash == -1 ) {
2631
+ hash = PyObject_Hash (key );
2632
+ if (hash == -1 ) {
2633
+ return -1 ;
2634
+ }
2635
+ }
2636
+ if (insertdict (mp , key , hash , value )) {
2637
+ return -1 ;
2638
+ }
2639
+ }
2640
+ ASSERT_CONSISTENT (mp );
2641
+ return 0 ;
2642
+ }
2643
+
2644
+
2645
+ static int
2646
+ dict_update_impl (PyObject * self , PyObject * const * args ,
2647
+ Py_ssize_t nargs , PyObject * kwnames ,
2648
+ const char * methname )
2649
+ {
2650
+ if (nargs ) {
2651
+ if (!_PyArg_CheckPositional (methname , nargs , 0 , 1 )) {
2652
+ return -1 ;
2653
+ }
2654
+ if (dict_merge_from_any (self , args [0 ])) {
2655
+ return -1 ;
2656
+ }
2657
+ args += 1 ;
2658
+ }
2659
+ if (kwnames ) {
2660
+ Py_ssize_t nkw = PyTuple_GET_SIZE (kwnames );
2661
+ PyObject * const * names = & PyTuple_GET_ITEM (kwnames , 0 );
2662
+ return dict_merge_from_arrays ((PyDictObject * )self , names , args , nkw );
2663
+ }
2664
+ return 0 ;
2665
+ }
2666
+
2667
+ static PyObject *
2668
+ dict_update (PyObject * self , PyObject * const * args ,
2669
+ Py_ssize_t nargs , PyObject * kwnames )
2670
+ {
2671
+ if (dict_update_impl (self , args , nargs , kwnames , "update" )) {
2672
+ return NULL ;
2673
+ }
2674
+ Py_RETURN_NONE ;
2675
+ }
2676
+
2677
+
2594
2678
int
2595
2679
PyDict_Update (PyObject * a , PyObject * b )
2596
2680
{
@@ -3193,7 +3277,7 @@ static PyMethodDef mapp_methods[] = {
3193
3277
items__doc__ },
3194
3278
{"values" , dictvalues_new , METH_NOARGS ,
3195
3279
values__doc__ },
3196
- {"update" , (PyCFunction )(void (* )(void ))dict_update , METH_VARARGS | METH_KEYWORDS ,
3280
+ {"update" , (PyCFunction )(void (* )(void ))dict_update , METH_FASTCALL | METH_KEYWORDS ,
3197
3281
update__doc__ },
3198
3282
DICT_FROMKEYS_METHODDEF
3199
3283
{"clear" , (PyCFunction )dict_clear , METH_NOARGS ,
0 commit comments