/js/src/frontend/ParseMaps.cpp

http://github.com/zpao/v8monkey · C++ · 196 lines · 131 code · 20 blank · 45 comment · 28 complexity · 18fb2bbaa3d87f3cb82fa9951e656487 MD5 · raw file

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  2. * vim: set ts=4 sw=4 et tw=99 ft=cpp:
  3. *
  4. * ***** BEGIN LICENSE BLOCK *****
  5. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  6. *
  7. * The contents of this file are subject to the Mozilla Public License Version
  8. * 1.1 (the "License"); you may not use this file except in compliance with
  9. * the License. You may obtain a copy of the License at
  10. * http://www.mozilla.org/MPL/
  11. *
  12. * Software distributed under the License is distributed on an "AS IS" basis,
  13. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  14. * for the specific language governing rights and limitations under the
  15. * License.
  16. *
  17. * The Original Code is SpiderMonkey JavaScript engine.
  18. *
  19. * The Initial Developer of the Original Code is
  20. * Mozilla Corporation.
  21. * Portions created by the Initial Developer are Copyright (C) 2011
  22. * the Initial Developer. All Rights Reserved.
  23. *
  24. * Contributor(s):
  25. * Chris Leary <cdleary@mozilla.com>
  26. *
  27. * Alternatively, the contents of this file may be used under the terms of
  28. * either the GNU General Public License Version 2 or later (the "GPL"), or
  29. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  30. * in which case the provisions of the GPL or the LGPL are applicable instead
  31. * of those above. If you wish to allow use of your version of this file only
  32. * under the terms of either the GPL or the LGPL, and not to allow others to
  33. * use your version of this file under the terms of the MPL, indicate your
  34. * decision by deleting the provisions above and replace them with the notice
  35. * and other provisions required by the GPL or the LGPL. If you do not delete
  36. * the provisions above, a recipient may use your version of this file under
  37. * the terms of any one of the MPL, the GPL or the LGPL.
  38. *
  39. * ***** END LICENSE BLOCK ***** */
  40. #include "ParseMaps-inl.h"
  41. #include "jscompartment.h"
  42. using namespace js;
  43. void
  44. ParseMapPool::checkInvariants()
  45. {
  46. /*
  47. * Having all values be of the same size permits us to easily reuse the
  48. * allocated space for each of the map types.
  49. */
  50. JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(jsatomid));
  51. JS_STATIC_ASSERT(sizeof(Definition *) == sizeof(DefnOrHeader));
  52. JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomIndexMap::Entry));
  53. JS_STATIC_ASSERT(sizeof(AtomDefnMap::Entry) == sizeof(AtomDOHMap::Entry));
  54. JS_STATIC_ASSERT(sizeof(AtomMapT::Entry) == sizeof(AtomDOHMap::Entry));
  55. /* Ensure that the HasTable::clear goes quickly via memset. */
  56. JS_STATIC_ASSERT(tl::IsPodType<AtomIndexMap::WordMap::Entry>::result);
  57. JS_STATIC_ASSERT(tl::IsPodType<AtomDOHMap::WordMap::Entry>::result);
  58. JS_STATIC_ASSERT(tl::IsPodType<AtomDefnMap::WordMap::Entry>::result);
  59. }
  60. void
  61. ParseMapPool::purgeAll()
  62. {
  63. for (void **it = all.begin(), **end = all.end(); it != end; ++it)
  64. cx->delete_<AtomMapT>(asAtomMap(*it));
  65. all.clearAndFree();
  66. recyclable.clearAndFree();
  67. }
  68. void *
  69. ParseMapPool::allocateFresh()
  70. {
  71. size_t newAllLength = all.length() + 1;
  72. if (!all.reserve(newAllLength) || !recyclable.reserve(newAllLength))
  73. return NULL;
  74. AtomMapT *map = cx->new_<AtomMapT>(cx);
  75. if (!map)
  76. return NULL;
  77. all.infallibleAppend(map);
  78. return (void *) map;
  79. }
  80. #ifdef DEBUG
  81. void
  82. AtomDecls::dump()
  83. {
  84. for (AtomDOHRange r = map->all(); !r.empty(); r.popFront()) {
  85. fprintf(stderr, "atom: ");
  86. js_DumpAtom(r.front().key());
  87. const DefnOrHeader &doh = r.front().value();
  88. if (doh.isHeader()) {
  89. AtomDeclNode *node = doh.header();
  90. do {
  91. fprintf(stderr, " node: %p\n", (void *) node);
  92. fprintf(stderr, " defn: %p\n", (void *) node->defn);
  93. node = node->next;
  94. } while (node);
  95. } else {
  96. fprintf(stderr, " defn: %p\n", (void *) doh.defn());
  97. }
  98. }
  99. }
  100. void
  101. DumpAtomDefnMap(const AtomDefnMapPtr &map)
  102. {
  103. if (map->empty()) {
  104. fprintf(stderr, "empty\n");
  105. return;
  106. }
  107. for (AtomDefnRange r = map->all(); !r.empty(); r.popFront()) {
  108. fprintf(stderr, "atom: ");
  109. js_DumpAtom(r.front().key());
  110. fprintf(stderr, "defn: %p\n", (void *) r.front().value());
  111. }
  112. }
  113. #endif
  114. AtomDeclNode *
  115. AtomDecls::allocNode(Definition *defn)
  116. {
  117. AtomDeclNode *p = cx->tempLifoAlloc().new_<AtomDeclNode>(defn);
  118. if (!p) {
  119. js_ReportOutOfMemory(cx);
  120. return NULL;
  121. }
  122. return p;
  123. }
  124. bool
  125. AtomDecls::addShadow(JSAtom *atom, Definition *defn)
  126. {
  127. AtomDeclNode *node = allocNode(defn);
  128. if (!node)
  129. return false;
  130. AtomDOHAddPtr p = map->lookupForAdd(atom);
  131. if (!p)
  132. return map->add(p, atom, DefnOrHeader(node));
  133. AtomDeclNode *toShadow;
  134. if (p.value().isHeader()) {
  135. toShadow = p.value().header();
  136. } else {
  137. toShadow = allocNode(p.value().defn());
  138. if (!toShadow)
  139. return false;
  140. }
  141. node->next = toShadow;
  142. p.value() = DefnOrHeader(node);
  143. return true;
  144. }
  145. AtomDeclNode *
  146. AtomDecls::lastAsNode(DefnOrHeader *doh)
  147. {
  148. if (doh->isHeader()) {
  149. AtomDeclNode *last = doh->header();
  150. while (last->next)
  151. last = last->next;
  152. return last;
  153. }
  154. /* Otherwise, we need to turn the existing defn into a node. */
  155. AtomDeclNode *node = allocNode(doh->defn());
  156. if (!node)
  157. return NULL;
  158. *doh = DefnOrHeader(node);
  159. return node;
  160. }
  161. bool
  162. AtomDecls::addHoist(JSAtom *atom, Definition *defn)
  163. {
  164. AtomDeclNode *node = allocNode(defn);
  165. if (!node)
  166. return false;
  167. AtomDOHAddPtr p = map->lookupForAdd(atom);
  168. if (p) {
  169. AtomDeclNode *last = lastAsNode(&p.value());
  170. if (!last)
  171. return false;
  172. last->next = node;
  173. return true;
  174. }
  175. return map->add(p, atom, DefnOrHeader(node));
  176. }