Browse Source

P3D_object needs to be reference-counted

David Rose 16 years ago
parent
commit
fbf81f90eb

+ 4 - 4
direct/src/plugin/p3dBoolObject.cxx

@@ -41,7 +41,7 @@ P3DBoolObject(const P3DBoolObject &copy) :
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DBoolObject::
 P3D_object_type P3DBoolObject::
-get_type() const {
+get_type() {
   return P3D_OT_bool;
   return P3D_OT_bool;
 }
 }
 
 
@@ -52,7 +52,7 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DBoolObject::
 bool P3DBoolObject::
-get_bool() const {
+get_bool() {
   return _value;
   return _value;
 }
 }
 
 
@@ -63,7 +63,7 @@ get_bool() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DBoolObject::
 int P3DBoolObject::
-get_int() const {
+get_int() {
   return _value;
   return _value;
 }
 }
 
 
@@ -74,7 +74,7 @@ get_int() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DBoolObject::
 void P3DBoolObject::
-make_string(string &value) const {
+make_string(string &value) {
   if (_value) {
   if (_value) {
     value = "True";
     value = "True";
   } else {
   } else {

+ 4 - 4
direct/src/plugin/p3dBoolObject.h

@@ -28,10 +28,10 @@ public:
   P3DBoolObject(const P3DBoolObject &copy);
   P3DBoolObject(const P3DBoolObject &copy);
 
 
 public:
 public:
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual int get_int() const;
-  virtual void make_string(string &value) const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual int get_int();
+  virtual void make_string(string &value);
 
 
 private:
 private:
   bool _value;
   bool _value;

+ 5 - 5
direct/src/plugin/p3dFloatObject.cxx

@@ -41,7 +41,7 @@ P3DFloatObject(const P3DFloatObject &copy) :
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DFloatObject::
 P3D_object_type P3DFloatObject::
-get_type() const {
+get_type() {
   return P3D_OT_float;
   return P3D_OT_float;
 }
 }
 
 
@@ -52,7 +52,7 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DFloatObject::
 bool P3DFloatObject::
-get_bool() const {
+get_bool() {
   return (_value != 0.0);
   return (_value != 0.0);
 }
 }
 
 
@@ -63,7 +63,7 @@ get_bool() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DFloatObject::
 int P3DFloatObject::
-get_int() const {
+get_int() {
   return (int)_value;
   return (int)_value;
 }
 }
 
 
@@ -74,7 +74,7 @@ get_int() const {
 //               value, if possible.
 //               value, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 double P3DFloatObject::
 double P3DFloatObject::
-get_float() const {
+get_float() {
   return _value;
   return _value;
 }
 }
 
 
@@ -85,7 +85,7 @@ get_float() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DFloatObject::
 void P3DFloatObject::
-make_string(string &value) const {
+make_string(string &value) {
   ostringstream strm;
   ostringstream strm;
   strm << _value;
   strm << _value;
   value = strm.str();
   value = strm.str();

+ 5 - 5
direct/src/plugin/p3dFloatObject.h

@@ -28,11 +28,11 @@ public:
   P3DFloatObject(const P3DFloatObject &copy);
   P3DFloatObject(const P3DFloatObject &copy);
 
 
 public:
 public:
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual int get_int() const;
-  virtual double get_float() const;
-  virtual void make_string(string &value) const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual int get_int();
+  virtual double get_float();
+  virtual void make_string(string &value);
 
 
 private:
 private:
   double _value;
   double _value;

+ 43 - 15
direct/src/plugin/p3dInstance.cxx

@@ -73,9 +73,7 @@ P3DInstance::
 ~P3DInstance() {
 ~P3DInstance() {
   assert(_session == NULL);
   assert(_session == NULL);
 
 
-  if (_browser_script_object != NULL) {
-    P3D_OBJECT_FINISH(_browser_script_object);
-  }
+  P3D_OBJECT_XDECREF(_browser_script_object);
 
 
   DESTROY_LOCK(_request_lock);
   DESTROY_LOCK(_request_lock);
 
 
@@ -118,6 +116,7 @@ set_fparams(const P3DFileParams &fparams) {
   strm << inst_mgr->get_unique_session_index();
   strm << inst_mgr->get_unique_session_index();
   _session_key = strm.str();
   _session_key = strm.str();
 
 
+  // TODO.
   _python_version = "python24";
   _python_version = "python24";
 
 
 
 
@@ -200,7 +199,8 @@ get_panda_script_object() const {
   }
   }
 
 
   if (result == NULL) {
   if (result == NULL) {
-    result = new P3DUndefinedObject;
+    P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+    result = inst_mgr->new_undefined_object();
   }
   }
 
 
   return result;
   return result;
@@ -211,16 +211,18 @@ get_panda_script_object() const {
 //       Access: Public
 //       Access: Public
 //  Description: Stores a pointer to the top-level window object
 //  Description: Stores a pointer to the top-level window object
 //               of the browser, to be used by Panda code to control
 //               of the browser, to be used by Panda code to control
-//               JavaScript.  Ownership of this object is passed into
-//               the instance.
+//               JavaScript.  The new object's reference count is
+//               incremented, and the previous object's is
+//               decremented.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DInstance::
 void P3DInstance::
 set_browser_script_object(P3D_object *browser_script_object) {
 set_browser_script_object(P3D_object *browser_script_object) {
   if (browser_script_object != _browser_script_object) {
   if (browser_script_object != _browser_script_object) {
+    P3D_OBJECT_XDECREF(_browser_script_object);
+    _browser_script_object = browser_script_object;
     if (_browser_script_object != NULL) {
     if (_browser_script_object != NULL) {
-      P3D_OBJECT_FINISH(_browser_script_object);
+      P3D_OBJECT_INCREF(_browser_script_object);
     }
     }
-    _browser_script_object = browser_script_object;
 
 
     if (_session != NULL) {
     if (_session != NULL) {
       send_browser_script_object();
       send_browser_script_object();
@@ -317,6 +319,36 @@ void P3DInstance::
 finish_request(P3D_request *request, bool handled) {
 finish_request(P3D_request *request, bool handled) {
   assert(request != NULL);
   assert(request != NULL);
 
 
+  switch (request->_request_type) {
+  case P3D_RT_stop:
+    break;
+
+  case P3D_RT_get_url:
+    free((char *)request->_request._get_url._url);
+    break;
+
+  case P3D_RT_post_url:
+    free((char *)request->_request._post_url._url);
+    free((char *)request->_request._post_url._post_data);
+    break;
+
+  case P3D_RT_notify:
+    free((char *)request->_request._notify._message);
+    break;
+
+  case P3D_RT_script:
+    {
+      P3D_OBJECT_DECREF(request->_request._script._object);
+      if (request->_request._script._property_name != NULL) {
+        free((char *)request->_request._script._property_name);
+      }
+      for (int i = 0; i < request->_request._script._num_values; ++i) {
+        P3D_OBJECT_DECREF(request->_request._script._values[i]);
+      }
+    }
+    break;
+  }
+
   delete request;
   delete request;
 }
 }
 
 
@@ -519,7 +551,7 @@ handle_script_request(P3D_request *request) {
       doc->LinkEndChild(xcommand);
       doc->LinkEndChild(xcommand);
       if (result != NULL) {
       if (result != NULL) {
         xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
         xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
-        P3D_OBJECT_FINISH(result);
+        P3D_OBJECT_DECREF(result);
       }
       }
 
 
       if (needs_response) {
       if (needs_response) {
@@ -598,10 +630,6 @@ handle_script_request(P3D_request *request) {
         P3D_OBJECT_CALL(object, request->_request._script._property_name,
         P3D_OBJECT_CALL(object, request->_request._script._property_name,
                         request->_request._script._values,
                         request->_request._script._values,
                         request->_request._script._num_values);
                         request->_request._script._num_values);
-      // Reset the value count to 0 so we won't double-delete the
-      // parameter values when the request is deleted (the above call
-      // has already deleted them).
-      request->_request._script._num_values = 0;
 
 
       // Feed the result back down to the subprocess.
       // Feed the result back down to the subprocess.
       TiXmlDocument *doc = new TiXmlDocument;
       TiXmlDocument *doc = new TiXmlDocument;
@@ -615,7 +643,7 @@ handle_script_request(P3D_request *request) {
 
 
       if (result != NULL) {
       if (result != NULL) {
         xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
         xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
-        P3D_OBJECT_FINISH(result);
+        P3D_OBJECT_DECREF(result);
       }
       }
       
       
       if (needs_response) {
       if (needs_response) {
@@ -654,7 +682,7 @@ handle_script_request(P3D_request *request) {
 
 
       if (result != NULL) {
       if (result != NULL) {
         xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
         xcommand->LinkEndChild(_session->p3dobj_to_xml(result));
-        P3D_OBJECT_FINISH(result);
+        P3D_OBJECT_DECREF(result);
       }
       }
 
 
       logfile << "eval  response: " << *doc << "\n";
       logfile << "eval  response: " << *doc << "\n";

+ 37 - 0
direct/src/plugin/p3dInstanceManager.I

@@ -70,3 +70,40 @@ inline int P3DInstanceManager::
 get_num_instances() const {
 get_num_instances() const {
   return _instances.size();
   return _instances.size();
 }
 }
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstanceManager::new_undefined_object
+//       Access: Public
+//  Description: Returns the singleton "undefined" object, as a new
+//               reference.
+////////////////////////////////////////////////////////////////////
+inline P3D_object *P3DInstanceManager::
+new_undefined_object() {
+  P3D_OBJECT_INCREF(_undefined_object);
+  return _undefined_object;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstanceManager::new_none_object
+//       Access: Public
+//  Description: Returns the singleton "none" object, as a new
+//               reference.
+////////////////////////////////////////////////////////////////////
+inline P3D_object *P3DInstanceManager::
+new_none_object() {
+  P3D_OBJECT_INCREF(_none_object);
+  return _none_object;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: P3DInstanceManager::new_bool_object
+//       Access: Public
+//  Description: Returns the singleton "true" or "false" object, as a
+//               new reference.
+////////////////////////////////////////////////////////////////////
+inline P3D_object *P3DInstanceManager::
+new_bool_object(bool value) {
+  P3D_object *obj = (value) ? _true_object : _false_object;
+  P3D_OBJECT_INCREF(obj);
+  return obj;
+}

+ 25 - 0
direct/src/plugin/p3dInstanceManager.cxx

@@ -18,6 +18,9 @@
 #include "p3dPackage.h"
 #include "p3dPackage.h"
 #include "p3d_plugin_config.h"
 #include "p3d_plugin_config.h"
 #include "p3dWinSplashWindow.h"
 #include "p3dWinSplashWindow.h"
+#include "p3dUndefinedObject.h"
+#include "p3dNoneObject.h"
+#include "p3dBoolObject.h"
 #include "find_root_dir.h"
 #include "find_root_dir.h"
 #include "mkdir_complete.h"
 #include "mkdir_complete.h"
 
 
@@ -43,6 +46,12 @@ P3DInstanceManager() {
   _started_notify_thread = false;
   _started_notify_thread = false;
   INIT_THREAD(_notify_thread);
   INIT_THREAD(_notify_thread);
 
 
+  // Initialize the singleton objects.
+  _undefined_object = new P3DUndefinedObject();
+  _none_object = new P3DNoneObject();
+  _true_object = new P3DBoolObject(true);
+  _false_object = new P3DBoolObject(false);
+
 #ifdef _WIN32
 #ifdef _WIN32
   // Ensure the appropriate Windows common controls are available to
   // Ensure the appropriate Windows common controls are available to
   // this application.
   // this application.
@@ -72,6 +81,22 @@ P3DInstanceManager::
   assert(_instances.empty());
   assert(_instances.empty());
   assert(_sessions.empty());
   assert(_sessions.empty());
 
 
+  nout << "counts: " << _undefined_object->_ref_count
+       << " " << _none_object->_ref_count
+       << " " << _true_object->_ref_count
+       << " " << _false_object->_ref_count
+       << "\n" << flush;
+
+  assert(_undefined_object->_ref_count == 1);
+  assert(_none_object->_ref_count == 1);
+  assert(_true_object->_ref_count == 1);
+  assert(_false_object->_ref_count == 1);
+
+  P3D_OBJECT_DECREF(_undefined_object);
+  P3D_OBJECT_DECREF(_none_object);
+  P3D_OBJECT_DECREF(_true_object);
+  P3D_OBJECT_DECREF(_false_object);
+
 #ifdef _WIN32
 #ifdef _WIN32
   P3DWinSplashWindow::unregister_window_class();
   P3DWinSplashWindow::unregister_window_class();
 #endif
 #endif

+ 9 - 0
direct/src/plugin/p3dInstanceManager.h

@@ -66,6 +66,10 @@ public:
 
 
   P3D_class_definition *make_class_definition() const;
   P3D_class_definition *make_class_definition() const;
 
 
+  inline P3D_object *new_undefined_object();
+  inline P3D_object *new_none_object();
+  inline P3D_object *new_bool_object(bool value);
+
   static P3DInstanceManager *get_global_ptr();
   static P3DInstanceManager *get_global_ptr();
   static void delete_global_ptr();
   static void delete_global_ptr();
 
 
@@ -82,6 +86,11 @@ private:
   string _download_url;
   string _download_url;
   string _platform;
   string _platform;
 
 
+  P3D_object *_undefined_object;
+  P3D_object *_none_object;
+  P3D_object *_true_object;
+  P3D_object *_false_object;
+
   typedef set<P3DInstance *> Instances;
   typedef set<P3DInstance *> Instances;
   Instances _instances;
   Instances _instances;
 
 

+ 4 - 4
direct/src/plugin/p3dIntObject.cxx

@@ -41,7 +41,7 @@ P3DIntObject(const P3DIntObject &copy) :
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DIntObject::
 P3D_object_type P3DIntObject::
-get_type() const {
+get_type() {
   return P3D_OT_int;
   return P3D_OT_int;
 }
 }
 
 
@@ -52,7 +52,7 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DIntObject::
 bool P3DIntObject::
-get_bool() const {
+get_bool() {
   return (_value != 0);
   return (_value != 0);
 }
 }
 
 
@@ -63,7 +63,7 @@ get_bool() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DIntObject::
 int P3DIntObject::
-get_int() const {
+get_int() {
   return _value;
   return _value;
 }
 }
 
 
@@ -74,7 +74,7 @@ get_int() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DIntObject::
 void P3DIntObject::
-make_string(string &value) const {
+make_string(string &value) {
   ostringstream strm;
   ostringstream strm;
   strm << _value;
   strm << _value;
   value = strm.str();
   value = strm.str();

+ 4 - 4
direct/src/plugin/p3dIntObject.h

@@ -28,10 +28,10 @@ public:
   P3DIntObject(const P3DIntObject &copy);
   P3DIntObject(const P3DIntObject &copy);
 
 
 public:
 public:
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual int get_int() const;
-  virtual void make_string(string &value) const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual int get_int();
+  virtual void make_string(string &value);
 
 
 private:
 private:
   int _value;
   int _value;

+ 3 - 3
direct/src/plugin/p3dNoneObject.cxx

@@ -29,7 +29,7 @@ P3DNoneObject() {
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DNoneObject::
 P3D_object_type P3DNoneObject::
-get_type() const {
+get_type() {
   return P3D_OT_none;
   return P3D_OT_none;
 }
 }
 
 
@@ -40,7 +40,7 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DNoneObject::
 bool P3DNoneObject::
-get_bool() const {
+get_bool() {
   return false;
   return false;
 }
 }
 
 
@@ -51,6 +51,6 @@ get_bool() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DNoneObject::
 void P3DNoneObject::
-make_string(string &value) const {
+make_string(string &value) {
   value = "None";
   value = "None";
 }
 }

+ 3 - 3
direct/src/plugin/p3dNoneObject.h

@@ -28,9 +28,9 @@ public:
   P3DNoneObject();
   P3DNoneObject();
 
 
 public:
 public:
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual void make_string(string &value) const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual void make_string(string &value);
 };
 };
 
 
 #endif
 #endif

+ 0 - 36
direct/src/plugin/p3dObject.I

@@ -37,39 +37,3 @@ P3DObject(const P3DObject &copy) {
   _class = copy._class;
   _class = copy._class;
   _ref_count = 1;
   _ref_count = 1;
 }
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: P3DObject::ref
-//       Access: Public
-//  Description: Increments the reference count.
-////////////////////////////////////////////////////////////////////
-inline void P3DObject::
-ref() const {
-  ++(((P3DObject *)this)->_ref_count);
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: P3DObject::unref
-//       Access: Public
-//  Description: Decrements the reference count, and returns the new
-//               count.
-////////////////////////////////////////////////////////////////////
-inline int P3DObject::
-unref() const {
-  --(((P3DObject *)this)->_ref_count);
-  return _ref_count;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: P3DObject::unref_delete
-//       Access: Public, Static
-//  Description: Decrements the reference count on the indicated
-//               object, and deletes it if the reference count reaches
-//               zero.
-////////////////////////////////////////////////////////////////////
-inline void P3DObject::
-unref_delete(P3DObject *obj) {
-  if (obj->unref() <= 0) {
-    delete obj;
-  }
-}

+ 42 - 80
direct/src/plugin/p3dObject.cxx

@@ -21,47 +21,42 @@
 // P3D_object structure.
 // P3D_object structure.
 static void
 static void
 object_finish(P3D_object *object) {
 object_finish(P3D_object *object) {
-  P3DObject::unref_delete(((P3DObject *)object));
-}
-
-static P3D_object *
-object_copy(const P3D_object *object) {
-  return ((const P3DObject *)object)->make_copy();
+  delete (P3DObject *)object;
 }
 }
 
 
 static P3D_object_type 
 static P3D_object_type 
-object_get_type(const P3D_object *object) {
-  return ((const P3DObject *)object)->get_type();
+object_get_type(P3D_object *object) {
+  return ((P3DObject *)object)->get_type();
 }
 }
 
 
 static bool 
 static bool 
-object_get_bool(const P3D_object *object) {
-  return ((const P3DObject *)object)->get_bool();
+object_get_bool(P3D_object *object) {
+  return ((P3DObject *)object)->get_bool();
 }
 }
 
 
 static int
 static int
-object_get_int(const P3D_object *object) {
-  return ((const P3DObject *)object)->get_int();
+object_get_int(P3D_object *object) {
+  return ((P3DObject *)object)->get_int();
 }
 }
 
 
 static double 
 static double 
-object_get_float(const P3D_object *object) {
-  return ((const P3DObject *)object)->get_float();
+object_get_float(P3D_object *object) {
+  return ((P3DObject *)object)->get_float();
 }
 }
 
 
 static int 
 static int 
-object_get_string(const P3D_object *object, char *buffer, int buffer_length) {
-  return ((const P3DObject *)object)->get_string(buffer, buffer_length);
+object_get_string(P3D_object *object, char *buffer, int buffer_length) {
+  return ((P3DObject *)object)->get_string(buffer, buffer_length);
 }
 }
 
 
 static int 
 static int 
-object_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
-  return ((const P3DObject *)object)->get_repr(buffer, buffer_length);
+object_get_repr(P3D_object *object, char *buffer, int buffer_length) {
+  return ((P3DObject *)object)->get_repr(buffer, buffer_length);
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-object_get_property(const P3D_object *object, const char *property) {
-  return ((const P3DObject *)object)->get_property(property);
+object_get_property(P3D_object *object, const char *property) {
+  return ((P3DObject *)object)->get_property(property);
 }
 }
 
 
 static bool
 static bool
@@ -71,27 +66,26 @@ object_set_property(P3D_object *object, const char *property,
 }
 }
 
 
 static bool
 static bool
-object_has_method(const P3D_object *object, const char *method_name) {
-  return ((const P3DObject *)object)->has_method(method_name);
+object_has_method(P3D_object *object, const char *method_name) {
+  return ((P3DObject *)object)->has_method(method_name);
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-object_call(const P3D_object *object, const char *method_name,
+object_call(P3D_object *object, const char *method_name,
             P3D_object *params[], int num_params) {
             P3D_object *params[], int num_params) {
   if (method_name == NULL) {
   if (method_name == NULL) {
     method_name = "";
     method_name = "";
   }
   }
-  return ((const P3DObject *)object)->call(method_name, params, num_params);
+  return ((P3DObject *)object)->call(method_name, params, num_params);
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-object_eval(const P3D_object *object, const char *expression) {
-  return ((const P3DObject *)object)->eval(expression);
+object_eval(P3D_object *object, const char *expression) {
+  return ((P3DObject *)object)->eval(expression);
 }
 }
 
 
 P3D_class_definition P3DObject::_object_class = {
 P3D_class_definition P3DObject::_object_class = {
   &object_finish,
   &object_finish,
-  &object_copy,
   &object_get_type,
   &object_get_type,
   &object_get_bool,
   &object_get_bool,
   &object_get_int,
   &object_get_int,
@@ -116,14 +110,8 @@ generic_finish(P3D_object *object) {
   nout << "Warning!  default object_finish() method does nothing; object will leak.\n" << flush;
   nout << "Warning!  default object_finish() method does nothing; object will leak.\n" << flush;
 }
 }
 
 
-static P3D_object *
-generic_copy(const P3D_object *object) {
-  nout << "Warning!  default object_copy() method does nothing; object pointer will be shared.\n" << flush;
-  return (P3D_object *)object;
-}
-
 static P3D_object_type 
 static P3D_object_type 
-generic_get_type(const P3D_object *object) {
+generic_get_type(P3D_object *object) {
   // We assume anyone going through the trouble of subclassing this
   // We assume anyone going through the trouble of subclassing this
   // will want to return an object, not one of the other fundamental
   // will want to return an object, not one of the other fundamental
   // types.
   // types.
@@ -131,66 +119,59 @@ generic_get_type(const P3D_object *object) {
 }
 }
 
 
 static bool 
 static bool 
-generic_get_bool(const P3D_object *object) {
+generic_get_bool(P3D_object *object) {
   return false;
   return false;
 }
 }
 
 
 static int
 static int
-generic_get_int(const P3D_object *object) {
+generic_get_int(P3D_object *object) {
   return 0;
   return 0;
 }
 }
 
 
 static double 
 static double 
-generic_get_float(const P3D_object *object) {
+generic_get_float(P3D_object *object) {
   return 0.0;
   return 0.0;
 }
 }
 
 
 static int 
 static int 
-generic_get_string(const P3D_object *object, char *buffer, int buffer_length) {
+generic_get_string(P3D_object *object, char *buffer, int buffer_length) {
   return 0;
   return 0;
 }
 }
 
 
 static int 
 static int 
-generic_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
+generic_get_repr(P3D_object *object, char *buffer, int buffer_length) {
   return 0;
   return 0;
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-generic_get_property(const P3D_object *object, const char *property) {
+generic_get_property(P3D_object *object, const char *property) {
   return NULL;
   return NULL;
 }
 }
 
 
 static bool
 static bool
 generic_set_property(P3D_object *object, const char *property,
 generic_set_property(P3D_object *object, const char *property,
                      P3D_object *value) {
                      P3D_object *value) {
-  if (value != NULL) {
-    P3D_OBJECT_FINISH(value);
-  }
   return false;
   return false;
 }
 }
 
 
 static bool
 static bool
-generic_has_method(const P3D_object *object, const char *method_name) {
-  return ((const P3DObject *)object)->has_method(method_name);
+generic_has_method(P3D_object *object, const char *method_name) {
+  return false;
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-generic_call(const P3D_object *object, const char *method_name,
+generic_call(P3D_object *object, const char *method_name,
             P3D_object *params[], int num_params) {
             P3D_object *params[], int num_params) {
-  for (int i = 0; i < num_params; ++i) {
-    P3D_OBJECT_FINISH(params[i]);
-  }
   return NULL;
   return NULL;
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-generic_eval(const P3D_object *object, const char *expression) {
+generic_eval(P3D_object *object, const char *expression) {
   return NULL;
   return NULL;
 }
 }
 
 
 P3D_class_definition P3DObject::_generic_class = {
 P3D_class_definition P3DObject::_generic_class = {
   &generic_finish,
   &generic_finish,
-  &generic_copy,
   &generic_get_type,
   &generic_get_type,
   &generic_get_bool,
   &generic_get_bool,
   &generic_get_int,
   &generic_get_int,
@@ -211,20 +192,7 @@ P3D_class_definition P3DObject::_generic_class = {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3DObject::
 P3DObject::
 ~P3DObject() {
 ~P3DObject() {
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: P3DObject::make_copy
-//       Access: Public, Virtual
-//  Description: Returns a new copy of the object, if necessary.  If
-//               the object type is static and all instances are
-//               identical, this actually simply ups the reference
-//               count and returns the same object.
-////////////////////////////////////////////////////////////////////
-P3DObject *P3DObject::
-make_copy() const {
-  ref();
-  return (P3DObject *)this;
+  assert(_ref_count == 0);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -234,7 +202,7 @@ make_copy() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DObject::
 int P3DObject::
-get_int() const {
+get_int() {
   return 0;
   return 0;
 }
 }
 
 
@@ -245,7 +213,7 @@ get_int() const {
 //               value, if possible.
 //               value, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 double P3DObject::
 double P3DObject::
-get_float() const {
+get_float() {
   return get_int();
   return get_int();
 }
 }
 
 
@@ -260,7 +228,7 @@ get_float() const {
 //               was too small).
 //               was too small).
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DObject::
 int P3DObject::
-get_string(char *buffer, int buffer_length) const {
+get_string(char *buffer, int buffer_length) {
   string result;
   string result;
   make_string(result);
   make_string(result);
   strncpy(buffer, result.c_str(), buffer_length);
   strncpy(buffer, result.c_str(), buffer_length);
@@ -274,7 +242,7 @@ get_string(char *buffer, int buffer_length) const {
 //               similar to get_string(), above.
 //               similar to get_string(), above.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DObject::
 int P3DObject::
-get_repr(char *buffer, int buffer_length) const {
+get_repr(char *buffer, int buffer_length) {
   ostringstream strm;
   ostringstream strm;
   output(strm);
   output(strm);
   string result = strm.str();
   string result = strm.str();
@@ -290,7 +258,7 @@ get_repr(char *buffer, int buffer_length) const {
 //               that must be deleted by the caller, or NULL on error.
 //               that must be deleted by the caller, or NULL on error.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DObject::
 P3D_object *P3DObject::
-get_property(const string &property) const {
+get_property(const string &property) {
   return NULL;
   return NULL;
 }
 }
 
 
@@ -303,9 +271,6 @@ get_property(const string &property) const {
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DObject::
 bool P3DObject::
 set_property(const string &property, P3D_object *value) {
 set_property(const string &property, P3D_object *value) {
-  if (value != NULL) {
-    P3D_OBJECT_FINISH(value);
-  }
   return false;
   return false;
 }
 }
 
 
@@ -316,7 +281,7 @@ set_property(const string &property, P3D_object *value) {
 //               object, false otherwise.
 //               object, false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DObject::
 bool P3DObject::
-has_method(const string &method_name) const {
+has_method(const string &method_name) {
   return false;
   return false;
 }
 }
 
 
@@ -329,10 +294,7 @@ has_method(const string &method_name) const {
 //               on success, NULL on error.
 //               on success, NULL on error.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DObject::
 P3D_object *P3DObject::
-call(const string &method_name, P3D_object *params[], int num_params) const {
-  for (int i = 0; i < num_params; ++i) {
-    P3D_OBJECT_FINISH(params[i]);
-  }
+call(const string &method_name, P3D_object *params[], int num_params) {
   return NULL;
   return NULL;
 }
 }
 
 
@@ -343,7 +305,7 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
 //               of the P3DObject classes implement this.
 //               of the P3DObject classes implement this.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DObject::
 P3D_object *P3DObject::
-eval(const string &expression) const {
+eval(const string &expression) {
   return NULL;
   return NULL;
 }
 }
 
 
@@ -355,7 +317,7 @@ eval(const string &expression) const {
 //               assistance.
 //               assistance.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DObject::
 void P3DObject::
-output(ostream &out) const {
+output(ostream &out) {
   string value;
   string value;
   make_string(value);
   make_string(value);
   out << value;
   out << value;

+ 13 - 21
direct/src/plugin/p3dObject.h

@@ -33,32 +33,24 @@ protected:
 public:
 public:
   virtual ~P3DObject();
   virtual ~P3DObject();
 
 
-  virtual P3DObject *make_copy() const; 
-  virtual P3D_object_type get_type() const=0;
-  virtual bool get_bool() const=0;
-  virtual int get_int() const;
-  virtual double get_float() const;
+  virtual P3D_object_type get_type()=0;
+  virtual bool get_bool()=0;
+  virtual int get_int();
+  virtual double get_float();
 
 
-  int get_string(char *buffer, int buffer_length) const;
-  int get_repr(char *buffer, int buffer_length) const;
-  virtual void make_string(string &value) const=0;
+  int get_string(char *buffer, int buffer_length);
+  int get_repr(char *buffer, int buffer_length);
+  virtual void make_string(string &value)=0;
 
 
-  virtual P3D_object *get_property(const string &property) const;
+  virtual P3D_object *get_property(const string &property);
   virtual bool set_property(const string &property, P3D_object *value);
   virtual bool set_property(const string &property, P3D_object *value);
 
 
-  virtual bool has_method(const string &method_name) const;
+  virtual bool has_method(const string &method_name);
   virtual P3D_object *call(const string &method_name, 
   virtual P3D_object *call(const string &method_name, 
-                           P3D_object *params[], int num_params) const;
-  virtual P3D_object *eval(const string &expression) const;
+                           P3D_object *params[], int num_params);
+  virtual P3D_object *eval(const string &expression);
 
 
-  virtual void output(ostream &out) const;
-
-  inline void ref() const;
-  inline int unref() const;
-  static inline void unref_delete(P3DObject *obj);
-
-private:
-  int _ref_count;
+  virtual void output(ostream &out);
 
 
 public:
 public:
   static P3D_class_definition _object_class;
   static P3D_class_definition _object_class;
@@ -71,7 +63,7 @@ public:
 // virtual method to write the output simply.  (For classes that
 // virtual method to write the output simply.  (For classes that
 // inherit only from P3D_object, we have to use the generic C method
 // inherit only from P3D_object, we have to use the generic C method
 // defined in p3d_plugin_common.h, a little clumsier.)
 // defined in p3d_plugin_common.h, a little clumsier.)
-inline ostream &operator << (ostream &out, const P3DObject &value) {
+inline ostream &operator << (ostream &out, P3DObject &value) {
   value.output(out);
   value.output(out);
   return out;
   return out;
 }
 }

+ 17 - 21
direct/src/plugin/p3dPythonObject.cxx

@@ -42,7 +42,7 @@ P3DPythonObject::
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DPythonObject::
 P3D_object_type P3DPythonObject::
-get_type() const {
+get_type() {
   return P3D_OT_object;
   return P3D_OT_object;
 }
 }
 
 
@@ -53,13 +53,13 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DPythonObject::
 bool P3DPythonObject::
-get_bool() const {
+get_bool() {
   bool bresult = 0;
   bool bresult = 0;
 
 
   P3D_object *result = call("__bool__", NULL, 0);
   P3D_object *result = call("__bool__", NULL, 0);
   if (result != NULL) {
   if (result != NULL) {
     bresult = P3D_OBJECT_GET_BOOL(result);
     bresult = P3D_OBJECT_GET_BOOL(result);
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }    
   }    
 
 
   return bresult;
   return bresult;
@@ -72,13 +72,13 @@ get_bool() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DPythonObject::
 int P3DPythonObject::
-get_int() const {
+get_int() {
   int iresult = 0;
   int iresult = 0;
 
 
   P3D_object *result = call("__int__", NULL, 0);
   P3D_object *result = call("__int__", NULL, 0);
   if (result != NULL) {
   if (result != NULL) {
     iresult = P3D_OBJECT_GET_INT(result);
     iresult = P3D_OBJECT_GET_INT(result);
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }    
   }    
 
 
   return iresult;
   return iresult;
@@ -91,13 +91,13 @@ get_int() const {
 //               value, if possible.
 //               value, if possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 double P3DPythonObject::
 double P3DPythonObject::
-get_float() const {
+get_float() {
   double fresult = 0.0;
   double fresult = 0.0;
 
 
   P3D_object *result = call("__float__", NULL, 0);
   P3D_object *result = call("__float__", NULL, 0);
   if (result != NULL) {
   if (result != NULL) {
     fresult = P3D_OBJECT_GET_FLOAT(result);
     fresult = P3D_OBJECT_GET_FLOAT(result);
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }    
   }    
 
 
   return fresult;
   return fresult;
@@ -110,7 +110,7 @@ get_float() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DPythonObject::
 void P3DPythonObject::
-make_string(string &value) const {
+make_string(string &value) {
   P3D_object *result = call("__str__", NULL, 0);
   P3D_object *result = call("__str__", NULL, 0);
   if (result != NULL) {
   if (result != NULL) {
     int size = P3D_OBJECT_GET_STRING(result, NULL, 0);
     int size = P3D_OBJECT_GET_STRING(result, NULL, 0);
@@ -119,7 +119,7 @@ make_string(string &value) const {
     value = string(buffer, size);
     value = string(buffer, size);
     delete[] buffer;
     delete[] buffer;
 
 
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }    
   }    
 }
 }
 
 
@@ -131,7 +131,7 @@ make_string(string &value) const {
 //               that must be deleted by the caller, or NULL on error.
 //               that must be deleted by the caller, or NULL on error.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DPythonObject::
 P3D_object *P3DPythonObject::
-get_property(const string &property) const {
+get_property(const string &property) {
   P3D_object *params[1];
   P3D_object *params[1];
   params[0] = new P3DStringObject(property);
   params[0] = new P3DStringObject(property);
 
 
@@ -167,7 +167,7 @@ set_property(const string &property, P3D_object *value) {
 
 
   if (result != NULL) {
   if (result != NULL) {
     bresult = P3D_OBJECT_GET_BOOL(result);
     bresult = P3D_OBJECT_GET_BOOL(result);
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }
   }
 
 
   return bresult;
   return bresult;
@@ -180,7 +180,7 @@ set_property(const string &property, P3D_object *value) {
 //               object, false otherwise.
 //               object, false otherwise.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DPythonObject::
 bool P3DPythonObject::
-has_method(const string &method_name) const {
+has_method(const string &method_name) {
   bool bresult = false;
   bool bresult = false;
 
 
   P3D_object *params[1];
   P3D_object *params[1];
@@ -190,7 +190,7 @@ has_method(const string &method_name) const {
 
 
   if (result != NULL) {
   if (result != NULL) {
     bresult = P3D_OBJECT_GET_BOOL(result);
     bresult = P3D_OBJECT_GET_BOOL(result);
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }
   }
 
 
   return bresult;
   return bresult;
@@ -205,7 +205,7 @@ has_method(const string &method_name) const {
 //               on success, NULL on error.
 //               on success, NULL on error.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DPythonObject::
 P3D_object *P3DPythonObject::
-call(const string &method_name, P3D_object *params[], int num_params) const {
+call(const string &method_name, P3D_object *params[], int num_params) {
   TiXmlDocument *doc = new TiXmlDocument;
   TiXmlDocument *doc = new TiXmlDocument;
   TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
   TiXmlDeclaration *decl = new TiXmlDeclaration("1.0", "utf-8", "");
   TiXmlElement *xcommand = new TiXmlElement("command");
   TiXmlElement *xcommand = new TiXmlElement("command");
@@ -222,10 +222,6 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
   for (int i = 0; i < num_params; ++i) {
   for (int i = 0; i < num_params; ++i) {
     TiXmlElement *xparams = _session->p3dobj_to_xml(params[i]);
     TiXmlElement *xparams = _session->p3dobj_to_xml(params[i]);
     xcommand->LinkEndChild(xparams);
     xcommand->LinkEndChild(xparams);
-
-    // Now we're done with the params object passed in, we can delete
-    // it as promised.
-    P3D_OBJECT_FINISH(params[i]);
   }
   }
 
 
   doc->LinkEndChild(decl);
   doc->LinkEndChild(decl);
@@ -255,12 +251,12 @@ call(const string &method_name, P3D_object *params[], int num_params) const {
 //               assistance.
 //               assistance.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DPythonObject::
 void P3DPythonObject::
-output(ostream &out) const {
+output(ostream &out) {
   P3D_object *result = call("__repr__", NULL, 0);
   P3D_object *result = call("__repr__", NULL, 0);
   out << "Python " << _object_id;
   out << "Python " << _object_id;
   if (result != NULL) {
   if (result != NULL) {
     out << ": " << *result;
     out << ": " << *result;
-    P3D_OBJECT_FINISH(result);
+    P3D_OBJECT_DECREF(result);
   }    
   }    
 }
 }
 
 
@@ -271,7 +267,7 @@ output(ostream &out) const {
 //               identify this object in the XML stream.
 //               identify this object in the XML stream.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 int P3DPythonObject::
 int P3DPythonObject::
-get_object_id() const {
+get_object_id() {
   return _object_id;
   return _object_id;
 }
 }
 
 

+ 10 - 10
direct/src/plugin/p3dPythonObject.h

@@ -34,22 +34,22 @@ public:
   virtual ~P3DPythonObject();
   virtual ~P3DPythonObject();
 
 
 public:
 public:
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual int get_int() const;
-  virtual double get_float() const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual int get_int();
+  virtual double get_float();
 
 
-  virtual void make_string(string &value) const;
+  virtual void make_string(string &value);
 
 
-  virtual P3D_object *get_property(const string &property) const;
+  virtual P3D_object *get_property(const string &property);
   virtual bool set_property(const string &property, P3D_object *value);
   virtual bool set_property(const string &property, P3D_object *value);
 
 
-  virtual bool has_method(const string &method_name) const;
+  virtual bool has_method(const string &method_name);
   virtual P3D_object *call(const string &method_name, 
   virtual P3D_object *call(const string &method_name, 
-                           P3D_object *params[], int num_params) const;
+                           P3D_object *params[], int num_params);
 
 
-  virtual void output(ostream &out) const;
-  int get_object_id() const;
+  virtual void output(ostream &out);
+  int get_object_id();
 
 
 private:
 private:
   P3DSession *_session;
   P3DSession *_session;

+ 17 - 13
direct/src/plugin/p3dSession.cxx

@@ -321,21 +321,23 @@ command_and_response(TiXmlDocument *command) {
 //       Access: Public
 //       Access: Public
 //  Description: Converts the XML representation of the particular
 //  Description: Converts the XML representation of the particular
 //               object value into a corresponding P3D_object.
 //               object value into a corresponding P3D_object.
-//               Returns the newly-allocated object.
+//               Returns the object, a new reference.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object *P3DSession::
 P3D_object *P3DSession::
 xml_to_p3dobj(const TiXmlElement *xvalue) {
 xml_to_p3dobj(const TiXmlElement *xvalue) {
   const char *type = xvalue->Attribute("type");
   const char *type = xvalue->Attribute("type");
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+
   if (strcmp(type, "undefined") == 0) {
   if (strcmp(type, "undefined") == 0) {
-    return new P3DUndefinedObject;
+    return inst_mgr->new_undefined_object();
 
 
   } else if (strcmp(type, "none") == 0) {
   } else if (strcmp(type, "none") == 0) {
-    return new P3DNoneObject;
+    return inst_mgr->new_none_object();
 
 
   } else if (strcmp(type, "bool") == 0) {
   } else if (strcmp(type, "bool") == 0) {
     int value;
     int value;
     if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
     if (xvalue->QueryIntAttribute("value", &value) == TIXML_SUCCESS) {
-      return new P3DBoolObject(value != 0);
+      return inst_mgr->new_bool_object(value != 0);
     }
     }
 
 
   } else if (strcmp(type, "int") == 0) {
   } else if (strcmp(type, "int") == 0) {
@@ -364,11 +366,12 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
       SentObjects::iterator si = _sent_objects.find(object_id);
       SentObjects::iterator si = _sent_objects.find(object_id);
       if (si == _sent_objects.end()) {
       if (si == _sent_objects.end()) {
         // Hmm, the child process gave us a bogus object ID.
         // Hmm, the child process gave us a bogus object ID.
-        return new P3DUndefinedObject;
+        return inst_mgr->new_undefined_object();
       }
       }
 
 
       P3D_object *obj = (*si).second;
       P3D_object *obj = (*si).second;
-      return P3D_OBJECT_COPY(obj);
+      P3D_OBJECT_INCREF(obj);
+      return obj;
     }
     }
 
 
   } else if (strcmp(type, "python") == 0) {
   } else if (strcmp(type, "python") == 0) {
@@ -379,7 +382,7 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
   }
   }
 
 
   // Something went wrong in decoding.
   // Something went wrong in decoding.
-  return new P3DUndefinedObject;
+  return inst_mgr->new_undefined_object();
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -387,10 +390,11 @@ xml_to_p3dobj(const TiXmlElement *xvalue) {
 //       Access: Public
 //       Access: Public
 //  Description: Allocates and returns a new XML structure
 //  Description: Allocates and returns a new XML structure
 //               corresponding to the indicated value.  The supplied
 //               corresponding to the indicated value.  The supplied
-//               P3DObject passed in is *not* deleted.
+//               P3DObject's reference count is not decremented; the
+//               caller remains responsible for decrementing it later.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 TiXmlElement *P3DSession::
 TiXmlElement *P3DSession::
-p3dobj_to_xml(const P3D_object *obj) {
+p3dobj_to_xml(P3D_object *obj) {
   TiXmlElement *xvalue = new TiXmlElement("value");
   TiXmlElement *xvalue = new TiXmlElement("value");
 
 
   switch (P3D_OBJECT_GET_TYPE(obj)) {
   switch (P3D_OBJECT_GET_TYPE(obj)) {
@@ -443,21 +447,21 @@ p3dobj_to_xml(const P3D_object *obj) {
       // should pass a reference down to this particular object, so
       // should pass a reference down to this particular object, so
       // the Python process knows to call back up to here to query it.
       // the Python process knows to call back up to here to query it.
 
 
-      P3D_object *dup = P3D_OBJECT_COPY(obj);
-
       int object_id = _next_sent_id;
       int object_id = _next_sent_id;
       ++_next_sent_id;
       ++_next_sent_id;
-      bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, dup)).second;
+      bool inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
       while (!inserted) {
       while (!inserted) {
         // Hmm, we must have cycled around the entire int space?  Either
         // Hmm, we must have cycled around the entire int space?  Either
         // that, or there's a logic bug somewhere.  Assume the former,
         // that, or there's a logic bug somewhere.  Assume the former,
         // and keep looking for an empty slot.
         // and keep looking for an empty slot.
         object_id = _next_sent_id;
         object_id = _next_sent_id;
         ++_next_sent_id;
         ++_next_sent_id;
-        inserted = _sent_objects.insert(SentObjects::value_type(object_id, dup)).second;
+        inserted = _sent_objects.insert(SentObjects::value_type(object_id, obj)).second;
       }
       }
 
 
+      // Now that it's stored in the map, increment its reference count.
       // TODO: implement removing things from this map.
       // TODO: implement removing things from this map.
+      P3D_OBJECT_INCREF(obj);
 
 
       xvalue->SetAttribute("type", "browser");
       xvalue->SetAttribute("type", "browser");
       xvalue->SetAttribute("object_id", object_id);
       xvalue->SetAttribute("object_id", object_id);

+ 1 - 1
direct/src/plugin/p3dSession.h

@@ -50,7 +50,7 @@ public:
   void send_command(TiXmlDocument *command);
   void send_command(TiXmlDocument *command);
   TiXmlDocument *command_and_response(TiXmlDocument *command);
   TiXmlDocument *command_and_response(TiXmlDocument *command);
   P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue);
   P3D_object *xml_to_p3dobj(const TiXmlElement *xvalue);
-  TiXmlElement *p3dobj_to_xml(const P3D_object *obj);
+  TiXmlElement *p3dobj_to_xml(P3D_object *obj);
 
 
 private:
 private:
   void install_progress(P3DPackage *package, double progress);
   void install_progress(P3DPackage *package, double progress);

+ 4 - 4
direct/src/plugin/p3dStringObject.cxx

@@ -50,7 +50,7 @@ P3DStringObject::
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DStringObject::
 P3D_object_type P3DStringObject::
-get_type() const {
+get_type() {
   return P3D_OT_string;
   return P3D_OT_string;
 }
 }
 
 
@@ -61,7 +61,7 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DStringObject::
 bool P3DStringObject::
-get_bool() const {
+get_bool() {
   return !_value.empty();
   return !_value.empty();
 }
 }
 
 
@@ -72,7 +72,7 @@ get_bool() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DStringObject::
 void P3DStringObject::
-make_string(string &value) const {
+make_string(string &value) {
   value = _value;
   value = _value;
 }
 }
 
 
@@ -84,7 +84,7 @@ make_string(string &value) const {
 //               assistance.
 //               assistance.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DStringObject::
 void P3DStringObject::
-output(ostream &out) const {
+output(ostream &out) {
   out << '"';
   out << '"';
   for (string::const_iterator si = _value.begin(); si != _value.end(); ++si) {
   for (string::const_iterator si = _value.begin(); si != _value.end(); ++si) {
     if (isprint(*si)) {
     if (isprint(*si)) {

+ 4 - 4
direct/src/plugin/p3dStringObject.h

@@ -30,11 +30,11 @@ public:
 public:
 public:
   virtual ~P3DStringObject();
   virtual ~P3DStringObject();
 
 
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual void make_string(string &value) const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual void make_string(string &value);
 
 
-  virtual void output(ostream &out) const;
+  virtual void output(ostream &out);
 
 
 private:
 private:
   string _value;
   string _value;

+ 3 - 3
direct/src/plugin/p3dUndefinedObject.cxx

@@ -29,7 +29,7 @@ P3DUndefinedObject() {
 //  Description: Returns the fundamental type of this kind of object.
 //  Description: Returns the fundamental type of this kind of object.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 P3D_object_type P3DUndefinedObject::
 P3D_object_type P3DUndefinedObject::
-get_type() const {
+get_type() {
   return P3D_OT_undefined;
   return P3D_OT_undefined;
 }
 }
 
 
@@ -40,7 +40,7 @@ get_type() const {
 //               possible.
 //               possible.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 bool P3DUndefinedObject::
 bool P3DUndefinedObject::
-get_bool() const {
+get_bool() {
   return false;
   return false;
 }
 }
 
 
@@ -51,6 +51,6 @@ get_bool() const {
 //               of this object coerced to a string.
 //               of this object coerced to a string.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void P3DUndefinedObject::
 void P3DUndefinedObject::
-make_string(string &value) const {
+make_string(string &value) {
   value = "Undefined";
   value = "Undefined";
 }
 }

+ 3 - 3
direct/src/plugin/p3dUndefinedObject.h

@@ -29,9 +29,9 @@ public:
   P3DUndefinedObject();
   P3DUndefinedObject();
 
 
 public:
 public:
-  virtual P3D_object_type get_type() const;
-  virtual bool get_bool() const;
-  virtual void make_string(string &value) const;
+  virtual P3D_object_type get_type();
+  virtual bool get_bool();
+  virtual void make_string(string &value);
 };
 };
 
 
 #endif
 #endif

+ 7 - 4
direct/src/plugin/p3d_plugin.cxx

@@ -138,7 +138,8 @@ P3D_new_undefined_object() {
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   ACQUIRE_LOCK(_api_lock);
   ACQUIRE_LOCK(_api_lock);
 
 
-  P3D_object *result = new P3DUndefinedObject();
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+  P3D_object *result = inst_mgr->new_undefined_object();
   
   
   RELEASE_LOCK(_api_lock);
   RELEASE_LOCK(_api_lock);
   return result;
   return result;
@@ -149,7 +150,8 @@ P3D_new_none_object() {
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   ACQUIRE_LOCK(_api_lock);
   ACQUIRE_LOCK(_api_lock);
 
 
-  P3D_object *result = new P3DNoneObject();
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+  P3D_object *result = inst_mgr->new_none_object();
   
   
   RELEASE_LOCK(_api_lock);
   RELEASE_LOCK(_api_lock);
   return result;
   return result;
@@ -160,7 +162,8 @@ P3D_new_bool_object(bool value) {
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   ACQUIRE_LOCK(_api_lock);
   ACQUIRE_LOCK(_api_lock);
 
 
-  P3D_object *result = new P3DBoolObject(value);
+  P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
+  P3D_object *result = inst_mgr->new_bool_object(value);
   
   
   RELEASE_LOCK(_api_lock);
   RELEASE_LOCK(_api_lock);
   return result;
   return result;
@@ -212,7 +215,7 @@ P3D_instance_get_panda_script_object(P3D_instance *instance) {
 
 
 void
 void
 P3D_instance_set_browser_script_object(P3D_instance *instance, 
 P3D_instance_set_browser_script_object(P3D_instance *instance, 
-                               P3D_object *object) {
+                                       P3D_object *object) {
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   assert(P3DInstanceManager::get_global_ptr()->is_initialized());
   ACQUIRE_LOCK(_api_lock);
   ACQUIRE_LOCK(_api_lock);
 
 

+ 74 - 72
direct/src/plugin/p3d_plugin.h

@@ -307,25 +307,30 @@ typedef enum {
   P3D_OT_object,
   P3D_OT_object,
 } P3D_object_type;
 } P3D_object_type;
 
 
+/* Most methods and functions that return a P3D_object return it with
+   its reference count already incremented by one for the benefit of
+   the caller, leaving the caller the owner of the implicit reference
+   count.  This is referred to as returning a "new reference", using
+   the Python naming convention.  Similarly, most methods that receive
+   a P3D_object will implicitly increment the reference count
+   internally if necessary, leaving the caller still the owner of its
+   own reference count.  Thus, it is the caller's responsibility to
+   call P3D_OBJECT_DECREF() on any P3D_objects it has received but no
+   longer wishes to keep. */
+
 /* This method is called to deallocate the object and all of its
 /* This method is called to deallocate the object and all of its
-   internal structures. */
+   internal structures.  Do not call it directly; call
+   P3D_OBJECT_DECREF() instead. */
 typedef void
 typedef void
 P3D_object_finish_method(P3D_object *object);
 P3D_object_finish_method(P3D_object *object);
 
 
-/* Returns a new copy of the object.  The caller receives ownership of
-   the new object and must eventually pass its pointer to
-   P3D_OBJECT_FINISH() to delete it, or into some other call that
-   transfers ownership. */
-typedef P3D_object *
-P3D_object_copy_method(const P3D_object *object);
-
 /* Returns the fundamental type of the object.  This should be treated
 /* Returns the fundamental type of the object.  This should be treated
    as a hint to suggest how the object can most accurately be
    as a hint to suggest how the object can most accurately be
    represented; it does not limit the actual interfaces available to
    represented; it does not limit the actual interfaces available to
    an object.  For instance, you may call P3D_OBJECT_GET_PROPERTY()
    an object.  For instance, you may call P3D_OBJECT_GET_PROPERTY()
    even if the object's type is not "object". */
    even if the object's type is not "object". */
 typedef P3D_object_type
 typedef P3D_object_type
-P3D_object_get_type_method(const P3D_object *object);
+P3D_object_get_type_method(P3D_object *object);
 
 
 /* Each of the following methods returns the object's value expressed
 /* Each of the following methods returns the object's value expressed
    as the corresponding type.  If the object is not precisely that
    as the corresponding type.  If the object is not precisely that
@@ -333,15 +338,15 @@ P3D_object_get_type_method(const P3D_object *object);
 
 
 /* Return the object as a bool. */
 /* Return the object as a bool. */
 typedef bool
 typedef bool
-P3D_object_get_bool_method(const P3D_object *object);
+P3D_object_get_bool_method(P3D_object *object);
 
 
 /* Return the object as an integer. */
 /* Return the object as an integer. */
 typedef int
 typedef int
-P3D_object_get_int_method(const P3D_object *object);
+P3D_object_get_int_method(P3D_object *object);
 
 
 /* Return the object as a floating-point number. */
 /* Return the object as a floating-point number. */
 typedef double
 typedef double
-P3D_object_get_float_method(const P3D_object *object);
+P3D_object_get_float_method(P3D_object *object);
 
 
 /* Get the object as a string.  This method copies the string into the
 /* Get the object as a string.  This method copies the string into the
    provided buffer, and returns the actual length of the internal
    provided buffer, and returns the actual length of the internal
@@ -352,7 +357,7 @@ P3D_object_get_float_method(const P3D_object *object);
    buffer = NULL and buffer_length = 0 to return just the required
    buffer = NULL and buffer_length = 0 to return just the required
    size of the buffer. */
    size of the buffer. */
 typedef int
 typedef int
-P3D_object_get_string_method(const P3D_object *object, 
+P3D_object_get_string_method(P3D_object *object, 
                              char *buffer, int buffer_length);
                              char *buffer, int buffer_length);
 
 
 /* As above, but instead of the literal object data, returns a
 /* As above, but instead of the literal object data, returns a
@@ -362,23 +367,19 @@ P3D_object_get_string_method(const P3D_object *object,
    marks and escape characters from P3D_OBJECT_GET_REPR().
    marks and escape characters from P3D_OBJECT_GET_REPR().
    Mechanically, this function works the same way as get_string(). */
    Mechanically, this function works the same way as get_string(). */
 typedef int
 typedef int
-P3D_object_get_repr_method(const P3D_object *object, 
+P3D_object_get_repr_method(P3D_object *object, 
                            char *buffer, int buffer_length);
                            char *buffer, int buffer_length);
 
 
 /* Looks up a property on the object by name, i.e. a data member or a
 /* Looks up a property on the object by name, i.e. a data member or a
-   method.  The return value is a newly-allocated P3D_object if the
-   property exists, or NULL if it does not.  If it is not NULL,
-   ownership of the return value is transferred to the caller, who
-   will be responsible for deleting it later. */
+   method.  The return value is a new-reference P3D_object if the
+   property exists, or NULL if it does not. */
 typedef P3D_object *
 typedef P3D_object *
-P3D_object_get_property_method(const P3D_object *object, const char *property);
+P3D_object_get_property_method(P3D_object *object, const char *property);
 
 
 /* Changes the value at the indicated property.  Any existing object
 /* Changes the value at the indicated property.  Any existing object
    already at the corresponding property is deleted.  If the value
    already at the corresponding property is deleted.  If the value
-   object pointer is NULL, the property is deleted.  Returns true on
-   success, false on failure.  The caller must have ownership of the
-   value object before the call; after the call, ownership of the
-   value object is transferred to this object. */
+   pointer is NULL, the property is deleted.  Returns true on success,
+   false on failure.  */
 typedef bool
 typedef bool
 P3D_object_set_property_method(P3D_object *object, const char *property,
 P3D_object_set_property_method(P3D_object *object, const char *property,
                                P3D_object *value);
                                P3D_object *value);
@@ -389,36 +390,32 @@ P3D_object_set_property_method(P3D_object *object, const char *property,
    a callable object.  If method_name is empty or NULL, returns true
    a callable object.  If method_name is empty or NULL, returns true
    if the object itself is callable. */
    if the object itself is callable. */
 typedef bool
 typedef bool
-P3D_object_has_method_method(const P3D_object *object, const char *method_name);
+P3D_object_has_method_method(P3D_object *object, const char *method_name);
 
 
 /* Invokes a named method on the object.  If method_name is empty or
 /* Invokes a named method on the object.  If method_name is empty or
    NULL, invokes the object itself as a function.  You must pass an
    NULL, invokes the object itself as a function.  You must pass an
-   array of P3D_objects as the list of parameters.  The ownership of
-   each of the parameters in this array (but not of the array pointer
-   itself) is passed into this call; the objects will be deleted when
-   the call is completed.
-
-   The return value is a newly-allocated P3D_object on success, or
-   NULL on failure.  Ownership of the return value is transferred to
-   the caller. */
+   array of P3D_objects as the list of parameters, and ownership of
+   these objects' reference counts is not transferred with the call
+   (you must still DECREF these objects afterwards).
+
+   The return value is a new-reference P3D_object on success, or NULL
+   on failure. */
 typedef P3D_object *
 typedef P3D_object *
-P3D_object_call_method(const P3D_object *object, const char *method_name,
+P3D_object_call_method(P3D_object *object, const char *method_name,
                        P3D_object *params[], int num_params);
                        P3D_object *params[], int num_params);
 
 
 /* Evaluates an arbitrary JavaScript expression in the context of the
 /* Evaluates an arbitrary JavaScript expression in the context of the
    object.
    object.
 
 
-   The return value is a newly-allocated P3D_object on success, or
-   NULL on failure.  Ownership of the return value is transferred to
-   the caller. */
+   The return value is a new-reference P3D_object on success, or NULL
+   on failure. */
 typedef P3D_object *
 typedef P3D_object *
-P3D_object_eval_method(const P3D_object *object, const char *expression);
+P3D_object_eval_method(P3D_object *object, const char *expression);
 
 
 /* This defines the class structure that implements all of the above
 /* This defines the class structure that implements all of the above
    methods. */
    methods. */
 typedef struct _P3D_class_definition {
 typedef struct _P3D_class_definition {
   P3D_object_finish_method *_finish;
   P3D_object_finish_method *_finish;
-  P3D_object_copy_method *_copy;
 
 
   P3D_object_get_type_method *_get_type;
   P3D_object_get_type_method *_get_type;
   P3D_object_get_bool_method *_get_bool;
   P3D_object_get_bool_method *_get_bool;
@@ -439,6 +436,7 @@ typedef struct _P3D_class_definition {
 /* And this structure defines the actual instances of P3D_object. */
 /* And this structure defines the actual instances of P3D_object. */
 struct _P3D_object {
 struct _P3D_object {
   const P3D_class_definition *_class;
   const P3D_class_definition *_class;
+  int _ref_count;
 
 
   /* Additional opaque data may be stored here. */
   /* Additional opaque data may be stored here. */
 };
 };
@@ -446,9 +444,6 @@ struct _P3D_object {
 /* These macros are defined for the convenience of invoking any of the
 /* These macros are defined for the convenience of invoking any of the
    above method functions on an object. */
    above method functions on an object. */
 
 
-#define P3D_OBJECT_FINISH(object) ((object)->_class->_finish((object)))
-#define P3D_OBJECT_COPY(object) ((object)->_class->_copy((object)))
-
 #define P3D_OBJECT_GET_TYPE(object) ((object)->_class->_get_type((object)))
 #define P3D_OBJECT_GET_TYPE(object) ((object)->_class->_get_type((object)))
 #define P3D_OBJECT_GET_BOOL(object) ((object)->_class->_get_bool((object)))
 #define P3D_OBJECT_GET_BOOL(object) ((object)->_class->_get_bool((object)))
 #define P3D_OBJECT_GET_INT(object) ((object)->_class->_get_int((object)))
 #define P3D_OBJECT_GET_INT(object) ((object)->_class->_get_int((object)))
@@ -463,58 +458,65 @@ struct _P3D_object {
 #define P3D_OBJECT_CALL(object, method_name, params, num_params) ((object)->_class->_call((object), (method_name), (params), (num_params)))
 #define P3D_OBJECT_CALL(object, method_name, params, num_params) ((object)->_class->_call((object), (method_name), (params), (num_params)))
 #define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression)))
 #define P3D_OBJECT_EVAL(object, expression) ((object)->_class->_eval((object), (expression)))
 
 
+/* These macros are provided to manipulate the reference count of the
+   indicated object.  Following Python's convention, XDECREF is
+   provided to decrement the reference count for a pointer that might
+   be NULL (it does nothing in the case of a NULL pointer). */
+
+#define P3D_OBJECT_INCREF(object) (++(object)->_ref_count)
+#define P3D_OBJECT_DECREF(object) { if (--(object)->_ref_count <= 0) { (object)->_class->_finish((object)); } }
+#define P3D_OBJECT_XDECREF(object) { if ((object) != (P3D_object *)NULL) { P3D_OBJECT_DECREF(object); } }
 
 
-/* The following function types are once again meant to define
-   actual function pointers to be found within the core API DLL. */
 
 
-/* Returns a newly-allocated P3D_class_definition object, filled with
-   generic function pointers that have reasonable default behavior for
-   all methods.  The host should use this function to get a clean
+/* End of method pointer definitions.  The following function types
+   are once again meant to define actual function pointers to be found
+   within the core API DLL. */
+
+/* Returns a new P3D_class_definition object, filled with generic
+   function pointers that have reasonable default behavior for all
+   methods.  The host should use this function to get a clean
    P3D_class_definition object before calling
    P3D_class_definition object before calling
-   P3D_instance_set_browser_script_object() (see below).  Note that this
-   pointer will automatically be freed when P3D_finalize() is
+   P3D_instance_set_browser_script_object() (see below).  Note that
+   this pointer will automatically be freed when P3D_finalize() is
    called. */
    called. */
 typedef P3D_class_definition *
 typedef P3D_class_definition *
 P3D_make_class_definition_func();
 P3D_make_class_definition_func();
 
 
-/* Allocates a new P3D_object of type "undefined".  This corresponds
-   to the undefined or void type on JavaScript.  It is similar to
-   Python's None, but has a subtly different shade of meaning; we map
-   it to an explicit Undefined instance in runp3d.py. */
+/* Returns a new-reference P3D_object of type "undefined".  This
+   corresponds to the undefined or void type on JavaScript.  It is
+   similar to Python's None, but has a subtly different shade of
+   meaning; we map it to an explicit Undefined instance in
+   runp3d.py. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_undefined_object_func();
 P3D_new_undefined_object_func();
 
 
-/* Allocates a new P3D_object of type none.  This value has no
+/* Returns a new-reference P3D_object of type none.  This value has no
    particular value and corresponds to Python's None type or
    particular value and corresponds to Python's None type or
    JavaScript's null type. */
    JavaScript's null type. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_none_object_func();
 P3D_new_none_object_func();
 
 
-/* Allocates a new P3D_object of type bool. */
+/* Returns a new-reference P3D_object of type bool. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_bool_object_func(bool value);
 P3D_new_bool_object_func(bool value);
 
 
-/* Allocates a new P3D_object of type int. */
+/* Returns a new-reference P3D_object of type int. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_int_object_func(int value);
 P3D_new_int_object_func(int value);
 
 
-/* Allocates a new P3D_object of type float. */
+/* Returns a new-reference P3D_object of type float. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_float_object_func(double value);
 P3D_new_float_object_func(double value);
 
 
-/* Allocates a new P3D_object of type string.  The supplied string is
-   copied into the object and stored internally. */
+/* Returns a new-reference P3D_object of type string.  The supplied
+   string is copied into the object and stored internally. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_new_string_object_func(const char *string, int length);
 P3D_new_string_object_func(const char *string, int length);
 
 
-/* Returns a pointer to the top-level scriptable object of the
-   instance.  Scripts running on the host may use this object to
-   communicate with the instance, by using the above methods to set or
-   query properties, and/or call methods, on the instance. 
-
-   The return value from this function is a newly-allocated object;
-   ownership of the object is passed to the caller, who should be
-   responsible for deleting it eventually. */
+/* Returns a new-reference pointer to the top-level scriptable object
+   of the instance.  Scripts running on the host may use this object
+   to communicate with the instance, by using the above methods to set
+   or query properties, and/or call methods, on the instance. */
 typedef P3D_object *
 typedef P3D_object *
 P3D_instance_get_panda_script_object_func(P3D_instance *instance);
 P3D_instance_get_panda_script_object_func(P3D_instance *instance);
 
 
@@ -528,8 +530,8 @@ P3D_instance_get_panda_script_object_func(P3D_instance *instance);
    have a custom P3D_class_definition pointer, which also must have
    have a custom P3D_class_definition pointer, which also must have
    been created by the host.  The best way to create an appropriate
    been created by the host.  The best way to create an appropriate
    class definition is call P3D_make_class_definition(), and then
    class definition is call P3D_make_class_definition(), and then
-   replace the function pointers for at least _finish, _copy,
-   _get_property, _set_property, and _call.  Set these pointers to the
+   replace the function pointers for at least _finish, _get_property,
+   _set_property, _has_method, and _call.  Set these pointers to the
    host's own functions that make the appropriate changes in the DOM,
    host's own functions that make the appropriate changes in the DOM,
    or invoke the appropriate JavaScript functions.
    or invoke the appropriate JavaScript functions.
 
 
@@ -538,10 +540,10 @@ P3D_instance_get_panda_script_object_func(P3D_instance *instance);
    able to control the instance via P3D_instance_get_panda_script_object(),
    able to control the instance via P3D_instance_get_panda_script_object(),
    above. 
    above. 
 
 
-   Ownership of the object is passed into the instance.  The caller
-   must have freshly allocated the object, and should no longer store
-   or delete it.  The instance will eventually delete it by calling
-   its _finish method. */
+   Note that the object's constructor should initialize its reference
+   count to 1.  The instance will increment reference count as a
+   result of this call; the caller is responsible for calling DECREF
+   on the object after this call to remove its own reference. */
 typedef void
 typedef void
 P3D_instance_set_browser_script_object_func(P3D_instance *instance, 
 P3D_instance_set_browser_script_object_func(P3D_instance *instance, 
                                             P3D_object *object);
                                             P3D_object *object);

+ 1 - 1
direct/src/plugin/p3d_plugin_common.h

@@ -41,7 +41,7 @@ extern ostream *nout_stream;
 // A convenience function for formatting a generic P3D_object to an
 // A convenience function for formatting a generic P3D_object to an
 // ostream.
 // ostream.
 inline ostream &
 inline ostream &
-operator << (ostream &out, const P3D_object &value) {
+operator << (ostream &out, P3D_object &value) {
   int size = P3D_OBJECT_GET_REPR(&value, NULL, 0);
   int size = P3D_OBJECT_GET_REPR(&value, NULL, 0);
   char *buffer = new char[size];
   char *buffer = new char[size];
   P3D_OBJECT_GET_REPR(&value, buffer, size);
   P3D_OBJECT_GET_REPR(&value, buffer, size);

+ 7 - 11
direct/src/plugin_npapi/ppBrowserObject.cxx

@@ -26,18 +26,13 @@ object_finish(P3D_object *object) {
   delete ((PPBrowserObject *)object);
   delete ((PPBrowserObject *)object);
 }
 }
 
 
-static P3D_object *
-object_copy(const P3D_object *object) {
-  return new PPBrowserObject(*(const PPBrowserObject *)object);
-}
-
 static int 
 static int 
-object_get_repr(const P3D_object *object, char *buffer, int buffer_length) {
+object_get_repr(P3D_object *object, char *buffer, int buffer_length) {
   return ((const PPBrowserObject *)object)->get_repr(buffer, buffer_length);
   return ((const PPBrowserObject *)object)->get_repr(buffer, buffer_length);
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-object_get_property(const P3D_object *object, const char *property) {
+object_get_property(P3D_object *object, const char *property) {
   return ((const PPBrowserObject *)object)->get_property(property);
   return ((const PPBrowserObject *)object)->get_property(property);
 }
 }
 
 
@@ -48,7 +43,7 @@ object_set_property(P3D_object *object, const char *property,
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-object_call(const P3D_object *object, const char *method_name,
+object_call(P3D_object *object, const char *method_name,
             P3D_object *params[], int num_params) {
             P3D_object *params[], int num_params) {
   if (method_name == NULL) {
   if (method_name == NULL) {
     method_name = "";
     method_name = "";
@@ -57,7 +52,7 @@ object_call(const P3D_object *object, const char *method_name,
 }
 }
 
 
 static P3D_object *
 static P3D_object *
-object_eval(const P3D_object *object, const char *expression) {
+object_eval(P3D_object *object, const char *expression) {
   return ((const PPBrowserObject *)object)->eval(expression);
   return ((const PPBrowserObject *)object)->eval(expression);
 }
 }
 
 
@@ -74,6 +69,7 @@ PPBrowserObject(PPInstance *inst, NPObject *npobj) :
   _npobj(npobj)
   _npobj(npobj)
 {
 {
   _class = get_class_definition();
   _class = get_class_definition();
+  _ref_count = 1;
   browser->retainobject(_npobj);
   browser->retainobject(_npobj);
 }
 }
 
 
@@ -88,6 +84,7 @@ PPBrowserObject(const PPBrowserObject &copy) :
   _npobj(copy._npobj)
   _npobj(copy._npobj)
 {
 {
   _class = get_class_definition();
   _class = get_class_definition();
+  _ref_count = 1;
   browser->retainobject(_npobj);
   browser->retainobject(_npobj);
 }
 }
 
 
@@ -98,6 +95,7 @@ PPBrowserObject(const PPBrowserObject &copy) :
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 PPBrowserObject::
 PPBrowserObject::
 ~PPBrowserObject() {
 ~PPBrowserObject() {
+  assert(_ref_count == 0);
   browser->releaseobject(_npobj);
   browser->releaseobject(_npobj);
 }
 }
 
 
@@ -162,7 +160,6 @@ set_property(const string &property, P3D_object *value) {
     result = browser->setproperty(_instance->get_npp_instance(), _npobj,
     result = browser->setproperty(_instance->get_npp_instance(), _npobj,
                                   property_name, &npvalue);
                                   property_name, &npvalue);
     browser->releasevariantvalue(&npvalue);
     browser->releasevariantvalue(&npvalue);
-    P3D_OBJECT_FINISH(value);
 
 
   } else {
   } else {
     // Delete the property.
     // Delete the property.
@@ -268,7 +265,6 @@ get_class_definition() {
     // appropriate pointers.
     // appropriate pointers.
     _browser_object_class = P3D_make_class_definition();
     _browser_object_class = P3D_make_class_definition();
     _browser_object_class->_finish = &object_finish;
     _browser_object_class->_finish = &object_finish;
-    _browser_object_class->_copy = &object_copy;
 
 
     _browser_object_class->_get_repr = &object_get_repr;
     _browser_object_class->_get_repr = &object_get_repr;
     _browser_object_class->_get_property = &object_get_property;
     _browser_object_class->_get_property = &object_get_property;

+ 4 - 4
direct/src/plugin_npapi/ppInstance.cxx

@@ -501,7 +501,7 @@ get_panda_script_object() {
 //               NPVariant, and stores it in result.
 //               NPVariant, and stores it in result.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PPInstance::
 void PPInstance::
-p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
+p3dobj_to_variant(NPVariant *result, P3D_object *object) {
   switch (P3D_OBJECT_GET_TYPE(object)) {
   switch (P3D_OBJECT_GET_TYPE(object)) {
   case P3D_OT_undefined:
   case P3D_OT_undefined:
     VOID_TO_NPVARIANT(*result);
     VOID_TO_NPVARIANT(*result);
@@ -534,7 +534,7 @@ p3dobj_to_variant(NPVariant *result, const P3D_object *object) {
 
 
   case P3D_OT_object:
   case P3D_OT_object:
     {
     {
-      PPPandaObject *ppobj = PPPandaObject::make_new(this, P3D_OBJECT_COPY(object));
+      PPPandaObject *ppobj = PPPandaObject::make_new(this, object);
       OBJECT_TO_NPVARIANT(ppobj, *result);
       OBJECT_TO_NPVARIANT(ppobj, *result);
     }
     }
     break;
     break;
@@ -571,7 +571,7 @@ variant_to_p3dobj(const NPVariant *variant) {
       PPPandaObject *ppobject = (PPPandaObject *)object;
       PPPandaObject *ppobject = (PPPandaObject *)object;
       P3D_object *obj = ppobject->get_p3d_object();
       P3D_object *obj = ppobject->get_p3d_object();
       logfile << "Found nested Panda Object " << obj << "\n" << flush;
       logfile << "Found nested Panda Object " << obj << "\n" << flush;
-      return P3D_OBJECT_COPY(obj);
+      return obj;
     }
     }
 
 
     // It's a generic NPObject of some kind.
     // It's a generic NPObject of some kind.
@@ -899,7 +899,7 @@ create_instance() {
       logfile << "Couldn't get window_object\n" << flush;
       logfile << "Couldn't get window_object\n" << flush;
     }
     }
     
     
-    const P3D_token *tokens = NULL;
+    P3D_token *tokens = NULL;
     if (!_tokens.empty()) {
     if (!_tokens.empty()) {
       tokens = &_tokens[0];
       tokens = &_tokens[0];
     }
     }

+ 1 - 1
direct/src/plugin_npapi/ppInstance.h

@@ -55,7 +55,7 @@ public:
 
 
   NPObject *get_panda_script_object();
   NPObject *get_panda_script_object();
 
 
-  void p3dobj_to_variant(NPVariant *result, const P3D_object *object);
+  void p3dobj_to_variant(NPVariant *result, P3D_object *object);
   P3D_object *variant_to_p3dobj(const NPVariant *variant);
   P3D_object *variant_to_p3dobj(const NPVariant *variant);
 
 
   static void output_np_variant(ostream &out, const NPVariant &result);
   static void output_np_variant(ostream &out, const NPVariant &result);

+ 4 - 0
direct/src/plugin_npapi/ppPandaObject.I

@@ -18,8 +18,12 @@
 //       Access: Public
 //       Access: Public
 //  Description: Returns the p3d_object this PPPandaObject maps to.  This
 //  Description: Returns the p3d_object this PPPandaObject maps to.  This
 //               may be NULL if the object is not fully initialized.
 //               may be NULL if the object is not fully initialized.
+//               If not NULL, this returns a new reference.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 inline P3D_object *PPPandaObject::
 inline P3D_object *PPPandaObject::
 get_p3d_object() const {
 get_p3d_object() const {
+  if (_p3d_object != NULL) {
+    P3D_OBJECT_INCREF(_p3d_object);
+  }
   return _p3d_object;
   return _p3d_object;
 }
 }

+ 21 - 10
direct/src/plugin_npapi/ppPandaObject.cxx

@@ -53,16 +53,17 @@ make_new(PPInstance *inst, P3D_object *p3d_object) {
 //     Function: PPPandaObject::set_p3d_object
 //     Function: PPPandaObject::set_p3d_object
 //       Access: Public
 //       Access: Public
 //  Description: Changes the p3d_object this PPPandaObject maps to.  The
 //  Description: Changes the p3d_object this PPPandaObject maps to.  The
-//               previous object, if any, is deleted.  Ownership of
-//               the new object is passed to the PPPandaObject.
+//               new object's reference count is incremented, and the
+//               previous object's is decremented.
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 void PPPandaObject::
 void PPPandaObject::
 set_p3d_object(P3D_object *p3d_object) {
 set_p3d_object(P3D_object *p3d_object) {
   if (_p3d_object != p3d_object) {
   if (_p3d_object != p3d_object) {
+    P3D_OBJECT_XDECREF(_p3d_object);
+    _p3d_object = p3d_object;
     if (_p3d_object != NULL) {
     if (_p3d_object != NULL) {
-      P3D_OBJECT_FINISH(_p3d_object);
+      P3D_OBJECT_INCREF(_p3d_object);
     }
     }
-    _p3d_object = p3d_object;
   }
   }
 }
 }
  
  
@@ -78,7 +79,8 @@ void PPPandaObject::
 construct(PPInstance *inst, P3D_object *p3d_object) {
 construct(PPInstance *inst, P3D_object *p3d_object) {
   logfile << "construct: " << this << "\n" << flush;
   logfile << "construct: " << this << "\n" << flush;
   _instance = inst;
   _instance = inst;
-  _p3d_object = p3d_object;
+  _p3d_object = NULL;
+  set_p3d_object(p3d_object);
 }
 }
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
@@ -141,12 +143,16 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount,
   }
   }
 
 
   P3D_object **p3dargs = new P3D_object *[argCount];
   P3D_object **p3dargs = new P3D_object *[argCount];
-  for (unsigned int i = 0; i < argCount; ++i) {
+  unsigned int i;
+  for (i = 0; i < argCount; ++i) {
     p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
     p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
   }
   }
 
 
   P3D_object *value = P3D_OBJECT_CALL(_p3d_object, method_name.c_str(), 
   P3D_object *value = P3D_OBJECT_CALL(_p3d_object, method_name.c_str(), 
                                       p3dargs, argCount);
                                       p3dargs, argCount);
+  for (i = 0; i < argCount; ++i) {
+    P3D_OBJECT_DECREF(p3dargs[i]);
+  }
   delete[] p3dargs;
   delete[] p3dargs;
 
 
   if (value == NULL) {
   if (value == NULL) {
@@ -156,7 +162,7 @@ invoke(NPIdentifier name, const NPVariant *args, uint32_t argCount,
 
 
   // We have the return value, and its value is stored in value.
   // We have the return value, and its value is stored in value.
   _instance->p3dobj_to_variant(result, value);
   _instance->p3dobj_to_variant(result, value);
-  P3D_OBJECT_FINISH(value);
+  P3D_OBJECT_DECREF(value);
   return true;
   return true;
 }
 }
 
 
@@ -177,12 +183,16 @@ invoke_default(const NPVariant *args, uint32_t argCount,
   }
   }
 
 
   P3D_object **p3dargs = new P3D_object *[argCount];
   P3D_object **p3dargs = new P3D_object *[argCount];
-  for (unsigned int i = 0; i < argCount; ++i) {
+  unsigned int i;
+  for (i = 0; i < argCount; ++i) {
     p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
     p3dargs[i] = _instance->variant_to_p3dobj(&args[i]);
   }
   }
 
 
   P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "",
   P3D_object *value = P3D_OBJECT_CALL(_p3d_object, "",
                                       p3dargs, argCount);
                                       p3dargs, argCount);
+  for (i = 0; i < argCount; ++i) {
+    P3D_OBJECT_DECREF(p3dargs[i]);
+  }
   delete[] p3dargs;
   delete[] p3dargs;
 
 
   if (value == NULL) {
   if (value == NULL) {
@@ -192,7 +202,7 @@ invoke_default(const NPVariant *args, uint32_t argCount,
 
 
   // We have the return value, and its value is stored in value.
   // We have the return value, and its value is stored in value.
   _instance->p3dobj_to_variant(result, value);
   _instance->p3dobj_to_variant(result, value);
-  P3D_OBJECT_FINISH(value);
+  P3D_OBJECT_DECREF(value);
   return true;
   return true;
 }
 }
 
 
@@ -239,7 +249,7 @@ get_property(NPIdentifier name, NPVariant *result) {
 
 
   // We have the property, and its value is stored in value.
   // We have the property, and its value is stored in value.
   _instance->p3dobj_to_variant(result, value);
   _instance->p3dobj_to_variant(result, value);
-  P3D_OBJECT_FINISH(value);
+  P3D_OBJECT_DECREF(value);
   return true;
   return true;
 }
 }
 
 
@@ -260,6 +270,7 @@ set_property(NPIdentifier name, const NPVariant *value) {
 
 
   P3D_object *object = _instance->variant_to_p3dobj(value);
   P3D_object *object = _instance->variant_to_p3dobj(value);
   bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
   bool result = P3D_OBJECT_SET_PROPERTY(_p3d_object, property_name.c_str(), object);
+  P3D_OBJECT_DECREF(object);
   return result;
   return result;
 }
 }