Sfoglia il codice sorgente

add in_interpreter flag

David Rose 24 anni fa
parent
commit
e4622d5696

+ 10 - 0
dtool/Config.pp

@@ -132,6 +132,16 @@
 #define PYTHON_LPATH
 #defer HAVE_PYTHON $[isdir $[PYTHON_IPATH]]
 
+// Do you want to enable the "in_interpreter" global variable?  This
+// will enable some callbacks, particularly the MemoryUsage object, to
+// know whether they were called from Python code (or other high-level
+// show code) and react accordingly, generally for debugging
+// purporses.  It adds a bit of runtime overhead, and isn't usually
+// useful unless we're building a debug tree anyway.  The default is
+// to enable it only for optimize levels 1 and 2.
+#defer TRACK_IN_INTERPRETER $[<= $[OPTIMIZE], 2]
+
+
 // Is NSPR installed, and where?  This is the Netscape Portable
 // Runtime library, downloadable as part of the Mozilla package from
 // mozilla.org.  It provides portable threading and networking

+ 3 - 0
dtool/LocalSetup.pp

@@ -31,6 +31,9 @@ $[cdefine HAVE_DINKUM]
 /* Define if we have Python installed.  */
 $[cdefine HAVE_PYTHON]
 
+/* Define if we have want to track callbacks from within the show code.  */
+$[cdefine TRACK_IN_INTERPRETER]
+
 /* Define if we have NSPR installed.  */
 $[cdefine HAVE_NSPR]
 

+ 7 - 2
dtool/pptempl/Global.pp

@@ -739,9 +739,14 @@ Warning: Variable $[upcase $[tree]]_INSTALL is not set!
     $[filter -D%,$[C++FLAGS]] \
     $[INTERROGATE_OPTIONS] \
     $[if $[INTERROGATE_PYTHON_INTERFACE],-python] \
-    $[if $[<= $[OPTIMIZE], 1],-spam] \
-    $[if $[INTERROGATE_C_INTERFACE],-c]
+    $[if $[INTERROGATE_C_INTERFACE],-c] \
+    $[if $[TRACK_IN_INTERPRETER],-track-interpreter] \
+    $[if $[<= $[OPTIMIZE], 1],-spam]
 
+#defer interrogate_module_options \
+    $[if $[INTERROGATE_PYTHON_INTERFACE],-python] \
+    $[if $[INTERROGATE_C_INTERFACE],-c] \
+    $[if $[TRACK_IN_INTERPRETER],-track-interpreter]
 
 
 // Include the global definitions for this particular build_type, if

+ 1 - 1
dtool/pptempl/Template.gmsvc.pp

@@ -494,7 +494,7 @@ lib$[TARGET]_igatemscan = $[igatemscan]
 #define target $[so_dir]/$[igatemout]
 #define sources $(lib$[TARGET]_igatemscan)
 $[target] : $[sources] $[so_dir]/stamp
-$[TAB] interrogate_module -oc $[target] -module "$[igatemod]" -library "$[igatelib]" -python $[sources]
+$[TAB] interrogate_module -oc $[target] -module "$[igatemod]" -library "$[igatelib]" $[interrogate_module_options] $[sources]
 
 #define target $[igatemout:%.cxx=$[so_dir]/%.obj]
 #define source $[so_dir]/$[igatemout]

+ 1 - 1
dtool/pptempl/Template.msvc.pp

@@ -465,7 +465,7 @@ lib$[TARGET]_igatemscan = $[osfilename $[igatemscan]]
 #define target $[so_dir]\$[igatemout]
 #define sources $(lib$[TARGET]_igatemscan)
 $[target] : $[sources]
-$[TAB] interrogate_module -oc $[target] -module "$[igatemod]" -library "$[igatelib]" -python $[sources]
+$[TAB] interrogate_module -oc $[target] -module "$[igatemod]" -library "$[igatelib]" $[interrogate_module_options] $[sources]
 
 #define target $[igatemout:%.cxx=$[so_dir]\%.obj]
 #define source $[so_dir]\$[igatemout]

+ 10 - 2
dtool/pptempl/Template.unix.pp

