summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2019-03-12 09:01:49 +0100
committerMichaël Zasso <targos@protonmail.com>2019-03-14 18:49:21 +0100
commit7b48713334469818661fe276cf571de9c7899f2d (patch)
tree4dbda49ac88db76ce09dc330a0cb587e68e139ba /deps/v8/test/unittests
parent8549ac09b256666cf5275224ec58fab9939ff32e (diff)
downloadandroid-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.gz
android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.tar.bz2
android-node-v8-7b48713334469818661fe276cf571de9c7899f2d.zip
deps: update V8 to 7.3.492.25
PR-URL: https://github.com/nodejs/node/pull/25852 Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Diffstat (limited to 'deps/v8/test/unittests')
-rw-r--r--deps/v8/test/unittests/BUILD.gn31
-rw-r--r--deps/v8/test/unittests/api/isolate-unittest.cc4
-rw-r--r--deps/v8/test/unittests/asmjs/asm-types-unittest.cc2
-rw-r--r--deps/v8/test/unittests/asmjs/switch-logic-unittest.cc89
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc22
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc22
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc22
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc22
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc22
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc26
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc22
-rw-r--r--deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc22
-rw-r--r--deps/v8/test/unittests/background-compile-task-unittest.cc (renamed from deps/v8/test/unittests/compiler-dispatcher/unoptimized-compile-job-unittest.cc)180
-rw-r--r--deps/v8/test/unittests/base/atomic-utils-unittest.cc18
-rw-r--r--deps/v8/test/unittests/base/ieee754-unittest.cc9
-rw-r--r--deps/v8/test/unittests/base/logging-unittest.cc3
-rw-r--r--deps/v8/test/unittests/base/platform/condition-variable-unittest.cc30
-rw-r--r--deps/v8/test/unittests/base/platform/mutex-unittest.cc8
-rw-r--r--deps/v8/test/unittests/base/threaded-list-unittest.cc31
-rw-r--r--deps/v8/test/unittests/cancelable-tasks-unittest.cc330
-rw-r--r--deps/v8/test/unittests/char-predicates-unittest.cc217
-rw-r--r--deps/v8/test/unittests/code-stub-assembler-unittest.cc10
-rw-r--r--deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc47
-rw-r--r--deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc475
-rw-r--r--deps/v8/test/unittests/compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc3
-rw-r--r--deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc16
-rw-r--r--deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc (renamed from deps/v8/test/unittests/compiler/instruction-selector-unittest.cc)35
-rw-r--r--deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.h (renamed from deps/v8/test/unittests/compiler/instruction-selector-unittest.h)6
-rw-r--r--deps/v8/test/unittests/compiler/backend/instruction-sequence-unittest.cc (renamed from deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc)87
-rw-r--r--deps/v8/test/unittests/compiler/backend/instruction-sequence-unittest.h (renamed from deps/v8/test/unittests/compiler/instruction-sequence-unittest.h)17
-rw-r--r--deps/v8/test/unittests/compiler/backend/instruction-unittest.cc (renamed from deps/v8/test/unittests/compiler/instruction-unittest.cc)2
-rw-r--r--deps/v8/test/unittests/compiler/code-assembler-unittest.cc38
-rw-r--r--deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc44
-rw-r--r--deps/v8/test/unittests/compiler/graph-unittest.cc13
-rw-r--r--deps/v8/test/unittests/compiler/graph-unittest.h7
-rw-r--r--deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/js-call-reducer-unittest.cc25
-rw-r--r--deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc6
-rw-r--r--deps/v8/test/unittests/compiler/js-native-context-specialization-unittest.cc12
-rw-r--r--deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc5
-rw-r--r--deps/v8/test/unittests/compiler/live-range-builder.h78
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc22
-rw-r--r--deps/v8/test/unittests/compiler/machine-operator-unittest.cc3
-rw-r--r--deps/v8/test/unittests/compiler/mips/OWNERS5
-rw-r--r--deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/mips64/OWNERS5
-rw-r--r--deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.cc11
-rw-r--r--deps/v8/test/unittests/compiler/node-test-utils.h10
-rw-r--r--deps/v8/test/unittests/compiler/persistent-unittest.cc24
-rw-r--r--deps/v8/test/unittests/compiler/ppc/OWNERS3
-rw-r--r--deps/v8/test/unittests/compiler/ppc/instruction-selector-ppc-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc207
-rw-r--r--deps/v8/test/unittests/compiler/regalloc/live-range-unittest.cc60
-rw-r--r--deps/v8/test/unittests/compiler/regalloc/move-optimizer-unittest.cc11
-rw-r--r--deps/v8/test/unittests/compiler/regalloc/register-allocator-unittest.cc24
-rw-r--r--deps/v8/test/unittests/compiler/s390/OWNERS3
-rw-r--r--deps/v8/test/unittests/compiler/s390/instruction-selector-s390-unittest.cc2
-rw-r--r--deps/v8/test/unittests/compiler/simplified-lowering-unittest.cc6
-rw-r--r--deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc5
-rw-r--r--deps/v8/test/unittests/compiler/typed-optimization-unittest.cc3
-rw-r--r--deps/v8/test/unittests/compiler/typer-unittest.cc34
-rw-r--r--deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc108
-rw-r--r--deps/v8/test/unittests/compiler/zone-stats-unittest.cc2
-rw-r--r--deps/v8/test/unittests/conversions-unittest.cc76
-rw-r--r--deps/v8/test/unittests/detachable-vector-unittest.cc60
-rw-r--r--deps/v8/test/unittests/heap/barrier-unittest.cc22
-rw-r--r--deps/v8/test/unittests/heap/embedder-tracing-unittest.cc83
-rw-r--r--deps/v8/test/unittests/heap/gc-tracer-unittest.cc26
-rw-r--r--deps/v8/test/unittests/heap/heap-unittest.cc36
-rw-r--r--deps/v8/test/unittests/heap/marking-unittest.cc8
-rw-r--r--deps/v8/test/unittests/heap/slot-set-unittest.cc95
-rw-r--r--deps/v8/test/unittests/heap/spaces-unittest.cc21
-rw-r--r--deps/v8/test/unittests/heap/unmapper-unittest.cc299
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc11
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc7
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-array-random-iterator-unittest.cc43
-rw-r--r--deps/v8/test/unittests/interpreter/bytecode-decoder-unittest.cc7
-rw-r--r--deps/v8/test/unittests/interpreter/bytecodes-unittest.cc2
-rw-r--r--deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc16
-rw-r--r--deps/v8/test/unittests/microtask-queue-unittest.cc187
-rw-r--r--deps/v8/test/unittests/objects/microtask-queue-unittest.cc55
-rw-r--r--deps/v8/test/unittests/register-configuration-unittest.cc16
-rw-r--r--deps/v8/test/unittests/regress/regress-crbug-938251-unittest.cc20
-rw-r--r--deps/v8/test/unittests/test-helpers.cc2
-rw-r--r--deps/v8/test/unittests/test-helpers.h1
-rw-r--r--deps/v8/test/unittests/test-utils.cc105
-rw-r--r--deps/v8/test/unittests/test-utils.h295
-rw-r--r--deps/v8/test/unittests/torque/torque-unittest.cc21
-rw-r--r--deps/v8/test/unittests/unicode-unittest.cc3
-rw-r--r--deps/v8/test/unittests/unittests.status7
-rw-r--r--deps/v8/test/unittests/utils-unittest.cc68
-rw-r--r--deps/v8/test/unittests/value-serializer-unittest.cc218
-rw-r--r--deps/v8/test/unittests/wasm/OWNERS2
-rw-r--r--deps/v8/test/unittests/wasm/decoder-unittest.cc4
-rw-r--r--deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc337
-rw-r--r--deps/v8/test/unittests/wasm/module-decoder-unittest.cc1939
-rw-r--r--deps/v8/test/unittests/wasm/streaming-decoder-unittest.cc82
-rw-r--r--deps/v8/test/unittests/wasm/trap-handler-posix-unittest.cc (renamed from deps/v8/test/unittests/wasm/trap-handler-unittest.cc)4
-rw-r--r--deps/v8/test/unittests/wasm/trap-handler-win-unittest.cc93
-rw-r--r--deps/v8/test/unittests/wasm/trap-handler-x64-unittest.cc478
-rw-r--r--deps/v8/test/unittests/wasm/wasm-code-manager-unittest.cc137
-rw-r--r--deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc71
104 files changed, 4577 insertions, 2996 deletions
diff --git a/deps/v8/test/unittests/BUILD.gn b/deps/v8/test/unittests/BUILD.gn
index f63e2af197..77d503c7d4 100644
--- a/deps/v8/test/unittests/BUILD.gn
+++ b/deps/v8/test/unittests/BUILD.gn
@@ -54,7 +54,7 @@ v8_source_set("unittests_sources") {
"api/v8-object-unittest.cc",
"asmjs/asm-scanner-unittest.cc",
"asmjs/asm-types-unittest.cc",
- "asmjs/switch-logic-unittest.cc",
+ "background-compile-task-unittest.cc",
"base/address-region-unittest.cc",
"base/atomic-utils-unittest.cc",
"base/bits-unittest.cc",
@@ -83,10 +83,13 @@ v8_source_set("unittests_sources") {
"char-predicates-unittest.cc",
"code-stub-assembler-unittest.cc",
"code-stub-assembler-unittest.h",
- "compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc",
"compiler-dispatcher/compiler-dispatcher-unittest.cc",
"compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc",
- "compiler-dispatcher/unoptimized-compile-job-unittest.cc",
+ "compiler/backend/instruction-selector-unittest.cc",
+ "compiler/backend/instruction-selector-unittest.h",
+ "compiler/backend/instruction-sequence-unittest.cc",
+ "compiler/backend/instruction-sequence-unittest.h",
+ "compiler/backend/instruction-unittest.cc",
"compiler/branch-elimination-unittest.cc",
"compiler/bytecode-analysis-unittest.cc",
"compiler/checkpoint-elimination-unittest.cc",
@@ -106,11 +109,6 @@ v8_source_set("unittests_sources") {
"compiler/graph-trimmer-unittest.cc",
"compiler/graph-unittest.cc",
"compiler/graph-unittest.h",
- "compiler/instruction-selector-unittest.cc",
- "compiler/instruction-selector-unittest.h",
- "compiler/instruction-sequence-unittest.cc",
- "compiler/instruction-sequence-unittest.h",
- "compiler/instruction-unittest.cc",
"compiler/int64-lowering-unittest.cc",
"compiler/js-call-reducer-unittest.cc",
"compiler/js-create-lowering-unittest.cc",
@@ -119,7 +117,6 @@ v8_source_set("unittests_sources") {
"compiler/js-operator-unittest.cc",
"compiler/js-typed-lowering-unittest.cc",
"compiler/linkage-tail-call-unittest.cc",
- "compiler/live-range-builder.h",
"compiler/load-elimination-unittest.cc",
"compiler/loop-peeling-unittest.cc",
"compiler/machine-operator-reducer-unittest.cc",
@@ -147,6 +144,7 @@ v8_source_set("unittests_sources") {
"compiler/typer-unittest.cc",
"compiler/value-numbering-reducer-unittest.cc",
"compiler/zone-stats-unittest.cc",
+ "conversions-unittest.cc",
"counters-unittest.cc",
"detachable-vector-unittest.cc",
"eh-frame-iterator-unittest.cc",
@@ -186,11 +184,12 @@ v8_source_set("unittests_sources") {
"libplatform/task-queue-unittest.cc",
"libplatform/worker-thread-unittest.cc",
"locked-queue-unittest.cc",
+ "microtask-queue-unittest.cc",
"object-unittest.cc",
- "objects/microtask-queue-unittest.cc",
"parser/ast-value-unittest.cc",
"parser/preparser-unittest.cc",
"register-configuration-unittest.cc",
+ "regress/regress-crbug-938251-unittest.cc",
"run-all-unittests.cc",
"source-position-table-unittest.cc",
"strings-storage-unittest.cc",
@@ -199,6 +198,7 @@ v8_source_set("unittests_sources") {
"test-utils.cc",
"test-utils.h",
"torque/earley-parser-unittest.cc",
+ "torque/torque-unittest.cc",
"unicode-unittest.cc",
"utils-unittest.cc",
"value-serializer-unittest.cc",
@@ -209,8 +209,8 @@ v8_source_set("unittests_sources") {
"wasm/loop-assignment-analysis-unittest.cc",
"wasm/module-decoder-unittest.cc",
"wasm/streaming-decoder-unittest.cc",
- "wasm/trap-handler-unittest.cc",
"wasm/wasm-code-manager-unittest.cc",
+ "wasm/wasm-compiler-unittest.cc",
"wasm/wasm-macro-gen-unittest.cc",
"wasm/wasm-module-builder-unittest.cc",
"wasm/wasm-opcodes-unittest.cc",
@@ -258,6 +258,7 @@ v8_source_set("unittests_sources") {
sources += [
"assembler/turbo-assembler-x64-unittest.cc",
"compiler/x64/instruction-selector-x64-unittest.cc",
+ "wasm/trap-handler-x64-unittest.cc",
]
} else if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") {
sources += [
@@ -271,6 +272,14 @@ v8_source_set("unittests_sources") {
]
}
+ if (is_posix) {
+ sources += [ "wasm/trap-handler-posix-unittest.cc" ]
+ }
+
+ if (is_win) {
+ sources += [ "wasm/trap-handler-win-unittest.cc" ]
+ }
+
configs = [
"../..:external_config",
"../..:internal_config_base",
diff --git a/deps/v8/test/unittests/api/isolate-unittest.cc b/deps/v8/test/unittests/api/isolate-unittest.cc
index 8ddf8a29c8..10fa7bba22 100644
--- a/deps/v8/test/unittests/api/isolate-unittest.cc
+++ b/deps/v8/test/unittests/api/isolate-unittest.cc
@@ -74,8 +74,7 @@ using IncumbentContextTest = TestWithIsolate;
// Check that Isolate::GetIncumbentContext() returns the correct one in basic
// scenarios.
-#if !defined(V8_USE_ADDRESS_SANITIZER)
-TEST_F(IncumbentContextTest, MAYBE_Basic) {
+TEST_F(IncumbentContextTest, Basic) {
auto Str = [&](const char* s) {
return String::NewFromUtf8(isolate(), s, NewStringType::kNormal)
.ToLocalChecked();
@@ -137,6 +136,5 @@ TEST_F(IncumbentContextTest, MAYBE_Basic) {
EXPECT_EQ(global_c, Run(context_a, "funcA()"));
}
}
-#endif // !defined(V8_USE_ADDRESS_SANITIZER)
} // namespace v8
diff --git a/deps/v8/test/unittests/asmjs/asm-types-unittest.cc b/deps/v8/test/unittests/asmjs/asm-types-unittest.cc
index db5ed2ba52..afc1be0991 100644
--- a/deps/v8/test/unittests/asmjs/asm-types-unittest.cc
+++ b/deps/v8/test/unittests/asmjs/asm-types-unittest.cc
@@ -250,7 +250,7 @@ TEST_F(AsmTypeTest, IsExactly) {
for (size_t ii = 0; ii < arraysize(test_types); ++ii) {
for (size_t jj = 0; jj < arraysize(test_types); ++jj) {
- EXPECT_EQ(ii == jj, test_types[ii]->IsExactly(test_types[jj]))
+ EXPECT_EQ(ii == jj, AsmType::IsExactly(test_types[ii], test_types[jj]))
<< test_types[ii]->Name()
<< ((ii == jj) ? " is not exactly " : " is exactly ")
<< test_types[jj]->Name();
diff --git a/deps/v8/test/unittests/asmjs/switch-logic-unittest.cc b/deps/v8/test/unittests/asmjs/switch-logic-unittest.cc
deleted file mode 100644
index cc3fbb05cc..0000000000
--- a/deps/v8/test/unittests/asmjs/switch-logic-unittest.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright 2016 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.
-
-#include "src/asmjs/switch-logic.h"
-#include "test/unittests/test-utils.h"
-
-namespace v8 {
-namespace internal {
-namespace wasm {
-class SwitchLogicTest : public TestWithZone {};
-
-void CheckNodeValues(CaseNode* node, int begin, int end) {
- CHECK_EQ(node->begin, begin);
- CHECK_EQ(node->end, end);
-}
-
-TEST_F(SwitchLogicTest, Single_Table_Test) {
- ZoneVector<int> values(zone());
- values.push_back(14);
- values.push_back(12);
- values.push_back(15);
- values.push_back(19);
- values.push_back(18);
- values.push_back(16);
- CaseNode* root = OrderCases(&values, zone());
- CHECK_NULL(root->left);
- CHECK_NULL(root->right);
- CheckNodeValues(root, 12, 19);
-}
-
-TEST_F(SwitchLogicTest, Balanced_Tree_Test) {
- ZoneVector<int> values(zone());
- values.push_back(5);
- values.push_back(1);
- values.push_back(6);
- values.push_back(9);
- values.push_back(-4);
- CaseNode* root = OrderCases(&values, zone());
- CheckNodeValues(root, 5, 5);
- CheckNodeValues(root->left, -4, -4);
- CHECK_NULL(root->left->left);
- CheckNodeValues(root->left->right, 1, 1);
- CHECK_NULL(root->left->right->left);
- CHECK_NULL(root->left->right->right);
- CheckNodeValues(root->right, 6, 6);
- CHECK_NULL(root->right->left);
- CheckNodeValues(root->right->right, 9, 9);
- CHECK_NULL(root->right->right->left);
- CHECK_NULL(root->right->right->right);
-}
-
-TEST_F(SwitchLogicTest, Hybrid_Test) {
- ZoneVector<int> values(zone());
- values.push_back(1);
- values.push_back(2);
- values.push_back(3);
- values.push_back(4);
- values.push_back(7);
- values.push_back(10);
- values.push_back(11);
- values.push_back(12);
- values.push_back(13);
- values.push_back(16);
- CaseNode* root = OrderCases(&values, zone());
- CheckNodeValues(root, 7, 7);
- CheckNodeValues(root->left, 1, 4);
- CheckNodeValues(root->right, 10, 13);
- CheckNodeValues(root->right->right, 16, 16);
-}
-
-TEST_F(SwitchLogicTest, Single_Case) {
- ZoneVector<int> values(zone());
- values.push_back(3);
- CaseNode* root = OrderCases(&values, zone());
- CheckNodeValues(root, 3, 3);
- CHECK_NULL(root->left);
- CHECK_NULL(root->right);
-}
-
-TEST_F(SwitchLogicTest, Empty_Case) {
- ZoneVector<int> values(zone());
- CaseNode* root = OrderCases(&values, zone());
- CHECK_NULL(root);
-}
-
-} // namespace wasm
-} // namespace internal
-} // namespace v8
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc
index 056bd1c2c6..63c68ff48f 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc
@@ -30,28 +30,26 @@ namespace internal {
class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, ERROR_MESSAGE("abort: no reason"));
}
TEST_F(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter is 17.
@@ -62,9 +60,9 @@ TEST_F(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc
index e354fb91d9..57e82ecde3 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc
@@ -30,28 +30,26 @@ namespace internal {
class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, ERROR_MESSAGE("abort: no reason"));
}
TEST_F(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter is 17.
@@ -62,9 +60,9 @@ TEST_F(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc
index ba3634314f..3ef812e07a 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc
@@ -17,27 +17,25 @@ namespace internal {
// V8 library, create a context, or use any V8 objects.
TEST(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
- auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer);
+ buffer->MakeExecutable();
+ auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
}
TEST(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter is 17.
@@ -48,8 +46,8 @@ TEST(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
- auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer);
+ buffer->MakeExecutable();
+ auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc
index abba0ff30b..6da112c5dd 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc
@@ -21,28 +21,26 @@ namespace internal {
class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
}
TEST_F(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter (in {a0}) is 17.
@@ -51,9 +49,9 @@ TEST_F(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc
index 8d8bc0756c..5b798b8e02 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc
@@ -21,28 +21,26 @@ namespace internal {
class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
}
TEST_F(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter (in {a0}) is 17.
@@ -51,9 +49,9 @@ TEST_F(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc
index dcc138fce1..24e2e71fd8 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc
@@ -21,12 +21,9 @@ namespace internal {
class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
- // Called from C
- __ function_descriptor();
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
@@ -34,20 +31,17 @@ TEST_F(TurboAssemblerTest, TestHardAbort) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
}
TEST_F(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
- // Called from C
- __ function_descriptor();
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
@@ -59,9 +53,9 @@ TEST_F(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc
index 7d45ec907f..f3f0a532d6 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc
@@ -21,28 +21,26 @@ namespace internal {
class TurboAssemblerTest : public TestWithIsolate {};
TEST_F(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
}
TEST_F(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter is 17.
@@ -53,9 +51,9 @@ TEST_F(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
+ buffer->MakeExecutable();
// We need an isolate here to execute in the simulator.
- auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer);
+ auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc
index 060060c762..8142cbc274 100644
--- a/deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc
+++ b/deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc
@@ -17,27 +17,25 @@ namespace internal {
// V8 library, create a context, or use any V8 objects.
TEST(TurboAssemblerTest, TestHardAbort) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
__ Abort(AbortReason::kNoReason);
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
- auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer);
+ buffer->MakeExecutable();
+ auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer->start());
ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason");
}
TEST(TurboAssemblerTest, TestCheck) {
- size_t allocated;
- byte* buffer = AllocateAssemblerBuffer(&allocated);
- TurboAssembler tasm(nullptr, AssemblerOptions{}, buffer,
- static_cast<int>(allocated), CodeObjectRequired::kNo);
+ auto buffer = AllocateAssemblerBuffer();
+ TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer->CreateView());
__ set_abort_hard(true);
// Fail if the first parameter is 17.
@@ -48,8 +46,8 @@ TEST(TurboAssemblerTest, TestCheck) {
CodeDesc desc;
tasm.GetCode(nullptr, &desc);
- MakeAssemblerBufferExecutable(buffer, allocated);
- auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer);
+ buffer->MakeExecutable();
+ auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer->start());
f.Call(0);
f.Call(18);
diff --git a/deps/v8/test/unittests/compiler-dispatcher/unoptimized-compile-job-unittest.cc b/deps/v8/test/unittests/background-compile-task-unittest.cc
index e3d4ae078b..5bb6b68285 100644
--- a/deps/v8/test/unittests/compiler-dispatcher/unoptimized-compile-job-unittest.cc
+++ b/deps/v8/test/unittests/background-compile-task-unittest.cc
@@ -1,4 +1,4 @@
-// Copyright 2016 the V8 project authors. All rights reserved.
+// 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.
@@ -10,13 +10,13 @@
#include "src/ast/scopes.h"
#include "src/base/platform/semaphore.h"
#include "src/base/template-utils.h"
-#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
-#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
-#include "src/compiler-dispatcher/unoptimized-compile-job.h"
+#include "src/compiler.h"
#include "src/flags.h"
#include "src/isolate-inl.h"
+#include "src/objects/smi.h"
#include "src/parsing/parse-info.h"
-#include "src/parsing/preparsed-scope-data.h"
+#include "src/parsing/parser.h"
+#include "src/parsing/preparse-data.h"
#include "src/v8.h"
#include "test/unittests/test-helpers.h"
#include "test/unittests/test-utils.h"
@@ -25,14 +25,12 @@
namespace v8 {
namespace internal {
-class UnoptimizedCompileJobTest : public TestWithNativeContext {
+class BackgroundCompileTaskTest : public TestWithNativeContext {
public:
- UnoptimizedCompileJobTest()
- : tracer_(isolate()), allocator_(isolate()->allocator()) {}
- ~UnoptimizedCompileJobTest() override = default;
+ BackgroundCompileTaskTest() : allocator_(isolate()->allocator()) {}
+ ~BackgroundCompileTaskTest() override = default;
AccountingAllocator* allocator() { return allocator_; }
- CompilerDispatcherTracer* tracer() { return &tracer_; }
static void SetUpTestCase() {
CHECK_NULL(save_flags_);
@@ -47,7 +45,7 @@ class UnoptimizedCompileJobTest : public TestWithNativeContext {
save_flags_ = nullptr;
}
- UnoptimizedCompileJob* NewUnoptimizedCompileJob(
+ BackgroundCompileTask* NewBackgroundCompileTask(
Isolate* isolate, Handle<SharedFunctionInfo> shared,
size_t stack_size = FLAG_stack_size) {
std::unique_ptr<ParseInfo> outer_parse_info =
@@ -66,82 +64,55 @@ class UnoptimizedCompileJobTest : public TestWithNativeContext {
outer_parse_info->zone(), script_scope, FUNCTION_SCOPE);
function_scope->set_start_position(shared->StartPosition());
function_scope->set_end_position(shared->EndPosition());
+ std::vector<void*> buffer;
+ ScopedPtrList<Statement> statements(&buffer);
const FunctionLiteral* function_literal =
ast_node_factory.NewFunctionLiteral(
- function_name, function_scope, nullptr, -1, -1, -1,
+ function_name, function_scope, statements, -1, -1, -1,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression,
FunctionLiteral::kShouldEagerCompile, shared->StartPosition(), true,
shared->FunctionLiteralId(isolate), nullptr);
- return new UnoptimizedCompileJob(
- tracer(), allocator(), outer_parse_info.get(), function_name,
- function_literal,
+ return new BackgroundCompileTask(
+ allocator(), outer_parse_info.get(), function_name, function_literal,
isolate->counters()->worker_thread_runtime_call_stats(),
isolate->counters()->compile_function_on_background(), FLAG_stack_size);
}
private:
- CompilerDispatcherTracer tracer_;
AccountingAllocator* allocator_;
static SaveFlags* save_flags_;
- DISALLOW_COPY_AND_ASSIGN(UnoptimizedCompileJobTest);
+ DISALLOW_COPY_AND_ASSIGN(BackgroundCompileTaskTest);
};
-SaveFlags* UnoptimizedCompileJobTest::save_flags_ = nullptr;
+SaveFlags* BackgroundCompileTaskTest::save_flags_ = nullptr;
-#define ASSERT_JOB_STATUS(STATUS, JOB) ASSERT_EQ(STATUS, JOB->status())
-
-TEST_F(UnoptimizedCompileJobTest, Construct) {
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(isolate(), nullptr);
- ASSERT_FALSE(shared->is_compiled());
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
-}
-
-TEST_F(UnoptimizedCompileJobTest, StateTransitions) {
+TEST_F(BackgroundCompileTaskTest, Construct) {
Handle<SharedFunctionInfo> shared =
test::CreateSharedFunctionInfo(isolate(), nullptr);
ASSERT_FALSE(shared->is_compiled());
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
-
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
- job->Compile(false);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kReadyToFinalize, job);
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared));
}
-TEST_F(UnoptimizedCompileJobTest, SyntaxError) {
+TEST_F(BackgroundCompileTaskTest, SyntaxError) {
test::ScriptResource* script = new test::ScriptResource("^^^", strlen("^^^"));
Handle<SharedFunctionInfo> shared =
test::CreateSharedFunctionInfo(isolate(), script);
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared));
- job->Compile(false);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kReadyToFinalize, job);
-
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_TRUE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kFailed, job);
+ task->Run();
+ ASSERT_FALSE(Compiler::FinalizeBackgroundCompileTask(
+ task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(isolate()->has_pending_exception());
isolate()->clear_pending_exception();
-
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
-TEST_F(UnoptimizedCompileJobTest, CompileAndRun) {
+TEST_F(BackgroundCompileTaskTest, CompileAndRun) {
const char raw_script[] =
"function g() {\n"
" f = function(a) {\n"
@@ -156,21 +127,19 @@ TEST_F(UnoptimizedCompileJobTest, CompileAndRun) {
Handle<JSFunction> f = RunJS<JSFunction>(script);
Handle<SharedFunctionInfo> shared = handle(f->shared(), isolate());
ASSERT_FALSE(shared->is_compiled());
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared));
- job->Compile(false);
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
+ task->Run();
+ ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
+ task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(shared->is_compiled());
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
- Smi* value = Smi::cast(*RunJS("f(100);"));
+ Smi value = Smi::cast(*RunJS("f(100);"));
ASSERT_TRUE(value == Smi::FromInt(160));
}
-TEST_F(UnoptimizedCompileJobTest, CompileFailure) {
+TEST_F(BackgroundCompileTaskTest, CompileFailure) {
std::string raw_script("() { var a = ");
for (int i = 0; i < 10000; i++) {
// TODO(leszeks): Figure out a more "unit-test-y" way of forcing an analysis
@@ -184,42 +153,35 @@ TEST_F(UnoptimizedCompileJobTest, CompileFailure) {
new test::ScriptResource(raw_script.c_str(), strlen(raw_script.c_str()));
Handle<SharedFunctionInfo> shared =
test::CreateSharedFunctionInfo(isolate(), script);
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared, 100));
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared, 100));
- job->Compile(false);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kReadyToFinalize, job);
-
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_TRUE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kFailed, job);
+ task->Run();
+ ASSERT_FALSE(Compiler::FinalizeBackgroundCompileTask(
+ task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(isolate()->has_pending_exception());
isolate()->clear_pending_exception();
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
class CompileTask : public Task {
public:
- CompileTask(UnoptimizedCompileJob* job, base::Semaphore* semaphore)
- : job_(job), semaphore_(semaphore) {}
+ CompileTask(BackgroundCompileTask* task, base::Semaphore* semaphore)
+ : task_(task), semaphore_(semaphore) {}
~CompileTask() override = default;
void Run() override {
- job_->Compile(true);
- ASSERT_FALSE(job_->IsFailed());
+ task_->Run();
semaphore_->Signal();
}
private:
- UnoptimizedCompileJob* job_;
+ BackgroundCompileTask* task_;
base::Semaphore* semaphore_;
DISALLOW_COPY_AND_ASSIGN(CompileTask);
};
-TEST_F(UnoptimizedCompileJobTest, CompileOnBackgroundThread) {
+TEST_F(BackgroundCompileTaskTest, CompileOnBackgroundThread) {
const char* raw_script =
"(a, b) {\n"
" var c = a + b;\n"
@@ -231,24 +193,20 @@ TEST_F(UnoptimizedCompileJobTest, CompileOnBackgroundThread) {
new test::ScriptResource(raw_script, strlen(raw_script));
Handle<SharedFunctionInfo> shared =
test::CreateSharedFunctionInfo(isolate(), script);
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared));
base::Semaphore semaphore(0);
- auto background_task = base::make_unique<CompileTask>(job.get(), &semaphore);
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
+ auto background_task = base::make_unique<CompileTask>(task.get(), &semaphore);
V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(background_task));
semaphore.Wait();
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
-
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
+ ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
+ task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
+ ASSERT_TRUE(shared->is_compiled());
}
-TEST_F(UnoptimizedCompileJobTest, EagerInnerFunctions) {
+TEST_F(BackgroundCompileTaskTest, EagerInnerFunctions) {
const char raw_script[] =
"function g() {\n"
" f = function() {\n"
@@ -264,25 +222,20 @@ TEST_F(UnoptimizedCompileJobTest, EagerInnerFunctions) {
Handle<JSFunction> f = RunJS<JSFunction>(script);
Handle<SharedFunctionInfo> shared = handle(f->shared(), isolate());
ASSERT_FALSE(shared->is_compiled());
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
-
- job->Compile(false);
- ASSERT_FALSE(job->IsFailed());
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared));
+
+ task->Run();
+ ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
+ task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(shared->is_compiled());
Handle<JSFunction> e = RunJS<JSFunction>("f();");
ASSERT_TRUE(e->shared()->is_compiled());
-
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
-TEST_F(UnoptimizedCompileJobTest, LazyInnerFunctions) {
+TEST_F(BackgroundCompileTaskTest, LazyInnerFunctions) {
const char raw_script[] =
"function g() {\n"
" f = function() {\n"
@@ -297,25 +250,18 @@ TEST_F(UnoptimizedCompileJobTest, LazyInnerFunctions) {
Handle<JSFunction> f = RunJS<JSFunction>(script);
Handle<SharedFunctionInfo> shared = handle(f->shared(), isolate());
ASSERT_FALSE(shared->is_compiled());
- std::unique_ptr<UnoptimizedCompileJob> job(
- NewUnoptimizedCompileJob(isolate(), shared));
-
- job->Compile(false);
- ASSERT_FALSE(job->IsFailed());
- job->FinalizeOnMainThread(isolate(), shared);
- ASSERT_FALSE(job->IsFailed());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kDone, job);
+ std::unique_ptr<BackgroundCompileTask> task(
+ NewBackgroundCompileTask(isolate(), shared));
+
+ task->Run();
+ ASSERT_TRUE(Compiler::FinalizeBackgroundCompileTask(
+ task.get(), shared, isolate(), Compiler::KEEP_EXCEPTION));
ASSERT_TRUE(shared->is_compiled());
Handle<JSFunction> e = RunJS<JSFunction>("f();");
ASSERT_FALSE(e->shared()->is_compiled());
-
- job->ResetOnMainThread(isolate());
- ASSERT_JOB_STATUS(CompilerDispatcherJob::Status::kInitial, job);
}
-#undef ASSERT_JOB_STATUS
-
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/base/atomic-utils-unittest.cc b/deps/v8/test/unittests/base/atomic-utils-unittest.cc
index 1d8e71c9aa..442257eff8 100644
--- a/deps/v8/test/unittests/base/atomic-utils-unittest.cc
+++ b/deps/v8/test/unittests/base/atomic-utils-unittest.cc
@@ -12,11 +12,7 @@ namespace v8 {
namespace base {
namespace {
-enum TestFlag : base::AtomicWord {
- kA,
- kB,
- kC,
-};
+enum TestFlag : base::AtomicWord { kA, kB, kC };
} // namespace
@@ -26,15 +22,6 @@ TEST(AtomicValue, Initial) {
EXPECT_EQ(TestFlag::kA, a.Value());
}
-
-TEST(AtomicValue, TrySetValue) {
- AtomicValue<TestFlag> a(kA);
- EXPECT_FALSE(a.TrySetValue(kB, kC));
- EXPECT_TRUE(a.TrySetValue(kA, kC));
- EXPECT_EQ(TestFlag::kC, a.Value());
-}
-
-
TEST(AtomicValue, SetValue) {
AtomicValue<TestFlag> a(kB);
a.SetValue(kC);
@@ -48,9 +35,6 @@ TEST(AtomicValue, WithVoidStar) {
EXPECT_EQ(nullptr, a.Value());
a.SetValue(&a);
EXPECT_EQ(&a, a.Value());
- EXPECT_FALSE(a.TrySetValue(nullptr, &dummy));
- EXPECT_TRUE(a.TrySetValue(&a, &dummy));
- EXPECT_EQ(&dummy, a.Value());
}
TEST(AsAtomic8, CompareAndSwap_Sequential) {
diff --git a/deps/v8/test/unittests/base/ieee754-unittest.cc b/deps/v8/test/unittests/base/ieee754-unittest.cc
index 2110b63976..56f1812a9e 100644
--- a/deps/v8/test/unittests/base/ieee754-unittest.cc
+++ b/deps/v8/test/unittests/base/ieee754-unittest.cc
@@ -6,6 +6,7 @@
#include "src/base/ieee754.h"
#include "src/base/macros.h"
+#include "src/base/overflowing-math.h"
#include "testing/gmock-support.h"
#include "testing/gtest-support.h"
@@ -314,8 +315,8 @@ TEST(Ieee754, Sin) {
EXPECT_THAT(sin(-kInfinity), IsNaN());
// Tests for sin for |x| < pi/4
- EXPECT_EQ(-kInfinity, 1 / sin(-0.0));
- EXPECT_EQ(kInfinity, 1 / sin(0.0));
+ EXPECT_EQ(-kInfinity, Divide(1.0, sin(-0.0)));
+ EXPECT_EQ(kInfinity, Divide(1.0, sin(0.0)));
// sin(x) = x for x < 2^-27
EXPECT_EQ(2.3283064365386963e-10, sin(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, sin(-2.3283064365386963e-10));
@@ -361,8 +362,8 @@ TEST(Ieee754, Tan) {
EXPECT_THAT(tan(-kInfinity), IsNaN());
// Tests for tan for |x| < pi/4
- EXPECT_EQ(kInfinity, 1 / tan(0.0));
- EXPECT_EQ(-kInfinity, 1 / tan(-0.0));
+ EXPECT_EQ(kInfinity, Divide(1.0, tan(0.0)));
+ EXPECT_EQ(-kInfinity, Divide(1.0, tan(-0.0)));
// tan(x) = x for |x| < 2^-28
EXPECT_EQ(2.3283064365386963e-10, tan(2.3283064365386963e-10));
EXPECT_EQ(-2.3283064365386963e-10, tan(-2.3283064365386963e-10));
diff --git a/deps/v8/test/unittests/base/logging-unittest.cc b/deps/v8/test/unittests/base/logging-unittest.cc
index d73845c373..b720331c9e 100644
--- a/deps/v8/test/unittests/base/logging-unittest.cc
+++ b/deps/v8/test/unittests/base/logging-unittest.cc
@@ -6,6 +6,7 @@
#include "src/base/logging.h"
#include "src/objects.h"
+#include "src/objects/smi.h"
#include "testing/gtest-support.h"
namespace v8 {
@@ -64,7 +65,7 @@ TEST(LoggingTest, CompareSignedMismatch) {
TEST(LoggingTest, CompareAgainstStaticConstPointer) {
// These used to produce link errors before http://crrev.com/2524093002.
- CHECK_FAIL(EQ, v8::internal::Smi::kZero, v8::internal::Smi::FromInt(17));
+ CHECK_FAIL(EQ, v8::internal::Smi::zero(), v8::internal::Smi::FromInt(17));
CHECK_SUCCEED(GT, 0, v8::internal::Smi::kMinValue);
}
diff --git a/deps/v8/test/unittests/base/platform/condition-variable-unittest.cc b/deps/v8/test/unittests/base/platform/condition-variable-unittest.cc
index b32863f4b2..6206569433 100644
--- a/deps/v8/test/unittests/base/platform/condition-variable-unittest.cc
+++ b/deps/v8/test/unittests/base/platform/condition-variable-unittest.cc
@@ -16,7 +16,7 @@ TEST(ConditionVariable, WaitForAfterNofityOnSameThread) {
Mutex mutex;
ConditionVariable cv;
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
cv.NotifyOne();
EXPECT_FALSE(cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n)));
@@ -37,7 +37,7 @@ class ThreadWithMutexAndConditionVariable final : public Thread {
finished_(false) {}
void Run() override {
- LockGuard<Mutex> lock_guard(&mutex_);
+ MutexGuard lock_guard(&mutex_);
running_ = true;
cv_.NotifyOne();
while (running_) {
@@ -61,7 +61,7 @@ TEST(ConditionVariable, MultipleThreadsWithSeparateConditionVariables) {
ThreadWithMutexAndConditionVariable threads[kThreadCount];
for (int n = 0; n < kThreadCount; ++n) {
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
+ MutexGuard lock_guard(&threads[n].mutex_);
EXPECT_FALSE(threads[n].running_);
EXPECT_FALSE(threads[n].finished_);
threads[n].Start();
@@ -72,13 +72,13 @@ TEST(ConditionVariable, MultipleThreadsWithSeparateConditionVariables) {
}
for (int n = kThreadCount - 1; n >= 0; --n) {
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
+ MutexGuard lock_guard(&threads[n].mutex_);
EXPECT_TRUE(threads[n].running_);
EXPECT_FALSE(threads[n].finished_);
}
for (int n = 0; n < kThreadCount; ++n) {
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
+ MutexGuard lock_guard(&threads[n].mutex_);
EXPECT_TRUE(threads[n].running_);
EXPECT_FALSE(threads[n].finished_);
// Tell the nth thread to quit.
@@ -88,7 +88,7 @@ TEST(ConditionVariable, MultipleThreadsWithSeparateConditionVariables) {
for (int n = kThreadCount - 1; n >= 0; --n) {
// Wait for nth thread to quit.
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
+ MutexGuard lock_guard(&threads[n].mutex_);
while (!threads[n].finished_) {
threads[n].cv_.Wait(&threads[n].mutex_);
}
@@ -98,7 +98,7 @@ TEST(ConditionVariable, MultipleThreadsWithSeparateConditionVariables) {
for (int n = 0; n < kThreadCount; ++n) {
threads[n].Join();
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
+ MutexGuard lock_guard(&threads[n].mutex_);
EXPECT_FALSE(threads[n].running_);
EXPECT_TRUE(threads[n].finished_);
}
@@ -117,7 +117,7 @@ class ThreadWithSharedMutexAndConditionVariable final : public Thread {
mutex_(nullptr) {}
void Run() override {
- LockGuard<Mutex> lock_guard(mutex_);
+ MutexGuard lock_guard(mutex_);
running_ = true;
cv_->NotifyAll();
while (running_) {
@@ -149,7 +149,7 @@ TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
// Start all threads.
{
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
for (int n = 0; n < kThreadCount; ++n) {
EXPECT_FALSE(threads[n].running_);
EXPECT_FALSE(threads[n].finished_);
@@ -159,7 +159,7 @@ TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
// Wait for all threads to start.
{
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
for (int n = kThreadCount - 1; n >= 0; --n) {
while (!threads[n].running_) {
cv.Wait(&mutex);
@@ -169,7 +169,7 @@ TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
// Make sure that all threads are running.
{
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
for (int n = 0; n < kThreadCount; ++n) {
EXPECT_TRUE(threads[n].running_);
EXPECT_FALSE(threads[n].finished_);
@@ -178,7 +178,7 @@ TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
// Tell all threads to quit.
{
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
for (int n = kThreadCount - 1; n >= 0; --n) {
EXPECT_TRUE(threads[n].running_);
EXPECT_FALSE(threads[n].finished_);
@@ -190,7 +190,7 @@ TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
// Wait for all threads to quit.
{
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
for (int n = 0; n < kThreadCount; ++n) {
while (!threads[n].finished_) {
cv.Wait(&mutex);
@@ -200,7 +200,7 @@ TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
// Make sure all threads are finished.
{
- LockGuard<Mutex> lock_guard(&mutex);
+ MutexGuard lock_guard(&mutex);
for (int n = kThreadCount - 1; n >= 0; --n) {
EXPECT_FALSE(threads[n].running_);
EXPECT_TRUE(threads[n].finished_);
@@ -234,7 +234,7 @@ class LoopIncrementThread final : public Thread {
void Run() override {
int last_count = -1;
while (true) {
- LockGuard<Mutex> lock_guard(mutex_);
+ MutexGuard lock_guard(mutex_);
int count = *counter_;
while (count % thread_count_ != rem_ && count < limit_) {
cv_->Wait(mutex_);
diff --git a/deps/v8/test/unittests/base/platform/mutex-unittest.cc b/deps/v8/test/unittests/base/platform/mutex-unittest.cc
index 5af5efb5a9..7eb3973e51 100644
--- a/deps/v8/test/unittests/base/platform/mutex-unittest.cc
+++ b/deps/v8/test/unittests/base/platform/mutex-unittest.cc
@@ -11,8 +11,8 @@ namespace base {
TEST(Mutex, LockGuardMutex) {
Mutex mutex;
- { LockGuard<Mutex> lock_guard(&mutex); }
- { LockGuard<Mutex> lock_guard(&mutex); }
+ { MutexGuard lock_guard(&mutex); }
+ { MutexGuard lock_guard(&mutex); }
}
@@ -28,8 +28,8 @@ TEST(Mutex, LockGuardRecursiveMutex) {
TEST(Mutex, LockGuardLazyMutex) {
LazyMutex lazy_mutex = LAZY_MUTEX_INITIALIZER;
- { LockGuard<Mutex> lock_guard(lazy_mutex.Pointer()); }
- { LockGuard<Mutex> lock_guard(lazy_mutex.Pointer()); }
+ { MutexGuard lock_guard(lazy_mutex.Pointer()); }
+ { MutexGuard lock_guard(lazy_mutex.Pointer()); }
}
diff --git a/deps/v8/test/unittests/base/threaded-list-unittest.cc b/deps/v8/test/unittests/base/threaded-list-unittest.cc
index 96a730370b..effe9b08f7 100644
--- a/deps/v8/test/unittests/base/threaded-list-unittest.cc
+++ b/deps/v8/test/unittests/base/threaded-list-unittest.cc
@@ -20,6 +20,10 @@ struct ThreadedListTestNode {
ThreadedListTestNode* next_;
struct OtherTraits {
+ static ThreadedListTestNode** start(ThreadedListTestNode** h) { return h; }
+ static ThreadedListTestNode* const* start(ThreadedListTestNode* const* h) {
+ return h;
+ }
static ThreadedListTestNode** next(ThreadedListTestNode* t) {
return t->other_next();
}
@@ -134,16 +138,6 @@ TEST_F(ThreadedListTest, AddFront) {
CHECK_EQ(list.first(), &new_node);
}
-TEST_F(ThreadedListTest, ReinitializeHead) {
- CHECK_EQ(list.LengthForTest(), 5);
- CHECK_NE(extra_test_list.first(), list.first());
- list.ReinitializeHead(&extra_test_node_0);
- list.Verify();
- CHECK_EQ(extra_test_list.first(), list.first());
- CHECK_EQ(extra_test_list.end(), list.end());
- CHECK_EQ(extra_test_list.LengthForTest(), 3);
-}
-
TEST_F(ThreadedListTest, DropHead) {
CHECK_EQ(extra_test_list.LengthForTest(), 3);
CHECK_EQ(extra_test_list.first(), &extra_test_node_0);
@@ -166,6 +160,23 @@ TEST_F(ThreadedListTest, Append) {
CHECK_EQ(list.end(), initial_extra_list_end);
}
+TEST_F(ThreadedListTest, AppendOutOfScope) {
+ ThreadedListTestNode local_extra_test_node_0;
+ CHECK_EQ(list.LengthForTest(), 5);
+ {
+ ThreadedList<ThreadedListTestNode, ThreadedListTestNode::OtherTraits>
+ scoped_extra_test_list;
+
+ list.Append(std::move(scoped_extra_test_list));
+ }
+ list.Add(&local_extra_test_node_0);
+
+ list.Verify();
+ CHECK_EQ(list.LengthForTest(), 6);
+ CHECK_EQ(list.AtForTest(4), &nodes[4]);
+ CHECK_EQ(list.AtForTest(5), &local_extra_test_node_0);
+}
+
TEST_F(ThreadedListTest, Prepend) {
CHECK_EQ(list.LengthForTest(), 5);
list.Prepend(std::move(extra_test_list));
diff --git a/deps/v8/test/unittests/cancelable-tasks-unittest.cc b/deps/v8/test/unittests/cancelable-tasks-unittest.cc
index 97ac4d4b7d..05048136aa 100644
--- a/deps/v8/test/unittests/cancelable-tasks-unittest.cc
+++ b/deps/v8/test/unittests/cancelable-tasks-unittest.cc
@@ -5,258 +5,262 @@
#include "src/base/atomicops.h"
#include "src/base/platform/platform.h"
#include "src/cancelable-task.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-
namespace v8 {
namespace internal {
namespace {
+using ResultType = std::atomic<CancelableTaskManager::Id>;
+
+class CancelableTaskManagerTest;
+
class TestTask : public Task, public Cancelable {
public:
- enum Mode { kDoNothing, kWaitTillCanceledAgain, kCheckNotRun };
+ enum Mode { kDoNothing, kWaitTillCancelTriggered, kCheckNotRun };
- TestTask(CancelableTaskManager* parent, base::AtomicWord* result,
- Mode mode = kDoNothing)
- : Cancelable(parent), result_(result), mode_(mode) {}
+ TestTask(CancelableTaskManagerTest* test, ResultType* result, Mode mode);
- // Task overrides.
- void Run() final {
- if (TryRun()) {
- RunInternal();
- }
- }
+ // Task override.
+ void Run() final;
private:
- void RunInternal() {
- base::Release_Store(result_, id());
-
- switch (mode_) {
- case kWaitTillCanceledAgain:
- // Simple busy wait until the main thread tried to cancel.
- while (CancelAttempts() == 0) {
- }
- break;
- case kCheckNotRun:
- // Check that we never execute {RunInternal}.
- EXPECT_TRUE(false);
- break;
- default:
- break;
- }
- }
-
- base::AtomicWord* result_;
- Mode mode_;
+ ResultType* const result_;
+ const Mode mode_;
+ CancelableTaskManagerTest* const test_;
};
-
class SequentialRunner {
public:
- explicit SequentialRunner(TestTask* task) : task_(task) {}
+ explicit SequentialRunner(std::unique_ptr<TestTask> task)
+ : task_(std::move(task)), task_id_(task_->id()) {}
void Run() {
task_->Run();
- delete task_;
+ task_.reset();
}
+ CancelableTaskManager::Id task_id() const { return task_id_; }
+
private:
- TestTask* task_;
+ std::unique_ptr<TestTask> task_;
+ const CancelableTaskManager::Id task_id_;
};
-
class ThreadedRunner final : public base::Thread {
public:
- explicit ThreadedRunner(TestTask* task)
- : Thread(Options("runner thread")), task_(task) {}
+ explicit ThreadedRunner(std::unique_ptr<TestTask> task)
+ : Thread(Options("runner thread")),
+ task_(std::move(task)),
+ task_id_(task_->id()) {}
void Run() override {
task_->Run();
- delete task_;
+ task_.reset();
}
+ CancelableTaskManager::Id task_id() const { return task_id_; }
+
private:
- TestTask* task_;
+ std::unique_ptr<TestTask> task_;
+ const CancelableTaskManager::Id task_id_;
};
+class CancelableTaskManagerTest : public ::testing::Test {
+ public:
+ CancelableTaskManager* manager() { return &manager_; }
-typedef base::AtomicWord ResultType;
+ std::unique_ptr<TestTask> NewTask(
+ ResultType* result, TestTask::Mode mode = TestTask::kDoNothing) {
+ return base::make_unique<TestTask>(this, result, mode);
+ }
+ void CancelAndWait() {
+ cancel_triggered_.store(true);
+ manager_.CancelAndWait();
+ }
-intptr_t GetValue(ResultType* result) { return base::Acquire_Load(result); }
+ TryAbortResult TryAbortAll() {
+ cancel_triggered_.store(true);
+ return manager_.TryAbortAll();
+ }
-} // namespace
+ bool cancel_triggered() const { return cancel_triggered_.load(); }
+ private:
+ CancelableTaskManager manager_;
+ std::atomic<bool> cancel_triggered_{false};
+};
-TEST(CancelableTask, EmptyCancelableTaskManager) {
- CancelableTaskManager manager;
- manager.CancelAndWait();
+TestTask::TestTask(CancelableTaskManagerTest* test, ResultType* result,
+ Mode mode)
+ : Cancelable(test->manager()), result_(result), mode_(mode), test_(test) {}
+
+void TestTask::Run() {
+ if (!TryRun()) return;
+
+ result_->store(id());
+
+ switch (mode_) {
+ case kWaitTillCancelTriggered:
+ // Simple busy wait until the main thread tried to cancel.
+ while (!test_->cancel_triggered()) {
+ }
+ break;
+ case kCheckNotRun:
+ // Check that we never execute {RunInternal}.
+ EXPECT_TRUE(false);
+ break;
+ default:
+ break;
+ }
}
+} // namespace
-TEST(CancelableTask, SequentialCancelAndWait) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- SequentialRunner runner1(
- new TestTask(&manager, &result1, TestTask::kCheckNotRun));
- EXPECT_EQ(GetValue(&result1), 0);
- manager.CancelAndWait();
- EXPECT_EQ(GetValue(&result1), 0);
- runner1.Run(); // Run to avoid leaking the Task.
- EXPECT_EQ(GetValue(&result1), 0);
+TEST_F(CancelableTaskManagerTest, EmptyCancelableTaskManager) {
+ CancelAndWait();
}
-
-TEST(CancelableTask, SequentialMultipleTasks) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- ResultType result2 = 0;
- TestTask* task1 = new TestTask(&manager, &result1);
- TestTask* task2 = new TestTask(&manager, &result2);
- SequentialRunner runner1(task1);
- SequentialRunner runner2(task2);
- EXPECT_EQ(task1->id(), 1u);
- EXPECT_EQ(task2->id(), 2u);
-
- EXPECT_EQ(GetValue(&result1), 0);
- runner1.Run(); // Don't touch task1 after running it.
- EXPECT_EQ(GetValue(&result1), 1);
-
- EXPECT_EQ(GetValue(&result2), 0);
- runner2.Run(); // Don't touch task2 after running it.
- EXPECT_EQ(GetValue(&result2), 2);
-
- manager.CancelAndWait();
- EXPECT_FALSE(manager.TryAbort(1));
- EXPECT_FALSE(manager.TryAbort(2));
+TEST_F(CancelableTaskManagerTest, SequentialCancelAndWait) {
+ ResultType result1{0};
+ SequentialRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
+ EXPECT_EQ(0u, result1);
+ CancelAndWait();
+ EXPECT_EQ(0u, result1);
+ runner1.Run();
+ EXPECT_EQ(0u, result1);
}
+TEST_F(CancelableTaskManagerTest, SequentialMultipleTasks) {
+ ResultType result1{0};
+ ResultType result2{0};
+ SequentialRunner runner1(NewTask(&result1));
+ SequentialRunner runner2(NewTask(&result2));
+ EXPECT_EQ(1u, runner1.task_id());
+ EXPECT_EQ(2u, runner2.task_id());
+
+ EXPECT_EQ(0u, result1);
+ runner1.Run();
+ EXPECT_EQ(1u, result1);
+
+ EXPECT_EQ(0u, result2);
+ runner2.Run();
+ EXPECT_EQ(2u, result2);
+
+ CancelAndWait();
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(2));
+}
-TEST(CancelableTask, ThreadedMultipleTasksStarted) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- ResultType result2 = 0;
- TestTask* task1 =
- new TestTask(&manager, &result1, TestTask::kWaitTillCanceledAgain);
- TestTask* task2 =
- new TestTask(&manager, &result2, TestTask::kWaitTillCanceledAgain);
- ThreadedRunner runner1(task1);
- ThreadedRunner runner2(task2);
+TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksStarted) {
+ ResultType result1{0};
+ ResultType result2{0};
+ ThreadedRunner runner1(NewTask(&result1, TestTask::kWaitTillCancelTriggered));
+ ThreadedRunner runner2(NewTask(&result2, TestTask::kWaitTillCancelTriggered));
runner1.Start();
runner2.Start();
// Busy wait on result to make sure both tasks are done.
- while ((GetValue(&result1) == 0) || (GetValue(&result2) == 0)) {
+ while (result1.load() == 0 || result2.load() == 0) {
}
- manager.CancelAndWait();
+ CancelAndWait();
runner1.Join();
runner2.Join();
- EXPECT_EQ(GetValue(&result1), 1);
- EXPECT_EQ(GetValue(&result2), 2);
+ EXPECT_EQ(1u, result1);
+ EXPECT_EQ(2u, result2);
}
-
-TEST(CancelableTask, ThreadedMultipleTasksNotRun) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- ResultType result2 = 0;
- TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun);
- TestTask* task2 = new TestTask(&manager, &result2, TestTask::kCheckNotRun);
- ThreadedRunner runner1(task1);
- ThreadedRunner runner2(task2);
- manager.CancelAndWait();
+TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksNotRun) {
+ ResultType result1{0};
+ ResultType result2{0};
+ ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
+ ThreadedRunner runner2(NewTask(&result2, TestTask::kCheckNotRun));
+ CancelAndWait();
// Tasks are canceled, hence the runner will bail out and not update result.
runner1.Start();
runner2.Start();
runner1.Join();
runner2.Join();
- EXPECT_EQ(GetValue(&result1), 0);
- EXPECT_EQ(GetValue(&result2), 0);
+ EXPECT_EQ(0u, result1);
+ EXPECT_EQ(0u, result2);
}
-
-TEST(CancelableTask, RemoveBeforeCancelAndWait) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun);
- ThreadedRunner runner1(task1);
- CancelableTaskManager::Id id = task1->id();
- EXPECT_EQ(id, 1u);
- EXPECT_TRUE(manager.TryAbort(id));
+TEST_F(CancelableTaskManagerTest, RemoveBeforeCancelAndWait) {
+ ResultType result1{0};
+ ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
+ CancelableTaskManager::Id id = runner1.task_id();
+ EXPECT_EQ(1u, id);
+ EXPECT_EQ(TryAbortResult::kTaskAborted, manager()->TryAbort(id));
runner1.Start();
runner1.Join();
- manager.CancelAndWait();
- EXPECT_EQ(GetValue(&result1), 0);
+ CancelAndWait();
+ EXPECT_EQ(0u, result1);
}
-
-TEST(CancelableTask, RemoveAfterCancelAndWait) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- TestTask* task1 = new TestTask(&manager, &result1);
- ThreadedRunner runner1(task1);
- CancelableTaskManager::Id id = task1->id();
- EXPECT_EQ(id, 1u);
+TEST_F(CancelableTaskManagerTest, RemoveAfterCancelAndWait) {
+ ResultType result1{0};
+ ThreadedRunner runner1(NewTask(&result1));
+ CancelableTaskManager::Id id = runner1.task_id();
+ EXPECT_EQ(1u, id);
runner1.Start();
runner1.Join();
- manager.CancelAndWait();
- EXPECT_FALSE(manager.TryAbort(id));
- EXPECT_EQ(GetValue(&result1), 1);
+ CancelAndWait();
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(id));
+ EXPECT_EQ(1u, result1);
}
-
-TEST(CancelableTask, RemoveUnmanagedId) {
- CancelableTaskManager manager;
- EXPECT_FALSE(manager.TryAbort(1));
- EXPECT_FALSE(manager.TryAbort(2));
- manager.CancelAndWait();
- EXPECT_FALSE(manager.TryAbort(1));
- EXPECT_FALSE(manager.TryAbort(3));
+TEST_F(CancelableTaskManagerTest, RemoveUnmanagedId) {
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(2));
+ CancelAndWait();
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(1));
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, manager()->TryAbort(3));
}
-TEST(CancelableTask, EmptyTryAbortAll) {
- CancelableTaskManager manager;
- EXPECT_EQ(manager.TryAbortAll(), CancelableTaskManager::kTaskRemoved);
+TEST_F(CancelableTaskManagerTest, EmptyTryAbortAll) {
+ EXPECT_EQ(TryAbortResult::kTaskRemoved, TryAbortAll());
+ CancelAndWait();
}
-TEST(CancelableTask, ThreadedMultipleTasksNotRunTryAbortAll) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- ResultType result2 = 0;
- TestTask* task1 = new TestTask(&manager, &result1, TestTask::kCheckNotRun);
- TestTask* task2 = new TestTask(&manager, &result2, TestTask::kCheckNotRun);
- ThreadedRunner runner1(task1);
- ThreadedRunner runner2(task2);
- EXPECT_EQ(manager.TryAbortAll(), CancelableTaskManager::kTaskAborted);
+TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksNotRunTryAbortAll) {
+ ResultType result1{0};
+ ResultType result2{0};
+ ThreadedRunner runner1(NewTask(&result1, TestTask::kCheckNotRun));
+ ThreadedRunner runner2(NewTask(&result2, TestTask::kCheckNotRun));
+ EXPECT_EQ(TryAbortResult::kTaskAborted, TryAbortAll());
// Tasks are canceled, hence the runner will bail out and not update result.
runner1.Start();
runner2.Start();
runner1.Join();
runner2.Join();
- EXPECT_EQ(GetValue(&result1), 0);
- EXPECT_EQ(GetValue(&result2), 0);
+ EXPECT_EQ(0u, result1);
+ EXPECT_EQ(0u, result2);
+ CancelAndWait();
}
-TEST(CancelableTask, ThreadedMultipleTasksStartedTryAbortAll) {
- CancelableTaskManager manager;
- ResultType result1 = 0;
- ResultType result2 = 0;
- TestTask* task1 =
- new TestTask(&manager, &result1, TestTask::kWaitTillCanceledAgain);
- TestTask* task2 =
- new TestTask(&manager, &result2, TestTask::kWaitTillCanceledAgain);
- ThreadedRunner runner1(task1);
- ThreadedRunner runner2(task2);
+TEST_F(CancelableTaskManagerTest, ThreadedMultipleTasksStartedTryAbortAll) {
+ ResultType result1{0};
+ ResultType result2{0};
+ ThreadedRunner runner1(NewTask(&result1, TestTask::kWaitTillCancelTriggered));
+ ThreadedRunner runner2(NewTask(&result2, TestTask::kWaitTillCancelTriggered));
runner1.Start();
// Busy wait on result to make sure task1 is done.
- while (GetValue(&result1) == 0) {
+ while (result1.load() == 0) {
}
- EXPECT_EQ(manager.TryAbortAll(), CancelableTaskManager::kTaskRunning);
+ // If the task saw that we triggered the cancel and finished *before* the
+ // actual cancel happened, we get {kTaskAborted}. Otherwise, we get
+ // {kTaskRunning}.
+ EXPECT_THAT(TryAbortAll(),
+ testing::AnyOf(testing::Eq(TryAbortResult::kTaskAborted),
+ testing::Eq(TryAbortResult::kTaskRunning)));
runner2.Start();
runner1.Join();
runner2.Join();
- EXPECT_EQ(GetValue(&result1), 1);
- EXPECT_EQ(GetValue(&result2), 0);
+ EXPECT_EQ(1u, result1);
+ EXPECT_EQ(0u, result2);
+ CancelAndWait();
}
} // namespace internal
diff --git a/deps/v8/test/unittests/char-predicates-unittest.cc b/deps/v8/test/unittests/char-predicates-unittest.cc
index 3c6cf5d6a6..85c550a7e2 100644
--- a/deps/v8/test/unittests/char-predicates-unittest.cc
+++ b/deps/v8/test/unittests/char-predicates-unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "src/char-predicates.h"
+#include "src/char-predicates-inl.h"
#include "src/unicode.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -10,122 +11,122 @@ namespace v8 {
namespace internal {
TEST(CharPredicatesTest, WhiteSpace) {
- EXPECT_TRUE(WhiteSpace::Is(0x0009));
- EXPECT_TRUE(WhiteSpace::Is(0x000B));
- EXPECT_TRUE(WhiteSpace::Is(0x000C));
- EXPECT_TRUE(WhiteSpace::Is(' '));
- EXPECT_TRUE(WhiteSpace::Is(0x00A0));
- EXPECT_TRUE(WhiteSpace::Is(0x1680));
- EXPECT_TRUE(WhiteSpace::Is(0x2000));
- EXPECT_TRUE(WhiteSpace::Is(0x2007));
- EXPECT_TRUE(WhiteSpace::Is(0x202F));
- EXPECT_TRUE(WhiteSpace::Is(0x205F));
- EXPECT_TRUE(WhiteSpace::Is(0x3000));
- EXPECT_TRUE(WhiteSpace::Is(0xFEFF));
- EXPECT_FALSE(WhiteSpace::Is(0x180E));
+ EXPECT_TRUE(IsWhiteSpace(0x0009));
+ EXPECT_TRUE(IsWhiteSpace(0x000B));
+ EXPECT_TRUE(IsWhiteSpace(0x000C));
+ EXPECT_TRUE(IsWhiteSpace(' '));
+ EXPECT_TRUE(IsWhiteSpace(0x00A0));
+ EXPECT_TRUE(IsWhiteSpace(0x1680));
+ EXPECT_TRUE(IsWhiteSpace(0x2000));
+ EXPECT_TRUE(IsWhiteSpace(0x2007));
+ EXPECT_TRUE(IsWhiteSpace(0x202F));
+ EXPECT_TRUE(IsWhiteSpace(0x205F));
+ EXPECT_TRUE(IsWhiteSpace(0x3000));
+ EXPECT_TRUE(IsWhiteSpace(0xFEFF));
+ EXPECT_FALSE(IsWhiteSpace(0x180E));
}
TEST(CharPredicatesTest, WhiteSpaceOrLineTerminator) {
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x0009));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000B));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000C));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(' '));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x00A0));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x1680));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x2000));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x2007));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x202F));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x205F));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0xFEFF));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x0009));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x000B));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x000C));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(' '));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x00A0));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x1680));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x2000));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x2007));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x202F));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x205F));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0xFEFF));
// Line terminators
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000A));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x000D));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x2028));
- EXPECT_TRUE(WhiteSpaceOrLineTerminator::Is(0x2029));
- EXPECT_FALSE(WhiteSpaceOrLineTerminator::Is(0x180E));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x000A));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x000D));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x2028));
+ EXPECT_TRUE(IsWhiteSpaceOrLineTerminator(0x2029));
+ EXPECT_FALSE(IsWhiteSpaceOrLineTerminator(0x180E));
}
TEST(CharPredicatesTest, IdentifierStart) {
- EXPECT_TRUE(IdentifierStart::Is('$'));
- EXPECT_TRUE(IdentifierStart::Is('_'));
- EXPECT_TRUE(IdentifierStart::Is('\\'));
+ EXPECT_TRUE(IsIdentifierStart('$'));
+ EXPECT_TRUE(IsIdentifierStart('_'));
+ EXPECT_TRUE(IsIdentifierStart('\\'));
// http://www.unicode.org/reports/tr31/
// curl http://www.unicode.org/Public/UCD/latest/ucd/PropList.txt |
// grep 'Other_ID_Start'
// Other_ID_Start
- EXPECT_TRUE(IdentifierStart::Is(0x1885));
- EXPECT_TRUE(IdentifierStart::Is(0x1886));
- EXPECT_TRUE(IdentifierStart::Is(0x2118));
- EXPECT_TRUE(IdentifierStart::Is(0x212E));
- EXPECT_TRUE(IdentifierStart::Is(0x309B));
- EXPECT_TRUE(IdentifierStart::Is(0x309C));
+ EXPECT_TRUE(IsIdentifierStart(0x1885));
+ EXPECT_TRUE(IsIdentifierStart(0x1886));
+ EXPECT_TRUE(IsIdentifierStart(0x2118));
+ EXPECT_TRUE(IsIdentifierStart(0x212E));
+ EXPECT_TRUE(IsIdentifierStart(0x309B));
+ EXPECT_TRUE(IsIdentifierStart(0x309C));
// Issue 2892:
// \u2E2F has the Pattern_Syntax property, excluding it from ID_Start.
- EXPECT_FALSE(IdentifierStart::Is(0x2E2F));
+ EXPECT_FALSE(IsIdentifierStart(0x2E2F));
#ifdef V8_INTL_SUPPORT
// New in Unicode 8.0 (6,847 code points)
// [:ID_Start:] & [[:Age=8.0:] - [:Age=7.0:]]
- EXPECT_TRUE(IdentifierStart::Is(0x08B3));
- EXPECT_TRUE(IdentifierStart::Is(0x0AF9));
- EXPECT_TRUE(IdentifierStart::Is(0x13F8));
- EXPECT_TRUE(IdentifierStart::Is(0x9FCD));
- EXPECT_TRUE(IdentifierStart::Is(0xAB60));
- EXPECT_TRUE(IdentifierStart::Is(0x10CC0));
- EXPECT_TRUE(IdentifierStart::Is(0x108E0));
- EXPECT_TRUE(IdentifierStart::Is(0x2B820));
+ EXPECT_TRUE(IsIdentifierStart(0x08B3));
+ EXPECT_TRUE(IsIdentifierStart(0x0AF9));
+ EXPECT_TRUE(IsIdentifierStart(0x13F8));
+ EXPECT_TRUE(IsIdentifierStart(0x9FCD));
+ EXPECT_TRUE(IsIdentifierStart(0xAB60));
+ EXPECT_TRUE(IsIdentifierStart(0x10CC0));
+ EXPECT_TRUE(IsIdentifierStart(0x108E0));
+ EXPECT_TRUE(IsIdentifierStart(0x2B820));
// New in Unicode 9.0 (7,177 code points)
// [:ID_Start:] & [[:Age=9.0:] - [:Age=8.0:]]
- EXPECT_TRUE(IdentifierStart::Is(0x1C80));
- EXPECT_TRUE(IdentifierStart::Is(0x104DB));
- EXPECT_TRUE(IdentifierStart::Is(0x1E922));
+ EXPECT_TRUE(IsIdentifierStart(0x1C80));
+ EXPECT_TRUE(IsIdentifierStart(0x104DB));
+ EXPECT_TRUE(IsIdentifierStart(0x1E922));
#endif
}
TEST(CharPredicatesTest, IdentifierPart) {
- EXPECT_TRUE(IdentifierPart::Is('$'));
- EXPECT_TRUE(IdentifierPart::Is('_'));
- EXPECT_TRUE(IdentifierPart::Is('\\'));
- EXPECT_TRUE(IdentifierPart::Is(0x200C));
- EXPECT_TRUE(IdentifierPart::Is(0x200D));
+ EXPECT_TRUE(IsIdentifierPart('$'));
+ EXPECT_TRUE(IsIdentifierPart('_'));
+ EXPECT_TRUE(IsIdentifierPart('\\'));
+ EXPECT_TRUE(IsIdentifierPart(0x200C));
+ EXPECT_TRUE(IsIdentifierPart(0x200D));
#ifdef V8_INTL_SUPPORT
// New in Unicode 8.0 (6,847 code points)
// [:ID_Start:] & [[:Age=8.0:] - [:Age=7.0:]]
- EXPECT_TRUE(IdentifierPart::Is(0x08B3));
- EXPECT_TRUE(IdentifierPart::Is(0x0AF9));
- EXPECT_TRUE(IdentifierPart::Is(0x13F8));
- EXPECT_TRUE(IdentifierPart::Is(0x9FCD));
- EXPECT_TRUE(IdentifierPart::Is(0xAB60));
- EXPECT_TRUE(IdentifierPart::Is(0x10CC0));
- EXPECT_TRUE(IdentifierPart::Is(0x108E0));
- EXPECT_TRUE(IdentifierPart::Is(0x2B820));
+ EXPECT_TRUE(IsIdentifierPart(0x08B3));
+ EXPECT_TRUE(IsIdentifierPart(0x0AF9));
+ EXPECT_TRUE(IsIdentifierPart(0x13F8));
+ EXPECT_TRUE(IsIdentifierPart(0x9FCD));
+ EXPECT_TRUE(IsIdentifierPart(0xAB60));
+ EXPECT_TRUE(IsIdentifierPart(0x10CC0));
+ EXPECT_TRUE(IsIdentifierPart(0x108E0));
+ EXPECT_TRUE(IsIdentifierPart(0x2B820));
// [[:ID_Continue:]-[:ID_Start:]] & [[:Age=8.0:]-[:Age=7.0:]]
// 162 code points
- EXPECT_TRUE(IdentifierPart::Is(0x08E3));
- EXPECT_TRUE(IdentifierPart::Is(0xA69E));
- EXPECT_TRUE(IdentifierPart::Is(0x11730));
+ EXPECT_TRUE(IsIdentifierPart(0x08E3));
+ EXPECT_TRUE(IsIdentifierPart(0xA69E));
+ EXPECT_TRUE(IsIdentifierPart(0x11730));
// New in Unicode 9.0 (7,177 code points)
// [:ID_Start:] & [[:Age=9.0:] - [:Age=8.0:]]
- EXPECT_TRUE(IdentifierPart::Is(0x1C80));
- EXPECT_TRUE(IdentifierPart::Is(0x104DB));
- EXPECT_TRUE(IdentifierPart::Is(0x1E922));
+ EXPECT_TRUE(IsIdentifierPart(0x1C80));
+ EXPECT_TRUE(IsIdentifierPart(0x104DB));
+ EXPECT_TRUE(IsIdentifierPart(0x1E922));
// [[:ID_Continue:]-[:ID_Start:]] & [[:Age=9.0:]-[:Age=8.0:]]
// 162 code points
- EXPECT_TRUE(IdentifierPart::Is(0x08D4));
- EXPECT_TRUE(IdentifierPart::Is(0x1DFB));
- EXPECT_TRUE(IdentifierPart::Is(0xA8C5));
- EXPECT_TRUE(IdentifierPart::Is(0x11450));
+ EXPECT_TRUE(IsIdentifierPart(0x08D4));
+ EXPECT_TRUE(IsIdentifierPart(0x1DFB));
+ EXPECT_TRUE(IsIdentifierPart(0xA8C5));
+ EXPECT_TRUE(IsIdentifierPart(0x11450));
#endif
// http://www.unicode.org/reports/tr31/
@@ -133,58 +134,58 @@ TEST(CharPredicatesTest, IdentifierPart) {
// grep 'Other_ID_(Continue|Start)'
// Other_ID_Start
- EXPECT_TRUE(IdentifierPart::Is(0x1885));
- EXPECT_TRUE(IdentifierPart::Is(0x1886));
- EXPECT_TRUE(IdentifierPart::Is(0x2118));
- EXPECT_TRUE(IdentifierPart::Is(0x212E));
- EXPECT_TRUE(IdentifierPart::Is(0x309B));
- EXPECT_TRUE(IdentifierPart::Is(0x309C));
+ EXPECT_TRUE(IsIdentifierPart(0x1885));
+ EXPECT_TRUE(IsIdentifierPart(0x1886));
+ EXPECT_TRUE(IsIdentifierPart(0x2118));
+ EXPECT_TRUE(IsIdentifierPart(0x212E));
+ EXPECT_TRUE(IsIdentifierPart(0x309B));
+ EXPECT_TRUE(IsIdentifierPart(0x309C));
// Other_ID_Continue
- EXPECT_TRUE(IdentifierPart::Is(0x00B7));
- EXPECT_TRUE(IdentifierPart::Is(0x0387));
- EXPECT_TRUE(IdentifierPart::Is(0x1369));
- EXPECT_TRUE(IdentifierPart::Is(0x1370));
- EXPECT_TRUE(IdentifierPart::Is(0x1371));
- EXPECT_TRUE(IdentifierPart::Is(0x19DA));
+ EXPECT_TRUE(IsIdentifierPart(0x00B7));
+ EXPECT_TRUE(IsIdentifierPart(0x0387));
+ EXPECT_TRUE(IsIdentifierPart(0x1369));
+ EXPECT_TRUE(IsIdentifierPart(0x1370));
+ EXPECT_TRUE(IsIdentifierPart(0x1371));
+ EXPECT_TRUE(IsIdentifierPart(0x19DA));
// Issue 2892:
// \u2E2F has the Pattern_Syntax property, excluding it from ID_Start.
- EXPECT_FALSE(IdentifierPart::Is(0x2E2F));
+ EXPECT_FALSE(IsIdentifierPart(0x2E2F));
}
#ifdef V8_INTL_SUPPORT
TEST(CharPredicatesTest, SupplementaryPlaneIdentifiers) {
// Both ID_Start and ID_Continue.
- EXPECT_TRUE(IdentifierStart::Is(0x10403)); // Category Lu
- EXPECT_TRUE(IdentifierPart::Is(0x10403));
- EXPECT_TRUE(IdentifierStart::Is(0x1043C)); // Category Ll
- EXPECT_TRUE(IdentifierPart::Is(0x1043C));
- EXPECT_TRUE(IdentifierStart::Is(0x16F9C)); // Category Lm
- EXPECT_TRUE(IdentifierPart::Is(0x16F9C));
- EXPECT_TRUE(IdentifierStart::Is(0x10048)); // Category Lo
- EXPECT_TRUE(IdentifierPart::Is(0x10048));
- EXPECT_TRUE(IdentifierStart::Is(0x1014D)); // Category Nl
- EXPECT_TRUE(IdentifierPart::Is(0x1014D));
+ EXPECT_TRUE(IsIdentifierStart(0x10403)); // Category Lu
+ EXPECT_TRUE(IsIdentifierPart(0x10403));
+ EXPECT_TRUE(IsIdentifierStart(0x1043C)); // Category Ll
+ EXPECT_TRUE(IsIdentifierPart(0x1043C));
+ EXPECT_TRUE(IsIdentifierStart(0x16F9C)); // Category Lm
+ EXPECT_TRUE(IsIdentifierPart(0x16F9C));
+ EXPECT_TRUE(IsIdentifierStart(0x10048)); // Category Lo
+ EXPECT_TRUE(IsIdentifierPart(0x10048));
+ EXPECT_TRUE(IsIdentifierStart(0x1014D)); // Category Nl
+ EXPECT_TRUE(IsIdentifierPart(0x1014D));
// New in Unicode 8.0
// [ [:ID_Start=Yes:] & [:Age=8.0:]] - [:Age=7.0:]
- EXPECT_TRUE(IdentifierStart::Is(0x108E0));
- EXPECT_TRUE(IdentifierStart::Is(0x10C80));
+ EXPECT_TRUE(IsIdentifierStart(0x108E0));
+ EXPECT_TRUE(IsIdentifierStart(0x10C80));
// Only ID_Continue.
- EXPECT_FALSE(IdentifierStart::Is(0x101FD)); // Category Mn
- EXPECT_TRUE(IdentifierPart::Is(0x101FD));
- EXPECT_FALSE(IdentifierStart::Is(0x11002)); // Category Mc
- EXPECT_TRUE(IdentifierPart::Is(0x11002));
- EXPECT_FALSE(IdentifierStart::Is(0x104A9)); // Category Nd
- EXPECT_TRUE(IdentifierPart::Is(0x104A9));
+ EXPECT_FALSE(IsIdentifierStart(0x101FD)); // Category Mn
+ EXPECT_TRUE(IsIdentifierPart(0x101FD));
+ EXPECT_FALSE(IsIdentifierStart(0x11002)); // Category Mc
+ EXPECT_TRUE(IsIdentifierPart(0x11002));
+ EXPECT_FALSE(IsIdentifierStart(0x104A9)); // Category Nd
+ EXPECT_TRUE(IsIdentifierPart(0x104A9));
// Neither.
- EXPECT_FALSE(IdentifierStart::Is(0x10111)); // Category No
- EXPECT_FALSE(IdentifierPart::Is(0x10111));
- EXPECT_FALSE(IdentifierStart::Is(0x1F4A9)); // Category So
- EXPECT_FALSE(IdentifierPart::Is(0x1F4A9));
+ EXPECT_FALSE(IsIdentifierStart(0x10111)); // Category No
+ EXPECT_FALSE(IsIdentifierPart(0x10111));
+ EXPECT_FALSE(IsIdentifierStart(0x1F4A9)); // Category So
+ EXPECT_FALSE(IsIdentifierPart(0x1F4A9));
}
#endif // V8_INTL_SUPPORT
diff --git a/deps/v8/test/unittests/code-stub-assembler-unittest.cc b/deps/v8/test/unittests/code-stub-assembler-unittest.cc
index dab7e3e3a6..836a18e2e6 100644
--- a/deps/v8/test/unittests/code-stub-assembler-unittest.cc
+++ b/deps/v8/test/unittests/code-stub-assembler-unittest.cc
@@ -20,14 +20,6 @@ namespace c = v8::internal::compiler;
namespace v8 {
namespace internal {
-#ifdef ENABLE_VERIFY_CSA
-#define IS_BITCAST_WORD_TO_TAGGED_SIGNED(x) IsBitcastWordToTaggedSigned(x)
-#define IS_BITCAST_TAGGED_TO_WORD(x) IsBitcastTaggedToWord(x)
-#else
-#define IS_BITCAST_WORD_TO_TAGGED_SIGNED(x) (x)
-#define IS_BITCAST_TAGGED_TO_WORD(x) (x)
-#endif
-
CodeStubAssemblerTestState::CodeStubAssemblerTestState(
CodeStubAssemblerTest* test)
: compiler::CodeAssemblerState(
@@ -39,7 +31,7 @@ TARGET_TEST_F(CodeStubAssemblerTest, SmiTag) {
CodeStubAssemblerForTest m(&state);
Node* value = m.Int32Constant(44);
EXPECT_THAT(m.SmiTag(value),
- IS_BITCAST_WORD_TO_TAGGED_SIGNED(c::IsIntPtrConstant(
+ IsBitcastWordToTaggedSigned(c::IsIntPtrConstant(
static_cast<intptr_t>(44) << (kSmiShiftSize + kSmiTagSize))));
EXPECT_THAT(m.SmiUntag(value),
c::IsIntPtrConstant(static_cast<intptr_t>(44) >>
diff --git a/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc b/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc
deleted file mode 100644
index 6ae5c7bd6c..0000000000
--- a/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-tracer-unittest.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2016 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.
-
-#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
-#include "testing/gtest-support.h"
-
-namespace v8 {
-namespace internal {
-
-TEST(CompilerDispatcherTracerTest, EstimateWithoutSamples) {
- CompilerDispatcherTracer tracer(nullptr);
-
- EXPECT_EQ(0.0, tracer.EstimatePrepareInMs());
- EXPECT_EQ(1.0, tracer.EstimateCompileInMs(1));
- EXPECT_EQ(1.0, tracer.EstimateCompileInMs(42));
- EXPECT_EQ(0.0, tracer.EstimateFinalizeInMs());
-}
-
-TEST(CompilerDispatcherTracerTest, Average) {
- CompilerDispatcherTracer tracer(nullptr);
-
- EXPECT_EQ(0.0, tracer.EstimatePrepareInMs());
-
- tracer.RecordPrepare(1.0);
- tracer.RecordPrepare(2.0);
- tracer.RecordPrepare(3.0);
-
- EXPECT_EQ((1.0 + 2.0 + 3.0) / 3, tracer.EstimatePrepareInMs());
-}
-
-TEST(CompilerDispatcherTracerTest, SizeBasedAverage) {
- CompilerDispatcherTracer tracer(nullptr);
-
- EXPECT_EQ(1.0, tracer.EstimateCompileInMs(100));
-
- // All three samples parse 100 units/ms.
- tracer.RecordCompile(1.0, 100);
- tracer.RecordCompile(2.0, 200);
- tracer.RecordCompile(3.0, 300);
-
- EXPECT_EQ(1.0, tracer.EstimateCompileInMs(100));
- EXPECT_EQ(5.0, tracer.EstimateCompileInMs(500));
-}
-
-} // namespace internal
-} // namespace v8
diff --git a/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc b/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
index bfc111aed5..0f918e3a07 100644
--- a/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
+++ b/deps/v8/test/unittests/compiler-dispatcher/compiler-dispatcher-unittest.cc
@@ -13,9 +13,6 @@
#include "src/ast/scopes.h"
#include "src/base/platform/semaphore.h"
#include "src/base/template-utils.h"
-#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
-#include "src/compiler-dispatcher/compiler-dispatcher-tracer.h"
-#include "src/compiler-dispatcher/unoptimized-compile-job.h"
#include "src/compiler.h"
#include "src/flags.h"
#include "src/handles.h"
@@ -88,9 +85,11 @@ class CompilerDispatcherTest : public TestWithNativeContext {
outer_parse_info->zone(), script_scope, FUNCTION_SCOPE);
function_scope->set_start_position(shared->StartPosition());
function_scope->set_end_position(shared->EndPosition());
+ std::vector<void*> pointer_buffer;
+ ScopedPtrList<Statement> statements(&pointer_buffer);
const FunctionLiteral* function_literal =
ast_node_factory.NewFunctionLiteral(
- function_name, function_scope, nullptr, -1, -1, -1,
+ function_name, function_scope, statements, -1, -1, -1,
FunctionLiteral::kNoDuplicateParameters,
FunctionLiteral::kAnonymousExpression,
FunctionLiteral::kShouldEagerCompile, shared->StartPosition(), true,
@@ -115,7 +114,7 @@ class MockPlatform : public v8::Platform {
sem_(0),
tracing_controller_(V8::GetCurrentPlatform()->GetTracingController()) {}
~MockPlatform() override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
EXPECT_TRUE(foreground_tasks_.empty());
EXPECT_TRUE(worker_tasks_.empty());
EXPECT_TRUE(idle_task_ == nullptr);
@@ -129,7 +128,7 @@ class MockPlatform : public v8::Platform {
}
void CallOnWorkerThread(std::unique_ptr<Task> task) override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
worker_tasks_.push_back(std::move(task));
}
@@ -139,7 +138,7 @@ class MockPlatform : public v8::Platform {
}
void CallOnForegroundThread(v8::Isolate* isolate, Task* task) override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
foreground_tasks_.push_back(std::unique_ptr<Task>(task));
}
@@ -150,7 +149,7 @@ class MockPlatform : public v8::Platform {
void CallIdleOnForegroundThread(v8::Isolate* isolate,
IdleTask* task) override {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
ASSERT_TRUE(idle_task_ == nullptr);
idle_task_ = task;
}
@@ -174,7 +173,7 @@ class MockPlatform : public v8::Platform {
time_step_ = time_step;
IdleTask* task;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
task = idle_task_;
ASSERT_TRUE(idle_task_ != nullptr);
idle_task_ = nullptr;
@@ -184,24 +183,24 @@ class MockPlatform : public v8::Platform {
}
bool IdleTaskPending() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
return idle_task_;
}
bool WorkerTasksPending() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
return !worker_tasks_.empty();
}
bool ForegroundTasksPending() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
return !foreground_tasks_.empty();
}
void RunWorkerTasksAndBlock(Platform* platform) {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(worker_tasks_);
}
platform->CallOnWorkerThread(
@@ -212,7 +211,7 @@ class MockPlatform : public v8::Platform {
void RunWorkerTasks(Platform* platform) {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(worker_tasks_);
}
platform->CallOnWorkerThread(
@@ -222,7 +221,7 @@ class MockPlatform : public v8::Platform {
void RunForegroundTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(foreground_tasks_);
}
for (auto& task : tasks) {
@@ -235,7 +234,7 @@ class MockPlatform : public v8::Platform {
void ClearWorkerTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(worker_tasks_);
}
}
@@ -243,13 +242,13 @@ class MockPlatform : public v8::Platform {
void ClearForegroundTasks() {
std::vector<std::unique_ptr<Task>> tasks;
{
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
tasks.swap(foreground_tasks_);
}
}
void ClearIdleTask() {
- base::LockGuard<base::Mutex> lock(&mutex_);
+ base::MutexGuard lock(&mutex_);
ASSERT_TRUE(idle_task_ != nullptr);
delete idle_task_;
idle_task_ = nullptr;
@@ -286,7 +285,7 @@ class MockPlatform : public v8::Platform {
: platform_(platform) {}
void PostTask(std::unique_ptr<v8::Task> task) override {
- base::LockGuard<base::Mutex> lock(&platform_->mutex_);
+ base::MutexGuard lock(&platform_->mutex_);
platform_->foreground_tasks_.push_back(std::move(task));
}
@@ -297,7 +296,7 @@ class MockPlatform : public v8::Platform {
void PostIdleTask(std::unique_ptr<IdleTask> task) override {
DCHECK(IdleTasksEnabled());
- base::LockGuard<base::Mutex> lock(&platform_->mutex_);
+ base::MutexGuard lock(&platform_->mutex_);
ASSERT_TRUE(platform_->idle_task_ == nullptr);
platform_->idle_task_ = task.release();
}
@@ -330,6 +329,7 @@ class MockPlatform : public v8::Platform {
TEST_F(CompilerDispatcherTest, Construct) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, IsEnqueued) {
@@ -352,12 +352,13 @@ TEST_F(CompilerDispatcherTest, IsEnqueued) {
ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- dispatcher.AbortAll(BlockingBehavior::kBlock);
+ dispatcher.AbortAll();
ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
- ASSERT_TRUE(platform.IdleTaskPending());
+
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_TRUE(platform.WorkerTasksPending());
platform.ClearWorkerTasks();
- platform.ClearIdleTask();
}
TEST_F(CompilerDispatcherTest, FinishNow) {
@@ -377,12 +378,13 @@ TEST_F(CompilerDispatcherTest, FinishNow) {
ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
- ASSERT_TRUE(platform.IdleTaskPending());
+
platform.ClearWorkerTasks();
- platform.ClearIdleTask();
+ ASSERT_FALSE(platform.IdleTaskPending());
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, IdleTask) {
+TEST_F(CompilerDispatcherTest, CompileAndFinalize) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -393,11 +395,10 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
base::Optional<CompilerDispatcher::JobId> job_id =
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_TRUE(platform.WorkerTasksPending());
- // Since time doesn't progress on the MockPlatform, this is enough idle time
- // to finish compiling the function.
- platform.RunIdleTask(1000.0, 0.0);
+ // Run compile steps.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
// Since we haven't yet registered the SFI for the job, it should still be
// enqueued and waiting.
@@ -405,7 +406,7 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
- // Register SFI, which should schedule another idle task to complete the
+ // Register SFI, which should schedule another idle task to finalize the
// compilation.
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
ASSERT_TRUE(platform.IdleTaskPending());
@@ -413,10 +414,12 @@ TEST_F(CompilerDispatcherTest, IdleTask) {
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ ASSERT_FALSE(platform.IdleTaskPending());
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
+TEST_F(CompilerDispatcherTest, IdleTaskNoIdleTime) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -429,25 +432,24 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
- ASSERT_TRUE(platform.IdleTaskPending());
+ // Run compile steps.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
- // The job should be scheduled for the main thread.
+ // Job should be ready to finalize.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE(platform.IdleTaskPending());
- // Only grant a little idle time and have time advance beyond it in one step.
- platform.RunIdleTask(2.0, 1.0);
+ // Grant no idle time and have time advance beyond it in one step.
+ platform.RunIdleTask(0.0, 1.0);
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_TRUE(platform.IdleTaskPending());
- // The job should be still scheduled for the main thread, but ready for
- // finalization.
+ // Job should be ready to finalize.
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
@@ -455,7 +457,58 @@ TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_TRUE(shared->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
+}
+
+TEST_F(CompilerDispatcherTest, IdleTaskSmallIdleTime) {
+ MockPlatform platform;
+ CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
+
+ Handle<SharedFunctionInfo> shared_1 =
+ test::CreateSharedFunctionInfo(i_isolate(), nullptr);
+ ASSERT_FALSE(shared_1->is_compiled());
+ Handle<SharedFunctionInfo> shared_2 =
+ test::CreateSharedFunctionInfo(i_isolate(), nullptr);
+ ASSERT_FALSE(shared_2->is_compiled());
+
+ base::Optional<CompilerDispatcher::JobId> job_id_1 =
+ EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_1);
+ base::Optional<CompilerDispatcher::JobId> job_id_2 =
+ EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_2);
+
+ dispatcher.RegisterSharedFunctionInfo(*job_id_1, *shared_1);
+ dispatcher.RegisterSharedFunctionInfo(*job_id_2, *shared_2);
+
+ // Run compile steps.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
+
+ // Both jobs should be ready to finalize.
+ ASSERT_EQ(dispatcher.jobs_.size(), 2u);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE((++dispatcher.jobs_.begin())->second->has_run);
+ ASSERT_TRUE(platform.IdleTaskPending());
+
+ // Grant a small anount of idle time and have time advance beyond it in one
+ // step.
+ platform.RunIdleTask(2.0, 1.0);
+
+ // Only one of the jobs should be finalized.
+ ASSERT_EQ(dispatcher.jobs_.size(), 1u);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_NE(dispatcher.IsEnqueued(shared_1), dispatcher.IsEnqueued(shared_2));
+ ASSERT_NE(shared_1->is_compiled(), shared_2->is_compiled());
+ ASSERT_TRUE(platform.IdleTaskPending());
+
+ // Now grant a lot of idle time and freeze time.
+ platform.RunIdleTask(1000.0, 0.0);
+
+ ASSERT_FALSE(dispatcher.IsEnqueued(shared_1) ||
+ dispatcher.IsEnqueued(shared_2));
+ ASSERT_TRUE(shared_1->is_compiled() && shared_2->is_compiled());
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, IdleTaskException) {
@@ -478,49 +531,15 @@ TEST_F(CompilerDispatcherTest, IdleTaskException) {
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
- // Since time doesn't progress on the MockPlatform, this is enough idle time
- // to finish compiling the function.
+ // Run compile steps and finalize.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
platform.RunIdleTask(1000.0, 0.0);
ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_FALSE(i_isolate()->has_pending_exception());
platform.ClearWorkerTasks();
-}
-
-TEST_F(CompilerDispatcherTest, CompileOnBackgroundThread) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared->is_compiled());
-
- base::Optional<CompilerDispatcher::JobId> job_id =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
-
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- ASSERT_FALSE(shared->is_compiled());
- ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(platform.WorkerTasksPending());
-
- platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
-
- ASSERT_TRUE(platform.IdleTaskPending());
- ASSERT_FALSE(platform.WorkerTasksPending());
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- dispatcher.jobs_.begin()->second->status());
-
- // Now grant a lot of idle time and freeze time.
- platform.RunIdleTask(1000.0, 0.0);
-
- ASSERT_FALSE(dispatcher.IsEnqueued(shared));
- ASSERT_TRUE(shared->is_compiled());
- ASSERT_FALSE(platform.IdleTaskPending());
- ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
@@ -536,14 +555,12 @@ TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(platform.WorkerTasksPending());
// This does not block, but races with the FinishNow() call below.
@@ -555,6 +572,7 @@ TEST_F(CompilerDispatcherTest, FinishNowWithWorkerTask) {
ASSERT_TRUE(shared->is_compiled());
if (platform.IdleTaskPending()) platform.ClearIdleTask();
ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, IdleTaskMultipleJobs) {
@@ -579,15 +597,17 @@ TEST_F(CompilerDispatcherTest, IdleTaskMultipleJobs) {
ASSERT_TRUE(dispatcher.IsEnqueued(shared_1));
ASSERT_TRUE(dispatcher.IsEnqueued(shared_2));
- // Since time doesn't progress on the MockPlatform, this is enough idle time
- // to finish compiling the function.
+ // Run compile steps and finalize.
+ platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
platform.RunIdleTask(1000.0, 0.0);
ASSERT_FALSE(dispatcher.IsEnqueued(shared_1));
ASSERT_FALSE(dispatcher.IsEnqueued(shared_2));
ASSERT_TRUE(shared_1->is_compiled());
ASSERT_TRUE(shared_2->is_compiled());
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, FinishNowException) {
@@ -617,11 +637,12 @@ TEST_F(CompilerDispatcherTest, FinishNowException) {
ASSERT_TRUE(i_isolate()->has_pending_exception());
i_isolate()->clear_pending_exception();
- platform.ClearIdleTask();
+ ASSERT_FALSE(platform.IdleTaskPending());
platform.ClearWorkerTasks();
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask) {
+TEST_F(CompilerDispatcherTest, AbortJobNotStarted) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -631,107 +652,27 @@ TEST_F(CompilerDispatcherTest, AsyncAbortAllPendingWorkerTask) {
base::Optional<CompilerDispatcher::JobId> job_id =
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- ASSERT_FALSE(shared->is_compiled());
- ASSERT_TRUE(platform.WorkerTasksPending());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
- // The background task hasn't yet started, so we can just cancel it.
- dispatcher.AbortAll(BlockingBehavior::kDontBlock);
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- ASSERT_FALSE(dispatcher.IsEnqueued(shared));
+ ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(shared->is_compiled());
-
- platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
-
- if (platform.IdleTaskPending()) platform.ClearIdleTask();
- ASSERT_FALSE(platform.WorkerTasksPending());
- ASSERT_FALSE(platform.ForegroundTasksPending());
-}
-
-TEST_F(CompilerDispatcherTest, AsyncAbortAllRunningWorkerTask) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared_1 =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared_1->is_compiled());
- Handle<SharedFunctionInfo> shared_2 =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared_2->is_compiled());
-
- base::Optional<CompilerDispatcher::JobId> job_id_1 =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_1);
- dispatcher.RegisterSharedFunctionInfo(*job_id_1, *shared_1);
-
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(dispatcher.IsEnqueued(shared_1));
- ASSERT_FALSE(shared_1->is_compiled());
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(platform.WorkerTasksPending());
- // Kick off background tasks and freeze them.
- dispatcher.block_for_testing_.SetValue(true);
- platform.RunWorkerTasks(V8::GetCurrentPlatform());
+ dispatcher.AbortJob(*job_id);
- // Busy loop until the background task started running.
- while (dispatcher.block_for_testing_.Value()) {
- }
- dispatcher.AbortAll(BlockingBehavior::kDontBlock);
- ASSERT_TRUE(platform.ForegroundTasksPending());
-
- // We can't schedule new tasks while we're aborting.
- base::Optional<CompilerDispatcher::JobId> job_id_2 =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_2);
- ASSERT_FALSE(job_id_2);
-
- // Run the first AbortTask. Since the background job is still pending, it
- // can't do anything.
- platform.RunForegroundTasks();
- {
- base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_TRUE(dispatcher.abort_);
- }
-
- // Release background task.
- dispatcher.semaphore_for_testing_.Signal();
-
- // Busy loop until the background task scheduled another AbortTask task.
- while (!platform.ForegroundTasksPending()) {
- }
-
- platform.RunForegroundTasks();
- ASSERT_TRUE(dispatcher.jobs_.empty());
- {
- base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_FALSE(dispatcher.abort_);
- }
-
- ASSERT_TRUE(platform.IdleTaskPending());
- platform.RunIdleTask(5.0, 1.0);
- ASSERT_FALSE(platform.WorkerTasksPending());
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- // Now it's possible to enqueue new functions again.
- job_id_2 = EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared_2);
- ASSERT_TRUE(job_id_2);
- ASSERT_TRUE(platform.IdleTaskPending());
- ASSERT_TRUE(platform.WorkerTasksPending());
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- dispatcher.AbortAll(BlockingBehavior::kBlock);
+ // Aborting removes the job from the queue.
+ ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
+ ASSERT_FALSE(shared->is_compiled());
+ ASSERT_FALSE(platform.IdleTaskPending());
platform.ClearWorkerTasks();
- platform.ClearIdleTask();
+ dispatcher.AbortAll();
}
-TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
+TEST_F(CompilerDispatcherTest, AbortJobAlreadyStarted) {
MockPlatform platform;
CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
@@ -741,154 +682,59 @@ TEST_F(CompilerDispatcherTest, FinishNowDuringAbortAll) {
base::Optional<CompilerDispatcher::JobId> job_id =
EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
+ ASSERT_EQ(dispatcher.jobs_.size(), 1u);
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
+
+ ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(shared->is_compiled());
ASSERT_EQ(dispatcher.jobs_.size(), 1u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
ASSERT_TRUE(platform.WorkerTasksPending());
- // Kick off background tasks and freeze them.
- dispatcher.block_for_testing_.SetValue(true);
- platform.RunWorkerTasks(V8::GetCurrentPlatform());
-
- // Busy loop until the background task started running.
- while (dispatcher.block_for_testing_.Value()) {
- }
- dispatcher.AbortAll(BlockingBehavior::kDontBlock);
- ASSERT_TRUE(platform.ForegroundTasksPending());
-
- // Run the first AbortTask. Since the background job is still pending, it
- // can't do anything.
- platform.RunForegroundTasks();
+ // Have dispatcher block on the background thread when running the job.
{
base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_TRUE(dispatcher.abort_);
+ dispatcher.block_for_testing_.SetValue(true);
}
- // Run the idle task, which should have already been canceled and won't do
- // anything.
- ASSERT_TRUE(platform.IdleTaskPending());
- platform.RunIdleTask(5.0, 1.0);
-
- // While the background thread holds on to a job, it is still enqueued.
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
-
- // Release background task.
- dispatcher.semaphore_for_testing_.Signal();
-
- // Force the compilation to finish, even while aborting.
- ASSERT_TRUE(dispatcher.FinishNow(shared));
- ASSERT_TRUE(dispatcher.jobs_.empty());
-
- // Busy wait for the background task to finish.
- for (;;) {
- base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- if (dispatcher.num_worker_tasks_ == 0) {
- break;
- }
+ // Start background thread and wait until it is about to run the job.
+ platform.RunWorkerTasks(V8::GetCurrentPlatform());
+ while (dispatcher.block_for_testing_.Value()) {
}
- ASSERT_TRUE(platform.ForegroundTasksPending());
- ASSERT_FALSE(platform.IdleTaskPending());
- ASSERT_FALSE(platform.WorkerTasksPending());
+ // Now abort while dispatcher is in the middle of running the job.
+ dispatcher.AbortJob(*job_id);
- platform.RunForegroundTasks();
+ // Unblock background thread, and wait for job to complete.
{
base::LockGuard<base::Mutex> lock(&dispatcher.mutex_);
- ASSERT_FALSE(dispatcher.abort_);
+ dispatcher.main_thread_blocking_on_job_ =
+ dispatcher.jobs_.begin()->second.get();
+ dispatcher.semaphore_for_testing_.Signal();
+ while (dispatcher.main_thread_blocking_on_job_ != nullptr) {
+ dispatcher.main_thread_blocking_signal_.Wait(&dispatcher.mutex_);
+ }
}
-}
-TEST_F(CompilerDispatcherTest, MemoryPressure) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
+ // Job should have finished running and then been aborted.
+ ASSERT_TRUE(dispatcher.IsEnqueued(*job_id));
ASSERT_FALSE(shared->is_compiled());
+ ASSERT_EQ(dispatcher.jobs_.size(), 1u);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->aborted);
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ ASSERT_TRUE(platform.IdleTaskPending());
- // Can't enqueue tasks under memory pressure.
- dispatcher.MemoryPressureNotification(v8::MemoryPressureLevel::kCritical,
- true);
- base::Optional<CompilerDispatcher::JobId> job_id =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- ASSERT_FALSE(job_id);
-
- dispatcher.MemoryPressureNotification(v8::MemoryPressureLevel::kNone, true);
-
- job_id = EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- ASSERT_TRUE(job_id);
+ // Runt the pending idle task
+ platform.RunIdleTask(1000.0, 0.0);
- // Memory pressure cancels current jobs.
- dispatcher.MemoryPressureNotification(v8::MemoryPressureLevel::kCritical,
- true);
+ // Aborting removes the SFI from the queue.
ASSERT_FALSE(dispatcher.IsEnqueued(*job_id));
- platform.ClearIdleTask();
- platform.ClearWorkerTasks();
-}
-
-namespace {
-
-class PressureNotificationTask : public CancelableTask {
- public:
- PressureNotificationTask(Isolate* isolate, CompilerDispatcher* dispatcher,
- base::Semaphore* sem)
- : CancelableTask(isolate), dispatcher_(dispatcher), sem_(sem) {}
- ~PressureNotificationTask() override = default;
-
- void RunInternal() override {
- dispatcher_->MemoryPressureNotification(v8::MemoryPressureLevel::kCritical,
- false);
- sem_->Signal();
- }
-
- private:
- CompilerDispatcher* dispatcher_;
- base::Semaphore* sem_;
-
- DISALLOW_COPY_AND_ASSIGN(PressureNotificationTask);
-};
-
-} // namespace
-
-TEST_F(CompilerDispatcherTest, MemoryPressureFromBackground) {
- MockPlatform platform;
- CompilerDispatcher dispatcher(i_isolate(), &platform, FLAG_stack_size);
-
- Handle<SharedFunctionInfo> shared =
- test::CreateSharedFunctionInfo(i_isolate(), nullptr);
- ASSERT_FALSE(shared->is_compiled());
-
- base::Optional<CompilerDispatcher::JobId> job_id =
- EnqueueUnoptimizedCompileJob(&dispatcher, i_isolate(), shared);
- dispatcher.RegisterSharedFunctionInfo(*job_id, *shared);
-
- base::Semaphore sem(0);
- V8::GetCurrentPlatform()->CallOnWorkerThread(
- base::make_unique<PressureNotificationTask>(i_isolate(), &dispatcher,
- &sem));
-
- sem.Wait();
-
- // A memory pressure task is pending, and running it will cancel the job.
- ASSERT_TRUE(platform.ForegroundTasksPending());
- ASSERT_TRUE(dispatcher.IsEnqueued(shared));
- platform.RunForegroundTasks();
- ASSERT_FALSE(dispatcher.IsEnqueued(shared));
ASSERT_FALSE(shared->is_compiled());
-
- // Since the AbortAll() call is made from a task, AbortAll thinks that there
- // is at least one task running, and fires of an AbortTask to be safe.
- ASSERT_TRUE(platform.ForegroundTasksPending());
- platform.RunForegroundTasks();
- ASSERT_FALSE(platform.ForegroundTasksPending());
-
- platform.ClearIdleTask();
- platform.ClearWorkerTasks();
+ ASSERT_FALSE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.WorkerTasksPending());
+ dispatcher.AbortAll();
}
TEST_F(CompilerDispatcherTest, CompileLazyFinishesDispatcherJob) {
@@ -972,16 +818,14 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
dispatcher.RegisterSharedFunctionInfo(*job_id_2, *shared_2);
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_EQ(UnoptimizedCompileJob::Status::kInitial,
- (++dispatcher.jobs_.begin())->second->status());
+ ASSERT_FALSE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_FALSE((++dispatcher.jobs_.begin())->second->has_run);
ASSERT_TRUE(dispatcher.IsEnqueued(shared_1));
ASSERT_TRUE(dispatcher.IsEnqueued(shared_2));
ASSERT_FALSE(shared_1->is_compiled());
ASSERT_FALSE(shared_2->is_compiled());
- ASSERT_TRUE(platform.IdleTaskPending());
+ ASSERT_FALSE(platform.IdleTaskPending());
ASSERT_TRUE(platform.WorkerTasksPending());
platform.RunWorkerTasksAndBlock(V8::GetCurrentPlatform());
@@ -989,10 +833,8 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_TRUE(platform.IdleTaskPending());
ASSERT_FALSE(platform.WorkerTasksPending());
ASSERT_EQ(dispatcher.jobs_.size(), 2u);
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- dispatcher.jobs_.begin()->second->status());
- ASSERT_EQ(UnoptimizedCompileJob::Status::kReadyToFinalize,
- (++dispatcher.jobs_.begin())->second->status());
+ ASSERT_TRUE(dispatcher.jobs_.begin()->second->has_run);
+ ASSERT_TRUE((++dispatcher.jobs_.begin())->second->has_run);
// Now grant a lot of idle time and freeze time.
platform.RunIdleTask(1000.0, 0.0);
@@ -1002,6 +844,7 @@ TEST_F(CompilerDispatcherTest, CompileMultipleOnBackgroundThread) {
ASSERT_TRUE(shared_1->is_compiled());
ASSERT_TRUE(shared_2->is_compiled());
ASSERT_FALSE(platform.IdleTaskPending());
+ dispatcher.AbortAll();
}
} // namespace internal
diff --git a/deps/v8/test/unittests/compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc b/deps/v8/test/unittests/compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc
index b796e457d4..d9e1731dc1 100644
--- a/deps/v8/test/unittests/compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc
+++ b/deps/v8/test/unittests/compiler-dispatcher/optimizing-compile-dispatcher-unittest.cc
@@ -73,6 +73,9 @@ TEST_F(OptimizingCompileDispatcherTest, Construct) {
TEST_F(OptimizingCompileDispatcherTest, NonBlockingFlush) {
Handle<JSFunction> fun =
RunJS<JSFunction>("function f() { function g() {}; return g;}; f();");
+ IsCompiledScope is_compiled_scope;
+ ASSERT_TRUE(
+ Compiler::Compile(fun, Compiler::CLEAR_EXCEPTION, &is_compiled_scope));
BlockingCompilationJob* job = new BlockingCompilationJob(i_isolate(), fun);
OptimizingCompileDispatcher dispatcher(i_isolate());
diff --git a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
index 011cc67c81..77a1587f0b 100644
--- a/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm/instruction-selector-arm-unittest.cc
@@ -4,7 +4,7 @@
#include <limits>
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/objects-inl.h"
diff --git a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
index aa54abe320..bca04a5cf3 100644
--- a/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/arm64/instruction-selector-arm64-unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "src/objects-inl.h"
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
namespace v8 {
namespace internal {
@@ -1288,7 +1288,7 @@ INSTANTIATE_TEST_CASE_P(InstructionSelectorTest,
TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
TRACED_FORRANGE(int, bit, 0, 63) {
- uint64_t mask = 1L << bit;
+ uint64_t mask = 1LL << bit;
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
RawMachineLabel a, b;
m.Branch(m.Word64And(m.Parameter(0), m.Int64Constant(mask)), &a, &b);
@@ -1309,7 +1309,7 @@ TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnRight) {
TEST_F(InstructionSelectorTest, Word64AndBranchWithOneBitMaskOnLeft) {
TRACED_FORRANGE(int, bit, 0, 63) {
- uint64_t mask = 1L << bit;
+ uint64_t mask = 1LL << bit;
StreamBuilder m(this, MachineType::Int64(), MachineType::Int64());
RawMachineLabel a, b;
m.Branch(m.Word64And(m.Int64Constant(mask), m.Parameter(0)), &a, &b);
@@ -4542,9 +4542,8 @@ TEST_F(InstructionSelectorTest, ExternalReferenceLoad1) {
const int64_t kOffsets[] = {0, 1, 4, INT32_MIN, INT32_MAX};
TRACED_FOREACH(int64_t, offset, kOffsets) {
StreamBuilder m(this, MachineType::Int64());
- ExternalReference reference = bit_cast<ExternalReference>(
- reinterpret_cast<intptr_t>(isolate()->heap()->roots_array_start()) +
- offset + kRootRegisterBias);
+ ExternalReference reference =
+ bit_cast<ExternalReference>(isolate()->isolate_root() + offset);
Node* const value =
m.Load(MachineType::Int64(), m.ExternalConstant(reference));
m.Return(value);
@@ -4564,9 +4563,8 @@ TEST_F(InstructionSelectorTest, ExternalReferenceLoad2) {
// Offset too large, we cannot use kMode_Root.
StreamBuilder m(this, MachineType::Int64());
int64_t offset = 0x100000000;
- ExternalReference reference = bit_cast<ExternalReference>(
- reinterpret_cast<intptr_t>(isolate()->heap()->roots_array_start()) +
- offset + kRootRegisterBias);
+ ExternalReference reference =
+ bit_cast<ExternalReference>(isolate()->isolate_root() + offset);
Node* const value =
m.Load(MachineType::Int64(), m.ExternalConstant(reference));
m.Return(value);
diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc
index 2d59393f9d..59d5dccd06 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.cc
+++ b/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/code-factory.h"
#include "src/compiler/compiler-source-position-table.h"
@@ -16,13 +16,10 @@ namespace v8 {
namespace internal {
namespace compiler {
-
InstructionSelectorTest::InstructionSelectorTest() : rng_(FLAG_random_seed) {}
-
InstructionSelectorTest::~InstructionSelectorTest() = default;
-
InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
InstructionSelector::Features features,
InstructionSelectorTest::StreamBuilderMode mode,
@@ -50,11 +47,9 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
PoisoningMitigationLevel::kPoisonAll);
selector.SelectInstructions();
if (FLAG_trace_turbo) {
- PrintableInstructionSequence printable = {RegisterConfiguration::Default(),
- &sequence};
StdoutStream{} << "=== Code sequence after instruction selection ==="
<< std::endl
- << printable;
+ << sequence;
}
Stream s;
s.virtual_registers_ = selector.GetVirtualRegistersForTesting();
@@ -115,14 +110,12 @@ InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
return s;
}
-
int InstructionSelectorTest::Stream::ToVreg(const Node* node) const {
VirtualRegisters::const_iterator i = virtual_registers_.find(node->id());
CHECK(i != virtual_registers_.end());
return i->second;
}
-
bool InstructionSelectorTest::Stream::IsFixed(const InstructionOperand* operand,
Register reg) const {
if (!operand->IsUnallocated()) return false;
@@ -131,7 +124,6 @@ bool InstructionSelectorTest::Stream::IsFixed(const InstructionOperand* operand,
return unallocated->fixed_register_index() == reg.code();
}
-
bool InstructionSelectorTest::Stream::IsSameAsFirst(
const InstructionOperand* operand) const {
if (!operand->IsUnallocated()) return false;
@@ -139,7 +131,6 @@ bool InstructionSelectorTest::Stream::IsSameAsFirst(
return unallocated->HasSameAsInputPolicy();
}
-
bool InstructionSelectorTest::Stream::IsUsedAtStart(
const InstructionOperand* operand) const {
if (!operand->IsUnallocated()) return false;
@@ -147,7 +138,6 @@ bool InstructionSelectorTest::Stream::IsUsedAtStart(
return unallocated->IsUsedAtStart();
}
-
const FrameStateFunctionInfo*
InstructionSelectorTest::StreamBuilder::GetFrameStateFunctionInfo(
int parameter_count, int local_count) {
@@ -156,11 +146,9 @@ InstructionSelectorTest::StreamBuilder::GetFrameStateFunctionInfo(
Handle<SharedFunctionInfo>());
}
-
// -----------------------------------------------------------------------------
// Return.
-
TARGET_TEST_F(InstructionSelectorTest, ReturnFloat32Constant) {
const float kValue = 4.2f;
StreamBuilder m(this, MachineType::Float32());
@@ -174,7 +162,6 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnFloat32Constant) {
EXPECT_EQ(2U, s[1]->InputCount());
}
-
TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32());
m.Return(m.Parameter(0));
@@ -186,7 +173,6 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnParameter) {
EXPECT_EQ(2U, s[1]->InputCount());
}
-
TARGET_TEST_F(InstructionSelectorTest, ReturnZero) {
StreamBuilder m(this, MachineType::Int32());
m.Return(m.Int32Constant(0));
@@ -200,7 +186,6 @@ TARGET_TEST_F(InstructionSelectorTest, ReturnZero) {
EXPECT_EQ(2U, s[1]->InputCount());
}
-
// -----------------------------------------------------------------------------
// Conversions.
@@ -216,11 +201,9 @@ TARGET_TEST_F(InstructionSelectorTest, TruncateFloat64ToWord32WithParameter) {
EXPECT_EQ(kArchRet, s[2]->arch_opcode());
}
-
// -----------------------------------------------------------------------------
// Parameters.
-
TARGET_TEST_F(InstructionSelectorTest, DoubleParameter) {
StreamBuilder m(this, MachineType::Float64(), MachineType::Float64());
Node* param = m.Parameter(0);
@@ -229,7 +212,6 @@ TARGET_TEST_F(InstructionSelectorTest, DoubleParameter) {
EXPECT_TRUE(s.IsDouble(param));
}
-
TARGET_TEST_F(InstructionSelectorTest, ReferenceParameter) {
StreamBuilder m(this, MachineType::AnyTagged(), MachineType::AnyTagged());
Node* param = m.Parameter(0);
@@ -238,11 +220,9 @@ TARGET_TEST_F(InstructionSelectorTest, ReferenceParameter) {
EXPECT_TRUE(s.IsReference(param));
}
-
// -----------------------------------------------------------------------------
// FinishRegion.
-
TARGET_TEST_F(InstructionSelectorTest, FinishRegion) {
StreamBuilder m(this, MachineType::AnyTagged(), MachineType::AnyTagged());
Node* param = m.Parameter(0);
@@ -260,15 +240,12 @@ TARGET_TEST_F(InstructionSelectorTest, FinishRegion) {
EXPECT_TRUE(s.IsReference(finish));
}
-
// -----------------------------------------------------------------------------
// Phi.
-
typedef InstructionSelectorTestWithParam<MachineType>
InstructionSelectorPhiTest;
-
TARGET_TEST_P(InstructionSelectorPhiTest, Doubleness) {
const MachineType type = GetParam();
StreamBuilder m(this, type, type, type);
@@ -288,7 +265,6 @@ TARGET_TEST_P(InstructionSelectorPhiTest, Doubleness) {
EXPECT_EQ(s.IsDouble(phi), s.IsDouble(param1));
}
-
TARGET_TEST_P(InstructionSelectorPhiTest, Referenceness) {
const MachineType type = GetParam();
StreamBuilder m(this, type, type, type);
@@ -308,7 +284,6 @@ TARGET_TEST_P(InstructionSelectorPhiTest, Referenceness) {
EXPECT_EQ(s.IsReference(phi), s.IsReference(param1));
}
-
INSTANTIATE_TEST_CASE_P(
InstructionSelectorTest, InstructionSelectorPhiTest,
::testing::Values(MachineType::Float64(), MachineType::Int8(),
@@ -318,11 +293,9 @@ INSTANTIATE_TEST_CASE_P(
MachineType::Uint64(), MachineType::Pointer(),
MachineType::AnyTagged()));
-
// -----------------------------------------------------------------------------
// ValueEffect.
-
TARGET_TEST_F(InstructionSelectorTest, ValueEffect) {
StreamBuilder m1(this, MachineType::Int32(), MachineType::Pointer());
Node* p1 = m1.Parameter(0);
@@ -346,11 +319,9 @@ TARGET_TEST_F(InstructionSelectorTest, ValueEffect) {
}
}
-
// -----------------------------------------------------------------------------
// Calls with deoptimization.
-
TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
StreamBuilder m(this, MachineType::AnyTagged(), MachineType::AnyTagged(),
MachineType::AnyTagged(), MachineType::AnyTagged());
@@ -405,7 +376,6 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) {
// TODO(jarin) Check deoptimization table.
}
-
TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeopt) {
StreamBuilder m(this, MachineType::AnyTagged(), MachineType::AnyTagged(),
MachineType::AnyTagged(), MachineType::AnyTagged());
@@ -498,7 +468,6 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeopt) {
EXPECT_EQ(index, s.size());
}
-
TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) {
StreamBuilder m(this, MachineType::AnyTagged(), MachineType::AnyTagged(),
MachineType::AnyTagged(), MachineType::AnyTagged());
diff --git a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h b/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.h
index 19f85ff1ff..3c4374101c 100644
--- a/deps/v8/test/unittests/compiler/instruction-selector-unittest.h
+++ b/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.h
@@ -9,7 +9,7 @@
#include <set>
#include "src/base/utils/random-number-generator.h"
-#include "src/compiler/instruction-selector.h"
+#include "src/compiler/backend/instruction-selector.h"
#include "src/compiler/raw-machine-assembler.h"
#include "src/macro-assembler.h"
#include "test/unittests/test-utils.h"
@@ -18,8 +18,7 @@ namespace v8 {
namespace internal {
namespace compiler {
-class InstructionSelectorTest : public TestWithContext,
- public TestWithIsolateAndZone {
+class InstructionSelectorTest : public TestWithNativeContextAndZone {
public:
InstructionSelectorTest();
~InstructionSelectorTest() override;
@@ -288,7 +287,6 @@ class InstructionSelectorTest : public TestWithContext,
base::RandomNumberGenerator rng_;
};
-
template <typename T>
class InstructionSelectorTestWithParam
: public InstructionSelectorTest,
diff --git a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc b/deps/v8/test/unittests/compiler/backend/instruction-sequence-unittest.cc
index 2dd910aafb..f5fe72d5be 100644
--- a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.cc
+++ b/deps/v8/test/unittests/compiler/backend/instruction-sequence-unittest.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "test/unittests/compiler/backend/instruction-sequence-unittest.h"
#include "src/base/utils/random-number-generator.h"
#include "src/compiler/pipeline.h"
-#include "test/unittests/compiler/instruction-sequence-unittest.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -12,48 +12,29 @@ namespace v8 {
namespace internal {
namespace compiler {
-static const char*
- general_register_names_[RegisterConfiguration::kMaxGeneralRegisters];
-static const char*
- double_register_names_[RegisterConfiguration::kMaxFPRegisters];
-static char register_names_[10 * (RegisterConfiguration::kMaxGeneralRegisters +
- RegisterConfiguration::kMaxFPRegisters)];
-
namespace {
-static int allocatable_codes[InstructionSequenceTest::kDefaultNRegs] = {
- 0, 1, 2, 3, 4, 5, 6, 7};
-}
-
-static void InitializeRegisterNames() {
- char* loc = register_names_;
- for (int i = 0; i < RegisterConfiguration::kMaxGeneralRegisters; ++i) {
- general_register_names_[i] = loc;
- loc += base::OS::SNPrintF(loc, 100, "gp_%d", i);
- *loc++ = 0;
- }
- for (int i = 0; i < RegisterConfiguration::kMaxFPRegisters; ++i) {
- double_register_names_[i] = loc;
- loc += base::OS::SNPrintF(loc, 100, "fp_%d", i) + 1;
- *loc++ = 0;
- }
+constexpr int kMaxNumAllocatable =
+ Max(Register::kNumRegisters, DoubleRegister::kNumRegisters);
+static std::array<int, kMaxNumAllocatable> kAllocatableCodes =
+ base::make_array<kMaxNumAllocatable>(
+ [](size_t i) { return static_cast<int>(i); });
}
InstructionSequenceTest::InstructionSequenceTest()
: sequence_(nullptr),
- num_general_registers_(kDefaultNRegs),
- num_double_registers_(kDefaultNRegs),
+ num_general_registers_(Register::kNumRegisters),
+ num_double_registers_(DoubleRegister::kNumRegisters),
instruction_blocks_(zone()),
current_block_(nullptr),
- block_returns_(false) {
- InitializeRegisterNames();
-}
-
+ block_returns_(false) {}
void InstructionSequenceTest::SetNumRegs(int num_general_registers,
int num_double_registers) {
CHECK(!config_);
CHECK(instructions_.empty());
CHECK(instruction_blocks_.empty());
+ CHECK_GE(Register::kNumRegisters, num_general_registers);
+ CHECK_GE(DoubleRegister::kNumRegisters, num_double_registers);
num_general_registers_ = num_general_registers;
num_double_registers_ = num_double_registers;
}
@@ -89,18 +70,14 @@ const RegisterConfiguration* InstructionSequenceTest::config() {
if (!config_) {
config_.reset(new RegisterConfiguration(
num_general_registers_, num_double_registers_, num_general_registers_,
- num_double_registers_, allocatable_codes, allocatable_codes,
+ num_double_registers_, kAllocatableCodes.data(),
+ kAllocatableCodes.data(),
kSimpleFPAliasing ? RegisterConfiguration::OVERLAP
- : RegisterConfiguration::COMBINE,
- general_register_names_,
- double_register_names_, // float register names
- double_register_names_,
- double_register_names_)); // SIMD 128 register names
+ : RegisterConfiguration::COMBINE));
}
return config_.get();
}
-
InstructionSequence* InstructionSequenceTest::sequence() {
if (sequence_ == nullptr) {
sequence_ = new (zone())
@@ -111,7 +88,6 @@ InstructionSequence* InstructionSequenceTest::sequence() {
return sequence_;
}
-
void InstructionSequenceTest::StartLoop(int loop_blocks) {
CHECK_NULL(current_block_);
if (!loop_blocks_.empty()) {
@@ -121,7 +97,6 @@ void InstructionSequenceTest::StartLoop(int loop_blocks) {
loop_blocks_.push_back(loop_data);
}
-
void InstructionSequenceTest::EndLoop() {
CHECK_NULL(current_block_);
CHECK(!loop_blocks_.empty());
@@ -129,13 +104,11 @@ void InstructionSequenceTest::EndLoop() {
loop_blocks_.pop_back();
}
-
void InstructionSequenceTest::StartBlock(bool deferred) {
block_returns_ = false;
NewBlock(deferred);
}
-
Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
Instruction* result = nullptr;
if (block_returns_) {
@@ -168,12 +141,10 @@ Instruction* InstructionSequenceTest::EndBlock(BlockCompletion completion) {
return result;
}
-
InstructionSequenceTest::TestOperand InstructionSequenceTest::Imm(int32_t imm) {
return TestOperand(kImmediate, imm);
}
-
InstructionSequenceTest::VReg InstructionSequenceTest::Define(
TestOperand output_op) {
VReg vreg = NewReg(output_op);
@@ -188,7 +159,6 @@ Instruction* InstructionSequenceTest::Return(TestOperand input_op_0) {
return Emit(kArchRet, 0, nullptr, 1, inputs);
}
-
PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
VReg incoming_vreg_1,
VReg incoming_vreg_2,
@@ -208,7 +178,6 @@ PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
return phi;
}
-
PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
size_t input_count) {
auto phi = new (zone()) PhiInstruction(zone(), NewReg().value_, input_count);
@@ -217,14 +186,12 @@ PhiInstruction* InstructionSequenceTest::Phi(VReg incoming_vreg_0,
return phi;
}
-
void InstructionSequenceTest::SetInput(PhiInstruction* phi, size_t input,
VReg vreg) {
CHECK_NE(kNoValue, vreg.value_);
phi->SetInput(input, vreg.value_);
}
-
InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant(
int32_t imm) {
VReg vreg = NewReg();
@@ -234,10 +201,8 @@ InstructionSequenceTest::VReg InstructionSequenceTest::DefineConstant(
return vreg;
}
-
Instruction* InstructionSequenceTest::EmitNop() { return Emit(kArchNop); }
-
static size_t CountInputs(size_t size,
InstructionSequenceTest::TestOperand* inputs) {
size_t i = 0;
@@ -247,14 +212,12 @@ static size_t CountInputs(size_t size,
return i;
}
-
Instruction* InstructionSequenceTest::EmitI(size_t input_size,
TestOperand* inputs) {
InstructionOperand* mapped_inputs = ConvertInputs(input_size, inputs);
return Emit(kArchNop, 0, nullptr, input_size, mapped_inputs);
}
-
Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0,
TestOperand input_op_1,
TestOperand input_op_2,
@@ -263,7 +226,6 @@ Instruction* InstructionSequenceTest::EmitI(TestOperand input_op_0,
return EmitI(CountInputs(arraysize(inputs), inputs), inputs);
}
-
InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
TestOperand output_op, size_t input_size, TestOperand* inputs) {
VReg output_vreg = NewReg(output_op);
@@ -273,7 +235,6 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
return output_vreg;
}
-
InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
TestOperand input_op_2, TestOperand input_op_3) {
@@ -281,7 +242,6 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitOI(
return EmitOI(output_op, CountInputs(arraysize(inputs), inputs), inputs);
}
-
InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
TestOperand output_op_0, TestOperand output_op_1, size_t input_size,
TestOperand* inputs) {
@@ -295,7 +255,6 @@ InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
return output_vregs;
}
-
InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
TestOperand output_op_0, TestOperand output_op_1, TestOperand input_op_0,
TestOperand input_op_1, TestOperand input_op_2, TestOperand input_op_3) {
@@ -304,7 +263,6 @@ InstructionSequenceTest::VRegPair InstructionSequenceTest::EmitOOI(
CountInputs(arraysize(inputs), inputs), inputs);
}
-
InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
TestOperand output_op, size_t input_size, TestOperand* inputs) {
VReg output_vreg = NewReg(output_op);
@@ -316,7 +274,6 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
return output_vreg;
}
-
InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
TestOperand output_op, TestOperand input_op_0, TestOperand input_op_1,
TestOperand input_op_2, TestOperand input_op_3) {
@@ -324,7 +281,6 @@ InstructionSequenceTest::VReg InstructionSequenceTest::EmitCall(
return EmitCall(output_op, CountInputs(arraysize(inputs), inputs), inputs);
}
-
Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) {
InstructionOperand inputs[4]{ConvertInputOp(input_op), ConvertInputOp(Imm()),
ConvertInputOp(Imm()), ConvertInputOp(Imm())};
@@ -334,20 +290,17 @@ Instruction* InstructionSequenceTest::EmitBranch(TestOperand input_op) {
return AddInstruction(instruction);
}
-
Instruction* InstructionSequenceTest::EmitFallThrough() {
auto instruction = NewInstruction(kArchNop, 0, nullptr);
return AddInstruction(instruction);
}
-
Instruction* InstructionSequenceTest::EmitJump() {
InstructionOperand inputs[1]{ConvertInputOp(Imm())};
auto instruction = NewInstruction(kArchJmp, 0, nullptr, 1, inputs);
return AddInstruction(instruction);
}
-
Instruction* InstructionSequenceTest::NewInstruction(
InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
@@ -357,32 +310,27 @@ Instruction* InstructionSequenceTest::NewInstruction(
inputs, temps_size, temps);
}
-
InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::ExtendedPolicy policy) {
return UnallocatedOperand(policy, op.vreg_.value_);
}
-
InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::ExtendedPolicy policy,
UnallocatedOperand::Lifetime lifetime) {
return UnallocatedOperand(policy, lifetime, op.vreg_.value_);
}
-
InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::ExtendedPolicy policy, int index) {
return UnallocatedOperand(policy, index, op.vreg_.value_);
}
-
InstructionOperand InstructionSequenceTest::Unallocated(
TestOperand op, UnallocatedOperand::BasicPolicy policy, int index) {
return UnallocatedOperand(policy, index, op.vreg_.value_);
}
-
InstructionOperand* InstructionSequenceTest::ConvertInputs(
size_t input_size, TestOperand* inputs) {
InstructionOperand* mapped_inputs =
@@ -393,7 +341,6 @@ InstructionOperand* InstructionSequenceTest::ConvertInputs(
return mapped_inputs;
}
-
InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
if (op.type_ == kImmediate) {
CHECK_EQ(op.vreg_.value_, kNoValue);
@@ -439,7 +386,6 @@ InstructionOperand InstructionSequenceTest::ConvertInputOp(TestOperand op) {
UNREACHABLE();
}
-
InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
TestOperand op) {
CHECK_EQ(op.vreg_.value_, kNoValue);
@@ -474,7 +420,6 @@ InstructionOperand InstructionSequenceTest::ConvertOutputOp(VReg vreg,
UNREACHABLE();
}
-
InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) {
CHECK_NULL(current_block_);
Rpo rpo = Rpo::FromInt(static_cast<int>(instruction_blocks_.size()));
@@ -504,7 +449,6 @@ InstructionBlock* InstructionSequenceTest::NewBlock(bool deferred) {
return instruction_block;
}
-
void InstructionSequenceTest::WireBlocks() {
CHECK(!current_block());
CHECK(instruction_blocks_.size() == completions_.size());
@@ -536,7 +480,6 @@ void InstructionSequenceTest::WireBlocks() {
}
}
-
void InstructionSequenceTest::WireBlock(size_t block_offset, int jump_offset) {
size_t target_block_offset = block_offset + static_cast<size_t>(jump_offset);
CHECK(block_offset < instruction_blocks_.size());
@@ -547,7 +490,6 @@ void InstructionSequenceTest::WireBlock(size_t block_offset, int jump_offset) {
target->predecessors().push_back(block->rpo_number());
}
-
Instruction* InstructionSequenceTest::Emit(
InstructionCode code, size_t outputs_size, InstructionOperand* outputs,
size_t inputs_size, InstructionOperand* inputs, size_t temps_size,
@@ -558,7 +500,6 @@ Instruction* InstructionSequenceTest::Emit(
return AddInstruction(instruction);
}
-
Instruction* InstructionSequenceTest::AddInstruction(Instruction* instruction) {
sequence()->AddInstruction(instruction);
return instruction;
diff --git a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.h b/deps/v8/test/unittests/compiler/backend/instruction-sequence-unittest.h
index 2c4df038fb..55dbe167c1 100644
--- a/deps/v8/test/unittests/compiler/instruction-sequence-unittest.h
+++ b/deps/v8/test/unittests/compiler/backend/instruction-sequence-unittest.h
@@ -7,7 +7,8 @@
#include <memory>
-#include "src/compiler/instruction.h"
+#include "src/compiler/backend/instruction.h"
+#include "src/register-configuration.h"
#include "test/unittests/test-utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -17,12 +18,14 @@ namespace compiler {
class InstructionSequenceTest : public TestWithIsolateAndZone {
public:
- static const int kDefaultNRegs = 8;
- static const int kNoValue = kMinInt;
- static const MachineRepresentation kNoRep = MachineRepresentation::kNone;
- static const MachineRepresentation kFloat32 = MachineRepresentation::kFloat32;
- static const MachineRepresentation kFloat64 = MachineRepresentation::kFloat64;
- static const MachineRepresentation kSimd128 = MachineRepresentation::kSimd128;
+ static constexpr int kNoValue = kMinInt;
+ static constexpr MachineRepresentation kNoRep = MachineRepresentation::kNone;
+ static constexpr MachineRepresentation kFloat32 =
+ MachineRepresentation::kFloat32;
+ static constexpr MachineRepresentation kFloat64 =
+ MachineRepresentation::kFloat64;
+ static constexpr MachineRepresentation kSimd128 =
+ MachineRepresentation::kSimd128;
typedef RpoNumber Rpo;
diff --git a/deps/v8/test/unittests/compiler/instruction-unittest.cc b/deps/v8/test/unittests/compiler/backend/instruction-unittest.cc
index 72deb12d02..09b4ea9295 100644
--- a/deps/v8/test/unittests/compiler/instruction-unittest.cc
+++ b/deps/v8/test/unittests/compiler/backend/instruction-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/instruction.h"
+#include "src/compiler/backend/instruction.h"
#include "src/register-configuration.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest-support.h"
diff --git a/deps/v8/test/unittests/compiler/code-assembler-unittest.cc b/deps/v8/test/unittests/compiler/code-assembler-unittest.cc
index 8a28ef389a..68a701136f 100644
--- a/deps/v8/test/unittests/compiler/code-assembler-unittest.cc
+++ b/deps/v8/test/unittests/compiler/code-assembler-unittest.cc
@@ -126,6 +126,44 @@ TARGET_TEST_F(CodeAssemblerTest, IntPtrMul) {
}
}
+TARGET_TEST_F(CodeAssemblerTest, IntPtrDiv) {
+ CodeAssemblerTestState state(this);
+ CodeAssemblerForTest m(&state);
+ {
+ TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
+ TNode<IntPtrT> b = m.IntPtrConstant(100);
+ TNode<IntPtrT> div = m.IntPtrDiv(a, b);
+ EXPECT_THAT(div, IsIntPtrDiv(Matcher<Node*>(a), Matcher<Node*>(b)));
+ }
+ // x / 1 => x
+ {
+ TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
+ TNode<IntPtrT> b = m.IntPtrConstant(1);
+ TNode<IntPtrT> div = m.IntPtrDiv(a, b);
+ EXPECT_THAT(div, a);
+ }
+ // CONST_a / CONST_b => CONST_c
+ {
+ TNode<IntPtrT> a = m.IntPtrConstant(100);
+ TNode<IntPtrT> b = m.IntPtrConstant(5);
+ TNode<IntPtrT> div = m.IntPtrDiv(a, b);
+ EXPECT_THAT(div, IsIntPtrConstant(20));
+ }
+ {
+ TNode<IntPtrT> a = m.IntPtrConstant(100);
+ TNode<IntPtrT> b = m.IntPtrConstant(5);
+ TNode<IntPtrT> div = m.IntPtrDiv(a, b);
+ EXPECT_THAT(div, IsIntPtrConstant(20));
+ }
+ // x / 2^CONST => x >> CONST
+ {
+ TNode<IntPtrT> a = m.UncheckedCast<IntPtrT>(m.Parameter(0));
+ TNode<IntPtrT> b = m.IntPtrConstant(1 << 3);
+ TNode<IntPtrT> div = m.IntPtrDiv(a, b);
+ EXPECT_THAT(div, IsWordSar(Matcher<Node*>(a), IsIntPtrConstant(3)));
+ }
+}
+
TARGET_TEST_F(CodeAssemblerTest, WordShl) {
CodeAssemblerTestState state(this);
CodeAssemblerForTest m(&state);
diff --git a/deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc b/deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc
index fd0845159f..640526bc90 100644
--- a/deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc
@@ -63,7 +63,7 @@ class ConstantFoldingReducerTest : public TypedGraphTest {
public:
ConstantFoldingReducerTest()
: TypedGraphTest(3),
- js_heap_broker_(isolate(), zone()),
+ broker_(isolate(), zone()),
simplified_(zone()),
deps_(isolate(), zone()) {}
~ConstantFoldingReducerTest() override = default;
@@ -76,23 +76,23 @@ class ConstantFoldingReducerTest : public TypedGraphTest {
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
- ConstantFoldingReducer reducer(&graph_reducer, &jsgraph, js_heap_broker());
+ ConstantFoldingReducer reducer(&graph_reducer, &jsgraph, broker());
return reducer.Reduce(node);
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
- JSHeapBroker* js_heap_broker() { return &js_heap_broker_; }
+ JSHeapBroker* broker() { return &broker_; }
private:
- JSHeapBroker js_heap_broker_;
+ JSHeapBroker broker_;
SimplifiedOperatorBuilder simplified_;
CompilationDependencies deps_;
};
TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
{
- Reduction r = Reduce(Parameter(Type::NewConstant(
- js_heap_broker(), factory()->minus_zero_value(), zone())));
+ Reduction r = Reduce(Parameter(
+ Type::NewConstant(broker(), factory()->minus_zero_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0));
}
@@ -104,8 +104,7 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
{
Reduction r = Reduce(Parameter(Type::Union(
Type::MinusZero(),
- Type::NewConstant(js_heap_broker(), factory()->NewNumber(0), zone()),
- zone())));
+ Type::NewConstant(broker(), factory()->NewNumber(0), zone()), zone())));
EXPECT_FALSE(r.Changed());
}
}
@@ -113,8 +112,7 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) {
TEST_F(ConstantFoldingReducerTest, ParameterWithNull) {
Handle<HeapObject> null = factory()->null_value();
{
- Reduction r =
- Reduce(Parameter(Type::NewConstant(js_heap_broker(), null, zone())));
+ Reduction r = Reduce(Parameter(Type::NewConstant(broker(), null, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(null));
}
@@ -131,14 +129,14 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
std::numeric_limits<double>::signaling_NaN()};
TRACED_FOREACH(double, nan, kNaNs) {
Handle<Object> constant = factory()->NewNumber(nan);
- Reduction r = Reduce(
- Parameter(Type::NewConstant(js_heap_broker(), constant, zone())));
+ Reduction r =
+ Reduce(Parameter(Type::NewConstant(broker(), constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
{
- Reduction r = Reduce(Parameter(
- Type::NewConstant(js_heap_broker(), factory()->nan_value(), zone())));
+ Reduction r = Reduce(
+ Parameter(Type::NewConstant(broker(), factory()->nan_value(), zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN()));
}
@@ -152,8 +150,8 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithNaN) {
TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) {
TRACED_FOREACH(double, value, kFloat64Values) {
Handle<Object> constant = factory()->NewNumber(value);
- Reduction r = Reduce(
- Parameter(Type::NewConstant(js_heap_broker(), constant, zone())));
+ Reduction r =
+ Reduce(Parameter(Type::NewConstant(broker(), constant, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsNumberConstant(value));
}
@@ -172,8 +170,8 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) {
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
{
- Reduction r = Reduce(
- Parameter(Type::NewConstant(js_heap_broker(), undefined, zone())));
+ Reduction r =
+ Reduce(Parameter(Type::NewConstant(broker(), undefined, zone())));
ASSERT_TRUE(r.Changed());
EXPECT_THAT(r.replacement(), IsHeapConstant(undefined));
}
@@ -194,10 +192,10 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
Type::Undefined(),
Type::Union(
Type::Undetectable(),
- Type::Union(Type::NewConstant(
- js_heap_broker(),
- factory()->false_value(), zone()),
- Type::Range(0.0, 0.0, zone()), zone()),
+ Type::Union(
+ Type::NewConstant(
+ broker(), factory()->false_value(), zone()),
+ Type::Range(0.0, 0.0, zone()), zone()),
zone()),
zone()),
zone()),
@@ -212,7 +210,7 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) {
TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) {
Node* input = Parameter(
Type::Union(
- Type::NewConstant(js_heap_broker(), factory()->true_value(), zone()),
+ Type::NewConstant(broker(), factory()->true_value(), zone()),
Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()),
zone()),
0);
diff --git a/deps/v8/test/unittests/compiler/graph-unittest.cc b/deps/v8/test/unittests/compiler/graph-unittest.cc
index 4736ddefa2..051aa68e64 100644
--- a/deps/v8/test/unittests/compiler/graph-unittest.cc
+++ b/deps/v8/test/unittests/compiler/graph-unittest.cc
@@ -15,17 +15,15 @@ namespace internal {
namespace compiler {
GraphTest::GraphTest(int num_parameters)
- : TestWithNativeContext(),
- TestWithIsolateAndZone(),
- canonical_(isolate()),
+ : canonical_(isolate()),
common_(zone()),
graph_(zone()),
- js_heap_broker_(isolate(), zone()),
+ broker_(isolate(), zone()),
source_positions_(&graph_),
node_origins_(&graph_) {
graph()->SetStart(graph()->NewNode(common()->Start(num_parameters)));
graph()->SetEnd(graph()->NewNode(common()->End(1), graph()->start()));
- js_heap_broker()->SetNativeContextRef();
+ broker()->SetNativeContextRef();
}
@@ -69,7 +67,7 @@ Node* GraphTest::NumberConstant(volatile double value) {
Node* GraphTest::HeapConstant(const Handle<HeapObject>& value) {
Node* node = graph()->NewNode(common()->HeapConstant(value));
- Type type = Type::NewConstant(js_heap_broker(), value, zone());
+ Type type = Type::NewConstant(broker(), value, zone());
NodeProperties::SetType(node, type);
return node;
}
@@ -119,8 +117,7 @@ Matcher<Node*> GraphTest::IsUndefinedConstant() {
}
TypedGraphTest::TypedGraphTest(int num_parameters)
- : GraphTest(num_parameters),
- typer_(js_heap_broker(), Typer::kNoFlags, graph()) {}
+ : GraphTest(num_parameters), typer_(broker(), Typer::kNoFlags, graph()) {}
TypedGraphTest::~TypedGraphTest() = default;
diff --git a/deps/v8/test/unittests/compiler/graph-unittest.h b/deps/v8/test/unittests/compiler/graph-unittest.h
index 8317ebf279..a4b719fe6b 100644
--- a/deps/v8/test/unittests/compiler/graph-unittest.h
+++ b/deps/v8/test/unittests/compiler/graph-unittest.h
@@ -24,8 +24,7 @@ namespace compiler {
using ::testing::Matcher;
-class GraphTest : public virtual TestWithNativeContext,
- public virtual TestWithIsolateAndZone {
+class GraphTest : public TestWithNativeContextAndZone {
public:
explicit GraphTest(int num_parameters = 1);
~GraphTest() override;
@@ -62,13 +61,13 @@ class GraphTest : public virtual TestWithNativeContext,
Graph* graph() { return &graph_; }
SourcePositionTable* source_positions() { return &source_positions_; }
NodeOriginTable* node_origins() { return &node_origins_; }
- JSHeapBroker* js_heap_broker() { return &js_heap_broker_; }
+ JSHeapBroker* broker() { return &broker_; }
private:
CanonicalHandleScope canonical_;
CommonOperatorBuilder common_;
Graph graph_;
- JSHeapBroker js_heap_broker_;
+ JSHeapBroker broker_;
SourcePositionTable source_positions_;
NodeOriginTable node_origins_;
};
diff --git a/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc b/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
index 5b808eab25..65903506ad 100644
--- a/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
+++ b/deps/v8/test/unittests/compiler/ia32/instruction-selector-ia32-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/objects-inl.h"
diff --git a/deps/v8/test/unittests/compiler/js-call-reducer-unittest.cc b/deps/v8/test/unittests/compiler/js-call-reducer-unittest.cc
index 7660f5851e..171658d830 100644
--- a/deps/v8/test/unittests/compiler/js-call-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-call-reducer-unittest.cc
@@ -22,9 +22,7 @@ class JSCallReducerTest : public TypedGraphTest {
public:
JSCallReducerTest()
: TypedGraphTest(3), javascript_(zone()), deps_(isolate(), zone()) {
- if (FLAG_concurrent_compiler_frontend) {
- js_heap_broker()->SerializeStandardObjects();
- }
+ broker()->SerializeStandardObjects();
}
~JSCallReducerTest() override = default;
@@ -37,24 +35,13 @@ class JSCallReducerTest : public TypedGraphTest {
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
- JSCallReducer reducer(&graph_reducer, &jsgraph, js_heap_broker(),
- JSCallReducer::kNoFlags, native_context(), &deps_);
+ JSCallReducer reducer(&graph_reducer, &jsgraph, broker(),
+ JSCallReducer::kNoFlags, &deps_);
return reducer.Reduce(node);
}
JSOperatorBuilder* javascript() { return &javascript_; }
- static void SetUpTestCase() {
- old_flag_lazy_ = i::FLAG_lazy_deserialization;
- i::FLAG_lazy_deserialization = false;
- TypedGraphTest::SetUpTestCase();
- }
-
- static void TearDownTestCase() {
- TypedGraphTest::TearDownTestCase();
- i::FLAG_lazy_deserialization = old_flag_lazy_;
- }
-
Node* GlobalFunction(const char* name) {
Handle<JSFunction> f = Handle<JSFunction>::cast(
Object::GetProperty(
@@ -131,9 +118,6 @@ class JSCallReducerTest : public TypedGraphTest {
private:
JSOperatorBuilder javascript_;
CompilationDependencies deps_;
-
- static bool old_flag_lazy_;
- static bool old_flag_lazy_handler_;
};
TEST_F(JSCallReducerTest, PromiseConstructorNoArgs) {
@@ -217,9 +201,6 @@ TEST_F(JSCallReducerTest, PromiseConstructorWithHook) {
ASSERT_FALSE(r.Changed());
}
-bool JSCallReducerTest::old_flag_lazy_;
-bool JSCallReducerTest::old_flag_lazy_handler_;
-
// -----------------------------------------------------------------------------
// Math unaries
diff --git a/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
index eafd7fa35e..41f0c180e6 100644
--- a/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-create-lowering-unittest.cc
@@ -45,7 +45,7 @@ class JSCreateLoweringTest : public TypedGraphTest {
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
- JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, js_heap_broker(),
+ JSCreateLowering reducer(&graph_reducer, &deps_, &jsgraph, broker(),
zone());
return reducer.Reduce(node);
}
@@ -75,8 +75,8 @@ class JSCreateLoweringTest : public TypedGraphTest {
TEST_F(JSCreateLoweringTest, JSCreate) {
Handle<JSFunction> function = isolate()->object_function();
- Node* const target = Parameter(
- Type::HeapConstant(js_heap_broker(), function, graph()->zone()));
+ Node* const target =
+ Parameter(Type::HeapConstant(broker(), function, graph()->zone()));
Node* const context = Parameter(Type::Any());
Node* const effect = graph()->start();
Node* const control = graph()->start();
diff --git a/deps/v8/test/unittests/compiler/js-native-context-specialization-unittest.cc b/deps/v8/test/unittests/compiler/js-native-context-specialization-unittest.cc
index fdc87904c4..bf9a144fab 100644
--- a/deps/v8/test/unittests/compiler/js-native-context-specialization-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-native-context-specialization-unittest.cc
@@ -34,14 +34,14 @@ TEST_F(JSNativeContextSpecializationTest, GetMaxStringLengthOfString) {
Node* const str_node = graph()->NewNode(
common()->HeapConstant(factory()->InternalizeUtf8String("str")));
- EXPECT_EQ(JSNativeContextSpecialization::GetMaxStringLength(js_heap_broker(),
- str_node),
- str_len);
+ EXPECT_EQ(
+ JSNativeContextSpecialization::GetMaxStringLength(broker(), str_node),
+ str_len);
Node* const num_node = graph()->NewNode(common()->NumberConstant(10.0 / 3));
- EXPECT_EQ(JSNativeContextSpecialization::GetMaxStringLength(js_heap_broker(),
- num_node),
- num_len);
+ EXPECT_EQ(
+ JSNativeContextSpecialization::GetMaxStringLength(broker(), num_node),
+ num_len);
}
} // namespace js_native_context_specialization_unittest
diff --git a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
index 43998824d2..b3326b0ad4 100644
--- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc
@@ -48,12 +48,13 @@ class JSTypedLoweringTest : public TypedGraphTest {
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
- JSTypedLowering reducer(&graph_reducer, &jsgraph, js_heap_broker(), zone());
+ JSTypedLowering reducer(&graph_reducer, &jsgraph, broker(), zone());
return reducer.Reduce(node);
}
Handle<JSArrayBuffer> NewArrayBuffer(void* bytes, size_t byte_length) {
- Handle<JSArrayBuffer> buffer = factory()->NewJSArrayBuffer();
+ Handle<JSArrayBuffer> buffer =
+ factory()->NewJSArrayBuffer(SharedFlag::kNotShared);
JSArrayBuffer::Setup(buffer, isolate(), true, bytes, byte_length);
return buffer;
}
diff --git a/deps/v8/test/unittests/compiler/live-range-builder.h b/deps/v8/test/unittests/compiler/live-range-builder.h
deleted file mode 100644
index 4a5621fab7..0000000000
--- a/deps/v8/test/unittests/compiler/live-range-builder.h
+++ /dev/null
@@ -1,78 +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_LIVE_RANGE_BUILDER_H_
-#define V8_LIVE_RANGE_BUILDER_H_
-
-#include "src/compiler/register-allocator.h"
-
-namespace v8 {
-namespace internal {
-namespace compiler {
-
-
-// Utility offering shorthand syntax for building up a range by providing its ID
-// and pairs (start, end) specifying intervals. Circumvents current incomplete
-// support for C++ features such as instantiation lists, on OS X and Android.
-class TestRangeBuilder {
- public:
- explicit TestRangeBuilder(Zone* zone)
- : id_(-1), pairs_(), uses_(), zone_(zone) {}
-
- TestRangeBuilder& Id(int id) {
- id_ = id;
- return *this;
- }
- TestRangeBuilder& Add(int start, int end) {
- pairs_.push_back({start, end});
- return *this;
- }
-
- TestRangeBuilder& AddUse(int pos) {
- uses_.insert(pos);
- return *this;
- }
-
- TopLevelLiveRange* Build(int start, int end) {
- return Add(start, end).Build();
- }
-
- TopLevelLiveRange* Build() {
- TopLevelLiveRange* range =
- new (zone_) TopLevelLiveRange(id_, MachineRepresentation::kTagged);
- // Traverse the provided interval specifications backwards, because that is
- // what LiveRange expects.
- for (int i = static_cast<int>(pairs_.size()) - 1; i >= 0; --i) {
- Interval pair = pairs_[i];
- LifetimePosition start = LifetimePosition::FromInt(pair.first);
- LifetimePosition end = LifetimePosition::FromInt(pair.second);
- CHECK(start < end);
- range->AddUseInterval(start, end, zone_);
- }
- for (int pos : uses_) {
- UsePosition* use_position =
- new (zone_) UsePosition(LifetimePosition::FromInt(pos), nullptr,
- nullptr, UsePositionHintType::kNone);
- range->AddUsePosition(use_position);
- }
-
- pairs_.clear();
- return range;
- }
-
- private:
- typedef std::pair<int, int> Interval;
- typedef std::vector<Interval> IntervalList;
- int id_;
- IntervalList pairs_;
- std::set<int> uses_;
- Zone* zone_;
-};
-
-
-} // namespace compiler
-} // namespace internal
-} // namespace v8
-
-#endif // V8_LIVE_RANGE_BUILDER_H_
diff --git a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
index b8b0c9004f..cd70b3bc41 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc
@@ -6,6 +6,7 @@
#include "src/base/bits.h"
#include "src/base/division-by-constant.h"
#include "src/base/ieee754.h"
+#include "src/base/overflowing-math.h"
#include "src/compiler/js-graph.h"
#include "src/compiler/typer.h"
#include "src/conversions-inl.h"
@@ -26,14 +27,20 @@ namespace compiler {
class MachineOperatorReducerTest : public GraphTest {
public:
explicit MachineOperatorReducerTest(int num_parameters = 2)
- : GraphTest(num_parameters), machine_(zone()) {}
+ : GraphTest(num_parameters),
+ machine_(zone()),
+ common_(zone()),
+ javascript_(zone()),
+ jsgraph_(isolate(), graph(), &common_, &javascript_, nullptr,
+ &machine_),
+ graph_reducer_(zone(), graph(), jsgraph_.Dead()) {}
protected:
Reduction Reduce(Node* node) {
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, nullptr,
&machine_);
- MachineOperatorReducer reducer(&jsgraph);
+ MachineOperatorReducer reducer(&graph_reducer_, &jsgraph);
return reducer.Reduce(node);
}
@@ -61,6 +68,10 @@ class MachineOperatorReducerTest : public GraphTest {
private:
MachineOperatorBuilder machine_;
+ CommonOperatorBuilder common_;
+ JSOperatorBuilder javascript_;
+ JSGraph jsgraph_;
+ GraphReducer graph_reducer_;
};
@@ -968,7 +979,8 @@ TEST_F(MachineOperatorReducerTest, Word32SarWithWord32ShlAndLoad) {
TEST_F(MachineOperatorReducerTest, Word32ShrWithWord32And) {
Node* const p0 = Parameter(0);
TRACED_FORRANGE(int32_t, shift, 1, 31) {
- uint32_t mask = (1 << shift) - 1;
+ uint32_t mask =
+ base::SubWithWraparound(base::ShlWithWraparound(1, shift), 1);
Node* node = graph()->NewNode(
machine()->Word32Shr(),
graph()->NewNode(machine()->Word32And(), p0, Int32Constant(mask)),
@@ -1057,7 +1069,9 @@ TEST_F(MachineOperatorReducerTest, Int32SubWithConstant) {
if (k == 0) {
EXPECT_EQ(p0, r.replacement());
} else {
- EXPECT_THAT(r.replacement(), IsInt32Add(p0, IsInt32Constant(-k)));
+ EXPECT_THAT(
+ r.replacement(),
+ IsInt32Add(p0, IsInt32Constant(base::NegateWithWraparound(k))));
}
}
}
diff --git a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
index eea7276f6f..9eddb1d311 100644
--- a/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/machine-operator-unittest.cc
@@ -13,8 +13,6 @@ namespace internal {
namespace compiler {
namespace machine_operator_unittest {
-#if GTEST_HAS_COMBINE
-
template <typename T>
class MachineOperatorTestWithParam
: public TestWithZone,
@@ -159,7 +157,6 @@ INSTANTIATE_TEST_CASE_P(
::testing::Combine(::testing::ValuesIn(kRepresentationsForStore),
::testing::Values(kNoWriteBarrier,
kFullWriteBarrier))));
-#endif
// -----------------------------------------------------------------------------
// Pure operators.
diff --git a/deps/v8/test/unittests/compiler/mips/OWNERS b/deps/v8/test/unittests/compiler/mips/OWNERS
index 8bbcab4c2d..b455d9ef29 100644
--- a/deps/v8/test/unittests/compiler/mips/OWNERS
+++ b/deps/v8/test/unittests/compiler/mips/OWNERS
@@ -1,2 +1,3 @@
-ibogosavljevic@wavecomp.com
-skovacevic@wavecomp.com \ No newline at end of file
+arikalo@wavecomp.com
+prudic@wavecomp.com
+skovacevic@wavecomp.com
diff --git a/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc b/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
index 15f5de7b2f..83edb6a21e 100644
--- a/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
+++ b/deps/v8/test/unittests/compiler/mips/instruction-selector-mips-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/objects-inl.h"
diff --git a/deps/v8/test/unittests/compiler/mips64/OWNERS b/deps/v8/test/unittests/compiler/mips64/OWNERS
index 8bbcab4c2d..b455d9ef29 100644
--- a/deps/v8/test/unittests/compiler/mips64/OWNERS
+++ b/deps/v8/test/unittests/compiler/mips64/OWNERS
@@ -1,2 +1,3 @@
-ibogosavljevic@wavecomp.com
-skovacevic@wavecomp.com \ No newline at end of file
+arikalo@wavecomp.com
+prudic@wavecomp.com
+skovacevic@wavecomp.com
diff --git a/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc b/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
index c090e29321..c6c1ff3ee8 100644
--- a/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/mips64/instruction-selector-mips64-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/objects-inl.h"
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.cc b/deps/v8/test/unittests/compiler/node-test-utils.cc
index 0b3d8786f8..f23265e8e4 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.cc
+++ b/deps/v8/test/unittests/compiler/node-test-utils.cc
@@ -6,7 +6,6 @@
#include <vector>
-#include "src/assembler.h"
#include "src/compiler/common-operator.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node-properties.h"
@@ -2152,6 +2151,7 @@ IS_BINOP_MATCHER(Word64Equal)
IS_BINOP_MATCHER(Int32AddWithOverflow)
IS_BINOP_MATCHER(Int32SubWithOverflow)
IS_BINOP_MATCHER(Int32Add)
+IS_BINOP_MATCHER(Int32Div)
IS_BINOP_MATCHER(Int32Sub)
IS_BINOP_MATCHER(Int32Mul)
IS_BINOP_MATCHER(Int32MulHigh)
@@ -2159,6 +2159,7 @@ IS_BINOP_MATCHER(Int32LessThan)
IS_BINOP_MATCHER(Uint32LessThan)
IS_BINOP_MATCHER(Uint32LessThanOrEqual)
IS_BINOP_MATCHER(Int64Add)
+IS_BINOP_MATCHER(Int64Div)
IS_BINOP_MATCHER(Int64Sub)
IS_BINOP_MATCHER(Int64Mul)
IS_BINOP_MATCHER(JSAdd)
@@ -2255,22 +2256,14 @@ IS_UNOP_MATCHER(TaggedPoisonOnSpeculation)
// Special-case Bitcast operators which are disabled when ENABLE_VERIFY_CSA is
// not enabled.
Matcher<Node*> IsBitcastTaggedToWord(const Matcher<Node*>& input_matcher) {
-#ifdef ENABLE_VERIFY_CSA
return MakeMatcher(
new IsUnopMatcher(IrOpcode::kBitcastTaggedToWord, input_matcher));
-#else
- return input_matcher;
-#endif
}
Matcher<Node*> IsBitcastWordToTaggedSigned(
const Matcher<Node*>& input_matcher) {
-#ifdef ENABLE_VERIFY_CSA
return MakeMatcher(
new IsUnopMatcher(IrOpcode::kBitcastWordToTaggedSigned, input_matcher));
-#else
- return input_matcher;
-#endif
}
#undef LOAD_MATCHER
diff --git a/deps/v8/test/unittests/compiler/node-test-utils.h b/deps/v8/test/unittests/compiler/node-test-utils.h
index 4e9c32e6d6..96bdbdf3be 100644
--- a/deps/v8/test/unittests/compiler/node-test-utils.h
+++ b/deps/v8/test/unittests/compiler/node-test-utils.h
@@ -387,6 +387,8 @@ Matcher<Node*> IsInt32Add(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsInt32Div(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32Mul(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt32MulHigh(const Matcher<Node*>& lhs_matcher,
@@ -403,6 +405,8 @@ Matcher<Node*> IsInt64Sub(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsInt64Mul(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
+Matcher<Node*> IsInt64Div(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsJSAdd(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher);
Matcher<Node*> IsJSParseInt(const Matcher<Node*>& lhs_matcher,
@@ -517,6 +521,12 @@ static inline Matcher<Node*> IsIntPtrMul(const Matcher<Node*>& lhs_matcher,
: IsInt32Mul(lhs_matcher, rhs_matcher);
}
+static inline Matcher<Node*> IsIntPtrDiv(const Matcher<Node*>& lhs_matcher,
+ const Matcher<Node*>& rhs_matcher) {
+ return kPointerSize == 8 ? IsInt64Div(lhs_matcher, rhs_matcher)
+ : IsInt32Div(lhs_matcher, rhs_matcher);
+}
+
static inline Matcher<Node*> IsWordShl(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsWord64Shl(lhs_matcher, rhs_matcher)
diff --git a/deps/v8/test/unittests/compiler/persistent-unittest.cc b/deps/v8/test/unittests/compiler/persistent-unittest.cc
index 8454aeaeb1..4c5a1974c7 100644
--- a/deps/v8/test/unittests/compiler/persistent-unittest.cc
+++ b/deps/v8/test/unittests/compiler/persistent-unittest.cc
@@ -83,19 +83,19 @@ TEST(PersistentMap, Zip) {
// Provoke hash collisions to stress the iterator.
struct bad_hash {
- size_t operator()(int key) {
+ size_t operator()(uint32_t key) {
return base::hash_value(static_cast<size_t>(key) % 1000);
}
};
- PersistentMap<int, int, bad_hash> a(&zone);
- PersistentMap<int, int, bad_hash> b(&zone);
+ PersistentMap<int, uint32_t, bad_hash> a(&zone);
+ PersistentMap<int, uint32_t, bad_hash> b(&zone);
- int sum_a = 0;
- int sum_b = 0;
+ uint32_t sum_a = 0;
+ uint32_t sum_b = 0;
for (int i = 0; i < 30000; ++i) {
int key = small_big_distr(&rand);
- int value = small_big_distr(&rand);
+ uint32_t value = small_big_distr(&rand);
if (rand.NextBool()) {
sum_a += value;
a.Set(key, a.Get(key) + value);
@@ -105,28 +105,28 @@ TEST(PersistentMap, Zip) {
}
}
- int sum = sum_a + sum_b;
+ uint32_t sum = sum_a + sum_b;
for (auto pair : a) {
sum_a -= pair.second;
}
- ASSERT_EQ(0, sum_a);
+ ASSERT_EQ(0u, sum_a);
for (auto pair : b) {
sum_b -= pair.second;
}
- ASSERT_EQ(0, sum_b);
+ ASSERT_EQ(0u, sum_b);
for (auto triple : a.Zip(b)) {
int key = std::get<0>(triple);
- int value_a = std::get<1>(triple);
- int value_b = std::get<2>(triple);
+ uint32_t value_a = std::get<1>(triple);
+ uint32_t value_b = std::get<2>(triple);
ASSERT_EQ(value_a, a.Get(key));
ASSERT_EQ(value_b, b.Get(key));
sum -= value_a;
sum -= value_b;
}
- ASSERT_EQ(0, sum);
+ ASSERT_EQ(0u, sum);
}
} // namespace compiler
diff --git a/deps/v8/test/unittests/compiler/ppc/OWNERS b/deps/v8/test/unittests/compiler/ppc/OWNERS
index eb007cb908..6d1a8fc472 100644
--- a/deps/v8/test/unittests/compiler/ppc/OWNERS
+++ b/deps/v8/test/unittests/compiler/ppc/OWNERS
@@ -1,5 +1,4 @@
jyan@ca.ibm.com
-dstence@us.ibm.com
joransiu@ca.ibm.com
-mbrandy@us.ibm.com
michael_dawson@ca.ibm.com
+miladfar@ca.ibm.com \ No newline at end of file
diff --git a/deps/v8/test/unittests/compiler/ppc/instruction-selector-ppc-unittest.cc b/deps/v8/test/unittests/compiler/ppc/instruction-selector-ppc-unittest.cc
index 86f7d69ec9..611e766edb 100644
--- a/deps/v8/test/unittests/compiler/ppc/instruction-selector-ppc-unittest.cc
+++ b/deps/v8/test/unittests/compiler/ppc/instruction-selector-ppc-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/assembler-inl.h"
diff --git a/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc b/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc
index f3ecd228a5..079cc4b99a 100644
--- a/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc
+++ b/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc
@@ -133,6 +133,67 @@ TEST_F(RedundancyEliminationTest, CheckNumberSubsumedByCheckSmi) {
}
// -----------------------------------------------------------------------------
+// CheckReceiver
+
+TEST_F(RedundancyEliminationTest, CheckReceiver) {
+ Node* value = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect =
+ graph()->NewNode(simplified()->CheckReceiver(), value, effect, control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect =
+ graph()->NewNode(simplified()->CheckReceiver(), value, effect, control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+}
+
+// -----------------------------------------------------------------------------
+// CheckReceiverOrNullOrUndefined
+
+TEST_F(RedundancyEliminationTest, CheckReceiverOrNullOrUndefined) {
+ Node* value = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect = graph()->NewNode(
+ simplified()->CheckReceiverOrNullOrUndefined(), value, effect, control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect = graph()->NewNode(
+ simplified()->CheckReceiverOrNullOrUndefined(), value, effect, control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+}
+
+TEST_F(RedundancyEliminationTest,
+ CheckReceiverOrNullOrUndefinedSubsumedByCheckReceiver) {
+ Node* value = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect =
+ graph()->NewNode(simplified()->CheckReceiver(), value, effect, control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect = graph()->NewNode(
+ simplified()->CheckReceiverOrNullOrUndefined(), value, effect, control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+}
+
+// -----------------------------------------------------------------------------
// CheckString
TEST_F(RedundancyEliminationTest,
@@ -207,6 +268,35 @@ TEST_F(RedundancyEliminationTest, CheckedFloat64ToInt32) {
}
// -----------------------------------------------------------------------------
+// CheckedFloat64ToInt64
+
+TEST_F(RedundancyEliminationTest, CheckedFloat64ToInt64) {
+ TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
+ TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
+ TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
+ Node* value = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect = graph()->NewNode(
+ simplified()->CheckedFloat64ToInt64(mode, feedback1), value, effect,
+ control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect = graph()->NewNode(
+ simplified()->CheckedFloat64ToInt64(mode, feedback2), value, effect,
+ control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
// CheckedInt32ToTaggedSigned
TEST_F(RedundancyEliminationTest, CheckedInt32ToTaggedSigned) {
@@ -427,6 +517,35 @@ TEST_F(RedundancyEliminationTest,
}
// -----------------------------------------------------------------------------
+// CheckedTaggedToInt64
+
+TEST_F(RedundancyEliminationTest, CheckedTaggedToInt64) {
+ TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
+ TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
+ TRACED_FOREACH(CheckForMinusZeroMode, mode, kCheckForMinusZeroModes) {
+ Node* value = Parameter(0);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect = graph()->NewNode(
+ simplified()->CheckedTaggedToInt64(mode, feedback1), value, effect,
+ control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect = graph()->NewNode(
+ simplified()->CheckedTaggedToInt64(mode, feedback2), value, effect,
+ control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+ }
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
// CheckedTaggedToTaggedPointer
TEST_F(RedundancyEliminationTest, CheckedTaggedToTaggedPointer) {
@@ -539,6 +658,34 @@ TEST_F(RedundancyEliminationTest,
}
// -----------------------------------------------------------------------------
+// CheckedUint32Bounds
+
+TEST_F(RedundancyEliminationTest, CheckedUint32Bounds) {
+ TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
+ TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
+ Node* index = Parameter(0);
+ Node* length = Parameter(1);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect =
+ graph()->NewNode(simplified()->CheckedUint32Bounds(feedback1), index,
+ length, effect, control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect =
+ graph()->NewNode(simplified()->CheckedUint32Bounds(feedback2), index,
+ length, effect, control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
// CheckedUint32ToInt32
TEST_F(RedundancyEliminationTest, CheckedUint32ToInt32) {
@@ -593,6 +740,34 @@ TEST_F(RedundancyEliminationTest, CheckedUint32ToTaggedSigned) {
}
// -----------------------------------------------------------------------------
+// CheckedUint64Bounds
+
+TEST_F(RedundancyEliminationTest, CheckedUint64Bounds) {
+ TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
+ TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
+ Node* index = Parameter(0);
+ Node* length = Parameter(1);
+ Node* effect = graph()->start();
+ Node* control = graph()->start();
+
+ Node* check1 = effect =
+ graph()->NewNode(simplified()->CheckedUint64Bounds(feedback1), index,
+ length, effect, control);
+ Reduction r1 = Reduce(check1);
+ ASSERT_TRUE(r1.Changed());
+ EXPECT_EQ(r1.replacement(), check1);
+
+ Node* check2 = effect =
+ graph()->NewNode(simplified()->CheckedUint64Bounds(feedback2), index,
+ length, effect, control);
+ Reduction r2 = Reduce(check2);
+ ASSERT_TRUE(r2.Changed());
+ EXPECT_EQ(r2.replacement(), check1);
+ }
+ }
+}
+
+// -----------------------------------------------------------------------------
// CheckedUint64ToInt32
TEST_F(RedundancyEliminationTest, CheckedUint64ToInt32) {
@@ -651,7 +826,7 @@ TEST_F(RedundancyEliminationTest, CheckedUint64ToTaggedSigned) {
TEST_F(RedundancyEliminationTest,
SpeculativeNumberEqualWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -687,7 +862,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberEqualWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::UnsignedSmall(), 0);
@@ -726,7 +901,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -762,7 +937,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::UnsignedSmall(), 0);
@@ -801,7 +976,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanOrEqualWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -837,7 +1012,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberLessThanOrEqualWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
Node* lhs = Parameter(Type::UnsignedSmall(), 0);
@@ -876,7 +1051,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberAddWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -902,7 +1077,7 @@ TEST_F(RedundancyEliminationTest,
}
TEST_F(RedundancyEliminationTest, SpeculativeNumberAddWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@@ -932,7 +1107,7 @@ TEST_F(RedundancyEliminationTest, SpeculativeNumberAddWithCheckBoundsSameType) {
TEST_F(RedundancyEliminationTest,
SpeculativeNumberSubtractWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -960,7 +1135,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeNumberSubtractWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@@ -991,7 +1166,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerAddWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -1019,7 +1194,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerAddWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@@ -1050,7 +1225,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerSubtractWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Any(), 0);
@@ -1078,7 +1253,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeSafeIntegerSubtractWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
Node* lhs = Parameter(Type::Range(42.0, 42.0, zone()), 0);
@@ -1109,7 +1284,7 @@ TEST_F(RedundancyEliminationTest,
TEST_F(RedundancyEliminationTest,
SpeculativeToNumberWithCheckBoundsBetterType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
@@ -1137,7 +1312,7 @@ TEST_F(RedundancyEliminationTest,
}
TEST_F(RedundancyEliminationTest, SpeculativeToNumberWithCheckBoundsSameType) {
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
TRACED_FOREACH(VectorSlotPair, feedback1, vector_slot_pairs()) {
TRACED_FOREACH(VectorSlotPair, feedback2, vector_slot_pairs()) {
TRACED_FOREACH(NumberOperationHint, hint, kNumberOperationHints) {
diff --git a/deps/v8/test/unittests/compiler/regalloc/live-range-unittest.cc b/deps/v8/test/unittests/compiler/regalloc/live-range-unittest.cc
index fc7b268b44..9ac6ca8810 100644
--- a/deps/v8/test/unittests/compiler/regalloc/live-range-unittest.cc
+++ b/deps/v8/test/unittests/compiler/regalloc/live-range-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/unittests/compiler/live-range-builder.h"
+#include "src/compiler/backend/register-allocator.h"
#include "test/unittests/test-utils.h"
// TODO(mtrofin): would we want to centralize this definition?
@@ -20,6 +20,64 @@ namespace v8 {
namespace internal {
namespace compiler {
+// Utility offering shorthand syntax for building up a range by providing its ID
+// and pairs (start, end) specifying intervals. Circumvents current incomplete
+// support for C++ features such as instantiation lists, on OS X and Android.
+class TestRangeBuilder {
+ public:
+ explicit TestRangeBuilder(Zone* zone)
+ : id_(-1), pairs_(), uses_(), zone_(zone) {}
+
+ TestRangeBuilder& Id(int id) {
+ id_ = id;
+ return *this;
+ }
+ TestRangeBuilder& Add(int start, int end) {
+ pairs_.push_back({start, end});
+ return *this;
+ }
+
+ TestRangeBuilder& AddUse(int pos) {
+ uses_.insert(pos);
+ return *this;
+ }
+
+ TopLevelLiveRange* Build(int start, int end) {
+ return Add(start, end).Build();
+ }
+
+ TopLevelLiveRange* Build() {
+ TopLevelLiveRange* range =
+ new (zone_) TopLevelLiveRange(id_, MachineRepresentation::kTagged);
+ // Traverse the provided interval specifications backwards, because that is
+ // what LiveRange expects.
+ for (int i = static_cast<int>(pairs_.size()) - 1; i >= 0; --i) {
+ Interval pair = pairs_[i];
+ LifetimePosition start = LifetimePosition::FromInt(pair.first);
+ LifetimePosition end = LifetimePosition::FromInt(pair.second);
+ CHECK(start < end);
+ range->AddUseInterval(start, end, zone_);
+ }
+ for (int pos : uses_) {
+ UsePosition* use_position =
+ new (zone_) UsePosition(LifetimePosition::FromInt(pos), nullptr,
+ nullptr, UsePositionHintType::kNone);
+ range->AddUsePosition(use_position);
+ }
+
+ pairs_.clear();
+ return range;
+ }
+
+ private:
+ typedef std::pair<int, int> Interval;
+ typedef std::vector<Interval> IntervalList;
+ int id_;
+ IntervalList pairs_;
+ std::set<int> uses_;
+ Zone* zone_;
+};
+
class LiveRangeUnitTest : public TestWithZone {
public:
// Split helper, to avoid int->LifetimePosition conversion nuisance.
diff --git a/deps/v8/test/unittests/compiler/regalloc/move-optimizer-unittest.cc b/deps/v8/test/unittests/compiler/regalloc/move-optimizer-unittest.cc
index 71767a964e..23f17b2b6c 100644
--- a/deps/v8/test/unittests/compiler/regalloc/move-optimizer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/regalloc/move-optimizer-unittest.cc
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/compiler/move-optimizer.h"
-#include "src/compiler/pipeline.h"
+#include "src/compiler/backend/move-optimizer.h"
#include "src/ostreams.h"
-#include "test/unittests/compiler/instruction-sequence-unittest.h"
+#include "test/unittests/compiler/backend/instruction-sequence-unittest.h"
namespace v8 {
namespace internal {
@@ -54,18 +53,16 @@ class MoveOptimizerTest : public InstructionSequenceTest {
void Optimize() {
WireBlocks();
if (FLAG_trace_turbo) {
- PrintableInstructionSequence printable = {config(), sequence()};
StdoutStream{}
<< "----- Instruction sequence before move optimization -----\n"
- << printable;
+ << *sequence();
}
MoveOptimizer move_optimizer(zone(), sequence());
move_optimizer.Run();
if (FLAG_trace_turbo) {
- PrintableInstructionSequence printable = {config(), sequence()};
StdoutStream{}
<< "----- Instruction sequence after move optimization -----\n"
- << printable;
+ << *sequence();
}
}
diff --git a/deps/v8/test/unittests/compiler/regalloc/register-allocator-unittest.cc b/deps/v8/test/unittests/compiler/regalloc/register-allocator-unittest.cc
index e12d53caf5..d77f424ef7 100644
--- a/deps/v8/test/unittests/compiler/regalloc/register-allocator-unittest.cc
+++ b/deps/v8/test/unittests/compiler/regalloc/register-allocator-unittest.cc
@@ -4,7 +4,7 @@
#include "src/assembler-inl.h"
#include "src/compiler/pipeline.h"
-#include "test/unittests/compiler/instruction-sequence-unittest.h"
+#include "test/unittests/compiler/backend/instruction-sequence-unittest.h"
namespace v8 {
namespace internal {
@@ -187,7 +187,7 @@ TEST_F(RegisterAllocatorTest, SimpleDiamondPhi) {
}
TEST_F(RegisterAllocatorTest, DiamondManyPhis) {
- const int kPhis = kDefaultNRegs * 2;
+ constexpr int kPhis = Register::kNumRegisters * 2;
StartBlock();
EndBlock(Branch(Reg(DefineConstant()), 1, 2));
@@ -218,7 +218,7 @@ TEST_F(RegisterAllocatorTest, DiamondManyPhis) {
}
TEST_F(RegisterAllocatorTest, DoubleDiamondManyRedundantPhis) {
- const int kPhis = kDefaultNRegs * 2;
+ constexpr int kPhis = Register::kNumRegisters * 2;
// First diamond.
StartBlock();
@@ -326,16 +326,16 @@ TEST_F(RegisterAllocatorTest, SpillPhi) {
TEST_F(RegisterAllocatorTest, MoveLotsOfConstants) {
StartBlock();
- VReg constants[kDefaultNRegs];
+ VReg constants[Register::kNumRegisters];
for (size_t i = 0; i < arraysize(constants); ++i) {
constants[i] = DefineConstant();
}
- TestOperand call_ops[kDefaultNRegs * 2];
- for (int i = 0; i < kDefaultNRegs; ++i) {
+ TestOperand call_ops[Register::kNumRegisters * 2];
+ for (int i = 0; i < Register::kNumRegisters; ++i) {
call_ops[i] = Reg(constants[i], i);
}
- for (int i = 0; i < kDefaultNRegs; ++i) {
- call_ops[i + kDefaultNRegs] = Slot(constants[i], i);
+ for (int i = 0; i < Register::kNumRegisters; ++i) {
+ call_ops[i + Register::kNumRegisters] = Slot(constants[i], i);
}
EmitCall(Slot(-1), arraysize(call_ops), call_ops);
EndBlock(Last());
@@ -488,7 +488,7 @@ TEST_F(RegisterAllocatorTest, RegressionSplitBeforeAndMove) {
StartBlock();
// Fill registers.
- VReg values[kDefaultNRegs];
+ VReg values[Register::kNumRegisters];
for (size_t i = 0; i < arraysize(values); ++i) {
if (i == 0 || i == 1) continue; // Leave a hole for c_1 to take.
values[i] = Define(Reg(static_cast<int>(i)));
@@ -522,7 +522,7 @@ TEST_F(RegisterAllocatorTest, RegressionSpillTwice) {
TEST_F(RegisterAllocatorTest, RegressionLoadConstantBeforeSpill) {
StartBlock();
// Fill registers.
- VReg values[kDefaultNRegs];
+ VReg values[Register::kNumRegisters];
for (size_t i = arraysize(values); i > 0; --i) {
values[i - 1] = Define(Reg(static_cast<int>(i - 1)));
}
@@ -711,8 +711,6 @@ class SlotConstraintTest : public RegisterAllocatorTest,
} // namespace
-#if GTEST_HAS_COMBINE
-
TEST_P(SlotConstraintTest, SlotConstraint) {
StartBlock();
VReg p_0;
@@ -762,8 +760,6 @@ INSTANTIATE_TEST_CASE_P(
::testing::Combine(::testing::ValuesIn(kParameterTypes),
::testing::Range(0, SlotConstraintTest::kMaxVariant)));
-#endif // GTEST_HAS_COMBINE
-
} // namespace compiler
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/compiler/s390/OWNERS b/deps/v8/test/unittests/compiler/s390/OWNERS
index eb007cb908..6d1a8fc472 100644
--- a/deps/v8/test/unittests/compiler/s390/OWNERS
+++ b/deps/v8/test/unittests/compiler/s390/OWNERS
@@ -1,5 +1,4 @@
jyan@ca.ibm.com
-dstence@us.ibm.com
joransiu@ca.ibm.com
-mbrandy@us.ibm.com
michael_dawson@ca.ibm.com
+miladfar@ca.ibm.com \ No newline at end of file
diff --git a/deps/v8/test/unittests/compiler/s390/instruction-selector-s390-unittest.cc b/deps/v8/test/unittests/compiler/s390/instruction-selector-s390-unittest.cc
index 86f7d69ec9..611e766edb 100644
--- a/deps/v8/test/unittests/compiler/s390/instruction-selector-s390-unittest.cc
+++ b/deps/v8/test/unittests/compiler/s390/instruction-selector-s390-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/assembler-inl.h"
diff --git a/deps/v8/test/unittests/compiler/simplified-lowering-unittest.cc b/deps/v8/test/unittests/compiler/simplified-lowering-unittest.cc
index 82bcda6e9f..722384da5b 100644
--- a/deps/v8/test/unittests/compiler/simplified-lowering-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-lowering-unittest.cc
@@ -42,12 +42,12 @@ class SimplifiedLoweringTest : public GraphTest {
{
// Simplified lowering needs to run w/o the typer decorator so make sure
// the object is not live at the same time.
- Typer typer(js_heap_broker(), Typer::kNoFlags, graph());
+ Typer typer(broker(), Typer::kNoFlags, graph());
typer.Run();
}
- SimplifiedLowering lowering(jsgraph(), js_heap_broker(), zone(),
- source_positions(), node_origins(),
+ SimplifiedLowering lowering(jsgraph(), broker(), zone(), source_positions(),
+ node_origins(),
PoisoningMitigationLevel::kDontPoison);
lowering.LowerAllNodes();
}
diff --git a/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc b/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
index 5e2f8f15cc..f3573d6379 100644
--- a/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/simplified-operator-reducer-unittest.cc
@@ -29,14 +29,13 @@ class SimplifiedOperatorReducerTest : public GraphTest {
protected:
Reduction Reduce(Node* node) {
- JSHeapBroker js_heap_broker(isolate(), zone());
+ JSHeapBroker broker(isolate(), zone());
MachineOperatorBuilder machine(zone());
JSOperatorBuilder javascript(zone());
JSGraph jsgraph(isolate(), graph(), common(), &javascript, simplified(),
&machine);
GraphReducer graph_reducer(zone(), graph());
- SimplifiedOperatorReducer reducer(&graph_reducer, &jsgraph,
- &js_heap_broker);
+ SimplifiedOperatorReducer reducer(&graph_reducer, &jsgraph, &broker);
return reducer.Reduce(node);
}
diff --git a/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc b/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc
index 51426a5f85..da1f3941f0 100644
--- a/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc
+++ b/deps/v8/test/unittests/compiler/typed-optimization-unittest.cc
@@ -38,8 +38,7 @@ class TypedOptimizationTest : public TypedGraphTest {
&machine);
// TODO(titzer): mock the GraphReducer here for better unit testing.
GraphReducer graph_reducer(zone(), graph());
- TypedOptimization reducer(&graph_reducer, &deps_, &jsgraph,
- js_heap_broker());
+ TypedOptimization reducer(&graph_reducer, &deps_, &jsgraph, broker());
return reducer.Reduce(node);
}
diff --git a/deps/v8/test/unittests/compiler/typer-unittest.cc b/deps/v8/test/unittests/compiler/typer-unittest.cc
index b827088336..5954dbc638 100644
--- a/deps/v8/test/unittests/compiler/typer-unittest.cc
+++ b/deps/v8/test/unittests/compiler/typer-unittest.cc
@@ -4,7 +4,7 @@
#include <functional>
-#include "src/codegen.h"
+#include "src/base/overflowing-math.h"
#include "src/compiler/js-operator.h"
#include "src/compiler/node-properties.h"
#include "src/compiler/operator-properties.h"
@@ -22,8 +22,8 @@ class TyperTest : public TypedGraphTest {
public:
TyperTest()
: TypedGraphTest(3),
- js_heap_broker_(isolate(), zone()),
- operation_typer_(&js_heap_broker_, zone()),
+ broker_(isolate(), zone()),
+ operation_typer_(&broker_, zone()),
types_(zone(), isolate(), random_number_generator()),
javascript_(zone()),
simplified_(zone()) {
@@ -56,7 +56,7 @@ class TyperTest : public TypedGraphTest {
const int kRepetitions = 50;
- JSHeapBroker js_heap_broker_;
+ JSHeapBroker broker_;
OperationTyper operation_typer_;
Types types_;
JSOperatorBuilder javascript_;
@@ -176,8 +176,8 @@ class TyperTest : public TypedGraphTest {
for (int x2 = rmin; x2 < rmin + width; x2++) {
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
- &js_heap_broker_,
- isolate()->factory()->NewNumber(result_value), zone());
+ &broker_, isolate()->factory()->NewNumber(result_value),
+ zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
}
@@ -198,23 +198,21 @@ class TyperTest : public TypedGraphTest {
double x2 = RandomInt(r2.AsRange());
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
- &js_heap_broker_, isolate()->factory()->NewNumber(result_value),
- zone());
+ &broker_, isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
}
// Test extreme cases.
double x1 = +1e-308;
double x2 = -1e-308;
- Type r1 = Type::NewConstant(&js_heap_broker_,
- isolate()->factory()->NewNumber(x1), zone());
- Type r2 = Type::NewConstant(&js_heap_broker_,
- isolate()->factory()->NewNumber(x2), zone());
+ Type r1 = Type::NewConstant(&broker_, isolate()->factory()->NewNumber(x1),
+ zone());
+ Type r2 = Type::NewConstant(&broker_, isolate()->factory()->NewNumber(x2),
+ zone());
Type expected_type = TypeBinaryOp(op, r1, r2);
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
- &js_heap_broker_, isolate()->factory()->NewNumber(result_value),
- zone());
+ &broker_, isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
@@ -229,7 +227,7 @@ class TyperTest : public TypedGraphTest {
double x2 = RandomInt(r2.AsRange());
bool result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
- &js_heap_broker_,
+ &broker_,
result_value ? isolate()->factory()->true_value()
: isolate()->factory()->false_value(),
zone());
@@ -249,8 +247,7 @@ class TyperTest : public TypedGraphTest {
int32_t x2 = static_cast<int32_t>(RandomInt(r2.AsRange()));
double result_value = opfun(x1, x2);
Type result_type = Type::NewConstant(
- &js_heap_broker_, isolate()->factory()->NewNumber(result_value),
- zone());
+ &broker_, isolate()->factory()->NewNumber(result_value), zone());
EXPECT_TRUE(result_type.Is(expected_type));
}
}
@@ -311,6 +308,7 @@ int32_t shift_right(int32_t x, int32_t y) { return x >> (y & 0x1F); }
int32_t bit_or(int32_t x, int32_t y) { return x | y; }
int32_t bit_and(int32_t x, int32_t y) { return x & y; }
int32_t bit_xor(int32_t x, int32_t y) { return x ^ y; }
+double divide_double_double(double x, double y) { return base::Divide(x, y); }
double modulo_double_double(double x, double y) { return Modulo(x, y); }
} // namespace
@@ -335,7 +333,7 @@ TEST_F(TyperTest, TypeJSMultiply) {
}
TEST_F(TyperTest, TypeJSDivide) {
- TestBinaryArithOp(javascript_.Divide(), std::divides<double>());
+ TestBinaryArithOp(javascript_.Divide(), divide_double_double);
}
TEST_F(TyperTest, TypeJSModulus) {
diff --git a/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc b/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
index fb7caa4bf9..f174b92731 100644
--- a/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
+++ b/deps/v8/test/unittests/compiler/x64/instruction-selector-x64-unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "test/unittests/compiler/instruction-selector-unittest.h"
+#include "test/unittests/compiler/backend/instruction-selector-unittest.h"
#include "src/compiler/node-matchers.h"
#include "src/objects-inl.h"
@@ -1205,10 +1205,114 @@ TEST_F(InstructionSelectorTest, Int32Shl4BecomesLea) {
EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
}
-
// -----------------------------------------------------------------------------
// Binops with a memory operand.
+TEST_F(InstructionSelectorTest, LoadCmp32) {
+ {
+ // Word32Equal(Load[Int8](p0, p1), Int32Constant(0)) -> cmpb [p0,p1], 0
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
+ MachineType::Int64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ m.Return(
+ m.Word32Equal(m.Load(MachineType::Int8(), p0, p1), m.Int32Constant(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
+ }
+ {
+ // Word32Equal(Load[Uint8](p0, p1), Int32Constant(0)) -> cmpb [p0,p1], 0
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
+ MachineType::Int64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ m.Return(m.Word32Equal(m.Load(MachineType::Uint8(), p0, p1),
+ m.Int32Constant(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Cmp8, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
+ }
+ {
+ // Word32Equal(Load[Int16](p0, p1), Int32Constant(0)) -> cmpw [p0,p1], 0
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
+ MachineType::Int64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ m.Return(m.Word32Equal(m.Load(MachineType::Int16(), p0, p1),
+ m.Int32Constant(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Cmp16, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
+ }
+ {
+ // Word32Equal(Load[Uint16](p0, p1), Int32Constant(0)) -> cmpw [p0,p1], 0
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
+ MachineType::Int64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ m.Return(m.Word32Equal(m.Load(MachineType::Uint16(), p0, p1),
+ m.Int32Constant(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Cmp16, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
+ }
+ {
+ // Word32Equal(Load[Int32](p0, p1), Int32Constant(0)) -> cmpl [p0,p1], 0
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
+ MachineType::Int64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ m.Return(m.Word32Equal(m.Load(MachineType::Int32(), p0, p1),
+ m.Int32Constant(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
+ }
+ {
+ // Word32Equal(Load[Uint32](p0, p1), Int32Constant(0)) -> cmpl [p0,p1], 0
+ StreamBuilder m(this, MachineType::Int32(), MachineType::Int64(),
+ MachineType::Int64());
+ Node* const p0 = m.Parameter(0);
+ Node* const p1 = m.Parameter(1);
+ m.Return(m.Word32Equal(m.Load(MachineType::Uint32(), p0, p1),
+ m.Int32Constant(0)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kX64Cmp32, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_MR1, s[0]->addressing_mode());
+ ASSERT_EQ(3U, s[0]->InputCount());
+ EXPECT_EQ(s.ToVreg(p0), s.ToVreg(s[0]->InputAt(0)));
+ EXPECT_EQ(s.ToVreg(p1), s.ToVreg(s[0]->InputAt(1)));
+ EXPECT_TRUE(s[0]->InputAt(2)->IsImmediate());
+ }
+}
+
TEST_F(InstructionSelectorTest, LoadAnd32) {
StreamBuilder m(this, MachineType::Int32(), MachineType::Int32(),
MachineType::Int32());
diff --git a/deps/v8/test/unittests/compiler/zone-stats-unittest.cc b/deps/v8/test/unittests/compiler/zone-stats-unittest.cc
index a643d1480c..9f3bd3493f 100644
--- a/deps/v8/test/unittests/compiler/zone-stats-unittest.cc
+++ b/deps/v8/test/unittests/compiler/zone-stats-unittest.cc
@@ -10,7 +10,7 @@ namespace v8 {
namespace internal {
namespace compiler {
-class ZoneStatsTest : public TestWithIsolate {
+class ZoneStatsTest : public ::testing::Test {
public:
ZoneStatsTest() : zone_stats_(&allocator_) {}
diff --git a/deps/v8/test/unittests/conversions-unittest.cc b/deps/v8/test/unittests/conversions-unittest.cc
new file mode 100644
index 0000000000..7c4bd96a6f
--- /dev/null
+++ b/deps/v8/test/unittests/conversions-unittest.cc
@@ -0,0 +1,76 @@
+// Copyright 2016 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.
+
+#include "src/v8.h"
+
+#include "src/conversions.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace interpreter {
+
+class ConversionsTest : public ::testing::Test {
+ public:
+ ConversionsTest() = default;
+ ~ConversionsTest() override = default;
+
+ SourcePosition toPos(int offset) {
+ return SourcePosition(offset, offset % 10 - 1);
+ }
+};
+
+// Some random offsets, mostly at 'suspicious' bit boundaries.
+
+struct IntStringPair {
+ int integer;
+ std::string string;
+};
+
+static IntStringPair int_pairs[] = {{0, "0"},
+ {101, "101"},
+ {-1, "-1"},
+ {1024, "1024"},
+ {200000, "200000"},
+ {-1024, "-1024"},
+ {-200000, "-200000"},
+ {kMinInt, "-2147483648"},
+ {kMaxInt, "2147483647"}};
+
+TEST_F(ConversionsTest, IntToCString) {
+ std::unique_ptr<char[]> buf(new char[4096]);
+
+ for (size_t i = 0; i < arraysize(int_pairs); i++) {
+ ASSERT_STREQ(IntToCString(int_pairs[i].integer, {buf.get(), 4096}),
+ int_pairs[i].string.c_str());
+ }
+}
+
+struct DoubleStringPair {
+ double number;
+ std::string string;
+};
+
+static DoubleStringPair double_pairs[] = {
+ {0.0, "0"},
+ {kMinInt, "-2147483648"},
+ {kMaxInt, "2147483647"},
+ // ES section 7.1.12.1 #sec-tostring-applied-to-the-number-type:
+ // -0.0 is stringified to "0".
+ {-0.0, "0"},
+ {1.1, "1.1"},
+ {0.1, "0.1"}};
+
+TEST_F(ConversionsTest, DoubleToCString) {
+ std::unique_ptr<char[]> buf(new char[4096]);
+
+ for (size_t i = 0; i < arraysize(double_pairs); i++) {
+ ASSERT_STREQ(DoubleToCString(double_pairs[i].number, {buf.get(), 4096}),
+ double_pairs[i].string.c_str());
+ }
+}
+
+} // namespace interpreter
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/detachable-vector-unittest.cc b/deps/v8/test/unittests/detachable-vector-unittest.cc
index f9c846df22..b805352a7e 100644
--- a/deps/v8/test/unittests/detachable-vector-unittest.cc
+++ b/deps/v8/test/unittests/detachable-vector-unittest.cc
@@ -63,5 +63,65 @@ TEST(DetachableVector, DetachLeaksBackingStore) {
// The destructor of v2 will release the backing store.
}
+TEST(DetachableVector, PushAndPopWithReallocation) {
+ DetachableVector<size_t> v;
+ const size_t kMinimumCapacity = DetachableVector<size_t>::kMinimumCapacity;
+
+ EXPECT_EQ(0u, v.capacity());
+ EXPECT_EQ(0u, v.size());
+ v.push_back(0);
+ EXPECT_EQ(kMinimumCapacity, v.capacity());
+ EXPECT_EQ(1u, v.size());
+
+ // Push values until the reallocation happens.
+ for (size_t i = 1; i <= kMinimumCapacity; ++i) {
+ v.push_back(i);
+ }
+ EXPECT_EQ(2 * kMinimumCapacity, v.capacity());
+ EXPECT_EQ(kMinimumCapacity + 1, v.size());
+
+ EXPECT_EQ(kMinimumCapacity, v.back());
+ v.pop_back();
+
+ v.push_back(100);
+ EXPECT_EQ(100u, v.back());
+ v.pop_back();
+ EXPECT_EQ(kMinimumCapacity - 1, v.back());
+}
+
+TEST(DetachableVector, ShrinkToFit) {
+ DetachableVector<size_t> v;
+ const size_t kMinimumCapacity = DetachableVector<size_t>::kMinimumCapacity;
+
+ // shrink_to_fit doesn't affect the empty capacity DetachableVector.
+ EXPECT_EQ(0u, v.capacity());
+ v.shrink_to_fit();
+ EXPECT_EQ(0u, v.capacity());
+
+ // Do not shrink the buffer if it's smaller than kMinimumCapacity.
+ v.push_back(0);
+ EXPECT_EQ(kMinimumCapacity, v.capacity());
+ v.shrink_to_fit();
+ EXPECT_EQ(kMinimumCapacity, v.capacity());
+
+ // Fill items to |v| until the buffer grows twice.
+ for (size_t i = 0; i < 2 * kMinimumCapacity; ++i) {
+ v.push_back(i);
+ }
+ EXPECT_EQ(2 * kMinimumCapacity + 1, v.size());
+ EXPECT_EQ(4 * kMinimumCapacity, v.capacity());
+
+ // Do not shrink the buffer if the number of unused slots is not large enough.
+ v.shrink_to_fit();
+ EXPECT_EQ(2 * kMinimumCapacity + 1, v.size());
+ EXPECT_EQ(4 * kMinimumCapacity, v.capacity());
+
+ v.pop_back();
+ v.pop_back();
+ v.shrink_to_fit();
+ EXPECT_EQ(2 * kMinimumCapacity - 1, v.size());
+ EXPECT_EQ(2 * kMinimumCapacity - 1, v.capacity());
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/heap/barrier-unittest.cc b/deps/v8/test/unittests/heap/barrier-unittest.cc
index 1d42f97a4f..07906b20c1 100644
--- a/deps/v8/test/unittests/heap/barrier-unittest.cc
+++ b/deps/v8/test/unittests/heap/barrier-unittest.cc
@@ -4,19 +4,27 @@
#include "src/heap/barrier.h"
#include "src/base/platform/platform.h"
+#include "src/base/platform/time.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
namespace heap {
+namespace {
+
+// Large timeout that will not trigger in tests.
+constexpr base::TimeDelta test_timeout = base::TimeDelta::FromHours(3);
+
+} // namespace
+
TEST(OneshotBarrier, InitializeNotDone) {
- OneshotBarrier barrier;
+ OneshotBarrier barrier(test_timeout);
EXPECT_FALSE(barrier.DoneForTesting());
}
TEST(OneshotBarrier, DoneAfterWait_Sequential) {
- OneshotBarrier barrier;
+ OneshotBarrier barrier(test_timeout);
barrier.Start();
barrier.Wait();
EXPECT_TRUE(barrier.DoneForTesting());
@@ -41,7 +49,7 @@ class ThreadWaitingOnBarrier final : public base::Thread {
TEST(OneshotBarrier, DoneAfterWait_Concurrent) {
const int kThreadCount = 2;
- OneshotBarrier barrier;
+ OneshotBarrier barrier(test_timeout);
ThreadWaitingOnBarrier threads[kThreadCount];
for (int i = 0; i < kThreadCount; i++) {
threads[i].Initialize(&barrier);
@@ -59,7 +67,7 @@ TEST(OneshotBarrier, DoneAfterWait_Concurrent) {
TEST(OneshotBarrier, EarlyFinish_Concurrent) {
const int kThreadCount = 2;
- OneshotBarrier barrier;
+ OneshotBarrier barrier(test_timeout);
ThreadWaitingOnBarrier threads[kThreadCount];
// Test that one thread that actually finishes processing work before other
// threads call Start() will move the barrier in Done state.
@@ -103,7 +111,7 @@ class CountingThread final : public base::Thread {
private:
void ProcessWork() {
- base::LockGuard<base::Mutex> guard(mutex_);
+ base::MutexGuard guard(mutex_);
processed_work_ += *work_;
*work_ = 0;
}
@@ -118,7 +126,7 @@ class CountingThread final : public base::Thread {
TEST(OneshotBarrier, Processing_Concurrent) {
const size_t kWorkCounter = 173173;
- OneshotBarrier barrier;
+ OneshotBarrier barrier(test_timeout);
base::Mutex mutex;
size_t work = 0;
CountingThread counting_thread(&barrier, &mutex, &work);
@@ -129,7 +137,7 @@ TEST(OneshotBarrier, Processing_Concurrent) {
for (size_t i = 0; i < kWorkCounter; i++) {
{
- base::LockGuard<base::Mutex> guard(&mutex);
+ base::MutexGuard guard(&mutex);
work++;
}
barrier.NotifyAll();
diff --git a/deps/v8/test/unittests/heap/embedder-tracing-unittest.cc b/deps/v8/test/unittests/heap/embedder-tracing-unittest.cc
index 33cc05e692..5bbbaceb3c 100644
--- a/deps/v8/test/unittests/heap/embedder-tracing-unittest.cc
+++ b/deps/v8/test/unittests/heap/embedder-tracing-unittest.cc
@@ -83,6 +83,14 @@ TEST(LocalEmbedderHeapTracer, EnterFinalPauseForwards) {
local_tracer.EnterFinalPause();
}
+TEST(LocalEmbedderHeapTracer, IsRemoteTracingDoneForwards) {
+ StrictMock<MockEmbedderHeapTracer> remote_tracer;
+ LocalEmbedderHeapTracer local_tracer(nullptr);
+ local_tracer.SetRemoteTracer(&remote_tracer);
+ EXPECT_CALL(remote_tracer, IsTracingDone());
+ local_tracer.IsRemoteTracingDone();
+}
+
TEST(LocalEmbedderHeapTracer, EnterFinalPauseDefaultStackStateUnkown) {
StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
@@ -102,6 +110,36 @@ TEST(LocalEmbedderHeapTracer, EnterFinalPauseStackStateIsForwarded) {
local_tracer.EnterFinalPause();
}
+TEST(LocalEmbedderHeapTracer, TemporaryEmbedderStackState) {
+ StrictMock<MockEmbedderHeapTracer> remote_tracer;
+ LocalEmbedderHeapTracer local_tracer(nullptr);
+ local_tracer.SetRemoteTracer(&remote_tracer);
+ // Default is unknown, see above.
+ {
+ EmbedderStackStateScope scope(&local_tracer, EmbedderHeapTracer::kEmpty);
+ EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kEmpty));
+ local_tracer.EnterFinalPause();
+ }
+}
+
+TEST(LocalEmbedderHeapTracer, TemporaryEmbedderStackStateRestores) {
+ StrictMock<MockEmbedderHeapTracer> remote_tracer;
+ LocalEmbedderHeapTracer local_tracer(nullptr);
+ local_tracer.SetRemoteTracer(&remote_tracer);
+ // Default is unknown, see above.
+ {
+ EmbedderStackStateScope scope(&local_tracer, EmbedderHeapTracer::kEmpty);
+ {
+ EmbedderStackStateScope scope(&local_tracer,
+ EmbedderHeapTracer::kUnknown);
+ EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kUnknown));
+ local_tracer.EnterFinalPause();
+ }
+ EXPECT_CALL(remote_tracer, EnterFinalPause(EmbedderHeapTracer::kEmpty));
+ local_tracer.EnterFinalPause();
+ }
+}
+
TEST(LocalEmbedderHeapTracer, EnterFinalPauseStackStateResets) {
StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
@@ -122,52 +160,19 @@ TEST(LocalEmbedderHeapTracer, IsRemoteTracingDoneIncludesRemote) {
local_tracer.IsRemoteTracingDone();
}
-TEST(LocalEmbedderHeapTracer, NumberOfCachedWrappersToTraceExcludesRemote) {
- LocalEmbedderHeapTracer local_tracer(nullptr);
- StrictMock<MockEmbedderHeapTracer> remote_tracer;
- local_tracer.SetRemoteTracer(&remote_tracer);
- local_tracer.NumberOfCachedWrappersToTrace();
-}
-
-TEST(LocalEmbedderHeapTracer, RegisterWrappersWithRemoteTracer) {
+TEST(LocalEmbedderHeapTracer, RegisterV8ReferencesWithRemoteTracer) {
StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(nullptr);
local_tracer.SetRemoteTracer(&remote_tracer);
- local_tracer.AddWrapperToTrace(CreateWrapperInfo());
- EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
- EXPECT_CALL(remote_tracer, RegisterV8References(_));
- local_tracer.RegisterWrappersWithRemoteTracer();
- EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
+ {
+ LocalEmbedderHeapTracer::ProcessingScope scope(&local_tracer);
+ scope.AddWrapperInfoForTesting(CreateWrapperInfo());
+ EXPECT_CALL(remote_tracer, RegisterV8References(_));
+ }
EXPECT_CALL(remote_tracer, IsTracingDone()).WillOnce(Return(false));
EXPECT_FALSE(local_tracer.IsRemoteTracingDone());
}
-TEST(LocalEmbedderHeapTracer, TraceFinishes) {
- StrictMock<MockEmbedderHeapTracer> remote_tracer;
- LocalEmbedderHeapTracer local_tracer(nullptr);
- local_tracer.SetRemoteTracer(&remote_tracer);
- local_tracer.AddWrapperToTrace(CreateWrapperInfo());
- EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
- EXPECT_CALL(remote_tracer, RegisterV8References(_));
- local_tracer.RegisterWrappersWithRemoteTracer();
- EXPECT_CALL(remote_tracer, AdvanceTracing(_)).WillOnce(Return(true));
- EXPECT_TRUE(local_tracer.Trace(std::numeric_limits<double>::infinity()));
- EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
-}
-
-TEST(LocalEmbedderHeapTracer, TraceDoesNotFinish) {
- StrictMock<MockEmbedderHeapTracer> remote_tracer;
- LocalEmbedderHeapTracer local_tracer(nullptr);
- local_tracer.SetRemoteTracer(&remote_tracer);
- local_tracer.AddWrapperToTrace(CreateWrapperInfo());
- EXPECT_EQ(1u, local_tracer.NumberOfCachedWrappersToTrace());
- EXPECT_CALL(remote_tracer, RegisterV8References(_));
- local_tracer.RegisterWrappersWithRemoteTracer();
- EXPECT_CALL(remote_tracer, AdvanceTracing(_)).WillOnce(Return(false));
- EXPECT_FALSE(local_tracer.Trace(1.0));
- EXPECT_EQ(0u, local_tracer.NumberOfCachedWrappersToTrace());
-}
-
TEST_F(LocalEmbedderHeapTracerWithIsolate, SetRemoteTracerSetsIsolate) {
StrictMock<MockEmbedderHeapTracer> remote_tracer;
LocalEmbedderHeapTracer local_tracer(isolate());
diff --git a/deps/v8/test/unittests/heap/gc-tracer-unittest.cc b/deps/v8/test/unittests/heap/gc-tracer-unittest.cc
index ac18e1817b..b1e646fa2c 100644
--- a/deps/v8/test/unittests/heap/gc-tracer-unittest.cc
+++ b/deps/v8/test/unittests/heap/gc-tracer-unittest.cc
@@ -468,7 +468,7 @@ class GcHistogram {
static void CleanUp() { histograms_.clear(); }
- int Total() {
+ int Total() const {
int result = 0;
for (int i : samples_) {
result += i;
@@ -476,7 +476,7 @@ class GcHistogram {
return result;
}
- int Count() { return static_cast<int>(samples_.size()); }
+ int Count() const { return static_cast<int>(samples_.size()); }
private:
std::vector<int> samples_;
@@ -524,5 +524,27 @@ TEST_F(GCTracerTest, RecordScavengerHistograms) {
GcHistogram::CleanUp();
}
+TEST_F(GCTracerTest, RecordGCSumHistograms) {
+ if (FLAG_stress_incremental_marking) return;
+ isolate()->SetCreateHistogramFunction(&GcHistogram::CreateHistogram);
+ isolate()->SetAddHistogramSampleFunction(&GcHistogram::AddHistogramSample);
+ GCTracer* tracer = i_isolate()->heap()->tracer();
+ tracer->ResetForTesting();
+ tracer->current_
+ .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_START]
+ .duration = 1;
+ tracer->current_
+ .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_SWEEPING]
+ .duration = 2;
+ tracer->AddIncrementalMarkingStep(3.0, 1024);
+ tracer->current_
+ .incremental_marking_scopes[GCTracer::Scope::MC_INCREMENTAL_FINALIZE]
+ .duration = 4;
+ const double atomic_pause_duration = 5.0;
+ tracer->RecordGCSumCounters(atomic_pause_duration);
+ EXPECT_EQ(15, GcHistogram::Get("V8.GCMarkCompactor")->Total());
+ GcHistogram::CleanUp();
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/heap/heap-unittest.cc b/deps/v8/test/unittests/heap/heap-unittest.cc
index dd14e22d54..53954d8178 100644
--- a/deps/v8/test/unittests/heap/heap-unittest.cc
+++ b/deps/v8/test/unittests/heap/heap-unittest.cc
@@ -20,6 +20,7 @@ namespace v8 {
namespace internal {
typedef TestWithIsolate HeapTest;
+typedef TestWithIsolateAndPointerCompression HeapWithPointerCompressionTest;
TEST(Heap, SemiSpaceSize) {
const size_t KB = static_cast<size_t>(i::KB);
@@ -61,15 +62,46 @@ TEST_F(HeapTest, ASLR) {
TEST_F(HeapTest, ExternalLimitDefault) {
Heap* heap = i_isolate()->heap();
- EXPECT_EQ(kExternalAllocationSoftLimit, heap->external_memory_limit_);
+ EXPECT_EQ(kExternalAllocationSoftLimit,
+ heap->isolate()->isolate_data()->external_memory_limit_);
}
TEST_F(HeapTest, ExternalLimitStaysAboveDefaultForExplicitHandling) {
v8_isolate()->AdjustAmountOfExternalAllocatedMemory(+10 * MB);
v8_isolate()->AdjustAmountOfExternalAllocatedMemory(-10 * MB);
Heap* heap = i_isolate()->heap();
- EXPECT_GE(heap->external_memory_limit_, kExternalAllocationSoftLimit);
+ EXPECT_GE(heap->isolate()->isolate_data()->external_memory_limit_,
+ kExternalAllocationSoftLimit);
}
+#if V8_TARGET_ARCH_64_BIT
+TEST_F(HeapWithPointerCompressionTest, HeapLayout) {
+ // Produce some garbage.
+ RunJS(
+ "let ar = [];"
+ "for (let i = 0; i < 100; i++) {"
+ " ar.push(Array(i));"
+ "}"
+ "ar.push(Array(32 * 1024 * 1024));");
+
+ Address isolate_root = i_isolate()->isolate_root();
+ EXPECT_TRUE(IsAligned(isolate_root, size_t{4} * GB));
+
+ // Check that all memory chunks belong this region.
+ base::AddressRegion heap_reservation(isolate_root - size_t{2} * GB,
+ size_t{4} * GB);
+
+ OldGenerationMemoryChunkIterator iter(i_isolate()->heap());
+ for (;;) {
+ MemoryChunk* chunk = iter.next();
+ if (chunk == nullptr) break;
+
+ Address address = chunk->address();
+ size_t size = chunk->area_end() - address;
+ EXPECT_TRUE(heap_reservation.contains(address, size));
+ }
+}
+#endif // V8_TARGET_ARCH_64_BIT
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/heap/marking-unittest.cc b/deps/v8/test/unittests/heap/marking-unittest.cc
index 0553dc0ea5..be26d4eebd 100644
--- a/deps/v8/test/unittests/heap/marking-unittest.cc
+++ b/deps/v8/test/unittests/heap/marking-unittest.cc
@@ -14,7 +14,7 @@ namespace internal {
TEST(Marking, TransitionWhiteBlackWhite) {
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
- calloc(Bitmap::kSize / kPointerSize, kPointerSize));
+ calloc(Bitmap::kSize / kTaggedSize, kTaggedSize));
const int kLocationsSize = 3;
int position[kLocationsSize] = {
Bitmap::kBitsPerCell - 2, Bitmap::kBitsPerCell - 1, Bitmap::kBitsPerCell};
@@ -34,7 +34,7 @@ TEST(Marking, TransitionWhiteBlackWhite) {
TEST(Marking, TransitionWhiteGreyBlack) {
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
- calloc(Bitmap::kSize / kPointerSize, kPointerSize));
+ calloc(Bitmap::kSize / kTaggedSize, kTaggedSize));
const int kLocationsSize = 3;
int position[kLocationsSize] = {
Bitmap::kBitsPerCell - 2, Bitmap::kBitsPerCell - 1, Bitmap::kBitsPerCell};
@@ -60,7 +60,7 @@ TEST(Marking, TransitionWhiteGreyBlack) {
TEST(Marking, SetAndClearRange) {
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
- calloc(Bitmap::kSize / kPointerSize, kPointerSize));
+ calloc(Bitmap::kSize / kTaggedSize, kTaggedSize));
for (int i = 0; i < 3; i++) {
bitmap->SetRange(i, Bitmap::kBitsPerCell + i);
CHECK_EQ(reinterpret_cast<uint32_t*>(bitmap)[0], 0xFFFFFFFFu << i);
@@ -74,7 +74,7 @@ TEST(Marking, SetAndClearRange) {
TEST(Marking, ClearMultipleRanges) {
Bitmap* bitmap = reinterpret_cast<Bitmap*>(
- calloc(Bitmap::kSize / kPointerSize, kPointerSize));
+ calloc(Bitmap::kSize / kTaggedSize, kTaggedSize));
CHECK(bitmap->AllBitsClearInRange(0, Bitmap::kBitsPerCell * 3));
bitmap->SetRange(0, Bitmap::kBitsPerCell * 3);
CHECK_EQ(reinterpret_cast<uint32_t*>(bitmap)[0], 0xFFFFFFFFu);
diff --git a/deps/v8/test/unittests/heap/slot-set-unittest.cc b/deps/v8/test/unittests/heap/slot-set-unittest.cc
index aff6f02130..168bc9c7bc 100644
--- a/deps/v8/test/unittests/heap/slot-set-unittest.cc
+++ b/deps/v8/test/unittests/heap/slot-set-unittest.cc
@@ -8,6 +8,7 @@
#include "src/globals.h"
#include "src/heap/slot-set.h"
#include "src/heap/spaces.h"
+#include "src/objects/slots.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
@@ -16,13 +17,13 @@ namespace internal {
TEST(SlotSet, InsertAndLookup1) {
SlotSet set;
set.SetPageStart(0);
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
EXPECT_FALSE(set.Lookup(i));
}
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
set.Insert(i);
}
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
EXPECT_TRUE(set.Lookup(i));
}
}
@@ -30,12 +31,12 @@ TEST(SlotSet, InsertAndLookup1) {
TEST(SlotSet, InsertAndLookup2) {
SlotSet set;
set.SetPageStart(0);
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 7 == 0) {
set.Insert(i);
}
}
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 7 == 0) {
EXPECT_TRUE(set.Lookup(i));
} else {
@@ -47,15 +48,15 @@ TEST(SlotSet, InsertAndLookup2) {
TEST(SlotSet, Iterate) {
SlotSet set;
set.SetPageStart(0);
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 7 == 0) {
set.Insert(i);
}
}
set.Iterate(
- [](Address slot_address) {
- if (slot_address % 3 == 0) {
+ [](MaybeObjectSlot slot) {
+ if (slot.address() % 3 == 0) {
return KEEP_SLOT;
} else {
return REMOVE_SLOT;
@@ -63,7 +64,7 @@ TEST(SlotSet, Iterate) {
},
SlotSet::KEEP_EMPTY_BUCKETS);
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 21 == 0) {
EXPECT_TRUE(set.Lookup(i));
} else {
@@ -75,19 +76,19 @@ TEST(SlotSet, Iterate) {
TEST(SlotSet, Remove) {
SlotSet set;
set.SetPageStart(0);
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 7 == 0) {
set.Insert(i);
}
}
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 3 != 0) {
set.Remove(i);
}
}
- for (int i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (int i = 0; i < Page::kPageSize; i += kTaggedSize) {
if (i % 21 == 0) {
EXPECT_TRUE(set.Lookup(i));
} else {
@@ -99,11 +100,11 @@ TEST(SlotSet, Remove) {
void CheckRemoveRangeOn(uint32_t start, uint32_t end) {
SlotSet set;
set.SetPageStart(0);
- uint32_t first = start == 0 ? 0 : start - kPointerSize;
- uint32_t last = end == Page::kPageSize ? end - kPointerSize : end;
+ uint32_t first = start == 0 ? 0 : start - kTaggedSize;
+ uint32_t last = end == Page::kPageSize ? end - kTaggedSize : end;
for (const auto mode :
{SlotSet::FREE_EMPTY_BUCKETS, SlotSet::KEEP_EMPTY_BUCKETS}) {
- for (uint32_t i = first; i <= last; i += kPointerSize) {
+ for (uint32_t i = first; i <= last; i += kTaggedSize) {
set.Insert(i);
}
set.RemoveRange(start, end, mode);
@@ -113,7 +114,7 @@ void CheckRemoveRangeOn(uint32_t start, uint32_t end) {
if (last == end) {
EXPECT_TRUE(set.Lookup(last));
}
- for (uint32_t i = start; i < end; i += kPointerSize) {
+ for (uint32_t i = start; i < end; i += kTaggedSize) {
EXPECT_FALSE(set.Lookup(i));
}
}
@@ -121,16 +122,16 @@ void CheckRemoveRangeOn(uint32_t start, uint32_t end) {
TEST(SlotSet, RemoveRange) {
CheckRemoveRangeOn(0, Page::kPageSize);
- CheckRemoveRangeOn(1 * kPointerSize, 1023 * kPointerSize);
+ CheckRemoveRangeOn(1 * kTaggedSize, 1023 * kTaggedSize);
for (uint32_t start = 0; start <= 32; start++) {
- CheckRemoveRangeOn(start * kPointerSize, (start + 1) * kPointerSize);
- CheckRemoveRangeOn(start * kPointerSize, (start + 2) * kPointerSize);
+ CheckRemoveRangeOn(start * kTaggedSize, (start + 1) * kTaggedSize);
+ CheckRemoveRangeOn(start * kTaggedSize, (start + 2) * kTaggedSize);
const uint32_t kEnds[] = {32, 64, 100, 128, 1024, 1500, 2048};
for (size_t i = 0; i < sizeof(kEnds) / sizeof(uint32_t); i++) {
for (int k = -3; k <= 3; k++) {
uint32_t end = (kEnds[i] + k);
if (start < end) {
- CheckRemoveRangeOn(start * kPointerSize, end * kPointerSize);
+ CheckRemoveRangeOn(start * kTaggedSize, end * kTaggedSize);
}
}
}
@@ -141,7 +142,7 @@ TEST(SlotSet, RemoveRange) {
{SlotSet::FREE_EMPTY_BUCKETS, SlotSet::KEEP_EMPTY_BUCKETS}) {
set.Insert(Page::kPageSize / 2);
set.RemoveRange(0, Page::kPageSize, mode);
- for (uint32_t i = 0; i < Page::kPageSize; i += kPointerSize) {
+ for (uint32_t i = 0; i < Page::kPageSize; i += kTaggedSize) {
EXPECT_FALSE(set.Lookup(i));
}
}
@@ -153,23 +154,18 @@ TEST(TypedSlotSet, Iterate) {
// for a MSVC++ bug about lambda captures, see the discussion at
// https://social.msdn.microsoft.com/Forums/SqlServer/4abf18bd-4ae4-4c72-ba3e-3b13e7909d5f
static const int kDelta = 10000001;
- static const int kHostDelta = 50001;
int added = 0;
- uint32_t j = 0;
- for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset;
- i += kDelta, j += kHostDelta) {
+ for (uint32_t i = 0; i < TypedSlotSet::kMaxOffset; i += kDelta) {
SlotType type = static_cast<SlotType>(i % CLEARED_SLOT);
- set.Insert(type, j, i);
+ set.Insert(type, i);
++added;
}
int iterated = 0;
set.Iterate(
- [&iterated](SlotType type, Address host_addr, Address addr) {
+ [&iterated](SlotType type, Address addr) {
uint32_t i = static_cast<uint32_t>(addr);
- uint32_t j = static_cast<uint32_t>(host_addr);
EXPECT_EQ(i % CLEARED_SLOT, static_cast<uint32_t>(type));
EXPECT_EQ(0u, i % kDelta);
- EXPECT_EQ(0u, j % kHostDelta);
++iterated;
return i % 2 == 0 ? KEEP_SLOT : REMOVE_SLOT;
},
@@ -177,7 +173,7 @@ TEST(TypedSlotSet, Iterate) {
EXPECT_EQ(added, iterated);
iterated = 0;
set.Iterate(
- [&iterated](SlotType type, Address host_addr, Address addr) {
+ [&iterated](SlotType type, Address addr) {
uint32_t i = static_cast<uint32_t>(addr);
EXPECT_EQ(0u, i % 2);
++iterated;
@@ -187,13 +183,13 @@ TEST(TypedSlotSet, Iterate) {
EXPECT_EQ(added / 2, iterated);
}
-TEST(TypedSlotSet, RemoveInvalidSlots) {
+TEST(TypedSlotSet, ClearInvalidSlots) {
TypedSlotSet set(0);
const int kHostDelta = 100;
uint32_t entries = 10;
for (uint32_t i = 0; i < entries; i++) {
SlotType type = static_cast<SlotType>(i % CLEARED_SLOT);
- set.Insert(type, i * kHostDelta, i * kHostDelta);
+ set.Insert(type, i * kHostDelta);
}
std::map<uint32_t, uint32_t> invalid_ranges;
@@ -202,19 +198,48 @@ TEST(TypedSlotSet, RemoveInvalidSlots) {
std::pair<uint32_t, uint32_t>(i * kHostDelta, i * kHostDelta + 1));
}
- set.RemoveInvaldSlots(invalid_ranges);
+ set.ClearInvalidSlots(invalid_ranges);
for (std::map<uint32_t, uint32_t>::iterator it = invalid_ranges.begin();
it != invalid_ranges.end(); ++it) {
uint32_t start = it->first;
uint32_t end = it->second;
set.Iterate(
- [start, end](SlotType slot_type, Address host_addr, Address slot_addr) {
- CHECK(host_addr < start || host_addr >= end);
+ [=](SlotType slot_type, Address slot_addr) {
+ CHECK(slot_addr < start || slot_addr >= end);
return KEEP_SLOT;
},
TypedSlotSet::KEEP_EMPTY_CHUNKS);
}
}
+TEST(TypedSlotSet, Merge) {
+ TypedSlotSet set0(0), set1(0);
+ static const uint32_t kEntries = 10000;
+ for (uint32_t i = 0; i < kEntries; i++) {
+ set0.Insert(EMBEDDED_OBJECT_SLOT, 2 * i);
+ set1.Insert(EMBEDDED_OBJECT_SLOT, 2 * i + 1);
+ }
+ uint32_t count = 0;
+ set0.Merge(&set1);
+ set0.Iterate(
+ [&count](SlotType slot_type, Address slot_addr) {
+ if (count < kEntries) {
+ CHECK_EQ(slot_addr % 2, 0);
+ } else {
+ CHECK_EQ(slot_addr % 2, 1);
+ }
+ ++count;
+ return KEEP_SLOT;
+ },
+ TypedSlotSet::KEEP_EMPTY_CHUNKS);
+ CHECK_EQ(2 * kEntries, count);
+ set1.Iterate(
+ [](SlotType slot_type, Address slot_addr) {
+ CHECK(false); // Unreachable.
+ return KEEP_SLOT;
+ },
+ TypedSlotSet::KEEP_EMPTY_CHUNKS);
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/heap/spaces-unittest.cc b/deps/v8/test/unittests/heap/spaces-unittest.cc
index 5266e54e09..de4bd39e1e 100644
--- a/deps/v8/test/unittests/heap/spaces-unittest.cc
+++ b/deps/v8/test/unittests/heap/spaces-unittest.cc
@@ -36,7 +36,7 @@ TEST_F(SpacesTest, CompactionSpaceMerge) {
const int kExpectedPages =
(kNumObjects + kNumObjectsPerPage - 1) / kNumObjectsPerPage;
for (int i = 0; i < kNumObjects; i++) {
- HeapObject* object =
+ HeapObject object =
compaction_space->AllocateRawUnaligned(kMaxRegularHeapObjectSize)
.ToObjectChecked();
heap->CreateFillerObjectAt(object->address(), kMaxRegularHeapObjectSize,
@@ -54,13 +54,13 @@ TEST_F(SpacesTest, CompactionSpaceMerge) {
TEST_F(SpacesTest, WriteBarrierFromHeapObject) {
constexpr Address address1 = Page::kPageSize;
- HeapObject* object1 = reinterpret_cast<HeapObject*>(address1);
+ HeapObject object1 = HeapObject::unchecked_cast(Object(address1));
MemoryChunk* chunk1 = MemoryChunk::FromHeapObject(object1);
heap_internals::MemoryChunk* slim_chunk1 =
heap_internals::MemoryChunk::FromHeapObject(object1);
EXPECT_EQ(static_cast<void*>(chunk1), static_cast<void*>(slim_chunk1));
constexpr Address address2 = 2 * Page::kPageSize - 1;
- HeapObject* object2 = reinterpret_cast<HeapObject*>(address2);
+ HeapObject object2 = HeapObject::unchecked_cast(Object(address2));
MemoryChunk* chunk2 = MemoryChunk::FromHeapObject(object2);
heap_internals::MemoryChunk* slim_chunk2 =
heap_internals::MemoryChunk::FromHeapObject(object2);
@@ -68,8 +68,9 @@ TEST_F(SpacesTest, WriteBarrierFromHeapObject) {
}
TEST_F(SpacesTest, WriteBarrierIsMarking) {
- char memory[256];
- memset(&memory, 0, sizeof(memory));
+ const size_t kSizeOfMemoryChunk = sizeof(MemoryChunk);
+ char memory[kSizeOfMemoryChunk];
+ memset(&memory, 0, kSizeOfMemoryChunk);
MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>(&memory);
heap_internals::MemoryChunk* slim_chunk =
reinterpret_cast<heap_internals::MemoryChunk*>(&memory);
@@ -84,8 +85,9 @@ TEST_F(SpacesTest, WriteBarrierIsMarking) {
}
TEST_F(SpacesTest, WriteBarrierInNewSpaceToSpace) {
- char memory[256];
- memset(&memory, 0, sizeof(memory));
+ const size_t kSizeOfMemoryChunk = sizeof(MemoryChunk);
+ char memory[kSizeOfMemoryChunk];
+ memset(&memory, 0, kSizeOfMemoryChunk);
MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>(&memory);
heap_internals::MemoryChunk* slim_chunk =
reinterpret_cast<heap_internals::MemoryChunk*>(&memory);
@@ -100,8 +102,9 @@ TEST_F(SpacesTest, WriteBarrierInNewSpaceToSpace) {
}
TEST_F(SpacesTest, WriteBarrierInNewSpaceFromSpace) {
- char memory[256];
- memset(&memory, 0, sizeof(memory));
+ const size_t kSizeOfMemoryChunk = sizeof(MemoryChunk);
+ char memory[kSizeOfMemoryChunk];
+ memset(&memory, 0, kSizeOfMemoryChunk);
MemoryChunk* chunk = reinterpret_cast<MemoryChunk*>(&memory);
heap_internals::MemoryChunk* slim_chunk =
reinterpret_cast<heap_internals::MemoryChunk*>(&memory);
diff --git a/deps/v8/test/unittests/heap/unmapper-unittest.cc b/deps/v8/test/unittests/heap/unmapper-unittest.cc
index e28e50e3b7..5b783c42b5 100644
--- a/deps/v8/test/unittests/heap/unmapper-unittest.cc
+++ b/deps/v8/test/unittests/heap/unmapper-unittest.cc
@@ -2,26 +2,237 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifdef __linux__
-#include <sys/mman.h>
-#undef MAP_TYPE
-#endif // __linux__
+#include <map>
+#include "src/base/region-allocator.h"
#include "src/heap/heap-inl.h"
#include "src/heap/spaces-inl.h"
#include "src/isolate.h"
+#include "src/ostreams.h"
#include "test/unittests/test-utils.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace v8 {
namespace internal {
+// This is a v8::PageAllocator implementation that decorates provided page
+// allocator object with page tracking functionality.
+class TrackingPageAllocator : public ::v8::PageAllocator {
+ public:
+ explicit TrackingPageAllocator(v8::PageAllocator* page_allocator)
+ : page_allocator_(page_allocator),
+ allocate_page_size_(page_allocator_->AllocatePageSize()),
+ commit_page_size_(page_allocator_->CommitPageSize()),
+ region_allocator_(kNullAddress, size_t{0} - commit_page_size_,
+ commit_page_size_) {
+ CHECK_NOT_NULL(page_allocator);
+ CHECK(IsAligned(allocate_page_size_, commit_page_size_));
+ }
+ ~TrackingPageAllocator() override = default;
+
+ size_t AllocatePageSize() override { return allocate_page_size_; }
+
+ size_t CommitPageSize() override { return commit_page_size_; }
+
+ void SetRandomMmapSeed(int64_t seed) override {
+ return page_allocator_->SetRandomMmapSeed(seed);
+ }
+
+ void* GetRandomMmapAddr() override {
+ return page_allocator_->GetRandomMmapAddr();
+ }
+
+ void* AllocatePages(void* address, size_t size, size_t alignment,
+ PageAllocator::Permission access) override {
+ void* result =
+ page_allocator_->AllocatePages(address, size, alignment, access);
+ if (result) {
+ // Mark pages as used.
+ Address current_page = reinterpret_cast<Address>(result);
+ CHECK(IsAligned(current_page, allocate_page_size_));
+ CHECK(IsAligned(size, allocate_page_size_));
+ CHECK(region_allocator_.AllocateRegionAt(current_page, size));
+ Address end = current_page + size;
+ while (current_page < end) {
+ page_permissions_.insert({current_page, access});
+ current_page += commit_page_size_;
+ }
+ }
+ return result;
+ }
+
+ bool FreePages(void* address, size_t size) override {
+ bool result = page_allocator_->FreePages(address, size);
+ if (result) {
+ // Mark pages as free.
+ Address start = reinterpret_cast<Address>(address);
+ CHECK(IsAligned(start, allocate_page_size_));
+ CHECK(IsAligned(size, allocate_page_size_));
+ size_t freed_size = region_allocator_.FreeRegion(start);
+ CHECK(IsAligned(freed_size, commit_page_size_));
+ CHECK_EQ(RoundUp(freed_size, allocate_page_size_), size);
+ auto start_iter = page_permissions_.find(start);
+ CHECK_NE(start_iter, page_permissions_.end());
+ auto end_iter = page_permissions_.lower_bound(start + size);
+ page_permissions_.erase(start_iter, end_iter);
+ }
+ return result;
+ }
+
+ bool ReleasePages(void* address, size_t size, size_t new_size) override {
+ bool result = page_allocator_->ReleasePages(address, size, new_size);
+ if (result) {
+ Address start = reinterpret_cast<Address>(address);
+ CHECK(IsAligned(start, allocate_page_size_));
+ CHECK(IsAligned(size, commit_page_size_));
+ CHECK(IsAligned(new_size, commit_page_size_));
+ CHECK_LT(new_size, size);
+ CHECK_EQ(region_allocator_.TrimRegion(start, new_size), size - new_size);
+ auto start_iter = page_permissions_.find(start + new_size);
+ CHECK_NE(start_iter, page_permissions_.end());
+ auto end_iter = page_permissions_.lower_bound(start + size);
+ page_permissions_.erase(start_iter, end_iter);
+ }
+ return result;
+ }
+
+ bool SetPermissions(void* address, size_t size,
+ PageAllocator::Permission access) override {
+ bool result = page_allocator_->SetPermissions(address, size, access);
+ if (result) {
+ UpdatePagePermissions(reinterpret_cast<Address>(address), size, access);
+ }
+ return result;
+ }
+
+ // Returns true if all the allocated pages were freed.
+ bool IsEmpty() { return page_permissions_.empty(); }
+
+ void CheckIsFree(Address address, size_t size) {
+ CHECK(IsAligned(address, allocate_page_size_));
+ CHECK(IsAligned(size, allocate_page_size_));
+ EXPECT_TRUE(region_allocator_.IsFree(address, size));
+ }
+
+ void CheckPagePermissions(Address address, size_t size,
+ PageAllocator::Permission access) {
+ ForEachPage(address, size, [=](PagePermissionsMap::value_type* value) {
+ EXPECT_EQ(access, value->second);
+ });
+ }
+
+ void Print(const char* comment) const {
+ i::StdoutStream os;
+ os << "\n========================================="
+ << "\nTracingPageAllocator state: ";
+ if (comment) os << comment;
+ os << "\n-----------------------------------------\n";
+ region_allocator_.Print(os);
+ os << "-----------------------------------------"
+ << "\nPage permissions:";
+ if (page_permissions_.empty()) {
+ os << " empty\n";
+ return;
+ }
+ os << "\n" << std::hex << std::showbase;
+
+ Address contiguous_region_start = static_cast<Address>(-1);
+ Address contiguous_region_end = contiguous_region_start;
+ PageAllocator::Permission contiguous_region_access =
+ PageAllocator::kNoAccess;
+ for (auto& pair : page_permissions_) {
+ if (contiguous_region_end == pair.first &&
+ pair.second == contiguous_region_access) {
+ contiguous_region_end += commit_page_size_;
+ continue;
+ }
+ if (contiguous_region_start != contiguous_region_end) {
+ PrintRegion(os, contiguous_region_start, contiguous_region_end,
+ contiguous_region_access);
+ }
+ contiguous_region_start = pair.first;
+ contiguous_region_end = pair.first + commit_page_size_;
+ contiguous_region_access = pair.second;
+ }
+ if (contiguous_region_start != contiguous_region_end) {
+ PrintRegion(os, contiguous_region_start, contiguous_region_end,
+ contiguous_region_access);
+ }
+ }
+
+ private:
+ typedef std::map<Address, PageAllocator::Permission> PagePermissionsMap;
+ typedef std::function<void(PagePermissionsMap::value_type*)> ForEachFn;
+
+ static void PrintRegion(std::ostream& os, Address start, Address end,
+ PageAllocator::Permission access) {
+ os << " page: [" << start << ", " << end << "), access: ";
+ switch (access) {
+ case PageAllocator::kNoAccess:
+ os << "--";
+ break;
+ case PageAllocator::kRead:
+ os << "R";
+ break;
+ case PageAllocator::kReadWrite:
+ os << "RW";
+ break;
+ case PageAllocator::kReadWriteExecute:
+ os << "RWX";
+ break;
+ case PageAllocator::kReadExecute:
+ os << "RX";
+ break;
+ }
+ os << "\n";
+ }
+
+ void ForEachPage(Address address, size_t size, const ForEachFn& fn) {
+ CHECK(IsAligned(address, commit_page_size_));
+ CHECK(IsAligned(size, commit_page_size_));
+ auto start_iter = page_permissions_.find(address);
+ // Start page must exist in page_permissions_.
+ CHECK_NE(start_iter, page_permissions_.end());
+ auto end_iter = page_permissions_.find(address + size - commit_page_size_);
+ // Ensure the last but one page exists in page_permissions_.
+ CHECK_NE(end_iter, page_permissions_.end());
+ // Now make it point to the next element in order to also process is by the
+ // following for loop.
+ ++end_iter;
+ for (auto iter = start_iter; iter != end_iter; ++iter) {
+ PagePermissionsMap::value_type& pair = *iter;
+ fn(&pair);
+ }
+ }
+
+ void UpdatePagePermissions(Address address, size_t size,
+ PageAllocator::Permission access) {
+ ForEachPage(address, size, [=](PagePermissionsMap::value_type* value) {
+ value->second = access;
+ });
+ }
+
+ v8::PageAllocator* const page_allocator_;
+ const size_t allocate_page_size_;
+ const size_t commit_page_size_;
+ // Region allocator tracks page allocation/deallocation requests.
+ base::RegionAllocator region_allocator_;
+ // This map keeps track of allocated pages' permissions.
+ PagePermissionsMap page_permissions_;
+};
+
class SequentialUnmapperTest : public TestWithIsolate {
public:
SequentialUnmapperTest() = default;
~SequentialUnmapperTest() override = default;
static void SetUpTestCase() {
+ CHECK_NULL(tracking_page_allocator_);
+ old_page_allocator_ = GetPlatformPageAllocator();
+ tracking_page_allocator_ = new TrackingPageAllocator(old_page_allocator_);
+ CHECK(tracking_page_allocator_->IsEmpty());
+ CHECK_EQ(old_page_allocator_,
+ SetPlatformPageAllocatorForTesting(tracking_page_allocator_));
old_flag_ = i::FLAG_concurrent_sweeping;
i::FLAG_concurrent_sweeping = false;
TestWithIsolate::SetUpTestCase();
@@ -30,57 +241,91 @@ class SequentialUnmapperTest : public TestWithIsolate {
static void TearDownTestCase() {
TestWithIsolate::TearDownTestCase();
i::FLAG_concurrent_sweeping = old_flag_;
+ CHECK(tracking_page_allocator_->IsEmpty());
+ delete tracking_page_allocator_;
+ tracking_page_allocator_ = nullptr;
}
Heap* heap() { return isolate()->heap(); }
MemoryAllocator* allocator() { return heap()->memory_allocator(); }
MemoryAllocator::Unmapper* unmapper() { return allocator()->unmapper(); }
+ TrackingPageAllocator* tracking_page_allocator() {
+ return tracking_page_allocator_;
+ }
+
private:
+ static TrackingPageAllocator* tracking_page_allocator_;
+ static v8::PageAllocator* old_page_allocator_;
static bool old_flag_;
DISALLOW_COPY_AND_ASSIGN(SequentialUnmapperTest);
};
+TrackingPageAllocator* SequentialUnmapperTest::tracking_page_allocator_ =
+ nullptr;
+v8::PageAllocator* SequentialUnmapperTest::old_page_allocator_ = nullptr;
bool SequentialUnmapperTest::old_flag_;
-#ifdef __linux__
-
// See v8:5945.
TEST_F(SequentialUnmapperTest, UnmapOnTeardownAfterAlreadyFreeingPooled) {
- Page* page =
- allocator()->AllocatePage(MemoryAllocator::PageAreaSize(OLD_SPACE),
- static_cast<PagedSpace*>(heap()->old_space()),
- Executability::NOT_EXECUTABLE);
+ Page* page = allocator()->AllocatePage(
+ MemoryChunkLayout::AllocatableMemoryInDataPage(),
+ static_cast<PagedSpace*>(heap()->old_space()),
+ Executability::NOT_EXECUTABLE);
EXPECT_NE(nullptr, page);
- const int page_size = getpagesize();
- void* start_address = reinterpret_cast<void*>(page->address());
- EXPECT_EQ(0, msync(start_address, page_size, MS_SYNC));
+ const size_t page_size = tracking_page_allocator()->AllocatePageSize();
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kReadWrite);
allocator()->Free<MemoryAllocator::kPooledAndQueue>(page);
- EXPECT_EQ(0, msync(start_address, page_size, MS_SYNC));
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kReadWrite);
unmapper()->FreeQueuedChunks();
- EXPECT_EQ(0, msync(start_address, page_size, MS_SYNC));
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kNoAccess);
unmapper()->TearDown();
- EXPECT_EQ(-1, msync(start_address, page_size, MS_SYNC));
+ if (i_isolate()->isolate_allocation_mode() ==
+ IsolateAllocationMode::kInV8Heap) {
+ // In this mode Isolate uses bounded page allocator which allocates pages
+ // inside prereserved region. Thus these pages are kept reserved until
+ // the Isolate dies.
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kNoAccess);
+ } else {
+ CHECK_EQ(IsolateAllocationMode::kInCppHeap,
+ i_isolate()->isolate_allocation_mode());
+ tracking_page_allocator()->CheckIsFree(page->address(), page_size);
+ }
}
// See v8:5945.
TEST_F(SequentialUnmapperTest, UnmapOnTeardown) {
- Page* page =
- allocator()->AllocatePage(MemoryAllocator::PageAreaSize(OLD_SPACE),
- static_cast<PagedSpace*>(heap()->old_space()),
- Executability::NOT_EXECUTABLE);
+ Page* page = allocator()->AllocatePage(
+ MemoryChunkLayout::AllocatableMemoryInDataPage(),
+ static_cast<PagedSpace*>(heap()->old_space()),
+ Executability::NOT_EXECUTABLE);
EXPECT_NE(nullptr, page);
- const int page_size = getpagesize();
- void* start_address = reinterpret_cast<void*>(page->address());
- EXPECT_EQ(0, msync(start_address, page_size, MS_SYNC));
+ const size_t page_size = tracking_page_allocator()->AllocatePageSize();
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kReadWrite);
+
allocator()->Free<MemoryAllocator::kPooledAndQueue>(page);
- EXPECT_EQ(0, msync(start_address, page_size, MS_SYNC));
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kReadWrite);
unmapper()->TearDown();
- EXPECT_EQ(-1, msync(start_address, page_size, MS_SYNC));
+ if (i_isolate()->isolate_allocation_mode() ==
+ IsolateAllocationMode::kInV8Heap) {
+ // In this mode Isolate uses bounded page allocator which allocates pages
+ // inside prereserved region. Thus these pages are kept reserved until
+ // the Isolate dies.
+ tracking_page_allocator()->CheckPagePermissions(page->address(), page_size,
+ PageAllocator::kNoAccess);
+ } else {
+ CHECK_EQ(IsolateAllocationMode::kInCppHeap,
+ i_isolate()->isolate_allocation_mode());
+ tracking_page_allocator()->CheckIsFree(page->address(), page_size);
+ }
}
-#endif // __linux__
-
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc
index a2c8d94793..ed53b8b0d2 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc
@@ -13,6 +13,7 @@
#include "src/interpreter/bytecode-label.h"
#include "src/interpreter/bytecode-register-allocator.h"
#include "src/objects-inl.h"
+#include "src/objects/smi.h"
#include "test/unittests/interpreter/bytecode-utils.h"
#include "test/unittests/test-utils.h"
@@ -54,7 +55,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CreateArguments(CreateArgumentsType::kRestParameter);
// Emit constant loads.
- builder.LoadLiteral(Smi::kZero)
+ builder.LoadLiteral(Smi::zero())
.StoreAccumulatorInRegister(reg)
.LoadLiteral(Smi::FromInt(8))
.CompareOperation(Token::Value::EQ, reg,
@@ -179,7 +180,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
// Emit literal creation operations.
builder.CreateRegExpLiteral(ast_factory.GetOneByteString("a"), 0, 0);
builder.CreateArrayLiteral(0, 0, 0);
- builder.CreateObjectLiteral(0, 0, 0, reg);
+ builder.CreateObjectLiteral(0, 0, 0);
// Emit tagged template operations.
builder.GetTemplateObject(0, 0);
@@ -380,7 +381,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
.CreateArrayLiteral(0, 0, 0)
.CreateEmptyArrayLiteral(0)
.CreateArrayFromIterable()
- .CreateObjectLiteral(0, 0, 0, reg)
+ .CreateObjectLiteral(0, 0, 0)
.CreateEmptyObjectLiteral()
.CloneObject(reg, 0, 0);
@@ -488,12 +489,12 @@ TEST_F(BytecodeArrayBuilderTest, FrameSizesLookGood) {
BytecodeArrayBuilder builder(zone(), 1, locals);
BytecodeRegisterAllocator* allocator(builder.register_allocator());
for (int i = 0; i < locals; i++) {
- builder.LoadLiteral(Smi::kZero);
+ builder.LoadLiteral(Smi::zero());
builder.StoreAccumulatorInRegister(Register(i));
}
for (int i = 0; i < temps; i++) {
Register temp = allocator->NewRegister();
- builder.LoadLiteral(Smi::kZero);
+ builder.LoadLiteral(Smi::zero());
builder.StoreAccumulatorInRegister(temp);
// Ensure temporaries are used so not optimized away by the
// register optimizer.
diff --git a/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
index 69d0e96507..ec70605dde 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc
@@ -7,6 +7,7 @@
#include "src/interpreter/bytecode-array-builder.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/objects-inl.h"
+#include "src/objects/smi.h"
#include "test/unittests/interpreter/bytecode-utils.h"
#include "test/unittests/test-utils.h"
@@ -29,9 +30,9 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
diff --git a/deps/v8/test/unittests/interpreter/bytecode-array-random-iterator-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-array-random-iterator-unittest.cc
index 71c79300f3..2e2d92628f 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-array-random-iterator-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-array-random-iterator-unittest.cc
@@ -7,6 +7,7 @@
#include "src/interpreter/bytecode-array-builder.h"
#include "src/interpreter/bytecode-array-random-iterator.h"
#include "src/objects-inl.h"
+#include "src/objects/smi.h"
#include "test/unittests/interpreter/bytecode-utils.h"
#include "test/unittests/test-utils.h"
@@ -29,9 +30,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidBeforeStart) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
@@ -83,9 +84,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidAfterEnd) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
@@ -137,9 +138,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesFirst) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
@@ -195,9 +196,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesLast) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
@@ -254,9 +255,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
@@ -439,9 +440,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
@@ -718,9 +719,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) {
isolate()->heap()->HashSeed());
double heap_num_0 = 2.718;
double heap_num_1 = 2.0 * Smi::kMaxValue;
- Smi* zero = Smi::kZero;
- Smi* smi_0 = Smi::FromInt(64);
- Smi* smi_1 = Smi::FromInt(-65536);
+ Smi zero = Smi::zero();
+ Smi smi_0 = Smi::FromInt(64);
+ Smi smi_1 = Smi::FromInt(-65536);
Register reg_0(0);
Register reg_1(1);
RegisterList pair = BytecodeUtils::NewRegisterList(0, 2);
diff --git a/deps/v8/test/unittests/interpreter/bytecode-decoder-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-decoder-unittest.cc
index eb4fdbb745..9c010f25e3 100644
--- a/deps/v8/test/unittests/interpreter/bytecode-decoder-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecode-decoder-unittest.cc
@@ -58,11 +58,10 @@ TEST(BytecodeDecoder, DecodeBytecodeAndOperands) {
2,
3,
" Ldar a1"},
- {{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165),
- R16(137)},
- 9,
+ {{B(Wide), B(CreateObjectLiteral), U16(513), U16(1027), U8(165)},
+ 7,
0,
- "CreateObjectLiteral.Wide [513], [1027], #165, r137"},
+ "CreateObjectLiteral.Wide [513], [1027], #165"},
{{B(ExtraWide), B(JumpIfNull), U32(123456789)},
6,
0,
diff --git a/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc b/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc
index ce6ba81fc1..16b4e80489 100644
--- a/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/bytecodes-unittest.cc
@@ -88,7 +88,7 @@ TEST(OperandScaling, ScalableAndNonScalable) {
CHECK_EQ(Bytecodes::Size(Bytecode::kCallRuntime, operand_scale),
1 + 2 + 2 * scale);
CHECK_EQ(Bytecodes::Size(Bytecode::kCreateObjectLiteral, operand_scale),
- 1 + 2 * scale + 1 + 1 * scale);
+ 1 + 2 * scale + 1);
CHECK_EQ(Bytecodes::Size(Bytecode::kTestIn, operand_scale), 1 + scale);
}
}
diff --git a/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc b/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc
index 46bbb900c0..55f1cacf56 100644
--- a/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc
+++ b/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc
@@ -138,7 +138,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) {
CHECK_EQ(operand_size, OperandSize::kByte);
}
for (size_t i = 0; i < duplicates_in_idx8_space; i++) {
- Smi* value = Smi::FromInt(static_cast<int>(2 * k8BitCapacity + i));
+ Smi value = Smi::FromInt(static_cast<int>(2 * k8BitCapacity + i));
size_t index = builder.CommitReservedEntry(OperandSize::kByte, value);
CHECK_EQ(index, k8BitCapacity - reserved + i);
}
@@ -155,13 +155,13 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) {
// Check all committed values match expected
for (size_t i = 0; i < k8BitCapacity - reserved; i++) {
- Object* value = constant_array->get(static_cast<int>(i));
- Smi* smi = Smi::FromInt(static_cast<int>(i));
+ Object value = constant_array->get(static_cast<int>(i));
+ Smi smi = Smi::FromInt(static_cast<int>(i));
CHECK(value->SameValue(smi));
}
for (size_t i = k8BitCapacity; i < 2 * k8BitCapacity + reserved; i++) {
- Object* value = constant_array->get(static_cast<int>(i));
- Smi* smi = Smi::FromInt(static_cast<int>(i - reserved));
+ Object value = constant_array->get(static_cast<int>(i));
+ Smi smi = Smi::FromInt(static_cast<int>(i - reserved));
CHECK(value->SameValue(smi));
}
}
@@ -207,7 +207,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithWideReservations) {
CHECK_EQ(constant_array->length(),
static_cast<int>(k8BitCapacity + reserved));
for (size_t i = 0; i < k8BitCapacity + reserved; i++) {
- Object* value = constant_array->get(static_cast<int>(i));
+ Object value = constant_array->get(static_cast<int>(i));
CHECK(value->SameValue(*isolate()->factory()->NewNumberFromSize(i)));
}
}
@@ -237,8 +237,8 @@ TEST_F(ConstantArrayBuilderTest, GapFilledWhenLowReservationCommitted) {
Handle<FixedArray> constant_array = builder.ToFixedArray(isolate());
CHECK_EQ(constant_array->length(), static_cast<int>(2 * k8BitCapacity));
for (size_t i = 0; i < k8BitCapacity; i++) {
- Object* original = constant_array->get(static_cast<int>(k8BitCapacity + i));
- Object* duplicate = constant_array->get(static_cast<int>(i));
+ Object original = constant_array->get(static_cast<int>(k8BitCapacity + i));
+ Object duplicate = constant_array->get(static_cast<int>(i));
CHECK(original->SameValue(duplicate));
Handle<Object> reference = isolate()->factory()->NewNumberFromSize(i);
CHECK(original->SameValue(*reference));
diff --git a/deps/v8/test/unittests/microtask-queue-unittest.cc b/deps/v8/test/unittests/microtask-queue-unittest.cc
new file mode 100644
index 0000000000..cc2c7f0de7
--- /dev/null
+++ b/deps/v8/test/unittests/microtask-queue-unittest.cc
@@ -0,0 +1,187 @@
+// 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.
+
+#include "src/microtask-queue.h"
+
+#include <algorithm>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "src/heap/factory.h"
+#include "src/objects/foreign.h"
+#include "src/visitors.h"
+#include "test/unittests/test-utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+
+using Closure = std::function<void()>;
+
+void RunStdFunction(void* data) {
+ std::unique_ptr<Closure> f(static_cast<Closure*>(data));
+ (*f)();
+}
+
+class MicrotaskQueueTest : public TestWithNativeContext {
+ public:
+ template <typename F>
+ Handle<Microtask> NewMicrotask(F&& f) {
+ Handle<Foreign> runner =
+ factory()->NewForeign(reinterpret_cast<Address>(&RunStdFunction));
+ Handle<Foreign> data = factory()->NewForeign(
+ reinterpret_cast<Address>(new Closure(std::forward<F>(f))));
+ return factory()->NewCallbackTask(runner, data);
+ }
+
+ void SetUp() override {
+ microtask_queue_ = MicrotaskQueue::New(isolate());
+ native_context()->set_microtask_queue(microtask_queue());
+ }
+
+ void TearDown() override {
+ if (microtask_queue()) {
+ microtask_queue()->RunMicrotasks(isolate());
+ context()->DetachGlobal();
+ }
+ }
+
+ MicrotaskQueue* microtask_queue() const { return microtask_queue_.get(); }
+
+ void ClearTestMicrotaskQueue() {
+ context()->DetachGlobal();
+ microtask_queue_ = nullptr;
+ }
+
+ private:
+ std::unique_ptr<MicrotaskQueue> microtask_queue_;
+};
+
+class RecordingVisitor : public RootVisitor {
+ public:
+ RecordingVisitor() = default;
+ ~RecordingVisitor() override = default;
+
+ void VisitRootPointers(Root root, const char* description,
+ FullObjectSlot start, FullObjectSlot end) override {
+ for (FullObjectSlot current = start; current != end; ++current) {
+ visited_.push_back(*current);
+ }
+ }
+
+ const std::vector<Object>& visited() const { return visited_; }
+
+ private:
+ std::vector<Object> visited_;
+};
+
+// Sanity check. Ensure a microtask is stored in a queue and run.
+TEST_F(MicrotaskQueueTest, EnqueueAndRun) {
+ bool ran = false;
+ EXPECT_EQ(0, microtask_queue()->capacity());
+ EXPECT_EQ(0, microtask_queue()->size());
+ microtask_queue()->EnqueueMicrotask(*NewMicrotask([&ran] {
+ EXPECT_FALSE(ran);
+ ran = true;
+ }));
+ EXPECT_EQ(MicrotaskQueue::kMinimumCapacity, microtask_queue()->capacity());
+ EXPECT_EQ(1, microtask_queue()->size());
+ microtask_queue()->RunMicrotasks(isolate());
+ EXPECT_TRUE(ran);
+ EXPECT_EQ(0, microtask_queue()->size());
+}
+
+// Check for a buffer growth.
+TEST_F(MicrotaskQueueTest, BufferGrowth) {
+ int count = 0;
+
+ // Enqueue and flush the queue first to have non-zero |start_|.
+ microtask_queue()->EnqueueMicrotask(
+ *NewMicrotask([&count] { EXPECT_EQ(0, count++); }));
+ microtask_queue()->RunMicrotasks(isolate());
+
+ EXPECT_LT(0, microtask_queue()->capacity());
+ EXPECT_EQ(0, microtask_queue()->size());
+ EXPECT_EQ(1, microtask_queue()->start());
+
+ // Fill the queue with Microtasks.
+ for (int i = 1; i <= MicrotaskQueue::kMinimumCapacity; ++i) {
+ microtask_queue()->EnqueueMicrotask(
+ *NewMicrotask([&count, i] { EXPECT_EQ(i, count++); }));
+ }
+ EXPECT_EQ(MicrotaskQueue::kMinimumCapacity, microtask_queue()->capacity());
+ EXPECT_EQ(MicrotaskQueue::kMinimumCapacity, microtask_queue()->size());
+
+ // Add another to grow the ring buffer.
+ microtask_queue()->EnqueueMicrotask(*NewMicrotask(
+ [&] { EXPECT_EQ(MicrotaskQueue::kMinimumCapacity + 1, count++); }));
+
+ EXPECT_LT(MicrotaskQueue::kMinimumCapacity, microtask_queue()->capacity());
+ EXPECT_EQ(MicrotaskQueue::kMinimumCapacity + 1, microtask_queue()->size());
+
+ // Run all pending Microtasks to ensure they run in the proper order.
+ microtask_queue()->RunMicrotasks(isolate());
+ EXPECT_EQ(MicrotaskQueue::kMinimumCapacity + 2, count);
+}
+
+// MicrotaskQueue instances form a doubly linked list.
+TEST_F(MicrotaskQueueTest, InstanceChain) {
+ ClearTestMicrotaskQueue();
+
+ MicrotaskQueue* default_mtq = isolate()->default_microtask_queue();
+ ASSERT_TRUE(default_mtq);
+ EXPECT_EQ(default_mtq, default_mtq->next());
+ EXPECT_EQ(default_mtq, default_mtq->prev());
+
+ // Create two instances, and check their connection.
+ // The list contains all instances in the creation order, and the next of the
+ // last instance is the first instance:
+ // default_mtq -> mtq1 -> mtq2 -> default_mtq.
+ std::unique_ptr<MicrotaskQueue> mtq1 = MicrotaskQueue::New(isolate());
+ std::unique_ptr<MicrotaskQueue> mtq2 = MicrotaskQueue::New(isolate());
+ EXPECT_EQ(default_mtq->next(), mtq1.get());
+ EXPECT_EQ(mtq1->next(), mtq2.get());
+ EXPECT_EQ(mtq2->next(), default_mtq);
+ EXPECT_EQ(default_mtq, mtq1->prev());
+ EXPECT_EQ(mtq1.get(), mtq2->prev());
+ EXPECT_EQ(mtq2.get(), default_mtq->prev());
+
+ // Deleted item should be also removed from the list.
+ mtq1 = nullptr;
+ EXPECT_EQ(default_mtq->next(), mtq2.get());
+ EXPECT_EQ(mtq2->next(), default_mtq);
+ EXPECT_EQ(default_mtq, mtq2->prev());
+ EXPECT_EQ(mtq2.get(), default_mtq->prev());
+}
+
+// Pending Microtasks in MicrotaskQueues are strong roots. Ensure they are
+// visited exactly once.
+TEST_F(MicrotaskQueueTest, VisitRoot) {
+ // Ensure that the ring buffer has separate in-use region.
+ for (int i = 0; i < MicrotaskQueue::kMinimumCapacity / 2 + 1; ++i) {
+ microtask_queue()->EnqueueMicrotask(*NewMicrotask([] {}));
+ }
+ microtask_queue()->RunMicrotasks(isolate());
+
+ std::vector<Object> expected;
+ for (int i = 0; i < MicrotaskQueue::kMinimumCapacity / 2 + 1; ++i) {
+ Handle<Microtask> microtask = NewMicrotask([] {});
+ expected.push_back(*microtask);
+ microtask_queue()->EnqueueMicrotask(*microtask);
+ }
+ EXPECT_GT(microtask_queue()->start() + microtask_queue()->size(),
+ microtask_queue()->capacity());
+
+ RecordingVisitor visitor;
+ microtask_queue()->IterateMicrotasks(&visitor);
+
+ std::vector<Object> actual = visitor.visited();
+ std::sort(expected.begin(), expected.end());
+ std::sort(actual.begin(), actual.end());
+ EXPECT_EQ(expected, actual);
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/objects/microtask-queue-unittest.cc b/deps/v8/test/unittests/objects/microtask-queue-unittest.cc
deleted file mode 100644
index 2b237ebc50..0000000000
--- a/deps/v8/test/unittests/objects/microtask-queue-unittest.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// 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.
-
-#include "src/objects/microtask-queue-inl.h"
-
-#include "test/unittests/test-utils.h"
-
-namespace v8 {
-namespace internal {
-
-void NoopCallback(void*) {}
-
-class MicrotaskQueueTest : public TestWithIsolate {
- public:
- Handle<Microtask> NewMicrotask() {
- MicrotaskCallback callback = &NoopCallback;
- void* data = nullptr;
- return factory()->NewCallbackTask(
- factory()->NewForeign(reinterpret_cast<Address>(callback)),
- factory()->NewForeign(reinterpret_cast<Address>(data)));
- }
-};
-
-TEST_F(MicrotaskQueueTest, EnqueueMicrotask) {
- Handle<MicrotaskQueue> microtask_queue = factory()->NewMicrotaskQueue();
- Handle<Microtask> microtask = NewMicrotask();
-
- EXPECT_EQ(0, microtask_queue->pending_microtask_count());
- MicrotaskQueue::EnqueueMicrotask(isolate(), microtask_queue, microtask);
- EXPECT_EQ(1, microtask_queue->pending_microtask_count());
- ASSERT_LE(1, microtask_queue->queue()->length());
- EXPECT_EQ(*microtask, microtask_queue->queue()->get(0));
-
- std::vector<Handle<Microtask>> microtasks;
- microtasks.push_back(microtask);
-
- // Queue microtasks until the reallocation happens.
- int queue_capacity = microtask_queue->queue()->length();
- for (int i = 0; i < queue_capacity; ++i) {
- microtask = NewMicrotask();
- MicrotaskQueue::EnqueueMicrotask(isolate(), microtask_queue, microtask);
- microtasks.push_back(microtask);
- }
-
- int num_tasks = static_cast<int>(microtasks.size());
- EXPECT_EQ(num_tasks, microtask_queue->pending_microtask_count());
- ASSERT_LE(num_tasks, microtask_queue->queue()->length());
- for (int i = 0; i < num_tasks; ++i) {
- EXPECT_EQ(*microtasks[i], microtask_queue->queue()->get(i));
- }
-}
-
-} // namespace internal
-} // namespace v8
diff --git a/deps/v8/test/unittests/register-configuration-unittest.cc b/deps/v8/test/unittests/register-configuration-unittest.cc
index f0da8a5b93..15873dd69c 100644
--- a/deps/v8/test/unittests/register-configuration-unittest.cc
+++ b/deps/v8/test/unittests/register-configuration-unittest.cc
@@ -26,10 +26,10 @@ TEST_F(RegisterConfigurationUnitTest, BasicProperties) {
int general_codes[kNumAllocatableGeneralRegs] = {1, 2};
int double_codes[kNumAllocatableDoubleRegs] = {2, 3};
- RegisterConfiguration test(
- kNumGeneralRegs, kNumDoubleRegs, kNumAllocatableGeneralRegs,
- kNumAllocatableDoubleRegs, general_codes, double_codes,
- RegisterConfiguration::OVERLAP, nullptr, nullptr, nullptr, nullptr);
+ RegisterConfiguration test(kNumGeneralRegs, kNumDoubleRegs,
+ kNumAllocatableGeneralRegs,
+ kNumAllocatableDoubleRegs, general_codes,
+ double_codes, RegisterConfiguration::OVERLAP);
EXPECT_EQ(test.num_general_registers(), kNumGeneralRegs);
EXPECT_EQ(test.num_double_registers(), kNumDoubleRegs);
@@ -62,10 +62,10 @@ TEST_F(RegisterConfigurationUnitTest, CombineAliasing) {
int general_codes[] = {1, 2};
int double_codes[] = {2, 3, 16}; // reg 16 should not alias registers 32, 33.
- RegisterConfiguration test(
- kNumGeneralRegs, kNumDoubleRegs, kNumAllocatableGeneralRegs,
- kNumAllocatableDoubleRegs, general_codes, double_codes,
- RegisterConfiguration::COMBINE, nullptr, nullptr, nullptr, nullptr);
+ RegisterConfiguration test(kNumGeneralRegs, kNumDoubleRegs,
+ kNumAllocatableGeneralRegs,
+ kNumAllocatableDoubleRegs, general_codes,
+ double_codes, RegisterConfiguration::COMBINE);
// There are 3 allocatable double regs, but only 2 can alias float regs.
EXPECT_EQ(test.num_allocatable_float_registers(), 4);
diff --git a/deps/v8/test/unittests/regress/regress-crbug-938251-unittest.cc b/deps/v8/test/unittests/regress/regress-crbug-938251-unittest.cc
new file mode 100644
index 0000000000..3a04fc46e6
--- /dev/null
+++ b/deps/v8/test/unittests/regress/regress-crbug-938251-unittest.cc
@@ -0,0 +1,20 @@
+// Copyright 2019 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.
+
+#include "src/heap/factory.h"
+#include "src/isolate.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+
+using NewFixedDoubleArrayTest = TestWithIsolateAndZone;
+
+TEST_F(NewFixedDoubleArrayTest, ThrowOnNegativeLength) {
+ ASSERT_DEATH_IF_SUPPORTED({ factory()->NewFixedDoubleArray(-1); },
+ "Fatal javascript OOM in invalid array length");
+}
+
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/test-helpers.cc b/deps/v8/test/unittests/test-helpers.cc
index 1ff25337e4..53b07da23b 100644
--- a/deps/v8/test/unittests/test-helpers.cc
+++ b/deps/v8/test/unittests/test-helpers.cc
@@ -44,7 +44,7 @@ Handle<SharedFunctionInfo> CreateSharedFunctionInfo(
int function_literal_id = 1;
// Ensure that the function can be compiled lazily.
shared->set_uncompiled_data(
- *isolate->factory()->NewUncompiledDataWithoutPreParsedScope(
+ *isolate->factory()->NewUncompiledDataWithoutPreparseData(
ReadOnlyRoots(isolate).empty_string_handle(), 0, source->length(),
function_literal_id));
// Make sure we have an outer scope info, even though it's empty
diff --git a/deps/v8/test/unittests/test-helpers.h b/deps/v8/test/unittests/test-helpers.h
index fadc0c3e2b..8a4d9f02ce 100644
--- a/deps/v8/test/unittests/test-helpers.h
+++ b/deps/v8/test/unittests/test-helpers.h
@@ -8,7 +8,6 @@
#include <memory>
#include "include/v8.h"
-#include "src/compiler-dispatcher/compiler-dispatcher-job.h"
#include "src/parsing/parse-info.h"
namespace v8 {
diff --git a/deps/v8/test/unittests/test-utils.cc b/deps/v8/test/unittests/test-utils.cc
index 32f405764d..8a31b9ce02 100644
--- a/deps/v8/test/unittests/test-utils.cc
+++ b/deps/v8/test/unittests/test-utils.cc
@@ -15,109 +15,34 @@
namespace v8 {
-// static
-v8::ArrayBuffer::Allocator* TestWithIsolate::array_buffer_allocator_ = nullptr;
-
-// static
-Isolate* TestWithIsolate::isolate_ = nullptr;
-
-TestWithIsolate::TestWithIsolate()
- : isolate_scope_(isolate()), handle_scope_(isolate()) {}
-
-TestWithIsolate::~TestWithIsolate() = default;
-
-// static
-void TestWithIsolate::SetUpTestCase() {
- Test::SetUpTestCase();
- EXPECT_EQ(nullptr, isolate_);
+IsolateWrapper::IsolateWrapper(bool enforce_pointer_compression)
+ : array_buffer_allocator_(
+ v8::ArrayBuffer::Allocator::NewDefaultAllocator()) {
v8::Isolate::CreateParams create_params;
- array_buffer_allocator_ = v8::ArrayBuffer::Allocator::NewDefaultAllocator();
create_params.array_buffer_allocator = array_buffer_allocator_;
- isolate_ = v8::Isolate::New(create_params);
- EXPECT_TRUE(isolate_ != nullptr);
+ if (enforce_pointer_compression) {
+ isolate_ = reinterpret_cast<v8::Isolate*>(
+ i::Isolate::New(i::IsolateAllocationMode::kInV8Heap));
+ v8::Isolate::Initialize(isolate_, create_params);
+ } else {
+ isolate_ = v8::Isolate::New(create_params);
+ }
+ CHECK_NOT_NULL(isolate_);
}
-
-// static
-void TestWithIsolate::TearDownTestCase() {
- ASSERT_TRUE(isolate_ != nullptr);
+IsolateWrapper::~IsolateWrapper() {
v8::Platform* platform = internal::V8::GetCurrentPlatform();
- ASSERT_TRUE(platform != nullptr);
+ CHECK_NOT_NULL(platform);
while (platform::PumpMessageLoop(platform, isolate_)) continue;
isolate_->Dispose();
- isolate_ = nullptr;
delete array_buffer_allocator_;
- Test::TearDownTestCase();
-}
-
-Local<Value> TestWithIsolate::RunJS(const char* source) {
- Local<Script> script =
- v8::Script::Compile(
- isolate()->GetCurrentContext(),
- v8::String::NewFromUtf8(isolate(), source, v8::NewStringType::kNormal)
- .ToLocalChecked())
- .ToLocalChecked();
- return script->Run(isolate()->GetCurrentContext()).ToLocalChecked();
-}
-
-Local<Value> TestWithIsolate::RunJS(
- String::ExternalOneByteStringResource* source) {
- Local<Script> script =
- v8::Script::Compile(
- isolate()->GetCurrentContext(),
- v8::String::NewExternalOneByte(isolate(), source).ToLocalChecked())
- .ToLocalChecked();
- return script->Run(isolate()->GetCurrentContext()).ToLocalChecked();
}
-TestWithContext::TestWithContext()
- : context_(Context::New(isolate())), context_scope_(context_) {}
-
-TestWithContext::~TestWithContext() = default;
-
-v8::Local<v8::String> TestWithContext::NewString(const char* string) {
- return v8::String::NewFromUtf8(v8_isolate(), string,
- v8::NewStringType::kNormal)
- .ToLocalChecked();
-}
-
-void TestWithContext::SetGlobalProperty(const char* name,
- v8::Local<v8::Value> value) {
- CHECK(v8_context()
- ->Global()
- ->Set(v8_context(), NewString(name), value)
- .FromJust());
-}
+// static
+v8::IsolateWrapper* SharedIsolateHolder::isolate_wrapper_ = nullptr;
namespace internal {
-TestWithIsolate::~TestWithIsolate() = default;
-
-TestWithIsolateAndZone::~TestWithIsolateAndZone() = default;
-
-Factory* TestWithIsolate::factory() const { return isolate()->factory(); }
-
-Handle<Object> TestWithIsolate::RunJSInternal(const char* source) {
- return Utils::OpenHandle(*::v8::TestWithIsolate::RunJS(source));
-}
-
-Handle<Object> TestWithIsolate::RunJSInternal(
- ::v8::String::ExternalOneByteStringResource* source) {
- return Utils::OpenHandle(*::v8::TestWithIsolate::RunJS(source));
-}
-
-base::RandomNumberGenerator* TestWithIsolate::random_number_generator() const {
- return isolate()->random_number_generator();
-}
-
-TestWithZone::~TestWithZone() = default;
-
-TestWithNativeContext::~TestWithNativeContext() = default;
-
-Handle<Context> TestWithNativeContext::native_context() const {
- return isolate()->native_context();
-}
-
SaveFlags::SaveFlags() { non_default_flags_ = FlagList::argv(); }
SaveFlags::~SaveFlags() {
diff --git a/deps/v8/test/unittests/test-utils.h b/deps/v8/test/unittests/test-utils.h
index 289ef5edf2..57db1a39e2 100644
--- a/deps/v8/test/unittests/test-utils.h
+++ b/deps/v8/test/unittests/test-utils.h
@@ -8,6 +8,7 @@
#include <vector>
#include "include/v8.h"
+#include "src/api-inl.h"
#include "src/base/macros.h"
#include "src/base/utils/random-number-generator.h"
#include "src/handles.h"
@@ -21,126 +22,286 @@ namespace v8 {
class ArrayBufferAllocator;
-// Use v8::internal::TestWithIsolate if you are testing internals,
-// aka. directly work with Handles.
-class TestWithIsolate : public virtual ::testing::Test {
+// RAII-like Isolate instance wrapper.
+class IsolateWrapper final {
public:
- TestWithIsolate();
- ~TestWithIsolate() override;
+ // When enforce_pointer_compression is true the Isolate is created with
+ // enabled pointer compression. When it's false then the Isolate is created
+ // with the default pointer compression state for current build.
+ explicit IsolateWrapper(bool enforce_pointer_compression = false);
+ ~IsolateWrapper();
- v8::Isolate* isolate() const { return v8_isolate(); }
+ v8::Isolate* isolate() const { return isolate_; }
+
+ private:
+ v8::ArrayBuffer::Allocator* array_buffer_allocator_;
+ v8::Isolate* isolate_;
- v8::Isolate* v8_isolate() const { return isolate_; }
+ DISALLOW_COPY_AND_ASSIGN(IsolateWrapper);
+};
- v8::internal::Isolate* i_isolate() const {
- return reinterpret_cast<v8::internal::Isolate*>(isolate());
+class SharedIsolateHolder final {
+ public:
+ static v8::Isolate* isolate() { return isolate_wrapper_->isolate(); }
+
+ static void CreateIsolate() {
+ CHECK_NULL(isolate_wrapper_);
+ isolate_wrapper_ = new IsolateWrapper();
+ }
+
+ static void DeleteIsolate() {
+ CHECK_NOT_NULL(isolate_wrapper_);
+ delete isolate_wrapper_;
+ isolate_wrapper_ = nullptr;
+ }
+
+ private:
+ static v8::IsolateWrapper* isolate_wrapper_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(SharedIsolateHolder);
+};
+
+//
+// A set of mixins from which the test fixtures will be constructed.
+//
+template <typename TMixin>
+class WithPrivateIsolateMixin : public TMixin {
+ public:
+ explicit WithPrivateIsolateMixin(bool enforce_pointer_compression = false)
+ : isolate_wrapper_(enforce_pointer_compression) {}
+
+ v8::Isolate* v8_isolate() const { return isolate_wrapper_.isolate(); }
+
+ static void SetUpTestCase() { TMixin::SetUpTestCase(); }
+ static void TearDownTestCase() { TMixin::TearDownTestCase(); }
+
+ private:
+ v8::IsolateWrapper isolate_wrapper_;
+
+ DISALLOW_COPY_AND_ASSIGN(WithPrivateIsolateMixin);
+};
+
+template <typename TMixin>
+class WithSharedIsolateMixin : public TMixin {
+ public:
+ WithSharedIsolateMixin() = default;
+
+ v8::Isolate* v8_isolate() const { return SharedIsolateHolder::isolate(); }
+
+ static void SetUpTestCase() {
+ TMixin::SetUpTestCase();
+ SharedIsolateHolder::CreateIsolate();
}
- Local<Value> RunJS(const char* source);
- Local<Value> RunJS(String::ExternalOneByteStringResource* source);
+ static void TearDownTestCase() {
+ SharedIsolateHolder::DeleteIsolate();
+ TMixin::TearDownTestCase();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WithSharedIsolateMixin);
+};
+
+template <typename TMixin>
+class WithPointerCompressionIsolateMixin
+ : public WithPrivateIsolateMixin<TMixin> {
+ public:
+ WithPointerCompressionIsolateMixin()
+ : WithPrivateIsolateMixin<TMixin>(true) {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WithPointerCompressionIsolateMixin);
+};
+
+template <typename TMixin>
+class WithIsolateScopeMixin : public TMixin {
+ public:
+ WithIsolateScopeMixin()
+ : isolate_scope_(v8_isolate()), handle_scope_(v8_isolate()) {}
- static void SetUpTestCase();
- static void TearDownTestCase();
+ v8::Isolate* isolate() const { return v8_isolate(); }
+ v8::Isolate* v8_isolate() const { return TMixin::v8_isolate(); }
+
+ v8::internal::Isolate* i_isolate() const {
+ return reinterpret_cast<v8::internal::Isolate*>(v8_isolate());
+ }
+
+ static void SetUpTestCase() { TMixin::SetUpTestCase(); }
+ static void TearDownTestCase() { TMixin::TearDownTestCase(); }
private:
- static v8::ArrayBuffer::Allocator* array_buffer_allocator_;
- static v8::Isolate* isolate_;
v8::Isolate::Scope isolate_scope_;
v8::HandleScope handle_scope_;
- DISALLOW_COPY_AND_ASSIGN(TestWithIsolate);
+ DISALLOW_COPY_AND_ASSIGN(WithIsolateScopeMixin);
};
-// Use v8::internal::TestWithNativeContext if you are testing internals,
-// aka. directly work with Handles.
-class TestWithContext : public virtual v8::TestWithIsolate {
+template <typename TMixin>
+class WithContextMixin : public TMixin {
public:
- TestWithContext();
- ~TestWithContext() override;
+ WithContextMixin()
+ : context_(Context::New(v8_isolate())), context_scope_(context_) {}
+
+ v8::Isolate* v8_isolate() const { return TMixin::v8_isolate(); }
const Local<Context>& context() const { return v8_context(); }
const Local<Context>& v8_context() const { return context_; }
- v8::Local<v8::String> NewString(const char* string);
- void SetGlobalProperty(const char* name, v8::Local<v8::Value> value);
+ Local<Value> RunJS(const char* source) {
+ return RunJS(v8::String::NewFromUtf8(v8_isolate(), source,
+ v8::NewStringType::kNormal)
+ .ToLocalChecked());
+ }
+
+ Local<Value> RunJS(v8::String::ExternalOneByteStringResource* source) {
+ return RunJS(
+ v8::String::NewExternalOneByte(v8_isolate(), source).ToLocalChecked());
+ }
+
+ v8::Local<v8::String> NewString(const char* string) {
+ return v8::String::NewFromUtf8(v8_isolate(), string,
+ v8::NewStringType::kNormal)
+ .ToLocalChecked();
+ }
+
+ void SetGlobalProperty(const char* name, v8::Local<v8::Value> value) {
+ CHECK(v8_context()
+ ->Global()
+ ->Set(v8_context(), NewString(name), value)
+ .FromJust());
+ }
+
+ static void SetUpTestCase() { TMixin::SetUpTestCase(); }
+ static void TearDownTestCase() { TMixin::TearDownTestCase(); }
private:
- Local<Context> context_;
+ Local<Value> RunJS(Local<String> source) {
+ auto context = v8_isolate()->GetCurrentContext();
+ Local<Script> script =
+ v8::Script::Compile(context, source).ToLocalChecked();
+ return script->Run(context).ToLocalChecked();
+ }
+
+ v8::Local<v8::Context> context_;
v8::Context::Scope context_scope_;
- DISALLOW_COPY_AND_ASSIGN(TestWithContext);
+ DISALLOW_COPY_AND_ASSIGN(WithContextMixin);
};
+// Use v8::internal::TestWithIsolate if you are testing internals,
+// aka. directly work with Handles.
+using TestWithIsolate = //
+ WithIsolateScopeMixin< //
+ WithSharedIsolateMixin< //
+ ::testing::Test>>;
+
+// Use v8::internal::TestWithNativeContext if you are testing internals,
+// aka. directly work with Handles.
+using TestWithContext = //
+ WithContextMixin< //
+ WithIsolateScopeMixin< //
+ WithSharedIsolateMixin< //
+ ::testing::Test>>>;
+
+using TestWithIsolateAndPointerCompression = //
+ WithContextMixin< //
+ WithIsolateScopeMixin< //
+ WithPointerCompressionIsolateMixin< //
+ ::testing::Test>>>;
+
namespace internal {
// Forward declarations.
class Factory;
-
-class TestWithIsolate : public virtual ::v8::TestWithIsolate {
+template <typename TMixin>
+class WithInternalIsolateMixin : public TMixin {
public:
- TestWithIsolate() = default;
- ~TestWithIsolate() override;
+ WithInternalIsolateMixin() = default;
+
+ Factory* factory() const { return isolate()->factory(); }
+ Isolate* isolate() const { return TMixin::i_isolate(); }
+
+ Handle<NativeContext> native_context() const {
+ return isolate()->native_context();
+ }
- Factory* factory() const;
- Isolate* isolate() const { return i_isolate(); }
template <typename T = Object>
Handle<T> RunJS(const char* source) {
return Handle<T>::cast(RunJSInternal(source));
}
- Handle<Object> RunJSInternal(const char* source);
+
+ Handle<Object> RunJSInternal(const char* source) {
+ return Utils::OpenHandle(*TMixin::RunJS(source));
+ }
+
template <typename T = Object>
Handle<T> RunJS(::v8::String::ExternalOneByteStringResource* source) {
return Handle<T>::cast(RunJSInternal(source));
}
- Handle<Object> RunJSInternal(
- ::v8::String::ExternalOneByteStringResource* source);
- base::RandomNumberGenerator* random_number_generator() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestWithIsolate);
-};
+ Handle<Object> RunJSInternal(
+ ::v8::String::ExternalOneByteStringResource* source) {
+ return Utils::OpenHandle(*TMixin::RunJS(source));
+ }
-class TestWithZone : public virtual ::testing::Test {
- public:
- TestWithZone() : zone_(&allocator_, ZONE_NAME) {}
- ~TestWithZone() override;
+ base::RandomNumberGenerator* random_number_generator() const {
+ return isolate()->random_number_generator();
+ }
- Zone* zone() { return &zone_; }
+ static void SetUpTestCase() { TMixin::SetUpTestCase(); }
+ static void TearDownTestCase() { TMixin::TearDownTestCase(); }
private:
- v8::internal::AccountingAllocator allocator_;
- Zone zone_;
-
- DISALLOW_COPY_AND_ASSIGN(TestWithZone);
+ DISALLOW_COPY_AND_ASSIGN(WithInternalIsolateMixin);
};
-class TestWithIsolateAndZone : public virtual TestWithIsolate {
+template <typename TMixin>
+class WithZoneMixin : public TMixin {
public:
- TestWithIsolateAndZone() : zone_(&allocator_, ZONE_NAME) {}
- ~TestWithIsolateAndZone() override;
+ WithZoneMixin() : zone_(&allocator_, ZONE_NAME) {}
Zone* zone() { return &zone_; }
+ static void SetUpTestCase() { TMixin::SetUpTestCase(); }
+ static void TearDownTestCase() { TMixin::TearDownTestCase(); }
+
private:
v8::internal::AccountingAllocator allocator_;
Zone zone_;
- DISALLOW_COPY_AND_ASSIGN(TestWithIsolateAndZone);
+ DISALLOW_COPY_AND_ASSIGN(WithZoneMixin);
};
-class TestWithNativeContext : public virtual ::v8::TestWithContext,
- public virtual TestWithIsolate {
- public:
- TestWithNativeContext() = default;
- ~TestWithNativeContext() override;
-
- Handle<Context> native_context() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestWithNativeContext);
-};
+using TestWithIsolate = //
+ WithInternalIsolateMixin< //
+ WithIsolateScopeMixin< //
+ WithSharedIsolateMixin< //
+ ::testing::Test>>>;
+
+using TestWithZone = WithZoneMixin<::testing::Test>;
+
+using TestWithIsolateAndZone = //
+ WithInternalIsolateMixin< //
+ WithIsolateScopeMixin< //
+ WithSharedIsolateMixin< //
+ WithZoneMixin< //
+ ::testing::Test>>>>;
+
+using TestWithNativeContext = //
+ WithInternalIsolateMixin< //
+ WithContextMixin< //
+ WithIsolateScopeMixin< //
+ WithSharedIsolateMixin< //
+ ::testing::Test>>>>;
+
+using TestWithNativeContextAndZone = //
+ WithZoneMixin< //
+ WithInternalIsolateMixin< //
+ WithContextMixin< //
+ WithIsolateScopeMixin< //
+ WithSharedIsolateMixin< //
+ ::testing::Test>>>>>;
class SaveFlags {
public:
@@ -153,6 +314,14 @@ class SaveFlags {
DISALLOW_COPY_AND_ASSIGN(SaveFlags);
};
+// For GTest.
+inline void PrintTo(Object o, ::std::ostream* os) {
+ *os << reinterpret_cast<void*>(o.ptr());
+}
+inline void PrintTo(Smi o, ::std::ostream* os) {
+ *os << reinterpret_cast<void*>(o.ptr());
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/torque/torque-unittest.cc b/deps/v8/test/unittests/torque/torque-unittest.cc
new file mode 100644
index 0000000000..eca4e6fda2
--- /dev/null
+++ b/deps/v8/test/unittests/torque/torque-unittest.cc
@@ -0,0 +1,21 @@
+// 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.
+
+#include "src/torque/utils.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace torque {
+
+TEST(Torque, StackDeleteRange) {
+ Stack<int> stack = {1, 2, 3, 4, 5, 6, 7};
+ stack.DeleteRange(StackRange{BottomOffset{2}, BottomOffset{4}});
+ Stack<int> result = {1, 2, 5, 6, 7};
+ ASSERT_TRUE(stack == result);
+}
+
+} // namespace torque
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/unicode-unittest.cc b/deps/v8/test/unittests/unicode-unittest.cc
index 068052a3fc..1bede08343 100644
--- a/deps/v8/test/unittests/unicode-unittest.cc
+++ b/deps/v8/test/unittests/unicode-unittest.cc
@@ -29,8 +29,7 @@ template <size_t kBufferSize>
void DecodeUtf16(unibrow::Utf8Decoder<kBufferSize>* decoder,
const std::vector<byte>& bytes,
std::vector<unibrow::uchar>* output) {
- const char* bytes_begin = reinterpret_cast<const char*>(&(*bytes.begin()));
- auto vector = Vector<const char>(bytes_begin, bytes.size());
+ auto vector = Vector<const char>::cast(VectorOf(bytes));
decoder->Reset(vector);
std::vector<uint16_t> utf16(decoder->Utf16Length());
diff --git a/deps/v8/test/unittests/unittests.status b/deps/v8/test/unittests/unittests.status
index f0eef446d1..7582deaedd 100644
--- a/deps/v8/test/unittests/unittests.status
+++ b/deps/v8/test/unittests/unittests.status
@@ -20,4 +20,11 @@
# Uses too much memory.
'Parameterized/WasmCodeManagerTest.GrowingVsFixedModule/Fixed': [SKIP]
}], # '(arch == arm or arch == mips) and not simulator_run'
+
+##############################################################################
+['lite_mode', {
+ # TODO(v8:7777): Re-enable once wasm is supported in jitless mode.
+ 'ValueSerializerTestWithWasm.*': [SKIP],
+}], # lite_mode
+
]
diff --git a/deps/v8/test/unittests/utils-unittest.cc b/deps/v8/test/unittests/utils-unittest.cc
index 0a37e84ab5..c8032d187d 100644
--- a/deps/v8/test/unittests/utils-unittest.cc
+++ b/deps/v8/test/unittests/utils-unittest.cc
@@ -132,5 +132,73 @@ TYPED_TEST(UtilsTest, PassesFilterTest) {
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("a")));
}
+TEST(UtilsTest, IsInBounds) {
+// for column consistency and terseness
+#define INB(x, y, z) EXPECT_TRUE(IsInBounds(x, y, z))
+#define OOB(x, y, z) EXPECT_FALSE(IsInBounds(x, y, z))
+ INB(0, 0, 1);
+ INB(0, 1, 1);
+ INB(1, 0, 1);
+
+ OOB(0, 2, 1);
+ OOB(2, 0, 1);
+
+ INB(0, 0, 2);
+ INB(0, 1, 2);
+ INB(0, 2, 2);
+
+ INB(0, 0, 2);
+ INB(1, 0, 2);
+ INB(2, 0, 2);
+
+ OOB(0, 3, 2);
+ OOB(3, 0, 2);
+
+ INB(0, 1, 2);
+ INB(1, 1, 2);
+
+ OOB(1, 2, 2);
+ OOB(2, 1, 2);
+
+ const size_t max = std::numeric_limits<size_t>::max();
+ const size_t half = max / 2;
+
+ // limit cases.
+ INB(0, 0, max);
+ INB(0, 1, max);
+ INB(1, 0, max);
+ INB(max, 0, max);
+ INB(0, max, max);
+ INB(max - 1, 0, max);
+ INB(0, max - 1, max);
+ INB(max - 1, 1, max);
+ INB(1, max - 1, max);
+
+ INB(half, half, max);
+ INB(half + 1, half, max);
+ INB(half, half + 1, max);
+
+ OOB(max, 0, 0);
+ OOB(0, max, 0);
+ OOB(max, 0, 1);
+ OOB(0, max, 1);
+ OOB(max, 0, 2);
+ OOB(0, max, 2);
+
+ OOB(max, 0, max - 1);
+ OOB(0, max, max - 1);
+
+ // wraparound cases.
+ OOB(max, 1, max);
+ OOB(1, max, max);
+ OOB(max - 1, 2, max);
+ OOB(2, max - 1, max);
+ OOB(half + 1, half + 1, max);
+ OOB(half + 1, half + 1, max);
+
+#undef INB
+#undef OOB
+}
+
} // namespace internal
} // namespace v8
diff --git a/deps/v8/test/unittests/value-serializer-unittest.cc b/deps/v8/test/unittests/value-serializer-unittest.cc
index 2cc0bdc8a6..3e6cac2175 100644
--- a/deps/v8/test/unittests/value-serializer-unittest.cc
+++ b/deps/v8/test/unittests/value-serializer-unittest.cc
@@ -119,7 +119,10 @@ class ValueSerializerTest : public TestWithIsolate {
}
std::pair<uint8_t*, size_t> buffer = serializer.Release();
std::vector<uint8_t> result(buffer.first, buffer.first + buffer.second);
- free(buffer.first);
+ if (auto* delegate = GetSerializerDelegate())
+ delegate->FreeBufferMemory(buffer.first);
+ else
+ free(buffer.first);
return Just(std::move(result));
}
@@ -138,6 +141,10 @@ class ValueSerializerTest : public TestWithIsolate {
return buffer;
}
+ std::vector<uint8_t> EncodeTest(const char* source) {
+ return EncodeTest(EvaluateScriptForInput(source));
+ }
+
v8::Local<v8::Message> InvalidEncodeTest(Local<Value> input_value) {
Context::Scope scope(serialization_context());
TryCatch try_catch(isolate());
@@ -318,6 +325,89 @@ TEST_F(ValueSerializerTest, DecodeOddball) {
EXPECT_TRUE(value->IsNull());
}
+TEST_F(ValueSerializerTest, EncodeArrayStackOverflow) {
+ InvalidEncodeTest("var a = []; for (var i = 0; i < 1E5; i++) a = [a]; a");
+}
+
+TEST_F(ValueSerializerTest, EncodeObjectStackOverflow) {
+ InvalidEncodeTest("var a = {}; for (var i = 0; i < 1E5; i++) a = {a}; a");
+}
+
+TEST_F(ValueSerializerTest, DecodeArrayStackOverflow) {
+ static const int nesting_level = 1E5;
+ std::vector<uint8_t> payload;
+ // Header.
+ payload.push_back(0xFF);
+ payload.push_back(0x0D);
+
+ // Nested arrays, each with one element.
+ for (int i = 0; i < nesting_level; i++) {
+ payload.push_back(0x41);
+ payload.push_back(0x01);
+ }
+
+ // Innermost array is empty.
+ payload.push_back(0x41);
+ payload.push_back(0x00);
+ payload.push_back(0x24);
+ payload.push_back(0x00);
+ payload.push_back(0x00);
+
+ // Close nesting.
+ for (int i = 0; i < nesting_level; i++) {
+ payload.push_back(0x24);
+ payload.push_back(0x00);
+ payload.push_back(0x01);
+ }
+
+ InvalidDecodeTest(payload);
+}
+
+TEST_F(ValueSerializerTest, DecodeObjectStackOverflow) {
+ static const int nesting_level = 1E5;
+ std::vector<uint8_t> payload;
+ // Header.
+ payload.push_back(0xFF);
+ payload.push_back(0x0D);
+
+ // Nested objects, each with one property 'a'.
+ for (int i = 0; i < nesting_level; i++) {
+ payload.push_back(0x6F);
+ payload.push_back(0x22);
+ payload.push_back(0x01);
+ payload.push_back(0x61);
+ }
+
+ // Innermost array is empty.
+ payload.push_back(0x6F);
+ payload.push_back(0x7B);
+ payload.push_back(0x00);
+
+ // Close nesting.
+ for (int i = 0; i < nesting_level; i++) {
+ payload.push_back(0x7B);
+ payload.push_back(0x01);
+ }
+
+ InvalidDecodeTest(payload);
+}
+
+TEST_F(ValueSerializerTest, DecodeVerifyObjectCount) {
+ static const int nesting_level = 1E5;
+ std::vector<uint8_t> payload;
+ // Header.
+ payload.push_back(0xFF);
+ payload.push_back(0x0D);
+
+ // Repeat SerializationTag:kVerifyObjectCount. This leads to stack overflow.
+ for (int i = 0; i < nesting_level; i++) {
+ payload.push_back(0x3F);
+ payload.push_back(0x01);
+ }
+
+ InvalidDecodeTest(payload);
+}
+
TEST_F(ValueSerializerTest, RoundTripNumber) {
Local<Value> value = RoundTripTest(Integer::New(isolate(), 42));
ASSERT_TRUE(value->IsInt32());
@@ -1871,19 +1961,15 @@ TEST_F(ValueSerializerTest, DecodeDataView) {
}
TEST_F(ValueSerializerTest, DecodeArrayWithLengthProperty1) {
- ASSERT_DEATH_IF_SUPPORTED(
- DecodeTest({0xff, 0x0d, 0x41, 0x03, 0x49, 0x02, 0x49, 0x04,
- 0x49, 0x06, 0x22, 0x06, 0x6c, 0x65, 0x6e, 0x67,
- 0x74, 0x68, 0x49, 0x02, 0x24, 0x01, 0x03}),
- ".*LookupIterator::NOT_FOUND == it.state\\(\\).*");
+ InvalidDecodeTest({0xff, 0x0d, 0x41, 0x03, 0x49, 0x02, 0x49, 0x04,
+ 0x49, 0x06, 0x22, 0x06, 0x6c, 0x65, 0x6e, 0x67,
+ 0x74, 0x68, 0x49, 0x02, 0x24, 0x01, 0x03});
}
TEST_F(ValueSerializerTest, DecodeArrayWithLengthProperty2) {
- ASSERT_DEATH_IF_SUPPORTED(
- DecodeTest({0xff, 0x0d, 0x41, 0x03, 0x49, 0x02, 0x49, 0x04,
- 0x49, 0x06, 0x22, 0x06, 0x6c, 0x65, 0x6e, 0x67,
- 0x74, 0x68, 0x6f, 0x7b, 0x00, 0x24, 0x01, 0x03}),
- ".*LookupIterator::NOT_FOUND == it.state\\(\\).*");
+ InvalidDecodeTest({0xff, 0x0d, 0x41, 0x03, 0x49, 0x02, 0x49, 0x04,
+ 0x49, 0x06, 0x22, 0x06, 0x6c, 0x65, 0x6e, 0x67,
+ 0x74, 0x68, 0x6f, 0x7b, 0x00, 0x24, 0x01, 0x03});
}
TEST_F(ValueSerializerTest, DecodeInvalidDataView) {
@@ -2386,7 +2472,7 @@ class ValueSerializerTestWithWasm : public ValueSerializerTest {
class ThrowingSerializer : public ValueSerializer::Delegate {
public:
Maybe<uint32_t> GetWasmModuleTransferId(
- Isolate* isolate, Local<WasmCompiledModule> module) override {
+ Isolate* isolate, Local<WasmModuleObject> module) override {
isolate->ThrowException(Exception::Error(
String::NewFromOneByte(
isolate,
@@ -2402,10 +2488,10 @@ class ValueSerializerTestWithWasm : public ValueSerializerTest {
class SerializeToTransfer : public ValueSerializer::Delegate {
public:
SerializeToTransfer(
- std::vector<WasmCompiledModule::TransferrableModule>* modules)
+ std::vector<WasmModuleObject::TransferrableModule>* modules)
: modules_(modules) {}
Maybe<uint32_t> GetWasmModuleTransferId(
- Isolate* isolate, Local<WasmCompiledModule> module) override {
+ Isolate* isolate, Local<WasmModuleObject> module) override {
modules_->push_back(module->GetTransferrableModule());
return Just(static_cast<uint32_t>(modules_->size()) - 1);
}
@@ -2413,23 +2499,23 @@ class ValueSerializerTestWithWasm : public ValueSerializerTest {
void ThrowDataCloneError(Local<String> message) override { UNREACHABLE(); }
private:
- std::vector<WasmCompiledModule::TransferrableModule>* modules_;
+ std::vector<WasmModuleObject::TransferrableModule>* modules_;
};
class DeserializeFromTransfer : public ValueDeserializer::Delegate {
public:
DeserializeFromTransfer(
- std::vector<WasmCompiledModule::TransferrableModule>* modules)
+ std::vector<WasmModuleObject::TransferrableModule>* modules)
: modules_(modules) {}
- MaybeLocal<WasmCompiledModule> GetWasmModuleFromId(Isolate* isolate,
- uint32_t id) override {
- return WasmCompiledModule::FromTransferrableModule(isolate,
- modules_->at(id));
+ MaybeLocal<WasmModuleObject> GetWasmModuleFromId(Isolate* isolate,
+ uint32_t id) override {
+ return WasmModuleObject::FromTransferrableModule(isolate,
+ modules_->at(id));
}
private:
- std::vector<WasmCompiledModule::TransferrableModule>* modules_;
+ std::vector<WasmModuleObject::TransferrableModule>* modules_;
};
ValueSerializer::Delegate* GetSerializerDelegate() override {
@@ -2440,9 +2526,9 @@ class ValueSerializerTestWithWasm : public ValueSerializerTest {
return current_deserializer_delegate_;
}
- Local<WasmCompiledModule> MakeWasm() {
+ Local<WasmModuleObject> MakeWasm() {
Context::Scope scope(serialization_context());
- return WasmCompiledModule::DeserializeOrCompile(
+ return WasmModuleObject::DeserializeOrCompile(
isolate(), {nullptr, 0},
{kIncrementerWasm, sizeof(kIncrementerWasm)})
.ToLocalChecked();
@@ -2509,7 +2595,7 @@ class ValueSerializerTestWithWasm : public ValueSerializerTest {
private:
static bool g_saved_flag;
- std::vector<WasmCompiledModule::TransferrableModule> transfer_modules_;
+ std::vector<WasmModuleObject::TransferrableModule> transfer_modules_;
SerializeToTransfer serialize_delegate_;
DeserializeFromTransfer deserialize_delegate_;
ValueSerializer::Delegate* current_serializer_delegate_ = nullptr;
@@ -2715,5 +2801,89 @@ TEST_F(ValueSerializerTestWithWasm, DecodeWasmModuleWithInvalidDataLength) {
InvalidDecodeTest({0xFF, 0x09, 0x3F, 0x00, 0x57, 0x79, 0x00, 0x7F});
}
+class ValueSerializerTestWithLimitedMemory : public ValueSerializerTest {
+ protected:
+// GMock doesn't use the "override" keyword.
+#if __clang__
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Winconsistent-missing-override"
+#endif
+
+ class SerializerDelegate : public ValueSerializer::Delegate {
+ public:
+ explicit SerializerDelegate(ValueSerializerTestWithLimitedMemory* test)
+ : test_(test) {}
+
+ ~SerializerDelegate() { EXPECT_EQ(nullptr, last_buffer_); }
+
+ void SetMemoryLimit(size_t limit) { memory_limit_ = limit; }
+
+ void* ReallocateBufferMemory(void* old_buffer, size_t size,
+ size_t* actual_size) override {
+ EXPECT_EQ(old_buffer, last_buffer_);
+ if (size > memory_limit_) return nullptr;
+ *actual_size = size;
+ last_buffer_ = realloc(old_buffer, size);
+ return last_buffer_;
+ }
+
+ void FreeBufferMemory(void* buffer) override {
+ EXPECT_EQ(buffer, last_buffer_);
+ last_buffer_ = nullptr;
+ free(buffer);
+ }
+
+ void ThrowDataCloneError(Local<String> message) override {
+ test_->isolate()->ThrowException(Exception::Error(message));
+ }
+
+ MOCK_METHOD2(WriteHostObject,
+ Maybe<bool>(Isolate* isolate, Local<Object> object));
+
+ private:
+ ValueSerializerTestWithLimitedMemory* test_;
+ void* last_buffer_ = nullptr;
+ size_t memory_limit_ = 0;
+ };
+
+#if __clang__
+#pragma clang diagnostic pop
+#endif
+
+ ValueSerializer::Delegate* GetSerializerDelegate() override {
+ return &serializer_delegate_;
+ }
+
+ void BeforeEncode(ValueSerializer* serializer) override {
+ serializer_ = serializer;
+ }
+
+ SerializerDelegate serializer_delegate_{this};
+ ValueSerializer* serializer_ = nullptr;
+};
+
+TEST_F(ValueSerializerTestWithLimitedMemory, FailIfNoMemoryInWriteHostObject) {
+ EXPECT_CALL(serializer_delegate_, WriteHostObject(isolate(), _))
+ .WillRepeatedly(Invoke([this](Isolate*, Local<Object>) {
+ static const char kDummyData[1024] = {};
+ serializer_->WriteRawBytes(&kDummyData, sizeof(kDummyData));
+ return Just(true);
+ }));
+
+ // If there is enough memory, things work.
+ serializer_delegate_.SetMemoryLimit(2048);
+ EncodeTest("new ExampleHostObject()");
+
+ // If not, we get a graceful failure, rather than silent misbehavior.
+ serializer_delegate_.SetMemoryLimit(1024);
+ InvalidEncodeTest("new ExampleHostObject()");
+
+ // And we definitely don't continue to serialize other things.
+ serializer_delegate_.SetMemoryLimit(1024);
+ EvaluateScriptForInput("gotA = false");
+ InvalidEncodeTest("[new ExampleHostObject, {get a() { gotA = true; }}]");
+ EXPECT_TRUE(EvaluateScriptForInput("gotA")->IsFalse());
+}
+
} // namespace
} // namespace v8
diff --git a/deps/v8/test/unittests/wasm/OWNERS b/deps/v8/test/unittests/wasm/OWNERS
index 3972f0dd99..dc68b39733 100644
--- a/deps/v8/test/unittests/wasm/OWNERS
+++ b/deps/v8/test/unittests/wasm/OWNERS
@@ -1,7 +1,5 @@
ahaas@chromium.org
-bradnelson@chromium.org
clemensh@chromium.org
-eholk@chromium.org
titzer@chromium.org
# COMPONENT: Blink>JavaScript>WebAssembly
diff --git a/deps/v8/test/unittests/wasm/decoder-unittest.cc b/deps/v8/test/unittests/wasm/decoder-unittest.cc
index e2a7bcc388..1d9d0ea15c 100644
--- a/deps/v8/test/unittests/wasm/decoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/decoder-unittest.cc
@@ -4,6 +4,7 @@
#include "test/unittests/test-utils.h"
+#include "src/base/overflowing-math.h"
#include "src/objects-inl.h"
#include "src/wasm/decoder.h"
#include "test/common/wasm/wasm-macro-gen.h"
@@ -475,7 +476,8 @@ TEST_F(DecoderTest, ReadU32v_Bits) {
// foreach length 1...32
for (int i = 1; i <= 32; i++) {
uint32_t val = kVals[v];
- if (i < 32) val &= ((1 << i) - 1);
+ if (i < 32)
+ val &= base::SubWithWraparound(base::ShlWithWraparound(1, i), 1);
unsigned length = 1 + i / 7;
for (unsigned j = 0; j < kMaxSize; j++) {
diff --git a/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc b/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc
index 31e4a12ae7..e13816744f 100644
--- a/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc
@@ -18,6 +18,7 @@
#include "test/common/wasm/flag-utils.h"
#include "test/common/wasm/test-signatures.h"
#include "test/common/wasm/wasm-macro-gen.h"
+#include "testing/gmock-support.h"
namespace v8 {
namespace internal {
@@ -54,39 +55,37 @@ static const WasmOpcode kInt32BinopOpcodes[] = {
val, WASM_ZERO, kExprBrIf, static_cast<byte>(depth)
#define EXPECT_VERIFIES_C(sig, x) \
- Verify(true, sigs.sig(), x, x + arraysize(x), kAppendEnd)
+ Verify(true, sigs.sig(), ArrayVector(x), kAppendEnd)
-#define EXPECT_FAILURE_C(sig, x) \
- Verify(false, sigs.sig(), x, x + arraysize(x), kAppendEnd)
+#define EXPECT_FAILURE_C(sig, x, ...) \
+ Verify(false, sigs.sig(), ArrayVector(x), kAppendEnd, ##__VA_ARGS__)
-#define EXPECT_VERIFIES_SC(sig, x) \
- Verify(true, sig, x, x + arraysize(x), kAppendEnd)
+#define EXPECT_VERIFIES_SC(sig, x) Verify(true, sig, ArrayVector(x), kAppendEnd)
-#define EXPECT_FAILURE_SC(sig, x) \
- Verify(false, sig, x, x + arraysize(x), kAppendEnd)
+#define EXPECT_FAILURE_SC(sig, x) Verify(false, sig, ArrayVector(x), kAppendEnd)
-#define EXPECT_VERIFIES_S(env, ...) \
- do { \
- static byte code[] = {__VA_ARGS__}; \
- Verify(true, env, code, code + arraysize(code), kAppendEnd); \
+#define EXPECT_VERIFIES_S(env, ...) \
+ do { \
+ static byte code[] = {__VA_ARGS__}; \
+ Verify(true, env, ArrayVector(code), kAppendEnd); \
} while (false)
-#define EXPECT_FAILURE_S(env, ...) \
- do { \
- static byte code[] = {__VA_ARGS__}; \
- Verify(false, env, code, code + arraysize(code), kAppendEnd); \
+#define EXPECT_FAILURE_S(env, ...) \
+ do { \
+ static byte code[] = {__VA_ARGS__}; \
+ Verify(false, env, ArrayVector(code), kAppendEnd); \
} while (false)
-#define EXPECT_VERIFIES(sig, ...) \
- do { \
- static const byte code[] = {__VA_ARGS__}; \
- Verify(true, sigs.sig(), code, code + sizeof(code), kAppendEnd); \
+#define EXPECT_VERIFIES(sig, ...) \
+ do { \
+ static const byte code[] = {__VA_ARGS__}; \
+ EXPECT_VERIFIES_C(sig, code); \
} while (false)
-#define EXPECT_FAILURE(sig, ...) \
- do { \
- static const byte code[] = {__VA_ARGS__}; \
- Verify(false, sigs.sig(), code, code + sizeof(code), kAppendEnd); \
+#define EXPECT_FAILURE(sig, ...) \
+ do { \
+ static const byte code[] = {__VA_ARGS__}; \
+ EXPECT_FAILURE_C(sig, code); \
} while (false)
class FunctionBodyDecoderTest : public TestWithZone {
@@ -108,49 +107,48 @@ class FunctionBodyDecoderTest : public TestWithZone {
enum AppendEnd : bool { kAppendEnd, kOmitEnd };
- void PrepareBytecode(const byte** startp, const byte** endp,
- AppendEnd append_end) {
- const byte* start = *startp;
- const byte* end = *endp;
+ Vector<const byte> PrepareBytecode(Vector<const byte> code,
+ AppendEnd append_end) {
size_t locals_size = local_decls.Size();
- size_t total_size = end - start + locals_size;
- if (append_end == kAppendEnd) ++total_size;
+ size_t total_size =
+ code.size() + locals_size + (append_end == kAppendEnd ? 1 : 0);
byte* buffer = static_cast<byte*>(zone()->New(total_size));
// Prepend the local decls to the code.
local_decls.Emit(buffer);
// Emit the code.
- memcpy(buffer + locals_size, start, end - start);
+ memcpy(buffer + locals_size, code.start(), code.size());
if (append_end == kAppendEnd) {
// Append an extra end opcode.
buffer[total_size - 1] = kExprEnd;
}
- *startp = buffer;
- *endp = buffer + total_size;
+ return {buffer, total_size};
}
// Prepends local variable declarations and renders nice error messages for
// verification failures.
- void Verify(bool expected_success, FunctionSig* sig, const byte* start,
- const byte* end, AppendEnd append_end) {
- PrepareBytecode(&start, &end, append_end);
+ void Verify(bool expected_success, FunctionSig* sig, Vector<const byte> code,
+ AppendEnd append_end, const char* message = nullptr) {
+ code = PrepareBytecode(code, append_end);
// Verify the code.
- FunctionBody body(sig, 0, start, end);
+ FunctionBody body(sig, 0, code.start(), code.end());
WasmFeatures unused_detected_features;
DecodeResult result =
VerifyWasmCode(zone()->allocator(), enabled_features_, module,
&unused_detected_features, body);
- uint32_t pc = result.error_offset();
std::ostringstream str;
- if (expected_success) {
- str << "Verification failed: pc = +" << pc
- << ", msg = " << result.error_msg();
+ if (result.failed()) {
+ str << "Verification failed: pc = +" << result.error().offset()
+ << ", msg = " << result.error().message();
} else {
- str << "Verification successed, expected failure; pc = +" << pc;
+ str << "Verification successed, expected failure";
}
EXPECT_EQ(result.ok(), expected_success) << str.str();
+ if (result.failed() && message) {
+ EXPECT_THAT(result.error().message(), ::testing::HasSubstr(message));
+ }
}
void TestBinop(WasmOpcode opcode, FunctionSig* success) {
@@ -264,6 +262,18 @@ class TestModuleBuilder {
void InitializeTable() { mod.tables.emplace_back(); }
+ byte AddPassiveElementSegment() {
+ mod.elem_segments.emplace_back();
+ return static_cast<byte>(mod.elem_segments.size() - 1);
+ }
+
+ // Set the number of data segments as declared by the DataCount section.
+ void SetDataSegmentCount(uint32_t data_segment_count) {
+ // The Data section occurs after the Code section, so we don't need to
+ // update mod.data_segments, as it is always empty.
+ mod.num_declared_data_segments = data_segment_count;
+ }
+
WasmModule* module() { return &mod; }
private:
@@ -286,9 +296,8 @@ TEST_F(FunctionBodyDecoderTest, RefNull) {
}
TEST_F(FunctionBodyDecoderTest, EmptyFunction) {
- byte code[] = {0};
- Verify(true, sigs.v_v(), code, code, kAppendEnd);
- Verify(false, sigs.i_i(), code, code, kAppendEnd);
+ Verify(true, sigs.v_v(), {}, kAppendEnd);
+ Verify(false, sigs.i_i(), {}, kAppendEnd);
}
TEST_F(FunctionBodyDecoderTest, IncompleteIf1) {
@@ -343,10 +352,10 @@ TEST_F(FunctionBodyDecoderTest, Float64Const) {
TEST_F(FunctionBodyDecoderTest, Int32Const_off_end) {
byte code[] = {kExprI32Const, 0xAA, 0xBB, 0xCC, 0x44};
- for (int size = 1; size <= 4; size++) {
- Verify(false, sigs.i_i(), code, code + size, kAppendEnd);
+ for (size_t size = 1; size <= 4; ++size) {
+ Verify(false, sigs.i_i(), {code, size}, kAppendEnd);
// Should also fail without the trailing 'end' opcode.
- Verify(false, sigs.i_i(), code, code + size, kOmitEnd);
+ Verify(false, sigs.i_i(), {code, size}, kOmitEnd);
}
}
@@ -524,15 +533,15 @@ TEST_F(FunctionBodyDecoderTest, TeeLocalN_local) {
}
TEST_F(FunctionBodyDecoderTest, BlockN) {
- const int kMaxSize = 200;
+ constexpr size_t kMaxSize = 200;
byte buffer[kMaxSize + 3];
- for (int i = 0; i <= kMaxSize; i++) {
+ for (size_t i = 0; i <= kMaxSize; i++) {
memset(buffer, kExprNop, sizeof(buffer));
buffer[0] = kExprBlock;
buffer[1] = kLocalVoid;
buffer[i + 2] = kExprEnd;
- Verify(true, sigs.v_i(), buffer, buffer + i + 3, kAppendEnd);
+ Verify(true, sigs.v_i(), {buffer, i + 3}, kAppendEnd);
}
}
@@ -679,8 +688,8 @@ TEST_F(FunctionBodyDecoderTest, BlockN_off_end) {
byte code[] = {WASM_BLOCK(kExprNop, kExprNop, kExprNop, kExprNop)};
EXPECT_VERIFIES_C(v_v, code);
for (size_t i = 1; i < arraysize(code); i++) {
- Verify(false, sigs.v_v(), code, code + i, kAppendEnd);
- Verify(false, sigs.v_v(), code, code + i, kOmitEnd);
+ Verify(false, sigs.v_v(), {code, i}, kAppendEnd);
+ Verify(false, sigs.v_v(), {code, i}, kOmitEnd);
}
}
@@ -787,6 +796,13 @@ TEST_F(FunctionBodyDecoderTest, IfElseUnreachable2) {
}
}
+TEST_F(FunctionBodyDecoderTest, OneArmedIfWithArity) {
+ static const byte code[] = {WASM_ZERO, kExprIf, kLocalI32, WASM_ONE,
+ kExprEnd};
+ EXPECT_FAILURE_C(i_v, code,
+ "start-arity and end-arity of one-armed if must match");
+}
+
TEST_F(FunctionBodyDecoderTest, IfBreak) {
EXPECT_VERIFIES(v_i, WASM_IF(WASM_GET_LOCAL(0), WASM_BR(0)));
EXPECT_VERIFIES(v_i, WASM_IF(WASM_GET_LOCAL(0), WASM_BR(1)));
@@ -1011,8 +1027,8 @@ TEST_F(FunctionBodyDecoderTest, If_off_end) {
static const byte kCode[] = {
WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0))};
for (size_t len = 3; len < arraysize(kCode); len++) {
- Verify(false, sigs.i_i(), kCode, kCode + len, kAppendEnd);
- Verify(false, sigs.i_i(), kCode, kCode + len, kOmitEnd);
+ Verify(false, sigs.i_i(), {kCode, len}, kAppendEnd);
+ Verify(false, sigs.i_i(), {kCode, len}, kOmitEnd);
}
}
@@ -1614,7 +1630,7 @@ TEST_F(FunctionBodyDecoderTest, IncompleteIndirectCall) {
module = builder.module();
static byte code[] = {kExprCallIndirect};
- Verify(false, sig, code, code + arraysize(code), kOmitEnd);
+ Verify(false, sig, ArrayVector(code), kOmitEnd);
}
TEST_F(FunctionBodyDecoderTest, IncompleteStore) {
@@ -1625,7 +1641,7 @@ TEST_F(FunctionBodyDecoderTest, IncompleteStore) {
module = builder.module();
static byte code[] = {kExprI32StoreMem};
- Verify(false, sig, code, code + arraysize(code), kOmitEnd);
+ Verify(false, sig, ArrayVector(code), kOmitEnd);
}
TEST_F(FunctionBodyDecoderTest, IncompleteS8x16Shuffle) {
@@ -1638,7 +1654,7 @@ TEST_F(FunctionBodyDecoderTest, IncompleteS8x16Shuffle) {
static byte code[] = {kSimdPrefix,
static_cast<byte>(kExprS8x16Shuffle & 0xff)};
- Verify(false, sig, code, code + arraysize(code), kOmitEnd);
+ Verify(false, sig, ArrayVector(code), kOmitEnd);
}
TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) {
@@ -1798,22 +1814,22 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) {
}
}
-TEST_F(FunctionBodyDecoderTest, WasmGrowMemory) {
+TEST_F(FunctionBodyDecoderTest, WasmMemoryGrow) {
TestModuleBuilder builder;
module = builder.module();
builder.InitializeMemory();
- byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0};
+ byte code[] = {WASM_GET_LOCAL(0), kExprMemoryGrow, 0};
EXPECT_VERIFIES_C(i_i, code);
EXPECT_FAILURE_C(i_d, code);
}
-TEST_F(FunctionBodyDecoderTest, AsmJsGrowMemory) {
+TEST_F(FunctionBodyDecoderTest, AsmJsMemoryGrow) {
TestModuleBuilder builder(kAsmJsOrigin);
module = builder.module();
builder.InitializeMemory();
- byte code[] = {WASM_GET_LOCAL(0), kExprGrowMemory, 0};
+ byte code[] = {WASM_GET_LOCAL(0), kExprMemoryGrow, 0};
EXPECT_FAILURE_C(i_i, code);
}
@@ -2214,8 +2230,8 @@ TEST_F(FunctionBodyDecoderTest, BrTable2b) {
TEST_F(FunctionBodyDecoderTest, BrTable_off_end) {
static byte code[] = {B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))};
for (size_t len = 1; len < sizeof(code); len++) {
- Verify(false, sigs.i_i(), code, code + len, kAppendEnd);
- Verify(false, sigs.i_i(), code, code + len, kOmitEnd);
+ Verify(false, sigs.i_i(), {code, len}, kAppendEnd);
+ Verify(false, sigs.i_i(), {code, len}, kOmitEnd);
}
}
@@ -2429,38 +2445,57 @@ TEST_F(FunctionBodyDecoderTest, ThrowUnreachable) {
}
#define WASM_TRY_OP kExprTry, kLocalVoid
-#define WASM_CATCH(index) kExprCatch, static_cast<byte>(index)
+#define WASM_BR_ON_EXN(depth, index) \
+ kExprBrOnExn, static_cast<byte>(depth), static_cast<byte>(index)
TEST_F(FunctionBodyDecoderTest, TryCatch) {
WASM_FEATURE_SCOPE(eh);
TestModuleBuilder builder;
module = builder.module();
- byte ex1 = builder.AddException(sigs.v_v());
- byte ex2 = builder.AddException(sigs.v_v());
- EXPECT_VERIFIES(v_v, WASM_TRY_OP, WASM_CATCH(ex1), kExprEnd);
- EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprEnd); // Missing catch.
- EXPECT_FAILURE(v_v, WASM_TRY_OP, WASM_CATCH(ex1)); // Missing end.
- EXPECT_FAILURE(v_v, WASM_CATCH(ex1), kExprEnd); // Missing try.
-
- // TODO(mstarzinger): Double catch. Fix this to verify.
- EXPECT_FAILURE(v_v, WASM_TRY_OP, WASM_CATCH(ex1), WASM_CATCH(ex2), kExprEnd);
+ EXPECT_VERIFIES(v_v, WASM_TRY_OP, kExprCatch, kExprDrop, kExprEnd);
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatch, kExprCatch, kExprEnd);
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprEnd); // Missing catch.
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatch); // Missing end.
+ EXPECT_FAILURE(v_v, kExprCatch, kExprEnd); // Missing try.
}
-TEST_F(FunctionBodyDecoderTest, TryCatchAll) {
+TEST_F(FunctionBodyDecoderTest, Rethrow) {
WASM_FEATURE_SCOPE(eh);
TestModuleBuilder builder;
module = builder.module();
- byte ex1 = builder.AddException(sigs.v_v());
- EXPECT_VERIFIES(v_v, WASM_TRY_OP, kExprCatchAll, kExprEnd);
- EXPECT_VERIFIES(v_v, WASM_TRY_OP, WASM_CATCH(ex1), kExprCatchAll, kExprEnd);
- EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatchAll, kExprCatchAll, kExprEnd);
- EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatchAll, WASM_CATCH(ex1), kExprEnd);
- EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatchAll); // Missing end.
- EXPECT_FAILURE(v_v, kExprCatchAll, kExprEnd); // Missing try.
+ EXPECT_VERIFIES(v_v, WASM_TRY_OP, kExprCatch, kExprRethrow, kExprEnd);
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprRethrow, kExprCatch, kExprEnd);
+ EXPECT_FAILURE(v_v, WASM_BLOCK(kExprRethrow));
+ EXPECT_FAILURE(v_v, kExprRethrow);
}
+TEST_F(FunctionBodyDecoderTest, BrOnExn) {
+ WASM_FEATURE_SCOPE(eh);
+ TestModuleBuilder builder;
+ module = builder.module();
+ byte ex1 = builder.AddException(sigs.v_v());
+ byte ex2 = builder.AddException(sigs.v_i());
+ EXPECT_VERIFIES(v_v, WASM_TRY_OP, kExprCatch, WASM_BR_ON_EXN(0, ex1),
+ kExprDrop, kExprEnd);
+ EXPECT_VERIFIES(v_v, WASM_TRY_OP, kExprCatch, WASM_BR_ON_EXN(1, ex1),
+ kExprDrop, kExprEnd);
+ EXPECT_VERIFIES(v_v, WASM_TRY_OP, kExprCatch, WASM_BR_ON_EXN(0, ex1),
+ WASM_BR_ON_EXN(0, ex1), kExprDrop, kExprEnd);
+ EXPECT_VERIFIES(v_v, WASM_BLOCK(WASM_TRY_OP, kExprCatch,
+ WASM_BR_ON_EXN(1, ex1), kExprDrop, kExprEnd));
+ EXPECT_VERIFIES(i_v,
+ WASM_BLOCK_I(WASM_TRY_OP, kExprCatch, WASM_BR_ON_EXN(1, ex2),
+ kExprDrop, kExprEnd, kExprI32Const, 0));
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatch, WASM_BR_ON_EXN(2, ex1),
+ kExprDrop, kExprEnd);
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatch, kExprDrop,
+ WASM_BR_ON_EXN(0, ex1), kExprEnd);
+ EXPECT_FAILURE(v_v, WASM_TRY_OP, kExprCatch, WASM_BR_ON_EXN(0, ex1),
+ kExprEnd);
+}
+
+#undef WASM_BR_ON_EXN
#undef WASM_TRY_OP
-#undef WASM_CATCH
TEST_F(FunctionBodyDecoderTest, MultiValBlock1) {
WASM_FEATURE_SCOPE(mv);
@@ -2690,13 +2725,10 @@ TEST_F(FunctionBodyDecoderTest, IfParam) {
TEST_F(FunctionBodyDecoderTest, Regression709741) {
AddLocals(kWasmI32, kV8MaxWasmFunctionLocals - 1);
EXPECT_VERIFIES(v_v, WASM_NOP);
- byte code[] = {WASM_NOP};
- const byte* start = code;
- const byte* end = code + sizeof(code);
- PrepareBytecode(&start, &end, kAppendEnd);
+ byte code[] = {WASM_NOP, WASM_END};
- for (const byte* i = start; i < end; i++) {
- FunctionBody body(sigs.v_v(), 0, start, i);
+ for (size_t i = 0; i < arraysize(code); ++i) {
+ FunctionBody body(sigs.v_v(), 0, code, code + i);
WasmFeatures unused_detected_features;
DecodeResult result =
VerifyWasmCode(zone()->allocator(), kAllWasmFeatures, nullptr,
@@ -2708,6 +2740,129 @@ TEST_F(FunctionBodyDecoderTest, Regression709741) {
}
}
+TEST_F(FunctionBodyDecoderTest, MemoryInit) {
+ TestModuleBuilder builder;
+ builder.InitializeMemory();
+ builder.SetDataSegmentCount(1);
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ EXPECT_FAILURE(v_v, WASM_TABLE_INIT(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(FunctionBodyDecoderTest, MemoryInitInvalid) {
+ TestModuleBuilder builder;
+ builder.InitializeMemory();
+ builder.SetDataSegmentCount(1);
+ module = builder.module();
+
+ WASM_FEATURE_SCOPE(bulk_memory);
+ byte code[] = {WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO),
+ WASM_END};
+ for (size_t i = 0; i <= arraysize(code); ++i) {
+ Verify(i == arraysize(code), sigs.v_v(), {code, i}, kOmitEnd);
+ }
+}
+
+TEST_F(FunctionBodyDecoderTest, MemoryDrop) {
+ TestModuleBuilder builder;
+ builder.InitializeMemory();
+ builder.SetDataSegmentCount(1);
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_MEMORY_DROP(0));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_MEMORY_DROP(0));
+ EXPECT_FAILURE(v_v, WASM_MEMORY_DROP(1));
+}
+
+TEST_F(FunctionBodyDecoderTest, MemoryCopy) {
+ TestModuleBuilder builder;
+ builder.InitializeMemory();
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_MEMORY_COPY(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_MEMORY_COPY(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(FunctionBodyDecoderTest, MemoryFill) {
+ TestModuleBuilder builder;
+ builder.InitializeMemory();
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_MEMORY_FILL(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_MEMORY_FILL(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(FunctionBodyDecoderTest, BulkMemoryOpsWithoutMemory) {
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_FAILURE(v_v, WASM_MEMORY_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ EXPECT_FAILURE(v_v, WASM_MEMORY_COPY(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ EXPECT_FAILURE(v_v, WASM_MEMORY_FILL(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(FunctionBodyDecoderTest, TableInit) {
+ TestModuleBuilder builder;
+ builder.InitializeTable();
+ builder.AddPassiveElementSegment();
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_TABLE_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_TABLE_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ EXPECT_FAILURE(v_v, WASM_TABLE_INIT(1, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(FunctionBodyDecoderTest, TableInitInvalid) {
+ TestModuleBuilder builder;
+ builder.InitializeTable();
+ builder.AddPassiveElementSegment();
+ module = builder.module();
+
+ WASM_FEATURE_SCOPE(bulk_memory);
+ byte code[] = {WASM_TABLE_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO), WASM_END};
+ for (size_t i = 0; i <= arraysize(code); ++i) {
+ Verify(i == arraysize(code), sigs.v_v(), {code, i}, kOmitEnd);
+ }
+}
+
+TEST_F(FunctionBodyDecoderTest, TableDrop) {
+ TestModuleBuilder builder;
+ builder.InitializeTable();
+ builder.AddPassiveElementSegment();
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_TABLE_DROP(0));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_TABLE_DROP(0));
+ EXPECT_FAILURE(v_v, WASM_TABLE_DROP(1));
+}
+
+TEST_F(FunctionBodyDecoderTest, TableCopy) {
+ TestModuleBuilder builder;
+ builder.InitializeTable();
+ module = builder.module();
+
+ EXPECT_FAILURE(v_v, WASM_TABLE_COPY(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(v_v, WASM_TABLE_COPY(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
+TEST_F(FunctionBodyDecoderTest, BulkTableOpsWithoutTable) {
+ TestModuleBuilder builder;
+ builder.InitializeTable();
+ builder.AddPassiveElementSegment();
+
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_FAILURE(v_v, WASM_TABLE_INIT(0, WASM_ZERO, WASM_ZERO, WASM_ZERO));
+ EXPECT_FAILURE(v_v, WASM_TABLE_DROP(0));
+ EXPECT_FAILURE(v_v, WASM_TABLE_COPY(WASM_ZERO, WASM_ZERO, WASM_ZERO));
+}
+
class BranchTableIteratorTest : public TestWithZone {
public:
BranchTableIteratorTest() : TestWithZone() {}
@@ -2795,10 +2950,12 @@ TEST_F(WasmOpcodeLengthTest, Statements) {
EXPECT_LENGTH(1, kExprElse);
EXPECT_LENGTH(1, kExprEnd);
EXPECT_LENGTH(1, kExprSelect);
+ EXPECT_LENGTH(1, kExprCatch);
+ EXPECT_LENGTH(1, kExprRethrow);
EXPECT_LENGTH(2, kExprBr);
EXPECT_LENGTH(2, kExprBrIf);
EXPECT_LENGTH(2, kExprThrow);
- EXPECT_LENGTH(2, kExprCatch);
+ EXPECT_LENGTH(3, kExprBrOnExn);
EXPECT_LENGTH_N(2, kExprBlock, kLocalI32);
EXPECT_LENGTH_N(2, kExprLoop, kLocalI32);
EXPECT_LENGTH_N(2, kExprIf, kLocalI32);
@@ -2874,7 +3031,7 @@ TEST_F(WasmOpcodeLengthTest, LoadsAndStores) {
TEST_F(WasmOpcodeLengthTest, MiscMemExpressions) {
EXPECT_LENGTH(2, kExprMemorySize);
- EXPECT_LENGTH(2, kExprGrowMemory);
+ EXPECT_LENGTH(2, kExprMemoryGrow);
}
TEST_F(WasmOpcodeLengthTest, SimpleExpressions) {
diff --git a/deps/v8/test/unittests/wasm/module-decoder-unittest.cc b/deps/v8/test/unittests/wasm/module-decoder-unittest.cc
index 83876b3e0f..3d99dffa72 100644
--- a/deps/v8/test/unittests/wasm/module-decoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/module-decoder-unittest.cc
@@ -12,6 +12,9 @@
#include "src/wasm/wasm-opcodes.h"
#include "test/common/wasm/flag-utils.h"
#include "test/common/wasm/wasm-macro-gen.h"
+#include "testing/gmock-support.h"
+
+using testing::HasSubstr;
namespace v8 {
namespace internal {
@@ -29,38 +32,50 @@ namespace module_decoder_unittest {
#define WASM_INIT_EXPR_ANYREF WASM_REF_NULL, kExprEnd
#define WASM_INIT_EXPR_GLOBAL(index) WASM_GET_GLOBAL(index), kExprEnd
-#define SIZEOF_EMPTY_FUNCTION ((size_t)5)
#define EMPTY_BODY 0
-#define SIZEOF_EMPTY_BODY ((size_t)1)
#define NOP_BODY 2, 0, kExprNop
-#define SIZEOF_NOP_BODY ((size_t)3)
#define SIG_ENTRY_i_i SIG_ENTRY_x_x(kLocalI32, kLocalI32)
-#define UNKNOWN_SECTION(size) 0, U32V_1(size + 5), 4, 'l', 'u', 'l', 'z'
+#define UNKNOWN_SECTION(size) 0, U32V_1(size + 5), ADD_COUNT('l', 'u', 'l', 'z')
+
+template <typename... Args>
+std::integral_constant<size_t, sizeof...(Args)> CountArgsHelper(Args...);
+#define COUNT_ARGS(...) (decltype(CountArgsHelper(__VA_ARGS__))::value)
+
+template <size_t num>
+struct CheckLEB1 : std::integral_constant<size_t, num> {
+ static_assert(num <= I32V_MAX(1), "LEB range check");
+};
+#define CHECK_LEB1(num) CheckLEB1<num>::value
-#define SECTION(name, size) k##name##SectionCode, U32V_1(size)
+#define ADD_COUNT(...) CHECK_LEB1(COUNT_ARGS(__VA_ARGS__)), __VA_ARGS__
-#define SIGNATURES_SECTION(count, ...) \
- SECTION(Type, 1 + 3 * (count)), U32V_1(count), __VA_ARGS__
+#define SECTION(name, ...) k##name##SectionCode, ADD_COUNT(__VA_ARGS__)
+
+#define SIGNATURES_SECTION(count, ...) SECTION(Type, U32V_1(count), __VA_ARGS__)
#define FUNCTION_SIGNATURES_SECTION(count, ...) \
- SECTION(Function, 1 + (count)), U32V_1(count), __VA_ARGS__
+ SECTION(Function, U32V_1(count), __VA_ARGS__)
-#define FOO_STRING 3, 'f', 'o', 'o'
+#define FOO_STRING ADD_COUNT('f', 'o', 'o')
#define NO_LOCAL_NAMES 0
-#define EMPTY_SIGNATURES_SECTION SECTION(Type, 1), 0
-#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(Function, 1), 0
-#define EMPTY_FUNCTION_BODIES_SECTION SECTION(Code, 1), 0
-#define SECTION_NAMES(size) SECTION(Unknown, size + 5), 4, 'n', 'a', 'm', 'e'
-#define SECTION_EXCEPTIONS(size) SECTION(Exception, size)
-#define EMPTY_NAMES_SECTION SECTION_NAMES(1), 0
+#define EMPTY_SIGNATURES_SECTION SECTION(Type, ENTRY_COUNT(0))
+#define EMPTY_FUNCTION_SIGNATURES_SECTION SECTION(Function, ENTRY_COUNT(0))
+#define EMPTY_FUNCTION_BODIES_SECTION SECTION(Code, ENTRY_COUNT(0))
+#define SECTION_NAMES(...) \
+ SECTION(Unknown, ADD_COUNT('n', 'a', 'm', 'e'), ##__VA_ARGS__)
+#define EMPTY_NAMES_SECTION SECTION_NAMES()
+#define SECTION_SRC_MAP(...) \
+ SECTION(Unknown, \
+ ADD_COUNT('s', 'o', 'u', 'r', 'c', 'e', 'M', 'a', 'p', 'p', 'i', \
+ 'n', 'g', 'U', 'R', 'L'), \
+ ADD_COUNT(__VA_ARGS__))
#define FAIL_IF_NO_EXPERIMENTAL_EH(data) \
do { \
ModuleResult result = DecodeModule((data), (data) + sizeof((data))); \
EXPECT_FALSE(result.ok()); \
- EXPECT_EQ(0u, result.val->exceptions.size()); \
} while (false)
#define X1(...) __VA_ARGS__
@@ -68,35 +83,30 @@ namespace module_decoder_unittest {
#define X3(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
#define X4(...) __VA_ARGS__, __VA_ARGS__, __VA_ARGS__, __VA_ARGS__
-#define ONE_EMPTY_FUNCTION SECTION(Function, 1 + 1 * 1), 1, X1(0)
-
-#define TWO_EMPTY_FUNCTIONS SECTION(Function, 1 + 2 * 1), 2, X2(0)
-
-#define THREE_EMPTY_FUNCTIONS SECTION(Function, 1 + 3 * 1), 3, X3(0)
+#define ONE_EMPTY_FUNCTION(sig_index) \
+ SECTION(Function, ENTRY_COUNT(1), X1(sig_index))
-#define FOUR_EMPTY_FUNCTIONS SECTION(Function, 1 + 4 * 1), 4, X4(0)
+#define TWO_EMPTY_FUNCTIONS(sig_index) \
+ SECTION(Function, ENTRY_COUNT(2), X2(sig_index))
-#define ONE_EMPTY_BODY \
- SECTION(Code, 1 + 1 * (1 + SIZEOF_EMPTY_BODY)) \
- , 1, X1(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+#define THREE_EMPTY_FUNCTIONS(sig_index) \
+ SECTION(Function, ENTRY_COUNT(3), X3(sig_index))
-#define TWO_EMPTY_BODIES \
- SECTION(Code, 1 + 2 * (1 + SIZEOF_EMPTY_BODY)) \
- , 2, X2(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+#define FOUR_EMPTY_FUNCTIONS(sig_index) \
+ SECTION(Function, ENTRY_COUNT(4), X4(sig_index))
-#define THREE_EMPTY_BODIES \
- SECTION(Code, 1 + 3 * (1 + SIZEOF_EMPTY_BODY)) \
- , 3, X3(SIZEOF_EMPTY_BODY, EMPTY_BODY)
-
-#define FOUR_EMPTY_BODIES \
- SECTION(Code, 1 + 4 * (1 + SIZEOF_EMPTY_BODY)) \
- , 4, X4(SIZEOF_EMPTY_BODY, EMPTY_BODY)
+#define ONE_EMPTY_BODY SECTION(Code, ENTRY_COUNT(1), X1(EMPTY_BODY))
+#define TWO_EMPTY_BODIES SECTION(Code, ENTRY_COUNT(2), X2(EMPTY_BODY))
+#define THREE_EMPTY_BODIES SECTION(Code, ENTRY_COUNT(3), X3(EMPTY_BODY))
+#define FOUR_EMPTY_BODIES SECTION(Code, ENTRY_COUNT(4), X4(EMPTY_BODY))
#define SIGNATURES_SECTION_VOID_VOID \
- SECTION(Type, 1 + SIZEOF_SIG_ENTRY_v_v), 1, SIG_ENTRY_v_v
+ SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_v)
#define LINEAR_MEMORY_INDEX_0 0
+#define EXCEPTION_ENTRY(sig_index) U32V_1(kExceptionAttribute), sig_index
+
#define EXPECT_VERIFIES(data) \
do { \
ModuleResult result = DecodeModule(data, data + sizeof(data)); \
@@ -111,11 +121,12 @@ namespace module_decoder_unittest {
#define EXPECT_FAILURE(data) EXPECT_FAILURE_LEN(data, sizeof(data))
-#define EXPECT_OFF_END_FAILURE(data, min, max) \
- do { \
- for (size_t length = min; length < max; length++) { \
- EXPECT_FAILURE_LEN(data, length); \
- } \
+#define EXPECT_OFF_END_FAILURE(data, min) \
+ do { \
+ STATIC_ASSERT(min < arraysize(data)); \
+ for (size_t length = min; length < arraysize(data); length++) { \
+ EXPECT_FAILURE_LEN(data, length); \
+ } \
} while (false)
#define EXPECT_OK(result) \
@@ -124,6 +135,12 @@ namespace module_decoder_unittest {
if (!result.ok()) return; \
} while (false)
+#define EXPECT_NOT_OK(result, msg) \
+ do { \
+ EXPECT_FALSE(result.ok()); \
+ EXPECT_THAT(result.error().message(), HasSubstr(msg)); \
+ } while (false)
+
static size_t SizeOfVarInt(size_t value) {
size_t size = 0;
do {
@@ -213,22 +230,22 @@ TEST_F(WasmModuleVerifyTest, DecodeEmpty) {
TEST_F(WasmModuleVerifyTest, OneGlobal) {
static const byte data[] = {
- SECTION(Global, 6), // --
- 1,
- kLocalI32, // local type
- 0, // immutable
- WASM_INIT_EXPR_I32V_1(13) // init
+ SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ kLocalI32, // local type
+ 0, // immutable
+ WASM_INIT_EXPR_I32V_1(13)) // init
};
{
// Should decode to exactly one global.
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(0u, result.val->data_segments.size());
+ EXPECT_EQ(1u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(0u, result.value()->data_segments.size());
- const WasmGlobal* global = &result.val->globals.back();
+ const WasmGlobal* global = &result.value()->globals.back();
EXPECT_EQ(kWasmI32, global->type);
EXPECT_EQ(0u, global->offset);
@@ -237,28 +254,28 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) {
EXPECT_EQ(13, global->init.val.i32_const);
}
- EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
+ EXPECT_OFF_END_FAILURE(data, 1);
}
TEST_F(WasmModuleVerifyTest, AnyRefGlobal) {
WASM_FEATURE_SCOPE(anyref);
static const byte data[] = {
- SECTION(Global, 5), // --
- 1,
- kLocalAnyRef, // local type
- 0, // immutable
- WASM_INIT_EXPR_ANYREF // init
+ SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ kLocalAnyRef, // local type
+ 0, // immutable
+ WASM_INIT_EXPR_ANYREF) // init
};
{
// Should decode to exactly one global.
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(0u, result.val->data_segments.size());
+ EXPECT_EQ(1u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(0u, result.value()->data_segments.size());
- const WasmGlobal* global = &result.val->globals.back();
+ const WasmGlobal* global = &result.value()->globals.back();
EXPECT_EQ(kWasmAnyRef, global->type);
EXPECT_FALSE(global->mutability);
@@ -269,31 +286,29 @@ TEST_F(WasmModuleVerifyTest, AnyRefGlobal) {
TEST_F(WasmModuleVerifyTest, AnyRefGlobalWithGlobalInit) {
WASM_FEATURE_SCOPE(anyref);
static const byte data[] = {
- SECTION(Import, 8), // section header
- 1, // number of imports
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 'f', // global name
- kExternalGlobal, // import kind
- kLocalAnyRef, // type
- 0, // mutability
- SECTION(Global, 6), // --
- 1,
- kLocalAnyRef, // local type
- 0, // immutable
- WASM_INIT_EXPR_GLOBAL(0),
+ SECTION(Import, // --
+ ENTRY_COUNT(1), // number of imports
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // global name
+ kExternalGlobal, // import kind
+ kLocalAnyRef, // type
+ 0), // mutability
+ SECTION(Global, // --
+ ENTRY_COUNT(1),
+ kLocalAnyRef, // local type
+ 0, // immutable
+ WASM_INIT_EXPR_GLOBAL(0)),
};
{
// Should decode to exactly one global.
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(2u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(0u, result.val->data_segments.size());
+ EXPECT_EQ(2u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(0u, result.value()->data_segments.size());
- const WasmGlobal* global = &result.val->globals.back();
+ const WasmGlobal* global = &result.value()->globals.back();
EXPECT_EQ(kWasmAnyRef, global->type);
EXPECT_FALSE(global->mutability);
@@ -303,76 +318,62 @@ TEST_F(WasmModuleVerifyTest, AnyRefGlobalWithGlobalInit) {
TEST_F(WasmModuleVerifyTest, Global_invalid_type) {
static const byte data[] = {
- SECTION(Global, 6), // --
- 1,
- 64, // invalid memory type
- 1, // mutable
- WASM_INIT_EXPR_I32V_1(33), // init
+ SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ 64, // invalid memory type
+ 1, // mutable
+ WASM_INIT_EXPR_I32V_1(33)), // init
};
- ModuleResult result = DecodeModule(data, data + sizeof(data));
- EXPECT_FALSE(result.ok());
+ EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, Global_invalid_type2) {
static const byte data[] = {
- SECTION(Global, 6), // --
- 1,
- kLocalVoid, // invalid memory type
- 1, // mutable
- WASM_INIT_EXPR_I32V_1(33), // init
+ SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ kLocalVoid, // invalid memory type
+ 1, // mutable
+ WASM_INIT_EXPR_I32V_1(33)), // init
};
- ModuleResult result = DecodeModule(data, data + sizeof(data));
- EXPECT_FALSE(result.ok());
+ EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ZeroGlobals) {
- static const byte data[] = {
- SECTION(Global, 1), // --
- 0, // declare 0 globals
- };
+ static const byte data[] = {SECTION(Global, ENTRY_COUNT(0))};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
}
TEST_F(WasmModuleVerifyTest, ExportMutableGlobal) {
- WASM_FEATURE_SCOPE(mut_global);
{
static const byte data[] = {
- SECTION(Global, 6), // --
- 1,
- kLocalI32, // local type
- 0, // immutable
- WASM_INIT_EXPR_I32V_1(13), // init
- SECTION(Export, 8), // --
- 1, // Export count
- 4, // name length
- 'n', // --
- 'a', // --
- 'm', // --
- 'e', // --
- kExternalGlobal, // global
- 0, // global index
+ SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ kLocalI32, // local type
+ 0, // immutable
+ WASM_INIT_EXPR_I32V_1(13)), // init
+ SECTION(Export, // --
+ ENTRY_COUNT(1), // export count
+ ADD_COUNT('n', 'a', 'm', 'e'), // name
+ kExternalGlobal, // global
+ 0), // global index
};
EXPECT_VERIFIES(data);
}
{
static const byte data[] = {
- SECTION(Global, 6), // --
- 1, // --
- kLocalI32, // local type
- 1, // mutable
- WASM_INIT_EXPR_I32V_1(13), // init
- SECTION(Export, 8), // --
- 1, // Export count
- 4, // name length
- 'n', // --
- 'a', // --
- 'm', // --
- 'e', // --
- kExternalGlobal, // global
- 0, // global index
+ SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ kLocalI32, // local type
+ 1, // mutable
+ WASM_INIT_EXPR_I32V_1(13)), // init
+ SECTION(Export, // --
+ ENTRY_COUNT(1), // export count
+ ADD_COUNT('n', 'a', 'm', 'e'), // name
+ kExternalGlobal, // global
+ 0), // global index
};
EXPECT_VERIFIES(data);
}
@@ -417,42 +418,41 @@ TEST_F(WasmModuleVerifyTest, NGlobals) {
}
TEST_F(WasmModuleVerifyTest, GlobalWithInvalidMemoryType) {
- static const byte data[] = {SECTION(Global, 7),
- 33, // memory type
- 0, // exported
- WASM_INIT_EXPR_I32V_1(1)};
+ static const byte data[] = {SECTION(Global, // --
+ ENTRY_COUNT(1), // --
+ 33, // memory type
+ 0, // exported
+ WASM_INIT_EXPR_I32V_1(1))};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, TwoGlobals) {
- static const byte data[] = {
- SECTION(Global, 21),
- 2,
- kLocalF32, // type
- 0, // immutable
- WASM_INIT_EXPR_F32(22.0),
- kLocalF64, // type
- 1, // mutable
- WASM_INIT_EXPR_F64(23.0),
- };
+ static const byte data[] = {SECTION(Global, // --
+ ENTRY_COUNT(2), // --
+ kLocalF32, // type
+ 0, // immutable
+ WASM_INIT_EXPR_F32(22.0), // --
+ kLocalF64, // type
+ 1, // mutable
+ WASM_INIT_EXPR_F64(23.0))}; // --
{
// Should decode to exactly two globals.
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(2u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(0u, result.val->data_segments.size());
+ EXPECT_EQ(2u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(0u, result.value()->data_segments.size());
- const WasmGlobal* g0 = &result.val->globals[0];
+ const WasmGlobal* g0 = &result.value()->globals[0];
EXPECT_EQ(kWasmF32, g0->type);
EXPECT_EQ(0u, g0->offset);
EXPECT_FALSE(g0->mutability);
EXPECT_EQ(WasmInitExpr::kF32Const, g0->init.kind);
- const WasmGlobal* g1 = &result.val->globals[1];
+ const WasmGlobal* g1 = &result.value()->globals[1];
EXPECT_EQ(kWasmF64, g1->type);
EXPECT_EQ(8u, g1->offset);
@@ -460,72 +460,103 @@ TEST_F(WasmModuleVerifyTest, TwoGlobals) {
EXPECT_EQ(WasmInitExpr::kF64Const, g1->init.kind);
}
- EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
+ EXPECT_OFF_END_FAILURE(data, 1);
}
TEST_F(WasmModuleVerifyTest, ZeroExceptions) {
- static const byte data[] = {
- SECTION_EXCEPTIONS(1), 0,
- };
+ static const byte data[] = {SECTION(Exception, ENTRY_COUNT(0))};
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(0u, result.val->exceptions.size());
+ EXPECT_EQ(0u, result.value()->exceptions.size());
}
TEST_F(WasmModuleVerifyTest, OneI32Exception) {
- static const byte data[] = {SECTION_EXCEPTIONS(3), 1,
- // except[0] (i32)
- 1, kLocalI32};
+ static const byte data[] = {
+ SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_v_x(kLocalI32)), // sig#0 (i32)
+ SECTION(Exception, ENTRY_COUNT(1),
+ EXCEPTION_ENTRY(SIG_INDEX(0)))}; // except[0] (sig#0)
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->exceptions.size());
+ EXPECT_EQ(1u, result.value()->exceptions.size());
- const WasmException& e0 = result.val->exceptions.front();
+ const WasmException& e0 = result.value()->exceptions.front();
EXPECT_EQ(1u, e0.sig->parameter_count());
EXPECT_EQ(kWasmI32, e0.sig->GetParam(0));
}
TEST_F(WasmModuleVerifyTest, TwoExceptions) {
- static const byte data[] = {SECTION_EXCEPTIONS(6), 2,
- // except[0] (f32, i64)
- 2, kLocalF32, kLocalI64,
- // except[1] (i32)
- 1, kLocalI32};
+ static const byte data[] = {
+ SECTION(Type, ENTRY_COUNT(2),
+ SIG_ENTRY_v_x(kLocalI32), // sig#0 (i32)
+ SIG_ENTRY_v_xx(kLocalF32, kLocalI64)), // sig#1 (f32, i64)
+ SECTION(Exception, ENTRY_COUNT(2),
+ EXCEPTION_ENTRY(SIG_INDEX(1)), // except[0] (sig#1)
+ EXCEPTION_ENTRY(SIG_INDEX(0)))}; // except[1] (sig#0)
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(2u, result.val->exceptions.size());
- const WasmException& e0 = result.val->exceptions.front();
+ EXPECT_EQ(2u, result.value()->exceptions.size());
+ const WasmException& e0 = result.value()->exceptions.front();
EXPECT_EQ(2u, e0.sig->parameter_count());
EXPECT_EQ(kWasmF32, e0.sig->GetParam(0));
EXPECT_EQ(kWasmI64, e0.sig->GetParam(1));
- const WasmException& e1 = result.val->exceptions.back();
+ const WasmException& e1 = result.value()->exceptions.back();
EXPECT_EQ(kWasmI32, e1.sig->GetParam(0));
}
-TEST_F(WasmModuleVerifyTest, Exception_invalid_type) {
- static const byte data[] = {SECTION_EXCEPTIONS(3), 1,
- // except[0] (?)
- 1, 64};
+TEST_F(WasmModuleVerifyTest, Exception_invalid_sig_index) {
+ static const byte data[] = {
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(Exception, ENTRY_COUNT(1),
+ EXCEPTION_ENTRY(
+ SIG_INDEX(23)))}; // except[0] (sig#23 [out-of-bounds])
+ FAIL_IF_NO_EXPERIMENTAL_EH(data);
+
+ // Should fail decoding exception section.
+ WASM_FEATURE_SCOPE(eh);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "signature index 23 out of bounds");
+}
+
+TEST_F(WasmModuleVerifyTest, Exception_invalid_sig_return) {
+ static const byte data[] = {
+ SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_i_i),
+ SECTION(Exception, ENTRY_COUNT(1),
+ EXCEPTION_ENTRY(
+ SIG_INDEX(0)))}; // except[0] (sig#0 [invalid-return-type])
+ FAIL_IF_NO_EXPERIMENTAL_EH(data);
+
+ // Should fail decoding exception section.
+ WASM_FEATURE_SCOPE(eh);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "exception signature 0 has non-void return");
+}
+
+TEST_F(WasmModuleVerifyTest, Exception_invalid_attribute) {
+ static const byte data[] = {
+ SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_i_i),
+ SECTION(Exception, ENTRY_COUNT(1), 23,
+ SIG_INDEX(0))}; // except[0] (sig#0) [invalid-attribute]
FAIL_IF_NO_EXPERIMENTAL_EH(data);
// Should fail decoding exception section.
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
- EXPECT_FALSE(result.ok());
+ EXPECT_NOT_OK(result, "exception attribute 23 not supported");
}
TEST_F(WasmModuleVerifyTest, ExceptionSectionCorrectPlacement) {
- static const byte data[] = {SECTION(Import, 1), 0, SECTION_EXCEPTIONS(1), 0,
- SECTION(Export, 1), 0};
+ static const byte data[] = {SECTION(Import, ENTRY_COUNT(0)),
+ SECTION(Exception, ENTRY_COUNT(0)),
+ SECTION(Export, ENTRY_COUNT(0))};
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
@@ -534,57 +565,72 @@ TEST_F(WasmModuleVerifyTest, ExceptionSectionCorrectPlacement) {
}
TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterExport) {
- static const byte data[] = {SECTION(Export, 1), 0, SECTION_EXCEPTIONS(1), 0};
+ static const byte data[] = {SECTION(Export, ENTRY_COUNT(0)),
+ SECTION(Exception, ENTRY_COUNT(0))};
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
- EXPECT_FALSE(result.ok());
+ EXPECT_NOT_OK(result,
+ "The Exception section must appear before the Export section");
}
-TEST_F(WasmModuleVerifyTest, ExceptionSectionBeforeImport) {
- static const byte data[] = {SECTION_EXCEPTIONS(1), 0, SECTION(Import, 1), 0};
+TEST_F(WasmModuleVerifyTest, ExceptionSectionBeforeGlobal) {
+ static const byte data[] = {SECTION(Exception, ENTRY_COUNT(0)),
+ SECTION(Global, ENTRY_COUNT(0))};
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
- EXPECT_FALSE(result.ok());
+ EXPECT_NOT_OK(result, "unexpected section: Global");
+}
+
+TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterMemoryBeforeGlobal) {
+ STATIC_ASSERT(kMemorySectionCode + 1 == kGlobalSectionCode);
+ static const byte data[] = {SECTION(Memory, ENTRY_COUNT(0)),
+ SECTION(Exception, ENTRY_COUNT(0)),
+ SECTION(Global, ENTRY_COUNT(0))};
+ FAIL_IF_NO_EXPERIMENTAL_EH(data);
+
+ WASM_FEATURE_SCOPE(eh);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "unexpected section: Global");
}
TEST_F(WasmModuleVerifyTest, ExceptionImport) {
- static const byte data[] = {SECTION(Import, 9), // section header
- 1, // number of imports
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(2), // --
- 'e', 'x', // exception name
- kExternalException, // import kind
- // except[0] (i32)
- 1, kLocalI32};
+ static const byte data[] = {
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(Import, // section header
+ ENTRY_COUNT(1), // number of imports
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('e', 'x'), // exception name
+ kExternalException, // import kind
+ EXCEPTION_ENTRY(SIG_INDEX(0)))}; // except[0] (sig#0)
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->exceptions.size());
- EXPECT_EQ(1u, result.val->import_table.size());
+ EXPECT_EQ(1u, result.value()->exceptions.size());
+ EXPECT_EQ(1u, result.value()->import_table.size());
}
TEST_F(WasmModuleVerifyTest, ExceptionExport) {
- static const byte data[] = {SECTION_EXCEPTIONS(3), 1,
- // except[0] (i32)
- 1, kLocalI32, SECTION(Export, 4),
- 1, // exports
- NO_NAME, // --
- kExternalException, // --
- EXCEPTION_INDEX(0)};
+ static const byte data[] = {
+ SIGNATURES_SECTION_VOID_VOID,
+ SECTION(Exception, ENTRY_COUNT(1),
+ EXCEPTION_ENTRY(SIG_INDEX(0))), // except[0] (sig#0)
+ SECTION(Export, ENTRY_COUNT(1), // --
+ NO_NAME, // --
+ kExternalException, // --
+ EXCEPTION_INDEX(0))};
FAIL_IF_NO_EXPERIMENTAL_EH(data);
WASM_FEATURE_SCOPE(eh);
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->exceptions.size());
- EXPECT_EQ(1u, result.val->export_table.size());
+ EXPECT_EQ(1u, result.value()->exceptions.size());
+ EXPECT_EQ(1u, result.value()->export_table.size());
}
TEST_F(WasmModuleVerifyTest, OneSignature) {
@@ -594,74 +640,61 @@ TEST_F(WasmModuleVerifyTest, OneSignature) {
}
{
- static const byte data[] = {SECTION(Type, 1 + SIZEOF_SIG_ENTRY_x_x), 1,
- SIG_ENTRY_i_i};
+ static const byte data[] = {SECTION(Type, ENTRY_COUNT(1), SIG_ENTRY_i_i)};
EXPECT_VERIFIES(data);
}
}
TEST_F(WasmModuleVerifyTest, MultipleSignatures) {
static const byte data[] = {
- SECTION(Type, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_x_x +
- SIZEOF_SIG_ENTRY_x_xx), // --
- 3, // --
- SIG_ENTRY_v_v, // void -> void
- SIG_ENTRY_x_x(kLocalI32, kLocalF32), // f32 -> i32
- SIG_ENTRY_x_xx(kLocalI32, kLocalF64, kLocalF64), // f64,f64 -> i32
+ SECTION(
+ Type, // --
+ ENTRY_COUNT(3), // --
+ SIG_ENTRY_v_v, // void -> void
+ SIG_ENTRY_x_x(kLocalI32, kLocalF32), // f32 -> i32
+ SIG_ENTRY_x_xx(kLocalI32, kLocalF64, kLocalF64)), // f64,f64 -> i32
};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(3u, result.val->signatures.size());
- if (result.val->signatures.size() == 3) {
- EXPECT_EQ(0u, result.val->signatures[0]->return_count());
- EXPECT_EQ(1u, result.val->signatures[1]->return_count());
- EXPECT_EQ(1u, result.val->signatures[2]->return_count());
-
- EXPECT_EQ(0u, result.val->signatures[0]->parameter_count());
- EXPECT_EQ(1u, result.val->signatures[1]->parameter_count());
- EXPECT_EQ(2u, result.val->signatures[2]->parameter_count());
+ EXPECT_EQ(3u, result.value()->signatures.size());
+ if (result.value()->signatures.size() == 3) {
+ EXPECT_EQ(0u, result.value()->signatures[0]->return_count());
+ EXPECT_EQ(1u, result.value()->signatures[1]->return_count());
+ EXPECT_EQ(1u, result.value()->signatures[2]->return_count());
+
+ EXPECT_EQ(0u, result.value()->signatures[0]->parameter_count());
+ EXPECT_EQ(1u, result.value()->signatures[1]->parameter_count());
+ EXPECT_EQ(2u, result.value()->signatures[2]->parameter_count());
}
- EXPECT_OFF_END_FAILURE(data, 1, sizeof(data));
+ EXPECT_OFF_END_FAILURE(data, 1);
}
TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableImportedGlobal) {
// Import 2 globals so that we can initialize data with a global index != 0.
const byte data[] = {
- SECTION(Import, 15), // section header
- 2, // number of imports
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 'f', // global name
- kExternalGlobal, // import kind
- kLocalI32, // type
- 0, // mutability
- NAME_LENGTH(1), // --
- 'n', // module name
- NAME_LENGTH(1), // --
- 'g', // global name
- kExternalGlobal, // import kind
- kLocalI32, // type
- 0, // mutability
- SECTION(Memory, 4),
- ENTRY_COUNT(1),
- kHasMaximumFlag,
- 28,
- 28,
- SECTION(Data, 9),
- ENTRY_COUNT(1),
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_GLOBAL(1), // dest addr
- U32V_1(3), // source size
- 'a',
- 'b',
- 'c' // data bytes
+ SECTION(Import, // section header
+ ENTRY_COUNT(2), // number of imports
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // global name
+ kExternalGlobal, // import kind
+ kLocalI32, // type
+ 0, // mutability
+ ADD_COUNT('n'), // module name
+ ADD_COUNT('g'), // global name
+ kExternalGlobal, // import kind
+ kLocalI32, // type
+ 0), // mutability
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_GLOBAL(1), // dest addr
+ U32V_1(3), // source size
+ 'a', 'b', 'c') // data bytes
};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- WasmInitExpr expr = result.val->data_segments.back().dest_addr;
+ WasmInitExpr expr = result.value()->data_segments.back().dest_addr;
EXPECT_EQ(WasmInitExpr::kGlobalIndex, expr.kind);
EXPECT_EQ(1u, expr.val.global_index);
}
@@ -669,52 +702,33 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableImportedGlobal) {
TEST_F(WasmModuleVerifyTest, DataSegmentWithMutableImportedGlobal) {
// Only an immutable imported global can be used as an init_expr.
const byte data[] = {
- SECTION(Import, 8), // section header
- 1, // number of imports
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 'f', // global name
- kExternalGlobal, // import kind
- kLocalI32, // type
- 1, // mutability
- SECTION(Memory, 4),
- ENTRY_COUNT(1),
- kHasMaximumFlag,
- 28,
- 28,
- SECTION(Data, 9),
- ENTRY_COUNT(1),
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_GLOBAL(0), // dest addr
- U32V_1(3), // source size
- 'a',
- 'b',
- 'c' // data bytes
+ SECTION(Import, // section header
+ ENTRY_COUNT(1), // number of imports
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // global name
+ kExternalGlobal, // import kind
+ kLocalI32, // type
+ 1), // mutability
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_GLOBAL(0), // dest addr
+ U32V_1(3), // source size
+ 'a', 'b', 'c') // data bytes
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableGlobal) {
// Only an immutable imported global can be used as an init_expr.
const byte data[] = {
- SECTION(Memory, 4),
- ENTRY_COUNT(1),
- kHasMaximumFlag,
- 28,
- 28,
- SECTION(Global, 8), // --
- 1,
- kLocalI32, // local type
- 0, // immutable
- WASM_INIT_EXPR_I32V_3(0x9BBAA), // init
- SECTION(Data, 9),
- ENTRY_COUNT(1),
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_GLOBAL(0), // dest addr
- U32V_1(3), // source size
- 'a',
- 'b',
- 'c' // data bytes
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Global, ENTRY_COUNT(1),
+ kLocalI32, // local type
+ 0, // immutable
+ WASM_INIT_EXPR_I32V_3(0x9BBAA)), // init
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_GLOBAL(0), // dest addr
+ U32V_1(3), // source size
+ 'a', 'b', 'c') // data bytes
};
EXPECT_FAILURE(data);
}
@@ -722,30 +736,22 @@ TEST_F(WasmModuleVerifyTest, DataSegmentWithImmutableGlobal) {
TEST_F(WasmModuleVerifyTest, OneDataSegment) {
const byte kDataSegmentSourceOffset = 24;
const byte data[] = {
- SECTION(Memory, 4),
- ENTRY_COUNT(1),
- kHasMaximumFlag,
- 28,
- 28,
- SECTION(Data, 11),
- ENTRY_COUNT(1),
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_I32V_3(0x9BBAA), // dest addr
- U32V_1(3), // source size
- 'a',
- 'b',
- 'c' // data bytes
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_I32V_3(0x9BBAA), // dest addr
+ U32V_1(3), // source size
+ 'a', 'b', 'c') // data bytes
};
{
EXPECT_VERIFIES(data);
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(0u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(1u, result.val->data_segments.size());
+ EXPECT_EQ(0u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(1u, result.value()->data_segments.size());
- const WasmDataSegment* segment = &result.val->data_segments.back();
+ const WasmDataSegment* segment = &result.value()->data_segments.back();
EXPECT_EQ(WasmInitExpr::kI32Const, segment->dest_addr.kind);
EXPECT_EQ(0x9BBAA, segment->dest_addr.val.i32_const);
@@ -753,7 +759,7 @@ TEST_F(WasmModuleVerifyTest, OneDataSegment) {
EXPECT_EQ(3u, segment->source.length());
}
- EXPECT_OFF_END_FAILURE(data, 14, sizeof(data));
+ EXPECT_OFF_END_FAILURE(data, 14);
}
TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
@@ -761,44 +767,28 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
const byte kDataSegment1SourceOffset = kDataSegment0SourceOffset + 11;
const byte data[] = {
- SECTION(Memory, 4),
- ENTRY_COUNT(1),
- kHasMaximumFlag,
- 28,
- 28,
- SECTION(Data, 29),
- ENTRY_COUNT(2), // segment count
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_I32V_3(0x7FFEE), // #0: dest addr
- U32V_1(4), // source size
- 1,
- 2,
- 3,
- 4, // data bytes
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_I32V_3(0x6DDCC), // #1: dest addr
- U32V_1(10), // source size
- 1,
- 2,
- 3,
- 4,
- 5,
- 6,
- 7,
- 8,
- 9,
- 10 // data bytes
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Data,
+ ENTRY_COUNT(2), // segment count
+ LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_I32V_3(0x7FFEE), // #0: dest addr
+ U32V_1(4), // source size
+ 1, 2, 3, 4, // data bytes
+ LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_I32V_3(0x6DDCC), // #1: dest addr
+ U32V_1(10), // source size
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // data bytes
};
{
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(0u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(2u, result.val->data_segments.size());
+ EXPECT_EQ(0u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(2u, result.value()->data_segments.size());
- const WasmDataSegment* s0 = &result.val->data_segments[0];
- const WasmDataSegment* s1 = &result.val->data_segments[1];
+ const WasmDataSegment* s0 = &result.value()->data_segments[0];
+ const WasmDataSegment* s1 = &result.value()->data_segments[1];
EXPECT_EQ(WasmInitExpr::kI32Const, s0->dest_addr.kind);
EXPECT_EQ(0x7FFEE, s0->dest_addr.val.i32_const);
@@ -811,19 +801,15 @@ TEST_F(WasmModuleVerifyTest, TwoDataSegments) {
EXPECT_EQ(10u, s1->source.length());
}
- EXPECT_OFF_END_FAILURE(data, 14, sizeof(data));
+ EXPECT_OFF_END_FAILURE(data, 14);
}
TEST_F(WasmModuleVerifyTest, DataWithoutMemory) {
const byte data[] = {
- SECTION(Data, 11),
- ENTRY_COUNT(1),
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_I32V_3(0x9BBAA), // dest addr
- U32V_1(3), // source size
- 'a',
- 'b',
- 'c' // data bytes
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_I32V_3(0x9BBAA), // dest addr
+ U32V_1(3), // source size
+ 'a', 'b', 'c') // data bytes
};
EXPECT_FAILURE(data);
}
@@ -831,33 +817,23 @@ TEST_F(WasmModuleVerifyTest, DataWithoutMemory) {
TEST_F(WasmModuleVerifyTest, MaxMaximumMemorySize) {
{
const byte data[] = {
- SECTION(Memory, 6), ENTRY_COUNT(1), kHasMaximumFlag, 0, U32V_3(65536),
- };
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 0, U32V_3(65536))};
EXPECT_VERIFIES(data);
}
{
const byte data[] = {
- SECTION(Memory, 6), ENTRY_COUNT(1), kHasMaximumFlag, 0, U32V_3(65537),
- };
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 0, U32V_3(65537))};
EXPECT_FAILURE(data);
}
}
TEST_F(WasmModuleVerifyTest, DataSegment_wrong_init_type) {
const byte data[] = {
- SECTION(Memory, 4),
- ENTRY_COUNT(1),
- kHasMaximumFlag,
- 28,
- 28,
- SECTION(Data, 11),
- ENTRY_COUNT(1),
- LINEAR_MEMORY_INDEX_0,
- WASM_INIT_EXPR_F64(9.9), // dest addr
- U32V_1(3), // source size
- 'a',
- 'b',
- 'c' // data bytes
+ SECTION(Memory, ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0,
+ WASM_INIT_EXPR_F64(9.9), // dest addr
+ U32V_1(3), // source size
+ 'a', 'b', 'c') // data bytes
};
EXPECT_FAILURE(data);
@@ -865,13 +841,13 @@ TEST_F(WasmModuleVerifyTest, DataSegment_wrong_init_type) {
TEST_F(WasmModuleVerifyTest, DataSegmentEndOverflow) {
const byte data[] = {
- SECTION(Memory, 4), // memory section
- ENTRY_COUNT(1), kHasMaximumFlag, 28, 28,
- SECTION(Data, 10), // data section
- ENTRY_COUNT(1), // one entry
- LINEAR_MEMORY_INDEX_0, // mem index
- WASM_INIT_EXPR_I32V_1(0), // offset
- U32V_5(0xFFFFFFFF) // size
+ SECTION(Memory, // memory section
+ ENTRY_COUNT(1), kHasMaximumFlag, 28, 28),
+ SECTION(Data, // data section
+ ENTRY_COUNT(1), // one entry
+ LINEAR_MEMORY_INDEX_0, // mem index
+ WASM_INIT_EXPR_I32V_1(0), // offset
+ U32V_5(0xFFFFFFFF)) // size
};
EXPECT_FAILURE(data);
@@ -882,28 +858,28 @@ TEST_F(WasmModuleVerifyTest, OneIndirectFunction) {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), kLocalAnyFunc, 0, 1};
+ SECTION(Table, ENTRY_COUNT(1), kLocalAnyFunc, 0, 1),
+ // code ----------------------------------------------------------------
+ ONE_EMPTY_BODY};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
if (result.ok()) {
- EXPECT_EQ(1u, result.val->signatures.size());
- EXPECT_EQ(1u, result.val->functions.size());
- EXPECT_EQ(1u, result.val->tables.size());
- EXPECT_EQ(1u, result.val->tables[0].initial_size);
+ EXPECT_EQ(1u, result.value()->signatures.size());
+ EXPECT_EQ(1u, result.value()->functions.size());
+ EXPECT_EQ(1u, result.value()->tables.size());
+ EXPECT_EQ(1u, result.value()->tables[0].initial_size);
}
}
TEST_F(WasmModuleVerifyTest, ElementSectionWithInternalTable) {
static const byte data[] = {
// table ---------------------------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), kLocalAnyFunc, 0, 1,
+ SECTION(Table, ENTRY_COUNT(1), kLocalAnyFunc, 0, 1),
// elements ------------------------------------------------------------
- SECTION(Element, 1),
- 0 // entry count
- };
+ SECTION(Element, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
@@ -911,19 +887,15 @@ TEST_F(WasmModuleVerifyTest, ElementSectionWithInternalTable) {
TEST_F(WasmModuleVerifyTest, ElementSectionWithImportedTable) {
static const byte data[] = {
// imports -------------------------------------------------------------
- SECTION(Import, 9), ENTRY_COUNT(1),
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 't', // table name
- kExternalTable, // import kind
- kLocalAnyFunc, // elem_type
- 0, // no maximum field
- 1, // initial size
+ SECTION(Import, ENTRY_COUNT(1),
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('t'), // table name
+ kExternalTable, // import kind
+ kLocalAnyFunc, // elem_type
+ 0, // no maximum field
+ 1), // initial size
// elements ------------------------------------------------------------
- SECTION(Element, 1),
- 0 // entry count
- };
+ SECTION(Element, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
@@ -932,11 +904,11 @@ TEST_F(WasmModuleVerifyTest, ElementSectionWithoutTable) {
// Test that an element section without a table causes a validation error.
static const byte data[] = {
// elements ------------------------------------------------------------
- SECTION(Element, 4),
- 1, // entry count
- 0, // table index
- 0, // offset
- 0 // number of elements
+ SECTION(Element,
+ ENTRY_COUNT(1), // entry count
+ 0, // table index
+ 0, // offset
+ 0) // number of elements
};
EXPECT_FAILURE(data);
@@ -948,15 +920,15 @@ TEST_F(WasmModuleVerifyTest, Regression_735887) {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), kLocalAnyFunc, 0, 1,
+ SECTION(Table, ENTRY_COUNT(1), kLocalAnyFunc, 0, 1),
// elements ------------------------------------------------------------
- SECTION(Element, 7),
- 1, // entry count
- TABLE_INDEX(0), WASM_INIT_EXPR_I32V_1(0),
- 1, // elements count
- 0x9A // invalid I32V as function index
+ SECTION(Element,
+ ENTRY_COUNT(1), // entry count
+ TABLE_INDEX0, WASM_INIT_EXPR_I32V_1(0),
+ 1, // elements count
+ 0x9A) // invalid I32V as function index
};
EXPECT_FAILURE(data);
@@ -967,88 +939,82 @@ TEST_F(WasmModuleVerifyTest, OneIndirectFunction_one_entry) {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), kLocalAnyFunc, 0, 1,
+ SECTION(Table, ENTRY_COUNT(1), kLocalAnyFunc, 0, 1),
// elements ------------------------------------------------------------
- SECTION(Element, 7),
- 1, // entry count
- TABLE_INDEX(0), WASM_INIT_EXPR_I32V_1(0),
- 1, // elements count
- FUNC_INDEX(0)};
+ SECTION(Element,
+ ENTRY_COUNT(1), // entry count
+ TABLE_INDEX0, WASM_INIT_EXPR_I32V_1(0),
+ 1, // elements count
+ FUNC_INDEX(0)),
+ // code ----------------------------------------------------------------
+ ONE_EMPTY_BODY};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- if (result.ok()) {
- EXPECT_EQ(1u, result.val->signatures.size());
- EXPECT_EQ(1u, result.val->functions.size());
- EXPECT_EQ(1u, result.val->tables.size());
- EXPECT_EQ(1u, result.val->tables[0].initial_size);
- }
+ EXPECT_EQ(1u, result.value()->signatures.size());
+ EXPECT_EQ(1u, result.value()->functions.size());
+ EXPECT_EQ(1u, result.value()->tables.size());
+ EXPECT_EQ(1u, result.value()->tables[0].initial_size);
}
TEST_F(WasmModuleVerifyTest, MultipleIndirectFunctions) {
static const byte data[] = {
// sig#0 -------------------------------------------------------
- SECTION(Type, 1 + SIZEOF_SIG_ENTRY_v_v + SIZEOF_SIG_ENTRY_v_x),
- 2, // --
- SIG_ENTRY_v_v, // void -> void
- SIG_ENTRY_v_x(kLocalI32), // void -> i32
+ SECTION(Type,
+ ENTRY_COUNT(2), // --
+ SIG_ENTRY_v_v, // void -> void
+ SIG_ENTRY_v_x(kLocalI32)), // void -> i32
// funcs ------------------------------------------------------
- FOUR_EMPTY_FUNCTIONS,
+ FOUR_EMPTY_FUNCTIONS(SIG_INDEX(0)),
// table declaration -------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), kLocalAnyFunc, 0, 8,
+ SECTION(Table, ENTRY_COUNT(1), kLocalAnyFunc, 0, 8),
// table elements ----------------------------------------------
- SECTION(Element, 14),
- 1, // entry count
- TABLE_INDEX(0), WASM_INIT_EXPR_I32V_1(0),
- 8, // elements count
- FUNC_INDEX(0), // --
- FUNC_INDEX(1), // --
- FUNC_INDEX(2), // --
- FUNC_INDEX(3), // --
- FUNC_INDEX(0), // --
- FUNC_INDEX(1), // --
- FUNC_INDEX(2), // --
- FUNC_INDEX(3), // --
+ SECTION(Element,
+ ENTRY_COUNT(1), // entry count
+ TABLE_INDEX0, WASM_INIT_EXPR_I32V_1(0),
+ ADD_COUNT(FUNC_INDEX(0), FUNC_INDEX(1), FUNC_INDEX(2),
+ FUNC_INDEX(3), FUNC_INDEX(0), FUNC_INDEX(1),
+ FUNC_INDEX(2), FUNC_INDEX(3))),
FOUR_EMPTY_BODIES};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- if (result.ok()) {
- EXPECT_EQ(2u, result.val->signatures.size());
- EXPECT_EQ(4u, result.val->functions.size());
- EXPECT_EQ(1u, result.val->tables.size());
- EXPECT_EQ(8u, result.val->tables[0].initial_size);
- }
+ EXPECT_EQ(2u, result.value()->signatures.size());
+ EXPECT_EQ(4u, result.value()->functions.size());
+ EXPECT_EQ(1u, result.value()->tables.size());
+ EXPECT_EQ(8u, result.value()->tables[0].initial_size);
}
TEST_F(WasmModuleVerifyTest, ElementSectionMultipleTables) {
// Test that if we have multiple tables, in the element section we can target
// and initialize all tables.
WASM_FEATURE_SCOPE(anyref);
+ WASM_FEATURE_SCOPE(bulk_memory);
static const byte data[] = {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 7), ENTRY_COUNT(2), // section header
- kLocalAnyFunc, 0, 5, // table 0
- kLocalAnyFunc, 0, 9, // table 1
+ SECTION(Table, ENTRY_COUNT(2), // section header
+ kLocalAnyFunc, 0, 5, // table 0
+ kLocalAnyFunc, 0, 9), // table 1
// elements ------------------------------------------------------------
- SECTION(Element, 14),
- 2, // entry count
- TABLE_INDEX(0), // element for table 0
- WASM_INIT_EXPR_I32V_1(0), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(1), // element for table 1
- WASM_INIT_EXPR_I32V_1(7), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
- };
+ SECTION(Element,
+ ENTRY_COUNT(2), // entry count
+ TABLE_INDEX0, // element for table 0
+ WASM_INIT_EXPR_I32V_1(0), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(1), // element for table 1
+ WASM_INIT_EXPR_I32V_1(7), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0)), // entry 1
+ // code ----------------------------------------------------------------
+ ONE_EMPTY_BODY};
EXPECT_VERIFIES(data);
}
@@ -1057,55 +1023,53 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMixedTables) {
// Test that if we have multiple tables, both imported and module-defined, in
// the element section we can target and initialize all tables.
WASM_FEATURE_SCOPE(anyref);
+ WASM_FEATURE_SCOPE(bulk_memory);
static const byte data[] = {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// imports -------------------------------------------------------------
- SECTION(Import, 17), ENTRY_COUNT(2),
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 't', // table name
- kExternalTable, // import kind
- kLocalAnyFunc, // elem_type
- 0, // no maximum field
- 5, // initial size
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 's', // table name
- kExternalTable, // import kind
- kLocalAnyFunc, // elem_type
- 0, // no maximum field
- 10, // initial size
+ SECTION(Import, ENTRY_COUNT(2),
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('t'), // table name
+ kExternalTable, // import kind
+ kLocalAnyFunc, // elem_type
+ 0, // no maximum field
+ 5, // initial size
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('s'), // table name
+ kExternalTable, // import kind
+ kLocalAnyFunc, // elem_type
+ 0, // no maximum field
+ 10), // initial size
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 7), ENTRY_COUNT(2), // section header
- kLocalAnyFunc, 0, 15, // table 0
- kLocalAnyFunc, 0, 19, // table 1
+ SECTION(Table, ENTRY_COUNT(2), // section header
+ kLocalAnyFunc, 0, 15, // table 0
+ kLocalAnyFunc, 0, 19), // table 1
// elements ------------------------------------------------------------
- SECTION(Element, 27),
- 4, // entry count
- TABLE_INDEX(0), // element for table 0
- WASM_INIT_EXPR_I32V_1(0), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(1), // element for table 1
- WASM_INIT_EXPR_I32V_1(7), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
- TABLE_INDEX(2), // element for table 2
- WASM_INIT_EXPR_I32V_1(12), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(3), // element for table 1
- WASM_INIT_EXPR_I32V_1(17), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
- };
+ SECTION(Element,
+ 4, // entry count
+ TABLE_INDEX0, // element for table 0
+ WASM_INIT_EXPR_I32V_1(0), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(1), // element for table 1
+ WASM_INIT_EXPR_I32V_1(7), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0), // entry 1
+ TABLE_INDEX(2), // element for table 2
+ WASM_INIT_EXPR_I32V_1(12), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(3), // element for table 1
+ WASM_INIT_EXPR_I32V_1(17), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0)), // entry 1
+ // code ----------------------------------------------------------------
+ ONE_EMPTY_BODY};
EXPECT_VERIFIES(data);
}
@@ -1114,32 +1078,34 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMultipleTablesArbitraryOrder) {
// Test that the order in which tables are targeted in the element secion
// can be arbitrary.
WASM_FEATURE_SCOPE(anyref);
+ WASM_FEATURE_SCOPE(bulk_memory);
static const byte data[] = {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 7), ENTRY_COUNT(2), // section header
- kLocalAnyFunc, 0, 5, // table 0
- kLocalAnyFunc, 0, 9, // table 1
+ SECTION(Table, ENTRY_COUNT(2), // section header
+ kLocalAnyFunc, 0, 5, // table 0
+ kLocalAnyFunc, 0, 9), // table 1
// elements ------------------------------------------------------------
- SECTION(Element, 20),
- 3, // entry count
- TABLE_INDEX(0), // element for table 1
- WASM_INIT_EXPR_I32V_1(0), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(1), // element for table 0
- WASM_INIT_EXPR_I32V_1(7), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
- TABLE_INDEX(0), // element for table 1
- WASM_INIT_EXPR_I32V_1(3), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- };
+ SECTION(Element,
+ ENTRY_COUNT(3), // entry count
+ TABLE_INDEX0, // element for table 1
+ WASM_INIT_EXPR_I32V_1(0), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(1), // element for table 0
+ WASM_INIT_EXPR_I32V_1(7), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0), // entry 1
+ TABLE_INDEX0, // element for table 1
+ WASM_INIT_EXPR_I32V_1(3), // index
+ 1, // elements count
+ FUNC_INDEX(0)), // function
+ // code ----------------------------------------------------------------
+ ONE_EMPTY_BODY};
EXPECT_VERIFIES(data);
}
@@ -1148,55 +1114,53 @@ TEST_F(WasmModuleVerifyTest, ElementSectionMixedTablesArbitraryOrder) {
// Test that the order in which tables are targeted in the element secion can
// be arbitrary. In this test, tables can be both imported and module-defined.
WASM_FEATURE_SCOPE(anyref);
+ WASM_FEATURE_SCOPE(bulk_memory);
static const byte data[] = {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// imports -------------------------------------------------------------
- SECTION(Import, 17), ENTRY_COUNT(2),
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 't', // table name
- kExternalTable, // import kind
- kLocalAnyFunc, // elem_type
- 0, // no maximum field
- 5, // initial size
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 's', // table name
- kExternalTable, // import kind
- kLocalAnyFunc, // elem_type
- 0, // no maximum field
- 10, // initial size
+ SECTION(Import, ENTRY_COUNT(2),
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('t'), // table name
+ kExternalTable, // import kind
+ kLocalAnyFunc, // elem_type
+ 0, // no maximum field
+ 5, // initial size
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('s'), // table name
+ kExternalTable, // import kind
+ kLocalAnyFunc, // elem_type
+ 0, // no maximum field
+ 10), // initial size
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 7), ENTRY_COUNT(2), // section header
- kLocalAnyFunc, 0, 15, // table 0
- kLocalAnyFunc, 0, 19, // table 1
+ SECTION(Table, ENTRY_COUNT(2), // section header
+ kLocalAnyFunc, 0, 15, // table 0
+ kLocalAnyFunc, 0, 19), // table 1
// elements ------------------------------------------------------------
- SECTION(Element, 27),
- 4, // entry count
- TABLE_INDEX(2), // element for table 0
- WASM_INIT_EXPR_I32V_1(10), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(3), // element for table 1
- WASM_INIT_EXPR_I32V_1(17), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
- TABLE_INDEX(0), // element for table 2
- WASM_INIT_EXPR_I32V_1(2), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(1), // element for table 1
- WASM_INIT_EXPR_I32V_1(7), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
- };
+ SECTION(Element,
+ 4, // entry count
+ TABLE_INDEX(2), // element for table 0
+ WASM_INIT_EXPR_I32V_1(10), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(3), // element for table 1
+ WASM_INIT_EXPR_I32V_1(17), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0), // entry 1
+ TABLE_INDEX0, // element for table 2
+ WASM_INIT_EXPR_I32V_1(2), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(1), // element for table 1
+ WASM_INIT_EXPR_I32V_1(7), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0)), // entry 1
+ // code ----------------------------------------------------------------
+ ONE_EMPTY_BODY};
EXPECT_VERIFIES(data);
}
@@ -1205,27 +1169,28 @@ TEST_F(WasmModuleVerifyTest, ElementSectionDontInitAnyRefTable) {
// Test that tables of type 'AnyRef' cannot be initialized by the element
// section.
WASM_FEATURE_SCOPE(anyref);
+ WASM_FEATURE_SCOPE(bulk_memory);
static const byte data[] = {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 7), ENTRY_COUNT(2), // section header
- kLocalAnyRef, 0, 5, // table 0
- kLocalAnyFunc, 0, 9, // table 1
+ SECTION(Table, ENTRY_COUNT(2), // section header
+ kLocalAnyRef, 0, 5, // table 0
+ kLocalAnyFunc, 0, 9), // table 1
// elements ------------------------------------------------------------
- SECTION(Element, 14),
- 2, // entry count
- TABLE_INDEX(0), // element for table 0
- WASM_INIT_EXPR_I32V_1(0), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(1), // element for table 1
- WASM_INIT_EXPR_I32V_1(7), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
+ SECTION(Element,
+ ENTRY_COUNT(2), // entry count
+ TABLE_INDEX0, // element for table 0
+ WASM_INIT_EXPR_I32V_1(0), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(1), // element for table 1
+ WASM_INIT_EXPR_I32V_1(7), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0)), // entry 1
};
EXPECT_FAILURE(data);
@@ -1235,45 +1200,42 @@ TEST_F(WasmModuleVerifyTest, ElementSectionDontInitAnyRefImportedTable) {
// Test that imported tables of type AnyRef cannot be initialized in the
// elements section.
WASM_FEATURE_SCOPE(anyref);
+ WASM_FEATURE_SCOPE(bulk_memory);
static const byte data[] = {
// sig#0 ---------------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// imports -------------------------------------------------------------
- SECTION(Import, 17), ENTRY_COUNT(2),
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 't', // table name
- kExternalTable, // import kind
- kLocalAnyFunc, // elem_type
- 0, // no maximum field
- 5, // initial size
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 's', // table name
- kExternalTable, // import kind
- kLocalAnyRef, // elem_type
- 0, // no maximum field
- 10, // initial size
+ SECTION(Import, ENTRY_COUNT(2),
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('t'), // table name
+ kExternalTable, // import kind
+ kLocalAnyFunc, // elem_type
+ 0, // no maximum field
+ 5, // initial size
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('s'), // table name
+ kExternalTable, // import kind
+ kLocalAnyRef, // elem_type
+ 0, // no maximum field
+ 10), // initial size
// funcs ---------------------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// table declaration ---------------------------------------------------
- SECTION(Table, 7), ENTRY_COUNT(2), // section header
- kLocalAnyFunc, 0, 15, // table 0
- kLocalAnyFunc, 0, 19, // table 1
+ SECTION(Table, ENTRY_COUNT(2), // section header
+ kLocalAnyFunc, 0, 15, // table 0
+ kLocalAnyFunc, 0, 19), // table 1
// elements ------------------------------------------------------------
- SECTION(Element, 14),
- 4, // entry count
- TABLE_INDEX(0), // element for table 0
- WASM_INIT_EXPR_I32V_1(10), // index
- 1, // elements count
- FUNC_INDEX(0), // function
- TABLE_INDEX(1), // element for table 1
- WASM_INIT_EXPR_I32V_1(17), // index
- 2, // elements count
- FUNC_INDEX(0), // entry 0
- FUNC_INDEX(0), // entry 1
+ SECTION(Element,
+ ENTRY_COUNT(4), // entry count
+ TABLE_INDEX0, // element for table 0
+ WASM_INIT_EXPR_I32V_1(10), // index
+ 1, // elements count
+ FUNC_INDEX(0), // function
+ TABLE_INDEX(1), // element for table 1
+ WASM_INIT_EXPR_I32V_1(17), // index
+ 2, // elements count
+ FUNC_INDEX(0), // entry 0
+ FUNC_INDEX(0)), // entry 1
};
EXPECT_FAILURE(data);
@@ -1284,8 +1246,7 @@ TEST_F(WasmModuleVerifyTest, IndirectFunctionNoFunctions) {
// sig#0 -------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// indirect table ----------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), 1, 0, 0,
- };
+ SECTION(Table, ENTRY_COUNT(1), 1, 0, 0)};
EXPECT_FAILURE(data);
}
@@ -1295,24 +1256,23 @@ TEST_F(WasmModuleVerifyTest, IndirectFunctionInvalidIndex) {
// sig#0 -------------------------------------------------------
SIGNATURES_SECTION_VOID_VOID,
// functions ---------------------------------------------------
- ONE_EMPTY_FUNCTION,
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
// indirect table ----------------------------------------------
- SECTION(Table, 4), ENTRY_COUNT(1), 1, 1, 0,
- };
+ SECTION(Table, ENTRY_COUNT(1), 1, 1, 0)};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, MultipleTablesWithoutFlag) {
static const byte data[] = {
- SECTION(Table, 7), // table section
- ENTRY_COUNT(2), // 2 tables
- kLocalAnyFunc, // table 1: type
- 0, // table 1: no maximum
- 10, // table 1: minimum size
- kLocalAnyFunc, // table 2: type
- 0, // table 2: no maximum
- 10, // table 2: minimum size
+ SECTION(Table, // table section
+ ENTRY_COUNT(2), // 2 tables
+ kLocalAnyFunc, // table 1: type
+ 0, // table 1: no maximum
+ 10, // table 1: minimum size
+ kLocalAnyFunc, // table 2: type
+ 0, // table 2: no maximum
+ 10), // table 2: minimum size
};
EXPECT_FAILURE(data);
}
@@ -1320,26 +1280,26 @@ TEST_F(WasmModuleVerifyTest, MultipleTablesWithoutFlag) {
TEST_F(WasmModuleVerifyTest, MultipleTablesWithFlag) {
WASM_FEATURE_SCOPE(anyref);
static const byte data[] = {
- SECTION(Table, 7), // table section
- ENTRY_COUNT(2), // 2 tables
- kLocalAnyFunc, // table 1: type
- 0, // table 1: no maximum
- 10, // table 1: minimum size
- kLocalAnyRef, // table 2: type
- 0, // table 2: no maximum
- 11, // table 2: minimum size
+ SECTION(Table, // table section
+ ENTRY_COUNT(2), // 2 tables
+ kLocalAnyFunc, // table 1: type
+ 0, // table 1: no maximum
+ 10, // table 1: minimum size
+ kLocalAnyRef, // table 2: type
+ 0, // table 2: no maximum
+ 11), // table 2: minimum size
};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(2u, result.val->tables.size());
+ EXPECT_EQ(2u, result.value()->tables.size());
- EXPECT_EQ(10u, result.val->tables[0].initial_size);
- EXPECT_EQ(kWasmAnyFunc, result.val->tables[0].type);
+ EXPECT_EQ(10u, result.value()->tables[0].initial_size);
+ EXPECT_EQ(kWasmAnyFunc, result.value()->tables[0].type);
- EXPECT_EQ(11u, result.val->tables[1].initial_size);
- EXPECT_EQ(kWasmAnyRef, result.val->tables[1].type);
+ EXPECT_EQ(11u, result.value()->tables[1].initial_size);
+ EXPECT_EQ(kWasmAnyRef, result.value()->tables[1].type);
}
class WasmSignatureDecodeTest : public TestWithZone {
@@ -1490,8 +1450,9 @@ TEST_F(WasmSignatureDecodeTest, Fail_anyref_without_flag) {
WASM_FEATURE_SCOPE_VAL(anyref, false);
byte ref_types[] = {kLocalAnyFunc, kLocalAnyRef};
for (byte invalid_type : ref_types) {
- for (size_t i = 0; i < SIZEOF_SIG_ENTRY_x_xx; i++) {
+ for (size_t i = 0;; i++) {
byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)};
+ if (i >= arraysize(data)) break;
data[i] = invalid_type;
FunctionSig* sig = DecodeSig(data, data + sizeof(data));
EXPECT_EQ(nullptr, sig);
@@ -1501,8 +1462,9 @@ TEST_F(WasmSignatureDecodeTest, Fail_anyref_without_flag) {
TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) {
byte kInvalidType = 76;
- for (size_t i = 0; i < SIZEOF_SIG_ENTRY_x_xx; i++) {
+ for (size_t i = 0;; i++) {
byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)};
+ if (i >= arraysize(data)) break;
data[i] = kInvalidType;
FunctionSig* sig = DecodeSig(data, data + sizeof(data));
EXPECT_EQ(nullptr, sig);
@@ -1529,15 +1491,12 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) {
class WasmFunctionVerifyTest : public TestWithIsolateAndZone {
public:
- WasmFeatures enabled_features_;
- WasmModule module;
- Vector<const byte> bytes;
-
FunctionResult DecodeWasmFunction(const ModuleWireBytes& wire_bytes,
const WasmModule* module,
const byte* function_start,
const byte* function_end) {
- return DecodeWasmFunctionForTesting(enabled_features_, zone(), wire_bytes,
+ WasmFeatures enabled_features;
+ return DecodeWasmFunctionForTesting(enabled_features, zone(), wire_bytes,
module, function_start, function_end,
isolate()->counters());
}
@@ -1558,16 +1517,16 @@ TEST_F(WasmFunctionVerifyTest, Ok_v_v_empty) {
kExprEnd // body
};
- FunctionResult result =
- DecodeWasmFunction(bytes, &module, data, data + sizeof(data));
+ WasmModule module;
+ FunctionResult result = DecodeWasmFunction(ModuleWireBytes({}), &module, data,
+ data + sizeof(data));
EXPECT_OK(result);
- if (result.val && result.ok()) {
- WasmFunction* function = result.val.get();
+ if (result.value() && result.ok()) {
+ WasmFunction* function = result.value().get();
EXPECT_EQ(0u, function->sig->parameter_count());
EXPECT_EQ(0u, function->sig->return_count());
- EXPECT_EQ(static_cast<uint32_t>(SIZEOF_SIG_ENTRY_v_v),
- function->code.offset());
+ EXPECT_EQ(COUNT_ARGS(SIG_ENTRY_v_v), function->code.offset());
EXPECT_EQ(sizeof(data), function->code.end_offset());
// TODO(titzer): verify encoding of local declarations
}
@@ -1658,102 +1617,94 @@ TEST_F(WasmModuleVerifyTest, UnknownSectionSkipped) {
static const byte data[] = {
UNKNOWN_SECTION(1),
0, // one byte section
- SECTION(Global, 6),
- 1,
- kLocalI32, // memory type
- 0, // exported
- WASM_INIT_EXPR_I32V_1(33), // init
+ SECTION(Global, ENTRY_COUNT(1),
+ kLocalI32, // memory type
+ 0, // exported
+ WASM_INIT_EXPR_I32V_1(33)), // init
};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->globals.size());
- EXPECT_EQ(0u, result.val->functions.size());
- EXPECT_EQ(0u, result.val->data_segments.size());
+ EXPECT_EQ(1u, result.value()->globals.size());
+ EXPECT_EQ(0u, result.value()->functions.size());
+ EXPECT_EQ(0u, result.value()->data_segments.size());
- const WasmGlobal* global = &result.val->globals.back();
+ const WasmGlobal* global = &result.value()->globals.back();
EXPECT_EQ(kWasmI32, global->type);
EXPECT_EQ(0u, global->offset);
}
TEST_F(WasmModuleVerifyTest, ImportTable_empty) {
- static const byte data[] = {SECTION(Type, 1), 0, SECTION(Import, 1), 0};
+ static const byte data[] = {SECTION(Type, ENTRY_COUNT(0)),
+ SECTION(Import, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ImportTable_nosigs1) {
- static const byte data[] = {SECTION(Import, 1), 0};
+ static const byte data[] = {SECTION(Import, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ImportTable_mutable_global) {
- WASM_FEATURE_SCOPE(mut_global);
{
static const byte data[] = {
- SECTION(Import, 8), // section header
- 1, // number of imports
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 'f', // global name
- kExternalGlobal, // import kind
- kLocalI32, // type
- 0, // mutability
+ SECTION(Import, // section header
+ ENTRY_COUNT(1), // number of imports
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // global name
+ kExternalGlobal, // import kind
+ kLocalI32, // type
+ 0), // mutability
};
EXPECT_VERIFIES(data);
}
{
static const byte data[] = {
- SECTION(Import, 8), // section header
- 1, // sig table
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 'f', // global name
- kExternalGlobal, // import kind
- kLocalI32, // type
- 1, // mutability
+ SECTION(Import, // section header
+ ENTRY_COUNT(1), // sig table
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // global name
+ kExternalGlobal, // import kind
+ kLocalI32, // type
+ 1), // mutability
};
EXPECT_VERIFIES(data);
}
}
TEST_F(WasmModuleVerifyTest, ImportTable_mutability_malformed) {
- WASM_FEATURE_SCOPE(mut_global);
- static const byte data[] = {
- SECTION(Import, 8),
- 1, // --
- NAME_LENGTH(1), // --
- 'm', // module name
- NAME_LENGTH(1), // --
- 'g', // global name
- kExternalGlobal, // import kind
- kLocalI32, // type
- 2, // invalid mutability
+ static const byte data[] = {
+ SECTION(Import,
+ ENTRY_COUNT(1), // --
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('g'), // global name
+ kExternalGlobal, // import kind
+ kLocalI32, // type
+ 2), // invalid mutability
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ImportTable_nosigs2) {
static const byte data[] = {
- SECTION(Import, 6), 1, // sig table
- NAME_LENGTH(1), 'm', // module name
- NAME_LENGTH(1), 'f', // function name
- kExternalFunction, // import kind
- IMPORT_SIG_INDEX(0), // sig index
+ SECTION(Import, ENTRY_COUNT(1), // sig table
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // function name
+ kExternalFunction, // import kind
+ SIG_INDEX(0)), // sig index
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ImportTable_invalid_sig) {
static const byte data[] = {
- SECTION(Type, 1), 0, // --
- SECTION(Import, 6), 1, // --
- NAME_LENGTH(1), 'm', // module name
- NAME_LENGTH(1), 'f', // function name
- kExternalFunction, // import kind
- IMPORT_SIG_INDEX(0), // sig index
+ SECTION(Type, ENTRY_COUNT(0)), // --
+ SECTION(Import, ENTRY_COUNT(1), // --
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // function name
+ kExternalFunction, // import kind
+ SIG_INDEX(0)), // sig index
};
EXPECT_FAILURE(data);
}
@@ -1762,14 +1713,12 @@ TEST_F(WasmModuleVerifyTest, ImportTable_one_sig) {
static const byte data[] = {
// signatures
SIGNATURES_SECTION_VOID_VOID,
- SECTION(Import, 7),
- 1, // --
- NAME_LENGTH(1),
- 'm', // module name
- NAME_LENGTH(1),
- 'f', // function name
- kExternalFunction, // import kind
- IMPORT_SIG_INDEX(0), // sig index
+ SECTION(Import,
+ ENTRY_COUNT(1), // --
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // function name
+ kExternalFunction, // import kind
+ SIG_INDEX(0)), // sig index
};
EXPECT_VERIFIES(data);
}
@@ -1778,13 +1727,13 @@ TEST_F(WasmModuleVerifyTest, ImportTable_invalid_module) {
static const byte data[] = {
// signatures
SIGNATURES_SECTION_VOID_VOID, // --
- SECTION(Import, 7), // --
- 1, // --
- NO_NAME, // module name
- NAME_LENGTH(1), // --
- 'f', // function name
- kExternalFunction, // import kind
- IMPORT_SIG_INDEX(0), // sig index
+ SECTION(Import, // --
+ ENTRY_COUNT(1), // --
+ NO_NAME, // module name
+ ADD_COUNT('f'), // function name
+ kExternalFunction, // import kind
+ SIG_INDEX(0), // sig index
+ 0), // auxiliary data
};
EXPECT_FAILURE(data);
}
@@ -1793,143 +1742,129 @@ TEST_F(WasmModuleVerifyTest, ImportTable_off_end) {
static const byte data[] = {
// signatures
SIGNATURES_SECTION_VOID_VOID,
- SECTION(Import, 6),
- 1,
- NAME_LENGTH(1),
- 'm', // module name
- NAME_LENGTH(1),
- 'f', // function name
- kExternalFunction, // import kind
- IMPORT_SIG_INDEX(0), // sig index
+ SECTION(Import, ENTRY_COUNT(1),
+ ADD_COUNT('m'), // module name
+ ADD_COUNT('f'), // function name
+ kExternalFunction), // import kind
+ SIG_INDEX(0), // sig index (outside import section!)
};
- EXPECT_OFF_END_FAILURE(data, 16, sizeof(data));
+ EXPECT_OFF_END_FAILURE(data, arraysize(data) - 3);
}
TEST_F(WasmModuleVerifyTest, ExportTable_empty1) {
static const byte data[] = { // signatures
SIGNATURES_SECTION_VOID_VOID, // --
- ONE_EMPTY_FUNCTION, SECTION(Export, 1), // --
- 0, // --
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
+ SECTION(Export, ENTRY_COUNT(0)), // --
ONE_EMPTY_BODY};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->functions.size());
- EXPECT_EQ(0u, result.val->export_table.size());
+ EXPECT_EQ(1u, result.value()->functions.size());
+ EXPECT_EQ(0u, result.value()->export_table.size());
}
TEST_F(WasmModuleVerifyTest, ExportTable_empty2) {
- static const byte data[] = {
- SECTION(Type, 1), 0, SECTION(Export, 1), 0 // --
- };
+ static const byte data[] = {SECTION(Type, ENTRY_COUNT(0)),
+ SECTION(Export, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ExportTable_NoFunctions2) {
- static const byte data[] = {SECTION(Export, 1), 0};
+ static const byte data[] = {SECTION(Export, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, ExportTableOne) {
- static const byte data[] = {// signatures
- SIGNATURES_SECTION_VOID_VOID,
- ONE_EMPTY_FUNCTION,
- SECTION(Export, 4),
- 1, // exports
- NO_NAME, // --
- kExternalFunction, // --
- FUNC_INDEX(0), // --
- ONE_EMPTY_BODY};
+ static const byte data[] = {
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
+ SECTION(Export,
+ ENTRY_COUNT(1), // exports
+ NO_NAME, // --
+ kExternalFunction, // --
+ FUNC_INDEX(0)), // --
+ ONE_EMPTY_BODY};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->functions.size());
- EXPECT_EQ(1u, result.val->export_table.size());
+ EXPECT_EQ(1u, result.value()->functions.size());
+ EXPECT_EQ(1u, result.value()->export_table.size());
}
TEST_F(WasmModuleVerifyTest, ExportNameWithInvalidStringLength) {
- static const byte data[] = {// signatures
- SIGNATURES_SECTION_VOID_VOID,
- ONE_EMPTY_FUNCTION,
- SECTION(Export, 12),
- 1, // exports
- NAME_LENGTH(84), // invalid string length
- 'e', // --
- kExternalFunction, // --
- FUNC_INDEX(0)};
+ static const byte data[] = {
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
+ SECTION(Export,
+ ENTRY_COUNT(1), // exports
+ U32V_1(84), // invalid string length
+ 'e', // --
+ kExternalFunction, // --
+ FUNC_INDEX(0), // --
+ 0, 0, 0) // auxiliary data
+ };
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, ExportTableTwo) {
- static const byte data[] = {// signatures
- SIGNATURES_SECTION_VOID_VOID,
- ONE_EMPTY_FUNCTION,
- SECTION(Export, 14),
- 2, // exports
- NAME_LENGTH(4),
- 'n',
- 'a',
- 'm',
- 'e', // --
- kExternalFunction,
- FUNC_INDEX(0), // --
- NAME_LENGTH(3),
- 'n',
- 'o',
- 'm', // --
- kExternalFunction, // --
- FUNC_INDEX(0), // --
- ONE_EMPTY_BODY};
+ static const byte data[] = {
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
+ SECTION(Export,
+ ENTRY_COUNT(2), // exports
+ ADD_COUNT('n', 'a', 'm', 'e'), // --
+ kExternalFunction, // --
+ FUNC_INDEX(0), // --
+ ADD_COUNT('n', 'o', 'm'), // --
+ kExternalFunction, // --
+ FUNC_INDEX(0)), // --
+ ONE_EMPTY_BODY};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(1u, result.val->functions.size());
- EXPECT_EQ(2u, result.val->export_table.size());
+ EXPECT_EQ(1u, result.value()->functions.size());
+ EXPECT_EQ(2u, result.value()->export_table.size());
}
TEST_F(WasmModuleVerifyTest, ExportTableThree) {
- static const byte data[] = {// signatures
- SIGNATURES_SECTION_VOID_VOID,
- THREE_EMPTY_FUNCTIONS,
- SECTION(Export, 13),
- 3, // exports
- NAME_LENGTH(1),
- 'a', // --
- kExternalFunction,
- FUNC_INDEX(0), // --
- NAME_LENGTH(1),
- 'b', // --
- kExternalFunction,
- FUNC_INDEX(1), // --
- NAME_LENGTH(1),
- 'c', // --
- kExternalFunction,
- FUNC_INDEX(2), // --
- THREE_EMPTY_BODIES};
+ static const byte data[] = {
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID, THREE_EMPTY_FUNCTIONS(SIG_INDEX(0)),
+ SECTION(Export,
+ ENTRY_COUNT(3), // exports
+ ADD_COUNT('a'), // --
+ kExternalFunction,
+ FUNC_INDEX(0), // --
+ ADD_COUNT('b'), // --
+ kExternalFunction,
+ FUNC_INDEX(1), // --
+ ADD_COUNT('c'), // --
+ kExternalFunction,
+ FUNC_INDEX(2)), // --
+ THREE_EMPTY_BODIES};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_OK(result);
- EXPECT_EQ(3u, result.val->functions.size());
- EXPECT_EQ(3u, result.val->export_table.size());
+ EXPECT_EQ(3u, result.value()->functions.size());
+ EXPECT_EQ(3u, result.value()->export_table.size());
}
TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
for (int i = 0; i < 6; i++) {
- const byte data[] = {// signatures
- SIGNATURES_SECTION_VOID_VOID,
- THREE_EMPTY_FUNCTIONS,
- SECTION(Export, 6),
- 1, // exports
- NAME_LENGTH(2),
- 'e',
- 'x', // --
- kExternalFunction,
- FUNC_INDEX(i), // --
- THREE_EMPTY_BODIES};
+ const byte data[] = {
+ // signatures
+ SIGNATURES_SECTION_VOID_VOID, THREE_EMPTY_FUNCTIONS(SIG_INDEX(0)),
+ SECTION(Export,
+ ENTRY_COUNT(1), // exports
+ ADD_COUNT('e', 'x'), // --
+ kExternalFunction,
+ FUNC_INDEX(i)), // --
+ THREE_EMPTY_BODIES};
if (i < 3) {
EXPECT_VERIFIES(data);
@@ -1942,43 +1877,23 @@ TEST_F(WasmModuleVerifyTest, ExportTableThreeOne) {
TEST_F(WasmModuleVerifyTest, ExportTableOne_off_end) {
static const byte data[] = {
// signatures
- SIGNATURES_SECTION_VOID_VOID,
- ONE_EMPTY_FUNCTION,
- SECTION(Export, 1 + 6),
- 1, // exports
- NO_NAME, // --
- kExternalFunction,
- FUNC_INDEX(0), // --
+ SIGNATURES_SECTION_VOID_VOID, ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
+ SECTION(Export,
+ ENTRY_COUNT(1), // exports
+ NO_NAME, // --
+ kExternalFunction,
+ FUNC_INDEX(0), // --
+ 0, 0, 0) // auxiliary data
};
- for (size_t length = 33; length < sizeof(data); length++) {
- ModuleResult result = DecodeModule(data, data + length);
- EXPECT_FALSE(result.ok());
- }
-}
-
-TEST_F(WasmModuleVerifyTest, FunctionSignatures_empty) {
- static const byte data[] = {
- SECTION(Type, 1), 0, // --
- SECTION(Function, 1), 0 // --
- }; // --
- EXPECT_VERIFIES(data);
-}
-
-TEST_F(WasmModuleVerifyTest, FunctionSignatures_one) {
- static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(1, 0) // --
- };
- EXPECT_VERIFIES(data);
+ EXPECT_OFF_END_FAILURE(data, arraysize(data) - 3);
}
TEST_F(WasmModuleVerifyTest, Regression_648070) {
static const byte data[] = {
- SECTION(Type, 1), 0, // --
- SECTION(Function, 5), // --
- U32V_5(3500228624) // function count = 3500228624
- }; // --
+ SECTION(Type, ENTRY_COUNT(0)), // --
+ SECTION(Function, U32V_5(3500228624)) // function count = 3500228624
+ }; // --
EXPECT_FAILURE(data);
}
@@ -1987,10 +1902,10 @@ TEST_F(WasmModuleVerifyTest, Regression_738097) {
static const byte data[] = {
SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
FUNCTION_SIGNATURES_SECTION(1, 0), // --
- SECTION(Code, 1 + 5 + 1), // --
- 1, // --
- U32V_5(0xFFFFFFFF), // function size,
- 0 // No real body
+ SECTION(Code, // --
+ ENTRY_COUNT(1), // --
+ U32V_5(0xFFFFFFFF), // function size,
+ 0) // No real body
};
EXPECT_FAILURE(data);
}
@@ -2031,40 +1946,36 @@ TEST_F(WasmModuleVerifyTest, FunctionBodies_empty) {
TEST_F(WasmModuleVerifyTest, FunctionBodies_one_empty) {
static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(1, 0), // --
- SECTION(Code, 1 + SIZEOF_EMPTY_BODY), 1, EMPTY_BODY // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ ONE_EMPTY_BODY // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_one_nop) {
static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(1, 0), // --
- SECTION(Code, 1 + SIZEOF_NOP_BODY), 1, NOP_BODY // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ SECTION(Code, ENTRY_COUNT(1), NOP_BODY) // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch1) {
static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
- SECTION(Code, 1 + SIZEOF_EMPTY_BODY), 1, // --
- EMPTY_BODY // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
+ ONE_EMPTY_BODY // --
};
EXPECT_FAILURE(data);
}
TEST_F(WasmModuleVerifyTest, FunctionBodies_count_mismatch2) {
static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(1, 0), // --
- SECTION(Code, 1 + 2 * SIZEOF_NOP_BODY), // --
- ENTRY_COUNT(2), // --
- NOP_BODY, // --
- NOP_BODY // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ SECTION(Code, ENTRY_COUNT(2), NOP_BODY, NOP_BODY) // --
};
EXPECT_FAILURE(data);
}
@@ -2077,54 +1988,71 @@ TEST_F(WasmModuleVerifyTest, Names_empty) {
}
TEST_F(WasmModuleVerifyTest, Names_one_empty) {
+ // TODO(wasm): This test does not test anything (corrupt name section does not
+ // fail validation).
static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(1, 0), // --
- SECTION(Code, 1 + SIZEOF_EMPTY_BODY),
- ENTRY_COUNT(1),
- EMPTY_BODY, // --
- SECTION_NAMES(1 + 5),
- ENTRY_COUNT(1),
- FOO_STRING,
- NO_LOCAL_NAMES // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(1, 0), // --
+ ONE_EMPTY_BODY, // --
+ SECTION_NAMES(ENTRY_COUNT(1), FOO_STRING, NO_LOCAL_NAMES) // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, Names_two_empty) {
+ // TODO(wasm): This test does not test anything (corrupt name section does not
+ // fail validation).
static const byte data[] = {
- SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
- FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
- SECTION(Code, 1 + 2 * SIZEOF_EMPTY_BODY), // --
- ENTRY_COUNT(2),
- EMPTY_BODY,
- EMPTY_BODY, // --
- SECTION_NAMES(1 + 10),
- ENTRY_COUNT(2), // --
- FOO_STRING,
- NO_LOCAL_NAMES, // --
- FOO_STRING,
- NO_LOCAL_NAMES, // --
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // --
+ FUNCTION_SIGNATURES_SECTION(2, 0, 0), // --
+ TWO_EMPTY_BODIES, // --
+ SECTION_NAMES(ENTRY_COUNT(2), // --
+ FOO_STRING, NO_LOCAL_NAMES, // --
+ FOO_STRING, NO_LOCAL_NAMES), // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, Regression684855) {
static const byte data[] = {
- SECTION_NAMES(12),
- 0xFB, // functions count
- 0x27, // |
- 0x00, // function name length
- 0xFF, // local names count
- 0xFF, // |
- 0xFF, // |
- 0xFF, // |
- 0xFF, // |
- 0xFF, // error: "varint too large"
- 0xFF, // |
- 0x00, // --
- 0x00 // --
+ SECTION_NAMES(0xFB, // functions count
+ 0x27, // |
+ 0x00, // function name length
+ 0xFF, // local names count
+ 0xFF, // |
+ 0xFF, // |
+ 0xFF, // |
+ 0xFF, // |
+ 0xFF, // error: "varint too large"
+ 0xFF, // |
+ 0x00, // --
+ 0x00) // --
+ };
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, FunctionSectionWithoutCodeSection) {
+ static const byte data[] = {
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // Type section.
+ FUNCTION_SIGNATURES_SECTION(1, 0), // Function section.
};
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "function count is 1, but code section is absent");
+}
+
+TEST_F(WasmModuleVerifyTest, CodeSectionWithoutFunctionSection) {
+ static const byte data[] = {ONE_EMPTY_BODY};
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "function body count 1 mismatch (0 expected)");
+}
+
+TEST_F(WasmModuleVerifyTest, EmptyFunctionSectionWithoutCodeSection) {
+ static const byte data[] = {SECTION(Function, ENTRY_COUNT(0))};
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, EmptyCodeSectionWithoutFunctionSection) {
+ static const byte data[] = {SECTION(Code, ENTRY_COUNT(0))};
EXPECT_VERIFIES(data);
}
@@ -2199,15 +2127,15 @@ TEST_F(WasmInitExprDecodeTest, InitExpr_illegal) {
TEST_F(WasmModuleVerifyTest, Multiple_Named_Sections) {
static const byte data[] = {
- SECTION(Unknown, 4), 1, 'X', 17, 18, // --
- SECTION(Unknown, 9), 3, 'f', 'o', 'o', 5, 6, 7, 8, 9, // --
- SECTION(Unknown, 8), 5, 'o', 't', 'h', 'e', 'r', 7, 8, // --
+ SECTION(Unknown, ADD_COUNT('X'), 17, 18), // --
+ SECTION(Unknown, ADD_COUNT('f', 'o', 'o'), 5, 6, 7, 8, 9), // --
+ SECTION(Unknown, ADD_COUNT('o', 't', 'h', 'e', 'r'), 7, 8), // --
};
EXPECT_VERIFIES(data);
}
TEST_F(WasmModuleVerifyTest, Section_Name_No_UTF8) {
- static const byte data[] = {SECTION(Unknown, 4), 1, 0xFF, 17, 18};
+ static const byte data[] = {SECTION(Unknown, 1, 0xFF, 17, 18)};
EXPECT_FAILURE(data);
}
@@ -2237,11 +2165,11 @@ class WasmModuleCustomSectionTest : public TestWithIsolateAndZone {
TEST_F(WasmModuleCustomSectionTest, ThreeUnknownSections) {
static constexpr byte data[] = {
- U32_LE(kWasmMagic), // --
- U32_LE(kWasmVersion), // --
- SECTION(Unknown, 4), 1, 'X', 17, 18, // --
- SECTION(Unknown, 9), 3, 'f', 'o', 'o', 5, 6, 7, 8, 9, // --
- SECTION(Unknown, 8), 5, 'o', 't', 'h', 'e', 'r', 7, 8, // --
+ U32_LE(kWasmMagic), // --
+ U32_LE(kWasmVersion), // --
+ SECTION(Unknown, 1, 'X', 17, 18), // --
+ SECTION(Unknown, 3, 'f', 'o', 'o', 5, 6, 7, 8, 9), // --
+ SECTION(Unknown, 5, 'o', 't', 'h', 'e', 'r', 7, 8), // --
};
static const CustomSectionOffset expected[] = {
@@ -2256,24 +2184,12 @@ TEST_F(WasmModuleCustomSectionTest, ThreeUnknownSections) {
TEST_F(WasmModuleCustomSectionTest, TwoKnownTwoUnknownSections) {
static const byte data[] = {
- U32_LE(kWasmMagic), // --
- U32_LE(kWasmVersion), // --
- SIGNATURES_SECTION(2, SIG_ENTRY_v_v, SIG_ENTRY_v_v), // --
- SECTION(Unknown, 4),
- 1,
- 'X',
- 17,
- 18, // --
- ONE_EMPTY_FUNCTION,
- SECTION(Unknown, 8),
- 5,
- 'o',
- 't',
- 'h',
- 'e',
- 'r',
- 7,
- 8, // --
+ U32_LE(kWasmMagic), // --
+ U32_LE(kWasmVersion), // --
+ SIGNATURES_SECTION(2, SIG_ENTRY_v_v, SIG_ENTRY_v_v), // --
+ SECTION(Unknown, ADD_COUNT('X'), 17, 18), // --
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)), // --
+ SECTION(Unknown, ADD_COUNT('o', 't', 'h', 'e', 'r'), 7, 8), // --
};
static const CustomSectionOffset expected[] = {
@@ -2285,79 +2201,162 @@ TEST_F(WasmModuleCustomSectionTest, TwoKnownTwoUnknownSections) {
CheckSections(data, data + sizeof(data), expected, arraysize(expected));
}
-#define SRC_MAP \
- 16, 's', 'o', 'u', 'r', 'c', 'e', 'M', 'a', 'p', 'p', 'i', 'n', 'g', 'U', \
- 'R', 'L'
TEST_F(WasmModuleVerifyTest, SourceMappingURLSection) {
-#define SRC 's', 'r', 'c', '/', 'x', 'y', 'z', '.', 'c'
- static const byte data[] = {SECTION(Unknown, 27), SRC_MAP, 9, SRC};
+ static const byte data[] = {
+ SECTION_SRC_MAP('s', 'r', 'c', '/', 'x', 'y', 'z', '.', 'c')};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
- EXPECT_EQ(9u, result.val->source_map_url.size());
- const char src[] = {SRC};
- EXPECT_EQ(
- 0,
- strncmp(reinterpret_cast<const char*>(result.val->source_map_url.data()),
- src, 9));
-#undef SRC
+ EXPECT_EQ("src/xyz.c", result.value()->source_map_url);
}
TEST_F(WasmModuleVerifyTest, BadSourceMappingURLSection) {
-#define BAD_SRC 's', 'r', 'c', '/', 'x', 0xff, 'z', '.', 'c'
- static const byte data[] = {SECTION(Unknown, 27), SRC_MAP, 9, BAD_SRC};
+ static const byte data[] = {
+ SECTION_SRC_MAP('s', 'r', 'c', '/', 'x', 0xff, 'z', '.', 'c')};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
- EXPECT_EQ(0u, result.val->source_map_url.size());
-#undef BAD_SRC
+ EXPECT_EQ(0u, result.value()->source_map_url.size());
}
TEST_F(WasmModuleVerifyTest, MultipleSourceMappingURLSections) {
-#define SRC 'a', 'b', 'c'
- static const byte data[] = {SECTION(Unknown, 21),
- SRC_MAP,
- 3,
- SRC,
- SECTION(Unknown, 21),
- SRC_MAP,
- 3,
- 'p',
- 'q',
- 'r'};
+ static const byte data[] = {SECTION_SRC_MAP('a', 'b', 'c'),
+ SECTION_SRC_MAP('p', 'q', 'r')};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
- EXPECT_EQ(3u, result.val->source_map_url.size());
- const char src[] = {SRC};
- EXPECT_EQ(
- 0,
- strncmp(reinterpret_cast<const char*>(result.val->source_map_url.data()),
- src, 3));
-#undef SRC
+ EXPECT_EQ("abc", result.value()->source_map_url);
}
-#undef SRC_MAP
TEST_F(WasmModuleVerifyTest, MultipleNameSections) {
-#define NAME_SECTION 4, 'n', 'a', 'm', 'e'
- static const byte data[] = {SECTION(Unknown, 11),
- NAME_SECTION,
- 0,
- 4,
- 3,
- 'a',
- 'b',
- 'c',
- SECTION(Unknown, 12),
- NAME_SECTION,
- 0,
- 5,
- 4,
- 'p',
- 'q',
- 'r',
- 's'};
+ static const byte data[] = {
+ SECTION_NAMES(0, ADD_COUNT(ADD_COUNT('a', 'b', 'c'))),
+ SECTION_NAMES(0, ADD_COUNT(ADD_COUNT('p', 'q', 'r', 's')))};
ModuleResult result = DecodeModule(data, data + sizeof(data));
EXPECT_TRUE(result.ok());
- EXPECT_EQ(3u, result.val->name.length());
-#undef NAME_SECTION
+ EXPECT_EQ(3u, result.value()->name.length());
+}
+
+TEST_F(WasmModuleVerifyTest, PassiveDataSegment) {
+ static const byte data[] = {
+ // memory declaration ----------------------------------------------------
+ SECTION(Memory, ENTRY_COUNT(1), 0, 1),
+ // data segments --------------------------------------------------------
+ SECTION(Data, ENTRY_COUNT(1), PASSIVE, ADD_COUNT('h', 'i')),
+ };
+ EXPECT_FAILURE(data);
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(data);
+ EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
+}
+
+TEST_F(WasmModuleVerifyTest, PassiveElementSegment) {
+ static const byte data[] = {
+ // sig#0 -----------------------------------------------------------------
+ SIGNATURES_SECTION_VOID_VOID,
+ // funcs -----------------------------------------------------------------
+ ONE_EMPTY_FUNCTION(SIG_INDEX(0)),
+ // table declaration -----------------------------------------------------
+ SECTION(Table, ENTRY_COUNT(1), kLocalAnyFunc, 0, 1),
+ // element segments -----------------------------------------------------
+ SECTION(Element, ENTRY_COUNT(1), PASSIVE,
+ ADD_COUNT(FUNC_INDEX(0), FUNC_INDEX(0))),
+ // code ------------------------------------------------------------------
+ ONE_EMPTY_BODY};
+ EXPECT_FAILURE(data);
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(data);
+ EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5);
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSectionCorrectPlacement) {
+ static const byte data[] = {SECTION(Element, ENTRY_COUNT(0)),
+ SECTION(DataCount, ENTRY_COUNT(0)),
+ SECTION(Code, ENTRY_COUNT(0))};
+ EXPECT_FAILURE(data);
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSectionAfterCode) {
+ static const byte data[] = {SECTION(Code, ENTRY_COUNT(0)),
+ SECTION(DataCount, ENTRY_COUNT(0))};
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result,
+ "The DataCount section must appear before the Code section");
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSectionBeforeElement) {
+ static const byte data[] = {SECTION(DataCount, ENTRY_COUNT(0)),
+ SECTION(Element, ENTRY_COUNT(0))};
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "unexpected section: Element");
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSectionAfterStartBeforeElement) {
+ STATIC_ASSERT(kStartSectionCode + 1 == kElementSectionCode);
+ static const byte data[] = {
+ // We need the start section for this test, but the start section must
+ // reference a valid function, which requires the type and function
+ // sections too.
+ SIGNATURES_SECTION(1, SIG_ENTRY_v_v), // Type section.
+ FUNCTION_SIGNATURES_SECTION(1, 0), // Function section.
+
+ SECTION(Start, U32V_1(0)), // Start section.
+ SECTION(DataCount, ENTRY_COUNT(0)), // DataCount section.
+ SECTION(Element, ENTRY_COUNT(0)) // Element section.
+ };
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "unexpected section: Element");
+}
+
+TEST_F(WasmModuleVerifyTest, MultipleDataCountSections) {
+ static const byte data[] = {SECTION(DataCount, ENTRY_COUNT(0)),
+ SECTION(DataCount, ENTRY_COUNT(0))};
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "Multiple DataCount sections not allowed");
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSegmentCountMatch) {
+ static const byte data[] = {
+ SECTION(Memory, ENTRY_COUNT(1), 0, 1), // Memory section.
+ SECTION(DataCount, ENTRY_COUNT(1)), // DataCount section.
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0, // Data section.
+ WASM_INIT_EXPR_I32V_1(12), ADD_COUNT('h', 'i'))};
+
+ EXPECT_FAILURE(data);
+ WASM_FEATURE_SCOPE(bulk_memory);
+ EXPECT_VERIFIES(data);
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_greater) {
+ static const byte data[] = {
+ SECTION(Memory, ENTRY_COUNT(1), 0, 1), // Memory section.
+ SECTION(DataCount, ENTRY_COUNT(3)), // DataCount section.
+ SECTION(Data, ENTRY_COUNT(0))}; // Data section.
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "data segments count 0 mismatch (3 expected)");
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_less) {
+ static const byte data[] = {
+ SECTION(Memory, ENTRY_COUNT(1), 0, 1), // Memory section.
+ SECTION(DataCount, ENTRY_COUNT(0)), // DataCount section.
+ SECTION(Data, ENTRY_COUNT(1), LINEAR_MEMORY_INDEX_0, // Data section.
+ WASM_INIT_EXPR_I32V_1(12), ADD_COUNT('a', 'b', 'c'))};
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "data segments count 1 mismatch (0 expected)");
+}
+
+TEST_F(WasmModuleVerifyTest, DataCountSegmentCount_omitted) {
+ static const byte data[] = {SECTION(Memory, ENTRY_COUNT(1), 0, 1),
+ SECTION(DataCount, ENTRY_COUNT(1))};
+ WASM_FEATURE_SCOPE(bulk_memory);
+ ModuleResult result = DecodeModule(data, data + sizeof(data));
+ EXPECT_NOT_OK(result, "data segments count 0 mismatch (1 expected)");
}
#undef WASM_FEATURE_SCOPE
@@ -2374,13 +2373,13 @@ TEST_F(WasmModuleVerifyTest, MultipleNameSections) {
#undef WASM_INIT_EXPR_F64
#undef WASM_INIT_EXPR_ANYREF
#undef WASM_INIT_EXPR_GLOBAL
-#undef SIZEOF_EMPTY_FUNCTION
#undef EMPTY_BODY
-#undef SIZEOF_EMPTY_BODY
#undef NOP_BODY
-#undef SIZEOF_NOP_BODY
#undef SIG_ENTRY_i_i
#undef UNKNOWN_SECTION
+#undef COUNT_ARGS
+#undef CHECK_LEB1
+#undef ADD_COUNT
#undef SECTION
#undef SIGNATURES_SECTION
#undef FUNCTION_SIGNATURES_SECTION
@@ -2390,8 +2389,8 @@ TEST_F(WasmModuleVerifyTest, MultipleNameSections) {
#undef EMPTY_FUNCTION_SIGNATURES_SECTION
#undef EMPTY_FUNCTION_BODIES_SECTION
#undef SECTION_NAMES
-#undef SECTION_EXCEPTIONS
#undef EMPTY_NAMES_SECTION
+#undef SECTION_SRC_MAP
#undef FAIL_IF_NO_EXPERIMENTAL_EH
#undef X1
#undef X2
@@ -2407,11 +2406,13 @@ TEST_F(WasmModuleVerifyTest, MultipleNameSections) {
#undef FOUR_EMPTY_BODIES
#undef SIGNATURES_SECTION_VOID_VOID
#undef LINEAR_MEMORY_INDEX_0
+#undef EXCEPTION_ENTRY
#undef EXPECT_VERIFIES
#undef EXPECT_FAILURE_LEN
#undef EXPECT_FAILURE
#undef EXPECT_OFF_END_FAILURE
#undef EXPECT_OK
+#undef EXPECT_NOT_OK
} // namespace module_decoder_unittest
} // namespace wasm
diff --git a/deps/v8/test/unittests/wasm/streaming-decoder-unittest.cc b/deps/v8/test/unittests/wasm/streaming-decoder-unittest.cc
index 4159117c26..a5b89762ad 100644
--- a/deps/v8/test/unittests/wasm/streaming-decoder-unittest.cc
+++ b/deps/v8/test/unittests/wasm/streaming-decoder-unittest.cc
@@ -17,20 +17,32 @@ namespace v8 {
namespace internal {
namespace wasm {
+struct MockStreamingResult {
+ size_t num_sections = 0;
+ size_t num_functions = 0;
+ bool ok = true;
+ OwnedVector<uint8_t> received_bytes;
+
+ MockStreamingResult() = default;
+};
+
class MockStreamingProcessor : public StreamingProcessor {
public:
+ explicit MockStreamingProcessor(MockStreamingResult* result)
+ : result_(result) {}
+
bool ProcessModuleHeader(Vector<const uint8_t> bytes,
uint32_t offset) override {
// TODO(ahaas): Share code with the module-decoder.
Decoder decoder(bytes.begin(), bytes.end());
uint32_t magic_word = decoder.consume_u32("wasm magic");
if (decoder.failed() || magic_word != kWasmMagic) {
- ok_ = false;
+ result_->ok = false;
return false;
}
uint32_t magic_version = decoder.consume_u32("wasm version");
if (decoder.failed() || magic_version != kWasmVersion) {
- ok_ = false;
+ result_->ok = false;
return false;
}
return true;
@@ -38,19 +50,19 @@ class MockStreamingProcessor : public StreamingProcessor {
// Process all sections but the code section.
bool ProcessSection(SectionCode section_code, Vector<const uint8_t> bytes,
uint32_t offset) override {
- ++num_sections_;
+ ++result_->num_sections;
return true;
}
- bool ProcessCodeSectionHeader(size_t num_functions,
- uint32_t offset) override {
+ bool ProcessCodeSectionHeader(size_t num_functions, uint32_t offset,
+ std::shared_ptr<WireBytesStorage>) override {
return true;
}
// Process a function body.
bool ProcessFunctionBody(Vector<const uint8_t> bytes,
uint32_t offset) override {
- ++num_functions_;
+ ++result_->num_functions;
return true;
}
@@ -58,26 +70,21 @@ class MockStreamingProcessor : public StreamingProcessor {
// Finish the processing of the stream.
void OnFinishedStream(OwnedVector<uint8_t> bytes) override {
- received_bytes_ = std::move(bytes);
+ result_->received_bytes = std::move(bytes);
}
// Report an error detected in the StreamingDecoder.
- void OnError(DecodeResult result) override { ok_ = false; }
+ void OnError(const WasmError&) override { result_->ok = false; }
void OnAbort() override {}
- size_t num_sections() const { return num_sections_; }
- size_t num_functions() const { return num_functions_; }
- bool ok() const { return ok_; }
- Vector<const uint8_t> received_bytes() const {
- return received_bytes_.as_vector();
- }
+ bool Deserialize(Vector<const uint8_t> module_bytes,
+ Vector<const uint8_t> wire_bytes) override {
+ return false;
+ };
private:
- size_t num_sections_ = 0;
- size_t num_functions_ = 0;
- bool ok_ = true;
- OwnedVector<uint8_t> received_bytes_;
+ MockStreamingResult* const result_;
};
class WasmStreamingDecoderTest : public ::testing::Test {
@@ -85,50 +92,49 @@ class WasmStreamingDecoderTest : public ::testing::Test {
void ExpectVerifies(Vector<const uint8_t> data, size_t expected_sections,
size_t expected_functions) {
for (int split = 0; split <= data.length(); ++split) {
- // Use a unique_ptr so that the StreamingDecoder can own the processor.
- std::unique_ptr<MockStreamingProcessor> p(new MockStreamingProcessor());
- MockStreamingProcessor* processor = p.get();
- StreamingDecoder stream(std::move(p));
+ MockStreamingResult result;
+ StreamingDecoder stream(
+ base::make_unique<MockStreamingProcessor>(&result));
stream.OnBytesReceived(data.SubVector(0, split));
stream.OnBytesReceived(data.SubVector(split, data.length()));
stream.Finish();
- EXPECT_TRUE(processor->ok());
- EXPECT_EQ(expected_sections, processor->num_sections());
- EXPECT_EQ(expected_functions, processor->num_functions());
- EXPECT_EQ(data, processor->received_bytes());
+ EXPECT_TRUE(result.ok);
+ EXPECT_EQ(expected_sections, result.num_sections);
+ EXPECT_EQ(expected_functions, result.num_functions);
+ EXPECT_EQ(data, result.received_bytes.as_vector());
}
}
void ExpectFailure(Vector<const uint8_t> data) {
for (int split = 0; split <= data.length(); ++split) {
- std::unique_ptr<MockStreamingProcessor> p(new MockStreamingProcessor());
- MockStreamingProcessor* processor = p.get();
- StreamingDecoder stream(std::move(p));
+ MockStreamingResult result;
+ StreamingDecoder stream(
+ base::make_unique<MockStreamingProcessor>(&result));
stream.OnBytesReceived(data.SubVector(0, split));
stream.OnBytesReceived(data.SubVector(split, data.length()));
stream.Finish();
- EXPECT_FALSE(processor->ok());
+ EXPECT_FALSE(result.ok);
}
}
+
+ MockStreamingResult result;
};
TEST_F(WasmStreamingDecoderTest, EmptyStream) {
- std::unique_ptr<MockStreamingProcessor> p(new MockStreamingProcessor());
- MockStreamingProcessor* processor = p.get();
- StreamingDecoder stream(std::move(p));
+ MockStreamingResult result;
+ StreamingDecoder stream(base::make_unique<MockStreamingProcessor>(&result));
stream.Finish();
- EXPECT_FALSE(processor->ok());
+ EXPECT_FALSE(result.ok);
}
TEST_F(WasmStreamingDecoderTest, IncompleteModuleHeader) {
const uint8_t data[] = {U32_LE(kWasmMagic), U32_LE(kWasmVersion)};
{
- std::unique_ptr<MockStreamingProcessor> p(new MockStreamingProcessor());
- MockStreamingProcessor* processor = p.get();
- StreamingDecoder stream(std::move(p));
+ MockStreamingResult result;
+ StreamingDecoder stream(base::make_unique<MockStreamingProcessor>(&result));
stream.OnBytesReceived(Vector<const uint8_t>(data, 1));
stream.Finish();
- EXPECT_FALSE(processor->ok());
+ EXPECT_FALSE(result.ok);
}
for (int length = 1; length < static_cast<int>(arraysize(data)); ++length) {
ExpectFailure(Vector<const uint8_t>(data, length));
diff --git a/deps/v8/test/unittests/wasm/trap-handler-unittest.cc b/deps/v8/test/unittests/wasm/trap-handler-posix-unittest.cc
index 07e3ca888d..604d2adfb2 100644
--- a/deps/v8/test/unittests/wasm/trap-handler-unittest.cc
+++ b/deps/v8/test/unittests/wasm/trap-handler-posix-unittest.cc
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/trap-handler/trap-handler.h"
#include "include/v8.h"
+#include "src/trap-handler/trap-handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#if V8_OS_POSIX
@@ -58,7 +58,7 @@ TEST_F(SignalHandlerFallbackTest, DoTest) {
FAIL();
} else {
// Our signal handler ran.
- v8::internal::trap_handler::RestoreOriginalSignalHandler();
+ v8::internal::trap_handler::RemoveTrapHandler();
SUCCEED();
return;
}
diff --git a/deps/v8/test/unittests/wasm/trap-handler-win-unittest.cc b/deps/v8/test/unittests/wasm/trap-handler-win-unittest.cc
new file mode 100644
index 0000000000..58302bad74
--- /dev/null
+++ b/deps/v8/test/unittests/wasm/trap-handler-win-unittest.cc
@@ -0,0 +1,93 @@
+// 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.
+
+#include <windows.h>
+
+#include "include/v8.h"
+#include "src/allocation.h"
+#include "src/base/page-allocator.h"
+#include "src/trap-handler/trap-handler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace {
+
+#if V8_TRAP_HANDLER_SUPPORTED
+
+bool g_handler_got_executed = false;
+// The start address of the virtual memory we use to cause an exception.
+i::Address g_start_address;
+
+// When using V8::EnableWebAssemblyTrapHandler, we save the old one to fall back
+// on if V8 doesn't handle the exception. This allows tools like ASan to
+// register a handler early on during the process startup and still generate
+// stack traces on failures.
+class ExceptionHandlerFallbackTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ // Register this handler as the last handler.
+ registered_handler_ = AddVectoredExceptionHandler(/*first=*/0, TestHandler);
+ CHECK_NOT_NULL(registered_handler_);
+
+ v8::PageAllocator* page_allocator = i::GetPlatformPageAllocator();
+ // We only need a single page.
+ size_t size = page_allocator->AllocatePageSize();
+ void* hint = page_allocator->GetRandomMmapAddr();
+ i::VirtualMemory mem(page_allocator, size, hint, size);
+ g_start_address = mem.address();
+ // Set the permissions of the memory to no-access.
+ CHECK(mem.SetPermissions(g_start_address, size,
+ v8::PageAllocator::kNoAccess));
+ mem_ = std::move(mem);
+ }
+
+ void WriteToTestMemory(int value) {
+ *reinterpret_cast<volatile int*>(g_start_address) = value;
+ }
+
+ int ReadFromTestMemory() {
+ return *reinterpret_cast<volatile int*>(g_start_address);
+ }
+
+ void TearDown() override {
+ // be a good citizen and remove the exception handler.
+ ULONG result = RemoveVectoredExceptionHandler(registered_handler_);
+ CHECK(result);
+ }
+
+ private:
+ static LONG WINAPI TestHandler(EXCEPTION_POINTERS* exception) {
+ g_handler_got_executed = true;
+ v8::PageAllocator* page_allocator = i::GetPlatformPageAllocator();
+ // Make the allocated memory accessible so that from now on memory accesses
+ // do not cause an exception anymore.
+ CHECK(i::SetPermissions(page_allocator, g_start_address,
+ page_allocator->AllocatePageSize(),
+ v8::PageAllocator::kReadWrite));
+ // The memory access should work now, we can continue execution.
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ i::VirtualMemory mem_;
+ void* registered_handler_;
+};
+
+TEST_F(ExceptionHandlerFallbackTest, DoTest) {
+ constexpr bool use_default_handler = true;
+ CHECK(v8::V8::EnableWebAssemblyTrapHandler(use_default_handler));
+ // In the original test setup the test memory is protected against any kind of
+ // access. Therefore the access here causes an access violation exception,
+ // which should be caught by the exception handler we install above. In the
+ // exception handler we change the permission of the test memory to make it
+ // accessible, and then return from the exception handler to execute the
+ // memory access again. This time we expect the memory access to work.
+ constexpr int test_value = 42;
+ WriteToTestMemory(test_value);
+ CHECK_EQ(test_value, ReadFromTestMemory());
+ CHECK(g_handler_got_executed);
+ v8::internal::trap_handler::RemoveTrapHandler();
+}
+
+#endif
+
+} // namespace
diff --git a/deps/v8/test/unittests/wasm/trap-handler-x64-unittest.cc b/deps/v8/test/unittests/wasm/trap-handler-x64-unittest.cc
new file mode 100644
index 0000000000..8c42b1735c
--- /dev/null
+++ b/deps/v8/test/unittests/wasm/trap-handler-x64-unittest.cc
@@ -0,0 +1,478 @@
+// 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.
+
+#include "include/v8config.h"
+
+#if V8_OS_LINUX
+#include <signal.h>
+#include <ucontext.h>
+#elif V8_OS_MACOSX
+#include <signal.h>
+#include <sys/ucontext.h>
+#elif V8_OS_WIN
+#include <windows.h>
+#endif
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#if V8_OS_POSIX
+#include "include/v8-wasm-trap-handler-posix.h"
+#elif V8_OS_WIN
+#include "include/v8-wasm-trap-handler-win.h"
+#endif
+#include "src/allocation.h"
+#include "src/assembler-inl.h"
+#include "src/base/page-allocator.h"
+#include "src/macro-assembler-inl.h"
+#include "src/simulator.h"
+#include "src/trap-handler/trap-handler.h"
+#include "src/vector.h"
+#include "src/wasm/wasm-engine.h"
+#include "src/wasm/wasm-memory.h"
+
+#include "test/common/assembler-tester.h"
+#include "test/unittests/test-utils.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+namespace {
+constexpr Register scratch = r10;
+bool g_test_handler_executed = false;
+#if V8_OS_LINUX || V8_OS_MACOSX
+struct sigaction g_old_segv_action;
+struct sigaction g_old_fpe_action;
+struct sigaction g_old_bus_action; // We get SIGBUS on Mac sometimes.
+#elif V8_OS_WIN
+void* g_registered_handler = nullptr;
+#endif
+
+// The recovery address allows us to recover from an intentional crash.
+Address g_recovery_address;
+// Flag to indicate if the test handler should call the trap handler as a first
+// chance handler.
+bool g_use_as_first_chance_handler = false;
+} // namespace
+
+#define __ masm.
+
+enum TrapHandlerStyle : int {
+ // The test uses the default trap handler of V8.
+ kDefault = 0,
+ // The test installs the trap handler callback in its own test handler.
+ kCallback = 1
+};
+
+std::string PrintTrapHandlerTestParam(
+ ::testing::TestParamInfo<TrapHandlerStyle> info) {
+ switch (info.param) {
+ case kDefault:
+ return "DefaultTrapHandler";
+ case kCallback:
+ return "Callback";
+ }
+ UNREACHABLE();
+}
+
+class TrapHandlerTest : public TestWithIsolate,
+ public ::testing::WithParamInterface<TrapHandlerStyle> {
+ protected:
+ void SetUp() override {
+ void* base = nullptr;
+ size_t length = 0;
+ accessible_memory_start_ =
+ i_isolate()
+ ->wasm_engine()
+ ->memory_tracker()
+ ->TryAllocateBackingStoreForTesting(
+ i_isolate()->heap(), 1 * kWasmPageSize, &base, &length);
+ memory_buffer_ =
+ base::AddressRegion(reinterpret_cast<Address>(base), length);
+
+ // The allocated memory buffer ends with a guard page.
+ crash_address_ = memory_buffer_.end() - 32;
+ // Allocate a buffer for the generated code.
+ buffer_ = AllocateAssemblerBuffer(AssemblerBase::kMinimalBufferSize,
+ GetRandomMmapAddr());
+
+ InitRecoveryCode();
+
+#if V8_OS_LINUX || V8_OS_MACOSX
+ // Set up a signal handler to recover from the expected crash.
+ struct sigaction action;
+ action.sa_sigaction = SignalHandler;
+ sigemptyset(&action.sa_mask);
+ action.sa_flags = SA_SIGINFO;
+ // SIGSEGV happens for wasm oob memory accesses on Linux.
+ CHECK_EQ(0, sigaction(SIGSEGV, &action, &g_old_segv_action));
+ // SIGBUS happens for wasm oob memory accesses on macOS.
+ CHECK_EQ(0, sigaction(SIGBUS, &action, &g_old_bus_action));
+ // SIGFPE to simulate crashes which are not handled by the trap handler.
+ CHECK_EQ(0, sigaction(SIGFPE, &action, &g_old_fpe_action));
+#elif V8_OS_WIN
+ g_registered_handler =
+ AddVectoredExceptionHandler(/*first=*/0, TestHandler);
+#endif
+ }
+
+ void TearDown() override {
+ // We should always have left wasm code.
+ CHECK(!GetThreadInWasmFlag());
+ buffer_.reset();
+ recovery_buffer_.reset();
+
+ // Free the allocated backing store.
+ i_isolate()->wasm_engine()->memory_tracker()->FreeBackingStoreForTesting(
+ memory_buffer_, accessible_memory_start_);
+
+ // Clean up the trap handler
+ trap_handler::RemoveTrapHandler();
+ if (!g_test_handler_executed) {
+#if V8_OS_LINUX || V8_OS_MACOSX
+ // The test handler cleans up the signal handler setup in the test. If the
+ // test handler was not called, we have to do the cleanup ourselves.
+ CHECK_EQ(0, sigaction(SIGSEGV, &g_old_segv_action, nullptr));
+ CHECK_EQ(0, sigaction(SIGFPE, &g_old_fpe_action, nullptr));
+ CHECK_EQ(0, sigaction(SIGBUS, &g_old_bus_action, nullptr));
+#elif V8_OS_WIN
+ RemoveVectoredExceptionHandler(g_registered_handler);
+ g_registered_handler = nullptr;
+#endif
+ }
+ }
+
+ void InitRecoveryCode() {
+ // Create a code snippet where we can jump to to recover from a signal or
+ // exception. The code snippet only consists of a return statement.
+ recovery_buffer_ = AllocateAssemblerBuffer(
+ AssemblerBase::kMinimalBufferSize, GetRandomMmapAddr());
+
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ recovery_buffer_->CreateView());
+ int recovery_offset = __ pc_offset();
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+ recovery_buffer_->MakeExecutable();
+ g_recovery_address =
+ reinterpret_cast<Address>(desc.buffer + recovery_offset);
+ }
+
+#if V8_OS_LINUX || V8_OS_MACOSX
+ static void SignalHandler(int signal, siginfo_t* info, void* context) {
+ if (g_use_as_first_chance_handler) {
+ if (v8::TryHandleWebAssemblyTrapPosix(signal, info, context)) {
+ return;
+ }
+ }
+
+ // Reset the signal handler, to avoid that this signal handler is called
+ // repeatedly.
+ sigaction(SIGSEGV, &g_old_segv_action, nullptr);
+ sigaction(SIGFPE, &g_old_fpe_action, nullptr);
+ sigaction(SIGBUS, &g_old_bus_action, nullptr);
+
+ g_test_handler_executed = true;
+ // Set the $rip to the recovery code.
+ ucontext_t* uc = reinterpret_cast<ucontext_t*>(context);
+#if V8_OS_LINUX
+ uc->uc_mcontext.gregs[REG_RIP] = g_recovery_address;
+#else // V8_OS_MACOSX
+ uc->uc_mcontext->__ss.__rip = g_recovery_address;
+#endif
+ }
+#endif
+
+#if V8_OS_WIN
+ static LONG WINAPI TestHandler(EXCEPTION_POINTERS* exception) {
+ if (g_use_as_first_chance_handler) {
+ if (v8::TryHandleWebAssemblyTrapWindows(exception)) {
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+ }
+ RemoveVectoredExceptionHandler(g_registered_handler);
+ g_registered_handler = nullptr;
+ g_test_handler_executed = true;
+ exception->ContextRecord->Rip = g_recovery_address;
+ return EXCEPTION_CONTINUE_EXECUTION;
+ }
+#endif
+
+ public:
+ void SetupTrapHandler(TrapHandlerStyle style) {
+ bool use_default_handler = style == kDefault;
+ g_use_as_first_chance_handler = !use_default_handler;
+ CHECK(v8::V8::EnableWebAssemblyTrapHandler(use_default_handler));
+ }
+
+ void GenerateSetThreadInWasmFlagCode(MacroAssembler* masm) {
+ masm->Move(scratch,
+ i_isolate()->thread_local_top()->thread_in_wasm_flag_address_,
+ RelocInfo::NONE);
+ masm->movl(MemOperand(scratch, 0), Immediate(1));
+ }
+
+ void GenerateResetThreadInWasmFlagCode(MacroAssembler* masm) {
+ masm->Move(scratch,
+ i_isolate()->thread_local_top()->thread_in_wasm_flag_address_,
+ RelocInfo::NONE);
+ masm->movl(MemOperand(scratch, 0), Immediate(0));
+ }
+
+ bool GetThreadInWasmFlag() {
+ return *reinterpret_cast<int*>(
+ trap_handler::GetThreadInWasmThreadLocalAddress());
+ }
+
+ // Execute the code in buffer.
+ void ExecuteBuffer() {
+ buffer_->MakeExecutable();
+ GeneratedCode<void>::FromAddress(
+ i_isolate(), reinterpret_cast<Address>(buffer_->start()))
+ .Call();
+ CHECK(!g_test_handler_executed);
+ }
+
+ // Execute the code in buffer. We expect a crash which we recover from in the
+ // test handler.
+ void ExecuteExpectCrash(TestingAssemblerBuffer* buffer,
+ bool check_wasm_flag = true) {
+ CHECK(!g_test_handler_executed);
+ buffer->MakeExecutable();
+ GeneratedCode<void>::FromAddress(i_isolate(),
+ reinterpret_cast<Address>(buffer->start()))
+ .Call();
+ CHECK(g_test_handler_executed);
+ g_test_handler_executed = false;
+ if (check_wasm_flag) CHECK(!GetThreadInWasmFlag());
+ }
+
+ bool test_handler_executed() { return g_test_handler_executed; }
+
+ // Allocated memory which corresponds to wasm memory with guard regions.
+ base::AddressRegion memory_buffer_;
+ // Address within the guard region of the wasm memory. Accessing this memory
+ // address causes a signal or exception.
+ Address crash_address_;
+ // The start of the accessible region in the allocated memory. This pointer is
+ // needed to de-register the memory from the wasm memory tracker again.
+ void* accessible_memory_start_;
+
+ // Buffer for generated code.
+ std::unique_ptr<TestingAssemblerBuffer> buffer_;
+ // Buffer for the code for the landing pad of the test handler.
+ std::unique_ptr<TestingAssemblerBuffer> recovery_buffer_;
+};
+
+TEST_P(TrapHandlerTest, TestTrapHandlerRecovery) {
+ // Test that the wasm trap handler can recover a memory access violation in
+ // wasm code (we fake the wasm code and the access violation).
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer_->CreateView());
+ __ Push(scratch);
+ GenerateSetThreadInWasmFlagCode(&masm);
+ __ Move(scratch, crash_address_, RelocInfo::NONE);
+ int crash_offset = __ pc_offset();
+ __ testl(MemOperand(scratch, 0), Immediate(1));
+ int recovery_offset = __ pc_offset();
+ GenerateResetThreadInWasmFlagCode(&masm);
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+
+ SetupTrapHandler(GetParam());
+ trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
+ recovery_offset};
+ trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
+ desc.instr_size, 1, &protected_instruction);
+
+ ExecuteBuffer();
+}
+
+TEST_P(TrapHandlerTest, TestReleaseHandlerData) {
+ // Test that after we release handler data in the trap handler, it cannot
+ // recover from the specific memory access violation anymore.
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer_->CreateView());
+ __ Push(scratch);
+ GenerateSetThreadInWasmFlagCode(&masm);
+ __ Move(scratch, crash_address_, RelocInfo::NONE);
+ int crash_offset = __ pc_offset();
+ __ testl(MemOperand(scratch, 0), Immediate(1));
+ int recovery_offset = __ pc_offset();
+ GenerateResetThreadInWasmFlagCode(&masm);
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+
+ trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
+ recovery_offset};
+ int handler_id = trap_handler::RegisterHandlerData(
+ reinterpret_cast<Address>(desc.buffer), desc.instr_size, 1,
+ &protected_instruction);
+
+ SetupTrapHandler(GetParam());
+
+ ExecuteBuffer();
+
+ // Deregister from the trap handler. The trap handler should not do the
+ // recovery now.
+ trap_handler::ReleaseHandlerData(handler_id);
+
+ ExecuteExpectCrash(buffer_.get());
+}
+
+TEST_P(TrapHandlerTest, TestNoThreadInWasmFlag) {
+ // That that if the thread_in_wasm flag is not set, the trap handler does not
+ // get active.
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer_->CreateView());
+ __ Push(scratch);
+ __ Move(scratch, crash_address_, RelocInfo::NONE);
+ int crash_offset = __ pc_offset();
+ __ testl(MemOperand(scratch, 0), Immediate(1));
+ int recovery_offset = __ pc_offset();
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+
+ trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
+ recovery_offset};
+ trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
+ desc.instr_size, 1, &protected_instruction);
+
+ SetupTrapHandler(GetParam());
+
+ ExecuteExpectCrash(buffer_.get());
+}
+
+TEST_P(TrapHandlerTest, TestCrashInWasmNoProtectedInstruction) {
+ // Test that if the crash in wasm happened at an instruction which is not
+ // protected, then the trap handler does not handle it.
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer_->CreateView());
+ __ Push(scratch);
+ GenerateSetThreadInWasmFlagCode(&masm);
+ int no_crash_offset = __ pc_offset();
+ __ Move(scratch, crash_address_, RelocInfo::NONE);
+ __ testl(MemOperand(scratch, 0), Immediate(1));
+ // Offset where the crash is not happening.
+ int recovery_offset = __ pc_offset();
+ GenerateResetThreadInWasmFlagCode(&masm);
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+
+ trap_handler::ProtectedInstructionData protected_instruction{no_crash_offset,
+ recovery_offset};
+ trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
+ desc.instr_size, 1, &protected_instruction);
+
+ SetupTrapHandler(GetParam());
+
+ ExecuteExpectCrash(buffer_.get());
+}
+
+TEST_P(TrapHandlerTest, TestCrashInWasmWrongCrashType) {
+ // Test that if the crash reason is not a memory access violation, then the
+ // wasm trap handler does not handle it.
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer_->CreateView());
+ __ Push(scratch);
+ GenerateSetThreadInWasmFlagCode(&masm);
+ __ xorq(scratch, scratch);
+ int crash_offset = __ pc_offset();
+ __ divq(scratch);
+ // Offset where the crash is not happening.
+ int recovery_offset = __ pc_offset();
+ GenerateResetThreadInWasmFlagCode(&masm);
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+
+ trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
+ recovery_offset};
+ trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
+ desc.instr_size, 1, &protected_instruction);
+
+ SetupTrapHandler(GetParam());
+
+#if V8_OS_POSIX
+ // The V8 default trap handler does not register for SIGFPE, therefore the
+ // thread-in-wasm flag is never reset in this test. We therefore do not check
+ // the value of this flag.
+ bool check_wasm_flag = GetParam() != kDefault;
+#else
+ bool check_wasm_flag = true;
+#endif
+ ExecuteExpectCrash(buffer_.get(), check_wasm_flag);
+ if (!check_wasm_flag) {
+ // Reset the thread-in-wasm flag because it was probably not reset in the
+ // trap handler.
+ *trap_handler::GetThreadInWasmThreadLocalAddress() = 0;
+ }
+}
+
+class CodeRunner : public v8::base::Thread {
+ public:
+ CodeRunner(TrapHandlerTest* test, TestingAssemblerBuffer* buffer)
+ : Thread(Options("CodeRunner")), test_(test), buffer_(buffer) {}
+
+ void Run() override { test_->ExecuteExpectCrash(buffer_); }
+
+ private:
+ TrapHandlerTest* test_;
+ TestingAssemblerBuffer* buffer_;
+};
+
+TEST_P(TrapHandlerTest, TestCrashInOtherThread) {
+ // Test setup:
+ // The current thread enters wasm land (sets the thread_in_wasm flag)
+ // A second thread crashes at a protected instruction without having the flag
+ // set.
+ MacroAssembler masm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo,
+ buffer_->CreateView());
+ __ Push(scratch);
+ __ Move(scratch, crash_address_, RelocInfo::NONE);
+ int crash_offset = __ pc_offset();
+ __ testl(MemOperand(scratch, 0), Immediate(1));
+ int recovery_offset = __ pc_offset();
+ __ Pop(scratch);
+ __ Ret();
+ CodeDesc desc;
+ masm.GetCode(nullptr, &desc);
+
+ trap_handler::ProtectedInstructionData protected_instruction{crash_offset,
+ recovery_offset};
+ trap_handler::RegisterHandlerData(reinterpret_cast<Address>(desc.buffer),
+ desc.instr_size, 1, &protected_instruction);
+
+ SetupTrapHandler(GetParam());
+
+ CodeRunner runner(this, buffer_.get());
+ CHECK(!GetThreadInWasmFlag());
+ // Set the thread-in-wasm flag manually in this thread.
+ *trap_handler::GetThreadInWasmThreadLocalAddress() = 1;
+ runner.Start();
+ runner.Join();
+ CHECK(GetThreadInWasmFlag());
+ // Reset the thread-in-wasm flag.
+ *trap_handler::GetThreadInWasmThreadLocalAddress() = 0;
+}
+
+INSTANTIATE_TEST_CASE_P(/* no prefix */, TrapHandlerTest,
+ ::testing::Values(kDefault, kCallback),
+ PrintTrapHandlerTestParam);
+
+#undef __
+} // namespace wasm
+} // namespace internal
+} // namespace v8
diff --git a/deps/v8/test/unittests/wasm/wasm-code-manager-unittest.cc b/deps/v8/test/unittests/wasm/wasm-code-manager-unittest.cc
index 5d695c8275..e90c97f3a1 100644
--- a/deps/v8/test/unittests/wasm/wasm-code-manager-unittest.cc
+++ b/deps/v8/test/unittests/wasm/wasm-code-manager-unittest.cc
@@ -8,6 +8,7 @@
#include "src/wasm/function-compiler.h"
#include "src/wasm/jump-table-assembler.h"
#include "src/wasm/wasm-code-manager.h"
+#include "src/wasm/wasm-engine.h"
#include "src/wasm/wasm-memory.h"
namespace v8 {
@@ -160,15 +161,12 @@ class WasmCodeManagerTest : public TestWithContext,
using NativeModulePtr = std::unique_ptr<NativeModule>;
- NativeModulePtr AllocModule(WasmCodeManager* manager, size_t size,
- ModuleStyle style) {
+ NativeModulePtr AllocModule(size_t size, ModuleStyle style) {
std::shared_ptr<WasmModule> module(new WasmModule);
module->num_declared_functions = kNumFunctions;
bool can_request_more = style == Growable;
- ModuleEnv env(module.get(), UseTrapHandler::kNoTrapHandler,
- RuntimeExceptionSupport::kNoRuntimeExceptionSupport);
- return manager->NewNativeModule(i_isolate(), kAllWasmFeatures, size,
- can_request_more, std::move(module), env);
+ return manager()->NewNativeModule(i_isolate(), kAllWasmFeatures, size,
+ can_request_more, std::move(module));
}
WasmCode* AddCode(NativeModule* native_module, uint32_t index, size_t size) {
@@ -178,15 +176,18 @@ class WasmCodeManagerTest : public TestWithContext,
desc.buffer = exec_buff.get();
desc.instr_size = static_cast<int>(size);
return native_module->AddCode(index, desc, 0, 0, 0, {}, OwnedVector<byte>(),
- WasmCode::kOther);
+ WasmCode::kFunction, WasmCode::kOther);
}
size_t page() const { return AllocatePageSize(); }
- WasmMemoryTracker* memory_tracker() { return &memory_tracker_; }
+ WasmCodeManager* manager() {
+ return i_isolate()->wasm_engine()->code_manager();
+ }
- private:
- WasmMemoryTracker memory_tracker_;
+ void SetMaxCommittedMemory(size_t limit) {
+ manager()->SetMaxCommittedMemoryForTesting(limit);
+ }
};
INSTANTIATE_TEST_CASE_P(Parameterized, WasmCodeManagerTest,
@@ -194,32 +195,32 @@ INSTANTIATE_TEST_CASE_P(Parameterized, WasmCodeManagerTest,
PrintWasmCodeManageTestParam);
TEST_P(WasmCodeManagerTest, EmptyCase) {
- WasmCodeManager manager(memory_tracker(), 0 * page());
- CHECK_EQ(0, manager.remaining_uncommitted_code_space());
+ SetMaxCommittedMemory(0 * page());
+ CHECK_EQ(0, manager()->remaining_uncommitted_code_space());
- ASSERT_DEATH_IF_SUPPORTED(AllocModule(&manager, 1 * page(), GetParam()),
+ ASSERT_DEATH_IF_SUPPORTED(AllocModule(1 * page(), GetParam()),
"OOM in NativeModule::AllocateForCode commit");
}
TEST_P(WasmCodeManagerTest, AllocateAndGoOverLimit) {
- WasmCodeManager manager(memory_tracker(), 1 * page());
- CHECK_EQ(1 * page(), manager.remaining_uncommitted_code_space());
- NativeModulePtr native_module = AllocModule(&manager, 1 * page(), GetParam());
+ SetMaxCommittedMemory(1 * page());
+ CHECK_EQ(1 * page(), manager()->remaining_uncommitted_code_space());
+ NativeModulePtr native_module = AllocModule(1 * page(), GetParam());
CHECK(native_module);
- CHECK_EQ(0, manager.remaining_uncommitted_code_space());
+ CHECK_EQ(0, manager()->remaining_uncommitted_code_space());
uint32_t index = 0;
WasmCode* code = AddCode(native_module.get(), index++, 1 * kCodeAlignment);
CHECK_NOT_NULL(code);
- CHECK_EQ(0, manager.remaining_uncommitted_code_space());
+ CHECK_EQ(0, manager()->remaining_uncommitted_code_space());
code = AddCode(native_module.get(), index++, 3 * kCodeAlignment);
CHECK_NOT_NULL(code);
- CHECK_EQ(0, manager.remaining_uncommitted_code_space());
+ CHECK_EQ(0, manager()->remaining_uncommitted_code_space());
code = AddCode(native_module.get(), index++,
page() - 4 * kCodeAlignment - kJumpTableSize);
CHECK_NOT_NULL(code);
- CHECK_EQ(0, manager.remaining_uncommitted_code_space());
+ CHECK_EQ(0, manager()->remaining_uncommitted_code_space());
// This fails in "reservation" if we cannot extend the code space, or in
// "commit" it we can (since we hit the allocation limit in the
@@ -230,9 +231,9 @@ TEST_P(WasmCodeManagerTest, AllocateAndGoOverLimit) {
}
TEST_P(WasmCodeManagerTest, TotalLimitIrrespectiveOfModuleCount) {
- WasmCodeManager manager(memory_tracker(), 3 * page());
- NativeModulePtr nm1 = AllocModule(&manager, 2 * page(), GetParam());
- NativeModulePtr nm2 = AllocModule(&manager, 2 * page(), GetParam());
+ SetMaxCommittedMemory(3 * page());
+ NativeModulePtr nm1 = AllocModule(2 * page(), GetParam());
+ NativeModulePtr nm2 = AllocModule(2 * page(), GetParam());
CHECK(nm1);
CHECK(nm2);
WasmCode* code = AddCode(nm1.get(), 0, 2 * page() - kJumpTableSize);
@@ -241,23 +242,9 @@ TEST_P(WasmCodeManagerTest, TotalLimitIrrespectiveOfModuleCount) {
"OOM in NativeModule::AllocateForCode commit");
}
-TEST_P(WasmCodeManagerTest, DifferentHeapsApplyLimitsIndependently) {
- WasmCodeManager manager1(memory_tracker(), 1 * page());
- WasmCodeManager manager2(memory_tracker(), 2 * page());
- NativeModulePtr nm1 = AllocModule(&manager1, 1 * page(), GetParam());
- NativeModulePtr nm2 = AllocModule(&manager2, 1 * page(), GetParam());
- CHECK(nm1);
- CHECK(nm2);
- WasmCode* code = AddCode(nm1.get(), 0, 1 * page() - kJumpTableSize);
- CHECK_NOT_NULL(code);
- CHECK_EQ(0, manager1.remaining_uncommitted_code_space());
- code = AddCode(nm2.get(), 0, 1 * page() - kJumpTableSize);
- CHECK_NOT_NULL(code);
-}
-
TEST_P(WasmCodeManagerTest, GrowingVsFixedModule) {
- WasmCodeManager manager(memory_tracker(), 3 * page());
- NativeModulePtr nm = AllocModule(&manager, 1 * page(), GetParam());
+ SetMaxCommittedMemory(3 * page());
+ NativeModulePtr nm = AllocModule(1 * page(), GetParam());
size_t module_size = GetParam() == Fixed ? kMaxWasmCodeMemory : 1 * page();
size_t remaining_space_in_module = module_size - kJumpTableSize;
if (GetParam() == Fixed) {
@@ -270,29 +257,29 @@ TEST_P(WasmCodeManagerTest, GrowingVsFixedModule) {
// The module grows by one page. One page remains uncommitted.
CHECK_NOT_NULL(
AddCode(nm.get(), 0, remaining_space_in_module + kCodeAlignment));
- CHECK_EQ(manager.remaining_uncommitted_code_space(), 1 * page());
+ CHECK_EQ(manager()->remaining_uncommitted_code_space(), 1 * page());
}
}
TEST_P(WasmCodeManagerTest, CommitIncrements) {
- WasmCodeManager manager(memory_tracker(), 10 * page());
- NativeModulePtr nm = AllocModule(&manager, 3 * page(), GetParam());
+ SetMaxCommittedMemory(10 * page());
+ NativeModulePtr nm = AllocModule(3 * page(), GetParam());
WasmCode* code = AddCode(nm.get(), 0, kCodeAlignment);
CHECK_NOT_NULL(code);
- CHECK_EQ(manager.remaining_uncommitted_code_space(), 9 * page());
+ CHECK_EQ(manager()->remaining_uncommitted_code_space(), 9 * page());
code = AddCode(nm.get(), 1, 2 * page());
CHECK_NOT_NULL(code);
- CHECK_EQ(manager.remaining_uncommitted_code_space(), 7 * page());
+ CHECK_EQ(manager()->remaining_uncommitted_code_space(), 7 * page());
code = AddCode(nm.get(), 2, page() - kCodeAlignment - kJumpTableSize);
CHECK_NOT_NULL(code);
- CHECK_EQ(manager.remaining_uncommitted_code_space(), 7 * page());
+ CHECK_EQ(manager()->remaining_uncommitted_code_space(), 7 * page());
}
TEST_P(WasmCodeManagerTest, Lookup) {
- WasmCodeManager manager(memory_tracker(), 2 * page());
+ SetMaxCommittedMemory(2 * page());
- NativeModulePtr nm1 = AllocModule(&manager, 1 * page(), GetParam());
- NativeModulePtr nm2 = AllocModule(&manager, 1 * page(), GetParam());
+ NativeModulePtr nm1 = AllocModule(1 * page(), GetParam());
+ NativeModulePtr nm2 = AllocModule(1 * page(), GetParam());
WasmCode* code1_0 = AddCode(nm1.get(), 0, kCodeAlignment);
CHECK_EQ(nm1.get(), code1_0->native_module());
WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
@@ -307,63 +294,41 @@ TEST_P(WasmCodeManagerTest, Lookup) {
// we know the manager object is allocated here, so we shouldn't
// find any WasmCode* associated with that ptr.
- WasmCode* not_found = manager.LookupCode(reinterpret_cast<Address>(&manager));
+ WasmCode* not_found =
+ manager()->LookupCode(reinterpret_cast<Address>(manager()));
CHECK_NULL(not_found);
- WasmCode* found = manager.LookupCode(code1_0->instruction_start());
+ WasmCode* found = manager()->LookupCode(code1_0->instruction_start());
CHECK_EQ(found, code1_0);
- found = manager.LookupCode(code2_1->instruction_start() +
- (code2_1->instructions().size() / 2));
+ found = manager()->LookupCode(code2_1->instruction_start() +
+ (code2_1->instructions().size() / 2));
CHECK_EQ(found, code2_1);
- found = manager.LookupCode(code2_1->instruction_start() +
- code2_1->instructions().size() - 1);
+ found = manager()->LookupCode(code2_1->instruction_start() +
+ code2_1->instructions().size() - 1);
CHECK_EQ(found, code2_1);
- found = manager.LookupCode(code2_1->instruction_start() +
- code2_1->instructions().size());
+ found = manager()->LookupCode(code2_1->instruction_start() +
+ code2_1->instructions().size());
CHECK_NULL(found);
Address mid_code1_1 =
code1_1->instruction_start() + (code1_1->instructions().size() / 2);
- CHECK_EQ(code1_1, manager.LookupCode(mid_code1_1));
+ CHECK_EQ(code1_1, manager()->LookupCode(mid_code1_1));
nm1.reset();
- CHECK_NULL(manager.LookupCode(mid_code1_1));
-}
-
-TEST_P(WasmCodeManagerTest, MultiManagerLookup) {
- WasmCodeManager manager1(memory_tracker(), 2 * page());
- WasmCodeManager manager2(memory_tracker(), 2 * page());
-
- NativeModulePtr nm1 = AllocModule(&manager1, 1 * page(), GetParam());
- NativeModulePtr nm2 = AllocModule(&manager2, 1 * page(), GetParam());
-
- WasmCode* code1_0 = AddCode(nm1.get(), 0, kCodeAlignment);
- CHECK_EQ(nm1.get(), code1_0->native_module());
- WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
- WasmCode* code2_0 = AddCode(nm2.get(), 0, kCodeAlignment);
- WasmCode* code2_1 = AddCode(nm2.get(), 1, kCodeAlignment);
- CHECK_EQ(nm2.get(), code2_1->native_module());
-
- CHECK_EQ(0, code1_0->index());
- CHECK_EQ(1, code1_1->index());
- CHECK_EQ(0, code2_0->index());
- CHECK_EQ(1, code2_1->index());
-
- CHECK_EQ(code1_0, manager1.LookupCode(code1_0->instruction_start()));
- CHECK_NULL(manager2.LookupCode(code1_0->instruction_start()));
+ CHECK_NULL(manager()->LookupCode(mid_code1_1));
}
TEST_P(WasmCodeManagerTest, LookupWorksAfterRewrite) {
- WasmCodeManager manager(memory_tracker(), 2 * page());
+ SetMaxCommittedMemory(2 * page());
- NativeModulePtr nm1 = AllocModule(&manager, 1 * page(), GetParam());
+ NativeModulePtr nm1 = AllocModule(1 * page(), GetParam());
WasmCode* code0 = AddCode(nm1.get(), 0, kCodeAlignment);
WasmCode* code1 = AddCode(nm1.get(), 1, kCodeAlignment);
CHECK_EQ(0, code0->index());
CHECK_EQ(1, code1->index());
- CHECK_EQ(code1, manager.LookupCode(code1->instruction_start()));
+ CHECK_EQ(code1, manager()->LookupCode(code1->instruction_start()));
WasmCode* code1_1 = AddCode(nm1.get(), 1, kCodeAlignment);
CHECK_EQ(1, code1_1->index());
- CHECK_EQ(code1, manager.LookupCode(code1->instruction_start()));
- CHECK_EQ(code1_1, manager.LookupCode(code1_1->instruction_start()));
+ CHECK_EQ(code1, manager()->LookupCode(code1->instruction_start()));
+ CHECK_EQ(code1_1, manager()->LookupCode(code1_1->instruction_start()));
}
} // namespace wasm_heap_unittest
diff --git a/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc b/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc
new file mode 100644
index 0000000000..3cca4bc55c
--- /dev/null
+++ b/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc
@@ -0,0 +1,71 @@
+// 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.
+
+#include "test/unittests/test-utils.h"
+
+#include "src/compiler/linkage.h"
+#include "src/compiler/wasm-compiler.h"
+#include "src/machine-type.h"
+#include "src/signature.h"
+#include "src/wasm/value-type.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class WasmCallDescriptorTest : public TestWithZone {};
+
+TEST_F(WasmCallDescriptorTest, TestAnyRefIsGrouped) {
+ constexpr size_t kMaxCount = 30;
+ ValueType params[kMaxCount];
+
+ for (size_t i = 0; i < kMaxCount; i += 2) {
+ params[i] = ValueType::kWasmAnyRef;
+ CHECK_LT(i + 1, kMaxCount);
+ params[i + 1] = ValueType::kWasmI32;
+ }
+
+ for (size_t count = 1; count <= kMaxCount; ++count) {
+ FunctionSig sig(/*return_count=*/0, count, params);
+ compiler::CallDescriptor* desc =
+ compiler::GetWasmCallDescriptor(zone(), &sig);
+
+ // The WasmInstance is the implicit first parameter.
+ CHECK_EQ(count + 1, desc->ParameterCount());
+
+ bool has_untagged_stack_param = false;
+ bool has_tagged_register_param = false;
+ int max_tagged_stack_location = std::numeric_limits<int>::min();
+ int min_untagged_stack_location = std::numeric_limits<int>::max();
+ for (size_t i = 1; i < desc->ParameterCount(); ++i) {
+ // InputLocation i + 1, because target is the first input.
+ compiler::LinkageLocation location = desc->GetInputLocation(i + 1);
+ if (desc->GetParameterType(i).IsTagged()) {
+ if (location.IsRegister()) {
+ has_tagged_register_param = true;
+ } else {
+ CHECK(location.IsCallerFrameSlot());
+ max_tagged_stack_location =
+ std::max(max_tagged_stack_location, location.AsCallerFrameSlot());
+ }
+ } else { // !isTagged()
+ if (location.IsCallerFrameSlot()) {
+ has_untagged_stack_param = true;
+ min_untagged_stack_location = std::min(min_untagged_stack_location,
+ location.AsCallerFrameSlot());
+ } else {
+ CHECK(location.IsRegister());
+ }
+ }
+ }
+ // There should never be a tagged parameter in a register and an untagged
+ // parameter on the stack at the same time.
+ CHECK_EQ(false, has_tagged_register_param && has_untagged_stack_param);
+ CHECK_LT(max_tagged_stack_location, min_untagged_stack_location);
+ }
+}
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8