libv8 3.10.8.0 → 3.11.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (215) hide show
  1. data/Rakefile +10 -3
  2. data/ext/libv8/compiler.rb +46 -0
  3. data/ext/libv8/extconf.rb +5 -1
  4. data/ext/libv8/make.rb +13 -0
  5. data/lib/libv8/version.rb +1 -1
  6. data/patches/add-freebsd9-and-freebsd10-to-gyp-GetFlavor.patch +11 -0
  7. data/patches/src_platform-freebsd.cc.patch +10 -0
  8. data/vendor/v8/ChangeLog +124 -0
  9. data/vendor/v8/DEPS +27 -0
  10. data/vendor/v8/Makefile +7 -0
  11. data/vendor/v8/SConstruct +15 -2
  12. data/vendor/v8/build/common.gypi +129 -157
  13. data/vendor/v8/build/gyp_v8 +11 -25
  14. data/vendor/v8/build/standalone.gypi +9 -3
  15. data/vendor/v8/include/v8.h +5 -3
  16. data/vendor/v8/src/SConscript +1 -0
  17. data/vendor/v8/src/api.cc +4 -33
  18. data/vendor/v8/src/api.h +2 -2
  19. data/vendor/v8/src/arm/builtins-arm.cc +5 -4
  20. data/vendor/v8/src/arm/code-stubs-arm.cc +21 -14
  21. data/vendor/v8/src/arm/codegen-arm.cc +2 -2
  22. data/vendor/v8/src/arm/debug-arm.cc +3 -1
  23. data/vendor/v8/src/arm/full-codegen-arm.cc +3 -102
  24. data/vendor/v8/src/arm/ic-arm.cc +30 -33
  25. data/vendor/v8/src/arm/lithium-arm.cc +20 -7
  26. data/vendor/v8/src/arm/lithium-arm.h +10 -4
  27. data/vendor/v8/src/arm/lithium-codegen-arm.cc +106 -60
  28. data/vendor/v8/src/arm/macro-assembler-arm.cc +49 -39
  29. data/vendor/v8/src/arm/macro-assembler-arm.h +5 -4
  30. data/vendor/v8/src/arm/regexp-macro-assembler-arm.cc +115 -55
  31. data/vendor/v8/src/arm/regexp-macro-assembler-arm.h +7 -6
  32. data/vendor/v8/src/arm/simulator-arm.h +6 -6
  33. data/vendor/v8/src/arm/stub-cache-arm.cc +64 -19
  34. data/vendor/v8/src/array.js +7 -3
  35. data/vendor/v8/src/ast.cc +11 -6
  36. data/vendor/v8/src/bootstrapper.cc +9 -11
  37. data/vendor/v8/src/builtins.cc +61 -31
  38. data/vendor/v8/src/code-stubs.cc +23 -9
  39. data/vendor/v8/src/code-stubs.h +1 -0
  40. data/vendor/v8/src/codegen.h +3 -3
  41. data/vendor/v8/src/compiler.cc +1 -1
  42. data/vendor/v8/src/contexts.h +2 -18
  43. data/vendor/v8/src/d8.cc +94 -93
  44. data/vendor/v8/src/d8.h +1 -1
  45. data/vendor/v8/src/debug-agent.cc +3 -3
  46. data/vendor/v8/src/debug.cc +41 -1
  47. data/vendor/v8/src/debug.h +50 -0
  48. data/vendor/v8/src/elements-kind.cc +134 -0
  49. data/vendor/v8/src/elements-kind.h +210 -0
  50. data/vendor/v8/src/elements.cc +356 -190
  51. data/vendor/v8/src/elements.h +36 -28
  52. data/vendor/v8/src/factory.cc +44 -4
  53. data/vendor/v8/src/factory.h +11 -7
  54. data/vendor/v8/src/flag-definitions.h +3 -0
  55. data/vendor/v8/src/frames.h +3 -0
  56. data/vendor/v8/src/full-codegen.cc +2 -1
  57. data/vendor/v8/src/func-name-inferrer.h +2 -0
  58. data/vendor/v8/src/globals.h +3 -0
  59. data/vendor/v8/src/heap-inl.h +16 -4
  60. data/vendor/v8/src/heap.cc +38 -32
  61. data/vendor/v8/src/heap.h +3 -17
  62. data/vendor/v8/src/hydrogen-instructions.cc +28 -5
  63. data/vendor/v8/src/hydrogen-instructions.h +142 -44
  64. data/vendor/v8/src/hydrogen.cc +160 -55
  65. data/vendor/v8/src/hydrogen.h +2 -0
  66. data/vendor/v8/src/ia32/assembler-ia32.h +3 -0
  67. data/vendor/v8/src/ia32/builtins-ia32.cc +5 -4
  68. data/vendor/v8/src/ia32/code-stubs-ia32.cc +22 -16
  69. data/vendor/v8/src/ia32/codegen-ia32.cc +2 -2
  70. data/vendor/v8/src/ia32/debug-ia32.cc +29 -2
  71. data/vendor/v8/src/ia32/full-codegen-ia32.cc +8 -101
  72. data/vendor/v8/src/ia32/ic-ia32.cc +23 -19
  73. data/vendor/v8/src/ia32/lithium-codegen-ia32.cc +126 -80
  74. data/vendor/v8/src/ia32/lithium-codegen-ia32.h +2 -1
  75. data/vendor/v8/src/ia32/lithium-ia32.cc +15 -9
  76. data/vendor/v8/src/ia32/lithium-ia32.h +14 -6
  77. data/vendor/v8/src/ia32/macro-assembler-ia32.cc +50 -40
  78. data/vendor/v8/src/ia32/macro-assembler-ia32.h +5 -4
  79. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.cc +113 -43
  80. data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.h +9 -4
  81. data/vendor/v8/src/ia32/simulator-ia32.h +4 -4
  82. data/vendor/v8/src/ia32/stub-cache-ia32.cc +52 -14
  83. data/vendor/v8/src/ic.cc +77 -20
  84. data/vendor/v8/src/ic.h +18 -2
  85. data/vendor/v8/src/incremental-marking-inl.h +21 -5
  86. data/vendor/v8/src/incremental-marking.cc +35 -8
  87. data/vendor/v8/src/incremental-marking.h +12 -3
  88. data/vendor/v8/src/isolate.cc +12 -2
  89. data/vendor/v8/src/isolate.h +1 -1
  90. data/vendor/v8/src/jsregexp.cc +66 -26
  91. data/vendor/v8/src/jsregexp.h +60 -31
  92. data/vendor/v8/src/list-inl.h +8 -0
  93. data/vendor/v8/src/list.h +3 -0
  94. data/vendor/v8/src/lithium.cc +5 -2
  95. data/vendor/v8/src/liveedit.cc +57 -5
  96. data/vendor/v8/src/mark-compact-inl.h +17 -11
  97. data/vendor/v8/src/mark-compact.cc +100 -143
  98. data/vendor/v8/src/mark-compact.h +44 -20
  99. data/vendor/v8/src/messages.js +131 -99
  100. data/vendor/v8/src/mips/builtins-mips.cc +5 -4
  101. data/vendor/v8/src/mips/code-stubs-mips.cc +23 -15
  102. data/vendor/v8/src/mips/codegen-mips.cc +2 -2
  103. data/vendor/v8/src/mips/debug-mips.cc +3 -1
  104. data/vendor/v8/src/mips/full-codegen-mips.cc +4 -102
  105. data/vendor/v8/src/mips/ic-mips.cc +34 -36
  106. data/vendor/v8/src/mips/lithium-codegen-mips.cc +116 -68
  107. data/vendor/v8/src/mips/lithium-mips.cc +20 -7
  108. data/vendor/v8/src/mips/lithium-mips.h +11 -4
  109. data/vendor/v8/src/mips/macro-assembler-mips.cc +50 -39
  110. data/vendor/v8/src/mips/macro-assembler-mips.h +5 -4
  111. data/vendor/v8/src/mips/regexp-macro-assembler-mips.cc +110 -50
  112. data/vendor/v8/src/mips/regexp-macro-assembler-mips.h +6 -5
  113. data/vendor/v8/src/mips/simulator-mips.h +5 -5
  114. data/vendor/v8/src/mips/stub-cache-mips.cc +66 -20
  115. data/vendor/v8/src/mksnapshot.cc +5 -1
  116. data/vendor/v8/src/objects-debug.cc +103 -6
  117. data/vendor/v8/src/objects-inl.h +215 -116
  118. data/vendor/v8/src/objects-printer.cc +13 -8
  119. data/vendor/v8/src/objects.cc +608 -331
  120. data/vendor/v8/src/objects.h +129 -94
  121. data/vendor/v8/src/parser.cc +16 -4
  122. data/vendor/v8/src/platform-freebsd.cc +1 -0
  123. data/vendor/v8/src/platform-linux.cc +9 -30
  124. data/vendor/v8/src/platform-posix.cc +28 -7
  125. data/vendor/v8/src/platform-win32.cc +15 -3
  126. data/vendor/v8/src/platform.h +2 -1
  127. data/vendor/v8/src/profile-generator-inl.h +25 -2
  128. data/vendor/v8/src/profile-generator.cc +300 -822
  129. data/vendor/v8/src/profile-generator.h +97 -214
  130. data/vendor/v8/src/regexp-macro-assembler-irregexp.cc +2 -1
  131. data/vendor/v8/src/regexp-macro-assembler-irregexp.h +2 -2
  132. data/vendor/v8/src/regexp-macro-assembler-tracer.cc +6 -5
  133. data/vendor/v8/src/regexp-macro-assembler-tracer.h +1 -1
  134. data/vendor/v8/src/regexp-macro-assembler.cc +7 -3
  135. data/vendor/v8/src/regexp-macro-assembler.h +10 -2
  136. data/vendor/v8/src/regexp.js +6 -0
  137. data/vendor/v8/src/runtime.cc +265 -212
  138. data/vendor/v8/src/runtime.h +6 -5
  139. data/vendor/v8/src/scopes.cc +20 -0
  140. data/vendor/v8/src/scopes.h +6 -3
  141. data/vendor/v8/src/spaces.cc +0 -2
  142. data/vendor/v8/src/string-stream.cc +2 -2
  143. data/vendor/v8/src/v8-counters.h +0 -2
  144. data/vendor/v8/src/v8natives.js +2 -2
  145. data/vendor/v8/src/v8utils.h +6 -3
  146. data/vendor/v8/src/version.cc +1 -1
  147. data/vendor/v8/src/x64/assembler-x64.h +2 -1
  148. data/vendor/v8/src/x64/builtins-x64.cc +5 -4
  149. data/vendor/v8/src/x64/code-stubs-x64.cc +25 -16
  150. data/vendor/v8/src/x64/codegen-x64.cc +2 -2
  151. data/vendor/v8/src/x64/debug-x64.cc +14 -1
  152. data/vendor/v8/src/x64/disasm-x64.cc +1 -1
  153. data/vendor/v8/src/x64/full-codegen-x64.cc +10 -106
  154. data/vendor/v8/src/x64/ic-x64.cc +20 -16
  155. data/vendor/v8/src/x64/lithium-codegen-x64.cc +156 -79
  156. data/vendor/v8/src/x64/lithium-codegen-x64.h +2 -1
  157. data/vendor/v8/src/x64/lithium-x64.cc +18 -8
  158. data/vendor/v8/src/x64/lithium-x64.h +7 -2
  159. data/vendor/v8/src/x64/macro-assembler-x64.cc +50 -40
  160. data/vendor/v8/src/x64/macro-assembler-x64.h +5 -4
  161. data/vendor/v8/src/x64/regexp-macro-assembler-x64.cc +122 -51
  162. data/vendor/v8/src/x64/regexp-macro-assembler-x64.h +17 -8
  163. data/vendor/v8/src/x64/simulator-x64.h +4 -4
  164. data/vendor/v8/src/x64/stub-cache-x64.cc +55 -17
  165. data/vendor/v8/test/cctest/cctest.status +1 -0
  166. data/vendor/v8/test/cctest/test-api.cc +24 -0
  167. data/vendor/v8/test/cctest/test-func-name-inference.cc +38 -0
  168. data/vendor/v8/test/cctest/test-heap-profiler.cc +21 -77
  169. data/vendor/v8/test/cctest/test-heap.cc +164 -3
  170. data/vendor/v8/test/cctest/test-list.cc +12 -0
  171. data/vendor/v8/test/cctest/test-mark-compact.cc +5 -5
  172. data/vendor/v8/test/cctest/test-regexp.cc +14 -8
  173. data/vendor/v8/test/cctest/testcfg.py +2 -0
  174. data/vendor/v8/test/mjsunit/accessor-map-sharing.js +176 -0
  175. data/vendor/v8/test/mjsunit/array-construct-transition.js +3 -3
  176. data/vendor/v8/test/mjsunit/array-literal-transitions.js +10 -10
  177. data/vendor/v8/test/mjsunit/big-array-literal.js +3 -0
  178. data/vendor/v8/test/mjsunit/compiler/inline-construct.js +4 -2
  179. data/vendor/v8/test/mjsunit/debug-liveedit-stack-padding.js +88 -0
  180. data/vendor/v8/test/mjsunit/elements-kind.js +4 -4
  181. data/vendor/v8/test/mjsunit/elements-transition-hoisting.js +2 -2
  182. data/vendor/v8/test/mjsunit/elements-transition.js +5 -5
  183. data/vendor/v8/test/mjsunit/error-constructors.js +68 -33
  184. data/vendor/v8/test/mjsunit/harmony/proxies.js +14 -6
  185. data/vendor/v8/test/mjsunit/mjsunit.status +1 -0
  186. data/vendor/v8/test/mjsunit/packed-elements.js +112 -0
  187. data/vendor/v8/test/mjsunit/regexp-capture-3.js +6 -0
  188. data/vendor/v8/test/mjsunit/regexp-global.js +132 -0
  189. data/vendor/v8/test/mjsunit/regexp.js +11 -0
  190. data/vendor/v8/test/mjsunit/regress/regress-117409.js +52 -0
  191. data/vendor/v8/test/mjsunit/regress/regress-126412.js +33 -0
  192. data/vendor/v8/test/mjsunit/regress/regress-128018.js +35 -0
  193. data/vendor/v8/test/mjsunit/regress/regress-128146.js +33 -0
  194. data/vendor/v8/test/mjsunit/regress/regress-1639-2.js +4 -1
  195. data/vendor/v8/test/mjsunit/regress/regress-1639.js +14 -8
  196. data/vendor/v8/test/mjsunit/regress/regress-1849.js +3 -3
  197. data/vendor/v8/test/mjsunit/regress/regress-1878.js +2 -2
  198. data/vendor/v8/test/mjsunit/regress/regress-2071.js +79 -0
  199. data/vendor/v8/test/mjsunit/regress/regress-2153.js +32 -0
  200. data/vendor/v8/test/mjsunit/regress/regress-crbug-122271.js +4 -4
  201. data/vendor/v8/test/mjsunit/regress/regress-crbug-126414.js +32 -0
  202. data/vendor/v8/test/mjsunit/regress/regress-smi-only-concat.js +2 -2
  203. data/vendor/v8/test/mjsunit/regress/regress-transcendental.js +49 -0
  204. data/vendor/v8/test/mjsunit/stack-traces.js +14 -0
  205. data/vendor/v8/test/mjsunit/unbox-double-arrays.js +4 -3
  206. data/vendor/v8/test/test262/testcfg.py +6 -1
  207. data/vendor/v8/tools/check-static-initializers.sh +11 -3
  208. data/vendor/v8/tools/fuzz-harness.sh +92 -0
  209. data/vendor/v8/tools/grokdump.py +658 -67
  210. data/vendor/v8/tools/gyp/v8.gyp +21 -39
  211. data/vendor/v8/tools/js2c.py +3 -3
  212. data/vendor/v8/tools/jsmin.py +2 -2
  213. data/vendor/v8/tools/presubmit.py +2 -1
  214. data/vendor/v8/tools/test-wrapper-gypbuild.py +25 -11
  215. metadata +624 -612