@@ -260,7 +260,15 @@ $[TAB]@test -d $[directory] || mkdir -p $[directory]
 // Now it's time to start generating the rules to make our actual
 // targets.
 
-igate : $[get_igatedb(metalib_target lib_target ss_lib_target):%=$[so_dir]/%]
+// Determine which files will be generated during the interrogate
+// pass, and make a special "igate" rule to generate all of them.
+#define build_igate
+#forscopes metalib_target lib_target ss_lib_target
+  #define igatemscan $[components $[get_igatedb],$[active_component_libs]]
+  #define igatemout $[if $[igatemscan],lib$[TARGET]_module.cxx]
+  #set build_igate $[build_igate] $[get_igatedb:%=$[so_dir]/%] $[igatemout:%=$[so_dir]/%]
+#end metalib_target lib_target ss_lib_target
+igate : $[sort $[build_igate]]
 
 
 /////////////////////////////////////////////////////////////////////
@@ -375,7 +383,7 @@ lib$[TARGET]_igatemscan = $[igatemscan]
 #define target $[so_dir]/$[igatemout]
 #define sources $(lib$[TARGET]_igatemscan)
 $[target] : $[sources]
-$[TAB]interrogate_module -oc $[target] -module "$[igatemod]" -library "$[igatelib]" -python $[sources]
+$[TAB]interrogate_module -oc $[target] -module "$[igatemod]" -library "$[igatelib]" $[interrogate_module_options] $[sources]
 
 #define target $[igatemout:%.cxx=$[so_dir]/%.o]
 #define source $[so_dir]/$[igatemout]

+ 12 - 0
dtool/src/interrogate/interrogate.cxx

@@ -46,6 +46,7 @@ bool watch_asserts = false;
 bool true_wrapper_names = false;
 bool build_c_wrappers = false;
 bool build_python_wrappers = false;
+bool track_interpreter = false;
 bool save_unique_names = false;
 bool no_database = false;
 bool generate_spam = false;
