diff options
author | Michaël Zasso <targos@protonmail.com> | 2020-05-05 09:19:02 +0200 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2020-05-12 16:12:13 +0200 |
commit | 1d6adf7432defeb39b751a19c68335e8afb0d8ee (patch) | |
tree | 7ab67931110b8d9db770d774c7a6d0d14c976c15 /deps/v8/test/unittests | |
parent | aee36a04475a20c13663d1037aa6f175ff368bc7 (diff) | |
download | node-new-1d6adf7432defeb39b751a19c68335e8afb0d8ee.tar.gz |
deps: update V8 to 8.3.110.9
PR-URL: https://github.com/nodejs/node/pull/32831
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/test/unittests')
54 files changed, 2494 insertions, 778 deletions
diff --git a/deps/v8/test/unittests/BUILD.gn b/deps/v8/test/unittests/BUILD.gn index ab407c2fe6..f3b060e5da 100644 --- a/deps/v8/test/unittests/BUILD.gn +++ b/deps/v8/test/unittests/BUILD.gn @@ -7,7 +7,7 @@ import("../../gni/v8.gni") if (is_fuchsia) { import("//build/config/fuchsia/rules.gni") - fuchsia_package("v8_unittests_pkg") { + cr_fuchsia_package("v8_unittests_pkg") { testonly = true binary = ":unittests" package_name_override = "v8_unittests" @@ -20,6 +20,52 @@ if (is_fuchsia) { } } +# Stand-alone target for C++ GC unittests. This is used to ensure that it +# builds without V8 as well. They are also included in the regular unittests +# target for simplicity. +v8_executable("cppgc_unittests") { + testonly = true + + configs = [ + "../..:external_config", + "../..:internal_config_base", + ] + + sources = [ "heap/cppgc/run-all-unittests.cc" ] + + deps = [ + ":cppgc_unittests_sources", + "//testing/gmock", + "//testing/gtest", + ] +} + +v8_source_set("cppgc_unittests_sources") { + testonly = true + + sources = [ + "heap/cppgc/allocation_unittest.cc", + "heap/cppgc/finalizer-trait_unittest.cc", + "heap/cppgc/garbage-collected_unittest.cc", + "heap/cppgc/gc-info_unittest.cc", + "heap/cppgc/heap-object-header_unittest.cc", + "heap/cppgc/stack_unittest.cc", + "heap/cppgc/tests.cc", + "heap/cppgc/tests.h", + ] + + configs = [ + "../..:external_config", + "../..:internal_config_base", + ] + + deps = [ + "../..:cppgc_for_testing", + "//testing/gmock", + "//testing/gtest", + ] +} + v8_executable("unittests") { testonly = true @@ -29,6 +75,7 @@ v8_executable("unittests") { #}], deps = [ + ":cppgc_unittests_sources", ":unittests_sources", "../..:v8_for_testing", "../..:v8_libbase", @@ -170,12 +217,13 @@ v8_source_set("unittests_sources") { "heap/heap-controller-unittest.cc", "heap/heap-unittest.cc", "heap/item-parallel-job-unittest.cc", + "heap/local-heap-unittest.cc", "heap/marking-unittest.cc", "heap/marking-worklist-unittest.cc", "heap/memory-reducer-unittest.cc", "heap/object-stats-unittest.cc", "heap/off-thread-factory-unittest.cc", - "heap/scavenge-job-unittest.cc", + "heap/safepoint-unittest.cc", "heap/slot-set-unittest.cc", "heap/spaces-unittest.cc", "heap/unmapper-unittest.cc", diff --git a/deps/v8/test/unittests/api/access-check-unittest.cc b/deps/v8/test/unittests/api/access-check-unittest.cc index 3b63666f4b..cdcce68efd 100644 --- a/deps/v8/test/unittests/api/access-check-unittest.cc +++ b/deps/v8/test/unittests/api/access-check-unittest.cc @@ -19,8 +19,7 @@ bool AccessCheck(Local<Context> accessing_context, MaybeLocal<Value> CompileRun(Isolate* isolate, const char* source) { Local<String> source_string = - String::NewFromUtf8(isolate, source, NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8(isolate, source).ToLocalChecked(); Local<Context> context = isolate->GetCurrentContext(); Local<Script> script = Script::Compile(context, source_string).ToLocalChecked(); @@ -28,9 +27,7 @@ MaybeLocal<Value> CompileRun(Isolate* isolate, const char* source) { } v8::Local<v8::String> v8_str(const char* x) { - return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x, - v8::NewStringType::kNormal) - .ToLocalChecked(); + return v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), x).ToLocalChecked(); } } // namespace diff --git a/deps/v8/test/unittests/api/isolate-unittest.cc b/deps/v8/test/unittests/api/isolate-unittest.cc index cda251f775..429d70617a 100644 --- a/deps/v8/test/unittests/api/isolate-unittest.cc +++ b/deps/v8/test/unittests/api/isolate-unittest.cc @@ -75,8 +75,7 @@ using IncumbentContextTest = TestWithIsolate; // scenarios. TEST_F(IncumbentContextTest, Basic) { auto Str = [&](const char* s) { - return String::NewFromUtf8(isolate(), s, NewStringType::kNormal) - .ToLocalChecked(); + return String::NewFromUtf8(isolate(), s).ToLocalChecked(); }; auto Run = [&](Local<Context> context, const char* script) { Context::Scope scope(context); diff --git a/deps/v8/test/unittests/api/remote-object-unittest.cc b/deps/v8/test/unittests/api/remote-object-unittest.cc index 39434a8f9a..5fcc78bbe1 100644 --- a/deps/v8/test/unittests/api/remote-object-unittest.cc +++ b/deps/v8/test/unittests/api/remote-object-unittest.cc @@ -105,8 +105,7 @@ TEST_F(RemoteObjectTest, ClassOf) { AccessCheck, NamedPropertyHandlerConfiguration(NamedGetter), IndexedPropertyHandlerConfiguration()); constructor_template->SetClassName( - String::NewFromUtf8(isolate(), "test_class", NewStringType::kNormal) - .ToLocalChecked()); + String::NewFromUtf8Literal(isolate(), "test_class")); Local<Object> remote_object = constructor_template->NewRemoteInstance().ToLocalChecked(); diff --git a/deps/v8/test/unittests/api/v8-object-unittest.cc b/deps/v8/test/unittests/api/v8-object-unittest.cc index eb72d45263..a3c0c2574c 100644 --- a/deps/v8/test/unittests/api/v8-object-unittest.cc +++ b/deps/v8/test/unittests/api/v8-object-unittest.cc @@ -20,9 +20,7 @@ TEST_F(ObjectTest, SetAccessorWhenUnconfigurablePropAlreadyDefined) { TryCatch try_catch(isolate()); Local<Object> global = context()->Global(); - Local<String> property_name = - String::NewFromUtf8(isolate(), "foo", NewStringType::kNormal) - .ToLocalChecked(); + Local<String> property_name = String::NewFromUtf8Literal(isolate(), "foo"); PropertyDescriptor prop_desc; prop_desc.set_configurable(false); @@ -51,8 +49,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate()); Local<Signature> signature = Signature::New(isolate(), function_template); Local<String> property_key = - String::NewFromUtf8(isolate(), "property", NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8Literal(isolate(), "property"); Local<FunctionTemplate> get_or_set = FunctionTemplate::New( isolate(), [](const FunctionCallbackInfo<Value>& info) { @@ -72,8 +69,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) { Local<Function> interface_for_prototype = function_template->GetFunction(prototype_context).ToLocalChecked(); Local<String> prototype_key = - String::NewFromUtf8(isolate(), "prototype", NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8Literal(isolate(), "prototype"); Local<Object> prototype = interface_for_prototype->Get(caller_context, prototype_key) .ToLocalChecked() @@ -91,9 +87,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) { EXPECT_EQ(2, call_count); // Test with a compiled version. - Local<String> object_key = - String::NewFromUtf8(isolate(), "object", NewStringType::kNormal) - .ToLocalChecked(); + Local<String> object_key = String::NewFromUtf8Literal(isolate(), "object"); caller_context->Global()->Set(caller_context, object_key, object).ToChecked(); const char script[] = "function f() { object.property; object.property = 0; } " @@ -103,10 +97,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPrototype) { "f();"; Context::Scope scope(caller_context); internal::FLAG_allow_natives_syntax = true; - Script::Compile( - caller_context, - String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal) - .ToLocalChecked()) + Script::Compile(caller_context, String::NewFromUtf8Literal(isolate(), script)) .ToLocalChecked() ->Run(caller_context) .ToLocalChecked(); @@ -123,8 +114,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPlatformObject) { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate()); Local<Signature> signature = Signature::New(isolate(), function_template); Local<String> property_key = - String::NewFromUtf8(isolate(), "property", NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8Literal(isolate(), "property"); Local<FunctionTemplate> get_or_set = FunctionTemplate::New( isolate(), [](const FunctionCallbackInfo<Value>& info) { @@ -149,9 +139,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPlatformObject) { EXPECT_EQ(2, call_count); // Test with a compiled version. - Local<String> object_key = - String::NewFromUtf8(isolate(), "object", NewStringType::kNormal) - .ToLocalChecked(); + Local<String> object_key = String::NewFromUtf8Literal(isolate(), "object"); caller_context->Global()->Set(caller_context, object_key, object).ToChecked(); const char script[] = "function f() { object.property; object.property = 0; } " @@ -161,10 +149,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnPlatformObject) { "f();"; Context::Scope scope(caller_context); internal::FLAG_allow_natives_syntax = true; - Script::Compile( - caller_context, - String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal) - .ToLocalChecked()) + Script::Compile(caller_context, String::NewFromUtf8Literal(isolate(), script)) .ToLocalChecked() ->Run(caller_context) .ToLocalChecked(); @@ -180,8 +165,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnInterface) { Local<FunctionTemplate> function_template = FunctionTemplate::New(isolate()); Local<String> property_key = - String::NewFromUtf8(isolate(), "property", NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8Literal(isolate(), "property"); Local<FunctionTemplate> get_or_set = FunctionTemplate::New( isolate(), [](const FunctionCallbackInfo<Value>& info) { @@ -204,8 +188,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnInterface) { // Test with a compiled version. Local<String> interface_key = - String::NewFromUtf8(isolate(), "Interface", NewStringType::kNormal) - .ToLocalChecked(); + String::NewFromUtf8Literal(isolate(), "Interface"); caller_context->Global() ->Set(caller_context, interface_key, interface) .ToChecked(); @@ -217,10 +200,7 @@ TEST_F(LapContextTest, CurrentContextInLazyAccessorOnInterface) { "f();"; Context::Scope scope(caller_context); internal::FLAG_allow_natives_syntax = true; - Script::Compile( - caller_context, - String::NewFromUtf8(isolate(), script, v8::NewStringType::kNormal) - .ToLocalChecked()) + Script::Compile(caller_context, String::NewFromUtf8Literal(isolate(), script)) .ToLocalChecked() ->Run(caller_context) .ToLocalChecked(); 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 76dd04d77c..2c0c01701c 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-arm-unittest.cc @@ -32,14 +32,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); @@ -49,8 +50,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter is 17. @@ -60,7 +62,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { __ Ret(); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); 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 02a6a8e763..0a9ac748c0 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-arm64-unittest.cc @@ -32,14 +32,17 @@ class TurboAssemblerTest : public TestWithIsolate {}; TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); + __ CodeEntry(); + __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); @@ -49,10 +52,13 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); + __ CodeEntry(); + // Fail if the first parameter is 17. __ Mov(w1, Immediate(17)); __ Cmp(w0, w1); // 1st parameter is in {w0}. @@ -60,7 +66,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { __ Ret(); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); @@ -113,6 +119,7 @@ TEST_P(TurboAssemblerTestMoveObjectAndSlot, MoveObjectAndSlot) { TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ CodeEntry(); __ Push(x0, padreg); __ Mov(test_case.object, x1); 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 548cb34fc7..f0cb96d47d 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-ia32-unittest.cc @@ -5,6 +5,7 @@ #include "src/codegen/macro-assembler.h" #include "src/execution/simulator.h" #include "test/common/assembler-tester.h" +#include "test/unittests/test-utils.h" #include "testing/gtest-support.h" namespace v8 { @@ -16,26 +17,30 @@ namespace internal { // a buffer and executing them. These tests do not initialize the // V8 library, create a context, or use any V8 objects. -TEST(TurboAssemblerTest, TestHardAbort) { +class TurboAssemblerTest : public TestWithIsolate {}; + +TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); - auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer->start()); + auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason"); } -TEST(TurboAssemblerTest, TestCheck) { +TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter is 17. @@ -45,9 +50,9 @@ TEST(TurboAssemblerTest, TestCheck) { __ ret(0); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); - auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer->start()); + 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-mips-unittest.cc b/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc index 5ea6b2f3f8..b8a645e6a7 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-mips-unittest.cc @@ -22,14 +22,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); @@ -39,8 +40,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter (in {a0}) is 17. @@ -48,7 +50,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { __ Ret(); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); 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 fe9e815981..c954ffcc65 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-mips64-unittest.cc @@ -22,14 +22,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); @@ -39,8 +40,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter (in {a0}) is 17. @@ -48,7 +50,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { __ Ret(); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); 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 51744bd92d..08c205c2ea 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-ppc-unittest.cc @@ -22,15 +22,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); - + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); @@ -40,9 +40,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); - + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter is 17. @@ -52,7 +52,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { __ Ret(); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); 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 959ec03157..b0c398f571 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-s390-unittest.cc @@ -22,14 +22,15 @@ class TurboAssemblerTest : public TestWithIsolate {}; TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); @@ -39,8 +40,9 @@ TEST_F(TurboAssemblerTest, TestHardAbort) { TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter is 17. @@ -50,7 +52,7 @@ TEST_F(TurboAssemblerTest, TestCheck) { __ Ret(); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); // We need an isolate here to execute in the simulator. auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); 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 621f598f75..43dd6b79d6 100644 --- a/deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc +++ b/deps/v8/test/unittests/assembler/turbo-assembler-x64-unittest.cc @@ -5,6 +5,7 @@ #include "src/codegen/macro-assembler.h" #include "src/execution/simulator.h" #include "test/common/assembler-tester.h" +#include "test/unittests/test-utils.h" #include "testing/gtest-support.h" namespace v8 { @@ -16,26 +17,30 @@ namespace internal { // a buffer and executing them. These tests do not initialize the // V8 library, create a context, or use any V8 objects. -TEST(TurboAssemblerTest, TestHardAbort) { +class TurboAssemblerTest : public TestWithIsolate {}; + +TEST_F(TurboAssemblerTest, TestHardAbort) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); __ Abort(AbortReason::kNoReason); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); - auto f = GeneratedCode<void>::FromBuffer(nullptr, buffer->start()); + auto f = GeneratedCode<void>::FromBuffer(isolate(), buffer->start()); ASSERT_DEATH_IF_SUPPORTED({ f.Call(); }, "abort: no reason"); } -TEST(TurboAssemblerTest, TestCheck) { +TEST_F(TurboAssemblerTest, TestCheck) { auto buffer = AllocateAssemblerBuffer(); - TurboAssembler tasm(nullptr, AssemblerOptions{}, CodeObjectRequired::kNo, + TurboAssembler tasm(isolate(), AssemblerOptions{}, CodeObjectRequired::kNo, buffer->CreateView()); + __ set_root_array_available(false); __ set_abort_hard(true); // Fail if the first parameter is 17. @@ -45,9 +50,9 @@ TEST(TurboAssemblerTest, TestCheck) { __ ret(0); CodeDesc desc; - tasm.GetCode(nullptr, &desc); + tasm.GetCode(isolate(), &desc); buffer->MakeExecutable(); - auto f = GeneratedCode<void, int>::FromBuffer(nullptr, buffer->start()); + auto f = GeneratedCode<void, int>::FromBuffer(isolate(), buffer->start()); f.Call(0); f.Call(18); diff --git a/deps/v8/test/unittests/base/platform/platform-unittest.cc b/deps/v8/test/unittests/base/platform/platform-unittest.cc index 27154b3c24..b447778b49 100644 --- a/deps/v8/test/unittests/base/platform/platform-unittest.cc +++ b/deps/v8/test/unittests/base/platform/platform-unittest.cc @@ -83,5 +83,18 @@ TEST_F(ThreadLocalStorageTest, DoTest) { Join(); } +TEST(StackTest, GetStackStart) { EXPECT_NE(nullptr, Stack::GetStackStart()); } + +TEST(StackTest, GetCurrentStackPosition) { + EXPECT_NE(nullptr, Stack::GetCurrentStackPosition()); +} + +TEST(StackTest, StackVariableInBounds) { + void* dummy; + ASSERT_GT(Stack::GetStackStart(), Stack::GetCurrentStackPosition()); + EXPECT_GT(Stack::GetStackStart(), Stack::GetStackSlot(&dummy)); + EXPECT_LT(Stack::GetCurrentStackPosition(), Stack::GetStackSlot(&dummy)); +} + } // namespace base } // namespace v8 diff --git a/deps/v8/test/unittests/base/region-allocator-unittest.cc b/deps/v8/test/unittests/base/region-allocator-unittest.cc index caec4894c9..df154ff4f3 100644 --- a/deps/v8/test/unittests/base/region-allocator-unittest.cc +++ b/deps/v8/test/unittests/base/region-allocator-unittest.cc @@ -14,9 +14,7 @@ using Address = RegionAllocator::Address; using v8::internal::KB; using v8::internal::MB; -class RegionAllocatorTest : public ::testing::TestWithParam<int> {}; - -TEST_P(RegionAllocatorTest, SimpleAllocateRegionAt) { +TEST(RegionAllocatorTest, SimpleAllocateRegionAt) { const size_t kPageSize = 4 * KB; const size_t kPageCount = 16; const size_t kSize = kPageSize * kPageCount; @@ -50,7 +48,7 @@ TEST_P(RegionAllocatorTest, SimpleAllocateRegionAt) { CHECK_EQ(ra.AllocateRegion(kSize), kBegin); } -TEST_P(RegionAllocatorTest, SimpleAllocateRegion) { +TEST(RegionAllocatorTest, SimpleAllocateRegion) { const size_t kPageSize = 4 * KB; const size_t kPageCount = 16; const size_t kSize = kPageSize * kPageCount; @@ -79,7 +77,7 @@ TEST_P(RegionAllocatorTest, SimpleAllocateRegion) { CHECK_EQ(ra.free_size(), 0); } -TEST_P(RegionAllocatorTest, AllocateRegionRandom) { +TEST(RegionAllocatorTest, AllocateRegionRandom) { const size_t kPageSize = 8 * KB; const size_t kPageCountLog = 16; const size_t kPageCount = (size_t{1} << kPageCountLog); @@ -87,7 +85,7 @@ TEST_P(RegionAllocatorTest, AllocateRegionRandom) { const Address kBegin = static_cast<Address>(153 * MB); const Address kEnd = kBegin + kSize; - base::RandomNumberGenerator rng(GetParam()); + base::RandomNumberGenerator rng(::testing::FLAGS_gtest_random_seed); RegionAllocator ra(kBegin, kSize, kPageSize); std::set<Address> allocated_pages; @@ -123,7 +121,7 @@ TEST_P(RegionAllocatorTest, AllocateRegionRandom) { CHECK_EQ(ra.AllocateRegion(kPageSize), RegionAllocator::kAllocationFailure); } -TEST_P(RegionAllocatorTest, AllocateBigRegions) { +TEST(RegionAllocatorTest, AllocateBigRegions) { const size_t kPageSize = 4 * KB; const size_t kPageCountLog = 10; const size_t kPageCount = (size_t{1} << kPageCountLog) - 1; @@ -153,7 +151,7 @@ TEST_P(RegionAllocatorTest, AllocateBigRegions) { CHECK_EQ(ra.free_size(), 0); } -TEST_P(RegionAllocatorTest, MergeLeftToRightCoalecsingRegions) { +TEST(RegionAllocatorTest, MergeLeftToRightCoalecsingRegions) { const size_t kPageSize = 4 * KB; const size_t kPageCountLog = 10; const size_t kPageCount = (size_t{1} << kPageCountLog); @@ -187,8 +185,8 @@ TEST_P(RegionAllocatorTest, MergeLeftToRightCoalecsingRegions) { CHECK_EQ(ra.free_size(), 0); } -TEST_P(RegionAllocatorTest, MergeRightToLeftCoalecsingRegions) { - base::RandomNumberGenerator rng(GetParam()); +TEST(RegionAllocatorTest, MergeRightToLeftCoalecsingRegions) { + base::RandomNumberGenerator rng(::testing::FLAGS_gtest_random_seed); const size_t kPageSize = 4 * KB; const size_t kPageCountLog = 10; const size_t kPageCount = (size_t{1} << kPageCountLog); @@ -236,7 +234,7 @@ TEST_P(RegionAllocatorTest, MergeRightToLeftCoalecsingRegions) { CHECK_EQ(ra.AllocateRegion(kSize), kBegin); } -TEST_P(RegionAllocatorTest, Fragmentation) { +TEST(RegionAllocatorTest, Fragmentation) { const size_t kPageSize = 64 * KB; const size_t kPageCount = 9; const size_t kSize = kPageSize * kPageCount; @@ -283,7 +281,7 @@ TEST_P(RegionAllocatorTest, Fragmentation) { CHECK_EQ(ra.AllocateRegion(kSize), kBegin); } -TEST_P(RegionAllocatorTest, FindRegion) { +TEST(RegionAllocatorTest, FindRegion) { const size_t kPageSize = 4 * KB; const size_t kPageCount = 16; const size_t kSize = kPageSize * kPageCount; @@ -322,7 +320,7 @@ TEST_P(RegionAllocatorTest, FindRegion) { } } -TEST_P(RegionAllocatorTest, TrimRegion) { +TEST(RegionAllocatorTest, TrimRegion) { const size_t kPageSize = 4 * KB; const size_t kPageCount = 64; const size_t kSize = kPageSize * kPageCount; @@ -352,7 +350,5 @@ TEST_P(RegionAllocatorTest, TrimRegion) { CHECK_EQ(ra.AllocateRegion(kSize), kBegin); } -INSTANTIATE_TEST_SUITE_P(RegionAllocatorTest, RegionAllocatorTest, - testing::Values(123)); } // namespace base } // namespace v8 diff --git a/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc b/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc index 95191819a8..9607aa94a9 100644 --- a/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc +++ b/deps/v8/test/unittests/compiler/backend/instruction-selector-unittest.cc @@ -338,7 +338,8 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) { Node* context = m.Parameter(2); ZoneVector<MachineType> int32_type(1, MachineType::Int32(), zone()); - ZoneVector<MachineType> empty_types(zone()); + ZoneVector<MachineType> tagged_type(1, MachineType::AnyTagged(), zone()); + ZoneVector<MachineType> empty_type(zone()); auto call_descriptor = Linkage::GetJSCallDescriptor( zone(), false, 1, @@ -349,9 +350,10 @@ TARGET_TEST_F(InstructionSelectorTest, CallJSFunctionWithDeopt) { m.common()->TypedStateValues(&int32_type, SparseInputMask::Dense()), m.Int32Constant(1)); Node* locals = m.AddNode( - m.common()->TypedStateValues(&empty_types, SparseInputMask::Dense())); + m.common()->TypedStateValues(&empty_type, SparseInputMask::Dense())); Node* stack = m.AddNode( - m.common()->TypedStateValues(&empty_types, SparseInputMask::Dense())); + m.common()->TypedStateValues(&tagged_type, SparseInputMask::Dense()), + m.UndefinedConstant()); Node* context_sentinel = m.Int32Constant(0); Node* state_node = m.AddNode( m.common()->FrameState(bailout_id, OutputFrameStateCombine::PokeAt(0), @@ -487,7 +489,6 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) { Node* context2 = m.Int32Constant(46); ZoneVector<MachineType> int32_type(1, MachineType::Int32(), zone()); - ZoneVector<MachineType> int32x2_type(2, MachineType::Int32(), zone()); ZoneVector<MachineType> float64_type(1, MachineType::Float64(), zone()); Callable callable = Builtins::CallableFor(isolate(), Builtins::kToObject); @@ -518,8 +519,8 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) { m.common()->TypedStateValues(&float64_type, SparseInputMask::Dense()), m.Float64Constant(0.25)); Node* stack2 = m.AddNode( - m.common()->TypedStateValues(&int32x2_type, SparseInputMask::Dense()), - m.Int32Constant(44), m.Int32Constant(45)); + m.common()->TypedStateValues(&int32_type, SparseInputMask::Dense()), + m.Int32Constant(44)); Node* state_node = m.AddNode(m.common()->FrameState(bailout_id_before, OutputFrameStateCombine::PokeAt(0), @@ -550,7 +551,7 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) { 1 + // Code object. 1 + // Poison index. 1 + // Frame state deopt id - 6 + // One input for each value in frame state + context. + 5 + // One input for each value in frame state + context. 5 + // One input for each value in the parent frame state + context. 1 + // Function. 1; // Context. @@ -576,17 +577,16 @@ TARGET_TEST_F(InstructionSelectorTest, CallStubWithDeoptRecursiveFrameState) { // Values from the nested frame. EXPECT_EQ(1u, desc_before->parameters_count()); EXPECT_EQ(1u, desc_before->locals_count()); - EXPECT_EQ(2u, desc_before->stack_count()); + EXPECT_EQ(1u, desc_before->stack_count()); EXPECT_EQ(43, s.ToInt32(call_instr->InputAt(9))); EXPECT_EQ(46, s.ToInt32(call_instr->InputAt(10))); EXPECT_EQ(0.25, s.ToFloat64(call_instr->InputAt(11))); EXPECT_EQ(44, s.ToInt32(call_instr->InputAt(12))); - EXPECT_EQ(45, s.ToInt32(call_instr->InputAt(13))); // Function. - EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(14))); + EXPECT_EQ(s.ToVreg(function_node), s.ToVreg(call_instr->InputAt(13))); // Context. - EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(15))); + EXPECT_EQ(s.ToVreg(context2), s.ToVreg(call_instr->InputAt(14))); // Continuation. EXPECT_EQ(kArchRet, s[index++]->arch_opcode()); diff --git a/deps/v8/test/unittests/compiler/bytecode-analysis-unittest.cc b/deps/v8/test/unittests/compiler/bytecode-analysis-unittest.cc index d3c81344f2..c6fe8948bc 100644 --- a/deps/v8/test/unittests/compiler/bytecode-analysis-unittest.cc +++ b/deps/v8/test/unittests/compiler/bytecode-analysis-unittest.cc @@ -256,7 +256,7 @@ TEST_F(BytecodeAnalysisTest, SimpleLoop) { expected_liveness.emplace_back("L..L", "L.L."); loop_builder.BindContinueTarget(); - loop_builder.JumpToHeader(0); + loop_builder.JumpToHeader(0, nullptr); expected_liveness.emplace_back("L.L.", "L.L."); } @@ -361,7 +361,7 @@ TEST_F(BytecodeAnalysisTest, DiamondInLoop) { builder.Bind(&end_label); loop_builder.BindContinueTarget(); - loop_builder.JumpToHeader(0); + loop_builder.JumpToHeader(0, nullptr); expected_liveness.emplace_back("L...", "L..."); } @@ -433,12 +433,12 @@ TEST_F(BytecodeAnalysisTest, KillingLoopInsideLoop) { expected_liveness.emplace_back("LL.L", "LL.."); inner_loop_builder.BindContinueTarget(); - inner_loop_builder.JumpToHeader(1); + inner_loop_builder.JumpToHeader(1, &loop_builder); expected_liveness.emplace_back(".L..", ".L.."); } loop_builder.BindContinueTarget(); - loop_builder.JumpToHeader(0); + loop_builder.JumpToHeader(0, nullptr); expected_liveness.emplace_back("LL..", "LL.."); } 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 dee5c56e82..4f3d05173d 100644 --- a/deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc +++ b/deps/v8/test/unittests/compiler/constant-folding-reducer-unittest.cc @@ -80,6 +80,12 @@ class ConstantFoldingReducerTest : public TypedGraphTest { return reducer.Reduce(node); } + Node* UseValue(Node* node) { + Node* start = graph()->NewNode(common()->Start(1)); + Node* zero = graph()->NewNode(common()->NumberConstant(0)); + return graph()->NewNode(common()->Return(), zero, node, start, start); + } + SimplifiedOperatorBuilder* simplified() { return &simplified_; } JSHeapBroker* broker() { return &broker_; } @@ -91,20 +97,26 @@ class ConstantFoldingReducerTest : public TypedGraphTest { TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) { { - Reduction r = Reduce(Parameter( - Type::NewConstant(broker(), factory()->minus_zero_value(), zone()))); + Node* node = Parameter( + Type::Constant(broker(), factory()->minus_zero_value(), zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0)); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(-0.0)); } { - Reduction r = Reduce(Parameter(Type::MinusZero())); + Node* node = Parameter(Type::MinusZero()); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(-0.0)); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(-0.0)); } { - Reduction r = Reduce(Parameter(Type::Union( + Node* node = Parameter(Type::Union( Type::MinusZero(), - Type::NewConstant(broker(), factory()->NewNumber(0), zone()), zone()))); + Type::Constant(broker(), factory()->NewNumber(0), zone()), zone())); + UseValue(node); + Reduction r = Reduce(node); EXPECT_FALSE(r.Changed()); } } @@ -112,14 +124,18 @@ TEST_F(ConstantFoldingReducerTest, ParameterWithMinusZero) { TEST_F(ConstantFoldingReducerTest, ParameterWithNull) { Handle<HeapObject> null = factory()->null_value(); { - Reduction r = Reduce(Parameter(Type::NewConstant(broker(), null, zone()))); + Node* node = Parameter(Type::Constant(broker(), null, zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsHeapConstant(null)); + EXPECT_THAT(use_value->InputAt(1), IsHeapConstant(null)); } { - Reduction r = Reduce(Parameter(Type::Null())); + Node* node = Parameter(Type::Null()); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsHeapConstant(null)); + EXPECT_THAT(use_value->InputAt(1), IsHeapConstant(null)); } } @@ -129,51 +145,62 @@ 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(broker(), constant, zone()))); + Node* node = Parameter(Type::Constant(broker(), constant, zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN())); } { - Reduction r = Reduce( - Parameter(Type::NewConstant(broker(), factory()->nan_value(), zone()))); + Node* node = + Parameter(Type::Constant(broker(), factory()->nan_value(), zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN())); } { - Reduction r = Reduce(Parameter(Type::NaN())); + Node* node = Parameter(Type::NaN()); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(IsNaN())); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(IsNaN())); } } TEST_F(ConstantFoldingReducerTest, ParameterWithPlainNumber) { TRACED_FOREACH(double, value, kFloat64Values) { Handle<Object> constant = factory()->NewNumber(value); - Reduction r = - Reduce(Parameter(Type::NewConstant(broker(), constant, zone()))); + Node* node = Parameter(Type::Constant(broker(), constant, zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(value)); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(value)); } TRACED_FOREACH(double, value, kIntegerValues) { - Reduction r = Reduce(Parameter(Type::Range(value, value, zone()))); + Node* node = Parameter(Type::Range(value, value, zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsNumberConstant(value)); + EXPECT_THAT(use_value->InputAt(1), IsNumberConstant(value)); } } TEST_F(ConstantFoldingReducerTest, ParameterWithUndefined) { Handle<HeapObject> undefined = factory()->undefined_value(); { - Reduction r = Reduce(Parameter(Type::Undefined())); + Node* node = Parameter(Type::Undefined()); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsHeapConstant(undefined)); + EXPECT_THAT(use_value->InputAt(1), IsUndefinedConstant()); } { - Reduction r = - Reduce(Parameter(Type::NewConstant(broker(), undefined, zone()))); + Node* node = Parameter(Type::Constant(broker(), undefined, zone())); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsHeapConstant(undefined)); + EXPECT_THAT(use_value->InputAt(1), IsUndefinedConstant()); } } @@ -193,8 +220,8 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) { Type::Union( Type::Undetectable(), Type::Union( - Type::NewConstant( - broker(), factory()->false_value(), zone()), + Type::Constant(broker(), factory()->false_value(), + zone()), Type::Range(0.0, 0.0, zone()), zone()), zone()), zone()), @@ -202,28 +229,34 @@ TEST_F(ConstantFoldingReducerTest, ToBooleanWithFalsish) { zone()), zone()), 0); - Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input)); + Node* node = graph()->NewNode(simplified()->ToBoolean(), input); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsFalseConstant()); + EXPECT_THAT(use_value->InputAt(1), IsFalseConstant()); } TEST_F(ConstantFoldingReducerTest, ToBooleanWithTruish) { Node* input = Parameter( Type::Union( - Type::NewConstant(broker(), factory()->true_value(), zone()), + Type::Constant(broker(), factory()->true_value(), zone()), Type::Union(Type::DetectableReceiver(), Type::Symbol(), zone()), zone()), 0); - Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input)); + Node* node = graph()->NewNode(simplified()->ToBoolean(), input); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsTrueConstant()); + EXPECT_THAT(use_value->InputAt(1), IsTrueConstant()); } TEST_F(ConstantFoldingReducerTest, ToBooleanWithNonZeroPlainNumber) { Node* input = Parameter(Type::Range(1, V8_INFINITY, zone()), 0); - Reduction r = Reduce(graph()->NewNode(simplified()->ToBoolean(), input)); + Node* node = graph()->NewNode(simplified()->ToBoolean(), input); + Node* use_value = UseValue(node); + Reduction r = Reduce(node); ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsTrueConstant()); + EXPECT_THAT(use_value->InputAt(1), IsTrueConstant()); } } // namespace constant_folding_reducer_unittest diff --git a/deps/v8/test/unittests/compiler/graph-unittest.cc b/deps/v8/test/unittests/compiler/graph-unittest.cc index 0008eadaf9..0d825dc60b 100644 --- a/deps/v8/test/unittests/compiler/graph-unittest.cc +++ b/deps/v8/test/unittests/compiler/graph-unittest.cc @@ -66,7 +66,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(broker(), value, zone()); + Type type = Type::Constant(broker(), value, zone()); NodeProperties::SetType(node, type); return node; } diff --git a/deps/v8/test/unittests/compiler/int64-lowering-unittest.cc b/deps/v8/test/unittests/compiler/int64-lowering-unittest.cc index 7e927ea078..30e24b0aa4 100644 --- a/deps/v8/test/unittests/compiler/int64-lowering-unittest.cc +++ b/deps/v8/test/unittests/compiler/int64-lowering-unittest.cc @@ -1016,10 +1016,8 @@ TEST_F(Int64LoweringTest, WasmBigIntSpecialCaseBigIntToI64) { StubCallMode::kCallCodeObject); // stub call mode auto lowering_special_case = std::make_unique<Int64LoweringSpecialCase>(); - lowering_special_case->bigint_to_i64_call_descriptor = - bigint_to_i64_call_descriptor; - lowering_special_case->bigint_to_i32_pair_call_descriptor = - bigint_to_i32_pair_call_descriptor; + lowering_special_case->replacements.insert( + {bigint_to_i64_call_descriptor, bigint_to_i32_pair_call_descriptor}); Node* call_node = graph()->NewNode(common()->Call(bigint_to_i64_call_descriptor), target, @@ -1064,10 +1062,8 @@ TEST_F(Int64LoweringTest, WasmBigIntSpecialCaseI64ToBigInt) { StubCallMode::kCallCodeObject); // stub call mode auto lowering_special_case = std::make_unique<Int64LoweringSpecialCase>(); - lowering_special_case->i64_to_bigint_call_descriptor = - i64_to_bigint_call_descriptor; - lowering_special_case->i32_pair_to_bigint_call_descriptor = - i32_pair_to_bigint_call_descriptor; + lowering_special_case->replacements.insert( + {i64_to_bigint_call_descriptor, i32_pair_to_bigint_call_descriptor}); Node* call = graph()->NewNode(common()->Call(i64_to_bigint_call_descriptor), target, i64, start(), start()); 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 eed74f6181..fe5a02e3f2 100644 --- a/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc +++ b/deps/v8/test/unittests/compiler/js-typed-lowering-unittest.cc @@ -174,8 +174,7 @@ TEST_F(JSTypedLoweringTest, JSStrictEqualWithTheHole) { Reduction r = Reduce( graph()->NewNode(javascript()->StrictEqual(CompareOperationHint::kAny), lhs, the_hole, context, effect, control)); - ASSERT_TRUE(r.Changed()); - EXPECT_THAT(r.replacement(), IsFalseConstant()); + ASSERT_FALSE(r.Changed()); } } 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 bcf0a7101c..c3659032cf 100644 --- a/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc +++ b/deps/v8/test/unittests/compiler/machine-operator-reducer-unittest.cc @@ -1058,6 +1058,76 @@ TEST_F(MachineOperatorReducerTest, Word32ShlWithWord32Shr) { } } +// ----------------------------------------------------------------------------- +// Word32Equal + +TEST_F(MachineOperatorReducerTest, + Word32EqualWithShiftedMaskedValueAndConstant) { + // ((x >> K1) & K2) == K3 => (x & (K2 << K1)) == (K3 << K1) + Node* const p0 = Parameter(0); + TRACED_FOREACH(uint32_t, mask, kUint32Values) { + TRACED_FOREACH(uint32_t, rhs, kUint32Values) { + TRACED_FORRANGE(uint32_t, shift_bits, 1, 31) { + Node* node = graph()->NewNode( + machine()->Word32Equal(), + graph()->NewNode(machine()->Word32And(), + graph()->NewNode(machine()->Word32Shr(), p0, + Uint32Constant(shift_bits)), + Uint32Constant(mask)), + Uint32Constant(rhs)); + Reduction r = Reduce(node); + uint32_t new_mask = mask << shift_bits; + uint32_t new_rhs = rhs << shift_bits; + if (new_mask >> shift_bits == mask && new_rhs >> shift_bits == rhs) { + ASSERT_TRUE(r.Changed()); + // The left-hand side of the equality is now a Word32And operation, + // unless the mask is zero in which case the newly-created Word32And + // is immediately reduced away. + Matcher<Node*> lhs = mask == 0 + ? IsInt32Constant(0) + : IsWord32And(p0, IsInt32Constant(new_mask)); + EXPECT_THAT(r.replacement(), + IsWord32Equal(lhs, IsInt32Constant(new_rhs))); + } else { + ASSERT_FALSE(r.Changed()); + } + } + } + } +} + +// ----------------------------------------------------------------------------- +// Branch + +TEST_F(MachineOperatorReducerTest, BranchWithShiftedMaskedValue) { + // Branch condition (x >> K1) & K2 => x & (K2 << K1) + Node* const p0 = Parameter(0); + TRACED_FOREACH(uint32_t, mask, kUint32Values) { + TRACED_FORRANGE(uint32_t, shift_bits, 1, 31) { + Node* node = graph()->NewNode( + common()->Branch(), + graph()->NewNode(machine()->Word32And(), + graph()->NewNode(machine()->Word32Shr(), p0, + Uint32Constant(shift_bits)), + Uint32Constant(mask)), + graph()->start()); + Reduction r = Reduce(node); + uint32_t new_mask = mask << shift_bits; + if (new_mask >> shift_bits == mask) { + ASSERT_TRUE(r.Changed()); + // The branch condition is now a Word32And operation, unless the mask is + // zero in which case the newly-created Word32And is immediately reduced + // away. + Matcher<Node*> lhs = mask == 0 + ? IsInt32Constant(0) + : IsWord32And(p0, IsInt32Constant(new_mask)); + EXPECT_THAT(r.replacement(), IsBranch(lhs, graph()->start())); + } else { + ASSERT_FALSE(r.Changed()); + } + } + } +} // ----------------------------------------------------------------------------- // Int32Sub diff --git a/deps/v8/test/unittests/compiler/node-cache-unittest.cc b/deps/v8/test/unittests/compiler/node-cache-unittest.cc index 10118c3a41..777652db1b 100644 --- a/deps/v8/test/unittests/compiler/node-cache-unittest.cc +++ b/deps/v8/test/unittests/compiler/node-cache-unittest.cc @@ -17,13 +17,13 @@ namespace node_cache_unittest { using NodeCacheTest = GraphTest; TEST_F(NodeCacheTest, Int32Constant_back_to_back) { - Int32NodeCache cache; + Int32NodeCache cache(zone()); for (int i = -2000000000; i < 2000000000; i += 3315177) { - Node** pos = cache.Find(zone(), i); + Node** pos = cache.Find(i); ASSERT_TRUE(pos != nullptr); for (int j = 0; j < 3; j++) { - Node** npos = cache.Find(zone(), i); + Node** npos = cache.Find(i); EXPECT_EQ(pos, npos); } } @@ -31,38 +31,38 @@ TEST_F(NodeCacheTest, Int32Constant_back_to_back) { TEST_F(NodeCacheTest, Int32Constant_five) { - Int32NodeCache cache; + Int32NodeCache cache(zone()); int32_t constants[] = {static_cast<int32_t>(0x80000000), -77, 0, 1, -1}; Node* nodes[arraysize(constants)]; for (size_t i = 0; i < arraysize(constants); i++) { int32_t k = constants[i]; Node* node = graph()->NewNode(common()->Int32Constant(k)); - *cache.Find(zone(), k) = nodes[i] = node; + *cache.Find(k) = nodes[i] = node; } for (size_t i = 0; i < arraysize(constants); i++) { int32_t k = constants[i]; - EXPECT_EQ(nodes[i], *cache.Find(zone(), k)); + EXPECT_EQ(nodes[i], *cache.Find(k)); } } TEST_F(NodeCacheTest, Int32Constant_hits) { - Int32NodeCache cache; + Int32NodeCache cache(zone()); const int32_t kSize = 1500; Node** nodes = zone()->NewArray<Node*>(kSize); for (int i = 0; i < kSize; i++) { int32_t v = i * -55; nodes[i] = graph()->NewNode(common()->Int32Constant(v)); - *cache.Find(zone(), v) = nodes[i]; + *cache.Find(v) = nodes[i]; } int hits = 0; for (int i = 0; i < kSize; i++) { int32_t v = i * -55; - Node** pos = cache.Find(zone(), v); + Node** pos = cache.Find(v); if (*pos != nullptr) { EXPECT_EQ(nodes[i], *pos); hits++; @@ -73,13 +73,13 @@ TEST_F(NodeCacheTest, Int32Constant_hits) { TEST_F(NodeCacheTest, Int64Constant_back_to_back) { - Int64NodeCache cache; + Int64NodeCache cache(zone()); for (int64_t i = -2000000000; i < 2000000000; i += 3315177) { - Node** pos = cache.Find(zone(), i); + Node** pos = cache.Find(i); ASSERT_TRUE(pos != nullptr); for (int j = 0; j < 3; j++) { - Node** npos = cache.Find(zone(), i); + Node** npos = cache.Find(i); EXPECT_EQ(pos, npos); } } @@ -87,20 +87,20 @@ TEST_F(NodeCacheTest, Int64Constant_back_to_back) { TEST_F(NodeCacheTest, Int64Constant_hits) { - Int64NodeCache cache; + Int64NodeCache cache(zone()); const int32_t kSize = 1500; Node** nodes = zone()->NewArray<Node*>(kSize); for (int i = 0; i < kSize; i++) { int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001); nodes[i] = graph()->NewNode(common()->Int32Constant(i)); - *cache.Find(zone(), v) = nodes[i]; + *cache.Find(v) = nodes[i]; } int hits = 0; for (int i = 0; i < kSize; i++) { int64_t v = static_cast<int64_t>(i) * static_cast<int64_t>(5003001); - Node** pos = cache.Find(zone(), v); + Node** pos = cache.Find(v); if (*pos != nullptr) { EXPECT_EQ(nodes[i], *pos); hits++; @@ -111,13 +111,13 @@ TEST_F(NodeCacheTest, Int64Constant_hits) { TEST_F(NodeCacheTest, GetCachedNodes_int32) { - Int32NodeCache cache; + Int32NodeCache cache(zone()); int32_t constants[] = {0, 311, 12, 13, 14, 555, -555, -44, -33, -22, -11, 0, 311, 311, 412, 412, 11, 11, -33, -33, -22, -11}; for (size_t i = 0; i < arraysize(constants); i++) { int32_t k = constants[i]; - Node** pos = cache.Find(zone(), k); + Node** pos = cache.Find(k); if (*pos != nullptr) { ZoneVector<Node*> nodes(zone()); cache.GetCachedNodes(&nodes); @@ -134,13 +134,13 @@ TEST_F(NodeCacheTest, GetCachedNodes_int32) { TEST_F(NodeCacheTest, GetCachedNodes_int64) { - Int64NodeCache cache; + Int64NodeCache cache(zone()); int64_t constants[] = {0, 311, 12, 13, 14, 555, -555, -44, -33, -22, -11, 0, 311, 311, 412, 412, 11, 11, -33, -33, -22, -11}; for (size_t i = 0; i < arraysize(constants); i++) { int64_t k = constants[i]; - Node** pos = cache.Find(zone(), k); + Node** pos = cache.Find(k); if (*pos != nullptr) { ZoneVector<Node*> nodes(zone()); cache.GetCachedNodes(&nodes); diff --git a/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc b/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc index 62135dddce..9dda52ed8e 100644 --- a/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc +++ b/deps/v8/test/unittests/compiler/redundancy-elimination-unittest.cc @@ -754,16 +754,18 @@ TEST_F(RedundancyEliminationTest, CheckedUint64Bounds) { Node* effect = graph()->start(); Node* control = graph()->start(); - Node* check1 = effect = - graph()->NewNode(simplified()->CheckedUint64Bounds(feedback1), index, - length, effect, control); + Node* check1 = effect = graph()->NewNode( + simplified()->CheckedUint64Bounds( + feedback1, CheckBoundsParameters::kDeoptOnOutOfBounds), + 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); + Node* check2 = effect = graph()->NewNode( + simplified()->CheckedUint64Bounds( + feedback2, CheckBoundsParameters::kDeoptOnOutOfBounds), + index, length, effect, control); Reduction r2 = Reduce(check2); ASSERT_TRUE(r2.Changed()); EXPECT_EQ(r2.replacement(), check1); diff --git a/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc b/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc index e6ba7696c5..c24b2f2d97 100644 --- a/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc +++ b/deps/v8/test/unittests/compiler/state-values-utils-unittest.cc @@ -153,11 +153,13 @@ TEST_F(StateValuesIteratorTest, TreeFromVectorWithLiveness) { // Check the tree contents with vector. int i = 0; - for (StateValuesAccess::TypedNode node : StateValuesAccess(values_node)) { + for (StateValuesAccess::iterator it = + StateValuesAccess(values_node).begin(); + !it.done(); ++it) { if (liveness.Contains(i)) { - EXPECT_THAT(node.node, IsInt32Constant(i)); + EXPECT_THAT(it.node(), IsInt32Constant(i)); } else { - EXPECT_EQ(node.node, nullptr); + EXPECT_EQ(it.node(), nullptr); } i++; } diff --git a/deps/v8/test/unittests/compiler/typer-unittest.cc b/deps/v8/test/unittests/compiler/typer-unittest.cc index bfb65e7c5f..8ecee3f8a1 100644 --- a/deps/v8/test/unittests/compiler/typer-unittest.cc +++ b/deps/v8/test/unittests/compiler/typer-unittest.cc @@ -175,7 +175,7 @@ class TyperTest : public TypedGraphTest { for (int x1 = lmin; x1 < lmin + width; x1++) { for (int x2 = rmin; x2 < rmin + width; x2++) { double result_value = opfun(x1, x2); - Type result_type = Type::NewConstant( + Type result_type = Type::Constant( &broker_, isolate()->factory()->NewNumber(result_value), zone()); EXPECT_TRUE(result_type.Is(expected_type)); @@ -197,7 +197,7 @@ class TyperTest : public TypedGraphTest { double x1 = RandomInt(r1.AsRange()); double x2 = RandomInt(r2.AsRange()); double result_value = opfun(x1, x2); - Type result_type = Type::NewConstant( + Type result_type = Type::Constant( &broker_, isolate()->factory()->NewNumber(result_value), zone()); EXPECT_TRUE(result_type.Is(expected_type)); } @@ -205,13 +205,13 @@ class TyperTest : public TypedGraphTest { // Test extreme cases. double x1 = +1e-308; double x2 = -1e-308; - Type r1 = Type::NewConstant(&broker_, isolate()->factory()->NewNumber(x1), - zone()); - Type r2 = Type::NewConstant(&broker_, isolate()->factory()->NewNumber(x2), - zone()); + Type r1 = + Type::Constant(&broker_, isolate()->factory()->NewNumber(x1), zone()); + Type r2 = + Type::Constant(&broker_, isolate()->factory()->NewNumber(x2), zone()); Type expected_type = TypeBinaryOp(op, r1, r2); double result_value = opfun(x1, x2); - Type result_type = Type::NewConstant( + Type result_type = Type::Constant( &broker_, isolate()->factory()->NewNumber(result_value), zone()); EXPECT_TRUE(result_type.Is(expected_type)); } @@ -226,11 +226,11 @@ class TyperTest : public TypedGraphTest { double x1 = RandomInt(r1.AsRange()); double x2 = RandomInt(r2.AsRange()); bool result_value = opfun(x1, x2); - Type result_type = Type::NewConstant( - &broker_, - result_value ? isolate()->factory()->true_value() - : isolate()->factory()->false_value(), - zone()); + Type result_type = + Type::Constant(&broker_, + result_value ? isolate()->factory()->true_value() + : isolate()->factory()->false_value(), + zone()); EXPECT_TRUE(result_type.Is(expected_type)); } } @@ -246,7 +246,7 @@ class TyperTest : public TypedGraphTest { int32_t x1 = static_cast<int32_t>(RandomInt(r1.AsRange())); int32_t x2 = static_cast<int32_t>(RandomInt(r2.AsRange())); double result_value = opfun(x1, x2); - Type result_type = Type::NewConstant( + Type result_type = Type::Constant( &broker_, isolate()->factory()->NewNumber(result_value), zone()); EXPECT_TRUE(result_type.Is(expected_type)); } @@ -585,6 +585,96 @@ SIMPLIFIED_NUMBER_BINOP_LIST(TEST_MONOTONICITY) SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(TEST_MONOTONICITY) #undef TEST_MONOTONICITY +TEST_F(TyperTest, Manual_Operation_NumberMax) { + BinaryTyper t = [&](Type type1, Type type2) { + return operation_typer_.NumberMax(type1, type2); + }; + + Type zero = Type::Constant(0, zone()); + Type zero_or_minuszero = Type::Union(zero, Type::MinusZero(), zone()); + Type dot_five = Type::Constant(0.5, zone()); + + Type a = t(Type::MinusZero(), Type::MinusZero()); + CHECK(Type::MinusZero().Is(a)); + + Type b = t(Type::MinusZero(), zero_or_minuszero); + CHECK(Type::MinusZero().Is(b)); + CHECK(zero.Is(b)); + CHECK(a.Is(b)); + + Type c = t(zero_or_minuszero, Type::MinusZero()); + CHECK(Type::MinusZero().Is(c)); + CHECK(zero.Is(c)); + CHECK(a.Is(c)); + + Type d = t(zero_or_minuszero, zero_or_minuszero); + CHECK(Type::MinusZero().Is(d)); + CHECK(zero.Is(d)); + CHECK(b.Is(d)); + CHECK(c.Is(d)); + + Type e = + t(Type::MinusZero(), Type::Union(Type::MinusZero(), dot_five, zone())); + CHECK(Type::MinusZero().Is(e)); + CHECK(dot_five.Is(e)); + CHECK(a.Is(e)); + + Type f = t(Type::MinusZero(), zero); + CHECK(zero.Is(f)); + CHECK(f.Is(b)); + + Type g = t(zero, Type::MinusZero()); + CHECK(zero.Is(g)); + CHECK(g.Is(c)); +} + +TEST_F(TyperTest, Manual_Operation_NumberMin) { + BinaryTyper t = [&](Type type1, Type type2) { + return operation_typer_.NumberMin(type1, type2); + }; + + Type zero = Type::Constant(0, zone()); + Type zero_or_minuszero = Type::Union(zero, Type::MinusZero(), zone()); + Type one = Type::Constant(1, zone()); + Type minus_dot_five = Type::Constant(-0.5, zone()); + + Type a = t(Type::MinusZero(), Type::MinusZero()); + CHECK(Type::MinusZero().Is(a)); + + Type b = t(Type::MinusZero(), zero_or_minuszero); + CHECK(Type::MinusZero().Is(b)); + CHECK(zero.Is(b)); + CHECK(a.Is(b)); + + Type c = t(zero_or_minuszero, Type::MinusZero()); + CHECK(Type::MinusZero().Is(c)); + CHECK(zero.Is(c)); + CHECK(a.Is(c)); + + Type d = t(zero_or_minuszero, zero_or_minuszero); + CHECK(Type::MinusZero().Is(d)); + CHECK(zero.Is(d)); + CHECK(b.Is(d)); + CHECK(c.Is(d)); + + Type e = t(Type::MinusZero(), + Type::Union(Type::MinusZero(), minus_dot_five, zone())); + CHECK(Type::MinusZero().Is(e)); + CHECK(minus_dot_five.Is(e)); + CHECK(a.Is(e)); + + Type f = t(Type::MinusZero(), zero); + CHECK(Type::MinusZero().Is(f)); + CHECK(f.Is(b)); + + Type g = t(zero, Type::MinusZero()); + CHECK(Type::MinusZero().Is(g)); + CHECK(g.Is(c)); + + Type h = t(one, Type::MinusZero()); + CHECK(Type::MinusZero().Is(h)); +} + } // namespace compiler } // namespace internal } // namespace v8 diff --git a/deps/v8/test/unittests/execution/microtask-queue-unittest.cc b/deps/v8/test/unittests/execution/microtask-queue-unittest.cc index 6cb9df0895..3b59b7cf35 100644 --- a/deps/v8/test/unittests/execution/microtask-queue-unittest.cc +++ b/deps/v8/test/unittests/execution/microtask-queue-unittest.cc @@ -30,10 +30,10 @@ void RunStdFunction(void* data) { } template <typename TMixin> -class WithFinalizationGroupMixin : public TMixin { +class WithFinalizationRegistryMixin : public TMixin { public: - WithFinalizationGroupMixin() = default; - ~WithFinalizationGroupMixin() override = default; + WithFinalizationRegistryMixin() = default; + ~WithFinalizationRegistryMixin() override = default; static void SetUpTestCase() { CHECK_NULL(save_flags_); @@ -54,21 +54,29 @@ class WithFinalizationGroupMixin : public TMixin { private: static SaveFlags* save_flags_; - DISALLOW_COPY_AND_ASSIGN(WithFinalizationGroupMixin); + DISALLOW_COPY_AND_ASSIGN(WithFinalizationRegistryMixin); }; template <typename TMixin> -SaveFlags* WithFinalizationGroupMixin<TMixin>::save_flags_ = nullptr; - -using TestWithNativeContextAndFinalizationGroup = // - WithInternalIsolateMixin< // - WithContextMixin< // - WithFinalizationGroupMixin< // - WithIsolateScopeMixin< // - WithSharedIsolateMixin< // +SaveFlags* WithFinalizationRegistryMixin<TMixin>::save_flags_ = nullptr; + +using TestWithNativeContextAndFinalizationRegistry = // + WithInternalIsolateMixin< // + WithContextMixin< // + WithFinalizationRegistryMixin< // + WithIsolateScopeMixin< // + WithSharedIsolateMixin< // ::testing::Test>>>>>; -class MicrotaskQueueTest : public TestWithNativeContextAndFinalizationGroup { +namespace { + +void DummyPromiseHook(PromiseHookType type, Local<Promise> promise, + Local<Value> parent) {} + +} // namespace + +class MicrotaskQueueTest : public TestWithNativeContextAndFinalizationRegistry, + public ::testing::WithParamInterface<bool> { public: template <typename F> Handle<Microtask> NewMicrotask(F&& f) { @@ -82,6 +90,12 @@ class MicrotaskQueueTest : public TestWithNativeContextAndFinalizationGroup { void SetUp() override { microtask_queue_ = MicrotaskQueue::New(isolate()); native_context()->set_microtask_queue(microtask_queue()); + + if (GetParam()) { + // Use a PromiseHook to switch the implementation to ResolvePromise + // runtime, instead of ResolvePromise builtin. + v8_isolate()->SetPromiseHook(&DummyPromiseHook); + } } void TearDown() override { @@ -126,7 +140,7 @@ class RecordingVisitor : public RootVisitor { }; // Sanity check. Ensure a microtask is stored in a queue and run. -TEST_F(MicrotaskQueueTest, EnqueueAndRun) { +TEST_P(MicrotaskQueueTest, EnqueueAndRun) { bool ran = false; EXPECT_EQ(0, microtask_queue()->capacity()); EXPECT_EQ(0, microtask_queue()->size()); @@ -142,7 +156,7 @@ TEST_F(MicrotaskQueueTest, EnqueueAndRun) { } // Check for a buffer growth. -TEST_F(MicrotaskQueueTest, BufferGrowth) { +TEST_P(MicrotaskQueueTest, BufferGrowth) { int count = 0; // Enqueue and flush the queue first to have non-zero |start_|. @@ -176,7 +190,7 @@ TEST_F(MicrotaskQueueTest, BufferGrowth) { } // MicrotaskQueue instances form a doubly linked list. -TEST_F(MicrotaskQueueTest, InstanceChain) { +TEST_P(MicrotaskQueueTest, InstanceChain) { ClearTestMicrotaskQueue(); MicrotaskQueue* default_mtq = isolate()->default_microtask_queue(); @@ -207,7 +221,7 @@ TEST_F(MicrotaskQueueTest, InstanceChain) { // Pending Microtasks in MicrotaskQueues are strong roots. Ensure they are // visited exactly once. -TEST_F(MicrotaskQueueTest, VisitRoot) { +TEST_P(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([] {})); @@ -233,7 +247,7 @@ TEST_F(MicrotaskQueueTest, VisitRoot) { EXPECT_EQ(expected, actual); } -TEST_F(MicrotaskQueueTest, PromiseHandlerContext) { +TEST_P(MicrotaskQueueTest, PromiseHandlerContext) { Local<v8::Context> v8_context2 = v8::Context::New(v8_isolate()); Local<v8::Context> v8_context3 = v8::Context::New(v8_isolate()); Local<v8::Context> v8_context4 = v8::Context::New(v8_isolate()); @@ -327,7 +341,7 @@ TEST_F(MicrotaskQueueTest, PromiseHandlerContext) { v8_context2->DetachGlobal(); } -TEST_F(MicrotaskQueueTest, DetachGlobal_Enqueue) { +TEST_P(MicrotaskQueueTest, DetachGlobal_Enqueue) { EXPECT_EQ(0, microtask_queue()->size()); // Detach MicrotaskQueue from the current context. @@ -339,7 +353,7 @@ TEST_F(MicrotaskQueueTest, DetachGlobal_Enqueue) { EXPECT_EQ(0, microtask_queue()->size()); } -TEST_F(MicrotaskQueueTest, DetachGlobal_Run) { +TEST_P(MicrotaskQueueTest, DetachGlobal_Run) { EXPECT_EQ(0, microtask_queue()->size()); // Enqueue microtasks to the current context. @@ -377,18 +391,7 @@ TEST_F(MicrotaskQueueTest, DetachGlobal_Run) { } } -namespace { - -void DummyPromiseHook(PromiseHookType type, Local<Promise> promise, - Local<Value> parent) {} - -} // namespace - -TEST_F(MicrotaskQueueTest, DetachGlobal_PromiseResolveThenableJobTask) { - // Use a PromiseHook to switch the implementation to ResolvePromise runtime, - // instead of ResolvePromise builtin. - v8_isolate()->SetPromiseHook(&DummyPromiseHook); - +TEST_P(MicrotaskQueueTest, DetachGlobal_PromiseResolveThenableJobTask) { RunJS( "var resolve;" "var promise = new Promise(r => { resolve = r; });" @@ -410,7 +413,71 @@ TEST_F(MicrotaskQueueTest, DetachGlobal_PromiseResolveThenableJobTask) { EXPECT_EQ(0, microtask_queue()->size()); } -TEST_F(MicrotaskQueueTest, DetachGlobal_HandlerContext) { +TEST_P(MicrotaskQueueTest, DetachGlobal_ResolveThenableForeignThen) { + Handle<JSArray> result = RunJS<JSArray>( + "let result = [false];" + "result"); + Handle<JSFunction> then = RunJS<JSFunction>("() => { result[0] = true; }"); + + Handle<JSPromise> stale_promise; + + { + // Create a context with its own microtask queue. + std::unique_ptr<MicrotaskQueue> sub_microtask_queue = + MicrotaskQueue::New(isolate()); + Local<v8::Context> sub_context = v8::Context::New( + v8_isolate(), + /* extensions= */ nullptr, + /* global_template= */ MaybeLocal<ObjectTemplate>(), + /* global_object= */ MaybeLocal<Value>(), + /* internal_fields_deserializer= */ DeserializeInternalFieldsCallback(), + sub_microtask_queue.get()); + + { + v8::Context::Scope scope(sub_context); + CHECK(sub_context->Global() + ->Set(sub_context, NewString("then"), + Utils::ToLocal(Handle<JSReceiver>::cast(then))) + .FromJust()); + + ASSERT_EQ(0, microtask_queue()->size()); + ASSERT_EQ(0, sub_microtask_queue->size()); + ASSERT_TRUE(Object::GetElement(isolate(), result, 0) + .ToHandleChecked() + ->IsFalse()); + + // With a regular thenable, a microtask is queued on the sub-context. + RunJS<JSPromise>("Promise.resolve({ then: cb => cb(1) })"); + EXPECT_EQ(0, microtask_queue()->size()); + EXPECT_EQ(1, sub_microtask_queue->size()); + EXPECT_TRUE(Object::GetElement(isolate(), result, 0) + .ToHandleChecked() + ->IsFalse()); + + // But when the `then` method comes from another context, a microtask is + // instead queued on the main context. + stale_promise = RunJS<JSPromise>("Promise.resolve({ then })"); + EXPECT_EQ(1, microtask_queue()->size()); + EXPECT_EQ(1, sub_microtask_queue->size()); + EXPECT_TRUE(Object::GetElement(isolate(), result, 0) + .ToHandleChecked() + ->IsFalse()); + } + + sub_context->DetachGlobal(); + } + + EXPECT_EQ(1, microtask_queue()->size()); + EXPECT_TRUE( + Object::GetElement(isolate(), result, 0).ToHandleChecked()->IsFalse()); + + EXPECT_EQ(1, microtask_queue()->RunMicrotasks(isolate())); + EXPECT_EQ(0, microtask_queue()->size()); + EXPECT_TRUE( + Object::GetElement(isolate(), result, 0).ToHandleChecked()->IsTrue()); +} + +TEST_P(MicrotaskQueueTest, DetachGlobal_HandlerContext) { // EnqueueMicrotask should use the context associated to the handler instead // of the current context. E.g. // // At Context A. @@ -489,7 +556,7 @@ TEST_F(MicrotaskQueueTest, DetachGlobal_HandlerContext) { .FromJust()); } -TEST_F(MicrotaskQueueTest, DetachGlobal_Chain) { +TEST_P(MicrotaskQueueTest, DetachGlobal_Chain) { Handle<JSPromise> stale_rejected_promise; Local<v8::Context> sub_context = v8::Context::New(v8_isolate()); @@ -516,7 +583,7 @@ TEST_F(MicrotaskQueueTest, DetachGlobal_Chain) { Object::GetElement(isolate(), result, 0).ToHandleChecked()->IsTrue()); } -TEST_F(MicrotaskQueueTest, DetachGlobal_InactiveHandler) { +TEST_P(MicrotaskQueueTest, DetachGlobal_InactiveHandler) { Local<v8::Context> sub_context = v8::Context::New(v8_isolate()); Utils::OpenHandle(*sub_context) ->native_context() @@ -558,7 +625,7 @@ TEST_F(MicrotaskQueueTest, DetachGlobal_InactiveHandler) { Object::GetElement(isolate(), result, 1).ToHandleChecked()->IsFalse()); } -TEST_F(MicrotaskQueueTest, MicrotasksScope) { +TEST_P(MicrotaskQueueTest, MicrotasksScope) { ASSERT_NE(isolate()->default_microtask_queue(), microtask_queue()); microtask_queue()->set_microtasks_policy(MicrotasksPolicy::kScoped); @@ -574,5 +641,11 @@ TEST_F(MicrotaskQueueTest, MicrotasksScope) { EXPECT_TRUE(ran); } +INSTANTIATE_TEST_SUITE_P( + , MicrotaskQueueTest, ::testing::Values(false, true), + [](const ::testing::TestParamInfo<MicrotaskQueueTest::ParamType>& info) { + return info.param ? "runtime" : "builtin"; + }); + } // namespace internal } // namespace v8 diff --git a/deps/v8/test/unittests/heap/cppgc/allocation_unittest.cc b/deps/v8/test/unittests/heap/cppgc/allocation_unittest.cc new file mode 100644 index 0000000000..3a02ae1721 --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/allocation_unittest.cc @@ -0,0 +1,42 @@ +// Copyright 2020 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/cppgc/allocation.h" + +#include <memory> + +#include "src/heap/cppgc/heap.h" +#include "test/unittests/heap/cppgc/tests.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cppgc { + +TEST(GCBasicHeapTest, CreateAndDestroyHeap) { + std::unique_ptr<Heap> heap{Heap::Create()}; +} + +namespace { + +class Foo : public GarbageCollected<Foo> { + public: + static size_t destructor_callcount; + + Foo() { destructor_callcount = 0; } + ~Foo() { destructor_callcount++; } +}; + +size_t Foo::destructor_callcount; + +class GCAllocationTest : public testing::TestWithHeap {}; + +} // namespace + +TEST_F(GCAllocationTest, MakeGarbageCollectedAndReclaim) { + MakeGarbageCollected<Foo>(GetHeap()); + EXPECT_EQ(0u, Foo::destructor_callcount); + internal::Heap::From(GetHeap())->CollectGarbage(); + EXPECT_EQ(1u, Foo::destructor_callcount); +} + +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/finalizer-trait_unittest.cc b/deps/v8/test/unittests/heap/cppgc/finalizer-trait_unittest.cc new file mode 100644 index 0000000000..91a255e727 --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/finalizer-trait_unittest.cc @@ -0,0 +1,118 @@ +// Copyright 2020 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/cppgc/finalizer-trait.h" +#include <type_traits> +#include "testing/gtest/include/gtest/gtest.h" + +namespace cppgc { +namespace internal { + +namespace { + +// Trivially destructible types. +class TypeWithoutDestructor final {}; +class TypeWithPrimitive final { + public: + int foo = 0; +}; + +class InvokeCounter { + public: + static size_t kCallcount; + static void Reset() { kCallcount = 0; } + static void Invoke() { kCallcount++; } +}; + +size_t InvokeCounter::kCallcount = 0; + +// Regular C++ use cases. + +class TypeWithDestructor final : public InvokeCounter { + public: + ~TypeWithDestructor() { Invoke(); } +}; + +class TypeWithVirtualDestructorBase { + public: + virtual ~TypeWithVirtualDestructorBase() = default; +}; + +class TypeWithVirtualDestructorChild final + : public TypeWithVirtualDestructorBase, + public InvokeCounter { + public: + ~TypeWithVirtualDestructorChild() final { Invoke(); } +}; + +// Manual dispatch to avoid vtables. + +class TypeWithCustomFinalizationMethod final : public InvokeCounter { + public: + void FinalizeGarbageCollectedObject() { Invoke(); } +}; + +class TypeWithCustomFinalizationMethodAtBase { + public: + void FinalizeGarbageCollectedObject(); +}; + +class TypeWithCustomFinalizationMethodAtBaseChild + : public TypeWithCustomFinalizationMethodAtBase, + public InvokeCounter { + public: + ~TypeWithCustomFinalizationMethodAtBaseChild() { Invoke(); } +}; + +void TypeWithCustomFinalizationMethodAtBase::FinalizeGarbageCollectedObject() { + // The test knows that base is only inherited by a single child. In practice + // users can maintain a map of valid types in already existing storage. + static_cast<TypeWithCustomFinalizationMethodAtBaseChild*>(this) + ->~TypeWithCustomFinalizationMethodAtBaseChild(); +} + +template <typename Type> +void ExpectFinalizerIsInvoked(Type* object) { + InvokeCounter::Reset(); + EXPECT_NE(nullptr, FinalizerTrait<Type>::kCallback); + FinalizerTrait<Type>::kCallback(object); + EXPECT_EQ(1u, InvokeCounter::kCallcount); + operator delete(object); +} + +} // namespace + +TEST(FinalizerTrait, TypeWithoutDestructorHasNoFinalizer) { + static_assert(std::is_trivially_destructible<TypeWithoutDestructor>::value, + "trivially destructible"); + EXPECT_EQ(nullptr, FinalizerTrait<TypeWithoutDestructor>::kCallback); +} + +TEST(FinalizerTrait, TypeWithPrimitiveHasNoFinalizer) { + static_assert(std::is_trivially_destructible<TypeWithPrimitive>::value, + "trivially destructible"); + EXPECT_EQ(nullptr, FinalizerTrait<TypeWithPrimitive>::kCallback); +} + +TEST(FinalizerTrait, FinalizerForTypeWithDestructor) { + ExpectFinalizerIsInvoked(new TypeWithDestructor()); +} + +TEST(FinalizerTrait, FinalizerForTypeWithVirtualBaseDtor) { + TypeWithVirtualDestructorBase* base = new TypeWithVirtualDestructorChild(); + ExpectFinalizerIsInvoked(base); +} + +TEST(FinalizerTrait, FinalizerForCustomFinalizationMethod) { + ExpectFinalizerIsInvoked(new TypeWithCustomFinalizationMethod()); +} + +TEST(FinalizerTrait, FinalizerForCustomFinalizationMethodInBase) { + TypeWithCustomFinalizationMethodAtBase* base = + new TypeWithCustomFinalizationMethodAtBaseChild(); + ExpectFinalizerIsInvoked(base); +} + +} // namespace internal +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/garbage-collected_unittest.cc b/deps/v8/test/unittests/heap/cppgc/garbage-collected_unittest.cc new file mode 100644 index 0000000000..5098bdf48e --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/garbage-collected_unittest.cc @@ -0,0 +1,26 @@ +// Copyright 2020 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/cppgc/garbage-collected.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace cppgc { +namespace internal { + +namespace { + +class GCed : public GarbageCollected<GCed> {}; +class NotGCed {}; + +} // namespace + +TEST(GarbageCollectedTest, GarbageCollectedTrait) { + EXPECT_FALSE(IsGarbageCollectedType<int>::value); + EXPECT_FALSE(IsGarbageCollectedType<NotGCed>::value); + EXPECT_TRUE(IsGarbageCollectedType<GCed>::value); +} + +} // namespace internal +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/gc-info_unittest.cc b/deps/v8/test/unittests/heap/cppgc/gc-info_unittest.cc new file mode 100644 index 0000000000..e7bfb5a7fe --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/gc-info_unittest.cc @@ -0,0 +1,153 @@ +// Copyright 2020 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/cppgc/gc-info.h" + +#include "include/cppgc/platform.h" +#include "src/base/page-allocator.h" +#include "src/base/platform/platform.h" +#include "src/heap/cppgc/gc-info-table.h" +#include "test/unittests/heap/cppgc/tests.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cppgc { +namespace internal { + +TEST(GCInfoTableTest, InitialEmpty) { + v8::base::PageAllocator page_allocator; + GCInfoTable table(&page_allocator); + EXPECT_EQ(GCInfoTable::kMinIndex, table.NumberOfGCInfosForTesting()); +} + +TEST(GCInfoTableTest, ResizeToMaxIndex) { + v8::base::PageAllocator page_allocator; + GCInfoTable table(&page_allocator); + GCInfo info = {nullptr, false}; + for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex; + i++) { + GCInfoIndex index = table.RegisterNewGCInfo(info); + EXPECT_EQ(i, index); + } +} + +TEST(GCInfoTableDeathTest, MoreThanMaxIndexInfos) { + v8::base::PageAllocator page_allocator; + GCInfoTable table(&page_allocator); + GCInfo info = {nullptr, false}; + // Create GCInfoTable::kMaxIndex entries. + for (GCInfoIndex i = GCInfoTable::kMinIndex; i < GCInfoTable::kMaxIndex; + i++) { + table.RegisterNewGCInfo(info); + } + EXPECT_DEATH_IF_SUPPORTED(table.RegisterNewGCInfo(info), ""); +} + +TEST(GCInfoTableDeathTest, OldTableAreaIsReadOnly) { + v8::base::PageAllocator page_allocator; + GCInfoTable table(&page_allocator); + GCInfo info = {nullptr, false}; + // Use up all slots until limit. + GCInfoIndex limit = table.LimitForTesting(); + // Bail out if initial limit is already the maximum because of large committed + // pages. In this case, nothing can be comitted as read-only. + if (limit == GCInfoTable::kMaxIndex) { + return; + } + for (GCInfoIndex i = GCInfoTable::kMinIndex; i < limit; i++) { + table.RegisterNewGCInfo(info); + } + EXPECT_EQ(limit, table.LimitForTesting()); + table.RegisterNewGCInfo(info); + EXPECT_NE(limit, table.LimitForTesting()); + // Old area is now read-only. + auto& first_slot = table.TableSlotForTesting(GCInfoTable::kMinIndex); + EXPECT_DEATH_IF_SUPPORTED(first_slot.finalize = nullptr, ""); +} + +namespace { + +class ThreadRegisteringGCInfoObjects final : public v8::base::Thread { + public: + ThreadRegisteringGCInfoObjects(GCInfoTable* table, + GCInfoIndex num_registrations) + : v8::base::Thread(Options("Thread registering GCInfo objects.")), + table_(table), + num_registrations_(num_registrations) {} + + void Run() final { + GCInfo info = {nullptr, false}; + for (GCInfoIndex i = 0; i < num_registrations_; i++) { + table_->RegisterNewGCInfo(info); + } + } + + private: + GCInfoTable* table_; + GCInfoIndex num_registrations_; +}; + +} // namespace + +TEST(GCInfoTableTest, MultiThreadedResizeToMaxIndex) { + constexpr size_t num_threads = 4; + constexpr size_t main_thread_initialized = 2; + constexpr size_t gc_infos_to_register = + (GCInfoTable::kMaxIndex - 1) - + (GCInfoTable::kMinIndex + main_thread_initialized); + static_assert(gc_infos_to_register % num_threads == 0, + "must sum up to kMaxIndex"); + constexpr size_t gc_infos_per_thread = gc_infos_to_register / num_threads; + + v8::base::PageAllocator page_allocator; + GCInfoTable table(&page_allocator); + GCInfo info = {nullptr, false}; + for (size_t i = 0; i < main_thread_initialized; i++) { + table.RegisterNewGCInfo(info); + } + + v8::base::Thread* threads[num_threads]; + for (size_t i = 0; i < num_threads; i++) { + threads[i] = + new ThreadRegisteringGCInfoObjects(&table, gc_infos_per_thread); + } + for (size_t i = 0; i < num_threads; i++) { + CHECK(threads[i]->Start()); + } + for (size_t i = 0; i < num_threads; i++) { + threads[i]->Join(); + delete threads[i]; + } +} + +// Tests using the global table and GCInfoTrait. + +namespace { + +class GCInfoTraitTest : public testing::TestWithPlatform {}; + +class BasicType final {}; +class OtherBasicType final {}; + +} // namespace + +TEST_F(GCInfoTraitTest, IndexInBounds) { + const GCInfoIndex index = GCInfoTrait<BasicType>::Index(); + EXPECT_GT(GCInfoTable::kMaxIndex, index); + EXPECT_LE(GCInfoTable::kMinIndex, index); +} + +TEST_F(GCInfoTraitTest, TraitReturnsSameIndexForSameType) { + const GCInfoIndex index1 = GCInfoTrait<BasicType>::Index(); + const GCInfoIndex index2 = GCInfoTrait<BasicType>::Index(); + EXPECT_EQ(index1, index2); +} + +TEST_F(GCInfoTraitTest, TraitReturnsDifferentIndexForDifferentTypes) { + const GCInfoIndex index1 = GCInfoTrait<BasicType>::Index(); + const GCInfoIndex index2 = GCInfoTrait<OtherBasicType>::Index(); + EXPECT_NE(index1, index2); +} + +} // namespace internal +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/heap-object-header_unittest.cc b/deps/v8/test/unittests/heap/cppgc/heap-object-header_unittest.cc new file mode 100644 index 0000000000..b062489cb3 --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/heap-object-header_unittest.cc @@ -0,0 +1,181 @@ +// Copyright 2020 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/cppgc/heap-object-header.h" + +#include <atomic> +#include <memory> + +#include "include/cppgc/allocation.h" +#include "src/base/atomic-utils.h" +#include "src/base/macros.h" +#include "src/base/platform/platform.h" +#include "src/heap/cppgc/globals.h" +#include "src/heap/cppgc/heap-object-header-inl.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cppgc { +namespace internal { + +TEST(HeapObjectHeaderTest, Constructor) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_EQ(kSize, header.GetSize()); + EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex()); + EXPECT_TRUE(header.IsInConstruction()); + EXPECT_FALSE(header.IsMarked()); +} + +TEST(HeapObjectHeaderTest, Payload) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_EQ(reinterpret_cast<ConstAddress>(&header) + sizeof(HeapObjectHeader), + header.Payload()); +} + +TEST(HeapObjectHeaderTest, GetGCInfoIndex) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex()); + EXPECT_EQ(kGCInfoIndex, + header.GetGCInfoIndex<HeapObjectHeader::AccessMode::kAtomic>()); +} + +TEST(HeapObjectHeaderTest, GetSize) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity * 23; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_EQ(kSize, header.GetSize()); + EXPECT_EQ(kSize, header.GetSize<HeapObjectHeader::AccessMode::kAtomic>()); +} + +TEST(HeapObjectHeaderTest, IsLargeObject) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity * 23; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_EQ(false, header.IsLargeObject()); + EXPECT_EQ(false, + header.IsLargeObject<HeapObjectHeader::AccessMode::kAtomic>()); + HeapObjectHeader large_header(0, kGCInfoIndex + 1); + EXPECT_EQ(true, large_header.IsLargeObject()); + EXPECT_EQ( + true, + large_header.IsLargeObject<HeapObjectHeader::AccessMode::kAtomic>()); +} + +TEST(HeapObjectHeaderTest, MarkObjectAsFullyConstructed) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_TRUE(header.IsInConstruction()); + header.MarkAsFullyConstructed(); + EXPECT_FALSE(header.IsInConstruction()); + // Size shares the same bitfield and should be unaffected by + // MarkObjectAsFullyConstructed. + EXPECT_EQ(kSize, header.GetSize()); +} + +TEST(HeapObjectHeaderTest, TryMark) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity * 7; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_FALSE(header.IsMarked()); + EXPECT_TRUE(header.TryMarkAtomic()); + // GCInfoIndex shares the same bitfield and should be unaffected by + // TryMarkAtomic. + EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex()); + EXPECT_FALSE(header.TryMarkAtomic()); + // GCInfoIndex shares the same bitfield and should be unaffected by + // TryMarkAtomic. + EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex()); + EXPECT_TRUE(header.IsMarked()); +} + +TEST(HeapObjectHeaderTest, Unmark) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = kAllocationGranularity * 7; + HeapObjectHeader header(kSize, kGCInfoIndex); + EXPECT_FALSE(header.IsMarked()); + EXPECT_TRUE(header.TryMarkAtomic()); + EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex()); + EXPECT_TRUE(header.IsMarked()); + header.Unmark(); + // GCInfoIndex shares the same bitfield and should be unaffected by Unmark. + EXPECT_EQ(kGCInfoIndex, header.GetGCInfoIndex()); + EXPECT_FALSE(header.IsMarked()); + HeapObjectHeader header2(kSize, kGCInfoIndex); + EXPECT_FALSE(header2.IsMarked()); + EXPECT_TRUE(header2.TryMarkAtomic()); + EXPECT_TRUE(header2.IsMarked()); + header2.Unmark<HeapObjectHeader::AccessMode::kAtomic>(); + // GCInfoIndex shares the same bitfield and should be unaffected by Unmark. + EXPECT_EQ(kGCInfoIndex, header2.GetGCInfoIndex()); + EXPECT_FALSE(header2.IsMarked()); +} + +namespace { + +struct Payload { + volatile size_t value{5}; +}; + +class ConcurrentGCThread final : public v8::base::Thread { + public: + explicit ConcurrentGCThread(HeapObjectHeader* header, Payload* payload) + : v8::base::Thread(Options("Thread accessing object.")), + header_(header), + payload_(payload) {} + + void Run() final { + while (header_->IsInConstruction<HeapObjectHeader::AccessMode::kAtomic>()) { + } + USE(v8::base::AsAtomicPtr(const_cast<size_t*>(&payload_->value)) + ->load(std::memory_order_relaxed)); + } + + private: + HeapObjectHeader* header_; + Payload* payload_; +}; + +} // namespace + +TEST(HeapObjectHeaderTest, ConstructionBitProtectsNonAtomicWrites) { + // Object publishing: Test checks that non-atomic stores in the payload can be + // guarded using MarkObjectAsFullyConstructed/IsInConstruction. The test + // relies on TSAN to find data races. + constexpr size_t kSize = + (sizeof(HeapObjectHeader) + sizeof(Payload) + kAllocationMask) & + ~kAllocationMask; + typename std::aligned_storage<kSize, kAllocationGranularity>::type data; + HeapObjectHeader* header = new (&data) HeapObjectHeader(kSize, 1); + ConcurrentGCThread gc_thread(header, + reinterpret_cast<Payload*>(header->Payload())); + CHECK(gc_thread.Start()); + new (header->Payload()) Payload(); + header->MarkAsFullyConstructed(); + gc_thread.Join(); +} + +#ifdef DEBUG + +TEST(HeapObjectHeaderDeathTest, ConstructorTooLargeSize) { + constexpr GCInfoIndex kGCInfoIndex = 17; + constexpr size_t kSize = HeapObjectHeader::kMaxSize + 1; + EXPECT_DEATH_IF_SUPPORTED(HeapObjectHeader header(kSize, kGCInfoIndex), ""); +} + +TEST(HeapObjectHeaderDeathTest, ConstructorTooLargeGCInfoIndex) { + constexpr GCInfoIndex kGCInfoIndex = GCInfoTable::kMaxIndex + 1; + constexpr size_t kSize = kAllocationGranularity; + EXPECT_DEATH_IF_SUPPORTED(HeapObjectHeader header(kSize, kGCInfoIndex), ""); +} + +#endif // DEBUG + +} // namespace internal +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/run-all-unittests.cc b/deps/v8/test/unittests/heap/cppgc/run-all-unittests.cc new file mode 100644 index 0000000000..cdc862e309 --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/run-all-unittests.cc @@ -0,0 +1,17 @@ +// Copyright 2020 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 "testing/gmock/include/gmock/gmock.h" + +int main(int argc, char** argv) { + // Don't catch SEH exceptions and continue as the following tests might hang + // in an broken environment on windows. + testing::GTEST_FLAG(catch_exceptions) = false; + + // Most unit-tests are multi-threaded, so enable thread-safe death-tests. + testing::FLAGS_gtest_death_test_style = "threadsafe"; + + testing::InitGoogleMock(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/deps/v8/test/unittests/heap/cppgc/stack_unittest.cc b/deps/v8/test/unittests/heap/cppgc/stack_unittest.cc new file mode 100644 index 0000000000..435c06f83f --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/stack_unittest.cc @@ -0,0 +1,256 @@ +// Copyright 2020 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/cppgc/stack.h" + +#include <memory> +#include <ostream> + +#include "include/v8config.h" +#include "src/base/platform/platform.h" +#include "testing/gtest/include/gtest/gtest.h" + +#if V8_OS_LINUX && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64) +#include <xmmintrin.h> +#endif + +namespace cppgc { +namespace internal { + +namespace { + +class GCStackTest : public ::testing::Test { + protected: + void SetUp() override { + stack_.reset(new Stack(v8::base::Stack::GetStackStart())); + } + + void TearDown() override { stack_.reset(); } + + Stack* GetStack() const { return stack_.get(); } + + private: + std::unique_ptr<Stack> stack_; +}; + +} // namespace + +TEST_F(GCStackTest, IsOnStackForStackValue) { + void* dummy; + EXPECT_TRUE(GetStack()->IsOnStack(&dummy)); +} + +TEST_F(GCStackTest, IsOnStackForHeapValue) { + auto dummy = std::make_unique<int>(); + EXPECT_FALSE(GetStack()->IsOnStack(dummy.get())); +} + +#ifdef CPPGC_SUPPORTS_CONSERVATIVE_STACK_SCAN + +namespace { + +class StackScanner final : public StackVisitor { + public: + struct Container { + std::unique_ptr<int> value; + }; + + StackScanner() : container_(new Container{}) { + container_->value = std::make_unique<int>(); + } + + void VisitPointer(const void* address) final { + if (address == container_->value.get()) found_ = true; + } + + void Reset() { found_ = false; } + bool found() const { return found_; } + int* needle() const { return container_->value.get(); } + + private: + std::unique_ptr<Container> container_; + bool found_ = false; +}; + +} // namespace + +TEST_F(GCStackTest, IteratePointersFindsOnStackValue) { + auto scanner = std::make_unique<StackScanner>(); + + // No check that the needle is initially not found as on some platforms it + // may be part of the redzone or temporaries after setting it up throuhg + // StackScanner. + { + int* volatile tmp = scanner->needle(); + USE(tmp); + GetStack()->IteratePointers(scanner.get()); + EXPECT_TRUE(scanner->found()); + } +} + +TEST_F(GCStackTest, IteratePointersFindsOnStackValuePotentiallyUnaligned) { + auto scanner = std::make_unique<StackScanner>(); + + // No check that the needle is initially not found as on some platforms it + // may be part of the redzone or temporaries after setting it up throuhg + // StackScanner. + { + char a = 'c'; + USE(a); + int* volatile tmp = scanner->needle(); + USE(tmp); + GetStack()->IteratePointers(scanner.get()); + EXPECT_TRUE(scanner->found()); + } +} + +namespace { + +void RecursivelyPassOnParameter(int* volatile p1, int* volatile p2, + int* volatile p3, int* volatile p4, + int* volatile p5, int* volatile p6, + int* volatile p7, int* volatile p8, + Stack* stack, StackVisitor* visitor) { + if (p1) { + RecursivelyPassOnParameter(nullptr, p1, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, stack, visitor); + } else if (p2) { + RecursivelyPassOnParameter(nullptr, nullptr, p2, nullptr, nullptr, nullptr, + nullptr, nullptr, stack, visitor); + } else if (p3) { + RecursivelyPassOnParameter(nullptr, nullptr, nullptr, p3, nullptr, nullptr, + nullptr, nullptr, stack, visitor); + } else if (p4) { + RecursivelyPassOnParameter(nullptr, nullptr, nullptr, nullptr, p4, nullptr, + nullptr, nullptr, stack, visitor); + } else if (p5) { + RecursivelyPassOnParameter(nullptr, nullptr, nullptr, nullptr, nullptr, p5, + nullptr, nullptr, stack, visitor); + } else if (p6) { + RecursivelyPassOnParameter(nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, p6, nullptr, stack, visitor); + } else if (p7) { + RecursivelyPassOnParameter(nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, p7, stack, visitor); + } else if (p8) { + stack->IteratePointers(visitor); + } +} + +} // namespace + +TEST_F(GCStackTest, IteratePointersFindsParameter) { + auto scanner = std::make_unique<StackScanner>(); + // No check that the needle is initially not found as on some platforms it + // may be part of the redzone or temporaries after setting it up throuhg + // StackScanner. + RecursivelyPassOnParameter(nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, scanner->needle(), GetStack(), + scanner.get()); + EXPECT_TRUE(scanner->found()); +} + +TEST_F(GCStackTest, IteratePointersFindsParameterInNestedFunction) { + auto scanner = std::make_unique<StackScanner>(); + // No check that the needle is initially not found as on some platforms it + // may be part of the redzone or temporaries after setting it up throuhg + // StackScanner. + RecursivelyPassOnParameter(scanner->needle(), nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, GetStack(), + scanner.get()); + EXPECT_TRUE(scanner->found()); +} + +// The following test uses inline assembly and has been checked to work on clang +// to verify that the stack-scanning trampoline pushes callee-saved registers. +// +// The test uses a macro loop as asm() can only be passed string literals. +#ifdef __clang__ +#ifdef V8_TARGET_ARCH_X64 +#ifdef V8_OS_WIN + +// Excluded from test: rbp +#define FOR_ALL_CALLEE_SAVED_REGS(V) \ + V("rdi") \ + V("rsi") \ + V("rbx") \ + V("r12") \ + V("r13") \ + V("r14") \ + V("r15") + +#else // !V8_OS_WIN + +// Excluded from test: rbp +#define FOR_ALL_CALLEE_SAVED_REGS(V) \ + V("rbx") \ + V("r12") \ + V("r13") \ + V("r14") \ + V("r15") + +#endif // !V8_OS_WIN +#endif // V8_TARGET_ARCH_X64 +#endif // __clang__ + +#ifdef FOR_ALL_CALLEE_SAVED_REGS + +TEST_F(GCStackTest, IteratePointersFindsCalleeSavedRegisters) { + auto scanner = std::make_unique<StackScanner>(); + + // No check that the needle is initially not found as on some platforms it + // may be part of the redzone or temporaries after setting it up throuhg + // StackScanner. + +// First, clear all callee-saved registers. +#define CLEAR_REGISTER(reg) asm("mov $0, %%" reg : : : reg); + + FOR_ALL_CALLEE_SAVED_REGS(CLEAR_REGISTER) +#undef CLEAR_REGISTER + + // Keep local raw pointers to keep instruction sequences small below. + auto* local_stack = GetStack(); + auto* local_scanner = scanner.get(); + +// Moves |local_scanner->needle()| into a callee-saved register, leaving the +// callee-saved register as the only register referencing the needle. +// (Ignoring implementation-dependent dirty registers/stack.) +#define KEEP_ALIVE_FROM_CALLEE_SAVED(reg) \ + local_scanner->Reset(); \ + /* This moves the temporary into the calee-saved register. */ \ + asm("mov %0, %%" reg : : "r"(local_scanner->needle()) : reg); \ + /* Register is unprotected from here till the actual invocation. */ \ + local_stack->IteratePointers(local_scanner); \ + EXPECT_TRUE(local_scanner->found()) \ + << "pointer in callee-saved register not found. register: " << reg \ + << std::endl; \ + /* Clear out the register again */ \ + asm("mov $0, %%" reg : : : reg); + + FOR_ALL_CALLEE_SAVED_REGS(KEEP_ALIVE_FROM_CALLEE_SAVED) +#undef KEEP_ALIVE_FROM_CALLEE_SAVED +#undef FOR_ALL_CALLEE_SAVED_REGS +} +#endif // FOR_ALL_CALLEE_SAVED_REGS + +#if V8_OS_LINUX && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64) +class CheckStackAlignmentVisitor final : public StackVisitor { + public: + void VisitPointer(const void*) final { + float f[4] = {0.}; + volatile auto xmm = ::_mm_load_ps(f); + USE(xmm); + } +}; + +TEST_F(GCStackTest, StackAlignment) { + auto checker = std::make_unique<CheckStackAlignmentVisitor>(); + GetStack()->IteratePointers(checker.get()); +} +#endif // V8_OS_LINUX && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64) + +#endif // CPPGC_SUPPORTS_CONSERVATIVE_STACK_SCAN + +} // namespace internal +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/tests.cc b/deps/v8/test/unittests/heap/cppgc/tests.cc new file mode 100644 index 0000000000..e67ac730d6 --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/tests.cc @@ -0,0 +1,36 @@ +// Copyright 2020 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/heap/cppgc/tests.h" + +namespace cppgc { +namespace testing { + +// static +std::unique_ptr<cppgc::PageAllocator> TestWithPlatform::page_allocator_; + +// static +void TestWithPlatform::SetUpTestSuite() { + page_allocator_.reset(new v8::base::PageAllocator()); + cppgc::InitializePlatform(page_allocator_.get()); +} + +// static +void TestWithPlatform::TearDownTestSuite() { + cppgc::ShutdownPlatform(); + page_allocator_.reset(); +} + +void TestWithHeap::SetUp() { + heap_ = Heap::Create(); + TestWithPlatform::SetUp(); +} + +void TestWithHeap::TearDown() { + heap_.reset(); + TestWithPlatform::TearDown(); +} + +} // namespace testing +} // namespace cppgc diff --git a/deps/v8/test/unittests/heap/cppgc/tests.h b/deps/v8/test/unittests/heap/cppgc/tests.h new file mode 100644 index 0000000000..d21f256444 --- /dev/null +++ b/deps/v8/test/unittests/heap/cppgc/tests.h @@ -0,0 +1,39 @@ +// Copyright 2020 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_UNITTESTS_HEAP_CPPGC_TESTS_H_ +#define V8_UNITTESTS_HEAP_CPPGC_TESTS_H_ + +#include "include/cppgc/heap.h" +#include "include/cppgc/platform.h" +#include "src/base/page-allocator.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace cppgc { +namespace testing { + +class TestWithPlatform : public ::testing::Test { + protected: + static void SetUpTestSuite(); + static void TearDownTestSuite(); + + private: + static std::unique_ptr<cppgc::PageAllocator> page_allocator_; +}; + +class TestWithHeap : public TestWithPlatform { + protected: + void SetUp() override; + void TearDown() override; + + Heap* GetHeap() const { return heap_.get(); } + + private: + std::unique_ptr<cppgc::Heap> heap_; +}; + +} // namespace testing +} // namespace cppgc + +#endif // V8_UNITTESTS_HEAP_CPPGC_TESTS_H_ diff --git a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc index b3901d74b0..c46ee35095 100644 --- a/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc +++ b/deps/v8/test/unittests/heap/gc-idle-time-handler-unittest.cc @@ -30,7 +30,6 @@ class GCIdleTimeHandlerTest : public ::testing::Test { static const size_t kSizeOfObjects = 100 * MB; static const size_t kMarkCompactSpeed = 200 * KB; - static const size_t kMarkingSpeed = 200 * KB; private: GCIdleTimeHandler handler_; @@ -74,20 +73,6 @@ TEST(GCIdleTimeHandler, EstimateMarkingStepSizeOverflow2) { } -TEST_F(GCIdleTimeHandlerTest, ShouldDoFinalIncrementalMarkCompact) { - size_t idle_time_ms = 16; - EXPECT_TRUE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( - idle_time_ms, 0, 0)); -} - - -TEST_F(GCIdleTimeHandlerTest, DontDoFinalIncrementalMarkCompact) { - size_t idle_time_ms = 1; - EXPECT_FALSE(GCIdleTimeHandler::ShouldDoFinalIncrementalMarkCompact( - idle_time_ms, kSizeOfObjects, kMarkingSpeed)); -} - - TEST_F(GCIdleTimeHandlerTest, ContextDisposeLowRate) { if (!handler()->Enabled()) return; GCIdleTimeHeapState heap_state = DefaultHeapState(); diff --git a/deps/v8/test/unittests/heap/local-heap-unittest.cc b/deps/v8/test/unittests/heap/local-heap-unittest.cc new file mode 100644 index 0000000000..bf6aad6efc --- /dev/null +++ b/deps/v8/test/unittests/heap/local-heap-unittest.cc @@ -0,0 +1,38 @@ +// Copyright 2020 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/local-heap.h" +#include "src/heap/heap.h" +#include "src/heap/safepoint.h" +#include "test/unittests/test-utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace v8 { +namespace internal { + +using LocalHeapTest = TestWithIsolate; + +TEST_F(LocalHeapTest, Initialize) { + Heap* heap = i_isolate()->heap(); + + { + LocalHeap lh1(heap); + CHECK(heap->safepoint()->ContainsLocalHeap(&lh1)); + LocalHeap lh2(heap); + CHECK(heap->safepoint()->ContainsLocalHeap(&lh2)); + + { + LocalHeap lh3(heap); + CHECK(heap->safepoint()->ContainsLocalHeap(&lh3)); + } + + CHECK(heap->safepoint()->ContainsLocalHeap(&lh1)); + CHECK(heap->safepoint()->ContainsLocalHeap(&lh2)); + } + + CHECK(!heap->safepoint()->ContainsAnyLocalHeap()); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/heap/off-thread-factory-unittest.cc b/deps/v8/test/unittests/heap/off-thread-factory-unittest.cc index 2c7bd639a8..0592d7b2db 100644 --- a/deps/v8/test/unittests/heap/off-thread-factory-unittest.cc +++ b/deps/v8/test/unittests/heap/off-thread-factory-unittest.cc @@ -8,65 +8,139 @@ #include <memory> #include "src/ast/ast-value-factory.h" +#include "src/ast/ast.h" +#include "src/ast/scopes.h" +#include "src/common/assert-scope.h" +#include "src/common/globals.h" +#include "src/execution/off-thread-isolate.h" #include "src/handles/handles-inl.h" #include "src/handles/handles.h" -#include "src/heap/off-thread-factory.h" +#include "src/heap/off-thread-factory-inl.h" #include "src/objects/fixed-array.h" +#include "src/objects/script.h" +#include "src/objects/shared-function-info.h" #include "src/objects/string.h" +#include "src/parsing/parse-info.h" +#include "src/parsing/parser.h" +#include "src/parsing/rewriter.h" +#include "src/parsing/scanner-character-streams.h" +#include "src/parsing/scanner.h" +#include "src/strings/unicode-inl.h" +#include "src/utils/utils.h" #include "test/unittests/test-utils.h" namespace v8 { namespace internal { +class OffThreadIsolate; + +namespace { + +std::vector<uint16_t> DecodeUtf8(const std::string& string) { + if (string.empty()) return {}; + + auto utf8_data = + Vector<const uint8_t>::cast(VectorOf(string.data(), string.length())); + Utf8Decoder decoder(utf8_data); + + std::vector<uint16_t> utf16(decoder.utf16_length()); + decoder.Decode(&utf16[0], utf8_data); + + return utf16; +} + +} // namespace + class OffThreadFactoryTest : public TestWithIsolateAndZone { public: OffThreadFactoryTest() - : TestWithIsolateAndZone(), off_thread_factory_(isolate()) {} + : TestWithIsolateAndZone(), + parse_info_(isolate()), + off_thread_isolate_(isolate(), parse_info_.zone()) {} + + FunctionLiteral* ParseProgram(const char* source) { + auto utf16_source = DecodeUtf8(source); - OffThreadFactory* off_thread_factory() { return &off_thread_factory_; } + // Normally this would be an external string or whatever, we don't have to + // worry about it for now. + source_string_ = + factory()->NewStringFromUtf8(CStrVector(source)).ToHandleChecked(); + + parse_info_.set_character_stream( + ScannerStream::ForTesting(utf16_source.data(), utf16_source.size())); + parse_info_.set_toplevel(); + parse_info_.set_allow_lazy_parsing(); + + { + DisallowHeapAllocation no_allocation; + DisallowHandleAllocation no_handles; + DisallowHeapAccess no_heap_access; + + Parser parser(parse_info()); + parser.InitializeEmptyScopeChain(parse_info()); + parser.ParseOnBackground(parse_info()); + + CHECK(DeclarationScope::Analyze(parse_info())); + } + + parse_info()->ast_value_factory()->Internalize(off_thread_isolate()); + DeclarationScope::AllocateScopeInfos(parse_info(), off_thread_isolate()); + + script_ = parse_info_.CreateScript(off_thread_isolate(), + off_thread_factory()->empty_string(), + ScriptOriginOptions()); + + // Create the SFI list on the script so that SFI SetScript works. + Handle<WeakFixedArray> infos = off_thread_factory()->NewWeakFixedArray( + parse_info()->max_function_literal_id() + 1, AllocationType::kOld); + script_->set_shared_function_infos(*infos); + + return parse_info()->literal(); + } + + ParseInfo* parse_info() { return &parse_info_; } + + Handle<Script> script() { return script_; } + + OffThreadIsolate* off_thread_isolate() { return &off_thread_isolate_; } + OffThreadFactory* off_thread_factory() { + return off_thread_isolate()->factory(); + } // We only internalize strings which are referred to in other slots, so create // a wrapper pointing at the off_thread_string. - OffThreadHandle<FixedArray> WrapString(OffThreadHandle<String> string) { + Handle<FixedArray> WrapString(Handle<String> string) { // TODO(leszeks): Replace with a different factory method (e.g. FixedArray) // once OffThreadFactory supports it. return off_thread_factory()->StringWrapperForTest(string); } private: - OffThreadFactory off_thread_factory_; + ParseInfo parse_info_; + OffThreadIsolate off_thread_isolate_; + Handle<String> source_string_; + Handle<Script> script_; }; -TEST_F(OffThreadFactoryTest, HandleOrOffThreadHandle_IsNullWhenConstructed) { - // Default constructed HandleOrOffThreadHandles should be considered both null - // and uninitialized. - EXPECT_TRUE(HandleOrOffThreadHandle<HeapObject>().is_null()); -#ifdef DEBUG - EXPECT_TRUE(!HandleOrOffThreadHandle<HeapObject>().is_initialized()); -#endif - - // Default constructed HandleOrOffThreadHandles should work as both null - // handles and null off-thread handles. - EXPECT_TRUE(HandleOrOffThreadHandle<HeapObject>().get<Factory>().is_null()); - EXPECT_TRUE( - HandleOrOffThreadHandle<HeapObject>().get<OffThreadFactory>().is_null()); -} - TEST_F(OffThreadFactoryTest, OneByteInternalizedString_IsAddedToStringTable) { Vector<const uint8_t> string_vector = StaticCharVector("foo"); uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( string_vector.begin(), string_vector.length(), HashSeed(isolate())); - OffThreadHandle<String> off_thread_string = - off_thread_factory()->NewOneByteInternalizedString(string_vector, - hash_field); + FixedArray off_thread_wrapper; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); - OffThreadHandle<FixedArray> off_thread_wrapper = - off_thread_factory()->StringWrapperForTest(off_thread_string); + Handle<String> off_thread_string = + off_thread_factory()->NewOneByteInternalizedString(string_vector, + hash_field); - off_thread_factory()->FinishOffThread(); + off_thread_wrapper = + *off_thread_factory()->StringWrapperForTest(off_thread_string); + off_thread_factory()->FinishOffThread(); + } - Handle<FixedArray> wrapper = handle(*off_thread_wrapper, isolate()); + Handle<FixedArray> wrapper = handle(off_thread_wrapper, isolate()); off_thread_factory()->Publish(isolate()); Handle<String> string = handle(String::cast(wrapper->get(0)), isolate()); @@ -92,22 +166,25 @@ TEST_F(OffThreadFactoryTest, uint32_t hash_field = StringHasher::HashSequentialString<uint8_t>( string_vector.begin(), string_vector.length(), HashSeed(isolate())); - OffThreadHandle<String> off_thread_string_1 = - off_thread_factory()->NewOneByteInternalizedString(string_vector, - hash_field); - OffThreadHandle<String> off_thread_string_2 = - off_thread_factory()->NewOneByteInternalizedString(string_vector, - hash_field); - - OffThreadHandle<FixedArray> off_thread_wrapper_1 = - WrapString(off_thread_string_1); - OffThreadHandle<FixedArray> off_thread_wrapper_2 = - WrapString(off_thread_string_2); - - off_thread_factory()->FinishOffThread(); + FixedArray off_thread_wrapper_1; + FixedArray off_thread_wrapper_2; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); + + Handle<String> off_thread_string_1 = + off_thread_factory()->NewOneByteInternalizedString(string_vector, + hash_field); + Handle<String> off_thread_string_2 = + off_thread_factory()->NewOneByteInternalizedString(string_vector, + hash_field); + + off_thread_wrapper_1 = *WrapString(off_thread_string_1); + off_thread_wrapper_2 = *WrapString(off_thread_string_2); + off_thread_factory()->FinishOffThread(); + } - Handle<FixedArray> wrapper_1 = handle(*off_thread_wrapper_1, isolate()); - Handle<FixedArray> wrapper_2 = handle(*off_thread_wrapper_2, isolate()); + Handle<FixedArray> wrapper_1 = handle(off_thread_wrapper_1, isolate()); + Handle<FixedArray> wrapper_2 = handle(off_thread_wrapper_2, isolate()); off_thread_factory()->Publish(isolate()); Handle<String> string_1 = handle(String::cast(wrapper_1->get(0)), isolate()); @@ -124,14 +201,17 @@ TEST_F(OffThreadFactoryTest, AstRawString_IsInternalized) { const AstRawString* raw_string = ast_value_factory.GetOneByteString("foo"); - ast_value_factory.Internalize(off_thread_factory()); + FixedArray off_thread_wrapper; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); - OffThreadHandle<FixedArray> off_thread_wrapper = - WrapString(raw_string->string().get<OffThreadFactory>()); + ast_value_factory.Internalize(off_thread_isolate()); - off_thread_factory()->FinishOffThread(); + off_thread_wrapper = *WrapString(raw_string->string()); + off_thread_factory()->FinishOffThread(); + } - Handle<FixedArray> wrapper = handle(*off_thread_wrapper, isolate()); + Handle<FixedArray> wrapper = handle(off_thread_wrapper, isolate()); off_thread_factory()->Publish(isolate()); Handle<String> string = handle(String::cast(wrapper->get(0)), isolate()); @@ -144,20 +224,24 @@ TEST_F(OffThreadFactoryTest, AstConsString_CreatesConsString) { AstValueFactory ast_value_factory(zone(), isolate()->ast_string_constants(), HashSeed(isolate())); - const AstRawString* foo_string = ast_value_factory.GetOneByteString("foo"); - const AstRawString* bar_string = - ast_value_factory.GetOneByteString("bar-plus-padding-for-length"); - const AstConsString* foobar_string = - ast_value_factory.NewConsString(foo_string, bar_string); + FixedArray off_thread_wrapper; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); - ast_value_factory.Internalize(off_thread_factory()); + const AstRawString* foo_string = ast_value_factory.GetOneByteString("foo"); + const AstRawString* bar_string = + ast_value_factory.GetOneByteString("bar-plus-padding-for-length"); + AstConsString* foobar_string = + ast_value_factory.NewConsString(foo_string, bar_string); - OffThreadHandle<FixedArray> off_thread_wrapper = - WrapString(foobar_string->string().get<OffThreadFactory>()); + ast_value_factory.Internalize(off_thread_isolate()); - off_thread_factory()->FinishOffThread(); + off_thread_wrapper = + *WrapString(foobar_string->GetString(off_thread_isolate())); + off_thread_factory()->FinishOffThread(); + } - Handle<FixedArray> wrapper = handle(*off_thread_wrapper, isolate()); + Handle<FixedArray> wrapper = handle(off_thread_wrapper, isolate()); off_thread_factory()->Publish(isolate()); Handle<String> string = handle(String::cast(wrapper->get(0)), isolate()); @@ -167,5 +251,111 @@ TEST_F(OffThreadFactoryTest, AstConsString_CreatesConsString) { "foobar-plus-padding-for-length"))); } +TEST_F(OffThreadFactoryTest, EmptyScript) { + FunctionLiteral* program = ParseProgram(""); + + SharedFunctionInfo shared; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); + + shared = *off_thread_factory()->NewSharedFunctionInfoForLiteral( + program, script(), true); + + off_thread_factory()->FinishOffThread(); + } + + Handle<SharedFunctionInfo> root_sfi = handle(shared, isolate()); + off_thread_factory()->Publish(isolate()); + + EXPECT_EQ(root_sfi->function_literal_id(), 0); +} + +TEST_F(OffThreadFactoryTest, LazyFunction) { + FunctionLiteral* program = ParseProgram("function lazy() {}"); + FunctionLiteral* lazy = program->scope() + ->declarations() + ->AtForTest(0) + ->AsFunctionDeclaration() + ->fun(); + + SharedFunctionInfo shared; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); + + shared = *off_thread_factory()->NewSharedFunctionInfoForLiteral( + lazy, script(), true); + + off_thread_factory()->FinishOffThread(); + } + + Handle<SharedFunctionInfo> lazy_sfi = handle(shared, isolate()); + off_thread_factory()->Publish(isolate()); + + EXPECT_EQ(lazy_sfi->function_literal_id(), 1); + EXPECT_TRUE(lazy_sfi->Name().IsOneByteEqualTo(CStrVector("lazy"))); + EXPECT_FALSE(lazy_sfi->is_compiled()); + EXPECT_TRUE(lazy_sfi->HasUncompiledDataWithoutPreparseData()); +} + +TEST_F(OffThreadFactoryTest, EagerFunction) { + FunctionLiteral* program = ParseProgram("(function eager() {})"); + FunctionLiteral* eager = program->body() + ->at(0) + ->AsExpressionStatement() + ->expression() + ->AsFunctionLiteral(); + + SharedFunctionInfo shared; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); + + shared = *off_thread_factory()->NewSharedFunctionInfoForLiteral( + eager, script(), true); + + off_thread_factory()->FinishOffThread(); + } + + Handle<SharedFunctionInfo> eager_sfi = handle(shared, isolate()); + off_thread_factory()->Publish(isolate()); + + EXPECT_EQ(eager_sfi->function_literal_id(), 1); + EXPECT_TRUE(eager_sfi->Name().IsOneByteEqualTo(CStrVector("eager"))); + EXPECT_FALSE(eager_sfi->HasUncompiledData()); + // TODO(leszeks): Allocate bytecode and enable these checks. + // EXPECT_TRUE(eager_sfi->is_compiled()); + // EXPECT_TRUE(eager_sfi->HasBytecodeArray()); +} + +TEST_F(OffThreadFactoryTest, ImplicitNameFunction) { + FunctionLiteral* program = ParseProgram("let implicit_name = function() {}"); + FunctionLiteral* implicit_name = program->body() + ->at(0) + ->AsBlock() + ->statements() + ->at(0) + ->AsExpressionStatement() + ->expression() + ->AsAssignment() + ->value() + ->AsFunctionLiteral(); + + SharedFunctionInfo shared; + { + OffThreadHandleScope handle_scope(off_thread_isolate()); + + shared = *off_thread_factory()->NewSharedFunctionInfoForLiteral( + implicit_name, script(), true); + + off_thread_factory()->FinishOffThread(); + } + + Handle<SharedFunctionInfo> implicit_name_sfi = handle(shared, isolate()); + off_thread_factory()->Publish(isolate()); + + EXPECT_EQ(implicit_name_sfi->function_literal_id(), 1); + EXPECT_TRUE( + implicit_name_sfi->Name().IsOneByteEqualTo(CStrVector("implicit_name"))); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/test/unittests/heap/safepoint-unittest.cc b/deps/v8/test/unittests/heap/safepoint-unittest.cc new file mode 100644 index 0000000000..462992f5fd --- /dev/null +++ b/deps/v8/test/unittests/heap/safepoint-unittest.cc @@ -0,0 +1,139 @@ +// Copyright 2020 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/safepoint.h" +#include "src/base/platform/mutex.h" +#include "src/base/platform/platform.h" +#include "src/heap/heap.h" +#include "src/heap/local-heap.h" +#include "test/unittests/test-utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace v8 { +namespace internal { + +using SafepointTest = TestWithIsolate; + +TEST_F(SafepointTest, ReachSafepointWithoutLocalHeaps) { + Heap* heap = i_isolate()->heap(); + bool run = false; + { + SafepointScope scope(heap); + run = true; + } + CHECK(run); +} + +class ParkedThread final : public v8::base::Thread { + public: + ParkedThread(Heap* heap, base::Mutex* mutex) + : v8::base::Thread(base::Thread::Options("ThreadWithLocalHeap")), + heap_(heap), + mutex_(mutex) {} + + void Run() override { + LocalHeap local_heap(heap_); + + if (mutex_) { + ParkedScope scope(&local_heap); + base::MutexGuard guard(mutex_); + } + } + + Heap* heap_; + base::Mutex* mutex_; +}; + +TEST_F(SafepointTest, StopParkedThreads) { + Heap* heap = i_isolate()->heap(); + + int safepoints = 0; + + const int kThreads = 10; + const int kRuns = 5; + + for (int run = 0; run < kRuns; run++) { + base::Mutex mutex; + std::vector<ParkedThread*> threads; + + mutex.Lock(); + + for (int i = 0; i < kThreads; i++) { + ParkedThread* thread = + new ParkedThread(heap, i % 2 == 0 ? &mutex : nullptr); + CHECK(thread->Start()); + threads.push_back(thread); + } + + { + SafepointScope scope(heap); + safepoints++; + } + mutex.Unlock(); + + for (ParkedThread* thread : threads) { + thread->Join(); + delete thread; + } + } + + CHECK_EQ(safepoints, kRuns); +} + +static const int kRuns = 10000; + +class RunningThread final : public v8::base::Thread { + public: + RunningThread(Heap* heap, std::atomic<int>* counter) + : v8::base::Thread(base::Thread::Options("ThreadWithLocalHeap")), + heap_(heap), + counter_(counter) {} + + void Run() override { + LocalHeap local_heap(heap_); + + for (int i = 0; i < kRuns; i++) { + counter_->fetch_add(1); + if (i % 100 == 0) local_heap.Safepoint(); + } + } + + Heap* heap_; + std::atomic<int>* counter_; +}; + +TEST_F(SafepointTest, StopRunningThreads) { + Heap* heap = i_isolate()->heap(); + + const int kThreads = 10; + const int kRuns = 5; + const int kSafepoints = 3; + int safepoint_count = 0; + + for (int run = 0; run < kRuns; run++) { + std::atomic<int> counter(0); + std::vector<RunningThread*> threads; + + for (int i = 0; i < kThreads; i++) { + RunningThread* thread = new RunningThread(heap, &counter); + CHECK(thread->Start()); + threads.push_back(thread); + } + + for (int i = 0; i < kSafepoints; i++) { + SafepointScope scope(heap); + safepoint_count++; + } + + for (RunningThread* thread : threads) { + thread->Join(); + delete thread; + } + } + + CHECK_EQ(safepoint_count, kRuns * kSafepoints); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/unittests/heap/scavenge-job-unittest.cc b/deps/v8/test/unittests/heap/scavenge-job-unittest.cc deleted file mode 100644 index 36d089f03b..0000000000 --- a/deps/v8/test/unittests/heap/scavenge-job-unittest.cc +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2014 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 <limits> - -#include "src/common/globals.h" -#include "src/heap/scavenge-job.h" -#include "src/utils/utils.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace v8 { -namespace internal { - -const size_t kScavengeSpeedInBytesPerMs = 500 * KB; -const size_t kNewSpaceCapacity = 8 * MB; - - -TEST(ScavengeJob, AllocationLimitEmptyNewSpace) { - EXPECT_FALSE(ScavengeJob::ReachedIdleAllocationLimit( - kScavengeSpeedInBytesPerMs, 0, kNewSpaceCapacity)); -} - - -TEST(ScavengeJob, AllocationLimitFullNewSpace) { - EXPECT_TRUE(ScavengeJob::ReachedIdleAllocationLimit( - kScavengeSpeedInBytesPerMs, kNewSpaceCapacity, kNewSpaceCapacity)); -} - - -TEST(ScavengeJob, AllocationLimitUnknownScavengeSpeed) { - size_t expected_size = ScavengeJob::kInitialScavengeSpeedInBytesPerMs * - ScavengeJob::kAverageIdleTimeMs - - ScavengeJob::kBytesAllocatedBeforeNextIdleTask; - expected_size = Max(expected_size, ScavengeJob::kMinAllocationLimit); - - EXPECT_FALSE(ScavengeJob::ReachedIdleAllocationLimit(0, expected_size - 1, - kNewSpaceCapacity)); - EXPECT_TRUE(ScavengeJob::ReachedIdleAllocationLimit(0, expected_size, - kNewSpaceCapacity)); -} - - -TEST(ScavengeJob, AllocationLimitLowScavengeSpeed) { - size_t scavenge_speed = 1 * KB; - EXPECT_FALSE(ScavengeJob::ReachedIdleAllocationLimit( - scavenge_speed, ScavengeJob::kMinAllocationLimit - 1, kNewSpaceCapacity)); - EXPECT_TRUE(ScavengeJob::ReachedIdleAllocationLimit( - scavenge_speed, ScavengeJob::kMinAllocationLimit, kNewSpaceCapacity)); -} - - -TEST(ScavengeJob, AllocationLimitAverageScavengeSpeed) { - size_t expected_size = - kScavengeSpeedInBytesPerMs * ScavengeJob::kAverageIdleTimeMs - - ScavengeJob::kBytesAllocatedBeforeNextIdleTask; - EXPECT_FALSE(ScavengeJob::ReachedIdleAllocationLimit( - kScavengeSpeedInBytesPerMs, ScavengeJob::kMinAllocationLimit, - kNewSpaceCapacity)); - EXPECT_FALSE(ScavengeJob::ReachedIdleAllocationLimit( - kScavengeSpeedInBytesPerMs, expected_size - 1, kNewSpaceCapacity)); - EXPECT_TRUE(ScavengeJob::ReachedIdleAllocationLimit( - kScavengeSpeedInBytesPerMs, expected_size, kNewSpaceCapacity)); -} - - -TEST(ScavengeJob, AllocationLimitHighScavengeSpeed) { - size_t scavenge_speed = kNewSpaceCapacity; - size_t expected_size = - static_cast<size_t>( - kNewSpaceCapacity * - ScavengeJob::kMaxAllocationLimitAsFractionOfNewSpace) - - ScavengeJob::kBytesAllocatedBeforeNextIdleTask; - EXPECT_FALSE(ScavengeJob::ReachedIdleAllocationLimit( - scavenge_speed, expected_size - 1, kNewSpaceCapacity)); - EXPECT_TRUE(ScavengeJob::ReachedIdleAllocationLimit( - scavenge_speed, expected_size + 1, kNewSpaceCapacity)); -} - - -TEST(ScavengeJob, EnoughIdleTimeForScavengeUnknownScavengeSpeed) { - size_t scavenge_speed = ScavengeJob::kInitialScavengeSpeedInBytesPerMs; - size_t new_space_size = 1 * MB; - size_t expected_time = (new_space_size + scavenge_speed - 1) / scavenge_speed; - EXPECT_TRUE( - ScavengeJob::EnoughIdleTimeForScavenge(expected_time, 0, new_space_size)); - EXPECT_FALSE(ScavengeJob::EnoughIdleTimeForScavenge(expected_time - 1, 0, - new_space_size)); -} - - -TEST(ScavengeJob, EnoughIdleTimeForScavengeLowScavengeSpeed) { - size_t scavenge_speed = 1 * KB; - size_t new_space_size = 1 * MB; - size_t expected_time = (new_space_size + scavenge_speed - 1) / scavenge_speed; - EXPECT_TRUE(ScavengeJob::EnoughIdleTimeForScavenge( - expected_time, scavenge_speed, new_space_size)); - EXPECT_FALSE(ScavengeJob::EnoughIdleTimeForScavenge( - expected_time - 1, scavenge_speed, new_space_size)); -} - - -TEST(ScavengeJob, EnoughIdleTimeForScavengeHighScavengeSpeed) { - size_t scavenge_speed = kNewSpaceCapacity; - size_t new_space_size = 1 * MB; - size_t expected_time = (new_space_size + scavenge_speed - 1) / scavenge_speed; - EXPECT_TRUE(ScavengeJob::EnoughIdleTimeForScavenge( - expected_time, scavenge_speed, new_space_size)); - EXPECT_FALSE(ScavengeJob::EnoughIdleTimeForScavenge( - expected_time - 1, scavenge_speed, new_space_size)); -} - -} // namespace internal -} // namespace v8 diff --git a/deps/v8/test/unittests/heap/worklist-unittest.cc b/deps/v8/test/unittests/heap/worklist-unittest.cc index b7e1231424..a12dcb0cee 100644 --- a/deps/v8/test/unittests/heap/worklist-unittest.cc +++ b/deps/v8/test/unittests/heap/worklist-unittest.cc @@ -148,13 +148,16 @@ TEST(WorkListTest, LocalPushStaysPrivate) { SomeObject dummy; SomeObject* retrieved = nullptr; EXPECT_TRUE(worklist.IsEmpty()); + EXPECT_EQ(0U, worklist.GlobalPoolSize()); EXPECT_TRUE(worklist_view1.Push(&dummy)); EXPECT_FALSE(worklist.IsEmpty()); + EXPECT_EQ(0U, worklist.GlobalPoolSize()); EXPECT_FALSE(worklist_view2.Pop(&retrieved)); EXPECT_EQ(nullptr, retrieved); EXPECT_TRUE(worklist_view1.Pop(&retrieved)); EXPECT_EQ(&dummy, retrieved); EXPECT_TRUE(worklist.IsEmpty()); + EXPECT_EQ(0U, worklist.GlobalPoolSize()); } TEST(WorkListTest, GlobalUpdateNull) { @@ -168,6 +171,7 @@ TEST(WorkListTest, GlobalUpdateNull) { EXPECT_TRUE(worklist_view.Push(object)); worklist.Update([](SomeObject* object, SomeObject** out) { return false; }); EXPECT_TRUE(worklist.IsEmpty()); + EXPECT_EQ(0U, worklist.GlobalPoolSize()); } TEST(WorkListTest, GlobalUpdate) { @@ -209,6 +213,7 @@ TEST(WorkListTest, FlushToGlobalPushSegment) { objectA = reinterpret_cast<SomeObject*>(&objectA); EXPECT_TRUE(worklist_view0.Push(objectA)); worklist.FlushToGlobal(0); + EXPECT_EQ(1U, worklist.GlobalPoolSize()); EXPECT_TRUE(worklist_view1.Pop(&object)); } @@ -223,6 +228,7 @@ TEST(WorkListTest, FlushToGlobalPopSegment) { EXPECT_TRUE(worklist_view0.Push(objectA)); EXPECT_TRUE(worklist_view0.Pop(&object)); worklist.FlushToGlobal(0); + EXPECT_EQ(1U, worklist.GlobalPoolSize()); EXPECT_TRUE(worklist_view1.Pop(&object)); } @@ -235,8 +241,10 @@ TEST(WorkListTest, Clear) { EXPECT_TRUE(worklist_view.Push(object)); } EXPECT_TRUE(worklist_view.Push(object)); + EXPECT_EQ(1U, worklist.GlobalPoolSize()); worklist.Clear(); EXPECT_TRUE(worklist.IsEmpty()); + EXPECT_EQ(0U, worklist.GlobalPoolSize()); } TEST(WorkListTest, SingleSegmentSteal) { @@ -252,6 +260,7 @@ TEST(WorkListTest, SingleSegmentSteal) { EXPECT_TRUE(worklist_view1.Push(nullptr)); EXPECT_TRUE(worklist_view1.Pop(&retrieved)); EXPECT_EQ(nullptr, retrieved); + EXPECT_EQ(1U, worklist.GlobalPoolSize()); // Stealing. for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { EXPECT_TRUE(worklist_view2.Pop(&retrieved)); @@ -259,6 +268,7 @@ TEST(WorkListTest, SingleSegmentSteal) { EXPECT_FALSE(worklist_view1.Pop(&retrieved)); } EXPECT_TRUE(worklist.IsEmpty()); + EXPECT_EQ(0U, worklist.GlobalPoolSize()); } TEST(WorkListTest, MultipleSegmentsStolen) { @@ -280,11 +290,13 @@ TEST(WorkListTest, MultipleSegmentsStolen) { EXPECT_TRUE(worklist_view1.Push(&dummy3)); EXPECT_TRUE(worklist_view1.Pop(&retrieved)); EXPECT_EQ(&dummy3, retrieved); + EXPECT_EQ(2U, worklist.GlobalPoolSize()); // Stealing. EXPECT_TRUE(worklist_view2.Pop(&retrieved)); SomeObject* const expect_bag2 = retrieved; EXPECT_TRUE(worklist_view3.Pop(&retrieved)); SomeObject* const expect_bag3 = retrieved; + EXPECT_EQ(0U, worklist.GlobalPoolSize()); EXPECT_NE(expect_bag2, expect_bag3); EXPECT_TRUE(expect_bag2 == &dummy1 || expect_bag2 == &dummy2); EXPECT_TRUE(expect_bag3 == &dummy1 || expect_bag3 == &dummy2); @@ -313,10 +325,13 @@ TEST(WorkListTest, MergeGlobalPool) { EXPECT_TRUE(worklist_view1.Push(nullptr)); EXPECT_TRUE(worklist_view1.Pop(&retrieved)); EXPECT_EQ(nullptr, retrieved); + EXPECT_EQ(1U, worklist1.GlobalPoolSize()); // Merging global pool into a new Worklist. TestWorklist worklist2; TestWorklist::View worklist_view2(&worklist2, 0); + EXPECT_EQ(0U, worklist2.GlobalPoolSize()); worklist2.MergeGlobalPool(&worklist1); + EXPECT_EQ(1U, worklist2.GlobalPoolSize()); EXPECT_FALSE(worklist2.IsEmpty()); for (size_t i = 0; i < TestWorklist::kSegmentCapacity; i++) { EXPECT_TRUE(worklist_view2.Pop(&retrieved)); 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 7591a30f6b..cc7ca63061 100644 --- a/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc +++ b/deps/v8/test/unittests/interpreter/bytecode-array-builder-unittest.cc @@ -79,8 +79,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { .StoreAccumulatorInRegister(wide); // Emit Ldar and Star taking care to foil the register optimizer. - builder.StackCheck(0) - .LoadAccumulatorWithRegister(other) + builder.LoadAccumulatorWithRegister(other) .BinaryOperation(Token::ADD, reg, 1) .StoreAccumulatorInRegister(reg) .LoadNull(); @@ -312,7 +311,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { .Bind(&after_jump10) .JumpIfFalse(ToBooleanMode::kAlreadyBoolean, &after_jump11) .Bind(&after_jump11) - .JumpLoop(&loop_header, 0) + .JumpLoop(&loop_header, 0, 0) .Bind(&after_loop); } @@ -343,9 +342,6 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { // Emit set pending message bytecode. builder.SetPendingMessage(); - // Emit stack check bytecode. - builder.StackCheck(0); - // Emit throw and re-throw in it's own basic block so that the rest of the // code isn't omitted due to being dead. BytecodeLabel after_throw, after_rethrow; @@ -447,7 +443,7 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { // Generate BytecodeArray. scope.SetScriptScopeInfo(factory->NewScopeInfo(1)); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> the_array = builder.ToBytecodeArray(isolate()); CHECK_EQ(the_array->frame_size(), builder.total_register_count() * kSystemPointerSize); @@ -535,7 +531,11 @@ TEST_F(BytecodeArrayBuilderTest, Parameters) { Register receiver(builder.Receiver()); Register param8(builder.Parameter(8)); +#ifdef V8_REVERSE_JSARGS + CHECK_EQ(receiver.index() - param8.index(), 9); +#else CHECK_EQ(param8.index() - receiver.index(), 9); +#endif } TEST_F(BytecodeArrayBuilderTest, Constants) { @@ -560,7 +560,7 @@ TEST_F(BytecodeArrayBuilderTest, Constants) { .LoadLiteral(nan) .Return(); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> array = builder.ToBytecodeArray(isolate()); // Should only have one entry for each identical constant. EXPECT_EQ(4, array->constant_pool().length()); @@ -706,12 +706,14 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { BytecodeLoopHeader loop_header; builder.JumpIfNull(&after_loop) .Bind(&loop_header) - .JumpLoop(&loop_header, 0) + .JumpLoop(&loop_header, 0, 0) .Bind(&after_loop); for (int i = 0; i < 42; i++) { BytecodeLabel after_loop; // Conditional jump to force the code after the JumpLoop to be live. - builder.JumpIfNull(&after_loop).JumpLoop(&loop_header, 0).Bind(&after_loop); + builder.JumpIfNull(&after_loop) + .JumpLoop(&loop_header, 0, 0) + .Bind(&after_loop); } // Add padding to force wide backwards jumps. @@ -719,7 +721,7 @@ TEST_F(BytecodeArrayBuilderTest, BackwardJumps) { builder.Debugger(); } - builder.JumpLoop(&loop_header, 0); + builder.JumpLoop(&loop_header, 0, 0); builder.Bind(&end); builder.Return(); 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 23f0d08c1c..5772b802c0 100644 --- a/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc +++ b/deps/v8/test/unittests/interpreter/bytecode-array-iterator-unittest.cc @@ -53,10 +53,8 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -73,7 +71,7 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { .Return(); // Test iterator sees the expected output from the builder. - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); BytecodeArrayIterator iterator(builder.ToBytecodeArray(isolate())); const int kPrefixByteSize = 1; int offset = 0; @@ -138,14 +136,6 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle); iterator.Advance(); - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck); - EXPECT_EQ(iterator.current_offset(), offset); - EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); - EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0); - CHECK(!iterator.done()); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); - iterator.Advance(); - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); @@ -164,14 +154,6 @@ TEST_F(BytecodeArrayIteratorTest, IteratesBytecodeArray) { kPrefixByteSize; iterator.Advance(); - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck); - EXPECT_EQ(iterator.current_offset(), offset); - EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); - EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0); - CHECK(!iterator.done()); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); - iterator.Advance(); - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); 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 9553058d8d..ecdf6757fb 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 @@ -49,10 +49,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidBeforeStart) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -66,7 +64,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidBeforeStart) { .Debugger() .Return(); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate()); BytecodeArrayRandomIterator iterator(bytecodeArray, zone()); @@ -103,10 +101,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidAfterEnd) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -120,7 +116,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, InvalidAfterEnd) { .Debugger() .Return(); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate()); BytecodeArrayRandomIterator iterator(bytecodeArray, zone()); @@ -157,10 +153,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesFirst) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -174,7 +168,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesFirst) { .Debugger() .Return(); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate()); BytecodeArrayRandomIterator iterator(bytecodeArray, zone()); @@ -216,10 +210,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesLast) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -233,7 +225,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesLast) { .Debugger() .Return(); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate()); BytecodeArrayRandomIterator iterator(bytecodeArray, zone()); @@ -242,7 +234,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, AccessesLast) { int offset = bytecodeArray->length() - Bytecodes::Size(Bytecode::kReturn, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn); - EXPECT_EQ(iterator.current_index(), 22); + EXPECT_EQ(iterator.current_index(), 20); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); ASSERT_TRUE(iterator.IsValid()); @@ -276,10 +268,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -294,13 +284,13 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { .Return(); // Test iterator sees the expected output from the builder. - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); BytecodeArrayRandomIterator iterator(builder.ToBytecodeArray(isolate()), zone()); const int kPrefixByteSize = 1; int offset = 0; - iterator.GoToIndex(13); + iterator.GoToIndex(11); offset = Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle); @@ -308,16 +298,14 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) + kPrefixByteSize; - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd); - EXPECT_EQ(iterator.current_index(), 13); + EXPECT_EQ(iterator.current_index(), 11); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -336,7 +324,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { heap_num_1); ASSERT_TRUE(iterator.IsValid()); - iterator.GoToIndex(18); + iterator.GoToIndex(16); offset = Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle); @@ -344,11 +332,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) + kPrefixByteSize; - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle); @@ -358,7 +344,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair); - EXPECT_EQ(iterator.current_index(), 18); + EXPECT_EQ(iterator.current_index(), 16); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall); @@ -375,7 +361,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset -= Bytecodes::Size(Bytecode::kLdaNamedProperty, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty); - EXPECT_EQ(iterator.current_index(), 15); + EXPECT_EQ(iterator.current_index(), 13); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -388,14 +374,14 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 17); + EXPECT_EQ(iterator.current_index(), 15); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), param.index()); EXPECT_EQ(iterator.GetRegisterOperandRange(0), 1); ASSERT_TRUE(iterator.IsValid()); - iterator.GoToIndex(22); + iterator.GoToIndex(20); offset = Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaConstant, OperandScale::kSingle); @@ -403,11 +389,9 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset += Bytecodes::Size(Bytecode::kLdaZero, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) + kPrefixByteSize; - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle); offset += Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle); @@ -422,12 +406,12 @@ TEST_F(BytecodeArrayRandomIteratorTest, RandomAccessValid) { offset += Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn); - EXPECT_EQ(iterator.current_index(), 22); + EXPECT_EQ(iterator.current_index(), 20); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); ASSERT_TRUE(iterator.IsValid()); - iterator.GoToIndex(24); + iterator.GoToIndex(22); EXPECT_FALSE(iterator.IsValid()); iterator.GoToIndex(-5); @@ -462,10 +446,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -480,7 +462,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { .Return(); // Test iterator sees the expected output from the builder. - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); BytecodeArrayRandomIterator iterator(builder.ToBytecodeArray(isolate()), zone()); const int kPrefixByteSize = 1; @@ -553,17 +535,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { offset += Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle); ++iterator; - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck); - EXPECT_EQ(iterator.current_index(), 7); - EXPECT_EQ(iterator.current_offset(), offset); - EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); - EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0); - ASSERT_TRUE(iterator.IsValid()); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); - ++iterator; - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 8); + EXPECT_EQ(iterator.current_index(), 7); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -573,7 +546,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi); - EXPECT_EQ(iterator.current_index(), 9); + EXPECT_EQ(iterator.current_index(), 8); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple); EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1); @@ -582,17 +555,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { kPrefixByteSize; ++iterator; - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck); - EXPECT_EQ(iterator.current_index(), 10); - EXPECT_EQ(iterator.current_offset(), offset); - EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); - EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0); - ASSERT_TRUE(iterator.IsValid()); - offset += Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); - ++iterator; - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 11); + EXPECT_EQ(iterator.current_index(), 9); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -602,7 +566,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdar); - EXPECT_EQ(iterator.current_index(), 12); + EXPECT_EQ(iterator.current_index(), 10); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -611,7 +575,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd); - EXPECT_EQ(iterator.current_index(), 13); + EXPECT_EQ(iterator.current_index(), 11); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -621,7 +585,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 14); + EXPECT_EQ(iterator.current_index(), 12); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -631,7 +595,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty); - EXPECT_EQ(iterator.current_index(), 15); + EXPECT_EQ(iterator.current_index(), 13); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -642,7 +606,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd); - EXPECT_EQ(iterator.current_index(), 16); + EXPECT_EQ(iterator.current_index(), 14); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -652,7 +616,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 17); + EXPECT_EQ(iterator.current_index(), 15); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), param.index()); @@ -662,7 +626,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair); - EXPECT_EQ(iterator.current_index(), 18); + EXPECT_EQ(iterator.current_index(), 16); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall); @@ -677,7 +641,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare); - EXPECT_EQ(iterator.current_index(), 19); + EXPECT_EQ(iterator.current_index(), 17); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -688,7 +652,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime); - EXPECT_EQ(iterator.current_index(), 20); + EXPECT_EQ(iterator.current_index(), 18); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss); @@ -699,7 +663,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kDebugger); - EXPECT_EQ(iterator.current_index(), 21); + EXPECT_EQ(iterator.current_index(), 19); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); ASSERT_TRUE(iterator.IsValid()); @@ -707,7 +671,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArray) { ++iterator; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn); - EXPECT_EQ(iterator.current_index(), 22); + EXPECT_EQ(iterator.current_index(), 20); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); ASSERT_TRUE(iterator.IsValid()); @@ -743,10 +707,8 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { .LoadLiteral(zero) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_0) - .StackCheck(0) .StoreAccumulatorInRegister(reg_0) .LoadLiteral(smi_1) - .StackCheck(1) .StoreAccumulatorInRegister(reg_1) .LoadAccumulatorWithRegister(reg_0) .BinaryOperation(Token::Value::ADD, reg_0, 2) @@ -761,7 +723,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { .Return(); // Test iterator sees the expected output from the builder. - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<BytecodeArray> bytecodeArray = builder.ToBytecodeArray(isolate()); BytecodeArrayRandomIterator iterator(bytecodeArray, zone()); const int kPrefixByteSize = 1; @@ -771,7 +733,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kReturn, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kReturn); - EXPECT_EQ(iterator.current_index(), 22); + EXPECT_EQ(iterator.current_index(), 20); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); ASSERT_TRUE(iterator.IsValid()); @@ -779,7 +741,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kDebugger, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kDebugger); - EXPECT_EQ(iterator.current_index(), 21); + EXPECT_EQ(iterator.current_index(), 19); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); ASSERT_TRUE(iterator.IsValid()); @@ -787,7 +749,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kCallRuntime, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntime); - EXPECT_EQ(iterator.current_index(), 20); + EXPECT_EQ(iterator.current_index(), 18); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadIC_Miss); @@ -798,7 +760,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kForInPrepare, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kForInPrepare); - EXPECT_EQ(iterator.current_index(), 19); + EXPECT_EQ(iterator.current_index(), 17); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -810,7 +772,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kCallRuntimeForPair, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kCallRuntimeForPair); - EXPECT_EQ(iterator.current_index(), 18); + EXPECT_EQ(iterator.current_index(), 16); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRuntimeIdOperand(0), Runtime::kLoadLookupSlotForCall); @@ -824,7 +786,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 17); + EXPECT_EQ(iterator.current_index(), 15); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), param.index()); @@ -834,7 +796,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd); - EXPECT_EQ(iterator.current_index(), 16); + EXPECT_EQ(iterator.current_index(), 14); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -844,7 +806,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kLdaNamedProperty, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaNamedProperty); - EXPECT_EQ(iterator.current_index(), 15); + EXPECT_EQ(iterator.current_index(), 13); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -855,7 +817,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 14); + EXPECT_EQ(iterator.current_index(), 12); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -865,7 +827,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kAdd, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kAdd); - EXPECT_EQ(iterator.current_index(), 13); + EXPECT_EQ(iterator.current_index(), 11); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -875,7 +837,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kLdar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdar); - EXPECT_EQ(iterator.current_index(), 12); + EXPECT_EQ(iterator.current_index(), 10); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -884,7 +846,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 11); + EXPECT_EQ(iterator.current_index(), 9); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_1.index()); @@ -892,19 +854,10 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { ASSERT_TRUE(iterator.IsValid()); --iterator; - offset -= Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck); - EXPECT_EQ(iterator.current_index(), 10); - EXPECT_EQ(iterator.current_offset(), offset); - EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); - EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0); - ASSERT_TRUE(iterator.IsValid()); - --iterator; - offset -= Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kQuadruple) + kPrefixByteSize; EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi); - EXPECT_EQ(iterator.current_index(), 9); + EXPECT_EQ(iterator.current_index(), 8); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kQuadruple); EXPECT_EQ(Smi::FromInt(iterator.GetImmediateOperand(0)), smi_1); @@ -913,7 +866,7 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { offset -= Bytecodes::Size(Bytecode::kStar, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStar); - EXPECT_EQ(iterator.current_index(), 8); + EXPECT_EQ(iterator.current_index(), 7); EXPECT_EQ(iterator.current_offset(), offset); EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); EXPECT_EQ(iterator.GetRegisterOperand(0).index(), reg_0.index()); @@ -921,15 +874,6 @@ TEST_F(BytecodeArrayRandomIteratorTest, IteratesBytecodeArrayBackwards) { ASSERT_TRUE(iterator.IsValid()); --iterator; - offset -= Bytecodes::Size(Bytecode::kStackCheck, OperandScale::kSingle); - EXPECT_EQ(iterator.current_bytecode(), Bytecode::kStackCheck); - EXPECT_EQ(iterator.current_index(), 7); - EXPECT_EQ(iterator.current_offset(), offset); - EXPECT_EQ(iterator.current_operand_scale(), OperandScale::kSingle); - EXPECT_EQ(Bytecodes::NumberOfOperands(iterator.current_bytecode()), 0); - ASSERT_TRUE(iterator.IsValid()); - --iterator; - offset -= Bytecodes::Size(Bytecode::kLdaSmi, OperandScale::kSingle); EXPECT_EQ(iterator.current_bytecode(), Bytecode::kLdaSmi); EXPECT_EQ(iterator.current_index(), 6); diff --git a/deps/v8/test/unittests/interpreter/bytecode-array-writer-unittest.cc b/deps/v8/test/unittests/interpreter/bytecode-array-writer-unittest.cc index 339fc33178..0bf431eaae 100644 --- a/deps/v8/test/unittests/interpreter/bytecode-array-writer-unittest.cc +++ b/deps/v8/test/unittests/interpreter/bytecode-array-writer-unittest.cc @@ -115,28 +115,24 @@ void BytecodeArrayWriterUnittest::WriteJumpLoop(Bytecode bytecode, TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { CHECK_EQ(bytecodes()->size(), 0u); - Write(Bytecode::kStackCheck, {10, false}); - CHECK_EQ(bytecodes()->size(), 1u); - Write(Bytecode::kLdaSmi, 127, {55, true}); - CHECK_EQ(bytecodes()->size(), 3u); + CHECK_EQ(bytecodes()->size(), 2u); Write(Bytecode::kStar, Register(20).ToOperand()); - CHECK_EQ(bytecodes()->size(), 5u); + CHECK_EQ(bytecodes()->size(), 4u); Write(Bytecode::kLdar, Register(200).ToOperand()); - CHECK_EQ(bytecodes()->size(), 9u); + CHECK_EQ(bytecodes()->size(), 8u); Write(Bytecode::kReturn, {70, true}); - CHECK_EQ(bytecodes()->size(), 10u); + CHECK_EQ(bytecodes()->size(), 9u); static const uint8_t expected_bytes[] = { // clang-format off - /* 0 10 E> */ B(StackCheck), - /* 1 55 S> */ B(LdaSmi), U8(127), - /* 3 */ B(Star), R8(20), - /* 5 */ B(Wide), B(Ldar), R16(200), - /* 9 70 S> */ B(Return), + /* 0 55 S> */ B(LdaSmi), U8(127), + /* 2 */ B(Star), R8(20), + /* 4 */ B(Wide), B(Ldar), R16(200), + /* 8 70 S> */ B(Return), // clang-format on }; CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes)); @@ -150,8 +146,7 @@ TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { *writer()->ToSourcePositionTable(isolate())); CHECK_EQ(bytecodes()->size(), arraysize(expected_bytes)); - PositionTableEntry expected_positions[] = { - {0, 10, false}, {1, 55, true}, {9, 70, true}}; + PositionTableEntry expected_positions[] = {{0, 55, true}, {8, 70, true}}; SourcePositionTableIterator source_iterator( bytecode_array->SourcePositionTable()); for (size_t i = 0; i < arraysize(expected_positions); ++i) { @@ -168,40 +163,37 @@ TEST_F(BytecodeArrayWriterUnittest, SimpleExample) { TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { static const uint8_t expected_bytes[] = { // clang-format off - /* 0 30 E> */ B(StackCheck), - /* 1 42 S> */ B(LdaConstant), U8(0), - /* 3 42 E> */ B(Add), R8(1), U8(1), - /* 5 68 S> */ B(JumpIfUndefined), U8(39), - /* 7 */ B(JumpIfNull), U8(37), - /* 9 */ B(ToObject), R8(3), - /* 11 */ B(ForInPrepare), R8(3), U8(4), - /* 14 */ B(LdaZero), - /* 15 */ B(Star), R8(7), - /* 17 63 S> */ B(ForInContinue), R8(7), R8(6), - /* 20 */ B(JumpIfFalse), U8(24), - /* 22 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1), - /* 27 */ B(JumpIfUndefined), U8(10), - /* 29 */ B(Star), R8(0), - /* 31 54 E> */ B(StackCheck), - /* 32 */ B(Ldar), R8(0), - /* 34 */ B(Star), R8(2), - /* 36 85 S> */ B(Return), - /* 37 */ B(ForInStep), R8(7), - /* 39 */ B(Star), R8(7), - /* 41 */ B(JumpLoop), U8(24), U8(0), - /* 44 */ B(LdaUndefined), - /* 45 85 S> */ B(Return), + /* 0 42 S> */ B(LdaConstant), U8(0), + /* 2 42 E> */ B(Add), R8(1), U8(1), + /* 4 68 S> */ B(JumpIfUndefined), U8(38), + /* 6 */ B(JumpIfNull), U8(36), + /* 8 */ B(ToObject), R8(3), + /* 10 */ B(ForInPrepare), R8(3), U8(4), + /* 13 */ B(LdaZero), + /* 14 */ B(Star), R8(7), + /* 16 63 S> */ B(ForInContinue), R8(7), R8(6), + /* 19 */ B(JumpIfFalse), U8(23), + /* 21 */ B(ForInNext), R8(3), R8(7), R8(4), U8(1), + /* 26 */ B(JumpIfUndefined), U8(9), + /* 28 */ B(Star), R8(0), + /* 30 */ B(Ldar), R8(0), + /* 32 */ B(Star), R8(2), + /* 34 85 S> */ B(Return), + /* 35 */ B(ForInStep), R8(7), + /* 37 */ B(Star), R8(7), + /* 39 */ B(JumpLoop), U8(23), U8(0), + /* 42 */ B(LdaUndefined), + /* 43 85 S> */ B(Return), // clang-format on }; static const PositionTableEntry expected_positions[] = { - {0, 30, false}, {1, 42, true}, {3, 42, false}, {6, 68, true}, - {18, 63, true}, {32, 54, false}, {37, 85, true}, {46, 85, true}}; + {0, 42, true}, {2, 42, false}, {5, 68, true}, + {17, 63, true}, {35, 85, true}, {44, 85, true}}; BytecodeLoopHeader loop_header; BytecodeLabel jump_for_in, jump_end_1, jump_end_2, jump_end_3; - Write(Bytecode::kStackCheck, {30, false}); Write(Bytecode::kLdaConstant, U8(0), {42, true}); Write(Bytecode::kAdd, R(1), U8(1), {42, false}); WriteJump(Bytecode::kJumpIfUndefined, &jump_end_1, {68, true}); @@ -216,7 +208,6 @@ TEST_F(BytecodeArrayWriterUnittest, ComplexExample) { Write(Bytecode::kForInNext, R(3), R(7), R(4), U8(1)); WriteJump(Bytecode::kJumpIfUndefined, &jump_for_in); Write(Bytecode::kStar, R(0)); - Write(Bytecode::kStackCheck, {54, false}); Write(Bytecode::kLdar, R(0)); Write(Bytecode::kStar, R(2)); Write(Bytecode::kReturn, {85, true}); @@ -258,23 +249,18 @@ TEST_F(BytecodeArrayWriterUnittest, ElideNoneffectfulBytecodes) { static const uint8_t expected_bytes[] = { // clang-format off - /* 0 10 E> */ B(StackCheck), - /* 1 55 S> */ B(Ldar), R8(20), - /* 3 */ B(Star), R8(20), - /* 5 */ B(CreateMappedArguments), - /* 6 60 S> */ B(LdaSmi), U8(127), - /* 8 70 S> */ B(Ldar), R8(20), - /* 10 75 S> */ B(Return), + /* 0 55 S> */ B(Ldar), R8(20), + /* 2 */ B(Star), R8(20), + /* 4 */ B(CreateMappedArguments), + /* 5 60 S> */ B(LdaSmi), U8(127), + /* 7 70 S> */ B(Ldar), R8(20), + /* 9 75 S> */ B(Return), // clang-format on }; - static const PositionTableEntry expected_positions[] = {{0, 10, false}, - {1, 55, true}, - {6, 60, false}, - {8, 70, true}, - {10, 75, true}}; + static const PositionTableEntry expected_positions[] = { + {0, 55, true}, {5, 60, false}, {7, 70, true}, {9, 75, true}}; - Write(Bytecode::kStackCheck, {10, false}); Write(Bytecode::kLdaSmi, 127, {55, true}); // Should be elided. Write(Bytecode::kLdar, Register(20).ToOperand()); Write(Bytecode::kStar, Register(20).ToOperand()); @@ -310,27 +296,25 @@ TEST_F(BytecodeArrayWriterUnittest, ElideNoneffectfulBytecodes) { TEST_F(BytecodeArrayWriterUnittest, DeadcodeElimination) { static const uint8_t expected_bytes[] = { // clang-format off - /* 0 10 E> */ B(StackCheck), - /* 1 55 S> */ B(LdaSmi), U8(127), - /* 3 */ B(Jump), U8(2), - /* 5 65 S> */ B(LdaSmi), U8(127), - /* 7 */ B(JumpIfFalse), U8(3), - /* 9 75 S> */ B(Return), - /* 10 */ B(JumpIfFalse), U8(3), - /* 12 */ B(Throw), - /* 13 */ B(JumpIfFalse), U8(3), - /* 15 */ B(ReThrow), - /* 16 */ B(Return), + /* 0 55 S> */ B(LdaSmi), U8(127), + /* 2 */ B(Jump), U8(2), + /* 4 65 S> */ B(LdaSmi), U8(127), + /* 6 */ B(JumpIfFalse), U8(3), + /* 8 75 S> */ B(Return), + /* 9 */ B(JumpIfFalse), U8(3), + /* 11 */ B(Throw), + /* 12 */ B(JumpIfFalse), U8(3), + /* 14 */ B(ReThrow), + /* 15 */ B(Return), // clang-format on }; static const PositionTableEntry expected_positions[] = { - {0, 10, false}, {1, 55, true}, {5, 65, true}, {9, 75, true}}; + {0, 55, true}, {4, 65, true}, {8, 75, true}}; BytecodeLabel after_jump, after_conditional_jump, after_return, after_throw, after_rethrow; - Write(Bytecode::kStackCheck, {10, false}); Write(Bytecode::kLdaSmi, 127, {55, true}); WriteJump(Bytecode::kJump, &after_jump); Write(Bytecode::kLdaSmi, 127); // Dead code. 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 680479754a..bfe83b03ca 100644 --- a/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc +++ b/deps/v8/test/unittests/interpreter/constant-array-builder-unittest.cc @@ -40,7 +40,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateAllEntries) { builder.Insert(i + 0.5); } CHECK_EQ(builder.size(), k16BitCapacity); - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); for (size_t i = 0; i < k16BitCapacity; i++) { CHECK_EQ( Handle<HeapNumber>::cast(builder.At(i, isolate()).ToHandleChecked()) @@ -90,7 +90,7 @@ TEST_F(ConstantArrayBuilderTest, ToLargeFixedArrayWithReservations) { for (int i = 0; i < kNumberOfElements; i++) { builder.CommitReservedEntry(builder.CreateReservedEntry(), Smi::FromInt(i)); } - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<FixedArray> constant_array = builder.ToFixedArray(isolate()); ASSERT_EQ(kNumberOfElements, constant_array->length()); for (int i = 0; i < kNumberOfElements; i++) { @@ -149,7 +149,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithIdx8Reservations) { builder.DiscardReservedEntry(OperandSize::kByte); } - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<FixedArray> constant_array = builder.ToFixedArray(isolate()); CHECK_EQ(constant_array->length(), static_cast<int>(2 * k8BitCapacity + reserved)); @@ -203,7 +203,7 @@ TEST_F(ConstantArrayBuilderTest, AllocateEntriesWithWideReservations) { CHECK_EQ(builder.size(), i + 1); } - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<FixedArray> constant_array = builder.ToFixedArray(isolate()); CHECK_EQ(constant_array->length(), static_cast<int>(k8BitCapacity + reserved)); @@ -234,7 +234,7 @@ TEST_F(ConstantArrayBuilderTest, GapFilledWhenLowReservationCommitted) { Smi::FromInt(static_cast<int>(i))); CHECK_EQ(builder.size(), 2 * k8BitCapacity); } - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); 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++) { @@ -300,7 +300,7 @@ TEST_F(ConstantArrayBuilderTest, HolesWithUnusedReservations) { builder.DiscardReservedEntry(OperandSize::kByte); } - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<FixedArray> constant_array = builder.ToFixedArray(isolate()); CHECK_EQ(constant_array->length(), k8BitCapacity + 1); for (int i = kNumberOfHoles; i < k8BitCapacity; i++) { @@ -343,7 +343,7 @@ TEST_F(ConstantArrayBuilderTest, ReservationsAtAllScales) { builder.DiscardReservedEntry(OperandSize::kQuad); } - ast_factory.Internalize(isolate()->factory()); + ast_factory.Internalize(isolate()); Handle<FixedArray> constant_array = builder.ToFixedArray(isolate()); CHECK_EQ(constant_array->length(), 65537); int count = 1; diff --git a/deps/v8/test/unittests/objects/value-serializer-unittest.cc b/deps/v8/test/unittests/objects/value-serializer-unittest.cc index fac266d3f9..59d9b4df78 100644 --- a/deps/v8/test/unittests/objects/value-serializer-unittest.cc +++ b/deps/v8/test/unittests/objects/value-serializer-unittest.cc @@ -235,8 +235,7 @@ class ValueSerializerTest : public TestWithIsolate { } Local<String> StringFromUtf8(const char* source) { - return String::NewFromUtf8(isolate(), source, NewStringType::kNormal) - .ToLocalChecked(); + return String::NewFromUtf8(isolate(), source).ToLocalChecked(); } std::string Utf8Value(Local<Value> value) { @@ -2500,10 +2499,8 @@ class ValueSerializerTestWithWasm : public ValueSerializerTest { Maybe<uint32_t> GetWasmModuleTransferId( Isolate* isolate, Local<WasmModuleObject> module) override { isolate->ThrowException(Exception::Error( - String::NewFromOneByte( - isolate, - reinterpret_cast<const uint8_t*>(kUnsupportedSerialization), - NewStringType::kNormal) + String::NewFromOneByte(isolate, reinterpret_cast<const uint8_t*>( + kUnsupportedSerialization)) .ToLocalChecked())); return Nothing<uint32_t>(); } diff --git a/deps/v8/test/unittests/profiler/strings-storage-unittest.cc b/deps/v8/test/unittests/profiler/strings-storage-unittest.cc index 31225f46c2..087a7bf735 100644 --- a/deps/v8/test/unittests/profiler/strings-storage-unittest.cc +++ b/deps/v8/test/unittests/profiler/strings-storage-unittest.cc @@ -108,5 +108,54 @@ TEST_F(StringsStorageWithIsolate, FormatAndGetShareStorage) { CHECK_EQ(stored_str, formatted_str); } +TEST_F(StringsStorageWithIsolate, Refcounting) { + StringsStorage storage; + + const char* a = storage.GetCopy("12"); + CHECK_EQ(storage.GetStringCountForTesting(), 1); + + const char* b = storage.GetCopy("12"); + CHECK_EQ(storage.GetStringCountForTesting(), 1); + + // Ensure that we deduplicate the string. + CHECK_EQ(a, b); + + CHECK(storage.Release(a)); + CHECK_EQ(storage.GetStringCountForTesting(), 1); + CHECK(storage.Release(b)); + CHECK_EQ(storage.GetStringCountForTesting(), 0); +#if !DEBUG + CHECK(!storage.Release("12")); +#endif // !DEBUG + + // Verify that other constructors refcount as intended. + const char* c = storage.GetFormatted("%d", 12); + CHECK_EQ(storage.GetStringCountForTesting(), 1); + + const char* d = storage.GetName(12); + CHECK_EQ(storage.GetStringCountForTesting(), 1); + + CHECK_EQ(c, d); + + CHECK(storage.Release(c)); + CHECK_EQ(storage.GetStringCountForTesting(), 1); + CHECK(storage.Release(d)); + CHECK_EQ(storage.GetStringCountForTesting(), 0); +#if !DEBUG + CHECK(!storage.Release("12")); +#endif // !DEBUG +} + +TEST_F(StringsStorageWithIsolate, InvalidRelease) { + StringsStorage storage; + + // If a refcount becomes invalid, throw in debug builds. +#ifdef DEBUG + ASSERT_DEATH_IF_SUPPORTED(storage.Release("12"), "check failed"); +#else + CHECK(!storage.Release("12")); +#endif // DEBUG +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/test/unittests/test-utils.h b/deps/v8/test/unittests/test-utils.h index 3746ee267e..c2ffbf1561 100644 --- a/deps/v8/test/unittests/test-utils.h +++ b/deps/v8/test/unittests/test-utils.h @@ -181,9 +181,8 @@ class WithContextMixin : public TMixin { const Local<Context>& v8_context() const { return context_; } Local<Value> RunJS(const char* source) { - return RunJS(v8::String::NewFromUtf8(v8_isolate(), source, - v8::NewStringType::kNormal) - .ToLocalChecked()); + return RunJS( + v8::String::NewFromUtf8(v8_isolate(), source).ToLocalChecked()); } Local<Value> RunJS(v8::String::ExternalOneByteStringResource* source) { @@ -192,9 +191,7 @@ class WithContextMixin : public TMixin { } v8::Local<v8::String> NewString(const char* string) { - return v8::String::NewFromUtf8(v8_isolate(), string, - v8::NewStringType::kNormal) - .ToLocalChecked(); + return v8::String::NewFromUtf8(v8_isolate(), string).ToLocalChecked(); } void SetGlobalProperty(const char* name, v8::Local<v8::Value> value) { diff --git a/deps/v8/test/unittests/torque/torque-unittest.cc b/deps/v8/test/unittests/torque/torque-unittest.cc index 5180e301cc..778efc7641 100644 --- a/deps/v8/test/unittests/torque/torque-unittest.cc +++ b/deps/v8/test/unittests/torque/torque-unittest.cc @@ -25,6 +25,9 @@ namespace torque_internal { const object: HeapObject; const offset: intptr; } + type ConstReference<T : type> extends Reference<T>; + type MutableReference<T : type> extends ConstReference<T>; + type UninitializedHeapObject extends HeapObject; } @@ -42,6 +45,7 @@ extern class HeapObject extends StrongTagged { } type Map extends HeapObject generates 'TNode<Map>'; type Object = Smi | HeapObject; +type Number = Smi|HeapNumber; type JSReceiver extends HeapObject generates 'TNode<JSReceiver>'; type JSObject extends JSReceiver generates 'TNode<JSObject>'; type int32 generates 'TNode<Int32T>' constexpr 'int32_t'; @@ -70,12 +74,18 @@ type Code extends HeapObject generates 'TNode<Code>'; type BuiltinPtr extends Smi generates 'TNode<BuiltinPtr>'; type Context extends HeapObject generates 'TNode<Context>'; type NativeContext extends Context; +type SmiTagged<T : type extends uint31> extends Smi; +type String extends HeapObject; +type HeapNumber extends HeapObject; +type FixedArrayBase extends HeapObject; struct float64_or_hole { is_hole: bool; value: float64; } +extern operator '+' macro IntPtrAdd(intptr, intptr): intptr; + intrinsic %FromConstexpr<To: type, From: type>(b: From): To; intrinsic %RawDownCast<To: type, From: type>(x: From): To; intrinsic %RawConstexprCast<To: type, From: type>(f: From): To; @@ -84,6 +94,7 @@ extern macro TaggedToSmi(Object): Smi labels CastError; extern macro TaggedToHeapObject(Object): HeapObject labels CastError; +extern macro Float64SilenceNaN(float64): float64; extern macro IntPtrConstant(constexpr int31): intptr; @@ -97,6 +108,9 @@ FromConstexpr<Smi, constexpr int31>(s: constexpr int31): Smi { FromConstexpr<intptr, constexpr int31>(i: constexpr int31): intptr { return IntPtrConstant(i); } +FromConstexpr<intptr, constexpr intptr>(i: constexpr intptr): intptr { + return %FromConstexpr<intptr>(i); +} macro Cast<A : type extends Object>(implicit context: Context)(o: Object): A labels CastError { @@ -613,6 +627,134 @@ TEST(Torque, EnumInTypeswitch) { )"); } +TEST(Torque, ConstClassFields) { + ExpectSuccessfulCompilation(R"( + class Foo extends HeapObject { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + const _x: int32 = o.x; + o.y = n; + } + )"); + + ExpectFailingCompilation(R"( + class Foo extends HeapObject { + const x: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + o.x = n; + } + )", + HasSubstr("cannot assign to const value")); + + ExpectSuccessfulCompilation(R"( + class Foo extends HeapObject { + s: Bar; + } + struct Bar { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + const _x: int32 = o.s.x; + // Assigning a struct as a value is OK, even when the struct contains + // const fields. + o.s = Bar{x: n, y: n}; + o.s.y = n; + } + )"); + + ExpectFailingCompilation(R"( + class Foo extends HeapObject { + const s: Bar; + } + struct Bar { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + o.s.y = n; + } + )", + HasSubstr("cannot assign to const value")); + + ExpectFailingCompilation(R"( + class Foo extends HeapObject { + s: Bar; + } + struct Bar { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + o.s.x = n; + } + )", + HasSubstr("cannot assign to const value")); +} + +TEST(Torque, References) { + ExpectSuccessfulCompilation(R"( + class Foo extends HeapObject { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + const constRefX: const &int32 = &o.x; + const refY: &int32 = &o.y; + const constRefY: const &int32 = refY; + const _x: int32 = *constRefX; + const _y1: int32 = *refY; + const _y2: int32 = *constRefY; + *refY = n; + let r: const &int32 = constRefX; + r = constRefY; + } + )"); + + ExpectFailingCompilation(R"( + class Foo extends HeapObject { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo) { + const _refX: &int32 = &o.x; + } + )", + HasSubstr("cannot use expression of type const " + "&int32 as a value of type &int32")); + + ExpectFailingCompilation(R"( + class Foo extends HeapObject { + const x: int32; + y: int32; + } + + @export + macro Test(implicit context: Context)(o: Foo, n: int32) { + const constRefX: const &int32 = &o.x; + *constRefX = n; + } + )", + HasSubstr("cannot assign to const value")); +} + } // namespace torque } // namespace internal } // namespace v8 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 de3f825335..e242132a14 100644 --- a/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc +++ b/deps/v8/test/unittests/wasm/function-body-decoder-unittest.cc @@ -109,7 +109,7 @@ class FunctionBodyDecoderTest : public TestWithZone { // Prepends local variable declarations and renders nice error messages for // verification failures. template <typename Code = std::initializer_list<const byte>> - void Validate(bool expected_success, FunctionSig* sig, Code&& raw_code, + void Validate(bool expected_success, const FunctionSig* sig, Code&& raw_code, AppendEnd append_end = kAppendEnd, const char* message = nullptr) { Vector<const byte> code = @@ -136,20 +136,20 @@ class FunctionBodyDecoderTest : public TestWithZone { } template <typename Code = std::initializer_list<const byte>> - void ExpectValidates(FunctionSig* sig, Code&& raw_code, + void ExpectValidates(const FunctionSig* sig, Code&& raw_code, AppendEnd append_end = kAppendEnd, const char* message = nullptr) { Validate(true, sig, std::forward<Code>(raw_code), append_end, message); } template <typename Code = std::initializer_list<const byte>> - void ExpectFailure(FunctionSig* sig, Code&& raw_code, + void ExpectFailure(const FunctionSig* sig, Code&& raw_code, AppendEnd append_end = kAppendEnd, const char* message = nullptr) { Validate(false, sig, std::forward<Code>(raw_code), append_end, message); } - void TestBinop(WasmOpcode opcode, FunctionSig* success) { + void TestBinop(WasmOpcode opcode, const FunctionSig* success) { // op(local[0], local[1]) byte code[] = {WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; ExpectValidates(success, code); @@ -171,7 +171,7 @@ class FunctionBodyDecoderTest : public TestWithZone { } } - void TestUnop(WasmOpcode opcode, FunctionSig* success) { + void TestUnop(WasmOpcode opcode, const FunctionSig* success) { TestUnop(opcode, success->GetReturn(), success->GetParam(0)); } @@ -215,22 +215,23 @@ class TestModuleBuilder { CHECK_LE(mod.globals.size(), kMaxByteSizedLeb128); return static_cast<byte>(mod.globals.size() - 1); } - byte AddSignature(FunctionSig* sig) { + byte AddSignature(const FunctionSig* sig) { mod.signatures.push_back(sig); CHECK_LE(mod.signatures.size(), kMaxByteSizedLeb128); return static_cast<byte>(mod.signatures.size() - 1); } - byte AddFunction(FunctionSig* sig) { - mod.functions.push_back({sig, // sig - 0, // func_index - 0, // sig_index - {0, 0}, // code - false, // import - false}); // export + byte AddFunction(const FunctionSig* sig, bool declared = true) { + mod.functions.push_back({sig, // sig + 0, // func_index + 0, // sig_index + {0, 0}, // code + false, // import + false, // export + declared}); // declared CHECK_LE(mod.functions.size(), kMaxByteSizedLeb128); return static_cast<byte>(mod.functions.size() - 1); } - byte AddImport(FunctionSig* sig) { + byte AddImport(const FunctionSig* sig) { byte result = AddFunction(sig); mod.functions[result].imported = true; return result; @@ -259,11 +260,16 @@ class TestModuleBuilder { mod.maximum_pages = 100; } - void InitializeTable() { mod.tables.emplace_back(); } + byte InitializeTable(wasm::ValueType type) { + mod.tables.emplace_back(); + mod.tables.back().type = type; + return static_cast<byte>(mod.tables.size() - 1); + } - byte AddPassiveElementSegment() { - mod.elem_segments.emplace_back(); + byte AddPassiveElementSegment(wasm::ValueType type) { + mod.elem_segments.emplace_back(false); auto& init = mod.elem_segments.back(); + init.type = type; // Add 5 empty elements. for (uint32_t j = 0; j < 5; j++) { init.entries.push_back(WasmElemSegment::kNullIndex); @@ -271,6 +277,12 @@ class TestModuleBuilder { return static_cast<byte>(mod.elem_segments.size() - 1); } + byte AddDeclarativeElementSegment() { + mod.elem_segments.emplace_back(true); + mod.elem_segments.back().entries.push_back(WasmElemSegment::kNullIndex); + 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 @@ -387,10 +399,8 @@ TEST_F(FunctionBodyDecoderTest, TooManyLocals) { } TEST_F(FunctionBodyDecoderTest, GetLocal0_param_n) { - FunctionSig* array[] = {sigs.i_i(), sigs.i_ii(), sigs.i_iii()}; - - for (size_t i = 0; i < arraysize(array); i++) { - ExpectValidates(array[i], kCodeGetLocal0); + for (const FunctionSig* sig : {sigs.i_i(), sigs.i_ii(), sigs.i_iii()}) { + ExpectValidates(sig, kCodeGetLocal0); } } @@ -1350,14 +1360,14 @@ TEST_F(FunctionBodyDecoderTest, MacrosInt64) { TEST_F(FunctionBodyDecoderTest, AllSimpleExpressions) { WASM_FEATURE_SCOPE(anyref); // Test all simple expressions which are described by a signature. -#define DECODE_TEST(name, opcode, sig) \ - { \ - FunctionSig* sig = WasmOpcodes::Signature(kExpr##name); \ - if (sig->parameter_count() == 1) { \ - TestUnop(kExpr##name, sig); \ - } else { \ - TestBinop(kExpr##name, sig); \ - } \ +#define DECODE_TEST(name, opcode, sig) \ + { \ + const FunctionSig* sig = WasmOpcodes::Signature(kExpr##name); \ + if (sig->parameter_count() == 1) { \ + TestUnop(kExpr##name, sig); \ + } else { \ + TestBinop(kExpr##name, sig); \ + } \ } FOREACH_SIMPLE_OPCODE(DECODE_TEST); @@ -1475,7 +1485,7 @@ TEST_F(FunctionBodyDecoderTest, AllLoadMemCombinations) { MachineType mem_type = machineTypes[j]; byte code[] = {WASM_LOAD_MEM(mem_type, WASM_ZERO)}; FunctionSig sig(1, 0, &local_type); - Validate(local_type == ValueTypes::ValueTypeFor(mem_type), &sig, code); + Validate(local_type == ValueType::For(mem_type), &sig, code); } } } @@ -1490,13 +1500,13 @@ TEST_F(FunctionBodyDecoderTest, AllStoreMemCombinations) { MachineType mem_type = machineTypes[j]; byte code[] = {WASM_STORE_MEM(mem_type, WASM_ZERO, WASM_GET_LOCAL(0))}; FunctionSig sig(0, 1, &local_type); - Validate(local_type == ValueTypes::ValueTypeFor(mem_type), &sig, code); + Validate(local_type == ValueType::For(mem_type), &sig, code); } } } TEST_F(FunctionBodyDecoderTest, SimpleCalls) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1511,7 +1521,7 @@ TEST_F(FunctionBodyDecoderTest, SimpleCalls) { } TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1525,7 +1535,7 @@ TEST_F(FunctionBodyDecoderTest, CallsWithTooFewArguments) { } TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1537,7 +1547,7 @@ TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs2) { } TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs3) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1557,7 +1567,7 @@ TEST_F(FunctionBodyDecoderTest, CallsWithMismatchedSigs3) { TEST_F(FunctionBodyDecoderTest, SimpleReturnCalls) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1574,7 +1584,7 @@ TEST_F(FunctionBodyDecoderTest, SimpleReturnCalls) { TEST_F(FunctionBodyDecoderTest, ReturnCallsWithTooFewArguments) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1590,7 +1600,7 @@ TEST_F(FunctionBodyDecoderTest, ReturnCallsWithTooFewArguments) { TEST_F(FunctionBodyDecoderTest, ReturnCallsWithMismatchedSigs) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1609,7 +1619,7 @@ TEST_F(FunctionBodyDecoderTest, ReturnCallsWithMismatchedSigs) { TEST_F(FunctionBodyDecoderTest, SimpleIndirectReturnCalls) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; builder.AddTable(kWasmFuncRef, 20, true, 30); module = builder.module(); @@ -1628,7 +1638,7 @@ TEST_F(FunctionBodyDecoderTest, SimpleIndirectReturnCalls) { TEST_F(FunctionBodyDecoderTest, IndirectReturnCallsOutOfBounds) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; builder.AddTable(kWasmFuncRef, 20, false, 20); module = builder.module(); @@ -1650,9 +1660,9 @@ TEST_F(FunctionBodyDecoderTest, IndirectReturnCallsOutOfBounds) { TEST_F(FunctionBodyDecoderTest, IndirectReturnCallsWithMismatchedSigs3) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); byte sig0 = builder.AddSignature(sigs.i_f()); @@ -1681,7 +1691,7 @@ TEST_F(FunctionBodyDecoderTest, IndirectReturnCallsWithMismatchedSigs3) { TEST_F(FunctionBodyDecoderTest, IndirectReturnCallsWithoutTableCrash) { WASM_FEATURE_SCOPE(return_call); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1697,9 +1707,9 @@ TEST_F(FunctionBodyDecoderTest, IndirectReturnCallsWithoutTableCrash) { } TEST_F(FunctionBodyDecoderTest, IncompleteIndirectReturnCall) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); static byte code[] = {kExprReturnCallIndirect}; @@ -1739,8 +1749,8 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) { ExpectValidates(&sig_cd_v, {WASM_CALL_FUNCTION0(0)}); - if (ValueTypes::IsSubType(kValueTypes[c], kValueTypes[a]) && - ValueTypes::IsSubType(kValueTypes[d], kValueTypes[b])) { + if (kValueTypes[c].IsSubTypeOf(kValueTypes[a]) && + kValueTypes[d].IsSubTypeOf(kValueTypes[b])) { ExpectValidates(&sig_ab_v, {WASM_CALL_FUNCTION0(0)}); } else { ExpectFailure(&sig_ab_v, {WASM_CALL_FUNCTION0(0)}); @@ -1752,7 +1762,7 @@ TEST_F(FunctionBodyDecoderTest, MultiReturnType) { } TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; builder.AddTable(kWasmFuncRef, 20, false, 20); module = builder.module(); @@ -1768,7 +1778,7 @@ TEST_F(FunctionBodyDecoderTest, SimpleIndirectCalls) { } TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; builder.AddTable(kWasmFuncRef, 20, false, 20); module = builder.module(); @@ -1785,9 +1795,9 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsOutOfBounds) { } TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); byte sig0 = builder.AddSignature(sigs.i_f()); @@ -1808,7 +1818,7 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithMismatchedSigs3) { } TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1823,9 +1833,9 @@ TEST_F(FunctionBodyDecoderTest, IndirectCallsWithoutTableCrash) { } TEST_F(FunctionBodyDecoderTest, IncompleteIndirectCall) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); static byte code[] = {kExprCallIndirect}; @@ -1833,10 +1843,10 @@ TEST_F(FunctionBodyDecoderTest, IncompleteIndirectCall) { } TEST_F(FunctionBodyDecoderTest, IncompleteStore) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; builder.InitializeMemory(); - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); static byte code[] = {kExprI32StoreMem}; @@ -1845,10 +1855,10 @@ TEST_F(FunctionBodyDecoderTest, IncompleteStore) { TEST_F(FunctionBodyDecoderTest, IncompleteS8x16Shuffle) { WASM_FEATURE_SCOPE(simd); - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; builder.InitializeMemory(); - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); static byte code[] = {kSimdPrefix, @@ -1857,7 +1867,7 @@ TEST_F(FunctionBodyDecoderTest, IncompleteS8x16Shuffle) { } TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1872,7 +1882,7 @@ TEST_F(FunctionBodyDecoderTest, SimpleImportCalls) { } TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1892,7 +1902,7 @@ TEST_F(FunctionBodyDecoderTest, ImportCallsWithMismatchedSigs3) { } TEST_F(FunctionBodyDecoderTest, Int32Globals) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1904,7 +1914,7 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals) { } TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) { - FunctionSig* sig = sigs.v_v(); + const FunctionSig* sig = sigs.v_v(); TestModuleBuilder builder; module = builder.module(); @@ -1916,7 +1926,7 @@ TEST_F(FunctionBodyDecoderTest, ImmutableGlobal) { } TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) { - FunctionSig* sig = sigs.i_i(); + const FunctionSig* sig = sigs.i_i(); TestModuleBuilder builder; module = builder.module(); @@ -1937,7 +1947,7 @@ TEST_F(FunctionBodyDecoderTest, Int32Globals_fail) { } TEST_F(FunctionBodyDecoderTest, Int64Globals) { - FunctionSig* sig = sigs.l_l(); + const FunctionSig* sig = sigs.l_l(); TestModuleBuilder builder; module = builder.module(); @@ -1954,7 +1964,7 @@ TEST_F(FunctionBodyDecoderTest, Int64Globals) { } TEST_F(FunctionBodyDecoderTest, Float32Globals) { - FunctionSig* sig = sigs.f_ff(); + const FunctionSig* sig = sigs.f_ff(); TestModuleBuilder builder; module = builder.module(); @@ -1966,7 +1976,7 @@ TEST_F(FunctionBodyDecoderTest, Float32Globals) { } TEST_F(FunctionBodyDecoderTest, Float64Globals) { - FunctionSig* sig = sigs.d_dd(); + const FunctionSig* sig = sigs.d_dd(); TestModuleBuilder builder; module = builder.module(); @@ -1986,8 +1996,7 @@ TEST_F(FunctionBodyDecoderTest, AllGetGlobalCombinations) { TestModuleBuilder builder; module = builder.module(); builder.AddGlobal(global_type); - Validate(ValueTypes::IsSubType(global_type, local_type), &sig, - {WASM_GET_GLOBAL(0)}); + Validate(global_type.IsSubTypeOf(local_type), &sig, {WASM_GET_GLOBAL(0)}); } } } @@ -2001,7 +2010,7 @@ TEST_F(FunctionBodyDecoderTest, AllSetGlobalCombinations) { TestModuleBuilder builder; module = builder.module(); builder.AddGlobal(global_type); - Validate(ValueTypes::IsSubType(local_type, global_type), &sig, + Validate(local_type.IsSubTypeOf(global_type), &sig, {WASM_SET_GLOBAL(0, WASM_GET_LOCAL(0))}); } } @@ -2181,7 +2190,7 @@ TEST_F(FunctionBodyDecoderTest, AsmJsBinOpsCheckOrigin) { FunctionSig sig_d_id(1, 2, float64int32float64); struct { WasmOpcode op; - FunctionSig* sig; + const FunctionSig* sig; } AsmJsBinOps[] = { {kExprF64Atan2, sigs.d_dd()}, {kExprF64Pow, sigs.d_dd()}, @@ -2225,7 +2234,7 @@ TEST_F(FunctionBodyDecoderTest, AsmJsUnOpsCheckOrigin) { FunctionSig sig_d_i(1, 1, float64int32); struct { WasmOpcode op; - FunctionSig* sig; + const FunctionSig* sig; } AsmJsUnOps[] = {{kExprF64Acos, sigs.d_d()}, {kExprF64Asin, sigs.d_d()}, {kExprF64Atan, sigs.d_d()}, @@ -2367,9 +2376,8 @@ TEST_F(FunctionBodyDecoderTest, BreakNesting_6_levels) { } TEST_F(FunctionBodyDecoderTest, Break_TypeCheck) { - FunctionSig* sigarray[] = {sigs.i_i(), sigs.l_l(), sigs.f_ff(), sigs.d_dd()}; - for (size_t i = 0; i < arraysize(sigarray); i++) { - FunctionSig* sig = sigarray[i]; + for (const FunctionSig* sig : + {sigs.i_i(), sigs.l_l(), sigs.f_ff(), sigs.d_dd()}) { // unify X and X => OK byte code[] = {WASM_BLOCK_T( sig->GetReturn(), WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))), @@ -2398,8 +2406,7 @@ TEST_F(FunctionBodyDecoderTest, Break_TypeCheckAll1) { sig.GetReturn(), WASM_IF(WASM_ZERO, WASM_BRV(0, WASM_GET_LOCAL(0))), WASM_GET_LOCAL(1))}; - Validate(ValueTypes::IsSubType(kValueTypes[j], kValueTypes[i]), &sig, - code); + Validate(kValueTypes[j].IsSubTypeOf(kValueTypes[i]), &sig, code); } } } @@ -2413,8 +2420,7 @@ TEST_F(FunctionBodyDecoderTest, Break_TypeCheckAll2) { WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(0)), WASM_GET_LOCAL(1))}; - Validate(ValueTypes::IsSubType(kValueTypes[j], kValueTypes[i]), &sig, - code); + Validate(kValueTypes[j].IsSubTypeOf(kValueTypes[i]), &sig, code); } } } @@ -2428,8 +2434,7 @@ TEST_F(FunctionBodyDecoderTest, Break_TypeCheckAll3) { WASM_GET_LOCAL(1), WASM_BRV_IF_ZERO(0, WASM_GET_LOCAL(0)))}; - Validate(ValueTypes::IsSubType(kValueTypes[j], kValueTypes[i]), &sig, - code); + Validate(kValueTypes[j].IsSubTypeOf(kValueTypes[i]), &sig, code); } } } @@ -2473,8 +2478,7 @@ TEST_F(FunctionBodyDecoderTest, BreakIf_val_type) { types[1], WASM_BRV_IF(0, WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)), WASM_DROP, WASM_GET_LOCAL(0))}; - Validate(ValueTypes::IsSubType(kValueTypes[j], kValueTypes[i]), &sig, - code); + Validate(kValueTypes[j].IsSubTypeOf(kValueTypes[i]), &sig, code); } } } @@ -3203,8 +3207,8 @@ TEST_F(FunctionBodyDecoderTest, BulkMemoryOpsWithoutMemory) { TEST_F(FunctionBodyDecoderTest, TableInit) { TestModuleBuilder builder; - builder.InitializeTable(); - builder.AddPassiveElementSegment(); + builder.InitializeTable(wasm::kWasmFuncRef); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); ExpectFailure(sigs.v_v(), @@ -3216,10 +3220,22 @@ TEST_F(FunctionBodyDecoderTest, TableInit) { {WASM_TABLE_INIT(0, 1, WASM_ZERO, WASM_ZERO, WASM_ZERO)}); } +TEST_F(FunctionBodyDecoderTest, TableInitWrongType) { + TestModuleBuilder builder; + uint32_t table_index = builder.InitializeTable(wasm::kWasmFuncRef); + uint32_t element_index = builder.AddPassiveElementSegment(wasm::kWasmAnyRef); + module = builder.module(); + + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + ExpectFailure(sigs.v_v(), {WASM_TABLE_INIT(table_index, element_index, + WASM_ZERO, WASM_ZERO, WASM_ZERO)}); +} + TEST_F(FunctionBodyDecoderTest, TableInitInvalid) { TestModuleBuilder builder; - builder.InitializeTable(); - builder.AddPassiveElementSegment(); + builder.InitializeTable(wasm::kWasmFuncRef); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); WASM_FEATURE_SCOPE(bulk_memory); @@ -3232,8 +3248,8 @@ TEST_F(FunctionBodyDecoderTest, TableInitInvalid) { TEST_F(FunctionBodyDecoderTest, ElemDrop) { TestModuleBuilder builder; - builder.InitializeTable(); - builder.AddPassiveElementSegment(); + builder.InitializeTable(wasm::kWasmFuncRef); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); ExpectFailure(sigs.v_v(), {WASM_ELEM_DROP(0)}); @@ -3242,11 +3258,62 @@ TEST_F(FunctionBodyDecoderTest, ElemDrop) { ExpectFailure(sigs.v_v(), {WASM_ELEM_DROP(1)}); } +TEST_F(FunctionBodyDecoderTest, TableInitDeclarativeElem) { + TestModuleBuilder builder; + builder.InitializeTable(wasm::kWasmFuncRef); + builder.AddDeclarativeElementSegment(); + module = builder.module(); + + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + byte code[] = {WASM_TABLE_INIT(0, 0, WASM_ZERO, WASM_ZERO, WASM_ZERO), + WASM_END}; + for (size_t i = 0; i <= arraysize(code); ++i) { + Validate(i == arraysize(code), sigs.v_v(), VectorOf(code, i), kOmitEnd); + } +} + +TEST_F(FunctionBodyDecoderTest, DeclarativeElemDrop) { + TestModuleBuilder builder; + builder.InitializeTable(wasm::kWasmFuncRef); + builder.AddDeclarativeElementSegment(); + module = builder.module(); + + ExpectFailure(sigs.v_v(), {WASM_ELEM_DROP(0)}); + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + ExpectValidates(sigs.v_v(), {WASM_ELEM_DROP(0)}); + ExpectFailure(sigs.v_v(), {WASM_ELEM_DROP(1)}); +} + +TEST_F(FunctionBodyDecoderTest, RefFuncDeclared) { + TestModuleBuilder builder; + builder.InitializeTable(wasm::kWasmStmt); + byte function_index = builder.AddFunction(sigs.v_i()); + module = builder.module(); + + ExpectFailure(sigs.a_v(), {WASM_REF_FUNC(function_index)}); + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + ExpectValidates(sigs.a_v(), {WASM_REF_FUNC(function_index)}); +} + +TEST_F(FunctionBodyDecoderTest, RefFuncUndeclared) { + TestModuleBuilder builder; + builder.InitializeTable(wasm::kWasmStmt); + byte function_index = builder.AddFunction(sigs.v_i(), false); + module = builder.module(); + + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + ExpectFailure(sigs.a_v(), {WASM_REF_FUNC(function_index)}); +} + TEST_F(FunctionBodyDecoderTest, ElemSegmentIndexUnsigned) { TestModuleBuilder builder; - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmFuncRef); for (int i = 0; i < 65; ++i) { - builder.AddPassiveElementSegment(); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); } module = builder.module(); @@ -3260,7 +3327,7 @@ TEST_F(FunctionBodyDecoderTest, ElemSegmentIndexUnsigned) { TEST_F(FunctionBodyDecoderTest, TableCopy) { TestModuleBuilder builder; - builder.InitializeTable(); + builder.InitializeTable(wasm::kWasmStmt); module = builder.module(); ExpectFailure(sigs.v_v(), @@ -3270,6 +3337,18 @@ TEST_F(FunctionBodyDecoderTest, TableCopy) { {WASM_TABLE_COPY(0, 0, WASM_ZERO, WASM_ZERO, WASM_ZERO)}); } +TEST_F(FunctionBodyDecoderTest, TableCopyWrongType) { + TestModuleBuilder builder; + uint32_t dst_table_index = builder.InitializeTable(wasm::kWasmFuncRef); + uint32_t src_table_index = builder.InitializeTable(wasm::kWasmAnyRef); + module = builder.module(); + + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + ExpectFailure(sigs.v_v(), {WASM_TABLE_COPY(dst_table_index, src_table_index, + WASM_ZERO, WASM_ZERO, WASM_ZERO)}); +} + TEST_F(FunctionBodyDecoderTest, TableGrow) { TestModuleBuilder builder; byte tab_func = builder.AddTable(kWasmFuncRef, 10, true, 20); @@ -3369,7 +3448,7 @@ TEST_F(FunctionBodyDecoderTest, TableOpsWithoutTable) { } { WASM_FEATURE_SCOPE(bulk_memory); - builder.AddPassiveElementSegment(); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); ExpectFailure(sigs.v_v(), {WASM_TABLE_INIT(0, 0, WASM_ZERO, WASM_ZERO, WASM_ZERO)}); ExpectFailure(sigs.v_v(), @@ -3383,7 +3462,7 @@ TEST_F(FunctionBodyDecoderTest, TableCopyMultiTable) { { TestModuleBuilder builder; builder.AddTable(kWasmAnyRef, 10, true, 20); - builder.AddPassiveElementSegment(); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); // We added one table, therefore table.copy on table 0 should work. int table_src = 0; @@ -3405,7 +3484,7 @@ TEST_F(FunctionBodyDecoderTest, TableCopyMultiTable) { TestModuleBuilder builder; builder.AddTable(kWasmAnyRef, 10, true, 20); builder.AddTable(kWasmAnyRef, 10, true, 20); - builder.AddPassiveElementSegment(); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); // We added two tables, therefore table.copy on table 0 should work. int table_src = 0; @@ -3433,7 +3512,7 @@ TEST_F(FunctionBodyDecoderTest, TableInitMultiTable) { { TestModuleBuilder builder; builder.AddTable(kWasmAnyRef, 10, true, 20); - builder.AddPassiveElementSegment(); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); // We added one table, therefore table.init on table 0 should work. int table_index = 0; @@ -3448,7 +3527,7 @@ TEST_F(FunctionBodyDecoderTest, TableInitMultiTable) { TestModuleBuilder builder; builder.AddTable(kWasmAnyRef, 10, true, 20); builder.AddTable(kWasmAnyRef, 10, true, 20); - builder.AddPassiveElementSegment(); + builder.AddPassiveElementSegment(wasm::kWasmFuncRef); module = builder.module(); // We added two tables, therefore table.init on table 0 should work. int table_index = 0; @@ -3727,8 +3806,7 @@ TEST_F(LocalDeclDecoderTest, OneLocal) { WASM_FEATURE_SCOPE(anyref); for (size_t i = 0; i < arraysize(kValueTypes); i++) { ValueType type = kValueTypes[i]; - const byte data[] = {1, 1, - static_cast<byte>(ValueTypes::ValueTypeCodeFor(type))}; + const byte data[] = {1, 1, static_cast<byte>(type.value_type_code())}; BodyLocalDecls decls(zone()); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); @@ -3743,8 +3821,7 @@ TEST_F(LocalDeclDecoderTest, FiveLocals) { WASM_FEATURE_SCOPE(anyref); for (size_t i = 0; i < arraysize(kValueTypes); i++) { ValueType type = kValueTypes[i]; - const byte data[] = {1, 5, - static_cast<byte>(ValueTypes::ValueTypeCodeFor(type))}; + const byte data[] = {1, 5, static_cast<byte>(type.value_type_code())}; BodyLocalDecls decls(zone()); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); @@ -3809,8 +3886,7 @@ TEST_F(LocalDeclDecoderTest, UseEncoder) { TEST_F(LocalDeclDecoderTest, ExnRef) { WASM_FEATURE_SCOPE(eh); ValueType type = kWasmExnRef; - const byte data[] = {1, 1, - static_cast<byte>(ValueTypes::ValueTypeCodeFor(type))}; + const byte data[] = {1, 1, static_cast<byte>(type.value_type_code())}; BodyLocalDecls decls(zone()); bool result = DecodeLocalDecls(&decls, data, data + sizeof(data)); EXPECT_TRUE(result); diff --git a/deps/v8/test/unittests/wasm/module-decoder-unittest.cc b/deps/v8/test/unittests/wasm/module-decoder-unittest.cc index f88beef794..68a2bb6ff1 100644 --- a/deps/v8/test/unittests/wasm/module-decoder-unittest.cc +++ b/deps/v8/test/unittests/wasm/module-decoder-unittest.cc @@ -130,6 +130,13 @@ struct CheckLEB1 : std::integral_constant<size_t, num> { #define EXPECT_FAILURE(data) EXPECT_FAILURE_LEN(data, sizeof(data)) +#define EXPECT_FAILURE_WITH_MSG(data, msg) \ + do { \ + ModuleResult result = DecodeModule(data, data + sizeof(data)); \ + EXPECT_FALSE(result.ok()); \ + EXPECT_THAT(result.error().message(), HasSubstr(msg)); \ + } while (false) + #define EXPECT_OFF_END_FAILURE(data, min) \ do { \ STATIC_ASSERT(min < arraysize(data)); \ @@ -252,6 +259,7 @@ TEST_F(WasmModuleVerifyTest, OneGlobal) { TEST_F(WasmModuleVerifyTest, AnyRefGlobal) { WASM_FEATURE_SCOPE(anyref); + WASM_FEATURE_SCOPE(bulk_memory); static const byte data[] = { // sig#0 --------------------------------------------------------------- SIGNATURES_SECTION_VOID_VOID, @@ -265,6 +273,16 @@ TEST_F(WasmModuleVerifyTest, AnyRefGlobal) { kLocalAnyRef, // local type 0, // immutable WASM_INIT_EXPR_REF_FUNC(1)), // init + SECTION(Element, // section name + ENTRY_COUNT(2), // entry count + DECLARATIVE, // flags 0 + kExternalFunction, // type + ENTRY_COUNT(1), // func entry count + FUNC_INDEX(0), // func index + DECLARATIVE_WITH_ELEMENTS, // flags 1 + kLocalFuncRef, // local type + ENTRY_COUNT(1), // func ref count + REF_FUNC_ELEMENT(1)), // func ref TWO_EMPTY_BODIES}; { @@ -290,6 +308,7 @@ TEST_F(WasmModuleVerifyTest, AnyRefGlobal) { TEST_F(WasmModuleVerifyTest, FuncRefGlobal) { WASM_FEATURE_SCOPE(anyref); + WASM_FEATURE_SCOPE(bulk_memory); static const byte data[] = { // sig#0 --------------------------------------------------------------- SIGNATURES_SECTION_VOID_VOID, @@ -303,6 +322,16 @@ TEST_F(WasmModuleVerifyTest, FuncRefGlobal) { kLocalFuncRef, // local type 0, // immutable WASM_INIT_EXPR_REF_FUNC(1)), // init + SECTION(Element, // section name + ENTRY_COUNT(2), // entry count + DECLARATIVE, // flags 0 + kExternalFunction, // type + ENTRY_COUNT(1), // func entry count + FUNC_INDEX(0), // func index + DECLARATIVE_WITH_ELEMENTS, // flags 1 + kLocalFuncRef, // local type + ENTRY_COUNT(1), // func ref count + REF_FUNC_ELEMENT(1)), // func ref TWO_EMPTY_BODIES}; { // Should decode to two globals. @@ -695,9 +724,9 @@ TEST_F(WasmModuleVerifyTest, Exception_invalid_attribute) { } TEST_F(WasmModuleVerifyTest, ExceptionSectionCorrectPlacement) { - static const byte data[] = {SECTION(Import, ENTRY_COUNT(0)), + static const byte data[] = {SECTION(Memory, ENTRY_COUNT(0)), SECTION(Exception, ENTRY_COUNT(0)), - SECTION(Export, ENTRY_COUNT(0))}; + SECTION(Global, ENTRY_COUNT(0))}; FAIL_IF_NO_EXPERIMENTAL_EH(data); WASM_FEATURE_SCOPE(eh); @@ -705,37 +734,37 @@ TEST_F(WasmModuleVerifyTest, ExceptionSectionCorrectPlacement) { EXPECT_OK(result); } -TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterExport) { - static const byte data[] = {SECTION(Export, ENTRY_COUNT(0)), +TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterGlobal) { + static const byte data[] = {SECTION(Global, 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_NOT_OK(result, - "The Exception section must appear before the Export section"); + "The Exception section must appear before the Global section"); } -TEST_F(WasmModuleVerifyTest, ExceptionSectionBeforeGlobal) { +TEST_F(WasmModuleVerifyTest, ExceptionSectionBeforeMemory) { static const byte data[] = {SECTION(Exception, ENTRY_COUNT(0)), - SECTION(Global, ENTRY_COUNT(0))}; + SECTION(Memory, 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>"); + EXPECT_NOT_OK(result, "unexpected section <Memory>"); } -TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterMemoryBeforeGlobal) { +TEST_F(WasmModuleVerifyTest, ExceptionSectionAfterTableBeforeMemory) { STATIC_ASSERT(kMemorySectionCode + 1 == kGlobalSectionCode); - static const byte data[] = {SECTION(Memory, ENTRY_COUNT(0)), + static const byte data[] = {SECTION(Table, ENTRY_COUNT(0)), SECTION(Exception, ENTRY_COUNT(0)), - SECTION(Global, ENTRY_COUNT(0))}; + SECTION(Memory, 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>"); + EXPECT_NOT_OK(result, "unexpected section <Memory>"); } TEST_F(WasmModuleVerifyTest, ExceptionImport) { @@ -1493,7 +1522,7 @@ class WasmSignatureDecodeTest : public TestWithZone { public: WasmFeatures enabled_features_ = WasmFeatures::None(); - FunctionSig* DecodeSig(const byte* start, const byte* end) { + const FunctionSig* DecodeSig(const byte* start, const byte* end) { return DecodeWasmSignatureForTesting(enabled_features_, zone(), start, end); } }; @@ -1502,7 +1531,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_v_v) { static const byte data[] = {SIG_ENTRY_v_v}; v8::internal::AccountingAllocator allocator; Zone zone(&allocator, ZONE_NAME); - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_TRUE(sig != nullptr); EXPECT_EQ(0u, sig->parameter_count()); @@ -1514,7 +1543,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_t_v) { for (size_t i = 0; i < arraysize(kValueTypes); i++) { ValueTypePair ret_type = kValueTypes[i]; const byte data[] = {SIG_ENTRY_x(ret_type.code)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_TRUE(sig != nullptr); EXPECT_EQ(0u, sig->parameter_count()); @@ -1528,7 +1557,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_v_t) { for (size_t i = 0; i < arraysize(kValueTypes); i++) { ValueTypePair param_type = kValueTypes[i]; const byte data[] = {SIG_ENTRY_v_x(param_type.code)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_TRUE(sig != nullptr); EXPECT_EQ(1u, sig->parameter_count()); @@ -1544,7 +1573,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_t_t) { for (size_t j = 0; j < arraysize(kValueTypes); j++) { ValueTypePair param_type = kValueTypes[j]; const byte data[] = {SIG_ENTRY_x_x(ret_type.code, param_type.code)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_TRUE(sig != nullptr); EXPECT_EQ(1u, sig->parameter_count()); @@ -1564,7 +1593,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_i_tt) { ValueTypePair p1_type = kValueTypes[j]; const byte data[] = { SIG_ENTRY_x_xx(kLocalI32, p0_type.code, p1_type.code)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_TRUE(sig != nullptr); EXPECT_EQ(2u, sig->parameter_count()); @@ -1584,7 +1613,7 @@ TEST_F(WasmSignatureDecodeTest, Ok_tt_tt) { ValueTypePair p1_type = kValueTypes[j]; const byte data[] = {SIG_ENTRY_xx_xx(p0_type.code, p1_type.code, p0_type.code, p1_type.code)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_TRUE(sig != nullptr); EXPECT_EQ(2u, sig->parameter_count()); @@ -1601,7 +1630,7 @@ TEST_F(WasmSignatureDecodeTest, TooManyParams) { static const byte data[] = {kWasmFunctionTypeCode, WASM_I32V_3(kV8MaxWasmFunctionParams + 1), kLocalI32, 0}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_FALSE(sig != nullptr); } @@ -1613,7 +1642,7 @@ TEST_F(WasmSignatureDecodeTest, TooManyReturns) { enable_mv ? kV8MaxWasmFunctionMultiReturns : kV8MaxWasmFunctionReturns); byte data[] = {kWasmFunctionTypeCode, 0, WASM_I32V_3(max_return_count + 1), kLocalI32}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_EQ(nullptr, sig); } } @@ -1626,7 +1655,7 @@ TEST_F(WasmSignatureDecodeTest, Fail_off_end) { for (int i = 0; i < p + 1; i++) { // Should fall off the end for all signatures. - FunctionSig* sig = DecodeSig(data, data + i); + const FunctionSig* sig = DecodeSig(data, data + i); EXPECT_EQ(nullptr, sig); } } @@ -1641,7 +1670,7 @@ TEST_F(WasmSignatureDecodeTest, Fail_anyref_without_flag) { 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)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_EQ(nullptr, sig); } } @@ -1653,26 +1682,26 @@ TEST_F(WasmSignatureDecodeTest, Fail_invalid_type) { byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalI32)}; if (i >= arraysize(data)) break; data[i] = kInvalidType; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_EQ(nullptr, sig); } } TEST_F(WasmSignatureDecodeTest, Fail_invalid_ret_type1) { static const byte data[] = {SIG_ENTRY_x_x(kLocalVoid, kLocalI32)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_EQ(nullptr, sig); } TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type1) { static const byte data[] = {SIG_ENTRY_x_x(kLocalI32, kLocalVoid)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_EQ(nullptr, sig); } TEST_F(WasmSignatureDecodeTest, Fail_invalid_param_type2) { static const byte data[] = {SIG_ENTRY_x_xx(kLocalI32, kLocalI32, kLocalVoid)}; - FunctionSig* sig = DecodeSig(data, data + sizeof(data)); + const FunctionSig* sig = DecodeSig(data, data + sizeof(data)); EXPECT_EQ(nullptr, sig); } @@ -1724,12 +1753,22 @@ TEST_F(WasmModuleVerifyTest, SectionWithoutNameLength) { EXPECT_FAILURE(data); } +TEST_F(WasmModuleVerifyTest, EmptyCustomSectionIsInvalid) { + // An empty custom section is invalid, because at least one byte for the + // length of the custom section name is required. + const byte data[] = { + 0, // unknown section code. + 0 // section length. + }; + EXPECT_FAILURE(data); +} + TEST_F(WasmModuleVerifyTest, TheLoneliestOfValidModulesTheTrulyEmptyOne) { const byte data[] = { 0, // unknown section code. - 0, // Empty section name. - // No section name, no content, nothing but sadness. - 0, // No section content. + 1, // section length, only one byte for the name length. + 0, // string length of 0. + // Empty section name, no content, nothing but sadness. }; EXPECT_VERIFIES(data); } @@ -2507,7 +2546,7 @@ TEST_F(WasmModuleVerifyTest, PassiveElementSegmentWithIndices) { ONE_EMPTY_FUNCTION(SIG_INDEX(0)), // table declaration ----------------------------------------------------- SECTION(Table, ENTRY_COUNT(1), kLocalFuncRef, 0, 1), - // element segments ----------------------------------------------------- + // element segments ------------------------------------------------------ SECTION(Element, ENTRY_COUNT(1), PASSIVE, kExternalFunction, ENTRY_COUNT(3), U32V_1(0), U32V_1(0), U32V_1(0)), // code ------------------------------------------------------------------ @@ -2518,6 +2557,67 @@ TEST_F(WasmModuleVerifyTest, PassiveElementSegmentWithIndices) { EXPECT_OFF_END_FAILURE(data, arraysize(data) - 5); } +TEST_F(WasmModuleVerifyTest, DeclarativeElementSegmentFuncRef) { + static const byte data[] = { + // sig#0 ----------------------------------------------------------------- + SIGNATURES_SECTION_VOID_VOID, + // funcs ----------------------------------------------------------------- + ONE_EMPTY_FUNCTION(SIG_INDEX(0)), + // element segments ----------------------------------------------------- + SECTION(Element, // section name + ENTRY_COUNT(1), // entry count + DECLARATIVE_WITH_ELEMENTS, // flags + kLocalFuncRef, // local type + U32V_1(0)), // func ref count + // code ------------------------------------------------------------------ + ONE_EMPTY_BODY}; + EXPECT_FAILURE(data); + WASM_FEATURE_SCOPE(bulk_memory); + EXPECT_FAILURE(data); + WASM_FEATURE_SCOPE(anyref); + EXPECT_VERIFIES(data); +} + +TEST_F(WasmModuleVerifyTest, DeclarativeElementSegmentWithInvalidIndex) { + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + static const byte data[] = { + // sig#0 ----------------------------------------------------------------- + SIGNATURES_SECTION_VOID_VOID, + // funcs ----------------------------------------------------------------- + ONE_EMPTY_FUNCTION(SIG_INDEX(0)), + // element segments ----------------------------------------------------- + SECTION(Element, // section name + ENTRY_COUNT(1), // entry count + DECLARATIVE, // flags + kExternalFunction, // type + ENTRY_COUNT(2), // func index count + U32V_1(0), // func index + U32V_1(1)), // func index + // code ------------------------------------------------------------------ + ONE_EMPTY_BODY}; + EXPECT_FAILURE_WITH_MSG(data, "element function index 1 out of bounds"); +} + +TEST_F(WasmModuleVerifyTest, DeclarativeElementSegmentMissingForGlobal) { + WASM_FEATURE_SCOPE(bulk_memory); + WASM_FEATURE_SCOPE(anyref); + static const byte data[] = { + // sig#0 ----------------------------------------------------------------- + SIGNATURES_SECTION_VOID_VOID, + // funcs ----------------------------------------------------------------- + ONE_EMPTY_FUNCTION(SIG_INDEX(0)), + // global definitions ---------------------------------------------------- + SECTION(Global, // section name + ENTRY_COUNT(1), // entry count + kLocalAnyRef, // local type + 0, // immutable + WASM_INIT_EXPR_REF_FUNC(0)), // init + // code ------------------------------------------------------------------ + ONE_EMPTY_BODY}; + EXPECT_FAILURE_WITH_MSG(data, "undeclared reference to function"); +} + TEST_F(WasmModuleVerifyTest, DataCountSectionCorrectPlacement) { static const byte data[] = {SECTION(Element, ENTRY_COUNT(0)), SECTION(DataCount, ENTRY_COUNT(0)), diff --git a/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc b/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc index 4b9f78dfdc..0b8cf6d11d 100644 --- a/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc +++ b/deps/v8/test/unittests/wasm/wasm-compiler-unittest.cc @@ -21,9 +21,9 @@ TEST_F(WasmCallDescriptorTest, TestAnyRefIsGrouped) { ValueType params[kMaxCount]; for (size_t i = 0; i < kMaxCount; i += 2) { - params[i] = ValueType::kWasmAnyRef; + params[i] = kWasmAnyRef; CHECK_LT(i + 1, kMaxCount); - params[i + 1] = ValueType::kWasmI32; + params[i + 1] = kWasmI32; } for (size_t count = 1; count <= kMaxCount; ++count) { |