@@ -3767,10 +3767,12 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
3767
3767
  Handle<FixedArray> object_literals =
3768
3768
  isolate()->factory()->NewFixedArray(values->length(), TENURED);
3769
3769
  Handle<FixedDoubleArray> double_literals;
3770
- ElementsKind elements_kind = FAST_SMI_ONLY_ELEMENTS;
3770
+ ElementsKind elements_kind = FAST_SMI_ELEMENTS;
3771
3771
  bool has_only_undefined_values = true;
3772
+ bool has_hole_values = false;
3772
3773
 
3773
3774
  // Fill in the literals.
3775
+ Heap* heap = isolate()->heap();
3774
3776
  bool is_simple = true;
3775
3777
  int depth = 1;
3776
3778
  for (int i = 0, n = values->length(); i < n; i++) {
@@ -3779,12 +3781,18 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
3779
3781
  depth = m_literal->depth() + 1;
3780
3782
  }
3781
3783
  Handle<Object> boilerplate_value = GetBoilerplateValue(values->at(i));
3782
- if (boilerplate_value->IsUndefined()) {
3784
+ if (boilerplate_value->IsTheHole()) {
3785
+ has_hole_values = true;
3783
3786
  object_literals->set_the_hole(i);
3784
3787
  if (elements_kind == FAST_DOUBLE_ELEMENTS) {
3785
3788
  double_literals->set_the_hole(i);
3786
3789
  }
3790
+ } else if (boilerplate_value->IsUndefined()) {
3787
3791
  is_simple = false;
3792
+ object_literals->set(i, Smi::FromInt(0));
3793
+ if (elements_kind == FAST_DOUBLE_ELEMENTS) {
3794
+ double_literals->set(i, 0);
3795
+ }
3788
3796
  } else {
3789
3797
  // Examine each literal element, and adjust the ElementsKind if the
3790
3798
  // literal element is not of a type that can be stored in the current
@@ -3794,7 +3802,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
3794
3802
  // ultimately end up in FAST_ELEMENTS.
3795
3803
  has_only_undefined_values = false;
3796
3804
  object_literals->set(i, *boilerplate_value);
3797
- if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3805
+ if (elements_kind == FAST_SMI_ELEMENTS) {
3798
3806
  // Smi only elements. Notice if a transition to FAST_DOUBLE_ELEMENTS or
3799
3807
  // FAST_ELEMENTS is required.
3800
3808
  if (!boilerplate_value->IsSmi()) {
@@ -3842,7 +3850,7 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
3842
3850
  // elements array to a copy-on-write array.
3843
3851
  if (is_simple && depth == 1 && values->length() > 0 &&
3844
3852
  elements_kind != FAST_DOUBLE_ELEMENTS) {
3845
- object_literals->set_map(isolate()->heap()->fixed_cow_array_map());
3853
+ object_literals->set_map(heap->fixed_cow_array_map());
3846
3854
  }
3847
3855
 
3848
3856
  Handle<FixedArrayBase> element_values = elements_kind == FAST_DOUBLE_ELEMENTS
@@ -3854,6 +3862,10 @@ Expression* Parser::ParseArrayLiteral(bool* ok) {
3854
3862
  Handle<FixedArray> literals =
3855
3863
  isolate()->factory()->NewFixedArray(2, TENURED);
3856
3864
 
3865
+ if (has_hole_values || !FLAG_packed_arrays) {
3866
+ elements_kind = GetHoleyElementsKind(elements_kind);
3867
+ }
3868
+
3857
3869
  literals->set(0, Smi::FromInt(elements_kind));
3858
3870
  literals->set(1, *element_values);
3859
3871
 
@@ -554,6 +554,7 @@ class FreeBSDMutex : public Mutex {
554
554
  ASSERT(result == 0);
555
555
  result = pthread_mutex_init(&mutex_, &attrs);
556
556
  ASSERT(result == 0);
557
+ USE(result);
557
558
  }
558
559
 
559
560
  virtual ~FreeBSDMutex() { pthread_mutex_destroy(&mutex_); }
@@ -966,43 +966,22 @@ typedef struct ucontext {
966
966
 
967
967
  #elif !defined(__GLIBC__) && defined(__i386__)
968
968
  // x86 version for Android.
969
- struct _libc_fpreg {
970
- uint16_t significand[4];
971
- uint16_t exponent;
972
- };
973
-
974
- struct _libc_fpstate {
975
- uint64_t cw;
976
- uint64_t sw;
977
- uint64_t tag;
978
- uint64_t ipoff;
979
- uint64_t cssel;
980
- uint64_t dataoff;
981
- uint64_t datasel;
982
- struct _libc_fpreg _st[8];
983
- uint64_t status;
969
+ struct sigcontext {
970
+ uint32_t gregs[19];
971
+ void* fpregs;
972
+ uint32_t oldmask;
973
+ uint32_t cr2;
984
974
  };
985
975
 
986
- typedef struct _libc_fpstate *fpregset_t;
987
-
988
- typedef struct mcontext {
989
- int32_t gregs[19];
990
- fpregset_t fpregs;
991
- int64_t oldmask;
992
- int64_t cr2;
993
- } mcontext_t;
994
-
995
- typedef uint64_t __sigset_t;
996
-
976
+ typedef uint32_t __sigset_t;
977
+ typedef struct sigcontext mcontext_t;
997
978
  typedef struct ucontext {
998
- uint64_t uc_flags;
999
- struct ucontext *uc_link;
979
+ uint32_t uc_flags;
980
+ struct ucontext* uc_link;
1000
981
  stack_t uc_stack;
1001
982
  mcontext_t uc_mcontext;
1002
983
  __sigset_t uc_sigmask;
1003
- struct _libc_fpstate __fpregs_mem;
1004
984
  } ucontext_t;
1005
-
1006
985
  enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 };
1007
986
  #endif
1008
987
 
@@ -1,4 +1,4 @@
1
- // Copyright 2011 the V8 project authors. All rights reserved.
1
+ // Copyright 2012 the V8 project authors. All rights reserved.
2
2
  // Redistribution and use in source and binary forms, with or without
3
3
  // modification, are permitted provided that the following conditions are
4
4
  // met:
@@ -421,7 +421,11 @@ Socket* POSIXSocket::Accept() const {
421
421
  return NULL;
422
422
  }
423
423
 
424
- int socket = accept(socket_, NULL, NULL);
424
+ int socket;
425
+ do {
426
+ socket = accept(socket_, NULL, NULL);
427
+ } while (socket == -1 && errno == EINTR);
428
+
425
429
  if (socket == -1) {
426
430
  return NULL;
427
431
  } else {
@@ -448,7 +452,9 @@ bool POSIXSocket::Connect(const char* host, const char* port) {
448
452
  }
449
453
 
450
454
  // Connect.
451
- status = connect(socket_, result->ai_addr, result->ai_addrlen);
455
+ do {
456
+ status = connect(socket_, result->ai_addr, result->ai_addrlen);
457
+ } while (status == -1 && errno == EINTR);
452
458
  freeaddrinfo(result);
453
459
  return status == 0;
454
460
  }
@@ -467,14 +473,29 @@ bool POSIXSocket::Shutdown() {
467
473
 
468
474
 
469
475
  int POSIXSocket::Send(const char* data, int len) const {
470
- int status = send(socket_, data, len, 0);
471
- return status;
476
+ if (len <= 0) return 0;
477
+ int written = 0;
478
+ while (written < len) {
479
+ int status = send(socket_, data + written, len - written, 0);
480
+ if (status == 0) {
481
+ break;
482
+ } else if (status > 0) {
483
+ written += status;
484
+ } else if (errno != EINTR) {
485
+ return 0;
486
+ }
487
+ }
488
+ return written;
472
489
  }
473
490
 
474
491
 
475
492
  int POSIXSocket::Receive(char* data, int len) const {
476
- int status = recv(socket_, data, len, 0);
477
- return status;
493
+ if (len <= 0) return 0;
494
+ int status;
495
+ do {
496
+ status = recv(socket_, data, len, 0);
497
+ } while (status == -1 && errno == EINTR);
498
+ return (status < 0) ? 0 : status;
478
499
  }
479
500
 
480
501
 
@@ -1848,14 +1848,26 @@ bool Win32Socket::Shutdown() {
1848
1848
 
1849
1849
 
1850
1850
  int Win32Socket::Send(const char* data, int len) const {
1851
- int status = send(socket_, data, len, 0);
1852
- return status;
1851
+ if (len <= 0) return 0;
1852
+ int written = 0;
1853
+ while (written < len) {
1854
+ int status = send(socket_, data + written, len - written, 0);
1855
+ if (status == 0) {
1856
+ break;
1857
+ } else if (status > 0) {
1858
+ written += status;
1859
+ } else {
1860
+ return 0;
1861
+ }
1862
+ }
1863
+ return written;
1853
1864
  }
1854
1865
 
1855
1866
 
1856
1867
  int Win32Socket::Receive(char* data, int len) const {
1868
+ if (len <= 0) return 0;
1857
1869
  int status = recv(socket_, data, len, 0);
1858
- return status;
1870
+ return (status == SOCKET_ERROR) ? 0 : status;
1859
1871
  }
1860
1872
 
1861
1873
 
@@ -1,4 +1,4 @@
1
- // Copyright 2011 the V8 project authors. All rights reserved.
1
+ // Copyright 2012 the V8 project authors. All rights reserved.
2
2
  // Redistribution and use in source and binary forms, with or without
3
3
  // modification, are permitted provided that the following conditions are
4
4
  // met:
@@ -653,6 +653,7 @@ class Socket {
653
653
  virtual bool Shutdown() = 0;
654
654
 
655
655
  // Data Transimission
656
+ // Return 0 on failure.
656
657
  virtual int Send(const char* data, int len) const = 0;
657
658
  virtual int Receive(char* data, int len) const = 0;
658
659
 
@@ -96,8 +96,31 @@ CodeEntry* ProfileGenerator::EntryForVMState(StateTag tag) {
96
96
 
97
97
 
98
98
  HeapEntry* HeapGraphEdge::from() const {
99
- return const_cast<HeapEntry*>(
100
- reinterpret_cast<const HeapEntry*>(this - child_index_) - 1);
99
+ return &snapshot()->entries()[from_index_];
100
+ }
101
+
102
+
103
+ HeapSnapshot* HeapGraphEdge::snapshot() const {
104
+ return to_entry_->snapshot();
105
+ }
106
+
107
+
108
+ int HeapEntry::index() const {
109
+ return static_cast<int>(this - &snapshot_->entries().first());
110
+ }
111
+
112
+
113
+ int HeapEntry::set_children_index(int index) {
114
+ children_index_ = index;
115
+ int next_index = index + children_count_;
116
+ children_count_ = 0;
117
+ return next_index;
118
+ }
119
+
120
+
121
+ HeapGraphEdge** HeapEntry::children_arr() {
122
+ ASSERT(children_index_ >= 0);
123
+ return &snapshot_->children()[children_index_];
101
124
  }
102
125
 
103
126
 
@@ -931,78 +931,63 @@ void ProfileGenerator::RecordTickSample(const TickSample& sample) {
931
931
  }
932
932
 
933
933
 
934
- void HeapGraphEdge::Init(
935
- int child_index, Type type, const char* name, HeapEntry* to) {
934
+ HeapGraphEdge::HeapGraphEdge(Type type, const char* name, int from, int to)
935
+ : type_(type),
936
+ from_index_(from),
937
+ to_index_(to),
938
+ name_(name) {
936
939
  ASSERT(type == kContextVariable
937
- || type == kProperty
938
- || type == kInternal
939
- || type == kShortcut);
940
- child_index_ = child_index;
941
- type_ = type;
942
- name_ = name;
943
- to_ = to;
940
+ || type == kProperty
941
+ || type == kInternal
942
+ || type == kShortcut);
944
943
  }
945
944
 
946
945
 
947
- void HeapGraphEdge::Init(int child_index, Type type, int index, HeapEntry* to) {
946
+ HeapGraphEdge::HeapGraphEdge(Type type, int index, int from, int to)
947
+ : type_(type),
948
+ from_index_(from),
949
+ to_index_(to),
950
+ index_(index) {
948
951
  ASSERT(type == kElement || type == kHidden || type == kWeak);
949
- child_index_ = child_index;
950
- type_ = type;
951
- index_ = index;
952
- to_ = to;
953
952
  }
954
953
 
955
954
 
956
- void HeapGraphEdge::Init(int child_index, int index, HeapEntry* to) {
957
- Init(child_index, kElement, index, to);
955
+ void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) {
956
+ to_entry_ = &snapshot->entries()[to_index_];
958
957
  }
959
958
 
960
959
 
961
- void HeapEntry::Init(HeapSnapshot* snapshot,
960
+ const int HeapEntry::kNoEntry = -1;
961
+
962
+ HeapEntry::HeapEntry(HeapSnapshot* snapshot,
962
963
  Type type,
963
964
  const char* name,
964
965
  SnapshotObjectId id,
965
- int self_size,
966
- int children_count,
967
- int retainers_count) {
968
- snapshot_ = snapshot;
969
- type_ = type;
970
- painted_ = false;
971
- user_reachable_ = false;
972
- name_ = name;
973
- self_size_ = self_size;
974
- retained_size_ = 0;
975
- entry_index_ = -1;
976
- children_count_ = children_count;
977
- retainers_count_ = retainers_count;
978
- dominator_ = NULL;
979
- id_ = id;
980
- }
966
+ int self_size)
967
+ : type_(type),
968
+ children_count_(0),
969
+ children_index_(-1),
970
+ self_size_(self_size),
971
+ id_(id),
972
+ snapshot_(snapshot),
973
+ name_(name) { }
981
974
 
982
975
 
983
976
  void HeapEntry::SetNamedReference(HeapGraphEdge::Type type,
984
- int child_index,
985
977
  const char* name,
986
- HeapEntry* entry,
987
- int retainer_index) {
988
- children()[child_index].Init(child_index, type, name, entry);
989
- entry->retainers()[retainer_index] = children_arr() + child_index;
978
+ HeapEntry* entry) {
979
+ HeapGraphEdge edge(type, name, this->index(), entry->index());
980
+ snapshot_->edges().Add(edge);
981
+ ++children_count_;
990
982
  }
991
983
 
992
984
 
993
985
  void HeapEntry::SetIndexedReference(HeapGraphEdge::Type type,
994
- int child_index,
995
986
  int index,
996
- HeapEntry* entry,
997
- int retainer_index) {
998
- children()[child_index].Init(child_index, type, index, entry);
999
- entry->retainers()[retainer_index] = children_arr() + child_index;
1000
- }
1001
-
1002
-
1003
- void HeapEntry::SetUnidirElementReference(
1004
- int child_index, int index, HeapEntry* entry) {
1005
- children()[child_index].Init(child_index, index, entry);
987
+ HeapEntry* entry) {
988
+ HeapGraphEdge edge(type, index, this->index(), entry->index());
989
+ snapshot_->edges().Add(edge);
990
+ ++children_count_;
1006
991
  }
1007
992
 
1008
993
 
@@ -1013,9 +998,9 @@ Handle<HeapObject> HeapEntry::GetHeapObject() {
1013
998
 
1014
999
  void HeapEntry::Print(
1015
1000
  const char* prefix, const char* edge_name, int max_depth, int indent) {
1016
- OS::Print("%6d %7d @%6llu %*c %s%s: ",
1017
- self_size(), retained_size(), id(),
1018
- indent, ' ', prefix, edge_name);
1001
+ STATIC_CHECK(sizeof(unsigned) == sizeof(id()));
1002
+ OS::Print("%6d @%6u %*c %s%s: ",
1003
+ self_size(), id(), indent, ' ', prefix, edge_name);
1019
1004
  if (type() != kString) {
1020
1005
  OS::Print("%s %.40s\n", TypeAsString(), name_);
1021
1006
  } else {
@@ -1031,9 +1016,9 @@ void HeapEntry::Print(
1031
1016
  OS::Print("\"\n");
1032
1017
  }
1033
1018
  if (--max_depth == 0) return;
1034
- Vector<HeapGraphEdge> ch = children();
1019
+ Vector<HeapGraphEdge*> ch = children();
1035
1020
  for (int i = 0; i < ch.length(); ++i) {
1036
- HeapGraphEdge& edge = ch[i];
1021
+ HeapGraphEdge& edge = *ch[i];
1037
1022
  const char* edge_prefix = "";
1038
1023
  EmbeddedVector<char, 64> index;
1039
1024
  const char* edge_name = index.start();
@@ -1089,15 +1074,6 @@ const char* HeapEntry::TypeAsString() {
1089
1074
  }
1090
1075
 
1091
1076
 
1092
- size_t HeapEntry::EntriesSize(int entries_count,
1093
- int children_count,
1094
- int retainers_count) {
1095
- return sizeof(HeapEntry) * entries_count // NOLINT
1096
- + sizeof(HeapGraphEdge) * children_count // NOLINT
1097
- + sizeof(HeapGraphEdge*) * retainers_count; // NOLINT
1098
- }
1099
-
1100
-
1101
1077
  // It is very important to keep objects that form a heap snapshot
1102
1078
  // as small as possible.
1103
1079
  namespace { // Avoid littering the global namespace.
@@ -1106,13 +1082,13 @@ template <size_t ptr_size> struct SnapshotSizeConstants;
1106
1082
 
1107
1083
  template <> struct SnapshotSizeConstants<4> {
1108
1084
  static const int kExpectedHeapGraphEdgeSize = 12;
1109
- static const int kExpectedHeapEntrySize = 36;
1085
+ static const int kExpectedHeapEntrySize = 24;
1110
1086
  static const size_t kMaxSerializableSnapshotRawSize = 256 * MB;
1111
1087
  };
1112
1088
 
1113
1089
  template <> struct SnapshotSizeConstants<8> {
1114
1090
  static const int kExpectedHeapGraphEdgeSize = 24;
1115
- static const int kExpectedHeapEntrySize = 48;
1091
+ static const int kExpectedHeapEntrySize = 32;
1116
1092
  static const uint64_t kMaxSerializableSnapshotRawSize =
1117
1093
  static_cast<uint64_t>(6000) * MB;
1118
1094
  };
@@ -1127,11 +1103,9 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1127
1103
  type_(type),
1128
1104
  title_(title),
1129
1105
  uid_(uid),
1130
- root_entry_(NULL),
1131
- gc_roots_entry_(NULL),
1132
- natives_root_entry_(NULL),
1133
- raw_entries_(NULL),
1134
- number_of_edges_(0),
1106
+ root_index_(HeapEntry::kNoEntry),
1107
+ gc_roots_index_(HeapEntry::kNoEntry),
1108
+ natives_root_index_(HeapEntry::kNoEntry),
1135
1109
  max_snapshot_js_object_id_(0) {
1136
1110
  STATIC_CHECK(
1137
1111
  sizeof(HeapGraphEdge) ==
@@ -1140,16 +1114,11 @@ HeapSnapshot::HeapSnapshot(HeapSnapshotsCollection* collection,
1140
1114
  sizeof(HeapEntry) ==
1141
1115
  SnapshotSizeConstants<kPointerSize>::kExpectedHeapEntrySize);
1142
1116
  for (int i = 0; i < VisitorSynchronization::kNumberOfSyncTags; ++i) {
1143
- gc_subroot_entries_[i] = NULL;
1117
+ gc_subroot_indexes_[i] = HeapEntry::kNoEntry;
1144
1118
  }
1145
1119
  }
1146
1120
 
1147
1121
 
1148
- HeapSnapshot::~HeapSnapshot() {
1149
- DeleteArray(raw_entries_);
1150
- }
1151
-
1152
-
1153
1122
  void HeapSnapshot::Delete() {
1154
1123
  collection_->RemoveSnapshot(this);
1155
1124
  delete this;
@@ -1161,97 +1130,67 @@ void HeapSnapshot::RememberLastJSObjectId() {
1161
1130
  }
1162
1131
 
1163
1132
 
1164
- void HeapSnapshot::AllocateEntries(int entries_count,
1165
- int children_count,
1166
- int retainers_count) {
1167
- ASSERT(raw_entries_ == NULL);
1168
- number_of_edges_ = children_count;
1169
- raw_entries_size_ =
1170
- HeapEntry::EntriesSize(entries_count, children_count, retainers_count);
1171
- raw_entries_ = NewArray<char>(raw_entries_size_);
1172
- }
1173
-
1174
-
1175
- static void HeapEntryClearPaint(HeapEntry** entry_ptr) {
1176
- (*entry_ptr)->clear_paint();
1177
- }
1178
-
1179
-
1180
- void HeapSnapshot::ClearPaint() {
1181
- entries_.Iterate(HeapEntryClearPaint);
1182
- }
1183
-
1184
-
1185
- HeapEntry* HeapSnapshot::AddRootEntry(int children_count) {
1186
- ASSERT(root_entry_ == NULL);
1133
+ HeapEntry* HeapSnapshot::AddRootEntry() {
1134
+ ASSERT(root_index_ == HeapEntry::kNoEntry);
1187
1135
  ASSERT(entries_.is_empty()); // Root entry must be the first one.
1188
- return (root_entry_ = AddEntry(HeapEntry::kObject,
1189
- "",
1190
- HeapObjectsMap::kInternalRootObjectId,
1191
- 0,
1192
- children_count,
1193
- 0));
1136
+ HeapEntry* entry = AddEntry(HeapEntry::kObject,
1137
+ "",
1138
+ HeapObjectsMap::kInternalRootObjectId,
1139
+ 0);
1140
+ root_index_ = entry->index();
1141
+ ASSERT(root_index_ == 0);
1142
+ return entry;
1194
1143
  }
1195
1144
 
1196
1145
 
1197
- HeapEntry* HeapSnapshot::AddGcRootsEntry(int children_count,
1198
- int retainers_count) {
1199
- ASSERT(gc_roots_entry_ == NULL);
1200
- return (gc_roots_entry_ = AddEntry(HeapEntry::kObject,
1201
- "(GC roots)",
1202
- HeapObjectsMap::kGcRootsObjectId,
1203
- 0,
1204
- children_count,
1205
- retainers_count));
1146
+ HeapEntry* HeapSnapshot::AddGcRootsEntry() {
1147
+ ASSERT(gc_roots_index_ == HeapEntry::kNoEntry);
1148
+ HeapEntry* entry = AddEntry(HeapEntry::kObject,
1149
+ "(GC roots)",
1150
+ HeapObjectsMap::kGcRootsObjectId,
1151
+ 0);
1152
+ gc_roots_index_ = entry->index();
1153
+ return entry;
1206
1154
  }
1207
1155
 
1208
1156
 
1209
- HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag,
1210
- int children_count,
1211
- int retainers_count) {
1212
- ASSERT(gc_subroot_entries_[tag] == NULL);
1157
+ HeapEntry* HeapSnapshot::AddGcSubrootEntry(int tag) {
1158
+ ASSERT(gc_subroot_indexes_[tag] == HeapEntry::kNoEntry);
1213
1159
  ASSERT(0 <= tag && tag < VisitorSynchronization::kNumberOfSyncTags);
1214
- return (gc_subroot_entries_[tag] = AddEntry(
1160
+ HeapEntry* entry = AddEntry(
1215
1161
  HeapEntry::kObject,
1216
1162
  VisitorSynchronization::kTagNames[tag],
1217
1163
  HeapObjectsMap::GetNthGcSubrootId(tag),
1218
- 0,
1219
- children_count,
1220
- retainers_count));
1164
+ 0);
1165
+ gc_subroot_indexes_[tag] = entry->index();
1166
+ return entry;
1221
1167
  }
1222
1168
 
1223
1169
 
1224
1170
  HeapEntry* HeapSnapshot::AddEntry(HeapEntry::Type type,
1225
1171
  const char* name,
1226
1172
  SnapshotObjectId id,
1227
- int size,
1228
- int children_count,
1229
- int retainers_count) {
1230
- HeapEntry* entry = GetNextEntryToInit();
1231
- entry->Init(this, type, name, id, size, children_count, retainers_count);
1232
- return entry;
1173
+ int size) {
1174
+ HeapEntry entry(this, type, name, id, size);
1175
+ entries_.Add(entry);
1176
+ return &entries_.last();
1233
1177
  }
1234
1178
 
1235
1179
 
1236
- void HeapSnapshot::SetDominatorsToSelf() {
1237
- for (int i = 0; i < entries_.length(); ++i) {
1238
- HeapEntry* entry = entries_[i];
1239
- if (entry->dominator() == NULL) entry->set_dominator(entry);
1180
+ void HeapSnapshot::FillChildren() {
1181
+ ASSERT(children().is_empty());
1182
+ children().Allocate(edges().length());
1183
+ int children_index = 0;
1184
+ for (int i = 0; i < entries().length(); ++i) {
1185
+ HeapEntry* entry = &entries()[i];
1186
+ children_index = entry->set_children_index(children_index);
1240
1187
  }
1241
- }
1242
-
1243
-
1244
- HeapEntry* HeapSnapshot::GetNextEntryToInit() {
1245
- if (entries_.length() > 0) {
1246
- HeapEntry* last_entry = entries_.last();
1247
- entries_.Add(reinterpret_cast<HeapEntry*>(
1248
- reinterpret_cast<char*>(last_entry) + last_entry->EntrySize()));
1249
- } else {
1250
- entries_.Add(reinterpret_cast<HeapEntry*>(raw_entries_));
1188
+ ASSERT(edges().length() == children_index);
1189
+ for (int i = 0; i < edges().length(); ++i) {
1190
+ HeapGraphEdge* edge = &edges()[i];
1191
+ edge->ReplaceToIndexWithEntry(this);
1192
+ edge->from()->add_child(edge);
1251
1193
  }
1252
- ASSERT(reinterpret_cast<char*>(entries_.last()) <
1253
- (raw_entries_ + raw_entries_size_));
1254
- return entries_.last();
1255
1194
  }
1256
1195
 
1257
1196
 
@@ -1287,7 +1226,10 @@ static int SortByIds(const T* entry1_ptr,
1287
1226
 
1288
1227
  List<HeapEntry*>* HeapSnapshot::GetSortedEntriesList() {
1289
1228
  if (sorted_entries_.is_empty()) {
1290
- sorted_entries_.AddAll(entries_);
1229
+ sorted_entries_.Allocate(entries_.length());
1230
+ for (int i = 0; i < entries_.length(); ++i) {
1231
+ sorted_entries_[i] = &entries_[i];
1232
+ }
1291
1233
  sorted_entries_.Sort(SortByIds);
1292
1234
  }
1293
1235
  return &sorted_entries_;
@@ -1299,6 +1241,21 @@ void HeapSnapshot::Print(int max_depth) {
1299
1241
  }
1300
1242
 
1301
1243
 
1244
+ template<typename T, class P>
1245
+ static size_t GetMemoryUsedByList(const List<T, P>& list) {
1246
+ return list.capacity() * sizeof(T);
1247
+ }
1248
+
1249
+
1250
+ size_t HeapSnapshot::RawSnapshotSize() const {
1251
+ return
1252
+ GetMemoryUsedByList(entries_) +
1253
+ GetMemoryUsedByList(edges_) +
1254
+ GetMemoryUsedByList(children_) +
1255
+ GetMemoryUsedByList(sorted_entries_);
1256
+ }
1257
+
1258
+
1302
1259
  // We split IDs on evens for embedder objects (see
1303
1260
  // HeapObjectsMap::GenerateId) and odds for native objects.
1304
1261
  const SnapshotObjectId HeapObjectsMap::kInternalRootObjectId = 1;
@@ -1567,99 +1524,22 @@ Handle<HeapObject> HeapSnapshotsCollection::FindHeapObjectById(
1567
1524
  }
1568
1525
 
1569
1526
 
1570
- HeapEntry* const HeapEntriesMap::kHeapEntryPlaceholder =
1571
- reinterpret_cast<HeapEntry*>(1);
1572
-
1573
1527
  HeapEntriesMap::HeapEntriesMap()
1574
- : entries_(HeapThingsMatch),
1575
- entries_count_(0),
1576
- total_children_count_(0),
1577
- total_retainers_count_(0) {
1578
- }
1579
-
1580
-
1581
- HeapEntriesMap::~HeapEntriesMap() {
1582
- for (HashMap::Entry* p = entries_.Start(); p != NULL; p = entries_.Next(p)) {
1583
- delete reinterpret_cast<EntryInfo*>(p->value);
1584
- }
1585
- }
1586
-
1587
-
1588
- void HeapEntriesMap::AllocateHeapEntryForMapEntry(HashMap::Entry* map_entry) {
1589
- EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(map_entry->value);
1590
- entry_info->entry = entry_info->allocator->AllocateEntry(
1591
- map_entry->key,
1592
- entry_info->children_count,
1593
- entry_info->retainers_count);
1594
- ASSERT(entry_info->entry != NULL);
1595
- ASSERT(entry_info->entry != kHeapEntryPlaceholder);
1596
- entry_info->children_count = 0;
1597
- entry_info->retainers_count = 0;
1598
- }
1599
-
1600
-
1601
- void HeapEntriesMap::AllocateEntries(HeapThing root_object) {
1602
- HashMap::Entry* root_entry =
1603
- entries_.Lookup(root_object, Hash(root_object), false);
1604
- ASSERT(root_entry != NULL);
1605
- // Make sure root entry is allocated first.
1606
- AllocateHeapEntryForMapEntry(root_entry);
1607
- void* root_entry_value = root_entry->value;
1608
- // Remove the root object from map while iterating through other entries.
1609
- entries_.Remove(root_object, Hash(root_object));
1610
- root_entry = NULL;
1611
-
1612
- for (HashMap::Entry* p = entries_.Start();
1613
- p != NULL;
1614
- p = entries_.Next(p)) {
1615
- AllocateHeapEntryForMapEntry(p);
1616
- }
1617
-
1618
- // Insert root entry back.
1619
- root_entry = entries_.Lookup(root_object, Hash(root_object), true);
1620
- root_entry->value = root_entry_value;
1528
+ : entries_(HeapThingsMatch) {
1621
1529
  }
1622
1530
 
1623
1531
 
1624
- HeapEntry* HeapEntriesMap::Map(HeapThing thing) {
1532
+ int HeapEntriesMap::Map(HeapThing thing) {
1625
1533
  HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
1626
- if (cache_entry != NULL) {
1627
- EntryInfo* entry_info = reinterpret_cast<EntryInfo*>(cache_entry->value);
1628
- return entry_info->entry;
1629
- } else {
1630
- return NULL;
1631
- }
1534
+ if (cache_entry == NULL) return HeapEntry::kNoEntry;
1535
+ return static_cast<int>(reinterpret_cast<intptr_t>(cache_entry->value));
1632
1536
  }
1633
1537
 
1634
1538
 
1635
- void HeapEntriesMap::Pair(
1636
- HeapThing thing, HeapEntriesAllocator* allocator, HeapEntry* entry) {
1539
+ void HeapEntriesMap::Pair(HeapThing thing, int entry) {
1637
1540
  HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), true);
1638
1541
  ASSERT(cache_entry->value == NULL);
1639
- cache_entry->value = new EntryInfo(entry, allocator);
1640
- ++entries_count_;
1641
- }
1642
-
1643
-
1644
- void HeapEntriesMap::CountReference(HeapThing from, HeapThing to,
1645
- int* prev_children_count,
1646
- int* prev_retainers_count) {
1647
- HashMap::Entry* from_cache_entry = entries_.Lookup(from, Hash(from), false);
1648
- HashMap::Entry* to_cache_entry = entries_.Lookup(to, Hash(to), false);
1649
- ASSERT(from_cache_entry != NULL);
1650
- ASSERT(to_cache_entry != NULL);
1651
- EntryInfo* from_entry_info =
1652
- reinterpret_cast<EntryInfo*>(from_cache_entry->value);
1653
- EntryInfo* to_entry_info =
1654
- reinterpret_cast<EntryInfo*>(to_cache_entry->value);
1655
- if (prev_children_count)
1656
- *prev_children_count = from_entry_info->children_count;
1657
- if (prev_retainers_count)
1658
- *prev_retainers_count = to_entry_info->retainers_count;
1659
- ++from_entry_info->children_count;
1660
- ++to_entry_info->retainers_count;
1661
- ++total_children_count_;
1662
- ++total_retainers_count_;
1542
+ cache_entry->value = reinterpret_cast<void*>(static_cast<intptr_t>(entry));
1663
1543
  }
1664
1544
 
1665
1545
 
@@ -1676,20 +1556,14 @@ void HeapObjectsSet::Clear() {
1676
1556
  bool HeapObjectsSet::Contains(Object* obj) {
1677
1557
  if (!obj->IsHeapObject()) return false;
1678
1558
  HeapObject* object = HeapObject::cast(obj);
1679
- HashMap::Entry* cache_entry =
1680
- entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
1681
- return cache_entry != NULL;
1559
+ return entries_.Lookup(object, HeapEntriesMap::Hash(object), false) != NULL;
1682
1560
  }
1683
1561
 
1684
1562
 
1685
1563
  void HeapObjectsSet::Insert(Object* obj) {
1686
1564
  if (!obj->IsHeapObject()) return;
1687
1565
  HeapObject* object = HeapObject::cast(obj);
1688
- HashMap::Entry* cache_entry =
1689
- entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1690
- if (cache_entry->value == NULL) {
1691
- cache_entry->value = HeapEntriesMap::kHeapEntryPlaceholder;
1692
- }
1566
+ entries_.Lookup(object, HeapEntriesMap::Hash(object), true);
1693
1567
  }
1694
1568
 
1695
1569
 
@@ -1697,12 +1571,9 @@ const char* HeapObjectsSet::GetTag(Object* obj) {
1697
1571
  HeapObject* object = HeapObject::cast(obj);
1698
1572
  HashMap::Entry* cache_entry =
1699
1573
  entries_.Lookup(object, HeapEntriesMap::Hash(object), false);
1700
- if (cache_entry != NULL
1701
- && cache_entry->value != HeapEntriesMap::kHeapEntryPlaceholder) {
1702
- return reinterpret_cast<const char*>(cache_entry->value);
1703
- } else {
1704
- return NULL;
1705
- }
1574
+ return cache_entry != NULL
1575
+ ? reinterpret_cast<const char*>(cache_entry->value)
1576
+ : NULL;
1706
1577
  }
1707
1578
 
1708
1579
 
@@ -1744,129 +1615,83 @@ V8HeapExplorer::~V8HeapExplorer() {
1744
1615
  }
1745
1616
 
1746
1617
 
1747
- HeapEntry* V8HeapExplorer::AllocateEntry(
1748
- HeapThing ptr, int children_count, int retainers_count) {
1749
- return AddEntry(
1750
- reinterpret_cast<HeapObject*>(ptr), children_count, retainers_count);
1618
+ HeapEntry* V8HeapExplorer::AllocateEntry(HeapThing ptr) {
1619
+ return AddEntry(reinterpret_cast<HeapObject*>(ptr));
1751
1620
  }
1752
1621
 
1753
1622
 
1754
- HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1755
- int children_count,
1756
- int retainers_count) {
1623
+ HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object) {
1757
1624
  if (object == kInternalRootObject) {
1758
- ASSERT(retainers_count == 0);
1759
- return snapshot_->AddRootEntry(children_count);
1625
+ snapshot_->AddRootEntry();
1626
+ return snapshot_->root();
1760
1627
  } else if (object == kGcRootsObject) {
1761
- return snapshot_->AddGcRootsEntry(children_count, retainers_count);
1628
+ HeapEntry* entry = snapshot_->AddGcRootsEntry();
1629
+ return entry;
1762
1630
  } else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) {
1763
- return snapshot_->AddGcSubrootEntry(
1764
- GetGcSubrootOrder(object),
1765
- children_count,
1766
- retainers_count);
1631
+ HeapEntry* entry = snapshot_->AddGcSubrootEntry(GetGcSubrootOrder(object));
1632
+ return entry;
1767
1633
  } else if (object->IsJSFunction()) {
1768
1634
  JSFunction* func = JSFunction::cast(object);
1769
1635
  SharedFunctionInfo* shared = func->shared();
1770
1636
  const char* name = shared->bound() ? "native_bind" :
1771
1637
  collection_->names()->GetName(String::cast(shared->name()));
1772
- return AddEntry(object,
1773
- HeapEntry::kClosure,
1774
- name,
1775
- children_count,
1776
- retainers_count);
1638
+ return AddEntry(object, HeapEntry::kClosure, name);
1777
1639
  } else if (object->IsJSRegExp()) {
1778
1640
  JSRegExp* re = JSRegExp::cast(object);
1779
1641
  return AddEntry(object,
1780
1642
  HeapEntry::kRegExp,
1781
- collection_->names()->GetName(re->Pattern()),
1782
- children_count,
1783
- retainers_count);
1643
+ collection_->names()->GetName(re->Pattern()));
1784
1644
  } else if (object->IsJSObject()) {
1785
- return AddEntry(object,
1786
- HeapEntry::kObject,
1787
- "",
1788
- children_count,
1789
- retainers_count);
1645
+ const char* name = collection_->names()->GetName(
1646
+ GetConstructorName(JSObject::cast(object)));
1647
+ if (object->IsJSGlobalObject()) {
1648
+ const char* tag = objects_tags_.GetTag(object);
1649
+ if (tag != NULL) {
1650
+ name = collection_->names()->GetFormatted("%s / %s", name, tag);
1651
+ }
1652
+ }
1653
+ return AddEntry(object, HeapEntry::kObject, name);
1790
1654
  } else if (object->IsString()) {
1791
1655
  return AddEntry(object,
1792
1656
  HeapEntry::kString,
1793
- collection_->names()->GetName(String::cast(object)),
1794
- children_count,
1795
- retainers_count);
1657
+ collection_->names()->GetName(String::cast(object)));
1796
1658
  } else if (object->IsCode()) {
1797
- return AddEntry(object,
1798
- HeapEntry::kCode,
1799
- "",
1800
- children_count,
1801
- retainers_count);
1659
+ return AddEntry(object, HeapEntry::kCode, "");
1802
1660
  } else if (object->IsSharedFunctionInfo()) {
1803
- SharedFunctionInfo* shared = SharedFunctionInfo::cast(object);
1661
+ String* name = String::cast(SharedFunctionInfo::cast(object)->name());
1804
1662
  return AddEntry(object,
1805
1663
  HeapEntry::kCode,
1806
- collection_->names()->GetName(String::cast(shared->name())),
1807
- children_count,
1808
- retainers_count);
1664
+ collection_->names()->GetName(name));
1809
1665
  } else if (object->IsScript()) {
1810
- Script* script = Script::cast(object);
1666
+ Object* name = Script::cast(object)->name();
1811
1667
  return AddEntry(object,
1812
1668
  HeapEntry::kCode,
1813
- script->name()->IsString() ?
1814
- collection_->names()->GetName(
1815
- String::cast(script->name()))
1816
- : "",
1817
- children_count,
1818
- retainers_count);
1669
+ name->IsString()
1670
+ ? collection_->names()->GetName(String::cast(name))
1671
+ : "");
1819
1672
  } else if (object->IsGlobalContext()) {
1820
- return AddEntry(object,
1821
- HeapEntry::kHidden,
1822
- "system / GlobalContext",
1823
- children_count,
1824
- retainers_count);
1673
+ return AddEntry(object, HeapEntry::kHidden, "system / GlobalContext");
1825
1674
  } else if (object->IsContext()) {
1826
- return AddEntry(object,
1827
- HeapEntry::kHidden,
1828
- "system / Context",
1829
- children_count,
1830
- retainers_count);
1675
+ return AddEntry(object, HeapEntry::kHidden, "system / Context");
1831
1676
  } else if (object->IsFixedArray() ||
1832
1677
  object->IsFixedDoubleArray() ||
1833
1678
  object->IsByteArray() ||
1834
1679
  object->IsExternalArray()) {
1835
- const char* tag = objects_tags_.GetTag(object);
1836
- return AddEntry(object,
1837
- HeapEntry::kArray,
1838
- tag != NULL ? tag : "",
1839
- children_count,
1840
- retainers_count);
1680
+ return AddEntry(object, HeapEntry::kArray, "");
1841
1681
  } else if (object->IsHeapNumber()) {
1842
- return AddEntry(object,
1843
- HeapEntry::kHeapNumber,
1844
- "number",
1845
- children_count,
1846
- retainers_count);
1682
+ return AddEntry(object, HeapEntry::kHeapNumber, "number");
1847
1683
  }
1848
- return AddEntry(object,
1849
- HeapEntry::kHidden,
1850
- GetSystemEntryName(object),
1851
- children_count,
1852
- retainers_count);
1684
+ return AddEntry(object, HeapEntry::kHidden, GetSystemEntryName(object));
1853
1685
  }
1854
1686
 
1855
1687
 
1856
1688
  HeapEntry* V8HeapExplorer::AddEntry(HeapObject* object,
1857
1689
  HeapEntry::Type type,
1858
- const char* name,
1859
- int children_count,
1860
- int retainers_count) {
1690
+ const char* name) {
1861
1691
  int object_size = object->Size();
1862
1692
  SnapshotObjectId object_id =
1863
1693
  collection_->GetObjectId(object->address(), object_size);
1864
- return snapshot_->AddEntry(type,
1865
- name,
1866
- object_id,
1867
- object_size,
1868
- children_count,
1869
- retainers_count);
1694
+ return snapshot_->AddEntry(type, name, object_id, object_size);
1870
1695
  }
1871
1696
 
1872
1697
 
@@ -1935,10 +1760,10 @@ class IndexedReferencesExtractor : public ObjectVisitor {
1935
1760
  public:
1936
1761
  IndexedReferencesExtractor(V8HeapExplorer* generator,
1937
1762
  HeapObject* parent_obj,
1938
- HeapEntry* parent_entry)
1763
+ int parent)
1939
1764
  : generator_(generator),
1940
1765
  parent_obj_(parent_obj),
1941
- parent_(parent_entry),
1766
+ parent_(parent),
1942
1767
  next_index_(1) {
1943
1768
  }
1944
1769
  void VisitPointers(Object** start, Object** end) {
@@ -1967,14 +1792,15 @@ class IndexedReferencesExtractor : public ObjectVisitor {
1967
1792
  }
1968
1793
  V8HeapExplorer* generator_;
1969
1794
  HeapObject* parent_obj_;
1970
- HeapEntry* parent_;
1795
+ int parent_;
1971
1796
  int next_index_;
1972
1797
  };
1973
1798
 
1974
1799
 
1975
1800
  void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
1976
- HeapEntry* entry = GetEntry(obj);
1977
- if (entry == NULL) return; // No interest in this object.
1801
+ HeapEntry* heap_entry = GetEntry(obj);
1802
+ if (heap_entry == NULL) return; // No interest in this object.
1803
+ int entry = heap_entry->index();
1978
1804
 
1979
1805
  bool extract_indexed_refs = true;
1980
1806
  if (obj->IsJSGlobalProxy()) {
@@ -2026,7 +1852,7 @@ void V8HeapExplorer::ExtractJSGlobalProxyReferences(JSGlobalProxy* proxy) {
2026
1852
 
2027
1853
 
2028
1854
  void V8HeapExplorer::ExtractJSObjectReferences(
2029
- HeapEntry* entry, JSObject* js_obj) {
1855
+ int entry, JSObject* js_obj) {
2030
1856
  HeapObject* obj = js_obj;
2031
1857
  ExtractClosureReferences(js_obj, entry);
2032
1858
  ExtractPropertyReferences(js_obj, entry);
@@ -2095,7 +1921,7 @@ void V8HeapExplorer::ExtractJSObjectReferences(
2095
1921
  }
2096
1922
 
2097
1923
 
2098
- void V8HeapExplorer::ExtractStringReferences(HeapEntry* entry, String* string) {
1924
+ void V8HeapExplorer::ExtractStringReferences(int entry, String* string) {
2099
1925
  if (string->IsConsString()) {
2100
1926
  ConsString* cs = ConsString::cast(string);
2101
1927
  SetInternalReference(cs, entry, "first", cs->first());
@@ -2107,8 +1933,7 @@ void V8HeapExplorer::ExtractStringReferences(HeapEntry* entry, String* string) {
2107
1933
  }
2108
1934
 
2109
1935
 
2110
- void V8HeapExplorer::ExtractContextReferences(
2111
- HeapEntry* entry, Context* context) {
1936
+ void V8HeapExplorer::ExtractContextReferences(int entry, Context* context) {
2112
1937
  #define EXTRACT_CONTEXT_FIELD(index, type, name) \
2113
1938
  SetInternalReference(context, entry, #name, context->get(Context::index), \
2114
1939
  FixedArray::OffsetOfElementAt(Context::index));
@@ -2134,7 +1959,7 @@ void V8HeapExplorer::ExtractContextReferences(
2134
1959
  }
2135
1960
 
2136
1961
 
2137
- void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map* map) {
1962
+ void V8HeapExplorer::ExtractMapReferences(int entry, Map* map) {
2138
1963
  SetInternalReference(map, entry,
2139
1964
  "prototype", map->prototype(), Map::kPrototypeOffset);
2140
1965
  SetInternalReference(map, entry,
@@ -2146,10 +1971,16 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map* map) {
2146
1971
  "descriptors", map->instance_descriptors(),
2147
1972
  Map::kInstanceDescriptorsOrBitField3Offset);
2148
1973
  }
2149
- TagObject(map->prototype_transitions(), "(prototype transitions)");
2150
- SetInternalReference(map, entry,
2151
- "prototype_transitions", map->prototype_transitions(),
2152
- Map::kPrototypeTransitionsOffset);
1974
+ if (map->unchecked_prototype_transitions()->IsFixedArray()) {
1975
+ TagObject(map->prototype_transitions(), "(prototype transitions)");
1976
+ SetInternalReference(map, entry,
1977
+ "prototype_transitions", map->prototype_transitions(),
1978
+ Map::kPrototypeTransitionsOrBackPointerOffset);
1979
+ } else {
1980
+ SetInternalReference(map, entry,
1981
+ "back_pointer", map->GetBackPointer(),
1982
+ Map::kPrototypeTransitionsOrBackPointerOffset);
1983
+ }
2153
1984
  SetInternalReference(map, entry,
2154
1985
  "code_cache", map->code_cache(),
2155
1986
  Map::kCodeCacheOffset);
@@ -2157,7 +1988,7 @@ void V8HeapExplorer::ExtractMapReferences(HeapEntry* entry, Map* map) {
2157
1988
 
2158
1989
 
2159
1990
  void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
2160
- HeapEntry* entry, SharedFunctionInfo* shared) {
1991
+ int entry, SharedFunctionInfo* shared) {
2161
1992
  HeapObject* obj = shared;
2162
1993
  SetInternalReference(obj, entry,
2163
1994
  "name", shared->name(),
@@ -2199,7 +2030,7 @@ void V8HeapExplorer::ExtractSharedFunctionInfoReferences(
2199
2030
  }
2200
2031
 
2201
2032
 
2202
- void V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry, Script* script) {
2033
+ void V8HeapExplorer::ExtractScriptReferences(int entry, Script* script) {
2203
2034
  HeapObject* obj = script;
2204
2035
  SetInternalReference(obj, entry,
2205
2036
  "source", script->source(),
@@ -2221,7 +2052,7 @@ void V8HeapExplorer::ExtractScriptReferences(HeapEntry* entry, Script* script) {
2221
2052
 
2222
2053
 
2223
2054
  void V8HeapExplorer::ExtractCodeCacheReferences(
2224
- HeapEntry* entry, CodeCache* code_cache) {
2055
+ int entry, CodeCache* code_cache) {
2225
2056
  TagObject(code_cache->default_cache(), "(default code cache)");
2226
2057
  SetInternalReference(code_cache, entry,
2227
2058
  "default_cache", code_cache->default_cache(),
@@ -2233,7 +2064,7 @@ void V8HeapExplorer::ExtractCodeCacheReferences(
2233
2064
  }
2234
2065
 
2235
2066
 
2236
- void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code* code) {
2067
+ void V8HeapExplorer::ExtractCodeReferences(int entry, Code* code) {
2237
2068
  TagObject(code->relocation_info(), "(code relocation info)");
2238
2069
  SetInternalReference(code, entry,
2239
2070
  "relocation_info", code->relocation_info(),
@@ -2255,13 +2086,12 @@ void V8HeapExplorer::ExtractCodeReferences(HeapEntry* entry, Code* code) {
2255
2086
 
2256
2087
 
2257
2088
  void V8HeapExplorer::ExtractJSGlobalPropertyCellReferences(
2258
- HeapEntry* entry, JSGlobalPropertyCell* cell) {
2089
+ int entry, JSGlobalPropertyCell* cell) {
2259
2090
  SetInternalReference(cell, entry, "value", cell->value());
2260
2091
  }
2261
2092
 
2262
2093
 
2263
- void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
2264
- HeapEntry* entry) {
2094
+ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj, int entry) {
2265
2095
  if (!js_obj->IsJSFunction()) return;
2266
2096
 
2267
2097
  JSFunction* func = JSFunction::cast(js_obj);
@@ -2303,8 +2133,7 @@ void V8HeapExplorer::ExtractClosureReferences(JSObject* js_obj,
2303
2133
  }
2304
2134
 
2305
2135
 
2306
- void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
2307
- HeapEntry* entry) {
2136
+ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj, int entry) {
2308
2137
  if (js_obj->HasFastProperties()) {
2309
2138
  DescriptorArray* descs = js_obj->map()->instance_descriptors();
2310
2139
  for (int i = 0; i < descs->number_of_descriptors(); i++) {
@@ -2377,9 +2206,8 @@ void V8HeapExplorer::ExtractPropertyReferences(JSObject* js_obj,
2377
2206
  }
2378
2207
 
2379
2208
 
2380
- void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
2381
- HeapEntry* entry) {
2382
- if (js_obj->HasFastElements()) {
2209
+ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj, int entry) {
2210
+ if (js_obj->HasFastObjectElements()) {
2383
2211
  FixedArray* elements = FixedArray::cast(js_obj->elements());
2384
2212
  int length = js_obj->IsJSArray() ?
2385
2213
  Smi::cast(JSArray::cast(js_obj)->length())->value() :
@@ -2404,8 +2232,7 @@ void V8HeapExplorer::ExtractElementReferences(JSObject* js_obj,
2404
2232
  }
2405
2233
 
2406
2234
 
2407
- void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj,
2408
- HeapEntry* entry) {
2235
+ void V8HeapExplorer::ExtractInternalReferences(JSObject* js_obj, int entry) {
2409
2236
  int length = js_obj->GetInternalFieldCount();
2410
2237
  for (int i = 0; i < length; ++i) {
2411
2238
  Object* o = js_obj->GetInternalField(i);
@@ -2531,6 +2358,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(
2531
2358
  filler_ = NULL;
2532
2359
  return false;
2533
2360
  }
2361
+
2534
2362
  SetRootGcRootsReference();
2535
2363
  RootsReferencesExtractor extractor;
2536
2364
  heap_->IterateRoots(&extractor, VISIT_ONLY_STRONG);
@@ -2538,33 +2366,7 @@ bool V8HeapExplorer::IterateAndExtractReferences(
2538
2366
  heap_->IterateRoots(&extractor, VISIT_ALL);
2539
2367
  extractor.FillReferences(this);
2540
2368
  filler_ = NULL;
2541
- return progress_->ProgressReport(false);
2542
- }
2543
-
2544
-
2545
- bool V8HeapExplorer::IterateAndSetObjectNames(SnapshotFillerInterface* filler) {
2546
- HeapIterator iterator(HeapIterator::kFilterUnreachable);
2547
- filler_ = filler;
2548
- for (HeapObject* obj = iterator.next(); obj != NULL; obj = iterator.next()) {
2549
- SetObjectName(obj);
2550
- }
2551
- return true;
2552
- }
2553
-
2554
-
2555
- void V8HeapExplorer::SetObjectName(HeapObject* object) {
2556
- if (!object->IsJSObject() || object->IsJSRegExp() || object->IsJSFunction()) {
2557
- return;
2558
- }
2559
- const char* name = collection_->names()->GetName(
2560
- GetConstructorName(JSObject::cast(object)));
2561
- if (object->IsJSGlobalObject()) {
2562
- const char* tag = objects_tags_.GetTag(object);
2563
- if (tag != NULL) {
2564
- name = collection_->names()->GetFormatted("%s / %s", name, tag);
2565
- }
2566
- }
2567
- GetEntry(object)->set_name(name);
2369
+ return progress_->ProgressReport(true);
2568
2370
  }
2569
2371
 
2570
2372
 
@@ -2586,55 +2388,49 @@ bool V8HeapExplorer::IsEssentialObject(Object* object) {
2586
2388
 
2587
2389
 
2588
2390
  void V8HeapExplorer::SetClosureReference(HeapObject* parent_obj,
2589
- HeapEntry* parent_entry,
2391
+ int parent_entry,
2590
2392
  String* reference_name,
2591
2393
  Object* child_obj) {
2592
2394
  HeapEntry* child_entry = GetEntry(child_obj);
2593
2395
  if (child_entry != NULL) {
2594
2396
  filler_->SetNamedReference(HeapGraphEdge::kContextVariable,
2595
- parent_obj,
2596
2397
  parent_entry,
2597
2398
  collection_->names()->GetName(reference_name),
2598
- child_obj,
2599
2399
  child_entry);
2600
2400
  }
2601
2401
  }
2602
2402
 
2603
2403
 
2604
2404
  void V8HeapExplorer::SetNativeBindReference(HeapObject* parent_obj,
2605
- HeapEntry* parent_entry,
2405
+ int parent_entry,
2606
2406
  const char* reference_name,
2607
2407
  Object* child_obj) {
2608
2408
  HeapEntry* child_entry = GetEntry(child_obj);
2609
2409
  if (child_entry != NULL) {
2610
2410
  filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2611
- parent_obj,
2612
2411
  parent_entry,
2613
2412
  reference_name,
2614
- child_obj,
2615
2413
  child_entry);
2616
2414
  }
2617
2415
  }
2618
2416
 
2619
2417
 
2620
2418
  void V8HeapExplorer::SetElementReference(HeapObject* parent_obj,
2621
- HeapEntry* parent_entry,
2419
+ int parent_entry,
2622
2420
  int index,
2623
2421
  Object* child_obj) {
2624
2422
  HeapEntry* child_entry = GetEntry(child_obj);
2625
2423
  if (child_entry != NULL) {
2626
2424
  filler_->SetIndexedReference(HeapGraphEdge::kElement,
2627
- parent_obj,
2628
2425
  parent_entry,
2629
2426
  index,
2630
- child_obj,
2631
2427
  child_entry);
2632
2428
  }
2633
2429
  }
2634
2430
 
2635
2431
 
2636
2432
  void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2637
- HeapEntry* parent_entry,
2433
+ int parent_entry,
2638
2434
  const char* reference_name,
2639
2435
  Object* child_obj,
2640
2436
  int field_offset) {
@@ -2642,16 +2438,16 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2642
2438
  if (child_entry == NULL) return;
2643
2439
  if (IsEssentialObject(child_obj)) {
2644
2440
  filler_->SetNamedReference(HeapGraphEdge::kInternal,
2645
- parent_obj, parent_entry,
2441
+ parent_entry,
2646
2442
  reference_name,
2647
- child_obj, child_entry);
2443
+ child_entry);
2648
2444
  }
2649
2445
  IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2650
2446
  }
2651
2447
 
2652
2448
 
2653
2449
  void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2654
- HeapEntry* parent_entry,
2450
+ int parent_entry,
2655
2451
  int index,
2656
2452
  Object* child_obj,
2657
2453
  int field_offset) {
@@ -2659,42 +2455,38 @@ void V8HeapExplorer::SetInternalReference(HeapObject* parent_obj,
2659
2455
  if (child_entry == NULL) return;
2660
2456
  if (IsEssentialObject(child_obj)) {
2661
2457
  filler_->SetNamedReference(HeapGraphEdge::kInternal,
2662
- parent_obj, parent_entry,
2458
+ parent_entry,
2663
2459
  collection_->names()->GetName(index),
2664
- child_obj, child_entry);
2460
+ child_entry);
2665
2461
  }
2666
2462
  IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2667
2463
  }
2668
2464
 
2669
2465
 
2670
2466
  void V8HeapExplorer::SetHiddenReference(HeapObject* parent_obj,
2671
- HeapEntry* parent_entry,
2467
+ int parent_entry,
2672
2468
  int index,
2673
2469
  Object* child_obj) {
2674
2470
  HeapEntry* child_entry = GetEntry(child_obj);
2675
2471
  if (child_entry != NULL && IsEssentialObject(child_obj)) {
2676
2472
  filler_->SetIndexedReference(HeapGraphEdge::kHidden,
2677
- parent_obj,
2678
2473
  parent_entry,
2679
2474
  index,
2680
- child_obj,
2681
2475
  child_entry);
2682
2476
  }
2683
2477
  }
2684
2478
 
2685
2479
 
2686
2480
  void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
2687
- HeapEntry* parent_entry,
2481
+ int parent_entry,
2688
2482
  int index,
2689
2483
  Object* child_obj,
2690
2484
  int field_offset) {
2691
2485
  HeapEntry* child_entry = GetEntry(child_obj);
2692
2486
  if (child_entry != NULL) {
2693
2487
  filler_->SetIndexedReference(HeapGraphEdge::kWeak,
2694
- parent_obj,
2695
2488
  parent_entry,
2696
2489
  index,
2697
- child_obj,
2698
2490
  child_entry);
2699
2491
  IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2700
2492
  }
@@ -2702,7 +2494,7 @@ void V8HeapExplorer::SetWeakReference(HeapObject* parent_obj,
2702
2494
 
2703
2495
 
2704
2496
  void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2705
- HeapEntry* parent_entry,
2497
+ int parent_entry,
2706
2498
  String* reference_name,
2707
2499
  Object* child_obj,
2708
2500
  const char* name_format_string,
@@ -2719,10 +2511,8 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2719
2511
  collection_->names()->GetName(reference_name);
2720
2512
 
2721
2513
  filler_->SetNamedReference(type,
2722
- parent_obj,
2723
2514
  parent_entry,
2724
2515
  name,
2725
- child_obj,
2726
2516
  child_entry);
2727
2517
  IndexedReferencesExtractor::MarkVisitedField(parent_obj, field_offset);
2728
2518
  }
@@ -2730,16 +2520,14 @@ void V8HeapExplorer::SetPropertyReference(HeapObject* parent_obj,
2730
2520
 
2731
2521
 
2732
2522
  void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
2733
- HeapEntry* parent_entry,
2523
+ int parent_entry,
2734
2524
  String* reference_name,
2735
2525
  Object* child_obj) {
2736
2526
  HeapEntry* child_entry = GetEntry(child_obj);
2737
2527
  if (child_entry != NULL) {
2738
2528
  filler_->SetNamedReference(HeapGraphEdge::kShortcut,
2739
- parent_obj,
2740
2529
  parent_entry,
2741
2530
  collection_->names()->GetName(reference_name),
2742
- child_obj,
2743
2531
  child_entry);
2744
2532
  }
2745
2533
  }
@@ -2748,8 +2536,8 @@ void V8HeapExplorer::SetPropertyShortcutReference(HeapObject* parent_obj,
2748
2536
  void V8HeapExplorer::SetRootGcRootsReference() {
2749
2537
  filler_->SetIndexedAutoIndexReference(
2750
2538
  HeapGraphEdge::kElement,
2751
- kInternalRootObject, snapshot_->root(),
2752
- kGcRootsObject, snapshot_->gc_roots());
2539
+ snapshot_->root()->index(),
2540
+ snapshot_->gc_roots());
2753
2541
  }
2754
2542
 
2755
2543
 
@@ -2758,16 +2546,16 @@ void V8HeapExplorer::SetUserGlobalReference(Object* child_obj) {
2758
2546
  ASSERT(child_entry != NULL);
2759
2547
  filler_->SetNamedAutoIndexReference(
2760
2548
  HeapGraphEdge::kShortcut,
2761
- kInternalRootObject, snapshot_->root(),
2762
- child_obj, child_entry);
2549
+ snapshot_->root()->index(),
2550
+ child_entry);
2763
2551
  }
2764
2552
 
2765
2553
 
2766
2554
  void V8HeapExplorer::SetGcRootsReference(VisitorSynchronization::SyncTag tag) {
2767
2555
  filler_->SetIndexedAutoIndexReference(
2768
2556
  HeapGraphEdge::kElement,
2769
- kGcRootsObject, snapshot_->gc_roots(),
2770
- GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag));
2557
+ snapshot_->gc_roots()->index(),
2558
+ snapshot_->gc_subroot(tag));
2771
2559
  }
2772
2560
 
2773
2561
 
@@ -2779,14 +2567,14 @@ void V8HeapExplorer::SetGcSubrootReference(
2779
2567
  if (name != NULL) {
2780
2568
  filler_->SetNamedReference(
2781
2569
  HeapGraphEdge::kInternal,
2782
- GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
2570
+ snapshot_->gc_subroot(tag)->index(),
2783
2571
  name,
2784
- child_obj, child_entry);
2572
+ child_entry);
2785
2573
  } else {
2786
2574
  filler_->SetIndexedAutoIndexReference(
2787
2575
  is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement,
2788
- GetNthGcSubrootObject(tag), snapshot_->gc_subroot(tag),
2789
- child_obj, child_entry);
2576
+ snapshot_->gc_subroot(tag)->index(),
2577
+ child_entry);
2790
2578
  }
2791
2579
  }
2792
2580
  }
@@ -2813,7 +2601,10 @@ const char* V8HeapExplorer::GetStrongGcSubrootName(Object* object) {
2813
2601
 
2814
2602
  void V8HeapExplorer::TagObject(Object* obj, const char* tag) {
2815
2603
  if (IsEssentialObject(obj)) {
2816
- objects_tags_.SetTag(obj, tag);
2604
+ HeapEntry* entry = GetEntry(obj);
2605
+ if (entry->name()[0] == '\0') {
2606
+ entry->set_name(tag);
2607
+ }
2817
2608
  }
2818
2609
  }
2819
2610
 
@@ -2903,8 +2694,7 @@ class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
2903
2694
  collection_(snapshot_->collection()),
2904
2695
  entries_type_(entries_type) {
2905
2696
  }
2906
- virtual HeapEntry* AllocateEntry(
2907
- HeapThing ptr, int children_count, int retainers_count);
2697
+ virtual HeapEntry* AllocateEntry(HeapThing ptr);
2908
2698
  private:
2909
2699
  HeapSnapshot* snapshot_;
2910
2700
  HeapSnapshotsCollection* collection_;
@@ -2912,23 +2702,19 @@ class BasicHeapEntriesAllocator : public HeapEntriesAllocator {
2912
2702
  };
2913
2703
 
2914
2704
 
2915
- HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(
2916
- HeapThing ptr, int children_count, int retainers_count) {
2705
+ HeapEntry* BasicHeapEntriesAllocator::AllocateEntry(HeapThing ptr) {
2917
2706
  v8::RetainedObjectInfo* info = reinterpret_cast<v8::RetainedObjectInfo*>(ptr);
2918
2707
  intptr_t elements = info->GetElementCount();
2919
2708
  intptr_t size = info->GetSizeInBytes();
2709
+ const char* name = elements != -1
2710
+ ? collection_->names()->GetFormatted(
2711
+ "%s / %" V8_PTR_PREFIX "d entries", info->GetLabel(), elements)
2712
+ : collection_->names()->GetCopy(info->GetLabel());
2920
2713
  return snapshot_->AddEntry(
2921
2714
  entries_type_,
2922
- elements != -1 ?
2923
- collection_->names()->GetFormatted(
2924
- "%s / %" V8_PTR_PREFIX "d entries",
2925
- info->GetLabel(),
2926
- info->GetElementCount()) :
2927
- collection_->names()->GetCopy(info->GetLabel()),
2715
+ name,
2928
2716
  HeapObjectsMap::GenerateId(info),
2929
- size != -1 ? static_cast<int>(size) : 0,
2930
- children_count,
2931
- retainers_count);
2717
+ size != -1 ? static_cast<int>(size) : 0);
2932
2718
  }
2933
2719
 
2934
2720
 
@@ -3009,9 +2795,9 @@ void NativeObjectsExplorer::FillImplicitReferences() {
3009
2795
  for (int i = 0; i < groups->length(); ++i) {
3010
2796
  ImplicitRefGroup* group = groups->at(i);
3011
2797
  HeapObject* parent = *group->parent_;
3012
- HeapEntry* parent_entry =
3013
- filler_->FindOrAddEntry(parent, native_entries_allocator_);
3014
- ASSERT(parent_entry != NULL);
2798
+ int parent_entry =
2799
+ filler_->FindOrAddEntry(parent, native_entries_allocator_)->index();
2800
+ ASSERT(parent_entry != HeapEntry::kNoEntry);
3015
2801
  Object*** children = group->children_;
3016
2802
  for (size_t j = 0; j < group->length_; ++j) {
3017
2803
  Object* child = *children[j];
@@ -3019,9 +2805,9 @@ void NativeObjectsExplorer::FillImplicitReferences() {
3019
2805
  filler_->FindOrAddEntry(child, native_entries_allocator_);
3020
2806
  filler_->SetNamedReference(
3021
2807
  HeapGraphEdge::kInternal,
3022
- parent, parent_entry,
2808
+ parent_entry,
3023
2809
  "native",
3024
- child, child_entry);
2810
+ child_entry);
3025
2811
  }
3026
2812
  }
3027
2813
  }
@@ -3099,8 +2885,9 @@ NativeGroupRetainedObjectInfo* NativeObjectsExplorer::FindOrAddGroupInfo(
3099
2885
  HEAP->HashSeed());
3100
2886
  HashMap::Entry* entry = native_groups_.Lookup(const_cast<char*>(label_copy),
3101
2887
  hash, true);
3102
- if (entry->value == NULL)
2888
+ if (entry->value == NULL) {
3103
2889
  entry->value = new NativeGroupRetainedObjectInfo(label);
2890
+ }
3104
2891
  return static_cast<NativeGroupRetainedObjectInfo*>(entry->value);
3105
2892
  }
3106
2893
 
@@ -3116,8 +2903,8 @@ void NativeObjectsExplorer::SetNativeRootReference(
3116
2903
  filler_->FindOrAddEntry(group_info, synthetic_entries_allocator_);
3117
2904
  filler_->SetNamedAutoIndexReference(
3118
2905
  HeapGraphEdge::kInternal,
3119
- group_info, group_entry,
3120
- info, child_entry);
2906
+ group_entry->index(),
2907
+ child_entry);
3121
2908
  }
3122
2909
 
3123
2910
 
@@ -3129,12 +2916,12 @@ void NativeObjectsExplorer::SetWrapperNativeReferences(
3129
2916
  filler_->FindOrAddEntry(info, native_entries_allocator_);
3130
2917
  ASSERT(info_entry != NULL);
3131
2918
  filler_->SetNamedReference(HeapGraphEdge::kInternal,
3132
- wrapper, wrapper_entry,
2919
+ wrapper_entry->index(),
3133
2920
  "native",
3134
- info, info_entry);
2921
+ info_entry);
3135
2922
  filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
3136
- info, info_entry,
3137
- wrapper, wrapper_entry);
2923
+ info_entry->index(),
2924
+ wrapper_entry);
3138
2925
  }
3139
2926
 
3140
2927
 
@@ -3149,8 +2936,8 @@ void NativeObjectsExplorer::SetRootNativeRootsReference() {
3149
2936
  ASSERT(group_entry != NULL);
3150
2937
  filler_->SetIndexedAutoIndexReference(
3151
2938
  HeapGraphEdge::kElement,
3152
- V8HeapExplorer::kInternalRootObject, snapshot_->root(),
3153
- group_info, group_entry);
2939
+ snapshot_->root()->index(),
2940
+ group_entry);
3154
2941
  }
3155
2942
  }
3156
2943
 
@@ -3165,56 +2952,6 @@ void NativeObjectsExplorer::VisitSubtreeWrapper(Object** p, uint16_t class_id) {
3165
2952
  }
3166
2953
 
3167
2954
 
3168
- class SnapshotCounter : public SnapshotFillerInterface {
3169
- public:
3170
- explicit SnapshotCounter(HeapEntriesMap* entries) : entries_(entries) { }
3171
- HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3172
- entries_->Pair(ptr, allocator, HeapEntriesMap::kHeapEntryPlaceholder);
3173
- return HeapEntriesMap::kHeapEntryPlaceholder;
3174
- }
3175
- HeapEntry* FindEntry(HeapThing ptr) {
3176
- return entries_->Map(ptr);
3177
- }
3178
- HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3179
- HeapEntry* entry = FindEntry(ptr);
3180
- return entry != NULL ? entry : AddEntry(ptr, allocator);
3181
- }
3182
- void SetIndexedReference(HeapGraphEdge::Type,
3183
- HeapThing parent_ptr,
3184
- HeapEntry*,
3185
- int,
3186
- HeapThing child_ptr,
3187
- HeapEntry*) {
3188
- entries_->CountReference(parent_ptr, child_ptr);
3189
- }
3190
- void SetIndexedAutoIndexReference(HeapGraphEdge::Type,
3191
- HeapThing parent_ptr,
3192
- HeapEntry*,
3193
- HeapThing child_ptr,
3194
- HeapEntry*) {
3195
- entries_->CountReference(parent_ptr, child_ptr);
3196
- }
3197
- void SetNamedReference(HeapGraphEdge::Type,
3198
- HeapThing parent_ptr,
3199
- HeapEntry*,
3200
- const char*,
3201
- HeapThing child_ptr,
3202
- HeapEntry*) {
3203
- entries_->CountReference(parent_ptr, child_ptr);
3204
- }
3205
- void SetNamedAutoIndexReference(HeapGraphEdge::Type,
3206
- HeapThing parent_ptr,
3207
- HeapEntry*,
3208
- HeapThing child_ptr,
3209
- HeapEntry*) {
3210
- entries_->CountReference(parent_ptr, child_ptr);
3211
- }
3212
-
3213
- private:
3214
- HeapEntriesMap* entries_;
3215
- };
3216
-
3217
-
3218
2955
  class SnapshotFiller : public SnapshotFillerInterface {
3219
2956
  public:
3220
2957
  explicit SnapshotFiller(HeapSnapshot* snapshot, HeapEntriesMap* entries)
@@ -3222,64 +2959,48 @@ class SnapshotFiller : public SnapshotFillerInterface {
3222
2959
  collection_(snapshot->collection()),
3223
2960
  entries_(entries) { }
3224
2961
  HeapEntry* AddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3225
- UNREACHABLE();
3226
- return NULL;
2962
+ HeapEntry* entry = allocator->AllocateEntry(ptr);
2963
+ entries_->Pair(ptr, entry->index());
2964
+ return entry;
3227
2965
  }
3228
2966
  HeapEntry* FindEntry(HeapThing ptr) {
3229
- return entries_->Map(ptr);
2967
+ int index = entries_->Map(ptr);
2968
+ return index != HeapEntry::kNoEntry ? &snapshot_->entries()[index] : NULL;
3230
2969
  }
3231
2970
  HeapEntry* FindOrAddEntry(HeapThing ptr, HeapEntriesAllocator* allocator) {
3232
2971
  HeapEntry* entry = FindEntry(ptr);
3233
2972
  return entry != NULL ? entry : AddEntry(ptr, allocator);
3234
2973
  }
3235
2974
  void SetIndexedReference(HeapGraphEdge::Type type,
3236
- HeapThing parent_ptr,
3237
- HeapEntry* parent_entry,
2975
+ int parent,
3238
2976
  int index,
3239
- HeapThing child_ptr,
3240
2977
  HeapEntry* child_entry) {
3241
- int child_index, retainer_index;
3242
- entries_->CountReference(
3243
- parent_ptr, child_ptr, &child_index, &retainer_index);
3244
- parent_entry->SetIndexedReference(
3245
- type, child_index, index, child_entry, retainer_index);
2978
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
2979
+ parent_entry->SetIndexedReference(type, index, child_entry);
3246
2980
  }
3247
2981
  void SetIndexedAutoIndexReference(HeapGraphEdge::Type type,
3248
- HeapThing parent_ptr,
3249
- HeapEntry* parent_entry,
3250
- HeapThing child_ptr,
2982
+ int parent,
3251
2983
  HeapEntry* child_entry) {
3252
- int child_index, retainer_index;
3253
- entries_->CountReference(
3254
- parent_ptr, child_ptr, &child_index, &retainer_index);
3255
- parent_entry->SetIndexedReference(
3256
- type, child_index, child_index + 1, child_entry, retainer_index);
2984
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
2985
+ int index = parent_entry->children_count() + 1;
2986
+ parent_entry->SetIndexedReference(type, index, child_entry);
3257
2987
  }
3258
2988
  void SetNamedReference(HeapGraphEdge::Type type,
3259
- HeapThing parent_ptr,
3260
- HeapEntry* parent_entry,
2989
+ int parent,
3261
2990
  const char* reference_name,
3262
- HeapThing child_ptr,
3263
2991
  HeapEntry* child_entry) {
3264
- int child_index, retainer_index;
3265
- entries_->CountReference(
3266
- parent_ptr, child_ptr, &child_index, &retainer_index);
3267
- parent_entry->SetNamedReference(
3268
- type, child_index, reference_name, child_entry, retainer_index);
2992
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
2993
+ parent_entry->SetNamedReference(type, reference_name, child_entry);
3269
2994
  }
3270
2995
  void SetNamedAutoIndexReference(HeapGraphEdge::Type type,
3271
- HeapThing parent_ptr,
3272
- HeapEntry* parent_entry,
3273
- HeapThing child_ptr,
2996
+ int parent,
3274
2997
  HeapEntry* child_entry) {
3275
- int child_index, retainer_index;
3276
- entries_->CountReference(
3277
- parent_ptr, child_ptr, &child_index, &retainer_index);
3278
- parent_entry->SetNamedReference(type,
3279
- child_index,
3280
- collection_->names()->GetName(child_index + 1),
3281
- child_entry,
3282
- retainer_index);
2998
+ HeapEntry* parent_entry = &snapshot_->entries()[parent];
2999
+ int index = parent_entry->children_count() + 1;
3000
+ parent_entry->SetNamedReference(
3001
+ type,
3002
+ collection_->names()->GetName(index),
3003
+ child_entry);
3283
3004
  }
3284
3005
 
3285
3006
  private:
@@ -3329,35 +3050,17 @@ bool HeapSnapshotGenerator::GenerateSnapshot() {
3329
3050
  debug_heap->Verify();
3330
3051
  #endif
3331
3052
 
3332
- SetProgressTotal(2); // 2 passes.
3053
+ SetProgressTotal(1); // 1 pass.
3333
3054
 
3334
3055
  #ifdef DEBUG
3335
3056
  debug_heap->Verify();
3336
3057
  #endif
3337
3058
 
3338
- // Pass 1. Iterate heap contents to count entries and references.
3339
- if (!CountEntriesAndReferences()) return false;
3340
-
3341
- #ifdef DEBUG
3342
- debug_heap->Verify();
3343
- #endif
3344
-
3345
- // Allocate memory for entries and references.
3346
- snapshot_->AllocateEntries(entries_.entries_count(),
3347
- entries_.total_children_count(),
3348
- entries_.total_retainers_count());
3349
-
3350
- // Allocate heap objects to entries hash map.
3351
- entries_.AllocateEntries(V8HeapExplorer::kInternalRootObject);
3352
-
3353
- // Pass 2. Fill references.
3354
3059
  if (!FillReferences()) return false;
3355
3060
 
3061
+ snapshot_->FillChildren();
3356
3062
  snapshot_->RememberLastJSObjectId();
3357
3063
 
3358
- if (!SetEntriesDominators()) return false;
3359
- if (!CalculateRetainedSizes()) return false;
3360
-
3361
3064
  progress_counter_ = progress_total_;
3362
3065
  if (!ProgressReport(true)) return false;
3363
3066
  return true;
@@ -3384,213 +3087,18 @@ bool HeapSnapshotGenerator::ProgressReport(bool force) {
3384
3087
  void HeapSnapshotGenerator::SetProgressTotal(int iterations_count) {
3385
3088
  if (control_ == NULL) return;
3386
3089
  HeapIterator iterator(HeapIterator::kFilterUnreachable);
3387
- progress_total_ = (
3090
+ progress_total_ = iterations_count * (
3388
3091
  v8_heap_explorer_.EstimateObjectsCount(&iterator) +
3389
- dom_explorer_.EstimateObjectsCount()) * iterations_count;
3092
+ dom_explorer_.EstimateObjectsCount());
3390
3093
  progress_counter_ = 0;
3391
3094
  }
3392
3095
 
3393
3096
 
3394
- bool HeapSnapshotGenerator::CountEntriesAndReferences() {
3395
- SnapshotCounter counter(&entries_);
3396
- v8_heap_explorer_.AddRootEntries(&counter);
3397
- return v8_heap_explorer_.IterateAndExtractReferences(&counter)
3398
- && dom_explorer_.IterateAndExtractReferences(&counter);
3399
- }
3400
-
3401
-
3402
3097
  bool HeapSnapshotGenerator::FillReferences() {
3403
3098
  SnapshotFiller filler(snapshot_, &entries_);
3404
- // IterateAndExtractReferences cannot set object names because
3405
- // it makes call to JSObject::LocalLookupRealNamedProperty which
3406
- // in turn may relocate objects in property maps thus changing the heap
3407
- // layout and affecting retainer counts. This is not acceptable because
3408
- // number of retainers must not change between count and fill passes.
3409
- // To avoid this there's a separate postpass that set object names.
3099
+ v8_heap_explorer_.AddRootEntries(&filler);
3410
3100
  return v8_heap_explorer_.IterateAndExtractReferences(&filler)
3411
- && dom_explorer_.IterateAndExtractReferences(&filler)
3412
- && v8_heap_explorer_.IterateAndSetObjectNames(&filler);
3413
- }
3414
-
3415
-
3416
- bool HeapSnapshotGenerator::IsUserGlobalReference(const HeapGraphEdge& edge) {
3417
- ASSERT(edge.from() == snapshot_->root());
3418
- return edge.type() == HeapGraphEdge::kShortcut;
3419
- }
3420
-
3421
-
3422
- void HeapSnapshotGenerator::MarkUserReachableObjects() {
3423
- List<HeapEntry*> worklist;
3424
-
3425
- Vector<HeapGraphEdge> children = snapshot_->root()->children();
3426
- for (int i = 0; i < children.length(); ++i) {
3427
- if (IsUserGlobalReference(children[i])) {
3428
- worklist.Add(children[i].to());
3429
- }
3430
- }
3431
-
3432
- while (!worklist.is_empty()) {
3433
- HeapEntry* entry = worklist.RemoveLast();
3434
- if (entry->user_reachable()) continue;
3435
- entry->set_user_reachable();
3436
- Vector<HeapGraphEdge> children = entry->children();
3437
- for (int i = 0; i < children.length(); ++i) {
3438
- HeapEntry* child = children[i].to();
3439
- if (!child->user_reachable()) {
3440
- worklist.Add(child);
3441
- }
3442
- }
3443
- }
3444
- }
3445
-
3446
-
3447
- static bool IsRetainingEdge(HeapGraphEdge* edge) {
3448
- if (edge->type() == HeapGraphEdge::kShortcut) return false;
3449
- // The edge is not retaining if it goes from system domain
3450
- // (i.e. an object not reachable from window) to the user domain
3451
- // (i.e. a reachable object).
3452
- return edge->from()->user_reachable()
3453
- || !edge->to()->user_reachable();
3454
- }
3455
-
3456
-
3457
- void HeapSnapshotGenerator::FillPostorderIndexes(
3458
- Vector<HeapEntry*>* entries) {
3459
- snapshot_->ClearPaint();
3460
- int current_entry = 0;
3461
- List<HeapEntry*> nodes_to_visit;
3462
- HeapEntry* root = snapshot_->root();
3463
- nodes_to_visit.Add(root);
3464
- snapshot_->root()->paint();
3465
- while (!nodes_to_visit.is_empty()) {
3466
- HeapEntry* entry = nodes_to_visit.last();
3467
- Vector<HeapGraphEdge> children = entry->children();
3468
- bool has_new_edges = false;
3469
- for (int i = 0; i < children.length(); ++i) {
3470
- if (entry != root && !IsRetainingEdge(&children[i])) continue;
3471
- HeapEntry* child = children[i].to();
3472
- if (!child->painted()) {
3473
- nodes_to_visit.Add(child);
3474
- child->paint();
3475
- has_new_edges = true;
3476
- }
3477
- }
3478
- if (!has_new_edges) {
3479
- entry->set_ordered_index(current_entry);
3480
- (*entries)[current_entry++] = entry;
3481
- nodes_to_visit.RemoveLast();
3482
- }
3483
- }
3484
- ASSERT_EQ(current_entry, entries->length());
3485
- }
3486
-
3487
-
3488
- static int Intersect(int i1, int i2, const Vector<int>& dominators) {
3489
- int finger1 = i1, finger2 = i2;
3490
- while (finger1 != finger2) {
3491
- while (finger1 < finger2) finger1 = dominators[finger1];
3492
- while (finger2 < finger1) finger2 = dominators[finger2];
3493
- }
3494
- return finger1;
3495
- }
3496
-
3497
-
3498
- // The algorithm is based on the article:
3499
- // K. Cooper, T. Harvey and K. Kennedy "A Simple, Fast Dominance Algorithm"
3500
- // Softw. Pract. Exper. 4 (2001), pp. 1-10.
3501
- bool HeapSnapshotGenerator::BuildDominatorTree(
3502
- const Vector<HeapEntry*>& entries,
3503
- Vector<int>* dominators) {
3504
- if (entries.length() == 0) return true;
3505
- HeapEntry* root = snapshot_->root();
3506
- const int entries_length = entries.length(), root_index = entries_length - 1;
3507
- static const int kNoDominator = -1;
3508
- for (int i = 0; i < root_index; ++i) (*dominators)[i] = kNoDominator;
3509
- (*dominators)[root_index] = root_index;
3510
-
3511
- // The affected array is used to mark entries which dominators
3512
- // have to be racalculated because of changes in their retainers.
3513
- ScopedVector<bool> affected(entries_length);
3514
- for (int i = 0; i < affected.length(); ++i) affected[i] = false;
3515
- // Mark the root direct children as affected.
3516
- Vector<HeapGraphEdge> children = entries[root_index]->children();
3517
- for (int i = 0; i < children.length(); ++i) {
3518
- affected[children[i].to()->ordered_index()] = true;
3519
- }
3520
-
3521
- bool changed = true;
3522
- while (changed) {
3523
- changed = false;
3524
- if (!ProgressReport(true)) return false;
3525
- for (int i = root_index - 1; i >= 0; --i) {
3526
- if (!affected[i]) continue;
3527
- affected[i] = false;
3528
- // If dominator of the entry has already been set to root,
3529
- // then it can't propagate any further.
3530
- if ((*dominators)[i] == root_index) continue;
3531
- int new_idom_index = kNoDominator;
3532
- Vector<HeapGraphEdge*> rets = entries[i]->retainers();
3533
- for (int j = 0; j < rets.length(); ++j) {
3534
- if (rets[j]->from() != root && !IsRetainingEdge(rets[j])) continue;
3535
- int ret_index = rets[j]->from()->ordered_index();
3536
- if (dominators->at(ret_index) != kNoDominator) {
3537
- new_idom_index = new_idom_index == kNoDominator
3538
- ? ret_index
3539
- : Intersect(ret_index, new_idom_index, *dominators);
3540
- // If idom has already reached the root, it doesn't make sense
3541
- // to check other retainers.
3542
- if (new_idom_index == root_index) break;
3543
- }
3544
- }
3545
- if (new_idom_index != kNoDominator
3546
- && dominators->at(i) != new_idom_index) {
3547
- (*dominators)[i] = new_idom_index;
3548
- changed = true;
3549
- Vector<HeapGraphEdge> children = entries[i]->children();
3550
- for (int j = 0; j < children.length(); ++j) {
3551
- affected[children[j].to()->ordered_index()] = true;
3552
- }
3553
- }
3554
- }
3555
- }
3556
- return true;
3557
- }
3558
-
3559
-
3560
- bool HeapSnapshotGenerator::SetEntriesDominators() {
3561
- MarkUserReachableObjects();
3562
- // This array is used for maintaining postorder of nodes.
3563
- ScopedVector<HeapEntry*> ordered_entries(snapshot_->entries()->length());
3564
- FillPostorderIndexes(&ordered_entries);
3565
- ScopedVector<int> dominators(ordered_entries.length());
3566
- if (!BuildDominatorTree(ordered_entries, &dominators)) return false;
3567
- for (int i = 0; i < ordered_entries.length(); ++i) {
3568
- ASSERT(dominators[i] >= 0);
3569
- ordered_entries[i]->set_dominator(ordered_entries[dominators[i]]);
3570
- }
3571
- return true;
3572
- }
3573
-
3574
-
3575
- bool HeapSnapshotGenerator::CalculateRetainedSizes() {
3576
- // As for the dominators tree we only know parent nodes, not
3577
- // children, to sum up total sizes we "bubble" node's self size
3578
- // adding it to all of its parents.
3579
- List<HeapEntry*>& entries = *snapshot_->entries();
3580
- for (int i = 0; i < entries.length(); ++i) {
3581
- HeapEntry* entry = entries[i];
3582
- entry->set_retained_size(entry->self_size());
3583
- }
3584
- for (int i = 0; i < entries.length(); ++i) {
3585
- HeapEntry* entry = entries[i];
3586
- int entry_size = entry->self_size();
3587
- for (HeapEntry* dominator = entry->dominator();
3588
- dominator != entry;
3589
- entry = dominator, dominator = entry->dominator()) {
3590
- dominator->add_retained_size(entry_size);
3591
- }
3592
- }
3593
- return true;
3101
+ && dom_explorer_.IterateAndExtractReferences(&filler);
3594
3102
  }
3595
3103
 
3596
3104
 
@@ -3690,19 +3198,23 @@ class OutputStreamWriter {
3690
3198
  };
3691
3199
 
3692
3200
 
3201
+ // type, name|index, to_node.
3202
+ const int HeapSnapshotJSONSerializer::kEdgeFieldsCount = 3;
3203
+ // type, name, id, self_size, children_index.
3204
+ const int HeapSnapshotJSONSerializer::kNodeFieldsCount = 5;
3205
+
3693
3206
  void HeapSnapshotJSONSerializer::Serialize(v8::OutputStream* stream) {
3694
3207
  ASSERT(writer_ == NULL);
3695
3208
  writer_ = new OutputStreamWriter(stream);
3696
3209
 
3697
3210
  HeapSnapshot* original_snapshot = NULL;
3698
- if (snapshot_->raw_entries_size() >=
3211
+ if (snapshot_->RawSnapshotSize() >=
3699
3212
  SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize) {
3700
3213
  // The snapshot is too big. Serialize a fake snapshot.
3701
3214
  original_snapshot = snapshot_;
3702
3215
  snapshot_ = CreateFakeSnapshot();
3703
3216
  }
3704
- // Since nodes graph is cyclic, we need the first pass to enumerate
3705
- // them. Strings can be serialized in one pass.
3217
+
3706
3218
  SerializeImpl();
3707
3219
 
3708
3220
  delete writer_;
@@ -3720,42 +3232,23 @@ HeapSnapshot* HeapSnapshotJSONSerializer::CreateFakeSnapshot() {
3720
3232
  HeapSnapshot::kFull,
3721
3233
  snapshot_->title(),
3722
3234
  snapshot_->uid());
3723
- result->AllocateEntries(2, 1, 0);
3724
- HeapEntry* root = result->AddRootEntry(1);
3235
+ result->AddRootEntry();
3725
3236
  const char* text = snapshot_->collection()->names()->GetFormatted(
3726
3237
  "The snapshot is too big. "
3727
3238
  "Maximum snapshot size is %" V8_PTR_PREFIX "u MB. "
3728
3239
  "Actual snapshot size is %" V8_PTR_PREFIX "u MB.",
3729
3240
  SnapshotSizeConstants<kPointerSize>::kMaxSerializableSnapshotRawSize / MB,
3730
- (snapshot_->raw_entries_size() + MB - 1) / MB);
3731
- HeapEntry* message = result->AddEntry(
3732
- HeapEntry::kString, text, 0, 4, 0, 0);
3733
- root->SetUnidirElementReference(0, 1, message);
3734
- result->SetDominatorsToSelf();
3241
+ (snapshot_->RawSnapshotSize() + MB - 1) / MB);
3242
+ HeapEntry* message = result->AddEntry(HeapEntry::kString, text, 0, 4);
3243
+ result->root()->SetIndexedReference(HeapGraphEdge::kElement, 1, message);
3244
+ result->FillChildren();
3735
3245
  return result;
3736
3246
  }
3737
3247
 
3738
3248
 
3739
- void HeapSnapshotJSONSerializer::CalculateNodeIndexes(
3740
- const List<HeapEntry*>& nodes) {
3741
- // type,name,id,self_size,retained_size,dominator,children_index.
3742
- const int node_fields_count = 7;
3743
- // Root must be the first.
3744
- ASSERT(nodes.first() == snapshot_->root());
3745
- // Rewrite node indexes, so they refer to actual array positions. Do this
3746
- // only once.
3747
- if (nodes[0]->entry_index() == -1) {
3748
- int index = 0;
3749
- for (int i = 0; i < nodes.length(); ++i, index += node_fields_count) {
3750
- nodes[i]->set_entry_index(index);
3751
- }
3752
- }
3753
- }
3754
-
3755
-
3756
3249
  void HeapSnapshotJSONSerializer::SerializeImpl() {
3757
- List<HeapEntry*>& nodes = *(snapshot_->entries());
3758
- CalculateNodeIndexes(nodes);
3250
+ List<HeapEntry>& nodes = snapshot_->entries();
3251
+ ASSERT(0 == snapshot_->root()->index());
3759
3252
  writer_->AddCharacter('{');
3760
3253
  writer_->AddString("\"snapshot\":{");
3761
3254
  SerializeSnapshot();
@@ -3788,16 +3281,9 @@ int HeapSnapshotJSONSerializer::GetStringId(const char* s) {
3788
3281
  }
3789
3282
 
3790
3283
 
3791
- // This function won't work correctly for MIN_INT but this is not
3792
- // a problem in case of heap snapshots serialization.
3793
- static int itoa(int value, const Vector<char>& buffer, int buffer_pos) {
3794
- if (value < 0) {
3795
- buffer[buffer_pos++] = '-';
3796
- value = -value;
3797
- }
3798
-
3284
+ static int utoa(unsigned value, const Vector<char>& buffer, int buffer_pos) {
3799
3285
  int number_of_digits = 0;
3800
- int t = value;
3286
+ unsigned t = value;
3801
3287
  do {
3802
3288
  ++number_of_digits;
3803
3289
  } while (t /= 10);
@@ -3827,23 +3313,23 @@ void HeapSnapshotJSONSerializer::SerializeEdge(HeapGraphEdge* edge,
3827
3313
  if (!first_edge) {
3828
3314
  buffer[buffer_pos++] = ',';
3829
3315
  }
3830
- buffer_pos = itoa(edge->type(), buffer, buffer_pos);
3316
+ buffer_pos = utoa(edge->type(), buffer, buffer_pos);
3831
3317
  buffer[buffer_pos++] = ',';
3832
- buffer_pos = itoa(edge_name_or_index, buffer, buffer_pos);
3318
+ buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos);
3833
3319
  buffer[buffer_pos++] = ',';
3834
- buffer_pos = itoa(edge->to()->entry_index(), buffer, buffer_pos);
3320
+ buffer_pos = utoa(entry_index(edge->to()), buffer, buffer_pos);
3835
3321
  buffer[buffer_pos++] = '\0';
3836
3322
  writer_->AddString(buffer.start());
3837
3323
  }
3838
3324
 
3839
3325
 
3840
- void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
3326
+ void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry>& nodes) {
3841
3327
  bool first_edge = true;
3842
3328
  for (int i = 0; i < nodes.length(); ++i) {
3843
- HeapEntry* entry = nodes[i];
3844
- Vector<HeapGraphEdge> children = entry->children();
3329
+ HeapEntry* entry = &nodes[i];
3330
+ Vector<HeapGraphEdge*> children = entry->children();
3845
3331
  for (int j = 0; j < children.length(); ++j) {
3846
- SerializeEdge(&children[j], first_edge);
3332
+ SerializeEdge(children[j], first_edge);
3847
3333
  first_edge = false;
3848
3334
  if (writer_->aborted()) return;
3849
3335
  }
@@ -3853,42 +3339,36 @@ void HeapSnapshotJSONSerializer::SerializeEdges(const List<HeapEntry*>& nodes) {
3853
3339
 
3854
3340
  void HeapSnapshotJSONSerializer::SerializeNode(HeapEntry* entry,
3855
3341
  int edges_index) {
3856
- // The buffer needs space for 6 ints, 1 uint32_t, 7 commas, \n and \0
3342
+ // The buffer needs space for 5 uint32_t, 5 commas, \n and \0
3857
3343
  static const int kBufferSize =
3858
- 6 * MaxDecimalDigitsIn<sizeof(int)>::kSigned // NOLINT
3859
- + MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3860
- + 7 + 1 + 1;
3344
+ 5 * MaxDecimalDigitsIn<sizeof(uint32_t)>::kUnsigned // NOLINT
3345
+ + 5 + 1 + 1;
3861
3346
  EmbeddedVector<char, kBufferSize> buffer;
3862
3347
  int buffer_pos = 0;
3863
- buffer[buffer_pos++] = '\n';
3864
- if (entry->entry_index() != 0) {
3348
+ if (entry_index(entry) != 0) {
3865
3349
  buffer[buffer_pos++] = ',';
3866
3350
  }
3867
- buffer_pos = itoa(entry->type(), buffer, buffer_pos);
3868
- buffer[buffer_pos++] = ',';
3869
- buffer_pos = itoa(GetStringId(entry->name()), buffer, buffer_pos);
3351
+ buffer_pos = utoa(entry->type(), buffer, buffer_pos);
3870
3352
  buffer[buffer_pos++] = ',';
3871
- buffer_pos = itoa(entry->id(), buffer, buffer_pos);
3353
+ buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos);
3872
3354
  buffer[buffer_pos++] = ',';
3873
- buffer_pos = itoa(entry->self_size(), buffer, buffer_pos);
3355
+ buffer_pos = utoa(entry->id(), buffer, buffer_pos);
3874
3356
  buffer[buffer_pos++] = ',';
3875
- buffer_pos = itoa(entry->retained_size(), buffer, buffer_pos);
3357
+ buffer_pos = utoa(entry->self_size(), buffer, buffer_pos);
3876
3358
  buffer[buffer_pos++] = ',';
3877
- buffer_pos = itoa(entry->dominator()->entry_index(), buffer, buffer_pos);
3878
- buffer[buffer_pos++] = ',';
3879
- buffer_pos = itoa(edges_index, buffer, buffer_pos);
3359
+ buffer_pos = utoa(edges_index, buffer, buffer_pos);
3360
+ buffer[buffer_pos++] = '\n';
3880
3361
  buffer[buffer_pos++] = '\0';
3881
3362
  writer_->AddString(buffer.start());
3882
3363
  }
3883
3364
 
3884
3365
 
3885
- void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry*>& nodes) {
3886
- const int edge_fields_count = 3; // type,name|index,to_node.
3366
+ void HeapSnapshotJSONSerializer::SerializeNodes(const List<HeapEntry>& nodes) {
3887
3367
  int edges_index = 0;
3888
3368
  for (int i = 0; i < nodes.length(); ++i) {
3889
- HeapEntry* entry = nodes[i];
3369
+ HeapEntry* entry = &nodes[i];
3890
3370
  SerializeNode(entry, edges_index);
3891
- edges_index += entry->children().length() * edge_fields_count;
3371
+ edges_index += entry->children().length() * kEdgeFieldsCount;
3892
3372
  if (writer_->aborted()) return;
3893
3373
  }
3894
3374
  }
@@ -3903,17 +3383,15 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3903
3383
  writer_->AddString(",\"meta\":");
3904
3384
  // The object describing node serialization layout.
3905
3385
  // We use a set of macros to improve readability.
3906
- #define JSON_A(s) "["s"]"
3907
- #define JSON_O(s) "{"s"}"
3908
- #define JSON_S(s) "\""s"\""
3386
+ #define JSON_A(s) "[" s "]"
3387
+ #define JSON_O(s) "{" s "}"
3388
+ #define JSON_S(s) "\"" s "\""
3909
3389
  writer_->AddString(JSON_O(
3910
3390
  JSON_S("node_fields") ":" JSON_A(
3911
3391
  JSON_S("type") ","
3912
3392
  JSON_S("name") ","
3913
3393
  JSON_S("id") ","
3914
3394
  JSON_S("self_size") ","
3915
- JSON_S("retained_size") ","
3916
- JSON_S("dominator") ","
3917
3395
  JSON_S("edges_index")) ","
3918
3396
  JSON_S("node_types") ":" JSON_A(
3919
3397
  JSON_A(
@@ -3952,9 +3430,9 @@ void HeapSnapshotJSONSerializer::SerializeSnapshot() {
3952
3430
  #undef JSON_O
3953
3431
  #undef JSON_A
3954
3432
  writer_->AddString(",\"node_count\":");
3955
- writer_->AddNumber(snapshot_->entries()->length());
3433
+ writer_->AddNumber(snapshot_->entries().length());
3956
3434
  writer_->AddString(",\"edge_count\":");
3957
- writer_->AddNumber(snapshot_->number_of_edges());
3435
+ writer_->AddNumber(snapshot_->edges().length());
3958
3436
  }
3959
3437
 
3960
3438