mustang 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (560) hide show
  1. data/.rspec +1 -0
  2. data/Isolate +9 -0
  3. data/README.md +6 -12
  4. data/Rakefile +30 -4
  5. data/TODO.md +9 -0
  6. data/ext/v8/extconf.rb +56 -0
  7. data/ext/v8/v8.cpp +37 -0
  8. data/ext/v8/v8_array.cpp +161 -0
  9. data/ext/v8/v8_array.h +17 -0
  10. data/ext/v8/v8_base.cpp +147 -0
  11. data/ext/v8/v8_base.h +23 -0
  12. data/ext/v8/v8_cast.cpp +151 -0
  13. data/ext/v8/v8_cast.h +64 -0
  14. data/ext/v8/v8_context.cpp +174 -0
  15. data/ext/v8/v8_context.h +12 -0
  16. data/ext/v8/v8_date.cpp +61 -0
  17. data/ext/v8/v8_date.h +16 -0
  18. data/ext/v8/v8_errors.cpp +147 -0
  19. data/ext/v8/v8_errors.h +19 -0
  20. data/ext/v8/v8_external.cpp +66 -0
  21. data/ext/v8/v8_external.h +16 -0
  22. data/ext/v8/v8_function.cpp +182 -0
  23. data/ext/v8/v8_function.h +14 -0
  24. data/ext/v8/v8_integer.cpp +70 -0
  25. data/ext/v8/v8_integer.h +16 -0
  26. data/ext/v8/v8_macros.h +30 -0
  27. data/ext/v8/v8_main.cpp +53 -0
  28. data/ext/v8/v8_main.h +13 -0
  29. data/ext/v8/v8_number.cpp +62 -0
  30. data/ext/v8/v8_number.h +16 -0
  31. data/ext/v8/v8_object.cpp +172 -0
  32. data/ext/v8/v8_object.h +17 -0
  33. data/ext/v8/v8_ref.cpp +72 -0
  34. data/ext/v8/v8_ref.h +43 -0
  35. data/ext/v8/v8_regexp.cpp +148 -0
  36. data/ext/v8/v8_regexp.h +16 -0
  37. data/ext/v8/v8_string.cpp +78 -0
  38. data/ext/v8/v8_string.h +16 -0
  39. data/ext/v8/v8_value.cpp +370 -0
  40. data/ext/v8/v8_value.h +19 -0
  41. data/gemspec.yml +2 -1
  42. data/lib/core_ext/class.rb +14 -0
  43. data/lib/core_ext/object.rb +12 -0
  44. data/lib/core_ext/symbol.rb +23 -0
  45. data/lib/mustang.rb +44 -0
  46. data/lib/mustang/context.rb +69 -0
  47. data/lib/mustang/errors.rb +36 -0
  48. data/lib/support/delegated.rb +25 -0
  49. data/lib/v8/array.rb +21 -0
  50. data/lib/v8/context.rb +13 -0
  51. data/lib/v8/date.rb +20 -0
  52. data/lib/v8/error.rb +15 -0
  53. data/lib/v8/external.rb +16 -0
  54. data/lib/v8/function.rb +11 -0
  55. data/lib/v8/integer.rb +16 -0
  56. data/lib/v8/number.rb +16 -0
  57. data/lib/v8/object.rb +66 -0
  58. data/lib/v8/regexp.rb +23 -0
  59. data/lib/v8/string.rb +27 -0
  60. data/mustang.gemspec +3 -0
  61. data/spec/core_ext/class_spec.rb +19 -0
  62. data/spec/core_ext/object_spec.rb +19 -0
  63. data/spec/core_ext/symbol_spec.rb +27 -0
  64. data/spec/fixtures/test1.js +2 -0
  65. data/spec/fixtures/test2.js +2 -0
  66. data/spec/spec_helper.rb +20 -0
  67. data/spec/v8/array_spec.rb +88 -0
  68. data/spec/v8/cast_spec.rb +151 -0
  69. data/spec/v8/context_spec.rb +78 -0
  70. data/spec/v8/data_spec.rb +39 -0
  71. data/spec/v8/date_spec.rb +45 -0
  72. data/spec/v8/empty_spec.rb +27 -0
  73. data/spec/v8/errors_spec.rb +142 -0
  74. data/spec/v8/external_spec.rb +44 -0
  75. data/spec/v8/function_spec.rb +170 -0
  76. data/spec/v8/integer_spec.rb +41 -0
  77. data/spec/v8/main_spec.rb +18 -0
  78. data/spec/v8/null_spec.rb +27 -0
  79. data/spec/v8/number_spec.rb +40 -0
  80. data/spec/v8/object_spec.rb +79 -0
  81. data/spec/v8/primitive_spec.rb +9 -0
  82. data/spec/v8/regexp_spec.rb +65 -0
  83. data/spec/v8/string_spec.rb +48 -0
  84. data/spec/v8/undefined_spec.rb +27 -0
  85. data/spec/v8/value_spec.rb +215 -0
  86. data/vendor/v8/.gitignore +2 -0
  87. data/vendor/v8/AUTHORS +3 -1
  88. data/vendor/v8/ChangeLog +117 -0
  89. data/vendor/v8/SConstruct +334 -53
  90. data/vendor/v8/include/v8-debug.h +21 -11
  91. data/vendor/v8/include/v8-preparser.h +1 -1
  92. data/vendor/v8/include/v8-profiler.h +122 -43
  93. data/vendor/v8/include/v8-testing.h +5 -0
  94. data/vendor/v8/include/v8.h +171 -17
  95. data/vendor/v8/preparser/SConscript +38 -0
  96. data/vendor/v8/preparser/preparser-process.cc +77 -114
  97. data/vendor/v8/samples/shell.cc +232 -46
  98. data/vendor/v8/src/SConscript +29 -5
  99. data/vendor/v8/src/accessors.cc +70 -211
  100. data/vendor/v8/{test/cctest/test-mips.cc → src/allocation-inl.h} +15 -18
  101. data/vendor/v8/src/allocation.cc +0 -82
  102. data/vendor/v8/src/allocation.h +9 -42
  103. data/vendor/v8/src/api.cc +1645 -1156
  104. data/vendor/v8/src/api.h +76 -12
  105. data/vendor/v8/src/apiutils.h +0 -7
  106. data/vendor/v8/src/arguments.h +15 -4
  107. data/vendor/v8/src/arm/assembler-arm-inl.h +10 -9
  108. data/vendor/v8/src/arm/assembler-arm.cc +62 -23
  109. data/vendor/v8/src/arm/assembler-arm.h +76 -11
  110. data/vendor/v8/src/arm/builtins-arm.cc +39 -33
  111. data/vendor/v8/src/arm/code-stubs-arm.cc +1182 -402
  112. data/vendor/v8/src/arm/code-stubs-arm.h +20 -54
  113. data/vendor/v8/src/arm/codegen-arm.cc +159 -106
  114. data/vendor/v8/src/arm/codegen-arm.h +6 -6
  115. data/vendor/v8/src/arm/constants-arm.h +16 -1
  116. data/vendor/v8/src/arm/cpu-arm.cc +7 -5
  117. data/vendor/v8/src/arm/debug-arm.cc +6 -4
  118. data/vendor/v8/src/arm/deoptimizer-arm.cc +51 -14
  119. data/vendor/v8/src/arm/disasm-arm.cc +47 -15
  120. data/vendor/v8/src/arm/frames-arm.h +1 -1
  121. data/vendor/v8/src/arm/full-codegen-arm.cc +724 -408
  122. data/vendor/v8/src/arm/ic-arm.cc +90 -85
  123. data/vendor/v8/src/arm/lithium-arm.cc +140 -69
  124. data/vendor/v8/src/arm/lithium-arm.h +161 -46
  125. data/vendor/v8/src/arm/lithium-codegen-arm.cc +567 -297
  126. data/vendor/v8/src/arm/lithium-codegen-arm.h +21 -9
  127. data/vendor/v8/src/arm/lithium-gap-resolver-arm.cc +2 -0
  128. data/vendor/v8/src/arm/macro-assembler-arm.cc +457 -96
  129. data/vendor/v8/src/arm/macro-assembler-arm.h +115 -18
  130. data/vendor/v8/src/arm/regexp-macro-assembler-arm.cc +20 -13
  131. data/vendor/v8/src/arm/regexp-macro-assembler-arm.h +1 -0
  132. data/vendor/v8/src/arm/simulator-arm.cc +184 -101
  133. data/vendor/v8/src/arm/simulator-arm.h +26 -21
  134. data/vendor/v8/src/arm/stub-cache-arm.cc +450 -467
  135. data/vendor/v8/src/arm/virtual-frame-arm.cc +14 -12
  136. data/vendor/v8/src/arm/virtual-frame-arm.h +11 -8
  137. data/vendor/v8/src/array.js +35 -18
  138. data/vendor/v8/src/assembler.cc +186 -92
  139. data/vendor/v8/src/assembler.h +106 -69
  140. data/vendor/v8/src/ast-inl.h +5 -0
  141. data/vendor/v8/src/ast.cc +46 -35
  142. data/vendor/v8/src/ast.h +107 -50
  143. data/vendor/v8/src/atomicops.h +2 -0
  144. data/vendor/v8/src/atomicops_internals_mips_gcc.h +169 -0
  145. data/vendor/v8/src/bootstrapper.cc +649 -399
  146. data/vendor/v8/src/bootstrapper.h +94 -27
  147. data/vendor/v8/src/builtins.cc +359 -227
  148. data/vendor/v8/src/builtins.h +157 -123
  149. data/vendor/v8/src/checks.cc +2 -2
  150. data/vendor/v8/src/checks.h +4 -0
  151. data/vendor/v8/src/code-stubs.cc +27 -17
  152. data/vendor/v8/src/code-stubs.h +38 -17
  153. data/vendor/v8/src/codegen-inl.h +5 -1
  154. data/vendor/v8/src/codegen.cc +27 -17
  155. data/vendor/v8/src/codegen.h +9 -9
  156. data/vendor/v8/src/compilation-cache.cc +92 -206
  157. data/vendor/v8/src/compilation-cache.h +205 -30
  158. data/vendor/v8/src/compiler.cc +107 -120
  159. data/vendor/v8/src/compiler.h +17 -2
  160. data/vendor/v8/src/contexts.cc +22 -15
  161. data/vendor/v8/src/contexts.h +14 -8
  162. data/vendor/v8/src/conversions.cc +86 -30
  163. data/vendor/v8/src/counters.cc +19 -4
  164. data/vendor/v8/src/counters.h +28 -16
  165. data/vendor/v8/src/cpu-profiler-inl.h +4 -3
  166. data/vendor/v8/src/cpu-profiler.cc +123 -72
  167. data/vendor/v8/src/cpu-profiler.h +33 -19
  168. data/vendor/v8/src/cpu.h +2 -0
  169. data/vendor/v8/src/d8-debug.cc +3 -3
  170. data/vendor/v8/src/d8-debug.h +7 -6
  171. data/vendor/v8/src/d8-posix.cc +2 -0
  172. data/vendor/v8/src/d8.cc +22 -12
  173. data/vendor/v8/src/d8.gyp +3 -0
  174. data/vendor/v8/src/d8.js +618 -0
  175. data/vendor/v8/src/data-flow.h +3 -3
  176. data/vendor/v8/src/dateparser.h +4 -2
  177. data/vendor/v8/src/debug-agent.cc +10 -9
  178. data/vendor/v8/src/debug-agent.h +9 -11
  179. data/vendor/v8/src/debug-debugger.js +121 -0
  180. data/vendor/v8/src/debug.cc +331 -227
  181. data/vendor/v8/src/debug.h +248 -219
  182. data/vendor/v8/src/deoptimizer.cc +173 -62
  183. data/vendor/v8/src/deoptimizer.h +119 -19
  184. data/vendor/v8/src/disasm.h +3 -0
  185. data/vendor/v8/src/disassembler.cc +10 -9
  186. data/vendor/v8/src/execution.cc +185 -129
  187. data/vendor/v8/src/execution.h +47 -78
  188. data/vendor/v8/src/extensions/experimental/break-iterator.cc +250 -0
  189. data/vendor/v8/src/extensions/experimental/break-iterator.h +89 -0
  190. data/vendor/v8/src/extensions/experimental/experimental.gyp +2 -0
  191. data/vendor/v8/src/extensions/experimental/i18n-extension.cc +22 -2
  192. data/vendor/v8/src/extensions/externalize-string-extension.cc +2 -2
  193. data/vendor/v8/src/extensions/gc-extension.cc +1 -1
  194. data/vendor/v8/src/factory.cc +261 -154
  195. data/vendor/v8/src/factory.h +162 -158
  196. data/vendor/v8/src/flag-definitions.h +17 -11
  197. data/vendor/v8/src/frame-element.cc +0 -5
  198. data/vendor/v8/src/frame-element.h +9 -13
  199. data/vendor/v8/src/frames-inl.h +7 -0
  200. data/vendor/v8/src/frames.cc +56 -46
  201. data/vendor/v8/src/frames.h +36 -25
  202. data/vendor/v8/src/full-codegen.cc +15 -24
  203. data/vendor/v8/src/full-codegen.h +13 -41
  204. data/vendor/v8/src/func-name-inferrer.cc +7 -6
  205. data/vendor/v8/src/func-name-inferrer.h +1 -1
  206. data/vendor/v8/src/gdb-jit.cc +1 -0
  207. data/vendor/v8/src/global-handles.cc +118 -56
  208. data/vendor/v8/src/global-handles.h +98 -40
  209. data/vendor/v8/src/globals.h +2 -2
  210. data/vendor/v8/src/handles-inl.h +106 -9
  211. data/vendor/v8/src/handles.cc +220 -157
  212. data/vendor/v8/src/handles.h +38 -59
  213. data/vendor/v8/src/hashmap.h +3 -3
  214. data/vendor/v8/src/heap-inl.h +141 -25
  215. data/vendor/v8/src/heap-profiler.cc +117 -63
  216. data/vendor/v8/src/heap-profiler.h +38 -21
  217. data/vendor/v8/src/heap.cc +805 -564
  218. data/vendor/v8/src/heap.h +640 -594
  219. data/vendor/v8/src/hydrogen-instructions.cc +216 -73
  220. data/vendor/v8/src/hydrogen-instructions.h +259 -124
  221. data/vendor/v8/src/hydrogen.cc +996 -1171
  222. data/vendor/v8/src/hydrogen.h +163 -144
  223. data/vendor/v8/src/ia32/assembler-ia32-inl.h +12 -11
  224. data/vendor/v8/src/ia32/assembler-ia32.cc +85 -39
  225. data/vendor/v8/src/ia32/assembler-ia32.h +82 -16
  226. data/vendor/v8/src/ia32/builtins-ia32.cc +64 -58
  227. data/vendor/v8/src/ia32/code-stubs-ia32.cc +248 -324
  228. data/vendor/v8/src/ia32/code-stubs-ia32.h +3 -44
  229. data/vendor/v8/src/ia32/codegen-ia32.cc +217 -165
  230. data/vendor/v8/src/ia32/codegen-ia32.h +3 -0
  231. data/vendor/v8/src/ia32/cpu-ia32.cc +6 -5
  232. data/vendor/v8/src/ia32/debug-ia32.cc +8 -5
  233. data/vendor/v8/src/ia32/deoptimizer-ia32.cc +124 -14
  234. data/vendor/v8/src/ia32/disasm-ia32.cc +85 -62
  235. data/vendor/v8/src/ia32/frames-ia32.h +1 -1
  236. data/vendor/v8/src/ia32/full-codegen-ia32.cc +348 -435
  237. data/vendor/v8/src/ia32/ic-ia32.cc +91 -91
  238. data/vendor/v8/src/ia32/lithium-codegen-ia32.cc +500 -255
  239. data/vendor/v8/src/ia32/lithium-codegen-ia32.h +13 -4
  240. data/vendor/v8/src/ia32/lithium-gap-resolver-ia32.cc +6 -0
  241. data/vendor/v8/src/ia32/lithium-ia32.cc +122 -45
  242. data/vendor/v8/src/ia32/lithium-ia32.h +128 -41
  243. data/vendor/v8/src/ia32/macro-assembler-ia32.cc +109 -84
  244. data/vendor/v8/src/ia32/macro-assembler-ia32.h +18 -9
  245. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.cc +26 -15
  246. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.h +1 -0
  247. data/vendor/v8/src/ia32/register-allocator-ia32.cc +30 -30
  248. data/vendor/v8/src/ia32/simulator-ia32.h +4 -4
  249. data/vendor/v8/src/ia32/stub-cache-ia32.cc +383 -400
  250. data/vendor/v8/src/ia32/virtual-frame-ia32.cc +36 -13
  251. data/vendor/v8/src/ia32/virtual-frame-ia32.h +11 -5
  252. data/vendor/v8/src/ic-inl.h +12 -2
  253. data/vendor/v8/src/ic.cc +304 -221
  254. data/vendor/v8/src/ic.h +115 -58
  255. data/vendor/v8/src/interpreter-irregexp.cc +25 -21
  256. data/vendor/v8/src/interpreter-irregexp.h +2 -1
  257. data/vendor/v8/src/isolate.cc +883 -0
  258. data/vendor/v8/src/isolate.h +1304 -0
  259. data/vendor/v8/src/json.js +10 -10
  260. data/vendor/v8/src/jsregexp.cc +111 -80
  261. data/vendor/v8/src/jsregexp.h +6 -7
  262. data/vendor/v8/src/jump-target-heavy.cc +5 -8
  263. data/vendor/v8/src/jump-target-heavy.h +0 -6
  264. data/vendor/v8/src/jump-target-inl.h +1 -1
  265. data/vendor/v8/src/jump-target-light.cc +3 -3
  266. data/vendor/v8/src/lithium-allocator-inl.h +2 -0
  267. data/vendor/v8/src/lithium-allocator.cc +42 -30
  268. data/vendor/v8/src/lithium-allocator.h +8 -22
  269. data/vendor/v8/src/lithium.cc +1 -0
  270. data/vendor/v8/src/liveedit.cc +141 -99
  271. data/vendor/v8/src/liveedit.h +7 -2
  272. data/vendor/v8/src/liveobjectlist-inl.h +90 -0
  273. data/vendor/v8/src/liveobjectlist.cc +2537 -1
  274. data/vendor/v8/src/liveobjectlist.h +245 -35
  275. data/vendor/v8/src/log-utils.cc +122 -35
  276. data/vendor/v8/src/log-utils.h +33 -36
  277. data/vendor/v8/src/log.cc +299 -241
  278. data/vendor/v8/src/log.h +177 -110
  279. data/vendor/v8/src/mark-compact.cc +612 -470
  280. data/vendor/v8/src/mark-compact.h +153 -80
  281. data/vendor/v8/src/messages.cc +16 -14
  282. data/vendor/v8/src/messages.js +30 -7
  283. data/vendor/v8/src/mips/assembler-mips-inl.h +155 -35
  284. data/vendor/v8/src/mips/assembler-mips.cc +1093 -219
  285. data/vendor/v8/src/mips/assembler-mips.h +552 -153
  286. data/vendor/v8/src/mips/builtins-mips.cc +43 -100
  287. data/vendor/v8/src/mips/code-stubs-mips.cc +752 -0
  288. data/vendor/v8/src/mips/code-stubs-mips.h +511 -0
  289. data/vendor/v8/src/mips/codegen-mips-inl.h +8 -14
  290. data/vendor/v8/src/mips/codegen-mips.cc +672 -896
  291. data/vendor/v8/src/mips/codegen-mips.h +271 -69
  292. data/vendor/v8/src/mips/constants-mips.cc +44 -20
  293. data/vendor/v8/src/mips/constants-mips.h +238 -40
  294. data/vendor/v8/src/mips/cpu-mips.cc +20 -3
  295. data/vendor/v8/src/mips/debug-mips.cc +35 -7
  296. data/vendor/v8/src/mips/deoptimizer-mips.cc +91 -0
  297. data/vendor/v8/src/mips/disasm-mips.cc +329 -93
  298. data/vendor/v8/src/mips/frames-mips.cc +2 -50
  299. data/vendor/v8/src/mips/frames-mips.h +24 -9
  300. data/vendor/v8/src/mips/full-codegen-mips.cc +473 -23
  301. data/vendor/v8/src/mips/ic-mips.cc +81 -45
  302. data/vendor/v8/src/mips/jump-target-mips.cc +11 -106
  303. data/vendor/v8/src/mips/lithium-codegen-mips.h +65 -0
  304. data/vendor/v8/src/mips/lithium-mips.h +304 -0
  305. data/vendor/v8/src/mips/macro-assembler-mips.cc +2391 -390
  306. data/vendor/v8/src/mips/macro-assembler-mips.h +718 -121
  307. data/vendor/v8/src/mips/regexp-macro-assembler-mips.cc +478 -0
  308. data/vendor/v8/src/mips/regexp-macro-assembler-mips.h +250 -0
  309. data/vendor/v8/src/mips/register-allocator-mips-inl.h +0 -3
  310. data/vendor/v8/src/mips/register-allocator-mips.h +3 -2
  311. data/vendor/v8/src/mips/simulator-mips.cc +1009 -221
  312. data/vendor/v8/src/mips/simulator-mips.h +119 -36
  313. data/vendor/v8/src/mips/stub-cache-mips.cc +331 -148
  314. data/vendor/v8/src/mips/{fast-codegen-mips.cc → virtual-frame-mips-inl.h} +11 -30
  315. data/vendor/v8/src/mips/virtual-frame-mips.cc +137 -149
  316. data/vendor/v8/src/mips/virtual-frame-mips.h +294 -312
  317. data/vendor/v8/src/mirror-debugger.js +9 -8
  318. data/vendor/v8/src/mksnapshot.cc +2 -2
  319. data/vendor/v8/src/objects-debug.cc +16 -16
  320. data/vendor/v8/src/objects-inl.h +421 -195
  321. data/vendor/v8/src/objects-printer.cc +7 -7
  322. data/vendor/v8/src/objects-visiting.cc +1 -1
  323. data/vendor/v8/src/objects-visiting.h +33 -12
  324. data/vendor/v8/src/objects.cc +935 -658
  325. data/vendor/v8/src/objects.h +234 -139
  326. data/vendor/v8/src/parser.cc +484 -439
  327. data/vendor/v8/src/parser.h +35 -14
  328. data/vendor/v8/src/platform-cygwin.cc +173 -107
  329. data/vendor/v8/src/platform-freebsd.cc +224 -72
  330. data/vendor/v8/src/platform-linux.cc +234 -95
  331. data/vendor/v8/src/platform-macos.cc +215 -82
  332. data/vendor/v8/src/platform-nullos.cc +9 -3
  333. data/vendor/v8/src/platform-openbsd.cc +22 -7
  334. data/vendor/v8/src/platform-posix.cc +30 -5
  335. data/vendor/v8/src/platform-solaris.cc +120 -38
  336. data/vendor/v8/src/platform-tls-mac.h +62 -0
  337. data/vendor/v8/src/platform-tls-win32.h +62 -0
  338. data/vendor/v8/src/platform-tls.h +50 -0
  339. data/vendor/v8/src/platform-win32.cc +195 -97
  340. data/vendor/v8/src/platform.h +72 -15
  341. data/vendor/v8/src/preparse-data.cc +2 -0
  342. data/vendor/v8/src/preparser-api.cc +8 -2
  343. data/vendor/v8/src/preparser.cc +1 -1
  344. data/vendor/v8/src/prettyprinter.cc +43 -52
  345. data/vendor/v8/src/prettyprinter.h +1 -1
  346. data/vendor/v8/src/profile-generator-inl.h +0 -28
  347. data/vendor/v8/src/profile-generator.cc +942 -685
  348. data/vendor/v8/src/profile-generator.h +210 -176
  349. data/vendor/v8/src/property.cc +6 -0
  350. data/vendor/v8/src/property.h +14 -3
  351. data/vendor/v8/src/regexp-macro-assembler-irregexp.cc +1 -1
  352. data/vendor/v8/src/regexp-macro-assembler.cc +28 -19
  353. data/vendor/v8/src/regexp-macro-assembler.h +11 -6
  354. data/vendor/v8/src/regexp-stack.cc +18 -10
  355. data/vendor/v8/src/regexp-stack.h +45 -21
  356. data/vendor/v8/src/regexp.js +3 -3
  357. data/vendor/v8/src/register-allocator-inl.h +3 -3
  358. data/vendor/v8/src/register-allocator.cc +1 -7
  359. data/vendor/v8/src/register-allocator.h +5 -15
  360. data/vendor/v8/src/rewriter.cc +2 -1
  361. data/vendor/v8/src/runtime-profiler.cc +158 -128
  362. data/vendor/v8/src/runtime-profiler.h +131 -15
  363. data/vendor/v8/src/runtime.cc +2409 -1692
  364. data/vendor/v8/src/runtime.h +93 -17
  365. data/vendor/v8/src/safepoint-table.cc +3 -0
  366. data/vendor/v8/src/safepoint-table.h +9 -3
  367. data/vendor/v8/src/scanner-base.cc +21 -28
  368. data/vendor/v8/src/scanner-base.h +22 -11
  369. data/vendor/v8/src/scanner.cc +3 -5
  370. data/vendor/v8/src/scanner.h +4 -2
  371. data/vendor/v8/src/scopeinfo.cc +11 -16
  372. data/vendor/v8/src/scopeinfo.h +26 -15
  373. data/vendor/v8/src/scopes.cc +67 -37
  374. data/vendor/v8/src/scopes.h +26 -12
  375. data/vendor/v8/src/serialize.cc +193 -154
  376. data/vendor/v8/src/serialize.h +41 -36
  377. data/vendor/v8/src/small-pointer-list.h +163 -0
  378. data/vendor/v8/src/snapshot-common.cc +1 -1
  379. data/vendor/v8/src/snapshot.h +3 -1
  380. data/vendor/v8/src/spaces-inl.h +30 -25
  381. data/vendor/v8/src/spaces.cc +263 -370
  382. data/vendor/v8/src/spaces.h +178 -166
  383. data/vendor/v8/src/string-search.cc +4 -3
  384. data/vendor/v8/src/string-search.h +21 -20
  385. data/vendor/v8/src/string-stream.cc +32 -24
  386. data/vendor/v8/src/string.js +7 -7
  387. data/vendor/v8/src/stub-cache.cc +324 -248
  388. data/vendor/v8/src/stub-cache.h +181 -155
  389. data/vendor/v8/src/token.cc +3 -3
  390. data/vendor/v8/src/token.h +3 -3
  391. data/vendor/v8/src/top.cc +218 -390
  392. data/vendor/v8/src/type-info.cc +98 -32
  393. data/vendor/v8/src/type-info.h +10 -3
  394. data/vendor/v8/src/unicode.cc +1 -1
  395. data/vendor/v8/src/unicode.h +1 -1
  396. data/vendor/v8/src/utils.h +3 -0
  397. data/vendor/v8/src/v8-counters.cc +18 -11
  398. data/vendor/v8/src/v8-counters.h +34 -13
  399. data/vendor/v8/src/v8.cc +66 -121
  400. data/vendor/v8/src/v8.h +7 -4
  401. data/vendor/v8/src/v8globals.h +18 -12
  402. data/vendor/v8/src/{memory.h → v8memory.h} +0 -0
  403. data/vendor/v8/src/v8natives.js +59 -18
  404. data/vendor/v8/src/v8threads.cc +127 -114
  405. data/vendor/v8/src/v8threads.h +42 -35
  406. data/vendor/v8/src/v8utils.h +2 -39
  407. data/vendor/v8/src/variables.h +1 -1
  408. data/vendor/v8/src/version.cc +26 -5
  409. data/vendor/v8/src/version.h +4 -0
  410. data/vendor/v8/src/virtual-frame-heavy-inl.h +2 -4
  411. data/vendor/v8/src/virtual-frame-light-inl.h +5 -4
  412. data/vendor/v8/src/vm-state-inl.h +21 -17
  413. data/vendor/v8/src/vm-state.h +7 -5
  414. data/vendor/v8/src/win32-headers.h +1 -0
  415. data/vendor/v8/src/x64/assembler-x64-inl.h +12 -11
  416. data/vendor/v8/src/x64/assembler-x64.cc +80 -40
  417. data/vendor/v8/src/x64/assembler-x64.h +67 -17
  418. data/vendor/v8/src/x64/builtins-x64.cc +34 -33
  419. data/vendor/v8/src/x64/code-stubs-x64.cc +636 -377
  420. data/vendor/v8/src/x64/code-stubs-x64.h +14 -48
  421. data/vendor/v8/src/x64/codegen-x64-inl.h +1 -1
  422. data/vendor/v8/src/x64/codegen-x64.cc +158 -136
  423. data/vendor/v8/src/x64/codegen-x64.h +4 -1
  424. data/vendor/v8/src/x64/cpu-x64.cc +7 -5
  425. data/vendor/v8/src/x64/debug-x64.cc +8 -6
  426. data/vendor/v8/src/x64/deoptimizer-x64.cc +195 -20
  427. data/vendor/v8/src/x64/disasm-x64.cc +42 -23
  428. data/vendor/v8/src/x64/frames-x64.cc +1 -1
  429. data/vendor/v8/src/x64/frames-x64.h +2 -2
  430. data/vendor/v8/src/x64/full-codegen-x64.cc +780 -218
  431. data/vendor/v8/src/x64/ic-x64.cc +77 -79
  432. data/vendor/v8/src/x64/jump-target-x64.cc +1 -1
  433. data/vendor/v8/src/x64/lithium-codegen-x64.cc +698 -181
  434. data/vendor/v8/src/x64/lithium-codegen-x64.h +31 -6
  435. data/vendor/v8/src/x64/lithium-x64.cc +136 -54
  436. data/vendor/v8/src/x64/lithium-x64.h +142 -51
  437. data/vendor/v8/src/x64/macro-assembler-x64.cc +456 -187
  438. data/vendor/v8/src/x64/macro-assembler-x64.h +166 -34
  439. data/vendor/v8/src/x64/regexp-macro-assembler-x64.cc +44 -28
  440. data/vendor/v8/src/x64/regexp-macro-assembler-x64.h +8 -4
  441. data/vendor/v8/src/x64/register-allocator-x64-inl.h +3 -3
  442. data/vendor/v8/src/x64/register-allocator-x64.cc +12 -8
  443. data/vendor/v8/src/x64/simulator-x64.h +5 -5
  444. data/vendor/v8/src/x64/stub-cache-x64.cc +299 -344
  445. data/vendor/v8/src/x64/virtual-frame-x64.cc +37 -13
  446. data/vendor/v8/src/x64/virtual-frame-x64.h +13 -7
  447. data/vendor/v8/src/zone-inl.h +49 -3
  448. data/vendor/v8/src/zone.cc +42 -41
  449. data/vendor/v8/src/zone.h +37 -34
  450. data/vendor/v8/test/benchmarks/testcfg.py +100 -0
  451. data/vendor/v8/test/cctest/SConscript +5 -4
  452. data/vendor/v8/test/cctest/cctest.h +3 -2
  453. data/vendor/v8/test/cctest/cctest.status +6 -11
  454. data/vendor/v8/test/cctest/test-accessors.cc +3 -3
  455. data/vendor/v8/test/cctest/test-alloc.cc +39 -33
  456. data/vendor/v8/test/cctest/test-api.cc +1092 -205
  457. data/vendor/v8/test/cctest/test-assembler-arm.cc +39 -25
  458. data/vendor/v8/test/cctest/test-assembler-ia32.cc +36 -37
  459. data/vendor/v8/test/cctest/test-assembler-mips.cc +1098 -40
  460. data/vendor/v8/test/cctest/test-assembler-x64.cc +32 -25
  461. data/vendor/v8/test/cctest/test-ast.cc +1 -0
  462. data/vendor/v8/test/cctest/test-circular-queue.cc +8 -5
  463. data/vendor/v8/test/cctest/test-compiler.cc +24 -24
  464. data/vendor/v8/test/cctest/test-cpu-profiler.cc +140 -5
  465. data/vendor/v8/test/cctest/test-dataflow.cc +1 -0
  466. data/vendor/v8/test/cctest/test-debug.cc +136 -77
  467. data/vendor/v8/test/cctest/test-decls.cc +1 -1
  468. data/vendor/v8/test/cctest/test-deoptimization.cc +25 -24
  469. data/vendor/v8/test/cctest/test-disasm-arm.cc +9 -4
  470. data/vendor/v8/test/cctest/test-disasm-ia32.cc +10 -8
  471. data/vendor/v8/test/cctest/test-func-name-inference.cc +10 -4
  472. data/vendor/v8/test/cctest/test-heap-profiler.cc +226 -164
  473. data/vendor/v8/test/cctest/test-heap.cc +240 -217
  474. data/vendor/v8/test/cctest/test-liveedit.cc +1 -0
  475. data/vendor/v8/test/cctest/test-log-stack-tracer.cc +18 -20
  476. data/vendor/v8/test/cctest/test-log.cc +114 -108
  477. data/vendor/v8/test/cctest/test-macro-assembler-x64.cc +247 -177
  478. data/vendor/v8/test/cctest/test-mark-compact.cc +129 -90
  479. data/vendor/v8/test/cctest/test-parsing.cc +15 -14
  480. data/vendor/v8/test/cctest/test-platform-linux.cc +1 -0
  481. data/vendor/v8/test/cctest/test-platform-tls.cc +66 -0
  482. data/vendor/v8/test/cctest/test-platform-win32.cc +1 -0
  483. data/vendor/v8/test/cctest/test-profile-generator.cc +1 -1
  484. data/vendor/v8/test/cctest/test-regexp.cc +53 -41
  485. data/vendor/v8/test/cctest/test-reloc-info.cc +18 -11
  486. data/vendor/v8/test/cctest/test-serialize.cc +44 -43
  487. data/vendor/v8/test/cctest/test-sockets.cc +8 -3
  488. data/vendor/v8/test/cctest/test-spaces.cc +47 -29
  489. data/vendor/v8/test/cctest/test-strings.cc +20 -20
  490. data/vendor/v8/test/cctest/test-thread-termination.cc +8 -3
  491. data/vendor/v8/test/cctest/test-threads.cc +5 -3
  492. data/vendor/v8/test/cctest/test-utils.cc +5 -4
  493. data/vendor/v8/test/cctest/testcfg.py +7 -3
  494. data/vendor/v8/test/es5conform/es5conform.status +2 -77
  495. data/vendor/v8/test/es5conform/testcfg.py +1 -1
  496. data/vendor/v8/test/message/testcfg.py +1 -1
  497. data/vendor/v8/test/mjsunit/accessors-on-global-object.js +3 -3
  498. data/vendor/v8/test/mjsunit/array-concat.js +43 -1
  499. data/vendor/v8/test/mjsunit/array-join.js +25 -0
  500. data/vendor/v8/test/mjsunit/bitops-info.js +7 -1
  501. data/vendor/v8/test/mjsunit/compiler/array-length.js +2 -2
  502. data/vendor/v8/test/mjsunit/compiler/global-accessors.js +47 -0
  503. data/vendor/v8/test/mjsunit/compiler/pic.js +1 -1
  504. data/vendor/v8/test/mjsunit/compiler/regress-loadfield.js +65 -0
  505. data/vendor/v8/test/mjsunit/math-sqrt.js +5 -1
  506. data/vendor/v8/test/mjsunit/mjsunit.js +59 -8
  507. data/vendor/v8/test/mjsunit/mjsunit.status +0 -12
  508. data/vendor/v8/test/mjsunit/mul-exhaustive.js +129 -11
  509. data/vendor/v8/test/mjsunit/negate-zero.js +1 -1
  510. data/vendor/v8/test/mjsunit/object-freeze.js +5 -13
  511. data/vendor/v8/test/mjsunit/object-prevent-extensions.js +9 -50
  512. data/vendor/v8/test/mjsunit/object-seal.js +4 -13
  513. data/vendor/v8/test/mjsunit/override-eval-with-non-function.js +36 -0
  514. data/vendor/v8/test/mjsunit/regress/regress-1145.js +54 -0
  515. data/vendor/v8/test/mjsunit/regress/regress-1172-bis.js +37 -0
  516. data/vendor/v8/test/mjsunit/regress/regress-1181.js +54 -0
  517. data/vendor/v8/test/mjsunit/regress/regress-1207.js +35 -0
  518. data/vendor/v8/test/mjsunit/regress/regress-1209.js +34 -0
  519. data/vendor/v8/test/mjsunit/regress/regress-1210.js +48 -0
  520. data/vendor/v8/test/mjsunit/regress/regress-1213.js +43 -0
  521. data/vendor/v8/test/mjsunit/regress/regress-1218.js +29 -0
  522. data/vendor/v8/test/mjsunit/regress/regress-1229.js +79 -0
  523. data/vendor/v8/test/mjsunit/regress/regress-1233.js +47 -0
  524. data/vendor/v8/test/mjsunit/regress/regress-1236.js +34 -0
  525. data/vendor/v8/test/mjsunit/regress/regress-1237.js +36 -0
  526. data/vendor/v8/test/mjsunit/regress/regress-1240.js +39 -0
  527. data/vendor/v8/test/mjsunit/regress/regress-1257.js +58 -0
  528. data/vendor/v8/test/mjsunit/regress/regress-1278.js +69 -0
  529. data/vendor/v8/test/mjsunit/regress/regress-create-exception.js +1 -0
  530. data/vendor/v8/test/mjsunit/regress/regress-lazy-deopt-reloc.js +52 -0
  531. data/vendor/v8/test/mjsunit/sin-cos.js +15 -10
  532. data/vendor/v8/test/mjsunit/smi-negative-zero.js +2 -2
  533. data/vendor/v8/test/mjsunit/str-to-num.js +1 -1
  534. data/vendor/v8/test/mjsunit/strict-mode.js +435 -0
  535. data/vendor/v8/test/mjsunit/testcfg.py +23 -6
  536. data/vendor/v8/test/mozilla/mozilla.status +0 -2
  537. data/vendor/v8/test/mozilla/testcfg.py +1 -1
  538. data/vendor/v8/test/preparser/empty.js +28 -0
  539. data/vendor/v8/test/preparser/functions-only.js +38 -0
  540. data/vendor/v8/test/preparser/non-alphanum.js +34 -0
  541. data/vendor/v8/test/preparser/symbols-only.js +49 -0
  542. data/vendor/v8/test/preparser/testcfg.py +90 -0
  543. data/vendor/v8/test/sputnik/testcfg.py +1 -1
  544. data/vendor/v8/test/test262/README +16 -0
  545. data/vendor/v8/test/test262/harness-adapt.js +80 -0
  546. data/vendor/v8/test/test262/test262.status +1506 -0
  547. data/vendor/v8/test/test262/testcfg.py +123 -0
  548. data/vendor/v8/tools/freebsd-tick-processor +10 -0
  549. data/vendor/v8/tools/gyp/v8.gyp +8 -33
  550. data/vendor/v8/tools/linux-tick-processor +5 -3
  551. data/vendor/v8/tools/test.py +37 -14
  552. data/vendor/v8/tools/tickprocessor.js +22 -8
  553. data/vendor/v8/tools/visual_studio/v8_base.vcproj +13 -1
  554. data/vendor/v8/tools/visual_studio/v8_base_arm.vcproj +5 -1
  555. data/vendor/v8/tools/visual_studio/v8_base_x64.vcproj +5 -1
  556. data/vendor/v8/tools/visual_studio/x64.vsprops +1 -0
  557. metadata +1495 -1341
  558. data/ext/extconf.rb +0 -22
  559. data/ext/mustang.cpp +0 -58
  560. data/vendor/v8/src/top.h +0 -608
