Subj : Re: JS_ASSERT in js_MarkScriptFilename() To : netscape.public.mozilla.jseng From : "Edward Chan" Date : Fri Feb 20 2004 05:25 pm I've got a few questions: 1: In jsscript.c, js_SaveScriptFilename(), when sfe is returned by JS_HashTableRawAdd(), there is check JS_ASSERT(!sfe->mark); Why must sfe->mark not be 0? I know it "should" not be 0. But JS_HashTableRawAdd just does a raw malloc and doesn't memset the memory to 0 or anything. So if you're lucky, sfe->mark is 0, but if you're not, it can be non-zero, right? Or am I wrong and there is a memset or something done after the malloc that I missed. 2. In jsscript.c, js_script_filename_sweeper(), the if statement is this: if (!sfe->mark) { return HT_ENUMERATE_REMOVE; } Why do we remove if "not" marked? I thought if it "is" marked, that means it is ok to remove. 3. I've done JS_AddRoot to the script object that "I" create.. And I don't call JS_DestroyScript, nor do I call JS_RemoveRoot. So I'm pretty sure it's not my script object that is unrooted. What I notice though is the js engine also creates a lot of script objects (I think one for each function in the script). And it is one of these script objects that is getting marked in fun_mark() of jsfun.c. And the fact that it is getting marked means it is unrooted, right? So I'm not sure if you need to root these or not. But if you don't, it will get marked, which will mark the script filename, which will get deleted. But there is still at least one script object still pointing to that filename. What am I missing here? Thanks, Ed "Edward Chan" wrote in message news:c15jtl$pj2@ripley.netscape.com... > > "Brendan Eich" wrote in message > news:4035C288.2000201@meer.net... > > Edward Chan wrote: > > > > >Ok, some more info. After some debugging, I'm getting closer to > > >understanding what's going on. > > > > > >This is what I'm seeing, > > > > > >I'm in the process of doing a gc. While enumerating gcRootsHash, > > > > > >JS_DHashTableEnumerate(&rt->gcRootsHash, gc_root_marker, cx); > > > > > >it has found a JSScript object that it is marking. However, when it gets > to > > >js_MarkScript(), script->filename is bad. > > > > > >The reason it is bad is because a previous gc, has removed it from > > >script_filename_table, and freed it. > > > > > > > > > > Then the script(s) that referenced that filename were not visible the GC > > activated on that thread's runtime, which says that the pattern of > > Compile/Execute/DestroyScript you showed can' be all that is going on. > > > > >So I have a few questions: > > > > > >When filename is removed from script_filename_table, and freed, do you > null > > >out script->filename for all the script objects that are pointing to that > > >address in memory that was just freed? It seems like this is not the > case. > > > > > >But shouldn't it be? > > > > > > > > > > On the contrary: garbage collection means marking live objects reachable > > from other objects, ultimately from members of the root set. There is > > no means of "nulling" out otherwise-dangling reference, and no purpose > > -- the GC is broken if it collects something that live objects still > > reference. > > So what you're saying is that the script is being gc'd because it is not > rooted. Is that correct? But I've changed the execution sequence to be: > > JS_CompileFileHandle > JS_NewScriptObject > JS_AddRoot > JS_ExecuteScript > //JS_RemoveRoot - I commented this out; worst case I have a memory leak > right? > //JS_DestroyScript - I commented this out; worst case I have a memory leak > right? > > So the script object that I'm creating should never be unrooted now, right? > I notice that the js engine is creating script objects that also reference > the same filename (same memory). Are those objects rooted? Could those be > the problem? When I get the assert, the JSScript* that points to the > deleted filename is not the JSScript* that I got from JS_CompileFileHandle. > > > > > >But if so, how do you know which script objects are pointing to that > > >filename? I don't see where this is being maintained. > > > > > > > > > > You are thinking of some kind of weak reference system, with > > notification when the strong references all go away to clear > > intermediate weak delegates. The script filename table entries are > > garbage collected using mark&sweep. The mark phase starts from GC roots > > and should reach all live scripts. Any scripts not marked will not have > > their script filename table entries marked, so those entries may be > > collected if they are not marked via other scripts from the same file. > > > > Again, you have to find the unrooted script. > > As I said above, I've added JS_AddRoot to the script object that I get from > calling JS_NewScriptObject, passing it the JSScript* that I get from calling > JS_CompileFileHandle. I don't call JS_RemoveRoot, or JS_DestroyScript just > to make sure I'm not prematurely unrooting it or destroying it. The worse > that could happen by doing this is a memory leak right? Obviously I'm not > going to keep it that way; it's just for debugging. But I just want to make > sure I'm rooting everything. > > > > > Reminder: JS_ExecuteScript roots the executing script from cx->fp->script. > > > > When does it get unrooted? > > > /be > > .