diff options
Diffstat (limited to 'deps/v8/test/cctest')
32 files changed, 737 insertions, 629 deletions
diff --git a/deps/v8/test/cctest/BUILD.gn b/deps/v8/test/cctest/BUILD.gn index 89a9e4bf0d..e7f011df74 100644 --- a/deps/v8/test/cctest/BUILD.gn +++ b/deps/v8/test/cctest/BUILD.gn @@ -89,8 +89,6 @@ v8_source_set("cctest_sources") { "compiler/function-tester.cc", "compiler/function-tester.h", "compiler/node-observer-tester.h", - "compiler/serializer-tester.cc", - "compiler/serializer-tester.h", "compiler/test-basic-block-profiler.cc", "compiler/test-branch-combine.cc", "compiler/test-calls-with-arraylike-or-spread.cc", diff --git a/deps/v8/test/cctest/cctest.cc b/deps/v8/test/cctest/cctest.cc index 2478fa7871..fa42921b77 100644 --- a/deps/v8/test/cctest/cctest.cc +++ b/deps/v8/test/cctest/cctest.cc @@ -414,7 +414,9 @@ int RegisterThreadedTest::count_ = 0; bool IsValidUnwrapObject(v8::Object* object) { i::Address addr = *reinterpret_cast<i::Address*>(object); auto instance_type = i::Internals::GetInstanceType(addr); - return (instance_type == i::Internals::kJSObjectType || - instance_type == i::Internals::kJSApiObjectType || + return (v8::base::IsInRange(instance_type, + i::Internals::kFirstJSApiObjectType, + i::Internals::kLastJSApiObjectType) || + instance_type == i::Internals::kJSObjectType || instance_type == i::Internals::kJSSpecialApiObjectType); } diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index f7a7726b30..9b36904475 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -117,9 +117,6 @@ 'test-serialize/CustomSnapshotDataBlobImmortalImmovableRoots': [PASS, ['mode == debug', SKIP]], 'test-parsing/ObjectRestNegativeTestSlow': [PASS, ['mode == debug', SKIP]], - # pthread_rwlock_t combined with signals is broken on Mac (https://crbug.com/v8/11399). - 'signals-and-mutexes/SignalsPlusSharedMutexes': [PASS, ['system == macos', SKIP]], - # Tests that need to run sequentially (e.g. due to memory consumption). 'test-accessors/HandleScopePop': [PASS, HEAVY], 'test-api/FastApiCalls': [PASS, HEAVY], @@ -614,7 +611,6 @@ # Tests that generate code at runtime. 'codegen-tester/*': [SKIP], - 'serializer-tester/*': [SKIP], 'test-accessor-assembler/*': [SKIP], 'test-assembler-*': [SKIP], 'test-basic-block-profiler/*': [SKIP], @@ -689,17 +685,6 @@ ############################################################################## ['variant == jitless', { # https://crbug.com/v8/7777 - 'serializer-tester/SerializeCallAnyReceiver': [SKIP], - 'serializer-tester/SerializeCallArguments': [SKIP], - 'serializer-tester/SerializeCallProperty': [SKIP], - 'serializer-tester/SerializeCallProperty2': [SKIP], - 'serializer-tester/SerializeCallUndefinedReceiver': [SKIP], - 'serializer-tester/SerializeCallUndefinedReceiver2': [SKIP], - 'serializer-tester/SerializeCallWithSpread': [SKIP], - 'serializer-tester/SerializeConstruct': [SKIP], - 'serializer-tester/SerializeConstructWithSpread': [SKIP], - 'serializer-tester/SerializeInlinedClosure': [SKIP], - 'serializer-tester/SerializeInlinedFunction': [SKIP], 'test-cpu-profiler/TickLinesOptimized': [SKIP], 'test-heap/TestOptimizeAfterBytecodeFlushingCandidate': [SKIP], 'test-js-to-wasm/*': [SKIP], @@ -745,8 +730,6 @@ # Turboprop doesn't use call feedback and hence doesn't inline even if # the inlining flag is explicitly set. 'test-cpu-profiler/DetailedSourcePositionAPI_Inlining': [SKIP], - 'serializer-tester/BoundFunctionArguments': [SKIP], - 'serializer-tester/BoundFunctionTarget': [SKIP], 'test-calls-with-arraylike-or-spread/*': [SKIP], 'test-js-to-wasm/*': [SKIP], }], # variant == turboprop or variant == turboprop_as_toptier @@ -822,28 +805,7 @@ 'test-invalidated-slots/InvalidatedSlotsNoInvalidatedRanges': [SKIP], 'test-invalidated-slots/InvalidatedSlotsResetObjectRegression': [SKIP], 'test-invalidated-slots/InvalidatedSlotsSomeInvalidatedRanges': [SKIP], - # Requires --concurrent_inlining / --finalize_streaming_on_background: - 'serializer-tester/ArrowFunctionInlined': [SKIP], - 'serializer-tester/BoundFunctionArguments': [SKIP], - 'serializer-tester/BoundFunctionResult': [SKIP], - 'serializer-tester/BoundFunctionTarget': [SKIP], - 'serializer-tester/MergeJumpTargetEnvironment': [SKIP], - 'serializer-tester/MultipleFunctionCalls': [SKIP], - 'serializer-tester/SerializeCallAnyReceiver': [SKIP], - 'serializer-tester/SerializeCallArguments': [SKIP], - 'serializer-tester/SerializeCallProperty': [SKIP], - 'serializer-tester/SerializeCallProperty2': [SKIP], - 'serializer-tester/SerializeCallUndefinedReceiver': [SKIP], - 'serializer-tester/SerializeCallUndefinedReceiver2': [SKIP], - 'serializer-tester/SerializeCallWithSpread': [SKIP], - 'serializer-tester/SerializeConditionalJump': [SKIP], - 'serializer-tester/SerializeConstruct': [SKIP], - 'serializer-tester/SerializeConstructSuper': [SKIP], - 'serializer-tester/SerializeConstructWithSpread': [SKIP], - 'serializer-tester/SerializeEmptyFunction': [SKIP], - 'serializer-tester/SerializeInlinedClosure': [SKIP], - 'serializer-tester/SerializeInlinedFunction': [SKIP], - 'serializer-tester/SerializeUnconditionalJump': [SKIP], + # Requires --finalize_streaming_on_background: 'test-concurrent-allocation/ConcurrentAllocationWhileMainThreadIsParked': [SKIP], 'test-concurrent-allocation/ConcurrentAllocationWhileMainThreadParksAndUnparks': [SKIP], 'test-concurrent-allocation/ConcurrentAllocationWhileMainThreadRunsWithSafepoints': [SKIP], diff --git a/deps/v8/test/cctest/compiler/serializer-tester.cc b/deps/v8/test/cctest/compiler/serializer-tester.cc deleted file mode 100644 index 9829f798a0..0000000000 --- a/deps/v8/test/cctest/compiler/serializer-tester.cc +++ /dev/null @@ -1,383 +0,0 @@ -// Copyright 2019 the V8 project authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Serializer tests don't make sense in lite mode, as it doesn't gather -// IC feedback. -#ifndef V8_LITE_MODE - -#include "test/cctest/compiler/serializer-tester.h" - -#include "src/api/api-inl.h" -#include "src/codegen/optimized-compilation-info.h" -#include "src/compiler/serializer-for-background-compilation.h" -#include "src/compiler/zone-stats.h" -#include "src/zone/zone.h" - -namespace v8 { -namespace internal { -namespace compiler { - -SerializerTester::SerializerTester(const char* global_source, - const char* local_source) - : canonical_(main_isolate()) { - // The tests only make sense in the context of concurrent compilation. - FLAG_concurrent_inlining = true; - // The tests don't make sense when optimizations are turned off. - FLAG_opt = true; - // We need the IC to feed it to the serializer. - FLAG_use_ic = true; - // We need manual control over when a given function is optimized. - FLAG_always_opt = false; - // We need allocation of executable memory for the compilation. - FLAG_jitless = false; - FLAG_allow_natives_syntax = true; - FlagList::EnforceFlagImplications(); - - CompileRun(global_source); - - std::string function_string = "(function() { "; - function_string += local_source; - function_string += " })();"; - Handle<JSFunction> function = Handle<JSFunction>::cast(v8::Utils::OpenHandle( - *v8::Local<v8::Function>::Cast(CompileRun(function_string.c_str())))); - uint32_t flags = i::OptimizedCompilationInfo::kInlining; - Optimize(function, main_zone(), main_isolate(), flags, &broker_); - // Update handle to the corresponding serialized Handle in the broker. - function = - broker_->FindCanonicalPersistentHandleForTesting<JSFunction>(*function); - function_ = MakeRef(broker(), function); -} - -TEST(SerializeEmptyFunction) { - SerializerTester tester( - "", "function f() {}; %EnsureFeedbackVectorForFunction(f); return f;"); - JSFunctionRef function = tester.function(); - CHECK(tester.broker()->IsSerializedForCompilation( - function.shared(), function.feedback_vector())); -} - -// This helper function allows for testing whether an inlinee candidate -// was properly serialized. It expects that the top-level function (that is -// run through the SerializerTester) will return its inlinee candidate. -void CheckForSerializedInlinee(const char* global_source, - const char* local_source, int argc = 0, - Handle<Object> argv[] = {}) { - SerializerTester tester(global_source, local_source); - JSFunctionRef f = tester.function(); - CHECK(tester.broker()->IsSerializedForCompilation(f.shared(), - f.feedback_vector())); - - MaybeHandle<Object> g_obj = Execution::Call( - tester.isolate(), tester.function().object(), - tester.isolate()->factory()->undefined_value(), argc, argv); - Handle<Object> g; - CHECK(g_obj.ToHandle(&g)); - CHECK_WITH_MSG( - g->IsJSFunction(), - "The return value of the outer function must be a function too"); - Handle<JSFunction> g_func = Handle<JSFunction>::cast(g); - - // Look up corresponding serialized Handles in the broker. - Handle<SharedFunctionInfo> sfi( - tester.broker() - ->FindCanonicalPersistentHandleForTesting<SharedFunctionInfo>( - g_func->shared())); - SharedFunctionInfoRef g_sfi = MakeRef(tester.broker(), sfi); - Handle<FeedbackVector> fv( - tester.broker()->FindCanonicalPersistentHandleForTesting<FeedbackVector>( - g_func->feedback_vector())); - FeedbackVectorRef g_fv = MakeRef(tester.broker(), fv); - CHECK(tester.broker()->IsSerializedForCompilation(g_sfi, g_fv)); -} - -TEST(SerializeInlinedClosure) { - CheckForSerializedInlinee("", - "function f() {" - " function g(){ return g; }" - " %EnsureFeedbackVectorForFunction(g);" - " return g();" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeInlinedFunction) { - CheckForSerializedInlinee("", - "function g() {};" - "%EnsureFeedbackVectorForFunction(g);" - "function f() {" - " g(); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeCallUndefinedReceiver) { - CheckForSerializedInlinee("", - "function g(a,b,c) {};" - "%EnsureFeedbackVectorForFunction(g);" - "function f() {" - " g(1,2,3); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeCallUndefinedReceiver2) { - CheckForSerializedInlinee("", - "function g(a,b) {};" - "%EnsureFeedbackVectorForFunction(g);" - "function f() {" - " g(1,2); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeCallProperty) { - CheckForSerializedInlinee("", - "let obj = {" - " g: function g(a,b,c) {}" - "};" - "%EnsureFeedbackVectorForFunction(obj.g);" - "function f() {" - " obj.g(1,2,3); return obj.g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeCallProperty2) { - CheckForSerializedInlinee("", - "let obj = {" - " g: function g(a,b) {}" - "};" - "%EnsureFeedbackVectorForFunction(obj.g);" - "function f() {" - " obj.g(1,2); return obj.g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeCallAnyReceiver) { - CheckForSerializedInlinee("", - "let obj = {" - " g: function g() {}" - "};" - "%EnsureFeedbackVectorForFunction(obj.g);" - "function f() {" - " with(obj) {" - " g(); return g;" - " };" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeCallWithSpread) { - CheckForSerializedInlinee("", - "function g(args) {};" - "%EnsureFeedbackVectorForFunction(g);" - "const arr = [1,2,3];" - "function f() {" - " g(...arr); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -// The following test causes the CallIC of `g` to turn megamorphic, -// thus allowing us to test if we forward arguments hints (`callee` in this -// example) and correctly serialize the inlining candidate `j`. -TEST(SerializeCallArguments) { - CheckForSerializedInlinee("", - "function g(callee) { callee(); };" - "function h() {};" - "function i() {};" - "%EnsureFeedbackVectorForFunction(g);" - "g(h); g(i);" - "function f() {" - " function j() {};" - " g(j);" - " return j;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "var j = f();" - "%EnsureFeedbackVectorForFunction(j);" - "f(); return f;"); -} - -TEST(SerializeConstruct) { - CheckForSerializedInlinee("", - "function g() {};" - "%EnsureFeedbackVectorForFunction(g);" - "function f() {" - " new g(); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeConstructWithSpread) { - CheckForSerializedInlinee("", - "function g(a, b, c) {};" - "%EnsureFeedbackVectorForFunction(g);" - "const arr = [1, 2];" - "function f() {" - " new g(0, ...arr); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeConstructSuper) { - CheckForSerializedInlinee("", - "class A {};" - "class B extends A { constructor() { super(); } };" - "%EnsureFeedbackVectorForFunction(A);" - "%EnsureFeedbackVectorForFunction(B);" - "function f() {" - " new B(); return A;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "f(); return f;"); -} - -TEST(SerializeConditionalJump) { - CheckForSerializedInlinee("", - "function g(callee) { callee(); };" - "function h() {};" - "function i() {};" - "%EnsureFeedbackVectorForFunction(g);" - "let a = true;" - "g(h); g(i);" - "function f() {" - " function q() {};" - " if (a) g(q);" - " return q;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "var q = f();" - "%EnsureFeedbackVectorForFunction(q);" - "f(); return f;"); -} - -TEST(SerializeUnconditionalJump) { - CheckForSerializedInlinee("", - "function g(callee) { callee(); };" - "function h() {};" - "function i() {};" - "%EnsureFeedbackVectorForFunction(g);" - "%EnsureFeedbackVectorForFunction(h);" - "%EnsureFeedbackVectorForFunction(i);" - "let a = false;" - "g(h); g(i);" - "function f() {" - " function p() {};" - " function q() {};" - " if (a) q();" - " else g(p);" - " return p;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "var p = f();" - "%EnsureFeedbackVectorForFunction(p);" - "f(); return f;"); -} - -TEST(MergeJumpTargetEnvironment) { - CheckForSerializedInlinee( - "", - "function f() {" - " let g;" - " while (true) {" - " if (g === undefined) {g = ()=>1; break;} else {g = ()=>2; break};" - " };" - " g(); return g;" - "};" - "%EnsureFeedbackVectorForFunction(f);" - "%EnsureFeedbackVectorForFunction(f());" - "f(); return f;"); // Two calls to f to make g() megamorhpic. -} - -TEST(BoundFunctionTarget) { - const char* global = "function apply1(foo, arg) { return foo(arg); };"; - CheckForSerializedInlinee( - global, - "%EnsureFeedbackVectorForFunction(apply1);" - "function test() {" - " const lambda = (a) => a;" - " %EnsureFeedbackVectorForFunction(lambda);" - " let bound = apply1.bind(null, lambda).bind(null, 42);" - " %TurbofanStaticAssert(bound() == 42); return apply1;" - "};" - "%EnsureFeedbackVectorForFunction(test);" - "test(); return test;"); -} - -TEST(BoundFunctionArguments) { - const char* global = "function apply2(foo, arg) { return foo(arg); };"; - CheckForSerializedInlinee( - global, - "%EnsureFeedbackVectorForFunction(apply2);" - "function test() {" - " const lambda = (a) => a;" - " %EnsureFeedbackVectorForFunction(lambda);" - " let bound = apply2.bind(null, lambda).bind(null, 42);" - " %TurbofanStaticAssert(bound() == 42); return lambda;" - "};" - "%EnsureFeedbackVectorForFunction(test);" - "test(); return test;"); -} - -TEST(ArrowFunctionInlined) { - // The loop is to ensure there is a feedback vector for the arrow function - // {b}. - CheckForSerializedInlinee("", - "function foo() {" - " let b = x => x * x;" - " let a = [1, 2, 3].map(b);" - " return b;" - "}" - "%EnsureFeedbackVectorForFunction(foo);" - "for (let i = 0; i < 100; ++i) foo();" - "return foo;"); -} - -TEST(BoundFunctionResult) { - CheckForSerializedInlinee( - "", - "function id(x) { return x }" - "function foo() { id.bind(undefined, 42)(); return id; }" - "%PrepareFunctionForOptimization(foo);" - "%PrepareFunctionForOptimization(id);" - "foo();" - "foo();" - "%OptimizeFunctionOnNextCall(foo);" - "foo(); return foo;"); -} - -TEST(MultipleFunctionCalls) { - CheckForSerializedInlinee( - "", - "function inc(x) { return ++x; }" - "function dec(x) { return --x; }" - "function apply(f, x) { return f(x); }" - "function foo() { apply(inc, 42); apply(dec, 42); return dec; }" - "%PrepareFunctionForOptimization(inc);" - "%PrepareFunctionForOptimization(dec);" - "%PrepareFunctionForOptimization(apply);" - "%PrepareFunctionForOptimization(foo);" - "foo();" - "foo();" - "%OptimizeFunctionOnNextCall(foo);" - "foo(); return foo;"); -} - -} // namespace compiler -} // namespace internal -} // namespace v8 - -#endif // V8_LITE_MODE diff --git a/deps/v8/test/cctest/compiler/test-calls-with-arraylike-or-spread.cc b/deps/v8/test/cctest/compiler/test-calls-with-arraylike-or-spread.cc index f47e03cf64..27c6465bca 100644 --- a/deps/v8/test/cctest/compiler/test-calls-with-arraylike-or-spread.cc +++ b/deps/v8/test/cctest/compiler/test-calls-with-arraylike-or-spread.cc @@ -126,6 +126,57 @@ TEST(ReduceJSCreateBoundFunction) { IrOpcode::kPhi); } +static void SumF(const v8::FunctionCallbackInfo<v8::Value>& args) { + ApiTestFuzzer::Fuzz(); + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + int this_x = args.This() + ->Get(context, v8_str("x")) + .ToLocalChecked() + ->Int32Value(context) + .FromJust(); + args.GetReturnValue().Set(v8_num( + args[0]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust() + + args[1]->Int32Value(args.GetIsolate()->GetCurrentContext()).FromJust() + + this_x)); +} + +TEST(ReduceCAPICallWithArrayLike) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + FLAG_allow_natives_syntax = true; + FLAG_turbo_optimize_apply = true; + + Local<v8::FunctionTemplate> sum = v8::FunctionTemplate::New(isolate, SumF); + CHECK(env->Global() + ->Set(env.local(), v8_str("sum"), + sum->GetFunction(env.local()).ToLocalChecked()) + .FromJust()); + + Local<v8::FunctionTemplate> fun = v8::FunctionTemplate::New(isolate); + v8::Local<v8::String> class_name = v8_str("the_class_name"); + fun->SetClassName(class_name); + Local<ObjectTemplate> templ1 = ObjectTemplate::New(isolate, fun); + templ1->Set(isolate, "x", v8_num(42)); + templ1->Set(isolate, "foo", sum); + Local<v8::Object> instance1 = + templ1->NewInstance(env.local()).ToLocalChecked(); + CHECK(env->Global()->Set(env.local(), v8_str("p"), instance1).FromJust()); + + std::string js_code = + "function bar(a, b) { return sum.apply(p, [a, b]); }" + "%PrepareFunctionForOptimization(bar);" + "bar(20, 22);" + "%OptimizeFunctionOnNextCall(bar);" + "bar(20, 22);"; + v8::Local<v8::Value> result_value = CompileRun(js_code.c_str()); + CHECK(result_value->IsNumber()); + int32_t result = + ConvertJSValue<int32_t>::Get(result_value, env.local()).ToChecked(); + CHECK_EQ(result, 84); +} + } // namespace compiler } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/compiler/test-concurrent-shared-function-info.cc b/deps/v8/test/cctest/compiler/test-concurrent-shared-function-info.cc index c286c1705c..81c5e69e4a 100644 --- a/deps/v8/test/cctest/compiler/test-concurrent-shared-function-info.cc +++ b/deps/v8/test/cctest/compiler/test-concurrent-shared-function-info.cc @@ -187,9 +187,15 @@ TEST(TestConcurrentSharedFunctionInfo) { // Finalize job. { + // Cannot assert successful completion here since concurrent modifications + // may have invalidated compilation dependencies (e.g. since the serialized + // JSFunctionRef no longer matches the actual JSFunction state). const CompilationJob::Status status = job->FinalizeJob(isolate); - CHECK_EQ(status, CompilationJob::SUCCEEDED); - CHECK(job->compilation_info()->has_bytecode_array()); + if (status == CompilationJob::SUCCEEDED) { + CHECK(job->compilation_info()->has_bytecode_array()); + } else { + CHECK_EQ(status, CompilationJob::FAILED); + } } } diff --git a/deps/v8/test/cctest/compiler/test-instruction-scheduler.cc b/deps/v8/test/cctest/compiler/test-instruction-scheduler.cc index b4bc78a72f..2fab39506d 100644 --- a/deps/v8/test/cctest/compiler/test-instruction-scheduler.cc +++ b/deps/v8/test/cctest/compiler/test-instruction-scheduler.cc @@ -77,8 +77,8 @@ TEST(DeoptInMiddleOfBasicBlock) { Node* node = Node::New(zone, 0, nullptr, 0, nullptr, false); FeedbackSource feedback; FlagsContinuation cont = FlagsContinuation::ForDeoptimize( - kEqual, DeoptimizeKind::kEager, DeoptimizeReason::kUnknown, feedback, - node); + kEqual, DeoptimizeKind::kEager, DeoptimizeReason::kUnknown, node->id(), + feedback, node); jmp_opcode = cont.Encode(jmp_opcode); Instruction* jmp_inst = Instruction::New(zone, jmp_opcode); tester.CheckIsDeopt(jmp_inst); diff --git a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc index aaec5e992c..d12c039f11 100644 --- a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc +++ b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc @@ -201,7 +201,7 @@ TEST(ReduceJSLoadContext1) { Node* start = t.graph()->NewNode(t.common()->Start(0)); t.graph()->SetStart(start); - Handle<ScopeInfo> empty(ScopeInfo::Empty(t.main_isolate()), t.main_isolate()); + ScopeInfoRef empty = MakeRef(t.broker(), ScopeInfo::Empty(t.main_isolate())); const i::compiler::Operator* create_function_context = t.javascript()->CreateFunctionContext(empty, 42, FUNCTION_SCOPE); @@ -271,7 +271,7 @@ TEST(ReduceJSLoadContext2) { Node* start = t.graph()->NewNode(t.common()->Start(0)); t.graph()->SetStart(start); - Handle<ScopeInfo> empty(ScopeInfo::Empty(t.main_isolate()), t.main_isolate()); + ScopeInfoRef empty = MakeRef(t.broker(), ScopeInfo::Empty(t.main_isolate())); const i::compiler::Operator* create_function_context = t.javascript()->CreateFunctionContext(empty, 42, FUNCTION_SCOPE); @@ -365,8 +365,7 @@ TEST(ReduceJSLoadContext3) { Node* start = t.graph()->NewNode(t.common()->Start(2)); t.graph()->SetStart(start); - Handle<ScopeInfo> empty(ScopeInfo::Empty(t.main_isolate()), - handle_zone_scope.main_isolate()); + ScopeInfoRef empty = MakeRef(t.broker(), ScopeInfo::Empty(t.main_isolate())); const i::compiler::Operator* create_function_context = t.javascript()->CreateFunctionContext(empty, 42, FUNCTION_SCOPE); @@ -496,7 +495,7 @@ TEST(ReduceJSStoreContext1) { Node* start = t.graph()->NewNode(t.common()->Start(0)); t.graph()->SetStart(start); - Handle<ScopeInfo> empty(ScopeInfo::Empty(t.main_isolate()), t.main_isolate()); + ScopeInfoRef empty = MakeRef(t.broker(), ScopeInfo::Empty(t.main_isolate())); const i::compiler::Operator* create_function_context = t.javascript()->CreateFunctionContext(empty, 42, FUNCTION_SCOPE); @@ -540,7 +539,7 @@ TEST(ReduceJSStoreContext2) { Node* start = t.graph()->NewNode(t.common()->Start(0)); t.graph()->SetStart(start); - Handle<ScopeInfo> empty(ScopeInfo::Empty(t.main_isolate()), t.main_isolate()); + ScopeInfoRef empty = MakeRef(t.broker(), ScopeInfo::Empty(t.main_isolate())); const i::compiler::Operator* create_function_context = t.javascript()->CreateFunctionContext(empty, 42, FUNCTION_SCOPE); @@ -606,8 +605,7 @@ TEST(ReduceJSStoreContext3) { Node* start = t.graph()->NewNode(t.common()->Start(2)); t.graph()->SetStart(start); - Handle<ScopeInfo> empty(ScopeInfo::Empty(t.main_isolate()), - handle_zone_scope.main_isolate()); + ScopeInfoRef empty = MakeRef(t.broker(), ScopeInfo::Empty(t.main_isolate())); const i::compiler::Operator* create_function_context = t.javascript()->CreateFunctionContext(empty, 42, FUNCTION_SCOPE); diff --git a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc index a2db7d62bd..b911164f3f 100644 --- a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "src/codegen/tick-counter.h" +#include "src/compiler/compilation-dependencies.h" #include "src/compiler/js-graph.h" #include "src/compiler/js-heap-broker.h" #include "src/compiler/js-heap-copy-reducer.h" @@ -37,7 +38,8 @@ class JSTypedLoweringTester : public HandleAndZoneScope { common(main_zone()), graph(main_zone()), typer(&js_heap_broker, Typer::kNoFlags, &graph, &tick_counter), - context_node(nullptr) { + context_node(nullptr), + deps(&js_heap_broker, main_zone()) { graph.SetStart(graph.NewNode(common.Start(num_parameters))); graph.SetEnd(graph.NewNode(common.End(1), graph.start())); typer.Run(); @@ -56,6 +58,7 @@ class JSTypedLoweringTester : public HandleAndZoneScope { Graph graph; Typer typer; Node* context_node; + CompilationDependencies deps; Node* Parameter(Type t, int32_t index = 0) { Node* n = graph.NewNode(common.Parameter(index), graph.start()); diff --git a/deps/v8/test/cctest/compiler/test-jump-threading.cc b/deps/v8/test/cctest/compiler/test-jump-threading.cc index a66bfb207f..64c8db7d0b 100644 --- a/deps/v8/test/cctest/compiler/test-jump-threading.cc +++ b/deps/v8/test/cctest/compiler/test-jump-threading.cc @@ -736,7 +736,7 @@ TEST(Rewire1_deferred) { code.Defer(); int j3 = code.Jump(3); // B3 - code.End(); + code.Return(0); static int forward[] = {3, 3, 3, 3}; ApplyForwarding(&code, kBlockCount, forward); @@ -774,6 +774,29 @@ TEST(Rewire2_deferred) { CheckAssemblyOrder(&code, kBlockCount, assembly); } +TEST(Rewire_deferred_diamond) { + constexpr size_t kBlockCount = 4; + TestCode code(kBlockCount); + + // B0 + int b1 = code.Branch(1, 2); + // B1 + code.Fallthru(); // To B3 + // B2 + code.Defer(); + int j1 = code.Jump(3); + // B3 + code.Return(0); + + static int forward[] = {0, 3, 3, 3}; + VerifyForwarding(&code, kBlockCount, forward); + ApplyForwarding(&code, kBlockCount, forward); + CheckBranch(&code, b1, 3, 3); + CheckNop(&code, j1); + + static int assembly[] = {0, 1, 2, 1}; + CheckAssemblyOrder(&code, kBlockCount, assembly); +} TEST(Rewire_diamond) { constexpr size_t kBlockCount = 5; diff --git a/deps/v8/test/cctest/compiler/test-linkage.cc b/deps/v8/test/cctest/compiler/test-linkage.cc index 7157dfdf39..ec801a8af4 100644 --- a/deps/v8/test/cctest/compiler/test-linkage.cc +++ b/deps/v8/test/cctest/compiler/test-linkage.cc @@ -6,6 +6,7 @@ #include "src/codegen/code-factory.h" #include "src/codegen/compiler.h" #include "src/codegen/optimized-compilation-info.h" +#include "src/codegen/script-details.h" #include "src/compiler/common-operator.h" #include "src/compiler/graph.h" #include "src/compiler/linkage.h" @@ -34,8 +35,7 @@ static Handle<JSFunction> Compile(const char* source) { .ToHandleChecked(); Handle<SharedFunctionInfo> shared = Compiler::GetSharedFunctionInfoForScript( - isolate, source_code, Compiler::ScriptDetails(), - v8::ScriptOriginOptions(), nullptr, nullptr, + isolate, source_code, ScriptDetails(), nullptr, nullptr, v8::ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE) .ToHandleChecked(); diff --git a/deps/v8/test/cctest/heap/test-heap.cc b/deps/v8/test/cctest/heap/test-heap.cc index 930084f61d..2974b82cb0 100644 --- a/deps/v8/test/cctest/heap/test-heap.cc +++ b/deps/v8/test/cctest/heap/test-heap.cc @@ -34,6 +34,7 @@ #include "src/codegen/assembler-inl.h" #include "src/codegen/compilation-cache.h" #include "src/codegen/macro-assembler-inl.h" +#include "src/codegen/script-details.h" #include "src/common/globals.h" #include "src/debug/debug.h" #include "src/deoptimizer/deoptimizer.h" @@ -1489,10 +1490,10 @@ TEST(CompilationCacheCachingBehavior) { // The script should be in the cache now. { v8::HandleScope scope(CcTest::isolate()); + ScriptDetails script_details(Handle<Object>(), + v8::ScriptOriginOptions(true, false)); MaybeHandle<SharedFunctionInfo> cached_script = - compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, - v8::ScriptOriginOptions(true, false), - language_mode); + compilation_cache->LookupScript(source, script_details, language_mode); CHECK(!cached_script.is_null()); } @@ -1500,10 +1501,10 @@ TEST(CompilationCacheCachingBehavior) { { CcTest::CollectAllGarbage(); v8::HandleScope scope(CcTest::isolate()); + ScriptDetails script_details(Handle<Object>(), + v8::ScriptOriginOptions(true, false)); MaybeHandle<SharedFunctionInfo> cached_script = - compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, - v8::ScriptOriginOptions(true, false), - language_mode); + compilation_cache->LookupScript(source, script_details, language_mode); CHECK(!cached_script.is_null()); // Progress code age until it's old and ready for GC. @@ -1520,10 +1521,10 @@ TEST(CompilationCacheCachingBehavior) { { v8::HandleScope scope(CcTest::isolate()); // Ensure code aging cleared the entry from the cache. + ScriptDetails script_details(Handle<Object>(), + v8::ScriptOriginOptions(true, false)); MaybeHandle<SharedFunctionInfo> cached_script = - compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, - v8::ScriptOriginOptions(true, false), - language_mode); + compilation_cache->LookupScript(source, script_details, language_mode); CHECK(cached_script.is_null()); } } @@ -5317,7 +5318,7 @@ TEST(OldSpaceAllocationCounter) { static void CheckLeak(const v8::FunctionCallbackInfo<v8::Value>& args) { Isolate* isolate = CcTest::i_isolate(); Object message( - *reinterpret_cast<Address*>(isolate->pending_message_obj_address())); + *reinterpret_cast<Address*>(isolate->pending_message_address())); CHECK(message.IsTheHole(isolate)); } diff --git a/deps/v8/test/cctest/heap/test-lab.cc b/deps/v8/test/cctest/heap/test-lab.cc index 6f39298a33..f277c6d846 100644 --- a/deps/v8/test/cctest/heap/test-lab.cc +++ b/deps/v8/test/cctest/heap/test-lab.cc @@ -95,11 +95,8 @@ TEST(SimpleAllocate) { LocalAllocationBuffer lab = LocalAllocationBuffer::FromResult(heap, lab_backing_store, kLabSize); CHECK(lab.IsValid()); - intptr_t sum = 0; for (auto size : sizes) { - if (AllocateFromLab(heap, &lab, size)) { - sum += size; - } + AllocateFromLab(heap, &lab, size); } } VerifyIterable(base, limit, expected_sizes); diff --git a/deps/v8/test/cctest/interpreter/generate-bytecode-expectations.cc b/deps/v8/test/cctest/interpreter/generate-bytecode-expectations.cc index 0e5a857b92..17b0909059 100644 --- a/deps/v8/test/cctest/interpreter/generate-bytecode-expectations.cc +++ b/deps/v8/test/cctest/interpreter/generate-bytecode-expectations.cc @@ -19,6 +19,8 @@ #ifdef V8_OS_POSIX #include <dirent.h> +#elif V8_OS_WIN +#include <windows.h> #endif using v8::internal::interpreter::BytecodeExpectationsPrinter; diff --git a/deps/v8/test/cctest/libsampler/signals-and-mutexes.cc b/deps/v8/test/cctest/libsampler/signals-and-mutexes.cc index d642501be1..b52365bc1f 100644 --- a/deps/v8/test/cctest/libsampler/signals-and-mutexes.cc +++ b/deps/v8/test/cctest/libsampler/signals-and-mutexes.cc @@ -19,6 +19,8 @@ namespace sampler { // https://stackoverflow.com/questions/22643374/deadlock-with-pthread-rwlock-t-and-signals // This test reproduces it, and can be used to test if this problem is fixed in // future Mac releases. +// Note: For now, we fall back to using pthread_mutex_t to implement SharedMutex +// on Mac, so this test succeeds. #ifdef USE_SIGNALS diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index cb32668ac5..25fba193bb 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -22622,25 +22622,86 @@ TEST(ChainSignatureCheck) { static const char* last_event_message; -static int last_event_status; +// See v8::LogEventStatus +static v8::LogEventStatus last_event_status; +static int event_count = 0; void StoringEventLoggerCallback(const char* message, int status) { last_event_message = message; - last_event_status = status; + last_event_status = static_cast<v8::LogEventStatus>(status); + event_count++; } TEST(EventLogging) { v8::Isolate* isolate = CcTest::isolate(); isolate->SetEventLogger(StoringEventLoggerCallback); - v8::internal::HistogramTimer histogramTimer( - "V8.Test", 0, 10000, v8::internal::HistogramTimerResolution::MILLISECOND, + v8::internal::NestedTimedHistogram histogram( + "V8.Test", 0, 10000, v8::internal::TimedHistogramResolution::MILLISECOND, 50, reinterpret_cast<v8::internal::Isolate*>(isolate)->counters()); - histogramTimer.Start(); - CHECK_EQ(0, strcmp("V8.Test", last_event_message)); - CHECK_EQ(0, last_event_status); - histogramTimer.Stop(); + event_count = 0; + int count = 0; + { + CHECK_EQ(0, event_count); + { + CHECK_EQ(0, event_count); + v8::internal::NestedTimedHistogramScope scope0(&histogram); + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kStart, last_event_status); + CHECK_EQ(++count, event_count); + } + CHECK_EQ(v8::LogEventStatus::kEnd, last_event_status); + CHECK_EQ(++count, event_count); + + v8::internal::NestedTimedHistogramScope scope1(&histogram); + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kStart, last_event_status); + CHECK_EQ(++count, event_count); + { + CHECK_EQ(count, event_count); + v8::internal::NestedTimedHistogramScope scope2(&histogram); + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kStart, last_event_status); + CHECK_EQ(++count, event_count); + { + CHECK_EQ(count, event_count); + v8::internal::NestedTimedHistogramScope scope3(&histogram); + CHECK_EQ(++count, event_count); + v8::internal::PauseNestedTimedHistogramScope scope4(&histogram); + // The outer timer scope is just paused, no event is emited yet. + CHECK_EQ(count, event_count); + { + CHECK_EQ(count, event_count); + v8::internal::NestedTimedHistogramScope scope5(&histogram); + v8::internal::NestedTimedHistogramScope scope5_1(&histogram); + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kStart, last_event_status); + count++; + CHECK_EQ(++count, event_count); + } + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kEnd, last_event_status); + count++; + CHECK_EQ(++count, event_count); + } + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kEnd, last_event_status); + CHECK_EQ(++count, event_count); + v8::internal::PauseNestedTimedHistogramScope scope6(&histogram); + // The outer timer scope is just paused, no event is emited yet. + CHECK_EQ(count, event_count); + { + v8::internal::PauseNestedTimedHistogramScope scope7(&histogram); + CHECK_EQ(count, event_count); + } + CHECK_EQ(count, event_count); + } + CHECK_EQ(0, strcmp("V8.Test", last_event_message)); + CHECK_EQ(v8::LogEventStatus::kEnd, last_event_status); + CHECK_EQ(++count, event_count); + } CHECK_EQ(0, strcmp("V8.Test", last_event_message)); - CHECK_EQ(1, last_event_status); + CHECK_EQ(v8::LogEventStatus::kEnd, last_event_status); + CHECK_EQ(++count, event_count); } TEST(PropertyDescriptor) { @@ -24378,7 +24439,7 @@ TEST(CreateSyntheticModule) { .IsUndefined()); CHECK_EQ(i_module->export_names().length(), 1); CHECK(i::String::cast(i_module->export_names().get(0)).Equals(*default_name)); - CHECK_EQ(i_module->status(), i::Module::kInstantiated); + CHECK_EQ(i_module->status(), i::Module::kLinked); CHECK(module->IsSyntheticModule()); CHECK(!module->IsSourceTextModule()); CHECK_EQ(module->GetModuleRequests()->Length(), 0); @@ -28737,7 +28798,7 @@ TEST(FastApiCalls) { #ifndef V8_LITE_MODE namespace { void FastCallback1TypedArray(v8::Local<v8::Object> receiver, int arg0, - v8::FastApiTypedArray<double> arg1) { + const v8::FastApiTypedArray<double>& arg1) { // TODO(mslekova): Use the TypedArray parameter } @@ -29251,3 +29312,57 @@ TEST(TestSetSabConstructorEnabledCallback) { sab_constructor_enabled_value = true; CHECK(i_isolate->IsSharedArrayBufferConstructorEnabled(i_context)); } + +namespace { +void NodeTypeCallback(const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Isolate* isolate = args.GetIsolate(); + args.GetReturnValue().Set(v8::Number::New(isolate, 1)); +} +} // namespace + +TEST(EmbedderInstanceTypes) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + i::FLAG_embedder_instance_types = true; + Local<FunctionTemplate> node = FunctionTemplate::New(isolate); + Local<ObjectTemplate> proto_template = node->PrototypeTemplate(); + Local<FunctionTemplate> nodeType = v8::FunctionTemplate::New( + isolate, NodeTypeCallback, Local<Value>(), + v8::Signature::New(isolate, node), 0, v8::ConstructorBehavior::kThrow, + v8::SideEffectType::kHasSideEffect, nullptr, 0, 1, 3); + proto_template->SetAccessorProperty( + String::NewFromUtf8Literal(isolate, "nodeType"), nodeType); + + Local<FunctionTemplate> element = FunctionTemplate::New( + isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0, + v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect, + nullptr, 1); + element->Inherit(node); + + Local<FunctionTemplate> html_element = FunctionTemplate::New( + isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0, + v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect, + nullptr, 2); + html_element->Inherit(element); + + Local<FunctionTemplate> div_element = FunctionTemplate::New( + isolate, nullptr, Local<Value>(), Local<v8::Signature>(), 0, + v8::ConstructorBehavior::kAllow, v8::SideEffectType::kHasSideEffect, + nullptr, 3); + div_element->Inherit(html_element); + + CHECK(env->Global() + ->Set(env.local(), v8_str("div"), + div_element->GetFunction(env.local()) + .ToLocalChecked() + ->NewInstance(env.local()) + .ToLocalChecked()) + .FromJust()); + + CompileRun("var x = div.nodeType;"); + + Local<Value> res = + env->Global()->Get(env.local(), v8_str("x")).ToLocalChecked(); + CHECK_EQ(1, res->ToInt32(env.local()).ToLocalChecked()->Value()); +} diff --git a/deps/v8/test/cctest/test-atomicops.cc b/deps/v8/test/cctest/test-atomicops.cc index 3ab3ac7c37..9d28cd484e 100644 --- a/deps/v8/test/cctest/test-atomicops.cc +++ b/deps/v8/test/cctest/test-atomicops.cc @@ -286,5 +286,22 @@ TEST(Load) { TestLoad<AtomicWord>(); } +TEST(Relaxed_Memmove) { + constexpr size_t kLen = 6; + Atomic8 arr[kLen]; + { + for (size_t i = 0; i < kLen; ++i) arr[i] = i; + Relaxed_Memmove(arr + 2, arr + 3, 2); + uint8_t expected[]{0, 1, 3, 4, 4, 5}; + for (size_t i = 0; i < kLen; ++i) CHECK_EQ(arr[i], expected[i]); + } + { + for (size_t i = 0; i < kLen; ++i) arr[i] = i; + Relaxed_Memmove(arr + 3, arr + 2, 2); + uint8_t expected[]{0, 1, 2, 2, 3, 5}; + for (size_t i = 0; i < kLen; ++i) CHECK_EQ(arr[i], expected[i]); + } +} + } // namespace base } // namespace v8 diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index 702046ade6..ee255d7b1f 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/deps/v8/test/cctest/test-compiler.cc @@ -27,18 +27,19 @@ #include <stdlib.h> #include <wchar.h> -#include <memory> -#include "src/init/v8.h" +#include <memory> #include "include/v8-profiler.h" #include "include/v8.h" #include "src/api/api-inl.h" #include "src/codegen/compilation-cache.h" #include "src/codegen/compiler.h" +#include "src/codegen/script-details.h" #include "src/diagnostics/disasm.h" #include "src/heap/factory.h" #include "src/heap/spaces.h" +#include "src/init/v8.h" #include "src/interpreter/interpreter.h" #include "src/objects/allocation-site-inl.h" #include "src/objects/objects-inl.h" @@ -72,8 +73,7 @@ static Handle<JSFunction> Compile(const char* source) { .ToHandleChecked(); Handle<SharedFunctionInfo> shared = Compiler::GetSharedFunctionInfoForScript( - isolate, source_code, Compiler::ScriptDetails(), - v8::ScriptOriginOptions(), nullptr, nullptr, + isolate, source_code, ScriptDetails(), nullptr, nullptr, v8::ScriptCompiler::kNoCompileOptions, ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE) .ToHandleChecked(); diff --git a/deps/v8/test/cctest/test-field-type-tracking.cc b/deps/v8/test/cctest/test-field-type-tracking.cc index b822b02828..342dd46d53 100644 --- a/deps/v8/test/cctest/test-field-type-tracking.cc +++ b/deps/v8/test/cctest/test-field-type-tracking.cc @@ -70,7 +70,9 @@ static void CheckMigrationTarget(Isolate* isolate, Map old_map, Map new_map) { .GetMigrationTarget(); if (target.is_null()) return; CHECK_EQ(new_map, target); - CHECK_EQ(Map::TryUpdateSlow(isolate, old_map), target); + CHECK_EQ(MapUpdater::TryUpdateNoLock(isolate, old_map, + ConcurrencyMode::kNotConcurrent), + target); } class Expectations { @@ -1831,8 +1833,8 @@ static void TestReconfigureElementsKind_GeneralizeFieldInPlace( { MapHandles map_list; map_list.push_back(updated_map); - Map transitioned_map = - map2->FindElementsKindTransitionedMap(isolate, map_list); + Map transitioned_map = map2->FindElementsKindTransitionedMap( + isolate, map_list, ConcurrencyMode::kNotConcurrent); CHECK_EQ(*updated_map, transitioned_map); } } diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index 743cb6e8f3..dc23a8f601 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -2358,7 +2358,7 @@ TEST(HiddenPropertiesFastCase) { GetProperty(isolate, global, v8::HeapGraphEdge::kProperty, "c"); CHECK(c); const v8::HeapGraphNode* hidden_props = - GetProperty(isolate, global, v8::HeapGraphEdge::kProperty, "<symbol>"); + GetProperty(isolate, c, v8::HeapGraphEdge::kProperty, "<symbol key>"); CHECK(!hidden_props); v8::Local<v8::Value> cHandle = @@ -2377,10 +2377,32 @@ TEST(HiddenPropertiesFastCase) { c = GetProperty(isolate, global, v8::HeapGraphEdge::kProperty, "c"); CHECK(c); hidden_props = - GetProperty(isolate, c, v8::HeapGraphEdge::kProperty, "<symbol>"); + GetProperty(isolate, c, v8::HeapGraphEdge::kProperty, "<symbol key>"); CHECK(hidden_props); } +TEST(SymbolsAndPrivateClassFields) { + v8::Isolate* isolate = CcTest::isolate(); + LocalContext env; + v8::HandleScope scope(isolate); + v8::HeapProfiler* heap_profiler = isolate->GetHeapProfiler(); + + CompileRun( + "class C { #private = this; [Symbol('MySymbol')] = this; };\n" + "c = new C;\n"); + const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); + CHECK(ValidateSnapshot(snapshot)); + const v8::HeapGraphNode* global = GetGlobalObject(snapshot); + const v8::HeapGraphNode* c = + GetProperty(isolate, global, v8::HeapGraphEdge::kProperty, "c"); + CHECK(c); + const v8::HeapGraphNode* prop; + prop = GetProperty(isolate, c, v8::HeapGraphEdge::kProperty, "#private"); + CHECK(prop); + prop = GetProperty(isolate, c, v8::HeapGraphEdge::kProperty, + "<symbol MySymbol>"); + CHECK(prop); +} TEST(AccessorInfo) { LocalContext env; diff --git a/deps/v8/test/cctest/test-icache.cc b/deps/v8/test/cctest/test-icache.cc index 529701c227..f68789df2c 100644 --- a/deps/v8/test/cctest/test-icache.cc +++ b/deps/v8/test/cctest/test-icache.cc @@ -189,15 +189,23 @@ TEST(TestFlushICacheOfWritableAndExecutable) { CHECK(SetPermissions(GetPlatformPageAllocator(), buffer->start(), buffer->size(), v8::PageAllocator::kReadWriteExecute)); - SwitchMemoryPermissionsToWritable(); - FloodWithInc(isolate, buffer.get()); - FlushInstructionCache(buffer->start(), buffer->size()); - SwitchMemoryPermissionsToExecutable(); + { +#if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64) + // Make sure to switch memory to writable on M1 hardware. + wasm::CodeSpaceWriteScope code_space_write_scope(nullptr); +#endif + FloodWithInc(isolate, buffer.get()); + FlushInstructionCache(buffer->start(), buffer->size()); + } CHECK_EQ(23 + kNumInstr, f.Call(23)); // Call into generated code. - SwitchMemoryPermissionsToWritable(); - FloodWithNop(isolate, buffer.get()); - FlushInstructionCache(buffer->start(), buffer->size()); - SwitchMemoryPermissionsToExecutable(); + { +#if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64) + // Make sure to switch memory to writable on M1 hardware. + wasm::CodeSpaceWriteScope code_space_write_scope(nullptr); +#endif + FloodWithNop(isolate, buffer.get()); + FlushInstructionCache(buffer->start(), buffer->size()); + } CHECK_EQ(23, f.Call(23)); // Call into generated code. } } diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 1abdfa10e9..b78052c9cd 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -33,6 +33,7 @@ #include "src/codegen/compilation-cache.h" #include "src/codegen/compiler.h" #include "src/codegen/macro-assembler-inl.h" +#include "src/codegen/script-details.h" #include "src/common/assert-scope.h" #include "src/debug/debug.h" #include "src/heap/heap-inl.h" @@ -1570,30 +1571,30 @@ int CountBuiltins() { } static Handle<SharedFunctionInfo> CompileScript( - Isolate* isolate, Handle<String> source, Handle<String> name, - ScriptData* cached_data, v8::ScriptCompiler::CompileOptions options) { + Isolate* isolate, Handle<String> source, + const ScriptDetails& script_details, AlignedCachedData* cached_data, + v8::ScriptCompiler::CompileOptions options) { return Compiler::GetSharedFunctionInfoForScript( - isolate, source, Compiler::ScriptDetails(name), - v8::ScriptOriginOptions(), nullptr, cached_data, options, + isolate, source, script_details, nullptr, cached_data, options, ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE) .ToHandleChecked(); } static Handle<SharedFunctionInfo> CompileScriptAndProduceCache( - Isolate* isolate, Handle<String> source, Handle<String> name, - ScriptData** script_data, v8::ScriptCompiler::CompileOptions options) { + Isolate* isolate, Handle<String> source, + const ScriptDetails& script_details, AlignedCachedData** out_cached_data, + v8::ScriptCompiler::CompileOptions options) { Handle<SharedFunctionInfo> sfi = Compiler::GetSharedFunctionInfoForScript( - isolate, source, Compiler::ScriptDetails(name), - v8::ScriptOriginOptions(), nullptr, nullptr, options, + isolate, source, script_details, nullptr, nullptr, options, ScriptCompiler::kNoCacheNoReason, NOT_NATIVES_CODE) .ToHandleChecked(); std::unique_ptr<ScriptCompiler::CachedData> cached_data( ScriptCompiler::CreateCodeCache(ToApiHandle<UnboundScript>(sfi))); uint8_t* buffer = NewArray<uint8_t>(cached_data->length); MemCopy(buffer, cached_data->data, cached_data->length); - *script_data = new i::ScriptData(buffer, cached_data->length); - (*script_data)->AcquireDataOwnership(); + *out_cached_data = new i::AlignedCachedData(buffer, cached_data->length); + (*out_cached_data)->AcquireDataOwnership(); return sfi; } @@ -1619,20 +1620,21 @@ TEST(CodeSerializerWithProfiler) { CHECK(!orig_source.is_identical_to(copy_source)); CHECK(orig_source->Equals(*copy_source)); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; + ScriptDetails default_script_details; Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, orig_source, Handle<String>(), &cache, + isolate, orig_source, default_script_details, &cache, v8::ScriptCompiler::kNoCompileOptions); CHECK(!orig->GetBytecodeArray(isolate).HasSourcePositionTable()); - isolate->set_is_profiling(true); + isolate->SetIsProfiling(true); // This does not assert that no compilation can happen as source position // collection could trigger it. Handle<SharedFunctionInfo> copy = - CompileScript(isolate, copy_source, Handle<String>(), cache, + CompileScript(isolate, copy_source, default_script_details, cache, v8::ScriptCompiler::kConsumeCodeCache); // Since the profiler is now enabled, source positions should be collected @@ -1661,10 +1663,11 @@ void TestCodeSerializerOnePlusOneImpl(bool verify_builtins_count = true) { CHECK(!orig_source.is_identical_to(copy_source)); CHECK(orig_source->Equals(*copy_source)); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; + ScriptDetails default_script_details; Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, orig_source, Handle<String>(), &cache, + isolate, orig_source, default_script_details, &cache, v8::ScriptCompiler::kNoCompileOptions); int builtins_count = CountBuiltins(); @@ -1672,7 +1675,7 @@ void TestCodeSerializerOnePlusOneImpl(bool verify_builtins_count = true) { Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, copy_source, Handle<String>(), cache, + copy = CompileScript(isolate, copy_source, default_script_details, cache, v8::ScriptCompiler::kConsumeCodeCache); } @@ -1719,23 +1722,126 @@ TEST(CodeSerializerPromotedToCompilationCache) { const char* source = "1 + 1"; - Handle<String> src = isolate->factory() - ->NewStringFromUtf8(base::CStrVector(source)) - .ToHandleChecked(); - ScriptData* cache = nullptr; - - CompileScriptAndProduceCache(isolate, src, src, &cache, + Handle<String> src = isolate->factory()->NewStringFromAsciiChecked(source); + AlignedCachedData* cache = nullptr; + + Handle<FixedArray> default_host_defined_options = + isolate->factory()->NewFixedArray(2); + default_host_defined_options->set(0, Smi::FromInt(0)); + const char* default_host_defined_option_1_string = "custom string"; + Handle<String> default_host_defined_option_1 = + isolate->factory()->NewStringFromAsciiChecked( + default_host_defined_option_1_string); + default_host_defined_options->set(1, *default_host_defined_option_1); + + ScriptDetails default_script_details(src); + default_script_details.host_defined_options = default_host_defined_options; + CompileScriptAndProduceCache(isolate, src, default_script_details, &cache, v8::ScriptCompiler::kNoCompileOptions); DisallowCompilation no_compile_expected(isolate); - Handle<SharedFunctionInfo> copy = CompileScript( - isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache); + Handle<SharedFunctionInfo> copy = + CompileScript(isolate, src, default_script_details, cache, + v8::ScriptCompiler::kConsumeCodeCache); - MaybeHandle<SharedFunctionInfo> shared = - isolate->compilation_cache()->LookupScript( - src, src, 0, 0, v8::ScriptOriginOptions(), LanguageMode::kSloppy); + { + ScriptDetails script_details(src); + script_details.host_defined_options = + default_script_details.host_defined_options; + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK_EQ(*shared.ToHandleChecked(), *copy); + } - CHECK(*shared.ToHandleChecked() == *copy); + { + // Lookup with strictly equal host_defined_options should succeed: + ScriptDetails script_details(src); + Handle<FixedArray> host_defined_options = + isolate->factory()->NewFixedArray(2); + host_defined_options->set(0, default_host_defined_options->get(0)); + Handle<String> host_defined_option_1 = + isolate->factory()->NewStringFromAsciiChecked( + default_host_defined_option_1_string); + host_defined_options->set(1, *host_defined_option_1); + script_details.host_defined_options = host_defined_options; + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK_EQ(*shared.ToHandleChecked(), *copy); + } + + { + // Lookup with different string with same contents should succeed: + ScriptDetails script_details( + isolate->factory()->NewStringFromAsciiChecked(source)); + script_details.host_defined_options = + default_script_details.host_defined_options; + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK_EQ(*shared.ToHandleChecked(), *copy); + } + + { + // Lookup with different string should fail: + ScriptDetails script_details( + isolate->factory()->NewStringFromAsciiChecked("other")); + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK(shared.is_null()); + } + + { + // Lookup with different position should fail: + ScriptDetails script_details(src); + script_details.line_offset = 0xFF; + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK(shared.is_null()); + } + + { + // Lookup with different position should fail: + ScriptDetails script_details(src); + script_details.column_offset = 0xFF; + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK(shared.is_null()); + } + + { + // Lookup with different language mode should fail: + ScriptDetails script_details(src); + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kStrict); + CHECK(shared.is_null()); + } + + { + // Lookup with different script_options should fail + ScriptOriginOptions origin_options(false, true); + CHECK_NE(ScriptOriginOptions().Flags(), origin_options.Flags()); + ScriptDetails script_details(src, origin_options); + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK(shared.is_null()); + } + + { + // Lookup with different host_defined_options should fail: + ScriptDetails script_details(src); + script_details.host_defined_options = isolate->factory()->NewFixedArray(5); + MaybeHandle<SharedFunctionInfo> shared = + isolate->compilation_cache()->LookupScript(src, script_details, + LanguageMode::kSloppy); + CHECK(shared.is_null()); + } delete cache; } @@ -1761,9 +1867,9 @@ TEST(CodeSerializerInternalizedString) { Handle<JSObject> global(isolate->context().global_object(), isolate); - i::ScriptData* script_data = nullptr; + i::AlignedCachedData* cached_data = nullptr; Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, orig_source, Handle<String>(), &script_data, + isolate, orig_source, ScriptDetails(), &cached_data, v8::ScriptCompiler::kNoCompileOptions); Handle<JSFunction> orig_fun = Factory::JSFunctionBuilder{isolate, orig, isolate->native_context()} @@ -1777,7 +1883,7 @@ TEST(CodeSerializerInternalizedString) { Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, copy_source, Handle<String>(), script_data, + copy = CompileScript(isolate, copy_source, ScriptDetails(), cached_data, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -1796,7 +1902,7 @@ TEST(CodeSerializerInternalizedString) { CHECK(Handle<String>::cast(copy_result)->Equals(*expected)); CHECK_EQ(builtins_count, CountBuiltins()); - delete script_data; + delete cached_data; } TEST(CodeSerializerLargeCodeObject) { @@ -1820,18 +1926,18 @@ TEST(CodeSerializerLargeCodeObject) { isolate->factory()->NewStringFromUtf8(source).ToHandleChecked(); Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, source_str, Handle<String>(), &cache, - v8::ScriptCompiler::kNoCompileOptions); + Handle<SharedFunctionInfo> orig = + CompileScriptAndProduceCache(isolate, source_str, ScriptDetails(), &cache, + v8::ScriptCompiler::kNoCompileOptions); CHECK(isolate->heap()->InSpace(orig->abstract_code(isolate), LO_SPACE)); Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_str, Handle<String>(), cache, + copy = CompileScript(isolate, source_str, ScriptDetails(), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -1887,11 +1993,11 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) { } Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, source_str, Handle<String>(), &cache, - v8::ScriptCompiler::kNoCompileOptions); + Handle<SharedFunctionInfo> orig = + CompileScriptAndProduceCache(isolate, source_str, ScriptDetails(), &cache, + v8::ScriptCompiler::kNoCompileOptions); CHECK(heap->InSpace(orig->abstract_code(isolate), LO_SPACE)); @@ -1906,7 +2012,7 @@ TEST(CodeSerializerLargeCodeObjectWithIncrementalMarking) { Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_str, Handle<String>(), cache, + copy = CompileScript(isolate, source_str, ScriptDetails(), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -1952,16 +2058,16 @@ TEST(CodeSerializerLargeStrings) { .ToHandleChecked(); Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, source_str, Handle<String>(), &cache, - v8::ScriptCompiler::kNoCompileOptions); + Handle<SharedFunctionInfo> orig = + CompileScriptAndProduceCache(isolate, source_str, ScriptDetails(), &cache, + v8::ScriptCompiler::kNoCompileOptions); Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_str, Handle<String>(), cache, + copy = CompileScript(isolate, source_str, ScriptDetails(), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -2026,16 +2132,16 @@ TEST(CodeSerializerThreeBigStrings) { .ToHandleChecked(); Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, source_str, Handle<String>(), &cache, - v8::ScriptCompiler::kNoCompileOptions); + Handle<SharedFunctionInfo> orig = + CompileScriptAndProduceCache(isolate, source_str, ScriptDetails(), &cache, + v8::ScriptCompiler::kNoCompileOptions); Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_str, Handle<String>(), cache, + copy = CompileScript(isolate, source_str, ScriptDetails(), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -2145,16 +2251,16 @@ TEST(CodeSerializerExternalString) { .ToHandleChecked(); Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, source_string, Handle<String>(), &cache, + isolate, source_string, ScriptDetails(), &cache, v8::ScriptCompiler::kNoCompileOptions); Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_string, Handle<String>(), cache, + copy = CompileScript(isolate, source_string, ScriptDetails(), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -2209,16 +2315,16 @@ TEST(CodeSerializerLargeExternalString) { .ToHandleChecked(); Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( - isolate, source_str, Handle<String>(), &cache, - v8::ScriptCompiler::kNoCompileOptions); + Handle<SharedFunctionInfo> orig = + CompileScriptAndProduceCache(isolate, source_str, ScriptDetails(), &cache, + v8::ScriptCompiler::kNoCompileOptions); Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_str, Handle<String>(), cache, + copy = CompileScript(isolate, source_str, ScriptDetails(), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -2263,16 +2369,16 @@ TEST(CodeSerializerExternalScriptName) { CHECK(!name->IsInternalizedString()); Handle<JSObject> global(isolate->context().global_object(), isolate); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - Handle<SharedFunctionInfo> orig = - CompileScriptAndProduceCache(isolate, source_string, name, &cache, - v8::ScriptCompiler::kNoCompileOptions); + Handle<SharedFunctionInfo> orig = CompileScriptAndProduceCache( + isolate, source_string, ScriptDetails(name), &cache, + v8::ScriptCompiler::kNoCompileOptions); Handle<SharedFunctionInfo> copy; { DisallowCompilation no_compile_expected(isolate); - copy = CompileScript(isolate, source_string, name, cache, + copy = CompileScript(isolate, source_string, ScriptDetails(name), cache, v8::ScriptCompiler::kConsumeCodeCache); } CHECK_NE(*orig, *copy); @@ -2631,11 +2737,11 @@ TEST(Regress503552) { HandleScope scope(isolate); Handle<String> source = isolate->factory()->NewStringFromAsciiChecked( "function f() {} function g() {}"); - ScriptData* script_data = nullptr; + AlignedCachedData* cached_data = nullptr; Handle<SharedFunctionInfo> shared = CompileScriptAndProduceCache( - isolate, source, Handle<String>(), &script_data, + isolate, source, ScriptDetails(), &cached_data, v8::ScriptCompiler::kNoCompileOptions); - delete script_data; + delete cached_data; heap::SimulateIncrementalMarking(isolate->heap()); @@ -4020,14 +4126,16 @@ TEST(WeakArraySerializationInCodeCache) { Handle<String> src = isolate->factory() ->NewStringFromUtf8(base::CStrVector(source)) .ToHandleChecked(); - ScriptData* cache = nullptr; + AlignedCachedData* cache = nullptr; - CompileScriptAndProduceCache(isolate, src, src, &cache, + ScriptDetails script_details(src); + CompileScriptAndProduceCache(isolate, src, script_details, &cache, v8::ScriptCompiler::kNoCompileOptions); DisallowCompilation no_compile_expected(isolate); - Handle<SharedFunctionInfo> copy = CompileScript( - isolate, src, src, cache, v8::ScriptCompiler::kConsumeCodeCache); + Handle<SharedFunctionInfo> copy = + CompileScript(isolate, src, script_details, cache, + v8::ScriptCompiler::kConsumeCodeCache); // Verify that the pointers in shared_function_infos are weak. WeakFixedArray sfis = Script::cast(copy->script()).shared_function_infos(); diff --git a/deps/v8/test/cctest/test-stack-unwinding-win64.cc b/deps/v8/test/cctest/test-stack-unwinding-win64.cc index cd0243723b..138f4822fa 100644 --- a/deps/v8/test/cctest/test-stack-unwinding-win64.cc +++ b/deps/v8/test/cctest/test-stack-unwinding-win64.cc @@ -12,6 +12,11 @@ #define CONTEXT_PC(context) (context.Pc) #endif +#include <windows.h> + +// This has to come after windows.h. +#include <versionhelpers.h> // For IsWindows8OrGreater(). + class UnwindingWin64Callbacks { public: UnwindingWin64Callbacks() = default; diff --git a/deps/v8/test/cctest/test-thread-termination.cc b/deps/v8/test/cctest/test-thread-termination.cc index dabd7b0dfe..93f899d559 100644 --- a/deps/v8/test/cctest/test-thread-termination.cc +++ b/deps/v8/test/cctest/test-thread-termination.cc @@ -239,6 +239,14 @@ TEST(TerminateBigIntToString) { "fail();"); } +TEST(TerminateBigIntFromString) { + TestTerminatingSlowOperation( + "var a = '12344567890'.repeat(10000);\n" + "terminate();\n" + "BigInt(a);\n" + "fail();\n"); +} + int call_count = 0; diff --git a/deps/v8/test/cctest/test-web-snapshots.cc b/deps/v8/test/cctest/test-web-snapshots.cc index c616b8428e..56c79d075a 100644 --- a/deps/v8/test/cctest/test-web-snapshots.cc +++ b/deps/v8/test/cctest/test-web-snapshots.cc @@ -366,8 +366,65 @@ TEST(SFIDeduplication) { } } +TEST(SFIDeduplicationClasses) { + CcTest::InitializeVM(); + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + + WebSnapshotData snapshot_data; + { + v8::Local<v8::Context> new_context = CcTest::NewContext(); + v8::Context::Scope context_scope(new_context); + const char* snapshot_source = + "let foo = {};\n" + "foo.create = function(a) {\n" + " return class {\n" + " constructor(x) {this.x = x;};\n" + " }\n" + "}\n" + "foo.class = foo.create('hi');"; + + CompileRun(snapshot_source); + v8::Local<v8::PrimitiveArray> exports = v8::PrimitiveArray::New(isolate, 1); + v8::Local<v8::String> str = + v8::String::NewFromUtf8(isolate, "foo").ToLocalChecked(); + exports->Set(isolate, 0, str); + WebSnapshotSerializer serializer(isolate); + CHECK(serializer.TakeSnapshot(new_context, exports, snapshot_data)); + CHECK(!serializer.has_error()); + CHECK_NOT_NULL(snapshot_data.buffer); + } + + { + v8::Local<v8::Context> new_context = CcTest::NewContext(); + v8::Context::Scope context_scope(new_context); + WebSnapshotDeserializer deserializer(isolate); + CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, + snapshot_data.buffer_size)); + CHECK(!deserializer.has_error()); + + const char* get_class = "foo.class"; + const char* create_new_class = "foo.create()"; + + // Verify that foo.inner and the JSFunction which is the result of calling + // foo.outer() after deserialization share the SFI. + v8::Local<v8::Function> v8_class1 = + CompileRun(get_class).As<v8::Function>(); + v8::Local<v8::Function> v8_class2 = + CompileRun(create_new_class).As<v8::Function>(); + + Handle<JSFunction> class1 = + Handle<JSFunction>::cast(Utils::OpenHandle(*v8_class1)); + Handle<JSFunction> class2 = + Handle<JSFunction>::cast(Utils::OpenHandle(*v8_class2)); + + CHECK_EQ(class1->shared(), class2->shared()); + } +} + TEST(SFIDeduplicationAfterBytecodeFlushing) { - FLAG_stress_flush_bytecode = true; + FLAG_stress_flush_code = true; + FLAG_flush_bytecode = true; CcTest::InitializeVM(); v8::Isolate* isolate = CcTest::isolate(); @@ -451,6 +508,92 @@ TEST(SFIDeduplicationAfterBytecodeFlushing) { } } +TEST(SFIDeduplicationAfterBytecodeFlushingClasses) { + FLAG_stress_flush_code = true; + FLAG_flush_bytecode = true; + CcTest::InitializeVM(); + v8::Isolate* isolate = CcTest::isolate(); + + WebSnapshotData snapshot_data; + { + v8::HandleScope scope(isolate); + v8::Local<v8::Context> new_context = CcTest::NewContext(); + v8::Context::Scope context_scope(new_context); + + const char* snapshot_source = + "let foo = {};\n" + "foo.create = function(a) {\n" + " return class {\n" + " constructor(x) {this.x = x;};\n" + " }\n" + "}\n" + "foo.class = foo.create('hi');"; + + CompileRun(snapshot_source); + + v8::Local<v8::PrimitiveArray> exports = v8::PrimitiveArray::New(isolate, 1); + v8::Local<v8::String> str = + v8::String::NewFromUtf8(isolate, "foo").ToLocalChecked(); + exports->Set(isolate, 0, str); + WebSnapshotSerializer serializer(isolate); + CHECK(serializer.TakeSnapshot(new_context, exports, snapshot_data)); + CHECK(!serializer.has_error()); + CHECK_NOT_NULL(snapshot_data.buffer); + } + + CcTest::CollectAllGarbage(); + CcTest::CollectAllGarbage(); + + { + v8::HandleScope scope(isolate); + v8::Local<v8::Context> new_context = CcTest::NewContext(); + v8::Context::Scope context_scope(new_context); + WebSnapshotDeserializer deserializer(isolate); + CHECK(deserializer.UseWebSnapshot(snapshot_data.buffer, + snapshot_data.buffer_size)); + CHECK(!deserializer.has_error()); + + const char* get_create = "foo.create"; + const char* get_class = "foo.class"; + const char* create_new_class = "foo.create()"; + + v8::Local<v8::Function> v8_create = + CompileRun(get_create).As<v8::Function>(); + Handle<JSFunction> create = + Handle<JSFunction>::cast(Utils::OpenHandle(*v8_create)); + CHECK(!create->shared().is_compiled()); + + v8::Local<v8::Function> v8_class1 = + CompileRun(get_class).As<v8::Function>(); + v8::Local<v8::Function> v8_class2 = + CompileRun(create_new_class).As<v8::Function>(); + + Handle<JSFunction> class1 = + Handle<JSFunction>::cast(Utils::OpenHandle(*v8_class1)); + Handle<JSFunction> class2 = + Handle<JSFunction>::cast(Utils::OpenHandle(*v8_class2)); + + CHECK(create->shared().is_compiled()); + CHECK_EQ(class1->shared(), class2->shared()); + + // Force bytecode flushing of "foo.outer". + CcTest::CollectAllGarbage(); + CcTest::CollectAllGarbage(); + + CHECK(!create->shared().is_compiled()); + + // Create another inner function. + v8::Local<v8::Function> v8_class3 = + CompileRun(create_new_class).As<v8::Function>(); + Handle<JSFunction> class3 = + Handle<JSFunction>::cast(Utils::OpenHandle(*v8_class3)); + + // Check that it shares the SFI with the original inner function which is in + // the snapshot. + CHECK_EQ(class1->shared(), class3->shared()); + } +} + TEST(SFIDeduplicationOfFunctionsNotInSnapshot) { CcTest::InitializeVM(); v8::Isolate* isolate = CcTest::isolate(); diff --git a/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc b/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc index f819fac2ca..e671d247ce 100644 --- a/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc +++ b/deps/v8/test/cctest/wasm/test-jump-table-assembler.cc @@ -159,8 +159,8 @@ void CompileJumpTableThunk(Address thunk, Address jump_target) { FlushInstructionCache(thunk, kThunkBufferSize); #if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64) // MacOS on arm64 refuses {mprotect} calls to toggle permissions of RWX - // memory. Simply do nothing here, and rely on - // {SwitchMemoryPermissionsToExecutable} in the JumpTableRunner. + // memory. Simply do nothing here, as the space will by default be executable + // and non-writable for the JumpTableRunner. #else CHECK(SetPermissions(GetPlatformPageAllocator(), thunk, kThunkBufferSize, v8::PageAllocator::kReadExecute)); @@ -176,7 +176,6 @@ class JumpTableRunner : public v8::base::Thread { void Run() override { TRACE("Runner #%d is starting ...\n", runner_id_); - SwitchMemoryPermissionsToExecutable(); GeneratedCode<void>::FromAddress(CcTest::i_isolate(), slot_address_).Call(); TRACE("Runner #%d is stopping ...\n", runner_id_); USE(runner_id_); @@ -199,7 +198,10 @@ class JumpTablePatcher : public v8::base::Thread { void Run() override { TRACE("Patcher %p is starting ...\n", this); - SwitchMemoryPermissionsToWritable(); +#if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64) + // Make sure to switch memory to writable on M1 hardware. + CodeSpaceWriteScope code_space_write_scope(nullptr); +#endif Address slot_address = slot_start_ + JumpTableAssembler::JumpSlotIndexToOffset(slot_index_); // First, emit code to the two thunks. @@ -250,7 +252,6 @@ TEST(JumpTablePatchingStress) { std::bitset<kAvailableBufferSlots> used_thunk_slots; buffer->MakeWritableAndExecutable(); - SwitchMemoryPermissionsToWritable(); // Iterate through jump-table slots to hammer at different alignments within // the jump-table, thereby increasing stress for variable-length ISAs. @@ -259,22 +260,29 @@ TEST(JumpTablePatchingStress) { TRACE("Hammering on jump table slot #%d ...\n", slot); uint32_t slot_offset = JumpTableAssembler::JumpSlotIndexToOffset(slot); std::vector<std::unique_ptr<TestingAssemblerBuffer>> thunk_buffers; - // Patch the jump table slot to jump to itself. This will later be patched - // by the patchers. - Address slot_addr = - slot_start + JumpTableAssembler::JumpSlotIndexToOffset(slot); - JumpTableAssembler::PatchJumpTableSlot(slot_addr, kNullAddress, slot_addr); - // For each patcher, generate two thunks where this patcher can emit code - // which finally jumps back to {slot} in the jump table. std::vector<Address> patcher_thunks; - for (int i = 0; i < 2 * kNumberOfPatcherThreads; ++i) { - Address thunk = - AllocateJumpTableThunk(slot_start + slot_offset, thunk_slot_buffer, - &used_thunk_slots, &thunk_buffers); - ZapCode(thunk, kThunkBufferSize); - patcher_thunks.push_back(thunk); - TRACE(" generated jump thunk: " V8PRIxPTR_FMT "\n", - patcher_thunks.back()); + { +#if defined(V8_OS_MACOSX) && defined(V8_HOST_ARCH_ARM64) + // Make sure to switch memory to writable on M1 hardware. + CodeSpaceWriteScope code_space_write_scope(nullptr); +#endif + // Patch the jump table slot to jump to itself. This will later be patched + // by the patchers. + Address slot_addr = + slot_start + JumpTableAssembler::JumpSlotIndexToOffset(slot); + JumpTableAssembler::PatchJumpTableSlot(slot_addr, kNullAddress, + slot_addr); + // For each patcher, generate two thunks where this patcher can emit code + // which finally jumps back to {slot} in the jump table. + for (int i = 0; i < 2 * kNumberOfPatcherThreads; ++i) { + Address thunk = + AllocateJumpTableThunk(slot_start + slot_offset, thunk_slot_buffer, + &used_thunk_slots, &thunk_buffers); + ZapCode(thunk, kThunkBufferSize); + patcher_thunks.push_back(thunk); + TRACE(" generated jump thunk: " V8PRIxPTR_FMT "\n", + patcher_thunks.back()); + } } // Start multiple runner threads that execute the jump table slot diff --git a/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc b/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc index ee93220bb1..2e3cdf48ca 100644 --- a/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc +++ b/deps/v8/test/cctest/wasm/test-liftoff-inspection.cc @@ -46,10 +46,10 @@ class LiftoffCompileEnvironment { WasmFeatures detected2; WasmCompilationResult result1 = ExecuteLiftoffCompilation( &env, test_func.body, test_func.code->index(), kNoDebugging, - isolate_->counters(), &detected1); + LiftoffOptions{}.set_detected_features(&detected1)); WasmCompilationResult result2 = ExecuteLiftoffCompilation( &env, test_func.body, test_func.code->index(), kNoDebugging, - isolate_->counters(), &detected2); + LiftoffOptions{}.set_detected_features(&detected2)); CHECK(result1.succeeded()); CHECK(result2.succeeded()); @@ -71,11 +71,12 @@ class LiftoffCompileEnvironment { auto test_func = AddFunction(return_types, param_types, raw_function_bytes); CompilationEnv env = wasm_runner_.builder().CreateCompilationEnv(); - WasmFeatures detected; std::unique_ptr<DebugSideTable> debug_side_table_via_compilation; auto result = ExecuteLiftoffCompilation( - &env, test_func.body, 0, kForDebugging, nullptr, &detected, - base::VectorOf(breakpoints), &debug_side_table_via_compilation); + &env, test_func.body, 0, kForDebugging, + LiftoffOptions{} + .set_breakpoints(base::VectorOf(breakpoints)) + .set_debug_sidetable(&debug_side_table_via_compilation)); CHECK(result.succeeded()); // If there are no breakpoint, then {ExecuteLiftoffCompilation} should diff --git a/deps/v8/test/cctest/wasm/test-run-wasm.cc b/deps/v8/test/cctest/wasm/test-run-wasm.cc index 1eddee2e6d..366a614cc0 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm.cc @@ -1053,35 +1053,41 @@ WASM_EXEC_TEST(BrTable_loop_target) { CHECK_EQ(1, r.Call(0)); } -WASM_EXEC_TEST(F32ReinterpretI32) { +WASM_EXEC_TEST(I32ReinterpretF32) { WasmRunner<int32_t> r(execution_tier); - int32_t* memory = - r.builder().AddMemoryElems<int32_t>(kWasmPageSize / sizeof(int32_t)); + float* memory = + r.builder().AddMemoryElems<float>(kWasmPageSize / sizeof(float)); BUILD(r, WASM_I32_REINTERPRET_F32( WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO))); - FOR_INT32_INPUTS(i) { - int32_t expected = i; - r.builder().WriteMemory(&memory[0], expected); + FOR_FLOAT32_INPUTS(i) { + float input = i; + int32_t expected = bit_cast<int32_t, float>(input); + r.builder().WriteMemory(&memory[0], input); CHECK_EQ(expected, r.Call()); } } -WASM_EXEC_TEST(I32ReinterpretF32) { - WasmRunner<int32_t, int32_t> r(execution_tier); +WASM_EXEC_TEST(F32ReinterpretI32) { + WasmRunner<float> r(execution_tier); int32_t* memory = r.builder().AddMemoryElems<int32_t>(kWasmPageSize / sizeof(int32_t)); - BUILD(r, - WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, - WASM_F32_REINTERPRET_I32(WASM_LOCAL_GET(0))), - WASM_I32V_2(107)); + BUILD(r, WASM_F32_REINTERPRET_I32( + WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO))); FOR_INT32_INPUTS(i) { - int32_t expected = i; - CHECK_EQ(107, r.Call(expected)); - CHECK_EQ(expected, r.builder().ReadMemory(&memory[0])); + int32_t input = i; + float expected = bit_cast<float, int32_t>(input); + r.builder().WriteMemory(&memory[0], input); + float result = r.Call(); + if (std::isnan(expected)) { + CHECK(std::isnan(result)); + CHECK(IsSameNan(expected, result)); + } else { + CHECK_EQ(expected, result); + } } } diff --git a/deps/v8/test/cctest/wasm/wasm-run-utils.cc b/deps/v8/test/cctest/wasm/wasm-run-utils.cc index 940a42beaa..3c3ba34d5a 100644 --- a/deps/v8/test/cctest/wasm/wasm-run-utils.cc +++ b/deps/v8/test/cctest/wasm/wasm-run-utils.cc @@ -21,6 +21,25 @@ namespace v8 { namespace internal { namespace wasm { +// Helper Functions. +bool IsSameNan(float expected, float actual) { + // Sign is non-deterministic. + uint32_t expected_bits = bit_cast<uint32_t>(expected) & ~0x80000000; + uint32_t actual_bits = bit_cast<uint32_t>(actual) & ~0x80000000; + // Some implementations convert signaling NaNs to quiet NaNs. + return (expected_bits == actual_bits) || + ((expected_bits | 0x00400000) == actual_bits); +} + +bool IsSameNan(double expected, double actual) { + // Sign is non-deterministic. + uint64_t expected_bits = bit_cast<uint64_t>(expected) & ~0x8000000000000000; + uint64_t actual_bits = bit_cast<uint64_t>(actual) & ~0x8000000000000000; + // Some implementations convert signaling NaNs to quiet NaNs. + return (expected_bits == actual_bits) || + ((expected_bits | 0x0008000000000000) == actual_bits); +} + TestingModuleBuilder::TestingModuleBuilder( Zone* zone, ManuallyImportedJSFunction* maybe_import, TestExecutionTier tier, RuntimeExceptionSupport exception_support, @@ -246,12 +265,12 @@ uint32_t TestingModuleBuilder::AddBytes(base::Vector<const byte> bytes) { uint32_t TestingModuleBuilder::AddException(const FunctionSig* sig) { DCHECK_EQ(0, sig->return_count()); - uint32_t index = static_cast<uint32_t>(test_module_->exceptions.size()); - test_module_->exceptions.push_back(WasmException{sig}); + uint32_t index = static_cast<uint32_t>(test_module_->tags.size()); + test_module_->tags.push_back(WasmTag{sig}); Handle<WasmExceptionTag> tag = WasmExceptionTag::New(isolate_, index); - Handle<FixedArray> table(instance_object_->exceptions_table(), isolate_); + Handle<FixedArray> table(instance_object_->tags_table(), isolate_); table = isolate_->factory()->CopyFixedArrayAndGrow(table, 1); - instance_object_->set_exceptions_table(*table); + instance_object_->set_tags_table(*table); table->set(index, *tag); return index; } @@ -351,7 +370,7 @@ Handle<WasmInstanceObject> TestingModuleBuilder::InitInstanceObject() { native_module_->ReserveCodeTableForTesting(kMaxFunctions); auto instance = WasmInstanceObject::New(isolate_, module_object); - instance->set_exceptions_table(*isolate_->factory()->empty_fixed_array()); + instance->set_tags_table(*isolate_->factory()->empty_fixed_array()); instance->set_globals_start(globals_data_); return instance; } @@ -549,21 +568,20 @@ void WasmFunctionCompiler::Build(const byte* start, const byte* end) { ForDebugging for_debugging = native_module->IsTieredDown() ? kForDebugging : kNoDebugging; - WasmFeatures unused_detected_features; - base::Optional<WasmCompilationResult> result; if (builder_->test_execution_tier() == TestExecutionTier::kLiftoffForFuzzing) { result.emplace(ExecuteLiftoffCompilation( &env, func_body, function_->func_index, kForDebugging, - isolate()->counters(), &unused_detected_features, {}, nullptr, 0, - builder_->max_steps_ptr(), builder_->non_determinism_ptr())); + LiftoffOptions{} + .set_max_steps(builder_->max_steps_ptr()) + .set_nondeterminism(builder_->non_determinism_ptr()))); } else { WasmCompilationUnit unit(function_->func_index, builder_->execution_tier(), for_debugging); result.emplace(unit.ExecuteCompilation( &env, native_module->compilation_state()->GetWireBytesStorage().get(), - isolate()->counters(), &unused_detected_features)); + nullptr, nullptr)); } WasmCode* code = native_module->PublishCode( native_module->AddCompiledCode(std::move(*result))); diff --git a/deps/v8/test/cctest/wasm/wasm-run-utils.h b/deps/v8/test/cctest/wasm/wasm-run-utils.h index 27e78a1737..8f6bb6074f 100644 --- a/deps/v8/test/cctest/wasm/wasm-run-utils.h +++ b/deps/v8/test/cctest/wasm/wasm-run-utils.h @@ -96,6 +96,10 @@ struct ManuallyImportedJSFunction { Handle<JSFunction> js_function; }; +// Helper Functions. +bool IsSameNan(float expected, float actual); +bool IsSameNan(double expected, double actual); + // A Wasm module builder. Globals are pre-set, however, memory and code may be // progressively added by a test. In turn, we piecemeal update the runtime // objects, i.e. {WasmInstanceObject}, {WasmModuleObject} and, if necessary, @@ -439,7 +443,8 @@ class WasmRunnerBase : public InitializedHandleScope { const char* name = nullptr) { functions_.emplace_back( new WasmFunctionCompiler(&zone_, sig, &builder_, name)); - builder().AddSignature(sig); + byte sig_index = builder().AddSignature(sig); + functions_.back()->SetSigIndex(sig_index); return *functions_.back(); } diff --git a/deps/v8/test/cctest/wasm/wasm-simd-utils.cc b/deps/v8/test/cctest/wasm/wasm-simd-utils.cc index 43b73f4bd0..aa6b755d0d 100644 --- a/deps/v8/test/cctest/wasm/wasm-simd-utils.cc +++ b/deps/v8/test/cctest/wasm/wasm-simd-utils.cc @@ -401,15 +401,6 @@ bool IsExtreme(float x) { (abs_x < kSmallFloatThreshold || abs_x > kLargeFloatThreshold); } -bool IsSameNan(float expected, float actual) { - // Sign is non-deterministic. - uint32_t expected_bits = bit_cast<uint32_t>(expected) & ~0x80000000; - uint32_t actual_bits = bit_cast<uint32_t>(actual) & ~0x80000000; - // Some implementations convert signaling NaNs to quiet NaNs. - return (expected_bits == actual_bits) || - ((expected_bits | 0x00400000) == actual_bits); -} - bool IsCanonical(float actual) { uint32_t actual_bits = bit_cast<uint32_t>(actual); // Canonical NaN has quiet bit and no payload. @@ -574,15 +565,6 @@ bool IsExtreme(double x) { (abs_x < kSmallFloatThreshold || abs_x > kLargeFloatThreshold); } -bool IsSameNan(double expected, double actual) { - // Sign is non-deterministic. - uint64_t expected_bits = bit_cast<uint64_t>(expected) & ~0x8000000000000000; - uint64_t actual_bits = bit_cast<uint64_t>(actual) & ~0x8000000000000000; - // Some implementations convert signaling NaNs to quiet NaNs. - return (expected_bits == actual_bits) || - ((expected_bits | 0x0008000000000000) == actual_bits); -} - bool IsCanonical(double actual) { uint64_t actual_bits = bit_cast<uint64_t>(actual); // Canonical NaN has quiet bit and no payload. diff --git a/deps/v8/test/cctest/wasm/wasm-simd-utils.h b/deps/v8/test/cctest/wasm/wasm-simd-utils.h index 140acda05c..d7698f2060 100644 --- a/deps/v8/test/cctest/wasm/wasm-simd-utils.h +++ b/deps/v8/test/cctest/wasm/wasm-simd-utils.h @@ -139,13 +139,11 @@ bool PlatformCanRepresent(T x) { // Returns true for very small and very large numbers. We skip these test // values for the approximation instructions, which don't work at the extremes. bool IsExtreme(float x); -bool IsSameNan(float expected, float actual); bool IsCanonical(float actual); void CheckFloatResult(float x, float y, float expected, float actual, bool exact = true); bool IsExtreme(double x); -bool IsSameNan(double expected, double actual); bool IsCanonical(double actual); void CheckDoubleResult(double x, double y, double expected, double actual, bool exact = true); |