From 88786fecff336342a56e6f2e7ff3b286be716e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Zasso?= Date: Wed, 7 Mar 2018 08:54:53 +0100 Subject: deps: update V8 to 6.5.254.31 PR-URL: https://github.com/nodejs/node/pull/18453 Reviewed-By: James M Snell Reviewed-By: Colin Ihrig Reviewed-By: Yang Guo Reviewed-By: Ali Ijaz Sheikh Reviewed-By: Michael Dawson --- deps/v8/.gitignore | 4 +- deps/v8/AUTHORS | 5 + deps/v8/BUILD.gn | 75 +- deps/v8/ChangeLog | 1300 ++++++ deps/v8/DEPS | 47 +- deps/v8/PRESUBMIT.py | 2 +- deps/v8/build_overrides/build.gni | 2 +- deps/v8/gni/v8.gni | 5 +- deps/v8/gypfiles/all.gyp | 1 + deps/v8/gypfiles/standalone.gypi | 2 +- deps/v8/include/v8-inspector.h | 5 +- deps/v8/include/v8-platform.h | 92 +- deps/v8/include/v8-version.h | 6 +- deps/v8/include/v8.h | 566 +-- deps/v8/infra/config/PRESUBMIT.py | 29 + deps/v8/infra/config/cq.cfg | 46 +- deps/v8/infra/mb/mb_config.pyl | 19 +- deps/v8/infra/testing/README.md | 36 +- deps/v8/infra/testing/client.v8.pyl | 37 +- deps/v8/infra/testing/tryserver.v8.pyl | 22 +- deps/v8/src/accessors.cc | 39 +- deps/v8/src/allocation.cc | 187 +- deps/v8/src/allocation.h | 67 +- deps/v8/src/api-arguments-inl.h | 292 +- deps/v8/src/api-arguments.cc | 32 +- deps/v8/src/api-arguments.h | 81 +- deps/v8/src/api-natives.cc | 10 +- deps/v8/src/api.cc | 979 ++--- deps/v8/src/api.h | 24 +- deps/v8/src/arguments.h | 2 +- deps/v8/src/arm/assembler-arm-inl.h | 30 +- deps/v8/src/arm/assembler-arm.cc | 130 +- deps/v8/src/arm/assembler-arm.h | 12 +- deps/v8/src/arm/code-stubs-arm.cc | 36 +- deps/v8/src/arm/codegen-arm.cc | 18 +- deps/v8/src/arm/constants-arm.cc | 2 +- deps/v8/src/arm/constants-arm.h | 3 - deps/v8/src/arm/deoptimizer-arm.cc | 8 +- deps/v8/src/arm/disasm-arm.cc | 44 +- deps/v8/src/arm/interface-descriptors-arm.cc | 7 +- deps/v8/src/arm/macro-assembler-arm.cc | 96 +- deps/v8/src/arm/macro-assembler-arm.h | 10 +- deps/v8/src/arm/simulator-arm.cc | 238 +- deps/v8/src/arm/simulator-arm.h | 124 +- deps/v8/src/arm64/assembler-arm64-inl.h | 30 +- deps/v8/src/arm64/assembler-arm64.cc | 56 +- deps/v8/src/arm64/assembler-arm64.h | 15 +- deps/v8/src/arm64/code-stubs-arm64.cc | 152 +- deps/v8/src/arm64/constants-arm64.h | 1 - deps/v8/src/arm64/cpu-arm64.cc | 2 +- deps/v8/src/arm64/deoptimizer-arm64.cc | 14 +- deps/v8/src/arm64/disasm-arm64.cc | 51 +- deps/v8/src/arm64/eh-frame-arm64.cc | 7 +- deps/v8/src/arm64/frame-constants-arm64.h | 25 +- deps/v8/src/arm64/instructions-arm64-constants.cc | 26 +- deps/v8/src/arm64/instrument-arm64.cc | 4 +- deps/v8/src/arm64/interface-descriptors-arm64.cc | 7 +- deps/v8/src/arm64/macro-assembler-arm64-inl.h | 54 +- deps/v8/src/arm64/macro-assembler-arm64.cc | 329 +- deps/v8/src/arm64/macro-assembler-arm64.h | 82 +- deps/v8/src/arm64/simulator-arm64.cc | 227 +- deps/v8/src/arm64/simulator-arm64.h | 156 +- deps/v8/src/arm64/simulator-logic-arm64.cc | 4 +- deps/v8/src/arm64/utils-arm64.cc | 4 +- deps/v8/src/asmjs/asm-parser.cc | 36 +- deps/v8/src/asmjs/asm-scanner.cc | 2 +- deps/v8/src/assembler.cc | 36 +- deps/v8/src/assembler.h | 28 +- deps/v8/src/ast/ast-numbering.cc | 26 +- deps/v8/src/ast/ast-traversal-visitor.h | 9 + deps/v8/src/ast/ast.cc | 21 +- deps/v8/src/ast/ast.h | 71 +- deps/v8/src/ast/prettyprinter.cc | 43 +- deps/v8/src/ast/prettyprinter.h | 1 + deps/v8/src/ast/scopes.cc | 26 +- deps/v8/src/ast/scopes.h | 14 +- deps/v8/src/bailout-reason.cc | 21 +- deps/v8/src/bailout-reason.h | 123 +- deps/v8/src/base/DEPS | 1 + deps/v8/src/base/cpu.cc | 20 +- deps/v8/src/base/debug/stack_trace_posix.cc | 8 +- deps/v8/src/base/functional.cc | 8 +- deps/v8/src/base/ieee754.cc | 282 +- deps/v8/src/base/lazy-instance.h | 12 +- deps/v8/src/base/logging.cc | 2 - deps/v8/src/base/logging.h | 18 +- deps/v8/src/base/macros.h | 57 +- deps/v8/src/base/once.cc | 4 +- deps/v8/src/base/once.h | 11 +- deps/v8/src/base/page-allocator.cc | 64 + deps/v8/src/base/page-allocator.h | 41 + deps/v8/src/base/platform/platform-fuchsia.cc | 5 +- deps/v8/src/base/platform/platform-posix.cc | 58 +- deps/v8/src/base/platform/platform-win32.cc | 33 +- deps/v8/src/base/platform/platform.h | 68 +- deps/v8/src/base/platform/semaphore.cc | 2 +- deps/v8/src/base/platform/time.cc | 3 +- deps/v8/src/base/safe_conversions.h | 3 +- deps/v8/src/base/utils/random-number-generator.cc | 4 +- deps/v8/src/base/utils/random-number-generator.h | 4 +- deps/v8/src/bignum.cc | 2 +- deps/v8/src/bootstrapper.cc | 182 +- deps/v8/src/builtins/arm/builtins-arm.cc | 91 +- deps/v8/src/builtins/arm64/builtins-arm64.cc | 587 +-- deps/v8/src/builtins/builtins-array-gen.cc | 539 ++- deps/v8/src/builtins/builtins-async-gen.cc | 1 + deps/v8/src/builtins/builtins-collections-gen.cc | 5 +- deps/v8/src/builtins/builtins-constructor-gen.cc | 9 +- deps/v8/src/builtins/builtins-conversion-gen.cc | 15 +- deps/v8/src/builtins/builtins-definitions.h | 85 +- deps/v8/src/builtins/builtins-function-gen.cc | 1 - deps/v8/src/builtins/builtins-handler-gen.cc | 54 - deps/v8/src/builtins/builtins-ic-gen.cc | 4 +- deps/v8/src/builtins/builtins-internal-gen.cc | 449 ++- deps/v8/src/builtins/builtins-intl-gen.cc | 1 - deps/v8/src/builtins/builtins-iterator-gen.cc | 53 +- deps/v8/src/builtins/builtins-iterator-gen.h | 13 +- deps/v8/src/builtins/builtins-math-gen.cc | 3 +- deps/v8/src/builtins/builtins-object-gen.cc | 321 +- deps/v8/src/builtins/builtins-object.cc | 25 - deps/v8/src/builtins/builtins-promise-gen.cc | 217 +- deps/v8/src/builtins/builtins-promise-gen.h | 3 +- deps/v8/src/builtins/builtins-proxy-gen.cc | 100 + deps/v8/src/builtins/builtins-proxy-gen.h | 9 + deps/v8/src/builtins/builtins-regexp-gen.cc | 59 +- .../src/builtins/builtins-sharedarraybuffer-gen.cc | 10 +- deps/v8/src/builtins/builtins-string-gen.cc | 236 +- deps/v8/src/builtins/builtins-string-gen.h | 17 +- deps/v8/src/builtins/builtins-string.cc | 4 +- deps/v8/src/builtins/builtins-typedarray-gen.cc | 207 +- deps/v8/src/builtins/builtins-utils-gen.h | 3 + deps/v8/src/builtins/builtins-utils.h | 3 +- deps/v8/src/builtins/builtins.cc | 32 + deps/v8/src/builtins/ia32/builtins-ia32.cc | 87 +- deps/v8/src/builtins/mips/builtins-mips.cc | 115 +- deps/v8/src/builtins/mips64/builtins-mips64.cc | 115 +- deps/v8/src/builtins/ppc/builtins-ppc.cc | 107 +- deps/v8/src/builtins/s390/builtins-s390.cc | 109 +- deps/v8/src/builtins/setup-builtins-internal.cc | 11 +- deps/v8/src/builtins/x64/builtins-x64.cc | 112 +- deps/v8/src/cached-powers.cc | 174 +- deps/v8/src/code-factory.cc | 26 - deps/v8/src/code-factory.h | 4 - deps/v8/src/code-stub-assembler.cc | 1250 +++--- deps/v8/src/code-stub-assembler.h | 218 +- deps/v8/src/code-stubs.cc | 43 +- deps/v8/src/code-stubs.h | 158 +- deps/v8/src/compilation-info.cc | 2 +- deps/v8/src/compilation-info.h | 6 +- .../src/compiler-dispatcher/compiler-dispatcher.cc | 2 +- deps/v8/src/compiler.cc | 141 +- deps/v8/src/compiler.h | 8 + deps/v8/src/compiler/OWNERS | 5 +- deps/v8/src/compiler/access-builder.cc | 8 + deps/v8/src/compiler/access-builder.h | 3 + deps/v8/src/compiler/arm/code-generator-arm.cc | 325 +- deps/v8/src/compiler/arm/instruction-codes-arm.h | 1 + .../src/compiler/arm/instruction-scheduler-arm.cc | 1 + .../src/compiler/arm/instruction-selector-arm.cc | 181 +- deps/v8/src/compiler/arm64/code-generator-arm64.cc | 425 +- .../src/compiler/arm64/instruction-codes-arm64.h | 9 +- .../compiler/arm64/instruction-scheduler-arm64.cc | 28 +- .../compiler/arm64/instruction-selector-arm64.cc | 263 +- deps/v8/src/compiler/branch-elimination.cc | 5 +- deps/v8/src/compiler/bytecode-graph-builder.cc | 47 +- deps/v8/src/compiler/bytecode-graph-builder.h | 8 +- deps/v8/src/compiler/c-linkage.cc | 2 +- deps/v8/src/compiler/code-assembler.cc | 17 +- deps/v8/src/compiler/code-assembler.h | 14 +- deps/v8/src/compiler/code-generator.cc | 23 +- deps/v8/src/compiler/common-operator-reducer.cc | 12 +- deps/v8/src/compiler/common-operator.cc | 97 +- deps/v8/src/compiler/common-operator.h | 22 +- deps/v8/src/compiler/dead-code-elimination.cc | 49 +- deps/v8/src/compiler/dead-code-elimination.h | 30 +- deps/v8/src/compiler/effect-control-linearizer.cc | 510 ++- deps/v8/src/compiler/effect-control-linearizer.h | 12 +- deps/v8/src/compiler/escape-analysis-reducer.cc | 45 +- deps/v8/src/compiler/escape-analysis-reducer.h | 2 +- deps/v8/src/compiler/escape-analysis.cc | 19 +- deps/v8/src/compiler/frame.cc | 11 +- deps/v8/src/compiler/frame.h | 49 +- deps/v8/src/compiler/gap-resolver.cc | 14 +- deps/v8/src/compiler/graph-assembler.cc | 36 +- deps/v8/src/compiler/graph-assembler.h | 16 +- deps/v8/src/compiler/graph-trimmer.h | 1 - deps/v8/src/compiler/ia32/code-generator-ia32.cc | 761 ++-- deps/v8/src/compiler/ia32/instruction-codes-ia32.h | 43 +- .../compiler/ia32/instruction-scheduler-ia32.cc | 53 +- .../src/compiler/ia32/instruction-selector-ia32.cc | 316 +- deps/v8/src/compiler/instruction-codes.h | 14 - deps/v8/src/compiler/instruction-scheduler.cc | 30 - deps/v8/src/compiler/instruction-selector-impl.h | 29 +- deps/v8/src/compiler/instruction-selector.cc | 348 +- deps/v8/src/compiler/instruction-selector.h | 31 +- deps/v8/src/compiler/instruction.cc | 4 +- deps/v8/src/compiler/instruction.h | 14 +- deps/v8/src/compiler/int64-lowering.cc | 15 +- deps/v8/src/compiler/js-builtin-reducer.cc | 742 +--- deps/v8/src/compiler/js-builtin-reducer.h | 11 +- deps/v8/src/compiler/js-call-reducer.cc | 2549 ++++++++++-- deps/v8/src/compiler/js-call-reducer.h | 29 +- deps/v8/src/compiler/js-create-lowering.cc | 16 +- deps/v8/src/compiler/js-generic-lowering.cc | 29 +- deps/v8/src/compiler/js-graph.cc | 4 - deps/v8/src/compiler/js-graph.h | 4 - deps/v8/src/compiler/js-inlining-heuristic.cc | 3 + deps/v8/src/compiler/js-inlining-heuristic.h | 2 + deps/v8/src/compiler/js-intrinsic-lowering.cc | 3 +- .../compiler/js-native-context-specialization.cc | 103 +- deps/v8/src/compiler/js-operator.cc | 43 +- deps/v8/src/compiler/js-operator.h | 48 +- deps/v8/src/compiler/js-type-hint-lowering.cc | 5 +- deps/v8/src/compiler/js-typed-lowering.cc | 121 +- deps/v8/src/compiler/js-typed-lowering.h | 5 +- deps/v8/src/compiler/linkage.cc | 41 +- deps/v8/src/compiler/linkage.h | 27 +- deps/v8/src/compiler/load-elimination.cc | 4 +- deps/v8/src/compiler/loop-analysis.cc | 2 +- deps/v8/src/compiler/loop-peeling.cc | 95 +- deps/v8/src/compiler/loop-peeling.h | 31 +- deps/v8/src/compiler/loop-variable-optimizer.cc | 34 +- deps/v8/src/compiler/loop-variable-optimizer.h | 7 +- deps/v8/src/compiler/machine-graph-verifier.cc | 43 +- deps/v8/src/compiler/machine-operator-reducer.cc | 24 +- deps/v8/src/compiler/machine-operator.cc | 84 +- deps/v8/src/compiler/machine-operator.h | 22 +- deps/v8/src/compiler/memory-optimizer.cc | 2 - deps/v8/src/compiler/mips/code-generator-mips.cc | 228 +- deps/v8/src/compiler/mips/instruction-codes-mips.h | 1 + .../src/compiler/mips/instruction-selector-mips.cc | 169 +- .../src/compiler/mips64/code-generator-mips64.cc | 245 +- .../src/compiler/mips64/instruction-codes-mips64.h | 1 + .../compiler/mips64/instruction-selector-mips64.cc | 190 +- deps/v8/src/compiler/node-properties.cc | 38 +- deps/v8/src/compiler/node-properties.h | 3 + deps/v8/src/compiler/opcodes.h | 46 +- deps/v8/src/compiler/operation-typer.cc | 10 + deps/v8/src/compiler/operation-typer.h | 2 + deps/v8/src/compiler/pipeline.cc | 96 +- deps/v8/src/compiler/pipeline.h | 2 +- deps/v8/src/compiler/ppc/code-generator-ppc.cc | 302 +- .../src/compiler/ppc/instruction-selector-ppc.cc | 307 +- deps/v8/src/compiler/property-access-builder.cc | 15 +- deps/v8/src/compiler/raw-machine-assembler.cc | 32 +- deps/v8/src/compiler/raw-machine-assembler.h | 7 + deps/v8/src/compiler/redundancy-elimination.cc | 55 +- deps/v8/src/compiler/representation-change.cc | 67 +- deps/v8/src/compiler/representation-change.h | 23 +- deps/v8/src/compiler/s390/code-generator-s390.cc | 212 +- .../src/compiler/s390/instruction-selector-s390.cc | 321 +- deps/v8/src/compiler/simd-scalar-lowering.cc | 8 +- deps/v8/src/compiler/simplified-lowering.cc | 135 +- deps/v8/src/compiler/simplified-lowering.h | 2 +- deps/v8/src/compiler/simplified-operator.cc | 315 +- deps/v8/src/compiler/simplified-operator.h | 178 +- deps/v8/src/compiler/state-values-utils.cc | 2 +- deps/v8/src/compiler/store-store-elimination.cc | 4 +- deps/v8/src/compiler/type-cache.h | 2 + deps/v8/src/compiler/typer.cc | 140 +- deps/v8/src/compiler/types.cc | 2 + deps/v8/src/compiler/types.h | 3 +- deps/v8/src/compiler/verifier.cc | 59 +- deps/v8/src/compiler/wasm-compiler.cc | 693 ++-- deps/v8/src/compiler/wasm-compiler.h | 121 +- deps/v8/src/compiler/wasm-linkage.cc | 123 +- deps/v8/src/compiler/x64/code-generator-x64.cc | 479 +-- deps/v8/src/compiler/x64/instruction-codes-x64.h | 16 + .../src/compiler/x64/instruction-scheduler-x64.cc | 32 +- .../src/compiler/x64/instruction-selector-x64.cc | 217 +- deps/v8/src/contexts-inl.h | 6 +- deps/v8/src/contexts.cc | 4 +- deps/v8/src/contexts.h | 19 +- deps/v8/src/conversions.cc | 7 +- deps/v8/src/counters-inl.h | 6 +- deps/v8/src/counters.cc | 99 +- deps/v8/src/counters.h | 160 +- deps/v8/src/d8-posix.cc | 14 +- deps/v8/src/d8.cc | 441 ++- deps/v8/src/d8.h | 51 +- deps/v8/src/debug/debug-coverage.cc | 33 +- deps/v8/src/debug/debug-evaluate.cc | 38 +- deps/v8/src/debug/debug-frames.h | 8 +- deps/v8/src/debug/debug-type-profile.cc | 5 +- deps/v8/src/debug/debug.cc | 8 +- deps/v8/src/debug/liveedit.cc | 7 +- deps/v8/src/debug/mirrors.js | 2 +- deps/v8/src/deoptimize-reason.h | 40 +- deps/v8/src/deoptimizer.cc | 1194 +++--- deps/v8/src/deoptimizer.h | 110 +- deps/v8/src/disassembler.cc | 42 +- deps/v8/src/disassembler.h | 2 +- deps/v8/src/eh-frame.cc | 14 +- deps/v8/src/elements-kind.h | 37 + deps/v8/src/elements.cc | 122 +- deps/v8/src/elements.h | 19 +- deps/v8/src/execution.cc | 65 +- deps/v8/src/execution.h | 13 +- deps/v8/src/extensions/statistics-extension.cc | 18 - deps/v8/src/external-reference-table.cc | 8 + deps/v8/src/factory-inl.h | 8 + deps/v8/src/factory.cc | 71 +- deps/v8/src/factory.h | 20 +- deps/v8/src/fast-dtoa.cc | 7 +- deps/v8/src/feedback-vector-inl.h | 9 +- deps/v8/src/feedback-vector.cc | 151 +- deps/v8/src/feedback-vector.h | 119 +- deps/v8/src/flag-definitions.h | 136 +- deps/v8/src/flags.cc | 78 +- deps/v8/src/frame-constants.h | 8 +- deps/v8/src/frames-inl.h | 12 +- deps/v8/src/frames.cc | 133 +- deps/v8/src/frames.h | 29 +- deps/v8/src/gdb-jit.cc | 60 +- deps/v8/src/global-handles.cc | 2 +- deps/v8/src/globals.h | 351 +- deps/v8/src/handles.cc | 2 +- deps/v8/src/heap-symbols.h | 15 + deps/v8/src/heap/array-buffer-collector.cc | 3 + deps/v8/src/heap/concurrent-marking.cc | 21 +- deps/v8/src/heap/gc-tracer.cc | 185 +- deps/v8/src/heap/gc-tracer.h | 69 +- deps/v8/src/heap/heap-inl.h | 29 +- deps/v8/src/heap/heap.cc | 390 +- deps/v8/src/heap/heap.h | 240 +- deps/v8/src/heap/incremental-marking-job.cc | 2 +- deps/v8/src/heap/incremental-marking.cc | 35 +- deps/v8/src/heap/local-allocator.h | 2 +- deps/v8/src/heap/mark-compact.cc | 203 +- deps/v8/src/heap/mark-compact.h | 11 +- deps/v8/src/heap/object-stats.cc | 307 +- deps/v8/src/heap/object-stats.h | 67 +- deps/v8/src/heap/objects-visiting.h | 1 + deps/v8/src/heap/scavenge-job.cc | 2 +- deps/v8/src/heap/scavenger-inl.h | 2 - deps/v8/src/heap/scavenger.cc | 14 - deps/v8/src/heap/scavenger.h | 2 - deps/v8/src/heap/setup-heap-internal.cc | 18 +- deps/v8/src/heap/spaces-inl.h | 35 +- deps/v8/src/heap/spaces.cc | 768 ++-- deps/v8/src/heap/spaces.h | 297 +- deps/v8/src/heap/store-buffer.cc | 14 +- deps/v8/src/heap/store-buffer.h | 8 +- deps/v8/src/heap/stress-marking-observer.cc | 21 + deps/v8/src/heap/stress-marking-observer.h | 26 + deps/v8/src/heap/stress-scavenge-observer.cc | 94 + deps/v8/src/heap/stress-scavenge-observer.h | 39 + deps/v8/src/heap/sweeper.cc | 153 +- deps/v8/src/heap/sweeper.h | 61 +- deps/v8/src/ia32/assembler-ia32-inl.h | 19 +- deps/v8/src/ia32/assembler-ia32.cc | 80 +- deps/v8/src/ia32/assembler-ia32.h | 34 +- deps/v8/src/ia32/code-stubs-ia32.cc | 30 +- deps/v8/src/ia32/codegen-ia32.cc | 12 +- deps/v8/src/ia32/disasm-ia32.cc | 162 +- deps/v8/src/ia32/interface-descriptors-ia32.cc | 7 +- deps/v8/src/ia32/macro-assembler-ia32.cc | 46 +- deps/v8/src/ia32/macro-assembler-ia32.h | 10 +- deps/v8/src/ia32/simulator-ia32.h | 46 +- deps/v8/src/ic/accessor-assembler.cc | 937 ++--- deps/v8/src/ic/accessor-assembler.h | 91 +- deps/v8/src/ic/handler-configuration-inl.h | 57 +- deps/v8/src/ic/handler-configuration.cc | 327 +- deps/v8/src/ic/handler-configuration.h | 109 +- deps/v8/src/ic/ic-inl.h | 3 +- deps/v8/src/ic/ic.cc | 209 +- deps/v8/src/ic/ic.h | 4 +- deps/v8/src/ic/keyed-store-generic.cc | 44 +- deps/v8/src/ic/stub-cache.cc | 2 +- deps/v8/src/ic/stub-cache.h | 3 +- deps/v8/src/icu_util.cc | 4 + deps/v8/src/inspector/BUILD.gn | 11 - deps/v8/src/inspector/OWNERS | 3 + deps/v8/src/inspector/injected-script-source.js | 28 +- deps/v8/src/inspector/injected_script_externs.js | 6 + deps/v8/src/inspector/js_protocol.json | 4167 +++++++++++++------ deps/v8/src/inspector/js_protocol.pdl | 1370 +++++++ deps/v8/src/inspector/string-16.cc | 32 +- deps/v8/src/inspector/v8-console-message.cc | 5 + deps/v8/src/inspector/v8-console-message.h | 1 + deps/v8/src/inspector/v8-console.cc | 22 +- deps/v8/src/inspector/v8-debugger-agent-impl.cc | 34 +- deps/v8/src/inspector/v8-debugger-agent-impl.h | 1 + deps/v8/src/inspector/v8-debugger.cc | 35 +- deps/v8/src/inspector/v8-debugger.h | 8 +- .../src/inspector/v8-heap-profiler-agent-impl.cc | 2 +- deps/v8/src/inspector/v8-injected-script-host.cc | 50 +- deps/v8/src/inspector/v8-injected-script-host.h | 2 + deps/v8/src/inspector/v8-inspector-session-impl.cc | 5 +- deps/v8/src/inspector/v8-inspector-session-impl.h | 4 +- deps/v8/src/inspector/v8-stack-trace-impl.cc | 8 +- deps/v8/src/inspector/v8-stack-trace-impl.h | 1 + deps/v8/src/inspector/v8-value-utils.cc | 1 + deps/v8/src/interface-descriptors.cc | 72 +- deps/v8/src/interface-descriptors.h | 80 +- deps/v8/src/interpreter/bytecode-array-builder.cc | 28 +- deps/v8/src/interpreter/bytecode-array-builder.h | 11 +- deps/v8/src/interpreter/bytecode-generator.cc | 400 +- deps/v8/src/interpreter/bytecode-generator.h | 21 + .../src/interpreter/bytecode-register-allocator.h | 5 + .../src/interpreter/bytecode-register-optimizer.cc | 2 +- .../src/interpreter/bytecode-register-optimizer.h | 2 +- deps/v8/src/interpreter/bytecode-register.h | 26 +- deps/v8/src/interpreter/bytecodes.h | 9 +- deps/v8/src/interpreter/constant-array-builder.cc | 2 +- deps/v8/src/interpreter/handler-table-builder.cc | 2 +- deps/v8/src/interpreter/interpreter-assembler.cc | 21 +- deps/v8/src/interpreter/interpreter-assembler.h | 6 +- deps/v8/src/interpreter/interpreter-generator.cc | 206 +- .../interpreter-intrinsics-generator.cc | 6 +- deps/v8/src/interpreter/interpreter.cc | 6 +- deps/v8/src/isolate.cc | 397 +- deps/v8/src/isolate.h | 64 +- deps/v8/src/js/array.js | 58 - deps/v8/src/js/prologue.js | 36 + deps/v8/src/js/proxy.js | 27 - deps/v8/src/js/v8natives.js | 64 - deps/v8/src/json-parser.cc | 62 +- deps/v8/src/json-parser.h | 8 +- deps/v8/src/json-stringifier.cc | 68 +- deps/v8/src/keys.cc | 25 +- deps/v8/src/label.h | 5 +- deps/v8/src/layout-descriptor-inl.h | 5 +- deps/v8/src/layout-descriptor.h | 2 +- deps/v8/src/libplatform/default-platform.cc | 6 + deps/v8/src/libplatform/default-platform.h | 3 + deps/v8/src/log-utils.cc | 5 +- deps/v8/src/log-utils.h | 6 +- deps/v8/src/log.cc | 98 +- deps/v8/src/log.h | 22 +- deps/v8/src/lookup.cc | 57 +- deps/v8/src/machine-type.h | 2 +- deps/v8/src/messages.cc | 54 +- deps/v8/src/messages.h | 9 +- deps/v8/src/mips/assembler-mips-inl.h | 42 +- deps/v8/src/mips/assembler-mips.cc | 20 +- deps/v8/src/mips/assembler-mips.h | 5 +- deps/v8/src/mips/code-stubs-mips.cc | 48 +- deps/v8/src/mips/codegen-mips.cc | 20 +- deps/v8/src/mips/disasm-mips.cc | 4 +- deps/v8/src/mips/interface-descriptors-mips.cc | 7 +- deps/v8/src/mips/macro-assembler-mips.cc | 76 +- deps/v8/src/mips/macro-assembler-mips.h | 6 +- deps/v8/src/mips/simulator-mips.cc | 203 +- deps/v8/src/mips/simulator-mips.h | 121 +- deps/v8/src/mips64/assembler-mips64-inl.h | 32 +- deps/v8/src/mips64/assembler-mips64.cc | 19 +- deps/v8/src/mips64/assembler-mips64.h | 5 +- deps/v8/src/mips64/code-stubs-mips64.cc | 48 +- deps/v8/src/mips64/codegen-mips64.cc | 20 +- deps/v8/src/mips64/disasm-mips64.cc | 10 +- deps/v8/src/mips64/interface-descriptors-mips64.cc | 7 +- deps/v8/src/mips64/macro-assembler-mips64.cc | 68 +- deps/v8/src/mips64/macro-assembler-mips64.h | 6 +- deps/v8/src/mips64/simulator-mips64.cc | 238 +- deps/v8/src/mips64/simulator-mips64.h | 132 +- deps/v8/src/objects-body-descriptors-inl.h | 3 + deps/v8/src/objects-debug.cc | 81 +- deps/v8/src/objects-inl.h | 1727 +------- deps/v8/src/objects-printer.cc | 102 +- deps/v8/src/objects.cc | 613 +-- deps/v8/src/objects.h | 985 +---- deps/v8/src/objects/bigint.cc | 84 +- deps/v8/src/objects/bigint.h | 25 +- deps/v8/src/objects/code-inl.h | 34 +- deps/v8/src/objects/code.h | 21 +- deps/v8/src/objects/data-handler-inl.h | 41 + deps/v8/src/objects/data-handler.h | 63 + deps/v8/src/objects/debug-objects.h | 1 + deps/v8/src/objects/descriptor-array.h | 1 + deps/v8/src/objects/fixed-array-inl.h | 634 +++ deps/v8/src/objects/fixed-array.h | 601 +++ deps/v8/src/objects/hash-table-inl.h | 109 + deps/v8/src/objects/hash-table.h | 34 +- deps/v8/src/objects/js-array-inl.h | 29 + deps/v8/src/objects/js-array.h | 4 + deps/v8/src/objects/js-collection-inl.h | 49 + deps/v8/src/objects/js-collection.h | 162 + deps/v8/src/objects/js-regexp.h | 15 +- deps/v8/src/objects/literal-objects.h | 1 + deps/v8/src/objects/map-inl.h | 645 ++- deps/v8/src/objects/map.h | 151 +- deps/v8/src/objects/module.cc | 179 +- deps/v8/src/objects/module.h | 16 +- deps/v8/src/objects/object-macros.h | 3 +- deps/v8/src/objects/scope-info.h | 5 +- deps/v8/src/objects/script-inl.h | 35 +- deps/v8/src/objects/script.h | 23 +- deps/v8/src/objects/shared-function-info-inl.h | 2 + deps/v8/src/objects/shared-function-info.h | 18 +- deps/v8/src/objects/string-inl.h | 31 + deps/v8/src/objects/string.h | 7 + deps/v8/src/ostreams.cc | 8 +- deps/v8/src/parsing/background-parsing-task.cc | 3 +- deps/v8/src/parsing/expression-classifier.h | 25 +- deps/v8/src/parsing/expression-scope-reparenter.cc | 8 +- deps/v8/src/parsing/parse-info.cc | 14 +- deps/v8/src/parsing/parse-info.h | 10 +- deps/v8/src/parsing/parser-base.h | 387 +- deps/v8/src/parsing/parser.cc | 350 +- deps/v8/src/parsing/parser.h | 54 +- deps/v8/src/parsing/pattern-rewriter.cc | 10 +- deps/v8/src/parsing/preparsed-scope-data.cc | 6 +- deps/v8/src/parsing/preparser.cc | 20 +- deps/v8/src/parsing/preparser.h | 25 +- deps/v8/src/parsing/rewriter.cc | 4 +- deps/v8/src/parsing/scanner-character-streams.cc | 57 +- deps/v8/src/parsing/scanner.cc | 117 +- deps/v8/src/parsing/scanner.h | 17 +- deps/v8/src/parsing/token.h | 1 + deps/v8/src/perf-jit.cc | 4 +- deps/v8/src/ppc/assembler-ppc-inl.h | 49 +- deps/v8/src/ppc/assembler-ppc.cc | 81 +- deps/v8/src/ppc/assembler-ppc.h | 5 +- deps/v8/src/ppc/code-stubs-ppc.cc | 33 +- deps/v8/src/ppc/codegen-ppc.cc | 6 +- deps/v8/src/ppc/interface-descriptors-ppc.cc | 7 +- deps/v8/src/ppc/macro-assembler-ppc.cc | 55 +- deps/v8/src/ppc/macro-assembler-ppc.h | 6 +- deps/v8/src/ppc/simulator-ppc.cc | 232 +- deps/v8/src/ppc/simulator-ppc.h | 111 +- deps/v8/src/profiler/cpu-profiler.cc | 4 +- deps/v8/src/profiler/heap-snapshot-generator.cc | 11 +- deps/v8/src/profiler/heap-snapshot-generator.h | 3 + deps/v8/src/profiler/profile-generator.cc | 8 - deps/v8/src/profiler/profiler-listener.cc | 2 +- deps/v8/src/profiler/sampling-heap-profiler.cc | 19 +- deps/v8/src/profiler/tick-sample.cc | 12 +- .../src/regexp/arm/regexp-macro-assembler-arm.cc | 35 +- .../regexp/arm64/regexp-macro-assembler-arm64.cc | 36 +- .../src/regexp/ia32/regexp-macro-assembler-ia32.cc | 32 +- deps/v8/src/regexp/jsregexp.cc | 76 +- .../src/regexp/mips/regexp-macro-assembler-mips.cc | 37 +- .../regexp/mips64/regexp-macro-assembler-mips64.cc | 37 +- .../src/regexp/ppc/regexp-macro-assembler-ppc.cc | 35 +- deps/v8/src/regexp/regexp-ast.h | 12 +- deps/v8/src/regexp/regexp-macro-assembler.cc | 40 +- deps/v8/src/regexp/regexp-parser.cc | 42 +- deps/v8/src/regexp/regexp-utils.cc | 2 +- .../src/regexp/s390/regexp-macro-assembler-s390.cc | 37 +- .../src/regexp/x64/regexp-macro-assembler-x64.cc | 32 +- deps/v8/src/runtime/runtime-bigint.cc | 3 +- deps/v8/src/runtime/runtime-classes.cc | 18 +- deps/v8/src/runtime/runtime-compiler.cc | 21 +- deps/v8/src/runtime/runtime-debug.cc | 1 + deps/v8/src/runtime/runtime-function.cc | 4 +- deps/v8/src/runtime/runtime-internal.cc | 18 + deps/v8/src/runtime/runtime-module.cc | 8 +- deps/v8/src/runtime/runtime-numbers.cc | 10 - deps/v8/src/runtime/runtime-object.cc | 55 + deps/v8/src/runtime/runtime-promise.cc | 16 - deps/v8/src/runtime/runtime-proxy.cc | 8 - deps/v8/src/runtime/runtime-regexp.cc | 9 +- deps/v8/src/runtime/runtime-scopes.cc | 4 + deps/v8/src/runtime/runtime-strings.cc | 8 +- deps/v8/src/runtime/runtime-test.cc | 128 +- deps/v8/src/runtime/runtime-typedarray.cc | 100 +- deps/v8/src/runtime/runtime-wasm.cc | 20 +- deps/v8/src/runtime/runtime.h | 40 +- deps/v8/src/s390/assembler-s390-inl.h | 42 +- deps/v8/src/s390/assembler-s390.cc | 38 +- deps/v8/src/s390/assembler-s390.h | 5 +- deps/v8/src/s390/code-stubs-s390.cc | 34 +- deps/v8/src/s390/codegen-s390.cc | 6 +- deps/v8/src/s390/constants-s390.cc | 312 +- deps/v8/src/s390/interface-descriptors-s390.cc | 8 +- deps/v8/src/s390/macro-assembler-s390.cc | 55 +- deps/v8/src/s390/macro-assembler-s390.h | 6 +- deps/v8/src/s390/simulator-s390.cc | 198 +- deps/v8/src/s390/simulator-s390.h | 110 +- deps/v8/src/safepoint-table.cc | 83 +- deps/v8/src/safepoint-table.h | 31 +- deps/v8/src/simulator-base.cc | 95 + deps/v8/src/simulator-base.h | 163 + deps/v8/src/simulator.h | 108 + .../src/snapshot/builtin-deserializer-allocator.h | 2 +- deps/v8/src/snapshot/code-serializer.cc | 49 +- deps/v8/src/snapshot/code-serializer.h | 2 +- .../src/snapshot/default-deserializer-allocator.cc | 2 +- .../src/snapshot/default-deserializer-allocator.h | 2 +- deps/v8/src/snapshot/deserializer.cc | 56 +- deps/v8/src/snapshot/mksnapshot.cc | 2 +- deps/v8/src/snapshot/partial-serializer.cc | 26 +- deps/v8/src/snapshot/partial-serializer.h | 3 +- deps/v8/src/snapshot/serializer-common.cc | 11 + deps/v8/src/snapshot/serializer-common.h | 3 + deps/v8/src/snapshot/serializer.cc | 23 +- deps/v8/src/snapshot/serializer.h | 2 +- deps/v8/src/snapshot/snapshot-common.cc | 12 +- deps/v8/src/snapshot/snapshot-empty.cc | 4 +- deps/v8/src/snapshot/snapshot-source-sink.cc | 14 +- deps/v8/src/snapshot/snapshot.h | 2 +- deps/v8/src/snapshot/startup-deserializer.cc | 2 +- deps/v8/src/snapshot/startup-serializer.cc | 39 +- deps/v8/src/snapshot/startup-serializer.h | 14 + deps/v8/src/string-stream.cc | 2 +- deps/v8/src/strtod.cc | 32 +- deps/v8/src/third_party/utf8-decoder/LICENSE | 19 + deps/v8/src/third_party/utf8-decoder/README.v8 | 18 + .../v8/src/third_party/utf8-decoder/utf8-decoder.h | 78 + deps/v8/src/tracing/traced-value.cc | 2 +- deps/v8/src/tracing/tracing-category-observer.cc | 15 +- deps/v8/src/transitions.cc | 4 +- deps/v8/src/trap-handler/trap-handler.h | 6 +- deps/v8/src/type-hints.cc | 4 + deps/v8/src/type-hints.h | 2 + deps/v8/src/unicode-inl.h | 4 +- deps/v8/src/unicode.cc | 325 +- deps/v8/src/unicode.h | 7 +- deps/v8/src/uri.cc | 14 +- deps/v8/src/utils.h | 18 +- deps/v8/src/v8.cc | 15 +- deps/v8/src/v8.gyp | 69 +- deps/v8/src/value-serializer.cc | 46 +- deps/v8/src/vector-slot-pair.cc | 39 + deps/v8/src/vector-slot-pair.h | 47 + .../wasm/baseline/arm/liftoff-assembler-arm-defs.h | 23 - .../src/wasm/baseline/arm/liftoff-assembler-arm.h | 202 +- .../baseline/arm64/liftoff-assembler-arm64-defs.h | 23 - .../wasm/baseline/arm64/liftoff-assembler-arm64.h | 202 +- .../baseline/ia32/liftoff-assembler-ia32-defs.h | 23 - .../wasm/baseline/ia32/liftoff-assembler-ia32.h | 494 ++- deps/v8/src/wasm/baseline/liftoff-assembler-defs.h | 64 + deps/v8/src/wasm/baseline/liftoff-assembler.cc | 268 +- deps/v8/src/wasm/baseline/liftoff-assembler.h | 348 +- deps/v8/src/wasm/baseline/liftoff-compiler.cc | 824 +++- deps/v8/src/wasm/baseline/liftoff-register.h | 242 ++ .../baseline/mips/liftoff-assembler-mips-defs.h | 23 - .../wasm/baseline/mips/liftoff-assembler-mips.h | 202 +- .../mips64/liftoff-assembler-mips64-defs.h | 23 - .../baseline/mips64/liftoff-assembler-mips64.h | 202 +- .../wasm/baseline/ppc/liftoff-assembler-ppc-defs.h | 23 - .../src/wasm/baseline/ppc/liftoff-assembler-ppc.h | 202 +- .../baseline/s390/liftoff-assembler-s390-defs.h | 23 - .../wasm/baseline/s390/liftoff-assembler-s390.h | 202 +- .../wasm/baseline/x64/liftoff-assembler-x64-defs.h | 23 - .../src/wasm/baseline/x64/liftoff-assembler-x64.h | 476 ++- deps/v8/src/wasm/decoder.h | 31 +- deps/v8/src/wasm/function-body-decoder-impl.h | 263 +- deps/v8/src/wasm/function-body-decoder.cc | 39 +- deps/v8/src/wasm/function-body-decoder.h | 17 +- deps/v8/src/wasm/memory-tracing.cc | 31 +- deps/v8/src/wasm/memory-tracing.h | 31 +- deps/v8/src/wasm/module-compiler.cc | 702 ++-- deps/v8/src/wasm/module-compiler.h | 20 +- deps/v8/src/wasm/module-decoder.cc | 42 +- deps/v8/src/wasm/module-decoder.h | 36 +- deps/v8/src/wasm/streaming-decoder.cc | 97 +- deps/v8/src/wasm/wasm-code-manager.cc | 1057 +++++ deps/v8/src/wasm/wasm-code-manager.h | 419 ++ deps/v8/src/wasm/wasm-code-specialization.cc | 30 +- deps/v8/src/wasm/wasm-code-wrapper.cc | 33 +- deps/v8/src/wasm/wasm-code-wrapper.h | 10 + deps/v8/src/wasm/wasm-constants.h | 83 + deps/v8/src/wasm/wasm-debug.cc | 64 +- deps/v8/src/wasm/wasm-engine.cc | 23 + deps/v8/src/wasm/wasm-engine.h | 46 + deps/v8/src/wasm/wasm-external-refs.cc | 26 +- deps/v8/src/wasm/wasm-external-refs.h | 4 + deps/v8/src/wasm/wasm-heap.cc | 886 ----- deps/v8/src/wasm/wasm-heap.h | 389 -- deps/v8/src/wasm/wasm-interpreter.cc | 341 +- deps/v8/src/wasm/wasm-interpreter.h | 10 +- deps/v8/src/wasm/wasm-js.cc | 91 +- deps/v8/src/wasm/wasm-limits.h | 7 +- deps/v8/src/wasm/wasm-memory.cc | 87 +- deps/v8/src/wasm/wasm-memory.h | 22 +- deps/v8/src/wasm/wasm-module-builder.cc | 34 +- deps/v8/src/wasm/wasm-module-builder.h | 4 +- deps/v8/src/wasm/wasm-module.cc | 116 +- deps/v8/src/wasm/wasm-module.h | 41 +- deps/v8/src/wasm/wasm-objects-inl.h | 35 +- deps/v8/src/wasm/wasm-objects.cc | 986 +++-- deps/v8/src/wasm/wasm-objects.h | 204 +- deps/v8/src/wasm/wasm-opcodes.cc | 65 +- deps/v8/src/wasm/wasm-opcodes.h | 229 +- deps/v8/src/wasm/wasm-serialization.cc | 183 +- deps/v8/src/wasm/wasm-serialization.h | 80 +- deps/v8/src/x64/assembler-x64-inl.h | 19 +- deps/v8/src/x64/assembler-x64.cc | 137 +- deps/v8/src/x64/assembler-x64.h | 11 +- deps/v8/src/x64/code-stubs-x64.cc | 28 +- deps/v8/src/x64/codegen-x64.cc | 6 +- deps/v8/src/x64/deoptimizer-x64.cc | 26 +- deps/v8/src/x64/disasm-x64.cc | 150 +- deps/v8/src/x64/interface-descriptors-x64.cc | 7 +- deps/v8/src/x64/macro-assembler-x64.cc | 147 +- deps/v8/src/x64/macro-assembler-x64.h | 13 +- deps/v8/src/x64/simulator-x64.cc | 2 + deps/v8/src/x64/simulator-x64.h | 42 +- deps/v8/src/zone/accounting-allocator.cc | 8 +- deps/v8/src/zone/zone-containers.h | 5 + deps/v8/src/zone/zone.cc | 9 +- deps/v8/src/zone/zone.h | 7 +- deps/v8/test/BUILD.gn | 23 + deps/v8/test/benchmarks/testcfg.py | 86 +- deps/v8/test/bot_default.gyp | 1 + deps/v8/test/cctest/BUILD.gn | 3 + deps/v8/test/cctest/assembler-helper-arm.cc | 8 +- deps/v8/test/cctest/assembler-helper-arm.h | 27 +- deps/v8/test/cctest/cctest.cc | 2 +- deps/v8/test/cctest/cctest.gyp | 3 + deps/v8/test/cctest/cctest.h | 22 +- deps/v8/test/cctest/cctest.status | 28 +- deps/v8/test/cctest/compiler/c-signature.h | 143 +- deps/v8/test/cctest/compiler/call-tester.h | 156 +- .../test/cctest/compiler/code-assembler-tester.h | 5 +- deps/v8/test/cctest/compiler/codegen-tester.cc | 36 +- deps/v8/test/cctest/compiler/codegen-tester.h | 209 +- .../v8/test/cctest/compiler/graph-builder-tester.h | 45 +- .../v8/test/cctest/compiler/test-code-generator.cc | 431 +- .../test/cctest/compiler/test-js-typed-lowering.cc | 2 +- deps/v8/test/cctest/compiler/test-loop-analysis.cc | 2 +- .../compiler/test-machine-operator-reducer.cc | 4 +- .../test/cctest/compiler/test-multiple-return.cc | 379 +- deps/v8/test/cctest/compiler/test-operator.cc | 2 +- .../cctest/compiler/test-representation-change.cc | 12 +- deps/v8/test/cctest/compiler/test-run-jsops.cc | 2 +- .../v8/test/cctest/compiler/test-run-load-store.cc | 614 +-- deps/v8/test/cctest/compiler/test-run-machops.cc | 593 +-- .../test/cctest/compiler/test-run-native-calls.cc | 10 +- deps/v8/test/cctest/compiler/test-run-retpoline.cc | 208 + .../v8/test/cctest/compiler/test-run-tail-calls.cc | 171 + .../test/cctest/compiler/test-run-wasm-machops.cc | 16 +- deps/v8/test/cctest/compiler/value-helper.h | 52 +- deps/v8/test/cctest/heap/heap-tester.h | 1 + deps/v8/test/cctest/heap/heap-utils.cc | 15 +- deps/v8/test/cctest/heap/test-embedder-tracing.cc | 197 + deps/v8/test/cctest/heap/test-heap.cc | 18 +- .../test/cctest/heap/test-incremental-marking.cc | 8 +- deps/v8/test/cctest/heap/test-mark-compact.cc | 2 +- deps/v8/test/cctest/heap/test-spaces.cc | 62 +- .../bytecode_expectations/AsyncGenerators.golden | 501 ++- .../bytecode_expectations/ClassFields.golden | 185 +- .../bytecode_expectations/DeclareGlobals.golden | 6 +- .../bytecode_expectations/ForAwaitOf.golden | 1143 +++--- .../interpreter/bytecode_expectations/ForOf.golden | 504 ++- .../bytecode_expectations/ForOfLoop.golden | 1340 +++---- .../bytecode_expectations/Generators.golden | 302 +- .../GlobalCompoundExpressions.golden | 4 +- .../GlobalCountOperators.golden | 8 +- .../bytecode_expectations/Modules.golden | 703 ++-- .../bytecode_expectations/StandardForLoop.golden | 52 +- .../bytecode_expectations/StaticClassFields.golden | 339 ++ .../bytecode_expectations/StoreGlobal.golden | 12 +- .../TopLevelObjectLiterals.golden | 2 +- .../interpreter/generate-bytecode-expectations.cc | 14 +- .../test/cctest/interpreter/interpreter-tester.h | 5 + .../cctest/interpreter/test-bytecode-generator.cc | 66 +- .../interpreter/test-interpreter-intrinsics.cc | 3 +- .../v8/test/cctest/interpreter/test-interpreter.cc | 119 +- deps/v8/test/cctest/parsing/test-preparser.cc | 20 +- .../v8/test/cctest/parsing/test-scanner-streams.cc | 18 +- deps/v8/test/cctest/parsing/test-scanner.cc | 8 +- deps/v8/test/cctest/profiler-extension.cc | 3 +- deps/v8/test/cctest/test-access-checks.cc | 2 +- deps/v8/test/cctest/test-accessors.cc | 107 +- deps/v8/test/cctest/test-allocation.cc | 17 +- deps/v8/test/cctest/test-api-interceptors.cc | 46 +- deps/v8/test/cctest/test-api.cc | 266 +- deps/v8/test/cctest/test-assembler-arm.cc | 710 ++-- deps/v8/test/cctest/test-assembler-arm64.cc | 4168 +++++++++----------- deps/v8/test/cctest/test-assembler-ia32.cc | 13 +- deps/v8/test/cctest/test-assembler-mips.cc | 1431 ++++--- deps/v8/test/cctest/test-assembler-mips64.cc | 1830 +++++---- deps/v8/test/cctest/test-assembler-ppc.cc | 95 +- deps/v8/test/cctest/test-assembler-s390.cc | 55 +- deps/v8/test/cctest/test-assembler-x64.cc | 240 +- deps/v8/test/cctest/test-atomicops.cc | 5 +- deps/v8/test/cctest/test-bignum.cc | 2 +- deps/v8/test/cctest/test-code-layout.cc | 10 +- deps/v8/test/cctest/test-code-stub-assembler.cc | 105 +- deps/v8/test/cctest/test-code-stubs-arm.cc | 6 +- deps/v8/test/cctest/test-code-stubs-arm64.cc | 70 +- deps/v8/test/cctest/test-code-stubs-ia32.cc | 3 +- deps/v8/test/cctest/test-code-stubs-mips.cc | 3 +- deps/v8/test/cctest/test-code-stubs-mips64.cc | 3 +- deps/v8/test/cctest/test-code-stubs-x64.cc | 3 +- deps/v8/test/cctest/test-code-stubs.cc | 2 +- deps/v8/test/cctest/test-compiler.cc | 151 +- deps/v8/test/cctest/test-conversions.cc | 6 +- deps/v8/test/cctest/test-cpu-profiler.cc | 74 +- deps/v8/test/cctest/test-debug.cc | 67 +- deps/v8/test/cctest/test-disasm-arm.cc | 18 +- deps/v8/test/cctest/test-disasm-arm64.cc | 75 +- deps/v8/test/cctest/test-disasm-ia32.cc | 11 + deps/v8/test/cctest/test-disasm-mips.cc | 17 +- deps/v8/test/cctest/test-disasm-mips64.cc | 19 +- deps/v8/test/cctest/test-disasm-x64.cc | 6 + deps/v8/test/cctest/test-diy-fp.cc | 6 +- deps/v8/test/cctest/test-double.cc | 14 +- deps/v8/test/cctest/test-feedback-vector.cc | 38 +- deps/v8/test/cctest/test-field-type-tracking.cc | 2 +- deps/v8/test/cctest/test-func-name-inference.cc | 28 + deps/v8/test/cctest/test-heap-profiler.cc | 36 +- .../v8/test/cctest/test-inobject-slack-tracking.cc | 6 + deps/v8/test/cctest/test-log-stack-tracer.cc | 2 +- deps/v8/test/cctest/test-log.cc | 21 +- deps/v8/test/cctest/test-macro-assembler-arm.cc | 22 +- deps/v8/test/cctest/test-macro-assembler-mips.cc | 127 +- deps/v8/test/cctest/test-macro-assembler-mips64.cc | 197 +- deps/v8/test/cctest/test-macro-assembler-x64.cc | 16 +- deps/v8/test/cctest/test-modules.cc | 185 +- deps/v8/test/cctest/test-parsing.cc | 972 ++++- deps/v8/test/cctest/test-platform.cc | 39 - deps/v8/test/cctest/test-profile-generator.cc | 3 +- deps/v8/test/cctest/test-regexp.cc | 10 +- .../v8/test/cctest/test-run-wasm-relocation-arm.cc | 2 +- .../test/cctest/test-run-wasm-relocation-arm64.cc | 2 +- .../test/cctest/test-run-wasm-relocation-ia32.cc | 2 +- .../v8/test/cctest/test-run-wasm-relocation-x64.cc | 2 +- deps/v8/test/cctest/test-serialize.cc | 399 +- deps/v8/test/cctest/test-strings.cc | 6 +- deps/v8/test/cctest/test-strtod.cc | 4 +- deps/v8/test/cctest/test-sync-primitives-arm.cc | 16 +- deps/v8/test/cctest/test-sync-primitives-arm64.cc | 10 +- deps/v8/test/cctest/test-thread-termination.cc | 8 +- deps/v8/test/cctest/test-traced-value.cc | 4 +- deps/v8/test/cctest/test-typedarrays.cc | 74 + deps/v8/test/cctest/test-types.cc | 34 +- deps/v8/test/cctest/test-unboxed-doubles.cc | 2 +- deps/v8/test/cctest/test-usecounters.cc | 25 - deps/v8/test/cctest/test-utils-arm64.cc | 4 +- deps/v8/test/cctest/test-utils-arm64.h | 2 +- deps/v8/test/cctest/test-utils.cc | 6 +- deps/v8/test/cctest/test-weakmaps.cc | 25 +- deps/v8/test/cctest/testcfg.py | 44 +- deps/v8/test/cctest/trace-extension.cc | 4 +- deps/v8/test/cctest/unicode-helpers.h | 12 +- deps/v8/test/cctest/wasm/test-c-wasm-entry.cc | 3 + deps/v8/test/cctest/wasm/test-run-wasm-64.cc | 493 +-- deps/v8/test/cctest/wasm/test-run-wasm-atomics.cc | 12 +- .../test/cctest/wasm/test-run-wasm-interpreter.cc | 12 +- deps/v8/test/cctest/wasm/test-run-wasm-module.cc | 143 +- deps/v8/test/cctest/wasm/test-run-wasm-simd.cc | 557 ++- deps/v8/test/cctest/wasm/test-run-wasm.cc | 267 +- .../test/cctest/wasm/test-streaming-compilation.cc | 123 +- deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc | 32 +- .../cctest/wasm/test-wasm-interpreter-entry.cc | 6 +- deps/v8/test/cctest/wasm/wasm-run-utils.cc | 133 +- deps/v8/test/cctest/wasm/wasm-run-utils.h | 43 +- deps/v8/test/common/wasm/wasm-macro-gen.h | 25 +- deps/v8/test/common/wasm/wasm-module-runner.cc | 6 +- deps/v8/test/d8_default.gyp | 31 + deps/v8/test/d8_default.isolate | 18 + .../debug/debug-modules-set-variable-value.js | 4 +- .../debug/harmony/modules-debug-scopes2.js | 10 +- .../v8/test/debugger/debug/regress/regress-1853.js | 3 +- .../debugger/debug/regress/regress-crbug-481896.js | 4 +- deps/v8/test/debugger/testcfg.py | 66 +- deps/v8/test/default.gyp | 1 + deps/v8/test/fuzzer/fuzzer-support.cc | 9 +- deps/v8/test/fuzzer/fuzzer.gyp | 30 + deps/v8/test/fuzzer/fuzzer.isolate | 2 + deps/v8/test/fuzzer/multi-return.cc | 346 ++ deps/v8/test/fuzzer/multi_return/README.md | 4 + deps/v8/test/fuzzer/regexp.cc | 2 +- deps/v8/test/fuzzer/testcfg.py | 64 +- deps/v8/test/fuzzer/wasm-async.cc | 2 +- deps/v8/test/fuzzer/wasm-compile.cc | 335 +- deps/v8/test/fuzzer/wasm-fuzzer-common.cc | 159 +- .../inspector/debugger/async-chains-expected.txt | 152 + deps/v8/test/inspector/debugger/async-chains.js | 77 + .../debugger/async-for-await-of-promise-stack.js | 2 - .../evaluate-on-call-frame-in-module-expected.txt | 228 +- .../debugger/evaluate-on-call-frame-in-module.js | 30 + .../inspector/debugger/external-stack-trace.js | 1 - .../inspector/debugger/for-of-loops-expected.txt | 8 +- .../get-possible-breakpoints-master-expected.txt | 12 +- .../debugger/pause-on-async-call-expected.txt | 78 + .../test/inspector/debugger/pause-on-async-call.js | 60 + .../debugger/return-break-locations-expected.txt | 6 + ...point-ignore-hint-when-no-location-expected.txt | 11 + .../set-breakpoint-ignore-hint-when-no-location.js | 27 + ...o-external-async-task-same-context-expected.txt | 14 + .../step-into-external-async-task-same-context.js | 81 + .../inspector/debugger/wasm-scripts-expected.txt | 7 +- deps/v8/test/inspector/inspector-test.cc | 45 +- deps/v8/test/inspector/protocol-test.js | 8 +- .../inspector/runtime/console-methods-expected.txt | 100 +- deps/v8/test/inspector/runtime/console-methods.js | 3 + .../runtime/console-time-repeat-expected.txt | 76 + .../test/inspector/runtime/console-time-repeat.js | 20 + .../inspector/runtime/evaluate-async-expected.txt | 16 +- .../inspector/runtime/get-properties-expected.txt | 37 + .../runtime/get-properties-on-proxy-expected.txt | 173 + .../inspector/runtime/get-properties-on-proxy.js | 209 +- deps/v8/test/inspector/runtime/get-properties.js | 94 +- .../runtime/regression-736302-expected.txt | 2 +- .../runtime-evaluate-null-property-expected.txt | 18 + .../runtime/runtime-evaluate-null-property.js | 14 + deps/v8/test/inspector/testcfg.py | 102 +- deps/v8/test/intl/testcfg.py | 61 +- deps/v8/test/js-perf-test/Array/every.js | 60 +- deps/v8/test/js-perf-test/Array/filter.js | 108 +- deps/v8/test/js-perf-test/Array/find-index.js | 63 + deps/v8/test/js-perf-test/Array/find.js | 63 + deps/v8/test/js-perf-test/Array/for-each.js | 62 + deps/v8/test/js-perf-test/Array/join.js | 36 +- deps/v8/test/js-perf-test/Array/map.js | 128 +- deps/v8/test/js-perf-test/Array/of.js | 117 + deps/v8/test/js-perf-test/Array/reduce-right.js | 61 +- deps/v8/test/js-perf-test/Array/reduce.js | 61 +- deps/v8/test/js-perf-test/Array/run.js | 73 +- deps/v8/test/js-perf-test/Array/some.js | 60 +- deps/v8/test/js-perf-test/Array/to-string.js | 37 +- deps/v8/test/js-perf-test/JSTests.json | 60 +- deps/v8/test/js-perf-test/Strings/run.js | 1 + .../v8/test/js-perf-test/Strings/string-indexof.js | 69 + .../js-perf-test/TypedArrays/slice-nospecies.js | 34 + .../js-perf-test/TypedArrays/subarray-nospecies.js | 34 + .../message/fail/array-binding-pattern-await1.js | 9 + .../message/fail/array-binding-pattern-await1.out | 4 + .../message/fail/class-field-static-constructor.js | 2 +- .../message/fail/class-field-static-prototype.js | 2 +- deps/v8/test/message/fail/modules-cycle1.out | 4 +- deps/v8/test/message/fail/modules-cycle2.out | 4 +- deps/v8/test/message/fail/modules-cycle3.out | 4 +- deps/v8/test/message/fail/modules-cycle4.out | 4 +- deps/v8/test/message/fail/modules-cycle5.out | 4 +- deps/v8/test/message/fail/modules-cycle6.out | 4 +- deps/v8/test/message/fail/modules-import1.out | 4 +- deps/v8/test/message/fail/modules-import2.out | 4 +- deps/v8/test/message/fail/modules-import3.out | 4 +- deps/v8/test/message/fail/modules-import4.out | 4 +- deps/v8/test/message/fail/modules-import5.out | 4 +- deps/v8/test/message/fail/modules-import6.out | 4 +- .../test/message/fail/modules-star-conflict1.out | 4 +- .../test/message/fail/modules-star-conflict2.out | 4 +- deps/v8/test/message/fail/modules-star-default.out | 4 +- .../message/fail/object-binding-pattern-await1.js | 9 + .../message/fail/object-binding-pattern-await1.out | 4 + deps/v8/test/message/message.status | 11 +- .../object-binding-pattern-await-computed-name.js | 9 + .../object-binding-pattern-await-computed-name.out | 0 deps/v8/test/message/testcfg.py | 112 +- .../test/message/wasm-trace-memory-interpreted.out | 14 +- deps/v8/test/message/wasm-trace-memory-liftoff.js | 7 + deps/v8/test/message/wasm-trace-memory-liftoff.out | 9 + deps/v8/test/message/wasm-trace-memory.js | 2 +- deps/v8/test/message/wasm-trace-memory.out | 18 +- deps/v8/test/mjsunit/array-iteration.js | 95 + deps/v8/test/mjsunit/array-reduce.js | 684 ++++ deps/v8/test/mjsunit/code-coverage-block-noopt.js | 2 +- deps/v8/test/mjsunit/code-coverage-block-opt.js | 4 +- deps/v8/test/mjsunit/code-coverage-block.js | 25 +- .../compiler/array-multiple-receiver-maps.js | 122 + .../test/mjsunit/compiler/deopt-array-builtins.js | 148 + deps/v8/test/mjsunit/compiler/deopt-array-push.js | 97 + .../v8/test/mjsunit/compiler/escape-analysis-13.js | 2 +- .../v8/test/mjsunit/compiler/escape-analysis-15.js | 2 +- .../mjsunit/compiler/escape-analysis-phi-type.js | 2 +- .../compiler/materialize-dictionary-properties.js | 18 + .../compiler/materialize-mutable-heap-number.js | 22 + deps/v8/test/mjsunit/compiler/new-cons-string.js | 71 + deps/v8/test/mjsunit/compiler/regress-786521.js | 23 + deps/v8/test/mjsunit/compiler/regress-793863.js | 12 + deps/v8/test/mjsunit/compiler/regress-796041.js | 35 + deps/v8/test/mjsunit/compiler/regress-797596.js | 30 + deps/v8/test/mjsunit/compiler/regress-801097.js | 19 + deps/v8/test/mjsunit/compiler/varargs.js | 49 + deps/v8/test/mjsunit/constant-folding-2.js | 4 +- deps/v8/test/mjsunit/d8-os.js | 188 - deps/v8/test/mjsunit/d8-performance-now.js | 57 - .../v8/test/mjsunit/d8-worker-sharedarraybuffer.js | 105 - deps/v8/test/mjsunit/d8-worker-spawn-worker.js | 40 - deps/v8/test/mjsunit/d8-worker.js | 156 - deps/v8/test/mjsunit/d8/.gitignore | 1 + deps/v8/test/mjsunit/d8/d8-os.js | 188 + deps/v8/test/mjsunit/d8/d8-performance-now.js | 57 + .../test/mjsunit/d8/d8-worker-sharedarraybuffer.js | 105 + deps/v8/test/mjsunit/d8/d8-worker-spawn-worker.js | 40 + deps/v8/test/mjsunit/d8/d8-worker.js | 156 + deps/v8/test/mjsunit/d8/enable-tracing.js | 8 + deps/v8/test/mjsunit/deserialize-reference.js | 2 +- deps/v8/test/mjsunit/dictionary-prototypes.js | 409 ++ deps/v8/test/mjsunit/es6/array-find.js | 34 + deps/v8/test/mjsunit/es6/array-findindex.js | 34 + deps/v8/test/mjsunit/es6/array-iterator-turbo.js | 2 +- .../mjsunit/es6/call-with-spread-modify-next.js | 4 +- ...puted-property-names-object-literals-methods.js | 2 - .../test/mjsunit/es6/destructuring-assignment.js | 44 +- deps/v8/test/mjsunit/es6/iteration-semantics.js | 8 +- deps/v8/test/mjsunit/es6/reflect-construct.js | 2 +- deps/v8/test/mjsunit/es6/spread-call.js | 18 +- .../mjsunit/es6/super-with-spread-modify-next.js | 4 +- deps/v8/test/mjsunit/es6/typedarray.js | 24 +- deps/v8/test/mjsunit/es8/object-entries.js | 33 +- deps/v8/test/mjsunit/es8/regress/regress-794744.js | 8 + deps/v8/test/mjsunit/global-prototypes.js | 354 ++ .../mjsunit/harmony/async-for-of-non-iterable.js | 1 - .../mjsunit/harmony/async-from-sync-iterator.js | 2 +- .../test/mjsunit/harmony/async-generators-basic.js | 2 +- .../harmony/async-generators-resume-return.js | 2 +- .../mjsunit/harmony/async-generators-return.js | 2 +- .../test/mjsunit/harmony/async-generators-yield.js | 2 +- deps/v8/test/mjsunit/harmony/bigint/as-int-n.js | 18 +- deps/v8/test/mjsunit/harmony/bigint/basics.js | 10 +- deps/v8/test/mjsunit/harmony/bigint/comparisons.js | 2 +- deps/v8/test/mjsunit/harmony/bigint/dec.js | 3 - deps/v8/test/mjsunit/harmony/bigint/exp.js | 43 + deps/v8/test/mjsunit/harmony/bigint/inc.js | 3 - deps/v8/test/mjsunit/harmony/bigint/json.js | 2 +- deps/v8/test/mjsunit/harmony/bigint/neg.js | 3 - deps/v8/test/mjsunit/harmony/bigint/not.js | 3 - deps/v8/test/mjsunit/harmony/bigint/regressions.js | 4 +- deps/v8/test/mjsunit/harmony/bigint/tonumber.js | 2 +- .../test/mjsunit/harmony/bigint/too-big-literal.js | 14 - deps/v8/test/mjsunit/harmony/bigint/turbo.js | 193 + deps/v8/test/mjsunit/harmony/for-await-of.js | 2 +- deps/v8/test/mjsunit/harmony/modules-import-15.js | 3 +- .../harmony/optional-catch-binding-breaks.js | 65 + .../test/mjsunit/harmony/optional-catch-binding.js | 39 + .../mjsunit/harmony/promise-prototype-finally.js | 10 + .../harmony/public-instance-class-fields.js | 82 +- .../mjsunit/harmony/public-static-class-fields.js | 130 +- .../test/mjsunit/harmony/regexp-named-captures.js | 123 +- .../test/mjsunit/harmony/regress/regress-6322.js | 2 - .../test/mjsunit/harmony/regress/regress-772649.js | 2 +- deps/v8/test/mjsunit/harmony/sharedarraybuffer.js | 3 - .../test/mjsunit/harmony/symbol-async-iterator.js | 2 - deps/v8/test/mjsunit/ic-lookup-on-receiver.js | 44 + deps/v8/test/mjsunit/mjsunit.status | 59 +- deps/v8/test/mjsunit/optimized-array-every.js | 520 +++ deps/v8/test/mjsunit/optimized-array-find.js | 460 +++ deps/v8/test/mjsunit/optimized-array-findindex.js | 460 +++ deps/v8/test/mjsunit/optimized-array-some.js | 502 +++ deps/v8/test/mjsunit/optimized-filter.js | 53 + deps/v8/test/mjsunit/optimized-foreach.js | 50 + deps/v8/test/mjsunit/optimized-map.js | 53 + .../regress/modules-skip-regress-797581-1.js | 5 + .../regress/modules-skip-regress-797581-2.js | 5 + .../regress/modules-skip-regress-797581-3.js | 5 + .../regress/modules-skip-regress-797581-4.js | 5 + .../regress/modules-skip-regress-797581-5.js | 6 + deps/v8/test/mjsunit/regress/regress-2646.js | 2 - deps/v8/test/mjsunit/regress/regress-370827.js | 2 +- deps/v8/test/mjsunit/regress/regress-599717.js | 2 +- deps/v8/test/mjsunit/regress/regress-791334.js | 8 + deps/v8/test/mjsunit/regress/regress-791958.js | 15 + deps/v8/test/mjsunit/regress/regress-793588.js | 13 + deps/v8/test/mjsunit/regress/regress-796427.js | 7 + deps/v8/test/mjsunit/regress/regress-797481.js | 10 + deps/v8/test/mjsunit/regress/regress-797581.js | 29 + deps/v8/test/mjsunit/regress/regress-800538.js | 6 + deps/v8/test/mjsunit/regress/regress-801171.js | 20 + deps/v8/test/mjsunit/regress/regress-801772.js | 9 + deps/v8/test/mjsunit/regress/regress-802060.js | 24 + .../test/mjsunit/regress/regress-crbug-789764.js | 15 + .../test/mjsunit/regress/regress-crbug-791245-1.js | 18 + .../test/mjsunit/regress/regress-crbug-791245-2.js | 18 + .../test/mjsunit/regress/regress-crbug-795922.js | 9 + .../test/mjsunit/regress/regress-crbug-798644.js | 21 + .../test/mjsunit/regress/regress-crbug-800077.js | 6 + .../test/mjsunit/regress/regress-crbug-800810.js | 13 + .../test/mjsunit/regress/regress-crbug-807096.js | 27 + .../test/mjsunit/regress/regress-crbug-808192.js | 32 + .../test/mjsunit/regress/regress-crbug-813427.js | 49 + deps/v8/test/mjsunit/regress/regress-v8-7245.js | 6 + .../v8/test/mjsunit/regress/wasm/regress-791810.js | 21 + .../v8/test/mjsunit/regress/wasm/regress-793551.js | 20 + .../v8/test/mjsunit/regress/wasm/regress-797846.js | 14 + .../v8/test/mjsunit/regress/wasm/regress-800756.js | 15 + .../v8/test/mjsunit/regress/wasm/regress-801850.js | 11 + .../v8/test/mjsunit/regress/wasm/regress-802244.js | 22 + .../v8/test/mjsunit/regress/wasm/regress-808980.js | 28 + deps/v8/test/mjsunit/serialize-after-execute.js | 15 + deps/v8/test/mjsunit/serialize-embedded-error.js | 2 +- deps/v8/test/mjsunit/serialize-ic.js | 2 +- deps/v8/test/mjsunit/testcfg.py | 75 +- deps/v8/test/mjsunit/wasm/errors.js | 18 +- deps/v8/test/mjsunit/wasm/grow-memory-detaching.js | 65 + deps/v8/test/mjsunit/wasm/indirect-tables.js | 101 +- deps/v8/test/mjsunit/wasm/lazy-compilation.js | 39 +- deps/v8/test/mjsunit/wasm/many-parameters.js | 9 +- deps/v8/test/mjsunit/wasm/module-memory.js | 23 + deps/v8/test/mjsunit/wasm/shared-memory.js | 39 +- deps/v8/test/mjsunit/wasm/trap-location.js | 2 +- deps/v8/test/mjsunit/wasm/wasm-module-builder.js | 25 +- deps/v8/test/mkgrokdump/mkgrokdump.cc | 9 +- deps/v8/test/mkgrokdump/testcfg.py | 60 +- deps/v8/test/mozilla/mozilla.status | 8 +- deps/v8/test/mozilla/testcfg.py | 53 +- deps/v8/test/optimize_for_size.gyp | 1 + deps/v8/test/perf.isolate | 2 +- deps/v8/test/preparser/testcfg.py | 68 +- deps/v8/test/promises-aplus/README | 29 - deps/v8/test/promises-aplus/lib/adapter.js | 41 - deps/v8/test/promises-aplus/lib/assert.js | 97 - deps/v8/test/promises-aplus/lib/global.js | 67 - deps/v8/test/promises-aplus/lib/mocha.js | 255 -- deps/v8/test/promises-aplus/lib/require.js | 50 - deps/v8/test/promises-aplus/lib/run-tests.js | 29 - deps/v8/test/promises-aplus/promises-aplus.status | 31 - deps/v8/test/promises-aplus/testcfg.py | 99 - .../fields-inner-arrow-err-contains-arguments.js | 26 + ...elds-inner-arrow-eval-err-contains-arguments.js | 33 + ...elds-inner-eval-arrow-err-contains-arguments.js | 30 + .../fields-inner-arrow-err-contains-arguments.js | 26 + ...elds-inner-arrow-eval-err-contains-arguments.js | 34 + ...elds-inner-eval-arrow-err-contains-arguments.js | 30 + deps/v8/test/test262/test262.status | 47 +- deps/v8/test/test262/testcfg.py | 277 +- deps/v8/test/unittests/BUILD.gn | 4 +- deps/v8/test/unittests/allocation-unittest.cc | 164 + .../v8/test/unittests/api/access-check-unittest.cc | 9 +- .../test/unittests/asmjs/asm-scanner-unittest.cc | 8 +- deps/v8/test/unittests/base/bits-unittest.cc | 60 +- deps/v8/test/unittests/base/logging-unittest.cc | 46 +- deps/v8/test/unittests/base/ostreams-unittest.cc | 4 +- .../unittests/base/platform/platform-unittest.cc | 116 - deps/v8/test/unittests/bigint-unittest.cc | 2 +- .../arm/instruction-selector-arm-unittest.cc | 45 +- .../arm64/instruction-selector-arm64-unittest.cc | 309 +- deps/v8/test/unittests/compiler/graph-unittest.cc | 3 +- deps/v8/test/unittests/compiler/graph-unittest.h | 3 + .../ia32/instruction-selector-ia32-unittest.cc | 11 +- .../compiler/instruction-sequence-unittest.cc | 6 +- .../unittests/compiler/int64-lowering-unittest.cc | 8 +- .../compiler/js-typed-lowering-unittest.cc | 3 +- .../compiler/linkage-tail-call-unittest.cc | 16 +- .../unittests/compiler/loop-peeling-unittest.cc | 21 +- .../compiler/machine-operator-reducer-unittest.cc | 180 +- .../mips/instruction-selector-mips-unittest.cc | 12 +- .../mips64/instruction-selector-mips64-unittest.cc | 28 +- deps/v8/test/unittests/compiler/node-test-utils.cc | 1 + deps/v8/test/unittests/compiler/node-test-utils.h | 1 + .../compiler/regalloc/move-optimizer-unittest.cc | 3 +- .../compiler/simplified-lowering-unittest.cc | 89 + .../simplified-operator-reducer-unittest.cc | 29 +- .../compiler/state-values-utils-unittest.cc | 4 +- deps/v8/test/unittests/compiler/typer-unittest.cc | 4 +- .../x64/instruction-selector-x64-unittest.cc | 23 +- deps/v8/test/unittests/counters-unittest.cc | 62 +- .../test/unittests/eh-frame-iterator-unittest.cc | 18 +- deps/v8/test/unittests/eh-frame-writer-unittest.cc | 8 +- deps/v8/test/unittests/heap/gc-tracer-unittest.cc | 121 + deps/v8/test/unittests/heap/heap-unittest.cc | 2 +- deps/v8/test/unittests/heap/marking-unittest.cc | 14 +- .../interpreter/bytecode-array-builder-unittest.cc | 19 +- .../bytecode-array-iterator-unittest.cc | 5 +- .../bytecode-array-random-iterator-unittest.cc | 29 +- .../interpreter/bytecode-node-unittest.cc | 8 +- .../bytecode-register-optimizer-unittest.cc | 9 +- .../v8/test/unittests/interpreter/bytecode-utils.h | 20 + .../interpreter/interpreter-assembler-unittest.cc | 4 +- deps/v8/test/unittests/object-unittest.cc | 4 +- .../v8/test/unittests/parser/ast-value-unittest.cc | 4 +- deps/v8/test/unittests/testcfg.py | 70 + deps/v8/test/unittests/unicode-unittest.cc | 476 +-- deps/v8/test/unittests/unittests.gyp | 4 +- deps/v8/test/unittests/unittests.isolate | 3 +- .../v8/test/unittests/value-serializer-unittest.cc | 521 ++- deps/v8/test/unittests/wasm/decoder-unittest.cc | 32 +- .../wasm/function-body-decoder-unittest.cc | 127 +- deps/v8/test/unittests/wasm/leb-helper-unittest.cc | 8 +- .../wasm/loop-assignment-analysis-unittest.cc | 6 +- .../test/unittests/wasm/module-decoder-unittest.cc | 70 +- .../unittests/wasm/streaming-decoder-unittest.cc | 70 +- .../unittests/wasm/wasm-code-manager-unittest.cc | 392 ++ deps/v8/test/unittests/wasm/wasm-heap-unittest.cc | 392 -- .../test/unittests/wasm/wasm-macro-gen-unittest.cc | 2 +- deps/v8/test/wasm-spec-tests/testcfg.py | 20 +- deps/v8/test/wasm-spec-tests/tests.tar.gz.sha1 | 2 +- deps/v8/test/webkit/date-constructor-expected.txt | 55 +- deps/v8/test/webkit/date-constructor.js | 58 +- deps/v8/test/webkit/testcfg.py | 124 +- .../binutils/Linux_ia32/binutils.tar.bz2.sha1 | 2 +- .../binutils/Linux_x64/binutils.tar.bz2.sha1 | 2 +- .../inspector_protocol/CodeGenerator.py | 55 +- .../inspector_protocol/ConvertProtocolToJSON.py | 183 + deps/v8/third_party/inspector_protocol/README.v8 | 2 +- .../lib/DispatcherBase_cpp.template | 44 +- .../lib/DispatcherBase_h.template | 3 +- .../templates/TypeBuilder_h.template | 4 - deps/v8/tools/BUILD.gn | 1 + deps/v8/tools/callstats.html | 2 + deps/v8/tools/callstats.py | 1 + deps/v8/tools/foozzie/testdata/failure_output.txt | 2 +- deps/v8/tools/foozzie/v8_foozzie.py | 34 + deps/v8/tools/foozzie/v8_suppressions.py | 65 +- deps/v8/tools/gdbinit | 2 +- deps/v8/tools/gen-postmortem-metadata.py | 4 +- deps/v8/tools/heap-stats/README.md | 15 + deps/v8/tools/heap-stats/categories.js | 167 + deps/v8/tools/heap-stats/details-selection.html | 72 + deps/v8/tools/heap-stats/details-selection.js | 211 + deps/v8/tools/heap-stats/global-timeline.html | 16 + deps/v8/tools/heap-stats/global-timeline.js | 135 + deps/v8/tools/heap-stats/index.html | 88 + deps/v8/tools/heap-stats/trace-file-reader.html | 26 + deps/v8/tools/heap-stats/trace-file-reader.js | 300 ++ deps/v8/tools/js2c.py | 12 +- deps/v8/tools/map-processor | 41 + deps/v8/tools/map-processor-driver.js | 33 + deps/v8/tools/map-processor.html | 1254 ++++++ deps/v8/tools/map-processor.js | 717 ++++ deps/v8/tools/node/backport_node.py | 126 + deps/v8/tools/node/build_gn.py | 82 + deps/v8/tools/node/fetch_deps.py | 96 + deps/v8/tools/node/node_common.py | 43 + deps/v8/tools/node/test_backport_node.py | 70 + deps/v8/tools/node/test_update_node.py | 120 + .../v8/tools/node/testdata/node/deps/v8/.gitignore | 7 + .../tools/node/testdata/node/deps/v8/baz/delete_me | 1 + .../v8/tools/node/testdata/node/deps/v8/baz/v8_foo | 1 + deps/v8/tools/node/testdata/node/deps/v8/delete_me | 1 + .../testdata/node/deps/v8/include/v8-version.h | 20 + deps/v8/tools/node/testdata/node/deps/v8/v8_foo | 1 + deps/v8/tools/node/testdata/v8/.gitignore | 4 + .../testdata/v8/base/trace_event/common/common | 0 deps/v8/tools/node/testdata/v8/baz/v8_foo | 1 + deps/v8/tools/node/testdata/v8/baz/v8_new | 1 + deps/v8/tools/node/testdata/v8/new/v8_new | 1 + deps/v8/tools/node/testdata/v8/v8_foo | 1 + deps/v8/tools/node/testdata/v8/v8_new | 1 + deps/v8/tools/node/update_node.py | 167 + deps/v8/tools/parse-processor | 41 + deps/v8/tools/parse-processor-driver.js | 33 + deps/v8/tools/parse-processor.html | 337 ++ deps/v8/tools/parse-processor.js | 918 +++++ deps/v8/tools/perf-compare.py | 1 - deps/v8/tools/perf-to-html.py | 1 - deps/v8/tools/predictable_wrapper.py | 66 + deps/v8/tools/presubmit.py | 14 +- deps/v8/tools/process-heap-prof.py | 120 - deps/v8/tools/release/backport_node.py | 119 - deps/v8/tools/release/test_backport_node.py | 71 - deps/v8/tools/release/test_update_node.py | 119 - .../tools/release/testdata/node/deps/v8/.gitignore | 7 - .../release/testdata/node/deps/v8/baz/delete_me | 1 - .../tools/release/testdata/node/deps/v8/baz/v8_foo | 1 - .../tools/release/testdata/node/deps/v8/delete_me | 1 - .../testdata/node/deps/v8/include/v8-version.h | 20 - deps/v8/tools/release/testdata/node/deps/v8/v8_foo | 1 - deps/v8/tools/release/testdata/v8/.gitignore | 4 - .../testdata/v8/base/trace_event/common/common | 0 deps/v8/tools/release/testdata/v8/baz/v8_foo | 1 - deps/v8/tools/release/testdata/v8/baz/v8_new | 1 - deps/v8/tools/release/testdata/v8/new/v8_new | 1 - deps/v8/tools/release/testdata/v8/v8_foo | 1 - deps/v8/tools/release/testdata/v8/v8_new | 1 - deps/v8/tools/run-num-fuzzer.isolate | 1 + deps/v8/tools/run_perf.py | 33 +- deps/v8/tools/testrunner/PRESUBMIT.py | 8 + deps/v8/tools/testrunner/base_runner.py | 141 +- deps/v8/tools/testrunner/deopt_fuzzer.py | 75 +- deps/v8/tools/testrunner/gc_fuzzer.py | 113 +- deps/v8/tools/testrunner/local/command.py | 171 + deps/v8/tools/testrunner/local/commands.py | 152 - deps/v8/tools/testrunner/local/execution.py | 275 +- deps/v8/tools/testrunner/local/junit_output.py | 9 +- deps/v8/tools/testrunner/local/perfdata.py | 17 +- deps/v8/tools/testrunner/local/pool.py | 22 +- deps/v8/tools/testrunner/local/progress.py | 185 +- deps/v8/tools/testrunner/local/statusfile.py | 79 +- deps/v8/tools/testrunner/local/testsuite.py | 328 +- .../tools/testrunner/local/testsuite_unittest.py | 54 +- deps/v8/tools/testrunner/local/utils.py | 2 +- deps/v8/tools/testrunner/local/variants.py | 36 +- deps/v8/tools/testrunner/local/verbose.py | 57 +- deps/v8/tools/testrunner/objects/context.py | 6 +- deps/v8/tools/testrunner/objects/output.py | 3 +- deps/v8/tools/testrunner/objects/predictable.py | 57 + deps/v8/tools/testrunner/objects/testcase.py | 271 +- deps/v8/tools/testrunner/outproc/__init__.py | 3 + deps/v8/tools/testrunner/outproc/base.py | 166 + deps/v8/tools/testrunner/outproc/message.py | 56 + deps/v8/tools/testrunner/outproc/mkgrokdump.py | 31 + deps/v8/tools/testrunner/outproc/mozilla.py | 33 + deps/v8/tools/testrunner/outproc/test262.py | 54 + deps/v8/tools/testrunner/outproc/webkit.py | 18 + deps/v8/tools/testrunner/standard_runner.py | 250 +- deps/v8/tools/testrunner/testproc/__init__.py | 3 + deps/v8/tools/testrunner/testproc/base.py | 207 + deps/v8/tools/testrunner/testproc/execution.py | 92 + deps/v8/tools/testrunner/testproc/filter.py | 83 + deps/v8/tools/testrunner/testproc/loader.py | 27 + deps/v8/tools/testrunner/testproc/progress.py | 385 ++ deps/v8/tools/testrunner/testproc/rerun.py | 59 + deps/v8/tools/testrunner/testproc/result.py | 97 + deps/v8/tools/testrunner/testproc/shard.py | 30 + deps/v8/tools/testrunner/testproc/variant.py | 68 + deps/v8/tools/turbolizer/code-view.js | 2 - deps/v8/tools/turbolizer/graph-view.js | 32 +- deps/v8/tools/turbolizer/index.html | 16 +- deps/v8/tools/turbolizer/turbo-visualizer.css | 147 +- deps/v8/tools/turbolizer/turbo-visualizer.js | 255 +- deps/v8/tools/turbolizer/view.js | 12 - deps/v8/tools/unittests/PRESUBMIT.py | 9 + .../v8/tools/unittests/predictable_wrapper_test.py | 57 + deps/v8/tools/unittests/run_perf_test.py | 40 +- deps/v8/tools/unittests/run_tests_test.py | 667 ++++ .../unittests/testdata/expected_test_results1.json | 107 + .../unittests/testdata/expected_test_results2.json | 74 + .../tools/unittests/testdata/predictable_mocked.py | 28 + .../unittests/testdata/testroot1/d8_mocked.py | 16 + .../testdata/testroot1/test/sweet/sweet.status | 35 + .../testdata/testroot1/test/sweet/testcfg.py | 31 + .../testdata/testroot1/v8_build_config.json | 18 + .../unittests/testdata/testroot2/d8_mocked.py | 29 + .../testdata/testroot2/test/sweet/sweet.status | 6 + .../testdata/testroot2/test/sweet/testcfg.py | 31 + .../testdata/testroot2/v8_build_config.json | 18 + deps/v8/tools/v8-rolls.sh | 120 - deps/v8/tools/v8heapconst.py | 370 +- deps/v8/tools/wasm/update-wasm-spec-tests.sh | 29 +- deps/v8/tools/whitespace.txt | 7 +- 1308 files changed, 73587 insertions(+), 45860 deletions(-) create mode 100644 deps/v8/infra/config/PRESUBMIT.py create mode 100644 deps/v8/src/base/page-allocator.cc create mode 100644 deps/v8/src/base/page-allocator.h create mode 100644 deps/v8/src/heap/stress-marking-observer.cc create mode 100644 deps/v8/src/heap/stress-marking-observer.h create mode 100644 deps/v8/src/heap/stress-scavenge-observer.cc create mode 100644 deps/v8/src/heap/stress-scavenge-observer.h create mode 100644 deps/v8/src/inspector/js_protocol.pdl delete mode 100644 deps/v8/src/js/proxy.js delete mode 100644 deps/v8/src/js/v8natives.js create mode 100644 deps/v8/src/objects/data-handler-inl.h create mode 100644 deps/v8/src/objects/data-handler.h create mode 100644 deps/v8/src/objects/fixed-array-inl.h create mode 100644 deps/v8/src/objects/fixed-array.h create mode 100644 deps/v8/src/objects/js-collection-inl.h create mode 100644 deps/v8/src/objects/js-collection.h create mode 100644 deps/v8/src/simulator-base.cc create mode 100644 deps/v8/src/simulator-base.h create mode 100644 deps/v8/src/third_party/utf8-decoder/LICENSE create mode 100644 deps/v8/src/third_party/utf8-decoder/README.v8 create mode 100644 deps/v8/src/third_party/utf8-decoder/utf8-decoder.h create mode 100644 deps/v8/src/vector-slot-pair.cc create mode 100644 deps/v8/src/vector-slot-pair.h delete mode 100644 deps/v8/src/wasm/baseline/arm/liftoff-assembler-arm-defs.h delete mode 100644 deps/v8/src/wasm/baseline/arm64/liftoff-assembler-arm64-defs.h delete mode 100644 deps/v8/src/wasm/baseline/ia32/liftoff-assembler-ia32-defs.h create mode 100644 deps/v8/src/wasm/baseline/liftoff-assembler-defs.h create mode 100644 deps/v8/src/wasm/baseline/liftoff-register.h delete mode 100644 deps/v8/src/wasm/baseline/mips/liftoff-assembler-mips-defs.h delete mode 100644 deps/v8/src/wasm/baseline/mips64/liftoff-assembler-mips64-defs.h delete mode 100644 deps/v8/src/wasm/baseline/ppc/liftoff-assembler-ppc-defs.h delete mode 100644 deps/v8/src/wasm/baseline/s390/liftoff-assembler-s390-defs.h delete mode 100644 deps/v8/src/wasm/baseline/x64/liftoff-assembler-x64-defs.h create mode 100644 deps/v8/src/wasm/wasm-code-manager.cc create mode 100644 deps/v8/src/wasm/wasm-code-manager.h create mode 100644 deps/v8/src/wasm/wasm-constants.h create mode 100644 deps/v8/src/wasm/wasm-engine.cc create mode 100644 deps/v8/src/wasm/wasm-engine.h delete mode 100644 deps/v8/src/wasm/wasm-heap.cc delete mode 100644 deps/v8/src/wasm/wasm-heap.h create mode 100644 deps/v8/test/cctest/compiler/test-run-retpoline.cc create mode 100644 deps/v8/test/cctest/compiler/test-run-tail-calls.cc create mode 100644 deps/v8/test/cctest/heap/test-embedder-tracing.cc create mode 100644 deps/v8/test/cctest/interpreter/bytecode_expectations/StaticClassFields.golden create mode 100644 deps/v8/test/d8_default.gyp create mode 100644 deps/v8/test/d8_default.isolate create mode 100644 deps/v8/test/fuzzer/multi-return.cc create mode 100644 deps/v8/test/fuzzer/multi_return/README.md create mode 100644 deps/v8/test/inspector/debugger/async-chains-expected.txt create mode 100644 deps/v8/test/inspector/debugger/async-chains.js create mode 100644 deps/v8/test/inspector/debugger/set-breakpoint-ignore-hint-when-no-location-expected.txt create mode 100644 deps/v8/test/inspector/debugger/set-breakpoint-ignore-hint-when-no-location.js create mode 100644 deps/v8/test/inspector/debugger/step-into-external-async-task-same-context-expected.txt create mode 100644 deps/v8/test/inspector/debugger/step-into-external-async-task-same-context.js create mode 100644 deps/v8/test/inspector/runtime/console-time-repeat-expected.txt create mode 100644 deps/v8/test/inspector/runtime/console-time-repeat.js create mode 100644 deps/v8/test/inspector/runtime/runtime-evaluate-null-property-expected.txt create mode 100644 deps/v8/test/inspector/runtime/runtime-evaluate-null-property.js create mode 100644 deps/v8/test/js-perf-test/Array/find-index.js create mode 100644 deps/v8/test/js-perf-test/Array/find.js create mode 100644 deps/v8/test/js-perf-test/Array/for-each.js create mode 100644 deps/v8/test/js-perf-test/Array/of.js create mode 100644 deps/v8/test/js-perf-test/Strings/string-indexof.js create mode 100644 deps/v8/test/js-perf-test/TypedArrays/slice-nospecies.js create mode 100644 deps/v8/test/js-perf-test/TypedArrays/subarray-nospecies.js create mode 100644 deps/v8/test/message/fail/array-binding-pattern-await1.js create mode 100644 deps/v8/test/message/fail/array-binding-pattern-await1.out create mode 100644 deps/v8/test/message/fail/object-binding-pattern-await1.js create mode 100644 deps/v8/test/message/fail/object-binding-pattern-await1.out create mode 100644 deps/v8/test/message/object-binding-pattern-await-computed-name.js create mode 100644 deps/v8/test/message/object-binding-pattern-await-computed-name.out create mode 100644 deps/v8/test/message/wasm-trace-memory-liftoff.js create mode 100644 deps/v8/test/message/wasm-trace-memory-liftoff.out create mode 100644 deps/v8/test/mjsunit/compiler/array-multiple-receiver-maps.js create mode 100644 deps/v8/test/mjsunit/compiler/deopt-array-builtins.js create mode 100644 deps/v8/test/mjsunit/compiler/deopt-array-push.js create mode 100644 deps/v8/test/mjsunit/compiler/materialize-dictionary-properties.js create mode 100644 deps/v8/test/mjsunit/compiler/materialize-mutable-heap-number.js create mode 100644 deps/v8/test/mjsunit/compiler/new-cons-string.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-786521.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-793863.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-796041.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-797596.js create mode 100644 deps/v8/test/mjsunit/compiler/regress-801097.js create mode 100644 deps/v8/test/mjsunit/compiler/varargs.js delete mode 100644 deps/v8/test/mjsunit/d8-os.js delete mode 100644 deps/v8/test/mjsunit/d8-performance-now.js delete mode 100644 deps/v8/test/mjsunit/d8-worker-sharedarraybuffer.js delete mode 100644 deps/v8/test/mjsunit/d8-worker-spawn-worker.js delete mode 100644 deps/v8/test/mjsunit/d8-worker.js create mode 100644 deps/v8/test/mjsunit/d8/.gitignore create mode 100644 deps/v8/test/mjsunit/d8/d8-os.js create mode 100644 deps/v8/test/mjsunit/d8/d8-performance-now.js create mode 100644 deps/v8/test/mjsunit/d8/d8-worker-sharedarraybuffer.js create mode 100644 deps/v8/test/mjsunit/d8/d8-worker-spawn-worker.js create mode 100644 deps/v8/test/mjsunit/d8/d8-worker.js create mode 100644 deps/v8/test/mjsunit/d8/enable-tracing.js create mode 100644 deps/v8/test/mjsunit/dictionary-prototypes.js create mode 100644 deps/v8/test/mjsunit/es8/regress/regress-794744.js create mode 100644 deps/v8/test/mjsunit/global-prototypes.js create mode 100644 deps/v8/test/mjsunit/harmony/bigint/exp.js delete mode 100644 deps/v8/test/mjsunit/harmony/bigint/too-big-literal.js create mode 100644 deps/v8/test/mjsunit/harmony/bigint/turbo.js create mode 100644 deps/v8/test/mjsunit/harmony/optional-catch-binding-breaks.js create mode 100644 deps/v8/test/mjsunit/harmony/optional-catch-binding.js create mode 100644 deps/v8/test/mjsunit/ic-lookup-on-receiver.js create mode 100644 deps/v8/test/mjsunit/optimized-array-every.js create mode 100644 deps/v8/test/mjsunit/optimized-array-find.js create mode 100644 deps/v8/test/mjsunit/optimized-array-findindex.js create mode 100644 deps/v8/test/mjsunit/optimized-array-some.js create mode 100644 deps/v8/test/mjsunit/regress/modules-skip-regress-797581-1.js create mode 100644 deps/v8/test/mjsunit/regress/modules-skip-regress-797581-2.js create mode 100644 deps/v8/test/mjsunit/regress/modules-skip-regress-797581-3.js create mode 100644 deps/v8/test/mjsunit/regress/modules-skip-regress-797581-4.js create mode 100644 deps/v8/test/mjsunit/regress/modules-skip-regress-797581-5.js create mode 100644 deps/v8/test/mjsunit/regress/regress-791334.js create mode 100644 deps/v8/test/mjsunit/regress/regress-791958.js create mode 100644 deps/v8/test/mjsunit/regress/regress-793588.js create mode 100644 deps/v8/test/mjsunit/regress/regress-796427.js create mode 100644 deps/v8/test/mjsunit/regress/regress-797481.js create mode 100644 deps/v8/test/mjsunit/regress/regress-797581.js create mode 100644 deps/v8/test/mjsunit/regress/regress-800538.js create mode 100644 deps/v8/test/mjsunit/regress/regress-801171.js create mode 100644 deps/v8/test/mjsunit/regress/regress-801772.js create mode 100644 deps/v8/test/mjsunit/regress/regress-802060.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-789764.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-791245-1.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-791245-2.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-795922.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-798644.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-800077.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-800810.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-807096.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-808192.js create mode 100644 deps/v8/test/mjsunit/regress/regress-crbug-813427.js create mode 100644 deps/v8/test/mjsunit/regress/regress-v8-7245.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-791810.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-793551.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-797846.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-800756.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-801850.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-802244.js create mode 100644 deps/v8/test/mjsunit/regress/wasm/regress-808980.js create mode 100644 deps/v8/test/mjsunit/serialize-after-execute.js create mode 100644 deps/v8/test/mjsunit/wasm/grow-memory-detaching.js delete mode 100644 deps/v8/test/promises-aplus/README delete mode 100644 deps/v8/test/promises-aplus/lib/adapter.js delete mode 100644 deps/v8/test/promises-aplus/lib/assert.js delete mode 100644 deps/v8/test/promises-aplus/lib/global.js delete mode 100644 deps/v8/test/promises-aplus/lib/mocha.js delete mode 100644 deps/v8/test/promises-aplus/lib/require.js delete mode 100644 deps/v8/test/promises-aplus/lib/run-tests.js delete mode 100644 deps/v8/test/promises-aplus/promises-aplus.status delete mode 100644 deps/v8/test/promises-aplus/testcfg.py create mode 100644 deps/v8/test/test262/local-tests/test/language/expressions/class/fields-inner-arrow-err-contains-arguments.js create mode 100644 deps/v8/test/test262/local-tests/test/language/expressions/class/fields-inner-arrow-eval-err-contains-arguments.js create mode 100644 deps/v8/test/test262/local-tests/test/language/expressions/class/fields-inner-eval-arrow-err-contains-arguments.js create mode 100644 deps/v8/test/test262/local-tests/test/language/statements/class/fields-inner-arrow-err-contains-arguments.js create mode 100644 deps/v8/test/test262/local-tests/test/language/statements/class/fields-inner-arrow-eval-err-contains-arguments.js create mode 100644 deps/v8/test/test262/local-tests/test/language/statements/class/fields-inner-eval-arrow-err-contains-arguments.js create mode 100644 deps/v8/test/unittests/allocation-unittest.cc create mode 100644 deps/v8/test/unittests/compiler/simplified-lowering-unittest.cc create mode 100644 deps/v8/test/unittests/testcfg.py create mode 100644 deps/v8/test/unittests/wasm/wasm-code-manager-unittest.cc delete mode 100644 deps/v8/test/unittests/wasm/wasm-heap-unittest.cc create mode 100644 deps/v8/third_party/inspector_protocol/ConvertProtocolToJSON.py create mode 100644 deps/v8/tools/heap-stats/README.md create mode 100644 deps/v8/tools/heap-stats/categories.js create mode 100644 deps/v8/tools/heap-stats/details-selection.html create mode 100644 deps/v8/tools/heap-stats/details-selection.js create mode 100644 deps/v8/tools/heap-stats/global-timeline.html create mode 100644 deps/v8/tools/heap-stats/global-timeline.js create mode 100644 deps/v8/tools/heap-stats/index.html create mode 100644 deps/v8/tools/heap-stats/trace-file-reader.html create mode 100644 deps/v8/tools/heap-stats/trace-file-reader.js create mode 100755 deps/v8/tools/map-processor create mode 100644 deps/v8/tools/map-processor-driver.js create mode 100644 deps/v8/tools/map-processor.html create mode 100644 deps/v8/tools/map-processor.js create mode 100755 deps/v8/tools/node/backport_node.py create mode 100755 deps/v8/tools/node/build_gn.py create mode 100755 deps/v8/tools/node/fetch_deps.py create mode 100755 deps/v8/tools/node/node_common.py create mode 100755 deps/v8/tools/node/test_backport_node.py create mode 100755 deps/v8/tools/node/test_update_node.py create mode 100644 deps/v8/tools/node/testdata/node/deps/v8/.gitignore create mode 100644 deps/v8/tools/node/testdata/node/deps/v8/baz/delete_me create mode 100644 deps/v8/tools/node/testdata/node/deps/v8/baz/v8_foo create mode 100644 deps/v8/tools/node/testdata/node/deps/v8/delete_me create mode 100644 deps/v8/tools/node/testdata/node/deps/v8/include/v8-version.h create mode 100644 deps/v8/tools/node/testdata/node/deps/v8/v8_foo create mode 100644 deps/v8/tools/node/testdata/v8/.gitignore create mode 100644 deps/v8/tools/node/testdata/v8/base/trace_event/common/common create mode 100644 deps/v8/tools/node/testdata/v8/baz/v8_foo create mode 100644 deps/v8/tools/node/testdata/v8/baz/v8_new create mode 100644 deps/v8/tools/node/testdata/v8/new/v8_new create mode 100644 deps/v8/tools/node/testdata/v8/v8_foo create mode 100644 deps/v8/tools/node/testdata/v8/v8_new create mode 100755 deps/v8/tools/node/update_node.py create mode 100755 deps/v8/tools/parse-processor create mode 100644 deps/v8/tools/parse-processor-driver.js create mode 100644 deps/v8/tools/parse-processor.html create mode 100644 deps/v8/tools/parse-processor.js create mode 100644 deps/v8/tools/predictable_wrapper.py delete mode 100755 deps/v8/tools/process-heap-prof.py delete mode 100755 deps/v8/tools/release/backport_node.py delete mode 100755 deps/v8/tools/release/test_backport_node.py delete mode 100755 deps/v8/tools/release/test_update_node.py delete mode 100644 deps/v8/tools/release/testdata/node/deps/v8/.gitignore delete mode 100644 deps/v8/tools/release/testdata/node/deps/v8/baz/delete_me delete mode 100644 deps/v8/tools/release/testdata/node/deps/v8/baz/v8_foo delete mode 100644 deps/v8/tools/release/testdata/node/deps/v8/delete_me delete mode 100644 deps/v8/tools/release/testdata/node/deps/v8/include/v8-version.h delete mode 100644 deps/v8/tools/release/testdata/node/deps/v8/v8_foo delete mode 100644 deps/v8/tools/release/testdata/v8/.gitignore delete mode 100644 deps/v8/tools/release/testdata/v8/base/trace_event/common/common delete mode 100644 deps/v8/tools/release/testdata/v8/baz/v8_foo delete mode 100644 deps/v8/tools/release/testdata/v8/baz/v8_new delete mode 100644 deps/v8/tools/release/testdata/v8/new/v8_new delete mode 100644 deps/v8/tools/release/testdata/v8/v8_foo delete mode 100644 deps/v8/tools/release/testdata/v8/v8_new create mode 100644 deps/v8/tools/testrunner/PRESUBMIT.py create mode 100644 deps/v8/tools/testrunner/local/command.py delete mode 100644 deps/v8/tools/testrunner/local/commands.py create mode 100644 deps/v8/tools/testrunner/objects/predictable.py create mode 100644 deps/v8/tools/testrunner/outproc/__init__.py create mode 100644 deps/v8/tools/testrunner/outproc/base.py create mode 100644 deps/v8/tools/testrunner/outproc/message.py create mode 100644 deps/v8/tools/testrunner/outproc/mkgrokdump.py create mode 100644 deps/v8/tools/testrunner/outproc/mozilla.py create mode 100644 deps/v8/tools/testrunner/outproc/test262.py create mode 100644 deps/v8/tools/testrunner/outproc/webkit.py create mode 100644 deps/v8/tools/testrunner/testproc/__init__.py create mode 100644 deps/v8/tools/testrunner/testproc/base.py create mode 100644 deps/v8/tools/testrunner/testproc/execution.py create mode 100644 deps/v8/tools/testrunner/testproc/filter.py create mode 100644 deps/v8/tools/testrunner/testproc/loader.py create mode 100644 deps/v8/tools/testrunner/testproc/progress.py create mode 100644 deps/v8/tools/testrunner/testproc/rerun.py create mode 100644 deps/v8/tools/testrunner/testproc/result.py create mode 100644 deps/v8/tools/testrunner/testproc/shard.py create mode 100644 deps/v8/tools/testrunner/testproc/variant.py create mode 100644 deps/v8/tools/unittests/PRESUBMIT.py create mode 100755 deps/v8/tools/unittests/predictable_wrapper_test.py mode change 100644 => 100755 deps/v8/tools/unittests/run_perf_test.py create mode 100755 deps/v8/tools/unittests/run_tests_test.py create mode 100644 deps/v8/tools/unittests/testdata/expected_test_results1.json create mode 100644 deps/v8/tools/unittests/testdata/expected_test_results2.json create mode 100644 deps/v8/tools/unittests/testdata/predictable_mocked.py create mode 100644 deps/v8/tools/unittests/testdata/testroot1/d8_mocked.py create mode 100644 deps/v8/tools/unittests/testdata/testroot1/test/sweet/sweet.status create mode 100644 deps/v8/tools/unittests/testdata/testroot1/test/sweet/testcfg.py create mode 100644 deps/v8/tools/unittests/testdata/testroot1/v8_build_config.json create mode 100644 deps/v8/tools/unittests/testdata/testroot2/d8_mocked.py create mode 100644 deps/v8/tools/unittests/testdata/testroot2/test/sweet/sweet.status create mode 100644 deps/v8/tools/unittests/testdata/testroot2/test/sweet/testcfg.py create mode 100644 deps/v8/tools/unittests/testdata/testroot2/v8_build_config.json delete mode 100755 deps/v8/tools/v8-rolls.sh diff --git a/deps/v8/.gitignore b/deps/v8/.gitignore index 85ff179226..f07fc1cb62 100644 --- a/deps/v8/.gitignore +++ b/deps/v8/.gitignore @@ -50,9 +50,6 @@ /test/fuzzer/wasm_corpus /test/fuzzer/wasm_corpus.tar.gz /test/mozilla/data -/test/promises-aplus/promises-tests -/test/promises-aplus/promises-tests.tar.gz -/test/promises-aplus/sinon /test/test262/data /test/test262/data.tar /test/test262/harness @@ -94,6 +91,7 @@ TAGS bsuite compile_commands.json d8 +!/test/mjsunit/d8 d8_g gccauses gcsuspects diff --git a/deps/v8/AUTHORS b/deps/v8/AUTHORS index 08391a5566..b2b01df888 100644 --- a/deps/v8/AUTHORS +++ b/deps/v8/AUTHORS @@ -96,6 +96,7 @@ Luis Reis Luke Zarko Maciej Małecki Marcin Cieślak +Marcin Wiącek Mateusz Czeladka Mathias Bynens Matt Hanselman @@ -106,6 +107,7 @@ Michael Smith Michaël Zasso Mike Gilbert Mike Pennisi +Mikhail Gusarov Milton Chiang Myeong-bo Shim Nicolas Antonius Ernst Leopold Maria Kaiser @@ -118,6 +120,7 @@ Peter Rybin Peter Varga Peter Wong Paul Lind +Qingyan Li Qiuyi Zhang Rafal Krypa Refael Ackermann @@ -133,6 +136,8 @@ Sanjoy Das Seo Sanghyeon Stefan Penner Sylvestre Ledru +Taketoshi Aono +Tiancheng "Timothy" Gu Tobias Burnus Victor Costan Vlad Burlik diff --git a/deps/v8/BUILD.gn b/deps/v8/BUILD.gn index 8492cb5f62..4970765972 100644 --- a/deps/v8/BUILD.gn +++ b/deps/v8/BUILD.gn @@ -89,6 +89,9 @@ declare_args() { # Sets -dV8_CONCURRENT_MARKING v8_enable_concurrent_marking = true + # Enables various testing features. + v8_enable_test_features = "" + # Build the snapshot with unwinding information for perf. # Sets -dV8_USE_SNAPSHOT_WITH_UNWINDING_INFO. v8_perf_prof_unwinding_info = false @@ -133,8 +136,6 @@ declare_args() { # while rolling in a new version of V8. v8_check_microtasks_scopes_consistency = "" - v8_monolithic = false - # Enable mitigations for executing untrusted code. v8_untrusted_code_mitigations = true } @@ -152,6 +153,9 @@ if (v8_enable_disassembler == "") { if (v8_enable_trace_maps == "") { v8_enable_trace_maps = is_debug } +if (v8_enable_test_features == "") { + v8_enable_test_features = is_debug || dcheck_always_on +} if (v8_enable_v8_checks == "") { v8_enable_v8_checks = is_debug } @@ -278,6 +282,10 @@ config("features") { if (v8_enable_trace_feedback_updates) { defines += [ "V8_TRACE_FEEDBACK_UPDATES" ] } + if (v8_enable_test_features) { + defines += [ "V8_ENABLE_ALLOCATION_TIMEOUT" ] + defines += [ "V8_ENABLE_FORCE_SLOW_PATH" ] + } if (v8_enable_v8_checks) { defines += [ "V8_ENABLE_CHECKS" ] } @@ -511,6 +519,12 @@ config("toolchain") { # TODO(hans): Remove once http://crbug.com/428099 is resolved. "-Winconsistent-missing-override", ] + + if (v8_current_cpu != "mips" && v8_current_cpu != "mipsel") { + # We exclude MIPS because the IsMipsArchVariant macro causes trouble. + cflags += [ "-Wunreachable-code" ] + } + if (v8_current_cpu == "x64" || v8_current_cpu == "arm64" || v8_current_cpu == "mips64el") { cflags += [ "-Wshorten-64-to-32" ] @@ -575,12 +589,10 @@ action("js2c") { "src/js/macros.py", "src/messages.h", "src/js/prologue.js", - "src/js/v8natives.js", "src/js/array.js", "src/js/typedarray.js", "src/js/messages.js", "src/js/spread.js", - "src/js/proxy.js", "src/debug/mirrors.js", "src/debug/debug.js", "src/debug/liveedit.js", @@ -755,6 +767,10 @@ action("postmortem-metadata") { "src/objects-inl.h", "src/objects/code-inl.h", "src/objects/code.h", + "src/objects/data-handler.h", + "src/objects/data-handler-inl.h", + "src/objects/fixed-array-inl.h", + "src/objects/fixed-array.h", "src/objects/js-array-inl.h", "src/objects/js-array.h", "src/objects/js-regexp-inl.h", @@ -1680,6 +1696,10 @@ v8_source_set("v8_base") { "src/heap/spaces.h", "src/heap/store-buffer.cc", "src/heap/store-buffer.h", + "src/heap/stress-marking-observer.cc", + "src/heap/stress-marking-observer.h", + "src/heap/stress-scavenge-observer.cc", + "src/heap/stress-scavenge-observer.h", "src/heap/sweeper.cc", "src/heap/sweeper.h", "src/heap/worklist.h", @@ -1803,6 +1823,8 @@ v8_source_set("v8_base") { "src/objects/debug-objects.h", "src/objects/descriptor-array.h", "src/objects/dictionary.h", + "src/objects/fixed-array-inl.h", + "src/objects/fixed-array.h", "src/objects/frame-array-inl.h", "src/objects/frame-array.h", "src/objects/hash-table-inl.h", @@ -1811,6 +1833,8 @@ v8_source_set("v8_base") { "src/objects/intl-objects.h", "src/objects/js-array-inl.h", "src/objects/js-array.h", + "src/objects/js-collection-inl.h", + "src/objects/js-collection.h", "src/objects/js-regexp-inl.h", "src/objects/js-regexp.h", "src/objects/literal-objects-inl.h", @@ -1974,6 +1998,8 @@ v8_source_set("v8_base") { "src/safepoint-table.h", "src/setup-isolate.h", "src/signature.h", + "src/simulator-base.cc", + "src/simulator-base.h", "src/simulator.h", "src/snapshot/builtin-deserializer-allocator.cc", "src/snapshot/builtin-deserializer-allocator.h", @@ -2032,6 +2058,7 @@ v8_source_set("v8_base") { "src/string-stream.h", "src/strtod.cc", "src/strtod.h", + "src/third_party/utf8-decoder/utf8-decoder.h", "src/tracing/trace-event.cc", "src/tracing/trace-event.h", "src/tracing/traced-value.cc", @@ -2066,6 +2093,8 @@ v8_source_set("v8_base") { "src/v8threads.h", "src/value-serializer.cc", "src/value-serializer.h", + "src/vector-slot-pair.cc", + "src/vector-slot-pair.h", "src/vector.h", "src/version.cc", "src/version.h", @@ -2073,9 +2102,11 @@ v8_source_set("v8_base") { "src/visitors.h", "src/vm-state-inl.h", "src/vm-state.h", + "src/wasm/baseline/liftoff-assembler-defs.h", "src/wasm/baseline/liftoff-assembler.cc", "src/wasm/baseline/liftoff-assembler.h", "src/wasm/baseline/liftoff-compiler.cc", + "src/wasm/baseline/liftoff-register.h", "src/wasm/compilation-manager.cc", "src/wasm/compilation-manager.h", "src/wasm/decoder.h", @@ -2097,15 +2128,18 @@ v8_source_set("v8_base") { "src/wasm/streaming-decoder.h", "src/wasm/wasm-api.cc", "src/wasm/wasm-api.h", + "src/wasm/wasm-code-manager.cc", + "src/wasm/wasm-code-manager.h", "src/wasm/wasm-code-specialization.cc", "src/wasm/wasm-code-specialization.h", "src/wasm/wasm-code-wrapper.cc", "src/wasm/wasm-code-wrapper.h", + "src/wasm/wasm-constants.h", "src/wasm/wasm-debug.cc", + "src/wasm/wasm-engine.cc", + "src/wasm/wasm-engine.h", "src/wasm/wasm-external-refs.cc", "src/wasm/wasm-external-refs.h", - "src/wasm/wasm-heap.cc", - "src/wasm/wasm-heap.h", "src/wasm/wasm-interpreter.cc", "src/wasm/wasm-interpreter.h", "src/wasm/wasm-js.cc", @@ -2184,7 +2218,6 @@ v8_source_set("v8_base") { "src/ia32/sse-instr.h", "src/regexp/ia32/regexp-macro-assembler-ia32.cc", "src/regexp/ia32/regexp-macro-assembler-ia32.h", - "src/wasm/baseline/ia32/liftoff-assembler-ia32-defs.h", "src/wasm/baseline/ia32/liftoff-assembler-ia32.h", ] } else if (v8_current_cpu == "x64") { @@ -2199,7 +2232,6 @@ v8_source_set("v8_base") { "src/regexp/x64/regexp-macro-assembler-x64.cc", "src/regexp/x64/regexp-macro-assembler-x64.h", "src/third_party/valgrind/valgrind.h", - "src/wasm/baseline/x64/liftoff-assembler-x64-defs.h", "src/wasm/baseline/x64/liftoff-assembler-x64.h", "src/x64/assembler-x64-inl.h", "src/x64/assembler-x64.cc", @@ -2253,7 +2285,6 @@ v8_source_set("v8_base") { "src/debug/arm/debug-arm.cc", "src/regexp/arm/regexp-macro-assembler-arm.cc", "src/regexp/arm/regexp-macro-assembler-arm.h", - "src/wasm/baseline/arm/liftoff-assembler-arm-defs.h", "src/wasm/baseline/arm/liftoff-assembler-arm.h", ] } else if (v8_current_cpu == "arm64") { @@ -2299,7 +2330,6 @@ v8_source_set("v8_base") { "src/debug/arm64/debug-arm64.cc", "src/regexp/arm64/regexp-macro-assembler-arm64.cc", "src/regexp/arm64/regexp-macro-assembler-arm64.h", - "src/wasm/baseline/arm64/liftoff-assembler-arm64-defs.h", "src/wasm/baseline/arm64/liftoff-assembler-arm64.h", ] if (use_jumbo_build) { @@ -2336,7 +2366,6 @@ v8_source_set("v8_base") { "src/mips/simulator-mips.h", "src/regexp/mips/regexp-macro-assembler-mips.cc", "src/regexp/mips/regexp-macro-assembler-mips.h", - "src/wasm/baseline/mips/liftoff-assembler-mips-defs.h", "src/wasm/baseline/mips/liftoff-assembler-mips.h", ] } else if (v8_current_cpu == "mips64" || v8_current_cpu == "mips64el") { @@ -2366,7 +2395,6 @@ v8_source_set("v8_base") { "src/mips64/simulator-mips64.h", "src/regexp/mips64/regexp-macro-assembler-mips64.cc", "src/regexp/mips64/regexp-macro-assembler-mips64.h", - "src/wasm/baseline/mips64/liftoff-assembler-mips64-defs.h", "src/wasm/baseline/mips64/liftoff-assembler-mips64.h", ] } else if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") { @@ -2396,7 +2424,6 @@ v8_source_set("v8_base") { "src/ppc/simulator-ppc.h", "src/regexp/ppc/regexp-macro-assembler-ppc.cc", "src/regexp/ppc/regexp-macro-assembler-ppc.h", - "src/wasm/baseline/ppc/liftoff-assembler-ppc-defs.h", "src/wasm/baseline/ppc/liftoff-assembler-ppc.h", ] } else if (v8_current_cpu == "s390" || v8_current_cpu == "s390x") { @@ -2426,7 +2453,6 @@ v8_source_set("v8_base") { "src/s390/macro-assembler-s390.h", "src/s390/simulator-s390.cc", "src/s390/simulator-s390.h", - "src/wasm/baseline/s390/liftoff-assembler-s390-defs.h", "src/wasm/baseline/s390/liftoff-assembler-s390.h", ] } @@ -2506,6 +2532,8 @@ v8_component("v8_libbase") { "src/base/once.cc", "src/base/once.h", "src/base/optional.h", + "src/base/page-allocator.cc", + "src/base/page-allocator.h", "src/base/platform/condition-variable.cc", "src/base/platform/condition-variable.h", "src/base/platform/elapsed-timer.h", @@ -2812,6 +2840,7 @@ group("v8_fuzzers") { testonly = true deps = [ ":v8_simple_json_fuzzer", + ":v8_simple_multi_return_fuzzer", ":v8_simple_parser_fuzzer", ":v8_simple_regexp_fuzzer", ":v8_simple_wasm_async_fuzzer", @@ -3062,6 +3091,24 @@ v8_source_set("json_fuzzer") { v8_fuzzer("json_fuzzer") { } +v8_source_set("multi_return_fuzzer") { + sources = [ + "test/fuzzer/multi-return.cc", + ] + + deps = [ + ":fuzzer_support", + ] + + configs = [ + ":external_config", + ":internal_config_base", + ] +} + +v8_fuzzer("multi_return_fuzzer") { +} + v8_source_set("parser_fuzzer") { sources = [ "test/fuzzer/parser.cc", diff --git a/deps/v8/ChangeLog b/deps/v8/ChangeLog index 248b42b8d0..1fe3135a01 100644 --- a/deps/v8/ChangeLog +++ b/deps/v8/ChangeLog @@ -1,3 +1,1303 @@ +2018-01-17: Version 6.5.254 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.253 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.252 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.251 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.250 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.249 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.248 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.247 + + Performance and stability improvements on all platforms. + + +2018-01-17: Version 6.5.246 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.245 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.244 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.243 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.242 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.241 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.240 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.239 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.238 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.237 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.236 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.235 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.234 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.233 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.232 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.231 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.230 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.229 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.228 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.227 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.226 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.225 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.224 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.223 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.222 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.221 + + Performance and stability improvements on all platforms. + + +2018-01-16: Version 6.5.220 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.219 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.218 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.217 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.216 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.215 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.214 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.213 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.212 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.211 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.210 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.209 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.208 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.207 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.206 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.205 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.204 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.203 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.202 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.201 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.200 + + Performance and stability improvements on all platforms. + + +2018-01-15: Version 6.5.199 + + Performance and stability improvements on all platforms. + + +2018-01-14: Version 6.5.198 + + Performance and stability improvements on all platforms. + + +2018-01-13: Version 6.5.197 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.196 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.195 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.194 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.193 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.192 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.191 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.190 + + Performance and stability improvements on all platforms. + + +2018-01-12: Version 6.5.189 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.188 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.187 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.186 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.185 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.184 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.183 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.182 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.181 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.180 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.179 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.178 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.177 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.176 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.175 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.174 + + Performance and stability improvements on all platforms. + + +2018-01-11: Version 6.5.173 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.172 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.171 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.170 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.169 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.168 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.167 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.166 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.165 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.164 + + Performance and stability improvements on all platforms. + + +2018-01-10: Version 6.5.163 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.162 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.161 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.160 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.159 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.158 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.157 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.156 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.155 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.154 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.153 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.152 + + Performance and stability improvements on all platforms. + + +2018-01-09: Version 6.5.151 + + Performance and stability improvements on all platforms. + + +2018-01-08: Version 6.5.150 + + Performance and stability improvements on all platforms. + + +2018-01-08: Version 6.5.149 + + Performance and stability improvements on all platforms. + + +2018-01-08: Version 6.5.148 + + Performance and stability improvements on all platforms. + + +2018-01-08: Version 6.5.147 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.146 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.145 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.144 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.143 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.142 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.141 + + Performance and stability improvements on all platforms. + + +2018-01-05: Version 6.5.140 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.139 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.138 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.137 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.136 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.135 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.134 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.133 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.132 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.131 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.130 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.129 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.128 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.127 + + Performance and stability improvements on all platforms. + + +2018-01-04: Version 6.5.126 + + Performance and stability improvements on all platforms. + + +2018-01-03: Version 6.5.125 + + Performance and stability improvements on all platforms. + + +2018-01-03: Version 6.5.124 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.123 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.122 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.121 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.120 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.119 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.118 + + Performance and stability improvements on all platforms. + + +2018-01-02: Version 6.5.117 + + Performance and stability improvements on all platforms. + + +2017-12-29: Version 6.5.116 + + Performance and stability improvements on all platforms. + + +2017-12-29: Version 6.5.115 + + Performance and stability improvements on all platforms. + + +2017-12-29: Version 6.5.114 + + Performance and stability improvements on all platforms. + + +2017-12-29: Version 6.5.113 + + Performance and stability improvements on all platforms. + + +2017-12-29: Version 6.5.112 + + Performance and stability improvements on all platforms. + + +2017-12-29: Version 6.5.111 + + Performance and stability improvements on all platforms. + + +2017-12-28: Version 6.5.110 + + Performance and stability improvements on all platforms. + + +2017-12-28: Version 6.5.109 + + Performance and stability improvements on all platforms. + + +2017-12-27: Version 6.5.108 + + Performance and stability improvements on all platforms. + + +2017-12-22: Version 6.5.107 + + Performance and stability improvements on all platforms. + + +2017-12-22: Version 6.5.106 + + Performance and stability improvements on all platforms. + + +2017-12-22: Version 6.5.105 + + Performance and stability improvements on all platforms. + + +2017-12-22: Version 6.5.104 + + Performance and stability improvements on all platforms. + + +2017-12-21: Version 6.5.103 + + Performance and stability improvements on all platforms. + + +2017-12-21: Version 6.5.102 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.101 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.100 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.99 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.98 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.97 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.96 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.95 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.94 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.93 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.92 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.91 + + Performance and stability improvements on all platforms. + + +2017-12-20: Version 6.5.90 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.89 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.88 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.87 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.86 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.85 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.84 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.83 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.82 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.81 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.80 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.79 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.78 + + Performance and stability improvements on all platforms. + + +2017-12-19: Version 6.5.77 + + Performance and stability improvements on all platforms. + + +2017-12-18: Version 6.5.76 + + Performance and stability improvements on all platforms. + + +2017-12-18: Version 6.5.75 + + Performance and stability improvements on all platforms. + + +2017-12-18: Version 6.5.74 + + Performance and stability improvements on all platforms. + + +2017-12-16: Version 6.5.73 + + Performance and stability improvements on all platforms. + + +2017-12-15: Version 6.5.72 + + Performance and stability improvements on all platforms. + + +2017-12-15: Version 6.5.71 + + Performance and stability improvements on all platforms. + + +2017-12-15: Version 6.5.70 + + Performance and stability improvements on all platforms. + + +2017-12-14: Version 6.5.69 + + Performance and stability improvements on all platforms. + + +2017-12-14: Version 6.5.68 + + Performance and stability improvements on all platforms. + + +2017-12-13: Version 6.5.67 + + Performance and stability improvements on all platforms. + + +2017-12-13: Version 6.5.66 + + Performance and stability improvements on all platforms. + + +2017-12-13: Version 6.5.65 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.64 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.63 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.62 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.61 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.60 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.59 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.58 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.57 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.56 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.55 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.54 + + Performance and stability improvements on all platforms. + + +2017-12-12: Version 6.5.53 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.52 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.51 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.50 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.49 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.48 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.47 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.46 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.45 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.44 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.43 + + Performance and stability improvements on all platforms. + + +2017-12-11: Version 6.5.42 + + Performance and stability improvements on all platforms. + + +2017-12-10: Version 6.5.41 + + Performance and stability improvements on all platforms. + + +2017-12-10: Version 6.5.40 + + Performance and stability improvements on all platforms. + + +2017-12-09: Version 6.5.39 + + Performance and stability improvements on all platforms. + + +2017-12-09: Version 6.5.38 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.37 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.36 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.35 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.34 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.33 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.32 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.31 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.30 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.29 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.28 + + Performance and stability improvements on all platforms. + + +2017-12-08: Version 6.5.27 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.26 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.25 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.24 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.23 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.22 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.21 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.20 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.19 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.18 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.17 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.16 + + Performance and stability improvements on all platforms. + + +2017-12-07: Version 6.5.15 + + Performance and stability improvements on all platforms. + + +2017-12-06: Version 6.5.14 + + Performance and stability improvements on all platforms. + + +2017-12-06: Version 6.5.13 + + Performance and stability improvements on all platforms. + + +2017-12-05: Version 6.5.12 + + Performance and stability improvements on all platforms. + + +2017-12-05: Version 6.5.11 + + Performance and stability improvements on all platforms. + + +2017-12-05: Version 6.5.10 + + Performance and stability improvements on all platforms. + + +2017-12-05: Version 6.5.9 + + Performance and stability improvements on all platforms. + + +2017-12-05: Version 6.5.8 + + Performance and stability improvements on all platforms. + + +2017-12-04: Version 6.5.7 + + Performance and stability improvements on all platforms. + + +2017-12-04: Version 6.5.6 + + Performance and stability improvements on all platforms. + + +2017-12-04: Version 6.5.5 + + Performance and stability improvements on all platforms. + + +2017-12-04: Version 6.5.4 + + Performance and stability improvements on all platforms. + + +2017-12-04: Version 6.5.3 + + Performance and stability improvements on all platforms. + + +2017-12-04: Version 6.5.2 + + Performance and stability improvements on all platforms. + + +2017-12-03: Version 6.5.1 + + Performance and stability improvements on all platforms. + + +2017-11-30: Version 6.4.394 + + Performance and stability improvements on all platforms. + + +2017-11-30: Version 6.4.393 + + Performance and stability improvements on all platforms. + + +2017-11-29: Version 6.4.392 + + Performance and stability improvements on all platforms. + + +2017-11-29: Version 6.4.391 + + Performance and stability improvements on all platforms. + + +2017-11-29: Version 6.4.390 + + Performance and stability improvements on all platforms. + + +2017-11-29: Version 6.4.389 + + Performance and stability improvements on all platforms. + + 2017-11-29: Version 6.4.388 Performance and stability improvements on all platforms. diff --git a/deps/v8/DEPS b/deps/v8/DEPS index 0d6b49d3b4..bc9e4e0a90 100644 --- a/deps/v8/DEPS +++ b/deps/v8/DEPS @@ -5,27 +5,32 @@ vars = { 'checkout_instrumented_libraries': False, 'chromium_url': 'https://chromium.googlesource.com', + 'build_for_node': False, } deps = { 'v8/build': - Var('chromium_url') + '/chromium/src/build.git' + '@' + '9338ce52d0b9bcef34c38285fbd5023b62739fac', + Var('chromium_url') + '/chromium/src/build.git' + '@' + 'b3a78cd03a95c30ff10f863f736249eb04f0f34d', 'v8/tools/gyp': Var('chromium_url') + '/external/gyp.git' + '@' + 'd61a9397e668fa9843c4aa7da9e79460fe590bfb', 'v8/third_party/icu': - Var('chromium_url') + '/chromium/deps/icu.git' + '@' + '741688ebf328da9adc52505248bf4e2ef868722c', + Var('chromium_url') + '/chromium/deps/icu.git' + '@' + 'c8ca2962b46670ec89071ffd1291688983cd319c', 'v8/third_party/instrumented_libraries': - Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + '28417458ac4dc79f68915079d0f283f682504cc0', + Var('chromium_url') + '/chromium/src/third_party/instrumented_libraries.git' + '@' + 'b7578b4132cf73ca3265e2ee0b7bd0a422a54ebf', 'v8/buildtools': - Var('chromium_url') + '/chromium/buildtools.git' + '@' + '505de88083136eefd056e5ee4ca0f01fe9b33de8', + Var('chromium_url') + '/chromium/buildtools.git' + '@' + '6fe4a3251488f7af86d64fc25cf442e817cf6133', 'v8/base/trace_event/common': Var('chromium_url') + '/chromium/src/base/trace_event/common.git' + '@' + '0e9a47d74970bee1bbfc063c47215406f8918699', + 'v8/third_party/android_ndk': { + 'url': Var('chromium_url') + '/android_ndk.git' + '@' + 'e951c37287c7d8cd915bf8d4149fd4a06d808b55', + 'condition': 'checkout_android', + }, 'v8/third_party/android_tools': { - 'url': Var('chromium_url') + '/android_tools.git' + '@' + 'a2e9bc7c1b41d983577907df51d339fb1e0fd02f', + 'url': Var('chromium_url') + '/android_tools.git' + '@' + 'c78b25872734e0038ae2a333edc645cd96bc232d', 'condition': 'checkout_android', }, 'v8/third_party/catapult': { - 'url': Var('chromium_url') + '/catapult.git' + '@' + '11d7efb857ae77eff1cea4640e3f3d9ac49cba0a', + 'url': Var('chromium_url') + '/catapult.git' + '@' + 'b4826a52853c9c2778d496f6c6fa853f777f94df', 'condition': 'checkout_android', }, 'v8/third_party/colorama/src': { @@ -37,7 +42,7 @@ deps = { 'v8/third_party/markupsafe': Var('chromium_url') + '/chromium/src/third_party/markupsafe.git' + '@' + '8f45f5cfa0009d2a70589bcda0349b8cb2b72783', 'v8/tools/swarming_client': - Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '4bd9152f8a975d57c972c071dfb4ddf668e02200', + Var('chromium_url') + '/infra/luci/client-py.git' + '@' + '88229872dd17e71658fe96763feaa77915d8cbd6', 'v8/testing/gtest': Var('chromium_url') + '/external/github.com/google/googletest.git' + '@' + '6f8a66431cb592dad629028a50b3dd418a408c87', 'v8/testing/gmock': @@ -47,15 +52,15 @@ deps = { 'v8/test/mozilla/data': Var('chromium_url') + '/v8/deps/third_party/mozilla-tests.git' + '@' + 'f6c578a10ea707b1a8ab0b88943fe5115ce2b9be', 'v8/test/test262/data': - Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + '5d4c667b271a9b39d0de73aef5ffe6879c6f8811', + Var('chromium_url') + '/external/github.com/tc39/test262.git' + '@' + '8311965251953d4745aeb68c98fb71fab2eac1d0', 'v8/test/test262/harness': Var('chromium_url') + '/external/github.com/test262-utils/test262-harness-py.git' + '@' + '0f2acdd882c84cff43b9d60df7574a1901e2cdcd', 'v8/tools/clang': - Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + '8688d267571de76a56746324dcc249bf4232b85a', + Var('chromium_url') + '/chromium/src/tools/clang.git' + '@' + '27088876ff821e8a1518383576a43662a3255d56', 'v8/tools/luci-go': - Var('chromium_url') + '/chromium/src/tools/luci-go.git' + '@' + '45a8a51fda92e123619a69e7644d9c64a320b0c1', + Var('chromium_url') + '/chromium/src/tools/luci-go.git' + '@' + 'd882048313f6f51df29856406fa03b620c1d0205', 'v8/test/wasm-js': - Var('chromium_url') + '/external/github.com/WebAssembly/spec.git' + '@' + 'a7e226a92e660a3d5413cfea4269824f513259d2', + Var('chromium_url') + '/external/github.com/WebAssembly/spec.git' + '@' + 'a25083ac7076b05e3f304ec9e093ef1b1ee09422', } recursedeps = [ @@ -93,7 +98,7 @@ hooks = [ { 'name': 'clang_format_win', 'pattern': '.', - 'condition': 'host_os == "win"', + 'condition': 'host_os == "win" and build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--platform=win32', @@ -105,7 +110,7 @@ hooks = [ { 'name': 'clang_format_mac', 'pattern': '.', - 'condition': 'host_os == "mac"', + 'condition': 'host_os == "mac" and build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--platform=darwin', @@ -117,7 +122,7 @@ hooks = [ { 'name': 'clang_format_linux', 'pattern': '.', - 'condition': 'host_os == "linux"', + 'condition': 'host_os == "linux" and build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--platform=linux*', @@ -129,6 +134,7 @@ hooks = [ { 'name': 'gcmole', 'pattern': '.', + 'condition': 'build_for_node != True', # TODO(machenbach): Insert condition and remove GYP_DEFINES dependency. 'action': [ 'python', @@ -138,6 +144,7 @@ hooks = [ { 'name': 'jsfunfuzz', 'pattern': '.', + 'condition': 'build_for_node != True', # TODO(machenbach): Insert condition and remove GYP_DEFINES dependency. 'action': [ 'python', @@ -148,7 +155,7 @@ hooks = [ { 'name': 'luci-go_win', 'pattern': '.', - 'condition': 'host_os == "win"', + 'condition': 'host_os == "win" and build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--platform=win32', @@ -160,7 +167,7 @@ hooks = [ { 'name': 'luci-go_mac', 'pattern': '.', - 'condition': 'host_os == "mac"', + 'condition': 'host_os == "mac" and build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--platform=darwin', @@ -172,7 +179,7 @@ hooks = [ { 'name': 'luci-go_linux', 'pattern': '.', - 'condition': 'host_os == "linux"', + 'condition': 'host_os == "linux" and build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--platform=linux*', @@ -221,6 +228,7 @@ hooks = [ { 'name': 'wasm_spec_tests', 'pattern': '.', + 'condition': 'build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--no_auth', @@ -232,6 +240,7 @@ hooks = [ { 'name': 'closure_compiler', 'pattern': '.', + 'condition': 'build_for_node != True', 'action': [ 'download_from_google_storage', '--no_resume', '--no_auth', @@ -246,6 +255,7 @@ hooks = [ # change. 'name': 'sysroot', 'pattern': '.', + 'condition': 'build_for_node != True', 'action': [ 'python', 'v8/build/linux/sysroot_scripts/install-sysroot.py', @@ -287,7 +297,7 @@ hooks = [ { 'name': 'binutils', 'pattern': 'v8/third_party/binutils', - 'condition': 'host_os == "linux"', + 'condition': 'host_os == "linux" and build_for_node != True', 'action': [ 'python', 'v8/third_party/binutils/download.py', @@ -313,6 +323,7 @@ hooks = [ # A change to a .gyp, .gypi, or to GYP itself should run the generator. 'name': 'regyp_if_needed', 'pattern': '.', + 'condition': 'build_for_node != True', 'action': ['python', 'v8/gypfiles/gyp_v8', '--running-as-hook'], }, # Download and initialize "vpython" VirtualEnv environment packages. diff --git a/deps/v8/PRESUBMIT.py b/deps/v8/PRESUBMIT.py index a595220a09..b69e8f5089 100644 --- a/deps/v8/PRESUBMIT.py +++ b/deps/v8/PRESUBMIT.py @@ -430,6 +430,6 @@ def PostUploadHook(cl, change, output_api): return output_api.EnsureCQIncludeTrybotsAreAdded( cl, [ - 'master.tryserver.v8:v8_linux_noi18n_rel_ng' + 'luci.v8.try:v8_linux_noi18n_rel_ng' ], 'Automatically added noi18n trybots to run tests on CQ.') diff --git a/deps/v8/build_overrides/build.gni b/deps/v8/build_overrides/build.gni index b656fce61a..e4dcf1cc46 100644 --- a/deps/v8/build_overrides/build.gni +++ b/deps/v8/build_overrides/build.gni @@ -8,7 +8,7 @@ build_with_chromium = false # Uncomment these to specify a different NDK location and version in # non-Chromium builds. -# default_android_ndk_root = "//third_party/android_tools/ndk" +# default_android_ndk_root = "//third_party/android_ndk" # default_android_ndk_version = "r10e" # Some non-Chromium builds don't support building java targets. diff --git a/deps/v8/gni/v8.gni b/deps/v8/gni/v8.gni index 4b8292a244..ce9953ac68 100644 --- a/deps/v8/gni/v8.gni +++ b/deps/v8/gni/v8.gni @@ -45,6 +45,9 @@ declare_args() { # Use static libraries instead of source_sets. v8_static_library = false + + # Enable monolithic static library for embedders. + v8_monolithic = false } if (v8_use_external_startup_data == "") { @@ -97,7 +100,7 @@ if (v8_code_coverage && !is_clang) { ] } -if (is_posix && v8_enable_backtrace) { +if (is_posix && (v8_enable_backtrace || v8_monolithic)) { v8_remove_configs += [ "//build/config/gcc:symbol_visibility_hidden" ] v8_add_configs += [ "//build/config/gcc:symbol_visibility_default" ] } diff --git a/deps/v8/gypfiles/all.gyp b/deps/v8/gypfiles/all.gyp index 593ba2a795..2f9cf858c0 100644 --- a/deps/v8/gypfiles/all.gyp +++ b/deps/v8/gypfiles/all.gyp @@ -33,6 +33,7 @@ '../test/benchmarks/benchmarks.gyp:*', '../test/debugger/debugger.gyp:*', '../test/default.gyp:*', + '../test/d8_default.gyp:*', '../test/intl/intl.gyp:*', '../test/message/message.gyp:*', '../test/mjsunit/mjsunit.gyp:*', diff --git a/deps/v8/gypfiles/standalone.gypi b/deps/v8/gypfiles/standalone.gypi index 7a45dc615f..ec47f1c0ab 100644 --- a/deps/v8/gypfiles/standalone.gypi +++ b/deps/v8/gypfiles/standalone.gypi @@ -296,7 +296,7 @@ 'variables': { # The Android toolchain needs to use the absolute path to the NDK # because it is used at different levels in the GYP files. - 'android_ndk_root%': '<(base_dir)/third_party/android_tools/ndk/', + 'android_ndk_root%': '<(base_dir)/third_party/android_ndk/', 'android_host_arch%': " wrapObject( - v8::Local, v8::Local, - const StringView& groupName) = 0; + v8::Local, v8::Local, const StringView& groupName, + bool generatePreview) = 0; + virtual bool unwrapObject(std::unique_ptr* error, const StringView& objectId, v8::Local*, v8::Local*, diff --git a/deps/v8/include/v8-platform.h b/deps/v8/include/v8-platform.h index 43420a972c..2bb14df93e 100644 --- a/deps/v8/include/v8-platform.h +++ b/deps/v8/include/v8-platform.h @@ -166,6 +166,74 @@ class TracingController { virtual void RemoveTraceStateObserver(TraceStateObserver*) {} }; +/** + * A V8 memory page allocator. + * + * Can be implemented by an embedder to manage large host OS allocations. + */ +class PageAllocator { + public: + virtual ~PageAllocator() = default; + + /** + * Gets the page granularity for AllocatePages and FreePages. Addresses and + * lengths for those calls should be multiples of AllocatePageSize(). + */ + virtual size_t AllocatePageSize() = 0; + + /** + * Gets the page granularity for SetPermissions and ReleasePages. Addresses + * and lengths for those calls should be multiples of CommitPageSize(). + */ + virtual size_t CommitPageSize() = 0; + + /** + * Sets the random seed so that GetRandomMmapAddr() will generate repeatable + * sequences of random mmap addresses. + */ + virtual void SetRandomMmapSeed(int64_t seed) = 0; + + /** + * Returns a randomized address, suitable for memory allocation under ASLR. + * The address will be aligned to AllocatePageSize. + */ + virtual void* GetRandomMmapAddr() = 0; + + /** + * Memory permissions. + */ + enum Permission { + kNoAccess, + kReadWrite, + // TODO(hpayer): Remove this flag. Memory should never be rwx. + kReadWriteExecute, + kReadExecute + }; + + /** + * Allocates memory in range with the given alignment and permission. + */ + virtual void* AllocatePages(void* address, size_t length, size_t alignment, + Permission permissions) = 0; + + /** + * Frees memory in a range that was allocated by a call to AllocatePages. + */ + virtual bool FreePages(void* address, size_t length) = 0; + + /** + * Releases memory in a range that was allocated by a call to AllocatePages. + */ + virtual bool ReleasePages(void* address, size_t length, + size_t new_length) = 0; + + /** + * Sets permissions on pages in an allocated range. + */ + virtual bool SetPermissions(void* address, size_t length, + Permission permissions) = 0; +}; + /** * V8 Platform abstraction layer. * @@ -186,6 +254,14 @@ class Platform { virtual ~Platform() = default; + /** + * Allows the embedder to manage memory page allocations. + */ + virtual PageAllocator* GetPageAllocator() { + // TODO(bbudge) Make this abstract after all embedders implement this. + return nullptr; + } + /** * Enables the embedder to respond in cases where V8 can't allocate large * blocks of memory. V8 retries the failed allocation once after calling this @@ -193,7 +269,21 @@ class Platform { * error. * Embedder overrides of this function must NOT call back into V8. */ - virtual void OnCriticalMemoryPressure() {} + virtual void OnCriticalMemoryPressure() { + // TODO(bbudge) Remove this when embedders override the following method. + // See crbug.com/634547. + } + + /** + * Enables the embedder to respond in cases where V8 can't allocate large + * memory regions. The |length| parameter is the amount of memory needed. + * Returns true if memory is now available. Returns false if no memory could + * be made available. V8 will retry allocations until this method returns + * false. + * + * Embedder overrides of this function must NOT call back into V8. + */ + virtual bool OnCriticalMemoryPressure(size_t length) { return false; } /** * Gets the number of threads that are used to execute background tasks. Is diff --git a/deps/v8/include/v8-version.h b/deps/v8/include/v8-version.h index cb85da2cd7..6cc98294ec 100644 --- a/deps/v8/include/v8-version.h +++ b/deps/v8/include/v8-version.h @@ -9,9 +9,9 @@ // NOTE these macros are used by some of the tool scripts and the build // system so their names cannot be changed without changing the scripts. #define V8_MAJOR_VERSION 6 -#define V8_MINOR_VERSION 4 -#define V8_BUILD_NUMBER 388 -#define V8_PATCH_LEVEL 46 +#define V8_MINOR_VERSION 5 +#define V8_BUILD_NUMBER 254 +#define V8_PATCH_LEVEL 31 // Use 1 for candidates and 0 otherwise. // (Boolean macro values are not supported by all preprocessors.) diff --git a/deps/v8/include/v8.h b/deps/v8/include/v8.h index c09f610333..acb3efbc71 100644 --- a/deps/v8/include/v8.h +++ b/deps/v8/include/v8.h @@ -313,6 +313,7 @@ class Local { friend class String; friend class Object; friend class Context; + friend class Isolate; friend class Private; template friend class internal::CustomArguments; friend Local Undefined(Isolate* isolate); @@ -1129,15 +1130,15 @@ class V8_EXPORT Location { }; /** - * This is an unfinished experimental feature, and is only exposed - * here for internal testing purposes. DO NOT USE. - * * A compiled JavaScript module. */ class V8_EXPORT Module { public: /** * The different states a module can be in. + * This corresponds to the states used in ECMAScript except that "evaluated" + * is split into kEvaluated and kErrored, indicating success and failure, + * respectively. */ enum Status { kUninstantiated, @@ -1191,9 +1192,6 @@ class V8_EXPORT Module { * instantiation. (In the case where the callback throws an exception, that * exception is propagated.) */ - V8_DEPRECATED("Use Maybe version", - bool Instantiate(Local context, - ResolveCallback callback)); V8_WARN_UNUSED_RESULT Maybe InstantiateModule(Local context, ResolveCallback callback); @@ -1423,7 +1421,8 @@ class V8_EXPORT ScriptCompiler { kConsumeParserCache, kProduceCodeCache, kProduceFullCodeCache, - kConsumeCodeCache + kConsumeCodeCache, + kEagerCompile }; /** @@ -1443,7 +1442,8 @@ class V8_EXPORT ScriptCompiler { kNoCacheBecauseExtensionModule, kNoCacheBecausePacScript, kNoCacheBecauseInDocumentWrite, - kNoCacheBecauseResourceWithNoCacheHandler + kNoCacheBecauseResourceWithNoCacheHandler, + kNoCacheBecauseDeferredProduceCodeCache }; /** @@ -1459,11 +1459,6 @@ class V8_EXPORT ScriptCompiler { * \return Compiled script object (context independent; for running it must be * bound to a context). */ - static V8_DEPRECATED("Use maybe version", - Local CompileUnbound( - Isolate* isolate, Source* source, - CompileOptions options = kNoCompileOptions, - NoCacheReason no_cache_reason = kNoCacheNoReason)); static V8_WARN_UNUSED_RESULT MaybeLocal CompileUnboundScript( Isolate* isolate, Source* source, CompileOptions options = kNoCompileOptions, @@ -1480,11 +1475,6 @@ class V8_EXPORT ScriptCompiler { * when this function was called. When run it will always use this * context. */ - static V8_DEPRECATED( - "Use maybe version", - Local + \ No newline at end of file diff --git a/deps/v8/tools/heap-stats/details-selection.js b/deps/v8/tools/heap-stats/details-selection.js new file mode 100644 index 0000000000..43c000d3f4 --- /dev/null +++ b/deps/v8/tools/heap-stats/details-selection.js @@ -0,0 +1,211 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +const details_selection_template = + document.currentScript.ownerDocument.querySelector( + '#details-selection-template'); + +class DetailsSelection extends HTMLElement { + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.appendChild(details_selection_template.content.cloneNode(true)); + this.isolateSelect.addEventListener( + 'change', e => this.handleIsolateChange(e)); + this.datasetSelect.addEventListener( + 'change', e => this.notifySelectionChanged(e)); + this.$('#merge-categories') + .addEventListener('change', e => this.notifySelectionChanged(e)); + } + + connectedCallback() { + for (let category of CATEGORIES.keys()) { + this.$('#categories').appendChild(this.buildCategory(category)); + } + } + + set data(value) { + this._data = value; + this.dataChanged(); + } + + get data() { + return this._data; + } + + buildCategory(name) { + const div = document.createElement('div'); + div.id = name; + div.classList.add('box'); + const span = document.createElement('span'); + div.appendChild(span); + span.innerHTML = CATEGORY_NAMES.get(name) + ' '; + const all_button = document.createElement('button'); + span.appendChild(all_button); + all_button.innerHTML = 'All'; + all_button.addEventListener('click', e => this.selectCategory(name)); + const none_button = document.createElement('button'); + span.appendChild(none_button); + none_button.innerHTML = 'None'; + none_button.addEventListener('click', e => this.unselectCategory(name)); + const innerDiv = document.createElement('div'); + div.appendChild(innerDiv); + innerDiv.id = name + 'Content'; + return div; + } + + $(id) { + return this.shadowRoot.querySelector(id); + } + + get datasetSelect() { + return this.$('#dataset-select'); + } + + get isolateSelect() { + return this.$('#isolate-select'); + } + + dataChanged() { + this.clearUI(); + this.populateSelect('#isolate-select', Object.keys(this.data)); + this.handleIsolateChange(); + } + + clearUI() { + this.selection = {categories: {}}; + removeAllChildren(this.isolateSelect); + removeAllChildren(this.datasetSelect); + this.clearCategories(); + } + + handleIsolateChange(e) { + this.selection.isolate = this.isolateSelect.value; + if (this.selection.isolate.length === 0) { + this.selection.isolate = null; + return; + } + + this.populateSelect( + '#dataset-select', this.data[this.selection.isolate].data_sets, 'live'); + this.populateCategories(); + this.notifySelectionChanged(); + } + + notifySelectionChanged(e) { + if (!this.selection.isolate) return; + + this.selection.categories = {}; + for (let category of CATEGORIES.keys()) { + const selected = this.selectedInCategory(category); + if (selected.length > 0) this.selection.categories[category] = selected; + } + this.selection.category_names = CATEGORY_NAMES; + this.selection.data_set = this.datasetSelect.value; + this.selection.merge_categories = this.$('#merge-categories').checked; + this.dispatchEvent(new CustomEvent( + 'change', {bubbles: true, composed: true, detail: this.selection})); + } + + selectedInCategory(category) { + const selected = this.shadowRoot.querySelectorAll( + 'input[name=' + category + 'Checkbox]:checked'); + var tmp = []; + for (var val of selected.values()) tmp.push(val.value); + return tmp; + } + + categoryForType(instance_type) { + for (let [key, value] of CATEGORIES.entries()) { + if (value.has(instance_type)) return key; + } + return 'unclassified'; + } + + createOption(text) { + const option = document.createElement('option'); + option.value = text; + option.text = text; + return option; + } + + populateSelect(id, iterable, autoselect = null) { + for (let option_value of iterable) { + const option = this.createOption(option_value); + if (autoselect === option_value) { + option.selected = 'selected'; + } + this.$(id).appendChild(option); + } + } + + clearCategories() { + for (const category of CATEGORIES.keys()) { + let f = this.$('#' + category + 'Content'); + while (f.firstChild) { + f.removeChild(f.firstChild); + } + } + } + + populateCategories() { + this.clearCategories(); + const categories = {}; + for (let cat of CATEGORIES.keys()) { + categories[cat] = []; + } + + for (let instance_type of this.data[this.selection.isolate] + .non_empty_instance_types) { + if (IGNORED_INSTANCE_TYPES.has(instance_type)) continue; + const category = this.categoryForType(instance_type); + categories[category].push(instance_type); + } + for (let category of Object.keys(categories)) { + categories[category].sort(); + for (let instance_type of categories[category]) { + this.$('#' + category + 'Content') + .appendChild(this.createCheckBox(instance_type, category)); + } + } + } + + unselectCategory(category) { + for (let checkbox of this.shadowRoot.querySelectorAll( + 'input[name=' + category + 'Checkbox]')) { + checkbox.checked = false; + } + this.notifySelectionChanged(); + } + + selectCategory(category) { + for (let checkbox of this.shadowRoot.querySelectorAll( + 'input[name=' + category + 'Checkbox]')) { + checkbox.checked = true; + } + this.notifySelectionChanged(); + } + + createCheckBox(instance_type, category) { + const div = document.createElement('div'); + div.classList.add('boxDiv'); + const input = document.createElement('input'); + div.appendChild(input); + input.type = 'checkbox'; + input.name = category + 'Checkbox'; + input.checked = 'checked'; + input.id = instance_type + 'Checkbox'; + input.value = instance_type; + input.addEventListener('change', e => this.notifySelectionChanged(e)); + const label = document.createElement('label'); + div.appendChild(label); + label.innerText = instance_type; + label.htmlFor = instance_type + 'Checkbox'; + return div; + } +} + +customElements.define('details-selection', DetailsSelection); diff --git a/deps/v8/tools/heap-stats/global-timeline.html b/deps/v8/tools/heap-stats/global-timeline.html new file mode 100644 index 0000000000..788f966735 --- /dev/null +++ b/deps/v8/tools/heap-stats/global-timeline.html @@ -0,0 +1,16 @@ + + + \ No newline at end of file diff --git a/deps/v8/tools/heap-stats/global-timeline.js b/deps/v8/tools/heap-stats/global-timeline.js new file mode 100644 index 0000000000..0533f21432 --- /dev/null +++ b/deps/v8/tools/heap-stats/global-timeline.js @@ -0,0 +1,135 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +const KB = 1024; +const MB = KB * KB; + +const global_timeline_template = + document.currentScript.ownerDocument.querySelector( + '#global-timeline-template'); + +class GlobalTimeline extends HTMLElement { + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.appendChild(global_timeline_template.content.cloneNode(true)); + } + + $(id) { + return this.shadowRoot.querySelector(id); + } + + set data(value) { + this._data = value; + this.stateChanged(); + } + + get data() { + return this._data; + } + + set selection(value) { + this._selection = value; + this.stateChanged(); + } + + get selection() { + return this._selection; + } + + isValid() { + return this.data && this.selection; + } + + hide() { + this.$('#container').style.display = 'none'; + } + + show() { + this.$('#container').style.display = 'block'; + } + + stateChanged() { + if (this.isValid()) { + this.drawChart(); + } else { + this.hide(); + } + } + + getCategoryData() { + const categories = Object.keys(this.selection.categories) + .map(k => this.selection.category_names.get(k)); + const labels = ['Time', ...categories]; + const chart_data = [labels]; + const isolate_data = this.data[this.selection.isolate]; + Object.keys(isolate_data.gcs).forEach(gc_key => { + const gc_data = isolate_data.gcs[gc_key]; + const data_set = gc_data[this.selection.data_set].instance_type_data; + const data = []; + data.push(gc_data.time); + Object.values(this.selection.categories).forEach(instance_types => { + data.push( + instance_types + .map(instance_type => { + return data_set[instance_type].overall; + }) + .reduce((accu, current) => accu + current, 0) / + KB); + }); + chart_data.push(data); + }); + return chart_data; + } + + getInstanceTypeData() { + const categories = Object.keys(this.selection.categories); + const instance_types = + Object.values(this.selection.categories) + .reduce((accu, current) => accu.concat(current), []); + const labels = ['Time', ...instance_types]; + const chart_data = [labels]; + const isolate_data = this.data[this.selection.isolate]; + Object.keys(isolate_data.gcs).forEach(gc_key => { + const gc_data = isolate_data.gcs[gc_key]; + const data_set = gc_data[this.selection.data_set].instance_type_data; + const data = []; + data.push(gc_data.time); + instance_types.forEach(instance_type => { + data.push(data_set[instance_type].overall / KB); + }); + chart_data.push(data); + }); + return chart_data; + } + + drawChart() { + console.assert(this.data, 'invalid data'); + console.assert(this.selection, 'invalid selection'); + + const chart_data = (this.selection.merge_categories) ? + this.getCategoryData() : + this.getInstanceTypeData(); + const data = google.visualization.arrayToDataTable(chart_data); + const options = { + isStacked: true, + hAxis: { + title: 'Time [ms]', + }, + vAxis: {title: 'Memory consumption [KBytes]'}, + chartArea: {width: '85%', height: '70%'}, + legend: {position: 'top', maxLines: '1'}, + pointsVisible: true, + pointSize: 5, + explorer: {}, + }; + const chart = new google.visualization.AreaChart(this.$('#chart')); + this.show(); + chart.draw(data, google.charts.Line.convertOptions(options)); + } +} + +customElements.define('global-timeline', GlobalTimeline); diff --git a/deps/v8/tools/heap-stats/index.html b/deps/v8/tools/heap-stats/index.html new file mode 100644 index 0000000000..3c2e62b6d0 --- /dev/null +++ b/deps/v8/tools/heap-stats/index.html @@ -0,0 +1,88 @@ + + + + + + + + V8 Heap Statistics + + + + + + + + + + + + + +

V8 Heap Statistics

+

Visualize object statistics that have been gathered using

+
    +
  • --trace-gc-object-stats on V8
  • +
  • + Chrome's + tracing infrastructure collecting data for the category + v8.gc_stats. The trace file needs to be unpacked (e.g. using + gunzip). +
  • +
+

+ Note that the visualizer needs to run on a web server due to HTML imports + requiring CORS. +

+ + + + + + diff --git a/deps/v8/tools/heap-stats/trace-file-reader.html b/deps/v8/tools/heap-stats/trace-file-reader.html new file mode 100644 index 0000000000..98c2ef0c60 --- /dev/null +++ b/deps/v8/tools/heap-stats/trace-file-reader.html @@ -0,0 +1,26 @@ + + + diff --git a/deps/v8/tools/heap-stats/trace-file-reader.js b/deps/v8/tools/heap-stats/trace-file-reader.js new file mode 100644 index 0000000000..59825fe514 --- /dev/null +++ b/deps/v8/tools/heap-stats/trace-file-reader.js @@ -0,0 +1,300 @@ +// Copyright 2018 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +'use strict'; + +const trace_file_reader_template = + document.currentScript.ownerDocument.querySelector( + '#trace-file-reader-template'); + +class TraceFileReader extends HTMLElement { + constructor() { + super(); + const shadowRoot = this.attachShadow({mode: 'open'}); + shadowRoot.appendChild(trace_file_reader_template.content.cloneNode(true)); + this.addEventListener('click', e => this.handleClick(e)); + this.addEventListener('dragover', e => this.handleDragOver(e)); + this.addEventListener('drop', e => this.handleChange(e)); + this.$('#file').addEventListener('change', e => this.handleChange(e)); + } + + $(id) { + return this.shadowRoot.querySelector(id); + } + + updateLabel(text) { + this.$('#label').innerText = text; + } + + handleClick(event) { + this.$('#file').click(); + } + + handleChange(event) { + // Used for drop and file change. + event.preventDefault(); + var host = event.dataTransfer ? event.dataTransfer : event.target; + this.readFile(host.files[0]); + } + + handleDragOver(event) { + event.preventDefault(); + } + + connectedCallback() {} + + readFile(file) { + if (!file) { + this.updateLabel('Failed to load file.'); + return; + } + + const result = new FileReader(); + result.onload = (e) => { + let contents = e.target.result.split('\n'); + const return_data = (e.target.result.includes('V8.GC_Objects_Stats')) ? + this.createModelFromChromeTraceFile(contents) : + this.createModelFromV8TraceFile(contents); + this.updateLabel('Finished loading \'' + file.name + '\'.'); + this.dispatchEvent(new CustomEvent( + 'change', {bubbles: true, composed: true, detail: return_data})); + }; + result.readAsText(file); + } + + createOrUpdateEntryIfNeeded(data, keys, entry) { + console.assert(entry.isolate, 'entry should have an isolate'); + if (!(entry.isolate in keys)) { + keys[entry.isolate] = new Set(); + } + if (!(entry.isolate in data)) { + data[entry.isolate] = { + non_empty_instance_types: new Set(), + gcs: {}, + zonetags: [], + samples: {zone: {}}, + start: null, + end: null, + data_sets: new Set() + }; + } + const data_object = data[entry.isolate]; + if (('id' in entry) && !(entry.id in data_object.gcs)) { + data_object.gcs[entry.id] = {non_empty_instance_types: new Set()}; + } + if ('time' in entry) { + if (data_object.end === null || data_object.end < entry.time) + data_object.end = entry.time; + if (data_object.start === null || data_object.start > entry.time) + data_object.start = entry.time; + } + } + + createDatasetIfNeeded(data, keys, entry, data_set) { + if (!(data_set in data[entry.isolate].gcs[entry.id])) { + data[entry.isolate].gcs[entry.id][data_set] = { + instance_type_data: {}, + non_empty_instance_types: new Set(), + overall: 0 + }; + data[entry.isolate].data_sets.add(data_set); + } + } + + addInstanceTypeData( + data, keys, isolate, gc_id, data_set, instance_type, entry) { + keys[isolate].add(data_set); + data[isolate].gcs[gc_id][data_set].instance_type_data[instance_type] = { + overall: entry.overall, + count: entry.count, + histogram: entry.histogram, + over_allocated: entry.over_allocated, + over_allocated_histogram: entry.over_allocated_histogram + }; + data[isolate].gcs[gc_id][data_set].overall += entry.overall; + if (entry.overall !== 0) { + data[isolate].gcs[gc_id][data_set].non_empty_instance_types.add( + instance_type); + data[isolate].gcs[gc_id].non_empty_instance_types.add(instance_type); + data[isolate].non_empty_instance_types.add(instance_type); + } + } + + extendAndSanitizeModel(data, keys) { + const checkNonNegativeProperty = (obj, property) => { + console.assert(obj[property] >= 0, 'negative property', obj, property); + }; + + for (const isolate of Object.keys(data)) { + for (const gc of Object.keys(data[isolate].gcs)) { + for (const data_set_key of keys[isolate]) { + const data_set = data[isolate].gcs[gc][data_set_key]; + // 1. Create a ranked instance type array that sorts instance + // types by memory size (overall). + data_set.ranked_instance_types = + [...data_set.non_empty_instance_types].sort(function(a, b) { + if (data_set.instance_type_data[a].overall > + data_set.instance_type_data[b].overall) { + return 1; + } else if ( + data_set.instance_type_data[a].overall < + data_set.instance_type_data[b].overall) { + return -1; + } + return 0; + }); + + let known_count = 0; + let known_overall = 0; + let known_histogram = + Array( + data_set.instance_type_data.FIXED_ARRAY_TYPE.histogram.length) + .fill(0); + for (const instance_type in data_set.instance_type_data) { + if (!instance_type.startsWith('*FIXED_ARRAY')) continue; + const subtype = data_set.instance_type_data[instance_type]; + known_count += subtype.count; + known_overall += subtype.count; + for (let i = 0; i < subtype.histogram.length; i++) { + known_histogram[i] += subtype.histogram[i]; + } + } + + const fixed_array_data = data_set.instance_type_data.FIXED_ARRAY_TYPE; + const unknown_entry = { + count: fixed_array_data.count - known_count, + overall: fixed_array_data.overall - known_overall, + histogram: fixed_array_data.histogram.map( + (value, index) => value - known_histogram[index]) + }; + + // Check for non-negative values. + checkNonNegativeProperty(unknown_entry, 'count'); + checkNonNegativeProperty(unknown_entry, 'overall'); + for (let i = 0; i < unknown_entry.histogram.length; i++) { + checkNonNegativeProperty(unknown_entry.histogram, i); + } + + data_set.instance_type_data['*FIXED_ARRAY_UNKNOWN_SUB_TYPE'] = + unknown_entry; + data_set.non_empty_instance_types.add( + '*FIXED_ARRAY_UNKNOWN_SUB_TYPE'); + } + } + } + } + + createModelFromChromeTraceFile(contents) { + console.log('Processing log as chrome trace file.'); + const data = Object.create(null); // Final data container. + const keys = Object.create(null); // Collecting 'keys' per isolate. + + // Pop last line in log as it might be broken. + contents.pop(); + // Remove trailing comma. + contents[contents.length - 1] = contents[contents.length - 1].slice(0, -1); + // Terminate JSON. + const sanitized_contents = [...contents, ']}'].join(''); + try { + const raw_data = JSON.parse(sanitized_contents); + const objects_stats_data = + raw_data.traceEvents.filter(e => e.name == 'V8.GC_Objects_Stats'); + objects_stats_data.forEach(trace_data => { + const actual_data = trace_data.args; + const data_sets = new Set(Object.keys(actual_data)); + Object.keys(actual_data).forEach(data_set => { + const string_entry = actual_data[data_set]; + try { + const entry = JSON.parse(string_entry); + this.createOrUpdateEntryIfNeeded(data, keys, entry); + this.createDatasetIfNeeded(data, keys, entry, data_set); + const isolate = entry.isolate; + const time = entry.time; + const gc_id = entry.id; + data[isolate].gcs[gc_id].time = time; + data[isolate].gcs[gc_id][data_set].bucket_sizes = + entry.bucket_sizes; + for (let [instance_type, value] of Object.entries( + entry.type_data)) { + // Trace file format uses markers that do not have actual + // properties. + if (!('overall' in value)) continue; + this.addInstanceTypeData( + data, keys, isolate, gc_id, data_set, instance_type, value); + } + } catch (e) { + console.log('Unable to parse data set entry', e); + } + }); + }); + } catch (e) { + console.log('Unable to parse chrome trace file.', e); + } + this.extendAndSanitizeModel(data, keys); + return data; + } + + createModelFromV8TraceFile(contents) { + console.log('Processing log as V8 trace file.'); + contents = contents.map(function(line) { + try { + // Strip away a potentially present adb logcat prefix. + line = line.replace(/^I\/v8\s*\(\d+\):\s+/g, ''); + return JSON.parse(line); + } catch (e) { + console.log('Unable to parse line: \'' + line + '\'\' (' + e + ')'); + } + return null; + }); + + const data = Object.create(null); // Final data container. + const keys = Object.create(null); // Collecting 'keys' per isolate. + + for (var entry of contents) { + if (entry === null || entry.type === undefined) { + continue; + } + if (entry.type === 'zone') { + this.createOrUpdateEntryIfNeeded(data, keys, entry); + const stacktrace = ('stacktrace' in entry) ? entry.stacktrace : []; + data[entry.isolate].samples.zone[entry.time] = { + allocated: entry.allocated, + pooled: entry.pooled, + stacktrace: stacktrace + }; + } else if ( + entry.type === 'zonecreation' || entry.type === 'zonedestruction') { + this.createOrUpdateEntryIfNeeded(data, keys, entry); + data[entry.isolate].zonetags.push( + Object.assign({opening: entry.type === 'zonecreation'}, entry)); + } else if (entry.type === 'gc_descriptor') { + this.createOrUpdateEntryIfNeeded(data, keys, entry); + data[entry.isolate].gcs[entry.id].time = entry.time; + if ('zone' in entry) + data[entry.isolate].gcs[entry.id].malloced = entry.zone; + } else if (entry.type === 'instance_type_data') { + if (entry.id in data[entry.isolate].gcs) { + this.createOrUpdateEntryIfNeeded(data, keys, entry); + this.createDatasetIfNeeded(data, keys, entry, entry.key); + this.addInstanceTypeData( + data, keys, entry.isolate, entry.id, entry.key, + entry.instance_type_name, entry); + } + } else if (entry.type === 'bucket_sizes') { + if (entry.id in data[entry.isolate].gcs) { + this.createOrUpdateEntryIfNeeded(data, keys, entry); + this.createDatasetIfNeeded(data, keys, entry, entry.key); + data[entry.isolate].gcs[entry.id][entry.key].bucket_sizes = + entry.sizes; + } + } else { + console.log('Unknown entry type: ' + entry.type); + } + } + this.extendAndSanitizeModel(data, keys); + return data; + } +} + +customElements.define('trace-file-reader', TraceFileReader); diff --git a/deps/v8/tools/js2c.py b/deps/v8/tools/js2c.py index 105be0c1b6..0107436df6 100755 --- a/deps/v8/tools/js2c.py +++ b/deps/v8/tools/js2c.py @@ -50,10 +50,12 @@ def ToCArray(byte_sequence): return textwrap.fill(joined, 80) -def RemoveCommentsAndTrailingWhitespace(lines): +def RemoveCommentsEmptyLinesAndWhitespace(lines): + lines = re.sub(r'\n+', '\n', lines) # empty lines lines = re.sub(r'//.*\n', '\n', lines) # end-of-line comments lines = re.sub(re.compile(r'/\*.*?\*/', re.DOTALL), '', lines) # comments. - lines = re.sub(r'\s+\n+', '\n', lines) # trailing whitespace + lines = re.sub(r'\s+\n', '\n', lines) # trailing whitespace + lines = re.sub(r'\n\s+', '\n', lines) # initial whitespace return lines @@ -342,7 +344,7 @@ def BuildFilterChain(macro_filename, message_template_file): filter_chain.append(lambda l: ExpandConstants(l, message_templates)) filter_chain.extend([ - RemoveCommentsAndTrailingWhitespace, + RemoveCommentsEmptyLinesAndWhitespace, ExpandInlineMacros, ExpandInlineConstants, Validate, @@ -355,7 +357,7 @@ def BuildFilterChain(macro_filename, message_template_file): return reduce(chain, filter_chain) def BuildExtraFilterChain(): - return lambda x: RemoveCommentsAndTrailingWhitespace(Validate(x)) + return lambda x: RemoveCommentsEmptyLinesAndWhitespace(Validate(x)) class Sources: def __init__(self): @@ -365,7 +367,7 @@ class Sources: def IsDebuggerFile(filename): - return "debug" in filename + return os.path.basename(os.path.dirname(filename)) == "debug" def IsMacroFile(filename): return filename.endswith("macros.py") diff --git a/deps/v8/tools/map-processor b/deps/v8/tools/map-processor new file mode 100755 index 0000000000..c0713bdf13 --- /dev/null +++ b/deps/v8/tools/map-processor @@ -0,0 +1,41 @@ +#!/bin/sh + +# find the name of the log file to process, it must not start with a dash. +log_file="v8.log" +for arg in "$@" +do + if ! expr "X${arg}" : "^X-" > /dev/null; then + log_file=${arg} + fi +done + +tools_path=`cd $(dirname "$0");pwd` +if [ ! "$D8_PATH" ]; then + d8_public=`which d8` + if [ -x "$d8_public" ]; then D8_PATH=$(dirname "$d8_public"); fi +fi +[ -n "$D8_PATH" ] || D8_PATH=$tools_path/.. +d8_exec=$D8_PATH/d8 + +if [ ! -x "$d8_exec" ]; then + D8_PATH=`pwd`/out/native + d8_exec=$D8_PATH/d8 +fi + +if [ ! -x "$d8_exec" ]; then + d8_exec=`grep -m 1 -o '".*/d8"' $log_file | sed 's/"//g'` +fi + +if [ ! -x "$d8_exec" ]; then + echo "d8 shell not found in $D8_PATH" + echo "To build, execute 'make native' from the V8 directory" + exit 1 +fi + +# nm spits out 'no symbols found' messages to stderr. +cat $log_file | $d8_exec $tools_path/splaytree.js $tools_path/codemap.js \ + $tools_path/csvparser.js $tools_path/consarray.js \ + $tools_path/profile.js $tools_path/profile_view.js \ + $tools_path/logreader.js $tools_path/arguments.js \ + $tools_path/map-processor.js $tools_path/SourceMap.js \ + $tools_path/map-processor-driver.js -- $@ 2>/dev/null diff --git a/deps/v8/tools/map-processor-driver.js b/deps/v8/tools/map-processor-driver.js new file mode 100644 index 0000000000..31a4860849 --- /dev/null +++ b/deps/v8/tools/map-processor-driver.js @@ -0,0 +1,33 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function processArguments(args) { + var processor = new ArgumentsProcessor(args); + if (processor.parse()) { + return processor.result(); + } else { + processor.printUsageAndExit(); + } +} + +function initSourceMapSupport() { + // Pull dev tools source maps into our name space. + SourceMap = WebInspector.SourceMap; + + // Overwrite the load function to load scripts synchronously. + SourceMap.load = function(sourceMapURL) { + var content = readFile(sourceMapURL); + var sourceMapObject = (JSON.parse(content)); + return new SourceMap(sourceMapURL, sourceMapObject); + }; +} + +var params = processArguments(arguments); +var sourceMap = null; +if (params.sourceMap) { + initSourceMapSupport(); + sourceMap = SourceMap.load(params.sourceMap); +} +var mapProcessor = new MapProcessor(); +mapProcessor.processLogFile(params.logFileName); diff --git a/deps/v8/tools/map-processor.html b/deps/v8/tools/map-processor.html new file mode 100644 index 0000000000..4029e96343 --- /dev/null +++ b/deps/v8/tools/map-processor.html @@ -0,0 +1,1254 @@ + + + + + + + + + + + + + + + + + + + + + +

Data

+
+
+

+ +

+
+
+ +

Stats

+
+ +

Timeline

+
+
+ +
+
+
+
+
+
+
+ +

Transitions

+
+
+ +

Selected Map

+
+ + + + +
+
+
+ + diff --git a/deps/v8/tools/map-processor.js b/deps/v8/tools/map-processor.js new file mode 100644 index 0000000000..5b0e46909c --- /dev/null +++ b/deps/v8/tools/map-processor.js @@ -0,0 +1,717 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// =========================================================================== +class MapProcessor extends LogReader { + constructor() { + super(); + this.dispatchTable_ = { + 'code-creation': { + parsers: [null, parseInt, parseInt, parseInt, parseInt, null, 'var-args'], + processor: this.processCodeCreation + }, + 'code-move': { + parsers: [parseInt, parseInt], + 'sfi-move': { + parsers: [parseInt, parseInt], + processor: this.processCodeMove + }, + 'code-delete': { + parsers: [parseInt], + processor: this.processCodeDelete + }, + processor: this.processFunctionMove + }, + 'map-create': { + parsers: [parseInt, parseInt, null], + processor: this.processMapCreate + }, + 'map': { + parsers: [null, parseInt, parseInt, parseInt, parseInt, parseInt, + null, null, null + ], + processor: this.processMap + }, + 'map-details': { + parsers: [parseInt, parseInt, null], + processor: this.processMapDetails + } + }; + this.deserializedEntriesNames_ = []; + this.profile_ = new Profile(); + this.timeline_ = new Timeline(); + } + + printError(str) { + console.error(str); + throw str + } + + processString(string) { + let end = string.length; + let current = 0; + let next = 0; + let line; + let i = 0; + let entry; + try { + while (current < end) { + next = string.indexOf("\n", current); + if (next === -1) break; + i++; + line = string.substring(current, next); + current = next + 1; + this.processLogLine(line); + } + } catch(e) { + console.log("Error occurred during parsing, trying to continue: " + e); + } + return this.finalize(); + } + + processLogFile(fileName) { + this.collectEntries = true + this.lastLogFileName_ = fileName; + let line; + while (line = readline()) { + this.processLogLine(line); + } + return this.finalize(); + } + + finalize() { + // TODO(cbruni): print stats; + this.timeline_.finalize(); + return this.timeline_; + } + + addEntry(entry) { + this.entries.push(entry); + } + + /** + * Parser for dynamic code optimization state. + */ + parseState(s) { + switch (s) { + case "": + return Profile.CodeState.COMPILED; + case "~": + return Profile.CodeState.OPTIMIZABLE; + case "*": + return Profile.CodeState.OPTIMIZED; + } + throw new Error("unknown code state: " + s); + } + + processCodeCreation( + type, kind, timestamp, start, size, name, maybe_func) { + name = this.deserializedEntriesNames_[start] || name; + if (name.startsWith("onComplete")) { + console.log(name); + } + if (maybe_func.length) { + let funcAddr = parseInt(maybe_func[0]); + let state = this.parseState(maybe_func[1]); + this.profile_.addFuncCode(type, name, timestamp, start, size, funcAddr, state); + } else { + this.profile_.addCode(type, name, timestamp, start, size); + } + } + + processCodeMove(from, to) { + this.profile_.moveCode(from, to); + } + + processCodeDelete(start) { + this.profile_.deleteCode(start); + } + + processFunctionMove(from, to) { + this.profile_.moveFunc(from, to); + } + + formatPC(pc, line, column) { + let entry = this.profile_.findEntry(pc); + if (!entry) return "" + if (entry.type == "Builtin") { + return entry.name; + } + let name = entry.func.getName(); + let re = /(.*):[0-9]+:[0-9]+$/; + let array = re.exec(name); + if (!array) { + entry = name; + } else { + entry = entry.getState() + array[1]; + } + return entry + ":" + line + ":" + column; + } + + processMap(type, time, from, to, pc, line, column, reason, name) { + time = parseInt(time); + if (type == "Deprecate") return this.deprecateMap(type, time, from); + from = this.getExistingMap(from, time); + to = this.getExistingMap(to, time); + let edge = new Edge(type, name, reason, time, from, to); + edge.filePosition = this.formatPC(pc, line, column); + edge.finishSetup(); + } + + deprecateMap(type, time, id) { + this.getExistingMap(id, time).deprecate(); + } + + processMapCreate(time, id, string) { + // map-create events might override existing maps if the addresses get + // rcycled. Hence we do not check for existing maps. + let map = this.createMap(id, time); + map.description = string; + } + + processMapDetails(time, id, string) { + //TODO(cbruni): fix initial map logging. + let map = this.getExistingMap(id, time); + if (!map.description) { + map.description = string; + } + } + + createMap(id, time) { + if (id == 0x1821257d1761) { + console.log(id); + } + let map = new V8Map(id, time); + this.timeline_.push(map); + return map; + } + + getExistingMap(id, time) { + if (id === 0) return undefined; + let map = V8Map.get(id); + if (map === undefined) { + console.error("No map details provided: id=" + id); + // Manually patch in a map to continue running. + return this.createMap(id, time); + }; + return map; + } +} + +// =========================================================================== + +class V8Map { + constructor(id, time = -1) { + if (!id) throw "Invalid ID"; + this.id = id; + this.time = time; + if (!(time > 0)) throw "Invalid time"; + this.description = ""; + this.edge = void 0; + this.children = []; + this.depth = 0; + this._isDeprecated = false; + this.deprecationTargets = null; + V8Map.set(id, this); + this.leftId = 0; + this.rightId = 0; + } + + finalize(id) { + // Initialize preorder tree traversal Ids for fast subtree inclusion checks + if (id <= 0) throw "invalid id"; + let currentId = id; + this.leftId = currentId + this.children.forEach(edge => { + let map = edge.to; + currentId = map.finalize(currentId + 1); + }); + this.rightId = currentId + 1; + return currentId + 1; + } + + parent() { + if (this.edge === void 0) return void 0; + return this.edge.from; + } + + isDeprecated() { + return this._isDeprecated; + } + + deprecate() { + this._isDeprecated = true; + } + + isRoot() { + return this.edge == void 0 || this.edge.from == void 0; + } + + contains(map) { + return this.leftId < map.leftId && map.rightId < this.rightId; + } + + addEdge(edge) { + this.children.push(edge); + } + + chunkIndex(chunks) { + // Did anybody say O(n)? + for (let i = 0; i < chunks.length; i++) { + let chunk = chunks[i]; + if (chunk.isEmpty()) continue; + if (chunk.last().time < this.time) continue; + return i; + } + return -1; + } + + position(chunks) { + let index = this.chunkIndex(chunks); + let xFrom = (index + 0.5) * kChunkWidth; + let yFrom = kChunkHeight - chunks[index].yOffset(this); + return [xFrom, yFrom]; + } + + transitions() { + let transitions = Object.create(null); + let current = this; + while (current) { + let edge = current.edge; + if (edge && edge.isTransition()) { + transitions[edge.name] = edge; + } + current = current.parent() + } + return transitions; + } + + getType() { + return this.edge === void 0 ? "new" : this.edge.type; + } + + getParents() { + let parents = []; + let current = this.parent(); + while (current) { + parents.push(current); + current = current.parent(); + } + return parents; + } + + static get(id) { + if (!this.cache) return undefined; + return this.cache.get(id); + } + + static set(id, map) { + if (!this.cache) this.cache = new Map(); + this.cache.set(id, map); + } +} + + +// =========================================================================== +class Edge { + constructor(type, name, reason, time, from, to) { + this.type = type; + this.name = name; + this.reason = reason; + this.time = time; + this.from = from; + this.to = to; + this.filePosition = ""; + } + + finishSetup() { + if (this.from) this.from.addEdge(this); + if (this.to) { + this.to.edge = this; + if (this.to === this.from) throw "From and to must be distinct."; + if (this.from) { + if (this.to.time < this.from.time) { + console.error("invalid time order"); + } + let newDepth = this.from.depth + 1; + if (this.to.depth > 0 && this.to.depth != newDepth) { + console.error("Depth has already been initialized"); + } + this.to.depth = newDepth; + } + } + } + + chunkIndex(chunks) { + // Did anybody say O(n)? + for (let i = 0; i < chunks.length; i++) { + let chunk = chunks[i]; + if (chunk.isEmpty()) continue; + if (chunk.last().time < this.time) continue; + return i; + } + return -1; + } + + parentEdge() { + if (!this.from) return undefined; + return this.from.edge; + } + + chainLength() { + let length = 0; + let prev = this; + while (prev) { + prev = this.parent; + length++; + } + return length; + } + + isTransition() { + return this.type == "Transition" + } + + isFastToSlow() { + return this.type == "Normalize" + } + + isSlowToFast() { + return this.type == "SlowToFast" + } + + isInitial() { + return this.type == "InitialMap" + } + + isReplaceDescriptors() { + return this.type == "ReplaceDescriptors" + } + + isCopyAsPrototype() { + return this.reason == "CopyAsPrototype" + } + + isOptimizeAsPrototype() { + return this.reason == "OptimizeAsPrototype" + } + + symbol() { + if (this.isTransition()) return "+"; + if (this.isFastToSlow()) return "⊡"; + if (this.isSlowToFast()) return "⊛"; + if (this.isReplaceDescriptors()) { + if (this.name) return "+"; + return "∥"; + } + return ""; + } + + toString() { + let s = this.symbol(); + if (this.isTransition()) return s + this.name; + if (this.isFastToSlow()) return s + this.reason; + if (this.isCopyAsPrototype()) return s + "Copy as Prototype"; + if (this.isOptimizeAsPrototype()) { + return s + "Optimize as Prototype"; + } + if (this.isReplaceDescriptors() && this.name) { + return this.type + " " + this.symbol() + this.name; + } + return this.type + " " + (this.reason ? this.reason : "") + " " + + (this.name ? this.name : "") + } +} + + +// =========================================================================== +class Marker { + constructor(time, name) { + this.time = parseInt(time); + this.name = name; + } +} + +// =========================================================================== +class Timeline { + constructor() { + this.values = []; + this.transitions = new Map(); + this.markers = []; + this.startTime = 0; + this.endTime = 0; + } + + push(map) { + let time = map.time; + if (!this.isEmpty() && this.last().time > time) { + // Invalid insertion order, might happen without --single-process, + // finding insertion point. + let insertionPoint = this.find(time); + this.values.splice(insertionPoint, map); + } else { + this.values.push(map); + } + if (time > 0) { + this.endTime = Math.max(this.endTime, time); + if (this.startTime === 0) { + this.startTime = time; + } else { + this.startTime = Math.min(this.startTime, time); + } + } + } + + addMarker(time, message) { + this.markers.push(new Marker(time, message)); + } + + finalize() { + let id = 0; + this.forEach(map => { + if (map.isRoot()) id = map.finalize(id + 1); + if (map.edge && map.edge.name) { + let edge = map.edge; + let list = this.transitions.get(edge.name); + if (list === undefined) { + this.transitions.set(edge.name, [edge]); + } else { + list.push(edge); + } + } + }); + this.markers.sort((a, b) => b.time - a.time); + } + + at(index) { + return this.values[index] + } + + isEmpty() { + return this.size() == 0 + } + + size() { + return this.values.length + } + + first() { + return this.values.first() + } + + last() { + return this.values.last() + } + + duration() { + return this.last().time - this.first().time + } + + forEachChunkSize(count, fn) { + const increment = this.duration() / count; + let currentTime = this.first().time + increment; + let index = 0; + for (let i = 0; i < count; i++) { + let nextIndex = this.find(currentTime, index); + let nextTime = currentTime + increment; + fn(index, nextIndex, currentTime, nextTime); + index = nextIndex + currentTime = nextTime; + } + } + + chunkSizes(count) { + let chunks = []; + this.forEachChunkSize(count, (start, end) => chunks.push(end - start)); + return chunks; + } + + chunks(count) { + let chunks = []; + let emptyMarkers = []; + this.forEachChunkSize(count, (start, end, startTime, endTime) => { + let items = this.values.slice(start, end); + let markers = this.markersAt(startTime, endTime); + chunks.push(new Chunk(chunks.length, startTime, endTime, items, markers)); + }); + return chunks; + } + + range(start, end) { + const first = this.find(start); + if (first < 0) return []; + const last = this.find(end, first); + return this.values.slice(first, last); + } + + find(time, offset = 0) { + return this.basicFind(this.values, each => each.time - time, offset); + } + + markersAt(startTime, endTime) { + let start = this.basicFind(this.markers, each => each.time - startTime); + let end = this.basicFind(this.markers, each => each.time - endTime, start); + return this.markers.slice(start, end); + } + + basicFind(array, cmp, offset = 0) { + let min = offset; + let max = array.length; + while (min < max) { + let mid = min + Math.floor((max - min) / 2); + let result = cmp(array[mid]); + if (result > 0) { + max = mid - 1; + } else { + min = mid + 1; + } + } + return min; + } + + count(filter) { + return this.values.reduce((sum, each) => { + return sum + (filter(each) ? 1 : 0); + }, 0); + } + + filter(predicate) { + return this.values.filter(predicate); + } + + filterUniqueTransitions(filter) { + // Returns a list of Maps whose parent is not in the list. + return this.values.filter(map => { + if (!filter(map)) return false; + let parent = map.parent(); + if (!parent) return true; + return !filter(parent); + }); + } + + depthHistogram() { + return this.values.histogram(each => each.depth); + } + + fanOutHistogram() { + return this.values.histogram(each => each.children.length); + } + + forEach(fn) { + return this.values.forEach(fn) + } +} + + +// =========================================================================== +class Chunk { + constructor(index, start, end, items, markers) { + this.index = index; + this.start = start; + this.end = end; + this.items = items; + this.markers = markers + this.height = 0; + } + + isEmpty() { + return this.items.length == 0; + } + + last() { + return this.at(this.size() - 1); + } + + first() { + return this.at(0); + } + + at(index) { + return this.items[index]; + } + + size() { + return this.items.length; + } + + yOffset(map) { + // items[0] == oldest map, displayed at the top of the chunk + // items[n-1] == youngest map, displayed at the bottom of the chunk + return (1 - (this.indexOf(map) + 0.5) / this.size()) * this.height; + } + + indexOf(map) { + return this.items.indexOf(map); + } + + has(map) { + if (this.isEmpty()) return false; + return this.first().time <= map.time && map.time <= this.last().time; + } + + next(chunks) { + return this.findChunk(chunks, 1); + } + + prev(chunks) { + return this.findChunk(chunks, -1); + } + + findChunk(chunks, delta) { + let i = this.index + delta; + let chunk = chunks[i]; + while (chunk && chunk.size() == 0) { + i += delta; + chunk = chunks[i] + } + return chunk; + } + + getTransitionBreakdown() { + return BreakDown(this.items, map => map.getType()) + } + + getUniqueTransitions() { + // Filter out all the maps that have parents within the same chunk. + return this.items.filter(map => !map.parent() || !this.has(map.parent())); + } +} + + +// =========================================================================== +function BreakDown(list, map_fn) { + if (map_fn === void 0) { + map_fn = each => each; + } + let breakdown = {__proto__:null}; + list.forEach(each=> { + let type = map_fn(each); + let v = breakdown[type]; + breakdown[type] = (v | 0) + 1 + }); + return Object.entries(breakdown) + .sort((a,b) => a[1] - b[1]); +} + + +// =========================================================================== +class ArgumentsProcessor extends BaseArgumentsProcessor { + getArgsDispatch() { + return { + '--range': ['range', 'auto,auto', + 'Specify the range limit as [start],[end]' + ], + '--source-map': ['sourceMap', null, + 'Specify the source map that should be used for output' + ] + }; + } + + getDefaultResults() { + return { + logFileName: 'v8.log', + range: 'auto,auto', + }; + } +} diff --git a/deps/v8/tools/node/backport_node.py b/deps/v8/tools/node/backport_node.py new file mode 100755 index 0000000000..50b0b077fa --- /dev/null +++ b/deps/v8/tools/node/backport_node.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Use this script to cherry-pick a V8 commit to backport to a Node.js checkout. + +Requirements: + - Node.js checkout to backport to. + - V8 checkout that contains the commit to cherry-pick. + +Usage: + $ backport_node.py + + This will apply the commit to /deps/v8 and create a commit in + the Node.js checkout, increment patch level, and copy over the original + commit message. + +Optional flags: + --no-review Run `gclient sync` on the V8 checkout before updating. +""" + +import argparse +import os +import subprocess +import re +import sys + +TARGET_SUBDIR = os.path.join("deps", "v8") +VERSION_FILE = os.path.join("include", "v8-version.h") +VERSION_PATTERN = r'(?<=#define V8_PATCH_LEVEL )\d+' + +def FileToText(file_name): + with open(file_name) as f: + return f.read() + +def TextToFile(text, file_name): + with open(file_name, "w") as f: + f.write(text) + + +def Clean(options): + print ">> Cleaning target directory." + subprocess.check_call(["git", "clean", "-fd"], + cwd = os.path.join(options.node_path, TARGET_SUBDIR)) + +def CherryPick(options): + print ">> Apply patch." + patch = subprocess.Popen(["git", "diff-tree", "-p", options.commit], + stdout=subprocess.PIPE, cwd=options.v8_path) + patch.wait() + try: + subprocess.check_output(["git", "apply", "-3", "--directory=%s" % TARGET_SUBDIR], + stdin=patch.stdout, cwd=options.node_path) + except: + print ">> In another shell, please resolve patch conflicts" + print ">> and `git add` affected files." + print ">> Finally continue by entering RESOLVED." + while raw_input("[RESOLVED]") != "RESOLVED": + print ">> You need to type RESOLVED" + +def UpdateVersion(options): + print ">> Increment patch level." + version_file = os.path.join(options.node_path, TARGET_SUBDIR, VERSION_FILE) + text = FileToText(version_file) + def increment(match): + patch = int(match.group(0)) + return str(patch + 1) + text = re.sub(VERSION_PATTERN, increment, text, flags=re.MULTILINE) + TextToFile(text, version_file) + +def CreateCommit(options): + print ">> Creating commit." + # Find short hash from source. + shorthash = subprocess.check_output( + ["git", "rev-parse", "--short", options.commit], + cwd=options.v8_path).strip() + + # Commit message + title = "deps: backport %s from upstream V8" % shorthash + body = subprocess.check_output( + ["git", "log", options.commit, "-1", "--format=%B"], + cwd=options.v8_path).strip() + body = '\n'.join(" " + line for line in body.splitlines()) + + message = title + "\n\nOriginal commit message:\n\n" + body + + # Create commit at target. + review_message = "--no-edit" if options.no_review else "--edit" + git_commands = [ + ["git", "checkout", "-b", "backport_%s" % shorthash], # new branch + ["git", "add", TARGET_SUBDIR], # add files + ["git", "commit", "-m", message, review_message] # new commit + ] + for command in git_commands: + subprocess.check_call(command, cwd=options.node_path) + +def ParseOptions(args): + parser = argparse.ArgumentParser(description="Backport V8 commit to Node.js") + parser.add_argument("v8_path", help="Path to V8 checkout") + parser.add_argument("node_path", help="Path to Node.js checkout") + parser.add_argument("commit", help="Commit to backport") + parser.add_argument("--no-review", action="store_true", + help="Skip editing commit message") + options = parser.parse_args(args) + options.v8_path = os.path.abspath(options.v8_path) + assert os.path.isdir(options.v8_path) + options.node_path = os.path.abspath(options.node_path) + assert os.path.isdir(options.node_path) + return options + +def Main(args): + options = ParseOptions(args) + Clean(options) + try: + CherryPick(options) + UpdateVersion(options) + CreateCommit(options) + except: + print ">> Failed. Resetting." + subprocess.check_output(["git", "reset", "--hard"], cwd=options.node_path) + raise + +if __name__ == "__main__": + Main(sys.argv[1:]) diff --git a/deps/v8/tools/node/build_gn.py b/deps/v8/tools/node/build_gn.py new file mode 100755 index 0000000000..8ab2a635ea --- /dev/null +++ b/deps/v8/tools/node/build_gn.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Use this script to build libv8_monolith.a as dependency for Node.js +Required dependencies can be fetched with fetch_deps.py. + +Usage: build_gn.py []... + +Build flags are passed either as "strings" or numeric value. True/false +are represented as 1/0. E.g. + + v8_promise_internal_field_count=2 + target_cpu="x64" + v8_enable_disassembler=0 +""" + +import os +import subprocess +import sys + +import node_common + +GN_ARGS = [ + "v8_monolithic = true", + "is_component_build = false", + "v8_use_external_startup_data = false", + "use_custom_libcxx = false", + "use_sysroot = false", +] + +BUILD_SUBDIR = "gn" + +# TODO: make this cross-platform. +GN_SUBDIR = ["buildtools", "linux64", "gn"] + +def Build(v8_path, build_path, depot_tools, is_debug, build_flags): + print "Setting GN args." + lines = [] + lines.extend(GN_ARGS) + for flag in build_flags: + flag = flag.replace("=1", "=true") + flag = flag.replace("=0", "=false") + flag = flag.replace("target_cpu=ia32", "target_cpu=\"x86\"") + lines.append(flag) + lines.append("is_debug = %s" % ("true" if is_debug else "false")) + with open(os.path.join(build_path, "args.gn"), "w") as args_file: + args_file.write("\n".join(lines)) + gn = os.path.join(v8_path, *GN_SUBDIR) + subprocess.check_call([gn, "gen", "-C", build_path], cwd=v8_path) + ninja = os.path.join(depot_tools, "ninja") + print "Building." + subprocess.check_call([ninja, "-v", "-C", build_path, "v8_monolith"], + cwd=v8_path) + +def Main(v8_path, build_path, is_debug, build_flags): + # Verify paths. + v8_path = os.path.abspath(v8_path) + assert os.path.isdir(v8_path) + build_path = os.path.abspath(build_path) + build_path = os.path.join(build_path, BUILD_SUBDIR) + if not os.path.isdir(build_path): + os.makedirs(build_path) + + # Check that we have depot tools. + depot_tools = node_common.EnsureDepotTools(v8_path, False) + + # Build with GN. + Build(v8_path, build_path, depot_tools, is_debug, build_flags) + +if __name__ == "__main__": + # TODO: use argparse to parse arguments. + build_mode = sys.argv[1] + v8_path = sys.argv[2] + build_path = sys.argv[3] + assert build_mode == "Debug" or build_mode == "Release" + is_debug = build_mode == "Debug" + # TODO: introduce "--" flag for pass-through flags. + build_flags = sys.argv[4:] + Main(v8_path, build_path, is_debug, build_flags) diff --git a/deps/v8/tools/node/fetch_deps.py b/deps/v8/tools/node/fetch_deps.py new file mode 100755 index 0000000000..a3e6d74917 --- /dev/null +++ b/deps/v8/tools/node/fetch_deps.py @@ -0,0 +1,96 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Use this script to fetch all dependencies for V8 to run build_gn.py. + +Usage: fetch_deps.py +""" + +import os +import subprocess +import sys + +import node_common + +GCLIENT_SOLUTION = [ + { "name" : "v8", + "url" : "https://chromium.googlesource.com/v8/v8.git", + "deps_file" : "DEPS", + "managed" : False, + "custom_deps" : { + # These deps are already part of Node.js. + "v8/base/trace_event/common" : None, + "v8/testing/gtest" : None, + "v8/third_party/jinja2" : None, + "v8/third_party/markupsafe" : None, + # These deps are unnecessary for building. + "v8/test/benchmarks/data" : None, + "v8/testing/gmock" : None, + "v8/test/mozilla/data" : None, + "v8/test/test262/data" : None, + "v8/test/test262/harness" : None, + "v8/test/wasm-js" : None, + "v8/third_party/android_tools" : None, + "v8/third_party/catapult" : None, + "v8/third_party/colorama/src" : None, + "v8/third_party/instrumented_libraries" : None, + "v8/tools/gyp" : None, + "v8/tools/luci-go" : None, + "v8/tools/swarming_client" : None, + }, + "custom_vars": { + "build_for_node" : True, + }, + }, +] + +def EnsureGit(v8_path): + expected_git_dir = os.path.join(v8_path, ".git") + actual_git_dir = subprocess.check_output( + ["git", "rev-parse", "--absolute-git-dir"], cwd=v8_path).strip() + if expected_git_dir == actual_git_dir: + print "V8 is tracked stand-alone by git." + return False + print "Initializing temporary git repository in v8." + subprocess.check_call(["git", "init"], cwd=v8_path) + subprocess.check_call(["git", "commit", "--allow-empty", "-m", "init"], + cwd=v8_path) + return True + +def FetchDeps(v8_path): + # Verify path. + v8_path = os.path.abspath(v8_path) + assert os.path.isdir(v8_path) + + # Check out depot_tools if necessary. + depot_tools = node_common.EnsureDepotTools(v8_path, True) + + temporary_git = EnsureGit(v8_path) + try: + print "Fetching dependencies." + env = os.environ.copy() + # gclient needs to have depot_tools in the PATH. + env["PATH"] = depot_tools + os.pathsep + env["PATH"] + spec = "solutions = %s" % GCLIENT_SOLUTION + subprocess.check_call(["gclient", "sync", "--spec", spec], + cwd=os.path.join(v8_path, os.path.pardir), + env=env) + except: + raise + finally: + if temporary_git: + node_common.UninitGit(v8_path) + # Clean up .gclient_entries file. + gclient_entries = os.path.normpath( + os.path.join(v8_path, os.pardir, ".gclient_entries")) + if os.path.isfile(gclient_entries): + os.remove(gclient_entries) + # Enable building with GN for configure script. + return True + + +if __name__ == "__main__": + FetchDeps(sys.argv[1]) diff --git a/deps/v8/tools/node/node_common.py b/deps/v8/tools/node/node_common.py new file mode 100755 index 0000000000..f7ca3a6a79 --- /dev/null +++ b/deps/v8/tools/node/node_common.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import shutil +import stat +import subprocess + +DEPOT_TOOLS_URL = \ + "https://chromium.googlesource.com/chromium/tools/depot_tools.git" + +def EnsureDepotTools(v8_path, fetch_if_not_exist): + def _Get(v8_path): + depot_tools = os.path.join(v8_path, "_depot_tools") + try: + gclient_path = os.path.join(depot_tools, "gclient") + gclient_check = subprocess.check_output([gclient_path, "--version"]) + if "gclient.py" in gclient_check: + return depot_tools + except: + pass + if fetch_if_not_exist: + print "Checking out depot_tools." + subprocess.check_call(["git", "clone", DEPOT_TOOLS_URL, depot_tools]) + return depot_tools + return None + depot_tools = _Get(v8_path) + assert depot_tools is not None + print "Using depot tools in %s" % depot_tools + return depot_tools + +def UninitGit(v8_path): + print "Uninitializing temporary git repository" + target = os.path.join(v8_path, ".git") + if os.path.isdir(target): + print ">> Cleaning up %s" % target + def OnRmError(func, path, exec_info): + # This might happen on Windows + os.chmod(path, stat.S_IWRITE) + os.unlink(path) + shutil.rmtree(target, onerror=OnRmError) diff --git a/deps/v8/tools/node/test_backport_node.py b/deps/v8/tools/node/test_backport_node.py new file mode 100755 index 0000000000..3c61a402c4 --- /dev/null +++ b/deps/v8/tools/node/test_backport_node.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import shutil +import subprocess +import sys +import tempfile +import unittest + +import backport_node + +# Base paths. +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +TEST_DATA = os.path.join(BASE_DIR, 'testdata') + +def gitify(path): + files = os.listdir(path) + subprocess.check_call(['git', 'init'], cwd=path) + subprocess.check_call(['git', 'add'] + files, cwd=path) + subprocess.check_call(['git', 'commit', '-m', 'Initial'], cwd=path) + +class TestUpdateNode(unittest.TestCase): + def setUp(self): + self.workdir = tempfile.mkdtemp(prefix='tmp_test_node_') + + def tearDown(self): + shutil.rmtree(self.workdir) + + def testUpdate(self): + v8_cwd = os.path.join(self.workdir, 'v8') + node_cwd = os.path.join(self.workdir, 'node') + + # Set up V8 test fixture. + shutil.copytree(src=os.path.join(TEST_DATA, 'v8'), dst=v8_cwd) + gitify(v8_cwd) + + # Set up node test fixture. + shutil.copytree(src=os.path.join(TEST_DATA, 'node'), dst=node_cwd) + gitify(os.path.join(node_cwd)) + + # Add a patch. + with open(os.path.join(v8_cwd, 'v8_foo'), 'w') as f: + f.write('zonk') + subprocess.check_call(['git', 'add', 'v8_foo'], cwd=v8_cwd) + subprocess.check_call(['git', 'commit', '-m', "Title\n\nBody"], cwd=v8_cwd) + commit = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=v8_cwd).strip() + + # Run update script. + backport_node.Main([v8_cwd, node_cwd, commit, "--no-review"]) + + # Check message. + message = subprocess.check_output(['git', 'log', '-1', '--format=%B'], cwd=node_cwd) + self.assertIn('Original commit message:\n\n Title\n\n Body', message) + + # Check patch. + gitlog = subprocess.check_output( + ['git', 'diff', 'master', '--cached', '--', 'deps/v8/v8_foo'], + cwd=node_cwd, + ) + self.assertIn('+zonk', gitlog.strip()) + + # Check version. + version_file = os.path.join(node_cwd, "deps", "v8", "include", "v8-version.h") + self.assertIn('#define V8_PATCH_LEVEL 4322', backport_node.FileToText(version_file)) + +if __name__ == "__main__": + unittest.main() diff --git a/deps/v8/tools/node/test_update_node.py b/deps/v8/tools/node/test_update_node.py new file mode 100755 index 0000000000..1a29b4ea61 --- /dev/null +++ b/deps/v8/tools/node/test_update_node.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import os +import shutil +import subprocess +import sys +import tempfile +import unittest + +import update_node + +# Base paths. +BASE_DIR = os.path.dirname(os.path.abspath(__file__)) +TEST_DATA = os.path.join(BASE_DIR, 'testdata') + +# Expectations. +EXPECTED_GITIGNORE = """ +/testing/gtest/* +!/testing/gtest/include +/testing/gtest/include/* +!/testing/gtest/include/gtest +/testing/gtest/include/gtest/* +!/testing/gtest/include/gtest/gtest_prod.h +!/third_party/jinja2 +!/third_party/markupsafe +/unrelated +""" + +EXPECTED_GIT_DIFF = """ + create mode 100644 deps/v8/base/trace_event/common/common + rename deps/v8/baz/{delete_me => v8_new} (100%) + delete mode 100644 deps/v8/include/v8-version.h + rename deps/v8/{delete_me => new/v8_new} (100%) + create mode 100644 deps/v8/third_party/jinja2/jinja2 + create mode 100644 deps/v8/third_party/markupsafe/markupsafe + create mode 100644 deps/v8/v8_new +""" + +ADDED_FILES = [ + 'v8_new', + 'new/v8_new', + 'baz/v8_new', + 'testing/gtest/gtest_new', + 'testing/gtest/new/gtest_new', + 'testing/gtest/baz/gtest_new', + 'third_party/jinja2/jinja2', + 'third_party/markupsafe/markupsafe' +] + +REMOVED_FILES = [ + 'delete_me', + 'baz/delete_me', + 'testing/gtest/delete_me', + 'testing/gtest/baz/delete_me', +] + +def gitify(path): + files = os.listdir(path) + subprocess.check_call(['git', 'init'], cwd=path) + subprocess.check_call(['git', 'add'] + files, cwd=path) + subprocess.check_call(['git', 'commit', '-m', 'Initial'], cwd=path) + + +class TestUpdateNode(unittest.TestCase): + def setUp(self): + self.workdir = tempfile.mkdtemp(prefix='tmp_test_node_') + + def tearDown(self): + shutil.rmtree(self.workdir) + + def testUpdate(self): + v8_cwd = os.path.join(self.workdir, 'v8') + node_cwd = os.path.join(self.workdir, 'node') + + # Set up V8 test fixture. + shutil.copytree(src=os.path.join(TEST_DATA, 'v8'), dst=v8_cwd) + gitify(v8_cwd) + for repository in update_node.SUB_REPOSITORIES: + gitify(os.path.join(v8_cwd, *repository)) + + # Set up node test fixture. + shutil.copytree(src=os.path.join(TEST_DATA, 'node'), dst=node_cwd) + gitify(os.path.join(node_cwd)) + + # Add a patch. + with open(os.path.join(v8_cwd, 'v8_foo'), 'w') as f: + f.write('zonk') + subprocess.check_call(['git', 'add', 'v8_foo'], cwd=v8_cwd) + + # Run update script. + update_node.Main([v8_cwd, node_cwd, "--commit", "--with-patch"]) + + # Check expectations. + with open(os.path.join(node_cwd, 'deps', 'v8', '.gitignore')) as f: + actual_gitignore = f.read() + self.assertEquals(EXPECTED_GITIGNORE.strip(), actual_gitignore.strip()) + for f in ADDED_FILES: + added_file = os.path.join(node_cwd, 'deps', 'v8', *f.split('/')) + self.assertTrue(os.path.exists(added_file)) + for f in REMOVED_FILES: + removed_file = os.path.join(node_cwd, 'deps', 'v8', *f.split('/')) + self.assertFalse(os.path.exists(removed_file)) + gitlog = subprocess.check_output( + ['git', 'diff', 'master', '--summary'], + cwd=node_cwd, + ) + self.assertEquals(EXPECTED_GIT_DIFF.strip(), gitlog.strip()) + + # Check patch. + gitlog = subprocess.check_output( + ['git', 'diff', 'master', '--cached', '--', 'deps/v8/v8_foo'], + cwd=node_cwd, + ) + self.assertIn('+zonk', gitlog.strip()) + +if __name__ == "__main__": + unittest.main() diff --git a/deps/v8/tools/node/testdata/node/deps/v8/.gitignore b/deps/v8/tools/node/testdata/node/deps/v8/.gitignore new file mode 100644 index 0000000000..23c2024827 --- /dev/null +++ b/deps/v8/tools/node/testdata/node/deps/v8/.gitignore @@ -0,0 +1,7 @@ +/unrelated +/testing/gtest/* +!/testing/gtest/include +/testing/gtest/include/* +!/testing/gtest/include/gtest +/testing/gtest/include/gtest/* +!/testing/gtest/include/gtest/gtest_prod.h diff --git a/deps/v8/tools/node/testdata/node/deps/v8/baz/delete_me b/deps/v8/tools/node/testdata/node/deps/v8/baz/delete_me new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/node/deps/v8/baz/delete_me @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/node/deps/v8/baz/v8_foo b/deps/v8/tools/node/testdata/node/deps/v8/baz/v8_foo new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/node/deps/v8/baz/v8_foo @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/node/deps/v8/delete_me b/deps/v8/tools/node/testdata/node/deps/v8/delete_me new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/node/deps/v8/delete_me @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/node/deps/v8/include/v8-version.h b/deps/v8/tools/node/testdata/node/deps/v8/include/v8-version.h new file mode 100644 index 0000000000..fe8b2712e3 --- /dev/null +++ b/deps/v8/tools/node/testdata/node/deps/v8/include/v8-version.h @@ -0,0 +1,20 @@ +// Copyright 2015 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_INCLUDE_VERSION_H_ // V8_VERSION_H_ conflicts with src/version.h +#define V8_INCLUDE_VERSION_H_ + +// These macros define the version number for the current version. +// NOTE these macros are used by some of the tool scripts and the build +// system so their names cannot be changed without changing the scripts. +#define V8_MAJOR_VERSION 1 +#define V8_MINOR_VERSION 2 +#define V8_BUILD_NUMBER 3 +#define V8_PATCH_LEVEL 4321 + +// Use 1 for candidates and 0 otherwise. +// (Boolean macro values are not supported by all preprocessors.) +#define V8_IS_CANDIDATE_VERSION 0 + +#endif // V8_INCLUDE_VERSION_H_ diff --git a/deps/v8/tools/node/testdata/node/deps/v8/v8_foo b/deps/v8/tools/node/testdata/node/deps/v8/v8_foo new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/node/deps/v8/v8_foo @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/.gitignore b/deps/v8/tools/node/testdata/v8/.gitignore new file mode 100644 index 0000000000..855286229f --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/.gitignore @@ -0,0 +1,4 @@ +/unrelated +/testing/gtest +/third_party/jinja2 +/third_party/markupsafe \ No newline at end of file diff --git a/deps/v8/tools/node/testdata/v8/base/trace_event/common/common b/deps/v8/tools/node/testdata/v8/base/trace_event/common/common new file mode 100644 index 0000000000..e69de29bb2 diff --git a/deps/v8/tools/node/testdata/v8/baz/v8_foo b/deps/v8/tools/node/testdata/v8/baz/v8_foo new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/baz/v8_foo @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/baz/v8_new b/deps/v8/tools/node/testdata/v8/baz/v8_new new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/baz/v8_new @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/new/v8_new b/deps/v8/tools/node/testdata/v8/new/v8_new new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/new/v8_new @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/v8_foo b/deps/v8/tools/node/testdata/v8/v8_foo new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/v8_foo @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/testdata/v8/v8_new b/deps/v8/tools/node/testdata/v8/v8_new new file mode 100644 index 0000000000..eb1ae458f8 --- /dev/null +++ b/deps/v8/tools/node/testdata/v8/v8_new @@ -0,0 +1 @@ +... diff --git a/deps/v8/tools/node/update_node.py b/deps/v8/tools/node/update_node.py new file mode 100755 index 0000000000..ebd953a903 --- /dev/null +++ b/deps/v8/tools/node/update_node.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Use this script to update V8 in a Node.js checkout. + +Requirements: + - Node.js checkout in which V8 should be updated. + - V8 checkout at the commit to which Node.js should be updated. + +Usage: + $ update_node.py + + This will synchronize the content of /deps/v8 with , + and a few V8 dependencies require in Node.js. It will also update .gitignore + appropriately. + +Optional flags: + --gclient Run `gclient sync` on the V8 checkout before updating. + --commit Create commit with the updated V8 in the Node.js checkout. + --with-patch Also include currently staged files in the V8 checkout. +""" + +import argparse +import os +import shutil +import subprocess +import sys +import stat +import node_common + +TARGET_SUBDIR = os.path.join("deps", "v8") + +SUB_REPOSITORIES = [ ["base", "trace_event", "common"], + ["testing", "gtest"], + ["third_party", "jinja2"], + ["third_party", "markupsafe"] ] + +DELETE_FROM_GITIGNORE = [ "/base", + "/testing/gtest", + "/third_party/jinja2", + "/third_party/markupsafe" ] + +# Node.js requires only a single header file from gtest to build V8. +# Both jinja2 and markupsafe are required to generate part of the inspector. +ADD_TO_GITIGNORE = [ "/testing/gtest/*", + "!/testing/gtest/include", + "/testing/gtest/include/*", + "!/testing/gtest/include/gtest", + "/testing/gtest/include/gtest/*", + "!/testing/gtest/include/gtest/gtest_prod.h", + "!/third_party/jinja2", + "!/third_party/markupsafe" ] + +def RunGclient(path): + assert os.path.isdir(path) + print ">> Running gclient sync" + subprocess.check_call(["gclient", "sync", "--nohooks"], cwd=path) + +def CommitPatch(options): + """Makes a dummy commit for the changes in the index. + + On trybots, bot_updated applies the patch to the index. We commit it to make + the fake git clone fetch it into node.js. We can leave the commit, as + bot_update will ensure a clean state on each run. + """ + print ">> Committing patch" + subprocess.check_call( + ["git", "-c", "user.name=fake", "-c", "user.email=fake@chromium.org", + "commit", "--allow-empty", "-m", "placeholder-commit"], + cwd=options.v8_path, + ) + +def UpdateTarget(repository, options): + source = os.path.join(options.v8_path, *repository) + target = os.path.join(options.node_path, TARGET_SUBDIR, *repository) + print ">> Updating target directory %s" % target + print ">> from active branch at %s" % source + if not os.path.exists(target): + os.makedirs(target) + # Remove possible remnants of previous incomplete runs. + node_common.UninitGit(target) + + git_commands = [ + ["git", "init"], # initialize target repo + ["git", "remote", "add", "origin", source], # point to the source repo + ["git", "fetch", "origin", "HEAD"], # sync to the current branch + ["git", "reset", "--hard", "FETCH_HEAD"], # reset to the current branch + ["git", "clean", "-fd"], # delete removed files + ] + try: + for command in git_commands: + subprocess.check_call(command, cwd=target) + except: + raise + finally: + node_common.UninitGit(target) + +def UpdateGitIgnore(options): + file_name = os.path.join(options.node_path, TARGET_SUBDIR, ".gitignore") + assert os.path.isfile(file_name) + print ">> Updating .gitignore with lines" + with open(file_name) as gitignore: + content = gitignore.readlines() + content = [x.strip() for x in content] + for x in DELETE_FROM_GITIGNORE: + if x in content: + print "- %s" % x + content.remove(x) + for x in ADD_TO_GITIGNORE: + if x not in content: + print "+ %s" % x + content.append(x) + content.sort(key=lambda x: x[1:] if x.startswith("!") else x) + with open(file_name, "w") as gitignore: + for x in content: + gitignore.write("%s\n" % x) + +def CreateCommit(options): + print ">> Creating commit." + # Find git hash from source. + githash = subprocess.check_output(["git", "rev-parse", "--short", "HEAD"], + cwd=options.v8_path).strip() + # Create commit at target. + git_commands = [ + ["git", "checkout", "-b", "update_v8_to_%s" % githash], # new branch + ["git", "add", "."], # add files + ["git", "commit", "-m", "Update V8 to %s" % githash] # new commit + ] + for command in git_commands: + subprocess.check_call(command, cwd=options.node_path) + +def ParseOptions(args): + parser = argparse.ArgumentParser(description="Update V8 in Node.js") + parser.add_argument("v8_path", help="Path to V8 checkout") + parser.add_argument("node_path", help="Path to Node.js checkout") + parser.add_argument("--gclient", action="store_true", help="Run gclient sync") + parser.add_argument("--commit", action="store_true", help="Create commit") + parser.add_argument("--with-patch", action="store_true", + help="Apply also staged files") + options = parser.parse_args(args) + assert os.path.isdir(options.v8_path) + options.v8_path = os.path.abspath(options.v8_path) + assert os.path.isdir(options.node_path) + options.node_path = os.path.abspath(options.node_path) + return options + +def Main(args): + options = ParseOptions(args) + if options.gclient: + RunGclient(options.v8_path) + # Commit patch on trybots to main V8 repository. + if options.with_patch: + CommitPatch(options) + # Update main V8 repository. + UpdateTarget([""], options) + # Patch .gitignore before updating sub-repositories. + UpdateGitIgnore(options) + for repo in SUB_REPOSITORIES: + UpdateTarget(repo, options) + if options.commit: + CreateCommit(options) + +if __name__ == "__main__": + Main(sys.argv[1:]) diff --git a/deps/v8/tools/parse-processor b/deps/v8/tools/parse-processor new file mode 100755 index 0000000000..588f120b4e --- /dev/null +++ b/deps/v8/tools/parse-processor @@ -0,0 +1,41 @@ +#!/bin/sh + +# find the name of the log file to process, it must not start with a dash. +log_file="v8.log" +for arg in "$@" +do + if ! expr "X${arg}" : "^X-" > /dev/null; then + log_file=${arg} + fi +done + +tools_path=`cd $(dirname "$0");pwd` +if [ ! "$D8_PATH" ]; then + d8_public=`which d8` + if [ -x "$d8_public" ]; then D8_PATH=$(dirname "$d8_public"); fi +fi +[ -n "$D8_PATH" ] || D8_PATH=$tools_path/.. +d8_exec=$D8_PATH/d8 + +if [ ! -x "$d8_exec" ]; then + D8_PATH=`pwd`/out.gn/optdebug + d8_exec=$D8_PATH/d8 +fi + +if [ ! -x "$d8_exec" ]; then + d8_exec=`grep -m 1 -o '".*/d8"' $log_file | sed 's/"//g'` +fi + +if [ ! -x "$d8_exec" ]; then + echo "d8 shell not found in $D8_PATH" + echo "To build, execute 'make native' from the V8 directory" + exit 1 +fi + +# nm spits out 'no symbols found' messages to stderr. +cat $log_file | $d8_exec --trace-maps --allow-natives-syntax --trace-deopt $tools_path/splaytree.js $tools_path/codemap.js \ + $tools_path/csvparser.js $tools_path/consarray.js \ + $tools_path/profile.js $tools_path/profile_view.js \ + $tools_path/logreader.js $tools_path/arguments.js \ + $tools_path/parse-processor.js $tools_path/SourceMap.js \ + $tools_path/parse-processor-driver.js -- $@ 2>/dev/null diff --git a/deps/v8/tools/parse-processor-driver.js b/deps/v8/tools/parse-processor-driver.js new file mode 100644 index 0000000000..f8f0c15254 --- /dev/null +++ b/deps/v8/tools/parse-processor-driver.js @@ -0,0 +1,33 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +function processArguments(args) { + var processor = new ArgumentsProcessor(args); + if (processor.parse()) { + return processor.result(); + } else { + processor.printUsageAndExit(); + } +} + +function initSourceMapSupport() { + // Pull dev tools source maps into our name space. + SourceMap = WebInspector.SourceMap; + + // Overwrite the load function to load scripts synchronously. + SourceMap.load = function(sourceMapURL) { + var content = readFile(sourceMapURL); + var sourceMapObject = (JSON.parse(content)); + return new SourceMap(sourceMapURL, sourceMapObject); + }; +} + +var params = processArguments(arguments); +var sourceMap = null; +if (params.sourceMap) { + initSourceMapSupport(); + sourceMap = SourceMap.load(params.sourceMap); +} +var parseProcessor = new ParseProcessor(); +parseProcessor.processLogFile(params.logFileName); diff --git a/deps/v8/tools/parse-processor.html b/deps/v8/tools/parse-processor.html new file mode 100644 index 0000000000..e41fffbd5f --- /dev/null +++ b/deps/v8/tools/parse-processor.html @@ -0,0 +1,337 @@ + + + + + + + + + + + + + + + + + + + + +

BEHOLD, THIS IS PARSEROR!

+ +

Usage

+ Run your script with --log-function-events and upload v8.log on this page:
+ /path/to/d8 --log-function-events your_script.js + +

Data

+
+

+ trace entries: 0 +

+
+ +

Result

+
+ + + diff --git a/deps/v8/tools/parse-processor.js b/deps/v8/tools/parse-processor.js new file mode 100644 index 0000000000..30b593a156 --- /dev/null +++ b/deps/v8/tools/parse-processor.js @@ -0,0 +1,918 @@ +// Copyright 2017 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +"use strict"; + + +/** + * A thin wrapper around shell's 'read' function showing a file name on error. + */ +function readFile(fileName) { + try { + return read(fileName); + } catch (e) { + console.log(fileName + ': ' + (e.message || e)); + throw e; + } +} + +// =========================================================================== + +// This is the only true formatting, why? For an international audience the +// confusion between the decimal and thousands separator is big (alternating +// between comma "," vs dot "."). The Swiss formatting uses "'" as a thousands +// separator, dropping most of that confusion. +var numberFormat = new Intl.NumberFormat('de-CH', { + maximumFractionDigits: 2, + minimumFractionDigits: 2, +}); + +function formatNumber(value) { + return formatNumber(value); +} + +function BYTES(bytes, total) { + let units = ['B ', 'kB', 'mB', 'gB']; + let unitIndex = 0; + let value = bytes; + while (value > 1000 && unitIndex < units.length) { + value /= 1000; + unitIndex++; + } + let result = formatNumber(value).padStart(10) + ' ' + units[unitIndex]; + if (total !== void 0 && total != 0) { + result += PERCENT(bytes, total).padStart(5); + } + return result; +} + +function PERCENT(value, total) { + return Math.round(value / total * 100) + "%"; +} + +function timestampMin(list) { + let result = -1; + list.forEach(timestamp => { + if (result === -1) { + result = timestamp; + } else if (timestamp != -1) { + result = Math.min(result, timestamp); + } + }); + return Math.round(result); +} + + +// =========================================================================== +class Script { + constructor(file, id) { + this.file = file; + this.isNative = false; + this.id = id; + if (id === void 0 || id <= 0) { + throw new Error(`Invalid id=${id} for script with file='${file}'`); + } + this.isEval = false; + this.funktions = []; + this.metrics = new Map(); + this.maxNestingLevel = 0; + + this.firstEvent = -1; + this.firstParseEvent = -1; + this.lastParseEvent = -1; + this.executionTimestamp = -1; + this.compileTimestamp = -1; + this.lastEvent = -1; + + this.compileTime = -0.0; + + this.width = 0; + this.bytesTotal = 0; + this.ownBytes = -1; + this.finalized = false; + this.summary = ''; + this.setFile(file); + } + + setFile(name) { + this.file = name; + this.isNative = name.startsWith('native '); + } + + isEmpty() { + return this.funktions.length === 0 + } + + funktionAtPosition(start) { + if (start === 0) throw "position 0 is reserved for the script"; + if (this.finalized) throw 'Finalized script has no source position!'; + return this.funktions[start]; + } + + addMissingFunktions(list) { + if (this.finalized) throw 'script is finalized!'; + list.forEach(fn => { + if (this.funktions[fn.start] === void 0) { + this.addFunktion(fn); + } + }); + } + + addFunktion(fn) { + if (this.finalized) throw 'script is finalized!'; + if (fn.start === void 0) throw "Funktion has no start position"; + if (this.funktions[fn.start] !== void 0) { + fn.print(); + throw "adding same function twice to script"; + } + this.funktions[fn.start] = fn; + } + + finalize() { + this.finalized = true; + // Compact funktions as we no longer need access via start byte position. + this.funktions = this.funktions.filter(each => true); + let parent = null; + let maxNesting = 0; + // Iterate over the Funktions in byte position order. + this.funktions.forEach(fn => { + fn.fromEval = this.isEval; + if (parent === null) { + parent = fn; + } else { + // Walk up the nested chain of Funktions to find the parent. + while (parent !== null && !fn.isNestedIn(parent)) { + parent = parent.parent; + } + fn.parent = parent; + if (parent) { + maxNesting = Math.max(maxNesting, parent.addNestedFunktion(fn)); + } + parent = fn; + } + this.firstParseEvent = this.firstParseEvent === -1 ? + fn.getFirstParseEvent() : + Math.min(this.firstParseEvent, fn.getFirstParseEvent()); + this.lastParseEvent = + Math.max(this.lastParseEvent, fn.getLastParseEvent()); + fn.getFirstEvent(); + if (Number.isNaN(this.lastEvent)) throw "Invalid lastEvent"; + this.lastEvent = Math.max(this.lastEvent, fn.getLastEvent()); + if (Number.isNaN(this.lastEvent)) throw "Invalid lastEvent"; + }); + this.maxNestingLevel = maxNesting; + this.getFirstEvent(); + } + + print() { + console.log(this.toString()); + } + + toString() { + let str = `SCRIPT id=${this.id} file=${this.file}\n` + + `functions[${this.funktions.length}]:`; + this.funktions.forEach(fn => str += fn.toString()); + return str; + } + + getBytes() { + return this.bytesTotal; + } + + getOwnBytes() { + if (this.ownBytes === -1) { + this.ownBytes = this.funktions.reduce( + (bytes, each) => bytes - each.parent == null ? each.getBytes() : 0, + this.getBytes()); + if (this.ownBytes < 0) throw "Own bytes must be positive"; + } + return this.ownBytes; + } + + // Also see Funktion.prototype.getMetricBytes + getMetricBytes(name) { + if (name == 'lazyCompileTimestamp') return this.getOwnBytes(); + return this.getBytes(); + } + + getMetricTime(name) { + return this[name]; + } + + forEach(fn) { + fn(this); + this.funktions.forEach(fn); + } + + // Container helper for TotalScript / Script. + getScripts() { + return [this]; + } + + calculateMetrics(printSummary) { + let log = (str) => this.summary += str + '\n'; + log("SCRIPT: " + this.id); + let all = this.funktions; + if (all.length === 0) return; + + let nofFunktions = all.length; + let ownBytesSum = list => { + return list.reduce((bytes, each) => bytes + each.getOwnBytes(), 0) + }; + + let info = (name, funktions) => { + let ownBytes = ownBytesSum(funktions); + let nofPercent = Math.round(funktions.length / nofFunktions * 100); + let value = (funktions.length + "").padStart(6) + + (nofPercent + "%").padStart(5) + + BYTES(ownBytes, this.bytesTotal).padStart(10); + log((" - " + name).padEnd(20) + value); + this.metrics.set(name + "-bytes", ownBytes); + this.metrics.set(name + "-count", funktions.length); + this.metrics.set(name + "-count-percent", nofPercent); + this.metrics.set(name + "-bytes-percent", + Math.round(ownBytes / this.bytesTotal * 100)); + }; + + log(" - file: " + this.file); + info("scripts", this.getScripts()); + info("functions", all); + info("toplevel fn", all.filter(each => each.isToplevel())); + info("preparsed", all.filter(each => each.preparseTime > 0)); + + + info("fully parsed", all.filter(each => each.parseTime > 0)); + // info("fn parsed", all.filter(each => each.parse2Time > 0)); + // info("resolved", all.filter(each => each.resolutionTime > 0)); + info("executed", all.filter(each => each.executionTimestamp > 0)); + info("forEval", all.filter(each => each.fromEval)); + info("lazy compiled", all.filter(each => each.lazyCompileTimestamp > 0)); + info("eager compiled", all.filter(each => each.compileTimestamp > 0)); + + let parsingCost = new ExecutionCost('parse', all, + each => each.parseTime); + parsingCost.setMetrics(this.metrics); + log(parsingCost.toString()) + + let preParsingCost = new ExecutionCost('preparse', all, + each => each.preparseTime); + preParsingCost.setMetrics(this.metrics); + log(preParsingCost.toString()) + + let resolutionCost = new ExecutionCost('resolution', all, + each => each.resolutionTime); + resolutionCost.setMetrics(this.metrics); + log(resolutionCost.toString()) + + let nesting = new NestingDistribution(all); + nesting.setMetrics(this.metrics); + log(nesting.toString()) + + if (printSummary) console.log(this.summary); + } + + getAccumulatedTimeMetrics(metrics, start, end, delta, incremental = false) { + // Returns an array of the following format: + // [ [start, acc(metric0, start, start), acc(metric1, ...), ...], + // [start+delta, acc(metric0, start, start+delta), ...], + // [start+delta*2, acc(metric0, start, start+delta*2), ...], + // ... + // ] + const timespan = end - start; + const kSteps = Math.ceil(timespan / delta); + // To reduce the time spent iterating over the funktions of this script + // we iterate once over all funktions and add the metric changes to each + // timepoint: + // [ [0, 300, ...], [1, 15, ...], [2, 100, ...], [3, 0, ...] ... ] + // In a second step we accumulate all values: + // [ [0, 300, ...], [1, 315, ...], [2, 415, ...], [3, 415, ...] ... ] + // + // To limit the number of data points required in the resulting graphs, + // only the rows for entries with actual changes are created. + + const metricProperties = ["time"]; + metrics.forEach(each => { + metricProperties.push(each + 'Timestamp'); + metricProperties.push(each + 'Time'); + }); + // Create a packed {rowTemplate} which is copied later-on. + let indexToTime = (t) => (start + t * delta) / kSecondsToMillis; + let rowTemplate = [indexToTime(0)]; + for (let i = 1; i < metricProperties.length; i++) rowTemplate.push(0.0); + // Create rows with 0-time entry. + let rows = new Array(rowTemplate.slice()); + for (let t = 1; t <= kSteps; t++) rows.push(null); + // Create the real metric's property name on the Funktion object. + // Add the increments of each Funktion's metric to the result. + this.forEach(funktionOrScript => { + // Iterate over the Funktion's metric names, position 0 is the time. + for (let i = 1; i < metricProperties.length; i += 2) { + let property = metricProperties[i]; + let timestamp = funktionOrScript[property]; + if (timestamp === void 0) continue; + if (timestamp < 0 || end < timestamp) continue; + let index = Math.floor(timestamp / delta); + let row = rows[index]; + if (row === null) { + // Add a new row if it didn't exist, + row = rows[index] = rowTemplate.slice(); + // .. add the time offset. + row[0] = indexToTime(index); + } + // Add the metric value. + row[i] += funktionOrScript.getMetricBytes(property); + let timeMetricName = metricProperties[i + 1]; + row[i + 1] += funktionOrScript.getMetricTime(timeMetricName); + } + }); + // Create a packed array again with only the valid entries. + // Accumulate the incremental results by adding the metric values from + // the previous time window. + let previous = rows[0]; + let result = [previous]; + for (let t = 1; t < rows.length; t++) { + let current = rows[t]; + if (current === null) { + // Ensure a zero data-point after each non-zero point. + if (incremental && rows[t - 1] !== null) { + let duplicate = rowTemplate.slice(); + duplicate[0] = indexToTime(t); + result.push(duplicate); + } + continue; + } + if (!incremental) { + // Skip i==0 where the corresponding time value in seconds is. + for (let i = 1; i < metricProperties.length; i++) { + current[i] += previous[i]; + } + } + // Make sure we have a data-point in time right before the current one. + if (rows[t - 1] === null) { + let duplicate = (incremental ? rowTemplate : previous).slice(); + duplicate[0] = indexToTime(t - 1); + result.push(duplicate); + } + previous = current; + result.push(current); + } + // Make sure there is an entry at the last position to make sure all graphs + // have the same width. + const lastIndex = rows.length - 1; + if (rows[lastIndex] === null) { + let duplicate = previous.slice(); + duplicate[0] = indexToTime(lastIndex); + result.push(duplicate); + } + return result; + } + + getFunktionsAtTime(time, delta, metric) { + // Returns a list of Funktions whose metric changed in the + // [time-delta, time+delta] range. + return this.funktions.filter( + funktion => funktion.didMetricChange(time, delta, metric)); + return result; + } + + getFirstEvent() { + if (this.firstEvent === -1) { + // TODO(cbruni): add support for network request timestanp + this.firstEvent = this.firstParseEvent; + } + return this.firstEvent; + } +} + + +class TotalScript extends Script { + constructor() { + super('all files', 'all files'); + this.scripts = []; + } + + addAllFunktions(script) { + // funktions is indexed by byte offset and as such not packed. Add every + // Funktion one by one to keep this.funktions packed. + script.funktions.forEach(fn => this.funktions.push(fn)); + this.scripts.push(script); + this.bytesTotal += script.bytesTotal; + } + + // Iterate over all Scripts and nested Funktions. + forEach(fn) { + this.scripts.forEach(script => script.forEach(fn)); + } + + getScripts() { + return this.scripts; + } +} + + +// =========================================================================== + +class NestingDistribution { + constructor(funktions) { + // Stores the nof bytes per function nesting level. + this.accumulator = [0, 0, 0, 0, 0]; + // Max nof bytes encountered at any nesting level. + this.max = 0; + // avg bytes per nesting level. + this.avg = 0; + this.totalBytes = 0; + + funktions.forEach(each => each.accumulateNestingLevel(this.accumulator)); + this.max = this.accumulator.reduce((max, each) => Math.max(max, each), 0); + this.totalBytes = this.accumulator.reduce((sum, each) => sum + each, 0); + for (let i = 0; i < this.accumulator.length; i++) { + this.avg += this.accumulator[i] * i; + } + this.avg /= this.totalBytes; + } + + print() { + console.log(this.toString()) + } + + toString() { + let ticks = " ▁▂▃▄▅▆▇█"; + let accString = this.accumulator.reduce((str, each) => { + let index = Math.round(each / this.max * (ticks.length - 1)); + return str + ticks[index]; + }, ''); + let percent0 = this.accumulator[0] + let percent1 = this.accumulator[1]; + let percent2plus = this.accumulator.slice(2) + .reduce((sum, each) => sum + each, 0); + return " - nesting level: " + + ' avg=' + formatNumber(this.avg) + + ' l0=' + PERCENT(percent0, this.totalBytes) + + ' l1=' + PERCENT(percent1, this.totalBytes) + + ' l2+=' + PERCENT(percent2plus, this.totalBytes) + + ' distribution=[' + accString + ']'; + + } + + setMetrics(dict) {} +} + +class ExecutionCost { + constructor(prefix, funktions, time_fn) { + this.prefix = prefix; + // Time spent on executed functions. + this.executedCost = 0 + // Time spent on not executed functions. + this.nonExecutedCost = 0; + + this.executedCost = funktions.reduce((sum, each) => { + return sum + (each.hasBeenExecuted() ? time_fn(each) : 0) + }, 0); + this.nonExecutedCost = funktions.reduce((sum, each) => { + return sum + (each.hasBeenExecuted() ? 0 : time_fn(each)) + }, 0); + + } + + print() { + console.log(this.toString()) + } + + toString() { + return (' - ' + this.prefix + '-time:').padEnd(24) + + (" executed=" + formatNumber(this.executedCost) + 'ms').padEnd(20) + + " non-executed=" + formatNumber(this.nonExecutedCost) + 'ms'; + } + + setMetrics(dict) { + dict.set('parseMetric', this.executionCost); + dict.set('parseMetricNegative', this.nonExecutionCost); + } +} + +// =========================================================================== +const kNoTimeMetrics = { + __proto__: null, + executionTime: 0, + firstEventTimestamp: 0, + firstParseEventTimestamp: 0, + lastParseTimestamp: 0, + lastEventTimestamp: 0 +}; + +class Funktion { + constructor(name, start, end, script) { + if (start < 0) throw "invalid start position: " + start; + if (end <= 0) throw "invalid end position: " + end; + if (end <= start) throw "invalid start end positions"; + + this.name = name; + this.start = start; + this.end = end; + this.ownBytes = -1; + this.script = script; + this.parent = null; + this.fromEval = false; + this.nested = []; + this.nestingLevel = 0; + + this.preparseTimestamp = -1; + this.parseTimestamp = -1; + this.parse2Timestamp = -1; + this.resolutionTimestamp = -1; + this.lazyCompileTimestamp = -1; + this.compileTimestamp = -1; + this.executionTimestamp = -1; + + this.preparseTime = -0.0; + this.parseTime = -0.0; + this.parse2Time = -0.0; + this.resolutionTime = -0.0; + this.scopeResolutionTime = -0.0; + this.lazyCompileTime = -0.0; + this.compileTime = -0.0; + + // Lazily computed properties. + this.firstEventTimestamp = -1; + this.firstParseEventTimestamp = -1; + this.lastParseTimestamp = -1; + this.lastEventTimestamp = -1; + + if (script) this.script.addFunktion(this); + } + + getMetricBytes(name) { + if (name == 'lazyCompileTimestamp') return this.getOwnBytes(); + return this.getBytes(); + } + + getMetricTime(name) { + if (name in kNoTimeMetrics) return 0; + return this[name]; + } + + getFirstEvent() { + if (this.firstEventTimestamp === -1) { + this.firstEventTimestamp = timestampMin( + [this.parseTimestamp, this.preparseTimestamp, + this.resolutionTimestamp, this.executionTimestamp + ]); + if (!(this.firstEventTimestamp > 0)) { + this.firstEventTimestamp = 0; + } + } + return this.firstEventTimestamp; + } + + getFirstParseEvent() { + if (this.firstParseEventTimestamp === -1) { + this.firstParseEventTimestamp = timestampMin( + [this.parseTimestamp, this.preparseTimestamp, + this.resolutionTimestamp + ]); + if (!(this.firstParseEventTimestamp > 0)) { + this.firstParseEventTimestamp = 0; + } + } + return this.firstParseEventTimestamp; + } + + getLastParseEvent() { + if (this.lastParseTimestamp === -1) { + this.lastParseTimestamp = Math.max( + this.preparseTimestamp + this.preparseTime, + this.parseTimestamp + this.parseTime, + this.resolutionTimestamp + this.resolutionTime); + if (!(this.lastParseTimestamp > 0)) { + this.lastParseTimestamp = 0; + } + } + return this.lastParseTimestamp; + } + + getLastEvent() { + if (this.lastEventTimestamp === -1) { + this.lastEventTimestamp = Math.max( + this.getLastParseEvent(), this.executionTimestamp); + if (!(this.lastEventTimestamp > 0)) { + this.lastEventTimestamp = 0; + } + } + return this.lastEventTimestamp; + } + + isNestedIn(funktion) { + if (this.script != funktion.script) throw "Incompatible script"; + return funktion.start < this.start && this.end <= funktion.end; + } + + isToplevel() { + return this.parent === null + } + + hasBeenExecuted() { + return this.executionTimestamp > 0 + } + + accumulateNestingLevel(accumulator) { + let value = accumulator[this.nestingLevel] || 0; + accumulator[this.nestingLevel] = value + this.getOwnBytes(); + } + + addNestedFunktion(child) { + if (this.script != child.script) throw "Incompatible script"; + if (child == null) throw "Nesting non child"; + this.nested.push(child); + if (this.nested.length > 1) { + // Make sure the nested children don't overlap and have been inserted in + // byte start position order. + let last = this.nested[this.nested.length - 2]; + if (last.end > child.start || last.start > child.start || + last.end > child.end || last.start > child.end) { + throw "Wrongly nested child added"; + } + } + child.nestingLevel = this.nestingLevel + 1; + return child.nestingLevel; + } + + getBytes() { + return this.end - this.start; + } + + getOwnBytes() { + if (this.ownBytes === -1) { + this.ownBytes = this.nested.reduce( + (bytes, each) => bytes - each.getBytes(), + this.getBytes()); + if (this.ownBytes < 0) throw "Own bytes must be positive"; + } + return this.ownBytes; + } + + didMetricChange(time, delta, name) { + let value = this[name + 'Timestamp']; + return (time - delta) <= value && value <= (time + delta); + } + + print() { + console.log(this.toString()); + } + + toString(details = true) { + let result = 'function' + (this.name ? ' ' + this.name : '') + + `() range=${this.start}-${this.end}`; + if (details) result += ` script=${this.script ? this.script.id : 'X'}`; + return result; + } +} + + +// =========================================================================== + +const kTimestampFactor = 1000; +const kSecondsToMillis = 1000; + +function toTimestamp(microseconds) { + return microseconds / kTimestampFactor +} + +function startOf(timestamp, time) { + let result = toTimestamp(timestamp) - time; + if (result < 0) throw "start timestamp cannnot be negative"; + return result; +} + + +class ParseProcessor extends LogReader { + constructor() { + super(); + let config = (processor) => { + // {script file},{script id},{start position},{end position}, + // {time},{timestamp},{function name} + return { + parsers: [null, parseInt, parseInt, parseInt, parseFloat, parseInt, null], + processor: processor + } + }; + + this.dispatchTable_ = { + 'parse-full': config(this.processFull), + 'parse-function': config(this.processFunction), + 'parse-script': config(this.processScript), + 'parse-eval': config(this.processEval), + 'preparse-no-resolution': config(this.processPreparseNoResolution), + 'preparse-resolution': config(this.processPreparseResolution), + 'first-execution': config(this.processFirstExecution), + 'compile-lazy': config(this.processCompileLazy), + 'compile': config(this.processCompile) + }; + + this.idToScript = new Map(); + this.fileToScript = new Map(); + this.nameToFunction = new Map(); + this.scripts = []; + this.totalScript = new TotalScript(); + this.firstEvent = -1; + this.lastParseEvent = -1; + this.lastEvent = -1; + } + + print() { + console.log("scripts:"); + this.idToScript.forEach(script => script.print()); + } + + processString(string) { + let end = string.length; + let current = 0; + let next = 0; + let line; + let i = 0; + let entry; + while (current < end) { + next = string.indexOf("\n", current); + if (next === -1) break; + i++; + line = string.substring(current, next); + current = next + 1; + this.processLogLine(line); + } + this.postProcess(); + } + + processLogFile(fileName) { + this.collectEntries = true + this.lastLogFileName_ = fileName; + var line; + while (line = readline()) { + this.processLogLine(line); + } + this.postProcess(); + } + + postProcess() { + this.scripts = Array.from(this.idToScript.values()) + .filter(each => !each.isNative); + + this.scripts.forEach(script => script.finalize()); + this.scripts.forEach(script => script.calculateMetrics(false)); + + this.firstEvent = + timestampMin(this.scripts.map(each => each.firstEvent)); + this.lastParseEvent = this.scripts.reduce( + (max, script) => Math.max(max, script.lastParseEvent), -1); + this.lastEvent = this.scripts.reduce( + (max, script) => Math.max(max, script.lastEvent), -1); + + this.scripts.forEach(script => this.totalScript.addAllFunktions(script)); + this.totalScript.calculateMetrics(true); + const series = [ + ['firstParseEvent', 'Any Parse Event'], + ['parse', 'Parsing'], + ['preparse', 'Preparsing'], + ['resolution', 'Preparsing with Var. Resolution'], + ['lazyCompile', 'Lazy Compilation'], + ['compile', 'Eager Compilation'], + ['execution', 'First Execution'], + ]; + let metrics = series.map(each => each[0]); + this.totalScript.getAccumulatedTimeMetrics(metrics, 0, this.lastEvent, 10); + }; + + addEntry(entry) { + this.entries.push(entry); + } + + lookupScript(file, id) { + // During preparsing we only have the temporary ranges and no script yet. + let script; + if (this.idToScript.has(id)) { + script = this.idToScript.get(id); + } else { + script = new Script(file, id); + this.idToScript.set(id, script); + } + if (file.length > 0 && script.file.length === 0) { + script.setFile(file); + this.fileToScript.set(file, script); + } + return script; + } + + lookupFunktion(file, scriptId, + startPosition, endPosition, time, timestamp, functionName) { + let script = this.lookupScript(file, scriptId); + let funktion = script.funktionAtPosition(startPosition); + if (funktion === void 0) { + funktion = new Funktion(functionName, startPosition, endPosition, script); + } + return funktion; + } + + processEval(file, scriptId, startPosition, + endPosition, time, timestamp, functionName) { + let script = this.lookupScript(file, scriptId); + script.isEval = true; + } + + processFull(file, scriptId, startPosition, + endPosition, time, timestamp, functionName) { + let funktion = this.lookupFunktion(...arguments); + // TODO(cbruni): this should never happen, emit differen event from the + // parser. + if (funktion.parseTimestamp > 0) return; + funktion.parseTimestamp = startOf(timestamp, time); + funktion.parseTime = time; + } + + processFunction(file, scriptId, startPosition, + endPosition, time, timestamp, functionName) { + let funktion = this.lookupFunktion(...arguments); + funktion.parseTimestamp = startOf(timestamp, time); + funktion.parseTime = time; + } + + processScript(file, scriptId, startPosition, + endPosition, time, timestamp, functionName) { + // TODO timestamp and time + let script = this.lookupScript(file, scriptId); + let ts = startOf(timestamp, time); + script.parseTimestamp = ts; + script.firstEventTimestamp = ts; + script.firstParseEventTimestamp = ts; + script.parseTime = time; + } + + processPreparseResolution(file, scriptId, + startPosition, endPosition, time, timestamp, functionName) { + let funktion = this.lookupFunktion(...arguments); + // TODO(cbruni): this should never happen, emit different event from the + // parser. + if (funktion.resolutionTimestamp > 0) return; + funktion.resolutionTimestamp = startOf(timestamp, time); + funktion.resolutionTime = time; + } + + processPreparseNoResolution(file, scriptId, + startPosition, endPosition, time, timestamp, functionName) { + let funktion = this.lookupFunktion(...arguments); + funktion.preparseTimestamp = startOf(timestamp, time); + funktion.preparseTime = time; + } + + processFirstExecution(file, scriptId, + startPosition, endPosition, time, timestamp, functionName) { + let script = this.lookupScript(file, scriptId); + if (startPosition === 0) { + // undefined = eval fn execution + if (script) { + script.executionTimestamp = toTimestamp(timestamp); + } + } else { + let funktion = script.funktionAtPosition(startPosition); + if (funktion) { + funktion.executionTimestamp = toTimestamp(timestamp); + } else if (functionName.length > 0) { + // throw new Error("Could not find function: " + functionName); + } + } + } + + processCompileLazy(file, scriptId, + startPosition, endPosition, time, timestamp, functionName) { + let funktion = this.lookupFunktion(...arguments); + funktion.lazyCompileTimestamp = startOf(timestamp, time); + funktion.lazyCompileTime = time; + script.firstPar + } + + processCompile(file, scriptId, + startPosition, endPosition, time, timestamp, functionName) { + + let script = this.lookupScript(file, scriptId); + if (startPosition === 0) { + script.compileTimestamp = startOf(timestamp, time); + script.compileTime = time; + script.bytesTotal = endPosition; + } else { + let funktion = script.funktionAtPosition(startPosition); + funktion.compileTimestamp = startOf(timestamp, time); + funktion.compileTime = time; + } + } +} + + +class ArgumentsProcessor extends BaseArgumentsProcessor { + getArgsDispatch() { + return {}; + } + + getDefaultResults() { + return { + logFileName: 'v8.log', + range: 'auto,auto', + }; + } +} diff --git a/deps/v8/tools/perf-compare.py b/deps/v8/tools/perf-compare.py index b7a795b453..75f3c73c6a 100755 --- a/deps/v8/tools/perf-compare.py +++ b/deps/v8/tools/perf-compare.py @@ -12,7 +12,6 @@ Examples: ''' from collections import OrderedDict -import commands import json import math from argparse import ArgumentParser diff --git a/deps/v8/tools/perf-to-html.py b/deps/v8/tools/perf-to-html.py index ac9f53f617..e3979360a7 100755 --- a/deps/v8/tools/perf-to-html.py +++ b/deps/v8/tools/perf-to-html.py @@ -12,7 +12,6 @@ from standard input or via the --filename option. Examples: %prog -f results.json -t "ia32 results" -o results.html ''' -import commands import json import math from optparse import OptionParser diff --git a/deps/v8/tools/predictable_wrapper.py b/deps/v8/tools/predictable_wrapper.py new file mode 100644 index 0000000000..cf7bf00b3f --- /dev/null +++ b/deps/v8/tools/predictable_wrapper.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +""" +Wrapper script for verify-predictable mode. D8 is expected to be compiled with +v8_enable_verify_predictable. + +The actual test command is expected to be passed to this wraper as is. E.g.: +predictable_wrapper.py path/to/d8 --test --predictable --flag1 --flag2 + +The command is run up to three times and the printed allocation hash is +compared. Differences are reported as errors. +""" + +import sys + +from testrunner.local import command + +MAX_TRIES = 3 + +def main(args): + def allocation_str(stdout): + for line in reversed((stdout or '').splitlines()): + if line.startswith('### Allocations = '): + return line + return None + + cmd = command.Command(args[0], args[1:]) + + previous_allocations = None + for run in range(1, MAX_TRIES + 1): + print '### Predictable run #%d' % run + output = cmd.execute() + if output.stdout: + print '### Stdout:' + print output.stdout + if output.stderr: + print '### Stderr:' + print output.stderr + print '### Return code: %s' % output.exit_code + if output.HasTimedOut(): + # If we get a timeout in any run, we are in an unpredictable state. Just + # report it as a failure and don't rerun. + print '### Test timed out' + return 1 + allocations = allocation_str(output.stdout) + if not allocations: + print ('### Test had no allocation output. Ensure this is built ' + 'with v8_enable_verify_predictable and that ' + '--verify-predictable is passed at the cmd line.') + return 2 + if previous_allocations and previous_allocations != allocations: + print '### Allocations differ' + return 3 + if run >= MAX_TRIES: + # No difference on the last run -> report a success. + return 0 + previous_allocations = allocations + # Unreachable. + assert False + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/deps/v8/tools/presubmit.py b/deps/v8/tools/presubmit.py index 2290422459..9ac26ddb16 100755 --- a/deps/v8/tools/presubmit.py +++ b/deps/v8/tools/presubmit.py @@ -554,9 +554,15 @@ def CheckDeps(workspace): def PyTests(workspace): - test_scripts = join(workspace, 'tools', 'release', 'test_scripts.py') - return subprocess.call( - [sys.executable, test_scripts], stdout=subprocess.PIPE) == 0 + result = True + for script in [ + join(workspace, 'tools', 'release', 'test_scripts.py'), + join(workspace, 'tools', 'unittests', 'run_tests_test.py'), + ]: + print 'Running ' + script + result &= subprocess.call( + [sys.executable, script], stdout=subprocess.PIPE) == 0 + return result def GetOptions(): @@ -573,8 +579,8 @@ def Main(): success = True print "Running checkdeps..." success &= CheckDeps(workspace) - print "Running C++ lint check..." if not options.no_lint: + print "Running C++ lint check..." success &= CppLintProcessor().RunOnPath(workspace) print "Running copyright header, trailing whitespaces and " \ "two empty lines between declarations check..." diff --git a/deps/v8/tools/process-heap-prof.py b/deps/v8/tools/process-heap-prof.py deleted file mode 100755 index a26cbf1589..0000000000 --- a/deps/v8/tools/process-heap-prof.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2009 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -# This is an utility for converting V8 heap logs into .hp files that can -# be further processed using 'hp2ps' tool (bundled with GHC and Valgrind) -# to produce heap usage histograms. - -# Sample usage: -# $ ./shell --log-gc script.js -# $ tools/process-heap-prof.py v8.log | hp2ps -c > script-heap-graph.ps -# ('-c' enables color, see hp2ps manual page for more options) -# or -# $ tools/process-heap-prof.py --js-cons-profile v8.log | hp2ps -c > script-heap-graph.ps -# to get JS constructor profile - - -import csv, sys, time, optparse - -def ProcessLogFile(filename, options): - if options.js_cons_profile: - itemname = 'heap-js-cons-item' - else: - itemname = 'heap-sample-item' - - first_call_time = None - sample_time = 0.0 - sampling = False - try: - logfile = open(filename, 'rb') - try: - logreader = csv.reader(logfile) - - print('JOB "v8"') - print('DATE "%s"' % time.asctime(time.localtime())) - print('SAMPLE_UNIT "seconds"') - print('VALUE_UNIT "bytes"') - - for row in logreader: - if row[0] == 'heap-sample-begin' and row[1] == 'Heap': - sample_time = float(row[3])/1000.0 - if first_call_time == None: - first_call_time = sample_time - sample_time -= first_call_time - print('BEGIN_SAMPLE %.2f' % sample_time) - sampling = True - elif row[0] == 'heap-sample-end' and row[1] == 'Heap': - print('END_SAMPLE %.2f' % sample_time) - sampling = False - elif row[0] == itemname and sampling: - print(row[1]), - if options.count: - print('%d' % (int(row[2]))), - if options.size: - print('%d' % (int(row[3]))), - print - finally: - logfile.close() - except: - sys.exit('can\'t open %s' % filename) - - -def BuildOptions(): - result = optparse.OptionParser() - result.add_option("--js_cons_profile", help="Constructor profile", - default=False, action="store_true") - result.add_option("--size", help="Report object size", - default=False, action="store_true") - result.add_option("--count", help="Report object count", - default=False, action="store_true") - return result - - -def ProcessOptions(options): - if not options.size and not options.count: - options.size = True - return True - - -def Main(): - parser = BuildOptions() - (options, args) = parser.parse_args() - if not ProcessOptions(options): - parser.print_help() - sys.exit(); - - if not args: - print "Missing logfile" - sys.exit(); - - ProcessLogFile(args[0], options) - - -if __name__ == '__main__': - sys.exit(Main()) diff --git a/deps/v8/tools/release/backport_node.py b/deps/v8/tools/release/backport_node.py deleted file mode 100755 index 5523525671..0000000000 --- a/deps/v8/tools/release/backport_node.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# Copyright 2017 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Use this script to cherry-pick a V8 commit to backport to a Node.js checkout. - -Requirements: - - Node.js checkout to backport to. - - V8 checkout that contains the commit to cherry-pick. - -Usage: - $ backport_node.py - - This will apply the commit to /deps/v8 and create a commit in - the Node.js checkout, increment patch level, and copy over the original - commit message. - -Optional flags: - --no-review Run `gclient sync` on the V8 checkout before updating. -""" - -import argparse -import os -import subprocess -import re -import sys - -from common_includes import * - -TARGET_SUBDIR = os.path.join("deps", "v8") -VERSION_FILE = os.path.join("include", "v8-version.h") -VERSION_PATTERN = r'(?<=#define V8_PATCH_LEVEL )\d+' - -def Clean(options): - print ">> Cleaning target directory." - subprocess.check_call(["git", "clean", "-fd"], - cwd = os.path.join(options.node_path, TARGET_SUBDIR)) - -def CherryPick(options): - print ">> Apply patch." - patch = subprocess.Popen(["git", "diff-tree", "-p", options.commit], - stdout=subprocess.PIPE, cwd=options.v8_path) - patch.wait() - try: - subprocess.check_output(["git", "apply", "-3", "--directory=%s" % TARGET_SUBDIR], - stdin=patch.stdout, cwd=options.node_path) - except: - print ">> In another shell, please resolve patch conflicts" - print ">> and `git add` affected files." - print ">> Finally continue by entering RESOLVED." - while raw_input("[RESOLVED]") != "RESOLVED": - print ">> You need to type RESOLVED" - -def UpdateVersion(options): - print ">> Increment patch level." - version_file = os.path.join(options.node_path, TARGET_SUBDIR, VERSION_FILE) - text = FileToText(version_file) - def increment(match): - patch = int(match.group(0)) - return str(patch + 1) - text = re.sub(VERSION_PATTERN, increment, text, flags=re.MULTILINE) - TextToFile(text, version_file) - -def CreateCommit(options): - print ">> Creating commit." - # Find short hash from source. - shorthash = subprocess.check_output( - ["git", "rev-parse", "--short", options.commit], - cwd=options.v8_path).strip() - - # Commit message - title = "deps: backport %s from upstream V8" % shorthash - body = subprocess.check_output( - ["git", "log", options.commit, "-1", "--format=%B"], - cwd=options.v8_path).strip() - body = '\n'.join(" " + line for line in body.splitlines()) - - message = title + "\n\nOriginal commit message:\n\n" + body - - # Create commit at target. - review_message = "--no-edit" if options.no_review else "--edit" - git_commands = [ - ["git", "checkout", "-b", "backport_%s" % shorthash], # new branch - ["git", "add", TARGET_SUBDIR], # add files - ["git", "commit", "-m", message, review_message] # new commit - ] - for command in git_commands: - subprocess.check_call(command, cwd=options.node_path) - -def ParseOptions(args): - parser = argparse.ArgumentParser(description="Backport V8 commit to Node.js") - parser.add_argument("v8_path", help="Path to V8 checkout") - parser.add_argument("node_path", help="Path to Node.js checkout") - parser.add_argument("commit", help="Commit to backport") - parser.add_argument("--no-review", action="store_true", - help="Skip editing commit message") - options = parser.parse_args(args) - options.v8_path = os.path.abspath(options.v8_path) - assert os.path.isdir(options.v8_path) - options.node_path = os.path.abspath(options.node_path) - assert os.path.isdir(options.node_path) - return options - -def Main(args): - options = ParseOptions(args) - Clean(options) - try: - CherryPick(options) - UpdateVersion(options) - CreateCommit(options) - except: - print ">> Failed. Resetting." - subprocess.check_output(["git", "reset", "--hard"], cwd=options.node_path) - raise - -if __name__ == "__main__": - Main(sys.argv[1:]) diff --git a/deps/v8/tools/release/test_backport_node.py b/deps/v8/tools/release/test_backport_node.py deleted file mode 100755 index f9c015baf1..0000000000 --- a/deps/v8/tools/release/test_backport_node.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python -# Copyright 2017 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import shutil -import subprocess -import sys -import tempfile -import unittest - -from common_includes import FileToText -import backport_node - -# Base paths. -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -TEST_DATA = os.path.join(BASE_DIR, 'testdata') - -def gitify(path): - files = os.listdir(path) - subprocess.check_call(['git', 'init'], cwd=path) - subprocess.check_call(['git', 'add'] + files, cwd=path) - subprocess.check_call(['git', 'commit', '-m', 'Initial'], cwd=path) - -class TestUpdateNode(unittest.TestCase): - def setUp(self): - self.workdir = tempfile.mkdtemp(prefix='tmp_test_node_') - - def tearDown(self): - shutil.rmtree(self.workdir) - - def testUpdate(self): - v8_cwd = os.path.join(self.workdir, 'v8') - node_cwd = os.path.join(self.workdir, 'node') - - # Set up V8 test fixture. - shutil.copytree(src=os.path.join(TEST_DATA, 'v8'), dst=v8_cwd) - gitify(v8_cwd) - - # Set up node test fixture. - shutil.copytree(src=os.path.join(TEST_DATA, 'node'), dst=node_cwd) - gitify(os.path.join(node_cwd)) - - # Add a patch. - with open(os.path.join(v8_cwd, 'v8_foo'), 'w') as f: - f.write('zonk') - subprocess.check_call(['git', 'add', 'v8_foo'], cwd=v8_cwd) - subprocess.check_call(['git', 'commit', '-m', "Title\n\nBody"], cwd=v8_cwd) - commit = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=v8_cwd).strip() - - # Run update script. - backport_node.Main([v8_cwd, node_cwd, commit, "--no-review"]) - - # Check message. - message = subprocess.check_output(['git', 'log', '-1', '--format=%B'], cwd=node_cwd) - self.assertIn('Original commit message:\n\n Title\n\n Body', message) - - # Check patch. - gitlog = subprocess.check_output( - ['git', 'diff', 'master', '--cached', '--', 'deps/v8/v8_foo'], - cwd=node_cwd, - ) - self.assertIn('+zonk', gitlog.strip()) - - # Check version. - version_file = os.path.join(node_cwd, "deps", "v8", "include", "v8-version.h") - self.assertIn('#define V8_PATCH_LEVEL 4322', FileToText(version_file)) - -if __name__ == "__main__": - unittest.main() diff --git a/deps/v8/tools/release/test_update_node.py b/deps/v8/tools/release/test_update_node.py deleted file mode 100755 index bff3d08c2f..0000000000 --- a/deps/v8/tools/release/test_update_node.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# Copyright 2017 the V8 project authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import os -import shutil -import subprocess -import sys -import tempfile -import unittest - -import update_node - -# Base paths. -BASE_DIR = os.path.dirname(os.path.abspath(__file__)) -TEST_DATA = os.path.join(BASE_DIR, 'testdata') - -# Expectations. -EXPECTED_GITIGNORE = """ -/testing/gtest/* -!/testing/gtest/include -/testing/gtest/include/* -!/testing/gtest/include/gtest -/testing/gtest/include/gtest/* -!/testing/gtest/include/gtest/gtest_prod.h -!/third_party/jinja2 -!/third_party/markupsafe -/unrelated -""" - -EXPECTED_GIT_DIFF = """ - create mode 100644 deps/v8/base/trace_event/common/common - rename deps/v8/baz/{delete_me => v8_new} (100%) - rename deps/v8/{delete_me => new/v8_new} (100%) - create mode 100644 deps/v8/third_party/jinja2/jinja2 - create mode 100644 deps/v8/third_party/markupsafe/markupsafe - create mode 100644 deps/v8/v8_new -""" - -ADDED_FILES = [ - 'v8_new', - 'new/v8_new', - 'baz/v8_new', - 'testing/gtest/gtest_new', - 'testing/gtest/new/gtest_new', - 'testing/gtest/baz/gtest_new', - 'third_party/jinja2/jinja2', - 'third_party/markupsafe/markupsafe' -] - -REMOVED_FILES = [ - 'delete_me', - 'baz/delete_me', - 'testing/gtest/delete_me', - 'testing/gtest/baz/delete_me', -] - -def gitify(path): - files = os.listdir(path) - subprocess.check_call(['git', 'init'], cwd=path) - subprocess.check_call(['git', 'add'] + files, cwd=path) - subprocess.check_call(['git', 'commit', '-m', 'Initial'], cwd=path) - - -class TestUpdateNode(unittest.TestCase): - def setUp(self): - self.workdir = tempfile.mkdtemp(prefix='tmp_test_node_') - - def tearDown(self): - shutil.rmtree(self.workdir) - - def testUpdate(self): - v8_cwd = os.path.join(self.workdir, 'v8') - node_cwd = os.path.join(self.workdir, 'node') - - # Set up V8 test fixture. - shutil.copytree(src=os.path.join(TEST_DATA, 'v8'), dst=v8_cwd) - gitify(v8_cwd) - for repository in update_node.SUB_REPOSITORIES: - gitify(os.path.join(v8_cwd, *repository)) - - # Set up node test fixture. - shutil.copytree(src=os.path.join(TEST_DATA, 'node'), dst=node_cwd) - gitify(os.path.join(node_cwd)) - - # Add a patch. - with open(os.path.join(v8_cwd, 'v8_foo'), 'w') as f: - f.write('zonk') - subprocess.check_call(['git', 'add', 'v8_foo'], cwd=v8_cwd) - - # Run update script. - update_node.Main([v8_cwd, node_cwd, "--commit", "--with-patch"]) - - # Check expectations. - with open(os.path.join(node_cwd, 'deps', 'v8', '.gitignore')) as f: - actual_gitignore = f.read() - self.assertEquals(EXPECTED_GITIGNORE.strip(), actual_gitignore.strip()) - for f in ADDED_FILES: - added_file = os.path.join(node_cwd, 'deps', 'v8', *f.split('/')) - self.assertTrue(os.path.exists(added_file)) - for f in REMOVED_FILES: - removed_file = os.path.join(node_cwd, 'deps', 'v8', *f.split('/')) - self.assertFalse(os.path.exists(removed_file)) - gitlog = subprocess.check_output( - ['git', 'diff', 'master', '--summary'], - cwd=node_cwd, - ) - self.assertEquals(EXPECTED_GIT_DIFF.strip(), gitlog.strip()) - - # Check patch. - gitlog = subprocess.check_output( - ['git', 'diff', 'master', '--cached', '--', 'deps/v8/v8_foo'], - cwd=node_cwd, - ) - self.assertIn('+zonk', gitlog.strip()) - -if __name__ == "__main__": - unittest.main() diff --git a/deps/v8/tools/release/testdata/node/deps/v8/.gitignore b/deps/v8/tools/release/testdata/node/deps/v8/.gitignore deleted file mode 100644 index 23c2024827..0000000000 --- a/deps/v8/tools/release/testdata/node/deps/v8/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -/unrelated -/testing/gtest/* -!/testing/gtest/include -/testing/gtest/include/* -!/testing/gtest/include/gtest -/testing/gtest/include/gtest/* -!/testing/gtest/include/gtest/gtest_prod.h diff --git a/deps/v8/tools/release/testdata/node/deps/v8/baz/delete_me b/deps/v8/tools/release/testdata/node/deps/v8/baz/delete_me deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/node/deps/v8/baz/delete_me +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/node/deps/v8/baz/v8_foo b/deps/v8/tools/release/testdata/node/deps/v8/baz/v8_foo deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/node/deps/v8/baz/v8_foo +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/node/deps/v8/delete_me b/deps/v8/tools/release/testdata/node/deps/v8/delete_me deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/node/deps/v8/delete_me +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/node/deps/v8/include/v8-version.h b/deps/v8/tools/release/testdata/node/deps/v8/include/v8-version.h deleted file mode 100644 index fe8b2712e3..0000000000 --- a/deps/v8/tools/release/testdata/node/deps/v8/include/v8-version.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2015 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef V8_INCLUDE_VERSION_H_ // V8_VERSION_H_ conflicts with src/version.h -#define V8_INCLUDE_VERSION_H_ - -// These macros define the version number for the current version. -// NOTE these macros are used by some of the tool scripts and the build -// system so their names cannot be changed without changing the scripts. -#define V8_MAJOR_VERSION 1 -#define V8_MINOR_VERSION 2 -#define V8_BUILD_NUMBER 3 -#define V8_PATCH_LEVEL 4321 - -// Use 1 for candidates and 0 otherwise. -// (Boolean macro values are not supported by all preprocessors.) -#define V8_IS_CANDIDATE_VERSION 0 - -#endif // V8_INCLUDE_VERSION_H_ diff --git a/deps/v8/tools/release/testdata/node/deps/v8/v8_foo b/deps/v8/tools/release/testdata/node/deps/v8/v8_foo deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/node/deps/v8/v8_foo +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/v8/.gitignore b/deps/v8/tools/release/testdata/v8/.gitignore deleted file mode 100644 index 855286229f..0000000000 --- a/deps/v8/tools/release/testdata/v8/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/unrelated -/testing/gtest -/third_party/jinja2 -/third_party/markupsafe \ No newline at end of file diff --git a/deps/v8/tools/release/testdata/v8/base/trace_event/common/common b/deps/v8/tools/release/testdata/v8/base/trace_event/common/common deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/deps/v8/tools/release/testdata/v8/baz/v8_foo b/deps/v8/tools/release/testdata/v8/baz/v8_foo deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/v8/baz/v8_foo +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/v8/baz/v8_new b/deps/v8/tools/release/testdata/v8/baz/v8_new deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/v8/baz/v8_new +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/v8/new/v8_new b/deps/v8/tools/release/testdata/v8/new/v8_new deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/v8/new/v8_new +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/v8/v8_foo b/deps/v8/tools/release/testdata/v8/v8_foo deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/v8/v8_foo +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/release/testdata/v8/v8_new b/deps/v8/tools/release/testdata/v8/v8_new deleted file mode 100644 index eb1ae458f8..0000000000 --- a/deps/v8/tools/release/testdata/v8/v8_new +++ /dev/null @@ -1 +0,0 @@ -... diff --git a/deps/v8/tools/run-num-fuzzer.isolate b/deps/v8/tools/run-num-fuzzer.isolate index 4bd3d8b6c0..d0aca421a7 100644 --- a/deps/v8/tools/run-num-fuzzer.isolate +++ b/deps/v8/tools/run-num-fuzzer.isolate @@ -14,6 +14,7 @@ 'includes': [ 'testrunner/testrunner.isolate', '../src/d8.isolate', + '../test/benchmarks/benchmarks.isolate', '../test/mjsunit/mjsunit.isolate', '../test/webkit/webkit.isolate', ], diff --git a/deps/v8/tools/run_perf.py b/deps/v8/tools/run_perf.py index 0f1646d9ea..3823eb510c 100755 --- a/deps/v8/tools/run_perf.py +++ b/deps/v8/tools/run_perf.py @@ -106,7 +106,7 @@ import re import subprocess import sys -from testrunner.local import commands +from testrunner.local import command from testrunner.local import utils ARCH_GUESS = utils.DefaultArch() @@ -493,15 +493,23 @@ class RunnableConfig(GraphConfig): suffix = ["--"] + self.test_flags if self.test_flags else [] return self.flags + (extra_flags or []) + [self.main] + suffix - def GetCommand(self, shell_dir, extra_flags=None): + def GetCommand(self, cmd_prefix, shell_dir, extra_flags=None): # TODO(machenbach): This requires +.exe if run on windows. extra_flags = extra_flags or [] - cmd = [os.path.join(shell_dir, self.binary)] - if self.binary.endswith(".py"): - cmd = [sys.executable] + cmd if self.binary != 'd8' and '--prof' in extra_flags: print "Profiler supported only on a benchmark run with d8" - return cmd + self.GetCommandFlags(extra_flags=extra_flags) + + if self.process_size: + cmd_prefix = ["/usr/bin/time", "--format=MaxMemory: %MKB"] + cmd_prefix + if self.binary.endswith('.py'): + # Copy cmd_prefix instead of update (+=). + cmd_prefix = cmd_prefix + [sys.executable] + + return command.Command( + cmd_prefix=cmd_prefix, + shell=os.path.join(shell_dir, self.binary), + args=self.GetCommandFlags(extra_flags=extra_flags), + timeout=self.timeout or 60) def Run(self, runner, trybot): """Iterates over several runs and handles the output for all traces.""" @@ -677,18 +685,9 @@ class DesktopPlatform(Platform): suffix = ' - secondary' if secondary else '' shell_dir = self.shell_dir_secondary if secondary else self.shell_dir title = ">>> %%s (#%d)%s:" % ((count + 1), suffix) - if runnable.process_size: - command = ["/usr/bin/time", "--format=MaxMemory: %MKB"] - else: - command = [] - - command += self.command_prefix + runnable.GetCommand(shell_dir, - self.extra_flags) + cmd = runnable.GetCommand(self.command_prefix, shell_dir, self.extra_flags) try: - output = commands.Execute( - command, - timeout=runnable.timeout, - ) + output = cmd.execute() except OSError as e: # pragma: no cover print title % "OSError" print e diff --git a/deps/v8/tools/testrunner/PRESUBMIT.py b/deps/v8/tools/testrunner/PRESUBMIT.py new file mode 100644 index 0000000000..7f7596a85d --- /dev/null +++ b/deps/v8/tools/testrunner/PRESUBMIT.py @@ -0,0 +1,8 @@ +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +def CheckChangeOnCommit(input_api, output_api): + tests = input_api.canned_checks.GetUnitTestsInDirectory( + input_api, output_api, '../unittests', whitelist=['run_tests_test.py$']) + return input_api.RunTests(tests) diff --git a/deps/v8/tools/testrunner/base_runner.py b/deps/v8/tools/testrunner/base_runner.py index b6ef6fb5cd..8fc09eed7b 100644 --- a/deps/v8/tools/testrunner/base_runner.py +++ b/deps/v8/tools/testrunner/base_runner.py @@ -3,6 +3,7 @@ # found in the LICENSE file. +from collections import OrderedDict import json import optparse import os @@ -16,8 +17,11 @@ sys.path.insert( os.path.dirname(os.path.abspath(__file__)))) +from local import testsuite from local import utils +from testproc.shard import ShardProc + BASE_DIR = ( os.path.dirname( @@ -62,6 +66,16 @@ TEST_MAP = { "intl", "unittests", ], + # This needs to stay in sync with test/d8_default.isolate. + "d8_default": [ + # TODO(machenbach): uncomment after infra side lands. + #"debugger", + "mjsunit", + "webkit", + #"message", + #"preparser", + #"intl", + ], # This needs to stay in sync with test/optimize_for_size.isolate. "optimize_for_size": [ "debugger", @@ -177,16 +191,19 @@ class BuildConfig(object): class BaseTestRunner(object): - def __init__(self): + def __init__(self, basedir=None): + self.basedir = basedir or BASE_DIR self.outdir = None self.build_config = None self.mode_name = None self.mode_options = None - def execute(self): + def execute(self, sys_args=None): + if sys_args is None: # pragma: no cover + sys_args = sys.argv[1:] try: parser = self._create_parser() - options, args = self._parse_args(parser) + options, args = self._parse_args(parser, sys_args) self._load_build_config(options) @@ -197,10 +214,15 @@ class BaseTestRunner(object): parser.print_help() raise + args = self._parse_test_args(args) + suites = self._get_suites(args, options.verbose) + self._setup_env() - return self._do_execute(options, args) + return self._do_execute(suites, args, options) except TestRunnerError: return 1 + except KeyboardInterrupt: + return 2 def _create_parser(self): parser = optparse.OptionParser() @@ -227,15 +249,21 @@ class BaseTestRunner(object): "directory will be used") parser.add_option("-v", "--verbose", help="Verbose output", default=False, action="store_true") + parser.add_option("--shard-count", + help="Split tests into this number of shards", + default=1, type="int") + parser.add_option("--shard-run", + help="Run this shard from the split up tests.", + default=1, type="int") def _add_parser_options(self, parser): pass - def _parse_args(self, parser): - options, args = parser.parse_args() + def _parse_args(self, parser, sys_args): + options, args = parser.parse_args(sys_args) if any(map(lambda v: v and ',' in v, - [options.arch, options.mode])): + [options.arch, options.mode])): # pragma: no cover print 'Multiple arch/mode are deprecated' raise TestRunnerError() @@ -248,7 +276,7 @@ class BaseTestRunner(object): except TestRunnerError: pass - if not self.build_config: + if not self.build_config: # pragma: no cover print 'Failed to load build config' raise TestRunnerError @@ -274,14 +302,14 @@ class BaseTestRunner(object): '%s.%s' % (options.arch, options.mode)) for outdir in outdirs(): - yield os.path.join(BASE_DIR, outdir) + yield os.path.join(self.basedir, outdir) # buildbot option if options.mode: - yield os.path.join(BASE_DIR, outdir, options.mode) + yield os.path.join(self.basedir, outdir, options.mode) def _get_gn_outdir(self): - gn_out_dir = os.path.join(BASE_DIR, DEFAULT_OUT_GN) + gn_out_dir = os.path.join(self.basedir, DEFAULT_OUT_GN) latest_timestamp = -1 latest_config = None for gn_config in os.listdir(gn_out_dir): @@ -305,7 +333,7 @@ class BaseTestRunner(object): with open(build_config_path) as f: try: build_config_json = json.load(f) - except Exception: + except Exception: # pragma: no cover print("%s exists but contains invalid json. Is your build up-to-date?" % build_config_path) raise TestRunnerError() @@ -324,7 +352,7 @@ class BaseTestRunner(object): build_config_mode = 'debug' if self.build_config.is_debug else 'release' if options.mode: - if options.mode not in MODES: + if options.mode not in MODES: # pragma: no cover print '%s mode is invalid' % options.mode raise TestRunnerError() if MODES[options.mode].execution_mode != build_config_mode: @@ -346,7 +374,7 @@ class BaseTestRunner(object): options.arch, self.build_config.arch)) raise TestRunnerError() - if options.shell_dir: + if options.shell_dir: # pragma: no cover print('Warning: --shell-dir is deprecated. Searching for executables in ' 'build directory (%s) instead.' % self.outdir) @@ -364,7 +392,7 @@ class BaseTestRunner(object): def _setup_env(self): # Use the v8 root as cwd as some test cases use "load" with relative paths. - os.chdir(BASE_DIR) + os.chdir(self.basedir) # Many tests assume an English interface. os.environ['LANG'] = 'en_US.UTF-8' @@ -403,7 +431,7 @@ class BaseTestRunner(object): if self.build_config.tsan: suppressions_file = os.path.join( - BASE_DIR, + self.basedir, 'tools', 'sanitizers', 'tsan_suppressions.txt') @@ -418,7 +446,7 @@ class BaseTestRunner(object): def _get_external_symbolizer_option(self): external_symbolizer_path = os.path.join( - BASE_DIR, + self.basedir, 'third_party', 'llvm-build', 'Release+Asserts', @@ -432,7 +460,84 @@ class BaseTestRunner(object): return 'external_symbolizer_path=%s' % external_symbolizer_path + def _parse_test_args(self, args): + if not args: + args = self._get_default_suite_names() + + # Expand arguments with grouped tests. The args should reflect the list + # of suites as otherwise filters would break. + def expand_test_group(name): + return TEST_MAP.get(name, [name]) + + return reduce(list.__add__, map(expand_test_group, args), []) + + def _get_suites(self, args, verbose=False): + names = self._args_to_suite_names(args) + return self._load_suites(names, verbose) + + def _args_to_suite_names(self, args): + # Use default tests if no test configuration was provided at the cmd line. + all_names = set(utils.GetSuitePaths(os.path.join(self.basedir, 'test'))) + args_names = OrderedDict([(arg.split('/')[0], None) for arg in args]) # set + return [name for name in args_names if name in all_names] + + def _get_default_suite_names(self): + return [] + + def _expand_test_group(self, name): + return TEST_MAP.get(name, [name]) + + def _load_suites(self, names, verbose=False): + def load_suite(name): + if verbose: + print '>>> Loading test suite: %s' % name + return testsuite.TestSuite.LoadTestSuite( + os.path.join(self.basedir, 'test', name)) + return map(load_suite, names) # TODO(majeski): remove options & args parameters - def _do_execute(self, options, args): + def _do_execute(self, suites, args, options): raise NotImplementedError() + + def _create_shard_proc(self, options): + myid, count = self._get_shard_info(options) + if count == 1: + return None + return ShardProc(myid - 1, count) + + def _get_shard_info(self, options): + """ + Returns pair: + (id of the current shard [1; number of shards], number of shards) + """ + # Read gtest shard configuration from environment (e.g. set by swarming). + # If none is present, use values passed on the command line. + shard_count = int( + os.environ.get('GTEST_TOTAL_SHARDS', options.shard_count)) + shard_run = os.environ.get('GTEST_SHARD_INDEX') + if shard_run is not None: + # The v8 shard_run starts at 1, while GTEST_SHARD_INDEX starts at 0. + shard_run = int(shard_run) + 1 + else: + shard_run = options.shard_run + + if options.shard_count > 1: + # Log if a value was passed on the cmd line and it differs from the + # environment variables. + if options.shard_count != shard_count: # pragma: no cover + print("shard_count from cmd line differs from environment variable " + "GTEST_TOTAL_SHARDS") + if (options.shard_run > 1 and + options.shard_run != shard_run): # pragma: no cover + print("shard_run from cmd line differs from environment variable " + "GTEST_SHARD_INDEX") + + if shard_run < 1 or shard_run > shard_count: + # TODO(machenbach): Turn this into an assert. If that's wrong on the + # bots, printing will be quite useless. Or refactor this code to make + # sure we get a return code != 0 after testing if we got here. + print "shard-run not a valid number, should be in [1:shard-count]" + print "defaulting back to running all tests" + return 1, 1 + + return shard_run, shard_count diff --git a/deps/v8/tools/testrunner/deopt_fuzzer.py b/deps/v8/tools/testrunner/deopt_fuzzer.py index 75878d442c..5e6b79f5e9 100755 --- a/deps/v8/tools/testrunner/deopt_fuzzer.py +++ b/deps/v8/tools/testrunner/deopt_fuzzer.py @@ -26,7 +26,7 @@ from testrunner.local import verbose from testrunner.objects import context -DEFAULT_TESTS = ["mjsunit", "webkit"] +DEFAULT_SUITES = ["mjsunit", "webkit"] TIMEOUT_DEFAULT = 60 # Double the timeout for these: @@ -37,8 +37,8 @@ DISTRIBUTION_MODES = ["smooth", "random"] class DeoptFuzzer(base_runner.BaseTestRunner): - def __init__(self): - super(DeoptFuzzer, self).__init__() + def __init__(self, *args, **kwargs): + super(DeoptFuzzer, self).__init__(*args, **kwargs) class RandomDistribution: def __init__(self, seed=None): @@ -136,12 +136,6 @@ class DeoptFuzzer(base_runner.BaseTestRunner): " (verbose, dots, color, mono)"), choices=progress.PROGRESS_INDICATORS.keys(), default="mono") - parser.add_option("--shard-count", - help="Split testsuites into this number of shards", - default=1, type="int") - parser.add_option("--shard-run", - help="Run this shard from the split up tests.", - default=1, type="int") parser.add_option("--seed", help="The seed for the random distribution", type="int") parser.add_option("-t", "--timeout", help="Timeout in seconds", @@ -184,47 +178,6 @@ class DeoptFuzzer(base_runner.BaseTestRunner): options.coverage_lift = 0 return True - def _shard_tests(self, tests, shard_count, shard_run): - if shard_count < 2: - return tests - if shard_run < 1 or shard_run > shard_count: - print "shard-run not a valid number, should be in [1:shard-count]" - print "defaulting back to running all tests" - return tests - count = 0 - shard = [] - for test in tests: - if count % shard_count == shard_run - 1: - shard.append(test) - count += 1 - return shard - - def _do_execute(self, options, args): - suite_paths = utils.GetSuitePaths(join(base_runner.BASE_DIR, "test")) - - if len(args) == 0: - suite_paths = [ s for s in suite_paths if s in DEFAULT_TESTS ] - else: - args_suites = set() - for arg in args: - suite = arg.split(os.path.sep)[0] - if not suite in args_suites: - args_suites.add(suite) - suite_paths = [ s for s in suite_paths if s in args_suites ] - - suites = [] - for root in suite_paths: - suite = testsuite.TestSuite.LoadTestSuite( - os.path.join(base_runner.BASE_DIR, "test", root)) - if suite: - suites.append(suite) - - try: - return self._execute(args, options, suites) - except KeyboardInterrupt: - return 2 - - def _calculate_n_tests(self, m, options): """Calculates the number of tests from m deopt points with exponential coverage. @@ -235,8 +188,10 @@ class DeoptFuzzer(base_runner.BaseTestRunner): l = float(options.coverage_lift) return int(math.pow(m, (m * c + l) / (m + l))) + def _get_default_suite_names(self): + return DEFAULT_SUITES - def _execute(self, args, options, suites): + def _do_execute(self, suites, args, options): print(">>> Running tests for %s.%s" % (self.build_config.arch, self.mode_name)) @@ -264,7 +219,6 @@ class DeoptFuzzer(base_runner.BaseTestRunner): True, # No sorting of test cases. 0, # Don't rerun failing tests. 0, # No use of a rerun-failing-tests maximum. - False, # No predictable mode. False, # No no_harness mode. False, # Don't use perf data. False) # Coverage not supported. @@ -305,16 +259,16 @@ class DeoptFuzzer(base_runner.BaseTestRunner): if len(args) > 0: s.FilterTestCasesByArgs(args) s.FilterTestCasesByStatus(False) - for t in s.tests: - t.flags += s.GetStatusfileFlags(t) test_backup[s] = s.tests analysis_flags = ["--deopt-every-n-times", "%d" % MAX_DEOPT, "--print-deopt-stress"] - s.tests = [t.CopyAddingFlags(t.variant, analysis_flags) for t in s.tests] + s.tests = [t.create_variant(t.variant, analysis_flags, 'analysis') + for t in s.tests] num_tests += len(s.tests) for t in s.tests: t.id = test_id + t.cmd = t.get_command(ctx) test_id += 1 if num_tests == 0: @@ -333,7 +287,7 @@ class DeoptFuzzer(base_runner.BaseTestRunner): for s in suites: test_results = {} for t in s.tests: - for line in t.output.stdout.splitlines(): + for line in runner.outputs[t].stdout.splitlines(): if line.startswith("=== Stress deopt counter: "): test_results[t.path] = MAX_DEOPT - int(line.split(" ")[-1]) for t in s.tests: @@ -357,17 +311,18 @@ class DeoptFuzzer(base_runner.BaseTestRunner): distribution = dist.Distribute(n_deopt, max_deopt) if options.verbose: print "%s %s" % (t.path, distribution) - for i in distribution: - fuzzing_flags = ["--deopt-every-n-times", "%d" % i] - s.tests.append(t.CopyAddingFlags(t.variant, fuzzing_flags)) + for n, d in enumerate(distribution): + fuzzing_flags = ["--deopt-every-n-times", "%d" % d] + s.tests.append(t.create_variant(t.variant, fuzzing_flags, n)) num_tests += len(s.tests) for t in s.tests: t.id = test_id + t.cmd = t.get_command(ctx) test_id += 1 if num_tests == 0: print "No tests to run." - return 0 + return exit_code print(">>> Deopt fuzzing phase (%d test cases)" % num_tests) progress_indicator = progress.PROGRESS_INDICATORS[options.progress]() diff --git a/deps/v8/tools/testrunner/gc_fuzzer.py b/deps/v8/tools/testrunner/gc_fuzzer.py index 4130fff8be..18be227d98 100755 --- a/deps/v8/tools/testrunner/gc_fuzzer.py +++ b/deps/v8/tools/testrunner/gc_fuzzer.py @@ -27,7 +27,7 @@ from testrunner.local import verbose from testrunner.objects import context -DEFAULT_TESTS = ["mjsunit", "webkit"] +DEFAULT_SUITES = ["mjsunit", "webkit", "benchmarks"] TIMEOUT_DEFAULT = 60 # Double the timeout for these: @@ -36,8 +36,8 @@ SLOW_ARCHS = ["arm", class GCFuzzer(base_runner.BaseTestRunner): - def __init__(self): - super(GCFuzzer, self).__init__() + def __init__(self, *args, **kwargs): + super(GCFuzzer, self).__init__(*args, **kwargs) self.fuzzer_rng = None @@ -64,12 +64,6 @@ class GCFuzzer(base_runner.BaseTestRunner): " (verbose, dots, color, mono)"), choices=progress.PROGRESS_INDICATORS.keys(), default="mono") - parser.add_option("--shard-count", - help="Split testsuites into this number of shards", - default=1, type="int") - parser.add_option("--shard-run", - help="Run this shard from the split up tests.", - default=1, type="int") parser.add_option("-t", "--timeout", help="Timeout in seconds", default= -1, type="int") parser.add_option("--random-seed", default=0, @@ -102,47 +96,6 @@ class GCFuzzer(base_runner.BaseTestRunner): self.fuzzer_rng = random.Random(options.fuzzer_random_seed) return True - def _shard_tests(self, tests, shard_count, shard_run): - if shard_count < 2: - return tests - if shard_run < 1 or shard_run > shard_count: - print "shard-run not a valid number, should be in [1:shard-count]" - print "defaulting back to running all tests" - return tests - count = 0 - shard = [] - for test in tests: - if count % shard_count == shard_run - 1: - shard.append(test) - count += 1 - return shard - - def _do_execute(self, options, args): - suite_paths = utils.GetSuitePaths(join(base_runner.BASE_DIR, "test")) - - if len(args) == 0: - suite_paths = [ s for s in suite_paths if s in DEFAULT_TESTS ] - else: - args_suites = set() - for arg in args: - suite = arg.split(os.path.sep)[0] - if not suite in args_suites: - args_suites.add(suite) - suite_paths = [ s for s in suite_paths if s in args_suites ] - - suites = [] - for root in suite_paths: - suite = testsuite.TestSuite.LoadTestSuite( - os.path.join(base_runner.BASE_DIR, "test", root)) - if suite: - suites.append(suite) - - try: - return self._execute(args, options, suites) - except KeyboardInterrupt: - return 2 - - def _calculate_n_tests(self, m, options): """Calculates the number of tests from m points with exponential coverage. The coverage is expected to be between 0.0 and 1.0. @@ -152,8 +105,10 @@ class GCFuzzer(base_runner.BaseTestRunner): l = float(options.coverage_lift) return int(math.pow(m, (m * c + l) / (m + l))) + def _get_default_suite_names(self): + return DEFAULT_SUITES - def _execute(self, args, options, suites): + def _do_execute(self, suites, args, options): print(">>> Running tests for %s.%s" % (self.build_config.arch, self.mode_name)) @@ -179,7 +134,6 @@ class GCFuzzer(base_runner.BaseTestRunner): True, # No sorting of test cases. 0, # Don't rerun failing tests. 0, # No use of a rerun-failing-tests maximum. - False, # No predictable mode. False, # No no_harness mode. False, # Don't use perf data. False) # Coverage not supported. @@ -193,14 +147,12 @@ class GCFuzzer(base_runner.BaseTestRunner): print('>>> Collection phase') for s in suites: - analysis_flags = [ - # > 100% to not influence default incremental marking, but we need this - # flag to print reached incremental marking limit. - '--stress_marking', '1000', - '--trace_incremental_marking', - ] - s.tests = map(lambda t: t.CopyAddingFlags(t.variant, analysis_flags), + analysis_flags = ['--fuzzer-gc-analysis'] + s.tests = map(lambda t: t.create_variant(t.variant, analysis_flags, + 'analysis'), s.tests) + for t in s.tests: + t.cmd = t.get_command(ctx) progress_indicator = progress.PROGRESS_INDICATORS[options.progress]() runner = execution.Runner(suites, progress_indicator, ctx) @@ -211,13 +163,15 @@ class GCFuzzer(base_runner.BaseTestRunner): for s in suites: for t in s.tests: # Skip failed tests. - if s.HasUnexpectedOutput(t): + if t.output_proc.has_unexpected_output(runner.outputs[t]): print '%s failed, skipping' % t.path continue - max_limit = self._get_max_limit_reached(t) + max_limit = self._get_max_limit_reached(runner.outputs[t]) if max_limit: test_results[t.path] = max_limit + runner = None + if options.dump_results_file: with file("%s.%d.txt" % (options.dump_results_file, time.time()), "w") as f: @@ -237,7 +191,7 @@ class GCFuzzer(base_runner.BaseTestRunner): if options.verbose: print ('%s [x%d] (max marking limit=%.02f)' % (t.path, subtests_count, max_percent)) - for _ in xrange(0, subtests_count): + for i in xrange(0, subtests_count): fuzzer_seed = self._next_fuzzer_seed() fuzzing_flags = [ '--stress_marking', str(max_percent), @@ -245,12 +199,14 @@ class GCFuzzer(base_runner.BaseTestRunner): ] if options.stress_compaction: fuzzing_flags.append('--stress_compaction_random') - s.tests.append(t.CopyAddingFlags(t.variant, fuzzing_flags)) + s.tests.append(t.create_variant(t.variant, fuzzing_flags, i)) + for t in s.tests: + t.cmd = t.get_command(ctx) num_tests += len(s.tests) if num_tests == 0: print "No tests to run." - return 0 + return exit_code print(">>> Fuzzing phase (%d test cases)" % num_tests) progress_indicator = progress.PROGRESS_INDICATORS[options.progress]() @@ -292,8 +248,6 @@ class GCFuzzer(base_runner.BaseTestRunner): if len(args) > 0: s.FilterTestCasesByArgs(args) s.FilterTestCasesByStatus(False) - for t in s.tests: - t.flags += s.GetStatusfileFlags(t) num_tests += len(s.tests) for t in s.tests: @@ -304,31 +258,16 @@ class GCFuzzer(base_runner.BaseTestRunner): # Parses test stdout and returns what was the highest reached percent of the # incremental marking limit (0-100). - # Skips values >=100% since they already trigger incremental marking. @staticmethod - def _get_max_limit_reached(test): - def is_im_line(l): - return 'IncrementalMarking' in l and '% of the memory limit reached' in l - - def line_to_percent(l): - return filter(lambda part: '%' in part, l.split(' '))[0] - - def percent_str_to_float(s): - return float(s[:-1]) - - if not (test.output and test.output.stdout): + def _get_max_limit_reached(output): + if not output.stdout: return None - im_lines = filter(is_im_line, test.output.stdout.splitlines()) - percents_str = map(line_to_percent, im_lines) - percents = map(percent_str_to_float, percents_str) - - # Skip >= 100%. - percents = filter(lambda p: p < 100, percents) + for l in reversed(output.stdout.splitlines()): + if l.startswith('### Maximum marking limit reached ='): + return float(l.split()[6]) - if not percents: - return None - return max(percents) + return None def _next_fuzzer_seed(self): fuzzer_seed = None diff --git a/deps/v8/tools/testrunner/local/command.py b/deps/v8/tools/testrunner/local/command.py new file mode 100644 index 0000000000..93b1ac9497 --- /dev/null +++ b/deps/v8/tools/testrunner/local/command.py @@ -0,0 +1,171 @@ +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + + +import os +import subprocess +import sys +import threading +import time + +from ..local import utils +from ..objects import output + + +SEM_INVALID_VALUE = -1 +SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h + + +class BaseCommand(object): + def __init__(self, shell, args=None, cmd_prefix=None, timeout=60, env=None, + verbose=False): + assert(timeout > 0) + + self.shell = shell + self.args = args or [] + self.cmd_prefix = cmd_prefix or [] + self.timeout = timeout + self.env = env or {} + self.verbose = verbose + + def execute(self, **additional_popen_kwargs): + if self.verbose: + print '# %s' % self + + process = self._start_process(**additional_popen_kwargs) + + # Variable to communicate with the timer. + timeout_occured = [False] + timer = threading.Timer( + self.timeout, self._on_timeout, [process, timeout_occured]) + timer.start() + + start_time = time.time() + stdout, stderr = process.communicate() + duration = time.time() - start_time + + timer.cancel() + + return output.Output( + process.returncode, + timeout_occured[0], + stdout.decode('utf-8', 'replace').encode('utf-8'), + stderr.decode('utf-8', 'replace').encode('utf-8'), + process.pid, + duration + ) + + def _start_process(self, **additional_popen_kwargs): + try: + return subprocess.Popen( + args=self._get_popen_args(), + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + env=self._get_env(), + **additional_popen_kwargs + ) + except Exception as e: + sys.stderr.write('Error executing: %s\n' % self) + raise e + + def _get_popen_args(self): + return self._to_args_list() + + def _get_env(self): + env = os.environ.copy() + env.update(self.env) + # GTest shard information is read by the V8 tests runner. Make sure it + # doesn't leak into the execution of gtests we're wrapping. Those might + # otherwise apply a second level of sharding and as a result skip tests. + env.pop('GTEST_TOTAL_SHARDS', None) + env.pop('GTEST_SHARD_INDEX', None) + return env + + def _kill_process(self, process): + raise NotImplementedError() + + def _on_timeout(self, process, timeout_occured): + timeout_occured[0] = True + try: + self._kill_process(process) + except OSError: + sys.stderr.write('Error: Process %s already ended.\n' % process.pid) + + def __str__(self): + return self.to_string() + + def to_string(self, relative=False): + def escape(part): + # Escape spaces. We may need to escape more characters for this to work + # properly. + if ' ' in part: + return '"%s"' % part + return part + + parts = map(escape, self._to_args_list()) + cmd = ' '.join(parts) + if relative: + cmd = cmd.replace(os.getcwd() + os.sep, '') + return cmd + + def _to_args_list(self): + return self.cmd_prefix + [self.shell] + self.args + + +class PosixCommand(BaseCommand): + def _kill_process(self, process): + process.kill() + + +class WindowsCommand(BaseCommand): + def _start_process(self, **kwargs): + # Try to change the error mode to avoid dialogs on fatal errors. Don't + # touch any existing error mode flags by merging the existing error mode. + # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx. + def set_error_mode(mode): + prev_error_mode = SEM_INVALID_VALUE + try: + import ctypes + prev_error_mode = ( + ctypes.windll.kernel32.SetErrorMode(mode)) #@UndefinedVariable + except ImportError: + pass + return prev_error_mode + + error_mode = SEM_NOGPFAULTERRORBOX + prev_error_mode = set_error_mode(error_mode) + set_error_mode(error_mode | prev_error_mode) + + try: + return super(WindowsCommand, self)._start_process(**kwargs) + finally: + if prev_error_mode != SEM_INVALID_VALUE: + set_error_mode(prev_error_mode) + + def _get_popen_args(self): + return subprocess.list2cmdline(self._to_args_list()) + + def _kill_process(self, process): + if self.verbose: + print 'Attempting to kill process %d' % process.pid + sys.stdout.flush() + tk = subprocess.Popen( + 'taskkill /T /F /PID %d' % process.pid, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + ) + stdout, stderr = tk.communicate() + if self.verbose: + print 'Taskkill results for %d' % process.pid + print stdout + print stderr + print 'Return code: %d' % tk.returncode + sys.stdout.flush() + + +# Set the Command class to the OS-specific version. +if utils.IsWindows(): + Command = WindowsCommand +else: + Command = PosixCommand diff --git a/deps/v8/tools/testrunner/local/commands.py b/deps/v8/tools/testrunner/local/commands.py deleted file mode 100644 index 4afd450d2f..0000000000 --- a/deps/v8/tools/testrunner/local/commands.py +++ /dev/null @@ -1,152 +0,0 @@ -# Copyright 2012 the V8 project authors. All rights reserved. -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following -# disclaimer in the documentation and/or other materials provided -# with the distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - -import os -import subprocess -import sys -from threading import Timer - -from ..local import utils -from ..objects import output - - -SEM_INVALID_VALUE = -1 -SEM_NOGPFAULTERRORBOX = 0x0002 # Microsoft Platform SDK WinBase.h - - -def Win32SetErrorMode(mode): - prev_error_mode = SEM_INVALID_VALUE - try: - import ctypes - prev_error_mode = \ - ctypes.windll.kernel32.SetErrorMode(mode) #@UndefinedVariable - except ImportError: - pass - return prev_error_mode - - -def RunProcess(verbose, timeout, args, additional_env, **rest): - if verbose: print "#", " ".join(args) - popen_args = args - prev_error_mode = SEM_INVALID_VALUE - if utils.IsWindows(): - popen_args = subprocess.list2cmdline(args) - # Try to change the error mode to avoid dialogs on fatal errors. Don't - # touch any existing error mode flags by merging the existing error mode. - # See http://blogs.msdn.com/oldnewthing/archive/2004/07/27/198410.aspx. - error_mode = SEM_NOGPFAULTERRORBOX - prev_error_mode = Win32SetErrorMode(error_mode) - Win32SetErrorMode(error_mode | prev_error_mode) - - env = os.environ.copy() - env.update(additional_env) - # GTest shard information is read by the V8 tests runner. Make sure it - # doesn't leak into the execution of gtests we're wrapping. Those might - # otherwise apply a second level of sharding and as a result skip tests. - env.pop('GTEST_TOTAL_SHARDS', None) - env.pop('GTEST_SHARD_INDEX', None) - - try: - process = subprocess.Popen( - args=popen_args, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - env=env, - **rest - ) - except Exception as e: - sys.stderr.write("Error executing: %s\n" % popen_args) - raise e - - if (utils.IsWindows() and prev_error_mode != SEM_INVALID_VALUE): - Win32SetErrorMode(prev_error_mode) - - def kill_process(process, timeout_result): - timeout_result[0] = True - try: - if utils.IsWindows(): - if verbose: - print "Attempting to kill process %d" % process.pid - sys.stdout.flush() - tk = subprocess.Popen( - 'taskkill /T /F /PID %d' % process.pid, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - ) - stdout, stderr = tk.communicate() - if verbose: - print "Taskkill results for %d" % process.pid - print stdout - print stderr - print "Return code: %d" % tk.returncode - sys.stdout.flush() - else: - if utils.GuessOS() == "macos": - # TODO(machenbach): Temporary output for investigating hanging test - # driver on mac. - print "Attempting to kill process %d - cmd %s" % (process.pid, args) - try: - print subprocess.check_output( - "ps -e | egrep 'd8|cctest|unittests'", shell=True) - except Exception: - pass - sys.stdout.flush() - process.kill() - if utils.GuessOS() == "macos": - # TODO(machenbach): Temporary output for investigating hanging test - # driver on mac. This will probably not print much, since kill only - # sends the signal. - print "Return code after signalling the kill: %s" % process.returncode - sys.stdout.flush() - - except OSError: - sys.stderr.write('Error: Process %s already ended.\n' % process.pid) - - # Pseudo object to communicate with timer thread. - timeout_result = [False] - - timer = Timer(timeout, kill_process, [process, timeout_result]) - timer.start() - stdout, stderr = process.communicate() - timer.cancel() - - return output.Output( - process.returncode, - timeout_result[0], - stdout.decode('utf-8', 'replace').encode('utf-8'), - stderr.decode('utf-8', 'replace').encode('utf-8'), - process.pid, - ) - - -# TODO(machenbach): Instead of passing args around, we should introduce an -# immutable Command class (that just represents the command with all flags and -# is pretty-printable) and a member method for running such a command. -def Execute(args, verbose=False, timeout=None, env=None): - args = [ c for c in args if c != "" ] - return RunProcess(verbose, timeout, args, env or {}) diff --git a/deps/v8/tools/testrunner/local/execution.py b/deps/v8/tools/testrunner/local/execution.py index 8cc3556cae..d6d0725365 100644 --- a/deps/v8/tools/testrunner/local/execution.py +++ b/deps/v8/tools/testrunner/local/execution.py @@ -31,15 +31,14 @@ import os import re import shutil import sys -import time +import traceback -from pool import Pool -from . import commands +from . import command from . import perfdata from . import statusfile -from . import testsuite from . import utils -from ..objects import output +from . pool import Pool +from ..objects import predictable # Base dir of the v8 checkout. @@ -48,76 +47,22 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname( TEST_DIR = os.path.join(BASE_DIR, "test") -class Instructions(object): - def __init__(self, command, test_id, timeout, verbose, env): - self.command = command - self.id = test_id - self.timeout = timeout - self.verbose = verbose - self.env = env - - # Structure that keeps global information per worker process. ProcessContext = collections.namedtuple( - "process_context", ["suites", "context"]) + 'process_context', ['sancov_dir']) -def MakeProcessContext(context, suite_names): - """Generate a process-local context. +TestJobResult = collections.namedtuple( + 'TestJobResult', ['id', 'outproc_result']) - This reloads all suites per process and stores the global context. +def MakeProcessContext(sancov_dir): + return ProcessContext(sancov_dir) - Args: - context: The global context from the test runner. - suite_names (list of str): Suite names as loaded by the parent process. - Load the same suites in each subprocess. - """ - suites = {} - for root in suite_names: - # Don't reinitialize global state as this is concurrently called from - # different processes. - suite = testsuite.TestSuite.LoadTestSuite( - os.path.join(TEST_DIR, root), global_init=False) - if suite: - suites[suite.name] = suite - return ProcessContext(suites, context) - - -def GetCommand(test, context): - d8testflag = [] - shell = test.suite.GetShellForTestCase(test) - if shell == "d8": - d8testflag = ["--test"] - if utils.IsWindows(): - shell += ".exe" - if context.random_seed: - d8testflag += ["--random-seed=%s" % context.random_seed] - files, flags, env = test.suite.GetParametersForTestCase(test, context) - cmd = ( - context.command_prefix + - [os.path.abspath(os.path.join(context.shell_dir, shell))] + - d8testflag + - files + - context.extra_flags + - # Flags from test cases can overwrite extra cmd-line flags. - flags - ) - return cmd, env - - -def _GetInstructions(test, context): - command, env = GetCommand(test, context) - timeout = context.timeout - if ("--stress-opt" in test.flags or - "--stress-opt" in context.mode_flags or - "--stress-opt" in context.extra_flags): - timeout *= 4 - if "--noenable-vfp3" in context.extra_flags: - timeout *= 2 - - # TODO(majeski): make it slow outcome dependent. - timeout *= 2 - return Instructions(command, test.id, timeout, context.verbose, env) + +# Global function for multiprocessing, because pickling a static method doesn't +# work on Windows. +def run_job(job, process_context): + return job.run(process_context) class Job(object): @@ -126,31 +71,18 @@ class Job(object): All contained fields will be pickled/unpickled. """ - def Run(self, process_context): - """Executes the job. - - Args: - process_context: Process-local information that is initialized by the - executing worker. - """ + def run(self, process_context): raise NotImplementedError() -def SetupProblem(exception, test): - stderr = ">>> EXCEPTION: %s\n" % exception - match = re.match(r"^.*No such file or directory: '(.*)'$", str(exception)) - if match: - # Extra debuging information when files are claimed missing. - f = match.group(1) - stderr += ">>> File %s exists? -> %s\n" % (f, os.path.exists(f)) - return test.id, output.Output(1, False, "", stderr, None), 0 - - class TestJob(Job): - def __init__(self, test): - self.test = test + def __init__(self, test_id, cmd, outproc, run_num): + self.test_id = test_id + self.cmd = cmd + self.outproc = outproc + self.run_num = run_num - def _rename_coverage_data(self, output, context): + def _rename_coverage_data(self, out, sancov_dir): """Rename coverage data. Rename files with PIDs to files with unique test IDs, because the number @@ -159,64 +91,53 @@ class TestJob(Job): 42 is the test ID and 1 is the attempt (the same test might be rerun on failures). """ - if context.sancov_dir and output.pid is not None: - shell = self.test.suite.GetShellForTestCase(self.test) - sancov_file = os.path.join( - context.sancov_dir, "%s.%d.sancov" % (shell, output.pid)) + if sancov_dir and out.pid is not None: + # Doesn't work on windows so basename is sufficient to get the shell name. + shell = os.path.basename(self.cmd.shell) + sancov_file = os.path.join(sancov_dir, "%s.%d.sancov" % (shell, out.pid)) # Some tests are expected to fail and don't produce coverage data. if os.path.exists(sancov_file): parts = sancov_file.split(".") new_sancov_file = ".".join( parts[:-2] + - ["test", str(self.test.id), str(self.test.run)] + + ["test", str(self.test_id), str(self.run_num)] + parts[-1:] ) assert not os.path.exists(new_sancov_file) os.rename(sancov_file, new_sancov_file) - def Run(self, process_context): - try: - # Retrieve a new suite object on the worker-process side. The original - # suite object isn't pickled. - self.test.SetSuiteObject(process_context.suites) - instr = _GetInstructions(self.test, process_context.context) - except Exception, e: - # TODO(majeski): Better exception reporting. - return SetupProblem(e, self.test) - - start_time = time.time() - output = commands.Execute(instr.command, instr.verbose, instr.timeout, - instr.env) - self._rename_coverage_data(output, process_context.context) - return (instr.id, output, time.time() - start_time) - - -def RunTest(job, process_context): - return job.Run(process_context) + def run(self, context): + output = self.cmd.execute() + self._rename_coverage_data(output, context.sancov_dir) + return TestJobResult(self.test_id, self.outproc.process(output)) class Runner(object): - def __init__(self, suites, progress_indicator, context): + def __init__(self, suites, progress_indicator, context, outproc_factory=None): self.datapath = os.path.join("out", "testrunner_data") self.perf_data_manager = perfdata.GetPerfDataManager( context, self.datapath) self.perfdata = self.perf_data_manager.GetStore(context.arch, context.mode) self.perf_failures = False self.printed_allocations = False + self.outproc_factory = outproc_factory or (lambda test: test.output_proc) self.tests = [t for s in suites for t in s.tests] + + # TODO(majeski): Pass dynamically instead of keeping them in the runner. + # Maybe some observer? + self.outputs = {t: None for t in self.tests} + self.suite_names = [s.name for s in suites] # Always pre-sort by status file, slowest tests first. - slow_key = lambda t: statusfile.IsSlow(t.suite.GetStatusFileOutcomes(t)) - self.tests.sort(key=slow_key, reverse=True) + self.tests.sort(key=lambda t: t.is_slow, reverse=True) - # Sort by stored duration of not opted out. + # Sort by stored duration if not opted out. if not context.no_sorting: - for t in self.tests: - t.duration = self.perfdata.FetchPerfData(t) or 1.0 - self.tests.sort(key=lambda t: t.duration, reverse=True) + self.tests.sort(key=lambda t: self.perfdata.FetchPerfData(t) or 1.0, + reverse=True) self._CommonInit(suites, progress_indicator, context) @@ -242,7 +163,7 @@ class Runner(object): print("PerfData exception: %s" % e) self.perf_failures = True - def _MaybeRerun(self, pool, test): + def _MaybeRerun(self, pool, test, result): if test.run <= self.context.rerun_failures_count: # Possibly rerun this test if its run count is below the maximum per # test. <= as the flag controls reruns not including the first run. @@ -254,25 +175,25 @@ class Runner(object): # Don't rerun this if the overall number of rerun tests has been # reached. return - if test.run >= 2 and test.duration > self.context.timeout / 20.0: + if (test.run >= 2 and + result.output.duration > self.context.timeout / 20.0): # Rerun slow tests at most once. return # Rerun this test. - test.duration = None - test.output = None test.run += 1 - pool.add([TestJob(test)]) + pool.add([ + TestJob(test.id, test.cmd, self.outproc_factory(test), test.run) + ]) self.remaining += 1 self.total += 1 - def _ProcessTestNormal(self, test, result, pool): - test.output = result[1] - test.duration = result[2] - has_unexpected_output = test.suite.HasUnexpectedOutput(test) + def _ProcessTest(self, test, result, pool): + self.outputs[test] = result.output + has_unexpected_output = result.has_unexpected_output if has_unexpected_output: self.failed.append(test) - if test.output.HasCrashed(): + if result.output.HasCrashed(): self.crashed += 1 else: self.succeeded += 1 @@ -280,57 +201,15 @@ class Runner(object): # For the indicator, everything that happens after the first run is treated # as unexpected even if it flakily passes in order to include it in the # output. - self.indicator.HasRun(test, has_unexpected_output or test.run > 1) + self.indicator.HasRun(test, result.output, + has_unexpected_output or test.run > 1) if has_unexpected_output: # Rerun test failures after the indicator has processed the results. self._VerbosePrint("Attempting to rerun test after failure.") - self._MaybeRerun(pool, test) + self._MaybeRerun(pool, test, result) # Update the perf database if the test succeeded. return not has_unexpected_output - def _ProcessTestPredictable(self, test, result, pool): - def HasDifferentAllocations(output1, output2): - def AllocationStr(stdout): - for line in reversed((stdout or "").splitlines()): - if line.startswith("### Allocations = "): - self.printed_allocations = True - return line - return "" - return (AllocationStr(output1.stdout) != AllocationStr(output2.stdout)) - - # Always pass the test duration for the database update. - test.duration = result[2] - if test.run == 1 and result[1].HasTimedOut(): - # If we get a timeout in the first run, we are already in an - # unpredictable state. Just report it as a failure and don't rerun. - test.output = result[1] - self.remaining -= 1 - self.failed.append(test) - self.indicator.HasRun(test, True) - if test.run > 1 and HasDifferentAllocations(test.output, result[1]): - # From the second run on, check for different allocations. If a - # difference is found, call the indicator twice to report both tests. - # All runs of each test are counted as one for the statistic. - self.remaining -= 1 - self.failed.append(test) - self.indicator.HasRun(test, True) - test.output = result[1] - self.indicator.HasRun(test, True) - elif test.run >= 3: - # No difference on the third run -> report a success. - self.remaining -= 1 - self.succeeded += 1 - test.output = result[1] - self.indicator.HasRun(test, False) - else: - # No difference yet and less than three runs -> add another run and - # remember the output for comparison. - test.run += 1 - test.output = result[1] - pool.add([TestJob(test)]) - # Always update the perf database. - return True - def Run(self, jobs): self.indicator.Starting() self._RunInternal(jobs) @@ -350,50 +229,54 @@ class Runner(object): assert test.id >= 0 test_map[test.id] = test try: - yield [TestJob(test)] + yield [ + TestJob(test.id, test.cmd, self.outproc_factory(test), test.run) + ] except Exception, e: # If this failed, save the exception and re-raise it later (after # all other tests have had a chance to run). - queued_exception[0] = e + queued_exception[0] = e, traceback.format_exc() continue try: it = pool.imap_unordered( - fn=RunTest, + fn=run_job, gen=gen_tests(), process_context_fn=MakeProcessContext, - process_context_args=[self.context, self.suite_names], + process_context_args=[self.context.sancov_dir], ) for result in it: if result.heartbeat: self.indicator.Heartbeat() continue - test = test_map[result.value[0]] - if self.context.predictable: - update_perf = self._ProcessTestPredictable(test, result.value, pool) - else: - update_perf = self._ProcessTestNormal(test, result.value, pool) + + job_result = result.value + test_id = job_result.id + outproc_result = job_result.outproc_result + + test = test_map[test_id] + update_perf = self._ProcessTest(test, outproc_result, pool) if update_perf: - self._RunPerfSafe(lambda: self.perfdata.UpdatePerfData(test)) + self._RunPerfSafe(lambda: self.perfdata.UpdatePerfData( + test, outproc_result.output.duration)) + except KeyboardInterrupt: + raise + except: + traceback.print_exc() + raise finally: self._VerbosePrint("Closing process pool.") pool.terminate() self._VerbosePrint("Closing database connection.") - self._RunPerfSafe(lambda: self.perf_data_manager.close()) + self._RunPerfSafe(self.perf_data_manager.close) if self.perf_failures: # Nuke perf data in case of failures. This might not work on windows as # some files might still be open. print "Deleting perf test data due to db corruption." shutil.rmtree(self.datapath) if queued_exception[0]: - raise queued_exception[0] - - # Make sure that any allocations were printed in predictable mode (if we - # ran any tests). - assert ( - not self.total or - not self.context.predictable or - self.printed_allocations - ) + e, stacktrace = queued_exception[0] + print stacktrace + raise e def _VerbosePrint(self, text): if self.context.verbose: @@ -403,6 +286,8 @@ class Runner(object): class BreakNowException(Exception): def __init__(self, value): + super(BreakNowException, self).__init__() self.value = value + def __str__(self): return repr(self.value) diff --git a/deps/v8/tools/testrunner/local/junit_output.py b/deps/v8/tools/testrunner/local/junit_output.py index d2748febd9..52f31ec422 100644 --- a/deps/v8/tools/testrunner/local/junit_output.py +++ b/deps/v8/tools/testrunner/local/junit_output.py @@ -34,9 +34,10 @@ class JUnitTestOutput: self.root = xml.Element("testsuite") self.root.attrib["name"] = test_suite_name - def HasRunTest(self, test_name, test_duration, test_failure): + def HasRunTest(self, test_name, test_cmd, test_duration, test_failure): testCaseElement = xml.Element("testcase") - testCaseElement.attrib["name"] = " ".join(test_name) + testCaseElement.attrib["name"] = test_name + testCaseElement.attrib["cmd"] = test_cmd testCaseElement.attrib["time"] = str(round(test_duration, 3)) if len(test_failure): failureElement = xml.Element("failure") @@ -44,5 +45,5 @@ class JUnitTestOutput: testCaseElement.append(failureElement) self.root.append(testCaseElement) - def FinishAndWrite(self, file): - xml.ElementTree(self.root).write(file, "UTF-8") + def FinishAndWrite(self, f): + xml.ElementTree(self.root).write(f, "UTF-8") diff --git a/deps/v8/tools/testrunner/local/perfdata.py b/deps/v8/tools/testrunner/local/perfdata.py index 29ebff773a..4cb618b0be 100644 --- a/deps/v8/tools/testrunner/local/perfdata.py +++ b/deps/v8/tools/testrunner/local/perfdata.py @@ -62,22 +62,17 @@ class PerfDataStore(object): self.database.close() self.closed = True - def GetKey(self, test): - """Computes the key used to access data for the given testcase.""" - flags = "".join(test.flags) - return str("%s.%s.%s" % (test.suitename(), test.path, flags)) - def FetchPerfData(self, test): """Returns the observed duration for |test| as read from the store.""" - key = self.GetKey(test) + key = test.get_id() if key in self.database: return self.database[key].avg return None - def UpdatePerfData(self, test): - """Updates the persisted value in the store with test.duration.""" - testkey = self.GetKey(test) - self.RawUpdatePerfData(testkey, test.duration) + def UpdatePerfData(self, test, duration): + """Updates the persisted value in the store with duration.""" + testkey = test.get_id() + self.RawUpdatePerfData(testkey, duration) def RawUpdatePerfData(self, testkey, duration): with self.lock: @@ -121,7 +116,7 @@ class PerfDataManager(object): class NullPerfDataStore(object): - def UpdatePerfData(self, test): + def UpdatePerfData(self, test, duration): pass def FetchPerfData(self, test): diff --git a/deps/v8/tools/testrunner/local/pool.py b/deps/v8/tools/testrunner/local/pool.py index 99996ee3ce..9199b62d8a 100644 --- a/deps/v8/tools/testrunner/local/pool.py +++ b/deps/v8/tools/testrunner/local/pool.py @@ -8,6 +8,21 @@ from multiprocessing import Event, Process, Queue import traceback +def setup_testing(): + """For testing only: Use threading under the hood instead of multiprocessing + to make coverage work. + """ + global Queue + global Event + global Process + del Queue + del Event + del Process + from Queue import Queue + from threading import Event + from threading import Thread as Process + + class NormalResult(): def __init__(self, result): self.result = result @@ -120,8 +135,8 @@ class Pool(): self.done, process_context_fn, process_context_args)) - self.processes.append(p) p.start() + self.processes.append(p) self.advance(gen) while self.count > 0: @@ -145,6 +160,11 @@ class Pool(): else: yield MaybeResult.create_result(result.result) self.advance(gen) + except KeyboardInterrupt: + raise + except Exception as e: + traceback.print_exc() + print(">>> EXCEPTION: %s" % e) finally: self.terminate() if internal_error: diff --git a/deps/v8/tools/testrunner/local/progress.py b/deps/v8/tools/testrunner/local/progress.py index e57a6e36c9..f6ebddf2e5 100644 --- a/deps/v8/tools/testrunner/local/progress.py +++ b/deps/v8/tools/testrunner/local/progress.py @@ -32,12 +32,9 @@ import os import sys import time -from . import execution from . import junit_output from . import statusfile - - -ABS_PATH_PREFIX = os.getcwd() + os.sep +from ..testproc import progress as progress_proc class ProgressIndicator(object): @@ -54,33 +51,26 @@ class ProgressIndicator(object): def Done(self): pass - def HasRun(self, test, has_unexpected_output): + def HasRun(self, test, output, has_unexpected_output): pass def Heartbeat(self): pass def PrintFailureHeader(self, test): - if test.suite.IsNegativeTest(test): + if test.output_proc.negative: negative_marker = '[negative] ' else: negative_marker = '' print "=== %(label)s %(negative)s===" % { - 'label': test.GetLabel(), - 'negative': negative_marker + 'label': test, + 'negative': negative_marker, } - def _EscapeCommand(self, test): - command, _ = execution.GetCommand(test, self.runner.context) - parts = [] - for part in command: - if ' ' in part: - # Escape spaces. We may need to escape more characters for this - # to work properly. - parts.append('"%s"' % part) - else: - parts.append(part) - return " ".join(parts) + def ToProgressIndicatorProc(self): + print ('Warning: %s is not available as a processor' % + self.__class__.__name__) + return None class IndicatorNotifier(object): @@ -91,6 +81,9 @@ class IndicatorNotifier(object): def Register(self, indicator): self.indicators.append(indicator) + def ToProgressIndicatorProcs(self): + return [i.ToProgressIndicatorProc() for i in self.indicators] + # Forge all generic event-dispatching methods in IndicatorNotifier, which are # part of the ProgressIndicator interface. @@ -116,18 +109,19 @@ class SimpleProgressIndicator(ProgressIndicator): def Done(self): print for failed in self.runner.failed: + output = self.runner.outputs[failed] self.PrintFailureHeader(failed) - if failed.output.stderr: + if output.stderr: print "--- stderr ---" - print failed.output.stderr.strip() - if failed.output.stdout: + print output.stderr.strip() + if output.stdout: print "--- stdout ---" - print failed.output.stdout.strip() - print "Command: %s" % self._EscapeCommand(failed) - if failed.output.HasCrashed(): - print "exit code: %d" % failed.output.exit_code + print output.stdout.strip() + print "Command: %s" % failed.cmd.to_string() + if output.HasCrashed(): + print "exit code: %d" % output.exit_code print "--- CRASHED ---" - if failed.output.HasTimedOut(): + if output.HasTimedOut(): print "--- TIMEOUT ---" if len(self.runner.failed) == 0: print "===" @@ -144,33 +138,36 @@ class SimpleProgressIndicator(ProgressIndicator): class VerboseProgressIndicator(SimpleProgressIndicator): - def HasRun(self, test, has_unexpected_output): + def HasRun(self, test, output, has_unexpected_output): if has_unexpected_output: - if test.output.HasCrashed(): + if output.HasCrashed(): outcome = 'CRASH' else: outcome = 'FAIL' else: outcome = 'pass' - print 'Done running %s: %s' % (test.GetLabel(), outcome) + print 'Done running %s: %s' % (test, outcome) sys.stdout.flush() def Heartbeat(self): print 'Still working...' sys.stdout.flush() + def ToProgressIndicatorProc(self): + return progress_proc.VerboseProgressIndicator() + class DotsProgressIndicator(SimpleProgressIndicator): - def HasRun(self, test, has_unexpected_output): + def HasRun(self, test, output, has_unexpected_output): total = self.runner.succeeded + len(self.runner.failed) if (total > 1) and (total % 50 == 1): sys.stdout.write('\n') if has_unexpected_output: - if test.output.HasCrashed(): + if output.HasCrashed(): sys.stdout.write('C') sys.stdout.flush() - elif test.output.HasTimedOut(): + elif output.HasTimedOut(): sys.stdout.write('T') sys.stdout.flush() else: @@ -180,6 +177,9 @@ class DotsProgressIndicator(SimpleProgressIndicator): sys.stdout.write('.') sys.stdout.flush() + def ToProgressIndicatorProc(self): + return progress_proc.DotsProgressIndicator() + class CompactProgressIndicator(ProgressIndicator): """Abstract base class for {Color,Monochrome}ProgressIndicator""" @@ -194,22 +194,22 @@ class CompactProgressIndicator(ProgressIndicator): self.PrintProgress('Done') print "" # Line break. - def HasRun(self, test, has_unexpected_output): - self.PrintProgress(test.GetLabel()) + def HasRun(self, test, output, has_unexpected_output): + self.PrintProgress(str(test)) if has_unexpected_output: self.ClearLine(self.last_status_length) self.PrintFailureHeader(test) - stdout = test.output.stdout.strip() + stdout = output.stdout.strip() if len(stdout): print self.templates['stdout'] % stdout - stderr = test.output.stderr.strip() + stderr = output.stderr.strip() if len(stderr): print self.templates['stderr'] % stderr - print "Command: %s" % self._EscapeCommand(test) - if test.output.HasCrashed(): - print "exit code: %d" % test.output.exit_code + print "Command: %s" % test.cmd.to_string() + if output.HasCrashed(): + print "exit code: %d" % output.exit_code print "--- CRASHED ---" - if test.output.HasTimedOut(): + if output.HasTimedOut(): print "--- TIMEOUT ---" def Truncate(self, string, length): @@ -254,6 +254,9 @@ class ColorProgressIndicator(CompactProgressIndicator): def ClearLine(self, last_line_length): print "\033[1K\r", + def ToProgressIndicatorProc(self): + return progress_proc.ColorProgressIndicator() + class MonochromeProgressIndicator(CompactProgressIndicator): @@ -269,10 +272,15 @@ class MonochromeProgressIndicator(CompactProgressIndicator): def ClearLine(self, last_line_length): print ("\r" + (" " * last_line_length) + "\r"), + def ToProgressIndicatorProc(self): + return progress_proc.MonochromeProgressIndicator() -class JUnitTestProgressIndicator(ProgressIndicator): +class JUnitTestProgressIndicator(ProgressIndicator): def __init__(self, junitout, junittestsuite): + super(JUnitTestProgressIndicator, self).__init__() + self.junitout = junitout + self.juinttestsuite = junittestsuite self.outputter = junit_output.JUnitTestOutput(junittestsuite) if junitout: self.outfile = open(junitout, "w") @@ -284,29 +292,37 @@ class JUnitTestProgressIndicator(ProgressIndicator): if self.outfile != sys.stdout: self.outfile.close() - def HasRun(self, test, has_unexpected_output): + def HasRun(self, test, output, has_unexpected_output): fail_text = "" if has_unexpected_output: - stdout = test.output.stdout.strip() + stdout = output.stdout.strip() if len(stdout): fail_text += "stdout:\n%s\n" % stdout - stderr = test.output.stderr.strip() + stderr = output.stderr.strip() if len(stderr): fail_text += "stderr:\n%s\n" % stderr - fail_text += "Command: %s" % self._EscapeCommand(test) - if test.output.HasCrashed(): - fail_text += "exit code: %d\n--- CRASHED ---" % test.output.exit_code - if test.output.HasTimedOut(): + fail_text += "Command: %s" % test.cmd.to_string() + if output.HasCrashed(): + fail_text += "exit code: %d\n--- CRASHED ---" % output.exit_code + if output.HasTimedOut(): fail_text += "--- TIMEOUT ---" self.outputter.HasRunTest( - [test.GetLabel()] + self.runner.context.mode_flags + test.flags, - test.duration, - fail_text) + test_name=str(test), + test_cmd=test.cmd.to_string(relative=True), + test_duration=output.duration, + test_failure=fail_text) + + def ToProgressIndicatorProc(self): + if self.outfile != sys.stdout: + self.outfile.close() + return progress_proc.JUnitTestProgressIndicator(self.junitout, + self.junittestsuite) class JsonTestProgressIndicator(ProgressIndicator): def __init__(self, json_test_results, arch, mode, random_seed): + super(JsonTestProgressIndicator, self).__init__() self.json_test_results = json_test_results self.arch = arch self.mode = mode @@ -314,6 +330,10 @@ class JsonTestProgressIndicator(ProgressIndicator): self.results = [] self.tests = [] + def ToProgressIndicatorProc(self): + return progress_proc.JsonTestProgressIndicator( + self.json_test_results, self.arch, self.mode, self.random_seed) + def Done(self): complete_results = [] if os.path.exists(self.json_test_results): @@ -325,20 +345,19 @@ class JsonTestProgressIndicator(ProgressIndicator): if self.tests: # Get duration mean. duration_mean = ( - sum(t.duration for t in self.tests) / float(len(self.tests))) + sum(duration for (_, duration) in self.tests) / + float(len(self.tests))) # Sort tests by duration. - timed_tests = [t for t in self.tests if t.duration is not None] - timed_tests.sort(lambda a, b: cmp(b.duration, a.duration)) + self.tests.sort(key=lambda (_, duration): duration, reverse=True) slowest_tests = [ { - "name": test.GetLabel(), - "flags": test.flags, - "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""), - "duration": test.duration, - "marked_slow": statusfile.IsSlow( - test.suite.GetStatusFileOutcomes(test)), - } for test in timed_tests[:20] + "name": str(test), + "flags": test.cmd.args, + "command": test.cmd.to_string(relative=True), + "duration": duration, + "marked_slow": test.is_slow, + } for (test, duration) in self.tests[:20] ] complete_results.append({ @@ -353,30 +372,30 @@ class JsonTestProgressIndicator(ProgressIndicator): with open(self.json_test_results, "w") as f: f.write(json.dumps(complete_results)) - def HasRun(self, test, has_unexpected_output): + def HasRun(self, test, output, has_unexpected_output): # Buffer all tests for sorting the durations in the end. - self.tests.append(test) + self.tests.append((test, output.duration)) if not has_unexpected_output: # Omit tests that run as expected. Passing tests of reruns after failures # will have unexpected_output to be reported here has well. return self.results.append({ - "name": test.GetLabel(), - "flags": test.flags, - "command": self._EscapeCommand(test).replace(ABS_PATH_PREFIX, ""), + "name": str(test), + "flags": test.cmd.args, + "command": test.cmd.to_string(relative=True), "run": test.run, - "stdout": test.output.stdout, - "stderr": test.output.stderr, - "exit_code": test.output.exit_code, - "result": test.suite.GetOutcome(test), - "expected": test.suite.GetExpectedOutcomes(test), - "duration": test.duration, + "stdout": output.stdout, + "stderr": output.stderr, + "exit_code": output.exit_code, + "result": test.output_proc.get_outcome(output), + "expected": test.expected_outcomes, + "duration": output.duration, # TODO(machenbach): This stores only the global random seed from the # context and not possible overrides when using random-seed stress. "random_seed": self.random_seed, - "target_name": test.suite.GetShellForTestCase(test), + "target_name": test.get_shell(), "variant": test.variant, }) @@ -384,6 +403,7 @@ class JsonTestProgressIndicator(ProgressIndicator): class FlakinessTestProgressIndicator(ProgressIndicator): def __init__(self, json_test_results): + super(FlakinessTestProgressIndicator, self).__init__() self.json_test_results = json_test_results self.results = {} self.summary = { @@ -405,28 +425,23 @@ class FlakinessTestProgressIndicator(ProgressIndicator): "version": 3, }, f) - def HasRun(self, test, has_unexpected_output): - key = "/".join( - sorted(flag.lstrip("-") - for flag in self.runner.context.extra_flags + test.flags) + - ["test", test.GetLabel()], - ) - outcome = test.suite.GetOutcome(test) + def HasRun(self, test, output, has_unexpected_output): + key = test.get_id() + outcome = test.output_proc.get_outcome(output) assert outcome in ["PASS", "FAIL", "CRASH", "TIMEOUT"] if test.run == 1: # First run of this test. - expected_outcomes = test.suite.GetExpectedOutcomes(test) self.results[key] = { "actual": outcome, - "expected": " ".join(expected_outcomes), - "times": [test.duration], + "expected": " ".join(test.expected_outcomes), + "times": [output.duration], } self.summary[outcome] = self.summary[outcome] + 1 else: # This is a rerun and a previous result exists. result = self.results[key] result["actual"] = "%s %s" % (result["actual"], outcome) - result["times"].append(test.duration) + result["times"].append(output.duration) PROGRESS_INDICATORS = { diff --git a/deps/v8/tools/testrunner/local/statusfile.py b/deps/v8/tools/testrunner/local/statusfile.py index 7caf0711ca..988750d6b4 100644 --- a/deps/v8/tools/testrunner/local/statusfile.py +++ b/deps/v8/tools/testrunner/local/statusfile.py @@ -44,14 +44,13 @@ FAIL_SLOPPY = "FAIL_SLOPPY" # Modifiers SKIP = "SKIP" SLOW = "SLOW" -FAST_VARIANTS = "FAST_VARIANTS" NO_VARIANTS = "NO_VARIANTS" ALWAYS = "ALWAYS" KEYWORDS = {} -for key in [SKIP, FAIL, PASS, CRASH, SLOW, FAIL_OK, FAST_VARIANTS, NO_VARIANTS, - FAIL_SLOPPY, ALWAYS]: +for key in [SKIP, FAIL, PASS, CRASH, SLOW, FAIL_OK, NO_VARIANTS, FAIL_SLOPPY, + ALWAYS]: KEYWORDS[key] = key # Support arches, modes to be written as keywords instead of strings. @@ -67,31 +66,73 @@ for var in ["debug", "release", "big", "little", for var in ALL_VARIANTS: VARIABLES[var] = var +class StatusFile(object): + def __init__(self, path, variables): + """ + _rules: {variant: {test name: [rule]}} + _prefix_rules: {variant: {test name prefix: [rule]}} + """ + with open(path) as f: + self._rules, self._prefix_rules = ReadStatusFile(f.read(), variables) -def DoSkip(outcomes): - return SKIP in outcomes + def get_outcomes(self, testname, variant=None): + """Merges variant dependent and independent rules.""" + outcomes = frozenset() + for key in set([variant or '', '']): + rules = self._rules.get(key, {}) + prefix_rules = self._prefix_rules.get(key, {}) -def IsSlow(outcomes): - return SLOW in outcomes + if testname in rules: + outcomes |= rules[testname] + for prefix in prefix_rules: + if testname.startswith(prefix): + outcomes |= prefix_rules[prefix] -def OnlyStandardVariant(outcomes): - return NO_VARIANTS in outcomes + return outcomes + def warn_unused_rules(self, tests, check_variant_rules=False): + """Finds and prints unused rules in status file. -def OnlyFastVariants(outcomes): - return FAST_VARIANTS in outcomes + Rule X is unused when it doesn't apply to any tests, which can also mean + that all matching tests were skipped by another rule before evaluating X. + Args: + tests: list of pairs (testname, variant) + check_variant_rules: if set variant dependent rules are checked + """ -def IsPassOrFail(outcomes): - return (PASS in outcomes and - FAIL in outcomes and - CRASH not in outcomes) - - -def IsFailOk(outcomes): - return FAIL_OK in outcomes + if check_variant_rules: + variants = list(ALL_VARIANTS) + else: + variants = [''] + used_rules = set() + + for testname, variant in tests: + variant = variant or '' + + if testname in self._rules.get(variant, {}): + used_rules.add((testname, variant)) + if SKIP in self._rules[variant][testname]: + continue + + for prefix in self._prefix_rules.get(variant, {}): + if testname.startswith(prefix): + used_rules.add((prefix, variant)) + if SKIP in self._prefix_rules[variant][prefix]: + break + + for variant in variants: + for rule, value in ( + list(self._rules.get(variant, {}).iteritems()) + + list(self._prefix_rules.get(variant, {}).iteritems())): + if (rule, variant) not in used_rules: + if variant == '': + variant_desc = 'variant independent' + else: + variant_desc = 'variant: %s' % variant + print 'Unused rule: %s -> %s (%s)' % (rule, value, variant_desc) def _JoinsPassAndFail(outcomes1, outcomes2): diff --git a/deps/v8/tools/testrunner/local/testsuite.py b/deps/v8/tools/testrunner/local/testsuite.py index 946e89a3fc..6a9e9831ce 100644 --- a/deps/v8/tools/testrunner/local/testsuite.py +++ b/deps/v8/tools/testrunner/local/testsuite.py @@ -30,55 +30,65 @@ import fnmatch import imp import os -from . import commands +from . import command from . import statusfile from . import utils -from ..objects import testcase -from variants import ALL_VARIANTS, ALL_VARIANT_FLAGS, FAST_VARIANT_FLAGS +from ..objects.testcase import TestCase +from variants import ALL_VARIANTS, ALL_VARIANT_FLAGS -FAST_VARIANTS = set(["default", "turbofan"]) STANDARD_VARIANT = set(["default"]) -class VariantGenerator(object): +class LegacyVariantsGenerator(object): def __init__(self, suite, variants): self.suite = suite self.all_variants = ALL_VARIANTS & variants - self.fast_variants = FAST_VARIANTS & variants self.standard_variant = STANDARD_VARIANT & variants + def FilterVariantsByTest(self, test): + if test.only_standard_variant: + return self.standard_variant + return self.all_variants + + def GetFlagSets(self, test, variant): + return ALL_VARIANT_FLAGS[variant] + + +class StandardLegacyVariantsGenerator(LegacyVariantsGenerator): def FilterVariantsByTest(self, testcase): - result = self.all_variants - outcomes = testcase.suite.GetStatusFileOutcomes(testcase) - if outcomes: - if statusfile.OnlyStandardVariant(outcomes): - return self.standard_variant - if statusfile.OnlyFastVariants(outcomes): - result = self.fast_variants - return result - - def GetFlagSets(self, testcase, variant): - outcomes = testcase.suite.GetStatusFileOutcomes(testcase) - if outcomes and statusfile.OnlyFastVariants(outcomes): - return FAST_VARIANT_FLAGS[variant] - else: - return ALL_VARIANT_FLAGS[variant] + return self.standard_variant -class TestSuite(object): +class VariantsGenerator(object): + def __init__(self, variants): + self._all_variants = [v for v in variants if v in ALL_VARIANTS] + self._standard_variant = [v for v in variants if v in STANDARD_VARIANT] + + def gen(self, test): + """Generator producing (variant, flags, procid suffix) tuples.""" + flags_set = self._get_flags_set(test) + for n, variant in enumerate(self._get_variants(test)): + yield (variant, flags_set[variant][0], n) + + def _get_flags_set(self, test): + return ALL_VARIANT_FLAGS + def _get_variants(self, test): + if test.only_standard_variant: + return self._standard_variant + return self._all_variants + + +class TestSuite(object): @staticmethod - def LoadTestSuite(root, global_init=True): + def LoadTestSuite(root): name = root.split(os.path.sep)[-1] f = None try: (f, pathname, description) = imp.find_module("testcfg", [root]) module = imp.load_module(name + "_testcfg", f, pathname, description) return module.GetSuite(name, root) - except ImportError: - # Use default if no testcfg is present. - return GoogleTestSuite(name, root) finally: if f: f.close() @@ -88,69 +98,40 @@ class TestSuite(object): self.name = name # string self.root = root # string containing path self.tests = None # list of TestCase objects - self.rules = None # {variant: {test name: [rule]}} - self.prefix_rules = None # {variant: {test name prefix: [rule]}} - self.total_duration = None # float, assigned on demand - - self._outcomes_cache = dict() - - def suffix(self): - return ".js" + self.statusfile = None def status_file(self): return "%s/%s.status" % (self.root, self.name) - # Used in the status file and for stdout printing. - def CommonTestName(self, testcase): - if utils.IsWindows(): - return testcase.path.replace("\\", "/") - else: - return testcase.path - def ListTests(self, context): raise NotImplementedError - def _VariantGeneratorFactory(self): + def _LegacyVariantsGeneratorFactory(self): """The variant generator class to be used.""" - return VariantGenerator + return LegacyVariantsGenerator - def CreateVariantGenerator(self, variants): + def CreateLegacyVariantsGenerator(self, variants): """Return a generator for the testing variants of this suite. Args: variants: List of variant names to be run as specified by the test runner. - Returns: An object of type VariantGenerator. + Returns: An object of type LegacyVariantsGenerator. """ - return self._VariantGeneratorFactory()(self, set(variants)) + return self._LegacyVariantsGeneratorFactory()(self, set(variants)) - def PrepareSources(self): - """Called once before multiprocessing for doing file-system operations. + def get_variants_gen(self, variants): + return self._variants_gen_class()(variants) - This should not access the network. For network access use the method - below. - """ - pass + def _variants_gen_class(self): + return VariantsGenerator def ReadStatusFile(self, variables): - with open(self.status_file()) as f: - self.rules, self.prefix_rules = ( - statusfile.ReadStatusFile(f.read(), variables)) + self.statusfile = statusfile.StatusFile(self.status_file(), variables) def ReadTestCases(self, context): self.tests = self.ListTests(context) - def GetStatusfileFlags(self, test): - """Gets runtime flags from a status file. - - Every outcome that starts with "--" is a flag. Status file has to be loaded - before using this function. - """ - flags = [] - for outcome in self.GetStatusFileOutcomes(test): - if outcome.startswith('--'): - flags.append(outcome) - return flags def FilterTestCasesByStatus(self, slow_tests_mode=None, @@ -179,58 +160,16 @@ class TestSuite(object): (mode == 'skip' and pass_fail)) def _compliant(test): - outcomes = self.GetStatusFileOutcomes(test) - if statusfile.DoSkip(outcomes): + if test.do_skip: return False - if _skip_slow(statusfile.IsSlow(outcomes), slow_tests_mode): + if _skip_slow(test.is_slow, slow_tests_mode): return False - if _skip_pass_fail(statusfile.IsPassOrFail(outcomes), - pass_fail_tests_mode): + if _skip_pass_fail(test.is_pass_or_fail, pass_fail_tests_mode): return False return True self.tests = filter(_compliant, self.tests) - def WarnUnusedRules(self, check_variant_rules=False): - """Finds and prints unused rules in status file. - - Rule X is unused when it doesn't apply to any tests, which can also mean - that all matching tests were skipped by another rule before evaluating X. - - Status file has to be loaded before using this function. - """ - - if check_variant_rules: - variants = list(ALL_VARIANTS) - else: - variants = [''] - used_rules = set() - - for t in self.tests: - testname = self.CommonTestName(t) - variant = t.variant or "" - - if testname in self.rules.get(variant, {}): - used_rules.add((testname, variant)) - if statusfile.DoSkip(self.rules[variant][testname]): - continue - - for prefix in self.prefix_rules.get(variant, {}): - if testname.startswith(prefix): - used_rules.add((prefix, variant)) - if statusfile.DoSkip(self.prefix_rules[variant][prefix]): - break - - for variant in variants: - for rule, value in (list(self.rules.get(variant, {}).iteritems()) + - list(self.prefix_rules.get(variant, {}).iteritems())): - if (rule, variant) not in used_rules: - if variant == '': - variant_desc = 'variant independent' - else: - variant_desc = 'variant: %s' % variant - print('Unused rule: %s -> %s (%s)' % (rule, value, variant_desc)) - def FilterTestCasesByArgs(self, args): """Filter test cases based on command-line arguments. @@ -256,167 +195,14 @@ class TestSuite(object): break self.tests = filtered - def GetExpectedOutcomes(self, testcase): - """Gets expected outcomes from status file. + def _create_test(self, path, **kwargs): + test = self._test_class()(self, path, self._path_to_name(path), **kwargs) + return test - It differs from GetStatusFileOutcomes by selecting only outcomes that can - be result of test execution. - Status file has to be loaded before using this function. - """ - outcomes = self.GetStatusFileOutcomes(testcase) - - expected = [] - if (statusfile.FAIL in outcomes or - statusfile.FAIL_OK in outcomes): - expected.append(statusfile.FAIL) - - if statusfile.CRASH in outcomes: - expected.append(statusfile.CRASH) - - if statusfile.PASS in outcomes: - expected.append(statusfile.PASS) - - return expected or [statusfile.PASS] - - def GetStatusFileOutcomes(self, testcase): - """Gets outcomes from status file. - - Merges variant dependent and independent rules. Status file has to be loaded - before using this function. - """ - variant = testcase.variant or '' - testname = self.CommonTestName(testcase) - cache_key = '%s$%s' % (testname, variant) - - if cache_key not in self._outcomes_cache: - # Load statusfile to get outcomes for the first time. - assert(self.rules is not None) - assert(self.prefix_rules is not None) - - outcomes = frozenset() - - for key in set([variant, '']): - rules = self.rules.get(key, {}) - prefix_rules = self.prefix_rules.get(key, {}) - - if testname in rules: - outcomes |= rules[testname] - - for prefix in prefix_rules: - if testname.startswith(prefix): - outcomes |= prefix_rules[prefix] - - self._outcomes_cache[cache_key] = outcomes - - return self._outcomes_cache[cache_key] - - def GetShellForTestCase(self, testcase): - """Returns shell to be executed for this test case.""" - return 'd8' - - def GetParametersForTestCase(self, testcase, context): - """Returns a tuple of (files, flags, env) for this test case.""" + def _test_class(self): raise NotImplementedError - def GetSourceForTest(self, testcase): - return "(no source available)" - - def IsFailureOutput(self, testcase): - return testcase.output.exit_code != 0 - - def IsNegativeTest(self, testcase): - return False - - def HasFailed(self, testcase): - execution_failed = self.IsFailureOutput(testcase) - if self.IsNegativeTest(testcase): - return not execution_failed - else: - return execution_failed - - def GetOutcome(self, testcase): - if testcase.output.HasCrashed(): - return statusfile.CRASH - elif testcase.output.HasTimedOut(): - return statusfile.TIMEOUT - elif self.HasFailed(testcase): - return statusfile.FAIL - else: - return statusfile.PASS - - def HasUnexpectedOutput(self, testcase): - return self.GetOutcome(testcase) not in self.GetExpectedOutcomes(testcase) - - def StripOutputForTransmit(self, testcase): - if not self.HasUnexpectedOutput(testcase): - testcase.output.stdout = "" - testcase.output.stderr = "" - - def CalculateTotalDuration(self): - self.total_duration = 0.0 - for t in self.tests: - self.total_duration += t.duration - return self.total_duration - - -class StandardVariantGenerator(VariantGenerator): - def FilterVariantsByTest(self, testcase): - return self.standard_variant - - -class GoogleTestSuite(TestSuite): - def __init__(self, name, root): - super(GoogleTestSuite, self).__init__(name, root) - - def ListTests(self, context): - shell = os.path.abspath( - os.path.join(context.shell_dir, self.GetShellForTestCase(None))) + def _path_to_name(self, path): if utils.IsWindows(): - shell += ".exe" - - output = None - for i in xrange(3): # Try 3 times in case of errors. - cmd = ( - context.command_prefix + - [shell, "--gtest_list_tests"] + - context.extra_flags - ) - output = commands.Execute(cmd) - if output.exit_code == 0: - break - print "Test executable failed to list the tests (try %d).\n\nCmd:" % i - print ' '.join(cmd) - print "\nStdout:" - print output.stdout - print "\nStderr:" - print output.stderr - print "\nExit code: %d" % output.exit_code - else: - raise Exception("Test executable failed to list the tests.") - - tests = [] - test_case = '' - for line in output.stdout.splitlines(): - test_desc = line.strip().split()[0] - if test_desc.endswith('.'): - test_case = test_desc - elif test_case and test_desc: - test = testcase.TestCase(self, test_case + test_desc) - tests.append(test) - tests.sort(key=lambda t: t.path) - return tests - - def GetParametersForTestCase(self, testcase, context): - flags = ( - testcase.flags + - ["--gtest_filter=" + testcase.path] + - ["--gtest_random_seed=%s" % context.random_seed] + - ["--gtest_print_time=0"] + - context.mode_flags) - return [], flags, {} - - def _VariantGeneratorFactory(self): - return StandardVariantGenerator - - def GetShellForTestCase(self, testcase): - return self.name + return path.replace("\\", "/") + return path diff --git a/deps/v8/tools/testrunner/local/testsuite_unittest.py b/deps/v8/tools/testrunner/local/testsuite_unittest.py index a8483b9fc0..efefe4c533 100755 --- a/deps/v8/tools/testrunner/local/testsuite_unittest.py +++ b/deps/v8/tools/testrunner/local/testsuite_unittest.py @@ -19,10 +19,6 @@ from testrunner.objects.testcase import TestCase class TestSuiteTest(unittest.TestCase): def test_filter_testcases_by_status_first_pass(self): suite = TestSuite('foo', 'bar') - suite.tests = [ - TestCase(suite, 'foo/bar'), - TestCase(suite, 'baz/bar'), - ] suite.rules = { '': { 'foo/bar': set(['PASS', 'SKIP']), @@ -34,27 +30,22 @@ class TestSuiteTest(unittest.TestCase): 'baz/': set(['PASS', 'SLOW']), }, } + suite.tests = [ + TestCase(suite, 'foo/bar', 'foo/bar'), + TestCase(suite, 'baz/bar', 'baz/bar'), + ] suite.FilterTestCasesByStatus() self.assertEquals( - [TestCase(suite, 'baz/bar')], + [TestCase(suite, 'baz/bar', 'baz/bar')], suite.tests, ) - outcomes = suite.GetStatusFileOutcomes(suite.tests[0]) + outcomes = suite.GetStatusFileOutcomes(suite.tests[0].name, + suite.tests[0].variant) self.assertEquals(set(['PASS', 'FAIL', 'SLOW']), outcomes) def test_filter_testcases_by_status_second_pass(self): suite = TestSuite('foo', 'bar') - test1 = TestCase(suite, 'foo/bar') - test2 = TestCase(suite, 'baz/bar') - - suite.tests = [ - test1.CopyAddingFlags(variant='default', flags=[]), - test1.CopyAddingFlags(variant='stress', flags=['-v']), - test2.CopyAddingFlags(variant='default', flags=[]), - test2.CopyAddingFlags(variant='stress', flags=['-v']), - ] - suite.rules = { '': { 'foo/bar': set(['PREV']), @@ -78,30 +69,38 @@ class TestSuiteTest(unittest.TestCase): 'foo/': set(['PASS', 'SLOW']), }, } + + test1 = TestCase(suite, 'foo/bar', 'foo/bar') + test2 = TestCase(suite, 'baz/bar', 'baz/bar') + suite.tests = [ + test1.create_variant(variant='default', flags=[]), + test1.create_variant(variant='stress', flags=['-v']), + test2.create_variant(variant='default', flags=[]), + test2.create_variant(variant='stress', flags=['-v']), + ] + suite.FilterTestCasesByStatus() self.assertEquals( [ - TestCase(suite, 'foo/bar', flags=['-v']), - TestCase(suite, 'baz/bar'), + TestCase(suite, 'foo/bar', 'foo/bar').create_variant(None, ['-v']), + TestCase(suite, 'baz/bar', 'baz/bar'), ], suite.tests, ) self.assertEquals( set(['PREV', 'PASS', 'SLOW']), - suite.GetStatusFileOutcomes(suite.tests[0]), + suite.GetStatusFileOutcomes(suite.tests[0].name, + suite.tests[0].variant), ) self.assertEquals( set(['PREV', 'PASS', 'FAIL', 'SLOW']), - suite.GetStatusFileOutcomes(suite.tests[1]), + suite.GetStatusFileOutcomes(suite.tests[1].name, + suite.tests[1].variant), ) def test_fail_ok_outcome(self): suite = TestSuite('foo', 'bar') - suite.tests = [ - TestCase(suite, 'foo/bar'), - TestCase(suite, 'baz/bar'), - ] suite.rules = { '': { 'foo/bar': set(['FAIL_OK']), @@ -109,10 +108,13 @@ class TestSuiteTest(unittest.TestCase): }, } suite.prefix_rules = {} + suite.tests = [ + TestCase(suite, 'foo/bar', 'foo/bar'), + TestCase(suite, 'baz/bar', 'baz/bar'), + ] for t in suite.tests: - expected_outcomes = suite.GetExpectedOutcomes(t) - self.assertEquals(['FAIL'], expected_outcomes) + self.assertEquals(['FAIL'], t.expected_outcomes) if __name__ == '__main__': diff --git a/deps/v8/tools/testrunner/local/utils.py b/deps/v8/tools/testrunner/local/utils.py index 3e79e44afa..bf8c3d9f7e 100644 --- a/deps/v8/tools/testrunner/local/utils.py +++ b/deps/v8/tools/testrunner/local/utils.py @@ -26,10 +26,10 @@ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -import os from os.path import exists from os.path import isdir from os.path import join +import os import platform import re import subprocess diff --git a/deps/v8/tools/testrunner/local/variants.py b/deps/v8/tools/testrunner/local/variants.py index c8c7ce64a8..f1e9ad301e 100644 --- a/deps/v8/tools/testrunner/local/variants.py +++ b/deps/v8/tools/testrunner/local/variants.py @@ -4,38 +4,26 @@ # Use this to run several variants of the tests. ALL_VARIANT_FLAGS = { + "code_serializer": [["--cache=code"]], "default": [[]], "future": [["--future"]], + # Alias of exhaustive variants, but triggering new test framework features. + "infra_staging": [[]], "liftoff": [["--liftoff"]], - "stress": [["--stress-opt", "--always-opt"]], - # TODO(6792): Write protected code has been temporary added to the below - # variant until the feature has been enabled (or staged) by default. - "stress_incremental_marking": [["--stress-incremental-marking", "--write-protect-code-memory"]], - # No optimization means disable all optimizations. OptimizeFunctionOnNextCall - # would not force optimization too. It turns into a Nop. Please see - # https://chromium-review.googlesource.com/c/452620/ for more discussion. - "nooptimization": [["--noopt"]], - "stress_background_compile": [["--background-compile", "--stress-background-compile"]], - "wasm_traps": [["--wasm_trap_handler", "--invoke-weak-callbacks", "--wasm-jit-to-native"]], -} - -# FAST_VARIANTS implies no --always-opt. -FAST_VARIANT_FLAGS = { - "default": [[]], - "future": [["--future"]], - "liftoff": [["--liftoff"]], - "stress": [["--stress-opt"]], - # TODO(6792): Write protected code has been temporary added to the below - # variant until the feature has been enabled (or staged) by default. - "stress_incremental_marking": [["--stress-incremental-marking", "--write-protect-code-memory"]], + "minor_mc": [["--minor-mc"]], # No optimization means disable all optimizations. OptimizeFunctionOnNextCall # would not force optimization too. It turns into a Nop. Please see # https://chromium-review.googlesource.com/c/452620/ for more discussion. "nooptimization": [["--noopt"]], + "slow_path": [["--force-slow-path"]], + "stress": [["--stress-opt", "--always-opt"]], "stress_background_compile": [["--background-compile", "--stress-background-compile"]], + "stress_incremental_marking": [["--stress-incremental-marking"]], + # Trigger stress sampling allocation profiler with sample interval = 2^14 + "stress_sampling": [["--stress-sampling-allocation-profiler=16384"]], + "trusted": [["--no-untrusted-code-mitigations"]], "wasm_traps": [["--wasm_trap_handler", "--invoke-weak-callbacks", "--wasm-jit-to-native"]], + "wasm_no_native": [["--no-wasm-jit-to-native"]], } -ALL_VARIANTS = set(["default", "future", "liftoff", "stress", - "stress_incremental_marking", "nooptimization", - "stress_background_compile", "wasm_traps"]) +ALL_VARIANTS = set(ALL_VARIANT_FLAGS.keys()) diff --git a/deps/v8/tools/testrunner/local/verbose.py b/deps/v8/tools/testrunner/local/verbose.py index f28398fa42..49e808588c 100644 --- a/deps/v8/tools/testrunner/local/verbose.py +++ b/deps/v8/tools/testrunner/local/verbose.py @@ -38,28 +38,30 @@ REPORT_TEMPLATE = ( * %(nocrash)4d tests are expected to be flaky but not crash * %(pass)4d tests are expected to pass * %(fail_ok)4d tests are expected to fail that we won't fix - * %(fail)4d tests are expected to fail that we should fix""") + * %(fail)4d tests are expected to fail that we should fix + * %(crash)4d tests are expected to crash +""") +# TODO(majeski): Turn it into an observer. def PrintReport(tests): total = len(tests) - skipped = nocrash = passes = fail_ok = fail = 0 + skipped = nocrash = passes = fail_ok = fail = crash = 0 for t in tests: - outcomes = t.suite.GetStatusFileOutcomes(t) - if not outcomes: - passes += 1 - continue - if statusfile.DoSkip(outcomes): + if t.do_skip: skipped += 1 - continue - if statusfile.IsPassOrFail(outcomes): + elif t.is_pass_or_fail: nocrash += 1 - if list(outcomes) == [statusfile.PASS]: - passes += 1 - if statusfile.IsFailOk(outcomes): + elif t.is_fail_ok: fail_ok += 1 - if list(outcomes) == [statusfile.FAIL]: + elif t.expected_outcomes == [statusfile.PASS]: + passes += 1 + elif t.expected_outcomes == [statusfile.FAIL]: fail += 1 + elif t.expected_outcomes == [statusfile.CRASH]: + crash += 1 + else: + assert False # Unreachable # TODO: check this in outcomes parsing phase. print REPORT_TEMPLATE % { "total": total, @@ -67,18 +69,19 @@ def PrintReport(tests): "nocrash": nocrash, "pass": passes, "fail_ok": fail_ok, - "fail": fail + "fail": fail, + "crash": crash, } def PrintTestSource(tests): for test in tests: - suite = test.suite - source = suite.GetSourceForTest(test).strip() - if len(source) > 0: - print "--- begin source: %s/%s ---" % (suite.name, test.path) - print source - print "--- end source: %s/%s ---" % (suite.name, test.path) + print "--- begin source: %s ---" % test + if test.is_source_available(): + print test.get_source() + else: + print '(no source available)' + print "--- end source: %s ---" % test def FormatTime(d): @@ -86,16 +89,16 @@ def FormatTime(d): return time.strftime("%M:%S.", time.gmtime(d)) + ("%03i" % millis) -def PrintTestDurations(suites, overall_time): +def PrintTestDurations(suites, outputs, overall_time): # Write the times to stderr to make it easy to separate from the # test output. print sys.stderr.write("--- Total time: %s ---\n" % FormatTime(overall_time)) - timed_tests = [ t for s in suites for t in s.tests - if t.duration is not None ] - timed_tests.sort(lambda a, b: cmp(b.duration, a.duration)) + timed_tests = [(t, outputs[t].duration) for s in suites for t in s.tests + if t in outputs] + timed_tests.sort(key=lambda (_, duration): duration, reverse=True) index = 1 - for entry in timed_tests[:20]: - t = FormatTime(entry.duration) - sys.stderr.write("%4i (%s) %s\n" % (index, t, entry.GetLabel())) + for test, duration in timed_tests[:20]: + t = FormatTime(duration) + sys.stderr.write("%4i (%s) %s\n" % (index, t, test)) index += 1 diff --git a/deps/v8/tools/testrunner/objects/context.py b/deps/v8/tools/testrunner/objects/context.py index fb5d717728..a3dd56d2dd 100644 --- a/deps/v8/tools/testrunner/objects/context.py +++ b/deps/v8/tools/testrunner/objects/context.py @@ -29,8 +29,8 @@ class Context(): def __init__(self, arch, mode, shell_dir, mode_flags, verbose, timeout, isolates, command_prefix, extra_flags, noi18n, random_seed, - no_sorting, rerun_failures_count, rerun_failures_max, - predictable, no_harness, use_perf_data, sancov_dir): + no_sorting, rerun_failures_count, rerun_failures_max, no_harness, + use_perf_data, sancov_dir, infra_staging=False): self.arch = arch self.mode = mode self.shell_dir = shell_dir @@ -45,7 +45,7 @@ class Context(): self.no_sorting = no_sorting self.rerun_failures_count = rerun_failures_count self.rerun_failures_max = rerun_failures_max - self.predictable = predictable self.no_harness = no_harness self.use_perf_data = use_perf_data self.sancov_dir = sancov_dir + self.infra_staging = infra_staging diff --git a/deps/v8/tools/testrunner/objects/output.py b/deps/v8/tools/testrunner/objects/output.py index 99d6137698..adc33c9f12 100644 --- a/deps/v8/tools/testrunner/objects/output.py +++ b/deps/v8/tools/testrunner/objects/output.py @@ -32,12 +32,13 @@ from ..local import utils class Output(object): - def __init__(self, exit_code, timed_out, stdout, stderr, pid): + def __init__(self, exit_code, timed_out, stdout, stderr, pid, duration): self.exit_code = exit_code self.timed_out = timed_out self.stdout = stdout self.stderr = stderr self.pid = pid + self.duration = duration def HasCrashed(self): if utils.IsWindows(): diff --git a/deps/v8/tools/testrunner/objects/predictable.py b/deps/v8/tools/testrunner/objects/predictable.py new file mode 100644 index 0000000000..ad93077be9 --- /dev/null +++ b/deps/v8/tools/testrunner/objects/predictable.py @@ -0,0 +1,57 @@ +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from ..local import statusfile +from ..outproc import base as outproc_base +from ..testproc.result import Result + + +# Only check the exit code of the predictable_wrapper in +# verify-predictable mode. Negative tests are not supported as they +# usually also don't print allocation hashes. There are two versions of +# negative tests: one specified by the test, the other specified through +# the status file (e.g. known bugs). + + +def get_outproc(test): + output_proc = test.output_proc + if output_proc.negative or statusfile.FAIL in test.expected_outcomes: + # TODO(majeski): Skip these tests instead of having special outproc. + return NeverUnexpectedOutputOutProc(output_proc) + return OutProc(output_proc) + + +class OutProc(outproc_base.BaseOutProc): + """Output processor wrapper for predictable mode. It has custom process and + has_unexpected_output implementation, but for all other methods it simply + calls wrapped output processor. + """ + def __init__(self, _outproc): + super(OutProc, self).__init__() + self._outproc = _outproc + + def process(self, output): + return Result(self.has_unexpected_output(output), output) + + def has_unexpected_output(self, output): + return output.exit_code != 0 + + def get_outcome(self, output): + return self._outproc.get_outcome(output) + + @property + def negative(self): + return self._outproc.negative + + @property + def expected_outcomes(self): + return self._outproc.expected_outcomes + + +class NeverUnexpectedOutputOutProc(OutProc): + """Output processor wrapper for tests that we will return False for + has_unexpected_output in the predictable mode. + """ + def has_unexpected_output(self, output): + return False diff --git a/deps/v8/tools/testrunner/objects/testcase.py b/deps/v8/tools/testrunner/objects/testcase.py index fd8c27bc59..06db32802c 100644 --- a/deps/v8/tools/testrunner/objects/testcase.py +++ b/deps/v8/tools/testrunner/objects/testcase.py @@ -25,45 +25,274 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import copy +import os +import re +import shlex + +from ..outproc import base as outproc +from ..local import command +from ..local import statusfile +from ..local import utils + +FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") + + class TestCase(object): - def __init__(self, suite, path, variant=None, flags=None): + def __init__(self, suite, path, name): self.suite = suite # TestSuite object + self.path = path # string, e.g. 'div-mod', 'test-api/foo' - self.flags = flags or [] # list of strings, flags specific to this test - self.variant = variant # name of the used testing variant - self.output = None + self.name = name # string that identifies test in the status file + + self.variant = None # name of the used testing variant + self.variant_flags = [] # list of strings, flags specific to this test + self.id = None # int, used to map result back to TestCase instance - self.duration = None # assigned during execution self.run = 1 # The nth time this test is executed. + self.cmd = None + + # Fields used by the test processors. + self.origin = None # Test that this test is subtest of. + self.processor = None # Processor that created this subtest. + self.procid = '%s/%s' % (self.suite.name, self.name) # unique id + self.keep_output = False # Can output of this test be dropped + + self._statusfile_outcomes = None + self._expected_outcomes = None # optimization: None == [statusfile.PASS] + self._statusfile_flags = None + self._prepare_outcomes() + + def create_subtest(self, processor, subtest_id, variant=None, flags=None, + keep_output=False): + subtest = copy.copy(self) + subtest.origin = self + subtest.processor = processor + subtest.procid += '.%s' % subtest_id + subtest.keep_output = keep_output + if variant is not None: + assert self.variant is None + subtest.variant = variant + subtest.variant_flags = flags + subtest._prepare_outcomes() + return subtest + + def create_variant(self, variant, flags, procid_suffix=None): + """Makes a shallow copy of the object and updates variant, variant flags and + all fields that depend on it, e.g. expected outcomes. + + Args + variant - variant name + flags - flags that should be added to origin test's variant flags + procid_suffix - for multiple variants with the same name set suffix to + keep procid unique. + """ + other = copy.copy(self) + if not self.variant_flags: + other.variant_flags = flags + else: + other.variant_flags = self.variant_flags + flags + other.variant = variant + if procid_suffix: + other.procid += '[%s-%s]' % (variant, procid_suffix) + else: + other.procid += '[%s]' % variant + + other._prepare_outcomes(variant != self.variant) + + return other + + def _prepare_outcomes(self, force_update=True): + if force_update or self._statusfile_outcomes is None: + def is_flag(outcome): + return outcome.startswith('--') + def not_flag(outcome): + return not is_flag(outcome) + + outcomes = self.suite.statusfile.get_outcomes(self.name, self.variant) + self._statusfile_outcomes = filter(not_flag, outcomes) + self._statusfile_flags = filter(is_flag, outcomes) + self.expected_outcomes = ( + self._parse_status_file_outcomes(self._statusfile_outcomes)) + + def _parse_status_file_outcomes(self, outcomes): + if (statusfile.FAIL_SLOPPY in outcomes and + '--use-strict' not in self.variant_flags): + return outproc.OUTCOMES_FAIL + + expected_outcomes = [] + if (statusfile.FAIL in outcomes or + statusfile.FAIL_OK in outcomes): + expected_outcomes.append(statusfile.FAIL) + if statusfile.CRASH in outcomes: + expected_outcomes.append(statusfile.CRASH) + + # Do not add PASS if there is nothing else. Empty outcomes are converted to + # the global [PASS]. + if expected_outcomes and statusfile.PASS in outcomes: + expected_outcomes.append(statusfile.PASS) + + # Avoid creating multiple instances of a list with a single FAIL. + if expected_outcomes == outproc.OUTCOMES_FAIL: + return outproc.OUTCOMES_FAIL + return expected_outcomes or outproc.OUTCOMES_PASS + + @property + def do_skip(self): + return statusfile.SKIP in self._statusfile_outcomes + + @property + def is_slow(self): + return statusfile.SLOW in self._statusfile_outcomes + + @property + def is_fail_ok(self): + return statusfile.FAIL_OK in self._statusfile_outcomes - def CopyAddingFlags(self, variant, flags): - return TestCase(self.suite, self.path, variant, self.flags + flags) + @property + def is_pass_or_fail(self): + return (statusfile.PASS in self._statusfile_outcomes and + statusfile.FAIL in self._statusfile_outcomes and + statusfile.CRASH not in self._statusfile_outcomes) - def SetSuiteObject(self, suites): - self.suite = suites[self.suite] + @property + def only_standard_variant(self): + return statusfile.NO_VARIANTS in self._statusfile_outcomes - def suitename(self): - return self.suite.name + def get_command(self, context): + params = self._get_cmd_params(context) + env = self._get_cmd_env() + shell, shell_flags = self._get_shell_with_flags(context) + timeout = self._get_timeout(params, context.timeout) + return self._create_cmd(shell, shell_flags + params, env, timeout, context) - def GetLabel(self): - return self.suitename() + "/" + self.suite.CommonTestName(self) + def _get_cmd_params(self, ctx): + """Gets command parameters and combines them in the following order: + - files [empty by default] + - extra flags (from command line) + - user flags (variant/fuzzer flags) + - statusfile flags + - mode flags (based on chosen mode) + - source flags (from source code) [empty by default] - def __getstate__(self): - """Representation to pickle test cases. + The best way to modify how parameters are created is to only override + methods for getting partial parameters. + """ + return ( + self._get_files_params(ctx) + + self._get_extra_flags(ctx) + + self._get_variant_flags() + + self._get_statusfile_flags() + + self._get_mode_flags(ctx) + + self._get_source_flags() + + self._get_suite_flags(ctx) + ) + + def _get_cmd_env(self): + return {} + + def _get_files_params(self, ctx): + return [] + + def _get_extra_flags(self, ctx): + return ctx.extra_flags + + def _get_variant_flags(self): + return self.variant_flags - The original suite won't be sent beyond process boundaries. Instead - send the name only and retrieve a process-local suite later. + def _get_statusfile_flags(self): + """Gets runtime flags from a status file. + + Every outcome that starts with "--" is a flag. """ - return dict(self.__dict__, suite=self.suite.name) + return self._statusfile_flags + + def _get_mode_flags(self, ctx): + return ctx.mode_flags + + def _get_source_flags(self): + return [] + + def _get_suite_flags(self, ctx): + return [] + + def _get_shell_with_flags(self, ctx): + shell = self.get_shell() + shell_flags = [] + if shell == 'd8': + shell_flags.append('--test') + if utils.IsWindows(): + shell += '.exe' + if ctx.random_seed: + shell_flags.append('--random-seed=%s' % ctx.random_seed) + return shell, shell_flags + + def _get_timeout(self, params, timeout): + if "--stress-opt" in params: + timeout *= 4 + if "--noenable-vfp3" in params: + timeout *= 2 + + # TODO(majeski): make it slow outcome dependent. + timeout *= 2 + return timeout + + def get_shell(self): + return 'd8' + + def _get_suffix(self): + return '.js' + + def _create_cmd(self, shell, params, env, timeout, ctx): + return command.Command( + cmd_prefix=ctx.command_prefix, + shell=os.path.abspath(os.path.join(ctx.shell_dir, shell)), + args=params, + env=env, + timeout=timeout, + verbose=ctx.verbose + ) + + def _parse_source_flags(self, source=None): + source = source or self.get_source() + flags = [] + for match in re.findall(FLAGS_PATTERN, source): + flags += shlex.split(match.strip()) + return flags + + def is_source_available(self): + return self._get_source_path() is not None + + def get_source(self): + with open(self._get_source_path()) as f: + return f.read() + + def _get_source_path(self): + return None + + @property + def output_proc(self): + if self.expected_outcomes is outproc.OUTCOMES_PASS: + return outproc.DEFAULT + return outproc.OutProc(self.expected_outcomes) def __cmp__(self, other): # Make sure that test cases are sorted correctly if sorted without # key function. But using a key function is preferred for speed. return cmp( - (self.suite.name, self.path, self.flags), - (other.suite.name, other.path, other.flags), + (self.suite.name, self.name, self.variant_flags), + (other.suite.name, other.name, other.variant_flags) ) + def __hash__(self): + return hash((self.suite.name, self.name, ''.join(self.variant_flags))) + def __str__(self): - return "[%s/%s %s]" % (self.suite.name, self.path, self.flags) + return self.suite.name + '/' + self.name + + # TODO(majeski): Rename `id` field or `get_id` function since they're + # unrelated. + def get_id(self): + return '%s/%s %s' % ( + self.suite.name, self.name, ' '.join(self.variant_flags)) diff --git a/deps/v8/tools/testrunner/outproc/__init__.py b/deps/v8/tools/testrunner/outproc/__init__.py new file mode 100644 index 0000000000..4433538556 --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. diff --git a/deps/v8/tools/testrunner/outproc/base.py b/deps/v8/tools/testrunner/outproc/base.py new file mode 100644 index 0000000000..9a9db4e81d --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/base.py @@ -0,0 +1,166 @@ +# Copyright 2017 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import collections +import itertools + +from ..local import statusfile +from ..testproc.result import Result + + +OUTCOMES_PASS = [statusfile.PASS] +OUTCOMES_FAIL = [statusfile.FAIL] + + +class BaseOutProc(object): + def process(self, output): + return Result(self.has_unexpected_output(output), output) + + def has_unexpected_output(self, output): + return self.get_outcome(output) not in self.expected_outcomes + + def get_outcome(self, output): + if output.HasCrashed(): + return statusfile.CRASH + elif output.HasTimedOut(): + return statusfile.TIMEOUT + elif self._has_failed(output): + return statusfile.FAIL + else: + return statusfile.PASS + + def _has_failed(self, output): + execution_failed = self._is_failure_output(output) + if self.negative: + return not execution_failed + return execution_failed + + def _is_failure_output(self, output): + return output.exit_code != 0 + + @property + def negative(self): + return False + + @property + def expected_outcomes(self): + raise NotImplementedError() + + +class Negative(object): + @property + def negative(self): + return True + + +class PassOutProc(BaseOutProc): + """Output processor optimized for positive tests expected to PASS.""" + def has_unexpected_output(self, output): + return self.get_outcome(output) != statusfile.PASS + + @property + def expected_outcomes(self): + return OUTCOMES_PASS + + +class OutProc(BaseOutProc): + """Output processor optimized for positive tests with expected outcomes + different than a single PASS. + """ + def __init__(self, expected_outcomes): + self._expected_outcomes = expected_outcomes + + @property + def expected_outcomes(self): + return self._expected_outcomes + + # TODO(majeski): Inherit from PassOutProc in case of OUTCOMES_PASS and remove + # custom get/set state. + def __getstate__(self): + d = self.__dict__ + if self._expected_outcomes is OUTCOMES_PASS: + d = d.copy() + del d['_expected_outcomes'] + return d + + def __setstate__(self, d): + if '_expected_outcomes' not in d: + d['_expected_outcomes'] = OUTCOMES_PASS + self.__dict__.update(d) + + +# TODO(majeski): Override __reduce__ to make it deserialize as one instance. +DEFAULT = PassOutProc() + + +class ExpectedOutProc(OutProc): + """Output processor that has is_failure_output depending on comparing the + output with the expected output. + """ + def __init__(self, expected_outcomes, expected_filename): + super(ExpectedOutProc, self).__init__(expected_outcomes) + self._expected_filename = expected_filename + + def _is_failure_output(self, output): + with open(self._expected_filename, 'r') as f: + expected_lines = f.readlines() + + for act_iterator in self._act_block_iterator(output): + for expected, actual in itertools.izip_longest( + self._expected_iterator(expected_lines), + act_iterator, + fillvalue='' + ): + if expected != actual: + return True + return False + + def _act_block_iterator(self, output): + """Iterates over blocks of actual output lines.""" + lines = output.stdout.splitlines() + start_index = 0 + found_eqeq = False + for index, line in enumerate(lines): + # If a stress test separator is found: + if line.startswith('=='): + # Iterate over all lines before a separator except the first. + if not found_eqeq: + found_eqeq = True + else: + yield self._actual_iterator(lines[start_index:index]) + # The next block of output lines starts after the separator. + start_index = index + 1 + # Iterate over complete output if no separator was found. + if not found_eqeq: + yield self._actual_iterator(lines) + + def _actual_iterator(self, lines): + return self._iterator(lines, self._ignore_actual_line) + + def _expected_iterator(self, lines): + return self._iterator(lines, self._ignore_expected_line) + + def _ignore_actual_line(self, line): + """Ignore empty lines, valgrind output, Android output and trace + incremental marking output. + """ + if not line: + return True + return (line.startswith('==') or + line.startswith('**') or + line.startswith('ANDROID') or + line.startswith('###') or + # FIXME(machenbach): The test driver shouldn't try to use slow + # asserts if they weren't compiled. This fails in optdebug=2. + line == 'Warning: unknown flag --enable-slow-asserts.' or + line == 'Try --help for options') + + def _ignore_expected_line(self, line): + return not line + + def _iterator(self, lines, ignore_predicate): + for line in lines: + line = line.strip() + if not ignore_predicate(line): + yield line diff --git a/deps/v8/tools/testrunner/outproc/message.py b/deps/v8/tools/testrunner/outproc/message.py new file mode 100644 index 0000000000..bbfc1cdf7e --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/message.py @@ -0,0 +1,56 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import itertools +import os +import re + +from . import base + + +class OutProc(base.OutProc): + def __init__(self, expected_outcomes, basepath, expected_fail): + super(OutProc, self).__init__(expected_outcomes) + self._basepath = basepath + self._expected_fail = expected_fail + + def _is_failure_output(self, output): + fail = output.exit_code != 0 + if fail != self._expected_fail: + return True + + expected_lines = [] + # Can't use utils.ReadLinesFrom() here because it strips whitespace. + with open(self._basepath + '.out') as f: + for line in f: + if line.startswith("#") or not line.strip(): + continue + expected_lines.append(line) + raw_lines = output.stdout.splitlines() + actual_lines = [ s for s in raw_lines if not self._ignore_line(s) ] + if len(expected_lines) != len(actual_lines): + return True + + env = { + 'basename': os.path.basename(self._basepath + '.js'), + } + for (expected, actual) in itertools.izip_longest( + expected_lines, actual_lines, fillvalue=''): + pattern = re.escape(expected.rstrip() % env) + pattern = pattern.replace('\\*', '.*') + pattern = pattern.replace('\\{NUMBER\\}', '\d+(?:\.\d*)?') + pattern = '^%s$' % pattern + if not re.match(pattern, actual): + return True + return False + + def _ignore_line(self, string): + """Ignore empty lines, valgrind output, Android output.""" + return ( + not string or + not string.strip() or + string.startswith("==") or + string.startswith("**") or + string.startswith("ANDROID") + ) diff --git a/deps/v8/tools/testrunner/outproc/mkgrokdump.py b/deps/v8/tools/testrunner/outproc/mkgrokdump.py new file mode 100644 index 0000000000..8efde1226f --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/mkgrokdump.py @@ -0,0 +1,31 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import difflib + +from . import base + + +class OutProc(base.OutProc): + def __init__(self, expected_outcomes, expected_path): + super(OutProc, self).__init__(expected_outcomes) + self._expected_path = expected_path + + def _is_failure_output(self, output): + with open(self._expected_path) as f: + expected = f.read() + expected_lines = expected.splitlines() + actual_lines = output.stdout.splitlines() + diff = difflib.unified_diff(expected_lines, actual_lines, lineterm="", + fromfile="expected_path") + diffstring = '\n'.join(diff) + if diffstring is not "": + if "generated from a non-shipping build" in output.stdout: + return False + if not "generated from a shipping build" in output.stdout: + output.stdout = "Unexpected output:\n\n" + output.stdout + return True + output.stdout = diffstring + return True + return False diff --git a/deps/v8/tools/testrunner/outproc/mozilla.py b/deps/v8/tools/testrunner/outproc/mozilla.py new file mode 100644 index 0000000000..1400d0ec54 --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/mozilla.py @@ -0,0 +1,33 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from . import base + + +def _is_failure_output(self, output): + return ( + output.exit_code != 0 or + 'FAILED!' in output.stdout + ) + + +class OutProc(base.OutProc): + """Optimized for positive tests.""" +OutProc._is_failure_output = _is_failure_output + + +class PassOutProc(base.PassOutProc): + """Optimized for positive tests expected to PASS.""" +PassOutProc._is_failure_output = _is_failure_output + + +class NegOutProc(base.Negative, OutProc): + pass + +class NegPassOutProc(base.Negative, PassOutProc): + pass + + +MOZILLA_PASS_DEFAULT = PassOutProc() +MOZILLA_PASS_NEGATIVE = NegPassOutProc() diff --git a/deps/v8/tools/testrunner/outproc/test262.py b/deps/v8/tools/testrunner/outproc/test262.py new file mode 100644 index 0000000000..b5eb5547c3 --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/test262.py @@ -0,0 +1,54 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import re + +from . import base + + +class ExceptionOutProc(base.OutProc): + """Output processor for tests with expected exception.""" + def __init__(self, expected_outcomes, expected_exception=None): + super(ExceptionOutProc, self).__init__(expected_outcomes) + self._expected_exception = expected_exception + + def _is_failure_output(self, output): + if output.exit_code != 0: + return True + if self._expected_exception != self._parse_exception(output.stdout): + return True + return 'FAILED!' in output.stdout + + def _parse_exception(self, string): + # somefile:somelinenumber: someerror[: sometext] + # somefile might include an optional drive letter on windows e.g. "e:". + match = re.search( + '^(?:\w:)?[^:]*:[0-9]+: ([^: ]+?)($|: )', string, re.MULTILINE) + if match: + return match.group(1).strip() + else: + return None + + +def _is_failure_output(self, output): + return ( + output.exit_code != 0 or + 'FAILED!' in output.stdout + ) + + +class NoExceptionOutProc(base.OutProc): + """Output processor optimized for tests without expected exception.""" +NoExceptionOutProc._is_failure_output = _is_failure_output + + +class PassNoExceptionOutProc(base.PassOutProc): + """ + Output processor optimized for tests expected to PASS without expected + exception. + """ +PassNoExceptionOutProc._is_failure_output = _is_failure_output + + +PASS_NO_EXCEPTION = PassNoExceptionOutProc() diff --git a/deps/v8/tools/testrunner/outproc/webkit.py b/deps/v8/tools/testrunner/outproc/webkit.py new file mode 100644 index 0000000000..290e67dc5a --- /dev/null +++ b/deps/v8/tools/testrunner/outproc/webkit.py @@ -0,0 +1,18 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from . import base + + +class OutProc(base.ExpectedOutProc): + def _is_failure_output(self, output): + if output.exit_code != 0: + return True + return super(OutProc, self)._is_failure_output(output) + + def _ignore_expected_line(self, line): + return ( + line.startswith('#') or + super(OutProc, self)._ignore_expected_line(line) + ) diff --git a/deps/v8/tools/testrunner/standard_runner.py b/deps/v8/tools/testrunner/standard_runner.py index d838df783c..3be2099252 100755 --- a/deps/v8/tools/testrunner/standard_runner.py +++ b/deps/v8/tools/testrunner/standard_runner.py @@ -25,6 +25,15 @@ from testrunner.local import utils from testrunner.local import verbose from testrunner.local.variants import ALL_VARIANTS from testrunner.objects import context +from testrunner.objects import predictable +from testrunner.testproc.execution import ExecutionProc +from testrunner.testproc.filter import StatusFileFilterProc, NameFilterProc +from testrunner.testproc.loader import LoadProc +from testrunner.testproc.progress import (VerboseProgressIndicator, + ResultsTracker, + TestsCounter) +from testrunner.testproc.rerun import RerunProc +from testrunner.testproc.variant import VariantProc TIMEOUT_DEFAULT = 60 @@ -48,7 +57,7 @@ VARIANT_ALIASES = { # Shortcut for the two above ("more" first - it has the longer running tests). "exhaustive": MORE_VARIANTS + VARIANTS, # Additional variants, run on a subset of bots. - "extra": ["future", "liftoff"], + "extra": ["future", "liftoff", "trusted"], } GC_STRESS_FLAGS = ["--gc-interval=500", "--stress-compaction", @@ -66,14 +75,20 @@ SLOW_ARCHS = ["arm", "s390x", "arm64"] +PREDICTABLE_WRAPPER = os.path.join( + base_runner.BASE_DIR, 'tools', 'predictable_wrapper.py') + class StandardTestRunner(base_runner.BaseTestRunner): - def __init__(self): - super(StandardTestRunner, self).__init__() + def __init__(self, *args, **kwargs): + super(StandardTestRunner, self).__init__(*args, **kwargs) self.sancov_dir = None - def _do_execute(self, options, args): + def _get_default_suite_names(self): + return ['default'] + + def _do_execute(self, suites, args, options): if options.swarming: # Swarming doesn't print how isolated commands are called. Lets make # this less cryptic by printing it ourselves. @@ -89,42 +104,7 @@ class StandardTestRunner(base_runner.BaseTestRunner): except Exception: pass - suite_paths = utils.GetSuitePaths(join(base_runner.BASE_DIR, "test")) - - # Use default tests if no test configuration was provided at the cmd line. - if len(args) == 0: - args = ["default"] - - # Expand arguments with grouped tests. The args should reflect the list - # of suites as otherwise filters would break. - def ExpandTestGroups(name): - if name in base_runner.TEST_MAP: - return [suite for suite in base_runner.TEST_MAP[name]] - else: - return [name] - args = reduce(lambda x, y: x + y, - [ExpandTestGroups(arg) for arg in args], - []) - - args_suites = OrderedDict() # Used as set - for arg in args: - args_suites[arg.split('/')[0]] = True - suite_paths = [ s for s in args_suites if s in suite_paths ] - - suites = [] - for root in suite_paths: - suite = testsuite.TestSuite.LoadTestSuite( - os.path.join(base_runner.BASE_DIR, "test", root)) - if suite: - suites.append(suite) - - for s in suites: - s.PrepareSources() - - try: - return self._execute(args, options, suites) - except KeyboardInterrupt: - return 2 + return self._execute(args, options, suites) def _add_parser_options(self, parser): parser.add_option("--sancov-dir", @@ -154,6 +134,8 @@ class StandardTestRunner(base_runner.BaseTestRunner): parser.add_option("--extra-flags", help="Additional flags to pass to each test command", action="append", default=[]) + parser.add_option("--infra-staging", help="Use new test runner features", + default=False, action="store_true") parser.add_option("--isolates", help="Whether to test isolates", default=False, action="store_true") parser.add_option("-j", help="The number of parallel tasks to run", @@ -200,12 +182,6 @@ class StandardTestRunner(base_runner.BaseTestRunner): parser.add_option("--rerun-failures-max", help="Maximum number of failing test cases to rerun.", default=100, type="int") - parser.add_option("--shard-count", - help="Split testsuites into this number of shards", - default=1, type="int") - parser.add_option("--shard-run", - help="Run this shard from the split up tests.", - default=1, type="int") parser.add_option("--dont-skip-slow-simulator-tests", help="Don't skip more slow tests when using a" " simulator.", @@ -253,13 +229,13 @@ class StandardTestRunner(base_runner.BaseTestRunner): if options.novfp3: options.extra_flags.append("--noenable-vfp3") - if options.no_variants: + if options.no_variants: # pragma: no cover print ("Option --no-variants is deprecated. " "Pass --variants=default instead.") assert not options.variants options.variants = "default" - if options.exhaustive_variants: + if options.exhaustive_variants: # pragma: no cover # TODO(machenbach): Switch infra to --variants=exhaustive after M65. print ("Option --exhaustive-variants is deprecated. " "Pass --variants=exhaustive instead.") @@ -280,6 +256,9 @@ class StandardTestRunner(base_runner.BaseTestRunner): options.extra_flags.append("--predictable") options.extra_flags.append("--verify_predictable") options.extra_flags.append("--no-inline-new") + # Add predictable wrapper to command prefix. + options.command_prefix = ( + [sys.executable, PREDICTABLE_WRAPPER] + options.command_prefix) # TODO(machenbach): Figure out how to test a bigger subset of variants on # msan. @@ -295,6 +274,10 @@ class StandardTestRunner(base_runner.BaseTestRunner): # Use developer defaults if no variant was specified. options.variants = options.variants or "dev" + if options.variants == "infra_staging": + options.variants = "exhaustive" + options.infra_staging = True + # Resolve variant aliases and dedupe. # TODO(machenbach): Don't mutate global variable. Rather pass mutated # version as local variable. @@ -308,7 +291,7 @@ class StandardTestRunner(base_runner.BaseTestRunner): print "All variants must be in %s" % str(ALL_VARIANTS) raise base_runner.TestRunnerError() - def CheckTestMode(name, option): + def CheckTestMode(name, option): # pragma: no cover if not option in ["run", "skip", "dontcare"]: print "Unknown %s mode %s" % (name, option) raise base_runner.TestRunnerError() @@ -317,6 +300,8 @@ class StandardTestRunner(base_runner.BaseTestRunner): if self.build_config.no_i18n: base_runner.TEST_MAP["bot_default"].remove("intl") base_runner.TEST_MAP["default"].remove("intl") + # TODO(machenbach): uncomment after infra side lands. + # base_runner.TEST_MAP["d8_default"].remove("intl") def _setup_env(self): super(StandardTestRunner, self)._setup_env() @@ -366,10 +351,10 @@ class StandardTestRunner(base_runner.BaseTestRunner): options.no_sorting, options.rerun_failures_count, options.rerun_failures_max, - self.build_config.predictable, options.no_harness, use_perf_data=not options.swarming, - sancov_dir=self.sancov_dir) + sancov_dir=self.sancov_dir, + infra_staging=options.infra_staging) # TODO(all): Combine "simulator" and "simulator_run". # TODO(machenbach): In GN we can derive simulator run from @@ -405,6 +390,31 @@ class StandardTestRunner(base_runner.BaseTestRunner): "tsan": self.build_config.tsan, "ubsan_vptr": self.build_config.ubsan_vptr, } + + progress_indicator = progress.IndicatorNotifier() + progress_indicator.Register( + progress.PROGRESS_INDICATORS[options.progress]()) + if options.junitout: # pragma: no cover + progress_indicator.Register(progress.JUnitTestProgressIndicator( + options.junitout, options.junittestsuite)) + if options.json_test_results: + progress_indicator.Register(progress.JsonTestProgressIndicator( + options.json_test_results, + self.build_config.arch, + self.mode_options.execution_mode, + ctx.random_seed)) + if options.flakiness_results: # pragma: no cover + progress_indicator.Register(progress.FlakinessTestProgressIndicator( + options.flakiness_results)) + + if options.infra_staging: + for s in suites: + s.ReadStatusFile(variables) + s.ReadTestCases(ctx) + + return self._run_test_procs(suites, args, options, progress_indicator, + ctx) + all_tests = [] num_tests = 0 for s in suites: @@ -417,14 +427,15 @@ class StandardTestRunner(base_runner.BaseTestRunner): # First filtering by status applying the generic rules (tests without # variants) if options.warn_unused: - s.WarnUnusedRules(check_variant_rules=False) + tests = [(t.name, t.variant) for t in s.tests] + s.statusfile.warn_unused_rules(tests, check_variant_rules=False) s.FilterTestCasesByStatus(options.slow_tests, options.pass_fail_tests) if options.cat: verbose.PrintTestSource(s.tests) continue - variant_gen = s.CreateVariantGenerator(VARIANTS) - variant_tests = [ t.CopyAddingFlags(v, flags) + variant_gen = s.CreateLegacyVariantsGenerator(VARIANTS) + variant_tests = [ t.create_variant(v, flags) for t in s.tests for v in variant_gen.FilterVariantsByTest(t) for flags in variant_gen.GetFlagSets(t, v) ] @@ -440,22 +451,24 @@ class StandardTestRunner(base_runner.BaseTestRunner): else: yield ["--random-seed=%d" % self._random_seed()] s.tests = [ - t.CopyAddingFlags(t.variant, flags) + t.create_variant(t.variant, flags, 'seed-stress-%d' % n) for t in variant_tests - for flags in iter_seed_flags() + for n, flags in enumerate(iter_seed_flags()) ] else: s.tests = variant_tests # Second filtering by status applying also the variant-dependent rules. if options.warn_unused: - s.WarnUnusedRules(check_variant_rules=True) + tests = [(t.name, t.variant) for t in s.tests] + s.statusfile.warn_unused_rules(tests, check_variant_rules=True) + s.FilterTestCasesByStatus(options.slow_tests, options.pass_fail_tests) + s.tests = self._shard_tests(s.tests, options) for t in s.tests: - t.flags += s.GetStatusfileFlags(t) + t.cmd = t.get_command(ctx) - s.tests = self._shard_tests(s.tests, options) num_tests += len(s.tests) if options.cat: @@ -466,28 +479,19 @@ class StandardTestRunner(base_runner.BaseTestRunner): # Run the tests. start_time = time.time() - progress_indicator = progress.IndicatorNotifier() - progress_indicator.Register( - progress.PROGRESS_INDICATORS[options.progress]()) - if options.junitout: - progress_indicator.Register(progress.JUnitTestProgressIndicator( - options.junitout, options.junittestsuite)) - if options.json_test_results: - progress_indicator.Register(progress.JsonTestProgressIndicator( - options.json_test_results, - self.build_config.arch, - self.mode_options.execution_mode, - ctx.random_seed)) - if options.flakiness_results: - progress_indicator.Register(progress.FlakinessTestProgressIndicator( - options.flakiness_results)) - runner = execution.Runner(suites, progress_indicator, ctx) + if self.build_config.predictable: + outproc_factory = predictable.get_outproc + else: + outproc_factory = None + + runner = execution.Runner(suites, progress_indicator, ctx, + outproc_factory) exit_code = runner.Run(options.j) overall_duration = time.time() - start_time if options.time: - verbose.PrintTestDurations(suites, overall_duration) + verbose.PrintTestDurations(suites, runner.outputs, overall_duration) if num_tests == 0: print("Warning: no tests were run!") @@ -503,8 +507,7 @@ class StandardTestRunner(base_runner.BaseTestRunner): print "Merging sancov files." subprocess.check_call([ sys.executable, - join( - base_runner.BASE_DIR, "tools", "sanitizers", "sancov_merger.py"), + join(self.basedir, "tools", "sanitizers", "sancov_merger.py"), "--coverage-dir=%s" % self.sancov_dir]) except: print >> sys.stderr, "Error: Merging sancov files failed." @@ -513,33 +516,10 @@ class StandardTestRunner(base_runner.BaseTestRunner): return exit_code def _shard_tests(self, tests, options): - # Read gtest shard configuration from environment (e.g. set by swarming). - # If none is present, use values passed on the command line. - shard_count = int( - os.environ.get('GTEST_TOTAL_SHARDS', options.shard_count)) - shard_run = os.environ.get('GTEST_SHARD_INDEX') - if shard_run is not None: - # The v8 shard_run starts at 1, while GTEST_SHARD_INDEX starts at 0. - shard_run = int(shard_run) + 1 - else: - shard_run = options.shard_run - - if options.shard_count > 1: - # Log if a value was passed on the cmd line and it differs from the - # environment variables. - if options.shard_count != shard_count: - print("shard_count from cmd line differs from environment variable " - "GTEST_TOTAL_SHARDS") - if options.shard_run > 1 and options.shard_run != shard_run: - print("shard_run from cmd line differs from environment variable " - "GTEST_SHARD_INDEX") + shard_run, shard_count = self._get_shard_info(options) if shard_count < 2: return tests - if shard_run < 1 or shard_run > shard_count: - print "shard-run not a valid number, should be in [1:shard-count]" - print "defaulting back to running all tests" - return tests count = 0 shard = [] for test in tests: @@ -548,6 +528,72 @@ class StandardTestRunner(base_runner.BaseTestRunner): count += 1 return shard + def _run_test_procs(self, suites, args, options, progress_indicator, + context): + jobs = options.j + + print '>>> Running with test processors' + loader = LoadProc() + tests_counter = TestsCounter() + results = ResultsTracker() + indicators = progress_indicator.ToProgressIndicatorProcs() + execproc = ExecutionProc(jobs, context) + + procs = [ + loader, + NameFilterProc(args) if args else None, + StatusFileFilterProc(options.slow_tests, options.pass_fail_tests), + self._create_shard_proc(options), + tests_counter, + VariantProc(VARIANTS), + StatusFileFilterProc(options.slow_tests, options.pass_fail_tests), + ] + indicators + [ + results, + self._create_rerun_proc(context), + execproc, + ] + + procs = filter(None, procs) + + for i in xrange(0, len(procs) - 1): + procs[i].connect_to(procs[i + 1]) + + tests = [t for s in suites for t in s.tests] + tests.sort(key=lambda t: t.is_slow, reverse=True) + + loader.setup() + loader.load_tests(tests) + + print '>>> Running %d base tests' % tests_counter.total + tests_counter.remove_from_chain() + + execproc.start() + + for indicator in indicators: + indicator.finished() + + print '>>> %d tests ran' % results.total + + exit_code = 0 + if results.failed: + exit_code = 1 + if results.remaining: + exit_code = 2 + + + if exit_code == 1 and options.json_test_results: + print("Force exit code 0 after failures. Json test results file " + "generated with failure information.") + exit_code = 0 + return exit_code + + def _create_rerun_proc(self, ctx): + if not ctx.rerun_failures_count: + return None + return RerunProc(ctx.rerun_failures_count, + ctx.rerun_failures_max) + + if __name__ == '__main__': sys.exit(StandardTestRunner().execute()) diff --git a/deps/v8/tools/testrunner/testproc/__init__.py b/deps/v8/tools/testrunner/testproc/__init__.py new file mode 100644 index 0000000000..4433538556 --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. diff --git a/deps/v8/tools/testrunner/testproc/base.py b/deps/v8/tools/testrunner/testproc/base.py new file mode 100644 index 0000000000..1a87dbed55 --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/base.py @@ -0,0 +1,207 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from .result import SKIPPED + + +""" +Pipeline + +Test processors are chained together and communicate with each other by +calling previous/next processor in the chain. + ----next_test()----> ----next_test()----> +Proc1 Proc2 Proc3 + <---result_for()---- <---result_for()---- + +For every next_test there is exactly one result_for call. +If processor ignores the test it has to return SkippedResult. +If it created multiple subtests for one test and wants to pass all of them to +the previous processor it can enclose them in GroupedResult. + + +Subtests + +When test processor needs to modify the test or create some variants of the +test it creates subtests and sends them to the next processor. +Each subtest has: +- procid - globally unique id that should contain id of the parent test and + some suffix given by test processor, e.g. its name + subtest type. +- processor - which created it +- origin - pointer to the parent (sub)test +""" + + +DROP_RESULT = 0 +DROP_OUTPUT = 1 +DROP_PASS_OUTPUT = 2 +DROP_PASS_STDOUT = 3 + +def get_reduce_result_function(requirement): + if requirement == DROP_RESULT: + return lambda _: None + + if requirement == DROP_OUTPUT: + def f(result): + result.output = None + return result + return f + + if requirement == DROP_PASS_OUTPUT: + def f(result): + if not result.has_unexpected_output: + result.output = None + return result + return f + + if requirement == DROP_PASS_STDOUT: + def f(result): + if not result.has_unexpected_output: + result.output.stdout = None + result.output.stderr = None + return result + return f + + +class TestProc(object): + def __init__(self): + self._prev_proc = None + self._next_proc = None + self._requirement = DROP_RESULT + self._prev_requirement = None + self._reduce_result = lambda result: result + + def connect_to(self, next_proc): + """Puts `next_proc` after itself in the chain.""" + next_proc._prev_proc = self + self._next_proc = next_proc + + def remove_from_chain(self): + if self._prev_proc: + self._prev_proc._next_proc = self._next_proc + if self._next_proc: + self._next_proc._prev_proc = self._prev_proc + + def setup(self, requirement=DROP_RESULT): + """ + Method called by previous processor or processor pipeline creator to let + the processors know what part of the result can be ignored. + """ + self._prev_requirement = requirement + if self._next_proc: + self._next_proc.setup(max(requirement, self._requirement)) + if self._prev_requirement < self._requirement: + self._reduce_result = get_reduce_result_function(self._prev_requirement) + + def next_test(self, test): + """ + Method called by previous processor whenever it produces new test. + This method shouldn't be called by anyone except previous processor. + """ + raise NotImplementedError() + + def result_for(self, test, result): + """ + Method called by next processor whenever it has result for some test. + This method shouldn't be called by anyone except next processor. + """ + raise NotImplementedError() + + def heartbeat(self): + if self._prev_proc: + self._prev_proc.heartbeat() + + ### Communication + + def _send_test(self, test): + """Helper method for sending test to the next processor.""" + self._next_proc.next_test(test) + + def _send_result(self, test, result): + """Helper method for sending result to the previous processor.""" + result = self._reduce_result(result) + self._prev_proc.result_for(test, result) + + + +class TestProcObserver(TestProc): + """Processor used for observing the data.""" + def __init__(self): + super(TestProcObserver, self).__init__() + + def next_test(self, test): + self._on_next_test(test) + self._send_test(test) + + def result_for(self, test, result): + self._on_result_for(test, result) + self._send_result(test, result) + + def heartbeat(self): + self._on_heartbeat() + super(TestProcObserver, self).heartbeat() + + def _on_next_test(self, test): + """Method called after receiving test from previous processor but before + sending it to the next one.""" + pass + + def _on_result_for(self, test, result): + """Method called after receiving result from next processor but before + sending it to the previous one.""" + pass + + def _on_heartbeat(self): + pass + + +class TestProcProducer(TestProc): + """Processor for creating subtests.""" + + def __init__(self, name): + super(TestProcProducer, self).__init__() + self._name = name + + def next_test(self, test): + self._next_test(test) + + def result_for(self, subtest, result): + self._result_for(subtest.origin, subtest, result) + + ### Implementation + def _next_test(self, test): + raise NotImplementedError() + + def _result_for(self, test, subtest, result): + """ + result_for method extended with `subtest` parameter. + + Args + test: test used by current processor to create the subtest. + subtest: test for which the `result` is. + result: subtest execution result created by the output processor. + """ + raise NotImplementedError() + + ### Managing subtests + def _create_subtest(self, test, subtest_id, **kwargs): + """Creates subtest with subtest id -`subtest_id`.""" + return test.create_subtest(self, '%s-%s' % (self._name, subtest_id), + **kwargs) + + +class TestProcFilter(TestProc): + """Processor for filtering tests.""" + + def next_test(self, test): + if self._filter(test): + self._send_result(test, SKIPPED) + else: + self._send_test(test) + + def result_for(self, test, result): + self._send_result(test, result) + + def _filter(self, test): + """Returns whether test should be filtered out.""" + raise NotImplementedError() diff --git a/deps/v8/tools/testrunner/testproc/execution.py b/deps/v8/tools/testrunner/testproc/execution.py new file mode 100644 index 0000000000..021b02af3e --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/execution.py @@ -0,0 +1,92 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import collections +import traceback + +from . import base +from ..local import pool + + +# Global function for multiprocessing, because pickling a static method doesn't +# work on Windows. +def run_job(job, process_context): + return job.run(process_context) + + +def create_process_context(requirement): + return ProcessContext(base.get_reduce_result_function(requirement)) + + +JobResult = collections.namedtuple('JobResult', ['id', 'result']) +ProcessContext = collections.namedtuple('ProcessContext', ['reduce_result_f']) + + +class Job(object): + def __init__(self, test_id, cmd, outproc, keep_output): + self.test_id = test_id + self.cmd = cmd + self.outproc = outproc + self.keep_output = keep_output + + def run(self, process_ctx): + output = self.cmd.execute() + result = self.outproc.process(output) + if not self.keep_output: + result = process_ctx.reduce_result_f(result) + return JobResult(self.test_id, result) + + +class ExecutionProc(base.TestProc): + """Last processor in the chain. Instead of passing tests further it creates + commands and output processors, executes them in multiple worker processes and + sends results to the previous processor. + """ + + def __init__(self, jobs, context): + super(ExecutionProc, self).__init__() + self._pool = pool.Pool(jobs) + self._context = context + self._tests = {} + + def connect_to(self, next_proc): + assert False, 'ExecutionProc cannot be connected to anything' + + def start(self): + try: + it = self._pool.imap_unordered( + fn=run_job, + gen=[], + process_context_fn=create_process_context, + process_context_args=[self._prev_requirement], + ) + for pool_result in it: + if pool_result.heartbeat: + continue + + job_result = pool_result.value + test_id, result = job_result + + test, result.cmd = self._tests[test_id] + del self._tests[test_id] + self._send_result(test, result) + except KeyboardInterrupt: + raise + except: + traceback.print_exc() + raise + finally: + self._pool.terminate() + + def next_test(self, test): + test_id = test.procid + cmd = test.get_command(self._context) + self._tests[test_id] = test, cmd + + # TODO(majeski): Needs factory for outproc as in local/execution.py + outproc = test.output_proc + self._pool.add([Job(test_id, cmd, outproc, test.keep_output)]) + + def result_for(self, test, result): + assert False, 'ExecutionProc cannot receive results' diff --git a/deps/v8/tools/testrunner/testproc/filter.py b/deps/v8/tools/testrunner/testproc/filter.py new file mode 100644 index 0000000000..5081997751 --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/filter.py @@ -0,0 +1,83 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from collections import defaultdict +import fnmatch + +from . import base + + +class StatusFileFilterProc(base.TestProcFilter): + """Filters tests by outcomes from status file. + + Status file has to be loaded before using this function. + + Args: + slow_tests_mode: What to do with slow tests. + pass_fail_tests_mode: What to do with pass or fail tests. + + Mode options: + None (default): don't skip + "skip": skip if slow/pass_fail + "run": skip if not slow/pass_fail + """ + + def __init__(self, slow_tests_mode, pass_fail_tests_mode): + super(StatusFileFilterProc, self).__init__() + self._slow_tests_mode = slow_tests_mode + self._pass_fail_tests_mode = pass_fail_tests_mode + + def _filter(self, test): + return ( + test.do_skip or + self._skip_slow(test.is_slow) or + self._skip_pass_fail(test.is_pass_or_fail) + ) + + def _skip_slow(self, is_slow): + return ( + (self._slow_tests_mode == 'run' and not is_slow) or + (self._slow_tests_mode == 'skip' and is_slow) + ) + + def _skip_pass_fail(self, is_pass_fail): + return ( + (self._pass_fail_tests_mode == 'run' and not is_pass_fail) or + (self._pass_fail_tests_mode == 'skip' and is_pass_fail) + ) + + +class NameFilterProc(base.TestProcFilter): + """Filters tests based on command-line arguments. + + args can be a glob: asterisks in any position of the name + represent zero or more characters. Without asterisks, only exact matches + will be used with the exeption of the test-suite name as argument. + """ + def __init__(self, args): + super(NameFilterProc, self).__init__() + + self._globs = defaultdict(list) + for a in args: + argpath = a.split('/') + suitename = argpath[0] + path = '/'.join(argpath[1:]) or '*' + self._globs[suitename].append(path) + + for s, globs in self._globs.iteritems(): + if not globs or '*' in globs: + self._globs[s] = [] + + def _filter(self, test): + globs = self._globs.get(test.suite.name) + if globs is None: + return True + + if not globs: + return False + + for g in globs: + if fnmatch.fnmatch(test.path, g): + return False + return True diff --git a/deps/v8/tools/testrunner/testproc/loader.py b/deps/v8/tools/testrunner/testproc/loader.py new file mode 100644 index 0000000000..0a3d0df1b3 --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/loader.py @@ -0,0 +1,27 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from . import base + + +class LoadProc(base.TestProc): + """First processor in the chain that passes all tests to the next processor. + """ + + def load_tests(self, tests): + loaded = set() + for test in tests: + if test.procid in loaded: + print 'Warning: %s already obtained' % test.procid + continue + + loaded.add(test.procid) + self._send_test(test) + + def next_test(self, test): + assert False, 'Nothing can be connected to the LoadProc' + + def result_for(self, test, result): + # Ignore all results. + pass diff --git a/deps/v8/tools/testrunner/testproc/progress.py b/deps/v8/tools/testrunner/testproc/progress.py new file mode 100644 index 0000000000..78514f7252 --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/progress.py @@ -0,0 +1,385 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import json +import os +import sys +import time + +from . import base +from ..local import junit_output + + +def print_failure_header(test): + if test.output_proc.negative: + negative_marker = '[negative] ' + else: + negative_marker = '' + print "=== %(label)s %(negative)s===" % { + 'label': test, + 'negative': negative_marker, + } + + +class TestsCounter(base.TestProcObserver): + def __init__(self): + super(TestsCounter, self).__init__() + self.total = 0 + + def _on_next_test(self, test): + self.total += 1 + + +class ResultsTracker(base.TestProcObserver): + def __init__(self): + super(ResultsTracker, self).__init__() + self._requirement = base.DROP_OUTPUT + + self.failed = 0 + self.remaining = 0 + self.total = 0 + + def _on_next_test(self, test): + self.total += 1 + self.remaining += 1 + + def _on_result_for(self, test, result): + self.remaining -= 1 + if result.has_unexpected_output: + self.failed += 1 + + +class ProgressIndicator(base.TestProcObserver): + def finished(self): + pass + + +class SimpleProgressIndicator(ProgressIndicator): + def __init__(self): + super(SimpleProgressIndicator, self).__init__() + self._requirement = base.DROP_PASS_OUTPUT + + self._failed = [] + self._total = 0 + + def _on_next_test(self, test): + self._total += 1 + + def _on_result_for(self, test, result): + # TODO(majeski): Support for dummy/grouped results + if result.has_unexpected_output: + self._failed.append((test, result)) + + def finished(self): + crashed = 0 + print + for test, result in self._failed: + print_failure_header(test) + if result.output.stderr: + print "--- stderr ---" + print result.output.stderr.strip() + if result.output.stdout: + print "--- stdout ---" + print result.output.stdout.strip() + print "Command: %s" % result.cmd.to_string() + if result.output.HasCrashed(): + print "exit code: %d" % result.output.exit_code + print "--- CRASHED ---" + crashed += 1 + if result.output.HasTimedOut(): + print "--- TIMEOUT ---" + if len(self._failed) == 0: + print "===" + print "=== All tests succeeded" + print "===" + else: + print + print "===" + print "=== %i tests failed" % len(self._failed) + if crashed > 0: + print "=== %i tests CRASHED" % crashed + print "===" + + +class VerboseProgressIndicator(SimpleProgressIndicator): + def _on_result_for(self, test, result): + super(VerboseProgressIndicator, self)._on_result_for(test, result) + # TODO(majeski): Support for dummy/grouped results + if result.has_unexpected_output: + if result.output.HasCrashed(): + outcome = 'CRASH' + else: + outcome = 'FAIL' + else: + outcome = 'pass' + print 'Done running %s: %s' % (test, outcome) + sys.stdout.flush() + + def _on_heartbeat(self): + print 'Still working...' + sys.stdout.flush() + + +class DotsProgressIndicator(SimpleProgressIndicator): + def __init__(self): + super(DotsProgressIndicator, self).__init__() + self._count = 0 + + def _on_result_for(self, test, result): + # TODO(majeski): Support for dummy/grouped results + self._count += 1 + if self._count > 1 and self._count % 50 == 1: + sys.stdout.write('\n') + if result.has_unexpected_output: + if result.output.HasCrashed(): + sys.stdout.write('C') + sys.stdout.flush() + elif result.output.HasTimedOut(): + sys.stdout.write('T') + sys.stdout.flush() + else: + sys.stdout.write('F') + sys.stdout.flush() + else: + sys.stdout.write('.') + sys.stdout.flush() + + +class CompactProgressIndicator(ProgressIndicator): + def __init__(self, templates): + super(CompactProgressIndicator, self).__init__() + self._requirement = base.DROP_PASS_OUTPUT + + self._templates = templates + self._last_status_length = 0 + self._start_time = time.time() + + self._total = 0 + self._passed = 0 + self._failed = 0 + + def _on_next_test(self, test): + self._total += 1 + + def _on_result_for(self, test, result): + # TODO(majeski): Support for dummy/grouped results + if result.has_unexpected_output: + self._failed += 1 + else: + self._passed += 1 + + self._print_progress(str(test)) + if result.has_unexpected_output: + output = result.output + stdout = output.stdout.strip() + stderr = output.stderr.strip() + + self._clear_line(self._last_status_length) + print_failure_header(test) + if len(stdout): + print self._templates['stdout'] % stdout + if len(stderr): + print self._templates['stderr'] % stderr + print "Command: %s" % result.cmd + if output.HasCrashed(): + print "exit code: %d" % output.exit_code + print "--- CRASHED ---" + if output.HasTimedOut(): + print "--- TIMEOUT ---" + + def finished(self): + self._print_progress('Done') + print + + def _print_progress(self, name): + self._clear_line(self._last_status_length) + elapsed = time.time() - self._start_time + if not self._total: + progress = 0 + else: + progress = (self._passed + self._failed) * 100 // self._total + status = self._templates['status_line'] % { + 'passed': self._passed, + 'progress': progress, + 'failed': self._failed, + 'test': name, + 'mins': int(elapsed) / 60, + 'secs': int(elapsed) % 60 + } + status = self._truncate(status, 78) + self._last_status_length = len(status) + print status, + sys.stdout.flush() + + def _truncate(self, string, length): + if length and len(string) > (length - 3): + return string[:(length - 3)] + "..." + else: + return string + + def _clear_line(self, last_length): + raise NotImplementedError() + + +class ColorProgressIndicator(CompactProgressIndicator): + def __init__(self): + templates = { + 'status_line': ("[%(mins)02i:%(secs)02i|" + "\033[34m%%%(progress) 4d\033[0m|" + "\033[32m+%(passed) 4d\033[0m|" + "\033[31m-%(failed) 4d\033[0m]: %(test)s"), + 'stdout': "\033[1m%s\033[0m", + 'stderr': "\033[31m%s\033[0m", + } + super(ColorProgressIndicator, self).__init__(templates) + + def _clear_line(self, last_length): + print "\033[1K\r", + + +class MonochromeProgressIndicator(CompactProgressIndicator): + def __init__(self): + templates = { + 'status_line': ("[%(mins)02i:%(secs)02i|%%%(progress) 4d|" + "+%(passed) 4d|-%(failed) 4d]: %(test)s"), + 'stdout': '%s', + 'stderr': '%s', + } + super(MonochromeProgressIndicator, self).__init__(templates) + + def _clear_line(self, last_length): + print ("\r" + (" " * last_length) + "\r"), + + +class JUnitTestProgressIndicator(ProgressIndicator): + def __init__(self, junitout, junittestsuite): + super(JUnitTestProgressIndicator, self).__init__() + self._requirement = base.DROP_PASS_STDOUT + + self.outputter = junit_output.JUnitTestOutput(junittestsuite) + if junitout: + self.outfile = open(junitout, "w") + else: + self.outfile = sys.stdout + + def _on_result_for(self, test, result): + # TODO(majeski): Support for dummy/grouped results + fail_text = "" + output = result.output + if result.has_unexpected_output: + stdout = output.stdout.strip() + if len(stdout): + fail_text += "stdout:\n%s\n" % stdout + stderr = output.stderr.strip() + if len(stderr): + fail_text += "stderr:\n%s\n" % stderr + fail_text += "Command: %s" % result.cmd.to_string() + if output.HasCrashed(): + fail_text += "exit code: %d\n--- CRASHED ---" % output.exit_code + if output.HasTimedOut(): + fail_text += "--- TIMEOUT ---" + self.outputter.HasRunTest( + test_name=str(test), + test_cmd=result.cmd.to_string(relative=True), + test_duration=output.duration, + test_failure=fail_text) + + def finished(self): + self.outputter.FinishAndWrite(self.outfile) + if self.outfile != sys.stdout: + self.outfile.close() + + +class JsonTestProgressIndicator(ProgressIndicator): + def __init__(self, json_test_results, arch, mode, random_seed): + super(JsonTestProgressIndicator, self).__init__() + # We want to drop stdout/err for all passed tests on the first try, but we + # need to get outputs for all runs after the first one. To accommodate that, + # reruns are set to keep the result no matter what requirement says, i.e. + # keep_output set to True in the RerunProc. + self._requirement = base.DROP_PASS_STDOUT + + self.json_test_results = json_test_results + self.arch = arch + self.mode = mode + self.random_seed = random_seed + self.results = [] + self.tests = [] + + def _on_result_for(self, test, result): + if result.is_rerun: + self.process_results(test, result.results) + else: + self.process_results(test, [result]) + + def process_results(self, test, results): + for run, result in enumerate(results): + # TODO(majeski): Support for dummy/grouped results + output = result.output + # Buffer all tests for sorting the durations in the end. + # TODO(machenbach): Running average + buffer only slowest 20 tests. + self.tests.append((test, output.duration, result.cmd)) + + # Omit tests that run as expected on the first try. + # Everything that happens after the first run is included in the output + # even if it flakily passes. + if not result.has_unexpected_output and run == 0: + continue + + self.results.append({ + "name": str(test), + "flags": result.cmd.args, + "command": result.cmd.to_string(relative=True), + "run": run + 1, + "stdout": output.stdout, + "stderr": output.stderr, + "exit_code": output.exit_code, + "result": test.output_proc.get_outcome(output), + "expected": test.expected_outcomes, + "duration": output.duration, + + # TODO(machenbach): This stores only the global random seed from the + # context and not possible overrides when using random-seed stress. + "random_seed": self.random_seed, + "target_name": test.get_shell(), + "variant": test.variant, + }) + + def finished(self): + complete_results = [] + if os.path.exists(self.json_test_results): + with open(self.json_test_results, "r") as f: + # Buildbot might start out with an empty file. + complete_results = json.loads(f.read() or "[]") + + duration_mean = None + if self.tests: + # Get duration mean. + duration_mean = ( + sum(duration for (_, duration, cmd) in self.tests) / + float(len(self.tests))) + + # Sort tests by duration. + self.tests.sort(key=lambda (_, duration, cmd): duration, reverse=True) + slowest_tests = [ + { + "name": str(test), + "flags": cmd.args, + "command": cmd.to_string(relative=True), + "duration": duration, + "marked_slow": test.is_slow, + } for (test, duration, cmd) in self.tests[:20] + ] + + complete_results.append({ + "arch": self.arch, + "mode": self.mode, + "results": self.results, + "slowest_tests": slowest_tests, + "duration_mean": duration_mean, + "test_total": len(self.tests), + }) + + with open(self.json_test_results, "w") as f: + f.write(json.dumps(complete_results)) diff --git a/deps/v8/tools/testrunner/testproc/rerun.py b/deps/v8/tools/testrunner/testproc/rerun.py new file mode 100644 index 0000000000..7f96e0260c --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/rerun.py @@ -0,0 +1,59 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import collections + +from . import base +from .result import RerunResult + + +class RerunProc(base.TestProcProducer): + def __init__(self, rerun_max, rerun_max_total=None): + super(RerunProc, self).__init__('Rerun') + self._requirement = base.DROP_OUTPUT + + self._rerun = {} + self._results = collections.defaultdict(list) + self._rerun_max = rerun_max + self._rerun_total_left = rerun_max_total + + def _next_test(self, test): + self._send_next_subtest(test) + + def _result_for(self, test, subtest, result): + # First result + if subtest.procid[-2:] == '-1': + # Passed, no reruns + if not result.has_unexpected_output: + self._send_result(test, result) + return + + self._rerun[test.procid] = 0 + + results = self._results[test.procid] + results.append(result) + + if self._needs_rerun(test, result): + self._rerun[test.procid] += 1 + if self._rerun_total_left is not None: + self._rerun_total_left -= 1 + self._send_next_subtest(test, self._rerun[test.procid]) + else: + result = RerunResult.create(results) + self._finalize_test(test) + self._send_result(test, result) + + def _needs_rerun(self, test, result): + # TODO(majeski): Limit reruns count for slow tests. + return ((self._rerun_total_left is None or self._rerun_total_left > 0) and + self._rerun[test.procid] < self._rerun_max and + result.has_unexpected_output) + + def _send_next_subtest(self, test, run=0): + subtest = self._create_subtest(test, str(run + 1), keep_output=(run != 0)) + self._send_test(subtest) + + def _finalize_test(self, test): + del self._rerun[test.procid] + del self._results[test.procid] diff --git a/deps/v8/tools/testrunner/testproc/result.py b/deps/v8/tools/testrunner/testproc/result.py new file mode 100644 index 0000000000..c817fc06ec --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/result.py @@ -0,0 +1,97 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + + +class ResultBase(object): + @property + def is_skipped(self): + return False + + @property + def is_grouped(self): + return False + + @property + def is_rerun(self): + return False + + +class Result(ResultBase): + """Result created by the output processor.""" + + def __init__(self, has_unexpected_output, output, cmd=None): + self.has_unexpected_output = has_unexpected_output + self.output = output + self.cmd = cmd + + +class GroupedResult(ResultBase): + """Result consisting of multiple results. It can be used by processors that + create multiple subtests for each test and want to pass all results back. + """ + + @staticmethod + def create(results): + """Create grouped result from the list of results. It filters out skipped + results. If all results are skipped results it returns skipped result. + + Args: + results: list of pairs (test, result) + """ + results = [(t, r) for (t, r) in results if not r.is_skipped] + if not results: + return SKIPPED + return GroupedResult(results) + + def __init__(self, results): + self.results = results + + @property + def is_grouped(self): + return True + + +class SkippedResult(ResultBase): + """Result without any meaningful value. Used primarily to inform the test + processor that it's test wasn't executed. + """ + + @property + def is_skipped(self): + return True + + +SKIPPED = SkippedResult() + + +class RerunResult(Result): + """Result generated from several reruns of the same test. It's a subclass of + Result since the result of rerun is result of the last run. In addition to + normal result it contains results of all reruns. + """ + @staticmethod + def create(results): + """Create RerunResult based on list of results. List cannot be empty. If it + has only one element it's returned as a result. + """ + assert results + + if len(results) == 1: + return results[0] + return RerunResult(results) + + def __init__(self, results): + """Has unexpected output and the output itself of the RerunResult equals to + the last result in the passed list. + """ + assert results + + last = results[-1] + super(RerunResult, self).__init__(last.has_unexpected_output, last.output, + last.cmd) + self.results = results + + @property + def is_rerun(self): + return True diff --git a/deps/v8/tools/testrunner/testproc/shard.py b/deps/v8/tools/testrunner/testproc/shard.py new file mode 100644 index 0000000000..1caac9fee6 --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/shard.py @@ -0,0 +1,30 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from . import base + + +class ShardProc(base.TestProcFilter): + """Processor distributing tests between shards. + It simply passes every n-th test. To be deterministic it has to be placed + before all processors that generate tests dynamically. + """ + def __init__(self, myid, shards_count): + """ + Args: + myid: id of the shard within [0; shards_count - 1] + shards_count: number of shards + """ + super(ShardProc, self).__init__() + + assert myid >= 0 and myid < shards_count + + self._myid = myid + self._shards_count = shards_count + self._last = 0 + + def _filter(self, test): + res = self._last != self._myid + self._last = (self._last + 1) % self._shards_count + return res diff --git a/deps/v8/tools/testrunner/testproc/variant.py b/deps/v8/tools/testrunner/testproc/variant.py new file mode 100644 index 0000000000..dba1af91fc --- /dev/null +++ b/deps/v8/tools/testrunner/testproc/variant.py @@ -0,0 +1,68 @@ +# Copyright 2018 the V8 project authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +from . import base +from ..local.variants import ALL_VARIANTS, ALL_VARIANT_FLAGS +from .result import GroupedResult + + +STANDARD_VARIANT = set(["default"]) + + +class VariantProc(base.TestProcProducer): + """Processor creating variants. + + For each test it keeps generator that returns variant, flags and id suffix. + It produces variants one at a time, so it's waiting for the result of one + variant to create another variant of the same test. + It maintains the order of the variants passed to the init. + + There are some cases when particular variant of the test is not valid. To + ignore subtests like that, StatusFileFilterProc should be placed somewhere + after the VariantProc. + """ + + def __init__(self, variants): + super(VariantProc, self).__init__('VariantProc') + self._next_variant = {} + self._variant_gens = {} + self._variants = variants + + def setup(self, requirement=base.DROP_RESULT): + super(VariantProc, self).setup(requirement) + + # VariantProc is optimized for dropping the result and it should be placed + # in the chain where it's possible. + assert requirement == base.DROP_RESULT + + def _next_test(self, test): + gen = self._variants_gen(test) + self._next_variant[test.procid] = gen + self._try_send_new_subtest(test, gen) + + def _result_for(self, test, subtest, result): + gen = self._next_variant[test.procid] + self._try_send_new_subtest(test, gen) + + def _try_send_new_subtest(self, test, variants_gen): + for variant, flags, suffix in variants_gen: + subtest = self._create_subtest(test, '%s-%s' % (variant, suffix), + variant=variant, flags=flags) + self._send_test(subtest) + return + + del self._next_variant[test.procid] + self._send_result(test, None) + + def _variants_gen(self, test): + """Generator producing (variant, flags, procid suffix) tuples.""" + return self._get_variants_gen(test).gen(test) + + def _get_variants_gen(self, test): + key = test.suite.name + variants_gen = self._variant_gens.get(key) + if not variants_gen: + variants_gen = test.suite.get_variants_gen(self._variants) + self._variant_gens[key] = variants_gen + return variants_gen diff --git a/deps/v8/tools/turbolizer/code-view.js b/deps/v8/tools/turbolizer/code-view.js index 8165210c31..7f9728a83a 100644 --- a/deps/v8/tools/turbolizer/code-view.js +++ b/deps/v8/tools/turbolizer/code-view.js @@ -164,8 +164,6 @@ class CodeView extends View { } } } - - view.resizeToParent(); } deleteContent() {} diff --git a/deps/v8/tools/turbolizer/graph-view.js b/deps/v8/tools/turbolizer/graph-view.js index 8de050f3e6..cdbc40c8f0 100644 --- a/deps/v8/tools/turbolizer/graph-view.js +++ b/deps/v8/tools/turbolizer/graph-view.js @@ -706,6 +706,7 @@ class GraphView extends View { .on("mousedown", function(d){ graph.pathMouseDown.call(graph, d3.select(this), d); }) + .attr("adjacentToHover", "false"); // Set the correct styles on all of the paths visibleEdges.classed('value', function(e) { @@ -740,7 +741,8 @@ class GraphView extends View { var newGs = graph.visibleNodes.enter() .append("g"); - newGs.classed("control", function(n) { return n.isControl(); }) + newGs.classed("turbonode", function(n) { return true; }) + .classed("control", function(n) { return n.isControl(); }) .classed("live", function(n) { return n.isLive(); }) .classed("dead", function(n) { return !n.isLive(); }) .classed("javascript", function(n) { return n.isJavaScript(); }) @@ -754,6 +756,34 @@ class GraphView extends View { .on("mouseup", function(d){ graph.nodeMouseUp.call(graph, d3.select(this), d); }) + .on('mouseover', function(d){ + var nodeSelection = d3.select(this); + let node = graph.nodeMap[d.id]; + let adjInputEdges = graph.visibleEdges.filter(e => { return e.target === node; }); + let adjOutputEdges = graph.visibleEdges.filter(e => { return e.source === node; }); + adjInputEdges.attr('relToHover', "input"); + adjOutputEdges.attr('relToHover', "output"); + let adjInputNodes = adjInputEdges.data().map(e => e.source); + graph.visibleNodes.data(adjInputNodes, function(d) { + return d.id; + }).attr('relToHover', "input"); + let adjOutputNodes = adjOutputEdges.data().map(e => e.target); + graph.visibleNodes.data(adjOutputNodes, function(d) { + return d.id; + }).attr('relToHover', "output"); + graph.updateGraphVisibility(); + }) + .on('mouseout', function(d){ + var nodeSelection = d3.select(this); + let node = graph.nodeMap[d.id]; + let adjEdges = graph.visibleEdges.filter(e => { return e.target === node || e.source === node; }); + adjEdges.attr('relToHover', "none"); + let adjNodes = adjEdges.data().map(e => e.target).concat(adjEdges.data().map(e => e.source)); + let nodes = graph.visibleNodes.data(adjNodes, function(d) { + return d.id; + }).attr('relToHover', "none"); + graph.updateGraphVisibility(); + }) .call(graph.drag); newGs.append("rect") diff --git a/deps/v8/tools/turbolizer/index.html b/deps/v8/tools/turbolizer/index.html index 4066fd8010..552e83783a 100644 --- a/deps/v8/tools/turbolizer/index.html +++ b/deps/v8/tools/turbolizer/index.html @@ -4,13 +4,14 @@ Turbolizer - +
       
-
+
+
- +
+