From b87875dc00a60fa6a7687aebcdd2e6fb3346a5d4 Mon Sep 17 00:00:00 2001
From: Jacob Bower <jbower@meta.com>
Date: Thu, 2 Nov 2023 21:54:59 -0700
Subject: [PATCH] Make cinder.cpp more C++

Summary: Use  lambdas to make the code a bit more concise and a few other tweaks.

Reviewed By: alexmalyshev

Differential Revision: D50866123

fbshipit-source-id: 4850b8f07fd9e4687e1dc7be6f9ef71a439fadd1
---
 Cinder/cinder.cpp       | 195 ++++++++++++++++++----------------------
 Shadowcode/shadowcode.h |   3 +
 2 files changed, 92 insertions(+), 106 deletions(-)

diff --git a/Cinder/cinder.cpp b/Cinder/cinder.cpp
index 74f0f426772..725a66b1354 100644
--- a/Cinder/cinder.cpp
+++ b/Cinder/cinder.cpp
@@ -6,41 +6,40 @@
 #include "Jit/pyjit.h"
 #include "StaticPython/classloader.h"
 #include "StaticPython/descrobject_vectorcall.h"
+#include "Shadowcode/shadowcode.h"
 
 static int cinder_dict_watcher_id = -1;
 static int cinder_type_watcher_id = -1;
 static int cinder_func_watcher_id = -1;
 static int cinder_code_watcher_id = -1;
 
-static int cinder_dict_watcher(
-    PyDict_WatchEvent event,
-    PyObject* dict,
-    PyObject* key,
-    PyObject* new_value) {
-  switch (event) {
-    case PyDict_EVENT_ADDED:
-    case PyDict_EVENT_MODIFIED:
-    case PyDict_EVENT_DELETED:
-      if (!PyUnicode_CheckExact(key)) {
-        _PyJIT_NotifyDictUnwatch(dict);
-      } else {
-        _PyJIT_NotifyDictKey(dict, key, new_value);
-        _PyClassLoader_NotifyDictChange((PyDictObject *)dict, key);
-      }
-      break;
-    case PyDict_EVENT_CLEARED:
-      _PyJIT_NotifyDictClear(dict);
-      break;
-    case PyDict_EVENT_CLONED:
-    case PyDict_EVENT_DEALLOCATED:
-      _PyJIT_NotifyDictUnwatch(dict);
-      break;
-  }
-  return 0;
-}
-
 static int cinder_install_dict_watcher() {
-  int watcher_id = PyDict_AddWatcher(cinder_dict_watcher);
+  int watcher_id = PyDict_AddWatcher([](
+      PyDict_WatchEvent event,
+      PyObject* dict,
+      PyObject* key,
+      PyObject* new_value) {
+    switch (event) {
+      case PyDict_EVENT_ADDED:
+      case PyDict_EVENT_MODIFIED:
+      case PyDict_EVENT_DELETED:
+        if (!PyUnicode_CheckExact(key)) {
+          _PyJIT_NotifyDictUnwatch(dict);
+        } else {
+          _PyJIT_NotifyDictKey(dict, key, new_value);
+          _PyClassLoader_NotifyDictChange((PyDictObject *)dict, key);
+        }
+        break;
+      case PyDict_EVENT_CLEARED:
+        _PyJIT_NotifyDictClear(dict);
+        break;
+      case PyDict_EVENT_CLONED:
+      case PyDict_EVENT_DEALLOCATED:
+        _PyJIT_NotifyDictUnwatch(dict);
+        break;
+    }
+    return 0;
+  });
   if (watcher_id < 0) {
     return -1;
   }
@@ -62,17 +61,12 @@ void Cinder_UnwatchDict(PyObject* dict) {
   }
 }
 