@@ -111,7 +111,7 @@ class AstPrinter: public PrettyPrinter {
111
111
  void inc_indent() { indent_++; }
112
112
  void dec_indent() { indent_--; }
113
113
 
114
- static int indent_;
114
+ int indent_;
115
115
  };
116
116
 
117
117
 
@@ -121,34 +121,6 @@ uint64_t HeapEntry::id() {
121
121
  return id_adaptor.returned_id;
122
122
  }
123
123
 
124
-
125
- template<class Visitor>
126
- void HeapEntriesMap::UpdateEntries(Visitor* visitor) {
127
- for (HashMap::Entry* p = entries_.Start();
128
- p != NULL;
129
- p = entries_.Next(p)) {
130
- EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
131
- entry_info->entry = visitor->GetEntry(
132
- reinterpret_cast<HeapObject*>(p->key),
133
- entry_info->children_count,
134
- entry_info->retainers_count);
135
- entry_info->children_count = 0;
136
- entry_info->retainers_count = 0;
137
- }
138
- }
139
-
140
-
141
- bool HeapSnapshotGenerator::ReportProgress(bool force) {
142
- const int kProgressReportGranularity = 10000;
143
- if (control_ != NULL
144
- && (force || progress_counter_ % kProgressReportGranularity == 0)) {
145
- return
146
- control_->ReportProgressValue(progress_counter_, progress_total_) ==
147
- v8::ActivityControl::kContinue;
148
- }
149
- return true;
150
- }
151
-
152
124
  } } // namespace v8::internal
