JSBool jsd_ClearExecutionHook(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc) { JSDExecHook* jsdhook; JSD_LOCK(); jsdhook = _findHook(jsdc, jsdscript, pc); if( ! jsdhook ) { JSD_UNLOCK(); return JS_FALSE; } JS_ClearTrap(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc, NULL, NULL ); JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_ClearExecutionHook(JSDContext* jsdc, JSDScript* jsdscript, uintptr_t pc) { JSCompartment* oldCompartment; JSDExecHook* jsdhook; JSD_LOCK(); jsdhook = _findHook(jsdc, jsdscript, pc); if( ! jsdhook ) { JSD_UNLOCK(); return JS_FALSE; } oldCompartment = JS_EnterCompartmentOfScript(jsdc->dumbContext, jsdscript->script); JS_ClearTrap(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc, NULL, NULL ); JS_LeaveCompartment(jsdc->dumbContext, oldCompartment); JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); JSD_UNLOCK(); return JS_TRUE; }
static void _destroyJSDContext(JSDContext* jsdc) { JSD_ASSERT_VALID_CONTEXT(jsdc); JSD_LOCK(); JS_REMOVE_LINK(&jsdc->links); JSD_UNLOCK(); if ( jsdc->dumbContext && jsdc->glob ) { JS_RemoveObjectRootRT(JS_GetRuntime(jsdc->dumbContext), &jsdc->glob); } jsd_DestroyObjectManager(jsdc); jsd_DestroyAtomTable(jsdc); jsdc->inited = JS_FALSE; /* * We should free jsdc here, but we let it leak in case there are any * asynchronous hooks calling into the system using it as a handle * * XXX we also leak the locks */ JS_DestroyContext(jsdc->dumbContext); jsdc->dumbContext = NULL; }
static JSBool DropWatchPoint(JSContext *cx, JSWatchPoint *wp) { JSScopeProperty *sprop; if (--wp->nrefs != 0) return JS_TRUE; /* * Remove wp from the list, then if there are no other watchpoints for * wp->sprop in any scope, restore wp->sprop->setter from wp. */ JS_REMOVE_LINK(&wp->links); sprop = wp->sprop; if (!js_GetWatchedSetter(cx->runtime, NULL, sprop)) { sprop = js_ChangeNativePropertyAttrs(cx, wp->object, sprop, 0, sprop->attrs, sprop->getter, wp->setter); if (!sprop) return JS_FALSE; } js_RemoveRoot(cx->runtime, &wp->closure); JS_free(cx, wp); return JS_TRUE; }
JSBool jsd_ClearExecutionHook(JSDContext* jsdc, JSDScript* jsdscript, jsuword pc) { JSCrossCompartmentCall *call; JSDExecHook* jsdhook; JSD_LOCK(); jsdhook = _findHook(jsdc, jsdscript, pc); if( ! jsdhook ) { JSD_UNLOCK(); return JS_FALSE; } call = JS_EnterCrossCompartmentCallScript(jsdc->dumbContext, jsdscript->script); if(!call) { JSD_UNLOCK(); return JS_FALSE; } JS_ClearTrap(jsdc->dumbContext, jsdscript->script, (jsbytecode*)pc, NULL, NULL ); JS_LeaveCrossCompartmentCall(call); JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); JSD_UNLOCK(); return JS_TRUE; }
static void DestroyTrap(JSContext *cx, JSTrap *trap) { JS_REMOVE_LINK(&trap->links); *trap->pc = (jsbytecode)trap->op; js_RemoveRoot(cx->runtime, &trap->closure); JS_free(cx, trap); }
void jsd_DestroyThreadState(JSDContext* jsdc, JSDThreadState* jsdthreadstate) { JSDStackFrameInfo* jsdframe; JSCList* list; JS_ASSERT(jsdthreadstate); JS_ASSERT(JSD_CURRENT_THREAD() == jsdthreadstate->thread); JSD_LOCK_THREADSTATES(jsdc); JS_REMOVE_LINK(&jsdthreadstate->links); JSD_UNLOCK_THREADSTATES(jsdc); list = &jsdthreadstate->stack; while( (JSDStackFrameInfo*)list != (jsdframe = (JSDStackFrameInfo*)list->next) ) { JS_REMOVE_LINK(&jsdframe->links); _destroyFrame(jsdframe); } free(jsdthreadstate); }
/* * Sets current thread as owning thread of a context by assigning the * thread-private info to the context. If the current thread doesn't have * private JSThread info, create one. */ JSBool js_SetContextThread(JSContext *cx) { JSThread *thread = js_GetCurrentThread(cx->runtime); if (!thread) { JS_ReportOutOfMemory(cx); return JS_FALSE; } cx->thread = thread; JS_REMOVE_LINK(&cx->threadLinks); JS_APPEND_LINK(&cx->threadLinks, &thread->contextList); return JS_TRUE; }
static void _destroyJSDObject(JSDContext* jsdc, JSDObject* jsdobj) { JS_ASSERT(JSD_OBJECTS_LOCKED(jsdc)); JS_REMOVE_LINK(&jsdobj->links); JS_HashTableRemove(jsdc->objectsTable, jsdobj->obj); if(jsdobj->newURL) jsd_DropAtom(jsdc, jsdobj->newURL); if(jsdobj->ctorURL) jsd_DropAtom(jsdc, jsdobj->ctorURL); if(jsdobj->ctorName) jsd_DropAtom(jsdc, jsdobj->ctorName); free(jsdobj); }
static void _destroyJSDScript(JSDContext* jsdc, JSDScript* jsdscript) { JS_ASSERT(JSD_SCRIPTS_LOCKED(jsdc)); /* destroy all hooks */ jsd_ClearAllExecutionHooksForScript(jsdc, jsdscript); JS_REMOVE_LINK(&jsdscript->links); if(jsdscript->url) free(jsdscript->url); if (jsdscript->profileData) free(jsdscript->profileData); free(jsdscript); }
JSBool jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript) { JSDExecHook* jsdhook; JSCList* list = &jsdscript->hooks; JSD_LOCK(); while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) ) { JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); } JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script); JSD_UNLOCK(); return JS_TRUE; }
JSBool jsd_ClearAllExecutionHooksForScript(JSDContext* jsdc, JSDScript* jsdscript) { JSDExecHook* jsdhook; JSCList* list = &jsdscript->hooks; JSD_LOCK(); while( (JSDExecHook*)list != (jsdhook = (JSDExecHook*)list->next) ) { JS_REMOVE_LINK(&jsdhook->links); free(jsdhook); } /* No cross-compartment call here because we may be in the middle of GC */ JS_ClearScriptTraps(jsdc->dumbContext, jsdscript->script); JSD_UNLOCK(); return JS_TRUE; }
void js_DestroyContext(JSContext *cx, JSGCMode gcmode) { JSRuntime *rt; JSBool last; JSArgumentFormatMap *map; rt = cx->runtime; /* Remove cx from context list first. */ JS_LOCK_RUNTIME(rt); JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING); JS_REMOVE_LINK(&cx->links); last = (rt->contextList.next == &rt->contextList); if (last) rt->state = JSRTS_LANDING; JS_UNLOCK_RUNTIME(rt); if (last) { /* Unpin all pinned atoms before final GC. */ js_UnpinPinnedAtoms(&rt->atomState); /* Unlock and clear GC things held by runtime pointers. */ js_FinishRuntimeNumberState(cx); js_FinishRuntimeStringState(cx); /* Clear debugging state to remove GC roots. */ JS_ClearAllTraps(cx); JS_ClearAllWatchPoints(cx); } #if JS_HAS_REGEXPS /* * Remove more GC roots in regExpStatics, then collect garbage. * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within * XXX this function call to wait for any racing GC to complete, in the * XXX case where JS_DestroyContext is called outside of a request on cx */ js_FreeRegExpStatics(cx, &cx->regExpStatics); #endif #ifdef JS_THREADSAFE /* * Destroying a context implicitly calls JS_EndRequest(). Also, we must * end our request here in case we are "last" -- in that event, another * js_DestroyContext that was not last might be waiting in the GC for our * request to end. We'll let it run below, just before we do the truly * final GC and then free atom state. * * At this point, cx must be inaccessible to other threads. It's off the * rt->contextList, and it should not be reachable via any object private * data structure. */ while (cx->requestDepth != 0) JS_EndRequest(cx); #endif if (last) { /* Always force, so we wait for any racing GC to finish. */ js_ForceGC(cx); /* Iterate until no finalizer removes a GC root or lock. */ while (rt->gcPoke) js_GC(cx, GC_LAST_CONTEXT); /* Try to free atom state, now that no unrooted scripts survive. */ if (rt->atomState.liveAtoms == 0) js_FreeAtomState(cx, &rt->atomState); /* Take the runtime down, now that it has no contexts or atoms. */ JS_LOCK_RUNTIME(rt); rt->state = JSRTS_DOWN; JS_NOTIFY_ALL_CONDVAR(rt->stateChange); JS_UNLOCK_RUNTIME(rt); } else { if (gcmode == JS_FORCE_GC) js_ForceGC(cx); else if (gcmode == JS_MAYBE_GC) JS_MaybeGC(cx); } /* Free the stuff hanging off of cx. */ JS_FinishArenaPool(&cx->stackPool); JS_FinishArenaPool(&cx->codePool); JS_FinishArenaPool(&cx->notePool); JS_FinishArenaPool(&cx->tempPool); if (cx->lastMessage) free(cx->lastMessage); /* Remove any argument formatters. */ map = cx->argumentFormatMap; while (map) { JSArgumentFormatMap *temp = map; map = map->next; JS_free(cx, temp); } /* Destroy the resolve recursion damper. */ if (cx->resolvingTable) { JS_DHashTableDestroy(cx->resolvingTable); cx->resolvingTable = NULL; } /* Finally, free cx itself. */ free(cx); }
void js_DestroyContext(JSContext *cx, JSDestroyContextMode mode) { JSRuntime *rt; JSContextCallback cxCallback; JSBool last; JSArgumentFormatMap *map; JSLocalRootStack *lrs; JSLocalRootChunk *lrc; rt = cx->runtime; if (mode != JSDCM_NEW_FAILED) { cxCallback = rt->cxCallback; if (cxCallback) { /* * JSCONTEXT_DESTROY callback is not allowed to fail and must * return true. */ #ifdef DEBUG JSBool callbackStatus = #endif cxCallback(cx, JSCONTEXT_DESTROY); JS_ASSERT(callbackStatus); } } /* Remove cx from context list first. */ JS_LOCK_GC(rt); JS_ASSERT(rt->state == JSRTS_UP || rt->state == JSRTS_LAUNCHING); JS_REMOVE_LINK(&cx->links); last = (rt->contextList.next == &rt->contextList); if (last) rt->state = JSRTS_LANDING; JS_UNLOCK_GC(rt); if (last) { #ifdef JS_THREADSAFE /* * If cx is not in a request already, begin one now so that we wait * for any racing GC started on a not-last context to finish, before * we plow ahead and unpin atoms. Note that even though we begin a * request here if necessary, we end all requests on cx below before * forcing a final GC. This lets any not-last context destruction * racing in another thread try to force or maybe run the GC, but by * that point, rt->state will not be JSRTS_UP, and that GC attempt * will return early. */ if (cx->requestDepth == 0) JS_BeginRequest(cx); #endif /* Unlock and clear GC things held by runtime pointers. */ js_FinishRuntimeNumberState(cx); js_FinishRuntimeStringState(cx); /* Unpin all common atoms before final GC. */ js_FinishCommonAtoms(cx); /* Clear debugging state to remove GC roots. */ JS_ClearAllTraps(cx); JS_ClearAllWatchPoints(cx); } /* * Remove more GC roots in regExpStatics, then collect garbage. * XXX anti-modularity alert: we rely on the call to js_RemoveRoot within * XXX this function call to wait for any racing GC to complete, in the * XXX case where JS_DestroyContext is called outside of a request on cx */ js_FreeRegExpStatics(cx, &cx->regExpStatics); #ifdef JS_THREADSAFE /* * Destroying a context implicitly calls JS_EndRequest(). Also, we must * end our request here in case we are "last" -- in that event, another * js_DestroyContext that was not last might be waiting in the GC for our * request to end. We'll let it run below, just before we do the truly * final GC and then free atom state. * * At this point, cx must be inaccessible to other threads. It's off the * rt->contextList, and it should not be reachable via any object private * data structure. */ while (cx->requestDepth != 0) JS_EndRequest(cx); #endif if (last) { js_GC(cx, GC_LAST_CONTEXT); /* * Free the script filename table if it exists and is empty. Do this * after the last GC to avoid finalizers tripping on free memory. */ if (rt->scriptFilenameTable && rt->scriptFilenameTable->nentries == 0) js_FinishRuntimeScriptState(rt); /* Take the runtime down, now that it has no contexts or atoms. */ JS_LOCK_GC(rt); rt->state = JSRTS_DOWN; JS_NOTIFY_ALL_CONDVAR(rt->stateChange); JS_UNLOCK_GC(rt); } else { if (mode == JSDCM_FORCE_GC) js_GC(cx, GC_NORMAL); else if (mode == JSDCM_MAYBE_GC) JS_MaybeGC(cx); } /* Free the stuff hanging off of cx. */ JS_FinishArenaPool(&cx->stackPool); JS_FinishArenaPool(&cx->tempPool); if (cx->lastMessage) free(cx->lastMessage); /* Remove any argument formatters. */ map = cx->argumentFormatMap; while (map) { JSArgumentFormatMap *temp = map; map = map->next; JS_free(cx, temp); } /* Destroy the resolve recursion damper. */ if (cx->resolvingTable) { JS_DHashTableDestroy(cx->resolvingTable); cx->resolvingTable = NULL; } lrs = cx->localRootStack; if (lrs) { while ((lrc = lrs->topChunk) != &lrs->firstChunk) { lrs->topChunk = lrc->down; JS_free(cx, lrc); } JS_free(cx, lrs); } #ifdef JS_THREADSAFE js_ClearContextThread(cx); #endif /* Finally, free cx itself. */ free(cx); }
/* Remove the owning thread info of a context. */ void js_ClearContextThread(JSContext *cx) { cx->thread = NULL; JS_REMOVE_LINK(&cx->threadLinks); }