Advertisement
jimgreeno

Untitled

Apr 13th, 2018
420
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JSON 29.93 KB | None | 0 0
  1. // ==UserScript==
  2. // @name         New Userscript
  3. // @namespace    http://tampermonkey.net/
  4. // @version      0.1
  5. // @description  try to take over the world!
  6. // @author       james greeno
  7. // @match        http://*/*
  8. // @grant        none
  9. // ==/UserScript==
  10. // /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  11.  *
  12.  * ***** BEGIN LICENSE BLOCK *****
  13.  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  14.  *
  15.  * The contents of this file are subject to the Mozilla Public License Version
  16.  * 1.1 (the "License"); you may not use this file except in compliance with
  17.  * the License. You may obtain a copy of the License at
  18.  * http://www.mozilla.org/MPL/
  19.  *
  20.  * Software distributed under the License is distributed on an "AS IS" basis,
  21.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  22.  * for the specific language governing rights and limitations under the
  23.  * License.
  24.  *
  25.  * The Original Code is Mozilla Communicator client code, released
  26.  * March 31, 1998.
  27.  *
  28.  * The Initial Developer of the Original Code is
  29.  * Netscape Communications Corporation.
  30.  * Portions created by the Initial Developer are Copyright (C) 1998
  31.  * the Initial Developer. All Rights Reserved.
  32.  *
  33.  * Contributor(s):
  34.  *
  35.  * Alternatively, the contents of this file may be used under the terms of
  36.  * either of the GNU General Public License Version 2 or later (the "GPL"),
  37.  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  38.  * in which case the provisions of the GPL or the LGPL are applicable instead
  39.  * of those above. If you wish to allow use of your version of this file only
  40.  * under the terms of either the GPL or the LGPL, and not to allow others to
  41.  * use your version of this file under the terms of the MPL, indicate your
  42.  * decision by deleting the provisions above and replace them with the notice
  43.  * and other provisions required by the GPL or the LGPL. If you do not delete
  44.  * the provisions above, a recipient may use your version of this file under
  45.  * the terms of any one of the MPL, the GPL or the LGPL.
  46.  *
  47.  * ***** END LICENSE BLOCK ***** */
  48.  
  49. /*
  50.  * JS atom table.
  51.  */
  52. #include "jsstddef.h"
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include "jstypes.h"
  56. #include "jsutil.h" /* Added by JSIFY */
  57. #include "jshash.h" /* Added by JSIFY */
  58. #include "jsprf.h"
  59. #include "jsapi.h"
  60. #include "jsatom.h"
  61. #include "jscntxt.h"
  62. #include "jsconfig.h"
  63. #include "jsgc.h"
  64. #include "jslock.h"
  65. #include "jsnum.h"
  66. #include "jsscan.h"
  67. #include "jsstr.h"
  68.  
  69. JS_FRIEND_API(const char *)
  70. js_AtomToPrintableString(JSContext *cx, JSAtom *atom)
  71. {
  72.     return js_ValueToPrintableString(cx, ATOM_KEY(atom));
  73. }
  74.  
  75. /*
  76.  * Keep this in sync with jspubtd.h -- an assertion below will insist that
  77.  * its length match the JSType enum's JSTYPE_LIMIT limit value.
  78.  */
  79. const char *js_type_strs[] = {
  80.     "undefined",
  81.     js_object_str,
  82.     "function",
  83.     "string",
  84.     "number",
  85.     "boolean",
  86.     "null",
  87.     "xml",
  88. };
  89.  
  90. JS_STATIC_ASSERT(JSTYPE_LIMIT ==
  91.                  sizeof js_type_strs / sizeof js_type_strs[0]);
  92.  
  93. const char *js_boolean_strs[] = {
  94.     js_false_str,
  95.     js_true_str
  96. };
  97.  
  98. #define JS_PROTO(name,code,init) const char js_##name##_str[] = #name;
  99. #include "jsproto.tbl"
  100. #undef JS_PROTO
  101.  
  102. const char *js_proto_strs[JSProto_LIMIT] = {
  103. #define JS_PROTO(name,code,init) js_##name##_str,
  104. #include "jsproto.tbl"
  105. #undef JS_PROTO
  106. };
  107.  
  108. const char js_anonymous_str[]       = "anonymous";
  109. const char js_arguments_str[]       = "arguments";
  110. const char js_arity_str[]           = "arity";
  111. const char js_callee_str[]          = "callee";
  112. const char js_caller_str[]          = "caller";
  113. const char js_class_prototype_str[] = "prototype";
  114. const char js_constructor_str[]     = "constructor";
  115. const char js_count_str[]           = "__count__";
  116. const char js_each_str[]            = "each";
  117. const char js_eval_str[]            = "eval";
  118. const char js_fileName_str[]        = "fileName";
  119. const char js_get_str[]             = "get";
  120. const char js_getter_str[]          = "getter";
  121. const char js_index_str[]           = "index";
  122. const char js_input_str[]           = "input";
  123. const char js_iterator_str[]        = "__iterator__";
  124. const char js_length_str[]          = "length";
  125. const char js_lineNumber_str[]      = "lineNumber";
  126. const char js_message_str[]         = "message";
  127. const char js_name_str[]            = "name";
  128. const char js_next_str[]            = "next";
  129. const char js_noSuchMethod_str[]    = "__noSuchMethod__";
  130. const char js_object_str[]          = "object";
  131. const char js_parent_str[]          = "__parent__";
  132. const char js_proto_str[]           = "__proto__";
  133. const char js_setter_str[]          = "setter";
  134. const char js_set_str[]             = "set";
  135. const char js_stack_str[]           = "stack";
  136. const char js_toSource_str[]        = "toSource";
  137. const char js_toString_str[]        = "toString";
  138. const char js_toLocaleString_str[]  = "toLocaleString";
  139. const char js_valueOf_str[]         = "valueOf";
  140.  
  141. #if JS_HAS_XML_SUPPORT
  142. const char js_etago_str[]           = "</";
  143. const char js_namespace_str[]       = "namespace";
  144. const char js_ptagc_str[]           = "/>";
  145. const char js_qualifier_str[]       = "::";
  146. const char js_space_str[]           = " ";
  147. const char js_stago_str[]           = "<";
  148. const char js_star_str[]            = "*";
  149. const char js_starQualifier_str[]   = "*::";
  150. const char js_tagc_str[]            = ">";
  151. const char js_xml_str[]             = "xml";
  152. #endif
  153.  
  154. #if JS_HAS_GENERATORS
  155. const char js_close_str[]           = "close";
  156. const char js_send_str[]            = "send";
  157. #endif
  158.  
  159. #ifdef NARCISSUS
  160. const char js_call_str[]             = "__call__";
  161. const char js_construct_str[]        = "__construct__";
  162. const char js_hasInstance_str[]      = "__hasInstance__";
  163. const char js_ExecutionContext_str[] = "ExecutionContext";
  164. const char js_current_str[]          = "current";
  165. #endif
  166.  
  167. #define HASH_OBJECT(o)  (JS_PTR_TO_UINT32(o) >> JSVAL_TAGBITS)
  168. #define HASH_INT(i)     ((JSHashNumber)(i))
  169. #define HASH_DOUBLE(dp) ((JSDOUBLE_HI32(*dp) ^ JSDOUBLE_LO32(*dp)))
  170. #define HASH_BOOLEAN(b) ((JSHashNumber)(b))
  171.  
  172. JS_STATIC_DLL_CALLBACK(JSHashNumber)
  173. js_hash_atom_key(const void *key)
  174. {
  175.     jsval v;
  176.     jsdouble *dp;
  177.  
  178.     /* Order JSVAL_IS_* tests by likelihood of success. */
  179.     v = (jsval)key;
  180.     if (JSVAL_IS_STRING(v))
  181.         return js_HashString(JSVAL_TO_STRING(v));
  182.     if (JSVAL_IS_INT(v))
  183.         return HASH_INT(JSVAL_TO_INT(v));
  184.     if (JSVAL_IS_DOUBLE(v)) {
  185.         dp = JSVAL_TO_DOUBLE(v);
  186.         return HASH_DOUBLE(dp);
  187.     }
  188.     if (JSVAL_IS_OBJECT(v))
  189.         return HASH_OBJECT(JSVAL_TO_OBJECT(v));
  190.     if (JSVAL_IS_BOOLEAN(v))
  191.         return HASH_BOOLEAN(JSVAL_TO_BOOLEAN(v));
  192.     return (JSHashNumber)v;
  193. }
  194.  
  195. JS_STATIC_DLL_CALLBACK(intN)
  196. js_compare_atom_keys(const void *k1, const void *k2)
  197. {
  198.     jsval v1, v2;
  199.  
  200.     v1 = (jsval)k1, v2 = (jsval)k2;
  201.     if (JSVAL_IS_STRING(v1) && JSVAL_IS_STRING(v2))
  202.         return js_EqualStrings(JSVAL_TO_STRING(v1), JSVAL_TO_STRING(v2));
  203.     if (JSVAL_IS_DOUBLE(v1) && JSVAL_IS_DOUBLE(v2)) {
  204.         double d1 = *JSVAL_TO_DOUBLE(v1);
  205.         double d2 = *JSVAL_TO_DOUBLE(v2);
  206.         if (JSDOUBLE_IS_NaN(d1))
  207.             return JSDOUBLE_IS_NaN(d2);
  208. #if defined(XP_WIN)
  209.         /* XXX MSVC miscompiles such that (NaN == 0) */
  210.         if (JSDOUBLE_IS_NaN(d2))
  211.             return JS_FALSE;
  212. #endif
  213.         return d1 == d2;
  214.     }
  215.     return v1 == v2;
  216. }
  217.  
  218. JS_STATIC_DLL_CALLBACK(int)
  219. js_compare_stub(const void *v1, const void *v2)
  220. {
  221.     return 1;
  222. }
  223.  
  224. /* These next two are exported to jsscript.c and used similarly there. */
  225. void * JS_DLL_CALLBACK
  226. js_alloc_table_space(void *priv, size_t size)
  227. {
  228.     return malloc(size);
  229. }
  230.  
  231. void JS_DLL_CALLBACK
  232. js_free_table_space(void *priv, void *item)
  233. {
  234.     free(item);
  235. }
  236.  
  237. JS_STATIC_DLL_CALLBACK(JSHashEntry *)
  238. js_alloc_atom(void *priv, const void *key)
  239. {
  240.     JSAtomState *state = (JSAtomState *) priv;
  241.     JSAtom *atom;
  242.  
  243.     atom = (JSAtom *) malloc(sizeof(JSAtom));
  244.     if (!atom)
  245.         return NULL;
  246. #ifdef JS_THREADSAFE
  247.     state->tablegen++;
  248. #endif
  249.     atom->entry.key = key;
  250.     atom->entry.value = NULL;
  251.     atom->flags = 0;
  252.     atom->number = state->number++;
  253.     return &atom->entry;
  254. }
  255.  
  256. JS_STATIC_DLL_CALLBACK(void)
  257. js_free_atom(void *priv, JSHashEntry *he, uintN flag)
  258. {
  259.     if (flag != HT_FREE_ENTRY)
  260.         return;
  261. #ifdef JS_THREADSAFE
  262.     ((JSAtomState *)priv)->tablegen++;
  263. #endif
  264.     free(he);
  265. }
  266.  
  267. static JSHashAllocOps atom_alloc_ops = {
  268.     js_alloc_table_space,   js_free_table_space,
  269.     js_alloc_atom,          js_free_atom
  270. };
  271.  
  272. #define JS_ATOM_HASH_SIZE   1024
  273.  
  274. JSBool
  275. js_InitAtomState(JSContext *cx, JSAtomState *state)
  276. {
  277.     state->table = JS_NewHashTable(JS_ATOM_HASH_SIZE, js_hash_atom_key,
  278.                                    js_compare_atom_keys, js_compare_stub,
  279.                                    &atom_alloc_ops, state);
  280.     if (!state->table) {
  281.         JS_ReportOutOfMemory(cx);
  282.         return JS_FALSE;
  283.     }
  284.  
  285.     state->runtime = cx->runtime;
  286. #ifdef JS_THREADSAFE
  287.     js_InitLock(&state->lock);
  288.     state->tablegen = 0;
  289. #endif
  290.  
  291.     if (!js_InitPinnedAtoms(cx, state)) {
  292.         js_FreeAtomState(cx, state);
  293.         return JS_FALSE;
  294.     }
  295.     return JS_TRUE;
  296. }
  297.  
  298. JSBool
  299. js_InitPinnedAtoms(JSContext *cx, JSAtomState *state)
  300. {
  301.     uintN i;
  302.  
  303. #define FROB(lval,str)                                                        \
  304.     JS_BEGIN_MACRO                                                            \
  305.         if (!(state->lval = js_Atomize(cx, str, strlen(str), ATOM_PINNED)))   \
  306.             return JS_FALSE;                                                  \
  307.     JS_END_MACRO
  308.  
  309.     for (i = 0; i < JSTYPE_LIMIT; i++)
  310.         FROB(typeAtoms[i],        js_type_strs[i]);
  311.  
  312.     for (i = 0; i < JSProto_LIMIT; i++)
  313.         FROB(classAtoms[i],       js_proto_strs[i]);
  314.  
  315.     FROB(booleanAtoms[0],         js_false_str);
  316.     FROB(booleanAtoms[1],         js_true_str);
  317.     FROB(nullAtom,                js_null_str);
  318.  
  319.     FROB(anonymousAtom,           js_anonymous_str);
  320.     FROB(argumentsAtom,           js_arguments_str);
  321.     FROB(arityAtom,               js_arity_str);
  322.     FROB(calleeAtom,              js_callee_str);
  323.     FROB(callerAtom,              js_caller_str);
  324.     FROB(classPrototypeAtom,      js_class_prototype_str);
  325.     FROB(constructorAtom,         js_constructor_str);
  326.     FROB(countAtom,               js_count_str);
  327.     FROB(eachAtom,                js_each_str);
  328.     FROB(evalAtom,                js_eval_str);
  329.     FROB(fileNameAtom,            js_fileName_str);
  330.     FROB(getAtom,                 js_get_str);
  331.     FROB(getterAtom,              js_getter_str);
  332.     FROB(indexAtom,               js_index_str);
  333.     FROB(inputAtom,               js_input_str);
  334.     FROB(iteratorAtom,            js_iterator_str);
  335.     FROB(lengthAtom,              js_length_str);
  336.     FROB(lineNumberAtom,          js_lineNumber_str);
  337.     FROB(messageAtom,             js_message_str);
  338.     FROB(nameAtom,                js_name_str);
  339.     FROB(nextAtom,                js_next_str);
  340.     FROB(noSuchMethodAtom,        js_noSuchMethod_str);
  341.     FROB(parentAtom,              js_parent_str);
  342.     FROB(protoAtom,               js_proto_str);
  343.     FROB(setAtom,                 js_set_str);
  344.     FROB(setterAtom,              js_setter_str);
  345.     FROB(stackAtom,               js_stack_str);
  346.     FROB(toSourceAtom,            js_toSource_str);
  347.     FROB(toStringAtom,            js_toString_str);
  348.     FROB(toLocaleStringAtom,      js_toLocaleString_str);
  349.     FROB(valueOfAtom,             js_valueOf_str);
  350.  
  351. #if JS_HAS_XML_SUPPORT
  352.     FROB(etagoAtom,               js_etago_str);
  353.     FROB(namespaceAtom,           js_namespace_str);
  354.     FROB(ptagcAtom,               js_ptagc_str);
  355.     FROB(qualifierAtom,           js_qualifier_str);
  356.     FROB(spaceAtom,               js_space_str);
  357.     FROB(stagoAtom,               js_stago_str);
  358.     FROB(starAtom,                js_star_str);
  359.     FROB(starQualifierAtom,       js_starQualifier_str);
  360.     FROB(tagcAtom,                js_tagc_str);
  361.     FROB(xmlAtom,                 js_xml_str);
  362. #endif
  363.  
  364. #if JS_HAS_GENERATORS
  365.     FROB(closeAtom,               js_close_str);
  366. #endif
  367.  
  368. #ifdef NARCISSUS
  369.     FROB(callAtom,                js_call_str);
  370.     FROB(constructAtom,           js_construct_str);
  371.     FROB(hasInstanceAtom,         js_hasInstance_str);
  372.     FROB(ExecutionContextAtom,    js_ExecutionContext_str);
  373.     FROB(currentAtom,             js_current_str);
  374. #endif
  375.  
  376. #undef FROB
  377.  
  378.     memset(&state->lazy, 0, sizeof state->lazy);
  379.     return JS_TRUE;
  380. }
  381.  
  382. /* NB: cx unused; js_FinishAtomState calls us with null cx. */
  383. void
  384. js_FreeAtomState(JSContext *cx, JSAtomState *state)
  385. {
  386.     if (state->table)
  387.         JS_HashTableDestroy(state->table);
  388. #ifdef JS_THREADSAFE
  389.     js_FinishLock(&state->lock);
  390. #endif
  391.     memset(state, 0, sizeof *state);
  392. }
  393.  
  394. typedef struct UninternArgs {
  395.     JSRuntime   *rt;
  396.     jsatomid    leaks;
  397. } UninternArgs;
  398.  
  399. JS_STATIC_DLL_CALLBACK(intN)
  400. js_atom_uninterner(JSHashEntry *he, intN i, void *arg)
  401. {
  402.     JSAtom *atom;
  403.     UninternArgs *args;
  404.  
  405.     atom = (JSAtom *)he;
  406.     args = (UninternArgs *)arg;
  407.     if (ATOM_IS_STRING(atom))
  408.         js_FinalizeStringRT(args->rt, ATOM_TO_STRING(atom));
  409.     else if (ATOM_IS_OBJECT(atom))
  410.         args->leaks++;
  411.     return HT_ENUMERATE_NEXT;
  412. }
  413.  
  414. void
  415. js_FinishAtomState(JSAtomState *state)
  416. {
  417.     UninternArgs args;
  418.  
  419.     if (!state->table)
  420.         return;
  421.     args.rt = state->runtime;
  422.     args.leaks = 0;
  423.     JS_HashTableEnumerateEntries(state->table, js_atom_uninterner, &args);
  424. #ifdef DEBUG
  425.     if (args.leaks != 0) {
  426.         fprintf(stderr,
  427. "JS engine warning: %lu atoms remain after destroying the JSRuntime.\n"
  428. "                   These atoms may point to freed memory. Things reachable\n"
  429. "                   through them have not been finalized.\n",
  430.                 (unsigned long) args.leaks);
  431.     }
  432. #endif
  433.     js_FreeAtomState(NULL, state);
  434. }
  435.  
  436. typedef struct MarkArgs {
  437.     JSBool          keepAtoms;
  438.     JSGCThingMarker mark;
  439.     void            *data;
  440. } MarkArgs;
  441.  
  442. JS_STATIC_DLL_CALLBACK(intN)
  443. js_atom_marker(JSHashEntry *he, intN i, void *arg)
  444. {
  445.     JSAtom *atom;
  446.     MarkArgs *args;
  447.     jsval key;
  448.  
  449.     atom = (JSAtom *)he;
  450.     args = (MarkArgs *)arg;
  451.     if ((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) || args->keepAtoms) {
  452.         atom->flags |= ATOM_MARK;
  453.         key = ATOM_KEY(atom);
  454.         if (JSVAL_IS_GCTHING(key))
  455.             args->mark(JSVAL_TO_GCTHING(key), args->data);
  456.     }
  457.     return HT_ENUMERATE_NEXT;
  458. }
  459.  
  460. void
  461. js_MarkAtomState(JSAtomState *state, JSBool keepAtoms, JSGCThingMarker mark,
  462.                  void *data)
  463. {
  464.     MarkArgs args;
  465.  
  466.     if (!state->table)
  467.         return;
  468.     args.keepAtoms = keepAtoms;
  469.     args.mark = mark;
  470.     args.data = data;
  471.     JS_HashTableEnumerateEntries(state->table, js_atom_marker, &args);
  472. }
  473.  
  474. JS_STATIC_DLL_CALLBACK(intN)
  475. js_atom_sweeper(JSHashEntry *he, intN i, void *arg)
  476. {
  477.     JSAtom *atom;
  478.     JSAtomState *state;
  479.  
  480.     atom = (JSAtom *)he;
  481.     if (atom->flags & ATOM_MARK) {
  482.         atom->flags &= ~ATOM_MARK;
  483.         state = (JSAtomState *)arg;
  484.         state->liveAtoms++;
  485.         return HT_ENUMERATE_NEXT;
  486.     }
  487.     JS_ASSERT((atom->flags & (ATOM_PINNED | ATOM_INTERNED)) == 0);
  488.     atom->entry.key = atom->entry.value = NULL;
  489.     atom->flags = 0;
  490.     return HT_ENUMERATE_REMOVE;
  491. }
  492.  
  493. void
  494. js_SweepAtomState(JSAtomState *state)
  495. {
  496.     state->liveAtoms = 0;
  497.     if (state->table)
  498.         JS_HashTableEnumerateEntries(state->table, js_atom_sweeper, state);
  499. }
  500.  
  501. JS_STATIC_DLL_CALLBACK(intN)
  502. js_atom_unpinner(JSHashEntry *he, intN i, void *arg)
  503. {
  504.     JSAtom *atom;
  505.  
  506.     atom = (JSAtom *)he;
  507.     atom->flags &= ~ATOM_PINNED;
  508.     return HT_ENUMERATE_NEXT;
  509. }
  510.  
  511. void
  512. js_UnpinPinnedAtoms(JSAtomState *state)
  513. {
  514.     if (state->table)
  515.         JS_HashTableEnumerateEntries(state->table, js_atom_unpinner, NULL);
  516. }
  517.  
  518. static JSAtom *
  519. js_AtomizeHashedKey(JSContext *cx, jsval key, JSHashNumber keyHash, uintN flags)
  520. {
  521.     JSAtomState *state;
  522.     JSHashTable *table;
  523.     JSHashEntry *he, **hep;
  524.     JSAtom *atom;
  525.  
  526.     state = &cx->runtime->atomState;
  527.     JS_LOCK(&state->lock, cx);
  528.     table = state->table;
  529.     hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
  530.     if ((he = *hep) == NULL) {
  531.         he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
  532.         if (!he) {
  533.             JS_ReportOutOfMemory(cx);
  534.             atom = NULL;
  535.             goto out;
  536.         }
  537.     }
  538.  
  539.     atom = (JSAtom *)he;
  540.     atom->flags |= flags;
  541.     cx->weakRoots.lastAtom = atom;
  542. out:
  543.     JS_UNLOCK(&state->lock,cx);
  544.     return atom;
  545. }
  546.  
  547. JSAtom *
  548. js_AtomizeObject(JSContext *cx, JSObject *obj, uintN flags)
  549. {
  550.     jsval key;
  551.     JSHashNumber keyHash;
  552.  
  553.     /* XXX must be set in the following order or MSVC1.52 will crash */
  554.     keyHash = HASH_OBJECT(obj);
  555.     key = OBJECT_TO_JSVAL(obj);
  556.     return js_AtomizeHashedKey(cx, key, keyHash, flags);
  557. }
  558.  
  559. JSAtom *
  560. js_AtomizeBoolean(JSContext *cx, JSBool b, uintN flags)
  561. {
  562.     jsval key;
  563.     JSHashNumber keyHash;
  564.  
  565.     key = BOOLEAN_TO_JSVAL(b);
  566.     keyHash = HASH_BOOLEAN(b);
  567.     return js_AtomizeHashedKey(cx, key, keyHash, flags);
  568. }
  569.  
  570. JSAtom *
  571. js_AtomizeInt(JSContext *cx, jsint i, uintN flags)
  572. {
  573.     jsval key;
  574.     JSHashNumber keyHash;
  575.  
  576.     key = INT_TO_JSVAL(i);
  577.     keyHash = HASH_INT(i);
  578.     return js_AtomizeHashedKey(cx, key, keyHash, flags);
  579. }
  580.  
  581. /* Worst-case alignment grain and aligning macro for 2x-sized buffer. */
  582. #define ALIGNMENT(t)    JS_MAX(JSVAL_ALIGN, sizeof(t))
  583. #define ALIGN(b,t)      ((t*) &(b)[ALIGNMENT(t) - (jsuword)(b) % ALIGNMENT(t)])
  584.  
  585. JSAtom *
  586. js_AtomizeDouble(JSContext *cx, jsdouble d, uintN flags)
  587. {
  588.     jsdouble *dp;
  589.     JSHashNumber keyHash;
  590.     jsval key;
  591.     JSAtomState *state;
  592.     JSHashTable *table;
  593.     JSHashEntry *he, **hep;
  594.     JSAtom *atom;
  595.     char buf[2 * ALIGNMENT(double)];
  596.  
  597.     dp = ALIGN(buf, double);
  598.     *dp = d;
  599.     keyHash = HASH_DOUBLE(dp);
  600.     key = DOUBLE_TO_JSVAL(dp);
  601.     state = &cx->runtime->atomState;
  602.     JS_LOCK(&state->lock, cx);
  603.     table = state->table;
  604.     hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
  605.     if ((he = *hep) == NULL) {
  606. #ifdef JS_THREADSAFE
  607.         uint32 gen = state->tablegen;
  608. #endif
  609.         JS_UNLOCK(&state->lock,cx);
  610.         if (!js_NewDoubleValue(cx, d, &key))
  611.             return NULL;
  612.         JS_LOCK(&state->lock, cx);
  613. #ifdef JS_THREADSAFE
  614.         if (state->tablegen != gen) {
  615.             hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
  616.             if ((he = *hep) != NULL) {
  617.                 atom = (JSAtom *)he;
  618.                 goto out;
  619.             }
  620.         }
  621. #endif
  622.         he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
  623.         if (!he) {
  624.             JS_ReportOutOfMemory(cx);
  625.             atom = NULL;
  626.             goto out;
  627.         }
  628.     }
  629.  
  630.     atom = (JSAtom *)he;
  631.     atom->flags |= flags;
  632.     cx->weakRoots.lastAtom = atom;
  633. out:
  634.     JS_UNLOCK(&state->lock,cx);
  635.     return atom;
  636. }
  637.  
  638. /*
  639.  * To put an atom into the hidden subspace. XOR its keyHash with this value,
  640.  * which is (sqrt(2)-1) in 32-bit fixed point.
  641.  */
  642. #define HIDDEN_ATOM_SUBSPACE_KEYHASH    0x6A09E667
  643.  
  644. JSAtom *
  645. js_AtomizeString(JSContext *cx, JSString *str, uintN flags)
  646. {
  647.     JSHashNumber keyHash;
  648.     jsval key;
  649.     JSAtomState *state;
  650.     JSHashTable *table;
  651.     JSHashEntry *he, **hep;
  652.     JSAtom *atom;
  653.  
  654.     keyHash = js_HashString(str);
  655.     if (flags & ATOM_HIDDEN)
  656.         keyHash ^= HIDDEN_ATOM_SUBSPACE_KEYHASH;
  657.     key = STRING_TO_JSVAL(str);
  658.     state = &cx->runtime->atomState;
  659.     JS_LOCK(&state->lock, cx);
  660.     table = state->table;
  661.     hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
  662.     if ((he = *hep) == NULL) {
  663. #ifdef JS_THREADSAFE
  664.         uint32 gen = state->tablegen;
  665.         JS_UNLOCK(&state->lock, cx);
  666. #endif
  667.  
  668.         if (flags & ATOM_TMPSTR) {
  669.             str = (flags & ATOM_NOCOPY)
  670.                   ? js_NewString(cx, str->chars, str->length, 0)
  671.                   : js_NewStringCopyN(cx, str->chars, str->length, 0);
  672.             if (!str)
  673.                 return NULL;
  674.             key = STRING_TO_JSVAL(str);
  675.         } else {
  676.             if (!JS_MakeStringImmutable(cx, str))
  677.                 return NULL;
  678.         }
  679.  
  680. #ifdef JS_THREADSAFE
  681.         JS_LOCK(&state->lock, cx);
  682.         if (state->tablegen != gen) {
  683.             hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
  684.             if ((he = *hep) != NULL) {
  685.                 atom = (JSAtom *)he;
  686.                 if (flags & ATOM_NOCOPY)
  687.                     str->chars = NULL;
  688.                 goto out;
  689.             }
  690.         }
  691. #endif
  692.  
  693.         he = JS_HashTableRawAdd(table, hep, keyHash, (void *)key, NULL);
  694.         if (!he) {
  695.             JS_ReportOutOfMemory(cx);
  696.             atom = NULL;
  697.             goto out;
  698.         }
  699.     }
  700.  
  701.     atom = (JSAtom *)he;
  702.     atom->flags |= flags & (ATOM_PINNED | ATOM_INTERNED | ATOM_HIDDEN);
  703.     cx->weakRoots.lastAtom = atom;
  704. out:
  705.     JS_UNLOCK(&state->lock,cx);
  706.     return atom;
  707. }
  708.  
  709. JS_FRIEND_API(JSAtom *)
  710. js_Atomize(JSContext *cx, const char *bytes, size_t length, uintN flags)
  711. {
  712.     jschar *chars;
  713.     JSString *str;
  714.     JSAtom *atom;
  715.     char buf[2 * ALIGNMENT(JSString)];
  716.  
  717.     /*
  718.      * Avoiding the malloc in js_InflateString on shorter strings saves us
  719.      * over 20,000 malloc calls on mozilla browser startup. This compares to
  720.      * only 131 calls where the string is longer than a 31 char (net) buffer.
  721.      * The vast majority of atomized strings are already in the hashtable. So
  722.      * js_AtomizeString rarely has to copy the temp string we make.
  723.      */
  724. #define ATOMIZE_BUF_MAX 32
  725.     jschar inflated[ATOMIZE_BUF_MAX];
  726.     size_t inflatedLength = ATOMIZE_BUF_MAX - 1;
  727.  
  728.     if (length < ATOMIZE_BUF_MAX) {
  729.         js_InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
  730.         inflated[inflatedLength] = 0;
  731.         chars = inflated;
  732.     } else {
  733.         inflatedLength = length;
  734.         chars = js_InflateString(cx, bytes, &inflatedLength);
  735.         if (!chars)
  736.             return NULL;
  737.         flags |= ATOM_NOCOPY;
  738.     }
  739.  
  740.     str = ALIGN(buf, JSString);
  741.  
  742.     str->chars = chars;
  743.     str->length = inflatedLength;
  744.     atom = js_AtomizeString(cx, str, ATOM_TMPSTR | flags);
  745.     if (chars != inflated && (!atom || ATOM_TO_STRING(atom)->chars != chars))
  746.         JS_free(cx, chars);
  747.     return atom;
  748. }
  749.  
  750. JS_FRIEND_API(JSAtom *)
  751. js_AtomizeChars(JSContext *cx, const jschar *chars, size_t length, uintN flags)
  752. {
  753.     JSString *str;
  754.     char buf[2 * ALIGNMENT(JSString)];
  755.  
  756.     str = ALIGN(buf, JSString);
  757.     str->chars = (jschar *)chars;
  758.     str->length = length;
  759.     return js_AtomizeString(cx, str, ATOM_TMPSTR | flags);
  760. }
  761.  
  762. JSAtom *
  763. js_GetExistingStringAtom(JSContext *cx, const jschar *chars, size_t length)
  764. {
  765.     JSString *str;
  766.     char buf[2 * ALIGNMENT(JSString)];
  767.     JSHashNumber keyHash;
  768.     jsval key;
  769.     JSAtomState *state;
  770.     JSHashTable *table;
  771.     JSHashEntry **hep;
  772.  
  773.     str = ALIGN(buf, JSString);
  774.     str->chars = (jschar *)chars;
  775.     str->length = length;
  776.     keyHash = js_HashString(str);
  777.     key = STRING_TO_JSVAL(str);
  778.     state = &cx->runtime->atomState;
  779.     JS_LOCK(&state->lock, cx);
  780.     table = state->table;
  781.     hep = JS_HashTableRawLookup(table, keyHash, (void *)key);
  782.     JS_UNLOCK(&state->lock, cx);
  783.     return (hep) ? (JSAtom *)*hep : NULL;
  784. }
  785.  
  786. JSAtom *
  787. js_AtomizeValue(JSContext *cx, jsval value, uintN flags)
  788. {
  789.     if (JSVAL_IS_STRING(value))
  790.         return js_AtomizeString(cx, JSVAL_TO_STRING(value), flags);
  791.     if (JSVAL_IS_INT(value))
  792.         return js_AtomizeInt(cx, JSVAL_TO_INT(value), flags);
  793.     if (JSVAL_IS_DOUBLE(value))
  794.         return js_AtomizeDouble(cx, *JSVAL_TO_DOUBLE(value), flags);
  795.     if (JSVAL_IS_OBJECT(value))
  796.         return js_AtomizeObject(cx, JSVAL_TO_OBJECT(value), flags);
  797.     if (JSVAL_IS_BOOLEAN(value))
  798.         return js_AtomizeBoolean(cx, JSVAL_TO_BOOLEAN(value), flags);
  799.     return js_AtomizeHashedKey(cx, value, (JSHashNumber)value, flags);
  800. }
  801.  
  802. JSAtom *
  803. js_ValueToStringAtom(JSContext *cx, jsval v)
  804. {
  805.     JSString *str;
  806.  
  807.     str = js_ValueToString(cx, v);
  808.     if (!str)
  809.         return NULL;
  810.     return js_AtomizeString(cx, str, 0);
  811. }
  812.  
  813. JS_STATIC_DLL_CALLBACK(JSHashNumber)
  814. js_hash_atom_ptr(const void *key)
  815. {
  816.     const JSAtom *atom = key;
  817.     return atom->number;
  818. }
  819.  
  820. JS_STATIC_DLL_CALLBACK(void *)
  821. js_alloc_temp_space(void *priv, size_t size)
  822. {
  823.     JSContext *cx = priv;
  824.     void *space;
  825.  
  826.     JS_ARENA_ALLOCATE(space, &cx->tempPool, size);
  827.     if (!space)
  828.         JS_ReportOutOfMemory(cx);
  829.     return space;
  830. }
  831.  
  832. JS_STATIC_DLL_CALLBACK(void)
  833. js_free_temp_space(void *priv, void *item)
  834. {
  835. }
  836.  
  837. JS_STATIC_DLL_CALLBACK(JSHashEntry *)
  838. js_alloc_temp_entry(void *priv, const void *key)
  839. {
  840.     JSContext *cx = priv;
  841.     JSAtomListElement *ale;
  842.  
  843.     JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &cx->tempPool);
  844.     if (!ale) {
  845.         JS_ReportOutOfMemory(cx);
  846.         return NULL;
  847.     }
  848.     return &ale->entry;
  849. }
  850.  
  851. JS_STATIC_DLL_CALLBACK(void)
  852. js_free_temp_entry(void *priv, JSHashEntry *he, uintN flag)
  853. {
  854. }
  855.  
  856. static JSHashAllocOps temp_alloc_ops = {
  857.     js_alloc_temp_space,    js_free_temp_space,
  858.     js_alloc_temp_entry,    js_free_temp_entry
  859. };
  860.  
  861. JSAtomListElement *
  862. js_IndexAtom(JSContext *cx, JSAtom *atom, JSAtomList *al)
  863. {
  864.     JSAtomListElement *ale, *ale2, *next;
  865.     JSHashEntry **hep;
  866.  
  867.     ATOM_LIST_LOOKUP(ale, hep, al, atom);
  868.     if (!ale) {
  869.         if (al->count < 10) {
  870.             /* Few enough for linear search, no hash table needed. */
  871.             JS_ASSERT(!al->table);
  872.             ale = (JSAtomListElement *)js_alloc_temp_entry(cx, atom);
  873.             if (!ale)
  874.                 return NULL;
  875.             ALE_SET_ATOM(ale, atom);
  876.             ALE_SET_NEXT(ale, al->list);
  877.             al->list = ale;
  878.         } else {
  879.             /* We want to hash.  Have we already made a hash table? */
  880.             if (!al->table) {
  881.                 /* No hash table yet, so hep had better be null! */
  882.                 JS_ASSERT(!hep);
  883.                 al->table = JS_NewHashTable(al->count + 1, js_hash_atom_ptr,
  884.                                             JS_CompareValues, JS_CompareValues,
  885.                                             &temp_alloc_ops, cx);
  886.                 if (!al->table)
  887.                     return NULL;
  888.  
  889.                 /*
  890.                  * Set ht->nentries explicitly, because we are moving entries
  891.                  * from al to ht, not calling JS_HashTable(Raw|)Add.
  892.                  */
  893.                 al->table->nentries = al->count;
  894.  
  895.                 /* Insert each ale on al->list into the new hash table. */
  896.                 for (ale2 = al->list; ale2; ale2 = next) {
  897.                     next = ALE_NEXT(ale2);
  898.                     ale2->entry.keyHash = ALE_ATOM(ale2)->number;
  899.                     hep = JS_HashTableRawLookup(al->table, ale2->entry.keyHash,
  900.                                                 ale2->entry.key);
  901.                     ALE_SET_NEXT(ale2, *hep);
  902.                     *hep = &ale2->entry;
  903.                 }
  904.                 al->list = NULL;
  905.  
  906.                 /* Set hep for insertion of atom's ale, immediately below. */
  907.                 hep = JS_HashTableRawLookup(al->table, atom->number, atom);
  908.             }
  909.  
  910.             /* Finally, add an entry for atom into the hash bucket at hep. */
  911.             ale = (JSAtomListElement *)
  912.                   JS_HashTableRawAdd(al->table, hep, atom->number, atom, NULL);
  913.             if (!ale)
  914.                 return NULL;
  915.         }
  916.  
  917.         ALE_SET_INDEX(ale, al->count++);
  918.     }
  919.     return ale;
  920. }
  921.  
  922. JS_FRIEND_API(JSAtom *)
  923. js_GetAtom(JSContext *cx, JSAtomMap *map, jsatomid i)
  924. {
  925.     JSAtom *atom;
  926.     static JSAtom dummy;
  927.  
  928.     JS_ASSERT(map->vector && i < map->length);
  929.     if (!map->vector || i >= map->length) {
  930.         char numBuf[12];
  931.         JS_snprintf(numBuf, sizeof numBuf, "%lu", (unsigned long)i);
  932.         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
  933.                              JSMSG_BAD_ATOMIC_NUMBER, numBuf);
  934.         return &dummy;
  935.     }
  936.     atom = map->vector[i];
  937.     JS_ASSERT(atom);
  938.     return atom;
  939. }
  940.  
  941. JS_STATIC_DLL_CALLBACK(intN)
  942. js_map_atom(JSHashEntry *he, intN i, void *arg)
  943. {
  944.     JSAtomListElement *ale = (JSAtomListElement *)he;
  945.     JSAtom **vector = arg;
  946.  
  947.     vector[ALE_INDEX(ale)] = ALE_ATOM(ale);
  948.     return HT_ENUMERATE_NEXT;
  949. }
  950.  
  951. #ifdef DEBUG
  952. static jsrefcount js_atom_map_count;
  953. static jsrefcount js_atom_map_hash_table_count;
  954. #endif
  955.  
  956. JS_FRIEND_API(JSBool)
  957. js_InitAtomMap(JSContext *cx, JSAtomMap *map, JSAtomList *al)
  958. {
  959.     JSAtom **vector;
  960.     JSAtomListElement *ale;
  961.     uint32 count;
  962.  
  963. #ifdef DEBUG
  964.     JS_ATOMIC_INCREMENT(&js_atom_map_count);
  965. #endif
  966.     map->vector = NULL;
  967.     map->length = 0;
  968.     ale = al->list;
  969.     if (!ale && !al->table)
  970.         return JS_TRUE;
  971.  
  972.     count = al->count;
  973.     if (count >= ATOM_INDEX_LIMIT) {
  974.         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
  975.                              JSMSG_TOO_MANY_LITERALS);
  976.         return JS_FALSE;
  977.     }
  978.     vector = (JSAtom **) JS_malloc(cx, (size_t) count * sizeof *vector);
  979.     if (!vector)
  980.         return JS_FALSE;
  981.     memset(vector, 0, (size_t) count * sizeof(*vector) );
  982.  
  983.     if (al->table) {
  984. #ifdef DEBUG
  985.         JS_ATOMIC_INCREMENT(&js_atom_map_hash_table_count);
  986. #endif
  987.         JS_HashTableEnumerateEntries(al->table, js_map_atom, vector);
  988.     } else {
  989.         do {
  990.             const size_t index = ALE_INDEX(ale);
  991.             if(index < count && (vector[index] == NULL) )
  992.                 vector[index] = ALE_ATOM(ale);
  993.             else
  994.             {
  995.                 JS_free(cx,vector);
  996.                 vector = NULL;
  997.                 JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
  998.                     JSMSG_BAD_ATOMIC_NUMBER, index);
  999.                 return JS_FALSE;
  1000.             }
  1001.         } while ((ale = ALE_NEXT(ale)) != NULL);
  1002.     }
  1003.     ATOM_LIST_INIT(al);
  1004.  
  1005.     map->vector = vector;
  1006.     map->length = (jsatomid)count;
  1007.     return JS_TRUE;
  1008. }
  1009.  
  1010. JS_FRIEND_API(void)
  1011. js_FreeAtomMap(JSContext *cx, JSAtomMap *map)
  1012. {
  1013.     if (map->vector) {
  1014.         JS_free(cx, map->vector);
  1015.         map->vector = NULL;
  1016.     }
  1017.     map->length = 0;
  1018. }
  1019.  
  1020. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement