Subj : Re: JS_ASSERT in js_MarkScriptFilename() To : netscape.public.mozilla.jseng From : "Edward Chan" Date : Fri Feb 20 2004 05:47 pm Sorry for my previous post. Regarding (2) and (3), I now understand what the mark and sweep is doing. But I'm still not sure about (1). And I'm still not sure when the script objects (that js engine is creating) are unrooted. Because unless "all" the script objects are unrooted at the end (whatever "end" means, perhaps JS_DestroyScript?), the second one is unrooted the ScriptFilenameEntry in the script_filename_table will be unmarked and deleted. So when the other scripts try to mark it, it will be accessing deleted memory. Am I starting to understand the way gc is working, or am I still way off? Sorry for all this confusion. Ed "Edward Chan" wrote in message news:c16c8i$7rj3@ripley.netscape.com... > 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 > > > > > > .