153
125
 
154
126
  #endif // ENABLE_LOGGING_AND_PROFILING
@@ -29,8 +29,8 @@
29
29
 
30
30
  #include "v8.h"
31
31
  #include "global-handles.h"
32
+ #include "heap-profiler.h"
32
33
  #include "scopeinfo.h"
33
- #include "top.h"
34
34
  #include "unicode.h"
35
35
  #include "zone-inl.h"
36
36
 
@@ -47,24 +47,27 @@ TokenEnumerator::TokenEnumerator()
47
47
 
48
48
 
49
49
  TokenEnumerator::~TokenEnumerator() {
50
+ Isolate* isolate = Isolate::Current();
50
51
  for (int i = 0; i < token_locations_.length(); ++i) {
51
52
  if (!token_removed_[i]) {
52
- GlobalHandles::ClearWeakness(token_locations_[i]);
53
- GlobalHandles::Destroy(token_locations_[i]);
53
+ isolate->global_handles()->ClearWeakness(token_locations_[i]);
54
+ isolate->global_handles()->Destroy(token_locations_[i]);
54
55
  }
55
56
  }
56
57
  }
57
58
 
58
59
 
59
60
  int TokenEnumerator::GetTokenId(Object* token) {
61
+ Isolate* isolate = Isolate::Current();
60
62
  if (token == NULL) return TokenEnumerator::kNoSecurityToken;
61
63
  for (int i = 0; i < token_locations_.length(); ++i) {
62
64
  if (*token_locations_[i] == token && !token_removed_[i]) return i;
63
65
  }
64
- Handle<Object> handle = GlobalHandles::Create(token);
66
+ Handle<Object> handle = isolate->global_handles()->Create(token);
65
67
  // handle.location() points to a memory cell holding a pointer
66
68
  // to a token object in the V8's heap.
67
- GlobalHandles::MakeWeak(handle.location(), this, TokenRemovedCallback);
69
+ isolate->global_handles()->MakeWeak(handle.location(), this,
70
+ TokenRemovedCallback);
68
71
  token_locations_.Add(handle.location());
69
72
  token_removed_.Add(false);
70
73
  return token_locations_.length() - 1;
@@ -94,55 +97,74 @@ StringsStorage::StringsStorage()
94
97
  }
95
98
 
96
99
 
97
- static void DeleteIndexName(char** name_ptr) {
98
- DeleteArray(*name_ptr);
99
- }
100
-
101
-
102
100
  StringsStorage::~StringsStorage() {
103
101
  for (HashMap::Entry* p = names_.Start();
104
102
  p != NULL;
105
103
  p = names_.Next(p)) {
106
104
  DeleteArray(reinterpret_cast<const char*>(p->value));
107
105
  }
108
- index_names_.Iterate(DeleteIndexName);
106
+ }
107
+
108
+
109
+ const char* StringsStorage::GetCopy(const char* src) {
110
+ int len = static_cast<int>(strlen(src));
111
+ Vector<char> dst = Vector<char>::New(len + 1);
112
+ OS::StrNCpy(dst, src, len);
113
+ dst[len] = '\0';
114
+ uint32_t hash = HashSequentialString(dst.start(), len);
115
+ return AddOrDisposeString(dst.start(), hash);
116
+ }
117
+
118
+
119
+ const char* StringsStorage::GetFormatted(const char* format, ...) {
120
+ va_list args;
121
+ va_start(args, format);
122
+ const char* result = GetVFormatted(format, args);
123
+ va_end(args);
124
+ return result;
125
+ }
126
+
127
+
128
+ const char* StringsStorage::AddOrDisposeString(char* str, uint32_t hash) {
129
+ HashMap::Entry* cache_entry = names_.Lookup(str, hash, true);
130
+ if (cache_entry->value == NULL) {
131
+ // New entry added.
132
+ cache_entry->value = str;
133
+ } else {
134
+ DeleteArray(str);
135
+ }
136
+ return reinterpret_cast<const char*>(cache_entry->value);
137
+ }
138
+
139
+
140
+ const char* StringsStorage::GetVFormatted(const char* format, va_list args) {
141
+ Vector<char> str = Vector<char>::New(1024);
142
+ int len = OS::VSNPrintF(str, format, args);
143
+ if (len == -1) {
144
+ DeleteArray(str.start());
145
+ return format;
146
+ }
147
+ uint32_t hash = HashSequentialString(str.start(), len);
148
+ return AddOrDisposeString(str.start(), hash);
109
149
  }
110
150
 
111
151
 
112
152
  const char* StringsStorage::GetName(String* name) {
113
153
  if (name->IsString()) {
114
- char* c_name =
115
- name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach();
116
- HashMap::Entry* cache_entry = names_.Lookup(c_name, name->Hash(), true);
117
- if (cache_entry->value == NULL) {
118
- // New entry added.
119
- cache_entry->value = c_name;
120
- } else {
121
- DeleteArray(c_name);
122
- }
123
- return reinterpret_cast<const char*>(cache_entry->value);
154
+ return AddOrDisposeString(
155
+ name->ToCString(DISALLOW_NULLS, ROBUST_STRING_TRAVERSAL).Detach(),
156
+ name->Hash());
124
157
  }
125
158
  return "";
126
159
  }
127
160
 
128
161
 
129
162
  const char* StringsStorage::GetName(int index) {
130
- ASSERT(index >= 0);
131
- if (index_names_.length() <= index) {
132
- index_names_.AddBlock(
133
- NULL, index - index_names_.length() + 1);
134
- }
135
- if (index_names_[index] == NULL) {
136
- const int kMaximumNameLength = 32;
137
- char* name = NewArray<char>(kMaximumNameLength);
138
- OS::SNPrintF(Vector<char>(name, kMaximumNameLength), "%d", index);
139
- index_names_[index] = name;
140
- }
141
- return index_names_[index];
163
+ return GetFormatted("%d", index);
142
164
  }
143
165
 
144
166
 
145
- const char* CodeEntry::kEmptyNamePrefix = "";
167
+ const char* const CodeEntry::kEmptyNamePrefix = "";
146
168
 
147
169
 
148
170
  void CodeEntry::CopyData(const CodeEntry& source) {
@@ -298,7 +320,7 @@ struct NodesPair {
298
320
 
299
321
  class FilteredCloneCallback {
300
322
  public:
301
- explicit FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
323
+ FilteredCloneCallback(ProfileNode* dst_root, int security_token_id)
302
324
  : stack_(10),
303
325
  security_token_id_(security_token_id) {
304
326
  stack_.Add(NodesPair(NULL, dst_root));
@@ -465,7 +487,7 @@ void CpuProfile::Print() {
465
487
  }
466
488
 
467
489
 
468
- CodeEntry* const CodeMap::kSfiCodeEntry = NULL;
490
+ CodeEntry* const CodeMap::kSharedFunctionCodeEntry = NULL;
469
491
  const CodeMap::CodeTreeConfig::Key CodeMap::CodeTreeConfig::kNoKey = NULL;
470
492
  const CodeMap::CodeTreeConfig::Value CodeMap::CodeTreeConfig::kNoValue =
471
493
  CodeMap::CodeEntryInfo(NULL, 0);
@@ -483,18 +505,18 @@ CodeEntry* CodeMap::FindEntry(Address addr) {
483
505
  }
484
506
 
485
507
 
486
- int CodeMap::GetSFITag(Address addr) {
508
+ int CodeMap::GetSharedId(Address addr) {
487
509
  CodeTree::Locator locator;
488
- // For SFI entries, 'size' field is used to store their IDs.
510
+ // For shared function entries, 'size' field is used to store their IDs.
489
511
  if (tree_.Find(addr, &locator)) {
490
512
  const CodeEntryInfo& entry = locator.value();
491
- ASSERT(entry.entry == kSfiCodeEntry);
513
+ ASSERT(entry.entry == kSharedFunctionCodeEntry);
492
514
  return entry.size;
493
515
  } else {
494
516
  tree_.Insert(addr, &locator);
495
- int tag = next_sfi_tag_++;
496
- locator.set_value(CodeEntryInfo(kSfiCodeEntry, tag));
497
- return tag;
517
+ int id = next_shared_id_++;
518
+ locator.set_value(CodeEntryInfo(kSharedFunctionCodeEntry, id));
519
+ return id;
498
520
  }
499
521
  }
500
522
 
@@ -528,13 +550,16 @@ static void DeleteCpuProfile(CpuProfile** profile_ptr) {
528
550
  }
529
551
 
530
552
  static void DeleteProfilesList(List<CpuProfile*>** list_ptr) {
531
- (*list_ptr)->Iterate(DeleteCpuProfile);
532
- delete *list_ptr;
553
+ if (*list_ptr != NULL) {
554
+ (*list_ptr)->Iterate(DeleteCpuProfile);
555
+ delete *list_ptr;
556
+ }
533
557
  }
534
558
 
535
559
  CpuProfilesCollection::~CpuProfilesCollection() {
536
560
  delete current_profiles_semaphore_;
537
561
  current_profiles_.Iterate(DeleteCpuProfile);
562
+ detached_profiles_.Iterate(DeleteCpuProfile);
538
563
  profiles_by_token_.Iterate(DeleteProfilesList);
539
564
  code_entries_.Iterate(DeleteCodeEntry);
540
565
  }
@@ -599,15 +624,8 @@ CpuProfile* CpuProfilesCollection::StopProfiling(int security_token_id,
599
624
 
600
625
  CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
601
626
  unsigned uid) {
602
- HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
603
- static_cast<uint32_t>(uid),
604
- false);
605
- int index;
606
- if (entry != NULL) {
607
- index = static_cast<int>(reinterpret_cast<intptr_t>(entry->value));
608
- } else {
609
- return NULL;
610
- }
627
+ int index = GetProfileIndex(uid);
628
+ if (index < 0) return NULL;
611
629
  List<CpuProfile*>* unabridged_list =
612
630
  profiles_by_token_[TokenToIndex(TokenEnumerator::kNoSecurityToken)];
613
631
  if (security_token_id == TokenEnumerator::kNoSecurityToken) {
@@ -622,6 +640,15 @@ CpuProfile* CpuProfilesCollection::GetProfile(int security_token_id,
622
640
  }
623
641
 
624
642
 
643
+ int CpuProfilesCollection::GetProfileIndex(unsigned uid) {
644
+ HashMap::Entry* entry = profiles_uids_.Lookup(reinterpret_cast<void*>(uid),
645
+ static_cast<uint32_t>(uid),
646
+ false);
647
+ return entry != NULL ?
648
+ static_cast<int>(reinterpret_cast<intptr_t>(entry->value)) : -1;
649
+ }
650
+
651
+
625
652
  bool CpuProfilesCollection::IsLastProfile(const char* title) {
626
653
  // Called from VM thread, and only it can mutate the list,
627
654
  // so no locking is needed here.
@@ -631,6 +658,39 @@ bool CpuProfilesCollection::IsLastProfile(const char* title) {
631
658
  }
632
659
 
633
660
 
661
+ void CpuProfilesCollection::RemoveProfile(CpuProfile* profile) {
662
+ // Called from VM thread for a completed profile.
663
+ unsigned uid = profile->uid();
664
+ int index = GetProfileIndex(uid);
665
+ if (index < 0) {
666
+ detached_profiles_.RemoveElement(profile);
667
+ return;
668
+ }
669
+ profiles_uids_.Remove(reinterpret_cast<void*>(uid),
670
+ static_cast<uint32_t>(uid));
671
+ // Decrement all indexes above the deleted one.
672
+ for (HashMap::Entry* p = profiles_uids_.Start();
673
+ p != NULL;
674
+ p = profiles_uids_.Next(p)) {
675
+ intptr_t p_index = reinterpret_cast<intptr_t>(p->value);
676
+ if (p_index > index) {
677
+ p->value = reinterpret_cast<void*>(p_index - 1);
678
+ }
679
+ }
680
+ for (int i = 0; i < profiles_by_token_.length(); ++i) {
681
+ List<CpuProfile*>* list = profiles_by_token_[i];
682
+ if (list != NULL && index < list->length()) {
683
+ // Move all filtered clones into detached_profiles_,
684
+ // so we can know that they are still in use.
685
+ CpuProfile* cloned_profile = list->Remove(index);
686
+ if (cloned_profile != NULL && cloned_profile != profile) {
687
+ detached_profiles_.Add(cloned_profile);
688
+ }
689
+ }
690
+ }
691
+ }
692
+
693
+
634
694
  int CpuProfilesCollection::TokenToIndex(int security_token_id) {
635
695
  ASSERT(TokenEnumerator::kNoSecurityToken == -1);
636
696
  return security_token_id + 1; // kNoSecurityToken -> 0, 0 -> 1, ...
@@ -763,10 +823,12 @@ void SampleRateCalculator::UpdateMeasurements(double current_time) {
763
823
  }
764
824
 
765
825
 
766
- const char* ProfileGenerator::kAnonymousFunctionName = "(anonymous function)";
767
- const char* ProfileGenerator::kProgramEntryName = "(program)";
768
- const char* ProfileGenerator::kGarbageCollectorEntryName =
769
- "(garbage collector)";
826
+ const char* const ProfileGenerator::kAnonymousFunctionName =
827
+ "(anonymous function)";
828
+ const char* const ProfileGenerator::kProgramEntryName =
829
+ "(program)";
830
+ const char* const ProfileGenerator::kGarbageCollectorEntryName =
831
+ "(garbage collector)";
770
832
 
771
833
 
772
834
  ProfileGenerator::ProfileGenerator(CpuProfilesCollection* profiles)
@@ -789,7 +851,15 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
789
851
  if (sample.pc != NULL) {
790
852
  *entry++ = code_map_.FindEntry(sample.pc);
791
853
 
792
- if (sample.tos != NULL) {
854
+ if (sample.has_external_callback) {
855
+ // Don't use PC when in external callback code, as it can point
856
+ // inside callback's code, and we will erroneously report
857
+ // that a callback calls itself.
858
+ *(entries.start()) = NULL;
859
+ *entry++ = code_map_.FindEntry(sample.external_callback);
860
+ } else if (sample.tos != NULL) {
861
+ // Find out, if top of stack was pointing inside a JS function
862
+ // meaning that we have encountered a frameless invocation.
793
863
  *entry = code_map_.FindEntry(sample.tos);
794
864
  if (*entry != NULL && !(*entry)->is_js_function()) {
795
865
  *entry = NULL;
@@ -914,11 +984,6 @@ int HeapEntry::RetainedSize(bool exact) {
914
984
  }
915
985
 
916
986
 
917
- List<HeapGraphPath*>* HeapEntry::GetRetainingPaths() {
918
- return snapshot_->GetRetainingPaths(this);
919
- }
920
-
921
-
922
987
  template<class Visitor>
923
988
  void HeapEntry::ApplyAndPaintAllReachable(Visitor* visitor) {
924
989
  List<HeapEntry*> list(10);
@@ -1009,6 +1074,7 @@ const char* HeapEntry::TypeAsString() {
1009
1074
  case kArray: return "/array/";
1010
1075
  case kRegExp: return "/regexp/";
1011
1076
  case kHeapNumber: return "/number/";
1077
+ case kNative: return "/native/";
1012
1078
  default: return "???";
1013
1079
  }
1014
1080
  }
@@ -1076,113 +1142,6 @@ void HeapEntry::CalculateExactRetainedSize() {
1076
1142
  }
1077
1143
 
1078
1144
 
1079
- class CachedHeapGraphPath {
1080
- public:
1081
- CachedHeapGraphPath()
1082
- : nodes_(NodesMatch) { }
1083
- CachedHeapGraphPath(const CachedHeapGraphPath& src)
1084
- : nodes_(NodesMatch, &HashMap::DefaultAllocator, src.nodes_.capacity()),
1085
- path_(src.path_.length() + 1) {
1086
- for (HashMap::Entry* p = src.nodes_.Start();
1087
- p != NULL;
1088
- p = src.nodes_.Next(p)) {
1089
- nodes_.Lookup(p->key, p->hash, true);
1090
- }
1091
- path_.AddAll(src.path_);
1092
- }
1093
- void Add(HeapGraphEdge* edge) {
1094
- nodes_.Lookup(edge->to(), Hash(edge->to()), true);
1095
- path_.Add(edge);
1096
- }
1097
- bool ContainsNode(HeapEntry* node) {
1098
- return nodes_.Lookup(node, Hash(node), false) != NULL;
1099
- }
1100
- const List<HeapGraphEdge*>* path() const { return &path_; }
1101
-
1102
- private:
1103
- static uint32_t Hash(HeapEntry* entry) {
1104
- return static_cast<uint32_t>(reinterpret_cast<intptr_t>(entry));
1105
- }
1106
- static bool NodesMatch(void* key1, void* key2) { return key1 == key2; }
1107
-
1108
- HashMap nodes_;
1109
- List<HeapGraphEdge*> path_;
1110
- };
1111
-
1112
-
1113
- List<HeapGraphPath*>* HeapEntry::CalculateRetainingPaths() {
1114
- List<HeapGraphPath*>* retaining_paths = new List<HeapGraphPath*>(4);
1115
- CachedHeapGraphPath path;
1116
- FindRetainingPaths(&path, retaining_paths);
1117
- return retaining_paths;
1118
- }
1119
-
1120
-
1121
- void HeapEntry::FindRetainingPaths(CachedHeapGraphPath* prev_path,
1122
- List<HeapGraphPath*>* retaining_paths) {
1123
- Vector<HeapGraphEdge*> rets = retainers();
1124
- for (int i = 0; i < rets.length(); ++i) {
1125
- HeapGraphEdge* ret_edge = rets[i];
1126
- if (prev_path->ContainsNode(ret_edge->From())) continue;
1127
- if (ret_edge->From() != snapshot()->root()) {
1128
- CachedHeapGraphPath path(*prev_path);
1129
- path.Add(ret_edge);
1130
- ret_edge->From()->FindRetainingPaths(&path, retaining_paths);
1131
- } else {
1132
- HeapGraphPath* ret_path = new HeapGraphPath(*prev_path->path());
1133
- ret_path->Set(0, ret_edge);
1134
- retaining_paths->Add(ret_path);
1135
- }
1136
- }
1137
- }
1138
-
1139
-
1140
- HeapGraphPath::HeapGraphPath(const List<HeapGraphEdge*>& path)
1141
- : path_(path.length() + 1) {
1142
- Add(NULL);
1143
- for (int i = path.length() - 1; i >= 0; --i) {
1144
- Add(path[i]);
1145
- }
1146
- }
1147
-
1148
-
1149
- void HeapGraphPath::Print() {
1150
- path_[0]->From()->Print(1, 0);
1151
- for (int i = 0; i < path_.length(); ++i) {
1152
- OS::Print(" -> ");
1153
- HeapGraphEdge* edge = path_[i];
1154
- switch (edge->type()) {
1155
- case HeapGraphEdge::kContextVariable:
1156
- OS::Print("[#%s] ", edge->name());
1157
- break;
1158
- case HeapGraphEdge::kElement:
1159
- case HeapGraphEdge::kHidden:
1160
- OS::Print("[%d] ", edge->index());
1161
- break;
1162
- case HeapGraphEdge::kInternal:
1163
- OS::Print("[$%s] ", edge->name());
1164
- break;
1165
- case HeapGraphEdge::kProperty:
1166
- OS::Print("[%s] ", edge->name());
1167
- break;
1168
- case HeapGraphEdge::kShortcut:
1169
- OS::Print("[^%s] ", edge->name());
1170
- break;
1171
- default:
1172
- OS::Print("!!! unknown edge type: %d ", edge->type());
1173
- }
1174
- edge->to()->Print(1, 0);
1175
- }
1176
- OS::Print("\n");
1177
- }
1178
-
1179
-
1180
- HeapObject *const HeapSnapshot::kInternalRootObject =
1181
- reinterpret_cast<HeapObject*>(1);
1182
- HeapObject *const HeapSnapshot::kGcRootsObject =
1183
- reinterpret_cast<HeapObject*>(2);
1184
-
1185
-
1186
1145
  // It is very important to keep objects that form a heap snapshot
1187
1146
  // as small as possible.
1188
1147
  namespace { // Avoid littering the global namespace.
@@ -1211,9 +1170,9 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1211
1170
  uid_(uid),
1212
1171
  root_entry_(NULL),
1213
1172
  gc_roots_entry_(NULL),
1173
+ natives_root_entry_(NULL),
1214
1174
  raw_entries_(NULL),
1215
- entries_sorted_(false),
1216
- retaining_paths_(HeapEntry::Match) {
1175
+ entries_sorted_(false) {
1217
1176
  STATIC_ASSERT(
1218
1177
  sizeof(HeapGraphEdge) ==
1219
1178
  SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapGraphEdgeSize); // NOLINT
@@ -1222,21 +1181,14 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1222
1181
  SnapshotSizeConstants<sizeof(void*)>::kExpectedHeapEntrySize); // NOLINT
1223
1182
  }
1224
1183
 
1225
-
1226
- static void DeleteHeapGraphPath(HeapGraphPath** path_ptr) {
1227
- delete *path_ptr;
1228
- }
1229
-
1230
1184
  HeapSnapshot::~HeapSnapshot() {
1231
1185
  DeleteArray(raw_entries_);
1232
- for (HashMap::Entry* p = retaining_paths_.Start();
1233
- p != NULL;
1234
- p = retaining_paths_.Next(p)) {
1235
- List<HeapGraphPath*>* list =
1236
- reinterpret_cast<List<HeapGraphPath*>*>(p->value);
1237
- list->Iterate(DeleteHeapGraphPath);
1238
- delete list;
1239
- }
1186
+ }
1187
+
1188
+
1189
+ void HeapSnapshot::Delete() {
1190
+ collection_->RemoveSnapshot(this);
1191
+ delete this;
1240
1192
  }
1241
1193
 
1242
1194
 
@@ -1253,96 +1205,6 @@ void HeapSnapshot::AllocateEntries(int entries_count,
1253
1205
  }
1254
1206
 
1255
1207
 
1256
- HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1257
- int children_count,
1258
- int retainers_count) {
1259
- if (object == kInternalRootObject) {
1260
- ASSERT(root_entry_ == NULL);
1261
- ASSERT(retainers_count == 0);
1262
- return (root_entry_ = AddEntry(HeapEntry::kObject,
1263
- "",
1264
- HeapObjectsMap::kInternalRootObjectId,
1265
- 0,
1266
- children_count,
1267
- retainers_count));
1268
- } else if (object == kGcRootsObject) {
1269
- ASSERT(gc_roots_entry_ == NULL);
1270
- return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1271
- "(GC roots)",
1272
- HeapObjectsMap::kGcRootsObjectId,
1273
- 0,
1274
- children_count,
1275
- retainers_count));
1276
- } else if (object->IsJSFunction()) {
1277
- JSFunction* func = JSFunction::cast(object);
1278
- SharedFunctionInfo* shared = func->shared();
1279
- return AddEntry(object,
1280
- HeapEntry::kClosure,
1281
- collection_->GetName(String::cast(shared->name())),
1282
- children_count,
1283
- retainers_count);
1284
- } else if (object->IsJSRegExp()) {
1285
- JSRegExp* re = JSRegExp::cast(object);
1286
- return AddEntry(object,
1287
- HeapEntry::kRegExp,
1288
- collection_->GetName(re->Pattern()),
1289
- children_count,
1290
- retainers_count);
1291
- } else if (object->IsJSObject()) {
1292
- return AddEntry(object,
1293
- HeapEntry::kObject,
1294
- collection_->GetName(GetConstructorNameForHeapProfile(
1295
- JSObject::cast(object))),
1296
- children_count,
1297
- retainers_count);
1298
- } else if (object->IsString()) {
1299
- return AddEntry(object,
1300
- HeapEntry::kString,
1301
- collection_->GetName(String::cast(object)),
1302
- children_count,
1303
- retainers_count);
1304
- } else if (object->IsCode()) {
1305
- return AddEntry(object,
1306
- HeapEntry::kCode,
1307
- "",
1308
- children_count,
1309
- retainers_count);
1310
- } else if (object->IsSharedFunctionInfo()) {
1311
- SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1312
- return AddEntry(object,
1313
- HeapEntry::kCode,
1314
- collection_->GetName(String::cast(shared->name())),
1315
- children_count,
1316
- retainers_count);
1317
- } else if (object->IsScript()) {
1318
- Script* script = Script::cast(object);
1319
- return AddEntry(object,
1320
- HeapEntry::kCode,
1321
- script->name()->IsString() ?
1322
- collection_->GetName(String::cast(script->name())) : "",
1323
- children_count,
1324
- retainers_count);
1325
- } else if (object->IsFixedArray()) {
1326
- return AddEntry(object,
1327
- HeapEntry::kArray,
1328
- "",
1329
- children_count,
1330
- retainers_count);
1331
- } else if (object->IsHeapNumber()) {
1332
- return AddEntry(object,
1333
- HeapEntry::kHeapNumber,
1334
- "number",
1335
- children_count,
1336
- retainers_count);
1337
- }
1338
- return AddEntry(object,
1339
- HeapEntry::kHidden,
1340
- "system",
1341
- children_count,
1342
- retainers_count);
1343
- }
1344
-
1345
-
1346
1208
  static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1347
1209
  (*entry_ptr)->clear_paint();
1348
1210
  }
@@ -1352,17 +1214,39 @@ void HeapSnapshot::ClearPaint() {
1352
1214
  }
1353
1215
 
1354
1216
 
1355
- HeapEntry* HeapSnapshot::AddEntry(HeapObject* object,
1356
- HeapEntry::Type type,
1357
- const char* name,
1358
- int children_count,
1359
- int retainers_count) {
1360
- return AddEntry(type,
1361
- name,
1362
- collection_->GetObjectId(object->address()),
1363
- object->Size(),
1364
- children_count,
1365
- retainers_count);
1217
+ HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
1218
+ ASSERT(root_entry_ == NULL);
1219
+ return (root_entry_ = AddEntry(HeapEntry::kObject,
1220
+ "",
1221
+ HeapObjectsMap::kInternalRootObjectId,
1222
+ 0,
1223
+ children_count,
1224
+ 0));
1225
+ }
1226
+
1227
+
1228
+ HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
1229
+ int retainers_count) {
1230
+ ASSERT(gc_roots_entry_ == NULL);
1231
+ return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1232
+ "(GC roots)",
1233
+ HeapObjectsMap::kGcRootsObjectId,
1234
+ 0,
1235
+ children_count,
1236
+ retainers_count));
1237
+ }
1238
+
1239
+
1240
+ HeapEntry* HeapSnapshot::AddNativesRootEntry(int children_count,
1241
+ int retainers_count) {
1242
+ ASSERT(natives_root_entry_ == NULL);
1243
+ return (natives_root_entry_ = AddEntry(
1244
+ HeapEntry::kObject,
1245
+ "(Native objects)",
1246
+ HeapObjectsMap::kNativesRootObjectId,
1247
+ 0,
1248
+ children_count,
1249
+ retainers_count));
1366
1250
  }
1367
1251
 
1368
1252
 
@@ -1400,14 +1284,7 @@ HeapEntry* HeapSnapshot::GetNextEntryToInit() {
1400
1284
  }
1401
1285
 
1402
1286
 
1403
- HeapSnapshotsDiff* HeapSnapshot::CompareWith(HeapSnapshot* snapshot) {
1404
- return collection_->CompareSnapshots(this, snapshot);
1405
- }
1406
-
1407
-
1408
1287
  HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) {
1409
- // GetSortedEntriesList is used in diff algorithm and sorts
1410
- // entries by their id.
1411
1288
  List<HeapEntry*>* entries_by_id = GetSortedEntriesList();
1412
1289
 
1413
1290
  // Perform a binary search by id.
@@ -1428,16 +1305,6 @@ HeapEntry* HeapSnapshot::GetEntryById(uint64_t id) {
1428
1305
  }
1429
1306
 
1430
1307
 
1431
- List<HeapGraphPath*>* HeapSnapshot::GetRetainingPaths(HeapEntry* entry) {
1432
- HashMap::Entry* p =
1433
- retaining_paths_.Lookup(entry, HeapEntry::Hash(entry), true);
1434
- if (p->value == NULL) {
1435
- p->value = entry->CalculateRetainingPaths();
1436
- }
1437
- return reinterpret_cast<List<HeapGraphPath*>*>(p->value);
1438
- }
1439
-
1440
-
1441
1308
  template<class T>
1442
1309
  static int SortByIds(const T* entry1_ptr,
1443
1310
  const T* entry2_ptr) {
@@ -1459,10 +1326,13 @@ void HeapSnapshot::Print(int max_depth) {
1459
1326
  }
1460
1327
 
1461
1328
 
1462
- const uint64_t HeapObjectsMap::kInternalRootObjectId = 0;
1463
- const uint64_t HeapObjectsMap::kGcRootsObjectId = 1;
1329
+ // We split IDs on evens for embedder objects (see
1330
+ // HeapObjectsMap::GenerateId) and odds for native objects.
1331
+ const uint64_t HeapObjectsMap::kInternalRootObjectId = 1;
1332
+ const uint64_t HeapObjectsMap::kGcRootsObjectId = 3;
1333
+ const uint64_t HeapObjectsMap::kNativesRootObjectId = 5;
1464
1334
  // Increase kFirstAvailableObjectId if new 'special' objects appear.
1465
- const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 2;
1335
+ const uint64_t HeapObjectsMap::kFirstAvailableObjectId = 7;
1466
1336
 
1467
1337
  HeapObjectsMap::HeapObjectsMap()
1468
1338
  : initial_fill_mode_(true),
@@ -1487,7 +1357,8 @@ uint64_t HeapObjectsMap::FindObject(Address addr) {
1487
1357
  uint64_t existing = FindEntry(addr);
1488
1358
  if (existing != 0) return existing;
1489
1359
  }
1490
- uint64_t id = next_id_++;
1360
+ uint64_t id = next_id_;
1361
+ next_id_ += 2;
1491
1362
  AddEntry(addr, id);
1492
1363
  return id;
1493
1364
  }
@@ -1555,6 +1426,17 @@ void HeapObjectsMap::RemoveDeadEntries() {
1555
1426
  }
1556
1427
 
1557
1428
 
1429
+ uint64_t HeapObjectsMap::GenerateId(v8::RetainedObjectInfo* info) {
1430
+ uint64_t id = static_cast<uint64_t>(info->GetHash());
1431
+ const char* label = info->GetLabel();
1432
+ id ^= HashSequentialString(label, static_cast<int>(strlen(label)));
1433
+ intptr_t element_count = info->GetElementCount();
1434
+ if (element_count != -1)
1435
+ id ^= ComputeIntegerHash(static_cast<uint32_t>(element_count));
1436
+ return id << 1;
1437
+ }
1438
+
1439
+
1558
1440
  HeapSnapshotsCollection::HeapSnapshotsCollection()
1559
1441
  : is_tracking_objects_(false),
1560
1442
  snapshots_uids_(HeapSnapshotsMatch),
@@ -1604,10 +1486,11 @@ HeapSnapshot* HeapSnapshotsCollection::GetSnapshot(unsigned uid) {
1604
1486
  }
1605
1487
 
1606
1488
 
1607
- HeapSnapshotsDiff* HeapSnapshotsCollection::CompareSnapshots(
1608
- HeapSnapshot* snapshot1,
1609
- HeapSnapshot* snapshot2) {
1610
- return comparator_.Compare(snapshot1, snapshot2);
1489
+ void HeapSnapshotsCollection::RemoveSnapshot(HeapSnapshot* snapshot) {
1490
+ snapshots_.RemoveElement(snapshot);
1491
+ unsigned uid = snapshot->uid();
1492
+ snapshots_uids_.Remove(reinterpret_cast<void*>(uid),
1493
+ static_cast<uint32_t>(uid));
1611
1494
  }
1612
1495
 
1613
1496
 
@@ -1615,7 +1498,7 @@ HeapEntry *const HeapEntriesMap::kHeapEntryPlaceholder =
1615
1498
  reinterpret_cast<HeapEntry*>(1);
1616
1499
 
1617
1500
  HeapEntriesMap::HeapEntriesMap()
1618
- : entries_(HeapObjectsMatch),
1501
+ : entries_(HeapThingsMatch),
1619
1502
  entries_count_(0),
1620
1503
  total_children_count_(0),
1621
1504
  total_retainers_count_(0) {
@@ -1629,8 +1512,25 @@ HeapEntriesMap::~HeapEntriesMap() {
1629
1512
  }
1630
1513
 
1631
1514
 
1632
- HeapEntry* HeapEntriesMap::Map(HeapObject* object) {
1633
- HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), false);
1515
+ void HeapEntriesMap::AllocateEntries() {
1516
+ for (HashMap::Entry* p = entries_.Start();
1517
+ p != NULL;
1518
+ p = entries_.Next(p)) {
1519
+ EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(p->value);
1520
+ entry_info->entry = entry_info->allocator->AllocateEntry(
1521
+ p->key,
1522
+ entry_info->children_count,
1523
+ entry_info->retainers_count);
1524
+ ASSERT(entry_info->entry != NULL);
1525
+ ASSERT(entry_info->entry != kHeapEntryPlaceholder);
1526
+ entry_info->children_count = 0;
1527
+ entry_info->retainers_count = 0;
1528
+ }
1529
+ }
1530
+
1531
+
1532
+ HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1533
+ HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1634
1534
  if (cache_entry != NULL) {
1635
1535
  EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
1636
1536
  return entry_info->entry;
@@ -1640,15 +1540,16 @@ HeapEntry* HeapEntriesMap::Map(HeapObject* object) {
1640
1540
  }
1641
1541
 
1642
1542
 
1643
- void HeapEntriesMap::Pair(HeapObject* object, HeapEntry* entry) {
1644
- HashMap::Entry* cache_entry = entries_.Lookup(object, Hash(object), true);
1543
+ void HeapEntriesMap::Pair(
1544
+ HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
1545
+ HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
1645
1546
  ASSERT(cache_entry->value == NULL);
1646
- cache_entry->value = new EntryInfo(entry);
1547
+ cache_entry->value = new EntryInfo(entry, allocator);
1647
1548
  ++entries_count_;
1648
1549
  }
1649
1550
 
1650
1551
 
1651
- void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to,
1552
+ void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
1652
1553
  int* prev_children_count,
1653
1554
  int* prev_retainers_count) {
1654
1555
  HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
@@ -1671,7 +1572,7 @@ void HeapEntriesMap::CountReference(HeapObject* from, HeapObject* to,
1671
1572
 
1672
1573
 
1673
1574
  HeapObjectsSet::HeapObjectsSet()
1674
- : entries_(HeapEntriesMap::HeapObjectsMatch) {
1575
+ : entries_(HeapEntriesMap::HeapThingsMatch) {
1675
1576
  }
1676
1577
 
1677
1578
 
@@ -1700,242 +1601,212 @@ void HeapObjectsSet::Insert(Object* obj) {
1700
1601
  }
1701
1602
 
1702
1603
 
1703
- HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
1704
- v8::ActivityControl* control)
1604
+ HeapObject *const V8HeapExplorer::kInternalRootObject =
1605
+ reinterpret_cast<HeapObject*>(
1606
+ static_cast<intptr_t>(HeapObjectsMap::kInternalRootObjectId));
1607
+ HeapObject *const V8HeapExplorer::kGcRootsObject =
1608
+ reinterpret_cast<HeapObject*>(
1609
+ static_cast<intptr_t>(HeapObjectsMap::kGcRootsObjectId));
1610
+
1611
+
1612
+ V8HeapExplorer::V8HeapExplorer(
1613
+ HeapSnapshot* snapshot,
1614
+ SnapshottingProgressReportingInterface* progress)
1705
1615
  : snapshot_(snapshot),
1706
- control_(control),
1707
- collection_(snapshot->collection()),
1616
+ collection_(snapshot_->collection()),
1617
+ progress_(progress),
1708
1618
  filler_(NULL) {
1709
1619
  }
1710
1620
 
1711
- class SnapshotCounter : public HeapSnapshotGenerator::SnapshotFillerInterface {
1712
- public:
1713
- explicit SnapshotCounter(HeapEntriesMap* entries)
1714
- : entries_(entries) { }
1715
- HeapEntry* AddEntry(HeapObject* obj) {
1716
- entries_->Pair(obj, HeapEntriesMap::kHeapEntryPlaceholder);
1717
- return HeapEntriesMap::kHeapEntryPlaceholder;
1718
- }
1719
- void SetIndexedReference(HeapGraphEdge::Type,
1720
- HeapObject* parent_obj,
1721
- HeapEntry*,
1722
- int,
1723
- Object* child_obj,
1724
- HeapEntry*) {
1725
- entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1726
- }
1727
- void SetNamedReference(HeapGraphEdge::Type,
1728
- HeapObject* parent_obj,
1729
- HeapEntry*,
1730
- const char*,
1731
- Object* child_obj,
1732
- HeapEntry*) {
1733
- entries_->CountReference(parent_obj, HeapObject::cast(child_obj));
1734
- }
1735
- void SetRootShortcutReference(Object* child_obj, HeapEntry*) {
1736
- entries_->CountReference(
1737
- HeapSnapshot::kInternalRootObject, HeapObject::cast(child_obj));
1738
- }
1739
- void SetRootGcRootsReference() {
1740
- entries_->CountReference(
1741
- HeapSnapshot::kInternalRootObject, HeapSnapshot::kGcRootsObject);
1742
- }
1743
- void SetStrongRootReference(Object* child_obj, HeapEntry*) {
1744
- entries_->CountReference(
1745
- HeapSnapshot::kGcRootsObject, HeapObject::cast(child_obj));
1746
- }
1747
- private:
1748
- HeapEntriesMap* entries_;
1749
- };
1750
1621
 
1622
+ V8HeapExplorer::~V8HeapExplorer() {
1623
+ }
1751
1624
 
1752
- class SnapshotFiller : public HeapSnapshotGenerator::SnapshotFillerInterface {
1753
- public:
1754
- explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
1755
- : snapshot_(snapshot),
1756
- collection_(snapshot->collection()),
1757
- entries_(entries) { }
1758
- HeapEntry* AddEntry(HeapObject* obj) {
1759
- UNREACHABLE();
1760
- return NULL;
1761
- }
1762
- void SetIndexedReference(HeapGraphEdge::Type type,
1763
- HeapObject* parent_obj,
1764
- HeapEntry* parent_entry,
1765
- int index,
1766
- Object* child_obj,
1767
- HeapEntry* child_entry) {
1768
- int child_index, retainer_index;
1769
- entries_->CountReference(parent_obj,
1770
- HeapObject::cast(child_obj),
1771
- &child_index,
1772
- &retainer_index);
1773
- parent_entry->SetIndexedReference(
1774
- type, child_index, index, child_entry, retainer_index);
1775
- }
1776
- void SetNamedReference(HeapGraphEdge::Type type,
1777
- HeapObject* parent_obj,
1778
- HeapEntry* parent_entry,
1779
- const char* reference_name,
1780
- Object* child_obj,
1781
- HeapEntry* child_entry) {
1782
- int child_index, retainer_index;
1783
- entries_->CountReference(parent_obj, HeapObject::cast(child_obj),
1784
- &child_index, &retainer_index);
1785
- parent_entry->SetNamedReference(type,
1786
- child_index,
1787
- reference_name,
1788
- child_entry,
1789
- retainer_index);
1790
- }
1791
- void SetRootGcRootsReference() {
1792
- int child_index, retainer_index;
1793
- entries_->CountReference(HeapSnapshot::kInternalRootObject,
1794
- HeapSnapshot::kGcRootsObject,
1795
- &child_index,
1796
- &retainer_index);
1797
- snapshot_->root()->SetIndexedReference(HeapGraphEdge::kElement,
1798
- child_index,
1799
- child_index + 1,
1800
- snapshot_->gc_roots(),
1801
- retainer_index);
1802
- }
1803
- void SetRootShortcutReference(Object* child_obj,
1804
- HeapEntry* child_entry) {
1805
- int child_index, retainer_index;
1806
- entries_->CountReference(HeapSnapshot::kInternalRootObject,
1807
- HeapObject::cast(child_obj),
1808
- &child_index,
1809
- &retainer_index);
1810
- snapshot_->root()->SetNamedReference(HeapGraphEdge::kShortcut,
1811
- child_index,
1812
- collection_->GetName(child_index + 1),
1813
- child_entry,
1814
- retainer_index);
1815
- }
1816
- void SetStrongRootReference(Object* child_obj,
1817
- HeapEntry* child_entry) {
1818
- int child_index, retainer_index;
1819
- entries_->CountReference(HeapSnapshot::kGcRootsObject,
1820
- HeapObject::cast(child_obj),
1821
- &child_index,
1822
- &retainer_index);
1823
- snapshot_->gc_roots()->SetIndexedReference(HeapGraphEdge::kElement,
1824
- child_index,
1825
- child_index + 1,
1826
- child_entry,
1827
- retainer_index);
1828
- }
1829
- private:
1830
- HeapSnapshot* snapshot_;
1831
- HeapSnapshotsCollection* collection_;
1832
- HeapEntriesMap* entries_;
1833
- };
1834
1625
 
1835
- class SnapshotAllocator {
1836
- public:
1837
- explicit SnapshotAllocator(HeapSnapshot* snapshot)
1838
- : snapshot_(snapshot) { }
1839
- HeapEntry* GetEntry(
1840
- HeapObject* obj, int children_count, int retainers_count) {
1841
- HeapEntry* entry =
1842
- snapshot_->AddEntry(obj, children_count, retainers_count);
1843
- ASSERT(entry != NULL);
1844
- return entry;
1845
- }
1846
- private:
1847
- HeapSnapshot* snapshot_;
1848
- };
1849
-
1850
- class RootsReferencesExtractor : public ObjectVisitor {
1851
- public:
1852
- explicit RootsReferencesExtractor(HeapSnapshotGenerator* generator)
1853
- : generator_(generator) {
1854
- }
1855
- void VisitPointers(Object** start, Object** end) {
1856
- for (Object** p = start; p < end; p++) generator_->SetGcRootsReference(*p);
1857
- }
1858
- private:
1859
- HeapSnapshotGenerator* generator_;
1860
- };
1626
+ HeapEntry* V8HeapExplorer::AllocateEntry(
1627
+ HeapThing ptr, int children_count, int retainers_count) {
1628
+ return AddEntry(
1629
+ reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
1630
+ }
1861
1631
 
1862
1632
 
1863
- bool HeapSnapshotGenerator::GenerateSnapshot() {
1864
- AssertNoAllocation no_alloc;
1633
+ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1634
+ int children_count,
1635
+ int retainers_count) {
1636
+ if (object == kInternalRootObject) {
1637
+ ASSERT(retainers_count == 0);
1638
+ return snapshot_->AddRootEntry(children_count);
1639
+ } else if (object == kGcRootsObject) {
1640
+ return snapshot_->AddGcRootsEntry(children_count, retainers_count);
1641
+ } else if (object->IsJSFunction()) {
1642
+ JSFunction* func = JSFunction::cast(object);
1643
+ SharedFunctionInfo* shared = func->shared();
1644
+ return AddEntry(object,
1645
+ HeapEntry::kClosure,
1646
+ collection_->names()->GetName(String::cast(shared->name())),
1647
+ children_count,
1648
+ retainers_count);
1649
+ } else if (object->IsJSRegExp()) {
1650
+ JSRegExp* re = JSRegExp::cast(object);
1651
+ return AddEntry(object,
1652
+ HeapEntry::kRegExp,
1653
+ collection_->names()->GetName(re->Pattern()),
1654
+ children_count,
1655
+ retainers_count);
1656
+ } else if (object->IsJSObject()) {
1657
+ return AddEntry(object,
1658
+ HeapEntry::kObject,
1659
+ collection_->names()->GetName(
1660
+ GetConstructorNameForHeapProfile(
1661
+ JSObject::cast(object))),
1662
+ children_count,
1663
+ retainers_count);
1664
+ } else if (object->IsString()) {
1665
+ return AddEntry(object,
1666
+ HeapEntry::kString,
1667
+ collection_->names()->GetName(String::cast(object)),
1668
+ children_count,
1669
+ retainers_count);
1670
+ } else if (object->IsCode()) {
1671
+ return AddEntry(object,
1672
+ HeapEntry::kCode,
1673
+ "",
1674
+ children_count,
1675
+ retainers_count);
1676
+ } else if (object->IsSharedFunctionInfo()) {
1677
+ SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1678
+ return AddEntry(object,
1679
+ HeapEntry::kCode,
1680
+ collection_->names()->GetName(String::cast(shared->name())),
1681
+ children_count,
1682
+ retainers_count);
1683
+ } else if (object->IsScript()) {
1684
+ Script* script = Script::cast(object);
1685
+ return AddEntry(object,
1686
+ HeapEntry::kCode,
1687
+ script->name()->IsString() ?
1688
+ collection_->names()->GetName(
1689
+ String::cast(script->name()))
1690
+ : "",
1691
+ children_count,
1692
+ retainers_count);
1693
+ } else if (object->IsFixedArray() || object->IsByteArray()) {
1694
+ return AddEntry(object,
1695
+ HeapEntry::kArray,
1696
+ "",
1697
+ children_count,
1698
+ retainers_count);
1699
+ } else if (object->IsHeapNumber()) {
1700
+ return AddEntry(object,
1701
+ HeapEntry::kHeapNumber,
1702
+ "number",
1703
+ children_count,
1704
+ retainers_count);
1705
+ }
1706
+ return AddEntry(object,
1707
+ HeapEntry::kHidden,
1708
+ GetSystemEntryName(object),
1709
+ children_count,
1710
+ retainers_count);
1711
+ }
1865
1712
 
1866
- SetProgressTotal(4); // 2 passes + dominators + sizes.
1867
1713
 
1868
- // Pass 1. Iterate heap contents to count entries and references.
1869
- if (!CountEntriesAndReferences()) return false;
1714
+ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1715
+ HeapEntry::Type type,
1716
+ const char* name,
1717
+ int children_count,
1718
+ int retainers_count) {
1719
+ return snapshot_->AddEntry(type,
1720
+ name,
1721
+ collection_->GetObjectId(object->address()),
1722
+ object->Size(),
1723
+ children_count,
1724
+ retainers_count);
1725
+ }
1870
1726
 
1871
- // Allocate and fill entries in the snapshot, allocate references.
1872
- snapshot_->AllocateEntries(entries_.entries_count(),
1873
- entries_.total_children_count(),
1874
- entries_.total_retainers_count());
1875
- SnapshotAllocator allocator(snapshot_);
1876
- entries_.UpdateEntries(&allocator);
1877
1727
 
1878
- // Pass 2. Fill references.
1879
- if (!FillReferences()) return false;
1728
+ void V8HeapExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
1729
+ filler->AddEntry(kInternalRootObject, this);
1730
+ filler->AddEntry(kGcRootsObject, this);
1731
+ }
1880
1732
 
1881
- if (!SetEntriesDominators()) return false;
1882
- if (!ApproximateRetainedSizes()) return false;
1883
1733
 
1884
- progress_counter_ = progress_total_;
1885
- if (!ReportProgress(true)) return false;
1886
- return true;
1734
+ const char* V8HeapExplorer::GetSystemEntryName(HeapObject* object) {
1735
+ switch (object->map()->instance_type()) {
1736
+ case MAP_TYPE: return "system / Map";
1737
+ case JS_GLOBAL_PROPERTY_CELL_TYPE: return "system / JSGlobalPropertyCell";
1738
+ case PROXY_TYPE: return "system / Proxy";
1739
+ case ODDBALL_TYPE: return "system / Oddball";
1740
+ #define MAKE_STRUCT_CASE(NAME, Name, name) \
1741
+ case NAME##_TYPE: return "system / "#Name;
1742
+ STRUCT_LIST(MAKE_STRUCT_CASE)
1743
+ #undef MAKE_STRUCT_CASE
1744
+ default: return "system";
1745
+ }
1887
1746
  }
1888
1747
 
1889
1748
 
1890
- HeapEntry* HeapSnapshotGenerator::GetEntry(Object* obj) {
1891
- if (!obj->IsHeapObject()) return NULL;
1892
- HeapObject* object = HeapObject::cast(obj);
1893
- HeapEntry* entry = entries_.Map(object);
1894
- // A new entry.
1895
- if (entry == NULL) entry = filler_->AddEntry(object);
1896
- return entry;
1749
+ int V8HeapExplorer::EstimateObjectsCount() {
1750
+ HeapIterator iterator(HeapIterator::kFilterUnreachable);
1751
+ int objects_count = 0;
1752
+ for (HeapObject* obj = iterator.next();
1753
+ obj != NULL;
1754
+ obj = iterator.next(), ++objects_count) {}
1755
+ return objects_count;
1897
1756
  }
1898
1757
 
1899
1758
 
1900
1759
  class IndexedReferencesExtractor : public ObjectVisitor {
1901
1760
  public:
1902
- IndexedReferencesExtractor(HeapSnapshotGenerator* generator,
1761
+ IndexedReferencesExtractor(V8HeapExplorer* generator,
1903
1762
  HeapObject* parent_obj,
1904
- HeapEntry* parent_entry,
1905
- HeapObjectsSet* known_references = NULL)
1763
+ HeapEntry* parent_entry)
1906
1764
  : generator_(generator),
1907
1765
  parent_obj_(parent_obj),
1908
1766
  parent_(parent_entry),
1909
- known_references_(known_references),
1910
1767
  next_index_(1) {
1911
1768
  }
1912
1769
  void VisitPointers(Object** start, Object** end) {
1913
1770
  for (Object** p = start; p < end; p++) {
1914
- if (!known_references_ || !known_references_->Contains(*p)) {
1915
- generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
1916
- }
1771
+ if (CheckVisitedAndUnmark(p)) continue;
1772
+ generator_->SetHiddenReference(parent_obj_, parent_, next_index_++, *p);
1917
1773
  }
1918
1774
  }
1775
+ static void MarkVisitedField(HeapObject* obj, int offset) {
1776
+ if (offset < 0) return;
1777
+ Address field = obj->address() + offset;
1778
+ ASSERT(!Memory::Object_at(field)->IsFailure());
1779
+ ASSERT(Memory::Object_at(field)->IsHeapObject());
1780
+ *field |= kFailureTag;
1781
+ }
1919
1782
  private:
1920
- HeapSnapshotGenerator* generator_;
1783
+ bool CheckVisitedAndUnmark(Object** field) {
1784
+ if ((*field)->IsFailure()) {
1785
+ intptr_t untagged = reinterpret_cast<intptr_t>(*field) & ~kFailureTagMask;
1786
+ *field = reinterpret_cast<Object*>(untagged | kHeapObjectTag);
1787
+ ASSERT((*field)->IsHeapObject());
1788
+ return true;
1789
+ }
1790
+ return false;
1791
+ }
1792
+ V8HeapExplorer* generator_;
1921
1793
  HeapObject* parent_obj_;
1922
1794
  HeapEntry* parent_;
1923
- HeapObjectsSet* known_references_;
1924
1795
  int next_index_;
1925
1796
  };
1926
1797
 
1927
1798
 
1928
- void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
1799
+ void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
1929
1800
  HeapEntry* entry = GetEntry(obj);
1930
1801
  if (entry == NULL) return; // No interest in this object.
1931
1802
 
1932
- known_references_.Clear();
1933
1803
  if (obj->IsJSGlobalProxy()) {
1934
1804
  // We need to reference JS global objects from snapshot's root.
1935
1805
  // We use JSGlobalProxy because this is what embedder (e.g. browser)
1936
1806
  // uses for the global object.
1937
1807
  JSGlobalProxy* proxy = JSGlobalProxy::cast(obj);
1938
1808
  SetRootShortcutReference(proxy->map()->prototype());
1809
+ SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
1939
1810
  IndexedReferencesExtractor refs_extractor(this, obj, entry);
1940
1811
  obj->Iterate(&refs_extractor);
1941
1812
  } else if (obj->IsJSObject()) {
@@ -1945,16 +1816,40 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
1945
1816
  ExtractElementReferences(js_obj, entry);
1946
1817
  ExtractInternalReferences(js_obj, entry);
1947
1818
  SetPropertyReference(
1948
- obj, entry, Heap::Proto_symbol(), js_obj->GetPrototype());
1819
+ obj, entry, HEAP->Proto_symbol(), js_obj->GetPrototype());
1949
1820
  if (obj->IsJSFunction()) {
1950
- JSFunction* js_fun = JSFunction::cast(obj);
1951
- if (js_fun->has_prototype()) {
1952
- SetPropertyReference(
1953
- obj, entry, Heap::prototype_symbol(), js_fun->prototype());
1821
+ JSFunction* js_fun = JSFunction::cast(js_obj);
1822
+ Object* proto_or_map = js_fun->prototype_or_initial_map();
1823
+ if (!proto_or_map->IsTheHole()) {
1824
+ if (!proto_or_map->IsMap()) {
1825
+ SetPropertyReference(
1826
+ obj, entry,
1827
+ HEAP->prototype_symbol(), proto_or_map,
1828
+ JSFunction::kPrototypeOrInitialMapOffset);
1829
+ } else {
1830
+ SetPropertyReference(
1831
+ obj, entry,
1832
+ HEAP->prototype_symbol(), js_fun->prototype());
1833
+ }
1954
1834
  }
1835
+ SetInternalReference(js_fun, entry,
1836
+ "shared", js_fun->shared(),
1837
+ JSFunction::kSharedFunctionInfoOffset);
1838
+ SetInternalReference(js_fun, entry,
1839
+ "context", js_fun->unchecked_context(),
1840
+ JSFunction::kContextOffset);
1841
+ SetInternalReference(js_fun, entry,
1842
+ "literals", js_fun->literals(),
1843
+ JSFunction::kLiteralsOffset);
1955
1844
  }
1956
- IndexedReferencesExtractor refs_extractor(
1957
- this, obj, entry, &known_references_);
1845
+ SetInternalReference(obj, entry,
1846
+ "properties", js_obj->properties(),
1847
+ JSObject::kPropertiesOffset);
1848
+ SetInternalReference(obj, entry,
1849
+ "elements", js_obj->elements(),
1850
+ JSObject::kElementsOffset);
1851
+ SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
1852
+ IndexedReferencesExtractor refs_extractor(this, obj, entry);
1958
1853
  obj->Iterate(&refs_extractor);
1959
1854
  } else if (obj->IsString()) {
1960
1855
  if (obj->IsConsString()) {
@@ -1962,15 +1857,49 @@ void HeapSnapshotGenerator::ExtractReferences(HeapObject* obj) {
1962
1857
  SetInternalReference(obj, entry, 1, cs->first());
1963
1858
  SetInternalReference(obj, entry, 2, cs->second());
1964
1859
  }
1860
+ } else if (obj->IsMap()) {
1861
+ Map* map = Map::cast(obj);
1862
+ SetInternalReference(obj, entry,
1863
+ "prototype", map->prototype(), Map::kPrototypeOffset);
1864
+ SetInternalReference(obj, entry,
1865
+ "constructor", map->constructor(),
1866
+ Map::kConstructorOffset);
1867
+ SetInternalReference(obj, entry,
1868
+ "descriptors", map->instance_descriptors(),
1869
+ Map::kInstanceDescriptorsOffset);
1870
+ SetInternalReference(obj, entry,
1871
+ "code_cache", map->code_cache(),
1872
+ Map::kCodeCacheOffset);
1873
+ SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
1874
+ IndexedReferencesExtractor refs_extractor(this, obj, entry);
1875
+ obj->Iterate(&refs_extractor);
1876
+ } else if (obj->IsSharedFunctionInfo()) {
1877
+ SharedFunctionInfo* shared = SharedFunctionInfo::cast(obj);
1878
+ SetInternalReference(obj, entry,
1879
+ "name", shared->name(),
1880
+ SharedFunctionInfo::kNameOffset);
1881
+ SetInternalReference(obj, entry,
1882
+ "code", shared->unchecked_code(),
1883
+ SharedFunctionInfo::kCodeOffset);
1884
+ SetInternalReference(obj, entry,
1885
+ "instance_class_name", shared->instance_class_name(),
1886
+ SharedFunctionInfo::kInstanceClassNameOffset);
1887
+ SetInternalReference(obj, entry,
1888
+ "script", shared->script(),
1889
+ SharedFunctionInfo::kScriptOffset);
1890
+ SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
1891
+ IndexedReferencesExtractor refs_extractor(this, obj, entry);
1892
+ obj->Iterate(&refs_extractor);
1965
1893
  } else {
1894
+ SetInternalReference(obj, entry, "map", obj->map(), HeapObject::kMapOffset);
1966
1895
  IndexedReferencesExtractor refs_extractor(this, obj, entry);
1967
1896
  obj->Iterate(&refs_extractor);
1968
1897
  }
1969
1898
  }
1970
1899
 
1971
1900
 
1972
- void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
1973
- HeapEntry* entry) {
1901
+ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
1902
+ HeapEntry* entry) {
1974
1903
  if (js_obj->IsJSFunction()) {
1975
1904
  HandleScope hs;
1976
1905
  JSFunction* func = JSFunction::cast(js_obj);
@@ -1987,26 +1916,34 @@ void HeapSnapshotGenerator::ExtractClosureReferences(JSObject* js_obj,
1987
1916
  SetClosureReference(js_obj, entry, local_name, context->get(idx));
1988
1917
  }
1989
1918
  }
1990
- SetInternalReference(js_obj, entry, "code", func->shared());
1991
1919
  }
1992
1920
  }
1993
1921
 
1994
1922
 
1995
- void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj,
1996
- HeapEntry* entry) {
1923
+ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
1924
+ HeapEntry* entry) {
1997
1925
  if (js_obj->HasFastProperties()) {
1998
1926
  DescriptorArray* descs = js_obj->map()->instance_descriptors();
1999
1927
  for (int i = 0; i < descs->number_of_descriptors(); i++) {
2000
1928
  switch (descs->GetType(i)) {
2001
1929
  case FIELD: {
2002
1930
  int index = descs->GetFieldIndex(i);
2003
- SetPropertyReference(
2004
- js_obj, entry, descs->GetKey(i), js_obj->FastPropertyAt(index));
1931
+ if (index < js_obj->map()->inobject_properties()) {
1932
+ SetPropertyReference(
1933
+ js_obj, entry,
1934
+ descs->GetKey(i), js_obj->InObjectPropertyAt(index),
1935
+ js_obj->GetInObjectPropertyOffset(index));
1936
+ } else {
1937
+ SetPropertyReference(
1938
+ js_obj, entry,
1939
+ descs->GetKey(i), js_obj->FastPropertyAt(index));
1940
+ }
2005
1941
  break;
2006
1942
  }
2007
1943
  case CONSTANT_FUNCTION:
2008
1944
  SetPropertyReference(
2009
- js_obj, entry, descs->GetKey(i), descs->GetConstantFunction(i));
1945
+ js_obj, entry,
1946
+ descs->GetKey(i), descs->GetConstantFunction(i));
2010
1947
  break;
2011
1948
  default: ;
2012
1949
  }
@@ -2034,8 +1971,8 @@ void HeapSnapshotGenerator::ExtractPropertyReferences(JSObject* js_obj,
2034
1971
  }
2035
1972
 
2036
1973
 
2037
- void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
2038
- HeapEntry* entry) {
1974
+ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
1975
+ HeapEntry* entry) {
2039
1976
  if (js_obj->HasFastElements()) {
2040
1977
  FixedArray* elements = FixedArray::cast(js_obj->elements());
2041
1978
  int length = js_obj->IsJSArray() ?
@@ -2061,37 +1998,82 @@ void HeapSnapshotGenerator::ExtractElementReferences(JSObject* js_obj,
2061
1998
  }
2062
1999
 
2063
2000
 
2064
- void HeapSnapshotGenerator::ExtractInternalReferences(JSObject* js_obj,
2065
- HeapEntry* entry) {
2001
+ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
2002
+ HeapEntry* entry) {
2066
2003
  int length = js_obj->GetInternalFieldCount();
2067
2004
  for (int i = 0; i < length; ++i) {
2068
2005
  Object* o = js_obj->GetInternalField(i);
2069
- SetInternalReference(js_obj, entry, i, o);
2006
+ SetInternalReference(
2007
+ js_obj, entry, i, o, js_obj->GetInternalFieldOffset(i));
2070
2008
  }
2071
2009
  }
2072
2010
 
2073
2011
 
2074
- void HeapSnapshotGenerator::SetClosureReference(HeapObject* parent_obj,
2075
- HeapEntry* parent_entry,
2076
- String* reference_name,
2077
- Object* child_obj) {
2012
+ HeapEntry* V8HeapExplorer::GetEntry(Object* obj) {
2013
+ if (!obj->IsHeapObject()) return NULL;
2014
+ return filler_->FindOrAddEntry(obj, this);
2015
+ }
2016
+
2017
+
2018
+ class RootsReferencesExtractor : public ObjectVisitor {
2019
+ public:
2020
+ explicit RootsReferencesExtractor(V8HeapExplorer* explorer)
2021
+ : explorer_(explorer) {
2022
+ }
2023
+ void VisitPointers(Object** start, Object** end) {
2024
+ for (Object** p = start; p < end; p++) explorer_->SetGcRootsReference(*p);
2025
+ }
2026
+ private:
2027
+ V8HeapExplorer* explorer_;
2028
+ };
2029
+
2030
+
2031
+ bool V8HeapExplorer::IterateAndExtractReferences(
2032
+ SnapshotFillerInterface* filler) {
2033
+ filler_ = filler;
2034
+ HeapIterator iterator(HeapIterator::kFilterUnreachable);
2035
+ bool interrupted = false;
2036
+ // Heap iteration with filtering must be finished in any case.
2037
+ for (HeapObject* obj = iterator.next();
2038
+ obj != NULL;
2039
+ obj = iterator.next(), progress_->ProgressStep()) {
2040
+ if (!interrupted) {
2041
+ ExtractReferences(obj);
2042
+ if (!progress_->ProgressReport(false)) interrupted = true;
2043
+ }
2044
+ }
2045
+ if (interrupted) {
2046
+ filler_ = NULL;
2047
+ return false;
2048
+ }
2049
+ SetRootGcRootsReference();
2050
+ RootsReferencesExtractor extractor(this);
2051
+ HEAP->IterateRoots(&extractor, VISIT_ALL);
2052
+ filler_ = NULL;
2053
+ return progress_->ProgressReport(false);
2054
+ }
2055
+
2056
+
2057
+ void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
2058
+ HeapEntry* parent_entry,
2059
+ String* reference_name,
2060
+ Object* child_obj) {
2078
2061
  HeapEntry* child_entry = GetEntry(child_obj);
2079
2062
  if (child_entry != NULL) {
2080
2063
  filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
2081
2064
  parent_obj,
2082
2065
  parent_entry,
2083
- collection_->GetName(reference_name),
2066
+ collection_->names()->GetName(reference_name),
2084
2067
  child_obj,
2085
2068
  child_entry);
2086
- known_references_.Insert(child_obj);
2087
2069
  }
2088
2070
  }
2089
2071
 
2090
2072
 
2091
- void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj,
2092
- HeapEntry* parent_entry,
2093
- int index,
2094
- Object* child_obj) {
2073
+ void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
2074
+ HeapEntry* parent_entry,
2075
+ int index,
2076
+ Object* child_obj) {
2095
2077
  HeapEntry* child_entry = GetEntry(child_obj);
2096
2078
  if (child_entry != NULL) {
2097
2079
  filler_->SetIndexedReference(HeapGraphEdge::kElement,
@@ -2100,15 +2082,15 @@ void HeapSnapshotGenerator::SetElementReference(HeapObject* parent_obj,
2100
2082
  index,
2101
2083
  child_obj,
2102
2084
  child_entry);
2103
- known_references_.Insert(child_obj);
2104
2085
  }
2105
2086
  }
2106
2087
 
2107
2088
 
2108
- void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
2109
- HeapEntry* parent_entry,
2110
- const char* reference_name,
2111
- Object* child_obj) {
2089
+ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2090
+ HeapEntry* parent_entry,
2091
+ const char* reference_name,
2092
+ Object* child_obj,
2093
+ int field_offset) {
2112
2094
  HeapEntry* child_entry = GetEntry(child_obj);
2113
2095
  if (child_entry != NULL) {
2114
2096
  filler_->SetNamedReference(HeapGraphEdge::kInternal,
@@ -2117,32 +2099,33 @@ void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
2117
2099
  reference_name,
2118
2100
  child_obj,
2119
2101
  child_entry);
2120
- known_references_.Insert(child_obj);
2102
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2121
2103
  }
2122
2104
  }
2123
2105
 
2124
2106
 
2125
- void HeapSnapshotGenerator::SetInternalReference(HeapObject* parent_obj,
2126
- HeapEntry* parent_entry,
2127
- int index,
2128
- Object* child_obj) {
2107
+ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2108
+ HeapEntry* parent_entry,
2109
+ int index,
2110
+ Object* child_obj,
2111
+ int field_offset) {
2129
2112
  HeapEntry* child_entry = GetEntry(child_obj);
2130
2113
  if (child_entry != NULL) {
2131
2114
  filler_->SetNamedReference(HeapGraphEdge::kInternal,
2132
2115
  parent_obj,
2133
2116
  parent_entry,
2134
- collection_->GetName(index),
2117
+ collection_->names()->GetName(index),
2135
2118
  child_obj,
2136
2119
  child_entry);
2137
- known_references_.Insert(child_obj);
2120
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2138
2121
  }
2139
2122
  }
2140
2123
 
2141
2124
 
2142
- void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj,
2143
- HeapEntry* parent_entry,
2144
- int index,
2145
- Object* child_obj) {
2125
+ void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
2126
+ HeapEntry* parent_entry,
2127
+ int index,
2128
+ Object* child_obj) {
2146
2129
  HeapEntry* child_entry = GetEntry(child_obj);
2147
2130
  if (child_entry != NULL) {
2148
2131
  filler_->SetIndexedReference(HeapGraphEdge::kHidden,
@@ -2155,10 +2138,11 @@ void HeapSnapshotGenerator::SetHiddenReference(HeapObject* parent_obj,
2155
2138
  }
2156
2139
 
2157
2140
 
2158
- void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
2159
- HeapEntry* parent_entry,
2160
- String* reference_name,
2161
- Object* child_obj) {
2141
+ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2142
+ HeapEntry* parent_entry,
2143
+ String* reference_name,
2144
+ Object* child_obj,
2145
+ int field_offset) {
2162
2146
  HeapEntry* child_entry = GetEntry(child_obj);
2163
2147
  if (child_entry != NULL) {
2164
2148
  HeapGraphEdge::Type type = reference_name->length() > 0 ?
@@ -2166,77 +2150,446 @@ void HeapSnapshotGenerator::SetPropertyReference(HeapObject* parent_obj,
2166
2150
  filler_->SetNamedReference(type,
2167
2151
  parent_obj,
2168
2152
  parent_entry,
2169
- collection_->GetName(reference_name),
2153
+ collection_->names()->GetName(reference_name),
2170
2154
  child_obj,
2171
2155
  child_entry);
2172
- known_references_.Insert(child_obj);
2156
+ IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2173
2157
  }
2174
2158
  }
2175
2159
 
2176
2160
 
2177
- void HeapSnapshotGenerator::SetPropertyShortcutReference(
2178
- HeapObject* parent_obj,
2179
- HeapEntry* parent_entry,
2180
- String* reference_name,
2181
- Object* child_obj) {
2161
+ void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
2162
+ HeapEntry* parent_entry,
2163
+ String* reference_name,
2164
+ Object* child_obj) {
2182
2165
  HeapEntry* child_entry = GetEntry(child_obj);
2183
2166
  if (child_entry != NULL) {
2184
2167
  filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2185
2168
  parent_obj,
2186
2169
  parent_entry,
2187
- collection_->GetName(reference_name),
2170
+ collection_->names()->GetName(reference_name),
2188
2171
  child_obj,
2189
2172
  child_entry);
2190
2173
  }
2191
2174
  }
2192
2175
 
2193
2176
 
2194
- void HeapSnapshotGenerator::SetRootGcRootsReference() {
2195
- filler_->SetRootGcRootsReference();
2177
+ void V8HeapExplorer::SetRootGcRootsReference() {
2178
+ filler_->SetIndexedAutoIndexReference(
2179
+ HeapGraphEdge::kElement,
2180
+ kInternalRootObject, snapshot_->root(),
2181
+ kGcRootsObject, snapshot_->gc_roots());
2196
2182
  }
2197
2183
 
2198
2184
 
2199
- void HeapSnapshotGenerator::SetRootShortcutReference(Object* child_obj) {
2185
+ void V8HeapExplorer::SetRootShortcutReference(Object* child_obj) {
2200
2186
  HeapEntry* child_entry = GetEntry(child_obj);
2201
2187
  ASSERT(child_entry != NULL);
2202
- filler_->SetRootShortcutReference(child_obj, child_entry);
2188
+ filler_->SetNamedAutoIndexReference(
2189
+ HeapGraphEdge::kShortcut,
2190
+ kInternalRootObject, snapshot_->root(),
2191
+ child_obj, child_entry);
2203
2192
  }
2204
2193
 
2205
2194
 
2206
- void HeapSnapshotGenerator::SetGcRootsReference(Object* child_obj) {
2195
+ void V8HeapExplorer::SetGcRootsReference(Object* child_obj) {
2207
2196
  HeapEntry* child_entry = GetEntry(child_obj);
2208
2197
  if (child_entry != NULL) {
2209
- filler_->SetStrongRootReference(child_obj, child_entry);
2198
+ filler_->SetIndexedAutoIndexReference(
2199
+ HeapGraphEdge::kElement,
2200
+ kGcRootsObject, snapshot_->gc_roots(),
2201
+ child_obj, child_entry);
2202
+ }
2203
+ }
2204
+
2205
+
2206
+ class GlobalHandlesExtractor : public ObjectVisitor {
2207
+ public:
2208
+ explicit GlobalHandlesExtractor(NativeObjectsExplorer* explorer)
2209
+ : explorer_(explorer) {}
2210
+ virtual ~GlobalHandlesExtractor() {}
2211
+ virtual void VisitPointers(Object** start, Object** end) {
2212
+ UNREACHABLE();
2213
+ }
2214
+ virtual void VisitEmbedderReference(Object** p, uint16_t class_id) {
2215
+ explorer_->VisitSubtreeWrapper(p, class_id);
2216
+ }
2217
+ private:
2218
+ NativeObjectsExplorer* explorer_;
2219
+ };
2220
+
2221
+ HeapThing const NativeObjectsExplorer::kNativesRootObject =
2222
+ reinterpret_cast<HeapThing>(
2223
+ static_cast<intptr_t>(HeapObjectsMap::kNativesRootObjectId));
2224
+
2225
+
2226
+ NativeObjectsExplorer::NativeObjectsExplorer(
2227
+ HeapSnapshot* snapshot, SnapshottingProgressReportingInterface* progress)
2228
+ : snapshot_(snapshot),
2229
+ collection_(snapshot_->collection()),
2230
+ progress_(progress),
2231
+ embedder_queried_(false),
2232
+ objects_by_info_(RetainedInfosMatch),
2233
+ filler_(NULL) {
2234
+ }
2235
+
2236
+
2237
+ NativeObjectsExplorer::~NativeObjectsExplorer() {
2238
+ for (HashMap::Entry* p = objects_by_info_.Start();
2239
+ p != NULL;
2240
+ p = objects_by_info_.Next(p)) {
2241
+ v8::RetainedObjectInfo* info =
2242
+ reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
2243
+ info->Dispose();
2244
+ List<HeapObject*>* objects =
2245
+ reinterpret_cast<List<HeapObject*>* >(p->value);
2246
+ delete objects;
2247
+ }
2248
+ }
2249
+
2250
+
2251
+ HeapEntry* NativeObjectsExplorer::AllocateEntry(
2252
+ HeapThing ptr, int children_count, int retainers_count) {
2253
+ if (ptr == kNativesRootObject) {
2254
+ return snapshot_->AddNativesRootEntry(children_count, retainers_count);
2255
+ } else {
2256
+ v8::RetainedObjectInfo* info =
2257
+ reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
2258
+ intptr_t elements = info->GetElementCount();
2259
+ intptr_t size = info->GetSizeInBytes();
2260
+ return snapshot_->AddEntry(
2261
+ HeapEntry::kNative,
2262
+ elements != -1 ?
2263
+ collection_->names()->GetFormatted(
2264
+ "%s / %" V8_PTR_PREFIX "d entries",
2265
+ info->GetLabel(),
2266
+ info->GetElementCount()) :
2267
+ collection_->names()->GetCopy(info->GetLabel()),
2268
+ HeapObjectsMap::GenerateId(info),
2269
+ size != -1 ? static_cast<int>(size) : 0,
2270
+ children_count,
2271
+ retainers_count);
2272
+ }
2273
+ }
2274
+
2275
+
2276
+ void NativeObjectsExplorer::AddRootEntries(SnapshotFillerInterface* filler) {
2277
+ if (EstimateObjectsCount() <= 0) return;
2278
+ filler->AddEntry(kNativesRootObject, this);
2279
+ }
2280
+
2281
+
2282
+ int NativeObjectsExplorer::EstimateObjectsCount() {
2283
+ FillRetainedObjects();
2284
+ return objects_by_info_.occupancy();
2285
+ }
2286
+
2287
+
2288
+ void NativeObjectsExplorer::FillRetainedObjects() {
2289
+ if (embedder_queried_) return;
2290
+ Isolate* isolate = Isolate::Current();
2291
+ // Record objects that are joined into ObjectGroups.
2292
+ isolate->heap()->CallGlobalGCPrologueCallback();
2293
+ List<ObjectGroup*>* groups = isolate->global_handles()->object_groups();
2294
+ for (int i = 0; i < groups->length(); ++i) {
2295
+ ObjectGroup* group = groups->at(i);
2296
+ if (group->info_ == NULL) continue;
2297
+ List<HeapObject*>* list = GetListMaybeDisposeInfo(group->info_);
2298
+ for (int j = 0; j < group->objects_.length(); ++j) {
2299
+ HeapObject* obj = HeapObject::cast(*group->objects_[j]);
2300
+ list->Add(obj);
2301
+ in_groups_.Insert(obj);
2302
+ }
2303
+ group->info_ = NULL; // Acquire info object ownership.
2304
+ }
2305
+ isolate->global_handles()->RemoveObjectGroups();
2306
+ isolate->heap()->CallGlobalGCEpilogueCallback();
2307
+ // Record objects that are not in ObjectGroups, but have class ID.
2308
+ GlobalHandlesExtractor extractor(this);
2309
+ isolate->global_handles()->IterateAllRootsWithClassIds(&extractor);
2310
+ embedder_queried_ = true;
2311
+ }
2312
+
2313
+
2314
+ List<HeapObject*>* NativeObjectsExplorer::GetListMaybeDisposeInfo(
2315
+ v8::RetainedObjectInfo* info) {
2316
+ HashMap::Entry* entry =
2317
+ objects_by_info_.Lookup(info, InfoHash(info), true);
2318
+ if (entry->value != NULL) {
2319
+ info->Dispose();
2320
+ } else {
2321
+ entry->value = new List<HeapObject*>(4);
2322
+ }
2323
+ return reinterpret_cast<List<HeapObject*>* >(entry->value);
2324
+ }
2325
+
2326
+
2327
+ bool NativeObjectsExplorer::IterateAndExtractReferences(
2328
+ SnapshotFillerInterface* filler) {
2329
+ if (EstimateObjectsCount() <= 0) return true;
2330
+ filler_ = filler;
2331
+ FillRetainedObjects();
2332
+ for (HashMap::Entry* p = objects_by_info_.Start();
2333
+ p != NULL;
2334
+ p = objects_by_info_.Next(p)) {
2335
+ v8::RetainedObjectInfo* info =
2336
+ reinterpret_cast<v8::RetainedObjectInfo*>(p->key);
2337
+ SetNativeRootReference(info);
2338
+ List<HeapObject*>* objects =
2339
+ reinterpret_cast<List<HeapObject*>* >(p->value);
2340
+ for (int i = 0; i < objects->length(); ++i) {
2341
+ SetWrapperNativeReferences(objects->at(i), info);
2342
+ }
2343
+ }
2344
+ SetRootNativesRootReference();
2345
+ filler_ = NULL;
2346
+ return true;
2347
+ }
2348
+
2349
+
2350
+ void NativeObjectsExplorer::SetNativeRootReference(
2351
+ v8::RetainedObjectInfo* info) {
2352
+ HeapEntry* child_entry = filler_->FindOrAddEntry(info, this);
2353
+ ASSERT(child_entry != NULL);
2354
+ filler_->SetIndexedAutoIndexReference(
2355
+ HeapGraphEdge::kElement,
2356
+ kNativesRootObject, snapshot_->natives_root(),
2357
+ info, child_entry);
2358
+ }
2359
+
2360
+
2361
+ void NativeObjectsExplorer::SetWrapperNativeReferences(
2362
+ HeapObject* wrapper, v8::RetainedObjectInfo* info) {
2363
+ HeapEntry* wrapper_entry = filler_->FindEntry(wrapper);
2364
+ ASSERT(wrapper_entry != NULL);
2365
+ HeapEntry* info_entry = filler_->FindOrAddEntry(info, this);
2366
+ ASSERT(info_entry != NULL);
2367
+ filler_->SetNamedReference(HeapGraphEdge::kInternal,
2368
+ wrapper, wrapper_entry,
2369
+ "native",
2370
+ info, info_entry);
2371
+ filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
2372
+ info, info_entry,
2373
+ wrapper, wrapper_entry);
2374
+ }
2375
+
2376
+
2377
+ void NativeObjectsExplorer::SetRootNativesRootReference() {
2378
+ filler_->SetIndexedAutoIndexReference(
2379
+ HeapGraphEdge::kElement,
2380
+ V8HeapExplorer::kInternalRootObject, snapshot_->root(),
2381
+ kNativesRootObject, snapshot_->natives_root());
2382
+ }
2383
+
2384
+
2385
+ void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
2386
+ if (in_groups_.Contains(*p)) return;
2387
+ Isolate* isolate = Isolate::Current();
2388
+ v8::RetainedObjectInfo* info =
2389
+ isolate->heap_profiler()->ExecuteWrapperClassCallback(class_id, p);
2390
+ if (info == NULL) return;
2391
+ GetListMaybeDisposeInfo(info)->Add(HeapObject::cast(*p));
2392
+ }
2393
+
2394
+
2395
+ HeapSnapshotGenerator::HeapSnapshotGenerator(HeapSnapshot* snapshot,
2396
+ v8::ActivityControl* control)
2397
+ : snapshot_(snapshot),
2398
+ control_(control),
2399
+ v8_heap_explorer_(snapshot_, this),
2400
+ dom_explorer_(snapshot_, this) {
2401
+ }
2402
+
2403
+
2404
+ class SnapshotCounter : public SnapshotFillerInterface {
2405
+ public:
2406
+ explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
2407
+ HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2408
+ entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
2409
+ return HeapEntriesMap::kHeapEntryPlaceholder;
2410
+ }
2411
+ HeapEntry* FindEntry(HeapThing ptr) {
2412
+ return entries_->Map(ptr);
2413
+ }
2414
+ HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2415
+ HeapEntry* entry = FindEntry(ptr);
2416
+ return entry != NULL ? entry : AddEntry(ptr, allocator);
2417
+ }
2418
+ void SetIndexedReference(HeapGraphEdge::Type,
2419
+ HeapThing parent_ptr,
2420
+ HeapEntry*,
2421
+ int,
2422
+ HeapThing child_ptr,
2423
+ HeapEntry*) {
2424
+ entries_->CountReference(parent_ptr, child_ptr);
2425
+ }
2426
+ void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
2427
+ HeapThing parent_ptr,
2428
+ HeapEntry*,
2429
+ HeapThing child_ptr,
2430
+ HeapEntry*) {
2431
+ entries_->CountReference(parent_ptr, child_ptr);
2432
+ }
2433
+ void SetNamedReference(HeapGraphEdge::Type,
2434
+ HeapThing parent_ptr,
2435
+ HeapEntry*,
2436
+ const char*,
2437
+ HeapThing child_ptr,
2438
+ HeapEntry*) {
2439
+ entries_->CountReference(parent_ptr, child_ptr);
2440
+ }
2441
+ void SetNamedAutoIndexReference(HeapGraphEdge::Type,
2442
+ HeapThing parent_ptr,
2443
+ HeapEntry*,
2444
+ HeapThing child_ptr,
2445
+ HeapEntry*) {
2446
+ entries_->CountReference(parent_ptr, child_ptr);
2447
+ }
2448
+ private:
2449
+ HeapEntriesMap* entries_;
2450
+ };
2451
+
2452
+
2453
+ class SnapshotFiller : public SnapshotFillerInterface {
2454
+ public:
2455
+ explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
2456
+ : snapshot_(snapshot),
2457
+ collection_(snapshot->collection()),
2458
+ entries_(entries) { }
2459
+ HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2460
+ UNREACHABLE();
2461
+ return NULL;
2462
+ }
2463
+ HeapEntry* FindEntry(HeapThing ptr) {
2464
+ return entries_->Map(ptr);
2465
+ }
2466
+ HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
2467
+ HeapEntry* entry = FindEntry(ptr);
2468
+ return entry != NULL ? entry : AddEntry(ptr, allocator);
2469
+ }
2470
+ void SetIndexedReference(HeapGraphEdge::Type type,
2471
+ HeapThing parent_ptr,
2472
+ HeapEntry* parent_entry,
2473
+ int index,
2474
+ HeapThing child_ptr,
2475
+ HeapEntry* child_entry) {
2476
+ int child_index, retainer_index;
2477
+ entries_->CountReference(
2478
+ parent_ptr, child_ptr, &child_index, &retainer_index);
2479
+ parent_entry->SetIndexedReference(
2480
+ type, child_index, index, child_entry, retainer_index);
2481
+ }
2482
+ void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
2483
+ HeapThing parent_ptr,
2484
+ HeapEntry* parent_entry,
2485
+ HeapThing child_ptr,
2486
+ HeapEntry* child_entry) {
2487
+ int child_index, retainer_index;
2488
+ entries_->CountReference(
2489
+ parent_ptr, child_ptr, &child_index, &retainer_index);
2490
+ parent_entry->SetIndexedReference(
2491
+ type, child_index, child_index + 1, child_entry, retainer_index);
2492
+ }
2493
+ void SetNamedReference(HeapGraphEdge::Type type,
2494
+ HeapThing parent_ptr,
2495
+ HeapEntry* parent_entry,
2496
+ const char* reference_name,
2497
+ HeapThing child_ptr,
2498
+ HeapEntry* child_entry) {
2499
+ int child_index, retainer_index;
2500
+ entries_->CountReference(
2501
+ parent_ptr, child_ptr, &child_index, &retainer_index);
2502
+ parent_entry->SetNamedReference(
2503
+ type, child_index, reference_name, child_entry, retainer_index);
2504
+ }
2505
+ void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
2506
+ HeapThing parent_ptr,
2507
+ HeapEntry* parent_entry,
2508
+ HeapThing child_ptr,
2509
+ HeapEntry* child_entry) {
2510
+ int child_index, retainer_index;
2511
+ entries_->CountReference(
2512
+ parent_ptr, child_ptr, &child_index, &retainer_index);
2513
+ parent_entry->SetNamedReference(type,
2514
+ child_index,
2515
+ collection_->names()->GetName(child_index + 1),
2516
+ child_entry,
2517
+ retainer_index);
2210
2518
  }
2519
+ private:
2520
+ HeapSnapshot* snapshot_;
2521
+ HeapSnapshotsCollection* collection_;
2522
+ HeapEntriesMap* entries_;
2523
+ };
2524
+
2525
+
2526
+ bool HeapSnapshotGenerator::GenerateSnapshot() {
2527
+ AssertNoAllocation no_alloc;
2528
+
2529
+ SetProgressTotal(4); // 2 passes + dominators + sizes.
2530
+
2531
+ // Pass 1. Iterate heap contents to count entries and references.
2532
+ if (!CountEntriesAndReferences()) return false;
2533
+
2534
+ // Allocate and fill entries in the snapshot, allocate references.
2535
+ snapshot_->AllocateEntries(entries_.entries_count(),
2536
+ entries_.total_children_count(),
2537
+ entries_.total_retainers_count());
2538
+ entries_.AllocateEntries();
2539
+
2540
+ // Pass 2. Fill references.
2541
+ if (!FillReferences()) return false;
2542
+
2543
+ if (!SetEntriesDominators()) return false;
2544
+ if (!ApproximateRetainedSizes()) return false;
2545
+
2546
+ progress_counter_ = progress_total_;
2547
+ if (!ProgressReport(true)) return false;
2548
+ return true;
2549
+ }
2550
+
2551
+
2552
+ void HeapSnapshotGenerator::ProgressStep() {
2553
+ ++progress_counter_;
2554
+ }
2555
+
2556
+
2557
+ bool HeapSnapshotGenerator::ProgressReport(bool force) {
2558
+ const int kProgressReportGranularity = 10000;
2559
+ if (control_ != NULL
2560
+ && (force || progress_counter_ % kProgressReportGranularity == 0)) {
2561
+ return
2562
+ control_->ReportProgressValue(progress_counter_, progress_total_) ==
2563
+ v8::ActivityControl::kContinue;
2564
+ }
2565
+ return true;
2211
2566
  }
2212
2567
 
2213
2568
 
2214
2569
  void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
2215
2570
  if (control_ == NULL) return;
2216
-
2217
- HeapIterator iterator(HeapIterator::kFilterUnreachable);
2218
- int objects_count = 0;
2219
- for (HeapObject* obj = iterator.next();
2220
- obj != NULL;
2221
- obj = iterator.next(), ++objects_count) {}
2222
- progress_total_ = objects_count * iterations_count;
2571
+ progress_total_ = (
2572
+ v8_heap_explorer_.EstimateObjectsCount() +
2573
+ dom_explorer_.EstimateObjectsCount()) * iterations_count;
2223
2574
  progress_counter_ = 0;
2224
2575
  }
2225
2576
 
2226
2577
 
2227
2578
  bool HeapSnapshotGenerator::CountEntriesAndReferences() {
2228
2579
  SnapshotCounter counter(&entries_);
2229
- filler_ = &counter;
2230
- filler_->AddEntry(HeapSnapshot::kInternalRootObject);
2231
- filler_->AddEntry(HeapSnapshot::kGcRootsObject);
2232
- return IterateAndExtractReferences();
2580
+ v8_heap_explorer_.AddRootEntries(&counter);
2581
+ dom_explorer_.AddRootEntries(&counter);
2582
+ return
2583
+ v8_heap_explorer_.IterateAndExtractReferences(&counter) &&
2584
+ dom_explorer_.IterateAndExtractReferences(&counter);
2233
2585
  }
2234
2586
 
2235
2587
 
2236
2588
  bool HeapSnapshotGenerator::FillReferences() {
2237
2589
  SnapshotFiller filler(snapshot_, &entries_);
2238
- filler_ = &filler;
2239
- return IterateAndExtractReferences();
2590
+ return
2591
+ v8_heap_explorer_.IterateAndExtractReferences(&filler) &&
2592
+ dom_explorer_.IterateAndExtractReferences(&filler);
2240
2593
  }
2241
2594
 
2242
2595
 
@@ -2322,7 +2675,7 @@ bool HeapSnapshotGenerator::BuildDominatorTree(
2322
2675
  int remaining = entries_length - changed;
2323
2676
  if (remaining < 0) remaining = 0;
2324
2677
  progress_counter_ = base_progress_counter + remaining;
2325
- if (!ReportProgress(true)) return false;
2678
+ if (!ProgressReport(true)) return false;
2326
2679
  }
2327
2680
  return true;
2328
2681
  }
@@ -2352,7 +2705,7 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
2352
2705
  }
2353
2706
  for (int i = 0;
2354
2707
  i < snapshot_->entries()->length();
2355
- ++i, IncProgressCounter()) {
2708
+ ++i, ProgressStep()) {
2356
2709
  HeapEntry* entry = snapshot_->entries()->at(i);
2357
2710
  int entry_size = entry->self_size();
2358
2711
  for (HeapEntry* dominator = entry->dominator();
@@ -2360,109 +2713,12 @@ bool HeapSnapshotGenerator::ApproximateRetainedSizes() {
2360
2713
  entry = dominator, dominator = entry->dominator()) {
2361
2714
  dominator->add_retained_size(entry_size);
2362
2715
  }
2363
- if (!ReportProgress()) return false;
2716
+ if (!ProgressReport()) return false;
2364
2717
  }
2365
2718
  return true;
2366
2719
  }
2367
2720
 
2368
2721
 
2369
- bool HeapSnapshotGenerator::IterateAndExtractReferences() {
2370
- HeapIterator iterator(HeapIterator::kFilterUnreachable);
2371
- bool interrupted = false;
2372
- // Heap iteration with filtering must be finished in any case.
2373
- for (HeapObject* obj = iterator.next();
2374
- obj != NULL;
2375
- obj = iterator.next(), IncProgressCounter()) {
2376
- if (!interrupted) {
2377
- ExtractReferences(obj);
2378
- if (!ReportProgress()) interrupted = true;
2379
- }
2380
- }
2381
- if (interrupted) return false;
2382
- SetRootGcRootsReference();
2383
- RootsReferencesExtractor extractor(this);
2384
- Heap::IterateRoots(&extractor, VISIT_ALL);
2385
- return ReportProgress();
2386
- }
2387
-
2388
-
2389
- void HeapSnapshotsDiff::CreateRoots(int additions_count, int deletions_count) {
2390
- raw_additions_root_ =
2391
- NewArray<char>(HeapEntry::EntriesSize(1, additions_count, 0));
2392
- additions_root()->Init(
2393
- snapshot2_, HeapEntry::kHidden, "", 0, 0, additions_count, 0);
2394
- raw_deletions_root_ =
2395
- NewArray<char>(HeapEntry::EntriesSize(1, deletions_count, 0));
2396
- deletions_root()->Init(
2397
- snapshot1_, HeapEntry::kHidden, "", 0, 0, deletions_count, 0);
2398
- }
2399
-
2400
-
2401
- static void DeleteHeapSnapshotsDiff(HeapSnapshotsDiff** diff_ptr) {
2402
- delete *diff_ptr;
2403
- }
2404
-
2405
- HeapSnapshotsComparator::~HeapSnapshotsComparator() {
2406
- diffs_.Iterate(DeleteHeapSnapshotsDiff);
2407
- }
2408
-
2409
-
2410
- HeapSnapshotsDiff* HeapSnapshotsComparator::Compare(HeapSnapshot* snapshot1,
2411
- HeapSnapshot* snapshot2) {
2412
- snapshot1->ClearPaint();
2413
- snapshot1->root()->PaintAllReachable();
2414
- snapshot2->ClearPaint();
2415
- snapshot2->root()->PaintAllReachable();
2416
-
2417
- List<HeapEntry*>* entries1 = snapshot1->GetSortedEntriesList();
2418
- List<HeapEntry*>* entries2 = snapshot2->GetSortedEntriesList();
2419
- int i = 0, j = 0;
2420
- List<HeapEntry*> added_entries, deleted_entries;
2421
- while (i < entries1->length() && j < entries2->length()) {
2422
- uint64_t id1 = entries1->at(i)->id();
2423
- uint64_t id2 = entries2->at(j)->id();
2424
- if (id1 == id2) {
2425
- HeapEntry* entry1 = entries1->at(i++);
2426
- HeapEntry* entry2 = entries2->at(j++);
2427
- if (entry1->painted_reachable() != entry2->painted_reachable()) {
2428
- if (entry1->painted_reachable())
2429
- deleted_entries.Add(entry1);
2430
- else
2431
- added_entries.Add(entry2);
2432
- }
2433
- } else if (id1 < id2) {
2434
- HeapEntry* entry = entries1->at(i++);
2435
- deleted_entries.Add(entry);
2436
- } else {
2437
- HeapEntry* entry = entries2->at(j++);
2438
- added_entries.Add(entry);
2439
- }
2440
- }
2441
- while (i < entries1->length()) {
2442
- HeapEntry* entry = entries1->at(i++);
2443
- deleted_entries.Add(entry);
2444
- }
2445
- while (j < entries2->length()) {
2446
- HeapEntry* entry = entries2->at(j++);
2447
- added_entries.Add(entry);
2448
- }
2449
-
2450
- HeapSnapshotsDiff* diff = new HeapSnapshotsDiff(snapshot1, snapshot2);
2451
- diffs_.Add(diff);
2452
- diff->CreateRoots(added_entries.length(), deleted_entries.length());
2453
-
2454
- for (int i = 0; i < deleted_entries.length(); ++i) {
2455
- HeapEntry* entry = deleted_entries[i];
2456
- diff->AddDeletedEntry(i, i + 1, entry);
2457
- }
2458
- for (int i = 0; i < added_entries.length(); ++i) {
2459
- HeapEntry* entry = added_entries[i];
2460
- diff->AddAddedEntry(i, i + 1, entry);
2461
- }
2462
- return diff;
2463
- }
2464
-
2465
-
2466
2722
  class OutputStreamWriter {
2467
2723
  public:
2468
2724
  explicit OutputStreamWriter(v8::OutputStream* stream)
@@ -2674,7 +2930,8 @@ void HeapSnapshotJSONSerializer::SerializeNodes() {
2674
2930
  "," JSON_S("code")
2675
2931
  "," JSON_S("closure")
2676
2932
  "," JSON_S("regexp")
2677
- "," JSON_S("number"))
2933
+ "," JSON_S("number")
2934
+ "," JSON_S("native"))
2678
2935
  "," JSON_S("string")
2679
2936
  "," JSON_S("number")
2680
2937
  "," JSON_S("number")
@@ -2829,7 +3086,7 @@ void HeapSnapshotJSONSerializer::SortHashMap(
2829
3086
 
2830
3087
 
2831
3088
  String* GetConstructorNameForHeapProfile(JSObject* object) {
2832
- if (object->IsJSFunction()) return Heap::closure_symbol();
3089
+ if (object->IsJSFunction()) return HEAP->closure_symbol();
2833
3090
  return object->constructor_name();
2834
3091
  }
2835
3092