📄 jsatom.c
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS atom table. */#include "jsstddef.h"#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsutil.h" /* Added by JSIFY */#include "jshash.h" /* Added by JSIFY */#include "jsprf.h"#include "jsapi.h"#include "jsatom.h"#include "jscntxt.h"#include "jsconfig.h"#include "jsgc.h"#include "jslock.h"#include "jsnum.h"#include "jsscan.h"#include "jsstr.h"JS_FRIEND_API(const char *)js_AtomToPrintableString(JSContext *cx, JSAtom *atom){ return js_ValueToPrintableString(cx, ATOM_KEY(atom));}/* * Keep this in sync with jspubtd.h -- an assertion below will insist that * its length match the JSType enum's JSTYPE_LIMIT limit value. */const char *js_type_strs[] = { "undefined", js_object_str, "function", "string", "number", "boolean", "null", "xml",};JS_STATIC_ASSERT(JSTYPE_LIMIT == sizeof js_type_strs / sizeof js_type_strs[0]);const char *js_boolean_strs[] = { js_false_str, js_true_str};#define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;#include "jsproto.tbl"#undef JS_PROTOconst char *js_proto_strs[JSProto_LIMIT] = {#define JS_PROTO(name,code,init) js_##name##_str,#include "jsproto.tbl"#undef JS_PROTO};const char js_anonymous_str[] = "anonymous";const char js_arguments_str[] = "arguments";const char js_arity_str[] = "arity";const char js_callee_str[] = "callee";const char js_caller_str[] = "caller";const char js_class_prototype_str[] = "prototype";const char js_constructor_str[] = "constructor";const char js_count_str[] = "__count__";const char js_each_str[] = "each";const char js_eval_str[] = "eval";const char js_fileName_str[] = "fileName";const char js_get_str[] = "get";const char js_getter_str[] = "getter";const char js_index_str[] = "index";const char js_input_str[] = "input";const char js_iterator_str[] = "__iterator__";const char js_length_str[] = "length";const char js_lineNumber_str[] = "lineNumber";const char js_message_str[] = "message";const char js_name_str[] = "name";const char js_next_str[] = "next";const char js_noSuchMethod_str[] = "__noSuchMethod__";const char js_object_str[] = "object";const char js_parent_str[] = "__parent__";const char js_proto_str[] = "__proto__";const char js_setter_str[] = "setter";const char js_set_str[] = "set";const char js_stack_str[] = "stack";const char js_toSource_str[] = "toSource";const char js_toString_str[] = "toString";const char js_toLocaleString_str[] = "toLocaleString";const char js_valueOf_str[] = "valueOf";#if JS_HAS_XML_SUPPORTconst char js_etago_str[] = "</";const char js_namespace_str[] = "namespace";const char js_ptagc_str[] = "/>";const char js_qualifier_str[] = "::";const char js_space_str[] = " ";const char js_stago_str[] = "<";const char js_star_str[] = "*";const char js_starQualifier_str[] = "*::";const char js_tagc_str[] = ">";const char js_xml_str[] = "xml";#endif#if JS_HAS_GENERATORSconst char js_close_str[] = "close";const char js_send_str[] = "send";#endif#ifdef NARCISSUSconst char js_call_str[] = "__call__";const char js_construct_str[] = "__construct__";const char js_hasInstance_str[] = "__hasInstance__";const char js_ExecutionContext_str[] = "ExecutionContext";const char js_current_str[] = "current";#endif#define HASH_OBJECT(o) (JS_PTR_TO_UINT32(o) >> JSVAL_TAGBITS)#define HASH_INT(i) ((JSHashNumber)(i))#define HASH_DOUBLE(dp) ((JSDOUBLE_HI32(*dp) ^ JSDOUBLE_LO32(*dp)))#define HASH_BOOLEAN(b) ((JSHashNumber)(b))JS_STATIC_DLL_CALLBACK(JSHashNumber)js_hash_atom_key(const void *key){ jsval v; jsdouble *dp; /* Order JSVAL_IS_* tests by likelihood of success. */ v = (jsval)key; if (JSVAL_IS_STRING(v)) return js_HashString(JSVAL_TO_STRING(v)); if (JSVAL_IS_INT(v)) return HASH_INT(JSVAL_TO_INT(v)); if (JSVAL_IS_DOUBLE(v)) { dp = JSVAL_TO_DOUBLE(v); return HASH_DOUBLE(dp); } if (JSVAL_IS_OBJECT(v)) return HASH_OBJECT(JSVAL_TO_OBJECT(v)); if (JSVAL_IS_BOOLEAN(v)) return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v)); return (JSHashNumber)v;}JS_STATIC_DLL_CALLBACK(intN)js_compare_atom_keys(const void *k1, const void *k2){ jsval v1, v2; v1 = (jsval)k1, v2 = (jsval)k2; if (JSVAL_IS_STRING(v1) && JSVAL_IS_STRING(v2)) return js_EqualStrings(JSVAL_TO_STRING(v1), JSVAL_TO_STRING(v2)); if (JSVAL_IS_DOUBLE(v1) && JSVAL_IS_DOUBLE(v2)) { double d1 = *JSVAL_TO_DOUBLE(v1); double d2 = *JSVAL_TO_DOUBLE(v2); if (JSDOUBLE_IS_NaN(d1)) return JSDOUBLE_IS_NaN(d2);#if defined(XP_WIN) /* XXX MSVC miscompiles such that (NaN == 0) */ if (JSDOUBLE_IS_NaN(d2)) return JS_FALSE;#endif return d1 == d2; } return v1 == v2;}JS_STATIC_DLL_CALLBACK(int)js_compare_stub(const void *v1, const void *v2){ return 1;}/* These next two are exported to jsscript.c and used similarly there. */void * JS_DLL_CALLBACKjs_alloc_table_space(void *priv, size_t size){ return malloc(size);}void JS_DLL_CALLBACKjs_free_table_space(void *priv, void *item){ free(item);}JS_STATIC_DLL_CALLBACK(JSHashEntry *)js_alloc_atom(void *priv, const void *key){ JSAtomState *state = (JSAtomState *) priv; JSAtom *atom; atom = (JSAtom *) malloc(sizeof(JSAtom)); if (!atom) return NULL;#ifdef JS_THREADSAFE state->tablegen++;#endif atom->entry.key = key; atom->entry.value = NULL; atom->flags = 0; atom->number = state->number++; return &atom->entry;}JS_STATIC_DLL_CALLBACK(void)js_free_atom(void *priv, JSHashEntry *he, uintN flag){ if (flag != HT_FREE_ENTRY) return;#ifdef JS_THREADSAFE ((JSAtomState *)priv)->tablegen++;#endif free(he);}static JSHashAllocOps atom_alloc_ops = { js_alloc_table_space, js_free_table_space, js_alloc_atom, js_free_atom};#define JS_ATOM_HASH_SIZE 1024JSBooljs_InitAtomState(JSContext *cx, JSAtomState *state){ state->table = JS_NewHashTable(JS_ATOM_HASH_SIZE, js_hash_atom_key, js_compare_atom_keys, js_compare_stub, &atom_alloc_ops, state); if (!state->table) { JS_ReportOutOfMemory(cx); return JS_FALSE; } state->runtime = cx->runtime;#ifdef JS_THREADSAFE js_InitLock(&state->lock); state->tablegen = 0;#endif if (!js_InitPinnedAtoms(cx, state)) { js_FreeAtomState(cx, state); return JS_FALSE; } return JS_TRUE;}JSBooljs_InitPinnedAtoms(JSContext *cx, JSAtomState *state){ uintN i;#define FROB(lval,str) \ JS_BEGIN_MACRO \ if (!(state->lval = js_Atomize(cx, str, strlen(str), ATOM_PINNED))) \ return JS_FALSE; \ JS_END_MACRO for (i = 0; i < JSTYPE_LIMIT; i++) FROB(typeAtoms[i], js_type_strs[i]); for (i = 0; i < JSProto_LIMIT; i++) FROB(classAtoms[i], js_proto_strs[i]); FROB(booleanAtoms[0], js_false_str); FROB(booleanAtoms[1], js_true_str); FROB(nullAtom, js_null_str); FROB(anonymousAtom, js_anonymous_str); FROB(argumentsAtom, js_arguments_str); FROB(arityAtom, js_arity_str); FROB(calleeAtom, js_callee_str); FROB(callerAtom, js_caller_str); FROB(classPrototypeAtom, js_class_prototype_str); FROB(constructorAtom, js_constructor_str); FROB(countAtom, js_count_str); FROB(eachAtom, js_each_str); FROB(evalAtom, js_eval_str); FROB(fileNameAtom, js_fileName_str); FROB(getAtom, js_get_str); FROB(getterAtom, js_getter_str); FROB(indexAtom, js_index_str); FROB(inputAtom, js_input_str); FROB(iteratorAtom, js_iterator_str); FROB(lengthAtom, js_length_str); FROB(lineNumberAtom, js_lineNumber_str); FROB(messageAtom, js_message_str); FROB(nameAtom, js_name_str); FROB(nextAtom, js_next_str); FROB(noSuchMethodAtom, js_noSuchMethod_str); FROB(parentAtom, js_parent_str); FROB(protoAtom, js_proto_str); FROB(setAtom, js_set_str); FROB(setterAtom, js_setter_str); FROB(stackAtom, js_stack_str); FROB(toSourceAtom, js_toSource_str); FROB(toStringAtom, js_toString_str); FROB(toLocaleStringAtom, js_toLocaleString_str); FROB(valueOfAtom, js_valueOf_str);#if JS_HAS_XML_SUPPORT FROB(etagoAtom, js_etago_str); FROB(namespaceAtom, js_namespace_str); FROB(ptagcAtom, js_ptagc_str); FROB(qualifierAtom, js_qualifier_str); FROB(spaceAtom, js_space_str); FROB(stagoAtom, js_stago_str); FROB(starAtom, js_star_str); FROB(starQualifierAtom, js_starQualifier_str); FROB(tagcAtom, js_tagc_str); FROB(xmlAtom, js_xml_str);#endif#if JS_HAS_GENERATORS FROB(closeAtom, js_close_str);#endif#ifdef NARCISSUS FROB(callAtom, js_call_str); FROB(constructAtom, js_construct_str); FROB(hasInstanceAtom, js_hasInstance_str); FROB(ExecutionContextAtom, js_ExecutionContext_str); FROB(currentAtom, js_current_str);#endif#undef FROB memset(&state->lazy, 0, sizeof state->lazy); return JS_TRUE;}/* NB: cx unused; js_FinishAtomState calls us with null cx. */voidjs_FreeAtomState(JSContext *cx, JSAtomState *state){ if (state->table) JS_HashTableDestroy(state->table);#ifdef JS_THREADSAFE js_FinishLock(&state->lock);#endif memset(state, 0, sizeof *state);}typedef struct UninternArgs { JSRuntime *rt; jsatomid leaks;} UninternArgs;JS_STATIC_DLL_CALLBACK(intN)js_atom_uninterner(JSHashEntry *he, intN i, void *arg){ JSAtom *atom; UninternArgs *args; atom = (JSAtom *)he; args = (UninternArgs *)arg; if (ATOM_IS_STRING(atom)) js_FinalizeStringRT(args->rt, ATOM_TO_STRING(atom)); else if (ATOM_IS_OBJECT(atom)) args->leaks++; return HT_ENUMERATE_NEXT;}voidjs_FinishAtomState(JSAtomState *state){ UninternArgs args; if (!state->table) return; args.rt = state->runtime; args.leaks = 0; JS_HashTableEnumerateEntries(state->table, js_atom_uninterner, &args);#ifdef DEBUG if (args.leaks != 0) { fprintf(stderr,"JS engine warning: %lu atoms remain after destroying the JSRuntime.\n"" These atoms may point to freed memory. Things reachable\n"" through them have not been finalized.\n", (unsigned long) args.leaks); }#endif js_FreeAtomState(NULL, state);}typedef struct MarkArgs { JSBool keepAtoms; JSGCThingMarker mark; void *data;} MarkArgs;JS_STATIC_DLL_CALLBACK(intN)js_atom_marker(JSHashEntry *he, intN i, void *arg){ JSAtom *atom; MarkArgs *args; jsval key; atom = (JSAtom *)he; args = (MarkArgs *)arg; if ((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) || args->keepAtoms) { atom->flags |= ATOM_MARK; key = ATOM_KEY(atom); if (JSVAL_IS_GCTHING(key)) args->mark(JSVAL_TO_GCTHING(key), args->data); } return HT_ENUMERATE_NEXT;}voidjs_MarkAtomState(JSAtomState *state, JSBool keepAtoms, JSGCThingMarker mark, void *data){ MarkArgs args; if (!state->table) return; args.keepAtoms = keepAtoms; args.mark = mark; args.data = data; JS_HashTableEnumerateEntries(state->table, js_atom_marker, &args);}JS_STATIC_DLL_CALLBACK(intN)js_atom_sweeper(JSHashEntry *he, intN i, void *arg){ JSAtom *atom; JSAtomState *state; atom = (JSAtom *)he; if (atom->flags & ATOM_MARK) { atom->flags &= ~ATOM_MARK; state = (JSAtomState *)arg; state->liveAtoms++; return HT_ENUMERATE_NEXT; } JS_ASSERT((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) == 0); atom->entry.key = atom->entry.value = NULL; atom->flags = 0; return HT_ENUMERATE_REMOVE;}voidjs_SweepAtomState(JSAtomState *state){ state->liveAtoms = 0; if (state->table) JS_HashTableEnumerateEntries(state->table, js_atom_sweeper, state);}JS_STATIC_DLL_CALLBACK(intN)js_atom_unpinner(JSHashEntry *he, intN i, void *arg){ JSAtom *atom; atom = (JSAtom *)he; atom->flags &= ~ATOM_PINNED; return HT_ENUMERATE_NEXT;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -