Subj : Re: Performance Interfacing to C++ To : netscape.public.mozilla.jseng From : Brendan Eich Date : Fri Aug 27 2004 07:47 pm Thorsten R wrote: >>You can use JSPROP_SHARED to avoid a value slot for such properties, but >>the engine will still build a hash table per object map (per object with >>its own properties, not one delegating all properties to its prototype), >>and those hash table entries will point into a global (per-runtime) >>lexicographic tree. > > > Can you give me a hint how to create an object which delegates all > properties to its prototype? Or is this the default as long as I don't add > any individual properties to an object? Yes, it's the default for new objects. > I'm currently using JS_InitClass() to create my prototype and then > JS_DefineObject() for each instance of my internal C++ objects. I do not add > any additional properties or methods to individual instances. (BTW, I found > out that using a prototype requires about half as much memory than calling > JS_DefineObject() without a prototype.) Why are you using JS_DefineObject? Do you mean you are creating a JS object to act as a peer or proxy for each C++ object and giving it a name in the global scope? Hmm. Reading again, I take it from this that you are defining the objects on the prototype itself. Have you considered using lazy techniques? See JSClass.resolve, JSClass.getProperty, JSClass.enumerate -- the comments on the function pointer typedefs in jspubtd.h are useful. >>Strings require special handling even if you store references to them in >>your private (to the JS engine) data and do not use value slots (i.e., >>use JSPROP_SHARED as suggested above), if you want to avoid JS taking >>ownership of the malloc'd jschar array, or copying from your storage >>into its own. See JS_AddExternalStringFinalizer and its comments in >>jsapi.h. > > > Thank you for pointing me to this function. I think I have to call > JS_NewExternalString() in my C++ getter to return an internal C++ string to > the JS engine, is this correct? If my finalizer callback function is called, > do I *need* to free the string? I don't think so. You need to free it if it would leak otherwise, but... > And I can't do so, because > it is freed in the destructor of my C++ object. It sounds like it is freed when a larger object is deleted -- but what ensures that the larger C++ object is deleted? > Is it possible to call > JS_AddExternalStringFinalizer() with finalizer = NULL, so I just get my > type-code? No, you will need to use a stub. > There comes one additional question to my mind: > Let's assume I have a C++ class "Text" with a member char *m_szStr, which is > "exported" to the JS engine as the property "Text.Str". > > Then I execute the following JS code: > Text.Str = "Hello World"; > Text.Str = "xyz"; > > If the C++ setter is called the second time by the engine due to the > assignment (Text.Str = "xyz"), is it safe to free my internal C++ string at > that moment? Or am I not allowed to do so, because the GC or anything else > in SpiderMonkey is still working with it, and I must wait until my > StringFinalizer callback is called? If your C++ object owns the C++ string, it can and should free it as you say. But if you have handed off ownership to the GC, via JS_AddExternalStringFinalizer, then you can't free it until the GC calls the finalizer you added. You can't have it both ways. Figure out your storage ownership model, in light of the JS API but also in light of your C++ requirements. That will make everything clear. /be .