From e4622d5696e8e7d0e68b8f1ff25d3eaf41fb2ed1 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 7 Jun 2001 19:43:18 +0000 Subject: [PATCH] add in_interpreter flag --- dtool/Config.pp | 10 +++ dtool/LocalSetup.pp | 3 + dtool/pptempl/Global.pp | 9 +- dtool/pptempl/Template.gmsvc.pp | 2 +- dtool/pptempl/Template.msvc.pp | 2 +- dtool/pptempl/Template.unix.pp | 12 ++- dtool/src/interrogate/interrogate.cxx | 12 +++ dtool/src/interrogate/interrogate.h | 1 + dtool/src/interrogate/interrogate_module.cxx | 19 ++++- dtool/src/interrogate/parse_file.cxx | 3 +- .../src/interrogate/wrapperBuilderPython.cxx | 15 ++++ .../src/interrogatedb/interrogate_request.cxx | 4 + dtool/src/interrogatedb/interrogate_request.h | 85 ++++++++++++------- 13 files changed, 134 insertions(+), 43 deletions(-) diff --git a/dtool/Config.pp b/dtool/Config.pp index e688f0c480..cb71734aca 100644 --- a/dtool/Config.pp +++ b/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 diff --git a/dtool/LocalSetup.pp b/dtool/LocalSetup.pp index 8b344151c8..143555a60c 100644 --- a/dtool/LocalSetup.pp +++ b/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] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index f46a6c4204..9008d60791 100644 --- a/dtool/pptempl/Global.pp +++ b/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 diff --git a/dtool/pptempl/Template.gmsvc.pp b/dtool/pptempl/Template.gmsvc.pp index b51eeb1963..61af8c2a88 100644 --- a/dtool/pptempl/Template.gmsvc.pp +++ b/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] diff --git a/dtool/pptempl/Template.msvc.pp b/dtool/pptempl/Template.msvc.pp index 79f6c82d37..19d40fa4d0 100644 --- a/dtool/pptempl/Template.msvc.pp +++ b/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] diff --git a/dtool/pptempl/Template.unix.pp b/dtool/pptempl/Template.unix.pp index f3c7b2a33b..10582f4e8e 100644 --- a/dtool/pptempl/Template.unix.pp +++ b/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] diff --git a/dtool/src/interrogate/interrogate.cxx b/dtool/src/interrogate/interrogate.cxx index b986ad16da..4c72efebf8 100644 --- a/dtool/src/interrogate/interrogate.cxx +++ b/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; diff --git a/dtool/src/interrogate/interrogate.h b/dtool/src/interrogate/interrogate.h index c42afbf6d3..45c30d7d7a 100644 --- a/dtool/src/interrogate/interrogate.h +++ b/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; diff --git a/dtool/src/interrogate/interrogate_module.cxx b/dtool/src/interrogate/interrogate_module.cxx index 7332ead3cb..9b2eb6eeb9 100644 --- a/dtool/src/interrogate/interrogate_module.cxx +++ b/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 \n\n" - << "\n#include \n\n"; + out << "\n#include \n" + << "#include \n\n" + << "#include \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); } diff --git a/dtool/src/interrogate/parse_file.cxx b/dtool/src/interrogate/parse_file.cxx index f7ab66a154..a7106aeb15 100644 --- a/dtool/src/interrogate/parse_file.cxx +++ b/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) { diff --git a/dtool/src/interrogate/wrapperBuilderPython.cxx b/dtool/src/interrogate/wrapperBuilderPython.cxx index 5cb3a9ab99..9792ed8ce5 100644 --- a/dtool/src/interrogate/wrapperBuilderPython.cxx +++ b/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); diff --git a/dtool/src/interrogatedb/interrogate_request.cxx b/dtool/src/interrogatedb/interrogate_request.cxx index 5acc871eaf..3b026f812c 100644 --- a/dtool/src/interrogatedb/interrogate_request.cxx +++ b/dtool/src/interrogatedb/interrogate_request.cxx @@ -21,6 +21,10 @@ #include // for strdup +#ifdef TRACK_IN_INTERPRETER +int in_interpreter = false; +#endif + void interrogate_request_database(const char *database_filename) { InterrogateModuleDef *def = new InterrogateModuleDef; diff --git a/dtool/src/interrogatedb/interrogate_request.h b/dtool/src/interrogatedb/interrogate_request.h index d771fa36b8..db78803c14 100644 --- a/dtool/src/interrogatedb/interrogate_request.h +++ b/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 -// panda3d@yahoogroups.com . -// -//////////////////////////////////////////////////////////////////// +/* 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 + * panda3d@yahoogroups.com . + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #ifndef INTERROGATE_REQUEST #define INTERROGATE_REQUEST #include -// 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 }