-// actually including shadowcode.h from cpp throws lots of errors
-extern "C" void _PyShadow_TypeModified(PyTypeObject *type);
-
-static int cinder_type_watcher(PyTypeObject* type) {
-  _PyShadow_TypeModified(type);
-  _PyJIT_TypeModified(type);
-  return 0;
-}
-
 static int cinder_install_type_watcher() {
-  int watcher_id = PyType_AddWatcher(cinder_type_watcher);
+  int watcher_id = PyType_AddWatcher([](PyTypeObject* type) {
+    _PyShadow_TypeModified(type);
+    _PyJIT_TypeModified(type);
+    return 0;
+  });
   if (watcher_id < 0) {
     return -1;
   }
@@ -88,57 +82,44 @@ void Cinder_UnwatchType(PyTypeObject* type) {
   PyType_Unwatch(cinder_type_watcher_id, (PyObject *)type);
 }
 
-static int cinder_func_watcher(
-    PyFunction_WatchEvent event,
-    PyFunctionObject* func,
-    PyObject* new_value) {
-  switch (event) {
-    case PyFunction_EVENT_CREATE:
-      PyEntry_init(func);
-      break;
-    case PyFunction_EVENT_MODIFY_CODE:
-      _PyJIT_FuncModified(func);
-      // having deopted the func, we want to immediately consider recompiling.
-      // func_set_code will assign this again later, but we do it early so
-      // PyEntry_init can consider the new code object now
-      Py_INCREF(new_value);
-      Py_XSETREF(func->func_code, new_value);
-      PyEntry_init(func);
-      break;
-    case PyFunction_EVENT_MODIFY_DEFAULTS:
-      break;
-    case PyFunction_EVENT_MODIFY_KWDEFAULTS:
-      break;
-    case PyFunction_EVENT_MODIFY_QUALNAME:
-      // allow reconsideration of whether this function should be compiled
-      if (!_PyJIT_IsCompiled((PyObject*)func)) {
-        // func_set_qualname will assign this again, but we need to assign it
-        // now so that PyEntry_init can consider the new qualname
+static int cinder_install_func_watcher() {
+  int watcher_id = PyFunction_AddWatcher([](
+      PyFunction_WatchEvent event,
+      PyFunctionObject* func,
+      PyObject* new_value) {
+    switch (event) {
+      case PyFunction_EVENT_CREATE:
+        PyEntry_init(func);
+        break;
+      case PyFunction_EVENT_MODIFY_CODE:
+        _PyJIT_FuncModified(func);
+        // having deopted the func, we want to immediately consider recompiling.
+        // func_set_code will assign this again later, but we do it early so
+        // PyEntry_init can consider the new code object now
         Py_INCREF(new_value);
-        Py_XSETREF(func->func_qualname, new_value);
+        Py_XSETREF(func->func_code, new_value);
         PyEntry_init(func);
-      }
-      break;
-    case PyFunction_EVENT_DESTROY:
-      _PyJIT_FuncDestroyed(func);
-      break;
-  }
-  return 0;
-}
-
-static int init_funcs_visitor(PyObject* obj, void*) {
-  if (PyFunction_Check(obj)) {
-    PyEntry_init((PyFunctionObject*)obj);
-  }
-  return 1;
-}
-
-static void init_already_existing_funcs() {
-  PyUnstable_GC_VisitObjects(init_funcs_visitor, NULL);
-}
-
-static int cinder_install_func_watcher() {
-  int watcher_id = PyFunction_AddWatcher(cinder_func_watcher);
+        break;
+      case PyFunction_EVENT_MODIFY_DEFAULTS:
+        break;
+      case PyFunction_EVENT_MODIFY_KWDEFAULTS:
+        break;
+      case PyFunction_EVENT_MODIFY_QUALNAME:
+        // allow reconsideration of whether this function should be compiled
+        if (!_PyJIT_IsCompiled((PyObject*)func)) {
+          // func_set_qualname will assign this again, but we need to assign it
+          // now so that PyEntry_init can consider the new qualname
+          Py_INCREF(new_value);
+          Py_XSETREF(func->func_qualname, new_value);
+          PyEntry_init(func);
+        }
+        break;
+      case PyFunction_EVENT_DESTROY:
+        _PyJIT_FuncDestroyed(func);
+        break;
+    }
+    return 0;
+  });
   if (watcher_id < 0) {
     return -1;
   }
@@ -146,19 +127,23 @@ static int cinder_install_func_watcher() {
   return 0;
 }
 
-// actually including shadowcode.h from cpp throws lots of errors
-extern "C" void _PyShadow_ClearCache(PyObject *co);
-
-static int cinder_code_watcher(PyCodeEvent event, PyCodeObject* co) {
-  if (event == PY_CODE_EVENT_DESTROY) {
-    _PyShadow_ClearCache((PyObject *)co);
-    _PyJIT_CodeDestroyed(co);
-  }
-  return 0;
+static void init_already_existing_funcs() {
+  PyUnstable_GC_VisitObjects([](PyObject* obj, void*){
+    if (PyFunction_Check(obj)) {
+      PyEntry_init((PyFunctionObject*)obj);
+    }
+    return 1;
+  }, nullptr);
 }
 
 static int cinder_install_code_watcher() {
-  int watcher_id = PyCode_AddWatcher(cinder_code_watcher);
+  int watcher_id = PyCode_AddWatcher([](PyCodeEvent event, PyCodeObject* co) {
+    if (event == PY_CODE_EVENT_DESTROY) {
+      _PyShadow_ClearCache((PyObject *)co);
+      _PyJIT_CodeDestroyed(co);
+    }
+    return 0;
+  });
   if (watcher_id < 0) {
     return -1;
   }
@@ -166,15 +151,13 @@ static int cinder_install_code_watcher() {
   return 0;
 }
 
-static int init_types_visitor(PyObject* obj, void*) {
-  if (PyType_Check(obj) && PyType_HasFeature((PyTypeObject*)obj, Py_TPFLAGS_READY)) {
-    _PyJIT_TypeCreated((PyTypeObject*)obj);
-  }
-  return 1;
-}
-
 static void init_already_existing_types() {
-  PyUnstable_GC_VisitObjects(init_types_visitor, NULL);
+  PyUnstable_GC_VisitObjects([](PyObject* obj, void*) {
+    if (PyType_Check(obj) && PyType_HasFeature((PyTypeObject*)obj, Py_TPFLAGS_READY)) {
+      _PyJIT_TypeCreated((PyTypeObject*)obj);
+    }
+    return 1;
+  }, nullptr);
 }
 
 int Cinder_Init() {
@@ -202,7 +185,7 @@ int Cinder_Init() {
   //
   // TODO(T168696266): Remove this once we migrate to cinderx.
   PyObject *res = Cinder_GetParallelGCSettings();
-  if (res == NULL) {
+  if (res == nullptr) {
     return -1;
   }
   Py_DECREF(res);
diff --git a/Shadowcode/shadowcode.h b/Shadowcode/shadowcode.h
index b1a46942272..ee3daf1bceb 100644
--- a/Shadowcode/shadowcode.h
+++ b/Shadowcode/shadowcode.h
@@ -483,6 +483,9 @@ _PyShadow_TrySplitDictLookup(_PyShadow_InstanceAttrEntry *entry,
                              PyObject *dict,
                              int opcode)
 {
+    // opcode may not be used if INLINE_CACHE_PROFILE is not defined.
+    (void)opcode;
+
     PyDictObject *dictobj = (PyDictObject *)dict;
     if (_Py_LIKELY(dictobj != NULL)) {
         if (!_PyDict_HasSplitTable(dictobj)) {