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.
- data/Rakefile +10 -3
- data/ext/libv8/compiler.rb +46 -0
- data/ext/libv8/extconf.rb +5 -1
- data/ext/libv8/make.rb +13 -0
- data/lib/libv8/version.rb +1 -1
- data/patches/add-freebsd9-and-freebsd10-to-gyp-GetFlavor.patch +11 -0
- data/patches/src_platform-freebsd.cc.patch +10 -0
- data/vendor/v8/ChangeLog +124 -0
- data/vendor/v8/DEPS +27 -0
- data/vendor/v8/Makefile +7 -0
- data/vendor/v8/SConstruct +15 -2
- data/vendor/v8/build/common.gypi +129 -157
- data/vendor/v8/build/gyp_v8 +11 -25
- data/vendor/v8/build/standalone.gypi +9 -3
- data/vendor/v8/include/v8.h +5 -3
- data/vendor/v8/src/SConscript +1 -0
- data/vendor/v8/src/api.cc +4 -33
- data/vendor/v8/src/api.h +2 -2
- data/vendor/v8/src/arm/builtins-arm.cc +5 -4
- data/vendor/v8/src/arm/code-stubs-arm.cc +21 -14
- data/vendor/v8/src/arm/codegen-arm.cc +2 -2
- data/vendor/v8/src/arm/debug-arm.cc +3 -1
- data/vendor/v8/src/arm/full-codegen-arm.cc +3 -102
- data/vendor/v8/src/arm/ic-arm.cc +30 -33
- data/vendor/v8/src/arm/lithium-arm.cc +20 -7
- data/vendor/v8/src/arm/lithium-arm.h +10 -4
- data/vendor/v8/src/arm/lithium-codegen-arm.cc +106 -60
- data/vendor/v8/src/arm/macro-assembler-arm.cc +49 -39
- data/vendor/v8/src/arm/macro-assembler-arm.h +5 -4
- data/vendor/v8/src/arm/regexp-macro-assembler-arm.cc +115 -55
- data/vendor/v8/src/arm/regexp-macro-assembler-arm.h +7 -6
- data/vendor/v8/src/arm/simulator-arm.h +6 -6
- data/vendor/v8/src/arm/stub-cache-arm.cc +64 -19
- data/vendor/v8/src/array.js +7 -3
- data/vendor/v8/src/ast.cc +11 -6
- data/vendor/v8/src/bootstrapper.cc +9 -11
- data/vendor/v8/src/builtins.cc +61 -31
- data/vendor/v8/src/code-stubs.cc +23 -9
- data/vendor/v8/src/code-stubs.h +1 -0
- data/vendor/v8/src/codegen.h +3 -3
- data/vendor/v8/src/compiler.cc +1 -1
- data/vendor/v8/src/contexts.h +2 -18
- data/vendor/v8/src/d8.cc +94 -93
- data/vendor/v8/src/d8.h +1 -1
- data/vendor/v8/src/debug-agent.cc +3 -3
- data/vendor/v8/src/debug.cc +41 -1
- data/vendor/v8/src/debug.h +50 -0
- data/vendor/v8/src/elements-kind.cc +134 -0
- data/vendor/v8/src/elements-kind.h +210 -0
- data/vendor/v8/src/elements.cc +356 -190
- data/vendor/v8/src/elements.h +36 -28
- data/vendor/v8/src/factory.cc +44 -4
- data/vendor/v8/src/factory.h +11 -7
- data/vendor/v8/src/flag-definitions.h +3 -0
- data/vendor/v8/src/frames.h +3 -0
- data/vendor/v8/src/full-codegen.cc +2 -1
- data/vendor/v8/src/func-name-inferrer.h +2 -0
- data/vendor/v8/src/globals.h +3 -0
- data/vendor/v8/src/heap-inl.h +16 -4
- data/vendor/v8/src/heap.cc +38 -32
- data/vendor/v8/src/heap.h +3 -17
- data/vendor/v8/src/hydrogen-instructions.cc +28 -5
- data/vendor/v8/src/hydrogen-instructions.h +142 -44
- data/vendor/v8/src/hydrogen.cc +160 -55
- data/vendor/v8/src/hydrogen.h +2 -0
- data/vendor/v8/src/ia32/assembler-ia32.h +3 -0
- data/vendor/v8/src/ia32/builtins-ia32.cc +5 -4
- data/vendor/v8/src/ia32/code-stubs-ia32.cc +22 -16
- data/vendor/v8/src/ia32/codegen-ia32.cc +2 -2
- data/vendor/v8/src/ia32/debug-ia32.cc +29 -2
- data/vendor/v8/src/ia32/full-codegen-ia32.cc +8 -101
- data/vendor/v8/src/ia32/ic-ia32.cc +23 -19
- data/vendor/v8/src/ia32/lithium-codegen-ia32.cc +126 -80
- data/vendor/v8/src/ia32/lithium-codegen-ia32.h +2 -1
- data/vendor/v8/src/ia32/lithium-ia32.cc +15 -9
- data/vendor/v8/src/ia32/lithium-ia32.h +14 -6
- data/vendor/v8/src/ia32/macro-assembler-ia32.cc +50 -40
- data/vendor/v8/src/ia32/macro-assembler-ia32.h +5 -4
- data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.cc +113 -43
- data/vendor/v8/src/ia32/regexp-macro-assembler-ia32.h +9 -4
- data/vendor/v8/src/ia32/simulator-ia32.h +4 -4
- data/vendor/v8/src/ia32/stub-cache-ia32.cc +52 -14
- data/vendor/v8/src/ic.cc +77 -20
- data/vendor/v8/src/ic.h +18 -2
- data/vendor/v8/src/incremental-marking-inl.h +21 -5
- data/vendor/v8/src/incremental-marking.cc +35 -8
- data/vendor/v8/src/incremental-marking.h +12 -3
- data/vendor/v8/src/isolate.cc +12 -2
- data/vendor/v8/src/isolate.h +1 -1
- data/vendor/v8/src/jsregexp.cc +66 -26
- data/vendor/v8/src/jsregexp.h +60 -31
- data/vendor/v8/src/list-inl.h +8 -0
- data/vendor/v8/src/list.h +3 -0
- data/vendor/v8/src/lithium.cc +5 -2
- data/vendor/v8/src/liveedit.cc +57 -5
- data/vendor/v8/src/mark-compact-inl.h +17 -11
- data/vendor/v8/src/mark-compact.cc +100 -143
- data/vendor/v8/src/mark-compact.h +44 -20
- data/vendor/v8/src/messages.js +131 -99
- data/vendor/v8/src/mips/builtins-mips.cc +5 -4
- data/vendor/v8/src/mips/code-stubs-mips.cc +23 -15
- data/vendor/v8/src/mips/codegen-mips.cc +2 -2
- data/vendor/v8/src/mips/debug-mips.cc +3 -1
- data/vendor/v8/src/mips/full-codegen-mips.cc +4 -102
- data/vendor/v8/src/mips/ic-mips.cc +34 -36
- data/vendor/v8/src/mips/lithium-codegen-mips.cc +116 -68
- data/vendor/v8/src/mips/lithium-mips.cc +20 -7
- data/vendor/v8/src/mips/lithium-mips.h +11 -4
- data/vendor/v8/src/mips/macro-assembler-mips.cc +50 -39
- data/vendor/v8/src/mips/macro-assembler-mips.h +5 -4
- data/vendor/v8/src/mips/regexp-macro-assembler-mips.cc +110 -50
- data/vendor/v8/src/mips/regexp-macro-assembler-mips.h +6 -5
- data/vendor/v8/src/mips/simulator-mips.h +5 -5
- data/vendor/v8/src/mips/stub-cache-mips.cc +66 -20
- data/vendor/v8/src/mksnapshot.cc +5 -1
- data/vendor/v8/src/objects-debug.cc +103 -6
- data/vendor/v8/src/objects-inl.h +215 -116
- data/vendor/v8/src/objects-printer.cc +13 -8
- data/vendor/v8/src/objects.cc +608 -331
- data/vendor/v8/src/objects.h +129 -94
- data/vendor/v8/src/parser.cc +16 -4
- data/vendor/v8/src/platform-freebsd.cc +1 -0
- data/vendor/v8/src/platform-linux.cc +9 -30
- data/vendor/v8/src/platform-posix.cc +28 -7
- data/vendor/v8/src/platform-win32.cc +15 -3
- data/vendor/v8/src/platform.h +2 -1
- data/vendor/v8/src/profile-generator-inl.h +25 -2
- data/vendor/v8/src/profile-generator.cc +300 -822
- data/vendor/v8/src/profile-generator.h +97 -214
- data/vendor/v8/src/regexp-macro-assembler-irregexp.cc +2 -1
- data/vendor/v8/src/regexp-macro-assembler-irregexp.h +2 -2
- data/vendor/v8/src/regexp-macro-assembler-tracer.cc +6 -5
- data/vendor/v8/src/regexp-macro-assembler-tracer.h +1 -1
- data/vendor/v8/src/regexp-macro-assembler.cc +7 -3
- data/vendor/v8/src/regexp-macro-assembler.h +10 -2
- data/vendor/v8/src/regexp.js +6 -0
- data/vendor/v8/src/runtime.cc +265 -212
- data/vendor/v8/src/runtime.h +6 -5
- data/vendor/v8/src/scopes.cc +20 -0
- data/vendor/v8/src/scopes.h +6 -3
- data/vendor/v8/src/spaces.cc +0 -2
- data/vendor/v8/src/string-stream.cc +2 -2
- data/vendor/v8/src/v8-counters.h +0 -2
- data/vendor/v8/src/v8natives.js +2 -2
- data/vendor/v8/src/v8utils.h +6 -3
- data/vendor/v8/src/version.cc +1 -1
- data/vendor/v8/src/x64/assembler-x64.h +2 -1
- data/vendor/v8/src/x64/builtins-x64.cc +5 -4
- data/vendor/v8/src/x64/code-stubs-x64.cc +25 -16
- data/vendor/v8/src/x64/codegen-x64.cc +2 -2
- data/vendor/v8/src/x64/debug-x64.cc +14 -1
- data/vendor/v8/src/x64/disasm-x64.cc +1 -1
- data/vendor/v8/src/x64/full-codegen-x64.cc +10 -106
- data/vendor/v8/src/x64/ic-x64.cc +20 -16
- data/vendor/v8/src/x64/lithium-codegen-x64.cc +156 -79
- data/vendor/v8/src/x64/lithium-codegen-x64.h +2 -1
- data/vendor/v8/src/x64/lithium-x64.cc +18 -8
- data/vendor/v8/src/x64/lithium-x64.h +7 -2
- data/vendor/v8/src/x64/macro-assembler-x64.cc +50 -40
- data/vendor/v8/src/x64/macro-assembler-x64.h +5 -4
- data/vendor/v8/src/x64/regexp-macro-assembler-x64.cc +122 -51
- data/vendor/v8/src/x64/regexp-macro-assembler-x64.h +17 -8
- data/vendor/v8/src/x64/simulator-x64.h +4 -4
- data/vendor/v8/src/x64/stub-cache-x64.cc +55 -17
- data/vendor/v8/test/cctest/cctest.status +1 -0
- data/vendor/v8/test/cctest/test-api.cc +24 -0
- data/vendor/v8/test/cctest/test-func-name-inference.cc +38 -0
- data/vendor/v8/test/cctest/test-heap-profiler.cc +21 -77
- data/vendor/v8/test/cctest/test-heap.cc +164 -3
- data/vendor/v8/test/cctest/test-list.cc +12 -0
- data/vendor/v8/test/cctest/test-mark-compact.cc +5 -5
- data/vendor/v8/test/cctest/test-regexp.cc +14 -8
- data/vendor/v8/test/cctest/testcfg.py +2 -0
- data/vendor/v8/test/mjsunit/accessor-map-sharing.js +176 -0
- data/vendor/v8/test/mjsunit/array-construct-transition.js +3 -3
- data/vendor/v8/test/mjsunit/array-literal-transitions.js +10 -10
- data/vendor/v8/test/mjsunit/big-array-literal.js +3 -0
- data/vendor/v8/test/mjsunit/compiler/inline-construct.js +4 -2
- data/vendor/v8/test/mjsunit/debug-liveedit-stack-padding.js +88 -0
- data/vendor/v8/test/mjsunit/elements-kind.js +4 -4
- data/vendor/v8/test/mjsunit/elements-transition-hoisting.js +2 -2
- data/vendor/v8/test/mjsunit/elements-transition.js +5 -5
- data/vendor/v8/test/mjsunit/error-constructors.js +68 -33
- data/vendor/v8/test/mjsunit/harmony/proxies.js +14 -6
- data/vendor/v8/test/mjsunit/mjsunit.status +1 -0
- data/vendor/v8/test/mjsunit/packed-elements.js +112 -0
- data/vendor/v8/test/mjsunit/regexp-capture-3.js +6 -0
- data/vendor/v8/test/mjsunit/regexp-global.js +132 -0
- data/vendor/v8/test/mjsunit/regexp.js +11 -0
- data/vendor/v8/test/mjsunit/regress/regress-117409.js +52 -0
- data/vendor/v8/test/mjsunit/regress/regress-126412.js +33 -0
- data/vendor/v8/test/mjsunit/regress/regress-128018.js +35 -0
- data/vendor/v8/test/mjsunit/regress/regress-128146.js +33 -0
- data/vendor/v8/test/mjsunit/regress/regress-1639-2.js +4 -1
- data/vendor/v8/test/mjsunit/regress/regress-1639.js +14 -8
- data/vendor/v8/test/mjsunit/regress/regress-1849.js +3 -3
- data/vendor/v8/test/mjsunit/regress/regress-1878.js +2 -2
- data/vendor/v8/test/mjsunit/regress/regress-2071.js +79 -0
- data/vendor/v8/test/mjsunit/regress/regress-2153.js +32 -0
- data/vendor/v8/test/mjsunit/regress/regress-crbug-122271.js +4 -4
- data/vendor/v8/test/mjsunit/regress/regress-crbug-126414.js +32 -0
- data/vendor/v8/test/mjsunit/regress/regress-smi-only-concat.js +2 -2
- data/vendor/v8/test/mjsunit/regress/regress-transcendental.js +49 -0
- data/vendor/v8/test/mjsunit/stack-traces.js +14 -0
- data/vendor/v8/test/mjsunit/unbox-double-arrays.js +4 -3
- data/vendor/v8/test/test262/testcfg.py +6 -1
- data/vendor/v8/tools/check-static-initializers.sh +11 -3
- data/vendor/v8/tools/fuzz-harness.sh +92 -0
- data/vendor/v8/tools/grokdump.py +658 -67
- data/vendor/v8/tools/gyp/v8.gyp +21 -39
- data/vendor/v8/tools/js2c.py +3 -3
- data/vendor/v8/tools/jsmin.py +2 -2
- data/vendor/v8/tools/presubmit.py +2 -1
- data/vendor/v8/tools/test-wrapper-gypbuild.py +25 -11
- metadata +624 -612
data/vendor/v8/src/parser.cc
CHANGED
@@ -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 =
|
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->
|
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 ==
|
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(
|
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
|
|
@@ -966,43 +966,22 @@ typedef struct ucontext {
|
|
966
966
|
|
967
967
|
#elif !defined(__GLIBC__) && defined(__i386__)
|
968
968
|
// x86 version for Android.
|
969
|
-
struct
|
970
|
-
|
971
|
-
|
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
|
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
|
-
|
999
|
-
struct ucontext
|
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
|
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
|
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
|
-
|
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
|
-
|
471
|
-
|
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
|
-
|
477
|
-
|
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
|
-
|
1852
|
-
|
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
|
|
data/vendor/v8/src/platform.h
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
// Copyright
|
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
|
100
|
-
|
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
|
-
|
935
|
-
|
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
|
-
|
938
|
-
|
939
|
-
|
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
|
-
|
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::
|
957
|
-
|
955
|
+
void HeapGraphEdge::ReplaceToIndexWithEntry(HeapSnapshot* snapshot) {
|
956
|
+
to_entry_ = &snapshot->entries()[to_index_];
|
958
957
|
}
|
959
958
|
|
960
959
|
|
961
|
-
|
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
|
-
|
967
|
-
|
968
|
-
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
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
|
-
|
988
|
-
|
989
|
-
|
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
|
-
|
998
|
-
|
999
|
-
|
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
|
-
|
1017
|
-
|
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
|
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 =
|
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 =
|
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
|
-
|
1131
|
-
|
1132
|
-
|
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
|
-
|
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
|
-
|
1165
|
-
|
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
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
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(
|
1198
|
-
|
1199
|
-
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
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
|
-
|
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
|
-
|
1160
|
+
HeapEntry* entry = AddEntry(
|
1215
1161
|
HeapEntry::kObject,
|
1216
1162
|
VisitorSynchronization::kTagNames[tag],
|
1217
1163
|
HeapObjectsMap::GetNthGcSubrootId(tag),
|
1218
|
-
0
|
1219
|
-
|
1220
|
-
|
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
|
-
|
1229
|
-
|
1230
|
-
|
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::
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
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
|
-
|
1245
|
-
|
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_.
|
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
|
-
|
1532
|
+
int HeapEntriesMap::Map(HeapThing thing) {
|
1625
1533
|
HashMap::Entry* cache_entry = entries_.Lookup(thing, Hash(thing), false);
|
1626
|
-
if (cache_entry
|
1627
|
-
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
1701
|
-
|
1702
|
-
|
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
|
-
|
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
|
-
|
1759
|
-
return snapshot_->
|
1625
|
+
snapshot_->AddRootEntry();
|
1626
|
+
return snapshot_->root();
|
1760
1627
|
} else if (object == kGcRootsObject) {
|
1761
|
-
|
1628
|
+
HeapEntry* entry = snapshot_->AddGcRootsEntry();
|
1629
|
+
return entry;
|
1762
1630
|
} else if (object >= kFirstGcSubrootObject && object < kLastGcSubrootObject) {
|
1763
|
-
|
1764
|
-
|
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
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
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
|
-
|
1661
|
+
String* name = String::cast(SharedFunctionInfo::cast(object)->name());
|
1804
1662
|
return AddEntry(object,
|
1805
1663
|
HeapEntry::kCode,
|
1806
|
-
collection_->names()->GetName(
|
1807
|
-
children_count,
|
1808
|
-
retainers_count);
|
1664
|
+
collection_->names()->GetName(name));
|
1809
1665
|
} else if (object->IsScript()) {
|
1810
|
-
|
1666
|
+
Object* name = Script::cast(object)->name();
|
1811
1667
|
return AddEntry(object,
|
1812
1668
|
HeapEntry::kCode,
|
1813
|
-
|
1814
|
-
collection_->names()->GetName(
|
1815
|
-
|
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
|
-
|
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
|
-
|
1763
|
+
int parent)
|
1939
1764
|
: generator_(generator),
|
1940
1765
|
parent_obj_(parent_obj),
|
1941
|
-
parent_(
|
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
|
-
|
1795
|
+
int parent_;
|
1971
1796
|
int next_index_;
|
1972
1797
|
};
|
1973
1798
|
|
1974
1799
|
|
1975
1800
|
void V8HeapExplorer::ExtractReferences(HeapObject* obj) {
|
1976
|
-
HeapEntry*
|
1977
|
-
if (
|
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
|
-
|
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(
|
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(
|
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
|
-
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
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
|
-
|
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(
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2441
|
+
parent_entry,
|
2646
2442
|
reference_name,
|
2647
|
-
|
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
|
-
|
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
|
-
|
2458
|
+
parent_entry,
|
2663
2459
|
collection_->names()->GetName(index),
|
2664
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
2752
|
-
|
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
|
-
|
2762
|
-
|
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
|
-
|
2770
|
-
|
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
|
-
|
2570
|
+
snapshot_->gc_subroot(tag)->index(),
|
2783
2571
|
name,
|
2784
|
-
|
2572
|
+
child_entry);
|
2785
2573
|
} else {
|
2786
2574
|
filler_->SetIndexedAutoIndexReference(
|
2787
2575
|
is_weak ? HeapGraphEdge::kWeak : HeapGraphEdge::kElement,
|
2788
|
-
|
2789
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
3013
|
-
filler_->FindOrAddEntry(parent, native_entries_allocator_);
|
3014
|
-
ASSERT(parent_entry !=
|
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
|
-
|
2808
|
+
parent_entry,
|
3023
2809
|
"native",
|
3024
|
-
|
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
|
-
|
3120
|
-
|
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
|
-
|
2919
|
+
wrapper_entry->index(),
|
3133
2920
|
"native",
|
3134
|
-
|
2921
|
+
info_entry);
|
3135
2922
|
filler_->SetIndexedAutoIndexReference(HeapGraphEdge::kElement,
|
3136
|
-
|
3137
|
-
|
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
|
-
|
3153
|
-
|
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
|
-
|
3226
|
-
|
2962
|
+
HeapEntry* entry = allocator->AllocateEntry(ptr);
|
2963
|
+
entries_->Pair(ptr, entry->index());
|
2964
|
+
return entry;
|
3227
2965
|
}
|
3228
2966
|
HeapEntry* FindEntry(HeapThing ptr) {
|
3229
|
-
|
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
|
-
|
3237
|
-
HeapEntry* parent_entry,
|
2975
|
+
int parent,
|
3238
2976
|
int index,
|
3239
|
-
HeapThing child_ptr,
|
3240
2977
|
HeapEntry* child_entry) {
|
3241
|
-
|
3242
|
-
|
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
|
-
|
3249
|
-
HeapEntry* parent_entry,
|
3250
|
-
HeapThing child_ptr,
|
2982
|
+
int parent,
|
3251
2983
|
HeapEntry* child_entry) {
|
3252
|
-
|
3253
|
-
|
3254
|
-
|
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
|
-
|
3260
|
-
HeapEntry* parent_entry,
|
2989
|
+
int parent,
|
3261
2990
|
const char* reference_name,
|
3262
|
-
HeapThing child_ptr,
|
3263
2991
|
HeapEntry* child_entry) {
|
3264
|
-
|
3265
|
-
|
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
|
-
|
3272
|
-
HeapEntry* parent_entry,
|
3273
|
-
HeapThing child_ptr,
|
2996
|
+
int parent,
|
3274
2997
|
HeapEntry* child_entry) {
|
3275
|
-
|
3276
|
-
|
3277
|
-
|
3278
|
-
|
3279
|
-
|
3280
|
-
|
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(
|
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())
|
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
|
-
|
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_->
|
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
|
-
|
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->
|
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_->
|
3731
|
-
HeapEntry* message = result->AddEntry(
|
3732
|
-
|
3733
|
-
|
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
|
3758
|
-
|
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
|
-
|
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
|
-
|
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 =
|
3316
|
+
buffer_pos = utoa(edge->type(), buffer, buffer_pos);
|
3831
3317
|
buffer[buffer_pos++] = ',';
|
3832
|
-
buffer_pos =
|
3318
|
+
buffer_pos = utoa(edge_name_or_index, buffer, buffer_pos);
|
3833
3319
|
buffer[buffer_pos++] = ',';
|
3834
|
-
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
|
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
|
3329
|
+
HeapEntry* entry = &nodes[i];
|
3330
|
+
Vector<HeapGraphEdge*> children = entry->children();
|
3845
3331
|
for (int j = 0; j < children.length(); ++j) {
|
3846
|
-
SerializeEdge(
|
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
|
3342
|
+
// The buffer needs space for 5 uint32_t, 5 commas, \n and \0
|
3857
3343
|
static const int kBufferSize =
|
3858
|
-
|
3859
|
-
+
|
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
|
-
|
3864
|
-
if (entry->entry_index() != 0) {
|
3348
|
+
if (entry_index(entry) != 0) {
|
3865
3349
|
buffer[buffer_pos++] = ',';
|
3866
3350
|
}
|
3867
|
-
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 =
|
3353
|
+
buffer_pos = utoa(GetStringId(entry->name()), buffer, buffer_pos);
|
3872
3354
|
buffer[buffer_pos++] = ',';
|
3873
|
-
buffer_pos =
|
3355
|
+
buffer_pos = utoa(entry->id(), buffer, buffer_pos);
|
3874
3356
|
buffer[buffer_pos++] = ',';
|
3875
|
-
buffer_pos =
|
3357
|
+
buffer_pos = utoa(entry->self_size(), buffer, buffer_pos);
|
3876
3358
|
buffer[buffer_pos++] = ',';
|
3877
|
-
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
|
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() *
|
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()
|
3433
|
+
writer_->AddNumber(snapshot_->entries().length());
|
3956
3434
|
writer_->AddString(",\"edge_count\":");
|
3957
|
-
writer_->AddNumber(snapshot_->
|
3435
|
+
writer_->AddNumber(snapshot_->edges().length());
|
3958
3436
|
}
|
3959
3437
|
|
3960
3438
|
|