@@ -72,6 +73,7 @@ enum CommandOptions {
   CO_true_names,
   CO_c,
   CO_python,
+  CO_track_interpreter,
   CO_unique_names,
   CO_nodb,
   CO_longlong,
@@ -94,6 +96,7 @@ static struct option long_options[] = {
   { "true-names", no_argument, NULL, CO_true_names },
   { "c", no_argument, NULL, CO_c },
   { "python", no_argument, NULL, CO_python },
+  { "track-interpreter", no_argument, NULL, CO_track_interpreter },
   { "unique-names", no_argument, NULL, CO_unique_names },
   { "nodb", no_argument, NULL, CO_nodb },
   { "longlong", required_argument, NULL, CO_longlong },
@@ -231,6 +234,11 @@ void show_help() {
     << "  Either or both of -c and/or -python may be specified.  If both are\n"
     << "  omitted, the default is -c.\n\n"
 
+    << "  -track-interpreter\n"
+    << "        Generate code within each wrapper function to adjust the global\n"
+    << "        variable \"in_interpreter\" to indicated whether code is running\n"
+    << "        within the Panda C++ environment or within the high-level language.\n"
+
     << "  -unique-names\n"
     << "        Compile a table into the library (i.e. generate code into the -oc\n"
     << "        file) that defines a lookup of each function wrapper by its unique\n"
@@ -361,6 +369,10 @@ main(int argc, char *argv[]) {
       build_python_wrappers = true;
       break;
 
+    case CO_track_interpreter:
+      track_interpreter = true;
+      break;
+
     case CO_unique_names:
       save_unique_names = true;
       break;

+ 1 - 0
dtool/src/interrogate/interrogate.h

@@ -40,6 +40,7 @@ extern bool watch_asserts;
 extern bool true_wrapper_names;
 extern bool build_c_wrappers;
 extern bool build_python_wrappers;
+extern bool track_python;
 extern bool save_unique_names;
 extern bool no_database;
 extern bool generate_spam;

+ 15 - 4
dtool/src/interrogate/interrogate_module.cxx

@@ -40,6 +40,7 @@ string module_name;
 string library_name;
 bool build_c_wrappers = false;
 bool build_python_wrappers = false;
+bool track_interpreter = false;
 
 // Short command-line options.
 static const char *short_options = "";
@@ -51,6 +52,7 @@ enum CommandOptions {
   CO_library,
   CO_c,
   CO_python,
+  CO_track_interpreter,
 };
 
 static struct option long_options[] = {
@@ -59,6 +61,7 @@ static struct option long_options[] = {
   { "library", required_argument, NULL, CO_library },
   { "c", no_argument, NULL, CO_c },
   { "python", no_argument, NULL, CO_python },
+  { "track-interpreter", no_argument, NULL, CO_track_interpreter },
   { NULL }
 };
 
@@ -77,8 +80,9 @@ upcase_string(const string &str) {
 
 int
 write_python_table(ostream &out) {
-  out << "\n#include <dtoolbase.h>\n\n"
-      << "\n#include <Python.h>\n\n";
+  out << "\n#include <dtoolbase.h>\n"
+      << "#include <interrogate_request.h>\n\n"
+      << "#include <Python.h>\n\n";
 
   int count = 0;
 
@@ -160,8 +164,11 @@ write_python_table(ostream &out) {
       << "extern \"C\" void init" << library_name << "();\n"
       << "#endif\n\n"
 
-      << "void init" << library_name << "() {\n"
-      << "  Py_InitModule(\"" << library_name << "\", python_methods);\n"
+      << "void init" << library_name << "() {\n";
+  if (track_interpreter) {
+    out << "  in_interpreter = 1;\n";
+  }
+  out << "  Py_InitModule(\"" << library_name << "\", python_methods);\n"
       << "}\n\n";
 
   return count;
@@ -196,6 +203,10 @@ main(int argc, char *argv[]) {
       build_python_wrappers = true;
       break;
 
+    case CO_track_interpreter:
+      track_interpreter = true;
+      break;
+
     default:
       exit(1);
     }

+ 2 - 1
dtool/src/interrogate/parse_file.cxx

@@ -71,7 +71,8 @@ show_type_or_expression(const string &str) {
     CPPType *type = parser.parse_type(str);
     if (type != NULL) {
       cout << "\nType: " << *type << "\n"
-           << "Defined in: " << type->_file << "\n\n";
+           << "Defined in: " << type->_file << "\n"
+           << "Subtype code is: " << (int)type->get_subtype() << "\n\n";
 
       CPPStructType *stype = type->as_struct_type();
       if (stype != (CPPStructType *)NULL) {

+ 15 - 0
dtool/src/interrogate/wrapperBuilderPython.cxx

@@ -144,6 +144,10 @@ write_wrapper(ostream &out, const string &wrapper_name) const {
   out << "  if (PyArg_ParseTuple(args, \"" << format_specifiers
       << "\"" << parameter_list << ")) {\n";
 
+  if (track_interpreter) {
+    out << "    in_interpreter = 0;\n";
+  }
+
   if (_return_type->new_type_is_atomic_string()) {
     // Treat strings as a special case.  We don't want to format the
     // return expression.
@@ -153,6 +157,11 @@ write_wrapper(ostream &out, const string &wrapper_name) const {
     out << "    ";
     type->output_instance(out, "return_value", &parser);
     out << " = " << return_expr << ";\n";
+
+    if (track_interpreter) {
+      out << "    in_interpreter = 1;\n";
+    }
+
     return_expr = manage_return_value(out, 4, "return_value");
     test_assert(out, 4);
     pack_return_value(out, return_expr);
@@ -160,6 +169,9 @@ write_wrapper(ostream &out, const string &wrapper_name) const {
   } else {
     string return_expr = call_function(out, 4, true, pexprs);
     if (return_expr.empty()) {
+      if (track_interpreter) {
+        out << "    in_interpreter = 1;\n";
+      }
       test_assert(out, 4);
       out << "    return Py_BuildValue(\"\");\n";
 
@@ -168,6 +180,9 @@ write_wrapper(ostream &out, const string &wrapper_name) const {
       out << "    ";
       type->output_instance(out, "return_value", &parser);
       out << " = " << return_expr << ";\n";
+      if (track_interpreter) {
+        out << "    in_interpreter = 1;\n";
+      }
 
       return_expr = manage_return_value(out, 4, "return_value");
       test_assert(out, 4);

+ 4 - 0
dtool/src/interrogatedb/interrogate_request.cxx

@@ -21,6 +21,10 @@
 
 #include <string.h>  // for strdup
 
+#ifdef TRACK_IN_INTERPRETER
+int in_interpreter = false;
+#endif
+
 void
 interrogate_request_database(const char *database_filename) {
   InterrogateModuleDef *def = new InterrogateModuleDef;

+ 53 - 32
dtool/src/interrogatedb/interrogate_request.h

@@ -1,33 +1,35 @@
-// Filename: interrogate_request.h
-// Created by:  drose (01Aug00)
-//
-////////////////////////////////////////////////////////////////////
-//
-// PANDA 3D SOFTWARE
-// Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
-//
-// All use of this software is subject to the terms of the Panda 3d
-// Software license.  You should have received a copy of this license
-// along with this source code; you will also find a current copy of
-// the license at http://www.panda3d.org/license.txt .
-//
-// To contact the maintainers of this program write to
-// [email protected] .
-//
-////////////////////////////////////////////////////////////////////
+/* Filename: interrogate_request.h
+ * Created by:  drose (01Aug00)
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ * PANDA 3D SOFTWARE
+ * Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
+ *
+ * All use of this software is subject to the terms of the Panda 3d
+ * Software license.  You should have received a copy of this license
+ * along with this source code; you will also find a current copy of
+ * the license at http://www.panda3d.org/license.txt .
+ *
+ * To contact the maintainers of this program write to
+ * [email protected] .
+ *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
 
 #ifndef INTERROGATE_REQUEST
 #define INTERROGATE_REQUEST
 
 #include <dtoolbase.h>
 
-// The functions here are simple functions that are intended to be
-// called during static init time for the various libraries that
-// contain interrogate data.  They provide interfaces to add the
-// module's interrogate data to the main interrogate database.
-
-// The interface is entirely C here--no C++--so that it may be called
-// from C modules if required.
+/*
+ * The functions here are simple functions that are intended to be
+ * called during static init time for the various libraries that
+ * contain interrogate data.  They provide interfaces to add the
+ * module's interrogate data to the main interrogate database.
+ *
+ * The interface is entirely C here--no C++--so that it may be called
+ * from C modules if required.
+ */
 
 
 #ifdef __cplusplus
@@ -35,15 +37,17 @@ extern "C" {
 #endif
 
 
-// This is the simplest interface.  It just requests that the given
-// database filename (*.in) be read in.  This makes the interrogate
-// data available, but doesn't allow matching the database information
-// up with any compiled-in function wrappers or anything.
+/*
+ * This is the simplest interface.  It just requests that the given
+ * database filename (*.in) be read in.  This makes the interrogate
+ * data available, but doesn't allow matching the database information
+ * up with any compiled-in function wrappers or anything.
+ */
 EXPCL_DTOOLCONFIG void interrogate_request_database(const char *database_filename);
 
 
 
-// The more sophisticated interface uses these structures.
+/* The more sophisticated interface uses these structures. */
 
 typedef struct {
   const char *name;
@@ -69,11 +73,28 @@ typedef struct {
 } InterrogateModuleDef;
 
 
-// This requests that the given module be loaded and made available.
-// This includes all of the function pointers and/or unique names that
-// might be compiled in.
+/*
+ * This requests that the given module be loaded and made available.
+ * This includes all of the function pointers and/or unique names that
+ * might be compiled in.
+ */
 EXPCL_DTOOLCONFIG void interrogate_request_module(InterrogateModuleDef *def);
 
+#ifdef TRACK_IN_INTERPRETER
+/* 
+ * If we're tracking whether we're currently running in Python code
+ * (mainly for the purpose of debug logging from memory allocation
+ * callbacks), this variable will record that state.  It will be set
+ * true whenever we return to Python code, and false whenever we are
+ * entering local C or C++ code.  The flag will be toggled off and
+ * on within each generated Python wrapper function.
+ *
+ * This will mis-categorize some code that runs at static
+ * initialization time, but it will correctly identify the vast
+ * majority of code.
+ */
+EXPCL_DTOOLCONFIG extern int in_interpreter;
+#endif  // TRACK_IN_INTERPRETER
 
 #ifdef __cplusplus
 }