libv8-sgonyea 3.3.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (500) hide show
  1. data/.gitignore +8 -0
  2. data/.gitmodules +3 -0
  3. data/Gemfile +4 -0
  4. data/README.md +76 -0
  5. data/Rakefile +113 -0
  6. data/ext/libv8/extconf.rb +28 -0
  7. data/lib/libv8.rb +15 -0
  8. data/lib/libv8/Makefile +30 -0
  9. data/lib/libv8/detect_cpu.rb +27 -0
  10. data/lib/libv8/fpic-on-linux-amd64.patch +13 -0
  11. data/lib/libv8/v8/.gitignore +35 -0
  12. data/lib/libv8/v8/AUTHORS +44 -0
  13. data/lib/libv8/v8/ChangeLog +2839 -0
  14. data/lib/libv8/v8/LICENSE +52 -0
  15. data/lib/libv8/v8/LICENSE.strongtalk +29 -0
  16. data/lib/libv8/v8/LICENSE.v8 +26 -0
  17. data/lib/libv8/v8/LICENSE.valgrind +45 -0
  18. data/lib/libv8/v8/SConstruct +1478 -0
  19. data/lib/libv8/v8/build/README.txt +49 -0
  20. data/lib/libv8/v8/build/all.gyp +18 -0
  21. data/lib/libv8/v8/build/armu.gypi +32 -0
  22. data/lib/libv8/v8/build/common.gypi +144 -0
  23. data/lib/libv8/v8/build/gyp_v8 +145 -0
  24. data/lib/libv8/v8/include/v8-debug.h +395 -0
  25. data/lib/libv8/v8/include/v8-preparser.h +117 -0
  26. data/lib/libv8/v8/include/v8-profiler.h +505 -0
  27. data/lib/libv8/v8/include/v8-testing.h +104 -0
  28. data/lib/libv8/v8/include/v8.h +4124 -0
  29. data/lib/libv8/v8/include/v8stdint.h +53 -0
  30. data/lib/libv8/v8/preparser/SConscript +38 -0
  31. data/lib/libv8/v8/preparser/preparser-process.cc +379 -0
  32. data/lib/libv8/v8/src/SConscript +368 -0
  33. data/lib/libv8/v8/src/accessors.cc +767 -0
  34. data/lib/libv8/v8/src/accessors.h +123 -0
  35. data/lib/libv8/v8/src/allocation-inl.h +49 -0
  36. data/lib/libv8/v8/src/allocation.cc +122 -0
  37. data/lib/libv8/v8/src/allocation.h +143 -0
  38. data/lib/libv8/v8/src/api.cc +5845 -0
  39. data/lib/libv8/v8/src/api.h +574 -0
  40. data/lib/libv8/v8/src/apinatives.js +110 -0
  41. data/lib/libv8/v8/src/apiutils.h +73 -0
  42. data/lib/libv8/v8/src/arguments.h +118 -0
  43. data/lib/libv8/v8/src/arm/assembler-arm-inl.h +353 -0
  44. data/lib/libv8/v8/src/arm/assembler-arm.cc +2661 -0
  45. data/lib/libv8/v8/src/arm/assembler-arm.h +1375 -0
  46. data/lib/libv8/v8/src/arm/builtins-arm.cc +1658 -0
  47. data/lib/libv8/v8/src/arm/code-stubs-arm.cc +6398 -0
  48. data/lib/libv8/v8/src/arm/code-stubs-arm.h +673 -0
  49. data/lib/libv8/v8/src/arm/codegen-arm.cc +52 -0
  50. data/lib/libv8/v8/src/arm/codegen-arm.h +91 -0
  51. data/lib/libv8/v8/src/arm/constants-arm.cc +152 -0
  52. data/lib/libv8/v8/src/arm/constants-arm.h +775 -0
  53. data/lib/libv8/v8/src/arm/cpu-arm.cc +120 -0
  54. data/lib/libv8/v8/src/arm/debug-arm.cc +317 -0
  55. data/lib/libv8/v8/src/arm/deoptimizer-arm.cc +754 -0
  56. data/lib/libv8/v8/src/arm/disasm-arm.cc +1506 -0
  57. data/lib/libv8/v8/src/arm/frames-arm.cc +45 -0
  58. data/lib/libv8/v8/src/arm/frames-arm.h +168 -0
  59. data/lib/libv8/v8/src/arm/full-codegen-arm.cc +4375 -0
  60. data/lib/libv8/v8/src/arm/ic-arm.cc +1562 -0
  61. data/lib/libv8/v8/src/arm/lithium-arm.cc +2206 -0
  62. data/lib/libv8/v8/src/arm/lithium-arm.h +2348 -0
  63. data/lib/libv8/v8/src/arm/lithium-codegen-arm.cc +4526 -0
  64. data/lib/libv8/v8/src/arm/lithium-codegen-arm.h +403 -0
  65. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.cc +305 -0
  66. data/lib/libv8/v8/src/arm/lithium-gap-resolver-arm.h +84 -0
  67. data/lib/libv8/v8/src/arm/macro-assembler-arm.cc +3163 -0
  68. data/lib/libv8/v8/src/arm/macro-assembler-arm.h +1126 -0
  69. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.cc +1287 -0
  70. data/lib/libv8/v8/src/arm/regexp-macro-assembler-arm.h +253 -0
  71. data/lib/libv8/v8/src/arm/simulator-arm.cc +3424 -0
  72. data/lib/libv8/v8/src/arm/simulator-arm.h +431 -0
  73. data/lib/libv8/v8/src/arm/stub-cache-arm.cc +4243 -0
  74. data/lib/libv8/v8/src/array.js +1366 -0
  75. data/lib/libv8/v8/src/assembler.cc +1207 -0
  76. data/lib/libv8/v8/src/assembler.h +858 -0
  77. data/lib/libv8/v8/src/ast-inl.h +112 -0
  78. data/lib/libv8/v8/src/ast.cc +1146 -0
  79. data/lib/libv8/v8/src/ast.h +2188 -0
  80. data/lib/libv8/v8/src/atomicops.h +167 -0
  81. data/lib/libv8/v8/src/atomicops_internals_arm_gcc.h +145 -0
  82. data/lib/libv8/v8/src/atomicops_internals_mips_gcc.h +169 -0
  83. data/lib/libv8/v8/src/atomicops_internals_x86_gcc.cc +133 -0
  84. data/lib/libv8/v8/src/atomicops_internals_x86_gcc.h +287 -0
  85. data/lib/libv8/v8/src/atomicops_internals_x86_macosx.h +301 -0
  86. data/lib/libv8/v8/src/atomicops_internals_x86_msvc.h +203 -0
  87. data/lib/libv8/v8/src/bignum-dtoa.cc +655 -0
  88. data/lib/libv8/v8/src/bignum-dtoa.h +81 -0
  89. data/lib/libv8/v8/src/bignum.cc +768 -0
  90. data/lib/libv8/v8/src/bignum.h +140 -0
  91. data/lib/libv8/v8/src/bootstrapper.cc +2184 -0
  92. data/lib/libv8/v8/src/bootstrapper.h +188 -0
  93. data/lib/libv8/v8/src/builtins.cc +1707 -0
  94. data/lib/libv8/v8/src/builtins.h +371 -0
  95. data/lib/libv8/v8/src/bytecodes-irregexp.h +105 -0
  96. data/lib/libv8/v8/src/cached-powers.cc +177 -0
  97. data/lib/libv8/v8/src/cached-powers.h +65 -0
  98. data/lib/libv8/v8/src/char-predicates-inl.h +94 -0
  99. data/lib/libv8/v8/src/char-predicates.h +67 -0
  100. data/lib/libv8/v8/src/checks.cc +110 -0
  101. data/lib/libv8/v8/src/checks.h +296 -0
  102. data/lib/libv8/v8/src/circular-queue-inl.h +53 -0
  103. data/lib/libv8/v8/src/circular-queue.cc +122 -0
  104. data/lib/libv8/v8/src/circular-queue.h +103 -0
  105. data/lib/libv8/v8/src/code-stubs.cc +267 -0
  106. data/lib/libv8/v8/src/code-stubs.h +1011 -0
  107. data/lib/libv8/v8/src/code.h +70 -0
  108. data/lib/libv8/v8/src/codegen.cc +231 -0
  109. data/lib/libv8/v8/src/codegen.h +84 -0
  110. data/lib/libv8/v8/src/compilation-cache.cc +540 -0
  111. data/lib/libv8/v8/src/compilation-cache.h +287 -0
  112. data/lib/libv8/v8/src/compiler.cc +786 -0
  113. data/lib/libv8/v8/src/compiler.h +312 -0
  114. data/lib/libv8/v8/src/contexts.cc +347 -0
  115. data/lib/libv8/v8/src/contexts.h +391 -0
  116. data/lib/libv8/v8/src/conversions-inl.h +106 -0
  117. data/lib/libv8/v8/src/conversions.cc +1131 -0
  118. data/lib/libv8/v8/src/conversions.h +135 -0
  119. data/lib/libv8/v8/src/counters.cc +93 -0
  120. data/lib/libv8/v8/src/counters.h +254 -0
  121. data/lib/libv8/v8/src/cpu-profiler-inl.h +101 -0
  122. data/lib/libv8/v8/src/cpu-profiler.cc +609 -0
  123. data/lib/libv8/v8/src/cpu-profiler.h +302 -0
  124. data/lib/libv8/v8/src/cpu.h +69 -0
  125. data/lib/libv8/v8/src/d8-debug.cc +367 -0
  126. data/lib/libv8/v8/src/d8-debug.h +158 -0
  127. data/lib/libv8/v8/src/d8-posix.cc +695 -0
  128. data/lib/libv8/v8/src/d8-readline.cc +130 -0
  129. data/lib/libv8/v8/src/d8-windows.cc +42 -0
  130. data/lib/libv8/v8/src/d8.cc +803 -0
  131. data/lib/libv8/v8/src/d8.gyp +91 -0
  132. data/lib/libv8/v8/src/d8.h +235 -0
  133. data/lib/libv8/v8/src/d8.js +2798 -0
  134. data/lib/libv8/v8/src/data-flow.cc +66 -0
  135. data/lib/libv8/v8/src/data-flow.h +205 -0
  136. data/lib/libv8/v8/src/date.js +1103 -0
  137. data/lib/libv8/v8/src/dateparser-inl.h +127 -0
  138. data/lib/libv8/v8/src/dateparser.cc +178 -0
  139. data/lib/libv8/v8/src/dateparser.h +266 -0
  140. data/lib/libv8/v8/src/debug-agent.cc +447 -0
  141. data/lib/libv8/v8/src/debug-agent.h +129 -0
  142. data/lib/libv8/v8/src/debug-debugger.js +2569 -0
  143. data/lib/libv8/v8/src/debug.cc +3165 -0
  144. data/lib/libv8/v8/src/debug.h +1057 -0
  145. data/lib/libv8/v8/src/deoptimizer.cc +1256 -0
  146. data/lib/libv8/v8/src/deoptimizer.h +602 -0
  147. data/lib/libv8/v8/src/disasm.h +80 -0
  148. data/lib/libv8/v8/src/disassembler.cc +343 -0
  149. data/lib/libv8/v8/src/disassembler.h +58 -0
  150. data/lib/libv8/v8/src/diy-fp.cc +58 -0
  151. data/lib/libv8/v8/src/diy-fp.h +117 -0
  152. data/lib/libv8/v8/src/double.h +238 -0
  153. data/lib/libv8/v8/src/dtoa.cc +103 -0
  154. data/lib/libv8/v8/src/dtoa.h +85 -0
  155. data/lib/libv8/v8/src/execution.cc +849 -0
  156. data/lib/libv8/v8/src/execution.h +297 -0
  157. data/lib/libv8/v8/src/extensions/experimental/break-iterator.cc +250 -0
  158. data/lib/libv8/v8/src/extensions/experimental/break-iterator.h +89 -0
  159. data/lib/libv8/v8/src/extensions/experimental/collator.cc +218 -0
  160. data/lib/libv8/v8/src/extensions/experimental/collator.h +69 -0
  161. data/lib/libv8/v8/src/extensions/experimental/experimental.gyp +94 -0
  162. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.cc +78 -0
  163. data/lib/libv8/v8/src/extensions/experimental/i18n-extension.h +54 -0
  164. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.cc +112 -0
  165. data/lib/libv8/v8/src/extensions/experimental/i18n-locale.h +60 -0
  166. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.cc +43 -0
  167. data/lib/libv8/v8/src/extensions/experimental/i18n-utils.h +49 -0
  168. data/lib/libv8/v8/src/extensions/experimental/i18n.js +180 -0
  169. data/lib/libv8/v8/src/extensions/experimental/language-matcher.cc +251 -0
  170. data/lib/libv8/v8/src/extensions/experimental/language-matcher.h +95 -0
  171. data/lib/libv8/v8/src/extensions/externalize-string-extension.cc +141 -0
  172. data/lib/libv8/v8/src/extensions/externalize-string-extension.h +50 -0
  173. data/lib/libv8/v8/src/extensions/gc-extension.cc +58 -0
  174. data/lib/libv8/v8/src/extensions/gc-extension.h +49 -0
  175. data/lib/libv8/v8/src/factory.cc +1222 -0
  176. data/lib/libv8/v8/src/factory.h +442 -0
  177. data/lib/libv8/v8/src/fast-dtoa.cc +736 -0
  178. data/lib/libv8/v8/src/fast-dtoa.h +83 -0
  179. data/lib/libv8/v8/src/fixed-dtoa.cc +405 -0
  180. data/lib/libv8/v8/src/fixed-dtoa.h +55 -0
  181. data/lib/libv8/v8/src/flag-definitions.h +560 -0
  182. data/lib/libv8/v8/src/flags.cc +551 -0
  183. data/lib/libv8/v8/src/flags.h +79 -0
  184. data/lib/libv8/v8/src/frames-inl.h +247 -0
  185. data/lib/libv8/v8/src/frames.cc +1243 -0
  186. data/lib/libv8/v8/src/frames.h +870 -0
  187. data/lib/libv8/v8/src/full-codegen.cc +1374 -0
  188. data/lib/libv8/v8/src/full-codegen.h +771 -0
  189. data/lib/libv8/v8/src/func-name-inferrer.cc +92 -0
  190. data/lib/libv8/v8/src/func-name-inferrer.h +111 -0
  191. data/lib/libv8/v8/src/gdb-jit.cc +1555 -0
  192. data/lib/libv8/v8/src/gdb-jit.h +143 -0
  193. data/lib/libv8/v8/src/global-handles.cc +665 -0
  194. data/lib/libv8/v8/src/global-handles.h +284 -0
  195. data/lib/libv8/v8/src/globals.h +325 -0
  196. data/lib/libv8/v8/src/handles-inl.h +177 -0
  197. data/lib/libv8/v8/src/handles.cc +987 -0
  198. data/lib/libv8/v8/src/handles.h +382 -0
  199. data/lib/libv8/v8/src/hashmap.cc +230 -0
  200. data/lib/libv8/v8/src/hashmap.h +123 -0
  201. data/lib/libv8/v8/src/heap-inl.h +704 -0
  202. data/lib/libv8/v8/src/heap-profiler.cc +1173 -0
  203. data/lib/libv8/v8/src/heap-profiler.h +397 -0
  204. data/lib/libv8/v8/src/heap.cc +5930 -0
  205. data/lib/libv8/v8/src/heap.h +2268 -0
  206. data/lib/libv8/v8/src/hydrogen-instructions.cc +1769 -0
  207. data/lib/libv8/v8/src/hydrogen-instructions.h +3971 -0
  208. data/lib/libv8/v8/src/hydrogen.cc +6239 -0
  209. data/lib/libv8/v8/src/hydrogen.h +1202 -0
  210. data/lib/libv8/v8/src/ia32/assembler-ia32-inl.h +446 -0
  211. data/lib/libv8/v8/src/ia32/assembler-ia32.cc +2487 -0
  212. data/lib/libv8/v8/src/ia32/assembler-ia32.h +1144 -0
  213. data/lib/libv8/v8/src/ia32/builtins-ia32.cc +1621 -0
  214. data/lib/libv8/v8/src/ia32/code-stubs-ia32.cc +6198 -0
  215. data/lib/libv8/v8/src/ia32/code-stubs-ia32.h +517 -0
  216. data/lib/libv8/v8/src/ia32/codegen-ia32.cc +265 -0
  217. data/lib/libv8/v8/src/ia32/codegen-ia32.h +79 -0
  218. data/lib/libv8/v8/src/ia32/cpu-ia32.cc +88 -0
  219. data/lib/libv8/v8/src/ia32/debug-ia32.cc +312 -0
  220. data/lib/libv8/v8/src/ia32/deoptimizer-ia32.cc +774 -0
  221. data/lib/libv8/v8/src/ia32/disasm-ia32.cc +1628 -0
  222. data/lib/libv8/v8/src/ia32/frames-ia32.cc +45 -0
  223. data/lib/libv8/v8/src/ia32/frames-ia32.h +142 -0
  224. data/lib/libv8/v8/src/ia32/full-codegen-ia32.cc +4338 -0
  225. data/lib/libv8/v8/src/ia32/ic-ia32.cc +1597 -0
  226. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.cc +4461 -0
  227. data/lib/libv8/v8/src/ia32/lithium-codegen-ia32.h +375 -0
  228. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.cc +475 -0
  229. data/lib/libv8/v8/src/ia32/lithium-gap-resolver-ia32.h +110 -0
  230. data/lib/libv8/v8/src/ia32/lithium-ia32.cc +2261 -0
  231. data/lib/libv8/v8/src/ia32/lithium-ia32.h +2396 -0
  232. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.cc +2136 -0
  233. data/lib/libv8/v8/src/ia32/macro-assembler-ia32.h +775 -0
  234. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.cc +1263 -0
  235. data/lib/libv8/v8/src/ia32/regexp-macro-assembler-ia32.h +216 -0
  236. data/lib/libv8/v8/src/ia32/simulator-ia32.cc +30 -0
  237. data/lib/libv8/v8/src/ia32/simulator-ia32.h +74 -0
  238. data/lib/libv8/v8/src/ia32/stub-cache-ia32.cc +3847 -0
  239. data/lib/libv8/v8/src/ic-inl.h +130 -0
  240. data/lib/libv8/v8/src/ic.cc +2577 -0
  241. data/lib/libv8/v8/src/ic.h +736 -0
  242. data/lib/libv8/v8/src/inspector.cc +63 -0
  243. data/lib/libv8/v8/src/inspector.h +62 -0
  244. data/lib/libv8/v8/src/interpreter-irregexp.cc +659 -0
  245. data/lib/libv8/v8/src/interpreter-irregexp.h +49 -0
  246. data/lib/libv8/v8/src/isolate-inl.h +50 -0
  247. data/lib/libv8/v8/src/isolate.cc +1869 -0
  248. data/lib/libv8/v8/src/isolate.h +1382 -0
  249. data/lib/libv8/v8/src/json-parser.cc +504 -0
  250. data/lib/libv8/v8/src/json-parser.h +161 -0
  251. data/lib/libv8/v8/src/json.js +342 -0
  252. data/lib/libv8/v8/src/jsregexp.cc +5385 -0
  253. data/lib/libv8/v8/src/jsregexp.h +1492 -0
  254. data/lib/libv8/v8/src/list-inl.h +212 -0
  255. data/lib/libv8/v8/src/list.h +174 -0
  256. data/lib/libv8/v8/src/lithium-allocator-inl.h +142 -0
  257. data/lib/libv8/v8/src/lithium-allocator.cc +2123 -0
  258. data/lib/libv8/v8/src/lithium-allocator.h +630 -0
  259. data/lib/libv8/v8/src/lithium.cc +190 -0
  260. data/lib/libv8/v8/src/lithium.h +597 -0
  261. data/lib/libv8/v8/src/liveedit-debugger.js +1082 -0
  262. data/lib/libv8/v8/src/liveedit.cc +1691 -0
  263. data/lib/libv8/v8/src/liveedit.h +180 -0
  264. data/lib/libv8/v8/src/liveobjectlist-inl.h +126 -0
  265. data/lib/libv8/v8/src/liveobjectlist.cc +2589 -0
  266. data/lib/libv8/v8/src/liveobjectlist.h +322 -0
  267. data/lib/libv8/v8/src/log-inl.h +59 -0
  268. data/lib/libv8/v8/src/log-utils.cc +428 -0
  269. data/lib/libv8/v8/src/log-utils.h +231 -0
  270. data/lib/libv8/v8/src/log.cc +1993 -0
  271. data/lib/libv8/v8/src/log.h +476 -0
  272. data/lib/libv8/v8/src/macro-assembler.h +120 -0
  273. data/lib/libv8/v8/src/macros.py +178 -0
  274. data/lib/libv8/v8/src/mark-compact.cc +3143 -0
  275. data/lib/libv8/v8/src/mark-compact.h +506 -0
  276. data/lib/libv8/v8/src/math.js +264 -0
  277. data/lib/libv8/v8/src/messages.cc +179 -0
  278. data/lib/libv8/v8/src/messages.h +113 -0
  279. data/lib/libv8/v8/src/messages.js +1096 -0
  280. data/lib/libv8/v8/src/mips/assembler-mips-inl.h +312 -0
  281. data/lib/libv8/v8/src/mips/assembler-mips.cc +1960 -0
  282. data/lib/libv8/v8/src/mips/assembler-mips.h +1138 -0
  283. data/lib/libv8/v8/src/mips/builtins-mips.cc +1628 -0
  284. data/lib/libv8/v8/src/mips/code-stubs-mips.cc +6656 -0
  285. data/lib/libv8/v8/src/mips/code-stubs-mips.h +682 -0
  286. data/lib/libv8/v8/src/mips/codegen-mips.cc +52 -0
  287. data/lib/libv8/v8/src/mips/codegen-mips.h +98 -0
  288. data/lib/libv8/v8/src/mips/constants-mips.cc +352 -0
  289. data/lib/libv8/v8/src/mips/constants-mips.h +739 -0
  290. data/lib/libv8/v8/src/mips/cpu-mips.cc +96 -0
  291. data/lib/libv8/v8/src/mips/debug-mips.cc +308 -0
  292. data/lib/libv8/v8/src/mips/deoptimizer-mips.cc +91 -0
  293. data/lib/libv8/v8/src/mips/disasm-mips.cc +1050 -0
  294. data/lib/libv8/v8/src/mips/frames-mips.cc +47 -0
  295. data/lib/libv8/v8/src/mips/frames-mips.h +219 -0
  296. data/lib/libv8/v8/src/mips/full-codegen-mips.cc +4388 -0
  297. data/lib/libv8/v8/src/mips/ic-mips.cc +1580 -0
  298. data/lib/libv8/v8/src/mips/lithium-codegen-mips.h +65 -0
  299. data/lib/libv8/v8/src/mips/lithium-mips.h +307 -0
  300. data/lib/libv8/v8/src/mips/macro-assembler-mips.cc +4056 -0
  301. data/lib/libv8/v8/src/mips/macro-assembler-mips.h +1214 -0
  302. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.cc +1251 -0
  303. data/lib/libv8/v8/src/mips/regexp-macro-assembler-mips.h +252 -0
  304. data/lib/libv8/v8/src/mips/simulator-mips.cc +2621 -0
  305. data/lib/libv8/v8/src/mips/simulator-mips.h +401 -0
  306. data/lib/libv8/v8/src/mips/stub-cache-mips.cc +4285 -0
  307. data/lib/libv8/v8/src/mirror-debugger.js +2382 -0
  308. data/lib/libv8/v8/src/mksnapshot.cc +328 -0
  309. data/lib/libv8/v8/src/natives.h +64 -0
  310. data/lib/libv8/v8/src/objects-debug.cc +738 -0
  311. data/lib/libv8/v8/src/objects-inl.h +4323 -0
  312. data/lib/libv8/v8/src/objects-printer.cc +829 -0
  313. data/lib/libv8/v8/src/objects-visiting.cc +148 -0
  314. data/lib/libv8/v8/src/objects-visiting.h +424 -0
  315. data/lib/libv8/v8/src/objects.cc +10585 -0
  316. data/lib/libv8/v8/src/objects.h +6838 -0
  317. data/lib/libv8/v8/src/parser.cc +4997 -0
  318. data/lib/libv8/v8/src/parser.h +765 -0
  319. data/lib/libv8/v8/src/platform-cygwin.cc +779 -0
  320. data/lib/libv8/v8/src/platform-freebsd.cc +826 -0
  321. data/lib/libv8/v8/src/platform-linux.cc +1149 -0
  322. data/lib/libv8/v8/src/platform-macos.cc +830 -0
  323. data/lib/libv8/v8/src/platform-nullos.cc +479 -0
  324. data/lib/libv8/v8/src/platform-openbsd.cc +640 -0
  325. data/lib/libv8/v8/src/platform-posix.cc +424 -0
  326. data/lib/libv8/v8/src/platform-solaris.cc +762 -0
  327. data/lib/libv8/v8/src/platform-tls-mac.h +62 -0
  328. data/lib/libv8/v8/src/platform-tls-win32.h +62 -0
  329. data/lib/libv8/v8/src/platform-tls.h +50 -0
  330. data/lib/libv8/v8/src/platform-win32.cc +2021 -0
  331. data/lib/libv8/v8/src/platform.h +667 -0
  332. data/lib/libv8/v8/src/preparse-data-format.h +62 -0
  333. data/lib/libv8/v8/src/preparse-data.cc +183 -0
  334. data/lib/libv8/v8/src/preparse-data.h +225 -0
  335. data/lib/libv8/v8/src/preparser-api.cc +220 -0
  336. data/lib/libv8/v8/src/preparser.cc +1450 -0
  337. data/lib/libv8/v8/src/preparser.h +493 -0
  338. data/lib/libv8/v8/src/prettyprinter.cc +1493 -0
  339. data/lib/libv8/v8/src/prettyprinter.h +223 -0
  340. data/lib/libv8/v8/src/profile-generator-inl.h +128 -0
  341. data/lib/libv8/v8/src/profile-generator.cc +3098 -0
  342. data/lib/libv8/v8/src/profile-generator.h +1126 -0
  343. data/lib/libv8/v8/src/property.cc +105 -0
  344. data/lib/libv8/v8/src/property.h +365 -0
  345. data/lib/libv8/v8/src/proxy.js +83 -0
  346. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp-inl.h +78 -0
  347. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp.cc +471 -0
  348. data/lib/libv8/v8/src/regexp-macro-assembler-irregexp.h +142 -0
  349. data/lib/libv8/v8/src/regexp-macro-assembler-tracer.cc +373 -0
  350. data/lib/libv8/v8/src/regexp-macro-assembler-tracer.h +104 -0
  351. data/lib/libv8/v8/src/regexp-macro-assembler.cc +267 -0
  352. data/lib/libv8/v8/src/regexp-macro-assembler.h +243 -0
  353. data/lib/libv8/v8/src/regexp-stack.cc +111 -0
  354. data/lib/libv8/v8/src/regexp-stack.h +147 -0
  355. data/lib/libv8/v8/src/regexp.js +483 -0
  356. data/lib/libv8/v8/src/rewriter.cc +360 -0
  357. data/lib/libv8/v8/src/rewriter.h +50 -0
  358. data/lib/libv8/v8/src/runtime-profiler.cc +489 -0
  359. data/lib/libv8/v8/src/runtime-profiler.h +201 -0
  360. data/lib/libv8/v8/src/runtime.cc +12227 -0
  361. data/lib/libv8/v8/src/runtime.h +652 -0
  362. data/lib/libv8/v8/src/runtime.js +649 -0
  363. data/lib/libv8/v8/src/safepoint-table.cc +256 -0
  364. data/lib/libv8/v8/src/safepoint-table.h +270 -0
  365. data/lib/libv8/v8/src/scanner-base.cc +952 -0
  366. data/lib/libv8/v8/src/scanner-base.h +670 -0
  367. data/lib/libv8/v8/src/scanner.cc +345 -0
  368. data/lib/libv8/v8/src/scanner.h +146 -0
  369. data/lib/libv8/v8/src/scopeinfo.cc +646 -0
  370. data/lib/libv8/v8/src/scopeinfo.h +254 -0
  371. data/lib/libv8/v8/src/scopes.cc +1150 -0
  372. data/lib/libv8/v8/src/scopes.h +507 -0
  373. data/lib/libv8/v8/src/serialize.cc +1574 -0
  374. data/lib/libv8/v8/src/serialize.h +589 -0
  375. data/lib/libv8/v8/src/shell.h +55 -0
  376. data/lib/libv8/v8/src/simulator.h +43 -0
  377. data/lib/libv8/v8/src/small-pointer-list.h +163 -0
  378. data/lib/libv8/v8/src/smart-pointer.h +109 -0
  379. data/lib/libv8/v8/src/snapshot-common.cc +83 -0
  380. data/lib/libv8/v8/src/snapshot-empty.cc +54 -0
  381. data/lib/libv8/v8/src/snapshot.h +91 -0
  382. data/lib/libv8/v8/src/spaces-inl.h +529 -0
  383. data/lib/libv8/v8/src/spaces.cc +3145 -0
  384. data/lib/libv8/v8/src/spaces.h +2369 -0
  385. data/lib/libv8/v8/src/splay-tree-inl.h +310 -0
  386. data/lib/libv8/v8/src/splay-tree.h +205 -0
  387. data/lib/libv8/v8/src/string-search.cc +41 -0
  388. data/lib/libv8/v8/src/string-search.h +568 -0
  389. data/lib/libv8/v8/src/string-stream.cc +592 -0
  390. data/lib/libv8/v8/src/string-stream.h +191 -0
  391. data/lib/libv8/v8/src/string.js +994 -0
  392. data/lib/libv8/v8/src/strtod.cc +440 -0
  393. data/lib/libv8/v8/src/strtod.h +40 -0
  394. data/lib/libv8/v8/src/stub-cache.cc +1965 -0
  395. data/lib/libv8/v8/src/stub-cache.h +924 -0
  396. data/lib/libv8/v8/src/third_party/valgrind/valgrind.h +3925 -0
  397. data/lib/libv8/v8/src/token.cc +63 -0
  398. data/lib/libv8/v8/src/token.h +288 -0
  399. data/lib/libv8/v8/src/type-info.cc +507 -0
  400. data/lib/libv8/v8/src/type-info.h +272 -0
  401. data/lib/libv8/v8/src/unbound-queue-inl.h +95 -0
  402. data/lib/libv8/v8/src/unbound-queue.h +69 -0
  403. data/lib/libv8/v8/src/unicode-inl.h +238 -0
  404. data/lib/libv8/v8/src/unicode.cc +1624 -0
  405. data/lib/libv8/v8/src/unicode.h +280 -0
  406. data/lib/libv8/v8/src/uri.js +408 -0
  407. data/lib/libv8/v8/src/utils-inl.h +48 -0
  408. data/lib/libv8/v8/src/utils.cc +371 -0
  409. data/lib/libv8/v8/src/utils.h +800 -0
  410. data/lib/libv8/v8/src/v8-counters.cc +62 -0
  411. data/lib/libv8/v8/src/v8-counters.h +314 -0
  412. data/lib/libv8/v8/src/v8.cc +213 -0
  413. data/lib/libv8/v8/src/v8.h +131 -0
  414. data/lib/libv8/v8/src/v8checks.h +64 -0
  415. data/lib/libv8/v8/src/v8dll-main.cc +44 -0
  416. data/lib/libv8/v8/src/v8globals.h +512 -0
  417. data/lib/libv8/v8/src/v8memory.h +82 -0
  418. data/lib/libv8/v8/src/v8natives.js +1310 -0
  419. data/lib/libv8/v8/src/v8preparserdll-main.cc +39 -0
  420. data/lib/libv8/v8/src/v8threads.cc +464 -0
  421. data/lib/libv8/v8/src/v8threads.h +165 -0
  422. data/lib/libv8/v8/src/v8utils.h +319 -0
  423. data/lib/libv8/v8/src/variables.cc +114 -0
  424. data/lib/libv8/v8/src/variables.h +167 -0
  425. data/lib/libv8/v8/src/version.cc +116 -0
  426. data/lib/libv8/v8/src/version.h +68 -0
  427. data/lib/libv8/v8/src/vm-state-inl.h +138 -0
  428. data/lib/libv8/v8/src/vm-state.h +71 -0
  429. data/lib/libv8/v8/src/win32-headers.h +96 -0
  430. data/lib/libv8/v8/src/x64/assembler-x64-inl.h +462 -0
  431. data/lib/libv8/v8/src/x64/assembler-x64.cc +3027 -0
  432. data/lib/libv8/v8/src/x64/assembler-x64.h +1633 -0
  433. data/lib/libv8/v8/src/x64/builtins-x64.cc +1520 -0
  434. data/lib/libv8/v8/src/x64/code-stubs-x64.cc +5132 -0
  435. data/lib/libv8/v8/src/x64/code-stubs-x64.h +514 -0
  436. data/lib/libv8/v8/src/x64/codegen-x64.cc +146 -0
  437. data/lib/libv8/v8/src/x64/codegen-x64.h +76 -0
  438. data/lib/libv8/v8/src/x64/cpu-x64.cc +88 -0
  439. data/lib/libv8/v8/src/x64/debug-x64.cc +319 -0
  440. data/lib/libv8/v8/src/x64/deoptimizer-x64.cc +815 -0
  441. data/lib/libv8/v8/src/x64/disasm-x64.cc +1832 -0
  442. data/lib/libv8/v8/src/x64/frames-x64.cc +45 -0
  443. data/lib/libv8/v8/src/x64/frames-x64.h +130 -0
  444. data/lib/libv8/v8/src/x64/full-codegen-x64.cc +4318 -0
  445. data/lib/libv8/v8/src/x64/ic-x64.cc +1608 -0
  446. data/lib/libv8/v8/src/x64/lithium-codegen-x64.cc +4267 -0
  447. data/lib/libv8/v8/src/x64/lithium-codegen-x64.h +367 -0
  448. data/lib/libv8/v8/src/x64/lithium-gap-resolver-x64.cc +320 -0
  449. data/lib/libv8/v8/src/x64/lithium-gap-resolver-x64.h +74 -0
  450. data/lib/libv8/v8/src/x64/lithium-x64.cc +2202 -0
  451. data/lib/libv8/v8/src/x64/lithium-x64.h +2333 -0
  452. data/lib/libv8/v8/src/x64/macro-assembler-x64.cc +3745 -0
  453. data/lib/libv8/v8/src/x64/macro-assembler-x64.h +1290 -0
  454. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.cc +1398 -0
  455. data/lib/libv8/v8/src/x64/regexp-macro-assembler-x64.h +282 -0
  456. data/lib/libv8/v8/src/x64/simulator-x64.cc +27 -0
  457. data/lib/libv8/v8/src/x64/simulator-x64.h +72 -0
  458. data/lib/libv8/v8/src/x64/stub-cache-x64.cc +3610 -0
  459. data/lib/libv8/v8/src/zone-inl.h +140 -0
  460. data/lib/libv8/v8/src/zone.cc +196 -0
  461. data/lib/libv8/v8/src/zone.h +240 -0
  462. data/lib/libv8/v8/tools/codemap.js +265 -0
  463. data/lib/libv8/v8/tools/consarray.js +93 -0
  464. data/lib/libv8/v8/tools/csvparser.js +78 -0
  465. data/lib/libv8/v8/tools/disasm.py +92 -0
  466. data/lib/libv8/v8/tools/freebsd-tick-processor +10 -0
  467. data/lib/libv8/v8/tools/gc-nvp-trace-processor.py +342 -0
  468. data/lib/libv8/v8/tools/gcmole/README +62 -0
  469. data/lib/libv8/v8/tools/gcmole/gccause.lua +60 -0
  470. data/lib/libv8/v8/tools/gcmole/gcmole.cc +1261 -0
  471. data/lib/libv8/v8/tools/gcmole/gcmole.lua +378 -0
  472. data/lib/libv8/v8/tools/generate-ten-powers.scm +286 -0
  473. data/lib/libv8/v8/tools/grokdump.py +841 -0
  474. data/lib/libv8/v8/tools/gyp/v8.gyp +995 -0
  475. data/lib/libv8/v8/tools/js2c.py +364 -0
  476. data/lib/libv8/v8/tools/jsmin.py +280 -0
  477. data/lib/libv8/v8/tools/linux-tick-processor +35 -0
  478. data/lib/libv8/v8/tools/ll_prof.py +942 -0
  479. data/lib/libv8/v8/tools/logreader.js +185 -0
  480. data/lib/libv8/v8/tools/mac-nm +18 -0
  481. data/lib/libv8/v8/tools/mac-tick-processor +6 -0
  482. data/lib/libv8/v8/tools/oom_dump/README +31 -0
  483. data/lib/libv8/v8/tools/oom_dump/SConstruct +42 -0
  484. data/lib/libv8/v8/tools/oom_dump/oom_dump.cc +288 -0
  485. data/lib/libv8/v8/tools/presubmit.py +305 -0
  486. data/lib/libv8/v8/tools/process-heap-prof.py +120 -0
  487. data/lib/libv8/v8/tools/profile.js +751 -0
  488. data/lib/libv8/v8/tools/profile_view.js +219 -0
  489. data/lib/libv8/v8/tools/run-valgrind.py +77 -0
  490. data/lib/libv8/v8/tools/splaytree.js +316 -0
  491. data/lib/libv8/v8/tools/stats-viewer.py +468 -0
  492. data/lib/libv8/v8/tools/test.py +1510 -0
  493. data/lib/libv8/v8/tools/tickprocessor-driver.js +59 -0
  494. data/lib/libv8/v8/tools/tickprocessor.js +877 -0
  495. data/lib/libv8/v8/tools/utils.py +96 -0
  496. data/lib/libv8/v8/tools/visual_studio/README.txt +12 -0
  497. data/lib/libv8/v8/tools/windows-tick-processor.bat +30 -0
  498. data/lib/libv8/version.rb +5 -0
  499. data/libv8.gemspec +36 -0
  500. metadata +578 -0
