📄 jsapi.c
字号:
}JS_PUBLIC_API(JSBool)JS_UnlockGCThingRT(JSRuntime *rt, void *thing){ return js_UnlockGCThingRT(rt, thing);}JS_PUBLIC_API(void)JS_MarkGCThing(JSContext *cx, void *thing, const char *name, void *arg){ JS_ASSERT(cx->runtime->gcLevel > 0);#ifdef JS_THREADSAFE JS_ASSERT(cx->runtime->gcThread->id == js_CurrentThreadId());#endif GC_MARK(cx, thing, name);}JS_PUBLIC_API(void)JS_GC(JSContext *cx){#if JS_HAS_GENERATORS /* Run previously scheduled but delayed close hooks. */ js_RunCloseHooks(cx);#endif /* Don't nuke active arenas if executing or compiling. */ if (cx->stackPool.current == &cx->stackPool.first) JS_FinishArenaPool(&cx->stackPool); if (cx->tempPool.current == &cx->tempPool.first) JS_FinishArenaPool(&cx->tempPool); js_GC(cx, GC_NORMAL);#if JS_HAS_GENERATORS /* * Run close hooks for objects that became unreachable after the last GC. */ js_RunCloseHooks(cx);#endif}JS_PUBLIC_API(void)JS_MaybeGC(JSContext *cx){#ifdef WAY_TOO_MUCH_GC JS_GC(cx);#else JSRuntime *rt; uint32 bytes, lastBytes; rt = cx->runtime; bytes = rt->gcBytes; lastBytes = rt->gcLastBytes; /* * We run the GC if we used all available free GC cells and had to * allocate extra 1/5 of GC arenas since the last run of GC, or if * we have malloc'd more bytes through JS_malloc than we were told * to allocate by JS_NewRuntime. * * The reason for * bytes > 6/5 lastBytes * condition is the following. Bug 312238 changed bytes and lastBytes * to mean the total amount of memory that the GC uses now and right * after the last GC. * * Before the bug the variables meant the size of allocated GC things * now and right after the last GC. That size did not include the * memory taken by free GC cells and the condition was * bytes > 3/2 lastBytes. * That is, we run the GC if we have half again as many bytes of * GC-things as the last time we GC'd. To be compatible we need to * express that condition through the new meaning of bytes and * lastBytes. * * We write the original condition as * B*(1-F) > 3/2 Bl*(1-Fl) * where B is the total memory size allocated by GC and F is the free * cell density currently and Sl and Fl are the size and the density * right after GC. The density by definition is memory taken by free * cells divided by total amount of memory. In other words, B and Bl * are bytes and lastBytes with the new meaning and B*(1-F) and * Bl*(1-Fl) are bytes and lastBytes with the original meaning. * * Our task is to exclude F and Fl from the last statement. According * the stats from bug 331770 Fl is about 20-30% for GC allocations * that contribute to S and Sl for a typical run of the browser. It * means that the original condition implied that we did not run GC * unless we exhausted the pool of free cells. Indeed if we still * have free cells, then B == Bl since we did not yet allocated any * new arenas and the condition means * 1 - F > 3/2 (1-Fl) or 3/2Fl > 1/2 + F * That implies 3/2 Fl > 1/2 or Fl > 1/3. That can not be fulfilled * for the state described by the stats. So we can write the original * condition as: * F == 0 && B > 3/2 Bl(1-Fl) * Again using the stats we see that Fl is about 20% when the browser * starts up and when we are far from hitting rt->gcMaxBytes. With * this F we have * F == 0 && B > 3/2 Bl(1-0.8) or just B > 6/5 Bl. */ if ((bytes > 8192 && bytes > lastBytes + lastBytes / 5) || rt->gcMallocBytes >= rt->gcMaxMallocBytes) { JS_GC(cx); }#if JS_HAS_GENERATORS else { /* Run scheduled but not yet executed close hooks. */ js_RunCloseHooks(cx); }#endif#endif}JS_PUBLIC_API(JSGCCallback)JS_SetGCCallback(JSContext *cx, JSGCCallback cb){ return JS_SetGCCallbackRT(cx->runtime, cb);}JS_PUBLIC_API(JSGCCallback)JS_SetGCCallbackRT(JSRuntime *rt, JSGCCallback cb){ JSGCCallback oldcb; oldcb = rt->gcCallback; rt->gcCallback = cb; return oldcb;}JS_PUBLIC_API(JSBool)JS_IsAboutToBeFinalized(JSContext *cx, void *thing){ JS_ASSERT(thing); return js_IsAboutToBeFinalized(cx, thing);}JS_PUBLIC_API(void)JS_SetGCParameter(JSRuntime *rt, JSGCParamKey key, uint32 value){ switch (key) { case JSGC_MAX_BYTES: rt->gcMaxBytes = value; break; case JSGC_MAX_MALLOC_BYTES: rt->gcMaxMallocBytes = value; break; }}JS_PUBLIC_API(intN)JS_AddExternalStringFinalizer(JSStringFinalizeOp finalizer){ return js_ChangeExternalStringFinalizer(NULL, finalizer);}JS_PUBLIC_API(intN)JS_RemoveExternalStringFinalizer(JSStringFinalizeOp finalizer){ return js_ChangeExternalStringFinalizer(finalizer, NULL);}JS_PUBLIC_API(JSString *)JS_NewExternalString(JSContext *cx, jschar *chars, size_t length, intN type){ JSString *str; CHECK_REQUEST(cx); JS_ASSERT(GCX_EXTERNAL_STRING <= type && type < (intN) GCX_NTYPES); str = (JSString *) js_NewGCThing(cx, (uintN) type, sizeof(JSString)); if (!str) return NULL; str->length = length; str->chars = chars; return str;}JS_PUBLIC_API(intN)JS_GetExternalStringGCType(JSRuntime *rt, JSString *str){ uint8 type = (uint8) (*js_GetGCThingFlags(str) & GCF_TYPEMASK); if (type >= GCX_EXTERNAL_STRING) return (intN)type; JS_ASSERT(type == GCX_STRING || type == GCX_MUTABLE_STRING); return -1;}JS_PUBLIC_API(void)JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr){#if JS_STACK_GROWTH_DIRECTION > 0 if (limitAddr == 0) limitAddr = (jsuword)-1;#endif cx->stackLimit = limitAddr;}/************************************************************************/JS_PUBLIC_API(void)JS_DestroyIdArray(JSContext *cx, JSIdArray *ida){ JS_free(cx, ida);}JS_PUBLIC_API(JSBool)JS_ValueToId(JSContext *cx, jsval v, jsid *idp){ JSAtom *atom; CHECK_REQUEST(cx); if (JSVAL_IS_INT(v)) { *idp = INT_JSVAL_TO_JSID(v); } else {#if JS_HAS_XML_SUPPORT if (JSVAL_IS_OBJECT(v)) { *idp = OBJECT_JSVAL_TO_JSID(v); return JS_TRUE; }#endif atom = js_ValueToStringAtom(cx, v); if (!atom) return JS_FALSE; *idp = ATOM_TO_JSID(atom); } return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_IdToValue(JSContext *cx, jsid id, jsval *vp){ CHECK_REQUEST(cx); *vp = ID_TO_VALUE(id); return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_PropertyStub(JSContext *cx, JSObject *obj, jsval id, jsval *vp){ return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_EnumerateStub(JSContext *cx, JSObject *obj){ return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_ResolveStub(JSContext *cx, JSObject *obj, jsval id){ return JS_TRUE;}JS_PUBLIC_API(JSBool)JS_ConvertStub(JSContext *cx, JSObject *obj, JSType type, jsval *vp){ return js_TryValueOf(cx, obj, type, vp);}JS_PUBLIC_API(void)JS_FinalizeStub(JSContext *cx, JSObject *obj){}JS_PUBLIC_API(JSObject *)JS_InitClass(JSContext *cx, JSObject *obj, JSObject *parent_proto, JSClass *clasp, JSNative constructor, uintN nargs, JSPropertySpec *ps, JSFunctionSpec *fs, JSPropertySpec *static_ps, JSFunctionSpec *static_fs){ JSAtom *atom; JSProtoKey key; JSObject *proto, *ctor; JSTempValueRooter tvr; jsval cval, rval; JSBool named; JSFunction *fun; CHECK_REQUEST(cx); atom = js_Atomize(cx, clasp->name, strlen(clasp->name), 0); if (!atom) return NULL; /* * When initializing a standard class, if no parent_proto (grand-proto of * instances of the class, parent-proto of the class's prototype object) * is given, we must use Object.prototype if it is available. Otherwise, * we could look up the wrong binding for a class name in obj. Example: * * String = Array; * print("hi there".join); * * should print undefined, not Array.prototype.join. This is required by * ECMA-262, alas. It might have been better to make String readonly and * permanent in the global object, instead -- but that's too big a change * to swallow at this point. */ key = JSCLASS_CACHED_PROTO_KEY(clasp); if (key != JSProto_Null && !parent_proto && !js_GetClassPrototype(cx, obj, INT_TO_JSID(JSProto_Object), &parent_proto)) { return NULL; } /* Create a prototype object for this class. */ proto = js_NewObject(cx, clasp, parent_proto, obj); if (!proto) return NULL; /* After this point, control must exit via label bad or out. */ JS_PUSH_TEMP_ROOT_OBJECT(cx, proto, &tvr); if (!constructor) { /* * Lacking a constructor, name the prototype (e.g., Math) unless this * class (a) is anonymous, i.e. for internal use only; (b) the class * of obj (the global object) is has a reserved slot indexed by key; * and (c) key is not the null key. */ if ((clasp->flags & JSCLASS_IS_ANONYMOUS) && (OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_IS_GLOBAL) && key != JSProto_Null) { named = JS_FALSE; } else { named = OBJ_DEFINE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), OBJECT_TO_JSVAL(proto), NULL, NULL, (clasp->flags & JSCLASS_IS_ANONYMOUS) ? JSPROP_READONLY | JSPROP_PERMANENT : 0, NULL); if (!named) goto bad; } ctor = proto; } else { /* Define the constructor function in obj's scope. */ fun = js_DefineFunction(cx, obj, atom, constructor, nargs, 0); named = (fun != NULL); if (!fun) goto bad; /* * Remember the class this function is a constructor for so that * we know to create an object of this class when we call the * constructor. */ fun->clasp = clasp; /* * Optionally construct the prototype object, before the class has * been fully initialized. Allow the ctor to replace proto with a * different object, as is done for operator new -- and as at least * XML support requires. */ ctor = fun->object; if (clasp->flags & JSCLASS_CONSTRUCT_PROTOTYPE) { cval = OBJECT_TO_JSVAL(ctor); if (!js_InternalConstruct(cx, proto, cval, 0, NULL, &rval)) goto bad; if (!JSVAL_IS_PRIMITIVE(rval) && JSVAL_TO_OBJECT(rval) != proto) proto = JSVAL_TO_OBJECT(rval); } /* Connect constructor and prototype by named properties. */ if (!js_SetClassPrototype(cx, ctor, proto, JSPROP_READONLY | JSPROP_PERMANENT)) { goto bad; } /* Bootstrap Function.prototype (see also JS_InitStandardClasses). */ if (OBJ_GET_CLASS(cx, ctor) == clasp) { JS_ASSERT(!OBJ_GET_PROTO(cx, ctor)); OBJ_SET_PROTO(cx, ctor, proto); } } /* Add properties and methods to the prototype and the constructor. */ if ((ps && !JS_DefineProperties(cx, proto, ps)) || (fs && !JS_DefineFunctions(cx, proto, fs)) || (static_ps && !JS_DefineProperties(cx, ctor, static_ps)) || (static_fs && !JS_DefineFunctions(cx, ctor, static_fs))) { goto bad; } /* If this is a standard class, cache its prototype. */ if (key != JSProto_Null && !js_SetClassObject(cx, obj, key, ctor)) goto bad;out: JS_POP_TEMP_ROOT(cx, &tvr); return proto;bad: if (named) (void) OBJ_DELETE_PROPERTY(cx, obj, ATOM_TO_JSID(atom), &rval); proto = NULL; goto out;}#ifdef JS_THREADSAFEJS_PUBLIC_API(JSClass *)JS_GetClass(JSContext *cx, JSObject *obj){ return (JSClass *) JSVAL_TO_PRIVATE(GC_AWARE_GET_SLOT(cx, obj, JSSLOT_CLASS));}#elseJS_PUBLIC_API(JSClass *)JS_GetClass(JSObject *obj){ return LOCKED_OBJ_GET_CLASS(obj);}#endifJS_PUBLIC_API(JSBool)JS_InstanceOf(JSContext *cx, JSObject *obj, JSClass *clasp, jsval *argv){ JSFunction *fun; CHECK_REQUEST(cx); if (OBJ_GET_CLASS(cx, obj) == clasp) return JS_TRUE; if (argv) { fun = js_ValueToFunction(cx, &argv[-2], 0); if (fun) { JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_INCOMPATIBLE_PROTO, clasp->name, JS_GetFunctionName(fun), OBJ_GET_CLASS(cx, obj)->name); } } return JS_FALSE;}JS_PUBLIC_API(JSBool)JS_HasInstance(JSContext *cx, JSObject *obj, jsval v, JSBool *bp){ return js_HasInstance(cx, obj, v, bp);}JS_PUBLIC_API(void *)JS_GetPrivate(JSContext *cx, JSObject *obj){ jsval v; JS_ASSERT(OBJ_GET_CLASS(cx, obj)->flags & JSCLASS_HAS_PRIVATE); v = GC_AWARE_GET_SLOT(cx, obj, JSSLOT_PRIVATE); if (!JSVAL_IS_INT(v)) return NULL; return JSVAL_TO_PRIVATE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -