Author: [EMAIL PROTECTED]
Date: Fri Sep 26 23:18:55 2008
New Revision: 3690
Modified:
changes/jat/oophm-branch/plugins/common/HostChannel.cpp
changes/jat/oophm-branch/plugins/common/SessionHandler.h
changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp
changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h
changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp
Log:
Fixed JavaObject freeing and handled calls happening after the channel has
gone away. Seems pretty solid at this point with no major memory leaks
(not tested carefully, but running for a couple of hours with events going
on doesn't grow firefox a lot).
To do:
- verify this fixes the Windows/OSX crashes
- run end-to-end tests
- clean up build system
Modified: changes/jat/oophm-branch/plugins/common/HostChannel.cpp
==============================================================================
--- changes/jat/oophm-branch/plugins/common/HostChannel.cpp (original)
+++ changes/jat/oophm-branch/plugins/common/HostChannel.cpp Fri Sep 26
23:18:55 2008
@@ -203,6 +203,7 @@
Value returnValue;
bool exception = handler->invoke(*this, imsg->getThis(),
imsg->getMethodName(),
imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+ handler->sendFreeValues(*this);
ReturnMessage::send(*this, exception, returnValue);
}
break;
@@ -217,6 +218,7 @@
Value returnValue;
bool exception = handler->invokeSpecial(*this,
imsg->getDispatchId(),
imsg->getNumArgs(), imsg->getArgs(), &returnValue);
+ handler->sendFreeValues(*this);
ReturnMessage::send(*this, exception, returnValue);
}
break;
Modified: changes/jat/oophm-branch/plugins/common/SessionHandler.h
==============================================================================
--- changes/jat/oophm-branch/plugins/common/SessionHandler.h (original)
+++ changes/jat/oophm-branch/plugins/common/SessionHandler.h Fri Sep 26
23:18:55 2008
@@ -71,6 +71,11 @@
virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method,
int numArgs,
const Value* const args, Value* returnValue) = 0;
+ /**
+ * Send any queued up free values back to the server.
+ */
+ virtual void sendFreeValues(HostChannel& channel) = 0;
+
virtual ~SessionHandler() {}
};
Modified: changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp
==============================================================================
--- changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp (original)
+++ changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.cpp Fri Sep 26
23:18:55 2008
@@ -23,6 +23,7 @@
#include "scoped_ptr/scoped_ptr.h"
#include "RootedObject.h"
#include "InvokeMessage.h"
+#include "ServerMethods.h"
#include "jsapi.h"
#include "nsCOMPtr.h"
@@ -133,6 +134,21 @@
}
}
+void FFSessionHandler::sendFreeValues(HostChannel& channel) {
+ unsigned n = javaObjectsToFree.size();
+ if (n) {
+ scoped_array<int> ids(new int[n]);
+ int i = 0;
+ for (std::set<int>::iterator it = javaObjectsToFree.begin();
+ it != javaObjectsToFree.end(); ++it) {
+ ids[i++] = *it;
+ }
+ if (ServerMethods::freeJava(channel, this, n, ids.get())) {
+ javaObjectsToFree.clear();
+ }
+ }
+}
+
bool FFSessionHandler::invoke(HostChannel& channel, const Value& thisObj,
const std::string& methodName,
int numArgs, const Value* const args, Value* returnValue) {
Debug::log(Debug::Spam) << "FFSessionHandler::invoke " <<
thisObj.toString()
@@ -357,7 +373,6 @@
}
}
-// TODO(jat): actually free objects from javaObjectsToFree
void FFSessionHandler::freeJavaObject(int objectId) {
if (!javaObjectsById.erase(objectId)) {
Debug::log(Debug::Error) << "Trying to free unknown JavaObject: " <<
objectId << Debug::flush;
@@ -381,11 +396,25 @@
jsObjectsById = NULL;
}
JS_RemoveRoot(ctx, &toStringTearOff);
+ for (std::map<int, JSObject*>::iterator it = javaObjectsById.begin();
+ it != javaObjectsById.end(); ++it) {
+ int javaId = it->first;
+ JSObject* obj = it->second;
+ if (JavaObject::isJavaObject(ctx, obj)) {
+ // clear the SessionData pointer -- JavaObject knows it is
+ // disconnected if this is null
+ JS_SetPrivate(ctx, obj, NULL);
+ javaObjectsToFree.erase(javaId);
+ }
+ }
JS_EndRequest(ctx);
contextMap.erase(ctx);
ctx = NULL;
}
- getHostChannel()->disconnectFromHost();
+ HostChannel* channel = getHostChannel();
+ if (channel->isConnected()) {
+ channel->disconnectFromHost();
+ }
}
static JSBool contextCallback(JSContext* ctx, uintN contextOp) {
Modified: changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h
==============================================================================
--- changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h (original)
+++ changes/jat/oophm-branch/plugins/xpcom/FFSessionHandler.h Fri Sep 26
23:18:55 2008
@@ -31,6 +31,7 @@
public SessionData,
public SessionHandler
{
+ friend class JavaObject;
public:
FFSessionHandler(HostChannel* channel);
~FFSessionHandler(void);
@@ -47,6 +48,7 @@
int numArgs, const Value* const args, Value* returnValue);
virtual bool invokeSpecial(HostChannel& channel, SpecialMethodId method,
int numArgs,
const Value* const args, Value* returnValue);
+ virtual void sendFreeValues(HostChannel& channel);
private:
static void registerHandler(JSContext* context, FFSessionHandler*
handler);
Modified: changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp
==============================================================================
--- changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp (original)
+++ changes/jat/oophm-branch/plugins/xpcom/JavaObject.cpp Fri Sep 26
23:18:55 2008
@@ -46,7 +46,7 @@
NULL, /* object serialization */
NULL, /* has instance */
NULL, /* mark */
- NULL /* reserved slots */
+ NULL /* reserve slots */
};
int JavaObject::getObjectId(JSContext* ctx, JSObject* obj) {
@@ -113,21 +113,26 @@
return obj;
}
-JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsval id,
jsval* vp) {
+JSBool JavaObject::getProperty(JSContext* ctx, JSObject* obj, jsval id,
+ jsval* rval) {
Debug::log(Debug::Spam) << "JavaObject::getProperty obj=" << obj <<
Debug::flush;
SessionData* data = JavaObject::getSessionData(ctx, obj);
+ if (!data) {
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
int objectRef = JavaObject::getObjectId(ctx, obj);
if (JSVAL_IS_STRING(id)) {
JSString* str = JSVAL_TO_STRING(id);
#if 1
if ((JS_GetStringLength(str) == 8) && !strncmp("toString",
JS_GetStringBytes(str), 8)) {
- *vp = data->getToStringTearOff();
+ *rval = data->getToStringTearOff();
return JS_TRUE;
}
if ((JS_GetStringLength(str) == 2) && !strncmp("id",
JS_GetStringBytes(str), 2)) {
- *vp = INT_TO_JSVAL(objectRef);
+ *rval = INT_TO_JSVAL(objectRef);
return JS_TRUE;
}
#endif
@@ -146,22 +151,26 @@
SessionHandler* handler = data->getSessionHandler();
Value value = ServerMethods::getProperty(*channel, handler, objectRef,
dispId);
- data->makeValueRef(*vp, ctx, value);
+ data->makeValueRef(*rval, ctx, value);
return JS_TRUE;
}
-JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsval id,
jsval* vp) {
+JSBool JavaObject::setProperty(JSContext* ctx, JSObject* obj, jsval id,
+ jsval* vp) {
Debug::log(Debug::Spam) << "JavaObject::setProperty obj=" << obj <<
Debug::flush;
if (!JSVAL_IS_INT(id)) {
Debug::log(Debug::Error) << " Error: setting string property id" <<
Debug::flush;
return JS_FALSE;
}
+ SessionData* data = JavaObject::getSessionData(ctx, obj);
+ if (!data) {
+ return JS_TRUE;
+ }
+
int objectRef = JavaObject::getObjectId(ctx, obj);
int dispId = JSVAL_TO_INT(id);
- SessionData* data = JavaObject::getSessionData(ctx, obj);
-
Value value;
data->makeValue(value, ctx, *vp);
@@ -245,16 +254,19 @@
Debug::log(Debug::Debugging) << "JavaObject::finalize obj=" << obj
<< " objId=" << JavaObject::getObjectId(ctx, obj) << Debug::flush;
SessionData* data = JavaObject::getSessionData(ctx, obj);
- int objectId = JavaObject::getObjectId(ctx, obj);
- // TODO(jat): data can be invalid at the point this is called, causing a
- // crash -- need to consider how to make sure it is kept around or that
we
- // have some way of telling it is gone so we can ignore it.
- // data->freeJavaObject(objectId);
+ if (data) {
+ int objectId = JavaObject::getObjectId(ctx, obj);
+ data->freeJavaObject(objectId);
+ }
}
-JSBool JavaObject::toString(JSContext* ctx, JSObject* obj, uintN argc,
jsval* argv,
- jsval* rval) {
+JSBool JavaObject::toString(JSContext* ctx, JSObject* obj, uintN argc,
+ jsval* argv, jsval* rval) {
SessionData* data = JavaObject::getSessionData(ctx, obj);
+ if (!data) {
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
int oid = getObjectId(ctx, obj);
Debug::log(Debug::Spam) << "JavaObject::toString(id=" << oid << ")"
<< Debug::flush;
@@ -275,7 +287,8 @@
* the exception which was thrown. In this case, we always return false
and
* raise the exception ourselves.
*/
-JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval*
argv, jsval* rval) {
+JSBool JavaObject::call(JSContext* ctx, JSObject*, uintN argc, jsval* argv,
+ jsval* rval) {
// Get the JavaObject called as a function
JSObject* obj = JSVAL_TO_OBJECT(argv[-2]);
if (argc < 2 || !JSVAL_IS_INT(argv[0]) || !JSVAL_IS_OBJECT(argv[1])) {
@@ -294,6 +307,10 @@
dbg << ")" << Debug::flush;
SessionData* data = JavaObject::getSessionData(ctx, obj);
+ if (!data) {
+ *rval = JSVAL_VOID;
+ return JS_TRUE;
+ }
Debug::log(Debug::Spam) << "Data = " << data << Debug::flush;
Value javaThis;
@@ -338,6 +355,7 @@
// Debug::log(Debug::Spam) << " " << dumpJsVal(ctx, jsargs[i]) <<
Debug::flush;
data->makeValue(args[i], ctx, jsargs[i]);
}
+// static_cast<FFSessionHandler*>(handler)->sendFreeValues(*channel);
if (!InvokeMessage::send(*channel, javaThis, dispId, numArgs,
args.get())) {
Debug::log(Debug::Error) << "JavaObject::call failed to send invoke
message" << Debug::flush;
return false;
--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---