@@ -0,0 +1,1492 @@
1
+ // Copyright 2006-2008 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #ifndef V8_JSREGEXP_H_
29
+ #define V8_JSREGEXP_H_
30
+
31
+ #include "allocation.h"
32
+ #include "macro-assembler.h"
33
+ #include "zone-inl.h"
34
+
35
+ namespace v8 {
36
+ namespace internal {
37
+
38
+
39
+ class RegExpMacroAssembler;
40
+
41
+
42
+ class RegExpImpl {
43
+ public:
44
+ // Whether V8 is compiled with native regexp support or not.
45
+ static bool UsesNativeRegExp() {
46
+ #ifdef V8_INTERPRETED_REGEXP
47
+ return false;
48
+ #else
49
+ return true;
50
+ #endif
51
+ }
52
+
53
+ // Creates a regular expression literal in the old space.
54
+ // This function calls the garbage collector if necessary.
55
+ static Handle<Object> CreateRegExpLiteral(Handle<JSFunction> constructor,
56
+ Handle<String> pattern,
57
+ Handle<String> flags,
58
+ bool* has_pending_exception);
59
+
60
+ // Returns a string representation of a regular expression.
61
+ // Implements RegExp.prototype.toString, see ECMA-262 section 15.10.6.4.
62
+ // This function calls the garbage collector if necessary.
63
+ static Handle<String> ToString(Handle<Object> value);
64
+
65
+ // Parses the RegExp pattern and prepares the JSRegExp object with
66
+ // generic data and choice of implementation - as well as what
67
+ // the implementation wants to store in the data field.
68
+ // Returns false if compilation fails.
69
+ static Handle<Object> Compile(Handle<JSRegExp> re,
70
+ Handle<String> pattern,
71
+ Handle<String> flags);
72
+
73
+ // See ECMA-262 section 15.10.6.2.
74
+ // This function calls the garbage collector if necessary.
75
+ static Handle<Object> Exec(Handle<JSRegExp> regexp,
76
+ Handle<String> subject,
77
+ int index,
78
+ Handle<JSArray> lastMatchInfo);
79
+
80
+ // Prepares a JSRegExp object with Irregexp-specific data.
81
+ static void IrregexpInitialize(Handle<JSRegExp> re,
82
+ Handle<String> pattern,
83
+ JSRegExp::Flags flags,
84
+ int capture_register_count);
85
+
86
+
87
+ static void AtomCompile(Handle<JSRegExp> re,
88
+ Handle<String> pattern,
89
+ JSRegExp::Flags flags,
90
+ Handle<String> match_pattern);
91
+
92
+ static Handle<Object> AtomExec(Handle<JSRegExp> regexp,
93
+ Handle<String> subject,
94
+ int index,
95
+ Handle<JSArray> lastMatchInfo);
96
+
97
+ enum IrregexpResult { RE_FAILURE = 0, RE_SUCCESS = 1, RE_EXCEPTION = -1 };
98
+
99
+ // Prepare a RegExp for being executed one or more times (using
100
+ // IrregexpExecOnce) on the subject.
101
+ // This ensures that the regexp is compiled for the subject, and that
102
+ // the subject is flat.
103
+ // Returns the number of integer spaces required by IrregexpExecOnce
104
+ // as its "registers" argument. If the regexp cannot be compiled,
105
+ // an exception is set as pending, and this function returns negative.
106
+ static int IrregexpPrepare(Handle<JSRegExp> regexp,
107
+ Handle<String> subject);
108
+
109
+ // Execute a regular expression once on the subject, starting from
110
+ // character "index".
111
+ // If successful, returns RE_SUCCESS and set the capture positions
112
+ // in the first registers.
113
+ // If matching fails, returns RE_FAILURE.
114
+ // If execution fails, sets a pending exception and returns RE_EXCEPTION.
115
+ static IrregexpResult IrregexpExecOnce(Handle<JSRegExp> regexp,
116
+ Handle<String> subject,
117
+ int index,
118
+ Vector<int> registers);
119
+
120
+ // Execute an Irregexp bytecode pattern.
121
+ // On a successful match, the result is a JSArray containing
122
+ // captured positions. On a failure, the result is the null value.
123
+ // Returns an empty handle in case of an exception.
124
+ static Handle<Object> IrregexpExec(Handle<JSRegExp> regexp,
125
+ Handle<String> subject,
126
+ int index,
127
+ Handle<JSArray> lastMatchInfo);
128
+
129
+ // Array index in the lastMatchInfo array.
130
+ static const int kLastCaptureCount = 0;
131
+ static const int kLastSubject = 1;
132
+ static const int kLastInput = 2;
133
+ static const int kFirstCapture = 3;
134
+ static const int kLastMatchOverhead = 3;
135
+
136
+ // Direct offset into the lastMatchInfo array.
137
+ static const int kLastCaptureCountOffset =
138
+ FixedArray::kHeaderSize + kLastCaptureCount * kPointerSize;
139
+ static const int kLastSubjectOffset =
140
+ FixedArray::kHeaderSize + kLastSubject * kPointerSize;
141
+ static const int kLastInputOffset =
142
+ FixedArray::kHeaderSize + kLastInput * kPointerSize;
143
+ static const int kFirstCaptureOffset =
144
+ FixedArray::kHeaderSize + kFirstCapture * kPointerSize;
145
+
146
+ // Used to access the lastMatchInfo array.
147
+ static int GetCapture(FixedArray* array, int index) {
148
+ return Smi::cast(array->get(index + kFirstCapture))->value();
149
+ }
150
+
151
+ static void SetLastCaptureCount(FixedArray* array, int to) {
152
+ array->set(kLastCaptureCount, Smi::FromInt(to));
153
+ }
154
+
155
+ static void SetLastSubject(FixedArray* array, String* to) {
156
+ array->set(kLastSubject, to);
157
+ }
158
+
159
+ static void SetLastInput(FixedArray* array, String* to) {
160
+ array->set(kLastInput, to);
161
+ }
162
+
163
+ static void SetCapture(FixedArray* array, int index, int to) {
164
+ array->set(index + kFirstCapture, Smi::FromInt(to));
165
+ }
166
+
167
+ static int GetLastCaptureCount(FixedArray* array) {
168
+ return Smi::cast(array->get(kLastCaptureCount))->value();
169
+ }
170
+
171
+ // For acting on the JSRegExp data FixedArray.
172
+ static int IrregexpMaxRegisterCount(FixedArray* re);
173
+ static void SetIrregexpMaxRegisterCount(FixedArray* re, int value);
174
+ static int IrregexpNumberOfCaptures(FixedArray* re);
175
+ static int IrregexpNumberOfRegisters(FixedArray* re);
176
+ static ByteArray* IrregexpByteCode(FixedArray* re, bool is_ascii);
177
+ static Code* IrregexpNativeCode(FixedArray* re, bool is_ascii);
178
+
179
+ // Limit the space regexps take up on the heap. In order to limit this we
180
+ // would like to keep track of the amount of regexp code on the heap. This
181
+ // is not tracked, however. As a conservative approximation we track the
182
+ // total regexp code compiled including code that has subsequently been freed
183
+ // and the total executable memory at any point.
184
+ static const int kRegExpExecutableMemoryLimit = 16 * MB;
185
+ static const int kRegWxpCompiledLimit = 1 * MB;
186
+
187
+ private:
188
+ static String* last_ascii_string_;
189
+ static String* two_byte_cached_string_;
190
+
191
+ static bool CompileIrregexp(Handle<JSRegExp> re, bool is_ascii);
192
+ static inline bool EnsureCompiledIrregexp(Handle<JSRegExp> re, bool is_ascii);
193
+
194
+
195
+ // Set the subject cache. The previous string buffer is not deleted, so the
196
+ // caller should ensure that it doesn't leak.
197
+ static void SetSubjectCache(String* subject,
198
+ char* utf8_subject,
199
+ int uft8_length,
200
+ int character_position,
201
+ int utf8_position);
202
+
203
+ // A one element cache of the last utf8_subject string and its length. The
204
+ // subject JS String object is cached in the heap. We also cache a
205
+ // translation between position and utf8 position.
206
+ static char* utf8_subject_cache_;
207
+ static int utf8_length_cache_;
208
+ static int utf8_position_;
209
+ static int character_position_;
210
+ };
211
+
212
+
213
+ // Represents the location of one element relative to the intersection of
214
+ // two sets. Corresponds to the four areas of a Venn diagram.
215
+ enum ElementInSetsRelation {
216
+ kInsideNone = 0,
217
+ kInsideFirst = 1,
218
+ kInsideSecond = 2,
219
+ kInsideBoth = 3
220
+ };
221
+
222
+
223
+ // Represents the relation of two sets.
224
+ // Sets can be either disjoint, partially or fully overlapping, or equal.
225
+ class SetRelation BASE_EMBEDDED {
226
+ public:
227
+ // Relation is represented by a bit saying whether there are elements in
228
+ // one set that is not in the other, and a bit saying that there are elements
229
+ // that are in both sets.
230
+
231
+ // Location of an element. Corresponds to the internal areas of
232
+ // a Venn diagram.
233
+ enum {
234
+ kInFirst = 1 << kInsideFirst,
235
+ kInSecond = 1 << kInsideSecond,
236
+ kInBoth = 1 << kInsideBoth
237
+ };
238
+ SetRelation() : bits_(0) {}
239
+ ~SetRelation() {}
240
+ // Add the existence of objects in a particular
241
+ void SetElementsInFirstSet() { bits_ |= kInFirst; }
242
+ void SetElementsInSecondSet() { bits_ |= kInSecond; }
243
+ void SetElementsInBothSets() { bits_ |= kInBoth; }
244
+ // Check the currently known relation of the sets (common functions only,
245
+ // for other combinations, use value() to get the bits and check them
246
+ // manually).
247
+ // Sets are completely disjoint.
248
+ bool Disjoint() { return (bits_ & kInBoth) == 0; }
249
+ // Sets are equal.
250
+ bool Equals() { return (bits_ & (kInFirst | kInSecond)) == 0; }
251
+ // First set contains second.
252
+ bool Contains() { return (bits_ & kInSecond) == 0; }
253
+ // Second set contains first.
254
+ bool ContainedIn() { return (bits_ & kInFirst) == 0; }
255
+ bool NonTrivialIntersection() {
256
+ return (bits_ == (kInFirst | kInSecond | kInBoth));
257
+ }
258
+ int value() { return bits_; }
259
+ private:
260
+ int bits_;
261
+ };
262
+
263
+
264
+ class CharacterRange {
265
+ public:
266
+ CharacterRange() : from_(0), to_(0) { }
267
+ // For compatibility with the CHECK_OK macro
268
+ CharacterRange(void* null) { ASSERT_EQ(NULL, null); } //NOLINT
269
+ CharacterRange(uc16 from, uc16 to) : from_(from), to_(to) { }
270
+ static void AddClassEscape(uc16 type, ZoneList<CharacterRange>* ranges);
271
+ static Vector<const uc16> GetWordBounds();
272
+ static inline CharacterRange Singleton(uc16 value) {
273
+ return CharacterRange(value, value);
274
+ }
275
+ static inline CharacterRange Range(uc16 from, uc16 to) {
276
+ ASSERT(from <= to);
277
+ return CharacterRange(from, to);
278
+ }
279
+ static inline CharacterRange Everything() {
280
+ return CharacterRange(0, 0xFFFF);
281
+ }
282
+ bool Contains(uc16 i) { return from_ <= i && i <= to_; }
283
+ uc16 from() const { return from_; }
284
+ void set_from(uc16 value) { from_ = value; }
285
+ uc16 to() const { return to_; }
286
+ void set_to(uc16 value) { to_ = value; }
287
+ bool is_valid() { return from_ <= to_; }
288
+ bool IsEverything(uc16 max) { return from_ == 0 && to_ >= max; }
289
+ bool IsSingleton() { return (from_ == to_); }
290
+ void AddCaseEquivalents(ZoneList<CharacterRange>* ranges, bool is_ascii);
291
+ static void Split(ZoneList<CharacterRange>* base,
292
+ Vector<const uc16> overlay,
293
+ ZoneList<CharacterRange>** included,
294
+ ZoneList<CharacterRange>** excluded);
295
+ // Whether a range list is in canonical form: Ranges ordered by from value,
296
+ // and ranges non-overlapping and non-adjacent.
297
+ static bool IsCanonical(ZoneList<CharacterRange>* ranges);
298
+ // Convert range list to canonical form. The characters covered by the ranges
299
+ // will still be the same, but no character is in more than one range, and
300
+ // adjacent ranges are merged. The resulting list may be shorter than the
301
+ // original, but cannot be longer.
302
+ static void Canonicalize(ZoneList<CharacterRange>* ranges);
303
+ // Check how the set of characters defined by a CharacterRange list relates
304
+ // to the set of word characters. List must be in canonical form.
305
+ static SetRelation WordCharacterRelation(ZoneList<CharacterRange>* ranges);
306
+ // Takes two character range lists (representing character sets) in canonical
307
+ // form and merges them.
308
+ // The characters that are only covered by the first set are added to
309
+ // first_set_only_out. the characters that are only in the second set are
310
+ // added to second_set_only_out, and the characters that are in both are
311
+ // added to both_sets_out.
312
+ // The pointers to first_set_only_out, second_set_only_out and both_sets_out
313
+ // should be to empty lists, but they need not be distinct, and may be NULL.
314
+ // If NULL, the characters are dropped, and if two arguments are the same
315
+ // pointer, the result is the union of the two sets that would be created
316
+ // if the pointers had been distinct.
317
+ // This way, the Merge function can compute all the usual set operations:
318
+ // union (all three out-sets are equal), intersection (only both_sets_out is
319
+ // non-NULL), and set difference (only first_set is non-NULL).
320
+ static void Merge(ZoneList<CharacterRange>* first_set,
321
+ ZoneList<CharacterRange>* second_set,
322
+ ZoneList<CharacterRange>* first_set_only_out,
323
+ ZoneList<CharacterRange>* second_set_only_out,
324
+ ZoneList<CharacterRange>* both_sets_out);
325
+ // Negate the contents of a character range in canonical form.
326
+ static void Negate(ZoneList<CharacterRange>* src,
327
+ ZoneList<CharacterRange>* dst);
328
+ static const int kStartMarker = (1 << 24);
329
+ static const int kPayloadMask = (1 << 24) - 1;
330
+
331
+ private:
332
+ uc16 from_;
333
+ uc16 to_;
334
+ };
335
+
336
+
337
+ // A set of unsigned integers that behaves especially well on small
338
+ // integers (< 32). May do zone-allocation.
339
+ class OutSet: public ZoneObject {
340
+ public:
341
+ OutSet() : first_(0), remaining_(NULL), successors_(NULL) { }
342
+ OutSet* Extend(unsigned value);
343
+ bool Get(unsigned value);
344
+ static const unsigned kFirstLimit = 32;
345
+
346
+ private:
347
+ // Destructively set a value in this set. In most cases you want
348
+ // to use Extend instead to ensure that only one instance exists
349
+ // that contains the same values.
350
+ void Set(unsigned value);
351
+
352
+ // The successors are a list of sets that contain the same values
353
+ // as this set and the one more value that is not present in this
354
+ // set.
355
+ ZoneList<OutSet*>* successors() { return successors_; }
356
+
357
+ OutSet(uint32_t first, ZoneList<unsigned>* remaining)
358
+ : first_(first), remaining_(remaining), successors_(NULL) { }
359
+ uint32_t first_;
360
+ ZoneList<unsigned>* remaining_;
361
+ ZoneList<OutSet*>* successors_;
362
+ friend class Trace;
363
+ };
364
+
365
+
366
+ // A mapping from integers, specified as ranges, to a set of integers.
367
+ // Used for mapping character ranges to choices.
368
+ class DispatchTable : public ZoneObject {
369
+ public:
370
+ class Entry {
371
+ public:
372
+ Entry() : from_(0), to_(0), out_set_(NULL) { }
373
+ Entry(uc16 from, uc16 to, OutSet* out_set)
374
+ : from_(from), to_(to), out_set_(out_set) { }
375
+ uc16 from() { return from_; }
376
+ uc16 to() { return to_; }
377
+ void set_to(uc16 value) { to_ = value; }
378
+ void AddValue(int value) { out_set_ = out_set_->Extend(value); }
379
+ OutSet* out_set() { return out_set_; }
380
+ private:
381
+ uc16 from_;
382
+ uc16 to_;
383
+ OutSet* out_set_;
384
+ };
385
+
386
+ class Config {
387
+ public:
388
+ typedef uc16 Key;
389
+ typedef Entry Value;
390
+ static const uc16 kNoKey;
391
+ static const Entry kNoValue;
392
+ static inline int Compare(uc16 a, uc16 b) {
393
+ if (a == b)
394
+ return 0;
395
+ else if (a < b)
396
+ return -1;
397
+ else
398
+ return 1;
399
+ }
400
+ };
401
+
402
+ void AddRange(CharacterRange range, int value);
403
+ OutSet* Get(uc16 value);
404
+ void Dump();
405
+
406
+ template <typename Callback>
407
+ void ForEach(Callback* callback) { return tree()->ForEach(callback); }
408
+ private:
409
+ // There can't be a static empty set since it allocates its
410
+ // successors in a zone and caches them.
411
+ OutSet* empty() { return &empty_; }
412
+ OutSet empty_;
413
+ ZoneSplayTree<Config>* tree() { return &tree_; }
414
+ ZoneSplayTree<Config> tree_;
415
+ };
416
+
417
+
418
+ #define FOR_EACH_NODE_TYPE(VISIT) \
419
+ VISIT(End) \
420
+ VISIT(Action) \
421
+ VISIT(Choice) \
422
+ VISIT(BackReference) \
423
+ VISIT(Assertion) \
424
+ VISIT(Text)
425
+
426
+
427
+ #define FOR_EACH_REG_EXP_TREE_TYPE(VISIT) \
428
+ VISIT(Disjunction) \
429
+ VISIT(Alternative) \
430
+ VISIT(Assertion) \
431
+ VISIT(CharacterClass) \
432
+ VISIT(Atom) \
433
+ VISIT(Quantifier) \
434
+ VISIT(Capture) \
435
+ VISIT(Lookahead) \
436
+ VISIT(BackReference) \
437
+ VISIT(Empty) \
438
+ VISIT(Text)
439
+
440
+
441
+ #define FORWARD_DECLARE(Name) class RegExp##Name;
442
+ FOR_EACH_REG_EXP_TREE_TYPE(FORWARD_DECLARE)
443
+ #undef FORWARD_DECLARE
444
+
445
+
446
+ class TextElement {
447
+ public:
448
+ enum Type {UNINITIALIZED, ATOM, CHAR_CLASS};
449
+ TextElement() : type(UNINITIALIZED) { }
450
+ explicit TextElement(Type t) : type(t), cp_offset(-1) { }
451
+ static TextElement Atom(RegExpAtom* atom);
452
+ static TextElement CharClass(RegExpCharacterClass* char_class);
453
+ int length();
454
+ Type type;
455
+ union {
456
+ RegExpAtom* u_atom;
457
+ RegExpCharacterClass* u_char_class;
458
+ } data;
459
+ int cp_offset;
460
+ };
461
+
462
+
463
+ class Trace;
464
+
465
+
466
+ struct NodeInfo {
467
+ NodeInfo()
468
+ : being_analyzed(false),
469
+ been_analyzed(false),
470
+ follows_word_interest(false),
471
+ follows_newline_interest(false),
472
+ follows_start_interest(false),
473
+ at_end(false),
474
+ visited(false) { }
475
+
476
+ // Returns true if the interests and assumptions of this node
477
+ // matches the given one.
478
+ bool Matches(NodeInfo* that) {
479
+ return (at_end == that->at_end) &&
480
+ (follows_word_interest == that->follows_word_interest) &&
481
+ (follows_newline_interest == that->follows_newline_interest) &&
482
+ (follows_start_interest == that->follows_start_interest);
483
+ }
484
+
485
+ // Updates the interests of this node given the interests of the
486
+ // node preceding it.
487
+ void AddFromPreceding(NodeInfo* that) {
488
+ at_end |= that->at_end;
489
+ follows_word_interest |= that->follows_word_interest;
490
+ follows_newline_interest |= that->follows_newline_interest;
491
+ follows_start_interest |= that->follows_start_interest;
492
+ }
493
+
494
+ bool HasLookbehind() {
495
+ return follows_word_interest ||
496
+ follows_newline_interest ||
497
+ follows_start_interest;
498
+ }
499
+
500
+ // Sets the interests of this node to include the interests of the
501
+ // following node.
502
+ void AddFromFollowing(NodeInfo* that) {
503
+ follows_word_interest |= that->follows_word_interest;
504
+ follows_newline_interest |= that->follows_newline_interest;
505
+ follows_start_interest |= that->follows_start_interest;
506
+ }
507
+
508
+ void ResetCompilationState() {
509
+ being_analyzed = false;
510
+ been_analyzed = false;
511
+ }
512
+
513
+ bool being_analyzed: 1;
514
+ bool been_analyzed: 1;
515
+
516
+ // These bits are set of this node has to know what the preceding
517
+ // character was.
518
+ bool follows_word_interest: 1;
519
+ bool follows_newline_interest: 1;
520
+ bool follows_start_interest: 1;
521
+
522
+ bool at_end: 1;
523
+ bool visited: 1;
524
+ };
525
+
526
+
527
+ class SiblingList {
528
+ public:
529
+ SiblingList() : list_(NULL) { }
530
+ int length() {
531
+ return list_ == NULL ? 0 : list_->length();
532
+ }
533
+ void Ensure(RegExpNode* parent) {
534
+ if (list_ == NULL) {
535
+ list_ = new ZoneList<RegExpNode*>(2);
536
+ list_->Add(parent);
537
+ }
538
+ }
539
+ void Add(RegExpNode* node) { list_->Add(node); }
540
+ RegExpNode* Get(int index) { return list_->at(index); }
541
+ private:
542
+ ZoneList<RegExpNode*>* list_;
543
+ };
544
+
545
+
546
+ // Details of a quick mask-compare check that can look ahead in the
547
+ // input stream.
548
+ class QuickCheckDetails {
549
+ public:
550
+ QuickCheckDetails()
551
+ : characters_(0),
552
+ mask_(0),
553
+ value_(0),
554
+ cannot_match_(false) { }
555
+ explicit QuickCheckDetails(int characters)
556
+ : characters_(characters),
557
+ mask_(0),
558
+ value_(0),
559
+ cannot_match_(false) { }
560
+ bool Rationalize(bool ascii);
561
+ // Merge in the information from another branch of an alternation.
562
+ void Merge(QuickCheckDetails* other, int from_index);
563
+ // Advance the current position by some amount.
564
+ void Advance(int by, bool ascii);
565
+ void Clear();
566
+ bool cannot_match() { return cannot_match_; }
567
+ void set_cannot_match() { cannot_match_ = true; }
568
+ struct Position {
569
+ Position() : mask(0), value(0), determines_perfectly(false) { }
570
+ uc16 mask;
571
+ uc16 value;
572
+ bool determines_perfectly;
573
+ };
574
+ int characters() { return characters_; }
575
+ void set_characters(int characters) { characters_ = characters; }
576
+ Position* positions(int index) {
577
+ ASSERT(index >= 0);
578
+ ASSERT(index < characters_);
579
+ return positions_ + index;
580
+ }
581
+ uint32_t mask() { return mask_; }
582
+ uint32_t value() { return value_; }
583
+
584
+ private:
585
+ // How many characters do we have quick check information from. This is
586
+ // the same for all branches of a choice node.
587
+ int characters_;
588
+ Position positions_[4];
589
+ // These values are the condensate of the above array after Rationalize().
590
+ uint32_t mask_;
591
+ uint32_t value_;
592
+ // If set to true, there is no way this quick check can match at all.
593
+ // E.g., if it requires to be at the start of the input, and isn't.
594
+ bool cannot_match_;
595
+ };
596
+
597
+
598
+ class RegExpNode: public ZoneObject {
599
+ public:
600
+ RegExpNode() : first_character_set_(NULL), trace_count_(0) { }
601
+ virtual ~RegExpNode();
602
+ virtual void Accept(NodeVisitor* visitor) = 0;
603
+ // Generates a goto to this node or actually generates the code at this point.
604
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace) = 0;
605
+ // How many characters must this node consume at a minimum in order to
606
+ // succeed. If we have found at least 'still_to_find' characters that
607
+ // must be consumed there is no need to ask any following nodes whether
608
+ // they are sure to eat any more characters. The not_at_start argument is
609
+ // used to indicate that we know we are not at the start of the input. In
610
+ // this case anchored branches will always fail and can be ignored when
611
+ // determining how many characters are consumed on success.
612
+ virtual int EatsAtLeast(int still_to_find,
613
+ int recursion_depth,
614
+ bool not_at_start) = 0;
615
+ // Emits some quick code that checks whether the preloaded characters match.
616
+ // Falls through on certain failure, jumps to the label on possible success.
617
+ // If the node cannot make a quick check it does nothing and returns false.
618
+ bool EmitQuickCheck(RegExpCompiler* compiler,
619
+ Trace* trace,
620
+ bool preload_has_checked_bounds,
621
+ Label* on_possible_success,
622
+ QuickCheckDetails* details_return,
623
+ bool fall_through_on_failure);
624
+ // For a given number of characters this returns a mask and a value. The
625
+ // next n characters are anded with the mask and compared with the value.
626
+ // A comparison failure indicates the node cannot match the next n characters.
627
+ // A comparison success indicates the node may match.
628
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
629
+ RegExpCompiler* compiler,
630
+ int characters_filled_in,
631
+ bool not_at_start) = 0;
632
+ static const int kNodeIsTooComplexForGreedyLoops = -1;
633
+ virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
634
+ Label* label() { return &label_; }
635
+ // If non-generic code is generated for a node (ie the node is not at the
636
+ // start of the trace) then it cannot be reused. This variable sets a limit
637
+ // on how often we allow that to happen before we insist on starting a new
638
+ // trace and generating generic code for a node that can be reused by flushing
639
+ // the deferred actions in the current trace and generating a goto.
640
+ static const int kMaxCopiesCodeGenerated = 10;
641
+
642
+ NodeInfo* info() { return &info_; }
643
+
644
+ void AddSibling(RegExpNode* node) { siblings_.Add(node); }
645
+
646
+ // Static version of EnsureSibling that expresses the fact that the
647
+ // result has the same type as the input.
648
+ template <class C>
649
+ static C* EnsureSibling(C* node, NodeInfo* info, bool* cloned) {
650
+ return static_cast<C*>(node->EnsureSibling(info, cloned));
651
+ }
652
+
653
+ SiblingList* siblings() { return &siblings_; }
654
+ void set_siblings(SiblingList* other) { siblings_ = *other; }
655
+
656
+ // Return the set of possible next characters recognized by the regexp
657
+ // (or a safe subset, potentially the set of all characters).
658
+ ZoneList<CharacterRange>* FirstCharacterSet();
659
+
660
+ // Compute (if possible within the budget of traversed nodes) the
661
+ // possible first characters of the input matched by this node and
662
+ // its continuation. Returns the remaining budget after the computation.
663
+ // If the budget is spent, the result is negative, and the cached
664
+ // first_character_set_ value isn't set.
665
+ virtual int ComputeFirstCharacterSet(int budget);
666
+
667
+ // Get and set the cached first character set value.
668
+ ZoneList<CharacterRange>* first_character_set() {
669
+ return first_character_set_;
670
+ }
671
+ void set_first_character_set(ZoneList<CharacterRange>* character_set) {
672
+ first_character_set_ = character_set;
673
+ }
674
+
675
+ protected:
676
+ enum LimitResult { DONE, CONTINUE };
677
+ static const int kComputeFirstCharacterSetFail = -1;
678
+
679
+ LimitResult LimitVersions(RegExpCompiler* compiler, Trace* trace);
680
+
681
+ // Returns a sibling of this node whose interests and assumptions
682
+ // match the ones in the given node info. If no sibling exists NULL
683
+ // is returned.
684
+ RegExpNode* TryGetSibling(NodeInfo* info);
685
+
686
+ // Returns a sibling of this node whose interests match the ones in
687
+ // the given node info. The info must not contain any assertions.
688
+ // If no node exists a new one will be created by cloning the current
689
+ // node. The result will always be an instance of the same concrete
690
+ // class as this node.
691
+ RegExpNode* EnsureSibling(NodeInfo* info, bool* cloned);
692
+
693
+ // Returns a clone of this node initialized using the copy constructor
694
+ // of its concrete class. Note that the node may have to be pre-
695
+ // processed before it is on a usable state.
696
+ virtual RegExpNode* Clone() = 0;
697
+
698
+ private:
699
+ static const int kFirstCharBudget = 10;
700
+ Label label_;
701
+ NodeInfo info_;
702
+ SiblingList siblings_;
703
+ ZoneList<CharacterRange>* first_character_set_;
704
+ // This variable keeps track of how many times code has been generated for
705
+ // this node (in different traces). We don't keep track of where the
706
+ // generated code is located unless the code is generated at the start of
707
+ // a trace, in which case it is generic and can be reused by flushing the
708
+ // deferred operations in the current trace and generating a goto.
709
+ int trace_count_;
710
+ };
711
+
712
+
713
+ // A simple closed interval.
714
+ class Interval {
715
+ public:
716
+ Interval() : from_(kNone), to_(kNone) { }
717
+ Interval(int from, int to) : from_(from), to_(to) { }
718
+ Interval Union(Interval that) {
719
+ if (that.from_ == kNone)
720
+ return *this;
721
+ else if (from_ == kNone)
722
+ return that;
723
+ else
724
+ return Interval(Min(from_, that.from_), Max(to_, that.to_));
725
+ }
726
+ bool Contains(int value) {
727
+ return (from_ <= value) && (value <= to_);
728
+ }
729
+ bool is_empty() { return from_ == kNone; }
730
+ int from() { return from_; }
731
+ int to() { return to_; }
732
+ static Interval Empty() { return Interval(); }
733
+ static const int kNone = -1;
734
+ private:
735
+ int from_;
736
+ int to_;
737
+ };
738
+
739
+
740
+ class SeqRegExpNode: public RegExpNode {
741
+ public:
742
+ explicit SeqRegExpNode(RegExpNode* on_success)
743
+ : on_success_(on_success) { }
744
+ RegExpNode* on_success() { return on_success_; }
745
+ void set_on_success(RegExpNode* node) { on_success_ = node; }
746
+ private:
747
+ RegExpNode* on_success_;
748
+ };
749
+
750
+
751
+ class ActionNode: public SeqRegExpNode {
752
+ public:
753
+ enum Type {
754
+ SET_REGISTER,
755
+ INCREMENT_REGISTER,
756
+ STORE_POSITION,
757
+ BEGIN_SUBMATCH,
758
+ POSITIVE_SUBMATCH_SUCCESS,
759
+ EMPTY_MATCH_CHECK,
760
+ CLEAR_CAPTURES
761
+ };
762
+ static ActionNode* SetRegister(int reg, int val, RegExpNode* on_success);
763
+ static ActionNode* IncrementRegister(int reg, RegExpNode* on_success);
764
+ static ActionNode* StorePosition(int reg,
765
+ bool is_capture,
766
+ RegExpNode* on_success);
767
+ static ActionNode* ClearCaptures(Interval range, RegExpNode* on_success);
768
+ static ActionNode* BeginSubmatch(int stack_pointer_reg,
769
+ int position_reg,
770
+ RegExpNode* on_success);
771
+ static ActionNode* PositiveSubmatchSuccess(int stack_pointer_reg,
772
+ int restore_reg,
773
+ int clear_capture_count,
774
+ int clear_capture_from,
775
+ RegExpNode* on_success);
776
+ static ActionNode* EmptyMatchCheck(int start_register,
777
+ int repetition_register,
778
+ int repetition_limit,
779
+ RegExpNode* on_success);
780
+ virtual void Accept(NodeVisitor* visitor);
781
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
782
+ virtual int EatsAtLeast(int still_to_find,
783
+ int recursion_depth,
784
+ bool not_at_start);
785
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
786
+ RegExpCompiler* compiler,
787
+ int filled_in,
788
+ bool not_at_start) {
789
+ return on_success()->GetQuickCheckDetails(
790
+ details, compiler, filled_in, not_at_start);
791
+ }
792
+ Type type() { return type_; }
793
+ // TODO(erikcorry): We should allow some action nodes in greedy loops.
794
+ virtual int GreedyLoopTextLength() { return kNodeIsTooComplexForGreedyLoops; }
795
+ virtual ActionNode* Clone() { return new ActionNode(*this); }
796
+ virtual int ComputeFirstCharacterSet(int budget);
797
+ private:
798
+ union {
799
+ struct {
800
+ int reg;
801
+ int value;
802
+ } u_store_register;
803
+ struct {
804
+ int reg;
805
+ } u_increment_register;
806
+ struct {
807
+ int reg;
808
+ bool is_capture;
809
+ } u_position_register;
810
+ struct {
811
+ int stack_pointer_register;
812
+ int current_position_register;
813
+ int clear_register_count;
814
+ int clear_register_from;
815
+ } u_submatch;
816
+ struct {
817
+ int start_register;
818
+ int repetition_register;
819
+ int repetition_limit;
820
+ } u_empty_match_check;
821
+ struct {
822
+ int range_from;
823
+ int range_to;
824
+ } u_clear_captures;
825
+ } data_;
826
+ ActionNode(Type type, RegExpNode* on_success)
827
+ : SeqRegExpNode(on_success),
828
+ type_(type) { }
829
+ Type type_;
830
+ friend class DotPrinter;
831
+ };
832
+
833
+
834
+ class TextNode: public SeqRegExpNode {
835
+ public:
836
+ TextNode(ZoneList<TextElement>* elms,
837
+ RegExpNode* on_success)
838
+ : SeqRegExpNode(on_success),
839
+ elms_(elms) { }
840
+ TextNode(RegExpCharacterClass* that,
841
+ RegExpNode* on_success)
842
+ : SeqRegExpNode(on_success),
843
+ elms_(new ZoneList<TextElement>(1)) {
844
+ elms_->Add(TextElement::CharClass(that));
845
+ }
846
+ virtual void Accept(NodeVisitor* visitor);
847
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
848
+ virtual int EatsAtLeast(int still_to_find,
849
+ int recursion_depth,
850
+ bool not_at_start);
851
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
852
+ RegExpCompiler* compiler,
853
+ int characters_filled_in,
854
+ bool not_at_start);
855
+ ZoneList<TextElement>* elements() { return elms_; }
856
+ void MakeCaseIndependent(bool is_ascii);
857
+ virtual int GreedyLoopTextLength();
858
+ virtual TextNode* Clone() {
859
+ TextNode* result = new TextNode(*this);
860
+ result->CalculateOffsets();
861
+ return result;
862
+ }
863
+ void CalculateOffsets();
864
+ virtual int ComputeFirstCharacterSet(int budget);
865
+ private:
866
+ enum TextEmitPassType {
867
+ NON_ASCII_MATCH, // Check for characters that can't match.
868
+ SIMPLE_CHARACTER_MATCH, // Case-dependent single character check.
869
+ NON_LETTER_CHARACTER_MATCH, // Check characters that have no case equivs.
870
+ CASE_CHARACTER_MATCH, // Case-independent single character check.
871
+ CHARACTER_CLASS_MATCH // Character class.
872
+ };
873
+ static bool SkipPass(int pass, bool ignore_case);
874
+ static const int kFirstRealPass = SIMPLE_CHARACTER_MATCH;
875
+ static const int kLastPass = CHARACTER_CLASS_MATCH;
876
+ void TextEmitPass(RegExpCompiler* compiler,
877
+ TextEmitPassType pass,
878
+ bool preloaded,
879
+ Trace* trace,
880
+ bool first_element_checked,
881
+ int* checked_up_to);
882
+ int Length();
883
+ ZoneList<TextElement>* elms_;
884
+ };
885
+
886
+
887
+ class AssertionNode: public SeqRegExpNode {
888
+ public:
889
+ enum AssertionNodeType {
890
+ AT_END,
891
+ AT_START,
892
+ AT_BOUNDARY,
893
+ AT_NON_BOUNDARY,
894
+ AFTER_NEWLINE,
895
+ // Types not directly expressible in regexp syntax.
896
+ // Used for modifying a boundary node if its following character is
897
+ // known to be word and/or non-word.
898
+ AFTER_NONWORD_CHARACTER,
899
+ AFTER_WORD_CHARACTER
900
+ };
901
+ static AssertionNode* AtEnd(RegExpNode* on_success) {
902
+ return new AssertionNode(AT_END, on_success);
903
+ }
904
+ static AssertionNode* AtStart(RegExpNode* on_success) {
905
+ return new AssertionNode(AT_START, on_success);
906
+ }
907
+ static AssertionNode* AtBoundary(RegExpNode* on_success) {
908
+ return new AssertionNode(AT_BOUNDARY, on_success);
909
+ }
910
+ static AssertionNode* AtNonBoundary(RegExpNode* on_success) {
911
+ return new AssertionNode(AT_NON_BOUNDARY, on_success);
912
+ }
913
+ static AssertionNode* AfterNewline(RegExpNode* on_success) {
914
+ return new AssertionNode(AFTER_NEWLINE, on_success);
915
+ }
916
+ virtual void Accept(NodeVisitor* visitor);
917
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
918
+ virtual int EatsAtLeast(int still_to_find,
919
+ int recursion_depth,
920
+ bool not_at_start);
921
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
922
+ RegExpCompiler* compiler,
923
+ int filled_in,
924
+ bool not_at_start);
925
+ virtual int ComputeFirstCharacterSet(int budget);
926
+ virtual AssertionNode* Clone() { return new AssertionNode(*this); }
927
+ AssertionNodeType type() { return type_; }
928
+ void set_type(AssertionNodeType type) { type_ = type; }
929
+ private:
930
+ AssertionNode(AssertionNodeType t, RegExpNode* on_success)
931
+ : SeqRegExpNode(on_success), type_(t) { }
932
+ AssertionNodeType type_;
933
+ };
934
+
935
+
936
+ class BackReferenceNode: public SeqRegExpNode {
937
+ public:
938
+ BackReferenceNode(int start_reg,
939
+ int end_reg,
940
+ RegExpNode* on_success)
941
+ : SeqRegExpNode(on_success),
942
+ start_reg_(start_reg),
943
+ end_reg_(end_reg) { }
944
+ virtual void Accept(NodeVisitor* visitor);
945
+ int start_register() { return start_reg_; }
946
+ int end_register() { return end_reg_; }
947
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
948
+ virtual int EatsAtLeast(int still_to_find,
949
+ int recursion_depth,
950
+ bool not_at_start);
951
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
952
+ RegExpCompiler* compiler,
953
+ int characters_filled_in,
954
+ bool not_at_start) {
955
+ return;
956
+ }
957
+ virtual BackReferenceNode* Clone() { return new BackReferenceNode(*this); }
958
+ virtual int ComputeFirstCharacterSet(int budget);
959
+ private:
960
+ int start_reg_;
961
+ int end_reg_;
962
+ };
963
+
964
+
965
+ class EndNode: public RegExpNode {
966
+ public:
967
+ enum Action { ACCEPT, BACKTRACK, NEGATIVE_SUBMATCH_SUCCESS };
968
+ explicit EndNode(Action action) : action_(action) { }
969
+ virtual void Accept(NodeVisitor* visitor);
970
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
971
+ virtual int EatsAtLeast(int still_to_find,
972
+ int recursion_depth,
973
+ bool not_at_start) { return 0; }
974
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
975
+ RegExpCompiler* compiler,
976
+ int characters_filled_in,
977
+ bool not_at_start) {
978
+ // Returning 0 from EatsAtLeast should ensure we never get here.
979
+ UNREACHABLE();
980
+ }
981
+ virtual EndNode* Clone() { return new EndNode(*this); }
982
+ private:
983
+ Action action_;
984
+ };
985
+
986
+
987
+ class NegativeSubmatchSuccess: public EndNode {
988
+ public:
989
+ NegativeSubmatchSuccess(int stack_pointer_reg,
990
+ int position_reg,
991
+ int clear_capture_count,
992
+ int clear_capture_start)
993
+ : EndNode(NEGATIVE_SUBMATCH_SUCCESS),
994
+ stack_pointer_register_(stack_pointer_reg),
995
+ current_position_register_(position_reg),
996
+ clear_capture_count_(clear_capture_count),
997
+ clear_capture_start_(clear_capture_start) { }
998
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
999
+
1000
+ private:
1001
+ int stack_pointer_register_;
1002
+ int current_position_register_;
1003
+ int clear_capture_count_;
1004
+ int clear_capture_start_;
1005
+ };
1006
+
1007
+
1008
+ class Guard: public ZoneObject {
1009
+ public:
1010
+ enum Relation { LT, GEQ };
1011
+ Guard(int reg, Relation op, int value)
1012
+ : reg_(reg),
1013
+ op_(op),
1014
+ value_(value) { }
1015
+ int reg() { return reg_; }
1016
+ Relation op() { return op_; }
1017
+ int value() { return value_; }
1018
+
1019
+ private:
1020
+ int reg_;
1021
+ Relation op_;
1022
+ int value_;
1023
+ };
1024
+
1025
+
1026
+ class GuardedAlternative {
1027
+ public:
1028
+ explicit GuardedAlternative(RegExpNode* node) : node_(node), guards_(NULL) { }
1029
+ void AddGuard(Guard* guard);
1030
+ RegExpNode* node() { return node_; }
1031
+ void set_node(RegExpNode* node) { node_ = node; }
1032
+ ZoneList<Guard*>* guards() { return guards_; }
1033
+
1034
+ private:
1035
+ RegExpNode* node_;
1036
+ ZoneList<Guard*>* guards_;
1037
+ };
1038
+
1039
+
1040
+ class AlternativeGeneration;
1041
+
1042
+
1043
+ class ChoiceNode: public RegExpNode {
1044
+ public:
1045
+ explicit ChoiceNode(int expected_size)
1046
+ : alternatives_(new ZoneList<GuardedAlternative>(expected_size)),
1047
+ table_(NULL),
1048
+ not_at_start_(false),
1049
+ being_calculated_(false) { }
1050
+ virtual void Accept(NodeVisitor* visitor);
1051
+ void AddAlternative(GuardedAlternative node) { alternatives()->Add(node); }
1052
+ ZoneList<GuardedAlternative>* alternatives() { return alternatives_; }
1053
+ DispatchTable* GetTable(bool ignore_case);
1054
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
1055
+ virtual int EatsAtLeast(int still_to_find,
1056
+ int recursion_depth,
1057
+ bool not_at_start);
1058
+ int EatsAtLeastHelper(int still_to_find,
1059
+ int recursion_depth,
1060
+ RegExpNode* ignore_this_node,
1061
+ bool not_at_start);
1062
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1063
+ RegExpCompiler* compiler,
1064
+ int characters_filled_in,
1065
+ bool not_at_start);
1066
+ virtual ChoiceNode* Clone() { return new ChoiceNode(*this); }
1067
+
1068
+ bool being_calculated() { return being_calculated_; }
1069
+ bool not_at_start() { return not_at_start_; }
1070
+ void set_not_at_start() { not_at_start_ = true; }
1071
+ void set_being_calculated(bool b) { being_calculated_ = b; }
1072
+ virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
1073
+
1074
+ protected:
1075
+ int GreedyLoopTextLength(GuardedAlternative* alternative);
1076
+ ZoneList<GuardedAlternative>* alternatives_;
1077
+
1078
+ private:
1079
+ friend class DispatchTableConstructor;
1080
+ friend class Analysis;
1081
+ void GenerateGuard(RegExpMacroAssembler* macro_assembler,
1082
+ Guard* guard,
1083
+ Trace* trace);
1084
+ int CalculatePreloadCharacters(RegExpCompiler* compiler, bool not_at_start);
1085
+ void EmitOutOfLineContinuation(RegExpCompiler* compiler,
1086
+ Trace* trace,
1087
+ GuardedAlternative alternative,
1088
+ AlternativeGeneration* alt_gen,
1089
+ int preload_characters,
1090
+ bool next_expects_preload);
1091
+ DispatchTable* table_;
1092
+ // If true, this node is never checked at the start of the input.
1093
+ // Allows a new trace to start with at_start() set to false.
1094
+ bool not_at_start_;
1095
+ bool being_calculated_;
1096
+ };
1097
+
1098
+
1099
+ class NegativeLookaheadChoiceNode: public ChoiceNode {
1100
+ public:
1101
+ explicit NegativeLookaheadChoiceNode(GuardedAlternative this_must_fail,
1102
+ GuardedAlternative then_do_this)
1103
+ : ChoiceNode(2) {
1104
+ AddAlternative(this_must_fail);
1105
+ AddAlternative(then_do_this);
1106
+ }
1107
+ virtual int EatsAtLeast(int still_to_find,
1108
+ int recursion_depth,
1109
+ bool not_at_start);
1110
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1111
+ RegExpCompiler* compiler,
1112
+ int characters_filled_in,
1113
+ bool not_at_start);
1114
+ // For a negative lookahead we don't emit the quick check for the
1115
+ // alternative that is expected to fail. This is because quick check code
1116
+ // starts by loading enough characters for the alternative that takes fewest
1117
+ // characters, but on a negative lookahead the negative branch did not take
1118
+ // part in that calculation (EatsAtLeast) so the assumptions don't hold.
1119
+ virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; }
1120
+ virtual int ComputeFirstCharacterSet(int budget);
1121
+ };
1122
+
1123
+
1124
+ class LoopChoiceNode: public ChoiceNode {
1125
+ public:
1126
+ explicit LoopChoiceNode(bool body_can_be_zero_length)
1127
+ : ChoiceNode(2),
1128
+ loop_node_(NULL),
1129
+ continue_node_(NULL),
1130
+ body_can_be_zero_length_(body_can_be_zero_length) { }
1131
+ void AddLoopAlternative(GuardedAlternative alt);
1132
+ void AddContinueAlternative(GuardedAlternative alt);
1133
+ virtual void Emit(RegExpCompiler* compiler, Trace* trace);
1134
+ virtual int EatsAtLeast(int still_to_find,
1135
+ int recursion_depth,
1136
+ bool not_at_start);
1137
+ virtual void GetQuickCheckDetails(QuickCheckDetails* details,
1138
+ RegExpCompiler* compiler,
1139
+ int characters_filled_in,
1140
+ bool not_at_start);
1141
+ virtual int ComputeFirstCharacterSet(int budget);
1142
+ virtual LoopChoiceNode* Clone() { return new LoopChoiceNode(*this); }
1143
+ RegExpNode* loop_node() { return loop_node_; }
1144
+ RegExpNode* continue_node() { return continue_node_; }
1145
+ bool body_can_be_zero_length() { return body_can_be_zero_length_; }
1146
+ virtual void Accept(NodeVisitor* visitor);
1147
+
1148
+ private:
1149
+ // AddAlternative is made private for loop nodes because alternatives
1150
+ // should not be added freely, we need to keep track of which node
1151
+ // goes back to the node itself.
1152
+ void AddAlternative(GuardedAlternative node) {
1153
+ ChoiceNode::AddAlternative(node);
1154
+ }
1155
+
1156
+ RegExpNode* loop_node_;
1157
+ RegExpNode* continue_node_;
1158
+ bool body_can_be_zero_length_;
1159
+ };
1160
+
1161
+
1162
+ // There are many ways to generate code for a node. This class encapsulates
1163
+ // the current way we should be generating. In other words it encapsulates
1164
+ // the current state of the code generator. The effect of this is that we
1165
+ // generate code for paths that the matcher can take through the regular
1166
+ // expression. A given node in the regexp can be code-generated several times
1167
+ // as it can be part of several traces. For example for the regexp:
1168
+ // /foo(bar|ip)baz/ the code to match baz will be generated twice, once as part
1169
+ // of the foo-bar-baz trace and once as part of the foo-ip-baz trace. The code
1170
+ // to match foo is generated only once (the traces have a common prefix). The
1171
+ // code to store the capture is deferred and generated (twice) after the places
1172
+ // where baz has been matched.
1173
+ class Trace {
1174
+ public:
1175
+ // A value for a property that is either known to be true, know to be false,
1176
+ // or not known.
1177
+ enum TriBool {
1178
+ UNKNOWN = -1, FALSE = 0, TRUE = 1
1179
+ };
1180
+
1181
+ class DeferredAction {
1182
+ public:
1183
+ DeferredAction(ActionNode::Type type, int reg)
1184
+ : type_(type), reg_(reg), next_(NULL) { }
1185
+ DeferredAction* next() { return next_; }
1186
+ bool Mentions(int reg);
1187
+ int reg() { return reg_; }
1188
+ ActionNode::Type type() { return type_; }
1189
+ private:
1190
+ ActionNode::Type type_;
1191
+ int reg_;
1192
+ DeferredAction* next_;
1193
+ friend class Trace;
1194
+ };
1195
+
1196
+ class DeferredCapture : public DeferredAction {
1197
+ public:
1198
+ DeferredCapture(int reg, bool is_capture, Trace* trace)
1199
+ : DeferredAction(ActionNode::STORE_POSITION, reg),
1200
+ cp_offset_(trace->cp_offset()),
1201
+ is_capture_(is_capture) { }
1202
+ int cp_offset() { return cp_offset_; }
1203
+ bool is_capture() { return is_capture_; }
1204
+ private:
1205
+ int cp_offset_;
1206
+ bool is_capture_;
1207
+ void set_cp_offset(int cp_offset) { cp_offset_ = cp_offset; }
1208
+ };
1209
+
1210
+ class DeferredSetRegister : public DeferredAction {
1211
+ public:
1212
+ DeferredSetRegister(int reg, int value)
1213
+ : DeferredAction(ActionNode::SET_REGISTER, reg),
1214
+ value_(value) { }
1215
+ int value() { return value_; }
1216
+ private:
1217
+ int value_;
1218
+ };
1219
+
1220
+ class DeferredClearCaptures : public DeferredAction {
1221
+ public:
1222
+ explicit DeferredClearCaptures(Interval range)
1223
+ : DeferredAction(ActionNode::CLEAR_CAPTURES, -1),
1224
+ range_(range) { }
1225
+ Interval range() { return range_; }
1226
+ private:
1227
+ Interval range_;
1228
+ };
1229
+
1230
+ class DeferredIncrementRegister : public DeferredAction {
1231
+ public:
1232
+ explicit DeferredIncrementRegister(int reg)
1233
+ : DeferredAction(ActionNode::INCREMENT_REGISTER, reg) { }
1234
+ };
1235
+
1236
+ Trace()
1237
+ : cp_offset_(0),
1238
+ actions_(NULL),
1239
+ backtrack_(NULL),
1240
+ stop_node_(NULL),
1241
+ loop_label_(NULL),
1242
+ characters_preloaded_(0),
1243
+ bound_checked_up_to_(0),
1244
+ flush_budget_(100),
1245
+ at_start_(UNKNOWN) { }
1246
+
1247
+ // End the trace. This involves flushing the deferred actions in the trace
1248
+ // and pushing a backtrack location onto the backtrack stack. Once this is
1249
+ // done we can start a new trace or go to one that has already been
1250
+ // generated.
1251
+ void Flush(RegExpCompiler* compiler, RegExpNode* successor);
1252
+ int cp_offset() { return cp_offset_; }
1253
+ DeferredAction* actions() { return actions_; }
1254
+ // A trivial trace is one that has no deferred actions or other state that
1255
+ // affects the assumptions used when generating code. There is no recorded
1256
+ // backtrack location in a trivial trace, so with a trivial trace we will
1257
+ // generate code that, on a failure to match, gets the backtrack location
1258
+ // from the backtrack stack rather than using a direct jump instruction. We
1259
+ // always start code generation with a trivial trace and non-trivial traces
1260
+ // are created as we emit code for nodes or add to the list of deferred
1261
+ // actions in the trace. The location of the code generated for a node using
1262
+ // a trivial trace is recorded in a label in the node so that gotos can be
1263
+ // generated to that code.
1264
+ bool is_trivial() {
1265
+ return backtrack_ == NULL &&
1266
+ actions_ == NULL &&
1267
+ cp_offset_ == 0 &&
1268
+ characters_preloaded_ == 0 &&
1269
+ bound_checked_up_to_ == 0 &&
1270
+ quick_check_performed_.characters() == 0 &&
1271
+ at_start_ == UNKNOWN;
1272
+ }
1273
+ TriBool at_start() { return at_start_; }
1274
+ void set_at_start(bool at_start) { at_start_ = at_start ? TRUE : FALSE; }
1275
+ Label* backtrack() { return backtrack_; }
1276
+ Label* loop_label() { return loop_label_; }
1277
+ RegExpNode* stop_node() { return stop_node_; }
1278
+ int characters_preloaded() { return characters_preloaded_; }
1279
+ int bound_checked_up_to() { return bound_checked_up_to_; }
1280
+ int flush_budget() { return flush_budget_; }
1281
+ QuickCheckDetails* quick_check_performed() { return &quick_check_performed_; }
1282
+ bool mentions_reg(int reg);
1283
+ // Returns true if a deferred position store exists to the specified
1284
+ // register and stores the offset in the out-parameter. Otherwise
1285
+ // returns false.
1286
+ bool GetStoredPosition(int reg, int* cp_offset);
1287
+ // These set methods and AdvanceCurrentPositionInTrace should be used only on
1288
+ // new traces - the intention is that traces are immutable after creation.
1289
+ void add_action(DeferredAction* new_action) {
1290
+ ASSERT(new_action->next_ == NULL);
1291
+ new_action->next_ = actions_;
1292
+ actions_ = new_action;
1293
+ }
1294
+ void set_backtrack(Label* backtrack) { backtrack_ = backtrack; }
1295
+ void set_stop_node(RegExpNode* node) { stop_node_ = node; }
1296
+ void set_loop_label(Label* label) { loop_label_ = label; }
1297
+ void set_characters_preloaded(int count) { characters_preloaded_ = count; }
1298
+ void set_bound_checked_up_to(int to) { bound_checked_up_to_ = to; }
1299
+ void set_flush_budget(int to) { flush_budget_ = to; }
1300
+ void set_quick_check_performed(QuickCheckDetails* d) {
1301
+ quick_check_performed_ = *d;
1302
+ }
1303
+ void InvalidateCurrentCharacter();
1304
+ void AdvanceCurrentPositionInTrace(int by, RegExpCompiler* compiler);
1305
+ private:
1306
+ int FindAffectedRegisters(OutSet* affected_registers);
1307
+ void PerformDeferredActions(RegExpMacroAssembler* macro,
1308
+ int max_register,
1309
+ OutSet& affected_registers,
1310
+ OutSet* registers_to_pop,
1311
+ OutSet* registers_to_clear);
1312
+ void RestoreAffectedRegisters(RegExpMacroAssembler* macro,
1313
+ int max_register,
1314
+ OutSet& registers_to_pop,
1315
+ OutSet& registers_to_clear);
1316
+ int cp_offset_;
1317
+ DeferredAction* actions_;
1318
+ Label* backtrack_;
1319
+ RegExpNode* stop_node_;
1320
+ Label* loop_label_;
1321
+ int characters_preloaded_;
1322
+ int bound_checked_up_to_;
1323
+ QuickCheckDetails quick_check_performed_;
1324
+ int flush_budget_;
1325
+ TriBool at_start_;
1326
+ };
1327
+
1328
+
1329
+ class NodeVisitor {
1330
+ public:
1331
+ virtual ~NodeVisitor() { }
1332
+ #define DECLARE_VISIT(Type) \
1333
+ virtual void Visit##Type(Type##Node* that) = 0;
1334
+ FOR_EACH_NODE_TYPE(DECLARE_VISIT)
1335
+ #undef DECLARE_VISIT
1336
+ virtual void VisitLoopChoice(LoopChoiceNode* that) { VisitChoice(that); }
1337
+ };
1338
+
1339
+
1340
+ // Node visitor used to add the start set of the alternatives to the
1341
+ // dispatch table of a choice node.
1342
+ class DispatchTableConstructor: public NodeVisitor {
1343
+ public:
1344
+ DispatchTableConstructor(DispatchTable* table, bool ignore_case)
1345
+ : table_(table),
1346
+ choice_index_(-1),
1347
+ ignore_case_(ignore_case) { }
1348
+
1349
+ void BuildTable(ChoiceNode* node);
1350
+
1351
+ void AddRange(CharacterRange range) {
1352
+ table()->AddRange(range, choice_index_);
1353
+ }
1354
+
1355
+ void AddInverse(ZoneList<CharacterRange>* ranges);
1356
+
1357
+ #define DECLARE_VISIT(Type) \
1358
+ virtual void Visit##Type(Type##Node* that);
1359
+ FOR_EACH_NODE_TYPE(DECLARE_VISIT)
1360
+ #undef DECLARE_VISIT
1361
+
1362
+ DispatchTable* table() { return table_; }
1363
+ void set_choice_index(int value) { choice_index_ = value; }
1364
+
1365
+ protected:
1366
+ DispatchTable* table_;
1367
+ int choice_index_;
1368
+ bool ignore_case_;
1369
+ };
1370
+
1371
+
1372
+ // Assertion propagation moves information about assertions such as
1373
+ // \b to the affected nodes. For instance, in /.\b./ information must
1374
+ // be propagated to the first '.' that whatever follows needs to know
1375
+ // if it matched a word or a non-word, and to the second '.' that it
1376
+ // has to check if it succeeds a word or non-word. In this case the
1377
+ // result will be something like:
1378
+ //
1379
+ // +-------+ +------------+
1380
+ // | . | | . |
1381
+ // +-------+ ---> +------------+
1382
+ // | word? | | check word |
1383
+ // +-------+ +------------+
1384
+ class Analysis: public NodeVisitor {
1385
+ public:
1386
+ Analysis(bool ignore_case, bool is_ascii)
1387
+ : ignore_case_(ignore_case),
1388
+ is_ascii_(is_ascii),
1389
+ error_message_(NULL) { }
1390
+ void EnsureAnalyzed(RegExpNode* node);
1391
+
1392
+ #define DECLARE_VISIT(Type) \
1393
+ virtual void Visit##Type(Type##Node* that);
1394
+ FOR_EACH_NODE_TYPE(DECLARE_VISIT)
1395
+ #undef DECLARE_VISIT
1396
+ virtual void VisitLoopChoice(LoopChoiceNode* that);
1397
+
1398
+ bool has_failed() { return error_message_ != NULL; }
1399
+ const char* error_message() {
1400
+ ASSERT(error_message_ != NULL);
1401
+ return error_message_;
1402
+ }
1403
+ void fail(const char* error_message) {
1404
+ error_message_ = error_message;
1405
+ }
1406
+ private:
1407
+ bool ignore_case_;
1408
+ bool is_ascii_;
1409
+ const char* error_message_;
1410
+
1411
+ DISALLOW_IMPLICIT_CONSTRUCTORS(Analysis);
1412
+ };
1413
+
1414
+
1415
+ struct RegExpCompileData {
1416
+ RegExpCompileData()
1417
+ : tree(NULL),
1418
+ node(NULL),
1419
+ simple(true),
1420
+ contains_anchor(false),
1421
+ capture_count(0) { }
1422
+ RegExpTree* tree;
1423
+ RegExpNode* node;
1424
+ bool simple;
1425
+ bool contains_anchor;
1426
+ Handle<String> error;
1427
+ int capture_count;
1428
+ };
1429
+
1430
+
1431
+ class RegExpEngine: public AllStatic {
1432
+ public:
1433
+ struct CompilationResult {
1434
+ explicit CompilationResult(const char* error_message)
1435
+ : error_message(error_message),
1436
+ code(HEAP->the_hole_value()),
1437
+ num_registers(0) {}
1438
+ CompilationResult(Object* code, int registers)
1439
+ : error_message(NULL),
1440
+ code(code),
1441
+ num_registers(registers) {}
1442
+ const char* error_message;
1443
+ Object* code;
1444
+ int num_registers;
1445
+ };
1446
+
1447
+ static CompilationResult Compile(RegExpCompileData* input,
1448
+ bool ignore_case,
1449
+ bool multiline,
1450
+ Handle<String> pattern,
1451
+ bool is_ascii);
1452
+
1453
+ static void DotPrint(const char* label, RegExpNode* node, bool ignore_case);
1454
+ };
1455
+
1456
+
1457
+ class OffsetsVector {
1458
+ public:
1459
+ explicit inline OffsetsVector(int num_registers)
1460
+ : offsets_vector_length_(num_registers) {
1461
+ if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
1462
+ vector_ = NewArray<int>(offsets_vector_length_);
1463
+ } else {
1464
+ vector_ = Isolate::Current()->jsregexp_static_offsets_vector();
1465
+ }
1466
+ }
1467
+ inline ~OffsetsVector() {
1468
+ if (offsets_vector_length_ > Isolate::kJSRegexpStaticOffsetsVectorSize) {
1469
+ DeleteArray(vector_);
1470
+ vector_ = NULL;
1471
+ }
1472
+ }
1473
+ inline int* vector() { return vector_; }
1474
+ inline int length() { return offsets_vector_length_; }
1475
+
1476
+ static const int kStaticOffsetsVectorSize = 50;
1477
+
1478
+ private:
1479
+ static Address static_offsets_vector_address(Isolate* isolate) {
1480
+ return reinterpret_cast<Address>(isolate->jsregexp_static_offsets_vector());
1481
+ }
1482
+
1483
+ int* vector_;
1484
+ int offsets_vector_length_;
1485
+
1486
+ friend class ExternalReference;
1487
+ };
1488
+
1489
+
1490
+ } } // namespace v8::internal
1491
+
1492
+ #endif // V8_JSREGEXP_H_