diff options
Diffstat (limited to 'deps/v8/test/cctest')
143 files changed, 11664 insertions, 7503 deletions
diff --git a/deps/v8/test/cctest/BUILD.gn b/deps/v8/test/cctest/BUILD.gn index f926707915..54e733c2dc 100644 --- a/deps/v8/test/cctest/BUILD.gn +++ b/deps/v8/test/cctest/BUILD.gn @@ -44,7 +44,6 @@ v8_executable("cctest") { "compiler/test-run-bytecode-graph-builder.cc", "compiler/test-run-calls-to-external-references.cc", "compiler/test-run-deopt.cc", - "compiler/test-run-inlining.cc", "compiler/test-run-intrinsics.cc", "compiler/test-run-jsbranches.cc", "compiler/test-run-jscalls.cc", @@ -91,6 +90,7 @@ v8_executable("cctest") { "interpreter/test-source-positions.cc", "libplatform/test-tracing.cc", "libsampler/test-sampler.cc", + "parsing/test-parse-decision.cc", "parsing/test-scanner-streams.cc", "parsing/test-scanner.cc", "print-extension.cc", @@ -98,6 +98,7 @@ v8_executable("cctest") { "profiler-extension.cc", "profiler-extension.h", "test-access-checks.cc", + "test-accessor-assembler.cc", "test-accessors.cc", "test-api-accessors.cc", "test-api-fast-accessor-builder.cc", @@ -190,6 +191,7 @@ v8_executable("cctest") { "wasm/test-run-wasm-module.cc", "wasm/test-run-wasm-relocation.cc", "wasm/test-run-wasm.cc", + "wasm/test-wasm-breakpoints.cc", "wasm/test-wasm-stack.cc", "wasm/test-wasm-trap-position.cc", "wasm/wasm-run-utils.h", @@ -204,6 +206,7 @@ v8_executable("cctest") { "test-disasm-arm.cc", "test-macro-assembler-arm.cc", "test-run-wasm-relocation-arm.cc", + "wasm/test-run-wasm-simd.cc", ] } else if (v8_current_cpu == "arm64") { sources += [ ### gcmole(arch:arm64) ### @@ -218,6 +221,7 @@ v8_executable("cctest") { "test-run-wasm-relocation-arm64.cc", "test-utils-arm64.cc", "test-utils-arm64.h", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "x86") { sources += [ ### gcmole(arch:ia32) ### @@ -229,6 +233,7 @@ v8_executable("cctest") { "test-log-stack-tracer.cc", "test-macro-assembler-ia32.cc", "test-run-wasm-relocation-ia32.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "mips") { sources += [ ### gcmole(arch:mips) ### @@ -238,6 +243,7 @@ v8_executable("cctest") { "test-code-stubs.h", "test-disasm-mips.cc", "test-macro-assembler-mips.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "mipsel") { sources += [ ### gcmole(arch:mipsel) ### @@ -247,6 +253,7 @@ v8_executable("cctest") { "test-code-stubs.h", "test-disasm-mips.cc", "test-macro-assembler-mips.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "mips64") { sources += [ ### gcmole(arch:mips64) ### @@ -256,6 +263,7 @@ v8_executable("cctest") { "test-code-stubs.h", "test-disasm-mips64.cc", "test-macro-assembler-mips64.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "mips64el") { sources += [ ### gcmole(arch:mips64el) ### @@ -265,6 +273,7 @@ v8_executable("cctest") { "test-code-stubs.h", "test-disasm-mips64.cc", "test-macro-assembler-mips64.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "x64") { sources += [ ### gcmole(arch:x64) ### @@ -276,7 +285,6 @@ v8_executable("cctest") { "test-log-stack-tracer.cc", "test-macro-assembler-x64.cc", "test-run-wasm-relocation-x64.cc", - "wasm/test-run-wasm-simd-lowering.cc", "wasm/test-run-wasm-simd.cc", ] } else if (v8_current_cpu == "x87") { @@ -289,6 +297,7 @@ v8_executable("cctest") { "test-log-stack-tracer.cc", "test-macro-assembler-x87.cc", "test-run-wasm-relocation-x87.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64") { sources += [ ### gcmole(arch:ppc) ### @@ -296,6 +305,7 @@ v8_executable("cctest") { "test-code-stubs.cc", "test-code-stubs.h", "test-disasm-ppc.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } else if (v8_current_cpu == "s390" || v8_current_cpu == "s390x") { sources += [ ### gcmole(arch:s390) ### @@ -303,6 +313,7 @@ v8_executable("cctest") { "test-code-stubs.cc", "test-code-stubs.h", "test-disasm-s390.cc", + "wasm/test-run-wasm-simd-lowering.cc", ] } @@ -347,9 +358,16 @@ v8_executable("cctest") { cflags = [] ldflags = [] + # crbug.com/676417: Suppress symbol import warning from linker. + if (is_win && is_component_build) { + ldflags = [ "/ignore:4217" ] + } + if (v8_current_cpu == "ppc" || v8_current_cpu == "ppc64" || v8_current_cpu == "arm" || v8_current_cpu == "arm64" || - v8_current_cpu == "s390" || v8_current_cpu == "s390x") { + v8_current_cpu == "s390" || v8_current_cpu == "s390x" || + v8_current_cpu == "mips" || v8_current_cpu == "mips64" || + v8_current_cpu == "mipsel" || v8_current_cpu == "mipsel64") { # Disable fmadd/fmsub so that expected results match generated code in # RunFloat64MulAndFloat64Add1 and friends. cflags += [ "-ffp-contract=off" ] diff --git a/deps/v8/test/cctest/asmjs/OWNERS b/deps/v8/test/cctest/asmjs/OWNERS index d8fad3059a..509581c8db 100644 --- a/deps/v8/test/cctest/asmjs/OWNERS +++ b/deps/v8/test/cctest/asmjs/OWNERS @@ -4,6 +4,7 @@ set noparent ahaas@chromium.org bradnelson@chromium.org +clemensh@chromium.org jpp@chromium.org mtrofin@chromium.org rossberg@chromium.org diff --git a/deps/v8/test/cctest/asmjs/test-asm-typer.cc b/deps/v8/test/cctest/asmjs/test-asm-typer.cc index d345774dbf..892c968d1d 100644 --- a/deps/v8/test/cctest/asmjs/test-asm-typer.cc +++ b/deps/v8/test/cctest/asmjs/test-asm-typer.cc @@ -14,6 +14,7 @@ #include "src/ast/scopes.h" #include "src/base/platform/platform.h" #include "src/compiler.h" +#include "src/objects-inl.h" #include "src/parsing/parse-info.h" #include "src/parsing/parser.h" #include "src/v8.h" @@ -46,7 +47,8 @@ class AsmTyperHarnessBuilder { handles_(), zone_(handles_.main_zone()), isolate_(CcTest::i_isolate()), - ast_value_factory_(zone_, isolate_->heap()->HashSeed()), + ast_value_factory_(zone_, isolate_->ast_string_constants(), + isolate_->heap()->HashSeed()), factory_(isolate_->factory()), source_code_( factory_->NewStringFromUtf8(CStrVector(source)).ToHandleChecked()), @@ -69,7 +71,7 @@ class AsmTyperHarnessBuilder { ->AtForTest(0) ->AsFunctionDeclaration() ->fun(); - typer_.reset(new AsmTyper(isolate_, zone_, *script_, module_)); + typer_.reset(new AsmTyper(isolate_, zone_, script_, module_)); if (validation_type_ == ValidateStatement || validation_type_ == ValidateExpression) { @@ -99,6 +101,9 @@ class AsmTyperHarnessBuilder { CHECK(validation_type_ == ValidateStatement || validation_type_ == ValidateExpression); auto* var = DeclareVariable(var_name); + if (var->IsUnallocated()) { + var->AllocateTo(VariableLocation::LOCAL, -1); + } auto* var_info = new (zone_) AsmTyper::VariableInfo(type); var_info->set_mutability(AsmTyper::VariableInfo::kLocal); CHECK(typer_->AddLocal(var, var_info)); @@ -107,9 +112,14 @@ class AsmTyperHarnessBuilder { AsmTyperHarnessBuilder* WithGlobal(VariableName var_name, AsmType* type) { auto* var = DeclareVariable(var_name); - auto* var_info = new (zone_) AsmTyper::VariableInfo(type); - var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal); - CHECK(typer_->AddGlobal(var, var_info)); + if (var->IsUnallocated()) { + var->AllocateTo(VariableLocation::MODULE, -1); + } + if (type != nullptr) { + auto* var_info = new (zone_) AsmTyper::VariableInfo(type); + var_info->set_mutability(AsmTyper::VariableInfo::kMutableGlobal); + CHECK(typer_->AddGlobal(var, var_info)); + } return this; } @@ -126,13 +136,17 @@ class AsmTyperHarnessBuilder { WithGlobal(var_name, type); auto* var_info = typer_->Lookup(DeclareVariable(var_name)); CHECK(var_info); - var_info->FirstForwardUseIs(nullptr); + MessageLocation location; + var_info->SetFirstForwardUse(location); return this; } AsmTyperHarnessBuilder* WithImport(VariableName var_name, AsmTyper::StandardMember standard_member) { auto* var = DeclareVariable(var_name); + if (var->IsUnallocated()) { + var->AllocateTo(VariableLocation::LOCAL, -1); + } AsmTyper::VariableInfo* var_info = nullptr; auto* stdlib_map = &typer_->stdlib_math_types_; switch (standard_member) { @@ -217,7 +231,9 @@ class AsmTyperHarnessBuilder { return true; } - std::cerr << "Asm validation failed: " << typer_->error_message() << "\n"; + std::unique_ptr<char[]> msg = i::MessageHandler::GetLocalizedMessage( + isolate_, typer_->error_message()); + std::cerr << "Asm validation failed: " << msg.get() << "\n"; return false; } @@ -225,7 +241,9 @@ class AsmTyperHarnessBuilder { CHECK(validation_type_ == ValidateExpression); auto* validated_as = ValidateExpressionStatment(fun_decl_); if (validated_as == AsmType::None()) { - std::cerr << "Validation failure: " << typer_->error_message() << "\n"; + std::unique_ptr<char[]> msg = i::MessageHandler::GetLocalizedMessage( + isolate_, typer_->error_message()); + std::cerr << "Validation failure: " << msg.get() << "\n"; return false; } else if (validated_as != type) { std::cerr << "Validation succeeded with wrong type " @@ -260,12 +278,14 @@ class AsmTyperHarnessBuilder { return false; } - if (std::strstr(typer_->error_message(), error_message) == nullptr) { + std::unique_ptr<char[]> msg = i::MessageHandler::GetLocalizedMessage( + isolate_, typer_->error_message()); + if (std::strstr(msg.get(), error_message) == nullptr) { std::cerr << "Asm validation failed with the wrong error message:\n" "Expected to contain '" << error_message << "'\n" " Actually is '" - << typer_->error_message() << "'\n"; + << msg.get() << "'\n"; return false; } @@ -671,12 +691,18 @@ TEST(ErrorsInModuleExport) { {"return {'a': ffi}", "cannot export foreign functions"}, {"return {'a': f()}", "must be an asm.js function name"}, {"return {'a': f}", "Undefined identifier in asm.js module export"}, - {"function v() { a(); } return {b: d2s}", "Missing definition for forw"}, - {"return {b: d2s, 'a': d2s_tbl}", "cannot export function tables"}, - {"return {b: d2s, 'a': min}", "cannot export standard library"}, - {"return {b: d2s, 'a': ffi}", "cannot export foreign functions"}, - {"return {b: d2s, 'a': f()}", "must be an asm.js function name"}, - {"return {b: d2s, 'a': f}", "Undefined identifier in asm.js module"}, + {"function v() { a(); } return {b: d2s}", + "Invalid call of existing global function"}, + {"function v() {} return {b: v, 'a': d2s_tbl}", + "cannot export function tables"}, + {"function v() {} return {b: v, 'a': min}", + "cannot export standard library"}, + {"function v() {} return {b: v, 'a': ffi}", + "cannot export foreign functions"}, + {"function v() {} return {b: v, 'a': f()}", + "must be an asm.js function name"}, + {"function v() {} return {b: v, 'a': f}", + "Undefined identifier in asm.js module"}, }; auto d2s_tbl = [](Zone* zone) -> iw::AsmType* { @@ -687,17 +713,10 @@ TEST(ErrorsInModuleExport) { return ret; }; - auto d2s = [](Zone* zone) -> iw::AsmType* { - auto* ret = iw::AsmType::Function(zone, iw::AsmType::Signed()); - ret->AsFunctionType()->AddArgument(iw::AsmType::Double()); - return ret; - }; - for (size_t ii = 0; ii < arraysize(kTests); ++ii) { const auto* test = kTests + ii; if (!ValidationOf(Export(test->module_export)) ->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl) - ->WithGlobal(DynamicGlobal("d2s"), d2s) ->WithImport(DynamicGlobal("min"), iw::AsmTyper::kMathMin) ->WithImport(DynamicGlobal("ffi"), iw::AsmTyper::kFFI) ->WithGlobal(DynamicGlobal("I"), iw::AsmType::Int()) @@ -910,6 +929,7 @@ TEST(ErrorsInStatement) { ->WithImport(DynamicGlobal("fround"), iw::AsmTyper::kMathFround) ->WithLocal(DynamicGlobal("flocal"), iw::AsmType::Float()) ->WithLocal(DynamicGlobal("slocal"), iw::AsmType::Signed()) + ->WithGlobal(DynamicGlobal("d"), nullptr) ->FailsWithMessage(test->error_message)) { std::cerr << "Test:\n" << test->statement; CHECK(false); @@ -1040,6 +1060,7 @@ TEST(ErrorsInExpression) { ->WithGlobal(DynamicGlobal("d2s_tbl"), d2s_tbl) ->WithGlobal(DynamicGlobal("HEAP32"), iw::AsmType::Int32Array()) ->WithGlobal(DynamicGlobal("HEAP8"), iw::AsmType::Int8Array()) + ->WithGlobal(DynamicGlobal("a"), nullptr) ->FailsWithMessage(test->error_message)) { std::cerr << "Test:\n" << test->expression; CHECK(false); @@ -1367,6 +1388,8 @@ TEST(ValidateAssignmentExpression) { ->WithGlobal(DynamicGlobal("U32"), iw::AsmType::Uint32Array()) ->WithGlobal(DynamicGlobal("F32"), iw::AsmType::Float32Array()) ->WithGlobal(DynamicGlobal("F64"), iw::AsmType::Float64Array()) + ->WithGlobal(DynamicGlobal("make_float"), nullptr) + ->WithGlobal(DynamicGlobal("make_double"), nullptr) ->SucceedsWithExactType(test->load_type)) { std::cerr << "Test:\n" << test->expression; CHECK(false); @@ -1422,6 +1445,7 @@ TEST(ValidateUnaryExpression) { ->WithLocal(DynamicGlobal("ulocal"), iw::AsmType::Unsigned()) ->WithLocal(DynamicGlobal("ilocal"), iw::AsmType::Int()) ->WithGlobal(DynamicGlobal("dglobal"), iw::AsmType::Double()) + ->WithGlobal(DynamicGlobal("make_double"), nullptr) ->WithGlobal(DynamicGlobal("dbl"), v2d) ->SucceedsWithExactType(test->load_type)) { std::cerr << "Test:\n" << test->expression; @@ -1671,6 +1695,7 @@ TEST(ValidateBitwiseExpression) { ->WithLocal(DynamicGlobal("iish1"), iw::AsmType::Intish()) ->WithLocal(DynamicGlobal("iish0"), iw::AsmType::Intish()) ->WithGlobal(DynamicGlobal("signed"), v2s) + ->WithGlobal(DynamicGlobal("make_signed"), nullptr) ->SucceedsWithExactType(test->load_type)) { std::cerr << "Test:\n" << test->expression; CHECK(false); @@ -1718,7 +1743,7 @@ TEST(ValidateCall) { // // ifd2_(&iw::AsmType::Float) // - // returns an AsmType representing an asm.j function with the following + // returns an AsmType representing an asm.js function with the following // signature: // // float(int, float, double) @@ -1795,6 +1820,9 @@ TEST(ValidateCall) { ->WithLocal(DynamicGlobal("u"), iw::AsmType::Unsigned()) ->WithLocal(DynamicGlobal("iish"), iw::AsmType::Intish()) ->WithGlobal(DynamicGlobal("v2f"), v2f) + ->WithGlobal(DynamicGlobal("ifd2f"), nullptr) + ->WithGlobal(DynamicGlobal("ifd2d"), nullptr) + ->WithGlobal(DynamicGlobal("ifd2i"), nullptr) ->WithGlobal(DynamicGlobal("ifd2f_tbl"), ifd2f_tbl) ->WithGlobal(DynamicGlobal("ifd2d_tbl"), ifd2d_tbl) ->WithGlobal(DynamicGlobal("ifd2i_tbl"), ifd2i_tbl) diff --git a/deps/v8/test/cctest/cctest.gyp b/deps/v8/test/cctest/cctest.gyp index 6b5dba6472..1eff6c0c6d 100644 --- a/deps/v8/test/cctest/cctest.gyp +++ b/deps/v8/test/cctest/cctest.gyp @@ -64,7 +64,6 @@ 'compiler/test-run-bytecode-graph-builder.cc', 'compiler/test-run-calls-to-external-references.cc', 'compiler/test-run-deopt.cc', - 'compiler/test-run-inlining.cc', 'compiler/test-run-intrinsics.cc', 'compiler/test-run-jsbranches.cc', 'compiler/test-run-jscalls.cc', @@ -112,6 +111,7 @@ 'heap/test-spaces.cc', 'libplatform/test-tracing.cc', 'libsampler/test-sampler.cc', + 'parsing/test-parse-decision.cc', 'parsing/test-scanner-streams.cc', 'parsing/test-scanner.cc', 'print-extension.cc', @@ -119,6 +119,7 @@ 'profiler-extension.cc', 'profiler-extension.h', 'test-access-checks.cc', + 'test-accessor-assembler.cc', 'test-accessors.cc', 'test-api.cc', 'test-api.h', @@ -211,6 +212,7 @@ 'wasm/test-run-wasm-js.cc', 'wasm/test-run-wasm-module.cc', 'wasm/test-run-wasm-relocation.cc', + 'wasm/test-wasm-breakpoints.cc', 'wasm/test-wasm-stack.cc', 'wasm/test-wasm-trap-position.cc', 'wasm/wasm-run-utils.h', @@ -223,7 +225,8 @@ 'test-disasm-ia32.cc', 'test-macro-assembler-ia32.cc', 'test-log-stack-tracer.cc', - 'test-run-wasm-relocation-ia32.cc' + 'test-run-wasm-relocation-ia32.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_x64': [ ### gcmole(arch:x64) ### 'test-assembler-x64.cc', @@ -235,7 +238,6 @@ 'test-log-stack-tracer.cc', 'test-run-wasm-relocation-x64.cc', 'wasm/test-run-wasm-simd.cc', - 'wasm/test-run-wasm-simd-lowering.cc', ], 'cctest_sources_arm': [ ### gcmole(arch:arm) ### 'test-assembler-arm.cc', @@ -244,7 +246,8 @@ 'test-code-stubs-arm.cc', 'test-disasm-arm.cc', 'test-macro-assembler-arm.cc', - 'test-run-wasm-relocation-arm.cc' + 'test-run-wasm-relocation-arm.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_arm64': [ ### gcmole(arch:arm64) ### 'test-utils-arm64.cc', @@ -257,19 +260,22 @@ 'test-fuzz-arm64.cc', 'test-javascript-arm64.cc', 'test-js-arm64-variables.cc', - 'test-run-wasm-relocation-arm64.cc' + 'test-run-wasm-relocation-arm64.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_s390': [ ### gcmole(arch:s390) ### 'test-assembler-s390.cc', 'test-code-stubs.cc', 'test-code-stubs.h', - 'test-disasm-s390.cc' + 'test-disasm-s390.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_ppc': [ ### gcmole(arch:ppc) ### 'test-assembler-ppc.cc', 'test-code-stubs.cc', 'test-code-stubs.h', - 'test-disasm-ppc.cc' + 'test-disasm-ppc.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_mips': [ ### gcmole(arch:mips) ### 'test-assembler-mips.cc', @@ -277,7 +283,8 @@ 'test-code-stubs.h', 'test-code-stubs-mips.cc', 'test-disasm-mips.cc', - 'test-macro-assembler-mips.cc' + 'test-macro-assembler-mips.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_mipsel': [ ### gcmole(arch:mipsel) ### 'test-assembler-mips.cc', @@ -285,7 +292,8 @@ 'test-code-stubs.h', 'test-code-stubs-mips.cc', 'test-disasm-mips.cc', - 'test-macro-assembler-mips.cc' + 'test-macro-assembler-mips.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_mips64': [ ### gcmole(arch:mips64) ### 'test-assembler-mips64.cc', @@ -293,7 +301,8 @@ 'test-code-stubs.h', 'test-code-stubs-mips64.cc', 'test-disasm-mips64.cc', - 'test-macro-assembler-mips64.cc' + 'test-macro-assembler-mips64.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_mips64el': [ ### gcmole(arch:mips64el) ### 'test-assembler-mips64.cc', @@ -301,7 +310,8 @@ 'test-code-stubs.h', 'test-code-stubs-mips64.cc', 'test-disasm-mips64.cc', - 'test-macro-assembler-mips64.cc' + 'test-macro-assembler-mips64.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], 'cctest_sources_x87': [ ### gcmole(arch:x87) ### 'test-assembler-x87.cc', @@ -311,7 +321,8 @@ 'test-disasm-x87.cc', 'test-macro-assembler-x87.cc', 'test-log-stack-tracer.cc', - 'test-run-wasm-relocation-x87.cc' + 'test-run-wasm-relocation-x87.cc', + 'wasm/test-run-wasm-simd-lowering.cc' ], }, 'includes': ['../../gypfiles/toolchain.gypi', '../../gypfiles/features.gypi'], @@ -418,7 +429,9 @@ }], ['v8_target_arch=="ppc" or v8_target_arch=="ppc64" \ or v8_target_arch=="arm" or v8_target_arch=="arm64" \ - or v8_target_arch=="s390" or v8_target_arch=="s390x"', { + or v8_target_arch=="s390" or v8_target_arch=="s390x" \ + or v8_target_arch=="mips" or v8_target_arch=="mips64" \ + or v8_target_arch=="mipsel" or v8_target_arch=="mips64el"', { # disable fmadd/fmsub so that expected results match generated code in # RunFloat64MulAndFloat64Add1 and friends. 'cflags': ['-ffp-contract=off'], diff --git a/deps/v8/test/cctest/cctest.h b/deps/v8/test/cctest/cctest.h index 690a8c14cd..7d8ad59a26 100644 --- a/deps/v8/test/cctest/cctest.h +++ b/deps/v8/test/cctest/cctest.h @@ -583,7 +583,6 @@ class InitializedHandleScope { std::unique_ptr<InitializedHandleScopeImpl> initialized_handle_scope_impl_; }; - class HandleAndZoneScope : public InitializedHandleScope { public: HandleAndZoneScope(); @@ -597,4 +596,18 @@ class HandleAndZoneScope : public InitializedHandleScope { std::unique_ptr<i::Zone> main_zone_; }; +class StaticOneByteResource : public v8::String::ExternalOneByteStringResource { + public: + explicit StaticOneByteResource(const char* data) : data_(data) {} + + ~StaticOneByteResource() {} + + const char* data() const { return data_; } + + size_t length() const { return strlen(data_); } + + private: + const char* data_; +}; + #endif // ifndef CCTEST_H_ diff --git a/deps/v8/test/cctest/cctest.status b/deps/v8/test/cctest/cctest.status index 059d099bf5..e5ac07cd0e 100644 --- a/deps/v8/test/cctest/cctest.status +++ b/deps/v8/test/cctest/cctest.status @@ -77,9 +77,6 @@ 'test-cpu-profiler/HotDeoptNoFrameEntry': [SKIP], 'test-cpu-profiler/SampleWhenFrameIsNotSetup': [SKIP], - # BUG(v8:4358). Hangs flakily. - 'test-debug/ProcessDebugMessagesThreaded': [SKIP], - # BUG(2340). Preprocessing stack traces is disabled at the moment. 'test-heap/PreprocessStackTrace': [FAIL], @@ -87,6 +84,13 @@ 'test-func-name-inference/UpperCaseClass': [FAIL], 'test-func-name-inference/LowerCaseClass': [FAIL], + # Bug(5784). StubCache tests need to be redesigned, as a) they don't work + # in the new (ignition + turbofan) pipeline environment, and b) they are + # stymied by a move of code stubs into builtins. + 'test-api/PrimaryStubCache': [SKIP], + 'test-api/SecondaryStubCache': [SKIP], + 'test-api/AccessCheckInIC': [SKIP], + # BUG(3742). 'test-mark-compact/MarkCompactCollector': [PASS, ['arch==arm', NO_VARIANTS]], @@ -201,6 +205,9 @@ 'test-cpu-profiler/JsNativeJsSample': [SKIP], 'test-cpu-profiler/JsNative1JsNative2JsSample': [SKIP], + # BUG(v8:5193): Flaky. + 'test-cpu-profiler/FunctionApplySample': [SKIP], + # BUG(5193): Flaky timeout. 'test-sampler/LibSamplerCollectSample': [PASS, ['arch == x64', SKIP]], }], # 'system == windows' @@ -218,6 +225,10 @@ 'test-serialize/StartupSerializerTwice': [SKIP], 'test-serialize/StartupSerializerOnceRunScript': [SKIP], 'test-serialize/StartupSerializerTwiceRunScript': [SKIP], + 'test-run-wasm-simd/RunWasmCompiled_F32x4Add': [SKIP], + 'test-run-wasm-simd/RunWasmCompiled_F32x4Sub': [SKIP], + 'test-run-wasm-simd/RunWasmInterpreted_F32x4Add': [SKIP], + 'test-run-wasm-simd/RunWasmInterpreted_F32x4Sub': [SKIP], ############################################################################ # Slow tests. @@ -326,80 +337,47 @@ ############################################################################## ['variant == turbofan_opt', { - # TODO(mythria,4680): Lack of code-ageing and/or lack of compilation cache - # in interpreter. - 'test-heap/CompilationCacheCachingBehavior': [FAIL], - - # TODO(mstarzinger): Triggers Ignition+TurboFan on everything now and makes - # the stack traces within the profilers look different. Needs investigation. - 'test-api/SetFunctionEntryHook': [SKIP], - 'test-cpu-profiler/BoundFunctionCall': [FAIL], - 'test-cpu-profiler/CollectSampleAPI': [FAIL], - 'test-cpu-profiler/FunctionApplySample': [FAIL], - 'test-cpu-profiler/FunctionCallSample': [FAIL], - 'test-cpu-profiler/JsNativeJsRuntimeJsSample': [FAIL], - 'test-cpu-profiler/JsNativeJsSample': [FAIL], - 'test-cpu-profiler/JsNativeJsRuntimeJsSampleMultiple': [FAIL], - 'test-cpu-profiler/JsNative1JsNative2JsSample': [FAIL], - 'test-cpu-profiler/NativeMethodUninitializedIC': [FAIL], - 'test-cpu-profiler/NativeAccessorUninitializedIC': [FAIL], - 'test-profile-generator/LineNumber': [FAIL], - 'test-sampler-api/StackFramesConsistent': [FAIL], - # BUG(v8:5457) 'test-api/SetJitCodeEventHandler': [PASS, ['no_snap', SKIP]], }], # variant == turbofan_opt ############################################################################## -['variant == ignition', { - # TODO(mythria,4680): Lack of code-ageing and/or lack of compilation cache - # in interpreter. - 'test-heap/CompilationCacheCachingBehavior': [FAIL], - - # BUG(5193): Flaky. - 'test-cpu-profiler/FunctionApplySample': [PASS, ['system == windows', SKIP]], -}], # variant == ignition - -############################################################################## -['variant == ignition_staging', { - 'test-cpu-profiler/DeoptUntrackedFunction': [SKIP], - 'test-cpu-profiler/TickLinesOptimized': [SKIP], - 'test-heap/CompilationCacheCachingBehavior': [FAIL], - - # BUG(5193): Flaky. - 'test-cpu-profiler/FunctionApplySample': [PASS, ['system == windows', SKIP]], -}], # variant == ignition_staging - -############################################################################## ['variant == turbofan or variant == ignition_turbofan', { - # TODO(mythria,4680): Lack of code-ageing and/or lack of compilation cache - # in interpreter. - 'test-heap/CompilationCacheCachingBehavior': [FAIL], - - # BUG(4680): Missing type feedback makes optimistic optimizations fail. - 'test-cpu-profiler/CollectDeoptEvents': [FAIL], - 'test-cpu-profiler/DeoptUntrackedFunction': [SKIP], - # BUG(4751). Flaky with Ignition. 'test-cpu-profiler/JsNativeJsSample': [SKIP], # TODO(vogelheim,5548): Turbofan does support cached accessors. 'test-api-accessors/CachedAccessorCrankshaft': [FAIL], - - # BUG(5193): Flaky. - 'test-cpu-profiler/FunctionApplySample': [PASS, ['system == windows', SKIP]], }], # variant == turbofan or variant == ignition_turbofan ############################################################################## -['variant != ignition and variant != ignition_staging and variant != ignition_turbofan', { - # Ongoing implementation of modules. - # https://bugs.chromium.org/p/v8/issues/detail?id=1569 - 'test-modules/*': [SKIP], -}], # variant != ignition and variant != ignition_staging and variant != ignition_turbofan - -############################################################################## ['variant == asm_wasm', { '*': [SKIP], }], # variant == asm_wasm +############################################################################## +['variant == wasm_traps', { + 'test-accessors/*': [SKIP], + 'test-api-interceptors/*': [SKIP], + 'test-api/*': [SKIP], + 'test-bignum-dtoa/*': [SKIP], + 'test-cpu-profiler/*': [SKIP], + 'test-debug/*': [SKIP], + 'test-global-handles/*': [SKIP], + 'test-heap-profiler/*': [SKIP], + 'test-heap/*': [SKIP], + 'test-inobject-slack-tracking/*': [SKIP], + 'test-lockers/*': [SKIP], + 'test-run-machops/*': [SKIP], + 'test-serialize/*': [SKIP], + 'test-strings/*': [SKIP], + 'test-field-type-tracking/*': [SKIP], + 'test-parsing/*': [SKIP], + 'test-page-promotion/*': [SKIP], + 'test-decls/*': [SKIP], + 'test-log/*': [SKIP], + 'test-gap-resolver/*': [SKIP], + 'test-dtoa/*': [SKIP], +}], # variant == wasm_traps + ] diff --git a/deps/v8/test/cctest/compiler/code-assembler-tester.h b/deps/v8/test/cctest/compiler/code-assembler-tester.h index b0c84ec94a..f49e8c55c9 100644 --- a/deps/v8/test/cctest/compiler/code-assembler-tester.h +++ b/deps/v8/test/cctest/compiler/code-assembler-tester.h @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "src/compiler/code-assembler.h" #include "src/handles.h" #include "src/interface-descriptors.h" #include "src/isolate.h" @@ -11,51 +12,43 @@ namespace v8 { namespace internal { namespace compiler { -class ZoneHolder { +class CodeAssemblerTester { public: - explicit ZoneHolder(Isolate* isolate) - : held_zone_(isolate->allocator(), ZONE_NAME) {} - Zone* held_zone() { return &held_zone_; } - - private: - Zone held_zone_; -}; - -// Inherit from ZoneHolder in order to create a zone that can be passed to -// CodeAssembler base class constructor. -template <typename CodeAssemblerT> -class CodeAssemblerTesterImpl : private ZoneHolder, public CodeAssemblerT { - public: - // Test generating code for a stub. - CodeAssemblerTesterImpl(Isolate* isolate, - const CallInterfaceDescriptor& descriptor) - : ZoneHolder(isolate), - CodeAssemblerT(isolate, ZoneHolder::held_zone(), descriptor, - Code::ComputeFlags(Code::STUB), "test"), - scope_(isolate) {} + // Test generating code for a stub. Assumes VoidDescriptor call interface. + explicit CodeAssemblerTester(Isolate* isolate) + : zone_(isolate->allocator(), ZONE_NAME), + scope_(isolate), + state_(isolate, &zone_, VoidDescriptor(isolate), + Code::ComputeFlags(Code::STUB), "test") {} // Test generating code for a JS function (e.g. builtins). - CodeAssemblerTesterImpl(Isolate* isolate, int parameter_count, - Code::Kind kind = Code::BUILTIN) - : ZoneHolder(isolate), - CodeAssemblerT(isolate, ZoneHolder::held_zone(), parameter_count, - Code::ComputeFlags(kind), "test"), - scope_(isolate) {} + CodeAssemblerTester(Isolate* isolate, int parameter_count, + Code::Kind kind = Code::BUILTIN) + : zone_(isolate->allocator(), ZONE_NAME), + scope_(isolate), + state_(isolate, &zone_, parameter_count, Code::ComputeFlags(kind), + "test") {} // This constructor is intended to be used for creating code objects with // specific flags. - CodeAssemblerTesterImpl(Isolate* isolate, Code::Flags flags) - : ZoneHolder(isolate), - CodeAssemblerT(isolate, ZoneHolder::held_zone(), 0, flags, "test"), - scope_(isolate) {} + CodeAssemblerTester(Isolate* isolate, Code::Flags flags) + : zone_(isolate->allocator(), ZONE_NAME), + scope_(isolate), + state_(isolate, &zone_, 0, flags, "test") {} + + CodeAssemblerState* state() { return &state_; } + + Handle<Code> GenerateCode() { return CodeAssembler::GenerateCode(&state_); } Handle<Code> GenerateCodeCloseAndEscape() { - return scope_.CloseAndEscape(CodeAssemblerT::GenerateCode()); + return scope_.CloseAndEscape(GenerateCode()); } private: + Zone zone_; HandleScope scope_; LocalContext context_; + CodeAssemblerState state_; }; } // namespace compiler diff --git a/deps/v8/test/cctest/compiler/function-tester.cc b/deps/v8/test/cctest/compiler/function-tester.cc index 24a49b852c..c88713a6dc 100644 --- a/deps/v8/test/cctest/compiler/function-tester.cc +++ b/deps/v8/test/cctest/compiler/function-tester.cc @@ -14,7 +14,7 @@ #include "src/handles.h" #include "src/objects-inl.h" #include "src/parsing/parse-info.h" -#include "src/parsing/parser.h" +#include "src/parsing/parsing.h" #include "test/cctest/cctest.h" namespace v8 { @@ -46,9 +46,7 @@ FunctionTester::FunctionTester(Handle<Code> code, int param_count) function->ReplaceCode(*code); } -FunctionTester::FunctionTester(const CallInterfaceDescriptor& descriptor, - Handle<Code> code) - : FunctionTester(code, descriptor.GetParameterCount()) {} +FunctionTester::FunctionTester(Handle<Code> code) : FunctionTester(code, 0) {} MaybeHandle<Object> FunctionTester::Call() { return Execution::Call(isolate, function, undefined(), 0, nullptr); @@ -166,7 +164,9 @@ Handle<JSFunction> FunctionTester::Compile(Handle<JSFunction> function) { if (flags_ & CompilationInfo::kInliningEnabled) { info.MarkAsInliningEnabled(); } - if (Compiler::EnsureBytecode(&info)) { + + CHECK(Compiler::Compile(function, Compiler::CLEAR_EXCEPTION)); + if (info.shared_info()->HasBytecodeArray()) { info.MarkAsOptimizeFromBytecode(); } else { CHECK(Compiler::ParseAndAnalyze(info.parse_info())); @@ -189,7 +189,7 @@ Handle<JSFunction> FunctionTester::CompileGraph(Graph* graph) { ParseInfo parse_info(&zone, handle(function->shared())); CompilationInfo info(&parse_info, function); - CHECK(Parser::ParseStatic(info.parse_info())); + CHECK(parsing::ParseFunction(info.parse_info())); info.SetOptimizing(); Handle<Code> code = Pipeline::GenerateCodeForTesting(&info, graph); diff --git a/deps/v8/test/cctest/compiler/function-tester.h b/deps/v8/test/cctest/compiler/function-tester.h index e65fa78c13..07363a0f25 100644 --- a/deps/v8/test/cctest/compiler/function-tester.h +++ b/deps/v8/test/cctest/compiler/function-tester.h @@ -26,7 +26,8 @@ class FunctionTester : public InitializedHandleScope { FunctionTester(Handle<Code> code, int param_count); - FunctionTester(const CallInterfaceDescriptor& descriptor, Handle<Code> code); + // Assumes VoidDescriptor call interface. + explicit FunctionTester(Handle<Code> code); Isolate* isolate; Handle<JSFunction> function; diff --git a/deps/v8/test/cctest/compiler/test-code-assembler.cc b/deps/v8/test/cctest/compiler/test-code-assembler.cc index 6fe733af8d..90fdc2b7ae 100644 --- a/deps/v8/test/cctest/compiler/test-code-assembler.cc +++ b/deps/v8/test/cctest/compiler/test-code-assembler.cc @@ -12,11 +12,9 @@ namespace v8 { namespace internal { namespace compiler { -typedef CodeAssemblerTesterImpl<CodeAssembler> CodeAssemblerTester; - namespace { -Node* SmiTag(CodeAssemblerTester& m, Node* value) { +Node* SmiTag(CodeAssembler& m, Node* value) { int32_t constant_value; if (m.ToInt32Constant(value, constant_value) && Smi::IsValid(constant_value)) { @@ -25,36 +23,47 @@ Node* SmiTag(CodeAssemblerTester& m, Node* value) { return m.WordShl(value, m.IntPtrConstant(kSmiShiftSize + kSmiTagSize)); } -Node* UndefinedConstant(CodeAssemblerTester& m) { +Node* UndefinedConstant(CodeAssembler& m) { return m.LoadRoot(Heap::kUndefinedValueRootIndex); } -Node* LoadObjectField(CodeAssemblerTester& m, Node* object, int offset, +Node* SmiFromWord32(CodeAssembler& m, Node* value) { + value = m.ChangeInt32ToIntPtr(value); + return m.BitcastWordToTaggedSigned( + m.WordShl(value, kSmiShiftSize + kSmiTagSize)); +} + +Node* LoadObjectField(CodeAssembler& m, Node* object, int offset, MachineType rep = MachineType::AnyTagged()) { return m.Load(rep, object, m.IntPtrConstant(offset - kHeapObjectTag)); } +Node* LoadMap(CodeAssembler& m, Node* object) { + return LoadObjectField(m, object, JSObject::kMapOffset); +} + } // namespace TEST(SimpleSmiReturn) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); m.Return(SmiTag(m, m.Int32Constant(37))); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(37, Handle<Smi>::cast(result.ToHandleChecked())->value()); } TEST(SimpleIntPtrReturn) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); int test; - m.Return(m.IntPtrConstant(reinterpret_cast<intptr_t>(&test))); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + m.Return(m.BitcastWordToTagged( + m.IntPtrConstant(reinterpret_cast<intptr_t>(&test)))); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(reinterpret_cast<intptr_t>(&test), reinterpret_cast<intptr_t>(*result.ToHandleChecked())); @@ -62,65 +71,65 @@ TEST(SimpleIntPtrReturn) { TEST(SimpleDoubleReturn) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); m.Return(m.NumberConstant(0.5)); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(0.5, Handle<HeapNumber>::cast(result.ToHandleChecked())->value()); } TEST(SimpleCallRuntime1Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* b = SmiTag(m, m.Int32Constant(0)); m.Return(m.CallRuntime(Runtime::kNumberToSmi, context, b)); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); } TEST(SimpleTailCallRuntime1Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* b = SmiTag(m, m.Int32Constant(0)); m.TailCallRuntime(Runtime::kNumberToSmi, context, b); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(0, Handle<Smi>::cast(result.ToHandleChecked())->value()); } TEST(SimpleCallRuntime2Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* a = SmiTag(m, m.Int32Constant(2)); Node* b = SmiTag(m, m.Int32Constant(4)); m.Return(m.CallRuntime(Runtime::kAdd, context, a, b)); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); } TEST(SimpleTailCallRuntime2Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); Node* a = SmiTag(m, m.Int32Constant(2)); Node* b = SmiTag(m, m.Int32Constant(4)); m.TailCallRuntime(Runtime::kAdd, context, a, b); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(6, Handle<Smi>::cast(result.ToHandleChecked())->value()); } @@ -144,7 +153,8 @@ Handle<JSFunction> CreateSumAllArgumentsFunction(FunctionTester& ft) { TEST(SimpleCallJSFunction0Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 1; - CodeAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeAssembler m(data.state()); { Node* function = m.Parameter(0); Node* context = m.Parameter(kNumParams + 2); @@ -155,7 +165,7 @@ TEST(SimpleCallJSFunction0Arg) { Node* result = m.CallJS(callable, context, function, receiver); m.Return(result); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); @@ -166,7 +176,8 @@ TEST(SimpleCallJSFunction0Arg) { TEST(SimpleCallJSFunction1Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 2; - CodeAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeAssembler m(data.state()); { Node* function = m.Parameter(0); Node* context = m.Parameter(1); @@ -178,7 +189,7 @@ TEST(SimpleCallJSFunction1Arg) { Node* result = m.CallJS(callable, context, function, receiver, a); m.Return(result); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); @@ -189,7 +200,8 @@ TEST(SimpleCallJSFunction1Arg) { TEST(SimpleCallJSFunction2Arg) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 2; - CodeAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeAssembler m(data.state()); { Node* function = m.Parameter(0); Node* context = m.Parameter(1); @@ -202,7 +214,7 @@ TEST(SimpleCallJSFunction2Arg) { Node* result = m.CallJS(callable, context, function, receiver, a, b); m.Return(result); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<JSFunction> sum = CreateSumAllArgumentsFunction(ft); @@ -212,10 +224,10 @@ TEST(SimpleCallJSFunction2Arg) { TEST(VariableMerge1) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); - CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerVariable var1(&m, MachineRepresentation::kTagged); + CodeAssemblerLabel l1(&m), l2(&m), merge(&m); Node* temp = m.Int32Constant(0); var1.Bind(temp); m.Branch(m.Int32Constant(1), &l1, &l2); @@ -231,10 +243,10 @@ TEST(VariableMerge1) { TEST(VariableMerge2) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); - CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerVariable var1(&m, MachineRepresentation::kTagged); + CodeAssemblerLabel l1(&m), l2(&m), merge(&m); Node* temp = m.Int32Constant(0); var1.Bind(temp); m.Branch(m.Int32Constant(1), &l1, &l2); @@ -252,11 +264,11 @@ TEST(VariableMerge2) { TEST(VariableMerge3) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); - CodeStubAssembler::Variable var2(&m, MachineRepresentation::kTagged); - CodeStubAssembler::Label l1(&m), l2(&m), merge(&m); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerVariable var1(&m, MachineRepresentation::kTagged); + CodeAssemblerVariable var2(&m, MachineRepresentation::kTagged); + CodeAssemblerLabel l1(&m), l2(&m), merge(&m); Node* temp = m.Int32Constant(0); var1.Bind(temp); var2.Bind(temp); @@ -277,10 +289,10 @@ TEST(VariableMerge3) { TEST(VariableMergeBindFirst) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); - CodeStubAssembler::Label l1(&m), l2(&m), merge(&m, &var1), end(&m); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerVariable var1(&m, MachineRepresentation::kTagged); + CodeAssemblerLabel l1(&m), l2(&m), merge(&m, &var1), end(&m); Node* temp = m.Int32Constant(0); var1.Bind(temp); m.Branch(m.Int32Constant(1), &l1, &l2); @@ -303,11 +315,11 @@ TEST(VariableMergeBindFirst) { TEST(VariableMergeSwitch) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Variable var1(&m, MachineRepresentation::kTagged); - CodeStubAssembler::Label l1(&m), l2(&m), default_label(&m); - CodeStubAssembler::Label* labels[] = {&l1, &l2}; + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerVariable var1(&m, MachineRepresentation::kTagged); + CodeAssemblerLabel l1(&m), l2(&m), default_label(&m); + CodeAssemblerLabel* labels[] = {&l1, &l2}; int32_t values[] = {1, 2}; Node* temp = m.Int32Constant(0); var1.Bind(temp); @@ -325,22 +337,22 @@ TEST(VariableMergeSwitch) { TEST(SplitEdgeBranchMerge) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Label l1(&m), merge(&m); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerLabel l1(&m), merge(&m); m.Branch(m.Int32Constant(1), &l1, &merge); m.Bind(&l1); m.Goto(&merge); m.Bind(&merge); - USE(m.GenerateCode()); + USE(data.GenerateCode()); } TEST(SplitEdgeSwitchMerge) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); - CodeStubAssembler::Label l1(&m), l2(&m), l3(&m), default_label(&m); - CodeStubAssembler::Label* labels[] = {&l1, &l2}; + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); + CodeAssemblerLabel l1(&m), l2(&m), l3(&m), default_label(&m); + CodeAssemblerLabel* labels[] = {&l1, &l2}; int32_t values[] = {1, 2}; m.Branch(m.Int32Constant(1), &l3, &l1); m.Bind(&l3); @@ -350,13 +362,13 @@ TEST(SplitEdgeSwitchMerge) { m.Bind(&l2); m.Goto(&default_label); m.Bind(&default_label); - USE(m.GenerateCode()); + USE(data.GenerateCode()); } TEST(TestToConstant) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); int32_t value32; int64_t value64; Node* a = m.Int32Constant(5); @@ -381,36 +393,35 @@ TEST(TestToConstant) { } TEST(DeferredCodePhiHints) { - typedef compiler::Node Node; - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); Label block1(&m, Label::kDeferred); m.Goto(&block1); m.Bind(&block1); { Variable var_object(&m, MachineRepresentation::kTagged); Label loop(&m, &var_object); - var_object.Bind(m.IntPtrConstant(0)); + var_object.Bind(m.SmiConstant(0)); m.Goto(&loop); m.Bind(&loop); { - Node* map = LoadObjectField(m, var_object.value(), JSObject::kMapOffset); + Node* map = LoadMap(m, var_object.value()); var_object.Bind(map); m.Goto(&loop); } } - CHECK(!m.GenerateCode().is_null()); + CHECK(!data.GenerateCode().is_null()); } TEST(TestOutOfScopeVariable) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeAssembler m(data.state()); Label block1(&m); Label block2(&m); Label block3(&m); @@ -431,7 +442,136 @@ TEST(TestOutOfScopeVariable) { m.Goto(&block1); } m.Bind(&block1); - CHECK(!m.GenerateCode().is_null()); + CHECK(!data.GenerateCode().is_null()); +} + +TEST(GotoIfException) { + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + CodeAssembler m(data.state()); + + Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); + Node* to_string_tag = + m.HeapConstant(isolate->factory()->to_string_tag_symbol()); + Variable exception(&m, MachineRepresentation::kTagged); + + Label exception_handler(&m); + Callable to_string = CodeFactory::ToString(isolate); + Node* string = m.CallStub(to_string, context, to_string_tag); + m.GotoIfException(string, &exception_handler, &exception); + m.Return(string); + + m.Bind(&exception_handler); + m.Return(exception.value()); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = ft.Call().ToHandleChecked(); + + // Should be a TypeError. + CHECK(result->IsJSObject()); + + Handle<Object> constructor = + Object::GetPropertyOrElement(result, + isolate->factory()->constructor_string()) + .ToHandleChecked(); + CHECK(constructor->SameValue(*isolate->type_error_function())); +} + +TEST(GotoIfExceptionMultiple) { + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 4; // receiver, first, second, third + CodeAssemblerTester data(isolate, kNumParams); + CodeAssembler m(data.state()); + + Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); + Node* first_value = m.Parameter(0); + Node* second_value = m.Parameter(1); + Node* third_value = m.Parameter(2); + + Label exception_handler1(&m); + Label exception_handler2(&m); + Label exception_handler3(&m); + Variable return_value(&m, MachineRepresentation::kWord32); + Variable error(&m, MachineRepresentation::kTagged); + + return_value.Bind(m.Int32Constant(0)); + + // try { return ToString(param1) } catch (e) { ... } + Callable to_string = CodeFactory::ToString(isolate); + Node* string = m.CallStub(to_string, context, first_value); + m.GotoIfException(string, &exception_handler1, &error); + m.Return(string); + + // try { ToString(param2); return 7 } catch (e) { ... } + m.Bind(&exception_handler1); + return_value.Bind(m.Int32Constant(7)); + error.Bind(UndefinedConstant(m)); + string = m.CallStub(to_string, context, second_value); + m.GotoIfException(string, &exception_handler2, &error); + m.Return(SmiFromWord32(m, return_value.value())); + + // try { ToString(param3); return 7 & ~2; } catch (e) { return e; } + m.Bind(&exception_handler2); + // Return returnValue & ~2 + error.Bind(UndefinedConstant(m)); + string = m.CallStub(to_string, context, third_value); + m.GotoIfException(string, &exception_handler3, &error); + m.Return(SmiFromWord32( + m, m.Word32And(return_value.value(), + m.Word32Xor(m.Int32Constant(2), m.Int32Constant(-1))))); + + m.Bind(&exception_handler3); + m.Return(error.value()); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + + Handle<Object> result; + // First handler does not throw, returns result of first value. + result = ft.Call(isolate->factory()->undefined_value(), + isolate->factory()->to_string_tag_symbol()) + .ToHandleChecked(); + CHECK(String::cast(*result)->IsOneByteEqualTo(OneByteVector("undefined"))); + + // First handler returns a number. + result = ft.Call(isolate->factory()->to_string_tag_symbol(), + isolate->factory()->undefined_value()) + .ToHandleChecked(); + CHECK_EQ(7, Smi::cast(*result)->value()); + + // First handler throws, second handler returns a number. + result = ft.Call(isolate->factory()->to_string_tag_symbol(), + isolate->factory()->to_primitive_symbol()) + .ToHandleChecked(); + CHECK_EQ(7 & ~2, Smi::cast(*result)->value()); + + // First handler throws, second handler throws, third handler returns thrown + // value. + result = ft.Call(isolate->factory()->to_string_tag_symbol(), + isolate->factory()->to_primitive_symbol(), + isolate->factory()->unscopables_symbol()) + .ToHandleChecked(); + + // Should be a TypeError. + CHECK(result->IsJSObject()); + + Handle<Object> constructor = + Object::GetPropertyOrElement(result, + isolate->factory()->constructor_string()) + .ToHandleChecked(); + CHECK(constructor->SameValue(*isolate->type_error_function())); } } // namespace compiler 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 023ef483ea..d8122c4fdb 100644 --- a/deps/v8/test/cctest/compiler/test-js-context-specialization.cc +++ b/deps/v8/test/cctest/compiler/test-js-context-specialization.cc @@ -18,7 +18,7 @@ namespace compiler { class ContextSpecializationTester : public HandleAndZoneScope { public: - ContextSpecializationTester() + explicit ContextSpecializationTester(MaybeHandle<Context> context) : graph_(new (main_zone()) Graph(main_zone())), common_(main_zone()), javascript_(main_zone()), @@ -27,7 +27,7 @@ class ContextSpecializationTester : public HandleAndZoneScope { jsgraph_(main_isolate(), graph(), common(), &javascript_, &simplified_, &machine_), reducer_(main_zone(), graph()), - spec_(&reducer_, jsgraph(), MaybeHandle<Context>()) {} + spec_(&reducer_, jsgraph(), context) {} JSContextSpecialization* spec() { return &spec_; } Factory* factory() { return main_isolate()->factory(); } @@ -37,6 +37,13 @@ class ContextSpecializationTester : public HandleAndZoneScope { JSGraph* jsgraph() { return &jsgraph_; } Graph* graph() { return graph_; } + void CheckChangesToValue(Node* node, Handle<HeapObject> expected_value); + void CheckContextInputAndDepthChanges( + Node* node, Handle<Context> expected_new_context_object, + size_t expected_new_depth); + void CheckContextInputAndDepthChanges(Node* node, Node* expected_new_context, + size_t expected_new_depth); + private: Graph* graph_; CommonOperatorBuilder common_; @@ -48,9 +55,52 @@ class ContextSpecializationTester : public HandleAndZoneScope { JSContextSpecialization spec_; }; +void ContextSpecializationTester::CheckChangesToValue( + Node* node, Handle<HeapObject> expected_value) { + Reduction r = spec()->Reduce(node); + CHECK(r.Changed()); + HeapObjectMatcher match(r.replacement()); + CHECK(match.HasValue()); + CHECK_EQ(*match.Value(), *expected_value); +} + +void ContextSpecializationTester::CheckContextInputAndDepthChanges( + Node* node, Handle<Context> expected_new_context_object, + size_t expected_new_depth) { + ContextAccess access = OpParameter<ContextAccess>(node); + Reduction r = spec()->Reduce(node); + CHECK(r.Changed()); + + Node* new_context = NodeProperties::GetContextInput(r.replacement()); + CHECK_EQ(IrOpcode::kHeapConstant, new_context->opcode()); + HeapObjectMatcher match(new_context); + CHECK_EQ(*match.Value(), *expected_new_context_object); + + ContextAccess new_access = OpParameter<ContextAccess>(r.replacement()); + CHECK_EQ(new_access.depth(), expected_new_depth); + CHECK_EQ(new_access.index(), access.index()); + CHECK_EQ(new_access.immutable(), access.immutable()); +} + +void ContextSpecializationTester::CheckContextInputAndDepthChanges( + Node* node, Node* expected_new_context, size_t expected_new_depth) { + ContextAccess access = OpParameter<ContextAccess>(node); + Reduction r = spec()->Reduce(node); + CHECK(r.Changed()); + + Node* new_context = NodeProperties::GetContextInput(r.replacement()); + CHECK_EQ(new_context, expected_new_context); -TEST(ReduceJSLoadContext) { - ContextSpecializationTester t; + ContextAccess new_access = OpParameter<ContextAccess>(r.replacement()); + CHECK_EQ(new_access.depth(), expected_new_depth); + CHECK_EQ(new_access.index(), access.index()); + CHECK_EQ(new_access.immutable(), access.immutable()); +} + +static const int slot_index = Context::NATIVE_CONTEXT_INDEX; + +TEST(ReduceJSLoadContext0) { + ContextSpecializationTester t((MaybeHandle<Context>())); Node* start = t.graph()->NewNode(t.common()->Start(0)); t.graph()->SetStart(start); @@ -72,7 +122,7 @@ TEST(ReduceJSLoadContext) { { // Mutable slot, constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), - const_context, const_context, start); + const_context, start); Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -80,7 +130,7 @@ TEST(ReduceJSLoadContext) { { // Mutable slot, non-constant context, depth = 0 => do nothing. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, 0, false), - param_context, param_context, start); + param_context, start); Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -89,10 +139,10 @@ TEST(ReduceJSLoadContext) { // Mutable slot, constant context, depth > 0 => fold-in parent context. Node* load = t.graph()->NewNode( t.javascript()->LoadContext(2, Context::GLOBAL_EVAL_FUN_INDEX, false), - deep_const_context, deep_const_context, start); + deep_const_context, start); Reduction r = t.spec()->Reduce(load); CHECK(r.Changed()); - Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); + Node* new_context_input = NodeProperties::GetContextInput(r.replacement()); CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); HeapObjectMatcher match(new_context_input); CHECK_EQ(*native, *match.Value()); @@ -105,7 +155,7 @@ TEST(ReduceJSLoadContext) { { // Immutable slot, constant context, depth = 0 => specialize. Node* load = t.graph()->NewNode(t.javascript()->LoadContext(0, slot, true), - const_context, const_context, start); + const_context, start); Reduction r = t.spec()->Reduce(load); CHECK(r.Changed()); CHECK(r.replacement() != load); @@ -114,14 +164,239 @@ TEST(ReduceJSLoadContext) { CHECK(match.HasValue()); CHECK_EQ(*expected, *match.Value()); } +} + +TEST(ReduceJSLoadContext1) { + // The graph's context chain ends in the incoming context parameter: + // + // context2 <-- context1 <-- context0 (= Parameter(0)) + + ContextSpecializationTester t((MaybeHandle<Context>())); + + Node* start = t.graph()->NewNode(t.common()->Start(0)); + t.graph()->SetStart(start); + Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); + const i::compiler::Operator* create_function_context = + t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); + + Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); + Node* context1 = t.graph()->NewNode(create_function_context, undefined, + context0, start, start); + Node* context2 = t.graph()->NewNode(create_function_context, undefined, + context1, start, start); + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(0, slot_index, false), context2, start); + CHECK(!t.spec()->Reduce(load).Changed()); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(0, slot_index, true), context2, start); + CHECK(!t.spec()->Reduce(load).Changed()); + } - // TODO(titzer): test with other kinds of contexts, e.g. a function context. - // TODO(sigurds): test that loads below create context are not optimized + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(1, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(1, slot_index, true), context2, start); + t.CheckContextInputAndDepthChanges(load, context1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(2, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context0, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(2, slot_index, true), context2, start); + t.CheckContextInputAndDepthChanges(load, context0, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(3, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context0, 1); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(3, slot_index, true), context2, start); + t.CheckContextInputAndDepthChanges(load, context0, 1); + } } +TEST(ReduceJSLoadContext2) { + // The graph's context chain ends in a constant context (context_object1), + // which has has another outer context (context_object0). + // + // context2 <-- context1 <-- context0 (= HeapConstant(context_object1)) + // context_object1 <~~ context_object0 -TEST(ReduceJSStoreContext) { - ContextSpecializationTester t; + ContextSpecializationTester t((MaybeHandle<Context>())); + + Node* start = t.graph()->NewNode(t.common()->Start(0)); + t.graph()->SetStart(start); + Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); + const i::compiler::Operator* create_function_context = + t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); + + Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); + Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); + + Handle<Context> context_object0 = t.factory()->NewNativeContext(); + Handle<Context> context_object1 = t.factory()->NewNativeContext(); + context_object1->set_previous(*context_object0); + context_object0->set(slot_index, *slot_value0); + context_object1->set(slot_index, *slot_value1); + + Node* context0 = t.jsgraph()->Constant(context_object1); + Node* context1 = t.graph()->NewNode(create_function_context, undefined, + context0, start, start); + Node* context2 = t.graph()->NewNode(create_function_context, undefined, + context1, start, start); + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(0, slot_index, false), context2, start); + CHECK(!t.spec()->Reduce(load).Changed()); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(0, slot_index, true), context2, start); + CHECK(!t.spec()->Reduce(load).Changed()); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(1, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(1, slot_index, true), context2, start); + t.CheckContextInputAndDepthChanges(load, context1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(2, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context0, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(2, slot_index, true), context2, start); + t.CheckChangesToValue(load, slot_value1); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(3, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context_object0, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(3, slot_index, true), context2, start); + t.CheckChangesToValue(load, slot_value0); + } +} + +TEST(ReduceJSLoadContext3) { + // Like in ReduceJSLoadContext1, the graph's context chain ends in the + // incoming context parameter. However, this time we provide a concrete + // context for this parameter as the "specialization context". We choose + // context_object2 from ReduceJSLoadContext2 for this, so almost all test + // expectations are the same as in ReduceJSLoadContext2. + + HandleAndZoneScope handle_zone_scope; + auto factory = handle_zone_scope.main_isolate()->factory(); + + Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); + Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); + + Handle<Context> context_object0 = factory->NewNativeContext(); + Handle<Context> context_object1 = factory->NewNativeContext(); + context_object1->set_previous(*context_object0); + context_object0->set(slot_index, *slot_value0); + context_object1->set(slot_index, *slot_value1); + + ContextSpecializationTester t(context_object1); + + Node* start = t.graph()->NewNode(t.common()->Start(2)); + t.graph()->SetStart(start); + Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); + const i::compiler::Operator* create_function_context = + t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); + + Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); + Node* context1 = t.graph()->NewNode(create_function_context, undefined, + context0, start, start); + Node* context2 = t.graph()->NewNode(create_function_context, undefined, + context1, start, start); + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(0, slot_index, false), context2, start); + CHECK(!t.spec()->Reduce(load).Changed()); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(0, slot_index, true), context2, start); + CHECK(!t.spec()->Reduce(load).Changed()); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(1, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(1, slot_index, true), context2, start); + t.CheckContextInputAndDepthChanges(load, context1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(2, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context_object1, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(2, slot_index, true), context2, start); + t.CheckChangesToValue(load, slot_value1); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(3, slot_index, false), context2, start); + t.CheckContextInputAndDepthChanges(load, context_object0, 0); + } + + { + Node* load = t.graph()->NewNode( + t.javascript()->LoadContext(3, slot_index, true), context2, start); + t.CheckChangesToValue(load, slot_value0); + } +} + +TEST(ReduceJSStoreContext0) { + ContextSpecializationTester t((MaybeHandle<Context>())); Node* start = t.graph()->NewNode(t.common()->Start(0)); t.graph()->SetStart(start); @@ -142,27 +417,24 @@ TEST(ReduceJSStoreContext) { { // Mutable slot, constant context, depth = 0 => do nothing. - Node* load = - t.graph()->NewNode(t.javascript()->StoreContext(0, 0), const_context, - const_context, const_context, start, start); + Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, 0), + const_context, const_context, start, start); Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } { // Mutable slot, non-constant context, depth = 0 => do nothing. - Node* load = - t.graph()->NewNode(t.javascript()->StoreContext(0, 0), param_context, - param_context, const_context, start, start); + Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, 0), + param_context, param_context, start, start); Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } { // Immutable slot, constant context, depth = 0 => do nothing. - Node* load = - t.graph()->NewNode(t.javascript()->StoreContext(0, slot), const_context, - const_context, const_context, start, start); + Node* load = t.graph()->NewNode(t.javascript()->StoreContext(0, slot), + const_context, const_context, start, start); Reduction r = t.spec()->Reduce(load); CHECK(!r.Changed()); } @@ -171,10 +443,10 @@ TEST(ReduceJSStoreContext) { // Mutable slot, constant context, depth > 0 => fold-in parent context. Node* load = t.graph()->NewNode( t.javascript()->StoreContext(2, Context::GLOBAL_EVAL_FUN_INDEX), - deep_const_context, deep_const_context, const_context, start, start); + deep_const_context, deep_const_context, start, start); Reduction r = t.spec()->Reduce(load); CHECK(r.Changed()); - Node* new_context_input = NodeProperties::GetValueInput(r.replacement(), 0); + Node* new_context_input = NodeProperties::GetContextInput(r.replacement()); CHECK_EQ(IrOpcode::kHeapConstant, new_context_input->opcode()); HeapObjectMatcher match(new_context_input); CHECK_EQ(*native, *match.Value()); @@ -185,6 +457,158 @@ TEST(ReduceJSStoreContext) { } } +TEST(ReduceJSStoreContext1) { + ContextSpecializationTester t((MaybeHandle<Context>())); + + Node* start = t.graph()->NewNode(t.common()->Start(0)); + t.graph()->SetStart(start); + Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); + const i::compiler::Operator* create_function_context = + t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); + + Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); + Node* context1 = t.graph()->NewNode(create_function_context, undefined, + context0, start, start); + Node* context2 = t.graph()->NewNode(create_function_context, undefined, + context1, start, start); + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(0, slot_index), + context2, context2, start, start); + CHECK(!t.spec()->Reduce(store).Changed()); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(1, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context1, 0); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(2, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context0, 0); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context0, 1); + } +} + +TEST(ReduceJSStoreContext2) { + ContextSpecializationTester t((MaybeHandle<Context>())); + + Node* start = t.graph()->NewNode(t.common()->Start(0)); + t.graph()->SetStart(start); + Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); + const i::compiler::Operator* create_function_context = + t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); + + Handle<HeapObject> slot_value0 = t.factory()->InternalizeUtf8String("0"); + Handle<HeapObject> slot_value1 = t.factory()->InternalizeUtf8String("1"); + + Handle<Context> context_object0 = t.factory()->NewNativeContext(); + Handle<Context> context_object1 = t.factory()->NewNativeContext(); + context_object1->set_previous(*context_object0); + context_object0->set(slot_index, *slot_value0); + context_object1->set(slot_index, *slot_value1); + + Node* context0 = t.jsgraph()->Constant(context_object1); + Node* context1 = t.graph()->NewNode(create_function_context, undefined, + context0, start, start); + Node* context2 = t.graph()->NewNode(create_function_context, undefined, + context1, start, start); + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(0, slot_index), + context2, context2, start, start); + CHECK(!t.spec()->Reduce(store).Changed()); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(1, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context1, 0); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(2, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context0, 0); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context_object0, 0); + } +} + +TEST(ReduceJSStoreContext3) { + HandleAndZoneScope handle_zone_scope; + auto factory = handle_zone_scope.main_isolate()->factory(); + + Handle<HeapObject> slot_value0 = factory->InternalizeUtf8String("0"); + Handle<HeapObject> slot_value1 = factory->InternalizeUtf8String("1"); + + Handle<Context> context_object0 = factory->NewNativeContext(); + Handle<Context> context_object1 = factory->NewNativeContext(); + context_object1->set_previous(*context_object0); + context_object0->set(slot_index, *slot_value0); + context_object1->set(slot_index, *slot_value1); + + ContextSpecializationTester t(context_object1); + + Node* start = t.graph()->NewNode(t.common()->Start(2)); + t.graph()->SetStart(start); + Node* undefined = t.jsgraph()->Constant(t.factory()->undefined_value()); + const i::compiler::Operator* create_function_context = + t.javascript()->CreateFunctionContext(42, FUNCTION_SCOPE); + + Node* context0 = t.graph()->NewNode(t.common()->Parameter(0), start); + Node* context1 = t.graph()->NewNode(create_function_context, undefined, + context0, start, start); + Node* context2 = t.graph()->NewNode(create_function_context, undefined, + context1, start, start); + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(0, slot_index), + context2, context2, start, start); + CHECK(!t.spec()->Reduce(store).Changed()); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(1, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context1, 0); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(2, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context_object1, 0); + } + + { + Node* store = + t.graph()->NewNode(t.javascript()->StoreContext(3, slot_index), + context2, context2, start, start); + t.CheckContextInputAndDepthChanges(store, context_object0, 0); + } +} TEST(SpecializeJSFunction_ToConstant1) { FunctionTester T( 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 f504e549fd..606f338052 100644 --- a/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc +++ b/deps/v8/test/cctest/compiler/test-js-typed-lowering.cc @@ -77,9 +77,12 @@ class JSTypedLoweringTester : public HandleAndZoneScope { } Node* EmptyFrameState(Node* context) { - Node* parameters = graph.NewNode(common.StateValues(0)); - Node* locals = graph.NewNode(common.StateValues(0)); - Node* stack = graph.NewNode(common.StateValues(0)); + Node* parameters = + graph.NewNode(common.StateValues(0, SparseInputMask::Dense())); + Node* locals = + graph.NewNode(common.StateValues(0, SparseInputMask::Dense())); + Node* stack = + graph.NewNode(common.StateValues(0, SparseInputMask::Dense())); Node* state_node = graph.NewNode( common.FrameState(BailoutId::None(), OutputFrameStateCombine::Ignore(), diff --git a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc index 7ae14b54c8..b70df3563c 100644 --- a/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc +++ b/deps/v8/test/cctest/compiler/test-loop-assignment-analysis.cc @@ -5,8 +5,9 @@ #include "src/ast/scopes.h" #include "src/compilation-info.h" #include "src/compiler/ast-loop-assignment-analyzer.h" +#include "src/objects-inl.h" #include "src/parsing/parse-info.h" -#include "src/parsing/parser.h" +#include "src/parsing/parsing.h" #include "src/parsing/rewriter.h" #include "test/cctest/cctest.h" @@ -35,7 +36,7 @@ struct TestHelper : public HandleAndZoneScope { ParseInfo parse_info(main_zone(), handle(function->shared())); CompilationInfo info(&parse_info, function); - CHECK(Parser::ParseStatic(&parse_info)); + CHECK(parsing::ParseFunction(&parse_info)); CHECK(Rewriter::Rewrite(&parse_info)); DeclarationScope::Analyze(&parse_info, AnalyzeMode::kRegular); @@ -71,27 +72,8 @@ TEST(SimpleLoop1) { f.CheckLoopAssignedCount(0, "x"); } - -TEST(SimpleLoop2) { - const char* loops[] = { - "while (x) { var x = 0; }", "for(;;) { var x = 0; }", - "for(;x;) { var x = 0; }", "for(;x;x) { var x = 0; }", - "for(var i = x; x; x) { var x = 0; }", "for(y in 0) { var x = 0; }", - "for(y of 0) { var x = 0; }", "for(var x = 0; x; x++) { }", - "for(var x = 0; x++;) { }", "var x; for(;x;x++) { }", - "var x; do { x = 1; } while (0);", "do { var x = 1; } while (0);"}; - - for (size_t i = 0; i < arraysize(loops); i++) { - TestHelper f(loops[i]); - f.CheckLoopAssignedCount(1, "x"); - } -} - - -TEST(ForInOf1) { - const char* loops[] = { - "for(x in 0) { }", "for(x of 0) { }", - }; +TEST(ForIn1) { + const char* loops[] = {"for(x in 0) { }"}; for (size_t i = 0; i < arraysize(loops); i++) { TestHelper f(loops[i]); diff --git a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc index cf3da887ba..15bd72c4d4 100644 --- a/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc +++ b/deps/v8/test/cctest/compiler/test-machine-operator-reducer.cc @@ -850,12 +850,12 @@ TEST(ReduceFloat32Sub) { } Node* x = R.Parameter(); - Node* zero = R.Constant<float>(0.0); Node* nan = R.Constant<float>(std::numeric_limits<float>::quiet_NaN()); - R.CheckBinop(x, x, zero); // x - 0 => x - R.CheckBinop(nan, nan, x); // nan - x => nan - R.CheckBinop(nan, x, nan); // x - nan => nan + // nan - x => nan + R.CheckFoldBinop(std::numeric_limits<float>::quiet_NaN(), nan, x); + // x - nan => nan + R.CheckFoldBinop(std::numeric_limits<float>::quiet_NaN(), x, nan); } TEST(ReduceFloat64Sub) { @@ -870,12 +870,12 @@ TEST(ReduceFloat64Sub) { } Node* x = R.Parameter(); - Node* zero = R.Constant<double>(0.0); Node* nan = R.Constant<double>(std::numeric_limits<double>::quiet_NaN()); - R.CheckBinop(x, x, zero); // x - 0 => x - R.CheckBinop(nan, nan, x); // nan - x => nan - R.CheckBinop(nan, x, nan); // x - nan => nan + // nan - x => nan + R.CheckFoldBinop(std::numeric_limits<double>::quiet_NaN(), nan, x); + // x - nan => nan + R.CheckFoldBinop(std::numeric_limits<double>::quiet_NaN(), x, nan); } // TODO(titzer): test MachineOperatorReducer for Word64And diff --git a/deps/v8/test/cctest/compiler/test-representation-change.cc b/deps/v8/test/cctest/compiler/test-representation-change.cc index ab2a1f6dfe..c8519faeb5 100644 --- a/deps/v8/test/cctest/compiler/test-representation-change.cc +++ b/deps/v8/test/cctest/compiler/test-representation-change.cc @@ -427,7 +427,7 @@ TEST(SignednessInWord32) { MachineRepresentation::kFloat64, Type::Number(), MachineRepresentation::kWord32); CheckChange(IrOpcode::kCheckedTruncateTaggedToWord32, - MachineRepresentation::kTagged, Type::NumberOrOddball(), + MachineRepresentation::kTagged, Type::NonInternal(), MachineRepresentation::kWord32, UseInfo::CheckedNumberOrOddballAsWord32()); diff --git a/deps/v8/test/cctest/compiler/test-run-bytecode-graph-builder.cc b/deps/v8/test/cctest/compiler/test-run-bytecode-graph-builder.cc index 74a51b915a..ea7fcd6449 100644 --- a/deps/v8/test/cctest/compiler/test-run-bytecode-graph-builder.cc +++ b/deps/v8/test/cctest/compiler/test-run-bytecode-graph-builder.cc @@ -10,6 +10,7 @@ #include "src/handles.h" #include "src/interpreter/bytecode-array-builder.h" #include "src/interpreter/interpreter.h" +#include "src/objects-inl.h" #include "src/parsing/parse-info.h" #include "test/cctest/cctest.h" @@ -80,8 +81,6 @@ class BytecodeGraphTester { i::FLAG_always_opt = false; i::FLAG_allow_natives_syntax = true; i::FLAG_loop_assignment_analysis = false; - // Ensure handler table is generated. - isolate->interpreter()->Initialize(); } virtual ~BytecodeGraphTester() {} @@ -3029,35 +3028,32 @@ TEST(BytecodeGraphBuilderIllegalConstDeclaration) { } } +static int debug_break_count = 0; +static void DebugEventCounter(const v8::Debug::EventDetails& event_details) { + if (event_details.GetEvent() == v8::Break) debug_break_count++; +} + TEST(BytecodeGraphBuilderDebuggerStatement) { - FLAG_expose_debug_as = "debug"; HandleAndZoneScope scope; Isolate* isolate = scope.main_isolate(); Zone* zone = scope.main_zone(); + v8::Debug::SetDebugEventListener(CcTest::isolate(), DebugEventCounter); + ExpectedSnippet<0> snippet = { - "var Debug = debug.Debug;" - "var count = 0;" "function f() {" " debugger;" "}" - "function listener(event) {" - " if (event == Debug.DebugEvent.Break) count++;" - "}" - "Debug.setListener(listener);" - "f();" - "Debug.setListener(null);" - "return count;", - {handle(Smi::FromInt(1), isolate)}}; - - ScopedVector<char> script(1024); - SNPrintF(script, "function %s() { %s }\n%s();", kFunctionName, - snippet.code_snippet, kFunctionName); + "f();", + {isolate->factory()->undefined_value()}}; - BytecodeGraphTester tester(isolate, zone, script.start()); + BytecodeGraphTester tester(isolate, zone, snippet.code_snippet); auto callable = tester.GetCallable<>(); Handle<Object> return_value = callable().ToHandleChecked(); - CHECK(return_value->SameValue(*snippet.return_value())); + + v8::Debug::SetDebugEventListener(CcTest::isolate(), nullptr); + CHECK(return_value.is_identical_to(snippet.return_value())); + CHECK_EQ(2, debug_break_count); } } // namespace compiler diff --git a/deps/v8/test/cctest/compiler/test-run-inlining.cc b/deps/v8/test/cctest/compiler/test-run-inlining.cc deleted file mode 100644 index 22e791a5f8..0000000000 --- a/deps/v8/test/cctest/compiler/test-run-inlining.cc +++ /dev/null @@ -1,471 +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 "src/compilation-info.h" -#include "src/frames-inl.h" -#include "test/cctest/compiler/function-tester.h" - -namespace v8 { -namespace internal { -namespace compiler { - -namespace { - -// Helper to determine inline count via JavaScriptFrame::GetFunctions. -// Note that a count of 1 indicates that no inlining has occured. -void AssertInlineCount(const v8::FunctionCallbackInfo<v8::Value>& args) { - JavaScriptFrameIterator it(CcTest::i_isolate()); - int frames_seen = 0; - JavaScriptFrame* topmost = it.frame(); - while (!it.done()) { - JavaScriptFrame* frame = it.frame(); - List<JSFunction*> functions(2); - frame->GetFunctions(&functions); - PrintF("%d %s, inline count: %d\n", frames_seen, - frame->function()->shared()->DebugName()->ToCString().get(), - functions.length()); - frames_seen++; - it.Advance(); - } - List<JSFunction*> functions(2); - topmost->GetFunctions(&functions); - CHECK_EQ(args[0] - ->ToInt32(args.GetIsolate()->GetCurrentContext()) - .ToLocalChecked() - ->Value(), - functions.length()); -} - - -void InstallAssertInlineCountHelper(v8::Isolate* isolate) { - v8::Local<v8::Context> context = isolate->GetCurrentContext(); - v8::Local<v8::FunctionTemplate> t = - v8::FunctionTemplate::New(isolate, AssertInlineCount); - CHECK(context->Global() - ->Set(context, v8_str("AssertInlineCount"), - t->GetFunction(context).ToLocalChecked()) - .FromJust()); -} - -const uint32_t kRestrictedInliningFlags = 0; - -const uint32_t kInlineFlags = CompilationInfo::kInliningEnabled; - -} // namespace - - -TEST(SimpleInlining) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); return s; };" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); -} - - -TEST(SimpleInliningDeopt) { - FunctionTester T( - "function foo(s) { %DeoptimizeFunction(bar); return s; };" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); -} - - -TEST(SimpleInliningDeoptSelf) { - FunctionTester T( - "function foo(s) { %_DeoptimizeNow(); return s; };" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(1), T.Val(1), T.Val(2)); -} - - -TEST(SimpleInliningContext) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); var x = 12; return s + x; };" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(13), T.Val(1), T.Val(2)); -} - - -TEST(SimpleInliningContextDeopt) { - FunctionTester T( - "function foo(s) {" - " AssertInlineCount(2); %DeoptimizeFunction(bar); var x = 12;" - " return s + x;" - "};" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(13), T.Val(1), T.Val(2)); -} - - -TEST(CaptureContext) { - FunctionTester T( - "var f = (function () {" - " var x = 42;" - " function bar(s) { return x + s; };" - " return (function (s) { return bar(s); });" - "})();" - "(function (s) { return f(s) })", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); -} - - -// TODO(sigurds) For now we do not inline any native functions. If we do at -// some point, change this test. -TEST(DontInlineEval) { - FunctionTester T( - "var x = 42;" - "function bar(s, t) { return eval(\"AssertInlineCount(1); x\") };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42), T.Val("x"), T.undefined()); -} - - -TEST(InlineOmitArguments) { - FunctionTester T( - "var x = 42;" - "function bar(s, t, u, v) { AssertInlineCount(2); return x + s; };" - "function foo(s, t) { return bar(s); };" - "foo;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); -} - - -TEST(InlineOmitArgumentsObject) { - FunctionTester T( - "function bar(s, t, u, v) { AssertInlineCount(2); return arguments; };" - "function foo(s, t) { var args = bar(s);" - " return args.length == 1 &&" - " args[0] == 11; };" - "foo;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value(), T.Val(11), T.undefined()); -} - - -TEST(InlineOmitArgumentsDeopt) { - FunctionTester T( - "function foo(s,t,u,v) { AssertInlineCount(2);" - " %DeoptimizeFunction(bar); return baz(); };" - "function bar() { return foo(11); };" - "function baz() { return foo.arguments.length == 1 &&" - " foo.arguments[0] == 11; }" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value(), T.Val(12), T.Val(14)); -} - - -TEST(InlineSurplusArguments) { - FunctionTester T( - "var x = 42;" - "function foo(s) { AssertInlineCount(2); return x + s; };" - "function bar(s, t) { return foo(s, t, 13); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 12), T.Val(12), T.undefined()); -} - - -TEST(InlineSurplusArgumentsObject) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); return arguments; };" - "function bar(s, t) { var args = foo(s, t, 13);" - " return args.length == 3 &&" - " args[0] == 11 &&" - " args[1] == 12 &&" - " args[2] == 13; };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value(), T.Val(11), T.Val(12)); -} - - -TEST(InlineSurplusArgumentsDeopt) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); %DeoptimizeFunction(bar);" - " return baz(); };" - "function bar() { return foo(13, 14, 15); };" - "function baz() { return foo.arguments.length == 3 &&" - " foo.arguments[0] == 13 &&" - " foo.arguments[1] == 14 &&" - " foo.arguments[2] == 15; }" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value(), T.Val(12), T.Val(14)); -} - - -TEST(InlineTwice) { - FunctionTester T( - "var x = 42;" - "function bar(s) { AssertInlineCount(2); return x + s; };" - "function foo(s, t) { return bar(s) + bar(t); };" - "foo;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(2 * 42 + 12 + 4), T.Val(12), T.Val(4)); -} - - -TEST(InlineTwiceDependent) { - FunctionTester T( - "var x = 42;" - "function foo(s) { AssertInlineCount(2); return x + s; };" - "function bar(s,t) { return foo(foo(s)); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42 + 42 + 12), T.Val(12), T.Val(4)); -} - - -TEST(InlineTwiceDependentDiamond) { - FunctionTester T( - "var x = 41;" - "function foo(s) { AssertInlineCount(2); if (s % 2 == 0) {" - " return x - s } else { return x + s; } };" - "function bar(s,t) { return foo(foo(s)); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(-11), T.Val(11), T.Val(4)); -} - - -TEST(InlineTwiceDependentDiamondDifferent) { - FunctionTester T( - "var x = 41;" - "function foo(s,t) { AssertInlineCount(2); if (s % 2 == 0) {" - " return x - s * t } else { return x + s * t; } };" - "function bar(s,t) { return foo(foo(s, 3), 5); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(-329), T.Val(11), T.Val(4)); -} - - -TEST(InlineLoopGuardedEmpty) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); if (s) while (s); return s; };" - "function bar(s,t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4)); -} - - -TEST(InlineLoopGuardedOnce) { - FunctionTester T( - "function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {" - " s = s - 1; }; return s; };" - "function bar(s,t) { return foo(s,t); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(0.0), T.Val(11), T.Val(4)); -} - - -TEST(InlineLoopGuardedTwice) { - FunctionTester T( - "function foo(s,t) { AssertInlineCount(2); if (t > 0) while (s > 0) {" - " s = s - 1; }; return s; };" - "function bar(s,t) { return foo(foo(s,t),t); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(0.0), T.Val(11), T.Val(4)); -} - - -TEST(InlineLoopUnguardedEmpty) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); while (s); return s; };" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4)); -} - - -TEST(InlineLoopUnguardedOnce) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); while (s) {" - " s = s - 1; }; return s; };" - "function bar(s, t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4)); -} - - -TEST(InlineLoopUnguardedTwice) { - FunctionTester T( - "function foo(s) { AssertInlineCount(2); while (s > 0) {" - " s = s - 1; }; return s; };" - "function bar(s,t) { return foo(foo(s,t),t); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(0.0), T.Val(0.0), T.Val(4)); -} - - -TEST(InlineStrictIntoNonStrict) { - FunctionTester T( - "var x = Object.create({}, { y: { value:42, writable:false } });" - "function foo(s) { 'use strict';" - " x.y = 9; };" - "function bar(s,t) { return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckThrows(T.undefined(), T.undefined()); -} - - -TEST(InlineNonStrictIntoStrict) { - FunctionTester T( - "var x = Object.create({}, { y: { value:42, writable:false } });" - "function foo(s) { x.y = 9; return x.y; };" - "function bar(s,t) { \'use strict\'; return foo(s); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42), T.undefined(), T.undefined()); -} - - -TEST(InlineWithArguments) { - FunctionTester T( - "function foo(s,t,u) { AssertInlineCount(2);" - " return foo.arguments.length == 3 &&" - " foo.arguments[0] == 13 &&" - " foo.arguments[1] == 14 &&" - " foo.arguments[2] == 15;" - "}" - "function bar() { return foo(13, 14, 15); };" - "bar;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value(), T.Val(12), T.Val(14)); -} - - -TEST(InlineBuiltin) { - FunctionTester T( - "function foo(s,t,u) { AssertInlineCount(2); return true; }" - "function bar() { return foo(); };" - "%SetForceInlineFlag(foo);" - "bar;", - kRestrictedInliningFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value()); -} - - -TEST(InlineNestedBuiltin) { - FunctionTester T( - "function foo(s,t,u) { AssertInlineCount(3); return true; }" - "function baz(s,t,u) { return foo(s,t,u); }" - "function bar() { return baz(); };" - "%SetForceInlineFlag(foo);" - "%SetForceInlineFlag(baz);" - "bar;", - kRestrictedInliningFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.true_value()); -} - - -TEST(InlineSelfRecursive) { - FunctionTester T( - "function foo(x) { " - " AssertInlineCount(1);" - " if (x == 1) return foo(12);" - " return x;" - "}" - "foo;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(12), T.Val(1)); -} - - -TEST(InlineMutuallyRecursive) { - FunctionTester T( - "function bar(x) { AssertInlineCount(2); return foo(x); }" - "function foo(x) { " - " if (x == 1) return bar(42);" - " return x;" - "}" - "foo;", - kInlineFlags); - - InstallAssertInlineCountHelper(CcTest::isolate()); - T.CheckCall(T.Val(42), T.Val(1)); -} - -} // namespace compiler -} // namespace internal -} // namespace v8 diff --git a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc index 47116ad674..515e096f44 100644 --- a/deps/v8/test/cctest/compiler/test-run-intrinsics.cc +++ b/deps/v8/test/cctest/compiler/test-run-intrinsics.cc @@ -80,21 +80,6 @@ TEST(IsFunction) { } -TEST(IsRegExp) { - FunctionTester T("(function(a) { return %_IsRegExp(a); })", flags); - - T.CheckFalse(T.NewObject("new Date()")); - T.CheckFalse(T.NewObject("(function() {})")); - T.CheckFalse(T.NewObject("([1])")); - T.CheckFalse(T.NewObject("({})")); - T.CheckTrue(T.NewObject("(/x/)")); - T.CheckFalse(T.undefined()); - T.CheckFalse(T.null()); - T.CheckFalse(T.Val("x")); - T.CheckFalse(T.Val(1)); -} - - TEST(IsSmi) { FunctionTester T("(function(a) { return %_IsSmi(a); })", flags); diff --git a/deps/v8/test/cctest/compiler/test-run-jscalls.cc b/deps/v8/test/cctest/compiler/test-run-jscalls.cc index 64bd67cc0a..371d0f94fa 100644 --- a/deps/v8/test/cctest/compiler/test-run-jscalls.cc +++ b/deps/v8/test/cctest/compiler/test-run-jscalls.cc @@ -5,6 +5,7 @@ #include "src/api.h" #include "src/contexts.h" #include "src/flags.h" +#include "src/objects-inl.h" #include "src/objects.h" #include "test/cctest/compiler/function-tester.h" diff --git a/deps/v8/test/cctest/compiler/test-run-machops.cc b/deps/v8/test/cctest/compiler/test-run-machops.cc index 2794aec51e..195f0a91dc 100644 --- a/deps/v8/test/cctest/compiler/test-run-machops.cc +++ b/deps/v8/test/cctest/compiler/test-run-machops.cc @@ -3797,6 +3797,30 @@ TEST(RunFloat32Min) { } } +TEST(RunFloat64Max) { + RawMachineAssemblerTester<int32_t> m; + Float64BinopTester bt(&m); + bt.AddReturn(m.Float64Max(bt.param0, bt.param1)); + + FOR_FLOAT64_INPUTS(pl) { + FOR_FLOAT64_INPUTS(pr) { + CHECK_DOUBLE_EQ(JSMax(*pl, *pr), bt.call(*pl, *pr)); + } + } +} + +TEST(RunFloat64Min) { + RawMachineAssemblerTester<int32_t> m; + Float64BinopTester bt(&m); + bt.AddReturn(m.Float64Min(bt.param0, bt.param1)); + + FOR_FLOAT64_INPUTS(pl) { + FOR_FLOAT64_INPUTS(pr) { + CHECK_DOUBLE_EQ(JSMin(*pl, *pr), bt.call(*pl, *pr)); + } + } +} + TEST(RunFloat32SubP) { RawMachineAssemblerTester<int32_t> m; Float32BinopTester bt(&m); diff --git a/deps/v8/test/cctest/compiler/test-run-native-calls.cc b/deps/v8/test/cctest/compiler/test-run-native-calls.cc index 89629ec090..e877d258b5 100644 --- a/deps/v8/test/cctest/compiler/test-run-native-calls.cc +++ b/deps/v8/test/cctest/compiler/test-run-native-calls.cc @@ -458,12 +458,14 @@ class Computer { CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig); RawMachineAssembler raw(isolate, &graph, cdesc); Node* target = raw.HeapConstant(inner); - Node** args = zone.NewArray<Node*>(num_params); + Node** inputs = zone.NewArray<Node*>(num_params + 1); + int input_count = 0; + inputs[input_count++] = target; for (int i = 0; i < num_params; i++) { - args[i] = io.MakeConstant(raw, io.input[i]); + inputs[input_count++] = io.MakeConstant(raw, io.input[i]); } - Node* call = raw.CallN(desc, target, args); + Node* call = raw.CallN(desc, input_count, inputs); Node* store = io.StoreOutput(raw, call); USE(store); raw.Return(raw.Int32Constant(seed)); @@ -491,12 +493,14 @@ class Computer { RawMachineAssembler raw(isolate, &graph, cdesc); Node* base = raw.PointerConstant(io.input); Node* target = raw.HeapConstant(inner); - Node** args = zone.NewArray<Node*>(kMaxParamCount); + Node** inputs = zone.NewArray<Node*>(kMaxParamCount + 1); + int input_count = 0; + inputs[input_count++] = target; for (int i = 0; i < num_params; i++) { - args[i] = io.LoadInput(raw, base, i); + inputs[input_count++] = io.LoadInput(raw, base, i); } - Node* call = raw.CallN(desc, target, args); + Node* call = raw.CallN(desc, input_count, inputs); Node* store = io.StoreOutput(raw, call); USE(store); raw.Return(raw.Int32Constant(seed)); @@ -588,13 +592,15 @@ static void CopyTwentyInt32(CallDescriptor* desc) { RawMachineAssembler raw(isolate, &graph, cdesc); Node* base = raw.PointerConstant(input); Node* target = raw.HeapConstant(inner); - Node** args = zone.NewArray<Node*>(kNumParams); + Node** inputs = zone.NewArray<Node*>(kNumParams + 1); + int input_count = 0; + inputs[input_count++] = target; for (int i = 0; i < kNumParams; i++) { Node* offset = raw.Int32Constant(i * sizeof(int32_t)); - args[i] = raw.Load(MachineType::Int32(), base, offset); + inputs[input_count++] = raw.Load(MachineType::Int32(), base, offset); } - Node* call = raw.CallN(desc, target, args); + Node* call = raw.CallN(desc, input_count, inputs); raw.Return(call); wrapper = CompileGraph("CopyTwentyInt32-wrapper", cdesc, &graph, raw.Export()); @@ -970,12 +976,14 @@ static void Build_Select_With_Call(CallDescriptor* desc, { // Build a call to the function that does the select. Node* target = raw.HeapConstant(inner); - Node** args = raw.zone()->NewArray<Node*>(num_params); + Node** inputs = raw.zone()->NewArray<Node*>(num_params + 1); + int input_count = 0; + inputs[input_count++] = target; for (int i = 0; i < num_params; i++) { - args[i] = raw.Parameter(i); + inputs[input_count++] = raw.Parameter(i); } - Node* call = raw.CallN(desc, target, args); + Node* call = raw.CallN(desc, input_count, inputs); raw.Return(call); } } @@ -1075,7 +1083,9 @@ void MixedParamTest(int start) { CallDescriptor* cdesc = Linkage::GetSimplifiedCDescriptor(&zone, &csig); RawMachineAssembler raw(isolate, &graph, cdesc); Node* target = raw.HeapConstant(select); - Node** args = zone.NewArray<Node*>(num_params); + Node** inputs = zone.NewArray<Node*>(num_params + 1); + int input_count = 0; + inputs[input_count++] = target; int64_t constant = 0x0102030405060708; for (int i = 0; i < num_params; i++) { MachineType param_type = sig->GetParam(i); @@ -1102,11 +1112,11 @@ void MixedParamTest(int start) { } CHECK_NOT_NULL(konst); - args[i] = konst; + inputs[input_count++] = konst; constant += 0x1010101010101010; } - Node* call = raw.CallN(desc, target, args); + Node* call = raw.CallN(desc, input_count, inputs); Node* store = raw.StoreToPointer(output, sig->GetReturn().representation(), call); USE(store); @@ -1178,14 +1188,16 @@ void TestStackSlot(MachineType slot_type, T expected) { BufferedRawMachineAssemblerTester<T> f(slot_type); Node* target = f.HeapConstant(inner); Node* stack_slot = f.StackSlot(slot_type.representation()); - Node* args[12]; + Node* nodes[14]; + int input_count = 0; + nodes[input_count++] = target; for (int i = 0; i < 10; i++) { - args[i] = f.Int32Constant(i); + nodes[input_count++] = f.Int32Constant(i); } - args[10] = f.Parameter(0); - args[11] = stack_slot; + nodes[input_count++] = f.Parameter(0); + nodes[input_count++] = stack_slot; - f.CallN(desc, target, args); + f.CallN(desc, input_count, nodes); f.Return(f.Load(slot_type, stack_slot, f.IntPtrConstant(0))); CHECK_EQ(expected, f.Call(expected)); diff --git a/deps/v8/test/cctest/compiler/test-run-variables.cc b/deps/v8/test/cctest/compiler/test-run-variables.cc index 9d6291a5aa..d1f564a51c 100644 --- a/deps/v8/test/cctest/compiler/test-run-variables.cc +++ b/deps/v8/test/cctest/compiler/test-run-variables.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "src/api.h" +#include "src/objects-inl.h" #include "test/cctest/compiler/function-tester.h" namespace v8 { diff --git a/deps/v8/test/cctest/compiler/test-run-wasm-machops.cc b/deps/v8/test/cctest/compiler/test-run-wasm-machops.cc index c3f42388d4..9359b25779 100644 --- a/deps/v8/test/cctest/compiler/test-run-wasm-machops.cc +++ b/deps/v8/test/cctest/compiler/test-run-wasm-machops.cc @@ -40,6 +40,26 @@ static void UpdateMemoryReferences(Handle<Code> code, Address old_base, } } +static void UpdateFunctionTableSizeReferences(Handle<Code> code, + uint32_t old_size, + uint32_t new_size) { + Isolate* isolate = CcTest::i_isolate(); + bool modified = false; + int mode_mask = + RelocInfo::ModeMask(RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE); + for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) { + RelocInfo::Mode mode = it.rinfo()->rmode(); + if (RelocInfo::IsWasmFunctionTableSizeReference(mode)) { + it.rinfo()->update_wasm_function_table_size_reference(old_size, new_size); + modified = true; + } + } + if (modified) { + Assembler::FlushICache(isolate, code->instruction_start(), + code->instruction_size()); + } +} + template <typename CType> static void RunLoadStoreRelocation(MachineType rep) { const int kNumElems = 2; @@ -146,7 +166,7 @@ TEST(RunLoadStoreRelocationOffset) { RunLoadStoreRelocationOffset<double>(MachineType::Float64()); } -TEST(Uint32LessThanRelocation) { +TEST(Uint32LessThanMemoryRelocation) { RawMachineAssemblerTester<uint32_t> m; RawMachineLabel within_bounds, out_of_bounds; Node* index = m.Int32Constant(0x200); @@ -168,3 +188,25 @@ TEST(Uint32LessThanRelocation) { // Check that after limit is increased, index is within bounds. CHECK_EQ(0xacedu, m.Call()); } + +TEST(Uint32LessThanFunctionTableRelocation) { + RawMachineAssemblerTester<uint32_t> m; + RawMachineLabel within_bounds, out_of_bounds; + Node* index = m.Int32Constant(0x200); + Node* limit = m.RelocatableInt32Constant( + 0x200, RelocInfo::WASM_FUNCTION_TABLE_SIZE_REFERENCE); + Node* cond = m.AddNode(m.machine()->Uint32LessThan(), index, limit); + m.Branch(cond, &within_bounds, &out_of_bounds); + m.Bind(&within_bounds); + m.Return(m.Int32Constant(0xaced)); + m.Bind(&out_of_bounds); + m.Return(m.Int32Constant(0xdeadbeef)); + // Check that index is out of bounds with current size + CHECK_EQ(0xdeadbeef, m.Call()); + m.GenerateCode(); + + Handle<Code> code = m.GetCode(); + UpdateFunctionTableSizeReferences(code, 0x200, 0x400); + // Check that after limit is increased, index is within bounds. + CHECK_EQ(0xaced, m.Call()); +} diff --git a/deps/v8/test/cctest/heap/heap-tester.h b/deps/v8/test/cctest/heap/heap-tester.h index 99d39ca7ab..acfbe92bb6 100644 --- a/deps/v8/test/cctest/heap/heap-tester.h +++ b/deps/v8/test/cctest/heap/heap-tester.h @@ -34,6 +34,7 @@ V(Regress589413) \ V(Regress658718) \ V(Regress670675) \ + V(Regress5831) \ V(WriteBarriersInCopyJSObject) #define HEAP_TEST(Name) \ diff --git a/deps/v8/test/cctest/heap/heap-utils.cc b/deps/v8/test/cctest/heap/heap-utils.cc index c44f82f1d9..35a584b739 100644 --- a/deps/v8/test/cctest/heap/heap-utils.cc +++ b/deps/v8/test/cctest/heap/heap-utils.cc @@ -142,6 +142,7 @@ void SimulateFullSpace(v8::internal::NewSpace* space, } void SimulateIncrementalMarking(i::Heap* heap, bool force_completion) { + CHECK(FLAG_incremental_marking); i::IncrementalMarking* marking = heap->incremental_marking(); i::MarkCompactCollector* collector = heap->mark_compact_collector(); if (collector->sweeping_in_progress()) { diff --git a/deps/v8/test/cctest/heap/test-alloc.cc b/deps/v8/test/cctest/heap/test-alloc.cc index d7031e876d..3485c0ab07 100644 --- a/deps/v8/test/cctest/heap/test-alloc.cc +++ b/deps/v8/test/cctest/heap/test-alloc.cc @@ -30,6 +30,8 @@ #include "src/accessors.h" #include "src/api.h" +#include "src/objects-inl.h" +#include "src/property.h" #include "test/cctest/heap/heap-tester.h" #include "test/cctest/heap/heap-utils.h" @@ -154,8 +156,8 @@ TEST(StressJS) { Handle<AccessorInfo> foreign = TestAccessorInfo(isolate, attrs); Map::EnsureDescriptorSlack(map, 1); - AccessorConstantDescriptor d(Handle<Name>(Name::cast(foreign->name())), - foreign, attrs); + Descriptor d = Descriptor::AccessorConstant( + Handle<Name>(Name::cast(foreign->name())), foreign, attrs); map->AppendDescriptor(&d); // Add the Foo constructor the global object. diff --git a/deps/v8/test/cctest/heap/test-array-buffer-tracker.cc b/deps/v8/test/cctest/heap/test-array-buffer-tracker.cc index 0f3663041f..11bc4c0727 100644 --- a/deps/v8/test/cctest/heap/test-array-buffer-tracker.cc +++ b/deps/v8/test/cctest/heap/test-array-buffer-tracker.cc @@ -4,7 +4,9 @@ #include "src/api.h" #include "src/heap/array-buffer-tracker.h" +#include "src/heap/spaces.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "test/cctest/cctest.h" #include "test/cctest/heap/heap-utils.h" @@ -188,6 +190,7 @@ TEST(ArrayBuffer_UnregisterDuringSweep) { } TEST(ArrayBuffer_NonLivePromotion) { + if (!FLAG_incremental_marking) return; // The test verifies that the marking state is preserved when promoting // a buffer to old space. CcTest::InitializeVM(); @@ -223,6 +226,7 @@ TEST(ArrayBuffer_NonLivePromotion) { } TEST(ArrayBuffer_LivePromotion) { + if (!FLAG_incremental_marking) return; // The test verifies that the marking state is preserved when promoting // a buffer to old space. CcTest::InitializeVM(); @@ -257,6 +261,7 @@ TEST(ArrayBuffer_LivePromotion) { } TEST(ArrayBuffer_SemiSpaceCopyThenPagePromotion) { + if (!i::FLAG_incremental_marking) return; // The test verifies that the marking state is preserved across semispace // copy. CcTest::InitializeVM(); diff --git a/deps/v8/test/cctest/heap/test-heap.cc b/deps/v8/test/cctest/heap/test-heap.cc index 19474c3e95..a6cc7e8251 100644 --- a/deps/v8/test/cctest/heap/test-heap.cc +++ b/deps/v8/test/cctest/heap/test-heap.cc @@ -28,6 +28,7 @@ #include <stdlib.h> #include <utility> +#include "src/code-stubs.h" #include "src/compilation-cache.h" #include "src/context-measure.h" #include "src/deoptimizer.h" @@ -1362,6 +1363,7 @@ TEST(TestCodeFlushingPreAged) { TEST(TestCodeFlushingIncremental) { + if (!i::FLAG_incremental_marking) return; // If we do not flush code this test is invalid. if (!FLAG_flush_code) return; i::FLAG_allow_natives_syntax = true; @@ -1434,6 +1436,7 @@ TEST(TestCodeFlushingIncremental) { TEST(TestCodeFlushingIncrementalScavenge) { + if (!FLAG_incremental_marking) return; // If we do not flush code this test is invalid. if (!FLAG_flush_code) return; i::FLAG_allow_natives_syntax = true; @@ -1484,8 +1487,8 @@ TEST(TestCodeFlushingIncrementalScavenge) { // object is still located in new-space. const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - function->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); - function2->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + function->shared()->code()->MakeOlder(); + function2->shared()->code()->MakeOlder(); } // Simulate incremental marking so that the functions are enqueued as @@ -1505,6 +1508,7 @@ TEST(TestCodeFlushingIncrementalScavenge) { TEST(TestCodeFlushingIncrementalAbort) { + if (!i::FLAG_incremental_marking) return; // If we do not flush code this test is invalid. if (!FLAG_flush_code) return; i::FLAG_allow_natives_syntax = true; @@ -1542,7 +1546,7 @@ TEST(TestCodeFlushingIncrementalAbort) { // Bump the code age so that flushing is triggered. const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - function->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + function->shared()->code()->MakeOlder(); } // Simulate incremental marking so that the function is enqueued as @@ -1571,6 +1575,7 @@ TEST(TestCodeFlushingIncrementalAbort) { } TEST(TestUseOfIncrementalBarrierOnCompileLazy) { + if (!i::FLAG_incremental_marking) return; // Turn off always_opt because it interferes with running the built-in for // the last call to g(). i::FLAG_always_opt = false; @@ -1615,7 +1620,6 @@ TEST(TestUseOfIncrementalBarrierOnCompileLazy) { TEST(CompilationCacheCachingBehavior) { // If we do not flush code, or have the compilation cache turned off, this // test is invalid. - i::FLAG_allow_natives_syntax = true; if (!FLAG_flush_code || !FLAG_compilation_cache) { return; } @@ -1643,9 +1647,8 @@ TEST(CompilationCacheCachingBehavior) { // The script should be in the cache now. MaybeHandle<SharedFunctionInfo> info = compilation_cache->LookupScript( - source, Handle<Object>(), 0, 0, - v8::ScriptOriginOptions(false, true, false), native_context, - language_mode); + source, Handle<Object>(), 0, 0, v8::ScriptOriginOptions(true, false), + native_context, language_mode); CHECK(!info.is_null()); // Check that the code cache entry survives at least on GC. @@ -1653,29 +1656,26 @@ TEST(CompilationCacheCachingBehavior) { // immediately.) if (!FLAG_optimize_for_size) { CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - info = compilation_cache->LookupScript( - source, Handle<Object>(), 0, 0, - v8::ScriptOriginOptions(false, true, false), native_context, - language_mode); + info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(true, false), + native_context, language_mode); CHECK(!info.is_null()); } // Progress code age until it's old and ready for GC. - while (!info.ToHandleChecked()->code()->IsOld()) { - // To guarantee progress, we have to MakeOlder with different parities. - // We can't just use NO_MARKING_PARITY, since e.g. kExecutedOnceCodeAge is - // always NO_MARKING_PARITY and the code age only progresses if the parity - // is different. - info.ToHandleChecked()->code()->MakeOlder(ODD_MARKING_PARITY); - info.ToHandleChecked()->code()->MakeOlder(EVEN_MARKING_PARITY); + const int kAgingThreshold = 6; + for (int i = 0; i < kAgingThreshold; i++) { + info.ToHandleChecked()->code()->MakeOlder(); + if (info.ToHandleChecked()->HasBytecodeArray()) { + info.ToHandleChecked()->bytecode_array()->MakeOlder(); + } } CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); // Ensure code aging cleared the entry from the cache. - info = compilation_cache->LookupScript( - source, Handle<Object>(), 0, 0, - v8::ScriptOriginOptions(false, true, false), native_context, - language_mode); + info = compilation_cache->LookupScript(source, Handle<Object>(), 0, 0, + v8::ScriptOriginOptions(true, false), + native_context, language_mode); CHECK(info.is_null()); } @@ -1712,7 +1712,7 @@ static int CountOptimizedUserFunctions(v8::Local<v8::Context> context) { Handle<Context> icontext = v8::Utils::OpenHandle(*context); Object* object = icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST); while (object->IsJSFunction() && - !JSFunction::cast(object)->shared()->IsBuiltin()) { + JSFunction::cast(object)->shared()->IsUserJavaScript()) { count++; object = JSFunction::cast(object)->next_function_link(); } @@ -1854,7 +1854,7 @@ static int CountOptimizedUserFunctionsWithGC(v8::Local<v8::Context> context, Handle<Object> object(icontext->get(Context::OPTIMIZED_FUNCTIONS_LIST), isolate); while (object->IsJSFunction() && - !Handle<JSFunction>::cast(object)->shared()->IsBuiltin()) { + Handle<JSFunction>::cast(object)->shared()->IsUserJavaScript()) { count++; if (count == n) isolate->heap()->CollectAllGarbage( @@ -2608,6 +2608,7 @@ TEST(LeakNativeContextViaMapProto) { TEST(InstanceOfStubWriteBarrier) { + if (!i::FLAG_incremental_marking) return; i::FLAG_allow_natives_syntax = true; #ifdef VERIFY_HEAP i::FLAG_verify_heap = true; @@ -2674,6 +2675,7 @@ int GetProfilerTicks(SharedFunctionInfo* shared) { } // namespace TEST(ResetSharedFunctionInfoCountersDuringIncrementalMarking) { + if (!i::FLAG_incremental_marking) return; i::FLAG_stress_compaction = false; i::FLAG_allow_natives_syntax = true; #ifdef VERIFY_HEAP @@ -2765,6 +2767,7 @@ TEST(ResetSharedFunctionInfoCountersDuringMarkSweep) { HEAP_TEST(GCFlags) { + if (!i::FLAG_incremental_marking) return; CcTest::InitializeVM(); Heap* heap = CcTest::heap(); @@ -2797,6 +2800,7 @@ HEAP_TEST(GCFlags) { TEST(IdleNotificationFinishMarking) { + if (!i::FLAG_incremental_marking) return; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); const int initial_gc_count = CcTest::heap()->gc_count(); @@ -3296,6 +3300,7 @@ static int CountMapTransitions(Map* map) { // Test that map transitions are cleared and maps are collected with // incremental marking as well. TEST(Regress1465) { + if (!i::FLAG_incremental_marking) return; i::FLAG_stress_compaction = false; i::FLAG_allow_natives_syntax = true; i::FLAG_trace_incremental_marking = true; @@ -3671,6 +3676,7 @@ TEST(PrintSharedFunctionInfo) { TEST(IncrementalMarkingPreservesMonomorphicCallIC) { + if (!FLAG_incremental_marking) return; if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3746,6 +3752,7 @@ static void CheckVectorIC(Handle<JSFunction> f, int slot_index, } TEST(IncrementalMarkingPreservesMonomorphicConstructor) { + if (!i::FLAG_incremental_marking) return; if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3769,6 +3776,7 @@ TEST(IncrementalMarkingPreservesMonomorphicConstructor) { } TEST(IncrementalMarkingPreservesMonomorphicIC) { + if (!i::FLAG_incremental_marking) return; if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3790,6 +3798,7 @@ TEST(IncrementalMarkingPreservesMonomorphicIC) { } TEST(IncrementalMarkingPreservesPolymorphicIC) { + if (!i::FLAG_incremental_marking) return; if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3827,6 +3836,7 @@ TEST(IncrementalMarkingPreservesPolymorphicIC) { } TEST(ContextDisposeDoesntClearPolymorphicIC) { + if (!i::FLAG_incremental_marking) return; if (i::FLAG_always_opt) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -3982,6 +3992,7 @@ UNINITIALIZED_TEST(ReleaseStackTraceData) { TEST(Regress159140) { + if (!i::FLAG_incremental_marking) return; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -4023,7 +4034,7 @@ TEST(Regress159140) { CHECK(g->is_compiled()); const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - g->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + g->code()->MakeOlder(); } code = inner_scope.CloseAndEscape(Handle<Code>(f->code())); @@ -4042,6 +4053,7 @@ TEST(Regress159140) { TEST(Regress165495) { + if (!i::FLAG_incremental_marking) return; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -4070,7 +4082,7 @@ TEST(Regress165495) { CHECK(f->is_compiled()); const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + f->shared()->code()->MakeOlder(); } CompileRun("f = null;"); @@ -4088,6 +4100,7 @@ TEST(Regress165495) { TEST(Regress169209) { + if (!i::FLAG_incremental_marking) return; i::FLAG_always_opt = false; i::FLAG_stress_compaction = false; i::FLAG_allow_natives_syntax = true; @@ -4122,7 +4135,7 @@ TEST(Regress169209) { CHECK(f->is_compiled()); const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + f->shared()->code()->MakeOlder(); } shared1 = inner_scope.CloseAndEscape(handle(f->shared(), isolate)); @@ -4147,7 +4160,7 @@ TEST(Regress169209) { CHECK(f->is_compiled()); const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - f->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + f->shared()->code()->MakeOlder(); } shared2 = inner_scope.CloseAndEscape(handle(f->shared(), isolate)); @@ -4248,7 +4261,6 @@ TEST(Regress169928) { #ifdef DEBUG TEST(Regress513507) { - i::FLAG_flush_optimized_code_cache = false; i::FLAG_allow_natives_syntax = true; i::FLAG_gc_global = true; CcTest::InitializeVM(); @@ -4302,9 +4314,8 @@ TEST(Regress513507) { } #endif // DEBUG - TEST(Regress514122) { - i::FLAG_flush_optimized_code_cache = false; + if (!i::FLAG_incremental_marking) return; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -4319,8 +4330,9 @@ TEST(Regress514122) { Handle<SharedFunctionInfo> shared; { HandleScope inner_scope(isolate); - CompileRun("function f() { return 1 }" - "f(); %OptimizeFunctionOnNextCall(f); f();"); + CompileRun( + "function f() { return 1 }" + "f(); %OptimizeFunctionOnNextCall(f); f();"); Handle<JSFunction> f = Handle<JSFunction>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( @@ -4333,8 +4345,9 @@ TEST(Regress514122) { Handle<Code> code; { HandleScope inner_scope(isolate); - CompileRun("function g() { return 2 }" - "g(); %OptimizeFunctionOnNextCall(g); g();"); + CompileRun( + "function g() { return 2 }" + "g(); %OptimizeFunctionOnNextCall(g); g();"); Handle<JSFunction> g = Handle<JSFunction>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( @@ -4395,9 +4408,7 @@ TEST(Regress514122) { boomer->Print(); } - TEST(OptimizedCodeMapReuseEntries) { - i::FLAG_flush_optimized_code_cache = false; i::FLAG_allow_natives_syntax = true; // BUG(v8:4598): Since TurboFan doesn't treat maps in code weakly, we can't // run this test. @@ -4503,9 +4514,7 @@ TEST(OptimizedCodeMapReuseEntries) { } } - TEST(Regress513496) { - i::FLAG_flush_optimized_code_cache = false; i::FLAG_allow_natives_syntax = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -4537,7 +4546,7 @@ TEST(Regress513496) { CHECK(g->shared()->is_compiled()); const int kAgingThreshold = 6; for (int i = 0; i < kAgingThreshold; i++) { - g->shared()->code()->MakeOlder(static_cast<MarkingParity>(i % 2)); + g->shared()->code()->MakeOlder(); } Handle<JSFunction> f = Handle<JSFunction>::cast(v8::Utils::OpenHandle( @@ -4565,6 +4574,7 @@ TEST(Regress513496) { TEST(LargeObjectSlotRecording) { + if (!i::FLAG_incremental_marking) return; FLAG_manual_evacuation_candidates_selection = true; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); @@ -4637,6 +4647,7 @@ TEST(DeferredHandles) { TEST(IncrementalMarkingStepMakesBigProgressWithLargeObjects) { + if (!FLAG_incremental_marking) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); CompileRun("function f(n) {" @@ -5448,6 +5459,7 @@ TEST(WeakCell) { TEST(WeakCellsWithIncrementalMarking) { + if (!FLAG_incremental_marking) return; CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); v8::internal::Heap* heap = CcTest::heap(); @@ -5719,6 +5731,7 @@ UNINITIALIZED_TEST(PromotionQueue) { TEST(Regress388880) { + if (!FLAG_incremental_marking) return; i::FLAG_expose_gc = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -5766,6 +5779,7 @@ TEST(Regress388880) { TEST(Regress3631) { + if (!FLAG_incremental_marking) return; i::FLAG_expose_gc = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -5899,6 +5913,7 @@ void CheckMapRetainingFor(int n) { TEST(MapRetaining) { + if (!FLAG_incremental_marking) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); CheckMapRetainingFor(FLAG_retain_maps_for_n_gc); @@ -5963,8 +5978,7 @@ static void TestRightTrimFixedTypedArray(i::ExternalArrayType type, Handle<FixedTypedArrayBase> array = factory->NewFixedTypedArray(initial_length, type, true); int old_size = array->size(); - heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, - elements_to_trim); + heap->RightTrimFixedArray(*array, elements_to_trim); // Check that free space filler is at the right place and did not smash the // array header. @@ -6255,9 +6269,9 @@ static void RemoveCodeAndGC(const v8::FunctionCallbackInfo<v8::Value>& args) { Isolate* isolate = CcTest::i_isolate(); Handle<Object> obj = v8::Utils::OpenHandle(*args[0]); Handle<JSFunction> fun = Handle<JSFunction>::cast(obj); + fun->shared()->ClearBytecodeArray(); // Bytecode is code too. fun->ReplaceCode(*isolate->builtins()->CompileLazy()); fun->shared()->ReplaceCode(*isolate->builtins()->CompileLazy()); - fun->shared()->ClearBytecodeArray(); // Bytecode is code too. CcTest::CollectAllAvailableGarbage(); } @@ -6384,50 +6398,13 @@ TEST(SharedFunctionInfoIterator) { } { - SharedFunctionInfo::Iterator iterator(isolate); + SharedFunctionInfo::GlobalIterator iterator(isolate); while (iterator.Next()) sfi_count--; } CHECK_EQ(0, sfi_count); } - -template <typename T> -static UniqueId MakeUniqueId(const Persistent<T>& p) { - return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p))); -} - - -TEST(Regress519319) { - CcTest::InitializeVM(); - v8::Isolate* isolate = CcTest::isolate(); - v8::HandleScope scope(isolate); - Heap* heap = CcTest::heap(); - LocalContext context; - - v8::Persistent<Value> parent; - v8::Persistent<Value> child; - - parent.Reset(isolate, v8::Object::New(isolate)); - child.Reset(isolate, v8::Object::New(isolate)); - - heap::SimulateFullSpace(heap->old_space()); - CcTest::CollectGarbage(OLD_SPACE); - { - UniqueId id = MakeUniqueId(parent); - isolate->SetObjectGroupId(parent, id); - isolate->SetReferenceFromGroup(id, child); - } - // The CollectGarbage call above starts sweeper threads. - // The crash will happen if the following two functions - // are called before sweeping finishes. - heap->StartIncrementalMarking(i::Heap::kNoGCFlags, - i::GarbageCollectionReason::kTesting); - heap->FinalizeIncrementalMarkingIfComplete( - i::GarbageCollectionReason::kTesting); -} - - HEAP_TEST(Regress587004) { FLAG_concurrent_sweeping = false; #ifdef VERIFY_HEAP @@ -6449,7 +6426,7 @@ HEAP_TEST(Regress587004) { } CcTest::CollectGarbage(OLD_SPACE); heap::SimulateFullSpace(heap->old_space()); - heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(*array, N - 1); + heap->RightTrimFixedArray(*array, N - 1); heap->mark_compact_collector()->EnsureSweepingCompleted(); ByteArray* byte_array; const int M = 256; @@ -6467,6 +6444,7 @@ HEAP_TEST(Regress587004) { } HEAP_TEST(Regress589413) { + if (!FLAG_incremental_marking) return; FLAG_stress_compaction = true; FLAG_manual_evacuation_candidates_selection = true; FLAG_parallel_compaction = false; @@ -6533,7 +6511,7 @@ HEAP_TEST(Regress589413) { } heap::SimulateIncrementalMarking(heap); for (size_t j = 0; j < arrays.size(); j++) { - heap->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(arrays[j], N - 1); + heap->RightTrimFixedArray(arrays[j], N - 1); } } // Force allocation from the free list. @@ -6542,6 +6520,7 @@ HEAP_TEST(Regress589413) { } TEST(Regress598319) { + if (!FLAG_incremental_marking) return; // This test ensures that no white objects can cross the progress bar of large // objects during incremental marking. It checks this by using Shift() during // incremental marking. @@ -6658,6 +6637,7 @@ TEST(Regress609761) { } TEST(Regress615489) { + if (!i::FLAG_incremental_marking) return; FLAG_black_allocation = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -6712,6 +6692,7 @@ class StaticOneByteResource : public v8::String::ExternalOneByteStringResource { }; TEST(Regress631969) { + if (!FLAG_incremental_marking) return; FLAG_manual_evacuation_candidates_selection = true; FLAG_parallel_compaction = false; FLAG_concurrent_sweeping = false; @@ -6757,6 +6738,7 @@ TEST(Regress631969) { } TEST(LeftTrimFixedArrayInBlackArea) { + if (!i::FLAG_incremental_marking) return; FLAG_black_allocation = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -6795,6 +6777,7 @@ TEST(LeftTrimFixedArrayInBlackArea) { } TEST(ContinuousLeftTrimFixedArrayInBlackArea) { + if (!i::FLAG_incremental_marking) return; FLAG_black_allocation = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -6860,6 +6843,7 @@ TEST(ContinuousLeftTrimFixedArrayInBlackArea) { } TEST(ContinuousRightTrimFixedArrayInBlackArea) { + if (!i::FLAG_incremental_marking) return; FLAG_black_allocation = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); @@ -6898,19 +6882,19 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) { // Trim it once by one word to make checking for white marking color uniform. Address previous = end_address - kPointerSize; - heap->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(*array, 1); + heap->RightTrimFixedArray(*array, 1); HeapObject* filler = HeapObject::FromAddress(previous); CHECK(filler->IsFiller()); - CHECK(Marking::IsImpossible(ObjectMarking::MarkBitFrom(previous))); + CHECK(Marking::IsImpossible(ObjectMarking::MarkBitFrom(filler))); // Trim 10 times by one, two, and three word. for (int i = 1; i <= 3; i++) { for (int j = 0; j < 10; j++) { previous -= kPointerSize * i; - heap->RightTrimFixedArray<Heap::SEQUENTIAL_TO_SWEEPER>(*array, i); + heap->RightTrimFixedArray(*array, i); HeapObject* filler = HeapObject::FromAddress(previous); CHECK(filler->IsFiller()); - CHECK(Marking::IsWhite(ObjectMarking::MarkBitFrom(previous))); + CHECK(Marking::IsWhite(ObjectMarking::MarkBitFrom(filler))); } } @@ -6918,6 +6902,7 @@ TEST(ContinuousRightTrimFixedArrayInBlackArea) { } TEST(Regress618958) { + if (!i::FLAG_incremental_marking) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Heap* heap = CcTest::heap(); @@ -7057,5 +7042,57 @@ HEAP_TEST(Regress670675) { DCHECK(marking->IsStopped()); } +HEAP_TEST(Regress5831) { + CcTest::InitializeVM(); + Heap* heap = CcTest::heap(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope handle_scope(isolate); + + // Used to ensure that the first code space page remains filled. + Handle<FixedArray> array = isolate->factory()->NewFixedArray(32); + + { + // Ensure that the first code space page is full. + CEntryStub stub(isolate, 1); + Handle<Code> code = stub.GetCode(); + + int i = 0; + array = FixedArray::SetAndGrow(array, i++, code); + + while (heap->code_space()->FirstPage()->Contains(code->address())) { + code = isolate->factory()->CopyCode(code); + array = FixedArray::SetAndGrow(array, i++, code); + } + } + + class ImmovableCEntryStub : public i::CEntryStub { + public: + explicit ImmovableCEntryStub(i::Isolate* isolate) + : i::CEntryStub(isolate, 3, i::kSaveFPRegs, i::kArgvOnStack, true) {} + bool NeedsImmovableCode() override { return true; } + }; + + ImmovableCEntryStub stub(isolate); + + { + // Make sure the code object has not yet been generated. + Code* code; + CHECK(!stub.FindCodeInCache(&code)); + } + + // Fake a serializer run. + isolate->serializer_enabled_ = true; + + // Generate the code. + Handle<Code> code = stub.GetCode(); + CHECK(code->Size() <= i::kMaxRegularHeapObjectSize); + CHECK(!heap->code_space()->FirstPage()->Contains(code->address())); + + // Ensure it's not in large object space. + MemoryChunk* chunk = MemoryChunk::FromAddress(code->address()); + CHECK(chunk->owner()->identity() != LO_SPACE); + CHECK(chunk->NeverEvacuate()); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/heap/test-incremental-marking.cc b/deps/v8/test/cctest/heap/test-incremental-marking.cc index c659cecea7..642a3584e7 100644 --- a/deps/v8/test/cctest/heap/test-incremental-marking.cc +++ b/deps/v8/test/cctest/heap/test-incremental-marking.cc @@ -57,7 +57,7 @@ class MockPlatform : public v8::Platform { platform_->CallIdleOnForegroundThread(isolate, task); } - bool IdleTasksEnabled(v8::Isolate* isolate) override { return true; } + bool IdleTasksEnabled(v8::Isolate* isolate) override { return false; } bool PendingTask() { return task_ != nullptr; } @@ -114,31 +114,5 @@ TEST(IncrementalMarkingUsingTasks) { i::V8::SetPlatformForTesting(old_platform); } - -TEST(IncrementalMarkingUsingIdleTasksAfterGC) { - if (!i::FLAG_incremental_marking) return; - - CcTest::InitializeVM(); - v8::Platform* old_platform = i::V8::GetCurrentPlatform(); - MockPlatform platform(old_platform); - i::V8::SetPlatformForTesting(&platform); - i::heap::SimulateFullSpace(CcTest::heap()->old_space()); - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - // Perform any pending idle tasks. - while (platform.PendingTask()) { - platform.PerformTask(); - } - CHECK(!platform.PendingTask()); - i::IncrementalMarking* marking = CcTest::heap()->incremental_marking(); - marking->Stop(); - marking->Start(i::GarbageCollectionReason::kTesting); - CHECK(platform.PendingTask()); - while (platform.PendingTask()) { - platform.PerformTask(); - } - CHECK(marking->IsStopped()); - i::V8::SetPlatformForTesting(old_platform); -} - } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/heap/test-mark-compact.cc b/deps/v8/test/cctest/heap/test-mark-compact.cc index 0788e26108..ee37d070ac 100644 --- a/deps/v8/test/cctest/heap/test-mark-compact.cc +++ b/deps/v8/test/cctest/heap/test-mark-compact.cc @@ -41,6 +41,8 @@ #include "src/full-codegen/full-codegen.h" #include "src/global-handles.h" +#include "src/heap/mark-compact-inl.h" +#include "src/heap/mark-compact.h" #include "test/cctest/cctest.h" #include "test/cctest/heap/heap-tester.h" #include "test/cctest/heap/heap-utils.h" @@ -483,4 +485,36 @@ TEST(RegressJoinThreadsOnIsolateDeinit) { } } +TEST(Regress5829) { + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + v8::HandleScope sc(CcTest::isolate()); + Heap* heap = isolate->heap(); + heap::SealCurrentObjects(heap); + i::MarkCompactCollector* collector = heap->mark_compact_collector(); + i::IncrementalMarking* marking = heap->incremental_marking(); + if (collector->sweeping_in_progress()) { + collector->EnsureSweepingCompleted(); + } + CHECK(marking->IsMarking() || marking->IsStopped()); + if (marking->IsStopped()) { + heap->StartIncrementalMarking(i::Heap::kNoGCFlags, + i::GarbageCollectionReason::kTesting); + } + CHECK(marking->IsMarking()); + marking->StartBlackAllocationForTesting(); + Handle<FixedArray> array = isolate->factory()->NewFixedArray(10, TENURED); + Address old_end = array->address() + array->Size(); + // Right trim the array without clearing the mark bits. + array->set_length(9); + heap->CreateFillerObjectAt(old_end - kPointerSize, kPointerSize, + ClearRecordedSlots::kNo); + heap->old_space()->EmptyAllocationInfo(); + LiveObjectIterator<kGreyObjects> it(Page::FromAddress(array->address())); + HeapObject* object = nullptr; + while ((object = it.Next()) != nullptr) { + CHECK(!object->IsFiller()); + } +} + #endif // __linux__ and !USE_SIMULATOR diff --git a/deps/v8/test/cctest/heap/test-page-promotion.cc b/deps/v8/test/cctest/heap/test-page-promotion.cc index 4673f2edcf..3207c26250 100644 --- a/deps/v8/test/cctest/heap/test-page-promotion.cc +++ b/deps/v8/test/cctest/heap/test-page-promotion.cc @@ -42,6 +42,7 @@ namespace v8 { namespace internal { UNINITIALIZED_TEST(PagePromotion_NewToOld) { + if (!i::FLAG_incremental_marking) return; v8::Isolate* isolate = NewIsolateForPagePromotion(); i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); { diff --git a/deps/v8/test/cctest/interpreter/bytecode-expectations-printer.cc b/deps/v8/test/cctest/interpreter/bytecode-expectations-printer.cc index f7a5bb9467..8f34308ee0 100644 --- a/deps/v8/test/cctest/interpreter/bytecode-expectations-printer.cc +++ b/deps/v8/test/cctest/interpreter/bytecode-expectations-printer.cc @@ -25,6 +25,21 @@ namespace v8 { namespace internal { namespace interpreter { +static const char* NameForNativeContextIntrinsicIndex(uint32_t idx) { + switch (idx) { +#define COMPARE_NATIVE_CONTEXT_INTRINSIC_IDX(NAME, Type, name) \ + case Context::NAME: \ + return #name; + + NATIVE_CONTEXT_INTRINSIC_FUNCTIONS(COMPARE_NATIVE_CONTEXT_INTRINSIC_IDX) + + default: + break; + } + + return "UnknownIntrinsicIndex"; +} + // static const char* const BytecodeExpectationsPrinter::kDefaultTopFunctionName = "__genbckexp_wrapper__"; @@ -162,9 +177,15 @@ void BytecodeExpectationsPrinter::PrintBytecodeOperand( case OperandType::kFlag8: stream << bytecode_iterator.GetFlagOperand(op_index); break; - case OperandType::kIdx: - stream << bytecode_iterator.GetIndexOperand(op_index); + case OperandType::kIdx: { + uint32_t idx = bytecode_iterator.GetIndexOperand(op_index); + if (bytecode == Bytecode::kCallJSRuntime && op_index == 0) { + stream << "%" << NameForNativeContextIntrinsicIndex(idx); + } else { + stream << idx; + } break; + } case OperandType::kUImm: stream << bytecode_iterator.GetUnsignedImmediateOperand(op_index); break; diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden index 92cdcac1bf..2d57edf4a0 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiterals.golden @@ -18,7 +18,7 @@ bytecodes: [ /* 51 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] @@ -42,13 +42,13 @@ bytecodes: [ /* 54 E> */ B(StaKeyedPropertySloppy), R(2), R(1), U8(3), B(LdaSmi), U8(1), B(Star), R(1), - /* 57 E> */ B(AddSmi), U8(1), R(0), U8(2), + /* 59 E> */ B(AddSmi), U8(1), R(0), U8(2), B(StaKeyedPropertySloppy), R(2), R(1), U8(3), B(Ldar), R(2), /* 66 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] @@ -66,7 +66,7 @@ bytecodes: [ /* 62 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] @@ -100,7 +100,7 @@ bytecodes: [ B(Star), R(4), B(LdaZero), B(Star), R(3), - /* 66 E> */ B(AddSmi), U8(2), R(0), U8(4), + /* 68 E> */ B(AddSmi), U8(2), R(0), U8(4), B(StaKeyedPropertySloppy), R(4), R(3), U8(5), B(Ldar), R(4), B(StaKeyedPropertySloppy), R(2), R(1), U8(7), @@ -108,9 +108,9 @@ bytecodes: [ /* 77 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, - FIXED_ARRAY_TYPE, - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden index 6431d8adbe..1dcfc48cbc 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ArrayLiteralsWide.golden @@ -1043,7 +1043,7 @@ constant pool: [ HEAP_NUMBER_TYPE [1.23], HEAP_NUMBER_TYPE [1.23], HEAP_NUMBER_TYPE [1.23], - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden index d36860174c..4ea65897ff 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/AssignmentsInBinaryExpression.golden @@ -74,11 +74,11 @@ bytecodes: [ /* 46 S> */ B(LdaSmi), U8(100), B(Mov), R(0), R(1), B(Star), R(0), - /* 57 E> */ B(Add), R(1), U8(2), + /* 52 E> */ B(Add), R(1), U8(2), B(Star), R(1), B(LdaSmi), U8(101), B(Star), R(0), - /* 69 E> */ B(Add), R(1), U8(3), + /* 64 E> */ B(Add), R(1), U8(3), B(Star), R(0), /* 77 S> */ B(Nop), /* 87 S> */ B(Return), @@ -104,11 +104,11 @@ bytecodes: [ B(Star), R(0), /* 46 S> */ B(LdaSmi), U8(56), B(Star), R(0), - /* 61 E> */ B(Sub), R(0), U8(2), + /* 59 E> */ B(Sub), R(0), U8(2), B(Star), R(1), B(LdaSmi), U8(57), B(Star), R(0), - /* 68 E> */ B(Add), R(1), U8(3), + /* 63 E> */ B(Add), R(1), U8(3), B(Star), R(0), /* 75 S> */ B(Inc), U8(4), B(Star), R(0), @@ -136,15 +136,15 @@ bytecodes: [ /* 76 S> */ B(LdaSmi), U8(1), B(Mov), R(0), R(2), B(Star), R(0), - /* 61 E> */ B(Add), R(2), U8(2), + /* 56 E> */ B(Add), R(2), U8(2), B(Star), R(2), B(LdaSmi), U8(2), B(Star), R(0), - /* 71 E> */ B(Add), R(2), U8(3), + /* 66 E> */ B(Add), R(2), U8(3), B(Star), R(2), B(LdaSmi), U8(3), B(Star), R(0), - /* 81 E> */ B(Add), R(2), U8(4), + /* 76 E> */ B(Add), R(2), U8(4), B(Star), R(1), /* 87 S> */ B(Nop), /* 97 S> */ B(Return), @@ -170,15 +170,15 @@ bytecodes: [ /* 76 S> */ B(LdaSmi), U8(1), B(Mov), R(0), R(1), B(Star), R(0), - /* 61 E> */ B(Add), R(1), U8(2), + /* 56 E> */ B(Add), R(1), U8(2), B(Star), R(1), B(LdaSmi), U8(2), B(Star), R(0), - /* 71 E> */ B(Add), R(1), U8(3), + /* 66 E> */ B(Add), R(1), U8(3), B(Star), R(1), B(LdaSmi), U8(3), B(Star), R(0), - /* 81 E> */ B(Add), R(1), U8(4), + /* 76 E> */ B(Add), R(1), U8(4), B(Star), R(0), /* 87 S> */ B(Nop), /* 97 S> */ B(Return), @@ -205,29 +205,29 @@ bytecodes: [ /* 54 S> */ B(LdaSmi), U8(1), B(Mov), R(0), R(2), B(Star), R(0), - /* 68 E> */ B(Add), R(2), U8(2), + /* 63 E> */ B(Add), R(2), U8(2), B(Star), R(2), - /* 76 E> */ B(AddSmi), U8(1), R(0), U8(3), + /* 78 E> */ B(AddSmi), U8(1), R(0), U8(3), B(Star), R(3), B(LdaSmi), U8(2), B(Star), R(1), - /* 88 E> */ B(Mul), R(3), U8(4), - B(Add), R(2), U8(5), + /* 83 E> */ B(Mul), R(3), U8(4), + /* 73 E> */ B(Add), R(2), U8(5), B(Star), R(2), B(LdaSmi), U8(3), B(Star), R(1), - /* 98 E> */ B(Add), R(2), U8(6), + /* 93 E> */ B(Add), R(2), U8(6), B(Star), R(2), B(LdaSmi), U8(4), B(Star), R(0), - /* 108 E> */ B(Add), R(2), U8(7), + /* 103 E> */ B(Add), R(2), U8(7), B(Star), R(2), B(LdaSmi), U8(5), B(Star), R(1), - /* 118 E> */ B(Add), R(2), U8(8), + /* 113 E> */ B(Add), R(2), U8(8), B(Star), R(2), B(Ldar), R(1), - /* 125 E> */ B(Add), R(2), U8(9), + /* 123 E> */ B(Add), R(2), U8(9), /* 128 S> */ B(Return), ] constant pool: [ @@ -250,7 +250,7 @@ bytecodes: [ /* 46 S> */ B(LdaSmi), U8(1), B(Star), R(1), B(Ldar), R(0), - /* 57 E> */ B(Add), R(1), U8(2), + /* 55 E> */ B(Add), R(1), U8(2), B(Star), R(1), B(Ldar), R(0), B(ToNumber), R(2), @@ -258,12 +258,12 @@ bytecodes: [ B(Inc), U8(3), B(Star), R(0), B(Ldar), R(2), - /* 63 E> */ B(Add), R(1), U8(4), + /* 59 E> */ B(Add), R(1), U8(4), B(Star), R(1), B(Ldar), R(0), B(Inc), U8(5), B(Star), R(0), - /* 72 E> */ B(Add), R(1), U8(6), + /* 67 E> */ B(Add), R(1), U8(6), /* 76 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden index 1cbd05fcea..d0c7f4934c 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/BasicLoops.golden @@ -63,7 +63,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 53 +bytecode array length: 54 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -72,12 +72,13 @@ bytecodes: [ B(Star), R(1), /* 65 S> */ B(LdaSmi), U8(10), /* 65 E> */ B(TestLessThan), R(0), U8(2), - B(JumpIfFalse), U8(37), + B(JumpIfFalse), U8(38), /* 56 E> */ B(StackCheck), /* 75 S> */ B(LdaSmi), U8(12), - B(Mul), R(1), U8(3), + /* 81 E> */ B(Mul), R(1), U8(3), B(Star), R(1), - /* 89 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 89 S> */ B(LdaSmi), U8(1), + /* 95 E> */ B(Add), R(0), U8(4), B(Star), R(0), /* 102 S> */ B(LdaSmi), U8(3), /* 108 E> */ B(TestEqual), R(0), U8(5), @@ -87,7 +88,7 @@ bytecodes: [ /* 132 E> */ B(TestEqual), R(0), U8(6), B(JumpIfFalse), U8(4), /* 138 S> */ B(Jump), U8(5), - B(JumpLoop), U8(-39), U8(0), + B(JumpLoop), U8(-40), U8(0), /* 147 S> */ B(Ldar), R(1), /* 157 S> */ B(Return), ] @@ -111,7 +112,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 61 +bytecode array length: 62 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -120,26 +121,27 @@ bytecodes: [ /* 62 S> */ B(LdaZero), /* 68 E> */ B(TestLessThan), R(0), U8(2), B(JumpIfFalse), U8(4), - /* 73 S> */ B(Jump), U8(44), + /* 73 S> */ B(Jump), U8(45), /* 85 S> */ B(LdaSmi), U8(3), /* 91 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 97 S> */ B(Jump), U8(38), + /* 97 S> */ B(Jump), U8(39), /* 106 S> */ B(LdaSmi), U8(4), /* 112 E> */ B(TestEqual), R(0), U8(4), B(JumpIfFalse), U8(4), - /* 118 S> */ B(Jump), U8(29), + /* 118 S> */ B(Jump), U8(30), /* 127 S> */ B(LdaSmi), U8(10), /* 133 E> */ B(TestEqual), R(0), U8(5), B(JumpIfFalse), U8(4), - /* 140 S> */ B(Jump), U8(17), + /* 140 S> */ B(Jump), U8(18), /* 152 S> */ B(LdaSmi), U8(5), /* 158 E> */ B(TestEqual), R(0), U8(6), B(JumpIfFalse), U8(4), - /* 164 S> */ B(Jump), U8(11), - /* 173 S> */ B(AddSmi), U8(1), R(0), U8(7), + /* 164 S> */ B(Jump), U8(12), + /* 173 S> */ B(LdaSmi), U8(1), + /* 179 E> */ B(Add), R(0), U8(7), B(Star), R(0), - B(JumpLoop), U8(-51), U8(0), + B(JumpLoop), U8(-52), U8(0), /* 186 S> */ B(Ldar), R(0), /* 196 S> */ B(Return), ] @@ -163,7 +165,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 42 +bytecode array length: 44 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -171,16 +173,18 @@ bytecodes: [ /* 45 E> */ B(StackCheck), /* 71 S> */ B(LdaSmi), U8(3), /* 71 E> */ B(TestLessThan), R(0), U8(2), - B(JumpIfFalse), U8(21), + B(JumpIfFalse), U8(22), /* 62 E> */ B(StackCheck), /* 82 S> */ B(LdaSmi), U8(2), /* 88 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 94 S> */ B(Jump), U8(11), - /* 105 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 94 S> */ B(Jump), U8(12), + /* 105 S> */ B(LdaSmi), U8(1), + /* 111 E> */ B(Add), R(0), U8(4), B(Star), R(0), - B(JumpLoop), U8(-23), U8(1), - /* 122 S> */ B(AddSmi), U8(1), R(0), U8(5), + B(JumpLoop), U8(-24), U8(1), + /* 122 S> */ B(LdaSmi), U8(1), + /* 128 E> */ B(Add), R(0), U8(5), B(Star), R(0), /* 135 S> */ B(Jump), U8(2), /* 144 S> */ B(Ldar), R(0), @@ -203,7 +207,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 33 +bytecode array length: 34 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), @@ -211,14 +215,15 @@ bytecodes: [ /* 54 S> */ B(LdaSmi), U8(1), B(Star), R(1), /* 64 S> */ B(Ldar), R(0), - B(JumpIfToBooleanFalse), U8(19), + B(JumpIfToBooleanFalse), U8(20), /* 57 E> */ B(StackCheck), /* 71 S> */ B(LdaSmi), U8(12), - B(Mul), R(1), U8(2), + /* 77 E> */ B(Mul), R(1), U8(2), B(Star), R(1), - /* 85 S> */ B(SubSmi), U8(1), R(0), U8(3), + /* 85 S> */ B(LdaSmi), U8(1), + /* 91 E> */ B(Sub), R(0), U8(3), B(Star), R(0), - B(JumpLoop), U8(-18), U8(0), + B(JumpLoop), U8(-19), U8(0), /* 98 S> */ B(Ldar), R(1), /* 108 S> */ B(Return), ] @@ -240,7 +245,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 53 +bytecode array length: 54 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -249,22 +254,23 @@ bytecodes: [ B(Star), R(1), /* 56 E> */ B(StackCheck), /* 63 S> */ B(LdaSmi), U8(10), - B(Mul), R(1), U8(2), + /* 69 E> */ B(Mul), R(1), U8(2), B(Star), R(1), /* 77 S> */ B(LdaSmi), U8(5), /* 83 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 89 S> */ B(Jump), U8(27), + /* 89 S> */ B(Jump), U8(28), /* 98 S> */ B(LdaSmi), U8(6), /* 104 E> */ B(TestEqual), R(0), U8(4), B(JumpIfFalse), U8(4), - /* 110 S> */ B(Jump), U8(8), - /* 122 S> */ B(AddSmi), U8(1), R(0), U8(5), + /* 110 S> */ B(Jump), U8(9), + /* 122 S> */ B(LdaSmi), U8(1), + /* 128 E> */ B(Add), R(0), U8(5), B(Star), R(0), /* 144 S> */ B(LdaSmi), U8(10), /* 144 E> */ B(TestLessThan), R(0), U8(6), B(JumpIfFalse), U8(5), - B(JumpLoop), U8(-39), U8(0), + B(JumpLoop), U8(-40), U8(0), /* 151 S> */ B(Ldar), R(1), /* 161 S> */ B(Return), ] @@ -285,7 +291,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 31 +bytecode array length: 32 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), @@ -294,12 +300,13 @@ bytecodes: [ B(Star), R(1), /* 57 E> */ B(StackCheck), /* 64 S> */ B(LdaSmi), U8(12), - B(Mul), R(1), U8(2), + /* 70 E> */ B(Mul), R(1), U8(2), B(Star), R(1), - /* 78 S> */ B(SubSmi), U8(1), R(0), U8(3), + /* 78 S> */ B(LdaSmi), U8(1), + /* 84 E> */ B(Sub), R(0), U8(3), B(Star), R(0), /* 98 S> */ B(JumpIfToBooleanFalse), U8(5), - B(JumpLoop), U8(-16), U8(0), + B(JumpLoop), U8(-17), U8(0), /* 102 S> */ B(Ldar), R(1), /* 112 S> */ B(Return), ] @@ -321,7 +328,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 43 +bytecode array length: 44 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -330,13 +337,14 @@ bytecodes: [ B(Star), R(1), /* 56 E> */ B(StackCheck), /* 63 S> */ B(LdaSmi), U8(10), - B(Mul), R(1), U8(2), + /* 69 E> */ B(Mul), R(1), U8(2), B(Star), R(1), /* 77 S> */ B(LdaSmi), U8(5), /* 83 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 89 S> */ B(Jump), U8(17), - /* 98 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 89 S> */ B(Jump), U8(18), + /* 98 S> */ B(LdaSmi), U8(1), + /* 104 E> */ B(Add), R(0), U8(4), B(Star), R(0), /* 111 S> */ B(LdaSmi), U8(6), /* 117 E> */ B(TestEqual), R(0), U8(5), @@ -363,7 +371,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 46 +bytecode array length: 47 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -372,19 +380,20 @@ bytecodes: [ B(Star), R(1), /* 56 E> */ B(StackCheck), /* 63 S> */ B(LdaSmi), U8(10), - B(Mul), R(1), U8(2), + /* 69 E> */ B(Mul), R(1), U8(2), B(Star), R(1), /* 77 S> */ B(LdaSmi), U8(5), /* 83 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 89 S> */ B(Jump), U8(20), - /* 98 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 89 S> */ B(Jump), U8(21), + /* 98 S> */ B(LdaSmi), U8(1), + /* 104 E> */ B(Add), R(0), U8(4), B(Star), R(0), /* 111 S> */ B(LdaSmi), U8(6), /* 117 E> */ B(TestEqual), R(0), U8(5), B(JumpIfFalse), U8(4), /* 123 S> */ B(Jump), U8(2), - B(JumpLoop), U8(-32), U8(0), + B(JumpLoop), U8(-33), U8(0), /* 149 S> */ B(Ldar), R(1), /* 159 S> */ B(Return), ] @@ -404,7 +413,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 34 +bytecode array length: 35 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -413,14 +422,15 @@ bytecodes: [ /* 58 S> */ B(LdaSmi), U8(1), /* 64 E> */ B(TestEqual), R(0), U8(2), B(JumpIfFalse), U8(4), - /* 70 S> */ B(Jump), U8(20), + /* 70 S> */ B(Jump), U8(21), /* 79 S> */ B(LdaSmi), U8(2), /* 85 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 91 S> */ B(Jump), U8(8), - /* 103 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 91 S> */ B(Jump), U8(9), + /* 103 S> */ B(LdaSmi), U8(1), + /* 109 E> */ B(Add), R(0), U8(4), B(Star), R(0), - B(JumpLoop), U8(-25), U8(0), + B(JumpLoop), U8(-26), U8(0), B(LdaUndefined), /* 116 S> */ B(Return), ] @@ -439,7 +449,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 34 +bytecode array length: 35 bytecodes: [ /* 30 E> */ B(StackCheck), /* 47 S> */ B(LdaZero), @@ -448,14 +458,15 @@ bytecodes: [ /* 56 S> */ B(LdaSmi), U8(1), /* 62 E> */ B(TestEqual), R(0), U8(2), B(JumpIfFalse), U8(4), - /* 68 S> */ B(Jump), U8(20), + /* 68 S> */ B(Jump), U8(21), /* 77 S> */ B(LdaSmi), U8(2), /* 83 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 89 S> */ B(Jump), U8(8), - /* 101 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 89 S> */ B(Jump), U8(9), + /* 101 S> */ B(LdaSmi), U8(1), + /* 107 E> */ B(Add), R(0), U8(4), B(Star), R(0), - B(JumpLoop), U8(-25), U8(0), + B(JumpLoop), U8(-26), U8(0), B(LdaUndefined), /* 114 S> */ B(Return), ] @@ -474,7 +485,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 34 +bytecode array length: 35 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -483,14 +494,15 @@ bytecodes: [ /* 68 S> */ B(LdaSmi), U8(1), /* 74 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 80 S> */ B(Jump), U8(20), + /* 80 S> */ B(Jump), U8(21), /* 89 S> */ B(LdaSmi), U8(2), /* 95 E> */ B(TestEqual), R(0), U8(4), B(JumpIfFalse), U8(4), /* 101 S> */ B(Jump), U8(2), - /* 55 S> */ B(AddSmi), U8(1), R(0), U8(2), + /* 55 S> */ B(LdaSmi), U8(1), + /* 59 E> */ B(Add), R(0), U8(2), B(Star), R(0), - B(JumpLoop), U8(-25), U8(0), + B(JumpLoop), U8(-26), U8(0), B(LdaUndefined), /* 113 S> */ B(Return), ] @@ -508,7 +520,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 34 +bytecode array length: 35 bytecodes: [ /* 30 E> */ B(StackCheck), /* 47 S> */ B(LdaZero), @@ -517,14 +529,15 @@ bytecodes: [ /* 66 S> */ B(LdaSmi), U8(1), /* 72 E> */ B(TestEqual), R(0), U8(3), B(JumpIfFalse), U8(4), - /* 78 S> */ B(Jump), U8(20), + /* 78 S> */ B(Jump), U8(21), /* 87 S> */ B(LdaSmi), U8(2), /* 93 E> */ B(TestEqual), R(0), U8(4), B(JumpIfFalse), U8(4), /* 99 S> */ B(Jump), U8(2), - /* 53 S> */ B(AddSmi), U8(1), R(0), U8(2), + /* 53 S> */ B(LdaSmi), U8(1), + /* 57 E> */ B(Add), R(0), U8(2), B(Star), R(0), - B(JumpLoop), U8(-25), U8(0), + B(JumpLoop), U8(-26), U8(0), B(LdaUndefined), /* 111 S> */ B(Return), ] @@ -543,7 +556,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 34 +bytecode array length: 36 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -552,14 +565,16 @@ bytecodes: [ B(Star), R(1), /* 63 S> */ B(LdaSmi), U8(100), /* 63 E> */ B(TestLessThan), R(1), U8(2), - B(JumpIfFalse), U8(20), + B(JumpIfFalse), U8(22), /* 45 E> */ B(StackCheck), - /* 85 S> */ B(AddSmi), U8(1), R(0), U8(4), + /* 85 S> */ B(LdaSmi), U8(1), + /* 91 E> */ B(Add), R(0), U8(4), B(Star), R(0), /* 98 S> */ B(Jump), U8(2), - /* 72 S> */ B(AddSmi), U8(1), R(1), U8(3), + /* 72 S> */ B(LdaSmi), U8(1), + /* 76 E> */ B(Add), R(1), U8(3), B(Star), R(1), - B(JumpLoop), U8(-22), U8(0), + B(JumpLoop), U8(-24), U8(0), B(LdaUndefined), /* 110 S> */ B(Return), ] @@ -589,7 +604,7 @@ bytecodes: [ B(JumpIfToBooleanFalse), U8(19), /* 45 E> */ B(StackCheck), /* 74 S> */ B(LdaSmi), U8(12), - B(Mul), R(0), U8(3), + /* 80 E> */ B(Mul), R(0), U8(3), B(Star), R(0), /* 67 S> */ B(Ldar), R(1), B(Dec), U8(2), @@ -639,7 +654,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 35 +bytecode array length: 36 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), @@ -647,7 +662,8 @@ bytecodes: [ /* 58 S> */ B(LdaZero), B(Star), R(1), /* 45 E> */ B(StackCheck), - /* 76 S> */ B(AddSmi), U8(1), R(0), U8(3), + /* 76 S> */ B(LdaSmi), U8(1), + /* 82 E> */ B(Add), R(0), U8(3), B(Star), R(0), /* 89 S> */ B(LdaSmi), U8(20), /* 95 E> */ B(TestEqual), R(0), U8(4), @@ -656,7 +672,7 @@ bytecodes: [ /* 69 S> */ B(Ldar), R(1), B(Inc), U8(2), B(Star), R(1), - B(JumpLoop), U8(-22), U8(0), + B(JumpLoop), U8(-23), U8(0), /* 112 S> */ B(Ldar), R(0), /* 122 S> */ B(Return), ] @@ -679,20 +695,20 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 53 +bytecode array length: 54 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), B(Star), R(1), /* 52 S> */ B(Ldar), R(1), - B(JumpIfToBooleanFalse), U8(45), + B(JumpIfToBooleanFalse), U8(46), /* 45 E> */ B(StackCheck), B(Ldar), R(closure), B(CreateBlockContext), U8(0), B(PushContext), R(3), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(1), U8(2), + B(CreateClosure), U8(1), U8(2), U8(2), B(Star), R(0), /* 73 S> */ B(LdaSmi), U8(1), /* 73 E> */ B(StaCurrentContextSlot), U8(4), @@ -703,10 +719,10 @@ bytecodes: [ B(PopContext), R(3), B(Jump), U8(10), /* 126 S> */ B(LdaCurrentContextSlot), U8(4), - B(Inc), U8(2), + B(Inc), U8(3), /* 127 E> */ B(StaCurrentContextSlot), U8(4), B(PopContext), R(3), - B(JumpLoop), U8(-44), U8(0), + B(JumpLoop), U8(-45), U8(0), B(LdaUndefined), /* 137 S> */ B(Return), ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden index 9058fb8ad1..ce343d01b3 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/BreakableBlocks.golden @@ -17,12 +17,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 15 +bytecode array length: 16 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), B(Star), R(0), - /* 56 S> */ B(AddSmi), U8(1), R(0), U8(2), + /* 56 S> */ B(LdaSmi), U8(1), + /* 62 E> */ B(Add), R(0), U8(2), B(Star), R(0), /* 69 S> */ B(Jump), U8(2), /* 97 S> */ B(Ldar), R(0), @@ -69,7 +70,7 @@ bytecodes: [ B(Inc), U8(6), B(Star), R(0), /* 142 S> */ B(Ldar), R(2), - /* 150 E> */ B(Add), R(1), U8(7), + /* 148 E> */ B(Add), R(1), U8(7), B(Star), R(3), B(LdaSmi), U8(12), /* 152 E> */ B(TestEqual), R(3), U8(8), @@ -101,7 +102,7 @@ snippet: " " frame size: 3 parameter count: 1 -bytecode array length: 30 +bytecode array length: 31 bytecodes: [ /* 30 E> */ B(StackCheck), B(Ldar), R(closure), @@ -109,7 +110,7 @@ bytecodes: [ B(PushContext), R(2), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(1), U8(2), + B(CreateClosure), U8(1), U8(2), U8(2), B(Star), R(0), /* 53 S> */ B(LdaSmi), U8(10), /* 53 E> */ B(StaCurrentContextSlot), U8(4), @@ -142,7 +143,7 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 53 +bytecode array length: 54 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(2), @@ -156,7 +157,7 @@ bytecodes: [ B(PushContext), R(3), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(1), U8(2), + B(CreateClosure), U8(1), U8(2), U8(2), B(Star), R(0), /* 76 S> */ B(LdaSmi), U8(2), /* 76 E> */ B(StaCurrentContextSlot), U8(4), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden index 40be0533c1..beb9a30222 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden @@ -14,17 +14,18 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 14 +bytecode array length: 15 bytecodes: [ /* 27 E> */ B(StackCheck), /* 32 S> */ B(LdaUndefined), B(Star), R(1), - B(LdaGlobal), U8(4), + B(LdaGlobal), U8(0), U8(4), B(Star), R(0), /* 39 E> */ B(Call), R(0), R(1), U8(1), U8(2), /* 44 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["t"], ] handlers: [ ] @@ -37,12 +38,12 @@ snippet: " " frame size: 5 parameter count: 1 -bytecode array length: 26 +bytecode array length: 27 bytecodes: [ /* 34 E> */ B(StackCheck), /* 39 S> */ B(LdaUndefined), B(Star), R(1), - B(LdaGlobal), U8(4), + B(LdaGlobal), U8(0), U8(4), B(Star), R(0), B(LdaSmi), U8(1), B(Star), R(2), @@ -54,6 +55,7 @@ bytecodes: [ /* 58 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["t"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden index e05419fbff..cad09007e5 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden @@ -11,7 +11,7 @@ snippet: " " frame size: 10 parameter count: 1 -bytecode array length: 81 +bytecode array length: 82 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -22,11 +22,11 @@ bytecodes: [ B(Ldar), R(new_target), B(StaCurrentContextSlot), U8(5), /* 30 E> */ B(StackCheck), - /* 34 S> */ B(CreateClosure), U8(0), U8(2), + /* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 36 E> */ B(StaLookupSlotSloppy), U8(1), /* 52 S> */ B(LdaUndefined), B(Star), R(2), - /* 52 E> */ B(LdaLookupGlobalSlot), U8(2), U8(4), U8(1), + /* 52 E> */ B(LdaLookupGlobalSlot), U8(2), U8(5), U8(1), B(Star), R(1), B(LdaConstant), U8(3), B(Star), R(3), @@ -41,12 +41,12 @@ bytecodes: [ B(Mov), R(closure), R(6), B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), B(Star), R(1), - /* 52 E> */ B(Call), R(1), R(2), U8(2), U8(2), + /* 52 E> */ B(Call), R(1), R(2), U8(2), U8(3), /* 62 S> */ B(LdaUndefined), B(Star), R(2), - /* 69 E> */ B(LdaLookupGlobalSlot), U8(1), U8(8), U8(1), + /* 69 E> */ B(LdaLookupGlobalSlot), U8(1), U8(9), U8(1), B(Star), R(1), - /* 69 E> */ B(Call), R(1), R(2), U8(1), U8(6), + /* 69 E> */ B(Call), R(1), R(2), U8(1), U8(7), /* 74 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallNew.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallNew.golden index eb5b0630f4..f60f73e065 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallNew.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallNew.golden @@ -14,15 +14,16 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 11 +bytecode array length: 12 bytecodes: [ /* 45 E> */ B(StackCheck), - /* 50 S> */ B(LdaGlobal), U8(4), + /* 50 S> */ B(LdaGlobal), U8(0), U8(4), B(Star), R(0), /* 57 E> */ B(New), R(0), R(0), U8(0), U8(2), /* 68 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["bar"], ] handlers: [ ] @@ -35,10 +36,10 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 17 +bytecode array length: 18 bytecodes: [ /* 58 E> */ B(StackCheck), - /* 63 S> */ B(LdaGlobal), U8(4), + /* 63 S> */ B(LdaGlobal), U8(0), U8(4), B(Star), R(0), B(LdaSmi), U8(3), B(Star), R(1), @@ -47,6 +48,7 @@ bytecodes: [ /* 82 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["bar"], ] handlers: [ ] @@ -64,10 +66,10 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 25 +bytecode array length: 26 bytecodes: [ /* 100 E> */ B(StackCheck), - /* 105 S> */ B(LdaGlobal), U8(4), + /* 105 S> */ B(LdaGlobal), U8(0), U8(4), B(Star), R(0), B(LdaSmi), U8(3), B(Star), R(1), @@ -80,6 +82,7 @@ bytecodes: [ /* 130 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["bar"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden index 149e668291..31e697590e 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CallRuntime.golden @@ -79,11 +79,11 @@ bytecodes: [ B(Star), R(0), B(CreateArrayLiteral), U8(0), U8(0), U8(9), B(Star), R(1), - B(CallJSRuntime), U8(154), R(0), U8(2), + B(CallJSRuntime), U8(%spread_iterable), R(0), U8(2), /* 44 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden index 174641bc74..0c41685b86 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden @@ -36,7 +36,7 @@ bytecodes: [ B(Star), R(1), /* 117 E> */ B(Call), R(1), R(this), U8(1), U8(2), B(Star), R(1), - B(AddSmi), U8(1), R(1), U8(8), + /* 126 E> */ B(AddSmi), U8(1), R(1), U8(8), /* 131 S> */ B(Return), ] constant pool: [ @@ -107,14 +107,14 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 82 +bytecode array length: 75 bytecodes: [ B(Mov), R(closure), R(1), B(Mov), R(new_target), R(0), B(Ldar), R(new_target), /* 113 E> */ B(StackCheck), - /* 118 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), - B(Star), R(2), + /* 118 S> */ B(Ldar), R(1), + B(GetSuperConstructor), R(2), B(LdaSmi), U8(1), B(Star), R(3), B(Ldar), R(0), @@ -122,10 +122,8 @@ bytecodes: [ B(Star), R(2), B(Ldar), R(this), B(JumpIfNotHole), U8(4), - B(Jump), U8(11), - B(LdaConstant), U8(0), - B(Star), R(3), - /* 118 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), + B(Jump), U8(7), + /* 118 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0), B(Mov), R(2), R(this), /* 128 S> */ B(Ldar), R(this), B(JumpIfNotHole), U8(11), @@ -162,25 +160,23 @@ snippet: " test = new B().constructor; })(); " -frame size: 4 +frame size: 3 parameter count: 1 -bytecode array length: 78 +bytecode array length: 71 bytecodes: [ B(Mov), R(closure), R(1), B(Mov), R(new_target), R(0), B(Ldar), R(new_target), /* 112 E> */ B(StackCheck), - /* 117 S> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), - B(Star), R(2), + /* 117 S> */ B(Ldar), R(1), + B(GetSuperConstructor), R(2), B(Ldar), R(0), /* 117 E> */ B(New), R(2), R(0), U8(0), U8(2), B(Star), R(2), B(Ldar), R(this), B(JumpIfNotHole), U8(4), - B(Jump), U8(11), - B(LdaConstant), U8(0), - B(Star), R(3), - /* 117 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), + B(Jump), U8(7), + /* 117 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0), B(Mov), R(2), R(this), /* 126 S> */ B(Ldar), R(this), B(JumpIfNotHole), U8(11), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden index 765ce65efd..7b283024c8 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ClassDeclarations.golden @@ -12,7 +12,7 @@ snippet: " speak() { console.log(this.name + ' is speaking.'); } } " -frame size: 10 +frame size: 9 parameter count: 1 bytecode array length: 75 bytecodes: [ @@ -21,28 +21,26 @@ bytecodes: [ /* 30 E> */ B(StackCheck), B(LdaTheHole), B(Star), R(0), - /* 34 S> */ B(LdaTheHole), + /* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(3), - B(CreateClosure), U8(0), U8(2), + B(LdaTheHole), B(Star), R(4), B(LdaSmi), U8(34), - B(Star), R(5), - B(Wide), B(LdaSmi), U16(148), B(Star), R(6), - B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), - B(Star), R(3), - B(LdaNamedProperty), R(3), U8(1), U8(2), + B(Wide), B(LdaSmi), U16(148), + B(Star), R(7), + B(Mov), R(3), R(5), + B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), B(Star), R(4), - B(LdaConstant), U8(2), - B(ToName), R(6), - B(CreateClosure), U8(3), U8(2), + B(LdaConstant), U8(1), + B(Star), R(6), + B(CreateClosure), U8(2), U8(3), U8(2), B(Star), R(7), B(LdaSmi), U8(2), B(Star), R(8), - B(LdaZero), - B(Star), R(9), - B(Mov), R(4), R(5), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5), + B(Ldar), R(7), + B(StaDataPropertyInLiteral), R(4), R(6), U8(1), U8(4), + B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1), B(Star), R(0), B(Star), R(1), @@ -52,7 +50,6 @@ bytecodes: [ ] constant pool: [ SHARED_FUNCTION_INFO_TYPE, - ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["speak"], SHARED_FUNCTION_INFO_TYPE, ] @@ -66,7 +63,7 @@ snippet: " speak() { console.log(this.name + ' is speaking.'); } } " -frame size: 10 +frame size: 9 parameter count: 1 bytecode array length: 75 bytecodes: [ @@ -75,28 +72,26 @@ bytecodes: [ /* 30 E> */ B(StackCheck), B(LdaTheHole), B(Star), R(0), - /* 34 S> */ B(LdaTheHole), + /* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(3), - B(CreateClosure), U8(0), U8(2), + B(LdaTheHole), B(Star), R(4), B(LdaSmi), U8(34), - B(Star), R(5), - B(Wide), B(LdaSmi), U16(148), B(Star), R(6), - B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), - B(Star), R(3), - B(LdaNamedProperty), R(3), U8(1), U8(2), + B(Wide), B(LdaSmi), U16(148), + B(Star), R(7), + B(Mov), R(3), R(5), + B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), B(Star), R(4), - B(LdaConstant), U8(2), - B(ToName), R(6), - B(CreateClosure), U8(3), U8(2), + B(LdaConstant), U8(1), + B(Star), R(6), + B(CreateClosure), U8(2), U8(3), U8(2), B(Star), R(7), B(LdaSmi), U8(2), B(Star), R(8), - B(LdaZero), - B(Star), R(9), - B(Mov), R(4), R(5), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(5), U8(5), + B(Ldar), R(7), + B(StaDataPropertyInLiteral), R(4), R(6), U8(1), U8(4), + B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1), B(Star), R(0), B(Star), R(1), @@ -106,7 +101,6 @@ bytecodes: [ ] constant pool: [ SHARED_FUNCTION_INFO_TYPE, - ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["speak"], SHARED_FUNCTION_INFO_TYPE, ] @@ -122,9 +116,9 @@ snippet: " static [n1]() { return n1; } } " -frame size: 11 +frame size: 10 parameter count: 1 -bytecode array length: 121 +bytecode array length: 117 bytecodes: [ B(CreateFunctionContext), U8(2), B(PushContext), R(3), @@ -137,40 +131,36 @@ bytecodes: [ /* 57 E> */ B(StaCurrentContextSlot), U8(5), B(LdaTheHole), B(Star), R(0), - /* 62 S> */ B(LdaTheHole), + /* 62 S> */ B(CreateClosure), U8(2), U8(2), U8(2), B(Star), R(4), - B(CreateClosure), U8(2), U8(2), + B(LdaTheHole), B(Star), R(5), B(LdaSmi), U8(62), - B(Star), R(6), - B(Wide), B(LdaSmi), U16(128), B(Star), R(7), - B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), - B(Star), R(4), - B(LdaNamedProperty), R(4), U8(3), U8(2), + B(Wide), B(LdaSmi), U16(128), + B(Star), R(8), + B(Mov), R(4), R(6), + B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4), B(Star), R(5), B(LdaCurrentContextSlot), U8(4), /* 75 E> */ B(ToName), R(7), - B(CreateClosure), U8(4), U8(2), + B(CreateClosure), U8(3), U8(3), U8(2), B(Star), R(8), B(LdaSmi), U8(2), B(Star), R(9), - B(LdaSmi), U8(1), - B(Star), R(10), - B(Mov), R(5), R(6), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(6), U8(5), + B(Ldar), R(8), + B(StaDataPropertyInLiteral), R(5), R(7), U8(3), U8(5), B(LdaCurrentContextSlot), U8(5), /* 106 E> */ B(ToName), R(7), - B(LdaConstant), U8(3), + B(LdaConstant), U8(4), B(TestEqualStrict), R(7), U8(0), B(Mov), R(4), R(6), B(JumpIfToBooleanFalse), U8(7), B(CallRuntime), U16(Runtime::kThrowStaticPrototypeError), R(0), U8(0), - B(CreateClosure), U8(5), U8(2), + B(CreateClosure), U8(5), U8(4), U8(2), B(Star), R(8), - B(LdaSmi), U8(1), - B(Star), R(10), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(6), U8(5), + B(StaDataPropertyInLiteral), R(6), R(7), U8(3), U8(7), + B(CallRuntime), U16(Runtime::kInstallClassNameAccessorWithCheck), R(4), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), B(Star), R(0), B(Star), R(1), @@ -182,8 +172,8 @@ constant pool: [ ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["b"], SHARED_FUNCTION_INFO_TYPE, - ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"], SHARED_FUNCTION_INFO_TYPE, + ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"], SHARED_FUNCTION_INFO_TYPE, ] handlers: [ @@ -195,9 +185,9 @@ snippet: " class C { constructor() { count++; }} return new C(); " -frame size: 8 +frame size: 9 parameter count: 1 -bytecode array length: 61 +bytecode array length: 64 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(3), @@ -208,29 +198,90 @@ bytecodes: [ /* 46 E> */ B(StaCurrentContextSlot), U8(4), B(LdaTheHole), B(Star), R(0), - /* 49 S> */ B(LdaTheHole), + /* 49 S> */ B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(4), - B(CreateClosure), U8(0), U8(2), + B(LdaTheHole), B(Star), R(5), B(LdaSmi), U8(49), - B(Star), R(6), - B(LdaSmi), U8(86), B(Star), R(7), - B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), - B(Star), R(4), - B(LdaNamedProperty), R(4), U8(1), U8(2), + B(LdaSmi), U8(86), + B(Star), R(8), + B(Mov), R(4), R(6), + B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4), B(Star), R(5), + B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(4), U8(1), B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), B(Star), R(0), B(Star), R(1), B(Star), R(2), /* 87 S> */ B(Nop), - /* 94 E> */ B(New), R(2), R(0), U8(0), U8(4), + /* 94 E> */ B(New), R(2), R(0), U8(0), U8(3), /* 103 S> */ B(Return), ] constant pool: [ SHARED_FUNCTION_INFO_TYPE, - ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"], +] +handlers: [ +] + +--- +snippet: " + (class {}) + class E { static name () {}} +" +frame size: 10 +parameter count: 1 +bytecode array length: 102 +bytecodes: [ + B(LdaTheHole), + B(Star), R(3), + /* 30 E> */ B(StackCheck), + /* 35 S> */ B(CreateClosure), U8(0), U8(2), U8(2), + B(Star), R(4), + B(LdaTheHole), + B(Star), R(5), + B(LdaSmi), U8(35), + B(Star), R(7), + B(LdaSmi), U8(43), + B(Star), R(8), + B(Mov), R(4), R(6), + B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4), + B(Star), R(5), + B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), + B(Star), R(1), + B(LdaTheHole), + B(Star), R(0), + /* 45 S> */ B(CreateClosure), U8(1), U8(3), U8(2), + B(Star), R(4), + B(LdaTheHole), + B(Star), R(5), + B(LdaSmi), U8(45), + B(Star), R(7), + B(LdaSmi), U8(73), + B(Star), R(8), + B(Mov), R(4), R(6), + B(CallRuntime), U16(Runtime::kDefineClass), R(5), U8(4), + B(Star), R(5), + B(LdaConstant), U8(2), + B(Star), R(7), + B(CreateClosure), U8(3), U8(4), U8(2), + B(Star), R(8), + B(LdaSmi), U8(2), + B(Star), R(9), + B(Ldar), R(8), + B(StaDataPropertyInLiteral), R(6), R(7), U8(1), U8(5), + B(CallRuntime), U16(Runtime::kToFastProperties), R(4), U8(1), + B(Star), R(0), + B(Star), R(2), + B(Star), R(3), + B(LdaUndefined), + /* 74 S> */ B(Return), +] +constant pool: [ + SHARED_FUNCTION_INFO_TYPE, + SHARED_FUNCTION_INFO_TYPE, + ONE_BYTE_INTERNALIZED_STRING_TYPE ["name"], + SHARED_FUNCTION_INFO_TYPE, ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden index c5ecec9abf..273f3323eb 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CompoundExpressions.golden @@ -109,17 +109,17 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 24 +bytecode array length: 25 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), /* 42 E> */ B(StaCurrentContextSlot), U8(4), - /* 45 S> */ B(CreateClosure), U8(0), U8(2), + /* 45 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 75 S> */ B(LdaCurrentContextSlot), U8(4), B(Star), R(1), - B(BitwiseOrSmi), U8(24), R(1), U8(2), + B(BitwiseOrSmi), U8(24), R(1), U8(3), /* 77 E> */ B(StaCurrentContextSlot), U8(4), B(LdaUndefined), /* 84 S> */ B(Return), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden index 8ee13434af..8dc85b3326 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ConstVariableContextSlot.golden @@ -11,13 +11,13 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 19 +bytecode array length: 20 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 44 S> */ B(LdaSmi), U8(10), @@ -37,13 +37,13 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 20 +bytecode array length: 21 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 44 S> */ B(LdaSmi), U8(10), @@ -63,13 +63,13 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 39 +bytecode array length: 40 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 47 S> */ B(LdaSmi), U8(20), @@ -97,13 +97,13 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 26 +bytecode array length: 27 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 44 S> */ B(LdaSmi), U8(10), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden index 9a05916e14..63e48fd10a 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextParameters.golden @@ -13,14 +13,14 @@ snippet: " " frame size: 1 parameter count: 2 -bytecode array length: 13 +bytecode array length: 14 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), B(Ldar), R(arg0), B(StaCurrentContextSlot), U8(4), /* 10 E> */ B(StackCheck), - /* 19 S> */ B(CreateClosure), U8(0), U8(2), + /* 19 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 52 S> */ B(Return), ] constant pool: [ @@ -36,14 +36,14 @@ snippet: " " frame size: 2 parameter count: 2 -bytecode array length: 17 +bytecode array length: 18 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(Ldar), R(arg0), B(StaCurrentContextSlot), U8(4), /* 10 E> */ B(StackCheck), - /* 27 S> */ B(CreateClosure), U8(0), U8(2), + /* 27 S> */ B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 53 S> */ B(LdaCurrentContextSlot), U8(4), /* 66 S> */ B(Return), @@ -61,7 +61,7 @@ snippet: " " frame size: 1 parameter count: 5 -bytecode array length: 17 +bytecode array length: 18 bytecodes: [ B(CreateFunctionContext), U8(2), B(PushContext), R(0), @@ -70,7 +70,7 @@ bytecodes: [ B(Ldar), R(arg2), B(StaCurrentContextSlot), U8(4), /* 10 E> */ B(StackCheck), - /* 29 S> */ B(CreateClosure), U8(0), U8(2), + /* 29 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 61 S> */ B(Return), ] constant pool: [ @@ -86,14 +86,14 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 13 +bytecode array length: 14 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), /* 10 E> */ B(StackCheck), /* 26 S> */ B(Ldar), R(this), /* 26 E> */ B(StaCurrentContextSlot), U8(4), - /* 32 S> */ B(CreateClosure), U8(0), U8(2), + /* 32 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 65 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden index f4b7943740..b0df006a63 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden @@ -11,12 +11,12 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 9 +bytecode array length: 10 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), /* 30 E> */ B(StackCheck), - /* 41 S> */ B(CreateClosure), U8(0), U8(2), + /* 41 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 71 S> */ B(Return), ] constant pool: [ @@ -31,14 +31,14 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 13 +bytecode array length: 14 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), /* 42 E> */ B(StaCurrentContextSlot), U8(4), - /* 45 S> */ B(CreateClosure), U8(0), U8(2), + /* 45 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 75 S> */ B(Return), ] constant pool: [ @@ -53,7 +53,7 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 17 +bytecode array length: 18 bytecodes: [ B(CreateFunctionContext), U8(2), B(PushContext), R(0), @@ -62,7 +62,7 @@ bytecodes: [ /* 42 E> */ B(StaCurrentContextSlot), U8(4), /* 53 S> */ B(LdaSmi), U8(2), /* 53 E> */ B(StaCurrentContextSlot), U8(5), - /* 56 S> */ B(CreateClosure), U8(0), U8(2), + /* 56 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 92 S> */ B(Return), ] constant pool: [ @@ -77,14 +77,14 @@ snippet: " " frame size: 3 parameter count: 1 -bytecode array length: 21 +bytecode array length: 22 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), /* 30 E> */ B(StackCheck), /* 41 S> */ B(LdaUndefined), B(Star), R(2), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(4), U8(2), B(Star), R(1), /* 64 E> */ B(Call), R(1), R(2), U8(1), U8(2), /* 68 S> */ B(LdaCurrentContextSlot), U8(4), @@ -104,7 +104,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 31 +bytecode array length: 32 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), @@ -120,7 +120,7 @@ bytecodes: [ B(StaCurrentContextSlot), U8(4), /* 69 S> */ B(LdaSmi), U8(2), /* 69 E> */ B(StaCurrentContextSlot), U8(4), - /* 72 S> */ B(CreateClosure), U8(1), U8(2), + /* 72 S> */ B(CreateClosure), U8(1), U8(2), U8(2), B(PopContext), R(0), /* 104 S> */ B(Return), ] @@ -390,7 +390,7 @@ snippet: " " frame size: 3 parameter count: 1 -bytecode array length: 791 +bytecode array length: 792 bytecodes: [ B(CreateFunctionContext), U8(254), B(PushContext), R(0), @@ -903,7 +903,7 @@ bytecodes: [ /* 3435 E> */ B(StaCurrentContextSlot), U8(255), /* 3438 S> */ B(LdaUndefined), B(Star), R(2), - B(LdaGlobal), U8(4), + B(LdaGlobal), U8(0), U8(4), B(Star), R(1), /* 3438 E> */ B(Call), R(1), R(2), U8(1), U8(2), /* 3454 S> */ B(LdaSmi), U8(100), @@ -912,6 +912,7 @@ bytecodes: [ /* 3468 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["eval"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CountOperators.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CountOperators.golden index b17f3ecf20..61186cd887 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CountOperators.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CountOperators.golden @@ -201,17 +201,17 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 21 +bytecode array length: 22 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), /* 42 E> */ B(StaCurrentContextSlot), U8(4), - /* 53 S> */ B(CreateClosure), U8(0), U8(2), + /* 53 S> */ B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 78 S> */ B(LdaCurrentContextSlot), U8(4), - B(Inc), U8(2), + B(Inc), U8(3), /* 87 E> */ B(StaCurrentContextSlot), U8(4), /* 90 S> */ B(Return), ] @@ -227,19 +227,19 @@ snippet: " " frame size: 3 parameter count: 1 -bytecode array length: 27 +bytecode array length: 28 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), /* 42 E> */ B(StaCurrentContextSlot), U8(4), - /* 53 S> */ B(CreateClosure), U8(0), U8(2), + /* 53 S> */ B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 78 S> */ B(LdaCurrentContextSlot), U8(4), B(ToNumber), R(2), B(Ldar), R(2), - B(Dec), U8(2), + B(Dec), U8(3), /* 86 E> */ B(StaCurrentContextSlot), U8(4), B(Ldar), R(2), /* 90 S> */ B(Return), @@ -273,7 +273,7 @@ bytecodes: [ /* 84 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden index 851b953309..2abe2d8022 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/CreateRestParameter.golden @@ -95,7 +95,7 @@ bytecodes: [ B(Star), R(3), B(LdaZero), /* 59 E> */ B(LdaKeyedProperty), R(2), U8(4), - B(Add), R(3), U8(6), + /* 48 E> */ B(Add), R(3), U8(6), /* 64 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden index 00fa0180e6..91c3bb99d4 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden @@ -104,7 +104,7 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 31 +bytecode array length: 32 bytecodes: [ B(LdaConstant), U8(0), B(Star), R(1), @@ -115,14 +115,15 @@ bytecodes: [ /* 0 E> */ B(StackCheck), /* 16 S> */ B(LdaUndefined), B(Star), R(2), - B(LdaGlobal), U8(2), + B(LdaGlobal), U8(1), U8(2), B(Star), R(1), - /* 16 E> */ B(Call), R(1), R(2), U8(1), U8(4), + /* 16 E> */ B(Call), R(1), R(2), U8(1), U8(5), B(Star), R(0), /* 20 S> */ B(Return), ] constant pool: [ FIXED_ARRAY_TYPE, + ONE_BYTE_INTERNALIZED_STRING_TYPE ["f"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/Delete.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/Delete.golden index 12e421e883..e139fd65d1 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/Delete.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/Delete.golden @@ -98,7 +98,7 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 26 +bytecode array length: 27 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), @@ -106,7 +106,7 @@ bytecodes: [ /* 56 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(1), B(Ldar), R(1), /* 56 E> */ B(StaCurrentContextSlot), U8(4), - /* 64 S> */ B(CreateClosure), U8(1), U8(2), + /* 64 S> */ B(CreateClosure), U8(1), U8(2), U8(2), /* 93 S> */ B(LdaCurrentContextSlot), U8(4), B(Star), R(1), B(LdaSmi), U8(1), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForIn.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForIn.golden index c8cbc7a61d..e03f83d3fc 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForIn.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForIn.golden @@ -132,7 +132,7 @@ bytecodes: [ /* 80 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] @@ -188,7 +188,7 @@ bytecodes: [ ] constant pool: [ FIXED_ARRAY_TYPE, - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ] handlers: [ @@ -233,8 +233,8 @@ bytecodes: [ /* 98 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOf.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOf.golden index 96545a94d8..610b8b1a06 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOf.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ForOf.golden @@ -11,7 +11,7 @@ snippet: " " frame size: 15 parameter count: 1 -bytecode array length: 282 +bytecode array length: 272 bytecodes: [ /* 30 E> */ B(StackCheck), B(LdaZero), @@ -19,11 +19,12 @@ bytecodes: [ B(Mov), R(context), R(11), B(Mov), R(context), R(12), /* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(9), - B(Star), R(14), - B(LdaConstant), U8(1), - /* 48 E> */ B(LdaKeyedProperty), R(14), U8(4), B(Star), R(13), - /* 48 E> */ B(CallProperty), R(13), R(14), U8(1), U8(2), + B(LdaNamedProperty), R(13), U8(1), U8(2), + B(Star), R(14), + B(CallProperty), R(14), R(13), U8(1), U8(4), + B(JumpIfJSReceiver), U8(7), + B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0), B(Star), R(2), /* 45 S> */ B(LdaNamedProperty), R(2), U8(2), U8(8), B(Star), R(13), @@ -66,31 +67,28 @@ bytecodes: [ B(Star), R(10), B(LdaZero), B(Star), R(9), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(11), B(LdaZero), B(TestEqualStrict), R(4), U8(15), - B(JumpIfTrue), U8(122), - B(LdaUndefined), - B(TestEqualStrict), R(2), U8(16), - B(JumpIfTrue), U8(116), - B(LdaNamedProperty), R(2), U8(7), U8(17), + B(JumpIfTrue), U8(111), + B(LdaNamedProperty), R(2), U8(7), U8(16), B(Star), R(6), - B(LdaNull), - B(TestEqual), R(6), U8(19), + B(TestUndetectable), R(6), B(JumpIfFalse), U8(4), - B(Jump), U8(102), + B(Jump), U8(99), B(LdaSmi), U8(1), - B(TestEqualStrict), R(4), U8(20), - B(JumpIfFalse), U8(70), + B(TestEqualStrict), R(4), U8(19), + B(JumpIfFalse), U8(67), B(Ldar), R(6), B(TypeOf), B(Star), R(12), B(LdaConstant), U8(8), - B(TestEqualStrict), R(12), U8(21), + B(TestEqualStrict), R(12), U8(20), B(JumpIfFalse), U8(4), B(Jump), U8(18), - B(Wide), B(LdaSmi), U16(130), + B(Wide), B(LdaSmi), U16(129), B(Star), R(12), B(LdaConstant), U8(9), B(Star), R(13), @@ -100,12 +98,13 @@ bytecodes: [ B(Mov), R(6), R(13), B(Mov), R(2), R(14), B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2), - B(Jump), U8(23), + B(Jump), U8(20), B(Star), R(13), B(Ldar), R(closure), B(CreateCatchContext), R(13), U8(5), U8(10), B(Star), R(12), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(12), B(PushContext), R(8), B(PopContext), R(8), @@ -118,7 +117,8 @@ bytecodes: [ B(JumpIfToBooleanFalse), U8(4), B(Jump), U8(7), B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(7), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(11), U8(1), + B(Ldar), R(11), + B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(9), U8(0), B(JumpIfTrue), U8(4), @@ -129,7 +129,7 @@ bytecodes: [ /* 62 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, SYMBOL_TYPE, ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"], @@ -142,9 +142,9 @@ constant pool: [ FIXED_ARRAY_TYPE, ] handlers: [ - [7, 120, 126], - [10, 84, 86], - [204, 214, 216], + [7, 126, 132], + [10, 90, 92], + [199, 209, 211], ] --- @@ -154,7 +154,7 @@ snippet: " " frame size: 16 parameter count: 1 -bytecode array length: 293 +bytecode array length: 286 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaConstant), U8(0), @@ -163,10 +163,12 @@ bytecodes: [ B(Star), R(5), B(Mov), R(context), R(12), B(Mov), R(context), R(13), - /* 68 S> */ B(LdaConstant), U8(1), - /* 68 E> */ B(LdaKeyedProperty), R(0), U8(4), - B(Star), R(14), - /* 68 E> */ B(CallProperty), R(14), R(0), U8(1), U8(2), + /* 68 S> */ B(LdaNamedProperty), R(0), U8(1), U8(2), + B(Star), R(15), + B(CallProperty), R(15), R(0), U8(1), U8(4), + B(Mov), R(0), R(14), + B(JumpIfJSReceiver), U8(7), + B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0), B(Star), R(3), /* 65 S> */ B(LdaNamedProperty), R(3), U8(2), U8(8), B(Star), R(14), @@ -210,31 +212,28 @@ bytecodes: [ B(Star), R(11), B(LdaSmi), U8(1), B(Star), R(10), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(12), B(LdaZero), B(TestEqualStrict), R(5), U8(15), - B(JumpIfTrue), U8(122), - B(LdaUndefined), - B(TestEqualStrict), R(3), U8(16), - B(JumpIfTrue), U8(116), - B(LdaNamedProperty), R(3), U8(7), U8(17), + B(JumpIfTrue), U8(111), + B(LdaNamedProperty), R(3), U8(7), U8(16), B(Star), R(7), - B(LdaNull), - B(TestEqual), R(7), U8(19), + B(TestUndetectable), R(7), B(JumpIfFalse), U8(4), - B(Jump), U8(102), + B(Jump), U8(99), B(LdaSmi), U8(1), - B(TestEqualStrict), R(5), U8(20), - B(JumpIfFalse), U8(70), + B(TestEqualStrict), R(5), U8(19), + B(JumpIfFalse), U8(67), B(Ldar), R(7), B(TypeOf), B(Star), R(13), B(LdaConstant), U8(8), - B(TestEqualStrict), R(13), U8(21), + B(TestEqualStrict), R(13), U8(20), B(JumpIfFalse), U8(4), B(Jump), U8(18), - B(Wide), B(LdaSmi), U16(130), + B(Wide), B(LdaSmi), U16(129), B(Star), R(13), B(LdaConstant), U8(9), B(Star), R(14), @@ -244,12 +243,13 @@ bytecodes: [ B(Mov), R(7), R(14), B(Mov), R(3), R(15), B(InvokeIntrinsic), U8(Runtime::k_Call), R(14), U8(2), - B(Jump), U8(23), + B(Jump), U8(20), B(Star), R(14), B(Ldar), R(closure), B(CreateCatchContext), R(14), U8(5), U8(10), B(Star), R(13), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(13), B(PushContext), R(9), B(PopContext), R(9), @@ -262,7 +262,8 @@ bytecodes: [ B(JumpIfToBooleanFalse), U8(4), B(Jump), U8(7), B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(8), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(12), U8(1), + B(Ldar), R(12), + B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(10), U8(0), B(JumpIfTrue), U8(11), @@ -291,9 +292,9 @@ constant pool: [ FIXED_ARRAY_TYPE, ] handlers: [ - [11, 120, 126], - [14, 84, 86], - [205, 215, 217], + [11, 129, 135], + [14, 93, 95], + [203, 213, 215], ] --- @@ -305,7 +306,7 @@ snippet: " " frame size: 15 parameter count: 1 -bytecode array length: 300 +bytecode array length: 290 bytecodes: [ /* 30 E> */ B(StackCheck), B(LdaZero), @@ -313,11 +314,12 @@ bytecodes: [ B(Mov), R(context), R(11), B(Mov), R(context), R(12), /* 48 S> */ B(CreateArrayLiteral), U8(0), U8(0), U8(9), - B(Star), R(14), - B(LdaConstant), U8(1), - /* 48 E> */ B(LdaKeyedProperty), R(14), U8(4), B(Star), R(13), - /* 48 E> */ B(CallProperty), R(13), R(14), U8(1), U8(2), + B(LdaNamedProperty), R(13), U8(1), U8(2), + B(Star), R(14), + B(CallProperty), R(14), R(13), U8(1), U8(4), + B(JumpIfJSReceiver), U8(7), + B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0), B(Star), R(2), /* 45 S> */ B(LdaNamedProperty), R(2), U8(2), U8(8), B(Star), R(13), @@ -368,31 +370,28 @@ bytecodes: [ B(Star), R(10), B(LdaZero), B(Star), R(9), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(11), B(LdaZero), B(TestEqualStrict), R(4), U8(17), - B(JumpIfTrue), U8(122), - B(LdaUndefined), - B(TestEqualStrict), R(2), U8(18), - B(JumpIfTrue), U8(116), - B(LdaNamedProperty), R(2), U8(7), U8(19), + B(JumpIfTrue), U8(111), + B(LdaNamedProperty), R(2), U8(7), U8(18), B(Star), R(6), - B(LdaNull), - B(TestEqual), R(6), U8(21), + B(TestUndetectable), R(6), B(JumpIfFalse), U8(4), - B(Jump), U8(102), + B(Jump), U8(99), B(LdaSmi), U8(1), - B(TestEqualStrict), R(4), U8(22), - B(JumpIfFalse), U8(70), + B(TestEqualStrict), R(4), U8(21), + B(JumpIfFalse), U8(67), B(Ldar), R(6), B(TypeOf), B(Star), R(12), B(LdaConstant), U8(8), - B(TestEqualStrict), R(12), U8(23), + B(TestEqualStrict), R(12), U8(22), B(JumpIfFalse), U8(4), B(Jump), U8(18), - B(Wide), B(LdaSmi), U16(130), + B(Wide), B(LdaSmi), U16(129), B(Star), R(12), B(LdaConstant), U8(9), B(Star), R(13), @@ -402,12 +401,13 @@ bytecodes: [ B(Mov), R(6), R(13), B(Mov), R(2), R(14), B(InvokeIntrinsic), U8(Runtime::k_Call), R(13), U8(2), - B(Jump), U8(23), + B(Jump), U8(20), B(Star), R(13), B(Ldar), R(closure), B(CreateCatchContext), R(13), U8(5), U8(10), B(Star), R(12), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(12), B(PushContext), R(8), B(PopContext), R(8), @@ -420,7 +420,8 @@ bytecodes: [ B(JumpIfToBooleanFalse), U8(4), B(Jump), U8(7), B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(7), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(11), U8(1), + B(Ldar), R(11), + B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(9), U8(0), B(JumpIfTrue), U8(4), @@ -431,7 +432,7 @@ bytecodes: [ /* 113 S> */ B(Return), ] constant pool: [ - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, SYMBOL_TYPE, ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"], @@ -444,9 +445,9 @@ constant pool: [ FIXED_ARRAY_TYPE, ] handlers: [ - [7, 138, 144], - [10, 102, 104], - [222, 232, 234], + [7, 144, 150], + [10, 108, 110], + [217, 227, 229], ] --- @@ -456,7 +457,7 @@ snippet: " " frame size: 14 parameter count: 1 -bytecode array length: 307 +bytecode array length: 297 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(8), @@ -466,11 +467,12 @@ bytecodes: [ B(Mov), R(context), R(10), B(Mov), R(context), R(11), /* 77 S> */ B(CreateArrayLiteral), U8(1), U8(1), U8(9), - B(Star), R(13), - B(LdaConstant), U8(2), - /* 77 E> */ B(LdaKeyedProperty), R(13), U8(4), B(Star), R(12), - /* 77 E> */ B(CallProperty), R(12), R(13), U8(1), U8(2), + B(LdaNamedProperty), R(12), U8(2), U8(2), + B(Star), R(13), + B(CallProperty), R(13), R(12), U8(1), U8(4), + B(JumpIfJSReceiver), U8(7), + B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0), B(Star), R(1), /* 74 S> */ B(LdaNamedProperty), R(1), U8(3), U8(8), B(Star), R(12), @@ -516,31 +518,28 @@ bytecodes: [ B(Star), R(9), B(LdaSmi), U8(1), B(Star), R(8), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(10), B(LdaZero), B(TestEqualStrict), R(3), U8(19), - B(JumpIfTrue), U8(122), - B(LdaUndefined), - B(TestEqualStrict), R(1), U8(20), - B(JumpIfTrue), U8(116), - B(LdaNamedProperty), R(1), U8(9), U8(21), + B(JumpIfTrue), U8(111), + B(LdaNamedProperty), R(1), U8(9), U8(20), B(Star), R(5), - B(LdaNull), - B(TestEqual), R(5), U8(23), + B(TestUndetectable), R(5), B(JumpIfFalse), U8(4), - B(Jump), U8(102), + B(Jump), U8(99), B(LdaSmi), U8(1), - B(TestEqualStrict), R(3), U8(24), - B(JumpIfFalse), U8(70), + B(TestEqualStrict), R(3), U8(23), + B(JumpIfFalse), U8(67), B(Ldar), R(5), B(TypeOf), B(Star), R(11), B(LdaConstant), U8(10), - B(TestEqualStrict), R(11), U8(25), + B(TestEqualStrict), R(11), U8(24), B(JumpIfFalse), U8(4), B(Jump), U8(18), - B(Wide), B(LdaSmi), U16(130), + B(Wide), B(LdaSmi), U16(129), B(Star), R(11), B(LdaConstant), U8(11), B(Star), R(12), @@ -550,12 +549,13 @@ bytecodes: [ B(Mov), R(5), R(12), B(Mov), R(1), R(13), B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2), - B(Jump), U8(23), + B(Jump), U8(20), B(Star), R(12), B(Ldar), R(closure), B(CreateCatchContext), R(12), U8(7), U8(12), B(Star), R(11), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(11), B(PushContext), R(7), B(PopContext), R(7), @@ -568,7 +568,8 @@ bytecodes: [ B(JumpIfToBooleanFalse), U8(4), B(Jump), U8(7), B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(6), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(10), U8(1), + B(Ldar), R(10), + B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(8), U8(0), B(JumpIfTrue), U8(11), @@ -585,7 +586,7 @@ bytecodes: [ ] constant pool: [ FIXED_ARRAY_TYPE, - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, SYMBOL_TYPE, ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"], @@ -599,8 +600,8 @@ constant pool: [ FIXED_ARRAY_TYPE, ] handlers: [ - [15, 134, 140], - [18, 98, 100], - [219, 229, 231], + [15, 140, 146], + [18, 104, 106], + [214, 224, 226], ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden index 19aa219ac1..f897381d86 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden @@ -11,10 +11,10 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 5 +bytecode array length: 6 bytecodes: [ /* 30 E> */ B(StackCheck), - /* 34 S> */ B(CreateClosure), U8(0), U8(2), + /* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 55 S> */ B(Return), ] constant pool: [ @@ -29,12 +29,12 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 15 +bytecode array length: 16 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(LdaUndefined), B(Star), R(1), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(4), U8(2), B(Star), R(0), /* 56 E> */ B(Call), R(0), R(1), U8(1), U8(2), /* 59 S> */ B(Return), @@ -51,12 +51,12 @@ snippet: " " frame size: 3 parameter count: 1 -bytecode array length: 19 +bytecode array length: 20 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(LdaUndefined), B(Star), R(1), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(4), U8(2), B(Star), R(0), B(LdaSmi), U8(1), B(Star), R(2), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/GenerateTestUndetectable.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/GenerateTestUndetectable.golden new file mode 100644 index 0000000000..1ee3738f2e --- /dev/null +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/GenerateTestUndetectable.golden @@ -0,0 +1,239 @@ +# +# Autogenerated by generate-bytecode-expectations. +# + +--- +wrap: yes + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a == null) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestUndetectable), R(0), + B(JumpIfFalse), U8(6), + /* 88 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 97 S> */ B(Ldar), R(1), + /* 107 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a == undefined) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestUndetectable), R(0), + B(JumpIfFalse), U8(6), + /* 93 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 102 S> */ B(Ldar), R(1), + /* 112 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a != null) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestUndetectable), R(0), + B(JumpIfTrue), U8(6), + /* 88 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 97 S> */ B(Ldar), R(1), + /* 107 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a != undefined) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestUndetectable), R(0), + B(JumpIfTrue), U8(6), + /* 93 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 102 S> */ B(Ldar), R(1), + /* 112 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a === null) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestNull), R(0), + B(JumpIfFalse), U8(6), + /* 89 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 98 S> */ B(Ldar), R(1), + /* 108 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a === undefined) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestUndefined), R(0), + B(JumpIfFalse), U8(6), + /* 94 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 103 S> */ B(Ldar), R(1), + /* 113 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a !== null) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestNull), R(0), + B(JumpIfTrue), U8(6), + /* 89 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 98 S> */ B(Ldar), R(1), + /* 108 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + +--- +snippet: " + var obj_a = {val:1}; + var b = 10; + if (obj_a !== undefined) { b = 20;} + return b; +" +frame size: 3 +parameter count: 1 +bytecode array length: 24 +bytecodes: [ + /* 30 E> */ B(StackCheck), + /* 46 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(2), + B(Mov), R(2), R(0), + /* 63 S> */ B(LdaSmi), U8(10), + B(Star), R(1), + /* 67 S> */ B(TestUndefined), R(0), + B(JumpIfTrue), U8(6), + /* 94 S> */ B(LdaSmi), U8(20), + B(Star), R(1), + /* 103 S> */ B(Ldar), R(1), + /* 113 S> */ B(Return), +] +constant pool: [ + FIXED_ARRAY_TYPE, +] +handlers: [ +] + diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/Generators.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/Generators.golden index 7ca3be2345..a53f7f622f 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/Generators.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/Generators.golden @@ -11,20 +11,22 @@ snippet: " function* f() { } f(); " -frame size: 11 +frame size: 12 parameter count: 1 bytecode array length: 204 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(53), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(CreateFunctionContext), U8(2), @@ -32,78 +34,80 @@ bytecodes: [ B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 11 E> */ B(StackCheck), - B(Mov), R(context), R(4), + B(Mov), R(context), R(5), B(LdaCurrentContextSlot), U8(4), - B(Star), R(6), - B(Mov), R(closure), R(5), - /* 11 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2), + B(Star), R(7), + B(Mov), R(closure), R(6), + /* 11 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(6), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(5), - B(LdaCurrentContextSlot), U8(5), B(Star), R(6), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(7), B(LdaZero), - B(SuspendGenerator), R(6), - B(Ldar), R(5), + B(SuspendGenerator), R(7), + B(Ldar), R(6), /* 16 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1), - B(Star), R(7), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(7), U8(1), B(Star), R(8), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(7), U8(1), + B(Star), R(9), B(LdaZero), - B(TestEqualStrict), R(8), U8(0), - B(JumpIfTrue), U8(32), + B(TestEqualStrict), R(9), U8(0), + B(JumpIfTrue), U8(31), B(LdaSmi), U8(2), - B(TestEqualStrict), R(8), U8(0), - B(JumpIfTrue), U8(22), + B(TestEqualStrict), R(9), U8(0), + B(JumpIfTrue), U8(21), B(Jump), U8(2), B(LdaTrue), - B(Star), R(10), - B(Mov), R(7), R(9), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(9), U8(2), - B(Star), R(3), + B(Star), R(11), + B(Mov), R(8), R(10), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(10), U8(2), + B(Star), R(4), B(LdaZero), - B(Star), R(2), - B(Jump), U8(36), - B(Ldar), R(7), + B(Star), R(3), + B(Jump), U8(35), + B(Ldar), R(8), /* 11 E> */ B(Throw), B(LdaUndefined), - B(Star), R(5), - B(LdaTrue), B(Star), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(5), U8(2), - B(Star), R(3), + B(LdaTrue), + B(Star), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(4), B(LdaSmi), U8(1), - B(Star), R(2), + B(Star), R(3), B(Jump), U8(14), B(LdaSmi), U8(-1), - B(Star), R(2), - B(Jump), U8(8), B(Star), R(3), - B(LdaSmi), U8(2), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(Jump), U8(8), B(Star), R(4), - B(LdaCurrentContextSlot), U8(5), + B(LdaSmi), U8(2), + B(Star), R(3), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(5), - B(CallRuntime), U16(Runtime::k_GeneratorClose), R(5), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(6), + B(CallRuntime), U16(Runtime::k_GeneratorClose), R(6), U8(1), + B(Ldar), R(5), + B(SetPendingMessage), B(LdaZero), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(18), B(LdaSmi), U8(1), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(14), B(LdaSmi), U8(2), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(10), B(Jump), U8(11), - B(Ldar), R(3), + B(Ldar), R(4), /* 16 S> */ B(Return), - B(Ldar), R(3), + B(Ldar), R(4), /* 16 S> */ B(Return), - B(Ldar), R(3), + B(Ldar), R(4), B(ReThrow), B(LdaUndefined), /* 16 S> */ B(Return), @@ -111,7 +115,7 @@ bytecodes: [ constant pool: [ ] handlers: [ - [39, 138, 144], + [46, 143, 149], ] --- @@ -119,12 +123,14 @@ snippet: " function* f() { yield 42 } f(); " -frame size: 11 +frame size: 12 parameter count: 1 -bytecode array length: 301 +bytecode array length: 299 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(28), + B(JumpIfUndefined), U8(35), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), @@ -133,9 +139,9 @@ bytecodes: [ B(LdaSmi), U8(1), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrueConstant), U8(0), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(CreateFunctionContext), U8(2), @@ -143,127 +149,129 @@ bytecodes: [ B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 11 E> */ B(StackCheck), - B(Mov), R(context), R(4), + B(Mov), R(context), R(5), B(LdaCurrentContextSlot), U8(4), - B(Star), R(6), - B(Mov), R(closure), R(5), - /* 11 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(5), U8(2), + B(Star), R(7), + B(Mov), R(closure), R(6), + /* 11 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(6), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(5), - B(LdaCurrentContextSlot), U8(5), B(Star), R(6), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(7), B(LdaZero), - B(SuspendGenerator), R(6), - B(Ldar), R(5), + B(SuspendGenerator), R(7), + B(Ldar), R(6), /* 25 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1), - B(Star), R(7), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(7), U8(1), B(Star), R(8), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(7), U8(1), + B(Star), R(9), B(LdaZero), - B(TestEqualStrict), R(8), U8(0), - B(JumpIfTrue), U8(32), + B(TestEqualStrict), R(9), U8(0), + B(JumpIfTrue), U8(31), B(LdaSmi), U8(2), - B(TestEqualStrict), R(8), U8(0), - B(JumpIfTrue), U8(22), + B(TestEqualStrict), R(9), U8(0), + B(JumpIfTrue), U8(21), B(Jump), U8(2), B(LdaTrue), - B(Star), R(10), - B(Mov), R(7), R(9), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(9), U8(2), - B(Star), R(3), + B(Star), R(11), + B(Mov), R(8), R(10), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(10), U8(2), + B(Star), R(4), B(LdaZero), - B(Star), R(2), - B(Jump), U8(116), - B(Ldar), R(7), + B(Star), R(3), + B(Jump), U8(113), + B(Ldar), R(8), /* 11 E> */ B(Throw), /* 16 S> */ B(LdaSmi), U8(42), - B(Star), R(5), + B(Star), R(6), B(LdaFalse), + B(Star), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(6), U8(2), B(Star), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(5), U8(2), - B(Star), R(5), B(LdaCurrentContextSlot), U8(5), - B(Star), R(6), + B(Star), R(7), B(LdaSmi), U8(1), - B(SuspendGenerator), R(6), - B(Ldar), R(5), + B(SuspendGenerator), R(7), + B(Ldar), R(6), /* 25 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(6), U8(1), - B(Star), R(7), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(6), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(7), U8(1), B(Star), R(8), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(7), U8(1), + B(Star), R(9), B(LdaZero), - B(TestEqualStrict), R(8), U8(0), - B(JumpIfTrue), U8(33), + B(TestEqualStrict), R(9), U8(0), + B(JumpIfTrue), U8(32), B(LdaSmi), U8(2), - B(TestEqualStrict), R(8), U8(0), - B(JumpIfTrue), U8(23), + B(TestEqualStrict), R(9), U8(0), + B(JumpIfTrue), U8(22), B(Jump), U8(2), B(LdaTrue), - B(Star), R(10), - B(Mov), R(7), R(9), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(9), U8(2), - B(Star), R(3), + B(Star), R(11), + B(Mov), R(8), R(10), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(10), U8(2), + B(Star), R(4), B(LdaSmi), U8(1), - B(Star), R(2), - B(Jump), U8(36), - B(Ldar), R(7), + B(Star), R(3), + B(Jump), U8(35), + B(Ldar), R(8), /* 16 E> */ B(Throw), B(LdaUndefined), - B(Star), R(5), - B(LdaTrue), B(Star), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(5), U8(2), - B(Star), R(3), + B(LdaTrue), + B(Star), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(4), B(LdaSmi), U8(2), - B(Star), R(2), + B(Star), R(3), B(Jump), U8(14), B(LdaSmi), U8(-1), - B(Star), R(2), - B(Jump), U8(8), B(Star), R(3), - B(LdaSmi), U8(3), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(Jump), U8(8), B(Star), R(4), - B(LdaCurrentContextSlot), U8(5), + B(LdaSmi), U8(3), + B(Star), R(3), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(5), - B(CallRuntime), U16(Runtime::k_GeneratorClose), R(5), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(6), + B(CallRuntime), U16(Runtime::k_GeneratorClose), R(6), U8(1), + B(Ldar), R(5), + B(SetPendingMessage), B(LdaZero), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(25), B(LdaSmi), U8(1), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(21), B(LdaSmi), U8(2), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(17), B(LdaSmi), U8(3), - B(TestEqualStrict), R(2), U8(0), + B(TestEqualStrict), R(3), U8(0), B(JumpIfTrue), U8(13), B(Jump), U8(14), - B(Ldar), R(3), + B(Ldar), R(4), /* 25 S> */ B(Return), - B(Ldar), R(3), + B(Ldar), R(4), /* 25 S> */ B(Return), - B(Ldar), R(3), + B(Ldar), R(4), /* 25 S> */ B(Return), - B(Ldar), R(3), + B(Ldar), R(4), B(ReThrow), B(LdaUndefined), /* 25 S> */ B(Return), ] constant pool: [ - Smi [132], + Smi [130], ] handlers: [ - [46, 225, 231], + [53, 228, 234], ] --- @@ -271,12 +279,14 @@ snippet: " function* f() { for (let x of [42]) yield x } f(); " -frame size: 17 +frame size: 18 parameter count: 1 -bytecode array length: 796 +bytecode array length: 778 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(28), + B(JumpIfUndefined), U8(35), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(4), B(ResumeGenerator), R(new_target), B(Star), R(3), B(LdaZero), @@ -285,9 +295,9 @@ bytecodes: [ B(LdaSmi), U8(1), B(TestEqualStrict), R(3), U8(0), B(JumpIfTrueConstant), U8(3), - B(LdaSmi), U8(77), - B(Star), R(4), - B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1), + B(LdaSmi), U8(78), + B(Star), R(5), + B(CallRuntime), U16(Runtime::kAbort), R(5), U8(1), B(LdaSmi), U8(-2), B(Star), R(3), B(CreateFunctionContext), U8(9), @@ -295,41 +305,41 @@ bytecodes: [ B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 11 E> */ B(StackCheck), - B(Mov), R(context), R(6), + B(Mov), R(context), R(7), B(LdaCurrentContextSlot), U8(4), - B(Star), R(8), - B(Mov), R(closure), R(7), - /* 11 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(7), U8(2), + B(Star), R(9), + B(Mov), R(closure), R(8), + /* 11 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(8), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(7), - B(LdaCurrentContextSlot), U8(5), B(Star), R(8), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(9), B(LdaZero), - B(SuspendGenerator), R(8), - B(Ldar), R(7), + B(SuspendGenerator), R(9), + B(Ldar), R(8), /* 44 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(3), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(8), U8(1), - B(Star), R(9), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(8), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(9), U8(1), B(Star), R(10), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(9), U8(1), + B(Star), R(11), B(LdaZero), - B(TestEqualStrict), R(10), U8(0), - B(JumpIfTrue), U8(32), + B(TestEqualStrict), R(11), U8(0), + B(JumpIfTrue), U8(31), B(LdaSmi), U8(2), - B(TestEqualStrict), R(10), U8(0), - B(JumpIfTrue), U8(22), + B(TestEqualStrict), R(11), U8(0), + B(JumpIfTrue), U8(21), B(Jump), U8(2), B(LdaTrue), - B(Star), R(12), - B(Mov), R(9), R(11), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(11), U8(2), - B(Star), R(5), + B(Star), R(13), + B(Mov), R(10), R(12), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(12), U8(2), + B(Star), R(6), B(LdaZero), - B(Star), R(4), - B(JumpConstant), U8(19), - B(Ldar), R(9), + B(Star), R(5), + B(JumpConstant), U8(18), + B(Ldar), R(10), /* 11 E> */ B(Throw), B(Ldar), R(closure), B(CreateBlockContext), U8(0), @@ -338,14 +348,15 @@ bytecodes: [ B(StaCurrentContextSlot), U8(4), B(LdaZero), B(StaContextSlot), R(1), U8(9), U8(0), - B(Mov), R(context), R(9), B(Mov), R(context), R(10), + B(Mov), R(context), R(11), /* 30 S> */ B(CreateArrayLiteral), U8(1), U8(0), U8(9), B(Star), R(12), - B(LdaConstant), U8(2), - /* 30 E> */ B(LdaKeyedProperty), R(12), U8(4), - B(Star), R(11), - /* 30 E> */ B(CallProperty), R(11), R(12), U8(1), U8(2), + B(LdaNamedProperty), R(12), U8(2), U8(2), + B(Star), R(13), + B(CallProperty), R(13), R(12), U8(1), U8(4), + B(JumpIfJSReceiver), U8(7), + B(CallRuntime), U16(Runtime::kThrowSymbolIteratorInvalid), R(0), U8(0), /* 30 E> */ B(StaContextSlot), R(1), U8(7), U8(0), B(LdaSmi), U8(-2), B(TestEqual), R(3), U8(0), @@ -353,29 +364,29 @@ bytecodes: [ B(LdaSmi), U8(1), B(TestEqualStrict), R(3), U8(0), B(JumpIfTrueConstant), U8(8), - B(LdaSmi), U8(77), - B(Star), R(11), - B(CallRuntime), U16(Runtime::kAbort), R(11), U8(1), + B(LdaSmi), U8(78), + B(Star), R(12), + B(CallRuntime), U16(Runtime::kAbort), R(12), U8(1), /* 27 S> */ B(LdaContextSlot), R(1), U8(7), U8(0), + B(Star), R(13), + B(LdaNamedProperty), R(13), U8(4), U8(8), B(Star), R(12), - B(LdaNamedProperty), R(12), U8(4), U8(8), - B(Star), R(11), - /* 27 E> */ B(CallProperty), R(11), R(12), U8(1), U8(6), + /* 27 E> */ B(CallProperty), R(12), R(13), U8(1), U8(6), /* 27 E> */ B(StaContextSlot), R(1), U8(8), U8(0), - B(Star), R(11), - B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(11), U8(1), + B(Star), R(12), + B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(12), U8(1), B(ToBooleanLogicalNot), B(JumpIfFalse), U8(13), B(LdaContextSlot), R(1), U8(8), U8(0), - B(Star), R(11), - B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(11), U8(1), + B(Star), R(12), + B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(12), U8(1), B(LdaContextSlot), R(1), U8(8), U8(0), - B(Star), R(11), - B(LdaNamedProperty), R(11), U8(5), U8(10), + B(Star), R(12), + B(LdaNamedProperty), R(12), U8(5), U8(10), B(JumpIfToBooleanTrueConstant), U8(9), B(LdaContextSlot), R(1), U8(8), U8(0), - B(Star), R(11), - B(LdaNamedProperty), R(11), U8(6), U8(12), + B(Star), R(12), + B(LdaNamedProperty), R(12), U8(6), U8(12), B(StaContextSlot), R(1), U8(10), U8(0), B(LdaSmi), U8(2), B(StaContextSlot), R(1), U8(9), U8(0), @@ -390,240 +401,238 @@ bytecodes: [ B(LdaContextSlot), R(1), U8(6), U8(0), B(StaCurrentContextSlot), U8(4), /* 36 S> */ B(LdaCurrentContextSlot), U8(4), - B(Star), R(11), + B(Star), R(12), B(LdaFalse), + B(Star), R(13), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(12), U8(2), B(Star), R(12), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(11), U8(2), - B(Star), R(11), B(LdaContextSlot), R(1), U8(5), U8(0), - B(Star), R(12), + B(Star), R(13), B(LdaSmi), U8(1), - B(SuspendGenerator), R(12), - B(Ldar), R(11), + B(SuspendGenerator), R(13), + B(Ldar), R(12), /* 44 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(3), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(12), U8(1), - B(Star), R(13), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(12), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(13), U8(1), B(Star), R(14), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(13), U8(1), + B(Star), R(15), B(LdaZero), - B(TestEqualStrict), R(14), U8(0), - B(JumpIfTrue), U8(44), + B(TestEqualStrict), R(15), U8(0), + B(JumpIfTrue), U8(43), B(LdaSmi), U8(2), - B(TestEqualStrict), R(14), U8(0), - B(JumpIfTrue), U8(34), + B(TestEqualStrict), R(15), U8(0), + B(JumpIfTrue), U8(33), B(Jump), U8(2), B(LdaTrue), - B(Star), R(16), - B(Mov), R(13), R(15), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(15), U8(2), + B(Star), R(17), + B(Mov), R(14), R(16), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(16), U8(2), B(PopContext), R(2), B(PopContext), R(2), B(PopContext), R(2), B(PopContext), R(2), B(PopContext), R(2), B(PopContext), R(2), - B(Star), R(8), + B(Star), R(9), B(LdaZero), - B(Star), R(7), + B(Star), R(8), B(Jump), U8(74), - B(Ldar), R(13), + B(Ldar), R(14), /* 36 E> */ B(Throw), B(PopContext), R(2), B(LdaZero), B(StaContextSlot), R(1), U8(9), U8(0), - B(Wide), B(JumpLoop), U16(-221), U16(0), + B(Wide), B(JumpLoop), U16(-219), U16(0), B(Jump), U8(44), - B(Star), R(11), + B(Star), R(12), B(Ldar), R(closure), - B(CreateCatchContext), R(11), U8(10), U8(11), - B(Star), R(10), + B(CreateCatchContext), R(12), U8(10), U8(11), + B(Star), R(11), B(PushContext), R(2), B(LdaContextSlot), R(1), U8(9), U8(0), - B(Star), R(11), + B(Star), R(12), B(LdaSmi), U8(2), - B(TestEqualStrict), R(11), U8(14), + B(TestEqualStrict), R(12), U8(14), B(JumpIfFalse), U8(8), B(LdaSmi), U8(1), B(StaContextSlot), R(1), U8(9), U8(0), B(LdaCurrentContextSlot), U8(4), - B(Star), R(11), - B(CallRuntime), U16(Runtime::kReThrow), R(11), U8(1), + B(Star), R(12), + B(CallRuntime), U16(Runtime::kReThrow), R(12), U8(1), B(PopContext), R(2), B(LdaSmi), U8(-1), - B(Star), R(7), - B(Jump), U8(8), B(Star), R(8), - B(LdaSmi), U8(1), - B(Star), R(7), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(Jump), U8(8), B(Star), R(9), - B(LdaContextSlot), R(1), U8(9), U8(0), + B(LdaSmi), U8(1), + B(Star), R(8), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(10), + B(LdaContextSlot), R(1), U8(9), U8(0), + B(Star), R(11), B(LdaZero), - B(TestEqualStrict), R(10), U8(15), + B(TestEqualStrict), R(11), U8(15), B(JumpIfTrueConstant), U8(17), B(LdaContextSlot), R(1), U8(7), U8(0), - B(Star), R(10), - B(LdaUndefined), - B(TestEqualStrict), R(10), U8(16), - B(JumpIfTrueConstant), U8(18), - B(LdaContextSlot), R(1), U8(7), U8(0), - B(Star), R(10), - B(LdaNamedProperty), R(10), U8(12), U8(17), + B(Star), R(11), + B(LdaNamedProperty), R(11), U8(12), U8(16), B(StaContextSlot), R(1), U8(11), U8(0), B(LdaContextSlot), R(1), U8(11), U8(0), - B(Star), R(10), - B(LdaNull), - B(TestEqual), R(10), U8(19), + B(Star), R(11), + B(TestUndetectable), R(11), B(JumpIfFalse), U8(4), B(JumpConstant), U8(16), B(LdaContextSlot), R(1), U8(9), U8(0), - B(Star), R(10), + B(Star), R(11), B(LdaSmi), U8(1), - B(TestEqualStrict), R(10), U8(20), - B(JumpIfFalse), U8(78), + B(TestEqualStrict), R(11), U8(19), + B(JumpIfFalse), U8(75), B(LdaContextSlot), R(1), U8(11), U8(0), B(TypeOf), - B(Star), R(10), + B(Star), R(11), B(LdaConstant), U8(13), - B(TestEqualStrict), R(10), U8(21), + B(TestEqualStrict), R(11), U8(20), B(JumpIfFalse), U8(4), B(Jump), U8(18), - B(Wide), B(LdaSmi), U16(130), - B(Star), R(10), - B(LdaConstant), U8(14), + B(Wide), B(LdaSmi), U16(129), B(Star), R(11), - B(CallRuntime), U16(Runtime::kNewTypeError), R(10), U8(2), + B(LdaConstant), U8(14), + B(Star), R(12), + B(CallRuntime), U16(Runtime::kNewTypeError), R(11), U8(2), B(Throw), - B(Mov), R(context), R(10), + B(Mov), R(context), R(11), B(LdaContextSlot), R(1), U8(11), U8(0), - B(Star), R(11), + B(Star), R(12), B(LdaContextSlot), R(1), U8(7), U8(0), + B(Star), R(13), + B(InvokeIntrinsic), U8(Runtime::k_Call), R(12), U8(2), + B(Jump), U8(20), B(Star), R(12), - B(InvokeIntrinsic), U8(Runtime::k_Call), R(11), U8(2), - B(Jump), U8(23), - B(Star), R(11), B(Ldar), R(closure), - B(CreateCatchContext), R(11), U8(10), U8(15), - B(Star), R(10), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), - B(Ldar), R(10), + B(CreateCatchContext), R(12), U8(10), U8(15), + B(Star), R(11), + B(LdaTheHole), + B(SetPendingMessage), + B(Ldar), R(11), B(PushContext), R(2), B(PopContext), R(2), B(Jump), U8(47), B(LdaContextSlot), R(1), U8(11), U8(0), - B(Star), R(10), - B(LdaContextSlot), R(1), U8(7), U8(0), B(Star), R(11), - B(InvokeIntrinsic), U8(Runtime::k_Call), R(10), U8(2), + B(LdaContextSlot), R(1), U8(7), U8(0), + B(Star), R(12), + B(InvokeIntrinsic), U8(Runtime::k_Call), R(11), U8(2), B(StaContextSlot), R(1), U8(12), U8(0), B(LdaContextSlot), R(1), U8(12), U8(0), - B(Star), R(10), - B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(10), U8(1), + B(Star), R(11), + B(InvokeIntrinsic), U8(Runtime::k_IsJSReceiver), R(11), U8(1), B(JumpIfToBooleanFalse), U8(4), B(Jump), U8(13), B(LdaContextSlot), R(1), U8(12), U8(0), - B(Star), R(10), - B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(10), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(9), U8(1), + B(Star), R(11), + B(CallRuntime), U16(Runtime::kThrowIteratorResultNotAnObject), R(11), U8(1), + B(Ldar), R(10), + B(SetPendingMessage), B(LdaZero), - B(TestEqualStrict), R(7), U8(0), + B(TestEqualStrict), R(8), U8(0), B(JumpIfTrue), U8(11), B(LdaSmi), U8(1), - B(TestEqualStrict), R(7), U8(0), + B(TestEqualStrict), R(8), U8(0), B(JumpIfTrue), U8(17), B(Jump), U8(28), B(PopContext), R(1), B(PopContext), R(1), B(LdaSmi), U8(1), - B(Star), R(4), - B(Mov), R(8), R(5), - B(Jump), U8(48), + B(Star), R(5), + B(Mov), R(9), R(6), + B(Jump), U8(47), B(PopContext), R(1), B(PopContext), R(1), B(LdaSmi), U8(2), - B(Star), R(4), - B(Mov), R(8), R(5), - B(Jump), U8(35), + B(Star), R(5), + B(Mov), R(9), R(6), + B(Jump), U8(34), B(PopContext), R(1), B(LdaUndefined), - B(Star), R(7), - B(LdaTrue), B(Star), R(8), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(7), U8(2), - B(Star), R(5), + B(LdaTrue), + B(Star), R(9), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(8), U8(2), + B(Star), R(6), B(LdaSmi), U8(3), - B(Star), R(4), + B(Star), R(5), B(Jump), U8(14), B(LdaSmi), U8(-1), - B(Star), R(4), - B(Jump), U8(8), B(Star), R(5), - B(LdaSmi), U8(4), - B(Star), R(4), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(Jump), U8(8), B(Star), R(6), - B(LdaCurrentContextSlot), U8(5), + B(LdaSmi), U8(4), + B(Star), R(5), + B(LdaTheHole), + B(SetPendingMessage), B(Star), R(7), - B(CallRuntime), U16(Runtime::k_GeneratorClose), R(7), U8(1), - B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(6), U8(1), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(8), + B(CallRuntime), U16(Runtime::k_GeneratorClose), R(8), U8(1), + B(Ldar), R(7), + B(SetPendingMessage), B(LdaZero), - B(TestEqualStrict), R(4), U8(0), + B(TestEqualStrict), R(5), U8(0), B(JumpIfTrue), U8(32), B(LdaSmi), U8(1), - B(TestEqualStrict), R(4), U8(0), + B(TestEqualStrict), R(5), U8(0), B(JumpIfTrue), U8(28), B(LdaSmi), U8(2), - B(TestEqualStrict), R(4), U8(0), + B(TestEqualStrict), R(5), U8(0), B(JumpIfTrue), U8(24), B(LdaSmi), U8(3), - B(TestEqualStrict), R(4), U8(0), + B(TestEqualStrict), R(5), U8(0), B(JumpIfTrue), U8(20), B(LdaSmi), U8(4), - B(TestEqualStrict), R(4), U8(0), + B(TestEqualStrict), R(5), U8(0), B(JumpIfTrue), U8(16), B(Jump), U8(17), - B(Ldar), R(5), + B(Ldar), R(6), /* 44 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), /* 44 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), B(ReThrow), - B(Ldar), R(5), + B(Ldar), R(6), /* 44 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), B(ReThrow), B(LdaUndefined), /* 44 S> */ B(Return), ] constant pool: [ FIXED_ARRAY_TYPE, - FIXED_ARRAY_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, SYMBOL_TYPE, - Smi [149], + Smi [154], ONE_BYTE_INTERNALIZED_STRING_TYPE ["next"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["done"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["value"], FIXED_ARRAY_TYPE, - Smi [135], - Smi [152], + Smi [134], + Smi [150], ONE_BYTE_INTERNALIZED_STRING_TYPE [".catch"], FIXED_ARRAY_TYPE, ONE_BYTE_INTERNALIZED_STRING_TYPE ["return"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["function"], ONE_BYTE_INTERNALIZED_STRING_TYPE [""], FIXED_ARRAY_TYPE, - Smi [136], - Smi [176], - Smi [164], - Smi [601], + Smi [133], + Smi [159], + Smi [582], ] handlers: [ - [46, 710, 716], - [143, 438, 444], - [146, 394, 396], - [557, 573, 575], + [53, 697, 703], + [149, 448, 454], + [152, 404, 406], + [550, 566, 568], ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden index f8bece5c39..57403bc402 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCompoundExpressions.golden @@ -14,10 +14,10 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 13 +bytecode array length: 14 bytecodes: [ /* 26 E> */ B(StackCheck), - /* 31 S> */ B(LdaGlobal), U8(2), + /* 31 S> */ B(LdaGlobal), U8(0), U8(2), B(Star), R(0), B(BitwiseAndSmi), U8(1), R(0), U8(4), /* 45 E> */ B(StaGlobalSloppy), U8(0), U8(5), @@ -37,10 +37,10 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 13 +bytecode array length: 14 bytecodes: [ /* 27 E> */ B(StackCheck), - /* 32 S> */ B(LdaGlobal), U8(2), + /* 32 S> */ B(LdaGlobal), U8(0), U8(2), B(Star), R(0), B(AddSmi), U8(1), R(0), U8(4), /* 51 E> */ B(StaGlobalSloppy), U8(0), U8(5), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden index 1e0d530af5..a6090aadf0 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalCountOperators.golden @@ -14,10 +14,10 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 9 +bytecode array length: 10 bytecodes: [ /* 26 E> */ B(StackCheck), - /* 31 S> */ B(LdaGlobal), U8(2), + /* 31 S> */ B(LdaGlobal), U8(0), U8(2), B(Inc), U8(6), /* 40 E> */ B(StaGlobalSloppy), U8(0), U8(4), /* 48 S> */ B(Return), @@ -36,10 +36,10 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 15 +bytecode array length: 16 bytecodes: [ /* 26 E> */ B(StackCheck), - /* 31 S> */ B(LdaGlobal), U8(2), + /* 31 S> */ B(LdaGlobal), U8(0), U8(2), B(ToNumber), R(0), B(Ldar), R(0), B(Dec), U8(6), @@ -61,10 +61,10 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 9 +bytecode array length: 10 bytecodes: [ /* 27 E> */ B(StackCheck), - /* 46 S> */ B(LdaGlobal), U8(2), + /* 46 S> */ B(LdaGlobal), U8(0), U8(2), B(Dec), U8(6), /* 55 E> */ B(StaGlobalStrict), U8(0), U8(4), /* 68 S> */ B(Return), @@ -83,10 +83,10 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 15 +bytecode array length: 16 bytecodes: [ /* 27 E> */ B(StackCheck), - /* 32 S> */ B(LdaGlobal), U8(2), + /* 32 S> */ B(LdaGlobal), U8(0), U8(2), B(ToNumber), R(0), B(Ldar), R(0), B(Inc), U8(6), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden index e9540bb446..b717c71bea 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/GlobalDelete.golden @@ -16,16 +16,17 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 10 +bytecode array length: 11 bytecodes: [ /* 32 E> */ B(StackCheck), - /* 39 S> */ B(LdaGlobal), U8(2), + /* 39 S> */ B(LdaGlobal), U8(0), U8(2), B(Star), R(0), - B(LdaConstant), U8(0), + B(LdaConstant), U8(1), B(DeletePropertySloppy), R(0), /* 58 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ONE_BYTE_INTERNALIZED_STRING_TYPE ["x"], ] handlers: [ @@ -42,16 +43,17 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 10 +bytecode array length: 11 bytecodes: [ /* 28 E> */ B(StackCheck), - /* 51 S> */ B(LdaGlobal), U8(2), + /* 51 S> */ B(LdaGlobal), U8(0), U8(2), B(Star), R(0), B(LdaSmi), U8(1), B(DeletePropertyStrict), R(0), /* 71 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden index d45386e58b..c1c979c0ac 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/LetVariableContextSlot.golden @@ -11,13 +11,13 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 19 +bytecode array length: 20 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), @@ -37,13 +37,13 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 20 +bytecode array length: 21 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), @@ -63,13 +63,13 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 38 +bytecode array length: 39 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 45 S> */ B(LdaSmi), U8(20), @@ -98,13 +98,13 @@ snippet: " " frame size: 2 parameter count: 1 -bytecode array length: 23 +bytecode array length: 24 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(1), B(LdaTheHole), B(StaCurrentContextSlot), U8(4), - B(CreateClosure), U8(0), U8(2), + B(CreateClosure), U8(0), U8(2), U8(2), B(Star), R(0), /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden index 9c1c1b3701..addfa78a98 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/LoadGlobal.golden @@ -14,13 +14,14 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 4 +bytecode array length: 5 bytecodes: [ /* 21 E> */ B(StackCheck), - /* 26 S> */ B(LdaGlobal), U8(2), + /* 26 S> */ B(LdaGlobal), U8(0), U8(2), /* 36 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ] handlers: [ ] @@ -33,13 +34,14 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 4 +bytecode array length: 5 bytecodes: [ /* 27 E> */ B(StackCheck), - /* 32 S> */ B(LdaGlobal), U8(2), + /* 32 S> */ B(LdaGlobal), U8(0), U8(2), /* 42 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["t"], ] handlers: [ ] @@ -52,13 +54,14 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 4 +bytecode array length: 5 bytecodes: [ /* 17 E> */ B(StackCheck), - /* 22 S> */ B(LdaGlobal), U8(2), + /* 22 S> */ B(LdaGlobal), U8(0), U8(2), /* 32 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ] handlers: [ ] @@ -201,7 +204,7 @@ snippet: " " frame size: 0 parameter count: 2 -bytecode array length: 650 +bytecode array length: 652 bytecodes: [ /* 17 E> */ B(StackCheck), /* 25 S> */ B(Nop), @@ -460,11 +463,12 @@ bytecodes: [ /* 1286 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(254), /* 1295 S> */ B(Nop), /* 1296 E> */ B(Wide), B(LdaNamedProperty), R16(arg0), U16(0), U16(256), - /* 1305 S> */ B(Wide), B(LdaGlobal), U16(258), + /* 1305 S> */ B(Wide), B(LdaGlobal), U16(1), U16(258), /* 1315 S> */ B(Return), ] constant pool: [ ONE_BYTE_INTERNALIZED_STRING_TYPE ["name"], + ONE_BYTE_INTERNALIZED_STRING_TYPE ["a"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/Modules.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/Modules.golden index 7f13b4a3d5..db5b72c6ee 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/Modules.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/Modules.golden @@ -11,62 +11,64 @@ top level: yes snippet: " import \"bar\"; " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 125 +bytecode array length: 131 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(63), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 13 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 13 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), B(LdaUndefined), /* 13 S> */ B(Return), @@ -81,62 +83,64 @@ handlers: [ snippet: " import {foo} from \"bar\"; " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 125 +bytecode array length: 131 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(63), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 24 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 24 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), B(LdaUndefined), /* 24 S> */ B(Return), @@ -153,74 +157,76 @@ snippet: " goo(42); { let x; { goo(42) } }; " -frame size: 9 +frame size: 10 parameter count: 2 -bytecode array length: 195 +bytecode array length: 201 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(3), B(ResumeGenerator), R(new_target), B(Star), R(2), B(LdaZero), B(TestEqualStrict), R(2), U8(0), B(JumpIfTrue), U8(63), - B(LdaSmi), U8(77), - B(Star), R(3), - B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), + B(LdaSmi), U8(78), + B(Star), R(4), + B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1), B(LdaSmi), U8(-2), B(Star), R(2), B(LdaConstant), U8(0), - B(Star), R(5), - B(Mov), R(arg0), R(3), - B(Mov), R(closure), R(4), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), + B(Star), R(6), + B(Mov), R(arg0), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(4), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(4), - B(Mov), R(closure), R(3), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), + B(Star), R(5), + B(Mov), R(closure), R(4), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(4), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(3), - B(LdaCurrentContextSlot), U8(5), B(Star), R(4), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(5), B(LdaZero), - B(SuspendGenerator), R(4), - B(Ldar), R(3), + B(SuspendGenerator), R(5), + B(Ldar), R(4), /* 64 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(2), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), - B(Star), R(5), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(5), U8(1), B(Star), R(6), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1), + B(Star), R(7), B(LdaZero), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(8), - B(Mov), R(5), R(7), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(7), U8(2), + B(Star), R(9), + B(Mov), R(6), R(8), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(8), U8(2), /* 64 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), /* 0 E> */ B(Throw), /* 32 S> */ B(LdaUndefined), - B(Star), R(4), + B(Star), R(5), /* 32 E> */ B(LdaModuleVariable), U8(-1), U8(0), B(JumpIfNotHole), U8(11), B(LdaConstant), U8(1), - B(Star), R(5), - B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), - B(Star), R(3), + B(Star), R(6), + B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1), + B(Star), R(4), B(LdaSmi), U8(42), - B(Star), R(5), - /* 32 E> */ B(Call), R(3), R(4), U8(2), U8(2), + B(Star), R(6), + /* 32 E> */ B(Call), R(4), R(5), U8(2), U8(2), B(Ldar), R(closure), B(CreateBlockContext), U8(2), B(PushContext), R(1), @@ -229,16 +235,16 @@ bytecodes: [ /* 47 S> */ B(LdaUndefined), /* 47 E> */ B(StaCurrentContextSlot), U8(4), /* 52 S> */ B(LdaUndefined), - B(Star), R(4), + B(Star), R(5), /* 52 E> */ B(LdaModuleVariable), U8(-1), U8(1), B(JumpIfNotHole), U8(11), B(LdaConstant), U8(1), - B(Star), R(5), - B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), - B(Star), R(3), + B(Star), R(6), + B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1), + B(Star), R(4), B(LdaSmi), U8(42), - B(Star), R(5), - /* 52 E> */ B(Call), R(3), R(4), U8(2), U8(4), + B(Star), R(6), + /* 52 E> */ B(Call), R(4), R(5), U8(2), U8(4), B(PopContext), R(1), B(LdaUndefined), /* 64 S> */ B(Return), @@ -257,62 +263,64 @@ snippet: " foo++; { let x; { foo++ } }; " -frame size: 9 +frame size: 10 parameter count: 2 -bytecode array length: 160 +bytecode array length: 166 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(3), B(ResumeGenerator), R(new_target), B(Star), R(2), B(LdaZero), B(TestEqualStrict), R(2), U8(0), B(JumpIfTrue), U8(63), - B(LdaSmi), U8(77), - B(Star), R(3), - B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), + B(LdaSmi), U8(78), + B(Star), R(4), + B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1), B(LdaSmi), U8(-2), B(Star), R(2), B(LdaConstant), U8(0), - B(Star), R(5), - B(Mov), R(arg0), R(3), - B(Mov), R(closure), R(4), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), + B(Star), R(6), + B(Mov), R(arg0), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(4), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(4), - B(Mov), R(closure), R(3), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), + B(Star), R(5), + B(Mov), R(closure), R(4), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(4), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(3), - B(LdaCurrentContextSlot), U8(5), B(Star), R(4), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(5), B(LdaZero), - B(SuspendGenerator), R(4), - B(Ldar), R(3), + B(SuspendGenerator), R(5), + B(Ldar), R(4), /* 49 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(2), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), - B(Star), R(5), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(5), U8(1), B(Star), R(6), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1), + B(Star), R(7), B(LdaZero), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(8), - B(Mov), R(5), R(7), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(7), U8(2), + B(Star), R(9), + B(Mov), R(6), R(8), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(8), U8(2), /* 49 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), /* 0 E> */ B(Throw), /* 17 S> */ B(LdaSmi), U8(42), /* 17 E> */ B(StaModuleVariable), U8(1), U8(0), @@ -346,27 +354,29 @@ snippet: " foo++; { let x; { foo++ } }; " -frame size: 9 +frame size: 10 parameter count: 2 -bytecode array length: 164 +bytecode array length: 170 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(3), B(ResumeGenerator), R(new_target), B(Star), R(2), B(LdaZero), B(TestEqualStrict), R(2), U8(0), B(JumpIfTrue), U8(67), - B(LdaSmi), U8(77), - B(Star), R(3), - B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), + B(LdaSmi), U8(78), + B(Star), R(4), + B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1), B(LdaSmi), U8(-2), B(Star), R(2), B(LdaConstant), U8(0), - B(Star), R(5), - B(Mov), R(arg0), R(3), - B(Mov), R(closure), R(4), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), + B(Star), R(6), + B(Mov), R(arg0), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(4), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), @@ -374,36 +384,36 @@ bytecodes: [ B(StaModuleVariable), U8(1), U8(0), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(4), - B(Mov), R(closure), R(3), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), + B(Star), R(5), + B(Mov), R(closure), R(4), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(4), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(3), - B(LdaCurrentContextSlot), U8(5), B(Star), R(4), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(5), B(LdaZero), - B(SuspendGenerator), R(4), - B(Ldar), R(3), + B(SuspendGenerator), R(5), + B(Ldar), R(4), /* 49 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(2), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), - B(Star), R(5), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(5), U8(1), B(Star), R(6), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1), + B(Star), R(7), B(LdaZero), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(8), - B(Mov), R(5), R(7), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(7), U8(2), + B(Star), R(9), + B(Mov), R(6), R(8), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(8), U8(2), /* 49 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), /* 0 E> */ B(Throw), /* 17 S> */ B(LdaSmi), U8(42), /* 17 E> */ B(StaModuleVariable), U8(1), U8(0), @@ -437,27 +447,29 @@ snippet: " foo++; { let x; { foo++ } }; " -frame size: 9 +frame size: 10 parameter count: 2 -bytecode array length: 168 +bytecode array length: 174 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(3), B(ResumeGenerator), R(new_target), B(Star), R(2), B(LdaZero), B(TestEqualStrict), R(2), U8(0), B(JumpIfTrue), U8(67), - B(LdaSmi), U8(77), - B(Star), R(3), - B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), + B(LdaSmi), U8(78), + B(Star), R(4), + B(CallRuntime), U16(Runtime::kAbort), R(4), U8(1), B(LdaSmi), U8(-2), B(Star), R(2), B(LdaConstant), U8(0), - B(Star), R(5), - B(Mov), R(arg0), R(3), - B(Mov), R(closure), R(4), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), + B(Star), R(6), + B(Mov), R(arg0), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(4), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), @@ -465,36 +477,36 @@ bytecodes: [ B(StaModuleVariable), U8(1), U8(0), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(4), - B(Mov), R(closure), R(3), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), + B(Star), R(5), + B(Mov), R(closure), R(4), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(4), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(3), - B(LdaCurrentContextSlot), U8(5), B(Star), R(4), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(5), B(LdaZero), - B(SuspendGenerator), R(4), - B(Ldar), R(3), + B(SuspendGenerator), R(5), + B(Ldar), R(4), /* 51 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(2), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), - B(Star), R(5), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(5), U8(1), B(Star), R(6), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(5), U8(1), + B(Star), R(7), B(LdaZero), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(6), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(7), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(8), - B(Mov), R(5), R(7), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(7), U8(2), + B(Star), R(9), + B(Mov), R(6), R(8), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(8), U8(2), /* 51 S> */ B(Return), - B(Ldar), R(5), + B(Ldar), R(6), /* 0 E> */ B(Throw), /* 19 S> */ B(LdaSmi), U8(42), /* 19 E> */ B(StaModuleVariable), U8(1), U8(0), @@ -526,27 +538,29 @@ handlers: [ snippet: " export default (function () {}); " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 135 +bytecode array length: 142 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(67), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), @@ -554,38 +568,38 @@ bytecodes: [ B(StaModuleVariable), U8(1), U8(0), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 32 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 32 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), - B(CreateClosure), U8(1), U8(0), + B(CreateClosure), U8(1), U8(2), U8(0), B(StaModuleVariable), U8(1), U8(0), B(LdaUndefined), /* 32 S> */ B(Return), @@ -601,27 +615,29 @@ handlers: [ snippet: " export default (class {}); " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 170 +bytecode array length: 179 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(67), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), @@ -629,50 +645,50 @@ bytecodes: [ B(StaModuleVariable), U8(1), U8(0), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 26 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 26 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), - /* 16 S> */ B(LdaTheHole), - B(Star), R(2), - B(CreateClosure), U8(1), U8(0), + /* 16 S> */ B(CreateClosure), U8(1), U8(2), U8(0), B(Star), R(3), - B(LdaSmi), U8(16), + B(LdaTheHole), B(Star), R(4), + B(LdaSmi), U8(16), + B(Star), R(6), B(LdaSmi), U8(24), - B(Star), R(5), - B(CallRuntime), U16(Runtime::kDefineClass), R(2), U8(4), - B(Star), R(2), - B(LdaNamedProperty), R(2), U8(2), U8(2), - B(Star), R(3), - B(CallRuntime), U16(Runtime::kToFastProperties), R(2), U8(1), + B(Star), R(7), + B(Mov), R(3), R(5), + B(CallRuntime), U16(Runtime::kDefineClass), R(4), U8(4), + B(Star), R(4), + B(CallRuntime), U16(Runtime::kInstallClassNameAccessor), R(3), U8(1), + B(CallRuntime), U16(Runtime::kToFastProperties), R(3), U8(1), B(StaCurrentContextSlot), U8(6), B(LdaCurrentContextSlot), U8(6), /* 16 E> */ B(StaModuleVariable), U8(1), U8(0), @@ -682,7 +698,6 @@ bytecodes: [ constant pool: [ FIXED_ARRAY_TYPE, SHARED_FUNCTION_INFO_TYPE, - ONE_BYTE_INTERNALIZED_STRING_TYPE ["prototype"], ] handlers: [ ] @@ -691,62 +706,64 @@ handlers: [ snippet: " export {foo as goo} from \"bar\" " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 125 +bytecode array length: 131 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(63), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 30 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 30 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), B(LdaUndefined), /* 30 S> */ B(Return), @@ -761,62 +778,64 @@ handlers: [ snippet: " export * from \"bar\" " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 125 +bytecode array length: 131 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(63), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 19 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 19 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), B(LdaUndefined), /* 19 S> */ B(Return), @@ -832,78 +851,80 @@ snippet: " import * as foo from \"bar\" foo.f(foo, foo.x); " -frame size: 8 +frame size: 9 parameter count: 2 -bytecode array length: 164 +bytecode array length: 170 bytecodes: [ B(Ldar), R(new_target), - B(JumpIfUndefined), U8(21), + B(JumpIfUndefined), U8(28), + B(CallRuntime), U16(Runtime::k_GeneratorGetContext), R(new_target), U8(1), + B(PushContext), R(2), B(ResumeGenerator), R(new_target), B(Star), R(1), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(73), - B(LdaSmi), U8(77), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kAbort), R(2), U8(1), + B(LdaSmi), U8(78), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kAbort), R(3), U8(1), B(LdaSmi), U8(-2), B(Star), R(1), B(LdaConstant), U8(0), - B(Star), R(4), - B(Mov), R(arg0), R(2), - B(Mov), R(closure), R(3), - B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(3), + B(Star), R(5), + B(Mov), R(arg0), R(3), + B(Mov), R(closure), R(4), + B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(3), B(PushContext), R(0), B(Ldar), R(this), B(StaCurrentContextSlot), U8(4), B(LdaZero), - B(Star), R(2), - B(CallRuntime), U16(Runtime::kGetModuleNamespace), R(2), U8(1), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kGetModuleNamespace), R(3), U8(1), B(StaCurrentContextSlot), U8(6), /* 0 E> */ B(StackCheck), B(LdaCurrentContextSlot), U8(4), - B(Star), R(3), - B(Mov), R(closure), R(2), - /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(2), U8(2), + B(Star), R(4), + B(Mov), R(closure), R(3), + /* 0 E> */ B(CallRuntime), U16(Runtime::kCreateJSGeneratorObject), R(3), U8(2), B(StaCurrentContextSlot), U8(5), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(5), B(Star), R(3), + B(LdaCurrentContextSlot), U8(5), + B(Star), R(4), B(LdaZero), - B(SuspendGenerator), R(3), - B(Ldar), R(2), + B(SuspendGenerator), R(4), + B(Ldar), R(3), /* 45 S> */ B(Return), B(LdaSmi), U8(-2), B(Star), R(1), - B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(3), U8(1), - B(Star), R(4), - B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(3), U8(1), + B(CallRuntime), U16(Runtime::k_GeneratorGetInputOrDebugPos), R(4), U8(1), B(Star), R(5), + B(CallRuntime), U16(Runtime::k_GeneratorGetResumeMode), R(4), U8(1), + B(Star), R(6), B(LdaZero), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(26), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(25), B(LdaSmi), U8(2), - B(TestEqualStrict), R(5), U8(0), - B(JumpIfTrue), U8(16), + B(TestEqualStrict), R(6), U8(0), + B(JumpIfTrue), U8(15), B(Jump), U8(2), B(LdaTrue), - B(Star), R(7), - B(Mov), R(4), R(6), - B(CallRuntime), U16(Runtime::k_CreateIterResultObject), R(6), U8(2), + B(Star), R(8), + B(Mov), R(5), R(7), + B(InvokeIntrinsic), U8(Runtime::k_CreateIterResultObject), R(7), U8(2), /* 45 S> */ B(Return), - B(Ldar), R(4), + B(Ldar), R(5), /* 0 E> */ B(Throw), /* 27 S> */ B(LdaCurrentContextSlot), U8(6), - B(Star), R(3), - /* 30 E> */ B(LdaNamedProperty), R(3), U8(1), U8(4), - B(Star), R(2), - B(LdaCurrentContextSlot), U8(6), B(Star), R(4), + /* 30 E> */ B(LdaNamedProperty), R(4), U8(1), U8(4), + B(Star), R(3), B(LdaCurrentContextSlot), U8(6), B(Star), R(5), - /* 41 E> */ B(LdaNamedProperty), R(5), U8(2), U8(6), - B(Star), R(5), - /* 31 E> */ B(CallProperty), R(2), R(3), U8(3), U8(2), + B(LdaCurrentContextSlot), U8(6), + B(Star), R(6), + /* 41 E> */ B(LdaNamedProperty), R(6), U8(2), U8(6), + B(Star), R(6), + /* 31 E> */ B(CallProperty), R(3), R(4), U8(3), U8(2), B(LdaUndefined), /* 45 S> */ B(Return), ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden index 7f81d82a2d..75c6ff57be 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/ObjectLiterals.golden @@ -78,7 +78,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(1), B(Star), R(0), /* 45 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(1), - /* 67 E> */ B(AddSmi), U8(1), R(0), U8(2), + /* 69 E> */ B(AddSmi), U8(1), R(0), U8(2), B(StaNamedPropertySloppy), R(1), U8(1), U8(3), B(Ldar), R(1), /* 76 S> */ B(Return), @@ -96,12 +96,12 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 16 +bytecode array length: 17 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(0), - B(CreateClosure), U8(1), U8(2), - B(StaNamedPropertySloppy), R(0), U8(2), U8(2), + B(CreateClosure), U8(1), U8(2), U8(2), + B(StaNamedPropertySloppy), R(0), U8(2), U8(3), B(Ldar), R(0), /* 67 S> */ B(Return), ] @@ -119,12 +119,12 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 16 +bytecode array length: 17 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(0), - B(CreateClosure), U8(1), U8(2), - B(StaNamedPropertySloppy), R(0), U8(2), U8(2), + B(CreateClosure), U8(1), U8(2), U8(2), + B(StaNamedPropertySloppy), R(0), U8(2), U8(3), B(Ldar), R(0), /* 68 S> */ B(Return), ] @@ -142,13 +142,13 @@ snippet: " " frame size: 6 parameter count: 1 -bytecode array length: 32 +bytecode array length: 33 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(0), B(LdaConstant), U8(1), B(Star), R(2), - B(CreateClosure), U8(2), U8(2), + B(CreateClosure), U8(2), U8(2), U8(2), B(Star), R(3), B(LdaNull), B(Star), R(4), @@ -173,15 +173,15 @@ snippet: " " frame size: 6 parameter count: 1 -bytecode array length: 34 +bytecode array length: 36 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(0), B(LdaConstant), U8(1), B(Star), R(2), - B(CreateClosure), U8(2), U8(2), + B(CreateClosure), U8(2), U8(2), U8(2), B(Star), R(3), - B(CreateClosure), U8(3), U8(2), + B(CreateClosure), U8(3), U8(3), U8(2), B(Star), R(4), B(LdaZero), B(Star), R(5), @@ -205,7 +205,7 @@ snippet: " " frame size: 6 parameter count: 1 -bytecode array length: 32 +bytecode array length: 33 bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(CreateObjectLiteral), U8(0), U8(0), U8(1), R(0), @@ -213,7 +213,7 @@ bytecodes: [ B(Star), R(2), B(LdaNull), B(Star), R(3), - B(CreateClosure), U8(2), U8(2), + B(CreateClosure), U8(2), U8(2), U8(2), B(Star), R(4), B(LdaZero), B(Star), R(5), @@ -285,24 +285,19 @@ handlers: [ snippet: " var a = 'test'; return { [a]: 1 }; " -frame size: 7 +frame size: 4 parameter count: 1 -bytecode array length: 33 +bytecode array length: 24 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaConstant), U8(0), B(Star), R(0), /* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(1), - /* 60 E> */ B(ToName), R(3), + /* 60 E> */ B(ToName), R(2), B(LdaSmi), U8(1), - B(Star), R(4), - B(LdaZero), - B(Star), R(5), - B(LdaZero), - B(Star), R(6), - B(Mov), R(1), R(2), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5), - B(Ldar), R(2), + B(Star), R(3), + B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(2), + B(Ldar), R(1), /* 69 S> */ B(Return), ] constant pool: [ @@ -316,25 +311,20 @@ handlers: [ snippet: " var a = 'test'; return { val: a, [a]: 1 }; " -frame size: 7 +frame size: 4 parameter count: 1 -bytecode array length: 37 +bytecode array length: 28 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaConstant), U8(0), B(Star), R(0), /* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(1), R(1), /* 64 E> */ B(StaNamedPropertySloppy), R(1), U8(2), U8(2), - /* 68 E> */ B(ToName), R(3), + /* 68 E> */ B(ToName), R(2), B(LdaSmi), U8(1), - B(Star), R(4), - B(LdaZero), - B(Star), R(5), - B(LdaZero), - B(Star), R(6), - B(Mov), R(1), R(2), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5), - B(Ldar), R(2), + B(Star), R(3), + B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(4), + B(Ldar), R(1), /* 77 S> */ B(Return), ] constant pool: [ @@ -349,24 +339,20 @@ handlers: [ snippet: " var a = 'test'; return { [a]: 1, __proto__: {} }; " -frame size: 7 +frame size: 5 parameter count: 1 -bytecode array length: 46 +bytecode array length: 40 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaConstant), U8(0), B(Star), R(0), /* 50 S> */ B(CreateObjectLiteral), U8(1), U8(1), U8(35), R(1), - /* 60 E> */ B(ToName), R(3), + /* 60 E> */ B(ToName), R(2), B(LdaSmi), U8(1), - B(Star), R(4), - B(LdaZero), - B(Star), R(5), - B(LdaZero), - B(Star), R(6), - B(Mov), R(1), R(2), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5), + B(Star), R(3), + B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(2), B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(4), + B(Mov), R(1), R(2), B(Mov), R(4), R(3), B(CallRuntime), U16(Runtime::kInternalSetPrototype), R(2), U8(2), B(Ldar), R(2), @@ -383,33 +369,29 @@ handlers: [ snippet: " var n = 'name'; return { [n]: 'val', get a() { }, set a(b) {} }; " -frame size: 7 +frame size: 6 parameter count: 1 -bytecode array length: 67 +bytecode array length: 63 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaConstant), U8(0), B(Star), R(0), /* 50 S> */ B(CreateObjectLiteral), U8(1), U8(0), U8(35), R(1), - /* 60 E> */ B(ToName), R(3), + /* 60 E> */ B(ToName), R(2), B(LdaConstant), U8(2), - B(Star), R(4), - B(LdaZero), - B(Star), R(5), - B(LdaZero), - B(Star), R(6), - B(Mov), R(1), R(2), - B(CallRuntime), U16(Runtime::kDefineDataPropertyInLiteral), R(2), U8(5), + B(Star), R(3), + B(StaDataPropertyInLiteral), R(1), R(2), U8(0), U8(4), B(LdaConstant), U8(3), B(ToName), R(3), - B(CreateClosure), U8(4), U8(2), + B(CreateClosure), U8(4), U8(2), U8(2), B(Star), R(4), B(LdaZero), B(Star), R(5), + B(Mov), R(1), R(2), B(CallRuntime), U16(Runtime::kDefineGetterPropertyUnchecked), R(2), U8(4), B(LdaConstant), U8(3), B(ToName), R(3), - B(CreateClosure), U8(5), U8(2), + B(CreateClosure), U8(5), U8(3), U8(2), B(Star), R(4), B(LdaZero), B(Star), R(5), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden index 30b148b1d6..52ea01f910 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/OuterContextVariables.golden @@ -26,7 +26,7 @@ bytecodes: [ /* 102 S> */ B(LdaContextSlot), R(context), U8(4), U8(1), B(Star), R(0), B(LdaCurrentContextSlot), U8(4), - /* 120 E> */ B(Mul), R(0), U8(2), + /* 118 E> */ B(Mul), R(0), U8(2), /* 130 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden index adcf911cdd..90fb7b9dbb 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/PrimitiveExpressions.golden @@ -30,12 +30,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 9 +bytecode array length: 10 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), B(Star), R(0), - /* 45 S> */ B(AddSmi), U8(3), R(0), U8(2), + /* 45 S> */ B(LdaSmi), U8(3), + /* 54 E> */ B(Add), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -49,12 +50,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 9 +bytecode array length: 10 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), B(Star), R(0), - /* 45 S> */ B(SubSmi), U8(3), R(0), U8(2), + /* 45 S> */ B(LdaSmi), U8(3), + /* 54 E> */ B(Sub), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -74,7 +76,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(4), B(Star), R(0), /* 45 S> */ B(LdaSmi), U8(3), - B(Mul), R(0), U8(2), + /* 54 E> */ B(Mul), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -94,7 +96,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(4), B(Star), R(0), /* 45 S> */ B(LdaSmi), U8(3), - B(Div), R(0), U8(2), + /* 54 E> */ B(Div), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -114,7 +116,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(4), B(Star), R(0), /* 45 S> */ B(LdaSmi), U8(3), - B(Mod), R(0), U8(2), + /* 54 E> */ B(Mod), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -128,12 +130,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 10 +bytecode array length: 11 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), B(Star), R(0), - /* 45 S> */ B(BitwiseOrSmi), U8(2), R(0), U8(2), + /* 45 S> */ B(LdaSmi), U8(2), + /* 54 E> */ B(BitwiseOr), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -153,7 +156,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(1), B(Star), R(0), /* 45 S> */ B(LdaSmi), U8(2), - B(BitwiseXor), R(0), U8(2), + /* 54 E> */ B(BitwiseXor), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -167,12 +170,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 10 +bytecode array length: 11 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), B(Star), R(0), - /* 45 S> */ B(BitwiseAndSmi), U8(2), R(0), U8(2), + /* 45 S> */ B(LdaSmi), U8(2), + /* 54 E> */ B(BitwiseAnd), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -186,12 +190,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 10 +bytecode array length: 11 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), B(Star), R(0), - /* 46 S> */ B(ShiftLeftSmi), U8(3), R(0), U8(2), + /* 46 S> */ B(LdaSmi), U8(3), + /* 55 E> */ B(ShiftLeft), R(0), U8(2), /* 61 S> */ B(Return), ] constant pool: [ @@ -205,12 +210,13 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 10 +bytecode array length: 11 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(10), B(Star), R(0), - /* 46 S> */ B(ShiftRightSmi), U8(3), R(0), U8(2), + /* 46 S> */ B(LdaSmi), U8(3), + /* 55 E> */ B(ShiftRight), R(0), U8(2), /* 61 S> */ B(Return), ] constant pool: [ @@ -230,7 +236,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(10), B(Star), R(0), /* 46 S> */ B(LdaSmi), U8(3), - B(ShiftRightLogical), R(0), U8(2), + /* 55 E> */ B(ShiftRightLogical), R(0), U8(2), /* 62 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden index e401dbf88b..f0a51af8bd 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/PropertyCall.golden @@ -67,7 +67,7 @@ bytecodes: [ /* 27 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(4), B(Star), R(0), B(Ldar), R(arg1), - /* 37 E> */ B(Add), R(arg1), U8(6), + /* 35 E> */ B(Add), R(arg1), U8(6), B(Star), R(2), B(Mov), R(arg0), R(1), B(Mov), R(arg1), R(3), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden index de6e8935b3..1c806b7f46 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/RemoveRedundantLdar.golden @@ -23,7 +23,7 @@ bytecodes: [ B(Star), R(0), /* 48 E> */ B(StackCheck), /* 64 S> */ B(Ldar), R(0), - /* 78 E> */ B(Add), R(0), U8(2), + /* 76 E> */ B(Add), R(0), U8(2), B(Star), R(0), /* 86 S> */ B(LdaSmi), U8(10), /* 95 E> */ B(TestGreaterThan), R(0), U8(3), @@ -56,7 +56,7 @@ bytecodes: [ B(Star), R(0), /* 48 E> */ B(StackCheck), /* 55 S> */ B(Nop), - /* 69 E> */ B(Add), R(0), U8(2), + /* 67 E> */ B(Add), R(0), U8(2), B(Star), R(0), /* 77 S> */ B(LdaSmi), U8(10), /* 86 E> */ B(TestGreaterThan), R(0), U8(3), @@ -84,7 +84,7 @@ bytecodes: [ /* 45 S> */ B(LdaSmi), U8(1), B(Star), R(0), /* 50 S> */ B(Nop), - /* 64 E> */ B(Add), R(0), U8(2), + /* 62 E> */ B(Add), R(0), U8(2), B(Star), R(0), /* 72 S> */ B(Nop), /* 85 S> */ B(Return), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/SuperCallAndSpread.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/SuperCallAndSpread.golden new file mode 100644 index 0000000000..2dd9ec5383 --- /dev/null +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/SuperCallAndSpread.golden @@ -0,0 +1,155 @@ +# +# Autogenerated by generate-bytecode-expectations. +# + +--- +wrap: no +test function name: test + +--- +snippet: " + var test; + (function() { + class A { + constructor(...args) { this.baseArgs = args; } + } + class B extends A {} + test = new B(1, 2, 3).constructor; + })(); +" +frame size: 7 +parameter count: 1 +bytecode array length: 29 +bytecodes: [ + B(CreateRestParameter), + B(Star), R(2), + B(Mov), R(closure), R(1), + B(Mov), R(new_target), R(0), + B(Ldar), R(new_target), + /* 93 E> */ B(StackCheck), + /* 93 S> */ B(Ldar), R(1), + B(GetSuperConstructor), R(3), + B(Mov), R(3), R(4), + B(Mov), R(0), R(5), + B(Mov), R(2), R(6), + /* 93 E> */ B(NewWithSpread), R(4), U8(3), + /* 93 S> */ B(Return), +] +constant pool: [ +] +handlers: [ +] + +--- +snippet: " + var test; + (function() { + class A { + constructor(...args) { this.baseArgs = args; } + } + class B extends A { + constructor(...args) { super(1, ...args); } + } + test = new B(1, 2, 3).constructor; + })(); +" +frame size: 8 +parameter count: 1 +bytecode array length: 62 +bytecodes: [ + B(CreateRestParameter), + B(Star), R(2), + B(Mov), R(closure), R(1), + B(Mov), R(new_target), R(0), + B(Ldar), R(new_target), + /* 128 E> */ B(StackCheck), + /* 140 S> */ B(Ldar), R(1), + B(GetSuperConstructor), R(3), + B(LdaSmi), U8(1), + B(Star), R(6), + B(Mov), R(3), R(4), + B(Mov), R(0), R(5), + B(Mov), R(2), R(7), + /* 140 E> */ B(NewWithSpread), R(4), U8(4), + B(Star), R(3), + B(Ldar), R(this), + B(JumpIfNotHole), U8(4), + B(Jump), U8(7), + /* 140 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0), + B(Mov), R(3), R(this), + B(Ldar), R(this), + B(JumpIfNotHole), U8(11), + B(LdaConstant), U8(0), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), + /* 159 S> */ B(Return), +] +constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["this"], +] +handlers: [ +] + +--- +snippet: " + var test; + (function() { + class A { + constructor(...args) { this.baseArgs = args; } + } + class B extends A { + constructor(...args) { super(1, ...args, 1); } + } + test = new B(1, 2, 3).constructor; + })(); +" +frame size: 9 +parameter count: 1 +bytecode array length: 92 +bytecodes: [ + B(CreateRestParameter), + B(Star), R(2), + B(Mov), R(closure), R(1), + B(Mov), R(new_target), R(0), + B(Ldar), R(new_target), + /* 128 E> */ B(StackCheck), + /* 140 S> */ B(LdaUndefined), + B(Star), R(3), + /* 140 E> */ B(CallRuntime), U16(Runtime::k_GetSuperConstructor), R(1), U8(1), + B(Star), R(4), + B(LdaUndefined), + B(Star), R(5), + B(CreateArrayLiteral), U8(0), U8(0), U8(9), + B(Star), R(6), + B(LdaUndefined), + B(Star), R(7), + B(Mov), R(2), R(8), + /* 152 E> */ B(CallJSRuntime), U8(%spread_iterable), R(7), U8(2), + B(Star), R(7), + B(CreateArrayLiteral), U8(1), U8(1), U8(9), + B(Star), R(8), + B(CallJSRuntime), U8(%spread_arguments), R(5), U8(4), + B(Star), R(5), + B(Mov), R(0), R(6), + /* 140 E> */ B(CallJSRuntime), U8(%reflect_construct), R(3), U8(4), + B(Star), R(3), + B(Ldar), R(this), + B(JumpIfNotHole), U8(4), + B(Jump), U8(7), + /* 140 E> */ B(CallRuntime), U16(Runtime::kThrowSuperAlreadyCalledError), R(0), U8(0), + B(Mov), R(3), R(this), + B(Ldar), R(this), + B(JumpIfNotHole), U8(11), + B(LdaConstant), U8(2), + B(Star), R(3), + B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1), + /* 162 S> */ B(Return), +] +constant pool: [ + CONSTANT_ELEMENTS_PAIR_TYPE, + CONSTANT_ELEMENTS_PAIR_TYPE, + ONE_BYTE_INTERNALIZED_STRING_TYPE ["this"], +] +handlers: [ +] + diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/Switch.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/Switch.golden index 9334dbebfd..77bee13e14 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/Switch.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/Switch.golden @@ -493,7 +493,7 @@ bytecodes: [ B(TestEqualStrict), R(3), U8(6), B(JumpIfTrue), U8(34), B(Jump), U8(36), - /* 77 E> */ B(AddSmi), U8(1), R(0), U8(2), + /* 79 E> */ B(AddSmi), U8(1), R(0), U8(2), B(Star), R(1), /* 70 S> */ B(LdaSmi), U8(2), B(TestEqualStrict), R(1), U8(3), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden index d7b7917baf..1594422e49 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/TopLevelObjectLiterals.golden @@ -12,7 +12,7 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 42 +bytecode array length: 43 bytecodes: [ B(LdaConstant), U8(0), B(Star), R(1), @@ -26,8 +26,8 @@ bytecodes: [ B(LdaZero), B(CreateObjectLiteral), U8(2), U8(0), U8(1), R(3), B(Star), R(2), - B(CreateClosure), U8(3), U8(0), - B(StaNamedPropertySloppy), R(3), U8(4), U8(4), + B(CreateClosure), U8(3), U8(4), U8(0), + B(StaNamedPropertySloppy), R(3), U8(4), U8(5), B(CallRuntime), U16(Runtime::kInitializeVarGlobal), R(1), U8(3), B(LdaUndefined), /* 33 S> */ B(Return), diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/TryCatch.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/TryCatch.golden index c2f6113e71..b687ed24ca 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/TryCatch.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/TryCatch.golden @@ -11,18 +11,19 @@ snippet: " " frame size: 3 parameter count: 1 -bytecode array length: 35 +bytecode array length: 32 bytecodes: [ /* 30 E> */ B(StackCheck), B(Mov), R(context), R(1), /* 40 S> */ B(LdaSmi), U8(1), /* 75 S> */ B(Return), - B(Jump), U8(26), + B(Jump), U8(23), B(Star), R(2), B(Ldar), R(closure), B(CreateCatchContext), R(2), U8(0), U8(1), B(Star), R(1), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(1), B(PushContext), R(0), /* 63 S> */ B(LdaSmi), U8(2), @@ -47,30 +48,32 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 67 +bytecode array length: 61 bytecodes: [ /* 30 E> */ B(StackCheck), B(Mov), R(context), R(2), /* 47 S> */ B(LdaSmi), U8(1), B(Star), R(0), - B(Jump), U8(23), + B(Jump), U8(20), B(Star), R(3), B(Ldar), R(closure), /* 49 E> */ B(CreateCatchContext), R(3), U8(0), U8(1), B(Star), R(2), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(2), B(PushContext), R(1), B(PopContext), R(1), B(Mov), R(context), R(2), /* 75 S> */ B(LdaSmi), U8(2), B(Star), R(0), - B(Jump), U8(27), + B(Jump), U8(24), B(Star), R(3), B(Ldar), R(closure), /* 77 E> */ B(CreateCatchContext), R(3), U8(2), U8(3), B(Star), R(2), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(2), B(PushContext), R(1), /* 95 S> */ B(LdaSmi), U8(3), @@ -87,6 +90,6 @@ constant pool: [ ] handlers: [ [4, 8, 10], - [34, 38, 40], + [31, 35, 37], ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/TryFinally.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/TryFinally.golden index 61deb6e69c..b85ae8c51a 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/TryFinally.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/TryFinally.golden @@ -12,7 +12,7 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 52 +bytecode array length: 47 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), @@ -26,11 +26,13 @@ bytecodes: [ B(Star), R(2), B(LdaZero), B(Star), R(1), - /* 53 E> */ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + /* 53 E> */ B(SetPendingMessage), B(Star), R(3), /* 70 S> */ B(LdaSmi), U8(3), B(Star), R(0), - /* 72 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(3), U8(1), + B(Ldar), R(3), + /* 72 E> */ B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(1), U8(0), B(JumpIfTrue), U8(4), @@ -53,7 +55,7 @@ snippet: " " frame size: 7 parameter count: 1 -bytecode array length: 82 +bytecode array length: 74 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaSmi), U8(1), @@ -62,12 +64,13 @@ bytecodes: [ B(Mov), R(context), R(5), /* 51 S> */ B(LdaSmi), U8(2), B(Star), R(0), - B(Jump), U8(27), + B(Jump), U8(24), B(Star), R(6), B(Ldar), R(closure), /* 53 E> */ B(CreateCatchContext), R(6), U8(0), U8(1), B(Star), R(5), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(5), B(PushContext), R(1), /* 71 S> */ B(LdaSmi), U8(20), @@ -79,11 +82,13 @@ bytecodes: [ B(Star), R(3), B(LdaZero), B(Star), R(2), - /* 73 E> */ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + /* 73 E> */ B(SetPendingMessage), B(Star), R(4), /* 90 S> */ B(LdaSmi), U8(3), B(Star), R(0), - /* 92 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1), + B(Ldar), R(4), + /* 92 E> */ B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(2), U8(0), B(JumpIfTrue), U8(4), @@ -98,7 +103,7 @@ constant pool: [ FIXED_ARRAY_TYPE, ] handlers: [ - [8, 42, 48], + [8, 39, 45], [11, 15, 17], ] @@ -110,7 +115,7 @@ snippet: " " frame size: 8 parameter count: 1 -bytecode array length: 108 +bytecode array length: 97 bytecodes: [ /* 30 E> */ B(StackCheck), B(Mov), R(context), R(4), @@ -118,23 +123,25 @@ bytecodes: [ B(Mov), R(context), R(6), /* 55 S> */ B(LdaSmi), U8(1), B(Star), R(0), - B(Jump), U8(27), + B(Jump), U8(24), B(Star), R(7), B(Ldar), R(closure), /* 57 E> */ B(CreateCatchContext), R(7), U8(0), U8(1), B(Star), R(6), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(6), B(PushContext), R(1), /* 74 S> */ B(LdaSmi), U8(2), B(Star), R(0), B(PopContext), R(1), - B(Jump), U8(27), + B(Jump), U8(24), B(Star), R(6), B(Ldar), R(closure), /* 76 E> */ B(CreateCatchContext), R(6), U8(0), U8(2), B(Star), R(5), - B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + B(SetPendingMessage), B(Ldar), R(5), B(PushContext), R(1), /* 95 S> */ B(LdaSmi), U8(20), @@ -146,11 +153,13 @@ bytecodes: [ B(Star), R(3), B(LdaZero), B(Star), R(2), - /* 97 E> */ B(CallRuntime), U16(Runtime::kInterpreterClearPendingMessage), R(0), U8(0), + B(LdaTheHole), + /* 97 E> */ B(SetPendingMessage), B(Star), R(4), /* 114 S> */ B(LdaSmi), U8(3), B(Star), R(0), - /* 116 E> */ B(CallRuntime), U16(Runtime::kInterpreterSetPendingMessage), R(4), U8(1), + B(Ldar), R(4), + /* 116 E> */ B(SetPendingMessage), B(LdaZero), B(TestEqualStrict), R(2), U8(0), B(JumpIfTrue), U8(4), @@ -166,8 +175,8 @@ constant pool: [ FIXED_ARRAY_TYPE, ] handlers: [ - [4, 68, 74], - [7, 41, 43], + [4, 62, 68], + [7, 38, 40], [10, 14, 16], ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/Typeof.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/Typeof.golden index 5e15e5981e..d5ab090594 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/Typeof.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/Typeof.golden @@ -39,14 +39,15 @@ snippet: " " frame size: 0 parameter count: 1 -bytecode array length: 5 +bytecode array length: 6 bytecodes: [ /* 22 E> */ B(StackCheck), - /* 28 S> */ B(LdaGlobalInsideTypeof), U8(2), + /* 28 S> */ B(LdaGlobalInsideTypeof), U8(0), U8(2), B(TypeOf), /* 46 S> */ B(Return), ] constant pool: [ + ONE_BYTE_INTERNALIZED_STRING_TYPE ["x"], ] handlers: [ ] diff --git a/deps/v8/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden b/deps/v8/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden index 660a01b242..1620f93f5e 100644 --- a/deps/v8/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden +++ b/deps/v8/test/cctest/interpreter/bytecode_expectations/UnaryOperators.golden @@ -15,18 +15,19 @@ snippet: " " frame size: 1 parameter count: 1 -bytecode array length: 24 +bytecode array length: 25 bytecodes: [ /* 30 E> */ B(StackCheck), /* 42 S> */ B(LdaZero), B(Star), R(0), /* 54 S> */ B(LdaSmi), U8(10), /* 54 E> */ B(TestEqual), R(0), U8(2), - B(JumpIfTrue), U8(12), + B(JumpIfTrue), U8(13), /* 45 E> */ B(StackCheck), - /* 65 S> */ B(AddSmi), U8(10), R(0), U8(3), + /* 65 S> */ B(LdaSmi), U8(10), + /* 71 E> */ B(Add), R(0), U8(3), B(Star), R(0), - B(JumpLoop), U8(-14), U8(0), + B(JumpLoop), U8(-15), U8(0), /* 79 S> */ B(Ldar), R(0), /* 89 S> */ B(Return), ] @@ -79,7 +80,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(101), B(Star), R(0), /* 47 S> */ B(LdaSmi), U8(3), - B(Mul), R(0), U8(2), + /* 61 E> */ B(Mul), R(0), U8(2), B(LdaUndefined), /* 67 S> */ B(Return), ] @@ -102,9 +103,9 @@ bytecodes: [ /* 42 S> */ B(Wide), B(LdaSmi), U16(1234), B(Star), R(0), /* 56 S> */ B(Nop), - /* 66 E> */ B(Mul), R(0), U8(2), + /* 64 E> */ B(Mul), R(0), U8(2), B(Star), R(2), - B(SubSmi), U8(1), R(2), U8(3), + /* 68 E> */ B(SubSmi), U8(1), R(2), U8(3), B(LdaUndefined), B(Star), R(1), /* 74 S> */ B(Nop), @@ -128,7 +129,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(13), B(Star), R(0), /* 46 S> */ B(LdaSmi), U8(-1), - B(BitwiseXor), R(0), U8(2), + /* 53 E> */ B(BitwiseXor), R(0), U8(2), /* 57 S> */ B(Return), ] constant pool: [ @@ -149,7 +150,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(13), B(Star), R(0), /* 46 S> */ B(LdaSmi), U8(1), - B(Mul), R(0), U8(2), + /* 53 E> */ B(Mul), R(0), U8(2), /* 57 S> */ B(Return), ] constant pool: [ @@ -170,7 +171,7 @@ bytecodes: [ /* 42 S> */ B(LdaSmi), U8(13), B(Star), R(0), /* 46 S> */ B(LdaSmi), U8(-1), - B(Mul), R(0), U8(2), + /* 53 E> */ B(Mul), R(0), U8(2), /* 57 S> */ B(Return), ] constant pool: [ diff --git a/deps/v8/test/cctest/interpreter/interpreter-tester.cc b/deps/v8/test/cctest/interpreter/interpreter-tester.cc index df60c452cd..3896ff53ad 100644 --- a/deps/v8/test/cctest/interpreter/interpreter-tester.cc +++ b/deps/v8/test/cctest/interpreter/interpreter-tester.cc @@ -4,6 +4,8 @@ #include "test/cctest/interpreter/interpreter-tester.h" +#include "src/objects-inl.h" + namespace v8 { namespace internal { namespace interpreter { @@ -23,8 +25,6 @@ InterpreterTester::InterpreterTester( feedback_vector_(feedback_vector) { i::FLAG_ignition = true; i::FLAG_always_opt = false; - // Ensure handler table is generated. - isolate->interpreter()->Initialize(); } InterpreterTester::InterpreterTester( diff --git a/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc b/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc index 5a20d86297..b43384e946 100644 --- a/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc +++ b/deps/v8/test/cctest/interpreter/test-bytecode-generator.cc @@ -9,6 +9,7 @@ #include "src/interpreter/bytecode-array-iterator.h" #include "src/interpreter/bytecode-generator.h" #include "src/interpreter/interpreter.h" +#include "src/objects-inl.h" #include "test/cctest/cctest.h" #include "test/cctest/interpreter/bytecode-expectations-printer.h" #include "test/cctest/test-feedback-vector.h" @@ -74,7 +75,6 @@ class InitializedIgnitionHandleScope : public InitializedHandleScope { i::FLAG_ignition = true; i::FLAG_always_opt = false; i::FLAG_allow_natives_syntax = true; - CcTest::i_isolate()->interpreter()->Initialize(); } }; @@ -1746,6 +1746,54 @@ TEST(RemoveRedundantLdar) { LoadGolden("RemoveRedundantLdar.golden"))); } +TEST(GenerateTestUndetectable) { + InitializedIgnitionHandleScope scope; + BytecodeExpectationsPrinter printer(CcTest::isolate()); + const char* snippets[] = { + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a == null) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a == undefined) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a != null) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a != undefined) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a === null) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a === undefined) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a !== null) { b = 20;}\n" + "return b;\n", + + "var obj_a = {val:1};\n" + "var b = 10;\n" + "if (obj_a !== undefined) { b = 20;}\n" + "return b;\n"}; + + CHECK(CompareTexts(BuildActual(printer, snippets), + LoadGolden("GenerateTestUndetectable.golden"))); +} + TEST(AssignmentsInBinaryExpression) { InitializedIgnitionHandleScope scope; BytecodeExpectationsPrinter printer(CcTest::isolate()); @@ -2121,6 +2169,9 @@ TEST(ClassDeclarations) { "var count = 0;\n" "class C { constructor() { count++; }}\n" "return new C();\n", + + "(class {})\n" + "class E { static name () {}}\n", }; CHECK(CompareTexts(BuildActual(printer, snippets), @@ -2250,6 +2301,48 @@ TEST(Modules) { LoadGolden("Modules.golden"))); } +TEST(SuperCallAndSpread) { + InitializedIgnitionHandleScope scope; + BytecodeExpectationsPrinter printer(CcTest::isolate()); + printer.set_wrap(false); + printer.set_test_function_name("test"); + const char* snippets[] = { + "var test;\n" + "(function() {\n" + " class A {\n" + " constructor(...args) { this.baseArgs = args; }\n" + " }\n" + " class B extends A {}\n" + " test = new B(1, 2, 3).constructor;\n" + "})();\n", + + "var test;\n" + "(function() {\n" + " class A {\n" + " constructor(...args) { this.baseArgs = args; }\n" + " }\n" + " class B extends A {\n" + " constructor(...args) { super(1, ...args); }\n" + " }\n" + " test = new B(1, 2, 3).constructor;\n" + "})();\n", + + "var test;\n" + "(function() {\n" + " class A {\n" + " constructor(...args) { this.baseArgs = args; }\n" + " }\n" + " class B extends A {\n" + " constructor(...args) { super(1, ...args, 1); }\n" + " }\n" + " test = new B(1, 2, 3).constructor;\n" + "})();\n", + }; + + CHECK(CompareTexts(BuildActual(printer, snippets), + LoadGolden("SuperCallAndSpread.golden"))); +} + } // namespace interpreter } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/interpreter/test-interpreter-intrinsics.cc b/deps/v8/test/cctest/interpreter/test-interpreter-intrinsics.cc index 3cb2beffd4..70051253cc 100644 --- a/deps/v8/test/cctest/interpreter/test-interpreter-intrinsics.cc +++ b/deps/v8/test/cctest/interpreter/test-interpreter-intrinsics.cc @@ -114,27 +114,6 @@ TEST(IsJSProxy) { *helper.Invoke(helper.NewObject("new Proxy({},{})"))); } -TEST(IsRegExp) { - HandleAndZoneScope handles; - - InvokeIntrinsicHelper helper(handles.main_isolate(), handles.main_zone(), - Runtime::kInlineIsRegExp); - Factory* factory = handles.main_isolate()->factory(); - - CHECK_EQ(*factory->false_value(), - *helper.Invoke(helper.NewObject("new Date()"))); - CHECK_EQ(*factory->false_value(), - *helper.Invoke(helper.NewObject("(function() {})"))); - CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("([1])"))); - CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("({})"))); - CHECK_EQ(*factory->true_value(), *helper.Invoke(helper.NewObject("(/x/)"))); - CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Undefined())); - CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.Null())); - CHECK_EQ(*factory->false_value(), - *helper.Invoke(helper.NewObject("'string'"))); - CHECK_EQ(*factory->false_value(), *helper.Invoke(helper.NewObject("42"))); -} - TEST(IsTypedArray) { HandleAndZoneScope handles; diff --git a/deps/v8/test/cctest/interpreter/test-interpreter.cc b/deps/v8/test/cctest/interpreter/test-interpreter.cc index f3f4021f88..ad2577aeab 100644 --- a/deps/v8/test/cctest/interpreter/test-interpreter.cc +++ b/deps/v8/test/cctest/interpreter/test-interpreter.cc @@ -12,6 +12,8 @@ #include "src/interpreter/bytecode-array-iterator.h" #include "src/interpreter/bytecode-label.h" #include "src/interpreter/interpreter.h" +#include "src/objects-inl.h" +#include "src/unicode-cache.h" #include "test/cctest/cctest.h" #include "test/cctest/interpreter/interpreter-tester.h" #include "test/cctest/test-feedback-vector.h" @@ -555,6 +557,10 @@ TEST(InterpreterBinaryOpTypeFeedback) { isolate->factory()->NewHeapNumber(1.4142), isolate->factory()->NewHeapNumber(3.1415 + 1.4142), BinaryOperationFeedback::kNumber}, + {Token::Value::ADD, isolate->factory()->NewStringFromAsciiChecked("foo"), + isolate->factory()->NewStringFromAsciiChecked("bar"), + isolate->factory()->NewStringFromAsciiChecked("foobar"), + BinaryOperationFeedback::kString}, {Token::Value::ADD, Handle<Smi>(Smi::FromInt(2), isolate), isolate->factory()->NewStringFromAsciiChecked("2"), isolate->factory()->NewStringFromAsciiChecked("22"), @@ -1794,9 +1800,9 @@ TEST(InterpreterStringComparisons) { BytecodeArrayBuilder builder(isolate, handles.main_zone(), 0, 0, 1); Register r0(0); - builder.LoadLiteral(factory->NewStringFromAsciiChecked(lhs)) + builder.LoadLiteral(factory->InternalizeUtf8String(lhs)) .StoreAccumulatorInRegister(r0) - .LoadLiteral(factory->NewStringFromAsciiChecked(rhs)) + .LoadLiteral(factory->InternalizeUtf8String(rhs)) .CompareOperation(comparison, r0, vector->GetIndex(slot)) .Return(); @@ -1809,8 +1815,11 @@ TEST(InterpreterStringComparisons) { CompareC(comparison, inputs[i], inputs[j])); Object* feedback = vector->Get(slot); CHECK(feedback->IsSmi()); - CHECK_EQ(CompareOperationFeedback::kAny, - static_cast<Smi*>(feedback)->value()); + int const expected_feedback = + Token::IsOrderedRelationalCompareOp(comparison) + ? CompareOperationFeedback::kString + : CompareOperationFeedback::kInternalizedString; + CHECK_EQ(expected_feedback, static_cast<Smi*>(feedback)->value()); } } } @@ -1822,7 +1831,7 @@ TEST(InterpreterMixedComparisons) { // convertible to a HeapNumber so comparison will be between numeric // values except for the strict comparisons where no conversion is // performed. - const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e5", "2.01"}; + const char* inputs[] = {"-1.77", "-40.333", "0.01", "55.77e50", "2.01"}; UnicodeCache unicode_cache; @@ -1875,8 +1884,10 @@ TEST(InterpreterMixedComparisons) { CompareC(comparison, lhs, rhs, true)); Object* feedback = vector->Get(slot); CHECK(feedback->IsSmi()); - CHECK_EQ(CompareOperationFeedback::kAny, - static_cast<Smi*>(feedback)->value()); + // kNumber | kString gets converted to CompareOperationHint::kAny. + int expected_feedback = CompareOperationFeedback::kNumber | + CompareOperationFeedback::kString; + CHECK_EQ(expected_feedback, static_cast<Smi*>(feedback)->value()); } } } diff --git a/deps/v8/test/cctest/interpreter/test-source-positions.cc b/deps/v8/test/cctest/interpreter/test-source-positions.cc index 2b7f5c368a..22fd4991ac 100644 --- a/deps/v8/test/cctest/interpreter/test-source-positions.cc +++ b/deps/v8/test/cctest/interpreter/test-source-positions.cc @@ -9,6 +9,7 @@ #include "src/interpreter/bytecode-generator.h" #include "src/interpreter/interpreter.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "test/cctest/cctest.h" #include "test/cctest/interpreter/source-position-matcher.h" @@ -226,9 +227,6 @@ bool OptimizedBytecodeSourcePositionTester::SourcePositionsMatch( void TestSourcePositionsEquivalent(int optimization_bitmap) { HandleAndZoneScope handles; - // Ensure handler table is generated. - handles.main_isolate()->interpreter()->Initialize(); - OptimizedBytecodeSourcePositionTester tester(handles.main_isolate()); for (auto test_case_data : kTestCaseData) { CHECK(tester.SourcePositionsMatch( diff --git a/deps/v8/test/cctest/libplatform/test-tracing.cc b/deps/v8/test/cctest/libplatform/test-tracing.cc index 6189ed2dfc..5dc6b965f1 100644 --- a/deps/v8/test/cctest/libplatform/test-tracing.cc +++ b/deps/v8/test/cctest/libplatform/test-tracing.cc @@ -25,6 +25,14 @@ TEST(TestTraceConfig) { CHECK_EQ(trace_config->IsCategoryGroupEnabled( TRACE_DISABLED_BY_DEFAULT("v8.runtime")), true); + CHECK_EQ(trace_config->IsCategoryGroupEnabled("v8,v8.cpu_profile"), true); + CHECK_EQ( + trace_config->IsCategoryGroupEnabled("v8,disabled-by-default-v8.runtime"), + true); + CHECK_EQ(trace_config->IsCategoryGroupEnabled( + "v8_cpu_profile,v8.cpu_profile.hires"), + false); + delete trace_config; } diff --git a/deps/v8/test/cctest/parsing/test-parse-decision.cc b/deps/v8/test/cctest/parsing/test-parse-decision.cc new file mode 100644 index 0000000000..f91bd57739 --- /dev/null +++ b/deps/v8/test/cctest/parsing/test-parse-decision.cc @@ -0,0 +1,107 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Test specific cases of the lazy/eager-parse decision. +// +// Note that presently most unit tests for parsing are found in +// cctest/test-parsing.cc. + +#include <unordered_map> + +#include "include/v8.h" +#include "src/api.h" +#include "src/handles-inl.h" +#include "src/isolate.h" +#include "src/objects-inl.h" +#include "src/utils.h" + +#include "test/cctest/cctest.h" + +using namespace v8::internal; + +namespace { + +// Record the 'compiled' state of all top level functions. +void GetTopLevelFunctionInfo( + v8::Local<v8::Script> script, + std::unordered_map<std::string, bool>* is_compiled) { + // Get the v8::internal::Script object from the API v8::Script. + // The API object 'wraps' the compiled top-level function, not the i::Script. + Handle<JSFunction> toplevel_fn = v8::Utils::OpenHandle(*script); + Handle<Script> i_script = + handle(Script::cast(toplevel_fn->shared()->script())); + SharedFunctionInfo::ScriptIterator iterator(i_script); + + while (SharedFunctionInfo* shared = iterator.Next()) { + std::unique_ptr<char[]> name = String::cast(shared->name())->ToCString(); + is_compiled->insert(std::make_pair(name.get(), shared->is_compiled())); + } +} + +} // anonymous namespace + +TEST(GetTopLevelFunctionInfo) { + if (!FLAG_lazy) return; + + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + LocalContext env; + + const char src[] = "function foo() { var a; }\n"; + std::unordered_map<std::string, bool> is_compiled; + GetTopLevelFunctionInfo(v8_compile(src), &is_compiled); + + // Test that our helper function GetTopLevelFunctionInfo does what it claims: + DCHECK(is_compiled.find("foo") != is_compiled.end()); + DCHECK(is_compiled.find("bar") == is_compiled.end()); +} + +TEST(EagerlyCompileImmediateUseFunctions) { + if (!FLAG_lazy) return; + + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + LocalContext env; + + // Test parenthesized, exclaimed, and regular functions. Make sure these + // occur both intermixed and after each other, to make sure the 'reset' + // mechanism works. + const char src[] = + "function normal() { var a; }\n" // Normal: Should lazy parse. + "(function parenthesized() { var b; })()\n" // Parenthesized: Pre-parse. + "!function exclaimed() { var c; }() \n" // Exclaimed: Pre-parse. + "function normal2() { var d; }\n" + "(function parenthesized2() { var e; })()\n" + "function normal3() { var f; }\n" + "!function exclaimed2() { var g; }() \n" + "function normal4() { var h; }\n"; + + std::unordered_map<std::string, bool> is_compiled; + GetTopLevelFunctionInfo(v8_compile(src), &is_compiled); + + DCHECK(is_compiled["parenthesized"]); + DCHECK(is_compiled["parenthesized2"]); + DCHECK(is_compiled["exclaimed"]); + DCHECK(is_compiled["exclaimed2"]); + DCHECK(!is_compiled["normal"]); + DCHECK(!is_compiled["normal2"]); + DCHECK(!is_compiled["normal3"]); + DCHECK(!is_compiled["normal4"]); +} + +TEST(CommaFunctionSequence) { + if (!FLAG_lazy) return; + + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + LocalContext env; + + const char src[] = "!function a(){}(),function b(){}(),function c(){}();"; + std::unordered_map<std::string, bool> is_compiled; + GetTopLevelFunctionInfo(v8_compile(src), &is_compiled); + + DCHECK(is_compiled["a"]); + DCHECK(is_compiled["b"]); + DCHECK(is_compiled["c"]); +} diff --git a/deps/v8/test/cctest/parsing/test-scanner-streams.cc b/deps/v8/test/cctest/parsing/test-scanner-streams.cc index 3f5ae50d45..b4b28f1fc5 100644 --- a/deps/v8/test/cctest/parsing/test-scanner-streams.cc +++ b/deps/v8/test/cctest/parsing/test-scanner-streams.cc @@ -100,7 +100,7 @@ TEST(Utf8StreamAsciiOnly) { ChunkSource chunk_source(chunks); std::unique_ptr<v8::internal::Utf16CharacterStream> stream( v8::internal::ScannerStream::For( - &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); // Read the data without dying. v8::internal::uc32 c; @@ -118,7 +118,7 @@ TEST(Utf8StreamBOM) { ChunkSource chunk_source(chunks); std::unique_ptr<v8::internal::Utf16CharacterStream> stream( v8::internal::ScannerStream::For( - &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); // Read the data without tripping over the BOM. for (size_t i = 0; unicode_ucs2[i]; i++) { @@ -152,7 +152,7 @@ TEST(Utf8SplitBOM) { ChunkSource chunk_source(chunks); std::unique_ptr<v8::internal::Utf16CharacterStream> stream( v8::internal::ScannerStream::For( - &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); // Read the data without tripping over the BOM. for (size_t i = 0; unicode_ucs2[i]; i++) { @@ -168,7 +168,7 @@ TEST(Utf8SplitBOM) { ChunkSource chunk_source(chunks); std::unique_ptr<v8::internal::Utf16CharacterStream> stream( v8::internal::ScannerStream::For( - &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); // Read the data without tripping over the BOM. for (size_t i = 0; unicode_ucs2[i]; i++) { @@ -197,7 +197,7 @@ TEST(Utf8ChunkBoundaries) { ChunkSource chunk_source(chunks); std::unique_ptr<v8::internal::Utf16CharacterStream> stream( v8::internal::ScannerStream::For( - &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); for (size_t i = 0; unicode_ucs2[i]; i++) { CHECK_EQ(unicode_ucs2[i], stream->Advance()); @@ -226,7 +226,7 @@ TEST(Utf8SingleByteChunks) { ChunkSource chunk_source(chunks); std::unique_ptr<v8::internal::Utf16CharacterStream> stream( v8::internal::ScannerStream::For( - &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunk_source, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); for (size_t j = 0; unicode_ucs2[j]; j++) { CHECK_EQ(unicode_ucs2[j], stream->Advance()); @@ -358,13 +358,14 @@ void TestCharacterStreams(const char* one_byte_source, unsigned length, ChunkSource single_chunk(data, data_end - data, false); std::unique_ptr<i::Utf16CharacterStream> one_byte_streaming_stream( i::ScannerStream::For(&single_chunk, - v8::ScriptCompiler::StreamedSource::ONE_BYTE)); + v8::ScriptCompiler::StreamedSource::ONE_BYTE, + nullptr)); TestCharacterStream(one_byte_source, one_byte_streaming_stream.get(), length, start, end); ChunkSource many_chunks(data, data_end - data, true); one_byte_streaming_stream.reset(i::ScannerStream::For( - &many_chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE)); + &many_chunks, v8::ScriptCompiler::StreamedSource::ONE_BYTE, nullptr)); TestCharacterStream(one_byte_source, one_byte_streaming_stream.get(), length, start, end); } @@ -377,14 +378,14 @@ void TestCharacterStreams(const char* one_byte_source, unsigned length, reinterpret_cast<const uint8_t*>(one_byte_vector.end()); ChunkSource chunks(data, data_end - data, false); std::unique_ptr<i::Utf16CharacterStream> utf8_streaming_stream( - i::ScannerStream::For(&chunks, - v8::ScriptCompiler::StreamedSource::UTF8)); + i::ScannerStream::For(&chunks, v8::ScriptCompiler::StreamedSource::UTF8, + nullptr)); TestCharacterStream(one_byte_source, utf8_streaming_stream.get(), length, start, end); ChunkSource many_chunks(data, data_end - data, true); utf8_streaming_stream.reset(i::ScannerStream::For( - &many_chunks, v8::ScriptCompiler::StreamedSource::UTF8)); + &many_chunks, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); TestCharacterStream(one_byte_source, utf8_streaming_stream.get(), length, start, end); } @@ -397,14 +398,14 @@ void TestCharacterStreams(const char* one_byte_source, unsigned length, reinterpret_cast<const uint8_t*>(two_byte_vector.end()); ChunkSource chunks(data, data_end - data, false); std::unique_ptr<i::Utf16CharacterStream> two_byte_streaming_stream( - i::ScannerStream::For(&chunks, - v8::ScriptCompiler::StreamedSource::TWO_BYTE)); + i::ScannerStream::For( + &chunks, v8::ScriptCompiler::StreamedSource::TWO_BYTE, nullptr)); TestCharacterStream(one_byte_source, two_byte_streaming_stream.get(), length, start, end); ChunkSource many_chunks(data, data_end - data, true); two_byte_streaming_stream.reset(i::ScannerStream::For( - &many_chunks, v8::ScriptCompiler::StreamedSource::TWO_BYTE)); + &many_chunks, v8::ScriptCompiler::StreamedSource::TWO_BYTE, nullptr)); TestCharacterStream(one_byte_source, two_byte_streaming_stream.get(), length, start, end); } @@ -446,7 +447,7 @@ TEST(Regress651333) { // 65533) instead of the incorrectly coded Latin1 char. ChunkSource chunks(bytes, len, false); std::unique_ptr<i::Utf16CharacterStream> stream(i::ScannerStream::For( - &chunks, v8::ScriptCompiler::StreamedSource::UTF8)); + &chunks, v8::ScriptCompiler::StreamedSource::UTF8, nullptr)); for (size_t i = 0; i < len; i++) { CHECK_EQ(unicode[i], stream->Advance()); } diff --git a/deps/v8/test/cctest/parsing/test-scanner.cc b/deps/v8/test/cctest/parsing/test-scanner.cc index 12884ba106..0577d713fa 100644 --- a/deps/v8/test/cctest/parsing/test-scanner.cc +++ b/deps/v8/test/cctest/parsing/test-scanner.cc @@ -6,6 +6,7 @@ // Scanner are in cctest/test-parsing.cc, rather than here. #include "src/handles-inl.h" +#include "src/objects-inl.h" #include "src/parsing/scanner-character-streams.h" #include "src/parsing/scanner.h" #include "src/unicode-cache.h" @@ -17,10 +18,29 @@ namespace { const char src_simple[] = "function foo() { var x = 2 * a() + b; }"; -std::unique_ptr<Scanner> make_scanner(const char* src, UnicodeCache* cache) { - std::unique_ptr<Scanner> scanner(new Scanner(cache)); - scanner->Initialize(ScannerStream::ForTesting(src).release()); - return scanner; +struct ScannerTestHelper { + ScannerTestHelper() = default; + ScannerTestHelper(ScannerTestHelper&& other) + : unicode_cache(std::move(other.unicode_cache)), + stream(std::move(other.stream)), + scanner(std::move(other.scanner)) {} + + std::unique_ptr<UnicodeCache> unicode_cache; + std::unique_ptr<Utf16CharacterStream> stream; + std::unique_ptr<Scanner> scanner; + + Scanner* operator->() const { return scanner.get(); } + Scanner* get() const { return scanner.get(); } +}; + +ScannerTestHelper make_scanner(const char* src) { + ScannerTestHelper helper; + helper.unicode_cache = std::unique_ptr<UnicodeCache>(new UnicodeCache); + helper.stream = ScannerStream::ForTesting(src); + helper.scanner = + std::unique_ptr<Scanner>(new Scanner(helper.unicode_cache.get())); + helper.scanner->Initialize(helper.stream.get()); + return helper; } } // anonymous namespace @@ -30,13 +50,11 @@ std::unique_ptr<Scanner> make_scanner(const char* src, UnicodeCache* cache) { #define DCHECK_TOK(a, b) DCHECK_EQ(Token::Name(a), Token::Name(b)) TEST(Bookmarks) { - UnicodeCache unicode_cache; - // Scan through the given source and record the tokens for use as reference // below. std::vector<Token::Value> tokens; { - auto scanner = make_scanner(src_simple, &unicode_cache); + auto scanner = make_scanner(src_simple); do { tokens.push_back(scanner->Next()); } while (scanner->current_token() != Token::EOS); @@ -50,7 +68,7 @@ TEST(Bookmarks) { // - scan until the end. // At each step, compare to the reference token sequence generated above. for (size_t bookmark_pos = 0; bookmark_pos < tokens.size(); bookmark_pos++) { - auto scanner = make_scanner(src_simple, &unicode_cache); + auto scanner = make_scanner(src_simple); Scanner::BookmarkScope bookmark(scanner.get()); for (size_t i = 0; i < std::min(bookmark_pos + 10, tokens.size()); i++) { @@ -79,9 +97,8 @@ TEST(AllThePushbacks) { {"<!-- xx -->\nx", {Token::IDENTIFIER, Token::EOS}}, }; - UnicodeCache unicode_cache; for (const auto& test_case : test_cases) { - auto scanner = make_scanner(test_case.src, &unicode_cache); + auto scanner = make_scanner(test_case.src); for (size_t i = 0; test_case.tokens[i] != Token::EOS; i++) { DCHECK_TOK(test_case.tokens[i], scanner->Next()); } diff --git a/deps/v8/test/cctest/test-access-checks.cc b/deps/v8/test/cctest/test-access-checks.cc index 59c17b89eb..727444b532 100644 --- a/deps/v8/test/cctest/test-access-checks.cc +++ b/deps/v8/test/cctest/test-access-checks.cc @@ -102,6 +102,29 @@ void IndexedEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) { info.GetReturnValue().Set(names); } +void NamedGetterThrowsException( + v8::Local<v8::Name> property, + const v8::PropertyCallbackInfo<v8::Value>& info) { + info.GetIsolate()->ThrowException(v8_str("exception")); +} + +void NamedSetterThrowsException( + v8::Local<v8::Name> property, v8::Local<v8::Value> value, + const v8::PropertyCallbackInfo<v8::Value>& info) { + info.GetIsolate()->ThrowException(v8_str("exception")); +} + +void IndexedGetterThrowsException( + uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { + info.GetIsolate()->ThrowException(v8_str("exception")); +} + +void IndexedSetterThrowsException( + uint32_t index, v8::Local<v8::Value> value, + const v8::PropertyCallbackInfo<v8::Value>& info) { + info.GetIsolate()->ThrowException(v8_str("exception")); +} + bool AccessCheck(v8::Local<v8::Context> accessing_context, v8::Local<v8::Object> accessed_object, v8::Local<v8::Value> data) { @@ -181,6 +204,56 @@ void CheckCrossContextAccess(v8::Isolate* isolate, "[\"7\",\"cross_context_int\"]"); } +void CheckCrossContextAccessWithException( + v8::Isolate* isolate, v8::Local<v8::Context> accessing_context, + v8::Local<v8::Object> accessed_object) { + v8::HandleScope handle_scope(isolate); + accessing_context->Global() + ->Set(accessing_context, v8_str("other"), accessed_object) + .FromJust(); + v8::Context::Scope context_scope(accessing_context); + + { + v8::TryCatch try_catch(isolate); + CompileRun("this.other.should_throw"); + CHECK(try_catch.HasCaught()); + CHECK(try_catch.Exception()->IsString()); + CHECK(v8_str("exception") + ->Equals(accessing_context, try_catch.Exception()) + .FromJust()); + } + + { + v8::TryCatch try_catch(isolate); + CompileRun("this.other.should_throw = 8"); + CHECK(try_catch.HasCaught()); + CHECK(try_catch.Exception()->IsString()); + CHECK(v8_str("exception") + ->Equals(accessing_context, try_catch.Exception()) + .FromJust()); + } + + { + v8::TryCatch try_catch(isolate); + CompileRun("this.other[42]"); + CHECK(try_catch.HasCaught()); + CHECK(try_catch.Exception()->IsString()); + CHECK(v8_str("exception") + ->Equals(accessing_context, try_catch.Exception()) + .FromJust()); + } + + { + v8::TryCatch try_catch(isolate); + CompileRun("this.other[42] = 8"); + CHECK(try_catch.HasCaught()); + CHECK(try_catch.Exception()->IsString()); + CHECK(v8_str("exception") + ->Equals(accessing_context, try_catch.Exception()) + .FromJust()); + } +} + void Ctor(const v8::FunctionCallbackInfo<v8::Value>& info) { CHECK(info.IsConstructCall()); } @@ -215,6 +288,32 @@ TEST(AccessCheckWithInterceptor) { CheckCrossContextAccess(isolate, context1, context0->Global()); } +TEST(AccessCheckWithExceptionThrowingInterceptor) { + v8::Isolate* isolate = CcTest::isolate(); + isolate->SetFailedAccessCheckCallbackFunction([](v8::Local<v8::Object> target, + v8::AccessType type, + v8::Local<v8::Value> data) { + CHECK(false); // This should never be called. + }); + + v8::HandleScope scope(isolate); + v8::Local<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(isolate); + global_template->SetAccessCheckCallbackAndHandler( + AccessCheck, v8::NamedPropertyHandlerConfiguration( + NamedGetterThrowsException, NamedSetterThrowsException), + v8::IndexedPropertyHandlerConfiguration(IndexedGetterThrowsException, + IndexedSetterThrowsException)); + + // Create two contexts. + v8::Local<v8::Context> context0 = + v8::Context::New(isolate, nullptr, global_template); + v8::Local<v8::Context> context1 = + v8::Context::New(isolate, nullptr, global_template); + + CheckCrossContextAccessWithException(isolate, context1, context0->Global()); +} + TEST(NewRemoteContext) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); diff --git a/deps/v8/test/cctest/test-accessor-assembler.cc b/deps/v8/test/cctest/test-accessor-assembler.cc new file mode 100644 index 0000000000..c129bbaf13 --- /dev/null +++ b/deps/v8/test/cctest/test-accessor-assembler.cc @@ -0,0 +1,263 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "test/cctest/cctest.h" + +#include "src/base/utils/random-number-generator.h" +#include "src/ic/accessor-assembler-impl.h" +#include "src/ic/stub-cache.h" +#include "test/cctest/compiler/code-assembler-tester.h" +#include "test/cctest/compiler/function-tester.h" + +namespace v8 { +namespace internal { + +using compiler::CodeAssemblerTester; +using compiler::FunctionTester; +using compiler::Node; + +namespace { + +void TestStubCacheOffsetCalculation(StubCache::Table table) { + Isolate* isolate(CcTest::InitIsolateOnce()); + const int kNumParams = 2; + CodeAssemblerTester data(isolate, kNumParams); + AccessorAssemblerImpl m(data.state()); + + { + Node* name = m.Parameter(0); + Node* map = m.Parameter(1); + Node* primary_offset = m.StubCachePrimaryOffsetForTesting(name, map); + Node* result; + if (table == StubCache::kPrimary) { + result = primary_offset; + } else { + CHECK_EQ(StubCache::kSecondary, table); + result = m.StubCacheSecondaryOffsetForTesting(name, primary_offset); + } + m.Return(m.SmiTag(result)); + } + + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code, kNumParams); + + Factory* factory = isolate->factory(); + Handle<Name> names[] = { + factory->NewSymbol(), + factory->InternalizeUtf8String("a"), + factory->InternalizeUtf8String("bb"), + factory->InternalizeUtf8String("ccc"), + factory->NewPrivateSymbol(), + factory->InternalizeUtf8String("dddd"), + factory->InternalizeUtf8String("eeeee"), + factory->InternalizeUtf8String("name"), + factory->NewSymbol(), + factory->NewPrivateSymbol(), + }; + + Handle<Map> maps[] = { + Handle<Map>(nullptr, isolate), + factory->cell_map(), + Map::Create(isolate, 0), + factory->meta_map(), + factory->code_map(), + Map::Create(isolate, 0), + factory->hash_table_map(), + factory->symbol_map(), + factory->string_map(), + Map::Create(isolate, 0), + factory->sloppy_arguments_elements_map(), + }; + + for (size_t name_index = 0; name_index < arraysize(names); name_index++) { + Handle<Name> name = names[name_index]; + for (size_t map_index = 0; map_index < arraysize(maps); map_index++) { + Handle<Map> map = maps[map_index]; + + int expected_result; + { + int primary_offset = StubCache::PrimaryOffsetForTesting(*name, *map); + if (table == StubCache::kPrimary) { + expected_result = primary_offset; + } else { + expected_result = + StubCache::SecondaryOffsetForTesting(*name, primary_offset); + } + } + Handle<Object> result = ft.Call(name, map).ToHandleChecked(); + + Smi* expected = Smi::FromInt(expected_result & Smi::kMaxValue); + CHECK_EQ(expected, Smi::cast(*result)); + } + } +} + +} // namespace + +TEST(StubCachePrimaryOffset) { + TestStubCacheOffsetCalculation(StubCache::kPrimary); +} + +TEST(StubCacheSecondaryOffset) { + TestStubCacheOffsetCalculation(StubCache::kSecondary); +} + +namespace { + +Handle<Code> CreateCodeWithFlags(Code::Flags flags) { + Isolate* isolate(CcTest::InitIsolateOnce()); + CodeAssemblerTester data(isolate, flags); + CodeStubAssembler m(data.state()); + m.Return(m.UndefinedConstant()); + return data.GenerateCodeCloseAndEscape(); +} + +} // namespace + +TEST(TryProbeStubCache) { + typedef CodeStubAssembler::Label Label; + typedef CodeStubAssembler::Variable Variable; + Isolate* isolate(CcTest::InitIsolateOnce()); + const int kNumParams = 3; + CodeAssemblerTester data(isolate, kNumParams); + AccessorAssemblerImpl m(data.state()); + + Code::Kind ic_kind = Code::LOAD_IC; + StubCache stub_cache(isolate, ic_kind); + stub_cache.Clear(); + + { + Node* receiver = m.Parameter(0); + Node* name = m.Parameter(1); + Node* expected_handler = m.Parameter(2); + + Label passed(&m), failed(&m); + + Variable var_handler(&m, MachineRepresentation::kTagged); + Label if_handler(&m), if_miss(&m); + + m.TryProbeStubCache(&stub_cache, receiver, name, &if_handler, &var_handler, + &if_miss); + m.Bind(&if_handler); + m.Branch(m.WordEqual(expected_handler, var_handler.value()), &passed, + &failed); + + m.Bind(&if_miss); + m.Branch(m.WordEqual(expected_handler, m.IntPtrConstant(0)), &passed, + &failed); + + m.Bind(&passed); + m.Return(m.BooleanConstant(true)); + + m.Bind(&failed); + m.Return(m.BooleanConstant(false)); + } + + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code, kNumParams); + + std::vector<Handle<Name>> names; + std::vector<Handle<JSObject>> receivers; + std::vector<Handle<Code>> handlers; + + base::RandomNumberGenerator rand_gen(FLAG_random_seed); + + Factory* factory = isolate->factory(); + + // Generate some number of names. + for (int i = 0; i < StubCache::kPrimaryTableSize / 7; i++) { + Handle<Name> name; + switch (rand_gen.NextInt(3)) { + case 0: { + // Generate string. + std::stringstream ss; + ss << "s" << std::hex + << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize); + name = factory->InternalizeUtf8String(ss.str().c_str()); + break; + } + case 1: { + // Generate number string. + std::stringstream ss; + ss << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize); + name = factory->InternalizeUtf8String(ss.str().c_str()); + break; + } + case 2: { + // Generate symbol. + name = factory->NewSymbol(); + break; + } + default: + UNREACHABLE(); + } + names.push_back(name); + } + + // Generate some number of receiver maps and receivers. + for (int i = 0; i < StubCache::kSecondaryTableSize / 2; i++) { + Handle<Map> map = Map::Create(isolate, 0); + receivers.push_back(factory->NewJSObjectFromMap(map)); + } + + // Generate some number of handlers. + for (int i = 0; i < 30; i++) { + Code::Flags flags = + Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(ic_kind)); + handlers.push_back(CreateCodeWithFlags(flags)); + } + + // Ensure that GC does happen because from now on we are going to fill our + // own stub cache instance with raw values. + DisallowHeapAllocation no_gc; + + // Populate {stub_cache}. + const int N = StubCache::kPrimaryTableSize + StubCache::kSecondaryTableSize; + for (int i = 0; i < N; i++) { + int index = rand_gen.NextInt(); + Handle<Name> name = names[index % names.size()]; + Handle<JSObject> receiver = receivers[index % receivers.size()]; + Handle<Code> handler = handlers[index % handlers.size()]; + stub_cache.Set(*name, receiver->map(), *handler); + } + + // Perform some queries. + bool queried_existing = false; + bool queried_non_existing = false; + for (int i = 0; i < N; i++) { + int index = rand_gen.NextInt(); + Handle<Name> name = names[index % names.size()]; + Handle<JSObject> receiver = receivers[index % receivers.size()]; + Object* handler = stub_cache.Get(*name, receiver->map()); + if (handler == nullptr) { + queried_non_existing = true; + } else { + queried_existing = true; + } + + Handle<Object> expected_handler(handler, isolate); + ft.CheckTrue(receiver, name, expected_handler); + } + + for (int i = 0; i < N; i++) { + int index1 = rand_gen.NextInt(); + int index2 = rand_gen.NextInt(); + Handle<Name> name = names[index1 % names.size()]; + Handle<JSObject> receiver = receivers[index2 % receivers.size()]; + Object* handler = stub_cache.Get(*name, receiver->map()); + if (handler == nullptr) { + queried_non_existing = true; + } else { + queried_existing = true; + } + + Handle<Object> expected_handler(handler, isolate); + ft.CheckTrue(receiver, name, expected_handler); + } + // Ensure we performed both kind of queries. + CHECK(queried_existing && queried_non_existing); +} + +} // namespace internal +} // namespace v8 diff --git a/deps/v8/test/cctest/test-api-accessors.cc b/deps/v8/test/cctest/test-api-accessors.cc index e9773e918d..cc0c7efb5f 100644 --- a/deps/v8/test/cctest/test-api-accessors.cc +++ b/deps/v8/test/cctest/test-api-accessors.cc @@ -7,6 +7,7 @@ #include "include/v8-experimental.h" #include "include/v8.h" #include "src/api.h" +#include "src/objects-inl.h" namespace i = v8::internal; @@ -247,3 +248,33 @@ TEST(CachedAccessorCrankshaft) { ExpectInt32("g()", 789); } + +namespace { + +static void Setter(v8::Local<v8::String> name, v8::Local<v8::Value> value, + const v8::PropertyCallbackInfo<void>& info) {} +} + +// Re-declaration of non-configurable accessors should throw. +TEST(RedeclareAccessor) { + v8::HandleScope scope(CcTest::isolate()); + LocalContext env; + + v8::Local<v8::FunctionTemplate> templ = + v8::FunctionTemplate::New(CcTest::isolate()); + + v8::Local<v8::ObjectTemplate> object_template = templ->InstanceTemplate(); + object_template->SetAccessor( + v8_str("foo"), NULL, Setter, v8::Local<v8::Value>(), + v8::AccessControl::DEFAULT, v8::PropertyAttribute::DontDelete); + + v8::Local<v8::Context> ctx = + v8::Context::New(CcTest::isolate(), nullptr, object_template); + + // Declare function. + v8::Local<v8::String> code = v8_str("function foo() {};"); + + v8::TryCatch try_catch(CcTest::isolate()); + v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty(); + CHECK(try_catch.HasCaught()); +} diff --git a/deps/v8/test/cctest/test-api-fast-accessor-builder.cc b/deps/v8/test/cctest/test-api-fast-accessor-builder.cc index 6612f9047c..8b85e2aa34 100644 --- a/deps/v8/test/cctest/test-api-fast-accessor-builder.cc +++ b/deps/v8/test/cctest/test-api-fast-accessor-builder.cc @@ -8,6 +8,7 @@ #include "include/v8-experimental.h" #include "src/api.h" +#include "src/objects-inl.h" #include "test/cctest/cctest.h" namespace { diff --git a/deps/v8/test/cctest/test-api-interceptors.cc b/deps/v8/test/cctest/test-api-interceptors.cc index 396efca01d..6aebba67bc 100644 --- a/deps/v8/test/cctest/test-api-interceptors.cc +++ b/deps/v8/test/cctest/test-api-interceptors.cc @@ -380,11 +380,8 @@ void InterceptorHasOwnPropertyGetterGC( CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); } -} // namespace - int query_counter_int = 0; -namespace { void QueryCallback(Local<Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) { query_counter_int++; @@ -479,12 +476,13 @@ THREADED_TEST(QueryInterceptor) { CHECK_EQ(query_counter_int, 8); } +namespace { + bool get_was_called = false; bool set_was_called = false; int set_was_called_counter = 0; -namespace { void GetterCallback(Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) { get_was_called = true; @@ -609,56 +607,13 @@ THREADED_TEST(SetterCallbackFunctionDeclarationInterceptorThrow) { CHECK_EQ(set_was_called, false); } -namespace { -int descriptor_was_called; -void PropertyDescriptorCallback( - Local<Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { - // Intercept the callback by setting a different descriptor. - descriptor_was_called++; - const char* code = - "var desc = {value: 5};" - "desc;"; - Local<Value> descriptor = v8_compile(code) - ->Run(info.GetIsolate()->GetCurrentContext()) - .ToLocalChecked(); - info.GetReturnValue().Set(descriptor); -} -} // namespace -// Check that the descriptor callback is called on the global object. -THREADED_TEST(DescriptorCallbackOnGlobalObject) { - v8::HandleScope scope(CcTest::isolate()); - LocalContext env; - v8::Local<v8::FunctionTemplate> templ = - v8::FunctionTemplate::New(CcTest::isolate()); - - v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate(); - object_template->SetHandler(v8::NamedPropertyHandlerConfiguration( - nullptr, nullptr, PropertyDescriptorCallback, nullptr, nullptr, nullptr)); - v8::Local<v8::Context> ctx = - v8::Context::New(CcTest::isolate(), nullptr, object_template); - - descriptor_was_called = 0; - - // Declare function. - v8::Local<v8::String> code = v8_str( - "var x = 42; var desc = Object.getOwnPropertyDescriptor(this, 'x'); " - "desc.value;"); - CHECK_EQ(5, v8::Script::Compile(ctx, code) - .ToLocalChecked() - ->Run(ctx) - .ToLocalChecked() - ->Int32Value(ctx) - .FromJust()); - CHECK_EQ(1, descriptor_was_called); -} +namespace { bool get_was_called_in_order = false; bool define_was_called_in_order = false; -namespace { - void GetterCallbackOrder(Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) { get_was_called_in_order = true; @@ -700,6 +655,68 @@ THREADED_TEST(DefinerCallbackGetAndDefine) { CHECK_EQ(define_was_called_in_order, true); } +namespace { // namespace for InObjectLiteralDefinitionWithInterceptor + +// Workaround for no-snapshot builds: only intercept once Context::New() is +// done, otherwise we'll intercept +// bootstrapping like defining array on the global object. +bool context_is_done = false; +bool getter_callback_was_called = false; + +void ReturnUndefinedGetterCallback( + Local<Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) { + if (context_is_done) { + getter_callback_was_called = true; + info.GetReturnValue().SetUndefined(); + } +} + +} // namespace + +// Check that an interceptor is not invoked during ES6 style definitions inside +// an object literal. +THREADED_TEST(InObjectLiteralDefinitionWithInterceptor) { + v8::HandleScope scope(CcTest::isolate()); + LocalContext env; + + // Set up a context in which all global object definitions are intercepted. + v8::Local<v8::FunctionTemplate> templ = + v8::FunctionTemplate::New(CcTest::isolate()); + v8::Local<ObjectTemplate> object_template = templ->InstanceTemplate(); + object_template->SetHandler( + v8::NamedPropertyHandlerConfiguration(ReturnUndefinedGetterCallback)); + v8::Local<v8::Context> ctx = + v8::Context::New(CcTest::isolate(), nullptr, object_template); + + context_is_done = true; + + // The interceptor returns undefined for any global object, + // so setting a property on an object should throw. + v8::Local<v8::String> code = v8_str("var o = {}; o.x = 5"); + { + getter_callback_was_called = false; + v8::TryCatch try_catch(CcTest::isolate()); + CHECK(v8::Script::Compile(ctx, code).ToLocalChecked()->Run(ctx).IsEmpty()); + CHECK(try_catch.HasCaught()); + CHECK(getter_callback_was_called); + } + + // Defining a property in the object literal should not throw + // because the interceptor is not invoked. + { + getter_callback_was_called = false; + v8::TryCatch try_catch(CcTest::isolate()); + code = v8_str("var l = {x: 5};"); + CHECK(v8::Script::Compile(ctx, code) + .ToLocalChecked() + ->Run(ctx) + .ToLocalChecked() + ->IsUndefined()); + CHECK(!try_catch.HasCaught()); + CHECK(!getter_callback_was_called); + } +} + THREADED_TEST(InterceptorHasOwnProperty) { LocalContext context; v8::Isolate* isolate = context->GetIsolate(); @@ -1954,8 +1971,9 @@ THREADED_TEST(PropertyDescriptorCallback) { } } +namespace { int echo_indexed_call_count = 0; - +} // namespace static void EchoIndexedProperty( uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { @@ -4560,7 +4578,7 @@ TEST(NamedAllCanReadInterceptor) { ExpectInt32("checked.whatever", 17); CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')") ->IsUndefined()); - CHECK_EQ(6, access_check_data.count); + CHECK_EQ(5, access_check_data.count); access_check_data.result = false; ExpectInt32("checked.whatever", intercept_data_0.value); @@ -4569,7 +4587,7 @@ TEST(NamedAllCanReadInterceptor) { CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')"); CHECK(try_catch.HasCaught()); } - CHECK_EQ(9, access_check_data.count); + CHECK_EQ(7, access_check_data.count); intercept_data_1.should_intercept = true; ExpectInt32("checked.whatever", intercept_data_1.value); @@ -4578,7 +4596,7 @@ TEST(NamedAllCanReadInterceptor) { CompileRun("Object.getOwnPropertyDescriptor(checked, 'whatever')"); CHECK(try_catch.HasCaught()); } - CHECK_EQ(12, access_check_data.count); + CHECK_EQ(9, access_check_data.count); g_access_check_data = nullptr; } @@ -4647,7 +4665,7 @@ TEST(IndexedAllCanReadInterceptor) { ExpectInt32("checked[15]", 17); CHECK(!CompileRun("Object.getOwnPropertyDescriptor(checked, '15')") ->IsUndefined()); - CHECK_EQ(6, access_check_data.count); + CHECK_EQ(5, access_check_data.count); access_check_data.result = false; ExpectInt32("checked[15]", intercept_data_0.value); @@ -4656,7 +4674,7 @@ TEST(IndexedAllCanReadInterceptor) { CompileRun("Object.getOwnPropertyDescriptor(checked, '15')"); CHECK(try_catch.HasCaught()); } - CHECK_EQ(9, access_check_data.count); + CHECK_EQ(7, access_check_data.count); intercept_data_1.should_intercept = true; ExpectInt32("checked[15]", intercept_data_1.value); @@ -4665,7 +4683,7 @@ TEST(IndexedAllCanReadInterceptor) { CompileRun("Object.getOwnPropertyDescriptor(checked, '15')"); CHECK(try_catch.HasCaught()); } - CHECK_EQ(12, access_check_data.count); + CHECK_EQ(9, access_check_data.count); g_access_check_data = nullptr; } diff --git a/deps/v8/test/cctest/test-api.cc b/deps/v8/test/cctest/test-api.cc index c578115888..24cbafbab1 100644 --- a/deps/v8/test/cctest/test-api.cc +++ b/deps/v8/test/cctest/test-api.cc @@ -1584,7 +1584,6 @@ THREADED_TEST(IsGeneratorFunctionOrObject) { } THREADED_TEST(IsAsyncFunction) { - i::FLAG_harmony_async_await = true; LocalContext env; v8::Isolate* isolate = env->GetIsolate(); v8::HandleScope scope(isolate); @@ -3325,6 +3324,20 @@ THREADED_TEST(GlobalSymbols) { CHECK(!sym2->SameValue(glob_api)); } +THREADED_TEST(GlobalSymbolsNoContext) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + + v8::Local<String> name = v8_str("my-symbol"); + v8::Local<v8::Symbol> glob = v8::Symbol::For(isolate, name); + v8::Local<v8::Symbol> glob2 = v8::Symbol::For(isolate, name); + CHECK(glob2->SameValue(glob)); + + v8::Local<v8::Symbol> glob_api = v8::Symbol::ForApi(isolate, name); + v8::Local<v8::Symbol> glob_api2 = v8::Symbol::ForApi(isolate, name); + CHECK(glob_api2->SameValue(glob_api)); + CHECK(!glob_api->SameValue(glob)); +} static void CheckWellKnownSymbol(v8::Local<v8::Symbol>(*getter)(v8::Isolate*), const char* name) { @@ -4470,335 +4483,6 @@ static void WeakPointerCallback( data.GetParameter()->handle.Reset(); } - -template <typename T> -static UniqueId MakeUniqueId(const Persistent<T>& p) { - return UniqueId(reinterpret_cast<uintptr_t>(*v8::Utils::OpenPersistent(p))); -} - - -THREADED_TEST(ApiObjectGroups) { - LocalContext env; - v8::Isolate* iso = env->GetIsolate(); - HandleScope scope(iso); - - WeakCallCounter counter(1234); - - WeakCallCounterAndPersistent<Value> g1s1(&counter); - WeakCallCounterAndPersistent<Value> g1s2(&counter); - WeakCallCounterAndPersistent<Value> g1c1(&counter); - WeakCallCounterAndPersistent<Value> g2s1(&counter); - WeakCallCounterAndPersistent<Value> g2s2(&counter); - WeakCallCounterAndPersistent<Value> g2c1(&counter); - - { - HandleScope scope(iso); - g1s1.handle.Reset(iso, Object::New(iso)); - g1s2.handle.Reset(iso, Object::New(iso)); - g1c1.handle.Reset(iso, Object::New(iso)); - g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - - g2s1.handle.Reset(iso, Object::New(iso)); - g2s2.handle.Reset(iso, Object::New(iso)); - g2c1.handle.Reset(iso, Object::New(iso)); - g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - } - - WeakCallCounterAndPersistent<Value> root(&counter); - root.handle.Reset(iso, g1s1.handle); // make a root. - - // Connect group 1 and 2, make a cycle. - { - HandleScope scope(iso); - CHECK(Local<Object>::New(iso, g1s2.handle.As<Object>()) - ->Set(env.local(), 0, Local<Value>::New(iso, g2s2.handle)) - .FromJust()); - CHECK(Local<Object>::New(iso, g2s1.handle.As<Object>()) - ->Set(env.local(), 0, Local<Value>::New(iso, g1s1.handle)) - .FromJust()); - } - - { - UniqueId id1 = MakeUniqueId(g1s1.handle); - UniqueId id2 = MakeUniqueId(g2s2.handle); - iso->SetObjectGroupId(g1s1.handle, id1); - iso->SetObjectGroupId(g1s2.handle, id1); - iso->SetReferenceFromGroup(id1, g1c1.handle); - iso->SetObjectGroupId(g2s1.handle, id2); - iso->SetObjectGroupId(g2s2.handle, id2); - iso->SetReferenceFromGroup(id2, g2c1.handle); - } - // Do a single full GC, ensure incremental marking is stopped. - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - - // All object should be alive. - CHECK_EQ(0, counter.NumberOfWeakCalls()); - - // Weaken the root. - root.handle.SetWeak(&root, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - // But make children strong roots---all the objects (except for children) - // should be collectable now. - g1c1.handle.ClearWeak(); - g2c1.handle.ClearWeak(); - - // Groups are deleted, rebuild groups. - { - UniqueId id1 = MakeUniqueId(g1s1.handle); - UniqueId id2 = MakeUniqueId(g2s2.handle); - iso->SetObjectGroupId(g1s1.handle, id1); - iso->SetObjectGroupId(g1s2.handle, id1); - iso->SetReferenceFromGroup(id1, g1c1.handle); - iso->SetObjectGroupId(g2s1.handle, id2); - iso->SetObjectGroupId(g2s2.handle, id2); - iso->SetReferenceFromGroup(id2, g2c1.handle); - } - - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - - // All objects should be gone. 5 global handles in total. - CHECK_EQ(5, counter.NumberOfWeakCalls()); - - // And now make children weak again and collect them. - g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - CHECK_EQ(7, counter.NumberOfWeakCalls()); -} - - -THREADED_TEST(ApiObjectGroupsForSubtypes) { - LocalContext env; - v8::Isolate* iso = env->GetIsolate(); - HandleScope scope(iso); - - WeakCallCounter counter(1234); - - WeakCallCounterAndPersistent<Object> g1s1(&counter); - WeakCallCounterAndPersistent<String> g1s2(&counter); - WeakCallCounterAndPersistent<String> g1c1(&counter); - WeakCallCounterAndPersistent<Object> g2s1(&counter); - WeakCallCounterAndPersistent<String> g2s2(&counter); - WeakCallCounterAndPersistent<String> g2c1(&counter); - - { - HandleScope scope(iso); - g1s1.handle.Reset(iso, Object::New(iso)); - g1s2.handle.Reset(iso, v8_str("foo1")); - g1c1.handle.Reset(iso, v8_str("foo2")); - g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - - g2s1.handle.Reset(iso, Object::New(iso)); - g2s2.handle.Reset(iso, v8_str("foo3")); - g2c1.handle.Reset(iso, v8_str("foo4")); - g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - } - - WeakCallCounterAndPersistent<Value> root(&counter); - root.handle.Reset(iso, g1s1.handle); // make a root. - - // Connect group 1 and 2, make a cycle. - { - HandleScope scope(iso); - CHECK(Local<Object>::New(iso, g1s1.handle) - ->Set(env.local(), 0, Local<Object>::New(iso, g2s1.handle)) - .FromJust()); - CHECK(Local<Object>::New(iso, g2s1.handle) - ->Set(env.local(), 0, Local<Object>::New(iso, g1s1.handle)) - .FromJust()); - } - - { - UniqueId id1 = MakeUniqueId(g1s1.handle); - UniqueId id2 = MakeUniqueId(g2s2.handle); - iso->SetObjectGroupId(g1s1.handle, id1); - iso->SetObjectGroupId(g1s2.handle, id1); - iso->SetReference(g1s1.handle, g1c1.handle); - iso->SetObjectGroupId(g2s1.handle, id2); - iso->SetObjectGroupId(g2s2.handle, id2); - iso->SetReferenceFromGroup(id2, g2c1.handle); - } - // Do a single full GC, ensure incremental marking is stopped. - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - - // All object should be alive. - CHECK_EQ(0, counter.NumberOfWeakCalls()); - - // Weaken the root. - root.handle.SetWeak(&root, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - // But make children strong roots---all the objects (except for children) - // should be collectable now. - g1c1.handle.ClearWeak(); - g2c1.handle.ClearWeak(); - - // Groups are deleted, rebuild groups. - { - UniqueId id1 = MakeUniqueId(g1s1.handle); - UniqueId id2 = MakeUniqueId(g2s2.handle); - iso->SetObjectGroupId(g1s1.handle, id1); - iso->SetObjectGroupId(g1s2.handle, id1); - iso->SetReference(g1s1.handle, g1c1.handle); - iso->SetObjectGroupId(g2s1.handle, id2); - iso->SetObjectGroupId(g2s2.handle, id2); - iso->SetReferenceFromGroup(id2, g2c1.handle); - } - - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - - // All objects should be gone. 5 global handles in total. - CHECK_EQ(5, counter.NumberOfWeakCalls()); - - // And now make children weak again and collect them. - g1c1.handle.SetWeak(&g1c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2c1.handle.SetWeak(&g2c1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - CHECK_EQ(7, counter.NumberOfWeakCalls()); -} - - -THREADED_TEST(ApiObjectGroupsCycle) { - LocalContext env; - v8::Isolate* iso = env->GetIsolate(); - HandleScope scope(iso); - - WeakCallCounter counter(1234); - - WeakCallCounterAndPersistent<Value> g1s1(&counter); - WeakCallCounterAndPersistent<Value> g1s2(&counter); - WeakCallCounterAndPersistent<Value> g2s1(&counter); - WeakCallCounterAndPersistent<Value> g2s2(&counter); - WeakCallCounterAndPersistent<Value> g3s1(&counter); - WeakCallCounterAndPersistent<Value> g3s2(&counter); - WeakCallCounterAndPersistent<Value> g4s1(&counter); - WeakCallCounterAndPersistent<Value> g4s2(&counter); - - { - HandleScope scope(iso); - g1s1.handle.Reset(iso, Object::New(iso)); - g1s2.handle.Reset(iso, Object::New(iso)); - g1s1.handle.SetWeak(&g1s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g1s2.handle.SetWeak(&g1s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - CHECK(g1s1.handle.IsWeak()); - CHECK(g1s2.handle.IsWeak()); - - g2s1.handle.Reset(iso, Object::New(iso)); - g2s2.handle.Reset(iso, Object::New(iso)); - g2s1.handle.SetWeak(&g2s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g2s2.handle.SetWeak(&g2s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - CHECK(g2s1.handle.IsWeak()); - CHECK(g2s2.handle.IsWeak()); - - g3s1.handle.Reset(iso, Object::New(iso)); - g3s2.handle.Reset(iso, Object::New(iso)); - g3s1.handle.SetWeak(&g3s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g3s2.handle.SetWeak(&g3s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - CHECK(g3s1.handle.IsWeak()); - CHECK(g3s2.handle.IsWeak()); - - g4s1.handle.Reset(iso, Object::New(iso)); - g4s2.handle.Reset(iso, Object::New(iso)); - g4s1.handle.SetWeak(&g4s1, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - g4s2.handle.SetWeak(&g4s2, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - CHECK(g4s1.handle.IsWeak()); - CHECK(g4s2.handle.IsWeak()); - } - - WeakCallCounterAndPersistent<Value> root(&counter); - root.handle.Reset(iso, g1s1.handle); // make a root. - - // Connect groups. We're building the following cycle: - // G1: { g1s1, g2s1 }, g1s1 implicitly references g2s1, ditto for other - // groups. - { - UniqueId id1 = MakeUniqueId(g1s1.handle); - UniqueId id2 = MakeUniqueId(g2s1.handle); - UniqueId id3 = MakeUniqueId(g3s1.handle); - UniqueId id4 = MakeUniqueId(g4s1.handle); - iso->SetObjectGroupId(g1s1.handle, id1); - iso->SetObjectGroupId(g1s2.handle, id1); - iso->SetReferenceFromGroup(id1, g2s1.handle); - iso->SetObjectGroupId(g2s1.handle, id2); - iso->SetObjectGroupId(g2s2.handle, id2); - iso->SetReferenceFromGroup(id2, g3s1.handle); - iso->SetObjectGroupId(g3s1.handle, id3); - iso->SetObjectGroupId(g3s2.handle, id3); - iso->SetReferenceFromGroup(id3, g4s1.handle); - iso->SetObjectGroupId(g4s1.handle, id4); - iso->SetObjectGroupId(g4s2.handle, id4); - iso->SetReferenceFromGroup(id4, g1s1.handle); - } - // Do a single full GC - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - - // All object should be alive. - CHECK_EQ(0, counter.NumberOfWeakCalls()); - - // Weaken the root. - root.handle.SetWeak(&root, &WeakPointerCallback, - v8::WeakCallbackType::kParameter); - - // Groups are deleted, rebuild groups. - { - UniqueId id1 = MakeUniqueId(g1s1.handle); - UniqueId id2 = MakeUniqueId(g2s1.handle); - UniqueId id3 = MakeUniqueId(g3s1.handle); - UniqueId id4 = MakeUniqueId(g4s1.handle); - iso->SetObjectGroupId(g1s1.handle, id1); - iso->SetObjectGroupId(g1s2.handle, id1); - iso->SetReferenceFromGroup(id1, g2s1.handle); - iso->SetObjectGroupId(g2s1.handle, id2); - iso->SetObjectGroupId(g2s2.handle, id2); - iso->SetReferenceFromGroup(id2, g3s1.handle); - iso->SetObjectGroupId(g3s1.handle, id3); - iso->SetObjectGroupId(g3s2.handle, id3); - iso->SetReferenceFromGroup(id3, g4s1.handle); - iso->SetObjectGroupId(g4s1.handle, id4); - iso->SetObjectGroupId(g4s2.handle, id4); - iso->SetReferenceFromGroup(id4, g1s1.handle); - } - - CcTest::CollectAllGarbage(i::Heap::kFinalizeIncrementalMarkingMask); - - // All objects should be gone. 9 global handles in total. - CHECK_EQ(9, counter.NumberOfWeakCalls()); -} - - THREADED_TEST(ScriptException) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -4928,7 +4612,6 @@ static void check_message_3(v8::Local<v8::Message> message, v8::Local<Value> data) { CHECK(message->IsSharedCrossOrigin()); CHECK(message->GetScriptOrigin().Options().IsSharedCrossOrigin()); - CHECK(message->GetScriptOrigin().Options().IsEmbedderDebugScript()); CHECK(message->GetScriptOrigin().Options().IsOpaque()); CHECK_EQ(6.75, message->GetScriptOrigin() .ResourceName() @@ -4949,10 +4632,10 @@ TEST(MessageHandler3) { CHECK(!message_received); isolate->AddMessageListener(check_message_3); LocalContext context; - v8::ScriptOrigin origin = v8::ScriptOrigin( - v8_str("6.75"), v8::Integer::New(isolate, 1), - v8::Integer::New(isolate, 2), v8::True(isolate), Local<v8::Integer>(), - v8::True(isolate), v8_str("7.40"), v8::True(isolate)); + v8::ScriptOrigin origin = + v8::ScriptOrigin(v8_str("6.75"), v8::Integer::New(isolate, 1), + v8::Integer::New(isolate, 2), v8::True(isolate), + Local<v8::Integer>(), v8_str("7.40"), v8::True(isolate)); v8::Local<v8::Script> script = Script::Compile(context.local(), v8_str("throw 'error'"), &origin) .ToLocalChecked(); @@ -7086,6 +6769,9 @@ THREADED_TEST(Regress892105) { .FromJust()); } +static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) { + args.GetReturnValue().Set(args.This()); +} THREADED_TEST(UndetectableObject) { LocalContext env; @@ -7094,6 +6780,7 @@ THREADED_TEST(UndetectableObject) { Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(env->GetIsolate()); desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable + desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable Local<v8::Object> obj = desc->GetFunction(env.local()) .ToLocalChecked() @@ -7142,6 +6829,7 @@ THREADED_TEST(VoidLiteral) { Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate); desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable + desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable Local<v8::Object> obj = desc->GetFunction(env.local()) .ToLocalChecked() @@ -7192,6 +6880,7 @@ THREADED_TEST(ExtensibleOnUndetectable) { Local<v8::FunctionTemplate> desc = v8::FunctionTemplate::New(isolate); desc->InstanceTemplate()->MarkAsUndetectable(); // undetectable + desc->InstanceTemplate()->SetCallAsFunctionHandler(ReturnThis); // callable Local<v8::Object> obj = desc->GetFunction(env.local()) .ToLocalChecked() @@ -7811,7 +7500,8 @@ static void IndependentWeakHandle(bool global_gc, bool interlinked) { } // A single GC should be enough to reclaim the memory, since we are using // phantom handles. - CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 20000); + // BUG(5865): --expose-wasm with no snapshot builds requires a limit change. + CHECK_LT(CcTest::heap()->SizeOfObjects(), big_heap_size - 19000); CHECK(object_a.flag); CHECK(object_b.flag); } @@ -11776,11 +11466,6 @@ static void call_as_function(const v8::FunctionCallbackInfo<v8::Value>& args) { } -static void ReturnThis(const v8::FunctionCallbackInfo<v8::Value>& args) { - args.GetReturnValue().Set(args.This()); -} - - // Test that a call handler can be set for objects which will allow // non-function objects created through the API to be called as // functions. @@ -14561,17 +14246,22 @@ void SetFunctionEntryHookTest::RunTest() { RunLoopInNewEnv(isolate); // Check the expected invocation counts. - if (!i::FLAG_ignition && !i::FLAG_turbo) { + if (i::FLAG_always_opt || (!i::FLAG_ignition && !i::FLAG_turbo)) { CHECK_EQ(2, CountInvocations(NULL, "bar")); CHECK_EQ(200, CountInvocations("bar", "foo")); CHECK_EQ(200, CountInvocations(NULL, "foo")); - } else { + } else if (i::FLAG_crankshaft || i::FLAG_turbo) { // For ignition we don't see the actual functions being called, instead - // we see the IterpreterEntryTrampoline at least 102 times + // we see the InterpreterEntryTrampoline at least 102 times // (100 unoptimized calls to foo, and 2 calls to bar). CHECK_LE(102, CountInvocations(NULL, "InterpreterEntryTrampoline")); // We should also see the calls to the optimized function foo. CHECK_EQ(100, CountInvocations(NULL, "foo")); + } else { + // For ignition without an optimizing compiler, we should only see the + // InterpreterEntryTrampoline. + // (200 unoptimized calls to foo, and 2 calls to bar). + CHECK_LE(202, CountInvocations(NULL, "InterpreterEntryTrampoline")); } // Verify that we have an entry hook on some specific stubs. @@ -15364,7 +15054,6 @@ TEST(PreCompileSerialization) { v8::Isolate* isolate = env->GetIsolate(); HandleScope handle_scope(isolate); - i::FLAG_min_preparse_length = 0; const char* script = "function foo(a) { return a+1; }"; v8::ScriptCompiler::Source source(v8_str(script)); v8::ScriptCompiler::Compile(env.local(), &source, @@ -17336,6 +17025,79 @@ TEST(CaptureStackTraceForUncaughtExceptionAndSetters) { isolate->SetCaptureStackTraceForUncaughtExceptions(false); } +static int asm_warning_triggered = 0; + +static void AsmJsWarningListener(v8::Local<v8::Message> message, + v8::Local<Value>) { + DCHECK_EQ(v8::Isolate::kMessageWarning, message->ErrorLevel()); + asm_warning_triggered = 1; +} + +TEST(AsmJsWarning) { + i::FLAG_validate_asm = true; + + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + asm_warning_triggered = 0; + isolate->AddMessageListenerWithErrorLevel(AsmJsWarningListener, + v8::Isolate::kMessageAll); + CompileRun( + "function module() {\n" + " 'use asm';\n" + " var x = 'hi';\n" + " return {};\n" + "}\n" + "module();"); + DCHECK_EQ(1, asm_warning_triggered); + isolate->RemoveMessageListeners(AsmJsWarningListener); +} + +static int error_level_message_count = 0; +static int expected_error_level = 0; + +static void ErrorLevelListener(v8::Local<v8::Message> message, + v8::Local<Value>) { + DCHECK_EQ(expected_error_level, message->ErrorLevel()); + ++error_level_message_count; +} + +TEST(ErrorLevelWarning) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + v8::HandleScope scope(isolate); + + const char* source = "fake = 1;"; + v8::Local<v8::Script> lscript = CompileWithOrigin(source, "test"); + i::Handle<i::SharedFunctionInfo> obj = i::Handle<i::SharedFunctionInfo>::cast( + v8::Utils::OpenHandle(*lscript->GetUnboundScript())); + CHECK(obj->script()->IsScript()); + i::Handle<i::Script> script(i::Script::cast(obj->script())); + + int levels[] = { + v8::Isolate::kMessageLog, v8::Isolate::kMessageInfo, + v8::Isolate::kMessageDebug, v8::Isolate::kMessageWarning, + }; + error_level_message_count = 0; + isolate->AddMessageListenerWithErrorLevel(ErrorLevelListener, + v8::Isolate::kMessageAll); + for (size_t i = 0; i < arraysize(levels); i++) { + i::MessageLocation location(script, 0, 0); + i::Handle<i::String> msg(i_isolate->factory()->InternalizeOneByteString( + STATIC_CHAR_VECTOR("test"))); + i::Handle<i::JSMessageObject> message = + i::MessageHandler::MakeMessageObject( + i_isolate, i::MessageTemplate::kAsmJsInvalid, &location, msg, + i::Handle<i::JSArray>::null()); + message->set_error_level(levels[i]); + expected_error_level = levels[i]; + i::MessageHandler::ReportMessage(i_isolate, &location, message); + } + isolate->RemoveMessageListeners(ErrorLevelListener); + DCHECK_EQ(arraysize(levels), error_level_message_count); +} static void StackTraceFunctionNameListener(v8::Local<v8::Message> message, v8::Local<Value>) { @@ -18053,6 +17815,348 @@ TEST(InlineScriptWithSourceURLInStackTrace) { CHECK(CompileRunWithOrigin(code.start(), "url", 0, 1)->IsUndefined()); } +void SetPromise(const char* name, v8::Local<v8::Promise> promise) { + CcTest::global() + ->Set(CcTest::isolate()->GetCurrentContext(), v8_str(name), promise) + .FromJust(); +} + +class PromiseHookData { + public: + int before_hook_count = 0; + int after_hook_count = 0; + int promise_hook_count = 0; + int parent_promise_count = 0; + bool check_value = true; + std::string promise_hook_value; + + void Reset() { + before_hook_count = 0; + after_hook_count = 0; + promise_hook_count = 0; + parent_promise_count = 0; + check_value = true; + promise_hook_value = ""; + } +}; + +PromiseHookData* promise_hook_data; + +void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise, + v8::Local<v8::Value> parentPromise) { + promise_hook_data->promise_hook_count++; + switch (type) { + case v8::PromiseHookType::kInit: + SetPromise("init", promise); + + if (!parentPromise->IsUndefined()) { + promise_hook_data->parent_promise_count++; + SetPromise("parent", v8::Local<v8::Promise>::Cast(parentPromise)); + } + + break; + case v8::PromiseHookType::kResolve: + SetPromise("resolve", promise); + break; + case v8::PromiseHookType::kBefore: + promise_hook_data->before_hook_count++; + CHECK(promise_hook_data->before_hook_count > + promise_hook_data->after_hook_count); + CHECK(CcTest::global() + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value")) + .ToLocalChecked() + ->Equals(CcTest::isolate()->GetCurrentContext(), v8_str("")) + .FromJust()); + SetPromise("before", promise); + break; + case v8::PromiseHookType::kAfter: + promise_hook_data->after_hook_count++; + CHECK(promise_hook_data->after_hook_count <= + promise_hook_data->before_hook_count); + if (promise_hook_data->check_value) { + CHECK( + CcTest::global() + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value")) + .ToLocalChecked() + ->Equals(CcTest::isolate()->GetCurrentContext(), + v8_str(promise_hook_data->promise_hook_value.c_str())) + .FromJust()); + } + SetPromise("after", promise); + break; + } +} + +TEST(PromiseHook) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + v8::Local<v8::Object> global = CcTest::global(); + v8::Local<v8::Context> context = CcTest::isolate()->GetCurrentContext(); + + promise_hook_data = new PromiseHookData(); + isolate->SetPromiseHook(CustomPromiseHook); + + // Test that an initialized promise is passed to init. Other hooks + // can not have un initialized promise. + promise_hook_data->check_value = false; + CompileRun("var p = new Promise(() => {});"); + + auto init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); + auto init_promise_obj = v8::Local<v8::Promise>::Cast(init_promise); + CHECK(init_promise_obj->State() == v8::Promise::PromiseState::kPending); + CHECK_EQ(false, init_promise_obj->HasHandler()); + + promise_hook_data->Reset(); + promise_hook_data->promise_hook_value = "fulfilled"; + const char* source = + "var resolve, value = ''; \n" + "var p = new Promise(r => resolve = r); \n"; + + CompileRun(source); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); + CHECK_EQ(1, promise_hook_data->promise_hook_count); + CHECK_EQ(0, promise_hook_data->parent_promise_count); + + CompileRun("var p1 = p.then(() => { value = 'fulfilled'; }); \n"); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + auto parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust()); + CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust()); + CHECK_EQ(2, promise_hook_data->promise_hook_count); + CHECK_EQ(1, promise_hook_data->parent_promise_count); + + CompileRun("resolve(); \n"); + auto resolve_promise = + global->Get(context, v8_str("resolve")).ToLocalChecked(); + auto before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); + auto after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); + CHECK_EQ(6, promise_hook_data->promise_hook_count); + + CompileRun("value = ''; var p2 = p1.then(() => { value = 'fulfilled' }); \n"); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); + after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); + CHECK(GetPromise("p2")->Equals(env.local(), init_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), parent_promise).FromJust()); + CHECK(GetPromise("p2")->Equals(env.local(), before_promise).FromJust()); + CHECK(GetPromise("p2")->Equals(env.local(), after_promise).FromJust()); + CHECK(GetPromise("p2")->Equals(env.local(), resolve_promise).FromJust()); + CHECK_EQ(10, promise_hook_data->promise_hook_count); + + promise_hook_data->Reset(); + promise_hook_data->promise_hook_value = "rejected"; + source = + "var reject, value = ''; \n" + "var p = new Promise((_, r) => reject = r); \n"; + + CompileRun(source); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); + CHECK_EQ(1, promise_hook_data->promise_hook_count); + CHECK_EQ(0, promise_hook_data->parent_promise_count); + + CompileRun("var p1 = p.catch(() => { value = 'rejected'; }); \n"); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust()); + CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust()); + CHECK_EQ(2, promise_hook_data->promise_hook_count); + CHECK_EQ(1, promise_hook_data->parent_promise_count); + + CompileRun("reject(); \n"); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); + after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); + CHECK_EQ(6, promise_hook_data->promise_hook_count); + + promise_hook_data->Reset(); + promise_hook_data->promise_hook_value = "Promise.resolve"; + source = + "var value = ''; \n" + "var p = Promise.resolve('Promise.resolve'); \n"; + + CompileRun(source); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); + // init hook and resolve hook + CHECK_EQ(2, promise_hook_data->promise_hook_count); + CHECK_EQ(0, promise_hook_data->parent_promise_count); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust()); + + CompileRun("var p1 = p.then((v) => { value = v; }); \n"); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + parent_promise = global->Get(context, v8_str("parent")).ToLocalChecked(); + before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); + after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), init_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); + CHECK(GetPromise("p")->Equals(env.local(), parent_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust()); + CHECK_EQ(6, promise_hook_data->promise_hook_count); + CHECK_EQ(1, promise_hook_data->parent_promise_count); + + promise_hook_data->Reset(); + source = + "var resolve, value = ''; \n" + "var p = new Promise((_, r) => resolve = r); \n"; + + CompileRun(source); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); + CHECK_EQ(1, promise_hook_data->promise_hook_count); + CHECK_EQ(0, promise_hook_data->parent_promise_count); + + CompileRun("resolve(); \n"); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust()); + CHECK_EQ(2, promise_hook_data->promise_hook_count); + + promise_hook_data->Reset(); + source = + "var reject, value = ''; \n" + "var p = new Promise((_, r) => reject = r); \n"; + + CompileRun(source); + init_promise = global->Get(context, v8_str("init")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), init_promise).FromJust()); + CHECK_EQ(1, promise_hook_data->promise_hook_count); + CHECK_EQ(0, promise_hook_data->parent_promise_count); + + CompileRun("reject(); \n"); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + CHECK(GetPromise("p")->Equals(env.local(), resolve_promise).FromJust()); + CHECK_EQ(2, promise_hook_data->promise_hook_count); + + promise_hook_data->Reset(); + // This test triggers after callbacks right after each other, so + // lets just check the value at the end. + promise_hook_data->check_value = false; + promise_hook_data->promise_hook_value = "Promise.all"; + source = + "var resolve, value = ''; \n" + "var tempPromise = new Promise(r => resolve = r); \n" + "var p = Promise.all([tempPromise]);\n " + "var p1 = p.then(v => value = v[0]); \n"; + + CompileRun(source); + // 1) init hook (tempPromise) + // 2) init hook (p) + // 3) init hook (throwaway Promise in Promise.all, p) + // 4) init hook (p1, p) + CHECK_EQ(4, promise_hook_data->promise_hook_count); + CHECK_EQ(2, promise_hook_data->parent_promise_count); + + promise_hook_data->promise_hook_value = "Promise.all"; + CompileRun("resolve('Promise.all'); \n"); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); + // 5) resolve hook (tempPromise) + // 6) resolve hook (throwaway Promise in Promise.all) + // 6) before hook (throwaway Promise in Promise.all) + // 7) after hook (throwaway Promise in Promise.all) + // 8) before hook (p) + // 9) after hook (p) + // 10) resolve hook (p1) + // 11) before hook (p1) + // 12) after hook (p1) + CHECK_EQ(12, promise_hook_data->promise_hook_count); + CHECK(CcTest::global() + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value")) + .ToLocalChecked() + ->Equals(CcTest::isolate()->GetCurrentContext(), + v8_str(promise_hook_data->promise_hook_value.c_str())) + .FromJust()); + + promise_hook_data->Reset(); + // This test triggers after callbacks right after each other, so + // lets just check the value at the end. + promise_hook_data->check_value = false; + promise_hook_data->promise_hook_value = "Promise.race"; + source = + "var resolve, value = ''; \n" + "var tempPromise = new Promise(r => resolve = r); \n" + "var p = Promise.race([tempPromise]);\n " + "var p1 = p.then(v => value = v); \n"; + + CompileRun(source); + // 1) init hook (tempPromise) + // 2) init hook (p) + // 3) init hook (throwaway Promise in Promise.race, p) + // 4) init hook (p1, p) + CHECK_EQ(4, promise_hook_data->promise_hook_count); + CHECK_EQ(2, promise_hook_data->parent_promise_count); + + promise_hook_data->promise_hook_value = "Promise.race"; + CompileRun("resolve('Promise.race'); \n"); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); + // 5) resolve hook (tempPromise) + // 6) resolve hook (throwaway Promise in Promise.race) + // 6) before hook (throwaway Promise in Promise.race) + // 7) after hook (throwaway Promise in Promise.race) + // 8) before hook (p) + // 9) after hook (p) + // 10) resolve hook (p1) + // 11) before hook (p1) + // 12) after hook (p1) + CHECK_EQ(12, promise_hook_data->promise_hook_count); + CHECK(CcTest::global() + ->Get(CcTest::isolate()->GetCurrentContext(), v8_str("value")) + .ToLocalChecked() + ->Equals(CcTest::isolate()->GetCurrentContext(), + v8_str(promise_hook_data->promise_hook_value.c_str())) + .FromJust()); + + promise_hook_data->Reset(); + promise_hook_data->promise_hook_value = "subclass"; + source = + "var resolve, value = '';\n" + "class MyPromise extends Promise { \n" + " then(onFulfilled, onRejected) { \n" + " return super.then(onFulfilled, onRejected); \n" + " };\n" + "};\n" + "var p = new MyPromise(r => resolve = r);\n"; + + CompileRun(source); + // 1) init hook (p) + CHECK_EQ(1, promise_hook_data->promise_hook_count); + + CompileRun("var p1 = p.then(() => value = 'subclass');\n"); + // 2) init hook (p1) + CHECK_EQ(2, promise_hook_data->promise_hook_count); + + CompileRun("resolve();\n"); + resolve_promise = global->Get(context, v8_str("resolve")).ToLocalChecked(); + before_promise = global->Get(context, v8_str("before")).ToLocalChecked(); + after_promise = global->Get(context, v8_str("after")).ToLocalChecked(); + CHECK(GetPromise("p1")->Equals(env.local(), before_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), after_promise).FromJust()); + CHECK(GetPromise("p1")->Equals(env.local(), resolve_promise).FromJust()); + // 3) resolve hook (p) + // 4) before hook (p) + // 5) after hook (p) + // 6) resolve hook (p1) + CHECK_EQ(6, promise_hook_data->promise_hook_count); + + delete promise_hook_data; + isolate->SetPromiseHook(nullptr); +} void AnalyzeStackOfDynamicScriptWithSourceURL( const v8::FunctionCallbackInfo<v8::Value>& args) { @@ -18773,8 +18877,8 @@ THREADED_TEST(ScriptOrigin) { v8::ScriptOrigin origin = v8::ScriptOrigin( v8_str("test"), v8::Integer::New(env->GetIsolate(), 1), v8::Integer::New(env->GetIsolate(), 1), v8::True(env->GetIsolate()), - v8::Local<v8::Integer>(), v8::True(env->GetIsolate()), - v8_str("http://sourceMapUrl"), v8::True(env->GetIsolate())); + v8::Local<v8::Integer>(), v8_str("http://sourceMapUrl"), + v8::True(env->GetIsolate())); v8::Local<v8::String> script = v8_str("function f() {}\n\nfunction g() {}"); v8::Script::Compile(env.local(), script, &origin) .ToLocalChecked() @@ -18792,7 +18896,6 @@ THREADED_TEST(ScriptOrigin) { 1, script_origin_f.ResourceLineOffset()->Int32Value(env.local()).FromJust()); CHECK(script_origin_f.Options().IsSharedCrossOrigin()); - CHECK(script_origin_f.Options().IsEmbedderDebugScript()); CHECK(script_origin_f.Options().IsOpaque()); printf("is name = %d\n", script_origin_f.SourceMapUrl()->IsUndefined()); @@ -18806,7 +18909,6 @@ THREADED_TEST(ScriptOrigin) { 1, script_origin_g.ResourceLineOffset()->Int32Value(env.local()).FromJust()); CHECK(script_origin_g.Options().IsSharedCrossOrigin()); - CHECK(script_origin_g.Options().IsEmbedderDebugScript()); CHECK(script_origin_g.Options().IsOpaque()); CHECK_EQ(0, strcmp("http://sourceMapUrl", *v8::String::Utf8Value(script_origin_g.SourceMapUrl()))); @@ -19018,24 +19120,6 @@ THREADED_TEST(ScriptColumnNumber) { } -THREADED_TEST(FunctionIsBuiltin) { - LocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Function> f; - f = v8::Local<v8::Function>::Cast(CompileRun("Math.floor")); - CHECK(f->IsBuiltin()); - f = v8::Local<v8::Function>::Cast(CompileRun("Object")); - CHECK(f->IsBuiltin()); - f = v8::Local<v8::Function>::Cast(CompileRun("Object.__defineSetter__")); - CHECK(f->IsBuiltin()); - f = v8::Local<v8::Function>::Cast(CompileRun("Array.prototype.toString")); - CHECK(f->IsBuiltin()); - f = v8::Local<v8::Function>::Cast(CompileRun("function a() {}; a;")); - CHECK(!f->IsBuiltin()); -} - - THREADED_TEST(FunctionGetScriptId) { LocalContext env; v8::Isolate* isolate = env->GetIsolate(); @@ -21753,6 +21837,19 @@ int* LookupCounter(const char* name) { return NULL; } +template <typename Stub, typename... Args> +void Recompile(Args... args) { + Stub stub(args...); + stub.DeleteStubFromCacheForTesting(); + stub.GetCode(); +} + +void RecompileICStubs(i::Isolate* isolate) { + // BUG(5784): We had a list of IC stubs here to recompile. These are now + // builtins and we can't compile them again (easily). Bug 5784 tracks + // our progress in finding another way to do this. +} + } // namespace #ifdef ENABLE_DISASSEMBLER @@ -21786,46 +21883,35 @@ const char* kMegamorphicTestProgram = "}\n"; void TestStubCache(bool primary) { + using namespace i; + // The test does not work with interpreter because bytecode handlers taken // from the snapshot already refer to ICs with disabled counters and there // is no way to trigger bytecode handlers recompilation. - if (i::FLAG_ignition || i::FLAG_turbo) return; + if (FLAG_ignition || FLAG_turbo) return; - i::FLAG_native_code_counters = true; + FLAG_native_code_counters = true; if (primary) { - i::FLAG_test_primary_stub_cache = true; + FLAG_test_primary_stub_cache = true; } else { - i::FLAG_test_secondary_stub_cache = true; + FLAG_test_secondary_stub_cache = true; } - i::FLAG_crankshaft = false; - i::FLAG_turbo = false; + FLAG_crankshaft = false; + v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); create_params.counter_lookup_callback = LookupCounter; v8::Isolate* isolate = v8::Isolate::New(create_params); + Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate); { v8::Isolate::Scope isolate_scope(isolate); LocalContext env(isolate); v8::HandleScope scope(isolate); - { - // Enforce recompilation of IC stubs that access megamorphic stub cache - // to respect enabled native code counters and stub cache test flags. - i::CodeStub::Major code_stub_keys[] = { - i::CodeStub::LoadIC, i::CodeStub::LoadICTrampoline, - i::CodeStub::KeyedLoadICTF, i::CodeStub::KeyedLoadICTrampolineTF, - i::CodeStub::StoreIC, i::CodeStub::StoreICTrampoline, - i::CodeStub::KeyedStoreIC, i::CodeStub::KeyedStoreICTrampoline, - }; - i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - i::Heap* heap = i_isolate->heap(); - i::Handle<i::UnseededNumberDictionary> dict(heap->code_stubs()); - for (size_t i = 0; i < arraysize(code_stub_keys); i++) { - dict = i::UnseededNumberDictionary::DeleteKey(dict, code_stub_keys[i]); - } - heap->SetRootCodeStubs(*dict); - } + // Enforce recompilation of IC stubs that access megamorphic stub cache + // to respect enabled native code counters and stub cache test flags. + RecompileICStubs(i_isolate); int initial_probes = probes_counter; int initial_misses = misses_counter; @@ -22718,41 +22804,30 @@ TEST(AccessCheckThrows) { } TEST(AccessCheckInIC) { + using namespace i; + // The test does not work with interpreter because bytecode handlers taken // from the snapshot already refer to ICs with disabled counters and there // is no way to trigger bytecode handlers recompilation. - if (i::FLAG_ignition || i::FLAG_turbo) return; + if (FLAG_ignition || FLAG_turbo) return; + + FLAG_native_code_counters = true; + FLAG_crankshaft = false; - i::FLAG_native_code_counters = true; - i::FLAG_crankshaft = false; - i::FLAG_turbo = false; v8::Isolate::CreateParams create_params; create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); create_params.counter_lookup_callback = LookupCounter; v8::Isolate* isolate = v8::Isolate::New(create_params); + Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate); { v8::Isolate::Scope isolate_scope(isolate); LocalContext env(isolate); v8::HandleScope scope(isolate); - { - // Enforce recompilation of IC stubs that access megamorphic stub cache - // to respect enabled native code counters and stub cache test flags. - i::CodeStub::Major code_stub_keys[] = { - i::CodeStub::LoadIC, i::CodeStub::LoadICTrampoline, - i::CodeStub::KeyedLoadICTF, i::CodeStub::KeyedLoadICTrampolineTF, - i::CodeStub::StoreIC, i::CodeStub::StoreICTrampoline, - i::CodeStub::KeyedStoreIC, i::CodeStub::KeyedStoreICTrampoline, - }; - i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - i::Heap* heap = i_isolate->heap(); - i::Handle<i::UnseededNumberDictionary> dict(heap->code_stubs()); - for (size_t i = 0; i < arraysize(code_stub_keys); i++) { - dict = i::UnseededNumberDictionary::DeleteKey(dict, code_stub_keys[i]); - } - heap->SetRootCodeStubs(*dict); - } + // Enforce recompilation of IC stubs that access megamorphic stub cache + // to respect enabled native code counters and stub cache test flags. + RecompileICStubs(i_isolate); // Create an ObjectTemplate for global objects and install access // check callbacks that will block access. @@ -23228,20 +23303,15 @@ THREADED_TEST(FunctionNew) { CHECK(env->Global()->Set(env.local(), v8_str("func"), func).FromJust()); Local<Value> result = CompileRun("func();"); CHECK(v8::Integer::New(isolate, 17)->Equals(env.local(), result).FromJust()); - i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); - // Verify function not cached - auto serial_number = handle( + // Serial number should be invalid => should not be cached. + auto serial_number = i::Smi::cast(i::Handle<i::JSFunction>::cast(v8::Utils::OpenHandle(*func)) ->shared() ->get_api_func_data() - ->serial_number()), - i_isolate); - auto slow_cache = i_isolate->slow_template_instantiations_cache(); - CHECK(slow_cache->FindEntry(static_cast<uint32_t>(serial_number->value())) == - i::UnseededNumberDictionary::kNotFound); - auto fast_cache = i_isolate->fast_template_instantiations_cache(); - CHECK(fast_cache->get(static_cast<uint32_t>(serial_number->value())) - ->IsUndefined(i_isolate)); + ->serial_number()) + ->value(); + CHECK_EQ(i::FunctionTemplateInfo::kInvalidSerialNumber, serial_number); + // Verify that each Function::New creates a new function instance Local<Object> data2 = v8::Object::New(isolate); function_new_expected_env = data2; @@ -23986,6 +24056,25 @@ TEST(PromiseThen) { .FromJust()); } +TEST(PromiseStateAndValue) { + LocalContext context; + v8::Isolate* isolate = context->GetIsolate(); + v8::HandleScope scope(isolate); + v8::Local<v8::Value> result = CompileRun( + "var resolver;" + "new Promise((res, rej) => { resolver = res; })"); + v8::Local<v8::Promise> promise = v8::Local<v8::Promise>::Cast(result); + CHECK(promise->State() == v8::Promise::PromiseState::kPending); + + CompileRun("resolver('fulfilled')"); + CHECK(promise->State() == v8::Promise::PromiseState::kFulfilled); + CHECK(v8_str("fulfilled")->SameValue(promise->Result())); + + result = CompileRun("Promise.reject('rejected')"); + promise = v8::Local<v8::Promise>::Cast(result); + CHECK(promise->State() == v8::Promise::PromiseState::kRejected); + CHECK(v8_str("rejected")->SameValue(promise->Result())); +} TEST(DisallowJavascriptExecutionScope) { LocalContext context; @@ -24691,7 +24780,6 @@ TEST(StreamingUtf8ScriptWithSplitCharactersInvalidEdgeCases) { TEST(StreamingProducesParserCache) { - i::FLAG_min_preparse_length = 0; const char* chunks[] = {"function foo() { ret", "urn 13; } f", "oo(); ", NULL}; @@ -24724,7 +24812,6 @@ TEST(StreamingWithDebuggingEnabledLate) { // fully parsed. However, we may compile inner functions eagerly when // debugging. Make sure that we can deal with this when turning on debugging // after streaming parser has already finished parsing. - i::FLAG_min_preparse_length = 0; const char* chunks[] = {"with({x:1}) {", " var foo = function foo(y) {", " return x + y;", @@ -24971,7 +25058,6 @@ TEST(ParserCacheRejectedGracefully) { // Producing cached parser data while parsing eagerly is not supported. if (!i::FLAG_lazy) return; - i::FLAG_min_preparse_length = 0; v8::V8::Initialize(); v8::HandleScope scope(CcTest::isolate()); LocalContext context; @@ -26184,3 +26270,51 @@ TEST(InternalFieldsOnDataView) { array->GetAlignedPointerFromInternalField(i)); } } + +TEST(SetPrototypeTemplate) { + LocalContext env; + v8::Isolate* isolate = env->GetIsolate(); + v8::HandleScope scope(isolate); + + Local<FunctionTemplate> HTMLElementTemplate = FunctionTemplate::New(isolate); + Local<FunctionTemplate> HTMLImageElementTemplate = + FunctionTemplate::New(isolate); + HTMLImageElementTemplate->Inherit(HTMLElementTemplate); + + Local<FunctionTemplate> ImageTemplate = FunctionTemplate::New(isolate); + ImageTemplate->SetPrototypeProviderTemplate(HTMLImageElementTemplate); + + Local<Function> HTMLImageElement = + HTMLImageElementTemplate->GetFunction(env.local()).ToLocalChecked(); + Local<Function> Image = + ImageTemplate->GetFunction(env.local()).ToLocalChecked(); + + CHECK(env->Global() + ->Set(env.local(), v8_str("HTMLImageElement"), HTMLImageElement) + .FromJust()); + CHECK(env->Global()->Set(env.local(), v8_str("Image"), Image).FromJust()); + + ExpectTrue("Image.prototype === HTMLImageElement.prototype"); +} + +UNINITIALIZED_TEST(IncreaseHeapLimitForDebugging) { + using namespace i; + v8::Isolate::CreateParams create_params; + create_params.constraints.set_max_old_space_size(16); + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + v8::Isolate* isolate = v8::Isolate::New(create_params); + Isolate* i_isolate = reinterpret_cast<Isolate*>(isolate); + { + size_t limit_before = i_isolate->heap()->MaxOldGenerationSize(); + CHECK_EQ(16 * MB, limit_before); + CHECK(!isolate->IsHeapLimitIncreasedForDebugging()); + isolate->IncreaseHeapLimitForDebugging(); + CHECK(isolate->IsHeapLimitIncreasedForDebugging()); + size_t limit_after = i_isolate->heap()->MaxOldGenerationSize(); + CHECK_EQ(4 * 16 * MB, limit_after); + isolate->RestoreOriginalHeapLimit(); + CHECK(!isolate->IsHeapLimitIncreasedForDebugging()); + CHECK_EQ(limit_before, i_isolate->heap()->MaxOldGenerationSize()); + } + isolate->Dispose(); +} diff --git a/deps/v8/test/cctest/test-assembler-arm.cc b/deps/v8/test/cctest/test-assembler-arm.cc index 08f1f5a9f3..680b1233f7 100644 --- a/deps/v8/test/cctest/test-assembler-arm.cc +++ b/deps/v8/test/cctest/test-assembler-arm.cc @@ -1221,6 +1221,32 @@ TEST(14) { CHECK_EQ(kArmNanLower32, bit_cast<int64_t>(t.div_result) & 0xffffffffu); } +#define CHECK_EQ_SPLAT(field, ex) \ + CHECK_EQ(ex, t.field[0]); \ + CHECK_EQ(ex, t.field[1]); \ + CHECK_EQ(ex, t.field[2]); \ + CHECK_EQ(ex, t.field[3]); + +#define CHECK_EQ_32X4(field, ex0, ex1, ex2, ex3) \ + CHECK_EQ(ex0, t.field[0]); \ + CHECK_EQ(ex1, t.field[1]); \ + CHECK_EQ(ex2, t.field[2]); \ + CHECK_EQ(ex3, t.field[3]); + +#define CHECK_ESTIMATE(expected, tolerance, value) \ + CHECK_LT((expected) - (tolerance), value); \ + CHECK_GT((expected) + (tolerance), value); + +#define CHECK_ESTIMATE_SPLAT(field, ex, tol) \ + CHECK_ESTIMATE(ex, tol, t.field[0]); \ + CHECK_ESTIMATE(ex, tol, t.field[1]); \ + CHECK_ESTIMATE(ex, tol, t.field[2]); \ + CHECK_ESTIMATE(ex, tol, t.field[3]); + +#define INT32_TO_FLOAT(val) \ + std::round(static_cast<float>(bit_cast<int32_t>(val))) +#define UINT32_TO_FLOAT(val) \ + std::round(static_cast<float>(bit_cast<uint32_t>(val))) TEST(15) { // Test the Neon instructions. @@ -1255,18 +1281,50 @@ TEST(15) { uint32_t dstA5; uint32_t dstA6; uint32_t dstA7; + uint32_t lane_test[4]; + uint64_t vmov_to_scalar1, vmov_to_scalar2; + uint32_t vmov_from_scalar_s8, vmov_from_scalar_u8; + uint32_t vmov_from_scalar_s16, vmov_from_scalar_u16; + uint32_t vmov_from_scalar_32; + uint32_t vmov[4], vmvn[4]; + int32_t vcvt_s32_f32[4]; + uint32_t vcvt_u32_f32[4]; + float vcvt_f32_s32[4], vcvt_f32_u32[4]; + uint32_t vdup8[4], vdup16[4], vdup32[4]; + float vabsf[4], vnegf[4]; + uint32_t vabs_s8[4], vabs_s16[4], vabs_s32[4]; + uint32_t vneg_s8[4], vneg_s16[4], vneg_s32[4]; + uint32_t veor[4], vand[4], vorr[4]; + float vdupf[4], vaddf[4], vsubf[4], vmulf[4]; + uint32_t vmin_s8[4], vmin_u16[4], vmin_s32[4]; + uint32_t vmax_s8[4], vmax_u16[4], vmax_s32[4]; + uint32_t vadd8[4], vadd16[4], vadd32[4]; + uint32_t vsub8[4], vsub16[4], vsub32[4]; + uint32_t vmul8[4], vmul16[4], vmul32[4]; + uint32_t vceq[4], vceqf[4], vcgef[4], vcgtf[4]; + uint32_t vcge_s8[4], vcge_u16[4], vcge_s32[4]; + uint32_t vcgt_s8[4], vcgt_u16[4], vcgt_s32[4]; + float vrecpe[4], vrecps[4], vrsqrte[4], vrsqrts[4]; + float vminf[4], vmaxf[4]; + uint32_t vtst[4], vbsl[4]; + uint32_t vext[4]; + uint32_t vzip8a[4], vzip8b[4], vzip16a[4], vzip16b[4], vzip32a[4], + vzip32b[4]; + uint32_t vrev64_32[4], vrev64_16[4], vrev64_8[4]; + uint32_t vrev32_16[4], vrev32_8[4]; + uint32_t vrev16_8[4]; + uint32_t vtbl[2], vtbx[2]; } T; T t; // Create a function that accepts &t, and loads, manipulates, and stores - // the doubles and floats. + // the doubles, floats, and SIMD values. Assembler assm(isolate, NULL, 0); - if (CpuFeatures::IsSupported(NEON)) { CpuFeatureScope scope(&assm, NEON); - __ stm(db_w, sp, r4.bit() | lr.bit()); + __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); // Move 32 bytes with neon. __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, src0)))); __ vld1(Neon8, NeonListOperand(d0, 4), NeonMemOperand(r4)); @@ -1287,7 +1345,456 @@ TEST(15) { __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, dstA4)))); __ vst1(Neon8, NeonListOperand(d2, 2), NeonMemOperand(r4)); - __ ldm(ia_w, sp, r4.bit() | pc.bit()); + // ARM core register to scalar. + __ mov(r4, Operand(0xfffffff8)); + __ vmov(d0, 0); + __ vmov(NeonS8, d0, 1, r4); + __ vmov(NeonS16, d0, 1, r4); + __ vmov(NeonS32, d0, 1, r4); + __ vstr(d0, r0, offsetof(T, vmov_to_scalar1)); + __ vmov(d0, 0); + __ vmov(NeonS8, d0, 3, r4); + __ vmov(NeonS16, d0, 3, r4); + __ vstr(d0, r0, offsetof(T, vmov_to_scalar2)); + + // Scalar to ARM core register. + __ mov(r4, Operand(0xffffff00)); + __ mov(r5, Operand(0xffffffff)); + __ vmov(d0, r4, r5); + __ vmov(NeonS8, r4, d0, 1); + __ str(r4, MemOperand(r0, offsetof(T, vmov_from_scalar_s8))); + __ vmov(NeonU8, r4, d0, 1); + __ str(r4, MemOperand(r0, offsetof(T, vmov_from_scalar_u8))); + __ vmov(NeonS16, r4, d0, 1); + __ str(r4, MemOperand(r0, offsetof(T, vmov_from_scalar_s16))); + __ vmov(NeonU16, r4, d0, 1); + __ str(r4, MemOperand(r0, offsetof(T, vmov_from_scalar_u16))); + __ vmov(NeonS32, r4, d0, 1); + __ str(r4, MemOperand(r0, offsetof(T, vmov_from_scalar_32))); + + // vmov for q-registers. + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vmov(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmov)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vmvn. + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vmvn(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmvn)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vcvt for q-registers. + __ vmov(s0, -1.5); + __ vmov(s1, -1); + __ vmov(s2, 1); + __ vmov(s3, 1.5); + __ vcvt_s32_f32(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcvt_s32_f32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vcvt_u32_f32(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcvt_u32_f32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(kMinInt)); + __ mov(r5, Operand(kMaxInt)); + __ vmov(d0, r4, r5); + __ mov(r4, Operand(kMaxUInt32)); + __ mov(r5, Operand(kMinInt + 1)); + __ vmov(d1, r4, r5); // q0 = [kMinInt, kMaxInt, kMaxUInt32, kMinInt + 1] + __ vcvt_f32_s32(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcvt_f32_s32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vcvt_f32_u32(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcvt_f32_u32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vdup (integer). + __ mov(r4, Operand(0xa)); + __ vdup(Neon8, q0, r4); + __ vdup(Neon16, q1, r4); + __ vdup(Neon32, q2, r4); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vdup8)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vdup16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vdup32)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + + // vdup (float). + __ vmov(s0, -1.0); + __ vdup(q0, s0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vdupf)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + // vabs (float). + __ vmov(s0, -1.0); + __ vmov(s1, -0.0); + __ vmov(s2, 0.0); + __ vmov(s3, 1.0); + __ vabs(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vabsf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vneg (float). + __ vneg(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vnegf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vabs (integer). + __ mov(r4, Operand(0x7f7f7f7f)); + __ mov(r5, Operand(0x01010101)); + __ vmov(d0, r4, r5); + __ mov(r4, Operand(0xffffffff)); + __ mov(r5, Operand(0x80808080)); + __ vmov(d1, r4, r5); + __ vabs(Neon8, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vabs_s8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vabs(Neon16, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vabs_s16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vabs(Neon32, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vabs_s32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vneg (integer). + __ vneg(Neon8, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vneg_s8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vneg(Neon16, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vneg_s16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vneg(Neon32, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vneg_s32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // veor. + __ mov(r4, Operand(0xaa)); + __ vdup(Neon16, q0, r4); + __ mov(r4, Operand(0x55)); + __ vdup(Neon16, q1, r4); + __ veor(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, veor)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vand. + __ mov(r4, Operand(0xff)); + __ vdup(Neon16, q0, r4); + __ mov(r4, Operand(0xfe)); + __ vdup(Neon16, q1, r4); + __ vand(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vand)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vorr. + __ mov(r4, Operand(0xaa)); + __ vdup(Neon16, q0, r4); + __ mov(r4, Operand(0x55)); + __ vdup(Neon16, q1, r4); + __ vorr(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vorr)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vmin (float). + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vmov(s4, 1.0); + __ vdup(q1, s4); + __ vmin(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vminf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vmax (float). + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vmov(s4, 1.0); + __ vdup(q1, s4); + __ vmax(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmaxf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vadd (float). + __ vmov(s4, 1.0); + __ vdup(q0, s4); + __ vdup(q1, s4); + __ vadd(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vaddf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vsub (float). + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vmov(s4, 1.0); + __ vdup(q1, s4); + __ vsub(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vsubf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vmul (float). + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vdup(q1, s4); + __ vmul(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmulf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vrecpe. + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vrecpe(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrecpe)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vrecps. + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vmov(s4, 1.5); + __ vdup(q1, s4); + __ vrecps(q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrecps)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vrsqrte. + __ vmov(s4, 4.0); + __ vdup(q0, s4); + __ vrsqrte(q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrsqrte)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vrsqrts. + __ vmov(s4, 2.0); + __ vdup(q0, s4); + __ vmov(s4, 2.5); + __ vdup(q1, s4); + __ vrsqrts(q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrsqrts)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vceq (float). + __ vmov(s4, 1.0); + __ vdup(q0, s4); + __ vdup(q1, s4); + __ vceq(q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vceqf)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + // vcge (float). + __ vmov(s0, 1.0); + __ vmov(s1, -1.0); + __ vmov(s2, -0.0); + __ vmov(s3, 0.0); + __ vdup(q1, s3); + __ vcge(q2, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcgef)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vcgt(q2, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcgtf)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + + // vmin/vmax integer. + __ mov(r4, Operand(0x03)); + __ vdup(Neon16, q0, r4); + __ vdup(Neon8, q1, r4); + __ vmin(NeonS8, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmin_s8)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vmax(NeonS8, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmax_s8)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ mov(r4, Operand(0xff)); + __ vdup(Neon16, q0, r4); + __ vdup(Neon8, q1, r4); + __ vmin(NeonU16, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmin_u16)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vmax(NeonU16, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmax_u16)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ mov(r4, Operand(0xff)); + __ vdup(Neon32, q0, r4); + __ vdup(Neon8, q1, r4); + __ vmin(NeonS32, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmin_s32)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vmax(NeonS32, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmax_s32)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + + // vadd (integer). + __ mov(r4, Operand(0x81)); + __ vdup(Neon8, q0, r4); + __ mov(r4, Operand(0x82)); + __ vdup(Neon8, q1, r4); + __ vadd(Neon8, q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vadd8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(0x8001)); + __ vdup(Neon16, q0, r4); + __ mov(r4, Operand(0x8002)); + __ vdup(Neon16, q1, r4); + __ vadd(Neon16, q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vadd16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(0x80000001)); + __ vdup(Neon32, q0, r4); + __ mov(r4, Operand(0x80000002)); + __ vdup(Neon32, q1, r4); + __ vadd(Neon32, q1, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vadd32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vsub (integer). + __ mov(r4, Operand(0x01)); + __ vdup(Neon8, q0, r4); + __ mov(r4, Operand(0x03)); + __ vdup(Neon8, q1, r4); + __ vsub(Neon8, q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vsub8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(0x0001)); + __ vdup(Neon16, q0, r4); + __ mov(r4, Operand(0x0003)); + __ vdup(Neon16, q1, r4); + __ vsub(Neon16, q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vsub16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(0x00000001)); + __ vdup(Neon32, q0, r4); + __ mov(r4, Operand(0x00000003)); + __ vdup(Neon32, q1, r4); + __ vsub(Neon32, q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vsub32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vmul (integer). + __ mov(r4, Operand(0x02)); + __ vdup(Neon8, q0, r4); + __ vmul(Neon8, q1, q0, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmul8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(0x0002)); + __ vdup(Neon16, q0, r4); + __ vmul(Neon16, q1, q0, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmul16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ mov(r4, Operand(0x00000002)); + __ vdup(Neon32, q0, r4); + __ vmul(Neon32, q1, q0, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vmul32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vceq. + __ mov(r4, Operand(0x03)); + __ vdup(Neon8, q0, r4); + __ vdup(Neon16, q1, r4); + __ vceq(Neon8, q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vceq)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vcge/vcgt (integer). + __ mov(r4, Operand(0x03)); + __ vdup(Neon16, q0, r4); + __ vdup(Neon8, q1, r4); + __ vcge(NeonS8, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcge_s8)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vcgt(NeonS8, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcgt_s8)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ mov(r4, Operand(0xff)); + __ vdup(Neon16, q0, r4); + __ vdup(Neon8, q1, r4); + __ vcge(NeonU16, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcge_u16)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vcgt(NeonU16, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcgt_u16)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ mov(r4, Operand(0xff)); + __ vdup(Neon32, q0, r4); + __ vdup(Neon8, q1, r4); + __ vcge(NeonS32, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcge_s32)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + __ vcgt(NeonS32, q2, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vcgt_s32)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + + // vtst. + __ mov(r4, Operand(0x03)); + __ vdup(Neon8, q0, r4); + __ mov(r4, Operand(0x02)); + __ vdup(Neon16, q1, r4); + __ vtst(Neon8, q1, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vtst)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vbsl. + __ mov(r4, Operand(0x00ff)); + __ vdup(Neon16, q0, r4); + __ mov(r4, Operand(0x01)); + __ vdup(Neon8, q1, r4); + __ mov(r4, Operand(0x02)); + __ vdup(Neon8, q2, r4); + __ vbsl(q0, q1, q2); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vbsl)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + // vext. + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vmov(q1, q0); + __ vext(q2, q0, q1, 3); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vext)))); + __ vst1(Neon8, NeonListOperand(q2), NeonMemOperand(r4)); + + // vzip. + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vmov(q1, q0); + __ vzip(Neon8, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vzip8a)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vzip8b)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vmov(q1, q0); + __ vzip(Neon16, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vzip16a)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vzip16b)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vmov(q1, q0); + __ vzip(Neon32, q0, q1); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vzip32a)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vzip32b)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vrev64/32/16 + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, lane_test)))); + __ vld1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ vrev64(Neon32, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrev64_32)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vrev64(Neon16, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrev64_16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vrev64(Neon8, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrev64_8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vrev32(Neon16, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrev32_16)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vrev32(Neon8, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrev32_8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + __ vrev16(Neon8, q1, q0); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, vrev16_8)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + // vtb[l/x]. + __ mov(r4, Operand(0x06040200)); + __ mov(r5, Operand(0xff050301)); + __ vmov(d2, r4, r5); // d2 = ff05030106040200 + __ vtbl(d0, NeonListOperand(d2, 1), d2); + __ vstr(d0, r0, offsetof(T, vtbl)); + __ vtbx(d2, NeonListOperand(d2, 1), d2); + __ vstr(d2, r0, offsetof(T, vtbx)); + + // Restore and return. + __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); CodeDesc desc; assm.GetCode(&desc); @@ -1324,8 +1831,13 @@ TEST(15) { t.dstA5 = 0; t.dstA6 = 0; t.dstA7 = 0; + t.lane_test[0] = 0x03020100; + t.lane_test[1] = 0x07060504; + t.lane_test[2] = 0x0b0a0908; + t.lane_test[3] = 0x0f0e0d0c; Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); USE(dummy); + CHECK_EQ(0x01020304u, t.dst0); CHECK_EQ(0x11121314u, t.dst1); CHECK_EQ(0x21222324u, t.dst2); @@ -1342,10 +1854,118 @@ TEST(15) { CHECK_EQ(0x00410042u, t.dstA5); CHECK_EQ(0x00830084u, t.dstA6); CHECK_EQ(0x00810082u, t.dstA7); + + CHECK_EQ(0xfffffff8fff8f800u, t.vmov_to_scalar1); + CHECK_EQ(0xfff80000f8000000u, t.vmov_to_scalar2); + CHECK_EQ(0xFFFFFFFFu, t.vmov_from_scalar_s8); + CHECK_EQ(0xFFu, t.vmov_from_scalar_u8); + CHECK_EQ(0xFFFFFFFFu, t.vmov_from_scalar_s16); + CHECK_EQ(0xFFFFu, t.vmov_from_scalar_u16); + CHECK_EQ(0xFFFFFFFFu, t.vmov_from_scalar_32); + + CHECK_EQ_32X4(vmov, 0x03020100u, 0x07060504u, 0x0b0a0908u, 0x0f0e0d0cu); + CHECK_EQ_32X4(vmvn, 0xfcfdfeffu, 0xf8f9fafbu, 0xf4f5f6f7u, 0xf0f1f2f3u); + + CHECK_EQ_SPLAT(vdup8, 0x0a0a0a0au); + CHECK_EQ_SPLAT(vdup16, 0x000a000au); + CHECK_EQ_SPLAT(vdup32, 0x0000000au); + CHECK_EQ_SPLAT(vdupf, -1.0); + + // src: [-1, -1, 1, 1] + CHECK_EQ_32X4(vcvt_s32_f32, -1, -1, 1, 1); + CHECK_EQ_32X4(vcvt_u32_f32, 0u, 0u, 1u, 1u); + // src: [kMinInt, kMaxInt, kMaxUInt32, kMinInt + 1] + CHECK_EQ_32X4(vcvt_f32_s32, INT32_TO_FLOAT(kMinInt), + INT32_TO_FLOAT(kMaxInt), INT32_TO_FLOAT(kMaxUInt32), + INT32_TO_FLOAT(kMinInt + 1)); + CHECK_EQ_32X4(vcvt_f32_u32, UINT32_TO_FLOAT(kMinInt), + UINT32_TO_FLOAT(kMaxInt), UINT32_TO_FLOAT(kMaxUInt32), + UINT32_TO_FLOAT(kMinInt + 1)); + + CHECK_EQ_32X4(vabsf, 1.0, 0.0, 0.0, 1.0); + CHECK_EQ_32X4(vnegf, 1.0, 0.0, -0.0, -1.0); + // src: [0x7f7f7f7f, 0x01010101, 0xffffffff, 0x80808080] + CHECK_EQ_32X4(vabs_s8, 0x7f7f7f7fu, 0x01010101u, 0x01010101u, 0x80808080u); + CHECK_EQ_32X4(vabs_s16, 0x7f7f7f7fu, 0x01010101u, 0x00010001u, 0x7f807f80u); + CHECK_EQ_32X4(vabs_s32, 0x7f7f7f7fu, 0x01010101u, 0x00000001u, 0x7f7f7f80u); + CHECK_EQ_32X4(vneg_s8, 0x81818181u, 0xffffffffu, 0x01010101u, 0x80808080u); + CHECK_EQ_32X4(vneg_s16, 0x80818081u, 0xfefffeffu, 0x00010001u, 0x7f807f80u); + CHECK_EQ_32X4(vneg_s32, 0x80808081u, 0xfefefeffu, 0x00000001u, 0x7f7f7f80u); + + CHECK_EQ_SPLAT(veor, 0x00ff00ffu); + CHECK_EQ_SPLAT(vand, 0x00fe00feu); + CHECK_EQ_SPLAT(vorr, 0x00ff00ffu); + CHECK_EQ_SPLAT(vaddf, 2.0); + CHECK_EQ_SPLAT(vminf, 1.0); + CHECK_EQ_SPLAT(vmaxf, 2.0); + CHECK_EQ_SPLAT(vsubf, -1.0); + CHECK_EQ_SPLAT(vmulf, 4.0); + CHECK_ESTIMATE_SPLAT(vrecpe, 0.5f, 0.1f); // 1 / 2 + CHECK_EQ_SPLAT(vrecps, -1.0f); // 2 - (2 * 1.5) + CHECK_ESTIMATE_SPLAT(vrsqrte, 0.5f, 0.1f); // 1 / sqrt(4) + CHECK_EQ_SPLAT(vrsqrts, -1.0f); // (3 - (2 * 2.5)) / 2 + CHECK_EQ_SPLAT(vceqf, 0xffffffffu); + // [0] >= [-1, 1, -0, 0] + CHECK_EQ_32X4(vcgef, 0u, 0xffffffffu, 0xffffffffu, 0xffffffffu); + CHECK_EQ_32X4(vcgtf, 0u, 0xffffffffu, 0u, 0u); + // [0, 3, 0, 3, ...] and [3, 3, 3, 3, ...] + CHECK_EQ_SPLAT(vmin_s8, 0x00030003u); + CHECK_EQ_SPLAT(vmax_s8, 0x03030303u); + // [0x00ff, 0x00ff, ...] and [0xffff, 0xffff, ...] + CHECK_EQ_SPLAT(vmin_u16, 0x00ff00ffu); + CHECK_EQ_SPLAT(vmax_u16, 0xffffffffu); + // [0x000000ff, 0x000000ff, ...] and [0xffffffff, 0xffffffff, ...] + CHECK_EQ_SPLAT(vmin_s32, 0xffffffffu); + CHECK_EQ_SPLAT(vmax_s32, 0xffu); + CHECK_EQ_SPLAT(vadd8, 0x03030303u); + CHECK_EQ_SPLAT(vadd16, 0x00030003u); + CHECK_EQ_SPLAT(vadd32, 0x00000003u); + CHECK_EQ_SPLAT(vsub8, 0xfefefefeu); + CHECK_EQ_SPLAT(vsub16, 0xfffefffeu); + CHECK_EQ_SPLAT(vsub32, 0xfffffffeu); + CHECK_EQ_SPLAT(vmul8, 0x04040404u); + CHECK_EQ_SPLAT(vmul16, 0x00040004u); + CHECK_EQ_SPLAT(vmul32, 0x00000004u); + CHECK_EQ_SPLAT(vceq, 0x00ff00ffu); + // [0, 3, 0, 3, ...] >= [3, 3, 3, 3, ...] + CHECK_EQ_SPLAT(vcge_s8, 0x00ff00ffu); + CHECK_EQ_SPLAT(vcgt_s8, 0u); + // [0x00ff, 0x00ff, ...] >= [0xffff, 0xffff, ...] + CHECK_EQ_SPLAT(vcge_u16, 0u); + CHECK_EQ_SPLAT(vcgt_u16, 0u); + // [0x000000ff, 0x000000ff, ...] >= [0xffffffff, 0xffffffff, ...] + CHECK_EQ_SPLAT(vcge_s32, 0xffffffffu); + CHECK_EQ_SPLAT(vcgt_s32, 0xffffffffu); + CHECK_EQ_SPLAT(vtst, 0x00ff00ffu); + CHECK_EQ_SPLAT(vbsl, 0x02010201u); + + CHECK_EQ_32X4(vext, 0x06050403u, 0x0a090807u, 0x0e0d0c0bu, 0x0201000fu); + + CHECK_EQ_32X4(vzip8a, 0x01010000u, 0x03030202u, 0x05050404u, 0x07070606u); + CHECK_EQ_32X4(vzip8b, 0x09090808u, 0x0b0b0a0au, 0x0d0d0c0cu, 0x0f0f0e0eu); + CHECK_EQ_32X4(vzip16a, 0x01000100u, 0x03020302u, 0x05040504u, 0x07060706u); + CHECK_EQ_32X4(vzip16b, 0x09080908u, 0x0b0a0b0au, 0x0d0c0d0cu, 0x0f0e0f0eu); + CHECK_EQ_32X4(vzip32a, 0x03020100u, 0x03020100u, 0x07060504u, 0x07060504u); + CHECK_EQ_32X4(vzip32b, 0x0b0a0908u, 0x0b0a0908u, 0x0f0e0d0cu, 0x0f0e0d0cu); + + // src: 0 1 2 3 4 5 6 7 8 9 a b c d e f (little endian) + CHECK_EQ_32X4(vrev64_32, 0x07060504u, 0x03020100u, 0x0f0e0d0cu, + 0x0b0a0908u); + CHECK_EQ_32X4(vrev64_16, 0x05040706u, 0x01000302u, 0x0d0c0f0eu, + 0x09080b0au); + CHECK_EQ_32X4(vrev64_8, 0x04050607u, 0x00010203u, 0x0c0d0e0fu, 0x08090a0bu); + CHECK_EQ_32X4(vrev32_16, 0x01000302u, 0x05040706u, 0x09080b0au, + 0x0d0c0f0eu); + CHECK_EQ_32X4(vrev32_8, 0x00010203u, 0x04050607u, 0x08090a0bu, 0x0c0d0e0fu); + CHECK_EQ_32X4(vrev16_8, 0x02030001u, 0x06070405u, 0x0a0b0809u, 0x0e0f0c0du); + + CHECK_EQ(0x05010400u, t.vtbl[0]); + CHECK_EQ(0x00030602u, t.vtbl[1]); + CHECK_EQ(0x05010400u, t.vtbx[0]); + CHECK_EQ(0xff030602u, t.vtbx[1]); } } - TEST(16) { // Test the pkh, uxtb, uxtab and uxtb16 instructions. CcTest::InitializeVM(); @@ -2881,33 +3501,63 @@ TEST(unaligned_stores) { } TEST(vswp) { + if (!CpuFeatures::IsSupported(NEON)) return; + CcTest::InitializeVM(); Isolate* isolate = CcTest::i_isolate(); HandleScope scope(isolate); Assembler assm(isolate, NULL, 0); typedef struct { - double result0; - double result1; - double result2; - double result3; + uint64_t vswp_d0; + uint64_t vswp_d1; + uint64_t vswp_d30; + uint64_t vswp_d31; + uint32_t vswp_q4[4]; + uint32_t vswp_q5[4]; } T; T t; - __ vmov(d0, 1.0); - __ vmov(d1, -1.0); + __ stm(db_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | lr.bit()); + + uint64_t one = bit_cast<uint64_t>(1.0); + __ mov(r5, Operand(one >> 32)); + __ mov(r4, Operand(one & 0xffffffff)); + uint64_t minus_one = bit_cast<uint64_t>(-1.0); + __ mov(r7, Operand(minus_one >> 32)); + __ mov(r6, Operand(minus_one & 0xffffffff)); + + __ vmov(d0, r4, r5); // d0 = 1.0 + __ vmov(d1, r6, r7); // d1 = -1.0 __ vswp(d0, d1); - __ vstr(d0, r0, offsetof(T, result0)); - __ vstr(d1, r0, offsetof(T, result1)); + __ vstr(d0, r0, offsetof(T, vswp_d0)); + __ vstr(d1, r0, offsetof(T, vswp_d1)); if (CpuFeatures::IsSupported(VFP32DREGS)) { - __ vmov(d30, 1.0); - __ vmov(d31, -1.0); + __ vmov(d30, r4, r5); // d30 = 1.0 + __ vmov(d31, r6, r7); // d31 = -1.0 __ vswp(d30, d31); - __ vstr(d30, r0, offsetof(T, result2)); - __ vstr(d31, r0, offsetof(T, result3)); + __ vstr(d30, r0, offsetof(T, vswp_d30)); + __ vstr(d31, r0, offsetof(T, vswp_d31)); } + // q-register swap. + const uint32_t test_1 = 0x01234567; + const uint32_t test_2 = 0x89abcdef; + __ mov(r4, Operand(test_1)); + __ mov(r5, Operand(test_2)); + // TODO(bbudge) replace with vdup when implemented. + __ vmov(d8, r4, r4); + __ vmov(d9, r4, r4); // q4 = [1.0, 1.0] + __ vmov(d10, r5, r5); + __ vmov(d11, r5, r5); // q5 = [-1.0, -1.0] + __ vswp(q4, q5); + __ add(r6, r0, Operand(static_cast<int32_t>(offsetof(T, vswp_q4)))); + __ vst1(Neon8, NeonListOperand(q4), NeonMemOperand(r6)); + __ add(r6, r0, Operand(static_cast<int32_t>(offsetof(T, vswp_q5)))); + __ vst1(Neon8, NeonListOperand(q5), NeonMemOperand(r6)); + + __ ldm(ia_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | pc.bit()); __ bx(lr); CodeDesc desc; @@ -2921,12 +3571,20 @@ TEST(vswp) { F3 f = FUNCTION_CAST<F3>(code->entry()); Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); USE(dummy); - CHECK_EQ(-1.0, t.result0); - CHECK_EQ(1.0, t.result1); + CHECK_EQ(minus_one, t.vswp_d0); + CHECK_EQ(one, t.vswp_d1); if (CpuFeatures::IsSupported(VFP32DREGS)) { - CHECK_EQ(-1.0, t.result2); - CHECK_EQ(1.0, t.result3); + CHECK_EQ(minus_one, t.vswp_d30); + CHECK_EQ(one, t.vswp_d31); } + CHECK_EQ(t.vswp_q4[0], test_2); + CHECK_EQ(t.vswp_q4[1], test_2); + CHECK_EQ(t.vswp_q4[2], test_2); + CHECK_EQ(t.vswp_q4[3], test_2); + CHECK_EQ(t.vswp_q5[0], test_1); + CHECK_EQ(t.vswp_q5[1], test_1); + CHECK_EQ(t.vswp_q5[2], test_1); + CHECK_EQ(t.vswp_q5[3], test_1); } TEST(regress4292_b) { diff --git a/deps/v8/test/cctest/test-assembler-mips.cc b/deps/v8/test/cctest/test-assembler-mips.cc index 08d3c606c0..191589a73a 100644 --- a/deps/v8/test/cctest/test-assembler-mips.cc +++ b/deps/v8/test/cctest/test-assembler-mips.cc @@ -5457,12 +5457,14 @@ void helper_madd_msub_maddf_msubf(F func) { (CALL_GENERATED_CODE(isolate, f, &tc, 0, 0, 0, 0)); - T res_add = tc.fr + (tc.fs * tc.ft); + T res_add = 0; T res_sub = 0; if (IsMipsArchVariant(kMips32r2)) { + res_add = (tc.fs * tc.ft) + tc.fr; res_sub = (tc.fs * tc.ft) - tc.fr; } else if (IsMipsArchVariant(kMips32r6)) { - res_sub = tc.fr - (tc.fs * tc.ft); + res_add = std::fma(tc.fs, tc.ft, tc.fr); + res_sub = std::fma(-tc.fs, tc.ft, tc.fr); } else { UNREACHABLE(); } diff --git a/deps/v8/test/cctest/test-assembler-mips64.cc b/deps/v8/test/cctest/test-assembler-mips64.cc index b0315343b5..0ec51723e9 100644 --- a/deps/v8/test/cctest/test-assembler-mips64.cc +++ b/deps/v8/test/cctest/test-assembler-mips64.cc @@ -6005,12 +6005,14 @@ void helper_madd_msub_maddf_msubf(F func) { (CALL_GENERATED_CODE(isolate, f, &tc, 0, 0, 0, 0)); - T res_add = tc.fr + (tc.fs * tc.ft); T res_sub; + T res_add; if (kArchVariant != kMips64r6) { + res_add = tc.fr + (tc.fs * tc.ft); res_sub = (tc.fs * tc.ft) - tc.fr; } else { - res_sub = tc.fr - (tc.fs * tc.ft); + res_add = std::fma(tc.fs, tc.ft, tc.fr); + res_sub = std::fma(-tc.fs, tc.ft, tc.fr); } CHECK_EQ(tc.fd_add, res_add); diff --git a/deps/v8/test/cctest/test-assembler-s390.cc b/deps/v8/test/cctest/test-assembler-s390.cc index ab6796bf18..f6b79d4994 100644 --- a/deps/v8/test/cctest/test-assembler-s390.cc +++ b/deps/v8/test/cctest/test-assembler-s390.cc @@ -194,8 +194,8 @@ TEST(3) { __ ay(r13, MemOperand(r1, r2, 123)); __ brc(Condition(14), Operand(123)); __ brc(Condition(14), Operand(-123)); - __ brcl(Condition(14), Operand(123), false); - __ brcl(Condition(14), Operand(-123), false); + __ brcl(Condition(14), Operand(123)); + __ brcl(Condition(14), Operand(-123)); __ iilf(r13, Operand(123456789)); __ iihf(r13, Operand(-123456789)); __ mvc(MemOperand(r0, 123), MemOperand(r4, 567), 89); @@ -413,4 +413,89 @@ TEST(9) { } #endif +// Test msrkc and msgrkc +TEST(10) { + if (!CpuFeatures::IsSupported(MISC_INSTR_EXT2)) { + return; + } + + ::printf("MISC_INSTR_EXT2 is enabled.\n"); + + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + Assembler assm(isolate, NULL, 0); + + Label ok, failed; + + { // test 1: msrkc + __ lgfi(r2, Operand(3)); + __ lgfi(r3, Operand(4)); + __ msrkc(r1, r2, r3); // 3 * 4 + __ b(static_cast<Condition>(le | overflow), &failed); // test failed. + __ chi(r1, Operand(12)); + __ bne(&failed); // test failed. + + __ lgfi(r2, Operand(-3)); + __ lgfi(r3, Operand(4)); + __ msrkc(r1, r2, r3); // -3 * 4 + __ b(static_cast<Condition>(ge | overflow), &failed); // test failed. + __ chi(r1, Operand(-12)); + __ bne(&failed); // test failed. + + __ iilf(r2, Operand(0x80000000)); + __ lgfi(r3, Operand(-1)); + __ msrkc(r1, r2, r3); // INT_MIN * -1 + __ b(nooverflow, &failed); // test failed. + __ cfi(r1, Operand(0x80000000)); + __ bne(&failed); // test failed. + } + + { // test 1: msgrkc + __ lgfi(r2, Operand(3)); + __ lgfi(r3, Operand(4)); + __ msgrkc(r1, r2, r3); // 3 * 4 + __ b(static_cast<Condition>(le | overflow), &failed); // test failed. + __ chi(r1, Operand(12)); + __ bne(&failed); // test failed. + + __ lgfi(r2, Operand(-3)); + __ lgfi(r3, Operand(4)); + __ msgrkc(r1, r2, r3); // -3 * 4 + __ b(static_cast<Condition>(ge | overflow), &failed); // test failed. + __ chi(r1, Operand(-12)); + __ bne(&failed); // test failed. + + __ lgfi(r2, Operand::Zero()); + __ iihf(r2, Operand(0x80000000)); + __ lgfi(r3, Operand(-1)); + __ msgrkc(r1, r2, r3); // INT_MIN * -1 + __ b(nooverflow, &failed); // test failed. + __ cgr(r1, r2); + __ bne(&failed); // test failed. + } + + __ bind(&ok); + __ lgfi(r2, Operand::Zero()); + __ b(r14); // test done. + + __ bind(&failed); + __ lgfi(r2, Operand(1)); + __ b(r14); + + CodeDesc desc; + assm.GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + code->Print(); +#endif + F2 f = FUNCTION_CAST<F2>(code->entry()); + intptr_t res = reinterpret_cast<intptr_t>( + CALL_GENERATED_CODE(isolate, f, 3, 4, 0, 0, 0)); + ::printf("f() = %" V8PRIxPTR "\n", res); + CHECK_EQ(0, static_cast<int>(res)); +} + #undef __ diff --git a/deps/v8/test/cctest/test-assembler-x64.cc b/deps/v8/test/cctest/test-assembler-x64.cc index 36f1b30df9..0ea854d7fe 100644 --- a/deps/v8/test/cctest/test-assembler-x64.cc +++ b/deps/v8/test/cctest/test-assembler-x64.cc @@ -173,6 +173,22 @@ TEST(AssemblerX64CmpbOperation) { CHECK_EQ(0, result); } +TEST(Regression684407) { + CcTest::InitializeVM(); + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( + Assembler::kMinimalBufferSize, &actual_size, true)); + CHECK(buffer); + Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); + Address before = assm.pc(); + __ cmpl(Operand(arg1, 0), + Immediate(0, RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); + Address after = assm.pc(); + size_t instruction_size = static_cast<size_t>(after - before); + // Check that the immediate is not encoded as uint8. + CHECK_LT(sizeof(uint32_t), instruction_size); +} TEST(AssemblerX64ImulOperation) { CcTest::InitializeVM(); @@ -201,6 +217,173 @@ TEST(AssemblerX64ImulOperation) { CHECK_EQ(-1, result); } +TEST(AssemblerX64testbwqOperation) { + CcTest::InitializeVM(); + v8::HandleScope scope(CcTest::isolate()); + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( + Assembler::kMinimalBufferSize, &actual_size, true)); + CHECK(buffer); + Assembler assm(CcTest::i_isolate(), buffer, static_cast<int>(actual_size)); + + __ pushq(rbx); + __ pushq(rdi); + __ pushq(rsi); + __ pushq(r12); + __ pushq(r13); + __ pushq(r14); + __ pushq(r15); + + // Assemble a simple function that tests testb and testw + Label bad; + Label done; + + // Test immediate testb and testw + __ movq(rax, Immediate(2)); + __ movq(rbx, Immediate(4)); + __ movq(rcx, Immediate(8)); + __ movq(rdx, Immediate(16)); + __ movq(rsi, Immediate(32)); + __ movq(rdi, Immediate(64)); + __ movq(r10, Immediate(128)); + __ movq(r11, Immediate(0)); + __ movq(r12, Immediate(0)); + __ movq(r13, Immediate(0)); + __ testb(rax, Immediate(2)); + __ j(zero, &bad); + __ testb(rbx, Immediate(4)); + __ j(zero, &bad); + __ testb(rcx, Immediate(8)); + __ j(zero, &bad); + __ testb(rdx, Immediate(16)); + __ j(zero, &bad); + __ testb(rsi, Immediate(32)); + __ j(zero, &bad); + __ testb(rdi, Immediate(64)); + __ j(zero, &bad); + __ testb(r10, Immediate(128)); + __ j(zero, &bad); + __ testw(rax, Immediate(2)); + __ j(zero, &bad); + __ testw(rbx, Immediate(4)); + __ j(zero, &bad); + __ testw(rcx, Immediate(8)); + __ j(zero, &bad); + __ testw(rdx, Immediate(16)); + __ j(zero, &bad); + __ testw(rsi, Immediate(32)); + __ j(zero, &bad); + __ testw(rdi, Immediate(64)); + __ j(zero, &bad); + __ testw(r10, Immediate(128)); + __ j(zero, &bad); + + // Test reg, reg testb and testw + __ movq(rax, Immediate(2)); + __ movq(rbx, Immediate(2)); + __ testb(rax, rbx); + __ j(zero, &bad); + __ movq(rbx, Immediate(4)); + __ movq(rax, Immediate(4)); + __ testb(rbx, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(8)); + __ testb(rcx, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(16)); + __ testb(rdx, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(32)); + __ testb(rsi, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(64)); + __ testb(rdi, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(128)); + __ testb(r10, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(2)); + __ movq(rbx, Immediate(2)); + __ testw(rax, rbx); + __ j(zero, &bad); + __ movq(rbx, Immediate(4)); + __ movq(rax, Immediate(4)); + __ testw(rbx, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(8)); + __ testw(rcx, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(16)); + __ testw(rdx, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(32)); + __ testw(rsi, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(64)); + __ testw(rdi, rax); + __ j(zero, &bad); + __ movq(rax, Immediate(128)); + __ testw(r10, rax); + __ j(zero, &bad); + + // Test diffrrent extended register coding combinations. + __ movq(rax, Immediate(5)); + __ movq(r11, Immediate(5)); + __ testb(r11, rax); + __ j(zero, &bad); + __ testb(rax, r11); + __ j(zero, &bad); + __ testw(r11, rax); + __ j(zero, &bad); + __ testw(rax, r11); + __ j(zero, &bad); + __ movq(r11, Immediate(3)); + __ movq(r12, Immediate(3)); + __ movq(rdi, Immediate(3)); + __ testb(r12, rdi); + __ j(zero, &bad); + __ testb(rdi, r12); + __ j(zero, &bad); + __ testb(r12, r11); + __ j(zero, &bad); + __ testb(r11, r12); + __ j(zero, &bad); + __ testw(r12, r11); + __ j(zero, &bad); + __ testw(r11, r12); + __ j(zero, &bad); + + // Test sign-extended imediate tests + __ movq(r11, Immediate(2)); + __ shlq(r11, Immediate(32)); + __ testq(r11, Immediate(-1)); + __ j(zero, &bad); + + // All tests passed + __ movq(rax, Immediate(1)); + __ jmp(&done); + + __ bind(&bad); + __ movq(rax, Immediate(0)); + __ bind(&done); + + __ popq(r15); + __ popq(r14); + __ popq(r13); + __ popq(r12); + __ popq(rsi); + __ popq(rdi); + __ popq(rbx); + + __ ret(0); + + CodeDesc desc; + assm.GetCode(&desc); + // Call the function from C++. + int result = FUNCTION_CAST<F2>(buffer)(0, 0); + CHECK_EQ(1, result); +} TEST(AssemblerX64XchglOperations) { CcTest::InitializeVM(); diff --git a/deps/v8/test/cctest/test-ast.cc b/deps/v8/test/cctest/test-ast.cc index dfb4d11236..c027e88a52 100644 --- a/deps/v8/test/cctest/test-ast.cc +++ b/deps/v8/test/cctest/test-ast.cc @@ -30,18 +30,24 @@ #include "src/v8.h" #include "src/ast/ast.h" +#include "src/isolate.h" +#include "src/objects-inl.h" #include "src/zone/accounting-allocator.h" #include "test/cctest/cctest.h" using namespace v8::internal; TEST(List) { + v8::V8::Initialize(); + Isolate* isolate = CcTest::i_isolate(); + List<AstNode*>* list = new List<AstNode*>(0); CHECK_EQ(0, list->length()); v8::internal::AccountingAllocator allocator; Zone zone(&allocator, ZONE_NAME); - AstValueFactory value_factory(&zone, 0); + AstValueFactory value_factory(&zone, isolate->ast_string_constants(), + isolate->heap()->HashSeed()); AstNodeFactory factory(&value_factory); AstNode* node = factory.NewEmptyStatement(kNoSourcePosition); list->Add(node); @@ -59,43 +65,3 @@ TEST(List) { CHECK_EQ(0, list->length()); delete list; } - -TEST(ConcatStrings) { - v8::internal::AccountingAllocator allocator; - Zone zone(&allocator, ZONE_NAME); - AstValueFactory value_factory(&zone, 0); - - const AstRawString* one_byte = value_factory.GetOneByteString("a"); - - uint16_t two_byte_buffer[] = { - 0x3b1, - }; - const AstRawString* two_byte = value_factory.GetTwoByteString( - Vector<const uint16_t>(two_byte_buffer, 1)); - - const AstRawString* expectation = value_factory.GetOneByteString("aa"); - const AstRawString* result = value_factory.ConcatStrings(one_byte, one_byte); - CHECK(result->is_one_byte()); - CHECK_EQ(expectation, result); - - uint16_t expectation_buffer_one_two[] = {'a', 0x3b1}; - expectation = value_factory.GetTwoByteString( - Vector<const uint16_t>(expectation_buffer_one_two, 2)); - result = value_factory.ConcatStrings(one_byte, two_byte); - CHECK(!result->is_one_byte()); - CHECK_EQ(expectation, result); - - uint16_t expectation_buffer_two_one[] = {0x3b1, 'a'}; - expectation = value_factory.GetTwoByteString( - Vector<const uint16_t>(expectation_buffer_two_one, 2)); - result = value_factory.ConcatStrings(two_byte, one_byte); - CHECK(!result->is_one_byte()); - CHECK_EQ(expectation, result); - - uint16_t expectation_buffer_two_two[] = {0x3b1, 0x3b1}; - expectation = value_factory.GetTwoByteString( - Vector<const uint16_t>(expectation_buffer_two_two, 2)); - result = value_factory.ConcatStrings(two_byte, two_byte); - CHECK(!result->is_one_byte()); - CHECK_EQ(expectation, result); -} diff --git a/deps/v8/test/cctest/test-code-stub-assembler.cc b/deps/v8/test/cctest/test-code-stub-assembler.cc index da2773fdca..068ef9c3d1 100644 --- a/deps/v8/test/cctest/test-code-stub-assembler.cc +++ b/deps/v8/test/cctest/test-code-stub-assembler.cc @@ -3,10 +3,10 @@ // found in the LICENSE file. #include "src/base/utils/random-number-generator.h" +#include "src/builtins/builtins-promise.h" #include "src/code-factory.h" #include "src/code-stub-assembler.h" #include "src/compiler/node.h" -#include "src/ic/stub-cache.h" #include "src/isolate.h" #include "test/cctest/compiler/code-assembler-tester.h" #include "test/cctest/compiler/function-tester.h" @@ -14,48 +14,49 @@ namespace v8 { namespace internal { +using compiler::CodeAssemblerTester; using compiler::FunctionTester; using compiler::Node; - -typedef compiler::CodeAssemblerTesterImpl<CodeStubAssembler> - CodeStubAssemblerTester; +using compiler::CodeAssemblerLabel; +using compiler::CodeAssemblerVariable; +using compiler::CodeAssemblerVariableList; TEST(FixedArrayAccessSmiIndex) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeStubAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeStubAssembler m(data.state()); Handle<FixedArray> array = isolate->factory()->NewFixedArray(5); array->set(4, Smi::FromInt(733)); m.Return(m.LoadFixedArrayElement(m.HeapConstant(array), m.SmiTag(m.Int32Constant(4)), 0, CodeStubAssembler::SMI_PARAMETERS)); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(733, Handle<Smi>::cast(result.ToHandleChecked())->value()); } TEST(LoadHeapNumberValue) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeStubAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeStubAssembler m(data.state()); Handle<HeapNumber> number = isolate->factory()->NewHeapNumber(1234); - m.Return(m.SmiTag( + m.Return(m.SmiFromWord32( m.ChangeFloat64ToUint32(m.LoadHeapNumberValue(m.HeapConstant(number))))); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(1234, Handle<Smi>::cast(result.ToHandleChecked())->value()); } TEST(LoadInstanceType) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeStubAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeStubAssembler m(data.state()); Handle<HeapObject> undefined = isolate->factory()->undefined_value(); - m.Return(m.SmiTag(m.LoadInstanceType(m.HeapConstant(undefined)))); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + m.Return(m.SmiFromWord32(m.LoadInstanceType(m.HeapConstant(undefined)))); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); CHECK_EQ(InstanceType::ODDBALL_TYPE, Handle<Smi>::cast(result.ToHandleChecked())->value()); @@ -63,14 +64,14 @@ TEST(LoadInstanceType) { TEST(DecodeWordFromWord32) { Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeStubAssemblerTester m(isolate, descriptor); + CodeAssemblerTester data(isolate); + CodeStubAssembler m(data.state()); class TestBitField : public BitField<unsigned, 3, 3> {}; m.Return( m.SmiTag(m.DecodeWordFromWord32<TestBitField>(m.Int32Constant(0x2f)))); - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(descriptor, code); + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code); MaybeHandle<Object> result = ft.Call(); // value = 00101111 // mask = 00111000 @@ -81,11 +82,12 @@ TEST(DecodeWordFromWord32) { TEST(JSFunction) { const int kNumParams = 3; // Receiver, left, right. Isolate* isolate(CcTest::InitIsolateOnce()); - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.Return(m.SmiFromWord32(m.Int32Add(m.SmiToWord32(m.Parameter(1)), m.SmiToWord32(m.Parameter(2))))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); MaybeHandle<Object> result = ft.Call(isolate->factory()->undefined_value(), @@ -97,11 +99,12 @@ TEST(JSFunction) { TEST(ComputeIntegerHash) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 2; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.Return(m.SmiFromWord32(m.ComputeIntegerHash( - m.SmiToWord32(m.Parameter(0)), m.SmiToWord32(m.Parameter(1))))); + m.SmiUntag(m.Parameter(0)), m.SmiToWord32(m.Parameter(1))))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Smi> hash_seed = isolate->factory()->hash_seed(); @@ -123,10 +126,11 @@ TEST(ComputeIntegerHash) { TEST(ToString) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 1; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.Return(m.ToString(m.Parameter(kNumParams + 2), m.Parameter(0))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<FixedArray> test_cases = isolate->factory()->NewFixedArray(5); @@ -179,10 +183,11 @@ TEST(ToString) { TEST(FlattenString) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 1; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.Return(m.FlattenString(m.Parameter(0))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<FixedArray> test_cases(isolate->factory()->NewFixedArray(4)); @@ -217,12 +222,13 @@ TEST(FlattenString) { } TEST(TryToName) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 3; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); enum Result { kKeyIsIndex, kKeyIsUnique, kBailout }; { @@ -261,7 +267,7 @@ TEST(TryToName) { m.Return(m.BooleanConstant(false)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Object> expect_index(Smi::FromInt(kKeyIsIndex), isolate); @@ -352,14 +358,15 @@ void TestEntryToIndex() { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 1; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); { Node* entry = m.SmiUntag(m.Parameter(0)); Node* result = m.EntryToIndex<Dictionary>(entry); m.Return(m.SmiTag(result)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); // Test a wide range of entries but staying linear in the first 100 entries. @@ -380,12 +387,13 @@ namespace { template <typename Dictionary> void TestNameDictionaryLookup() { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); enum Result { kFound, kNotFound }; { @@ -404,7 +412,7 @@ void TestNameDictionaryLookup() { m.GotoUnless( m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))), &failed); - m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_name_index.value()), + m.Branch(m.WordEqual(m.SmiUntag(expected_arg), var_name_index.value()), &passed, &failed); m.Bind(&if_not_found); @@ -419,7 +427,7 @@ void TestNameDictionaryLookup() { m.Return(m.BooleanConstant(false)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Object> expect_found(Smi::FromInt(kFound), isolate); @@ -486,17 +494,18 @@ namespace { template <typename Dictionary> void TestNumberDictionaryLookup() { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); enum Result { kFound, kNotFound }; { Node* dictionary = m.Parameter(0); - Node* key = m.SmiToWord32(m.Parameter(1)); + Node* key = m.SmiUntag(m.Parameter(1)); Node* expected_result = m.Parameter(2); Node* expected_arg = m.Parameter(3); @@ -510,8 +519,8 @@ void TestNumberDictionaryLookup() { m.GotoUnless( m.WordEqual(expected_result, m.SmiConstant(Smi::FromInt(kFound))), &failed); - m.Branch(m.Word32Equal(m.SmiToWord32(expected_arg), var_entry.value()), - &passed, &failed); + m.Branch(m.WordEqual(m.SmiUntag(expected_arg), var_entry.value()), &passed, + &failed); m.Bind(&if_not_found); m.Branch( @@ -525,7 +534,7 @@ void TestNumberDictionaryLookup() { m.Return(m.BooleanConstant(false)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Object> expect_found(Smi::FromInt(kFound), isolate); @@ -624,11 +633,12 @@ void AddProperties(Handle<JSObject> object, Handle<Name> names[], } // namespace TEST(TryHasOwnProperty) { - typedef CodeStubAssembler::Label Label; + typedef CodeAssemblerLabel Label; Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); enum Result { kFound, kNotFound, kBailout }; { @@ -666,7 +676,7 @@ TEST(TryHasOwnProperty) { m.Return(m.BooleanConstant(false)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Object> expect_found(Smi::FromInt(kFound), isolate); @@ -808,13 +818,14 @@ TEST(TryHasOwnProperty) { } TEST(TryGetOwnProperty) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; + typedef CodeAssemblerLabel Label; + typedef CodeAssemblerVariable Variable; Isolate* isolate(CcTest::InitIsolateOnce()); Factory* factory = isolate->factory(); const int kNumParams = 2; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); Handle<Symbol> not_found_symbol = factory->NewSymbol(); Handle<Symbol> bailout_symbol = factory->NewSymbol(); @@ -843,7 +854,7 @@ TEST(TryGetOwnProperty) { m.Return(m.HeapConstant(bailout_symbol)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Name> deleted_property_name = @@ -1026,16 +1037,17 @@ void AddElement(Handle<JSObject> object, uint32_t index, Handle<Object> value, } // namespace TEST(TryLookupElement) { - typedef CodeStubAssembler::Label Label; + typedef CodeAssemblerLabel Label; Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 3; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); enum Result { kFound, kNotFound, kBailout }; { Node* object = m.Parameter(0); - Node* index = m.SmiToWord32(m.Parameter(1)); + Node* index = m.SmiUntag(m.Parameter(1)); Node* expected_result = m.Parameter(2); Label passed(&m), failed(&m); @@ -1068,7 +1080,7 @@ TEST(TryLookupElement) { m.Return(m.BooleanConstant(false)); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Factory* factory = isolate->factory(); @@ -1211,434 +1223,13 @@ TEST(TryLookupElement) { } } -TEST(DeferredCodePhiHints) { - typedef compiler::Node Node; - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; - Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeStubAssemblerTester m(isolate, descriptor); - Label block1(&m, Label::kDeferred); - m.Goto(&block1); - m.Bind(&block1); - { - Variable var_object(&m, MachineRepresentation::kTagged); - Label loop(&m, &var_object); - var_object.Bind(m.IntPtrConstant(0)); - m.Goto(&loop); - m.Bind(&loop); - { - Node* map = m.LoadMap(var_object.value()); - var_object.Bind(map); - m.Goto(&loop); - } - } - CHECK(!m.GenerateCode().is_null()); -} - -TEST(TestOutOfScopeVariable) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; - Isolate* isolate(CcTest::InitIsolateOnce()); - VoidDescriptor descriptor(isolate); - CodeStubAssemblerTester m(isolate, descriptor); - Label block1(&m); - Label block2(&m); - Label block3(&m); - Label block4(&m); - m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block1, &block4); - m.Bind(&block4); - { - Variable var_object(&m, MachineRepresentation::kTagged); - m.Branch(m.WordEqual(m.Parameter(0), m.IntPtrConstant(0)), &block2, - &block3); - - m.Bind(&block2); - var_object.Bind(m.IntPtrConstant(55)); - m.Goto(&block1); - - m.Bind(&block3); - var_object.Bind(m.IntPtrConstant(66)); - m.Goto(&block1); - } - m.Bind(&block1); - CHECK(!m.GenerateCode().is_null()); -} - -namespace { - -void TestStubCacheOffsetCalculation(StubCache::Table table) { - Isolate* isolate(CcTest::InitIsolateOnce()); - const int kNumParams = 2; - CodeStubAssemblerTester m(isolate, kNumParams); - - { - Node* name = m.Parameter(0); - Node* map = m.Parameter(1); - Node* primary_offset = m.StubCachePrimaryOffset(name, map); - Node* result; - if (table == StubCache::kPrimary) { - result = primary_offset; - } else { - CHECK_EQ(StubCache::kSecondary, table); - result = m.StubCacheSecondaryOffset(name, primary_offset); - } - m.Return(m.SmiFromWord32(result)); - } - - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(code, kNumParams); - - Factory* factory = isolate->factory(); - Handle<Name> names[] = { - factory->NewSymbol(), - factory->InternalizeUtf8String("a"), - factory->InternalizeUtf8String("bb"), - factory->InternalizeUtf8String("ccc"), - factory->NewPrivateSymbol(), - factory->InternalizeUtf8String("dddd"), - factory->InternalizeUtf8String("eeeee"), - factory->InternalizeUtf8String("name"), - factory->NewSymbol(), - factory->NewPrivateSymbol(), - }; - - Handle<Map> maps[] = { - Handle<Map>(nullptr, isolate), - factory->cell_map(), - Map::Create(isolate, 0), - factory->meta_map(), - factory->code_map(), - Map::Create(isolate, 0), - factory->hash_table_map(), - factory->symbol_map(), - factory->string_map(), - Map::Create(isolate, 0), - factory->sloppy_arguments_elements_map(), - }; - - for (size_t name_index = 0; name_index < arraysize(names); name_index++) { - Handle<Name> name = names[name_index]; - for (size_t map_index = 0; map_index < arraysize(maps); map_index++) { - Handle<Map> map = maps[map_index]; - - int expected_result; - { - int primary_offset = StubCache::PrimaryOffsetForTesting(*name, *map); - if (table == StubCache::kPrimary) { - expected_result = primary_offset; - } else { - expected_result = - StubCache::SecondaryOffsetForTesting(*name, primary_offset); - } - } - Handle<Object> result = ft.Call(name, map).ToHandleChecked(); - - Smi* expected = Smi::FromInt(expected_result & Smi::kMaxValue); - CHECK_EQ(expected, Smi::cast(*result)); - } - } -} - -} // namespace - -TEST(StubCachePrimaryOffset) { - TestStubCacheOffsetCalculation(StubCache::kPrimary); -} - -TEST(StubCacheSecondaryOffset) { - TestStubCacheOffsetCalculation(StubCache::kSecondary); -} - -namespace { - -Handle<Code> CreateCodeWithFlags(Code::Flags flags) { - Isolate* isolate(CcTest::InitIsolateOnce()); - CodeStubAssemblerTester m(isolate, flags); - m.Return(m.UndefinedConstant()); - return m.GenerateCodeCloseAndEscape(); -} - -} // namespace - -TEST(TryProbeStubCache) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; - Isolate* isolate(CcTest::InitIsolateOnce()); - const int kNumParams = 3; - CodeStubAssemblerTester m(isolate, kNumParams); - - Code::Kind ic_kind = Code::LOAD_IC; - StubCache stub_cache(isolate, ic_kind); - stub_cache.Clear(); - - { - Node* receiver = m.Parameter(0); - Node* name = m.Parameter(1); - Node* expected_handler = m.Parameter(2); - - Label passed(&m), failed(&m); - - Variable var_handler(&m, MachineRepresentation::kTagged); - Label if_handler(&m), if_miss(&m); - - m.TryProbeStubCache(&stub_cache, receiver, name, &if_handler, &var_handler, - &if_miss); - m.Bind(&if_handler); - m.Branch(m.WordEqual(expected_handler, var_handler.value()), &passed, - &failed); - - m.Bind(&if_miss); - m.Branch(m.WordEqual(expected_handler, m.IntPtrConstant(0)), &passed, - &failed); - - m.Bind(&passed); - m.Return(m.BooleanConstant(true)); - - m.Bind(&failed); - m.Return(m.BooleanConstant(false)); - } - - Handle<Code> code = m.GenerateCode(); - FunctionTester ft(code, kNumParams); - - std::vector<Handle<Name>> names; - std::vector<Handle<JSObject>> receivers; - std::vector<Handle<Code>> handlers; - - base::RandomNumberGenerator rand_gen(FLAG_random_seed); - - Factory* factory = isolate->factory(); - - // Generate some number of names. - for (int i = 0; i < StubCache::kPrimaryTableSize / 7; i++) { - Handle<Name> name; - switch (rand_gen.NextInt(3)) { - case 0: { - // Generate string. - std::stringstream ss; - ss << "s" << std::hex - << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize); - name = factory->InternalizeUtf8String(ss.str().c_str()); - break; - } - case 1: { - // Generate number string. - std::stringstream ss; - ss << (rand_gen.NextInt(Smi::kMaxValue) % StubCache::kPrimaryTableSize); - name = factory->InternalizeUtf8String(ss.str().c_str()); - break; - } - case 2: { - // Generate symbol. - name = factory->NewSymbol(); - break; - } - default: - UNREACHABLE(); - } - names.push_back(name); - } - - // Generate some number of receiver maps and receivers. - for (int i = 0; i < StubCache::kSecondaryTableSize / 2; i++) { - Handle<Map> map = Map::Create(isolate, 0); - receivers.push_back(factory->NewJSObjectFromMap(map)); - } - - // Generate some number of handlers. - for (int i = 0; i < 30; i++) { - Code::Flags flags = - Code::RemoveHolderFromFlags(Code::ComputeHandlerFlags(ic_kind)); - handlers.push_back(CreateCodeWithFlags(flags)); - } - - // Ensure that GC does happen because from now on we are going to fill our - // own stub cache instance with raw values. - DisallowHeapAllocation no_gc; - - // Populate {stub_cache}. - const int N = StubCache::kPrimaryTableSize + StubCache::kSecondaryTableSize; - for (int i = 0; i < N; i++) { - int index = rand_gen.NextInt(); - Handle<Name> name = names[index % names.size()]; - Handle<JSObject> receiver = receivers[index % receivers.size()]; - Handle<Code> handler = handlers[index % handlers.size()]; - stub_cache.Set(*name, receiver->map(), *handler); - } - - // Perform some queries. - bool queried_existing = false; - bool queried_non_existing = false; - for (int i = 0; i < N; i++) { - int index = rand_gen.NextInt(); - Handle<Name> name = names[index % names.size()]; - Handle<JSObject> receiver = receivers[index % receivers.size()]; - Object* handler = stub_cache.Get(*name, receiver->map()); - if (handler == nullptr) { - queried_non_existing = true; - } else { - queried_existing = true; - } - - Handle<Object> expected_handler(handler, isolate); - ft.CheckTrue(receiver, name, expected_handler); - } - - for (int i = 0; i < N; i++) { - int index1 = rand_gen.NextInt(); - int index2 = rand_gen.NextInt(); - Handle<Name> name = names[index1 % names.size()]; - Handle<JSObject> receiver = receivers[index2 % receivers.size()]; - Object* handler = stub_cache.Get(*name, receiver->map()); - if (handler == nullptr) { - queried_non_existing = true; - } else { - queried_existing = true; - } - - Handle<Object> expected_handler(handler, isolate); - ft.CheckTrue(receiver, name, expected_handler); - } - // Ensure we performed both kind of queries. - CHECK(queried_existing && queried_non_existing); -} - -TEST(GotoIfException) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; - Isolate* isolate(CcTest::InitIsolateOnce()); - - const int kNumParams = 1; - // Emulate TFJ builtin - CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN); - - Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); - Node* to_string_tag = - m.HeapConstant(isolate->factory()->to_string_tag_symbol()); - Variable exception(&m, MachineRepresentation::kTagged); - - Label exception_handler(&m); - Callable to_string = CodeFactory::ToString(isolate); - Node* string = m.CallStub(to_string, context, to_string_tag); - m.GotoIfException(string, &exception_handler, &exception); - m.Return(string); - - m.Bind(&exception_handler); - m.Return(exception.value()); - - Handle<Code> code = m.GenerateCode(); - CHECK(!code.is_null()); - - FunctionTester ft(code, kNumParams); - Handle<Object> result = ft.Call().ToHandleChecked(); - - // Should be a TypeError - CHECK(result->IsJSObject()); - - Handle<Object> constructor = - Object::GetPropertyOrElement(result, - isolate->factory()->constructor_string()) - .ToHandleChecked(); - CHECK(constructor->SameValue(*isolate->type_error_function())); -} - -TEST(GotoIfExceptionMultiple) { - typedef CodeStubAssembler::Label Label; - typedef CodeStubAssembler::Variable Variable; - Isolate* isolate(CcTest::InitIsolateOnce()); - - const int kNumParams = 4; // receiver, first, second, third - // Emulate TFJ builtin - CodeStubAssemblerTester m(isolate, kNumParams, Code::BUILTIN); - - Node* context = m.HeapConstant(Handle<Context>(isolate->native_context())); - Node* first_value = m.Parameter(0); - Node* second_value = m.Parameter(1); - Node* third_value = m.Parameter(2); - - Label exception_handler1(&m); - Label exception_handler2(&m); - Label exception_handler3(&m); - Variable return_value(&m, MachineRepresentation::kWord32); - Variable error(&m, MachineRepresentation::kTagged); - - return_value.Bind(m.Int32Constant(0)); - - // try { return ToString(param1) } catch (e) { ... } - Callable to_string = CodeFactory::ToString(isolate); - Node* string = m.CallStub(to_string, context, first_value); - m.GotoIfException(string, &exception_handler1, &error); - m.Return(string); - - // try { ToString(param2); return 7 } catch (e) { ... } - m.Bind(&exception_handler1); - return_value.Bind(m.Int32Constant(7)); - error.Bind(m.UndefinedConstant()); - string = m.CallStub(to_string, context, second_value); - m.GotoIfException(string, &exception_handler2, &error); - m.Return(m.SmiFromWord32(return_value.value())); - - // try { ToString(param3); return 7 & ~2; } catch (e) { return e; } - m.Bind(&exception_handler2); - // Return returnValue & ~2 - error.Bind(m.UndefinedConstant()); - string = m.CallStub(to_string, context, third_value); - m.GotoIfException(string, &exception_handler3, &error); - m.Return(m.SmiFromWord32( - m.Word32And(return_value.value(), - m.Word32Xor(m.Int32Constant(2), m.Int32Constant(-1))))); - - m.Bind(&exception_handler3); - m.Return(error.value()); - - Handle<Code> code = m.GenerateCode(); - CHECK(!code.is_null()); - - FunctionTester ft(code, kNumParams); - - Handle<Object> result; - // First handler does not throw, returns result of first value - result = ft.Call(isolate->factory()->undefined_value(), - isolate->factory()->to_string_tag_symbol()) - .ToHandleChecked(); - CHECK(String::cast(*result)->IsOneByteEqualTo(OneByteVector("undefined"))); - - // First handler returns a number - result = ft.Call(isolate->factory()->to_string_tag_symbol(), - isolate->factory()->undefined_value()) - .ToHandleChecked(); - CHECK_EQ(7, Smi::cast(*result)->value()); - - // First handler throws, second handler returns a number - result = ft.Call(isolate->factory()->to_string_tag_symbol(), - isolate->factory()->to_primitive_symbol()) - .ToHandleChecked(); - CHECK_EQ(7 & ~2, Smi::cast(*result)->value()); - - // First handler throws, second handler throws, third handler returns thrown - // value. - result = ft.Call(isolate->factory()->to_string_tag_symbol(), - isolate->factory()->to_primitive_symbol(), - isolate->factory()->unscopables_symbol()) - .ToHandleChecked(); - - // Should be a TypeError - CHECK(result->IsJSObject()); - - Handle<Object> constructor = - Object::GetPropertyOrElement(result, - isolate->factory()->constructor_string()) - .ToHandleChecked(); - CHECK(constructor->SameValue(*isolate->type_error_function())); -} - TEST(AllocateJSObjectFromMap) { Isolate* isolate(CcTest::InitIsolateOnce()); Factory* factory = isolate->factory(); const int kNumParams = 3; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); { Node* map = m.Parameter(0); @@ -1650,7 +1241,7 @@ TEST(AllocateJSObjectFromMap) { m.Return(result); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); Handle<Map> maps[] = { @@ -1701,7 +1292,8 @@ TEST(AllocateNameDictionary) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 1; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); { Node* capacity = m.Parameter(0); @@ -1709,7 +1301,7 @@ TEST(AllocateNameDictionary) { m.Return(result); } - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); FunctionTester ft(code, kNumParams); { @@ -1729,16 +1321,17 @@ TEST(PopAndReturnConstant) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - const int kNumProgramaticParams = 2; - CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams); + const int kNumProgrammaticParams = 2; + CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams); + CodeStubAssembler m(data.state()); // Call a function that return |kNumProgramaticParams| parameters in addition // to those specified by the static descriptor. |kNumProgramaticParams| is // specified as a constant. - m.PopAndReturn(m.Int32Constant(kNumProgramaticParams), + m.PopAndReturn(m.Int32Constant(kNumProgrammaticParams), m.SmiConstant(Smi::FromInt(1234))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); FunctionTester ft(code, kNumParams); @@ -1757,8 +1350,9 @@ TEST(PopAndReturnVariable) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - const int kNumProgramaticParams = 2; - CodeStubAssemblerTester m(isolate, kNumParams - kNumProgramaticParams); + const int kNumProgrammaticParams = 2; + CodeAssemblerTester data(isolate, kNumParams - kNumProgrammaticParams); + CodeStubAssembler m(data.state()); // Call a function that return |kNumProgramaticParams| parameters in addition // to those specified by the static descriptor. |kNumProgramaticParams| is @@ -1766,7 +1360,7 @@ TEST(PopAndReturnVariable) { // a constant. m.PopAndReturn(m.SmiUntag(m.Parameter(1)), m.SmiConstant(Smi::FromInt(1234))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); FunctionTester ft(code, kNumParams); @@ -1775,7 +1369,7 @@ TEST(PopAndReturnVariable) { result = ft.Call(isolate->factory()->undefined_value(), Handle<Smi>(Smi::FromInt(1234), isolate), isolate->factory()->undefined_value(), - Handle<Smi>(Smi::FromInt(kNumProgramaticParams), isolate)) + Handle<Smi>(Smi::FromInt(kNumProgrammaticParams), isolate)) .ToHandleChecked(); CHECK_EQ(1234, Handle<Smi>::cast(result)->value()); } @@ -1784,7 +1378,9 @@ TEST(PopAndReturnVariable) { TEST(OneToTwoByteStringCopy) { Isolate* isolate(CcTest::InitIsolateOnce()); - CodeStubAssemblerTester m(isolate, 2); + const int kNumParams = 2; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.CopyStringCharacters( m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), @@ -1793,7 +1389,7 @@ TEST(OneToTwoByteStringCopy) { CodeStubAssembler::SMI_PARAMETERS); m.Return(m.SmiConstant(Smi::FromInt(0))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde"); @@ -1818,7 +1414,9 @@ TEST(OneToTwoByteStringCopy) { TEST(OneToOneByteStringCopy) { Isolate* isolate(CcTest::InitIsolateOnce()); - CodeStubAssemblerTester m(isolate, 2); + const int kNumParams = 2; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.CopyStringCharacters( m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), @@ -1827,7 +1425,7 @@ TEST(OneToOneByteStringCopy) { CodeStubAssembler::SMI_PARAMETERS); m.Return(m.SmiConstant(Smi::FromInt(0))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde"); @@ -1852,7 +1450,9 @@ TEST(OneToOneByteStringCopy) { TEST(OneToOneByteStringCopyNonZeroStart) { Isolate* isolate(CcTest::InitIsolateOnce()); - CodeStubAssemblerTester m(isolate, 2); + const int kNumParams = 2; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.CopyStringCharacters( m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), @@ -1861,7 +1461,7 @@ TEST(OneToOneByteStringCopyNonZeroStart) { CodeStubAssembler::SMI_PARAMETERS); m.Return(m.SmiConstant(Smi::FromInt(0))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); Handle<String> string1 = isolate->factory()->InternalizeUtf8String("abcde"); @@ -1883,7 +1483,9 @@ TEST(OneToOneByteStringCopyNonZeroStart) { TEST(TwoToTwoByteStringCopy) { Isolate* isolate(CcTest::InitIsolateOnce()); - CodeStubAssemblerTester m(isolate, 2); + const int kNumParams = 2; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); m.CopyStringCharacters( m.Parameter(0), m.Parameter(1), m.SmiConstant(Smi::FromInt(0)), @@ -1892,7 +1494,7 @@ TEST(TwoToTwoByteStringCopy) { CodeStubAssembler::SMI_PARAMETERS); m.Return(m.SmiConstant(Smi::FromInt(0))); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); uc16 array1[] = {2000, 2001, 2002, 2003, 2004}; @@ -1921,9 +1523,10 @@ TEST(Arguments) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); - CodeStubArguments arguments(&m, m.IntPtrConstant(3)); + CodeStubArguments arguments(&m, m.Int32Constant(3)); CSA_ASSERT( &m, m.WordEqual(arguments.AtIndex(0), m.SmiConstant(Smi::FromInt(12)))); @@ -1934,7 +1537,7 @@ TEST(Arguments) { m.Return(arguments.GetReceiver()); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); FunctionTester ft(code, kNumParams); @@ -1950,23 +1553,22 @@ TEST(ArgumentsForEach) { Isolate* isolate(CcTest::InitIsolateOnce()); const int kNumParams = 4; - CodeStubAssemblerTester m(isolate, kNumParams); + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); - CodeStubArguments arguments(&m, m.IntPtrConstant(3)); + CodeStubArguments arguments(&m, m.Int32Constant(3)); - CodeStubAssemblerTester::Variable sum(&m, - MachineType::PointerRepresentation()); - CodeStubAssemblerTester::VariableList list({&sum}, m.zone()); + CodeAssemblerVariable sum(&m, MachineRepresentation::kTagged); + CodeAssemblerVariableList list({&sum}, m.zone()); - sum.Bind(m.IntPtrConstant(0)); + sum.Bind(m.SmiConstant(0)); - arguments.ForEach(list, [&m, &sum](CodeStubAssembler* assembler, Node* arg) { - sum.Bind(assembler->IntPtrAdd(sum.value(), arg)); - }); + arguments.ForEach( + list, [&m, &sum](Node* arg) { sum.Bind(m.SmiAdd(sum.value(), arg)); }); m.Return(sum.value()); - Handle<Code> code = m.GenerateCode(); + Handle<Code> code = data.GenerateCode(); CHECK(!code.is_null()); FunctionTester ft(code, kNumParams); @@ -1978,5 +1580,907 @@ TEST(ArgumentsForEach) { CHECK_EQ(Smi::FromInt(12 + 13 + 14), *result); } +TEST(IsDebugActive) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + + CodeAssemblerLabel if_active(&m), if_not_active(&m); + + m.Branch(m.IsDebugActive(), &if_active, &if_not_active); + m.Bind(&if_active); + m.Return(m.TrueConstant()); + m.Bind(&if_not_active); + m.Return(m.FalseConstant()); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + CHECK_EQ(false, isolate->debug()->is_active()); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); + + bool* debug_is_active = reinterpret_cast<bool*>( + ExternalReference::debug_is_active_address(isolate).address()); + + // Cheat to enable debug (TODO: do this properly). + *debug_is_active = true; + + result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->true_value(), *result); + + // Reset debug mode. + *debug_is_active = false; +} + +class AppendJSArrayCodeStubAssembler : public CodeStubAssembler { + public: + AppendJSArrayCodeStubAssembler(compiler::CodeAssemblerState* state, + ElementsKind kind) + : CodeStubAssembler(state), kind_(kind) {} + + void TestAppendJSArrayImpl(Isolate* isolate, CodeAssemblerTester* tester, + Object* o1, Object* o2, Object* o3, Object* o4, + int initial_size, int result_size) { + typedef CodeAssemblerVariable Variable; + typedef CodeAssemblerLabel Label; + Handle<JSArray> array = isolate->factory()->NewJSArray( + kind_, 2, initial_size, INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE); + JSObject::SetElement(isolate, array, 0, + Handle<Smi>(Smi::FromInt(1), isolate), SLOPPY) + .Check(); + JSObject::SetElement(isolate, array, 1, + Handle<Smi>(Smi::FromInt(2), isolate), SLOPPY) + .Check(); + CodeStubArguments args(this, Int32Constant(kNumParams)); + Variable arg_index(this, MachineType::PointerRepresentation()); + Label bailout(this); + arg_index.Bind(IntPtrConstant(0)); + Node* length = BuildAppendJSArray( + kind_, HeapConstant(Handle<HeapObject>(isolate->context(), isolate)), + HeapConstant(array), args, arg_index, &bailout); + Return(length); + + Bind(&bailout); + Return(SmiTag(IntPtrAdd(arg_index.value(), IntPtrConstant(2)))); + + Handle<Code> code = tester->GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + + Handle<Object> result = + ft.Call(Handle<Object>(o1, isolate), Handle<Object>(o2, isolate), + Handle<Object>(o3, isolate), Handle<Object>(o4, isolate)) + .ToHandleChecked(); + + CHECK_EQ(kind_, array->GetElementsKind()); + CHECK_EQ(result_size, Handle<Smi>::cast(result)->value()); + CHECK_EQ(result_size, Smi::cast(array->length())->value()); + Object* obj = *JSObject::GetElement(isolate, array, 2).ToHandleChecked(); + CHECK_EQ(result_size < 3 ? isolate->heap()->undefined_value() : o1, obj); + obj = *JSObject::GetElement(isolate, array, 3).ToHandleChecked(); + CHECK_EQ(result_size < 4 ? isolate->heap()->undefined_value() : o2, obj); + obj = *JSObject::GetElement(isolate, array, 4).ToHandleChecked(); + CHECK_EQ(result_size < 5 ? isolate->heap()->undefined_value() : o3, obj); + obj = *JSObject::GetElement(isolate, array, 5).ToHandleChecked(); + CHECK_EQ(result_size < 6 ? isolate->heap()->undefined_value() : o4, obj); + } + + static void TestAppendJSArray(Isolate* isolate, ElementsKind kind, Object* o1, + Object* o2, Object* o3, Object* o4, + int initial_size, int result_size) { + CodeAssemblerTester data(isolate, kNumParams); + AppendJSArrayCodeStubAssembler m(data.state(), kind); + m.TestAppendJSArrayImpl(isolate, &data, o1, o2, o3, o4, initial_size, + result_size); + } + + private: + static const int kNumParams = 4; + ElementsKind kind_; +}; + +TEST(BuildAppendJSArrayFastElement) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), Smi::FromInt(5), + Smi::FromInt(6), 6, 6); +} + +TEST(BuildAppendJSArrayFastElementGrow) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), Smi::FromInt(5), + Smi::FromInt(6), 2, 6); +} + +TEST(BuildAppendJSArrayFastSmiElement) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + Smi::FromInt(5), Smi::FromInt(6), 6, 6); +} + +TEST(BuildAppendJSArrayFastSmiElementGrow) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + Smi::FromInt(5), Smi::FromInt(6), 2, 6); +} + +TEST(BuildAppendJSArrayFastSmiElementObject) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + isolate->heap()->undefined_value(), Smi::FromInt(6), 6, 4); +} + +TEST(BuildAppendJSArrayFastSmiElementObjectGrow) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_SMI_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + isolate->heap()->undefined_value(), Smi::FromInt(6), 2, 4); +} + +TEST(BuildAppendJSArrayFastDoubleElements) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + Smi::FromInt(5), Smi::FromInt(6), 6, 6); +} + +TEST(BuildAppendJSArrayFastDoubleElementsGrow) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + Smi::FromInt(5), Smi::FromInt(6), 2, 6); +} + +TEST(BuildAppendJSArrayFastDoubleElementsObject) { + Isolate* isolate(CcTest::InitIsolateOnce()); + AppendJSArrayCodeStubAssembler::TestAppendJSArray( + isolate, FAST_DOUBLE_ELEMENTS, Smi::FromInt(3), Smi::FromInt(4), + isolate->heap()->undefined_value(), Smi::FromInt(6), 6, 4); +} + +namespace { + +template <typename Stub, typename... Args> +void Recompile(Args... args) { + Stub stub(args...); + stub.DeleteStubFromCacheForTesting(); + stub.GetCode(); +} + +} // namespace + +void CustomPromiseHook(v8::PromiseHookType type, v8::Local<v8::Promise> promise, + v8::Local<v8::Value> parentPromise) {} + +TEST(IsPromiseHookEnabled) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + + m.Return(m.SelectBooleanConstant(m.IsPromiseHookEnabled())); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); + + isolate->SetPromiseHook(CustomPromiseHook); + result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->true_value(), *result); + + isolate->SetPromiseHook(nullptr); + result = ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); +} + +TEST(AllocateAndInitJSPromise) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const promise = m.AllocateAndInitJSPromise(context); + m.Return(promise); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result->IsJSPromise()); +} + +TEST(AllocateAndSetJSPromise) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const promise = m.AllocateAndSetJSPromise( + context, m.SmiConstant(v8::Promise::kPending), m.SmiConstant(1)); + m.Return(promise); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result->IsJSPromise()); + Handle<JSPromise> js_promise = Handle<JSPromise>::cast(result); + CHECK_EQ(v8::Promise::kPending, js_promise->status()); + CHECK_EQ(Smi::FromInt(1), js_promise->result()); + CHECK(!js_promise->has_handler()); +} + +TEST(AllocatePromiseReactionJobInfo) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + PromiseBuiltinsAssembler p(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const tasks = m.AllocateFixedArray(FAST_ELEMENTS, m.IntPtrConstant(1)); + m.StoreFixedArrayElement(tasks, 0, m.UndefinedConstant()); + Node* const deferred_promise = + m.AllocateFixedArray(FAST_ELEMENTS, m.IntPtrConstant(1)); + m.StoreFixedArrayElement(deferred_promise, 0, m.UndefinedConstant()); + Node* const info = m.AllocatePromiseReactionJobInfo( + m.SmiConstant(1), tasks, deferred_promise, m.UndefinedConstant(), + m.UndefinedConstant(), context); + m.Return(info); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result->IsPromiseReactionJobInfo()); + Handle<PromiseReactionJobInfo> promise_info = + Handle<PromiseReactionJobInfo>::cast(result); + CHECK_EQ(Smi::FromInt(1), promise_info->value()); + CHECK(promise_info->tasks()->IsFixedArray()); + CHECK(promise_info->deferred_promise()->IsFixedArray()); + CHECK(promise_info->deferred_on_resolve()->IsUndefined(isolate)); + CHECK(promise_info->deferred_on_reject()->IsUndefined(isolate)); + CHECK(promise_info->context()->IsContext()); + CHECK_EQ(kDebugPromiseNoID, promise_info->debug_id()); +} + +TEST(AllocatePromiseResolveThenableJobInfo) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler p(data.state()); + + Node* const context = p.Parameter(kNumParams + 2); + Node* const native_context = p.LoadNativeContext(context); + Node* const thenable = p.AllocateAndInitJSPromise(context); + Node* const then_str = p.HeapConstant(isolate->factory()->then_string()); + Callable getproperty_callable = CodeFactory::GetProperty(isolate); + Node* const then = + p.CallStub(getproperty_callable, context, thenable, then_str); + Node* resolve = nullptr; + Node* reject = nullptr; + std::tie(resolve, reject) = p.CreatePromiseResolvingFunctions( + thenable, p.FalseConstant(), native_context); + + Node* const info = p.AllocatePromiseResolveThenableJobInfo( + thenable, then, resolve, reject, context); + p.Return(info); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result->IsPromiseResolveThenableJobInfo()); + Handle<PromiseResolveThenableJobInfo> promise_info = + Handle<PromiseResolveThenableJobInfo>::cast(result); + CHECK(promise_info->thenable()->IsJSPromise()); + CHECK(promise_info->then()->IsJSFunction()); + CHECK(promise_info->resolve()->IsJSFunction()); + CHECK(promise_info->reject()->IsJSFunction()); + CHECK_EQ(kDebugPromiseNoID, promise_info->debug_id()); + CHECK(promise_info->context()->IsContext()); +} + +TEST(IsSymbol) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + + Node* const symbol = m.Parameter(0); + m.Return(m.SelectBooleanConstant(m.IsSymbol(symbol))); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->NewSymbol()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->true_value(), *result); + + result = ft.Call(isolate->factory()->empty_string()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); +} + +TEST(IsPrivateSymbol) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + + Node* const symbol = m.Parameter(0); + m.Return(m.SelectBooleanConstant(m.IsPrivateSymbol(symbol))); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->NewSymbol()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); + + result = ft.Call(isolate->factory()->empty_string()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); + + result = ft.Call(isolate->factory()->NewPrivateSymbol()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->true_value(), *result); +} + +TEST(PromiseHasHandler) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const promise = + m.AllocateAndInitJSPromise(context, m.UndefinedConstant()); + m.Return(m.SelectBooleanConstant(m.PromiseHasHandler(promise))); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK_EQ(isolate->heap()->false_value(), *result); +} + +TEST(CreatePromiseResolvingFunctionsContext) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const native_context = m.LoadNativeContext(context); + Node* const promise = + m.AllocateAndInitJSPromise(context, m.UndefinedConstant()); + Node* const promise_context = m.CreatePromiseResolvingFunctionsContext( + promise, m.BooleanConstant(false), native_context); + m.Return(promise_context); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result->IsContext()); + Handle<Context> context_js = Handle<Context>::cast(result); + CHECK_EQ(isolate->native_context()->closure(), context_js->closure()); + CHECK_EQ(isolate->heap()->the_hole_value(), context_js->extension()); + CHECK_EQ(*isolate->native_context(), context_js->native_context()); + CHECK_EQ(Smi::FromInt(0), + context_js->get(PromiseBuiltinsAssembler::kAlreadyVisitedSlot)); + CHECK(context_js->get(PromiseBuiltinsAssembler::kPromiseSlot)->IsJSPromise()); + CHECK_EQ(isolate->heap()->false_value(), + context_js->get(PromiseBuiltinsAssembler::kDebugEventSlot)); +} + +TEST(CreatePromiseResolvingFunctions) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const native_context = m.LoadNativeContext(context); + Node* const promise = + m.AllocateAndInitJSPromise(context, m.UndefinedConstant()); + Node *resolve, *reject; + std::tie(resolve, reject) = m.CreatePromiseResolvingFunctions( + promise, m.BooleanConstant(false), native_context); + Node* const kSize = m.IntPtrConstant(2); + Node* const arr = m.AllocateFixedArray(FAST_ELEMENTS, kSize); + m.StoreFixedArrayElement(arr, 0, resolve); + m.StoreFixedArrayElement(arr, 1, reject); + m.Return(arr); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result_obj = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result_obj->IsFixedArray()); + Handle<FixedArray> result_arr = Handle<FixedArray>::cast(result_obj); + CHECK(result_arr->get(0)->IsJSFunction()); + CHECK(result_arr->get(1)->IsJSFunction()); +} + +TEST(NewElementsCapacity) { + Isolate* isolate(CcTest::InitIsolateOnce()); + CodeAssemblerTester data(isolate, 1); + CodeStubAssembler m(data.state()); + m.Return(m.SmiTag(m.CalculateNewElementsCapacity( + m.SmiUntag(m.Parameter(0)), CodeStubAssembler::INTPTR_PARAMETERS))); + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + FunctionTester ft(code, 1); + Handle<Smi> test_value = Handle<Smi>(Smi::FromInt(0), isolate); + Handle<Smi> result_obj = + Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); + test_value = Handle<Smi>(Smi::FromInt(1), isolate); + result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); + test_value = Handle<Smi>(Smi::FromInt(2), isolate); + result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); + test_value = Handle<Smi>(Smi::FromInt(1025), isolate); + result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); +} + +TEST(NewElementsCapacitySmi) { + Isolate* isolate(CcTest::InitIsolateOnce()); + CodeAssemblerTester data(isolate, 1); + CodeStubAssembler m(data.state()); + m.Return(m.CalculateNewElementsCapacity(m.Parameter(0), + CodeStubAssembler::SMI_PARAMETERS)); + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + FunctionTester ft(code, 1); + Handle<Smi> test_value = Handle<Smi>(Smi::FromInt(0), isolate); + Handle<Smi> result_obj = + Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); + test_value = Handle<Smi>(Smi::FromInt(1), isolate); + result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); + test_value = Handle<Smi>(Smi::FromInt(2), isolate); + result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); + test_value = Handle<Smi>(Smi::FromInt(1025), isolate); + result_obj = Handle<Smi>::cast(ft.Call(test_value).ToHandleChecked()); + CHECK_EQ( + result_obj->value(), + static_cast<int>(JSObject::NewElementsCapacity(test_value->value()))); +} + +TEST(AllocateFunctionWithMapAndContext) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const native_context = m.LoadNativeContext(context); + Node* const promise = + m.AllocateAndInitJSPromise(context, m.UndefinedConstant()); + Node* promise_context = m.CreatePromiseResolvingFunctionsContext( + promise, m.BooleanConstant(false), native_context); + Node* resolve_info = + m.LoadContextElement(native_context, Context::PROMISE_RESOLVE_SHARED_FUN); + Node* const map = m.LoadContextElement( + native_context, Context::STRICT_FUNCTION_WITHOUT_PROTOTYPE_MAP_INDEX); + Node* const resolve = + m.AllocateFunctionWithMapAndContext(map, resolve_info, promise_context); + m.Return(resolve); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result_obj = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result_obj->IsJSFunction()); + Handle<JSFunction> fun = Handle<JSFunction>::cast(result_obj); + CHECK_EQ(isolate->heap()->empty_fixed_array(), fun->properties()); + CHECK_EQ(isolate->heap()->empty_fixed_array(), fun->elements()); + CHECK_EQ(isolate->heap()->empty_literals_array(), fun->literals()); + CHECK_EQ(isolate->heap()->the_hole_value(), fun->prototype_or_initial_map()); + CHECK_EQ(*isolate->promise_resolve_shared_fun(), fun->shared()); + CHECK_EQ(isolate->promise_resolve_shared_fun()->code(), fun->code()); + CHECK_EQ(isolate->heap()->undefined_value(), fun->next_function_link()); +} + +TEST(CreatePromiseGetCapabilitiesExecutorContext) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const native_context = m.LoadNativeContext(context); + + Node* const map = m.LoadRoot(Heap::kJSPromiseCapabilityMapRootIndex); + Node* const capability = m.AllocateJSObjectFromMap(map); + m.StoreObjectFieldNoWriteBarrier( + capability, JSPromiseCapability::kPromiseOffset, m.UndefinedConstant()); + m.StoreObjectFieldNoWriteBarrier( + capability, JSPromiseCapability::kResolveOffset, m.UndefinedConstant()); + m.StoreObjectFieldNoWriteBarrier( + capability, JSPromiseCapability::kRejectOffset, m.UndefinedConstant()); + Node* const executor_context = + m.CreatePromiseGetCapabilitiesExecutorContext(capability, native_context); + m.Return(executor_context); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + + FunctionTester ft(code, kNumParams); + Handle<Object> result_obj = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result_obj->IsContext()); + Handle<Context> context_js = Handle<Context>::cast(result_obj); + CHECK_EQ(PromiseBuiltinsAssembler::kCapabilitiesContextLength, + context_js->length()); + CHECK_EQ(isolate->native_context()->closure(), context_js->closure()); + CHECK_EQ(isolate->heap()->the_hole_value(), context_js->extension()); + CHECK_EQ(*isolate->native_context(), context_js->native_context()); + CHECK(context_js->get(PromiseBuiltinsAssembler::kCapabilitySlot) + ->IsJSPromiseCapability()); +} + +TEST(NewPromiseCapability) { + Isolate* isolate(CcTest::InitIsolateOnce()); + + { // Builtin Promise + const int kNumParams = 1; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + Node* const native_context = m.LoadNativeContext(context); + Node* const promise_constructor = + m.LoadContextElement(native_context, Context::PROMISE_FUNCTION_INDEX); + + Node* const capability = + m.NewPromiseCapability(context, promise_constructor); + m.Return(capability); + + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code, kNumParams); + + Handle<Object> result_obj = + ft.Call(isolate->factory()->undefined_value()).ToHandleChecked(); + CHECK(result_obj->IsJSPromiseCapability()); + Handle<JSPromiseCapability> result = + Handle<JSPromiseCapability>::cast(result_obj); + + CHECK(result->promise()->IsJSPromise()); + CHECK(result->resolve()->IsJSFunction()); + CHECK(result->reject()->IsJSFunction()); + CHECK_EQ(isolate->native_context()->promise_resolve_shared_fun(), + JSFunction::cast(result->resolve())->shared()); + CHECK_EQ(isolate->native_context()->promise_reject_shared_fun(), + JSFunction::cast(result->reject())->shared()); + + Handle<JSFunction> callbacks[] = { + handle(JSFunction::cast(result->resolve())), + handle(JSFunction::cast(result->reject()))}; + + for (auto&& callback : callbacks) { + Handle<Context> context(Context::cast(callback->context())); + CHECK_EQ(isolate->native_context()->closure(), context->closure()); + CHECK_EQ(isolate->heap()->the_hole_value(), context->extension()); + CHECK_EQ(*isolate->native_context(), context->native_context()); + CHECK_EQ(PromiseBuiltinsAssembler::kPromiseContextLength, + context->length()); + CHECK_EQ(context->get(PromiseBuiltinsAssembler::kPromiseSlot), + result->promise()); + } + } + + { // Custom Promise + const int kNumParams = 2; + CodeAssemblerTester data(isolate, kNumParams); + PromiseBuiltinsAssembler m(data.state()); + + Node* const context = m.Parameter(kNumParams + 2); + + Node* const constructor = m.Parameter(1); + Node* const capability = m.NewPromiseCapability(context, constructor); + m.Return(capability); + + Handle<Code> code = data.GenerateCode(); + FunctionTester ft(code, kNumParams); + + Handle<JSFunction> constructor_fn = + Handle<JSFunction>::cast(v8::Utils::OpenHandle(*CompileRun( + "(function FakePromise(executor) {" + " var self = this;" + " function resolve(value) { self.resolvedValue = value; }" + " function reject(reason) { self.rejectedReason = reason; }" + " executor(resolve, reject);" + "})"))); + + Handle<Object> result_obj = + ft.Call(isolate->factory()->undefined_value(), constructor_fn) + .ToHandleChecked(); + CHECK(result_obj->IsJSPromiseCapability()); + Handle<JSPromiseCapability> result = + Handle<JSPromiseCapability>::cast(result_obj); + + CHECK(result->promise()->IsJSObject()); + Handle<JSObject> promise(JSObject::cast(result->promise())); + CHECK_EQ(constructor_fn->prototype_or_initial_map(), promise->map()); + CHECK(result->resolve()->IsJSFunction()); + CHECK(result->reject()->IsJSFunction()); + + Handle<String> resolved_str = + isolate->factory()->NewStringFromAsciiChecked("resolvedStr"); + Handle<String> rejected_str = + isolate->factory()->NewStringFromAsciiChecked("rejectedStr"); + + Handle<Object> argv1[] = {resolved_str}; + Handle<Object> ret = + Execution::Call(isolate, handle(result->resolve(), isolate), + isolate->factory()->undefined_value(), 1, argv1) + .ToHandleChecked(); + + Handle<Object> prop1 = + JSReceiver::GetProperty(isolate, promise, "resolvedValue") + .ToHandleChecked(); + CHECK_EQ(*resolved_str, *prop1); + + Handle<Object> argv2[] = {rejected_str}; + ret = Execution::Call(isolate, handle(result->reject(), isolate), + isolate->factory()->undefined_value(), 1, argv2) + .ToHandleChecked(); + Handle<Object> prop2 = + JSReceiver::GetProperty(isolate, promise, "rejectedReason") + .ToHandleChecked(); + CHECK_EQ(*rejected_str, *prop2); + } +} + +TEST(DirectMemoryTest8BitWord32Immediate) { + Isolate* isolate(CcTest::InitIsolateOnce()); + typedef CodeAssemblerLabel Label; + + const int kNumParams = 0; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + int8_t buffer[] = {1, 2, 4, 8, 17, 33, 65, 127}; + const int element_count = 8; + Label bad(&m); + + Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer)); + for (size_t i = 0; i < element_count; ++i) { + for (size_t j = 0; j < element_count; ++j) { + Node* loaded = m.LoadBufferObject(buffer_node, static_cast<int>(i), + MachineType::Uint8()); + Node* masked = m.Word32And(loaded, m.Int32Constant(buffer[j])); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + } + } + + m.Return(m.SmiConstant(1)); + + m.Bind(&bad); + m.Return(m.SmiConstant(0)); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + FunctionTester ft(code, kNumParams); + CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value()); +} + +TEST(DirectMemoryTest16BitWord32Immediate) { + Isolate* isolate(CcTest::InitIsolateOnce()); + typedef CodeAssemblerLabel Label; + + const int kNumParams = 0; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + int16_t buffer[] = {156, 2234, 4544, 8444, 1723, 3888, 658, 1278}; + const int element_count = 8; + Label bad(&m); + + Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer)); + for (size_t i = 0; i < element_count; ++i) { + for (size_t j = 0; j < element_count; ++j) { + Node* loaded = + m.LoadBufferObject(buffer_node, static_cast<int>(i * sizeof(int16_t)), + MachineType::Uint16()); + Node* masked = m.Word32And(loaded, m.Int32Constant(buffer[j])); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + } + } + + m.Return(m.SmiConstant(1)); + + m.Bind(&bad); + m.Return(m.SmiConstant(0)); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + FunctionTester ft(code, kNumParams); + CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value()); +} + +TEST(DirectMemoryTest8BitWord32) { + Isolate* isolate(CcTest::InitIsolateOnce()); + typedef CodeAssemblerLabel Label; + + const int kNumParams = 0; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + int8_t buffer[] = {1, 2, 4, 8, 17, 33, 65, 127, 67, 38}; + const int element_count = 10; + Label bad(&m); + Node* constants[element_count]; + + Node* buffer_node = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer)); + for (size_t i = 0; i < element_count; ++i) { + constants[i] = m.LoadBufferObject(buffer_node, static_cast<int>(i), + MachineType::Uint8()); + } + + for (size_t i = 0; i < element_count; ++i) { + for (size_t j = 0; j < element_count; ++j) { + Node* loaded = m.LoadBufferObject(buffer_node, static_cast<int>(i), + MachineType::Uint8()); + Node* masked = m.Word32And(loaded, constants[j]); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + + masked = m.Word32And(constants[i], constants[j]); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + } + } + + m.Return(m.SmiConstant(1)); + + m.Bind(&bad); + m.Return(m.SmiConstant(0)); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + FunctionTester ft(code, kNumParams); + CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value()); +} + +TEST(DirectMemoryTest16BitWord32) { + Isolate* isolate(CcTest::InitIsolateOnce()); + typedef CodeAssemblerLabel Label; + + const int kNumParams = 0; + CodeAssemblerTester data(isolate, kNumParams); + CodeStubAssembler m(data.state()); + int16_t buffer[] = {1, 2, 4, 8, 12345, 33, 65, 255, 67, 3823}; + const int element_count = 10; + Label bad(&m); + Node* constants[element_count]; + + Node* buffer_node1 = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer)); + for (size_t i = 0; i < element_count; ++i) { + constants[i] = + m.LoadBufferObject(buffer_node1, static_cast<int>(i * sizeof(int16_t)), + MachineType::Uint16()); + } + Node* buffer_node2 = m.IntPtrConstant(reinterpret_cast<intptr_t>(buffer)); + + for (size_t i = 0; i < element_count; ++i) { + for (size_t j = 0; j < element_count; ++j) { + Node* loaded = m.LoadBufferObject(buffer_node1, + static_cast<int>(i * sizeof(int16_t)), + MachineType::Uint16()); + Node* masked = m.Word32And(loaded, constants[j]); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + + // Force a memory access relative to a high-number register. + loaded = m.LoadBufferObject(buffer_node2, + static_cast<int>(i * sizeof(int16_t)), + MachineType::Uint16()); + masked = m.Word32And(loaded, constants[j]); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + + masked = m.Word32And(constants[i], constants[j]); + if ((buffer[j] & buffer[i]) != 0) { + m.GotoIf(m.Word32Equal(masked, m.Int32Constant(0)), &bad); + } else { + m.GotoIf(m.Word32NotEqual(masked, m.Int32Constant(0)), &bad); + } + } + } + + m.Return(m.SmiConstant(1)); + + m.Bind(&bad); + m.Return(m.SmiConstant(0)); + + Handle<Code> code = data.GenerateCode(); + CHECK(!code.is_null()); + FunctionTester ft(code, kNumParams); + CHECK_EQ(1, Handle<Smi>::cast(ft.Call().ToHandleChecked())->value()); +} + } // namespace internal } // namespace v8 diff --git a/deps/v8/test/cctest/test-compiler.cc b/deps/v8/test/cctest/test-compiler.cc index ef7506b58f..7191ceb78e 100644 --- a/deps/v8/test/cctest/test-compiler.cc +++ b/deps/v8/test/cctest/test-compiler.cc @@ -35,6 +35,7 @@ #include "src/disasm.h" #include "src/factory.h" #include "src/interpreter/interpreter.h" +#include "src/objects-inl.h" #include "test/cctest/cctest.h" using namespace v8::internal; @@ -625,7 +626,6 @@ TEST(IgnitionEntryTrampolineSelfHealing) { CcTest::InitializeVM(); FLAG_ignition = true; Isolate* isolate = CcTest::i_isolate(); - isolate->interpreter()->Initialize(); v8::HandleScope scope(CcTest::isolate()); CompileRun( diff --git a/deps/v8/test/cctest/test-conversions.cc b/deps/v8/test/cctest/test-conversions.cc index 2fee58a46d..65cd96e0df 100644 --- a/deps/v8/test/cctest/test-conversions.cc +++ b/deps/v8/test/cctest/test-conversions.cc @@ -444,3 +444,61 @@ TEST(NoHandlesForTryNumberToSize) { } } } + +TEST(TryNumberToSizeWithMaxSizePlusOne) { + i::Isolate* isolate = CcTest::i_isolate(); + { + HandleScope scope(isolate); + // 1 << 64, larger than the limit of size_t. + double value = 18446744073709551616.0; + size_t result = 0; + Handle<HeapNumber> heap_number = isolate->factory()->NewHeapNumber(value); + CHECK(!TryNumberToSize(*heap_number, &result)); + } +} + +TEST(PositiveNumberToUint32) { + i::Isolate* isolate = CcTest::i_isolate(); + i::Factory* factory = isolate->factory(); + uint32_t max = std::numeric_limits<uint32_t>::max(); + HandleScope scope(isolate); + // Test Smi conversions. + Handle<Object> number = handle(Smi::FromInt(0), isolate); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = handle(Smi::FromInt(-1), isolate); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = handle(Smi::FromInt(-1), isolate); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = handle(Smi::FromInt(Smi::kMinValue), isolate); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = handle(Smi::FromInt(Smi::kMaxValue), isolate); + CHECK_EQ(PositiveNumberToUint32(*number), + static_cast<uint32_t>(Smi::kMaxValue)); + // Test Double conversions. + number = factory->NewHeapNumber(0.0); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = factory->NewHeapNumber(0.999); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = factory->NewHeapNumber(1.999); + CHECK_EQ(PositiveNumberToUint32(*number), 1u); + number = factory->NewHeapNumber(-12.0); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = factory->NewHeapNumber(12000.0); + CHECK_EQ(PositiveNumberToUint32(*number), 12000u); + number = factory->NewHeapNumber(static_cast<double>(Smi::kMaxValue) + 1); + CHECK_EQ(PositiveNumberToUint32(*number), + static_cast<uint32_t>(Smi::kMaxValue) + 1); + number = factory->NewHeapNumber(max); + CHECK_EQ(PositiveNumberToUint32(*number), max); + number = factory->NewHeapNumber(static_cast<double>(max) * 1000); + CHECK_EQ(PositiveNumberToUint32(*number), max); + number = factory->NewHeapNumber(std::numeric_limits<double>::max()); + CHECK_EQ(PositiveNumberToUint32(*number), max); + number = factory->NewHeapNumber(std::numeric_limits<double>::infinity()); + CHECK_EQ(PositiveNumberToUint32(*number), max); + number = + factory->NewHeapNumber(-1.0 * std::numeric_limits<double>::infinity()); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); + number = factory->NewHeapNumber(std::nan("")); + CHECK_EQ(PositiveNumberToUint32(*number), 0u); +} diff --git a/deps/v8/test/cctest/test-cpu-profiler.cc b/deps/v8/test/cctest/test-cpu-profiler.cc index a69dd4cad4..6ec71a2ab3 100644 --- a/deps/v8/test/cctest/test-cpu-profiler.cc +++ b/deps/v8/test/cctest/test-cpu-profiler.cc @@ -1575,6 +1575,7 @@ TEST(JsNativeJsRuntimeJsSampleMultiple) { static const char* inlining_test_source = "%NeverOptimizeFunction(action);\n" "%NeverOptimizeFunction(start);\n" + "level1()\n" "%OptimizeFunctionOnNextCall(level1);\n" "%OptimizeFunctionOnNextCall(level2);\n" "%OptimizeFunctionOnNextCall(level3);\n" @@ -1871,15 +1872,20 @@ TEST(CollectDeoptEvents) { { const char* branch[] = {"", "opt_function0", "opt_function0"}; - CHECK_EQ(reason(i::DeoptimizeReason::kNotAHeapNumber), - GetBranchDeoptReason(env, iprofile, branch, arraysize(branch))); + const char* deopt_reason = + GetBranchDeoptReason(env, iprofile, branch, arraysize(branch)); + if (deopt_reason != reason(i::DeoptimizeReason::kNotAHeapNumber) && + deopt_reason != reason(i::DeoptimizeReason::kNotASmi)) { + FATAL(deopt_reason); + } } { const char* branch[] = {"", "opt_function1", "opt_function1"}; const char* deopt_reason = GetBranchDeoptReason(env, iprofile, branch, arraysize(branch)); if (deopt_reason != reason(i::DeoptimizeReason::kNaN) && - deopt_reason != reason(i::DeoptimizeReason::kLostPrecisionOrNaN)) { + deopt_reason != reason(i::DeoptimizeReason::kLostPrecisionOrNaN) && + deopt_reason != reason(i::DeoptimizeReason::kNotASmi)) { FATAL(deopt_reason); } } diff --git a/deps/v8/test/cctest/test-debug.cc b/deps/v8/test/cctest/test-debug.cc index 3b43d9d11f..54904f9b84 100644 --- a/deps/v8/test/cctest/test-debug.cc +++ b/deps/v8/test/cctest/test-debug.cc @@ -30,8 +30,6 @@ #include "src/v8.h" #include "src/api.h" -#include "src/base/platform/condition-variable.h" -#include "src/base/platform/platform.h" #include "src/compilation-cache.h" #include "src/debug/debug-interface.h" #include "src/debug/debug.h" @@ -40,11 +38,6 @@ #include "src/utils.h" #include "test/cctest/cctest.h" -using ::v8::base::Mutex; -using ::v8::base::LockGuard; -using ::v8::base::ConditionVariable; -using ::v8::base::OS; -using ::v8::base::Semaphore; using ::v8::internal::EmbeddedVector; using ::v8::internal::Object; using ::v8::internal::Handle; @@ -52,8 +45,6 @@ using ::v8::internal::Heap; using ::v8::internal::JSGlobalProxy; using ::v8::internal::Code; using ::v8::internal::Debug; -using ::v8::internal::CommandMessage; -using ::v8::internal::CommandMessageQueue; using ::v8::internal::StackFrame; using ::v8::internal::StepAction; using ::v8::internal::StepIn; // From StepAction enum @@ -321,8 +312,8 @@ static void ChangeBreakOnExceptionFromJS(v8::Isolate* isolate, bool caught, // Change break on exception using the native API call. static void ChangeBreakOnExceptionFromAPI( - v8::Isolate* isolate, v8::DebugInterface::ExceptionBreakState state) { - v8::DebugInterface::ChangeBreakOnException(isolate, state); + v8::Isolate* isolate, v8::debug::ExceptionBreakState state) { + v8::debug::ChangeBreakOnException(isolate, state); } // Prepare to step to next break location. @@ -408,9 +399,6 @@ void CheckDebuggerUnloaded(bool check_functions) { // Check that the debugger has been fully unloaded. static void CheckDebuggerUnloaded(v8::Isolate* isolate, bool check_functions = false) { - // Let debugger to unload itself synchronously - v8::Debug::ProcessDebugMessages(isolate); - v8::internal::CheckDebuggerUnloaded(check_functions); } @@ -1612,20 +1600,6 @@ TEST(EnableDisableScriptBreakPoint) { f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); CHECK_EQ(2, break_point_hit_count); - // Reload the script and get f again checking that the disabling survives. - v8::Script::Compile(context, script, &origin) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - f = v8::Local<v8::Function>::Cast( - env->Global()->Get(context, v8_str(isolate, "f")).ToLocalChecked()); - f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(2, break_point_hit_count); - - EnableScriptBreakPointFromJS(isolate, sbp); - f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(3, break_point_hit_count); - v8::Debug::SetDebugEventListener(isolate, nullptr); CheckDebuggerUnloaded(isolate); } @@ -1683,100 +1657,6 @@ TEST(ConditionalScriptBreakPoint) { } CHECK_EQ(5, break_point_hit_count); - // Reload the script and get f again checking that the condition survives. - v8::Script::Compile(context, script, &origin) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - f = v8::Local<v8::Function>::Cast( - env->Global() - ->Get(context, v8_str(env->GetIsolate(), "f")) - .ToLocalChecked()); - - break_point_hit_count = 0; - for (int i = 0; i < 10; i++) { - f->Call(env.context(), env->Global(), 0, NULL).ToLocalChecked(); - } - CHECK_EQ(5, break_point_hit_count); - - v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); - CheckDebuggerUnloaded(env->GetIsolate()); -} - - -// Test that script break points survive when a script is reloaded. -TEST(ScriptBreakPointReload) { - break_point_hit_count = 0; - DebugLocalContext env; - v8::HandleScope scope(env->GetIsolate()); - env.ExposeDebug(); - - v8::Debug::SetDebugEventListener(env->GetIsolate(), - DebugEventBreakPointHitCount); - - v8::Local<v8::Context> context = env.context(); - v8::Local<v8::Function> f; - v8::Local<v8::String> script = v8_str(env->GetIsolate(), - "function f() {\n" - " function h() {\n" - " a = 0; // line 2\n" - " }\n" - " b = 1; // line 4\n" - " return h();\n" - "}"); - - v8::ScriptOrigin origin_1 = v8::ScriptOrigin(v8_str(env->GetIsolate(), "1")); - v8::ScriptOrigin origin_2 = v8::ScriptOrigin(v8_str(env->GetIsolate(), "2")); - - // Set a script break point before the script is loaded. - SetScriptBreakPointByNameFromJS(env->GetIsolate(), "1", 2, 0); - - // Compile the script and get the function. - v8::Script::Compile(context, script, &origin_1) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - f = v8::Local<v8::Function>::Cast( - env->Global() - ->Get(context, v8_str(env->GetIsolate(), "f")) - .ToLocalChecked()); - - // Call f and check that the script break point is active. - break_point_hit_count = 0; - f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(1, break_point_hit_count); - - // Compile the script again with a different script data and get the - // function. - v8::Script::Compile(context, script, &origin_2) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - f = v8::Local<v8::Function>::Cast( - env->Global() - ->Get(context, v8_str(env->GetIsolate(), "f")) - .ToLocalChecked()); - - // Call f and check that no break points are set. - break_point_hit_count = 0; - f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(0, break_point_hit_count); - - // Compile the script again and get the function. - v8::Script::Compile(context, script, &origin_1) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - f = v8::Local<v8::Function>::Cast( - env->Global() - ->Get(context, v8_str(env->GetIsolate(), "f")) - .ToLocalChecked()); - - // Call f and check that the script break point is active. - break_point_hit_count = 0; - f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(1, break_point_hit_count); - v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate()); } @@ -1807,9 +1687,6 @@ TEST(ScriptBreakPointMultiple) { v8::ScriptOrigin origin = v8::ScriptOrigin(v8_str(env->GetIsolate(), "test")); - // Set a script break point before the scripts are loaded. - int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0); - // Compile the scripts with same script data and get the functions. v8::Script::Compile(context, script_f, &origin) .ToLocalChecked() @@ -1828,6 +1705,8 @@ TEST(ScriptBreakPointMultiple) { ->Get(context, v8_str(env->GetIsolate(), "g")) .ToLocalChecked()); + int sbp = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test", 1, 0); + // Call f and g and check that the script break point is active. break_point_hit_count = 0; f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); @@ -1883,17 +1762,17 @@ TEST(ScriptBreakPointLineOffset) { v8::ScriptOrigin origin(v8_str(env->GetIsolate(), "test.html"), v8::Integer::New(env->GetIsolate(), 7)); - // Set two script break points before the script is loaded. - int sbp1 = - SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 8, 0); - int sbp2 = - SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0); - // Compile the script and get the function. v8::Script::Compile(context, script, &origin) .ToLocalChecked() ->Run(context) .ToLocalChecked(); + + int sbp1 = + SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 8, 0); + int sbp2 = + SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 9, 0); + f = v8::Local<v8::Function>::Cast( env->Global() ->Get(context, v8_str(env->GetIsolate(), "f")) @@ -1959,7 +1838,13 @@ TEST(ScriptBreakPointLine) { " }\n" " a=5; // line 12"); - // Set a couple script break point before the script is loaded. + // Compile the script and get the function. + break_point_hit_count = 0; + v8::ScriptOrigin origin(v8_str(env->GetIsolate(), "test.html"), + v8::Integer::New(env->GetIsolate(), 0)); + v8::Local<v8::Script> compiled = + v8::Script::Compile(context, script, &origin).ToLocalChecked(); + int sbp1 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 0, -1); int sbp2 = @@ -1967,14 +1852,8 @@ TEST(ScriptBreakPointLine) { int sbp3 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 5, -1); - // Compile the script and get the function. - break_point_hit_count = 0; - v8::ScriptOrigin origin(v8_str(env->GetIsolate(), "test.html"), - v8::Integer::New(env->GetIsolate(), 0)); - v8::Script::Compile(context, script, &origin) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); + compiled->Run(context).ToLocalChecked(); + f = v8::Local<v8::Function>::Cast( env->Global() ->Get(context, v8_str(env->GetIsolate(), "f")) @@ -2020,39 +1899,21 @@ TEST(ScriptBreakPointLine) { g->Call(context, env->Global(), 0, NULL).ToLocalChecked(); CHECK_EQ(0, break_point_hit_count); - // Reload the script which should hit two break points. - break_point_hit_count = 0; - v8::Script::Compile(context, script, &origin) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - CHECK_EQ(2, break_point_hit_count); - CHECK_EQ(0, StrLength(last_function_hit)); - // Set a break point in the code after the last function decleration. int sbp6 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 12, -1); - // Reload the script which should hit three break points. + // Reloading the script should not hit any break points. break_point_hit_count = 0; v8::Script::Compile(context, script, &origin) .ToLocalChecked() ->Run(context) .ToLocalChecked(); - CHECK_EQ(3, break_point_hit_count); - CHECK_EQ(0, StrLength(last_function_hit)); + CHECK_EQ(0, break_point_hit_count); - // Clear the last break points, and reload the script which should not hit any - // break points. ClearBreakPointFromJS(env->GetIsolate(), sbp1); ClearBreakPointFromJS(env->GetIsolate(), sbp5); ClearBreakPointFromJS(env->GetIsolate(), sbp6); - break_point_hit_count = 0; - v8::Script::Compile(context, script, &origin) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - CHECK_EQ(0, break_point_hit_count); v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate()); @@ -2094,17 +1955,9 @@ TEST(ScriptBreakPointLineTopLevel) { f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); CHECK_EQ(0, break_point_hit_count); - // Recompile and run script and check that break point was hit. + // Recompile and run script and check that break point was not reapplied. break_point_hit_count = 0; CompileRunWithOrigin(script, "test.html"); - CHECK_EQ(1, break_point_hit_count); - - // Call f and check that there are still no break points. - break_point_hit_count = 0; - f = v8::Local<v8::Function>::Cast( - env->Global() - ->Get(context, v8_str(env->GetIsolate(), "f")) - .ToLocalChecked()); CHECK_EQ(0, break_point_hit_count); v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); @@ -2122,20 +1975,18 @@ TEST(ScriptBreakPointTopLevelCrash) { v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugEventBreakPointHitCount); - v8::Local<v8::String> script_source = v8_str(env->GetIsolate(), - "function f() {\n" - " return 0;\n" - "}\n" - "f()"); - + CompileRunWithOrigin( + "function f() {\n" + " return 0;\n" + "}\n", + "test.html"); int sbp1 = - SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1); - { - v8::HandleScope scope(env->GetIsolate()); - break_point_hit_count = 0; - CompileRunWithOrigin(script_source, "test.html"); - CHECK_EQ(1, break_point_hit_count); - } + SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 1, -1); + break_point_hit_count = 0; + + CompileRun("f();"); + + CHECK_EQ(1, break_point_hit_count); int sbp2 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), "test.html", 3, -1); @@ -2492,171 +2343,6 @@ TEST(DebugEvaluateWithCodeGenerationDisallowed) { } -// Copies a C string to a 16-bit string. Does not check for buffer overflow. -// Does not use the V8 engine to convert strings, so it can be used -// in any thread. Returns the length of the string. -int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) { - int i; - for (i = 0; input_buffer[i] != '\0'; ++i) { - // ASCII does not use chars > 127, but be careful anyway. - output_buffer[i] = static_cast<unsigned char>(input_buffer[i]); - } - output_buffer[i] = 0; - return i; -} - - -// Copies a 16-bit string to a C string by dropping the high byte of -// each character. Does not check for buffer overflow. -// Can be used in any thread. Requires string length as an input. -int Utf16ToAscii(const uint16_t* input_buffer, int length, - char* output_buffer, int output_len = -1) { - if (output_len >= 0) { - if (length > output_len - 1) { - length = output_len - 1; - } - } - - for (int i = 0; i < length; ++i) { - output_buffer[i] = static_cast<char>(input_buffer[i]); - } - output_buffer[length] = '\0'; - return length; -} - - -// We match parts of the message to get evaluate result int value. -bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) { - if (strstr(message, "\"command\":\"evaluate\"") == NULL) { - return false; - } - const char* prefix = "\"text\":\""; - char* pos1 = strstr(message, prefix); - if (pos1 == NULL) { - return false; - } - pos1 += strlen(prefix); - char* pos2 = strchr(pos1, '"'); - if (pos2 == NULL) { - return false; - } - Vector<char> buf(buffer, buffer_size); - int len = static_cast<int>(pos2 - pos1); - if (len > buffer_size - 1) { - len = buffer_size - 1; - } - StrNCpy(buf, pos1, len); - buffer[buffer_size - 1] = '\0'; - return true; -} - - -struct EvaluateResult { - static const int kBufferSize = 20; - char buffer[kBufferSize]; -}; - -struct DebugProcessDebugMessagesData { - static const int kArraySize = 5; - int counter; - EvaluateResult results[kArraySize]; - - void reset() { - counter = 0; - } - EvaluateResult* current() { - return &results[counter % kArraySize]; - } - void next() { - counter++; - } -}; - -DebugProcessDebugMessagesData process_debug_messages_data; - -static void DebugProcessDebugMessagesHandler( - const v8::Debug::Message& message) { - v8::Local<v8::String> json = message.GetJSON(); - v8::String::Utf8Value utf8(json); - EvaluateResult* array_item = process_debug_messages_data.current(); - - bool res = GetEvaluateStringResult(*utf8, - array_item->buffer, - EvaluateResult::kBufferSize); - if (res) { - process_debug_messages_data.next(); - } -} - - -// Test that the evaluation of expressions works even from ProcessDebugMessages -// i.e. with empty stack. -TEST(DebugEvaluateWithoutStack) { - DebugLocalContext env; - v8::Debug::SetMessageHandler(env->GetIsolate(), - DebugProcessDebugMessagesHandler); - v8::HandleScope scope(env->GetIsolate()); - - const char* source = - "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }"; - - v8::Local<v8::Context> context = env.context(); - v8::Script::Compile(context, v8_str(env->GetIsolate(), source)) - .ToLocalChecked() - ->Run(context) - .ToLocalChecked(); - - v8::Debug::ProcessDebugMessages(env->GetIsolate()); - - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - - const char* command_111 = "{\"seq\":111," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{" - " \"global\":true," - " \"expression\":\"v1\",\"disable_break\":true" - "}}"; - - v8::Isolate* isolate = CcTest::isolate(); - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_111, buffer)); - - const char* command_112 = "{\"seq\":112," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{" - " \"global\":true," - " \"expression\":\"getAnimal()\",\"disable_break\":true" - "}}"; - - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_112, buffer)); - - const char* command_113 = "{\"seq\":113," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{" - " \"global\":true," - " \"expression\":\"239 + 566\",\"disable_break\":true" - "}}"; - - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_113, buffer)); - - v8::Debug::ProcessDebugMessages(isolate); - - CHECK_EQ(3, process_debug_messages_data.counter); - - CHECK_EQ(strcmp("Pinguin", process_debug_messages_data.results[0].buffer), 0); - CHECK_EQ(strcmp("Capybara", process_debug_messages_data.results[1].buffer), - 0); - CHECK_EQ(strcmp("805", process_debug_messages_data.results[2].buffer), 0); - - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); - v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); - CheckDebuggerUnloaded(env->GetIsolate()); -} - - // Simple test of the stepping mechanism using only store ICs. TEST(DebugStepLinear) { DebugLocalContext env; @@ -3815,15 +3501,16 @@ TEST(PauseInScript) { const char* src = "(function (evt) {})"; const char* script_name = "StepInHandlerTest"; - // Set breakpoint in the script. - SetScriptBreakPointByNameFromJS(env->GetIsolate(), script_name, 0, -1); - break_point_hit_count = 0; - v8::ScriptOrigin origin(v8_str(env->GetIsolate(), script_name), v8::Integer::New(env->GetIsolate(), 0)); v8::Local<v8::Script> script = v8::Script::Compile(context, v8_str(env->GetIsolate(), src), &origin) .ToLocalChecked(); + + // Set breakpoint in the script. + SetScriptBreakPointByNameFromJS(env->GetIsolate(), script_name, 0, -1); + break_point_hit_count = 0; + v8::Local<v8::Value> r = script->Run(context).ToLocalChecked(); CHECK(r->IsFunction()); @@ -3995,7 +3682,7 @@ TEST(BreakOnException) { DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromAPI(env->GetIsolate(), - v8::DebugInterface::NoBreakOnException); + v8::debug::NoBreakOnException); caught->Call(context, env->Global(), 0, NULL).ToLocalChecked(); DebugEventCounterCheck(0, 0, 0); CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty()); @@ -4009,7 +3696,7 @@ TEST(BreakOnException) { DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromAPI(env->GetIsolate(), - v8::DebugInterface::BreakOnUncaughtException); + v8::debug::BreakOnUncaughtException); caught->Call(context, env->Global(), 0, NULL).ToLocalChecked(); DebugEventCounterCheck(0, 0, 0); CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty()); @@ -4023,7 +3710,7 @@ TEST(BreakOnException) { DebugEventCounterClear(); MessageCallbackCountClear(); ChangeBreakOnExceptionFromAPI(env->GetIsolate(), - v8::DebugInterface::BreakOnAnyException); + v8::debug::BreakOnAnyException); caught->Call(context, env->Global(), 0, NULL).ToLocalChecked(); DebugEventCounterCheck(1, 0, 0); CHECK(notCaught->Call(context, env->Global(), 0, NULL).IsEmpty()); @@ -4302,7 +3989,6 @@ TEST(DebugBreak) { // Set the debug break flag. v8::Debug::DebugBreak(env->GetIsolate()); - CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate())); // Call all functions with different argument count. break_point_hit_count = 0; @@ -4338,9 +4024,7 @@ TEST(DisableBreak) { // Set, test and cancel debug break. v8::Debug::DebugBreak(env->GetIsolate()); - CHECK(v8::Debug::CheckDebugBreak(env->GetIsolate())); v8::Debug::CancelDebugBreak(env->GetIsolate()); - CHECK(!v8::Debug::CheckDebugBreak(env->GetIsolate())); // Set the debug break flag. v8::Debug::DebugBreak(env->GetIsolate()); @@ -4353,7 +4037,7 @@ TEST(DisableBreak) { { v8::Debug::DebugBreak(env->GetIsolate()); i::Isolate* isolate = reinterpret_cast<i::Isolate*>(env->GetIsolate()); - v8::internal::DisableBreak disable_break(isolate->debug(), true); + v8::internal::DisableBreak disable_break(isolate->debug()); f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); CHECK_EQ(1, break_point_hit_count); } @@ -4942,787 +4626,10 @@ TEST(NoHiddenProperties) { } -// Multithreaded tests of JSON debugger protocol - -// Support classes - -// Provides synchronization between N threads, where N is a template parameter. -// The Wait() call blocks a thread until it is called for the Nth time, then all -// calls return. Each ThreadBarrier object can only be used once. -template <int N> -class ThreadBarrier final { - public: - ThreadBarrier() : num_blocked_(0) {} - - ~ThreadBarrier() { - LockGuard<Mutex> lock_guard(&mutex_); - if (num_blocked_ != 0) { - CHECK_EQ(N, num_blocked_); - } - } - - void Wait() { - LockGuard<Mutex> lock_guard(&mutex_); - CHECK_LT(num_blocked_, N); - num_blocked_++; - if (N == num_blocked_) { - // Signal and unblock all waiting threads. - cv_.NotifyAll(); - printf("BARRIER\n\n"); - fflush(stdout); - } else { // Wait for the semaphore. - while (num_blocked_ < N) { - cv_.Wait(&mutex_); - } - } - CHECK_EQ(N, num_blocked_); - } - - private: - ConditionVariable cv_; - Mutex mutex_; - int num_blocked_; - - STATIC_ASSERT(N > 0); - - DISALLOW_COPY_AND_ASSIGN(ThreadBarrier); -}; - - -// A set containing enough barriers and semaphores for any of the tests. -class Barriers { - public: - Barriers() : semaphore_1(0), semaphore_2(0) {} - ThreadBarrier<2> barrier_1; - ThreadBarrier<2> barrier_2; - ThreadBarrier<2> barrier_3; - ThreadBarrier<2> barrier_4; - ThreadBarrier<2> barrier_5; - v8::base::Semaphore semaphore_1; - v8::base::Semaphore semaphore_2; -}; - - -// We match parts of the message to decide if it is a break message. -bool IsBreakEventMessage(char *message) { - const char* type_event = "\"type\":\"event\""; - const char* event_break = "\"event\":\"break\""; - // Does the message contain both type:event and event:break? - return strstr(message, type_event) != NULL && - strstr(message, event_break) != NULL; -} - - -// We match parts of the message to decide if it is a exception message. -bool IsExceptionEventMessage(char *message) { - const char* type_event = "\"type\":\"event\""; - const char* event_exception = "\"event\":\"exception\""; - // Does the message contain both type:event and event:exception? - return strstr(message, type_event) != NULL && - strstr(message, event_exception) != NULL; -} - - -// We match the message wether it is an evaluate response message. -bool IsEvaluateResponseMessage(char* message) { - const char* type_response = "\"type\":\"response\""; - const char* command_evaluate = "\"command\":\"evaluate\""; - // Does the message contain both type:response and command:evaluate? - return strstr(message, type_response) != NULL && - strstr(message, command_evaluate) != NULL; -} - - -static int StringToInt(const char* s) { - return atoi(s); // NOLINT -} - - -// We match parts of the message to get evaluate result int value. -int GetEvaluateIntResult(char *message) { - const char* value = "\"value\":"; - char* pos = strstr(message, value); - if (pos == NULL) { - return -1; - } - int res = -1; - res = StringToInt(pos + strlen(value)); - return res; -} - - -// We match parts of the message to get hit breakpoint id. -int GetBreakpointIdFromBreakEventMessage(char *message) { - const char* breakpoints = "\"breakpoints\":["; - char* pos = strstr(message, breakpoints); - if (pos == NULL) { - return -1; - } - int res = -1; - res = StringToInt(pos + strlen(breakpoints)); - return res; -} - - -// We match parts of the message to get total frames number. -int GetTotalFramesInt(char *message) { - const char* prefix = "\"totalFrames\":"; - char* pos = strstr(message, prefix); - if (pos == NULL) { - return -1; - } - pos += strlen(prefix); - int res = StringToInt(pos); - return res; -} - - -// We match parts of the message to get source line. -int GetSourceLineFromBreakEventMessage(char *message) { - const char* source_line = "\"sourceLine\":"; - char* pos = strstr(message, source_line); - if (pos == NULL) { - return -1; - } - int res = -1; - res = StringToInt(pos + strlen(source_line)); - return res; -} - - -/* Test MessageQueues */ -/* Tests the message queues that hold debugger commands and - * response messages to the debugger. Fills queues and makes - * them grow. - */ -Barriers message_queue_barriers; - -// This is the debugger thread, that executes no v8 calls except -// placing JSON debugger commands in the queue. -class MessageQueueDebuggerThread : public v8::base::Thread { - public: - MessageQueueDebuggerThread() - : Thread(Options("MessageQueueDebuggerThread")) {} - void Run(); -}; - - -static void MessageHandler(const v8::Debug::Message& message) { - v8::Local<v8::String> json = message.GetJSON(); - v8::String::Utf8Value utf8(json); - if (IsBreakEventMessage(*utf8)) { - // Lets test script wait until break occurs to send commands. - // Signals when a break is reported. - message_queue_barriers.semaphore_2.Signal(); - } - - // Allow message handler to block on a semaphore, to test queueing of - // messages while blocked. - message_queue_barriers.semaphore_1.Wait(); -} - - -void MessageQueueDebuggerThread::Run() { - const int kBufferSize = 1000; - uint16_t buffer_1[kBufferSize]; - uint16_t buffer_2[kBufferSize]; - const char* command_1 = - "{\"seq\":117," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"1+2\"}}"; - const char* command_2 = - "{\"seq\":118," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"1+a\"}}"; - const char* command_3 = - "{\"seq\":119," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"c.d * b\"}}"; - const char* command_continue = - "{\"seq\":106," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; - const char* command_single_step = - "{\"seq\":107," - "\"type\":\"request\"," - "\"command\":\"continue\"," - "\"arguments\":{\"stepaction\":\"next\"}}"; - - /* Interleaved sequence of actions by the two threads:*/ - // Main thread compiles and runs source_1 - message_queue_barriers.semaphore_1.Signal(); - message_queue_barriers.barrier_1.Wait(); - // Post 6 commands, filling the command queue and making it expand. - // These calls return immediately, but the commands stay on the queue - // until the execution of source_2. - // Note: AsciiToUtf16 executes before SendCommand, so command is copied - // to buffer before buffer is sent to SendCommand. - v8::Isolate* isolate = CcTest::isolate(); - v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1)); - v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2)); - v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2)); - v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2)); - v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2)); - message_queue_barriers.barrier_2.Wait(); - // Main thread compiles and runs source_2. - // Queued commands are executed at the start of compilation of source_2( - // beforeCompile event). - // Free the message handler to process all the messages from the queue. 7 - // messages are expected: 2 afterCompile events and 5 responses. - // All the commands added so far will fail to execute as long as call stack - // is empty on beforeCompile event. - for (int i = 0; i < 6 ; ++i) { - message_queue_barriers.semaphore_1.Signal(); - } - message_queue_barriers.barrier_3.Wait(); - // Main thread compiles and runs source_3. - // Don't stop in the afterCompile handler. - message_queue_barriers.semaphore_1.Signal(); - // source_3 includes a debugger statement, which causes a break event. - // Wait on break event from hitting "debugger" statement - message_queue_barriers.semaphore_2.Wait(); - // These should execute after the "debugger" statement in source_2 - v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_1, buffer_1)); - v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_2, buffer_2)); - v8::Debug::SendCommand(isolate, buffer_2, AsciiToUtf16(command_3, buffer_2)); - v8::Debug::SendCommand( - isolate, buffer_2, AsciiToUtf16(command_single_step, buffer_2)); - // Run after 2 break events, 4 responses. - for (int i = 0; i < 6 ; ++i) { - message_queue_barriers.semaphore_1.Signal(); - } - // Wait on break event after a single step executes. - message_queue_barriers.semaphore_2.Wait(); - v8::Debug::SendCommand(isolate, buffer_1, AsciiToUtf16(command_2, buffer_1)); - v8::Debug::SendCommand( - isolate, buffer_2, AsciiToUtf16(command_continue, buffer_2)); - // Run after 2 responses. - for (int i = 0; i < 2 ; ++i) { - message_queue_barriers.semaphore_1.Signal(); - } - // Main thread continues running source_3 to end, waits for this thread. -} - - -// This thread runs the v8 engine. -TEST(MessageQueues) { - MessageQueueDebuggerThread message_queue_debugger_thread; - - // Create a V8 environment - DebugLocalContext env; - v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetMessageHandler(env->GetIsolate(), MessageHandler); - message_queue_debugger_thread.Start(); - - const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;"; - const char* source_2 = "e = 17;"; - const char* source_3 = "a = 4; debugger; a = 5; a = 6; a = 7;"; - - // See MessageQueueDebuggerThread::Run for interleaved sequence of - // API calls and events in the two threads. - CompileRun(source_1); - message_queue_barriers.barrier_1.Wait(); - message_queue_barriers.barrier_2.Wait(); - CompileRun(source_2); - message_queue_barriers.barrier_3.Wait(); - CompileRun(source_3); - message_queue_debugger_thread.Join(); - fflush(stdout); -} - - -class TestClientData : public v8::Debug::ClientData { - public: - TestClientData() { - constructor_call_counter++; - } - virtual ~TestClientData() { - destructor_call_counter++; - } - - static void ResetCounters() { - constructor_call_counter = 0; - destructor_call_counter = 0; - } - - static int constructor_call_counter; - static int destructor_call_counter; -}; - -int TestClientData::constructor_call_counter = 0; -int TestClientData::destructor_call_counter = 0; - - -// Tests that MessageQueue doesn't destroy client data when expands and -// does destroy when it dies. -TEST(MessageQueueExpandAndDestroy) { - TestClientData::ResetCounters(); - { // Create a scope for the queue. - CommandMessageQueue queue(1); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - CHECK_EQ(0, TestClientData::destructor_call_counter); - queue.Get().Dispose(); - CHECK_EQ(1, TestClientData::destructor_call_counter); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - queue.Put(CommandMessage::New(Vector<uint16_t>::empty(), - new TestClientData())); - CHECK_EQ(1, TestClientData::destructor_call_counter); - queue.Get().Dispose(); - CHECK_EQ(2, TestClientData::destructor_call_counter); - } - // All the client data should be destroyed when the queue is destroyed. - CHECK_EQ(TestClientData::destructor_call_counter, - TestClientData::destructor_call_counter); -} - - -static int handled_client_data_instances_count = 0; -static void MessageHandlerCountingClientData( - const v8::Debug::Message& message) { - if (message.GetClientData() != NULL) { - handled_client_data_instances_count++; - } -} - - -// Tests that all client data passed to the debugger are sent to the handler. -TEST(SendClientDataToHandler) { - // Create a V8 environment - DebugLocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - TestClientData::ResetCounters(); - handled_client_data_instances_count = 0; - v8::Debug::SetMessageHandler(isolate, MessageHandlerCountingClientData); - const char* source_1 = "a = 3; b = 4; c = new Object(); c.d = 5;"; - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - const char* command_1 = - "{\"seq\":117," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"1+2\"}}"; - const char* command_2 = - "{\"seq\":118," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"1+a\"}}"; - const char* command_continue = - "{\"seq\":106," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; - - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_1, buffer), - new TestClientData()); - v8::Debug::SendCommand( - isolate, buffer, AsciiToUtf16(command_2, buffer), NULL); - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer), - new TestClientData()); - v8::Debug::SendCommand(isolate, buffer, AsciiToUtf16(command_2, buffer), - new TestClientData()); - // All the messages will be processed on beforeCompile event. - CompileRun(source_1); - v8::Debug::SendCommand( - isolate, buffer, AsciiToUtf16(command_continue, buffer)); - CHECK_EQ(3, TestClientData::constructor_call_counter); - CHECK_EQ(TestClientData::constructor_call_counter, - handled_client_data_instances_count); - CHECK_EQ(TestClientData::constructor_call_counter, - TestClientData::destructor_call_counter); -} - - -/* Test ThreadedDebugging */ -/* This test interrupts a running infinite loop that is - * occupying the v8 thread by a break command from the - * debugger thread. It then changes the value of a - * global object, to make the loop terminate. - */ - -Barriers threaded_debugging_barriers; - -class V8Thread : public v8::base::Thread { - public: - V8Thread() : Thread(Options("V8Thread")) {} - void Run(); - v8::Isolate* isolate() { return isolate_; } - - private: - v8::Isolate* isolate_; -}; - -class DebuggerThread : public v8::base::Thread { - public: - explicit DebuggerThread(v8::Isolate* isolate) - : Thread(Options("DebuggerThread")), isolate_(isolate) {} - void Run(); - - private: - v8::Isolate* isolate_; -}; - - -static void ThreadedAtBarrier1( - const v8::FunctionCallbackInfo<v8::Value>& args) { - threaded_debugging_barriers.barrier_1.Wait(); -} - - -static void ThreadedMessageHandler(const v8::Debug::Message& message) { - static char print_buffer[1000]; - v8::String::Value json(message.GetJSON()); - Utf16ToAscii(*json, json.length(), print_buffer); - if (IsBreakEventMessage(print_buffer)) { - // Check that we are inside the while loop. - int source_line = GetSourceLineFromBreakEventMessage(print_buffer); - CHECK(4 <= source_line && source_line <= 10); - threaded_debugging_barriers.barrier_2.Wait(); - } -} - - -void V8Thread::Run() { - const char* source = - "flag = true;\n" - "\n" - "function foo() {\n" - " var x = 1;\n" - " while ( flag == true ) {\n" - " if ( x == 1 ) {\n" - " ThreadedAtBarrier1();\n" - " }\n" - " x = x + 1;\n" - " }\n" - "}\n" - "\n" - "foo();\n"; - - v8::Isolate::CreateParams create_params; - create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); - isolate_ = v8::Isolate::New(create_params); - threaded_debugging_barriers.barrier_3.Wait(); - { - v8::Isolate::Scope isolate_scope(isolate_); - DebugLocalContext env(isolate_); - v8::HandleScope scope(isolate_); - v8::Debug::SetMessageHandler(isolate_, &ThreadedMessageHandler); - v8::Local<v8::ObjectTemplate> global_template = - v8::ObjectTemplate::New(env->GetIsolate()); - global_template->Set( - v8_str(env->GetIsolate(), "ThreadedAtBarrier1"), - v8::FunctionTemplate::New(isolate_, ThreadedAtBarrier1)); - v8::Local<v8::Context> context = - v8::Context::New(isolate_, NULL, global_template); - v8::Context::Scope context_scope(context); - - CompileRun(source); - } - threaded_debugging_barriers.barrier_4.Wait(); - isolate_->Dispose(); -} - - -void DebuggerThread::Run() { - const int kBufSize = 1000; - uint16_t buffer[kBufSize]; - - const char* command_1 = - "{\"seq\":102," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"flag = false\"}}"; - const char* command_2 = "{\"seq\":103," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; - - threaded_debugging_barriers.barrier_1.Wait(); - v8::Debug::DebugBreak(isolate_); - threaded_debugging_barriers.barrier_2.Wait(); - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer)); - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer)); - threaded_debugging_barriers.barrier_4.Wait(); -} - - -TEST(ThreadedDebugging) { - V8Thread v8_thread; - - // Create a V8 environment - v8_thread.Start(); - threaded_debugging_barriers.barrier_3.Wait(); - DebuggerThread debugger_thread(v8_thread.isolate()); - debugger_thread.Start(); - - v8_thread.Join(); - debugger_thread.Join(); -} - - -/* Test RecursiveBreakpoints */ -/* In this test, the debugger evaluates a function with a breakpoint, after - * hitting a breakpoint in another function. We do this with both values - * of the flag enabling recursive breakpoints, and verify that the second - * breakpoint is hit when enabled, and missed when disabled. - */ - -class BreakpointsV8Thread : public v8::base::Thread { - public: - BreakpointsV8Thread() : Thread(Options("BreakpointsV8Thread")) {} - void Run(); - - v8::Isolate* isolate() { return isolate_; } - - private: - v8::Isolate* isolate_; -}; - -class BreakpointsDebuggerThread : public v8::base::Thread { - public: - BreakpointsDebuggerThread(bool global_evaluate, v8::Isolate* isolate) - : Thread(Options("BreakpointsDebuggerThread")), - global_evaluate_(global_evaluate), - isolate_(isolate) {} - void Run(); - - private: - bool global_evaluate_; - v8::Isolate* isolate_; -}; - - -Barriers* breakpoints_barriers; -int break_event_breakpoint_id; -int evaluate_int_result; - -static void BreakpointsMessageHandler(const v8::Debug::Message& message) { - static char print_buffer[1000]; - v8::String::Value json(message.GetJSON()); - Utf16ToAscii(*json, json.length(), print_buffer); - - if (IsBreakEventMessage(print_buffer)) { - break_event_breakpoint_id = - GetBreakpointIdFromBreakEventMessage(print_buffer); - breakpoints_barriers->semaphore_1.Signal(); - } else if (IsEvaluateResponseMessage(print_buffer)) { - evaluate_int_result = GetEvaluateIntResult(print_buffer); - breakpoints_barriers->semaphore_1.Signal(); - } -} - - -void BreakpointsV8Thread::Run() { - const char* source_1 = "var y_global = 3;\n" - "function cat( new_value ) {\n" - " var x = new_value;\n" - " y_global = y_global + 4;\n" - " x = 3 * x + 1;\n" - " y_global = y_global + 5;\n" - " return x;\n" - "}\n" - "\n" - "function dog() {\n" - " var x = 1;\n" - " x = y_global;" - " var z = 3;" - " x += 100;\n" - " return x;\n" - "}\n" - "\n"; - const char* source_2 = "cat(17);\n" - "cat(19);\n"; - - v8::Isolate::CreateParams create_params; - create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); - isolate_ = v8::Isolate::New(create_params); - breakpoints_barriers->barrier_3.Wait(); - { - v8::Isolate::Scope isolate_scope(isolate_); - DebugLocalContext env(isolate_); - v8::HandleScope scope(isolate_); - v8::Debug::SetMessageHandler(isolate_, &BreakpointsMessageHandler); - - CompileRun(source_1); - breakpoints_barriers->barrier_1.Wait(); - breakpoints_barriers->barrier_2.Wait(); - CompileRun(source_2); - } - breakpoints_barriers->barrier_4.Wait(); - isolate_->Dispose(); -} - - -void BreakpointsDebuggerThread::Run() { - const int kBufSize = 1000; - uint16_t buffer[kBufSize]; - - const char* command_1 = "{\"seq\":101," - "\"type\":\"request\"," - "\"command\":\"setbreakpoint\"," - "\"arguments\":{\"type\":\"function\",\"target\":\"cat\",\"line\":3}}"; - const char* command_2 = "{\"seq\":102," - "\"type\":\"request\"," - "\"command\":\"setbreakpoint\"," - "\"arguments\":{\"type\":\"function\",\"target\":\"dog\",\"line\":3}}"; - const char* command_3; - if (this->global_evaluate_) { - command_3 = "{\"seq\":103," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false," - "\"global\":true}}"; - } else { - command_3 = "{\"seq\":103," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":false}}"; - } - const char* command_4; - if (this->global_evaluate_) { - command_4 = "{\"seq\":104," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"100 + 8\",\"disable_break\":true," - "\"global\":true}}"; - } else { - command_4 = "{\"seq\":104," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"x + 1\",\"disable_break\":true}}"; - } - const char* command_5 = "{\"seq\":105," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; - const char* command_6 = "{\"seq\":106," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; - const char* command_7; - if (this->global_evaluate_) { - command_7 = "{\"seq\":107," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true," - "\"global\":true}}"; - } else { - command_7 = "{\"seq\":107," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"dog()\",\"disable_break\":true}}"; - } - const char* command_8 = "{\"seq\":108," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; - - - // v8 thread initializes, runs source_1 - breakpoints_barriers->barrier_1.Wait(); - // 1:Set breakpoint in cat() (will get id 1). - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_1, buffer)); - // 2:Set breakpoint in dog() (will get id 2). - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_2, buffer)); - breakpoints_barriers->barrier_2.Wait(); - // V8 thread starts compiling source_2. - // Automatic break happens, to run queued commands - // breakpoints_barriers->semaphore_1.Wait(); - // Commands 1 through 3 run, thread continues. - // v8 thread runs source_2 to breakpoint in cat(). - // message callback receives break event. - breakpoints_barriers->semaphore_1.Wait(); - // Must have hit breakpoint #1. - CHECK_EQ(1, break_event_breakpoint_id); - // 4:Evaluate dog() (which has a breakpoint). - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_3, buffer)); - // V8 thread hits breakpoint in dog(). - breakpoints_barriers->semaphore_1.Wait(); // wait for break event - // Must have hit breakpoint #2. - CHECK_EQ(2, break_event_breakpoint_id); - // 5:Evaluate (x + 1). - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_4, buffer)); - // Evaluate (x + 1) finishes. - breakpoints_barriers->semaphore_1.Wait(); - // Must have result 108. - CHECK_EQ(108, evaluate_int_result); - // 6:Continue evaluation of dog(). - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_5, buffer)); - // Evaluate dog() finishes. - breakpoints_barriers->semaphore_1.Wait(); - // Must have result 107. - CHECK_EQ(107, evaluate_int_result); - // 7:Continue evaluation of source_2, finish cat(17), hit breakpoint - // in cat(19). - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_6, buffer)); - // Message callback gets break event. - breakpoints_barriers->semaphore_1.Wait(); // wait for break event - // Must have hit breakpoint #1. - CHECK_EQ(1, break_event_breakpoint_id); - // 8: Evaluate dog() with breaks disabled. - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_7, buffer)); - // Evaluate dog() finishes. - breakpoints_barriers->semaphore_1.Wait(); - // Must have result 116. - CHECK_EQ(116, evaluate_int_result); - // 9: Continue evaluation of source2, reach end. - v8::Debug::SendCommand(isolate_, buffer, AsciiToUtf16(command_8, buffer)); - breakpoints_barriers->barrier_4.Wait(); -} - - -void TestRecursiveBreakpointsGeneric(bool global_evaluate) { - BreakpointsV8Thread breakpoints_v8_thread; - - // Create a V8 environment - Barriers stack_allocated_breakpoints_barriers; - breakpoints_barriers = &stack_allocated_breakpoints_barriers; - - breakpoints_v8_thread.Start(); - breakpoints_barriers->barrier_3.Wait(); - BreakpointsDebuggerThread breakpoints_debugger_thread( - global_evaluate, breakpoints_v8_thread.isolate()); - breakpoints_debugger_thread.Start(); - - breakpoints_v8_thread.Join(); - breakpoints_debugger_thread.Join(); -} - - -TEST(RecursiveBreakpoints) { - TestRecursiveBreakpointsGeneric(false); -} - - -TEST(RecursiveBreakpointsGlobal) { - TestRecursiveBreakpointsGeneric(true); -} - - TEST(SetDebugEventListenerOnUninitializedVM) { v8::Debug::SetDebugEventListener(CcTest::isolate(), DummyDebugEventListener); } - -static void DummyMessageHandler(const v8::Debug::Message& message) { -} - - -TEST(SetMessageHandlerOnUninitializedVM) { - v8::Debug::SetMessageHandler(CcTest::isolate(), DummyMessageHandler); -} - - // Source for a JavaScript function which returns the data parameter of a // function called in the context of the debugger. If no data parameter is // passed it throws an exception. @@ -5931,19 +4838,6 @@ TEST(CallFunctionInDebugger) { } -// Debugger message handler which counts the number of breaks. -static void SendContinueCommand(); -static void MessageHandlerBreakPointHitCount( - const v8::Debug::Message& message) { - if (message.IsEvent() && message.GetEvent() == v8::Break) { - // Count the number of breaks. - break_point_hit_count++; - - SendContinueCommand(); - } -} - - // Test that clearing the debug event listener actually clears all break points // and related information. TEST(DebuggerUnload) { @@ -5983,132 +4877,41 @@ TEST(DebuggerUnload) { // outside a handle scope. v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate(), true); - - // Now set a debug message handler. - break_point_hit_count = 0; - v8::Debug::SetMessageHandler(env->GetIsolate(), - MessageHandlerBreakPointHitCount); - { - v8::HandleScope scope(env->GetIsolate()); - - // Get the test functions again. - v8::Local<v8::Function> foo(v8::Local<v8::Function>::Cast( - env->Global() - ->Get(context, v8_str(env->GetIsolate(), "foo")) - .ToLocalChecked())); - - foo->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(0, break_point_hit_count); - - // Set break points and run again. - SetBreakPoint(foo, 0); - SetBreakPoint(foo, 4); - foo->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(2, break_point_hit_count); - } - - // Remove the debug message handler without clearing breakpoints. Do this - // outside a handle scope. - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); - CheckDebuggerUnloaded(env->GetIsolate(), true); } +int event_listener_hit_count = 0; -// Sends continue command to the debugger. -static void SendContinueCommand() { - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - const char* command_continue = - "{\"seq\":0," - "\"type\":\"request\"," - "\"command\":\"continue\"}"; +// Debugger event listener which clears itself while active. +static void EventListenerClearingItself( + const v8::Debug::EventDetails& details) { + event_listener_hit_count++; - v8::Debug::SendCommand( - CcTest::isolate(), buffer, AsciiToUtf16(command_continue, buffer)); -} - - -// Debugger message handler which counts the number of times it is called. -static int message_handler_hit_count = 0; -static void MessageHandlerHitCount(const v8::Debug::Message& message) { - message_handler_hit_count++; - - static char print_buffer[1000]; - v8::String::Value json(message.GetJSON()); - Utf16ToAscii(*json, json.length(), print_buffer); - if (IsExceptionEventMessage(print_buffer)) { - // Send a continue command for exception events. - SendContinueCommand(); - } -} - - -// Test clearing the debug message handler. -TEST(DebuggerClearMessageHandler) { - DebugLocalContext env; - v8::HandleScope scope(env->GetIsolate()); - - // Check debugger is unloaded before it is used. - CheckDebuggerUnloaded(env->GetIsolate()); - - // Set a debug message handler. - v8::Debug::SetMessageHandler(env->GetIsolate(), MessageHandlerHitCount); - - // Run code to throw a unhandled exception. This should end up in the message - // handler. - CompileRun("throw 1"); - - // The message handler should be called. - CHECK_GT(message_handler_hit_count, 0); - - // Clear debug message handler. - message_handler_hit_count = 0; - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); - - // Run code to throw a unhandled exception. This should end up in the message - // handler. - CompileRun("throw 1"); - - // The message handler should not be called more. - CHECK_EQ(0, message_handler_hit_count); - - CheckDebuggerUnloaded(env->GetIsolate(), true); -} - - -// Debugger message handler which clears the message handler while active. -static void MessageHandlerClearingMessageHandler( - const v8::Debug::Message& message) { - message_handler_hit_count++; - - // Clear debug message handler. - v8::Debug::SetMessageHandler(message.GetIsolate(), nullptr); + // Clear debug event listener. + v8::Debug::SetDebugEventListener(details.GetIsolate(), nullptr); } // Test clearing the debug message handler while processing a debug event. -TEST(DebuggerClearMessageHandlerWhileActive) { +TEST(DebuggerClearEventListenerWhileActive) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); // Check debugger is unloaded before it is used. CheckDebuggerUnloaded(env->GetIsolate()); - // Set a debug message handler. - v8::Debug::SetMessageHandler(env->GetIsolate(), - MessageHandlerClearingMessageHandler); + // Set a debug event listener. + v8::Debug::SetDebugEventListener(env->GetIsolate(), + EventListenerClearingItself); - // Run code to throw a unhandled exception. This should end up in the message - // handler. + // Run code to throw an uncaught exception. This should trigger the listener. CompileRun("throw 1"); - // The message handler should be called. - CHECK_EQ(1, message_handler_hit_count); + // The event listener should have been called. + CHECK_EQ(1, event_listener_hit_count); CheckDebuggerUnloaded(env->GetIsolate(), true); } - // Test for issue http://code.google.com/p/v8/issues/detail?id=289. // Make sure that DebugGetLoadedScripts doesn't return scripts // with disposed external source. @@ -6258,26 +5061,18 @@ static v8::Local<v8::Value> expected_context_data; // Check that the expected context is the one generating the debug event. -static void ContextCheckMessageHandler(const v8::Debug::Message& message) { - CHECK(message.GetEventContext() == expected_context); - CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals( +static void ContextCheckEventListener( + const v8::Debug::EventDetails& event_details) { + CHECK(event_details.GetEventContext() == expected_context); + CHECK(event_details.GetEventContext()->GetEmbedderData(0)->StrictEquals( expected_context_data)); - message_handler_hit_count++; - - static char print_buffer[1000]; - v8::String::Value json(message.GetJSON()); - Utf16ToAscii(*json, json.length(), print_buffer); - - // Send a continue command for break events. - if (IsBreakEventMessage(print_buffer)) { - SendContinueCommand(); - } + event_listener_hit_count++; } // Test which creates two contexts and sets different embedder data on each. -// Checks that this data is set correctly and that when the debug message -// handler is called the expected context is the one active. +// Checks that this data is set correctly and that when the debug event +// listener is called the expected context is the one active. TEST(ContextData) { v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope scope(isolate); @@ -6291,7 +5086,7 @@ TEST(ContextData) { context_1 = v8::Context::New(isolate, NULL, global_template, global_object); context_2 = v8::Context::New(isolate, NULL, global_template, global_object); - v8::Debug::SetMessageHandler(isolate, ContextCheckMessageHandler); + v8::Debug::SetDebugEventListener(isolate, ContextCheckEventListener); // Default data value is undefined. CHECK(context_1->GetEmbedderData(0)->IsUndefined()); @@ -6328,39 +5123,31 @@ TEST(ContextData) { } // Two times compile event and two times break event. - CHECK_GT(message_handler_hit_count, 4); + CHECK_GT(event_listener_hit_count, 3); - v8::Debug::SetMessageHandler(isolate, nullptr); + v8::Debug::SetDebugEventListener(isolate, nullptr); CheckDebuggerUnloaded(isolate); } - -// Debug message handler which issues a debug break when it hits a break event. -static int message_handler_break_hit_count = 0; -static void DebugBreakMessageHandler(const v8::Debug::Message& message) { +// Debug event listener which issues a debug break when it hits a break event. +static int event_listener_break_hit_count = 0; +static void DebugBreakEventListener(const v8::Debug::EventDetails& details) { // Schedule a debug break for break events. - if (message.IsEvent() && message.GetEvent() == v8::Break) { - message_handler_break_hit_count++; - if (message_handler_break_hit_count == 1) { - v8::Debug::DebugBreak(message.GetIsolate()); + if (details.GetEvent() == v8::Break) { + event_listener_break_hit_count++; + if (event_listener_break_hit_count == 1) { + v8::Debug::DebugBreak(details.GetIsolate()); } } - - // Issue a continue command if this event will not cause the VM to start - // running. - if (!message.WillStartRunning()) { - SendContinueCommand(); - } } - -// Test that a debug break can be scheduled while in a message handler. -TEST(DebugBreakInMessageHandler) { +// Test that a debug break can be scheduled while in a event listener. +TEST(DebugBreakInEventListener) { i::FLAG_turbo_inlining = false; // Make sure g is not inlined into f. DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); - v8::Debug::SetMessageHandler(env->GetIsolate(), DebugBreakMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), DebugBreakEventListener); v8::Local<v8::Context> context = env.context(); // Test functions. @@ -6378,10 +5165,10 @@ TEST(DebugBreakInMessageHandler) { // Call f then g. The debugger statement in f will cause a break which will // cause another break. f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(2, message_handler_break_hit_count); + CHECK_EQ(2, event_listener_break_hit_count); // Calling g will not cause any additional breaks. g->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - CHECK_EQ(2, message_handler_break_hit_count); + CHECK_EQ(2, event_listener_break_hit_count); } @@ -6458,18 +5245,21 @@ TEST(RegExpDebugBreak) { } #endif // V8_INTERPRETED_REGEXP +// Test which creates a context and sets embedder data on it. Checks that this +// data is set correctly and that when the debug event listener is called for +// break event in an eval statement the expected context is the one returned by +// Message.GetEventContext. +TEST(EvalContextData) { + v8::HandleScope scope(CcTest::isolate()); -// Common part of EvalContextData and NestedBreakEventContextData tests. -static void ExecuteScriptForContextCheck( - v8::Debug::MessageHandler message_handler) { - // Create a context. v8::Local<v8::Context> context_1; v8::Local<v8::ObjectTemplate> global_template = v8::Local<v8::ObjectTemplate>(); context_1 = v8::Context::New(CcTest::isolate(), NULL, global_template); - v8::Debug::SetMessageHandler(CcTest::isolate(), message_handler); + v8::Debug::SetDebugEventListener(CcTest::isolate(), + ContextCheckEventListener); // Default data value is undefined. CHECK(context_1->GetEmbedderData(0)->IsUndefined()); @@ -6491,124 +5281,42 @@ static void ExecuteScriptForContextCheck( f->Call(context_1, context_1->Global(), 0, NULL).ToLocalChecked(); } - v8::Debug::SetMessageHandler(CcTest::isolate(), nullptr); -} - - -// Test which creates a context and sets embedder data on it. Checks that this -// data is set correctly and that when the debug message handler is called for -// break event in an eval statement the expected context is the one returned by -// Message.GetEventContext. -TEST(EvalContextData) { - v8::HandleScope scope(CcTest::isolate()); - - ExecuteScriptForContextCheck(ContextCheckMessageHandler); + v8::Debug::SetDebugEventListener(CcTest::isolate(), nullptr); // One time compile event and one time break event. - CHECK_GT(message_handler_hit_count, 2); - CheckDebuggerUnloaded(CcTest::isolate()); -} - - -static bool sent_eval = false; -static int break_count = 0; -static int continue_command_send_count = 0; -// Check that the expected context is the one generating the debug event -// including the case of nested break event. -static void DebugEvalContextCheckMessageHandler( - const v8::Debug::Message& message) { - CHECK(message.GetEventContext() == expected_context); - CHECK(message.GetEventContext()->GetEmbedderData(0)->StrictEquals( - expected_context_data)); - message_handler_hit_count++; - - static char print_buffer[1000]; - v8::String::Value json(message.GetJSON()); - Utf16ToAscii(*json, json.length(), print_buffer); - - v8::Isolate* isolate = message.GetIsolate(); - if (IsBreakEventMessage(print_buffer)) { - break_count++; - if (!sent_eval) { - sent_eval = true; - - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - const char* eval_command = - "{\"seq\":0," - "\"type\":\"request\"," - "\"command\":\"evaluate\"," - "\"arguments\":{\"expression\":\"debugger;\"," - "\"global\":true,\"disable_break\":false}}"; - - // Send evaluate command. - v8::Debug::SendCommand( - isolate, buffer, AsciiToUtf16(eval_command, buffer)); - return; - } else { - // It's a break event caused by the evaluation request above. - SendContinueCommand(); - continue_command_send_count++; - } - } else if (IsEvaluateResponseMessage(print_buffer) && - continue_command_send_count < 2) { - // Response to the evaluation request. We're still on the breakpoint so - // send continue. - SendContinueCommand(); - continue_command_send_count++; - } -} - - -// Tests that context returned for break event is correct when the event occurs -// in 'evaluate' debugger request. -TEST(NestedBreakEventContextData) { - v8::HandleScope scope(CcTest::isolate()); - break_count = 0; - message_handler_hit_count = 0; - - ExecuteScriptForContextCheck(DebugEvalContextCheckMessageHandler); - - // One time compile event and two times break event. - CHECK_GT(message_handler_hit_count, 3); - - // One break from the source and another from the evaluate request. - CHECK_EQ(break_count, 2); + CHECK_GT(event_listener_hit_count, 2); CheckDebuggerUnloaded(CcTest::isolate()); } // Debug event listener which counts the after compile events. -int after_compile_message_count = 0; -static void AfterCompileMessageHandler(const v8::Debug::Message& message) { +int after_compile_event_count = 0; +static void AfterCompileEventListener(const v8::Debug::EventDetails& details) { // Count the number of scripts collected. - if (message.IsEvent()) { - if (message.GetEvent() == v8::AfterCompile) { - after_compile_message_count++; - } else if (message.GetEvent() == v8::Break) { - SendContinueCommand(); - } + if (details.GetEvent() == v8::AfterCompile) { + after_compile_event_count++; } } // Tests that after compile event is sent as many times as there are scripts // compiled. -TEST(AfterCompileMessageWhenMessageHandlerIsReset) { +TEST(AfterCompileEventWhenEventListenerIsReset) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); v8::Local<v8::Context> context = env.context(); - after_compile_message_count = 0; const char* script = "var a=1"; - v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), + AfterCompileEventListener); v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) .ToLocalChecked() ->Run(context) .ToLocalChecked(); - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); - v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), + AfterCompileEventListener); v8::Debug::DebugBreak(env->GetIsolate()); v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) .ToLocalChecked() @@ -6616,11 +5324,11 @@ TEST(AfterCompileMessageWhenMessageHandlerIsReset) { .ToLocalChecked(); // Setting listener to NULL should cause debugger unload. - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate()); // Compilation cache should be disabled when debugger is active. - CHECK_EQ(2, after_compile_message_count); + CHECK_EQ(2, after_compile_event_count); } @@ -6643,7 +5351,7 @@ static void CompileErrorEventCounter( // Tests that syntax error event is sent as many times as there are scripts // with syntax error compiled. -TEST(SyntaxErrorMessageOnSyntaxException) { +TEST(SyntaxErrorEventOnSyntaxException) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -6685,23 +5393,23 @@ TEST(SyntaxErrorMessageOnSyntaxException) { CHECK_EQ(3, compile_error_event_count); } - -// Tests that break event is sent when message handler is reset. -TEST(BreakMessageWhenMessageHandlerIsReset) { +// Tests that break event is sent when event listener is reset. +TEST(BreakEventWhenEventListenerIsReset) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); v8::Local<v8::Context> context = env.context(); - after_compile_message_count = 0; const char* script = "function f() {};"; - v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), + AfterCompileEventListener); v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) .ToLocalChecked() ->Run(context) .ToLocalChecked(); - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); - v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), + AfterCompileEventListener); v8::Debug::DebugBreak(env->GetIsolate()); v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( env->Global() @@ -6709,26 +5417,22 @@ TEST(BreakMessageWhenMessageHandlerIsReset) { .ToLocalChecked()); f->Call(context, env->Global(), 0, NULL).ToLocalChecked(); - // Setting message handler to NULL should cause debugger unload. - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + // Setting event listener to NULL should cause debugger unload. + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate()); // Compilation cache should be disabled when debugger is active. - CHECK_EQ(1, after_compile_message_count); + CHECK_EQ(1, after_compile_event_count); } static int exception_event_count = 0; -static void ExceptionMessageHandler(const v8::Debug::Message& message) { - if (message.IsEvent() && message.GetEvent() == v8::Exception) { - exception_event_count++; - SendContinueCommand(); - } +static void ExceptionEventListener(const v8::Debug::EventDetails& details) { + if (details.GetEvent() == v8::Exception) exception_event_count++; } - -// Tests that exception event is sent when message handler is reset. -TEST(ExceptionMessageWhenMessageHandlerIsReset) { +// Tests that exception event is sent when event listener is reset. +TEST(ExceptionEventWhenEventListenerIsReset) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -6739,22 +5443,23 @@ TEST(ExceptionMessageWhenMessageHandlerIsReset) { exception_event_count = 0; const char* script = "function f() {throw new Error()};"; - v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), + AfterCompileEventListener); v8::Script::Compile(context, v8_str(env->GetIsolate(), script)) .ToLocalChecked() ->Run(context) .ToLocalChecked(); - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); - v8::Debug::SetMessageHandler(env->GetIsolate(), ExceptionMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), ExceptionEventListener); v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast( env->Global() ->Get(context, v8_str(env->GetIsolate(), "f")) .ToLocalChecked()); CHECK(f->Call(context, env->Global(), 0, NULL).IsEmpty()); - // Setting message handler to NULL should cause debugger unload. - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + // Setting event listener to NULL should cause debugger unload. + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate()); CHECK_EQ(1, exception_event_count); @@ -6770,7 +5475,8 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { const char* script = "function f() {};"; const char* resource_name = "test_resource"; - v8::Debug::SetMessageHandler(env->GetIsolate(), AfterCompileMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), + AfterCompileEventListener); v8::Local<v8::Context> context = env.context(); // Set a couple of provisional breakpoint on lines out of the script lines @@ -6780,7 +5486,7 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { int sbp2 = SetScriptBreakPointByNameFromJS(env->GetIsolate(), resource_name, 5, 5); - after_compile_message_count = 0; + after_compile_event_count = 0; v8::ScriptOrigin origin(v8_str(env->GetIsolate(), resource_name), v8::Integer::New(env->GetIsolate(), 10), @@ -6795,46 +5501,28 @@ TEST(ProvisionalBreakpointOnLineOutOfRange) { // If the script is compiled successfully there is exactly one after compile // event. In case of an exception in debugger code after compile event is not // sent. - CHECK_EQ(1, after_compile_message_count); + CHECK_EQ(1, after_compile_event_count); ClearBreakPointFromJS(env->GetIsolate(), sbp1); ClearBreakPointFromJS(env->GetIsolate(), sbp2); - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); + CheckDebuggerUnloaded(env->GetIsolate()); } - -static void BreakMessageHandler(const v8::Debug::Message& message) { - i::Isolate* isolate = CcTest::i_isolate(); - if (message.IsEvent() && message.GetEvent() == v8::Break) { - // Count the number of breaks. - break_point_hit_count++; - - i::HandleScope scope(isolate); - message.GetJSON(); - - SendContinueCommand(); - } else if (message.IsEvent() && message.GetEvent() == v8::AfterCompile) { - i::HandleScope scope(isolate); - - int current_count = break_point_hit_count; - - // Force serialization to trigger some internal JS execution. - message.GetJSON(); - - CHECK_EQ(current_count, break_point_hit_count); - } +static void BreakEventListener(const v8::Debug::EventDetails& details) { + if (details.GetEvent() == v8::Break) break_point_hit_count++; } // Test that if DebugBreak is forced it is ignored when code from // debug-delay.js is executed. -TEST(NoDebugBreakInAfterCompileMessageHandler) { +TEST(NoDebugBreakInAfterCompileEventListener) { DebugLocalContext env; v8::HandleScope scope(env->GetIsolate()); v8::Local<v8::Context> context = env.context(); // Register a debug event listener which sets the break flag and counts. - v8::Debug::SetMessageHandler(env->GetIsolate(), BreakMessageHandler); + v8::Debug::SetDebugEventListener(env->GetIsolate(), BreakEventListener); // Set the debug break flag. v8::Debug::DebugBreak(env->GetIsolate()); @@ -6852,237 +5540,12 @@ TEST(NoDebugBreakInAfterCompileMessageHandler) { // There should be one more break event when the script is evaluated in 'f'. CHECK_EQ(2, break_point_hit_count); - // Get rid of the debug message handler. - v8::Debug::SetMessageHandler(env->GetIsolate(), nullptr); + // Get rid of the debug event listener. + v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CheckDebuggerUnloaded(env->GetIsolate()); } -static int counting_message_handler_counter; - -static void CountingMessageHandler(const v8::Debug::Message& message) { - if (message.IsResponse()) counting_message_handler_counter++; -} - - -// Test that debug messages get processed when ProcessDebugMessages is called. -TEST(ProcessDebugMessages) { - DebugLocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - - counting_message_handler_counter = 0; - - v8::Debug::SetMessageHandler(isolate, CountingMessageHandler); - - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - const char* scripts_command = - "{\"seq\":0," - "\"type\":\"request\"," - "\"command\":\"scripts\"}"; - - // Send scripts command. - v8::Debug::SendCommand( - isolate, buffer, AsciiToUtf16(scripts_command, buffer)); - - CHECK_EQ(0, counting_message_handler_counter); - v8::Debug::ProcessDebugMessages(isolate); - // At least one message should come - CHECK_GE(counting_message_handler_counter, 1); - - counting_message_handler_counter = 0; - - v8::Debug::SendCommand( - isolate, buffer, AsciiToUtf16(scripts_command, buffer)); - v8::Debug::SendCommand( - isolate, buffer, AsciiToUtf16(scripts_command, buffer)); - CHECK_EQ(0, counting_message_handler_counter); - v8::Debug::ProcessDebugMessages(isolate); - // At least two messages should come - CHECK_GE(counting_message_handler_counter, 2); - - // Get rid of the debug message handler. - v8::Debug::SetMessageHandler(isolate, nullptr); - CheckDebuggerUnloaded(isolate); -} - - -class SendCommandThread; -static SendCommandThread* send_command_thread_ = NULL; - - -class SendCommandThread : public v8::base::Thread { - public: - explicit SendCommandThread(v8::Isolate* isolate) - : Thread(Options("SendCommandThread")), - semaphore_(0), - isolate_(isolate) {} - - static void CountingAndSignallingMessageHandler( - const v8::Debug::Message& message) { - if (message.IsResponse()) { - counting_message_handler_counter++; - send_command_thread_->semaphore_.Signal(); - } - } - - virtual void Run() { - semaphore_.Wait(); - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - const char* scripts_command = - "{\"seq\":0," - "\"type\":\"request\"," - "\"command\":\"scripts\"}"; - int length = AsciiToUtf16(scripts_command, buffer); - // Send scripts command. - - for (int i = 0; i < 20; i++) { - v8::base::ElapsedTimer timer; - timer.Start(); - CHECK_EQ(i, counting_message_handler_counter); - // Queue debug message. - v8::Debug::SendCommand(isolate_, buffer, length); - // Wait for the message handler to pick up the response. - semaphore_.Wait(); - i::PrintF("iteration %d took %f ms\n", i, - timer.Elapsed().InMillisecondsF()); - } - - isolate_->TerminateExecution(); - } - - void StartSending() { semaphore_.Signal(); } - - private: - v8::base::Semaphore semaphore_; - v8::Isolate* isolate_; -}; - - -static void StartSendingCommands( - const v8::FunctionCallbackInfo<v8::Value>& info) { - send_command_thread_->StartSending(); -} - - -TEST(ProcessDebugMessagesThreaded) { - DebugLocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = env.context(); - - counting_message_handler_counter = 0; - - v8::Debug::SetMessageHandler( - isolate, SendCommandThread::CountingAndSignallingMessageHandler); - send_command_thread_ = new SendCommandThread(isolate); - send_command_thread_->Start(); - - v8::Local<v8::FunctionTemplate> start = - v8::FunctionTemplate::New(isolate, StartSendingCommands); - CHECK(env->Global() - ->Set(context, v8_str("start"), - start->GetFunction(context).ToLocalChecked()) - .FromJust()); - - CompileRun("start(); while (true) { }"); - - CHECK_EQ(20, counting_message_handler_counter); - - v8::Debug::SetMessageHandler(isolate, nullptr); - CheckDebuggerUnloaded(isolate); -} - - -struct BacktraceData { - static int frame_counter; - static void MessageHandler(const v8::Debug::Message& message) { - char print_buffer[1000]; - v8::String::Value json(message.GetJSON()); - Utf16ToAscii(*json, json.length(), print_buffer, 1000); - - if (strstr(print_buffer, "backtrace") == NULL) { - return; - } - frame_counter = GetTotalFramesInt(print_buffer); - } -}; - -int BacktraceData::frame_counter; - - -// Test that debug messages get processed when ProcessDebugMessages is called. -TEST(Backtrace) { - DebugLocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = env.context(); - - v8::Debug::SetMessageHandler(isolate, BacktraceData::MessageHandler); - - const int kBufferSize = 1000; - uint16_t buffer[kBufferSize]; - const char* scripts_command = - "{\"seq\":0," - "\"type\":\"request\"," - "\"command\":\"backtrace\"}"; - - // Check backtrace from ProcessDebugMessages. - BacktraceData::frame_counter = -10; - v8::Debug::SendCommand( - isolate, - buffer, - AsciiToUtf16(scripts_command, buffer), - NULL); - v8::Debug::ProcessDebugMessages(isolate); - CHECK_EQ(BacktraceData::frame_counter, 0); - - v8::Local<v8::String> void0 = v8_str(env->GetIsolate(), "void(0)"); - v8::Local<v8::Script> script = CompileWithOrigin(void0, void0); - - // Check backtrace from "void(0)" script. - BacktraceData::frame_counter = -10; - v8::Debug::SendCommand( - isolate, - buffer, - AsciiToUtf16(scripts_command, buffer), - NULL); - script->Run(context).ToLocalChecked(); - CHECK_EQ(BacktraceData::frame_counter, 1); - - // Get rid of the debug message handler. - v8::Debug::SetMessageHandler(isolate, nullptr); - CheckDebuggerUnloaded(isolate); -} - - -TEST(GetMirror) { - DebugLocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = env.context(); - v8::Local<v8::Value> obj = - v8::Debug::GetMirror(context, v8_str(isolate, "hodja")).ToLocalChecked(); - v8::ScriptCompiler::Source source(v8_str( - "function runTest(mirror) {" - " return mirror.isString() && (mirror.length() == 5);" - "}" - "" - "runTest;")); - v8::Local<v8::Function> run_test = v8::Local<v8::Function>::Cast( - v8::ScriptCompiler::CompileUnboundScript(isolate, &source) - .ToLocalChecked() - ->BindToCurrentContext() - ->Run(context) - .ToLocalChecked()); - v8::Local<v8::Value> result = - run_test->Call(context, env->Global(), 1, &obj).ToLocalChecked(); - CHECK(result->IsTrue()); -} - - // Test that the debug break flag works with function.apply. TEST(DebugBreakFunctionApply) { DebugLocalContext env; @@ -7200,62 +5663,6 @@ TEST(CallingContextIsNotDebugContext) { } -TEST(DebugContextIsPreservedBetweenAccesses) { - v8::HandleScope scope(CcTest::isolate()); - v8::Debug::SetDebugEventListener(CcTest::isolate(), - DebugEventBreakPointHitCount); - v8::Local<v8::Context> context1 = - v8::Debug::GetDebugContext(CcTest::isolate()); - v8::Local<v8::Context> context2 = - v8::Debug::GetDebugContext(CcTest::isolate()); - CHECK(v8::Utils::OpenHandle(*context1).is_identical_to( - v8::Utils::OpenHandle(*context2))); - v8::Debug::SetDebugEventListener(CcTest::isolate(), nullptr); -} - - -TEST(NoDebugContextWhenDebuggerDisabled) { - v8::HandleScope scope(CcTest::isolate()); - v8::Local<v8::Context> context = - v8::Debug::GetDebugContext(CcTest::isolate()); - CHECK(context.IsEmpty()); -} - -static void DebugEventCheckContext( - const v8::Debug::EventDetails& event_details) { - if (event_details.GetEvent() == v8::Break) { - v8::Isolate* isolate = event_details.GetIsolate(); - CHECK(v8::Debug::GetDebuggedContext(isolate) - .ToLocalChecked() - ->Global() - ->Equals(isolate->GetCurrentContext(), - event_details.GetEventContext()->Global()) - .FromJust()); - } -} - -static void CheckContext(const v8::FunctionCallbackInfo<v8::Value>& args) { - CHECK(v8::Debug::GetDebuggedContext(args.GetIsolate()).IsEmpty()); -} - -TEST(DebuggedContext) { - DebugLocalContext env; - v8::Isolate* isolate = env->GetIsolate(); - - v8::Debug::SetDebugEventListener(isolate, DebugEventCheckContext); - - v8::Local<v8::Function> foo = - CompileFunction(&env, "function foo(){bar=0;}", "foo"); - - SetBreakPoint(foo, 0); - foo->Call(env.context(), env->Global(), 0, nullptr).ToLocalChecked(); - - v8::Local<v8::Function> fun = v8::FunctionTemplate::New(isolate, CheckContext) - ->GetFunction(env.context()) - .ToLocalChecked(); - fun->Call(env.context(), env->Global(), 0, nullptr).ToLocalChecked(); -} - static v8::Local<v8::Value> expected_callback_data; static void DebugEventContextChecker(const v8::Debug::EventDetails& details) { CHECK(details.GetEventContext() == expected_context); @@ -8237,3 +6644,31 @@ TEST(DebugStepOverFunctionWithCaughtException) { v8::Debug::SetDebugEventListener(env->GetIsolate(), nullptr); CHECK_EQ(break_point_hit_count, 4); } + +bool out_of_memory_callback_called = false; +void OutOfMemoryCallback(void* data) { + out_of_memory_callback_called = true; + reinterpret_cast<v8::Isolate*>(data)->IncreaseHeapLimitForDebugging(); +} + +UNINITIALIZED_TEST(DebugSetOutOfMemoryListener) { + v8::Isolate::CreateParams create_params; + create_params.array_buffer_allocator = CcTest::array_buffer_allocator(); + create_params.constraints.set_max_old_space_size(10); + v8::Isolate* isolate = v8::Isolate::New(create_params); + i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate); + { + v8::Isolate::Scope i_scope(isolate); + v8::HandleScope scope(isolate); + LocalContext context(isolate); + v8::debug::SetOutOfMemoryCallback(isolate, OutOfMemoryCallback, + reinterpret_cast<void*>(isolate)); + CHECK(!out_of_memory_callback_called); + // The following allocation fails unless the out-of-memory callback + // increases the heap limit. + int length = 10 * i::MB / i::kPointerSize; + i_isolate->factory()->NewFixedArray(length, i::TENURED); + CHECK(out_of_memory_callback_called); + } + isolate->Dispose(); +} diff --git a/deps/v8/test/cctest/test-disasm-arm.cc b/deps/v8/test/cctest/test-disasm-arm.cc index 1c6d360d7f..3ba6bee8d4 100644 --- a/deps/v8/test/cctest/test-disasm-arm.cc +++ b/deps/v8/test/cctest/test-disasm-arm.cc @@ -936,10 +936,197 @@ TEST(Neon) { "f3886a11 vmovl.u8 q3, d1"); COMPARE(vmovl(NeonU8, q4, d2), "f3888a12 vmovl.u8 q4, d2"); + + COMPARE(vmov(NeonS8, d0, 0, r0), "ee400b10 vmov.8 d0[0], r0"); + COMPARE(vmov(NeonU8, d1, 1, r1), "ee411b30 vmov.8 d1[1], r1"); + COMPARE(vmov(NeonS8, d2, 2, r2), "ee422b50 vmov.8 d2[2], r2"); + COMPARE(vmov(NeonU8, d3, 3, r8), "ee438b70 vmov.8 d3[3], r8"); + COMPARE(vmov(NeonS8, d4, 4, r0), "ee640b10 vmov.8 d4[4], r0"); + COMPARE(vmov(NeonU8, d5, 5, r1), "ee651b30 vmov.8 d5[5], r1"); + COMPARE(vmov(NeonS8, d6, 6, r2), "ee662b50 vmov.8 d6[6], r2"); + COMPARE(vmov(NeonU8, d7, 7, r8), "ee678b70 vmov.8 d7[7], r8"); + COMPARE(vmov(NeonS16, d0, 0, r0), "ee000b30 vmov.16 d0[0], r0"); + COMPARE(vmov(NeonS16, d1, 1, r1), "ee011b70 vmov.16 d1[1], r1"); + COMPARE(vmov(NeonS16, d2, 2, r2), "ee222b30 vmov.16 d2[2], r2"); + COMPARE(vmov(NeonS16, d3, 3, r7), "ee237b70 vmov.16 d3[3], r7"); + COMPARE(vmov(NeonS32, d0, 0, r0), "ee000b10 vmov.32 d0[0], r0"); + COMPARE(vmov(NeonU32, d0, 1, r0), "ee200b10 vmov.32 d0[1], r0"); + + COMPARE(vmov(NeonS8, r0, d0, 0), "ee500b10 vmov.s8 r0, d0[0]"); + COMPARE(vmov(NeonU8, r1, d1, 1), "eed11b30 vmov.u8 r1, d1[1]"); + COMPARE(vmov(NeonS8, r2, d2, 2), "ee522b50 vmov.s8 r2, d2[2]"); + COMPARE(vmov(NeonU8, r8, d3, 3), "eed38b70 vmov.u8 r8, d3[3]"); + COMPARE(vmov(NeonS8, r0, d4, 4), "ee740b10 vmov.s8 r0, d4[4]"); + COMPARE(vmov(NeonU8, r1, d5, 5), "eef51b30 vmov.u8 r1, d5[5]"); + COMPARE(vmov(NeonS8, r2, d6, 6), "ee762b50 vmov.s8 r2, d6[6]"); + COMPARE(vmov(NeonU8, r8, d7, 7), "eef78b70 vmov.u8 r8, d7[7]"); + COMPARE(vmov(NeonS16, r0, d0, 0), "ee100b30 vmov.s16 r0, d0[0]"); + COMPARE(vmov(NeonU16, r1, d1, 1), "ee911b70 vmov.u16 r1, d1[1]"); + COMPARE(vmov(NeonS16, r2, d2, 2), "ee322b30 vmov.s16 r2, d2[2]"); + COMPARE(vmov(NeonU16, r7, d3, 3), "eeb37b70 vmov.u16 r7, d3[3]"); + COMPARE(vmov(NeonS32, r2, d15, 0), "ee1f2b10 vmov.32 r2, d15[0]"); + COMPARE(vmov(NeonS32, r3, d14, 1), "ee3e3b10 vmov.32 r3, d14[1]"); + + COMPARE(vmov(q0, q15), + "f22e01fe vmov q0, q15"); + COMPARE(vmov(q8, q9), + "f26201f2 vmov q8, q9"); + COMPARE(vmvn(q0, q15), + "f3b005ee vmvn q0, q15"); + COMPARE(vmvn(q8, q9), + "f3f005e2 vmvn q8, q9"); COMPARE(vswp(d0, d31), "f3b2002f vswp d0, d31"); COMPARE(vswp(d16, d14), "f3f2000e vswp d16, d14"); + COMPARE(vswp(q0, q15), + "f3b2006e vswp q0, q15"); + COMPARE(vswp(q8, q9), + "f3f20062 vswp q8, q9"); + COMPARE(vdup(Neon8, q0, r0), + "eee00b10 vdup.8 q0, r0"); + COMPARE(vdup(Neon16, q1, r4), + "eea24b30 vdup.16 q1, r4"); + COMPARE(vdup(Neon32, q15, r1), + "eeae1b90 vdup.32 q15, r1"); + COMPARE(vdup(q0, s3), + "f3bc0c41 vdup q0, d1[1]"); + COMPARE(vdup(q15, s2), + "f3f4ec41 vdup q15, d1[0]"); + COMPARE(vcvt_f32_s32(q15, q1), + "f3fbe642 vcvt.f32.s32 q15, q1"); + COMPARE(vcvt_f32_u32(q8, q9), + "f3fb06e2 vcvt.f32.u32 q8, q9"); + COMPARE(vcvt_s32_f32(q15, q1), + "f3fbe742 vcvt.s32.f32 q15, q1"); + COMPARE(vcvt_u32_f32(q8, q9), + "f3fb07e2 vcvt.u32.f32 q8, q9"); + COMPARE(vabs(q0, q1), + "f3b90742 vabs.f32 q0, q1"); + COMPARE(vabs(Neon8, q6, q7), + "f3b1c34e vabs.s8 q6, q7"); + COMPARE(vabs(Neon16, q0, q1), + "f3b50342 vabs.s16 q0, q1"); + COMPARE(vabs(Neon32, q0, q1), + "f3b90342 vabs.s32 q0, q1"); + COMPARE(vneg(q0, q1), + "f3b907c2 vneg.f32 q0, q1"); + COMPARE(vneg(Neon8, q6, q7), + "f3b1c3ce vneg.s8 q6, q7"); + COMPARE(vneg(Neon16, q0, q1), + "f3b503c2 vneg.s16 q0, q1"); + COMPARE(vneg(Neon32, q0, q1), + "f3b903c2 vneg.s32 q0, q1"); + COMPARE(veor(d0, d1, d2), + "f3010112 veor d0, d1, d2"); + COMPARE(veor(d0, d30, d31), + "f30e01bf veor d0, d30, d31"); + COMPARE(veor(q0, q1, q2), + "f3020154 veor q0, q1, q2"); + COMPARE(veor(q15, q0, q8), + "f340e170 veor q15, q0, q8"); + COMPARE(vand(q15, q0, q8), + "f240e170 vand q15, q0, q8"); + COMPARE(vorr(q15, q0, q8), + "f260e170 vorr q15, q0, q8"); + COMPARE(vmin(q15, q0, q8), + "f260ef60 vmin.f32 q15, q0, q8"); + COMPARE(vmax(q15, q0, q8), + "f240ef60 vmax.f32 q15, q0, q8"); + COMPARE(vmax(NeonS8, q0, q1, q2), + "f2020644 vmax.s8 q0, q1, q2"); + COMPARE(vmin(NeonU16, q1, q2, q8), + "f3142670 vmin.u16 q1, q2, q8"); + COMPARE(vmax(NeonS32, q15, q0, q8), + "f260e660 vmax.s32 q15, q0, q8"); + COMPARE(vadd(q15, q0, q8), + "f240ed60 vadd.f32 q15, q0, q8"); + COMPARE(vadd(Neon8, q0, q1, q2), + "f2020844 vadd.i8 q0, q1, q2"); + COMPARE(vadd(Neon16, q1, q2, q8), + "f2142860 vadd.i16 q1, q2, q8"); + COMPARE(vadd(Neon32, q15, q0, q8), + "f260e860 vadd.i32 q15, q0, q8"); + COMPARE(vsub(q15, q0, q8), + "f260ed60 vsub.f32 q15, q0, q8"); + COMPARE(vsub(Neon8, q0, q1, q2), + "f3020844 vsub.i8 q0, q1, q2"); + COMPARE(vsub(Neon16, q1, q2, q8), + "f3142860 vsub.i16 q1, q2, q8"); + COMPARE(vsub(Neon32, q15, q0, q8), + "f360e860 vsub.i32 q15, q0, q8"); + COMPARE(vmul(q0, q1, q2), + "f3020d54 vmul.f32 q0, q1, q2"); + COMPARE(vmul(Neon8, q0, q1, q2), + "f2020954 vmul.i8 q0, q1, q2"); + COMPARE(vmul(Neon16, q1, q2, q8), + "f2142970 vmul.i16 q1, q2, q8"); + COMPARE(vmul(Neon32, q15, q0, q8), + "f260e970 vmul.i32 q15, q0, q8"); + COMPARE(vrecpe(q15, q0), + "f3fbe540 vrecpe.f32 q15, q0"); + COMPARE(vrecps(q15, q0, q8), + "f240ef70 vrecps.f32 q15, q0, q8"); + COMPARE(vrsqrte(q15, q0), + "f3fbe5c0 vrsqrte.f32 q15, q0"); + COMPARE(vrsqrts(q15, q0, q8), + "f260ef70 vrsqrts.f32 q15, q0, q8"); + COMPARE(vtst(Neon8, q0, q1, q2), + "f2020854 vtst.i8 q0, q1, q2"); + COMPARE(vtst(Neon16, q1, q2, q8), + "f2142870 vtst.i16 q1, q2, q8"); + COMPARE(vtst(Neon32, q15, q0, q8), + "f260e870 vtst.i32 q15, q0, q8"); + COMPARE(vceq(q0, q1, q2), + "f2020e44 vceq.f32 q0, q1, q2"); + COMPARE(vcge(q0, q1, q2), + "f3020e44 vcge.f32 q0, q1, q2"); + COMPARE(vcgt(q0, q1, q2), + "f3220e44 vcgt.f32 q0, q1, q2"); + COMPARE(vceq(Neon8, q0, q1, q2), + "f3020854 vceq.i8 q0, q1, q2"); + COMPARE(vceq(Neon16, q1, q2, q8), + "f3142870 vceq.i16 q1, q2, q8"); + COMPARE(vceq(Neon32, q15, q0, q8), + "f360e870 vceq.i32 q15, q0, q8"); + COMPARE(vcge(NeonS8, q0, q1, q2), + "f2020354 vcge.s8 q0, q1, q2"); + COMPARE(vcge(NeonU16, q1, q2, q8), + "f3142370 vcge.u16 q1, q2, q8"); + COMPARE(vcge(NeonS32, q15, q0, q8), + "f260e370 vcge.s32 q15, q0, q8"); + COMPARE(vcgt(NeonS8, q0, q1, q2), + "f2020344 vcgt.s8 q0, q1, q2"); + COMPARE(vcgt(NeonU16, q1, q2, q8), + "f3142360 vcgt.u16 q1, q2, q8"); + COMPARE(vcgt(NeonS32, q15, q0, q8), + "f260e360 vcgt.s32 q15, q0, q8"); + COMPARE(vbsl(q0, q1, q2), + "f3120154 vbsl q0, q1, q2"); + COMPARE(vbsl(q15, q0, q8), + "f350e170 vbsl q15, q0, q8"); + COMPARE(vext(q15, q0, q8, 3), + "f2f0e360 vext.8 q15, q0, q8, #3"); + COMPARE(vzip(Neon16, q15, q0), + "f3f6e1c0 vzip.16 q15, q0"); + COMPARE(vrev64(Neon8, q15, q0), + "f3f0e040 vrev64.8 q15, q0"); + COMPARE(vtbl(d0, NeonListOperand(d1, 1), d2), + "f3b10802 vtbl.8 d0, {d1}, d2"); + COMPARE(vtbl(d31, NeonListOperand(d0, 2), d4), + "f3f0f904 vtbl.8 d31, {d0, d1}, d4"); + COMPARE(vtbl(d15, NeonListOperand(d1, 3), d5), + "f3b1fa05 vtbl.8 d15, {d1, d2, d3}, d5"); + COMPARE(vtbl(d15, NeonListOperand(d1, 4), d5), + "f3b1fb05 vtbl.8 d15, {d1, d2, d3, d4}, d5"); + COMPARE(vtbx(d0, NeonListOperand(d1, 1), d2), + "f3b10842 vtbx.8 d0, {d1}, d2"); + COMPARE(vtbx(d31, NeonListOperand(d0, 2), d4), + "f3f0f944 vtbx.8 d31, {d0, d1}, d4"); + COMPARE(vtbx(d15, NeonListOperand(d1, 3), d5), + "f3b1fa45 vtbx.8 d15, {d1, d2, d3}, d5"); + COMPARE(vtbx(d15, NeonListOperand(d1, 4), d5), + "f3b1fb45 vtbx.8 d15, {d1, d2, d3, d4}, d5"); } VERIFY_RUN(); diff --git a/deps/v8/test/cctest/test-extra.js b/deps/v8/test/cctest/test-extra.js index 0cc4df4cc4..88c5f6e659 100644 --- a/deps/v8/test/cctest/test-extra.js +++ b/deps/v8/test/cctest/test-extra.js @@ -53,7 +53,8 @@ const fulfilledPromise = v8.createPromise(); v8.resolvePromise( fulfilledPromise, - hasOwn({ test: 'test' }, 'test') ? 1 : -1 + hasOwn({ test: 'test' }, 'test') ? 1 : -1, + undefined // pass an extra arg to test arguments adapter frame ); const fulfilledPromise2 = Promise_resolve(call(function (arg1, arg2) { diff --git a/deps/v8/test/cctest/test-feedback-vector.cc b/deps/v8/test/cctest/test-feedback-vector.cc index 1f9ddc6f55..8ff4997c01 100644 --- a/deps/v8/test/cctest/test-feedback-vector.cc +++ b/deps/v8/test/cctest/test-feedback-vector.cc @@ -95,6 +95,20 @@ TEST(VectorStructure) { FeedbackVectorSlotKind::CALL_IC), vector->length()); } + + { + FeedbackVectorSpec spec(&zone); + spec.AddGeneralSlot(); + spec.AddCreateClosureSlot(5); + spec.AddGeneralSlot(); + vector = NewTypeFeedbackVector(isolate, &spec); + FeedbackVectorHelper helper(vector); + CHECK_EQ(1, TypeFeedbackMetadata::GetSlotSize( + FeedbackVectorSlotKind::CREATE_CLOSURE)); + FeedbackVectorSlot slot = helper.slot(1); + FixedArray* array = FixedArray::cast(vector->Get(slot)); + CHECK_EQ(array, *factory->empty_literals_array()); + } } diff --git a/deps/v8/test/cctest/test-field-type-tracking.cc b/deps/v8/test/cctest/test-field-type-tracking.cc index df6a06bfc7..4abde16cd6 100644 --- a/deps/v8/test/cctest/test-field-type-tracking.cc +++ b/deps/v8/test/cctest/test-field-type-tracking.cc @@ -73,23 +73,12 @@ static Handle<AccessorPair> CreateAccessorPair(bool with_getter, } -static bool EqualDetails(DescriptorArray* descriptors, int descriptor, - PropertyType type, PropertyAttributes attributes, - Representation representation, int field_index = -1) { - PropertyDetails details = descriptors->GetDetails(descriptor); - if (details.type() != type) return false; - if (details.attributes() != attributes) return false; - if (!details.representation().Equals(representation)) return false; - if (field_index >= 0 && details.field_index() != field_index) return false; - return true; -} - - class Expectations { static const int MAX_PROPERTIES = 10; Isolate* isolate_; ElementsKind elements_kind_; - PropertyType types_[MAX_PROPERTIES]; + PropertyKind kinds_[MAX_PROPERTIES]; + PropertyLocation locations_[MAX_PROPERTIES]; PropertyAttributes attributes_[MAX_PROPERTIES]; Representation representations_[MAX_PROPERTIES]; // FieldType for kField, value for DATA_CONSTANT and getter for @@ -110,10 +99,12 @@ class Expectations { isolate, isolate->object_function()->initial_map()->elements_kind()) {} - void Init(int index, PropertyType type, PropertyAttributes attributes, - Representation representation, Handle<Object> value) { + void Init(int index, PropertyKind kind, PropertyAttributes attributes, + PropertyLocation location, Representation representation, + Handle<Object> value) { CHECK(index < MAX_PROPERTIES); - types_[index] = type; + kinds_[index] = kind; + locations_[index] = location; attributes_[index] = attributes; representations_[index] = representation; values_[index] = value; @@ -125,29 +116,23 @@ class Expectations { for (int i = 0; i < number_of_properties_; i++) { os << " " << i << ": "; os << "Descriptor @ "; - if (types_[i] == ACCESSOR_CONSTANT) { + + if (kinds_[i] == kData) { + os << Brief(*values_[i]); + } else { + // kAccessor os << "(get: " << Brief(*values_[i]) << ", set: " << Brief(*setter_values_[i]) << ") "; - } else { - os << Brief(*values_[i]); } + os << " ("; - switch (types_[i]) { - case DATA_CONSTANT: - os << "immutable "; - // Fall through. - case DATA: - os << "data"; - break; - - case ACCESSOR_CONSTANT: - os << "immutable "; - // Fall through. - case ACCESSOR: - os << "accessor"; - break; + os << (kinds_[i] == kData ? "data " : "accessor "); + if (locations_[i] == kField) { + os << "field" + << ": " << representations_[i].Mnemonic(); + } else { + os << "descriptor"; } - os << ": " << representations_[i].Mnemonic(); os << ", attrs: " << attributes_[i] << ")\n"; } os << "\n"; @@ -159,22 +144,23 @@ class Expectations { Handle<FieldType> GetFieldType(int index) { CHECK(index < MAX_PROPERTIES); - CHECK(types_[index] == DATA || types_[index] == ACCESSOR); + CHECK_EQ(kField, locations_[index]); return Handle<FieldType>::cast(values_[index]); } void SetDataField(int index, PropertyAttributes attrs, - Representation representation, Handle<FieldType> value) { - Init(index, DATA, attrs, representation, value); + Representation representation, + Handle<FieldType> field_type) { + Init(index, kData, attrs, kField, representation, field_type); } void SetDataField(int index, Representation representation, - Handle<FieldType> value) { - SetDataField(index, attributes_[index], representation, value); + Handle<FieldType> field_type) { + SetDataField(index, attributes_[index], representation, field_type); } void SetAccessorField(int index, PropertyAttributes attrs) { - Init(index, ACCESSOR, attrs, Representation::Tagged(), + Init(index, kAccessor, attrs, kDescriptor, Representation::Tagged(), FieldType::Any(isolate_)); } @@ -184,7 +170,7 @@ class Expectations { void SetDataConstant(int index, PropertyAttributes attrs, Handle<JSFunction> value) { - Init(index, DATA_CONSTANT, attrs, Representation::HeapObject(), value); + Init(index, kData, attrs, kDescriptor, Representation::HeapObject(), value); } void SetDataConstant(int index, Handle<JSFunction> value) { @@ -193,14 +179,16 @@ class Expectations { void SetAccessorConstant(int index, PropertyAttributes attrs, Handle<Object> getter, Handle<Object> setter) { - Init(index, ACCESSOR_CONSTANT, attrs, Representation::Tagged(), getter); + Init(index, kAccessor, attrs, kDescriptor, Representation::Tagged(), + getter); setter_values_[index] = setter; } void SetAccessorConstantComponent(int index, PropertyAttributes attrs, AccessorComponent component, Handle<Object> accessor) { - CHECK_EQ(ACCESSOR_CONSTANT, types_[index]); + CHECK_EQ(kAccessor, kinds_[index]); + CHECK_EQ(kDescriptor, locations_[index]); CHECK(index < number_of_properties_); if (component == ACCESSOR_GETTER) { values_[index] = accessor; @@ -230,31 +218,41 @@ class Expectations { void GeneralizeRepresentation(int index) { CHECK(index < number_of_properties_); representations_[index] = Representation::Tagged(); - if (types_[index] == DATA || types_[index] == ACCESSOR) { + if (locations_[index] == kField) { values_[index] = FieldType::Any(isolate_); } } bool Check(DescriptorArray* descriptors, int descriptor) const { - PropertyType type = types_[descriptor]; - if (!EqualDetails(descriptors, descriptor, type, attributes_[descriptor], - representations_[descriptor])) { - return false; - } + PropertyDetails details = descriptors->GetDetails(descriptor); + + if (details.kind() != kinds_[descriptor]) return false; + if (details.location() != locations_[descriptor]) return false; + + PropertyAttributes expected_attributes = attributes_[descriptor]; + if (details.attributes() != expected_attributes) return false; + + Representation expected_representation = representations_[descriptor]; + if (!details.representation().Equals(expected_representation)) return false; + Object* value = descriptors->GetValue(descriptor); Object* expected_value = *values_[descriptor]; - switch (type) { - case DATA: - case ACCESSOR: { + if (details.location() == kField) { + if (details.kind() == kData) { FieldType* type = descriptors->GetFieldType(descriptor); return FieldType::cast(expected_value) == type; + } else { + // kAccessor + UNREACHABLE(); + return false; } - - case DATA_CONSTANT: + } else { + // kDescriptor + if (details.kind() == kData) { return value == expected_value; - - case ACCESSOR_CONSTANT: { + } else { + // kAccessor if (value == expected_value) return true; if (!value->IsAccessorPair()) return false; AccessorPair* pair = AccessorPair::cast(value); @@ -376,8 +374,8 @@ class Expectations { Handle<String> name = MakeName("prop", property_index); - AccessorConstantDescriptor new_desc(name, pair, attributes); - return Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION); + Descriptor d = Descriptor::AccessorConstant(name, pair, attributes); + return Map::CopyInsertDescriptor(map, &d, INSERT_TRANSITION); } Handle<Map> AddAccessorConstant(Handle<Map> map, @@ -396,14 +394,14 @@ class Expectations { if (!getter->IsNull(isolate_)) { Handle<AccessorPair> pair = factory->NewAccessorPair(); pair->SetComponents(*getter, *factory->null_value()); - AccessorConstantDescriptor new_desc(name, pair, attributes); - map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION); + Descriptor d = Descriptor::AccessorConstant(name, pair, attributes); + map = Map::CopyInsertDescriptor(map, &d, INSERT_TRANSITION); } if (!setter->IsNull(isolate_)) { Handle<AccessorPair> pair = factory->NewAccessorPair(); pair->SetComponents(*getter, *setter); - AccessorConstantDescriptor new_desc(name, pair, attributes); - map = Map::CopyInsertDescriptor(map, &new_desc, INSERT_TRANSITION); + Descriptor d = Descriptor::AccessorConstant(name, pair, attributes); + map = Map::CopyInsertDescriptor(map, &d, INSERT_TRANSITION); } return map; } @@ -457,7 +455,7 @@ TEST(ReconfigureAccessorToNonExistingDataField) { CHECK(expectations.Check(*map)); Handle<Map> new_map = Map::ReconfigureProperty( - map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD); + map, 0, kData, NONE, Representation::None(), none_type); // |map| did not change except marked unstable. CHECK(!map->is_deprecated()); CHECK(!map->is_stable()); @@ -470,7 +468,7 @@ TEST(ReconfigureAccessorToNonExistingDataField) { CHECK(expectations.Check(*new_map)); Handle<Map> new_map2 = Map::ReconfigureProperty( - map, 0, kData, NONE, Representation::None(), none_type, FORCE_FIELD); + map, 0, kData, NONE, Representation::None(), none_type); CHECK_EQ(*new_map, *new_map2); Handle<Object> value(Smi::kZero, isolate); @@ -594,7 +592,7 @@ static void TestGeneralizeRepresentation( if (is_detached_map) { detach_point_map = Map::ReconfigureProperty( detach_point_map, detach_property_at_index, kData, NONE, - Representation::Tagged(), any_type, FORCE_FIELD); + Representation::Tagged(), any_type); expectations.SetDataField(detach_property_at_index, Representation::Tagged(), any_type); CHECK(map->is_deprecated()); @@ -609,9 +607,8 @@ static void TestGeneralizeRepresentation( dependencies.AssumeFieldOwner(field_owner); - Handle<Map> new_map = - Map::ReconfigureProperty(map, property_index, kData, NONE, - to_representation, to_type, FORCE_FIELD); + Handle<Map> new_map = Map::ReconfigureProperty( + map, property_index, kData, NONE, to_representation, to_type); expectations.SetDataField(property_index, expected_representation, expected_type); @@ -902,7 +899,7 @@ TEST(GeneralizeRepresentationWithAccessorProperties) { continue; } Handle<Map> new_map = Map::ReconfigureProperty( - map, i, kData, NONE, Representation::Double(), any_type, FORCE_FIELD); + map, i, kData, NONE, Representation::Double(), any_type); maps[i] = new_map; expectations.SetDataField(i, Representation::Double(), any_type); @@ -1239,7 +1236,7 @@ struct CheckUnrelated { // Checks that given |map| is NOT deprecated, and |new_map| is a result of // copy-generalize-all-representations. -struct CheckCopyGeneralizeAllRepresentations { +struct CheckCopyGeneralizeAllFields { void Check(Handle<Map> map, Handle<Map> new_map, Expectations& expectations) { CHECK(!map->is_deprecated()); CHECK_NE(*map, *new_map); @@ -1379,11 +1376,23 @@ TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) { struct TestConfig { Handle<JSFunction> js_func1_; Handle<JSFunction> js_func2_; + Handle<FieldType> function_type_; TestConfig() { Isolate* isolate = CcTest::i_isolate(); Factory* factory = isolate->factory(); - js_func1_ = factory->NewFunction(factory->empty_string()); - js_func2_ = factory->NewFunction(factory->empty_string()); + Handle<String> name = factory->empty_string(); + Handle<Map> sloppy_map = + factory->CreateSloppyFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE); + Handle<SharedFunctionInfo> info = factory->NewSharedFunctionInfo( + name, MaybeHandle<Code>(), sloppy_map->is_constructor()); + function_type_ = FieldType::Class(sloppy_map, isolate); + CHECK(sloppy_map->is_stable()); + + js_func1_ = + factory->NewFunction(sloppy_map, info, isolate->native_context()); + + js_func2_ = + factory->NewFunction(sloppy_map, info, isolate->native_context()); } Handle<Map> AddPropertyAtBranch(int branch_id, Expectations& expectations, @@ -1394,11 +1403,8 @@ TEST(ReconfigureDataFieldAttribute_DataConstantToDataFieldAfterTargetMap) { } void UpdateExpectations(int property_index, Expectations& expectations) { - Isolate* isolate = CcTest::i_isolate(); - Handle<FieldType> function_type = - FieldType::Class(isolate->sloppy_function_map(), isolate); expectations.SetDataField(property_index, Representation::HeapObject(), - function_type); + function_type_); } }; @@ -1502,11 +1508,11 @@ TEST(ReconfigureDataFieldAttribute_AccConstantToAccFieldAfterTargetMap) { TestConfig config; if (IS_ACCESSOR_FIELD_SUPPORTED) { - CheckCopyGeneralizeAllRepresentations checker; + CheckCopyGeneralizeAllFields checker; TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); } else { // Currently we have a copy-generalize-all-representations case. - CheckCopyGeneralizeAllRepresentations checker; + CheckCopyGeneralizeAllFields checker; TestReconfigureProperty_CustomPropertyAfterTargetMap(config, checker); } } @@ -1847,8 +1853,7 @@ TEST(ReconfigurePropertySplitMapTransitionsOverflow) { } map2 = Map::ReconfigureProperty(map2, kSplitProp, kData, NONE, - Representation::Double(), any_type, - FORCE_FIELD); + Representation::Double(), any_type); expectations.SetDataField(kSplitProp, Representation::Double(), any_type); CHECK(expectations.Check(*split_map, kSplitProp)); @@ -1947,8 +1952,8 @@ static void TestGeneralizeRepresentationWithSpecialTransition( // Create new maps by generalizing representation of propX field. Handle<Map> maps[kPropCount]; for (int i = 0; i < kPropCount; i++) { - Handle<Map> new_map = Map::ReconfigureProperty( - map, i, kData, NONE, to_representation, to_type, FORCE_FIELD); + Handle<Map> new_map = Map::ReconfigureProperty(map, i, kData, NONE, + to_representation, to_type); maps[i] = new_map; expectations.SetDataField(i, expected_representation, expected_type); @@ -2365,13 +2370,20 @@ TEST(TransitionDataConstantToAnotherDataConstant) { v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); Factory* factory = isolate->factory(); - Handle<FieldType> function_type = - FieldType::Class(isolate->sloppy_function_map(), isolate); - - Handle<JSFunction> js_func1 = factory->NewFunction(factory->empty_string()); + Handle<String> name = factory->empty_string(); + Handle<Map> sloppy_map = + factory->CreateSloppyFunctionMap(FUNCTION_WITH_WRITEABLE_PROTOTYPE); + Handle<SharedFunctionInfo> info = factory->NewSharedFunctionInfo( + name, MaybeHandle<Code>(), sloppy_map->is_constructor()); + Handle<FieldType> function_type = FieldType::Class(sloppy_map, isolate); + CHECK(sloppy_map->is_stable()); + + Handle<JSFunction> js_func1 = + factory->NewFunction(sloppy_map, info, isolate->native_context()); TransitionToDataConstantOperator transition_op1(js_func1); - Handle<JSFunction> js_func2 = factory->NewFunction(factory->empty_string()); + Handle<JSFunction> js_func2 = + factory->NewFunction(sloppy_map, info, isolate->native_context()); TransitionToDataConstantOperator transition_op2(js_func2); FieldGeneralizationChecker checker( diff --git a/deps/v8/test/cctest/test-flags.cc b/deps/v8/test/cctest/test-flags.cc index fd49dae1e9..230b3d1dd0 100644 --- a/deps/v8/test/cctest/test-flags.cc +++ b/deps/v8/test/cctest/test-flags.cc @@ -252,7 +252,7 @@ TEST(FlagsRemoveIncomplete) { // if the list of arguments ends unexpectedly. SetFlagsToDefault(); int argc = 3; - const char* argv[] = { "", "--crankshaft", "--expose-debug-as" }; + const char* argv[] = {"", "--crankshaft", "--expose-natives-as"}; CHECK_EQ(2, FlagList::SetFlagsFromCommandLine(&argc, const_cast<char **>(argv), true)); diff --git a/deps/v8/test/cctest/test-global-handles.cc b/deps/v8/test/cctest/test-global-handles.cc index 256b74c616..2ace0296c1 100644 --- a/deps/v8/test/cctest/test-global-handles.cc +++ b/deps/v8/test/cctest/test-global-handles.cc @@ -29,6 +29,7 @@ #include "src/factory.h" #include "src/global-handles.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/objects.h" #include "test/cctest/cctest.h" diff --git a/deps/v8/test/cctest/test-global-object.cc b/deps/v8/test/cctest/test-global-object.cc index d6713208bf..9f32e05121 100644 --- a/deps/v8/test/cctest/test-global-object.cc +++ b/deps/v8/test/cctest/test-global-object.cc @@ -26,6 +26,7 @@ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "src/api.h" +#include "src/objects-inl.h" #include "src/v8.h" #include "test/cctest/cctest.h" @@ -105,3 +106,30 @@ TEST(KeysGlobalObject_Regress2764) { Local<Array>::Cast(CompileRun("Object.getOwnPropertyNames(global2)")); CHECK_EQ(0u, result->Length()); } + +TEST(KeysGlobalObject_SetPrototype) { + LocalContext env1; + v8::HandleScope scope(env1->GetIsolate()); + + // Create second environment. + v8::Local<Context> env2 = Context::New(env1->GetIsolate()); + + Local<Value> token = v8_str("foo"); + + // Set same security token for env1 and env2. + env1->SetSecurityToken(token); + env2->SetSecurityToken(token); + + // Create a reference to env2 global from env1 global. + env1->Global() + ->GetPrototype() + .As<v8::Object>() + ->SetPrototype(env1.local(), env2->Global()->GetPrototype()) + .FromJust(); + // Set some global variables in global2 + env2->Global()->Set(env2, v8_str("a"), v8_str("a")).FromJust(); + env2->Global()->Set(env2, v8_str("42"), v8_str("42")).FromJust(); + + // List all entries from global2. + ExpectTrue("a == 'a'"); +} diff --git a/deps/v8/test/cctest/test-heap-profiler.cc b/deps/v8/test/cctest/test-heap-profiler.cc index 9721477b28..9780b3f519 100644 --- a/deps/v8/test/cctest/test-heap-profiler.cc +++ b/deps/v8/test/cctest/test-heap-profiler.cc @@ -69,10 +69,10 @@ class NamedEntriesDetector { CheckEntry(root); while (!list.is_empty()) { i::HeapEntry* entry = list.RemoveLast(); - i::Vector<i::HeapGraphEdge*> children = entry->children(); - for (int i = 0; i < children.length(); ++i) { - if (children[i]->type() == i::HeapGraphEdge::kShortcut) continue; - i::HeapEntry* child = children[i]->to(); + for (int i = 0; i < entry->children_count(); ++i) { + i::HeapGraphEdge* edge = entry->child(i); + if (edge->type() == i::HeapGraphEdge::kShortcut) continue; + i::HeapEntry* child = edge->to(); v8::base::HashMap::Entry* entry = visited.LookupOrInsert( reinterpret_cast<void*>(child), static_cast<uint32_t>(reinterpret_cast<uintptr_t>(child))); @@ -137,8 +137,8 @@ static bool ValidateSnapshot(const v8::HeapSnapshot* snapshot, int depth = 3) { reinterpret_cast<const i::HeapSnapshot*>(snapshot)); v8::base::HashMap visited; - i::List<i::HeapGraphEdge>& edges = heap_snapshot->edges(); - for (int i = 0; i < edges.length(); ++i) { + std::deque<i::HeapGraphEdge>& edges = heap_snapshot->edges(); + for (size_t i = 0; i < edges.size(); ++i) { v8::base::HashMap::Entry* entry = visited.LookupOrInsert( reinterpret_cast<void*>(edges[i].to()), static_cast<uint32_t>(reinterpret_cast<uintptr_t>(edges[i].to()))); @@ -1570,88 +1570,6 @@ TEST(HeapSnapshotRetainedObjectInfo) { CHECK_EQ(ccc, GetProperty(n_CCC, v8::HeapGraphEdge::kInternal, "native")); } - -class GraphWithImplicitRefs { - public: - static const int kObjectsCount = 4; - explicit GraphWithImplicitRefs(LocalContext* env) { - CHECK(!instance_); - instance_ = this; - isolate_ = (*env)->GetIsolate(); - for (int i = 0; i < kObjectsCount; i++) { - objects_[i].Reset(isolate_, v8::Object::New(isolate_)); - } - (*env) - ->Global() - ->Set(isolate_->GetCurrentContext(), v8_str("root_object"), - v8::Local<v8::Value>::New(isolate_, objects_[0])) - .FromJust(); - } - ~GraphWithImplicitRefs() { - instance_ = NULL; - } - - static void gcPrologue(v8::Isolate* isolate, v8::GCType type, - v8::GCCallbackFlags flags) { - instance_->AddImplicitReferences(); - } - - private: - void AddImplicitReferences() { - // 0 -> 1 - isolate_->SetObjectGroupId(objects_[0], - v8::UniqueId(1)); - isolate_->SetReferenceFromGroup( - v8::UniqueId(1), objects_[1]); - // Adding two more references: 1 -> 2, 1 -> 3 - isolate_->SetReference(objects_[1].As<v8::Object>(), - objects_[2]); - isolate_->SetReference(objects_[1].As<v8::Object>(), - objects_[3]); - } - - v8::Persistent<v8::Value> objects_[kObjectsCount]; - static GraphWithImplicitRefs* instance_; - v8::Isolate* isolate_; -}; - -GraphWithImplicitRefs* GraphWithImplicitRefs::instance_ = NULL; - - -TEST(HeapSnapshotImplicitReferences) { - LocalContext env; - v8::HandleScope scope(env->GetIsolate()); - v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); - - GraphWithImplicitRefs graph(&env); - env->GetIsolate()->AddGCPrologueCallback(&GraphWithImplicitRefs::gcPrologue); - - const v8::HeapSnapshot* snapshot = heap_profiler->TakeHeapSnapshot(); - CHECK(ValidateSnapshot(snapshot)); - - const v8::HeapGraphNode* global_object = GetGlobalObject(snapshot); - const v8::HeapGraphNode* obj0 = GetProperty( - global_object, v8::HeapGraphEdge::kProperty, "root_object"); - CHECK(obj0); - CHECK_EQ(v8::HeapGraphNode::kObject, obj0->GetType()); - const v8::HeapGraphNode* obj1 = GetProperty( - obj0, v8::HeapGraphEdge::kInternal, "native"); - CHECK(obj1); - int implicit_targets_count = 0; - for (int i = 0, count = obj1->GetChildrenCount(); i < count; ++i) { - const v8::HeapGraphEdge* prop = obj1->GetChild(i); - v8::String::Utf8Value prop_name(prop->GetName()); - if (prop->GetType() == v8::HeapGraphEdge::kInternal && - strcmp("native", *prop_name) == 0) { - ++implicit_targets_count; - } - } - CHECK_EQ(2, implicit_targets_count); - env->GetIsolate()->RemoveGCPrologueCallback( - &GraphWithImplicitRefs::gcPrologue); -} - - TEST(DeleteAllHeapSnapshots) { LocalContext env; v8::HandleScope scope(env->GetIsolate()); @@ -2568,7 +2486,7 @@ TEST(TrackHeapAllocationsWithInlining) { const char* names[] = {"", "start", "f_0_0"}; AllocationTraceNode* node = FindNode(tracker, ArrayVector(names)); CHECK(node); - CHECK_GE(node->allocation_count(), 12u); + CHECK_GE(node->allocation_count(), 10u); CHECK_GE(node->allocation_size(), 4 * node->allocation_count()); heap_profiler->StopTrackingHeapObjects(); } diff --git a/deps/v8/test/cctest/test-inobject-slack-tracking.cc b/deps/v8/test/cctest/test-inobject-slack-tracking.cc index 9f33d55938..3c46fbee06 100644 --- a/deps/v8/test/cctest/test-inobject-slack-tracking.cc +++ b/deps/v8/test/cctest/test-inobject-slack-tracking.cc @@ -7,6 +7,7 @@ #include <utility> #include "src/api.h" +#include "src/objects-inl.h" #include "src/objects.h" #include "src/v8.h" @@ -1099,10 +1100,8 @@ TEST(SubclassPromiseBuiltin) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); - const int first_field = 5; TestSubclassBuiltin("A1", JS_PROMISE_TYPE, "Promise", - "function(resolve, reject) { resolve('ok'); }", - first_field); + "function(resolve, reject) { resolve('ok'); }"); } diff --git a/deps/v8/test/cctest/test-javascript-arm64.cc b/deps/v8/test/cctest/test-javascript-arm64.cc index aa4988ef06..d23b63e0a9 100644 --- a/deps/v8/test/cctest/test-javascript-arm64.cc +++ b/deps/v8/test/cctest/test-javascript-arm64.cc @@ -34,6 +34,7 @@ #include "src/compilation-cache.h" #include "src/execution.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/unicode-inl.h" #include "src/utils.h" #include "test/cctest/cctest.h" diff --git a/deps/v8/test/cctest/test-js-arm64-variables.cc b/deps/v8/test/cctest/test-js-arm64-variables.cc index f6958fd422..dbcf8f94ac 100644 --- a/deps/v8/test/cctest/test-js-arm64-variables.cc +++ b/deps/v8/test/cctest/test-js-arm64-variables.cc @@ -36,6 +36,7 @@ #include "src/compilation-cache.h" #include "src/execution.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/unicode-inl.h" #include "src/utils.h" #include "test/cctest/cctest.h" diff --git a/deps/v8/test/cctest/test-liveedit.cc b/deps/v8/test/cctest/test-liveedit.cc index 7525676b84..cde9e92331 100644 --- a/deps/v8/test/cctest/test-liveedit.cc +++ b/deps/v8/test/cctest/test-liveedit.cc @@ -30,6 +30,7 @@ #include "src/v8.h" #include "src/debug/liveedit.h" +#include "src/objects-inl.h" #include "test/cctest/cctest.h" diff --git a/deps/v8/test/cctest/test-lockers.cc b/deps/v8/test/cctest/test-lockers.cc index 4d4f3e2177..30fba8ac98 100644 --- a/deps/v8/test/cctest/test-lockers.cc +++ b/deps/v8/test/cctest/test-lockers.cc @@ -36,6 +36,7 @@ #include "src/compilation-cache.h" #include "src/execution.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/unicode-inl.h" #include "src/utils.h" #include "test/cctest/cctest.h" @@ -686,12 +687,9 @@ class IsolateGenesisThread : public JoinableThread { v8::Isolate* isolate = v8::Isolate::New(create_params); { v8::Isolate::Scope isolate_scope(isolate); - CHECK( - !reinterpret_cast<i::Isolate*>(isolate)->has_installed_extensions()); v8::ExtensionConfiguration extensions(count_, extension_names_); v8::HandleScope handle_scope(isolate); v8::Context::New(isolate, &extensions); - CHECK(reinterpret_cast<i::Isolate*>(isolate)->has_installed_extensions()); } isolate->Dispose(); } diff --git a/deps/v8/test/cctest/test-log.cc b/deps/v8/test/cctest/test-log.cc index 91029286f7..f208c5a7b6 100644 --- a/deps/v8/test/cctest/test-log.cc +++ b/deps/v8/test/cctest/test-log.cc @@ -37,6 +37,7 @@ #include "src/api.h" #include "src/log-utils.h" #include "src/log.h" +#include "src/objects-inl.h" #include "src/profiler/cpu-profiler.h" #include "src/snapshot/natives.h" #include "src/utils.h" diff --git a/deps/v8/test/cctest/test-macro-assembler-arm.cc b/deps/v8/test/cctest/test-macro-assembler-arm.cc index 06efc58cfa..63919a46cc 100644 --- a/deps/v8/test/cctest/test-macro-assembler-arm.cc +++ b/deps/v8/test/cctest/test-macro-assembler-arm.cc @@ -42,6 +42,7 @@ typedef void* (*F)(int x, int y, int p2, int p3, int p4); #define __ masm-> +typedef Object* (*F3)(void* p0, int p1, int p2, int p3, int p4); typedef int (*F5)(void*, void*, void*, void*, void*); @@ -134,4 +135,359 @@ TEST(LoadAndStoreWithRepresentation) { CHECK(!CALL_GENERATED_CODE(isolate, f, 0, 0, 0, 0, 0)); } +TEST(ExtractLane) { + if (!CpuFeatures::IsSupported(NEON)) return; + + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( + Assembler::kMinimalBufferSize, &actual_size, true)); + CHECK(buffer); + Isolate* isolate = CcTest::i_isolate(); + HandleScope handles(isolate); + MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. + + typedef struct { + int32_t i32x4_low[4]; + int32_t i32x4_high[4]; + int32_t i16x8_low[8]; + int32_t i16x8_high[8]; + int32_t i8x16_low[16]; + int32_t i8x16_high[16]; + int32_t f32x4_low[4]; + int32_t f32x4_high[4]; + } T; + T t; + + __ stm(db_w, sp, r4.bit() | r5.bit() | lr.bit()); + + for (int i = 0; i < 4; i++) { + __ mov(r4, Operand(i)); + __ vdup(Neon32, q1, r4); + __ ExtractLane(r5, q1, NeonS32, i); + __ str(r5, MemOperand(r0, offsetof(T, i32x4_low) + 4 * i)); + SwVfpRegister si = SwVfpRegister::from_code(i); + __ ExtractLane(si, q1, r4, i); + __ vstr(si, r0, offsetof(T, f32x4_low) + 4 * i); + } + + for (int i = 0; i < 8; i++) { + __ mov(r4, Operand(i)); + __ vdup(Neon16, q1, r4); + __ ExtractLane(r5, q1, NeonS16, i); + __ str(r5, MemOperand(r0, offsetof(T, i16x8_low) + 4 * i)); + } + + for (int i = 0; i < 16; i++) { + __ mov(r4, Operand(i)); + __ vdup(Neon8, q1, r4); + __ ExtractLane(r5, q1, NeonS8, i); + __ str(r5, MemOperand(r0, offsetof(T, i8x16_low) + 4 * i)); + } + + if (CpuFeatures::IsSupported(VFP32DREGS)) { + for (int i = 0; i < 4; i++) { + __ mov(r4, Operand(-i)); + __ vdup(Neon32, q15, r4); + __ ExtractLane(r5, q15, NeonS32, i); + __ str(r5, MemOperand(r0, offsetof(T, i32x4_high) + 4 * i)); + SwVfpRegister si = SwVfpRegister::from_code(i); + __ ExtractLane(si, q15, r4, i); + __ vstr(si, r0, offsetof(T, f32x4_high) + 4 * i); + } + + for (int i = 0; i < 8; i++) { + __ mov(r4, Operand(-i)); + __ vdup(Neon16, q15, r4); + __ ExtractLane(r5, q15, NeonS16, i); + __ str(r5, MemOperand(r0, offsetof(T, i16x8_high) + 4 * i)); + } + + for (int i = 0; i < 16; i++) { + __ mov(r4, Operand(-i)); + __ vdup(Neon8, q15, r4); + __ ExtractLane(r5, q15, NeonS8, i); + __ str(r5, MemOperand(r0, offsetof(T, i8x16_high) + 4 * i)); + } + } + + __ ldm(ia_w, sp, r4.bit() | r5.bit() | pc.bit()); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + F3 f = FUNCTION_CAST<F3>(code->entry()); + Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); + USE(dummy); + for (int i = 0; i < 4; i++) { + CHECK_EQ(i, t.i32x4_low[i]); + CHECK_EQ(i, t.f32x4_low[i]); + } + for (int i = 0; i < 8; i++) { + CHECK_EQ(i, t.i16x8_low[i]); + } + for (int i = 0; i < 16; i++) { + CHECK_EQ(i, t.i8x16_low[i]); + } + if (CpuFeatures::IsSupported(VFP32DREGS)) { + for (int i = 0; i < 4; i++) { + CHECK_EQ(-i, t.i32x4_high[i]); + CHECK_EQ(-i, t.f32x4_high[i]); + } + for (int i = 0; i < 8; i++) { + CHECK_EQ(-i, t.i16x8_high[i]); + } + for (int i = 0; i < 16; i++) { + CHECK_EQ(-i, t.i8x16_high[i]); + } + } +} + +TEST(ReplaceLane) { + if (!CpuFeatures::IsSupported(NEON)) return; + + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( + Assembler::kMinimalBufferSize, &actual_size, true)); + CHECK(buffer); + Isolate* isolate = CcTest::i_isolate(); + HandleScope handles(isolate); + MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. + + typedef struct { + int32_t i32x4_low[4]; + int32_t i32x4_high[4]; + int16_t i16x8_low[8]; + int16_t i16x8_high[8]; + int8_t i8x16_low[16]; + int8_t i8x16_high[16]; + int32_t f32x4_low[4]; + int32_t f32x4_high[4]; + } T; + T t; + + __ stm(db_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | lr.bit()); + + const Register kScratch = r5; + + __ veor(q0, q0, q0); // Zero + __ veor(q1, q1, q1); // Zero + for (int i = 0; i < 4; i++) { + __ mov(r4, Operand(i)); + __ ReplaceLane(q0, q0, r4, NeonS32, i); + SwVfpRegister si = SwVfpRegister::from_code(i); + __ vmov(si, r4); + __ ReplaceLane(q1, q1, si, kScratch, i); + } + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i32x4_low)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, f32x4_low)))); + __ vst1(Neon8, NeonListOperand(q1), NeonMemOperand(r4)); + + __ veor(q0, q0, q0); // Zero + for (int i = 0; i < 8; i++) { + __ mov(r4, Operand(i)); + __ ReplaceLane(q0, q0, r4, NeonS16, i); + } + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i16x8_low)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ veor(q0, q0, q0); // Zero + for (int i = 0; i < 16; i++) { + __ mov(r4, Operand(i)); + __ ReplaceLane(q0, q0, r4, NeonS8, i); + } + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i8x16_low)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + if (CpuFeatures::IsSupported(VFP32DREGS)) { + __ veor(q14, q14, q14); // Zero + __ veor(q15, q15, q15); // Zero + for (int i = 0; i < 4; i++) { + __ mov(r4, Operand(-i)); + __ ReplaceLane(q14, q14, r4, NeonS32, i); + SwVfpRegister si = SwVfpRegister::from_code(i); + __ vmov(si, r4); + __ ReplaceLane(q15, q15, si, kScratch, i); + } + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i32x4_high)))); + __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, f32x4_high)))); + __ vst1(Neon8, NeonListOperand(q15), NeonMemOperand(r4)); + + __ veor(q14, q14, q14); // Zero + for (int i = 0; i < 8; i++) { + __ mov(r4, Operand(-i)); + __ ReplaceLane(q14, q14, r4, NeonS16, i); + } + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i16x8_high)))); + __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); + + __ veor(q14, q14, q14); // Zero + for (int i = 0; i < 16; i++) { + __ mov(r4, Operand(-i)); + __ ReplaceLane(q14, q14, r4, NeonS8, i); + } + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, i8x16_high)))); + __ vst1(Neon8, NeonListOperand(q14), NeonMemOperand(r4)); + } + + __ ldm(ia_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | pc.bit()); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + F3 f = FUNCTION_CAST<F3>(code->entry()); + Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); + USE(dummy); + for (int i = 0; i < 4; i++) { + CHECK_EQ(i, t.i32x4_low[i]); + CHECK_EQ(i, t.f32x4_low[i]); + } + for (int i = 0; i < 8; i++) { + CHECK_EQ(i, t.i16x8_low[i]); + } + for (int i = 0; i < 16; i++) { + CHECK_EQ(i, t.i8x16_low[i]); + } + if (CpuFeatures::IsSupported(VFP32DREGS)) { + for (int i = 0; i < 4; i++) { + CHECK_EQ(-i, t.i32x4_high[i]); + CHECK_EQ(-i, t.f32x4_high[i]); + } + for (int i = 0; i < 8; i++) { + CHECK_EQ(-i, t.i16x8_high[i]); + } + for (int i = 0; i < 16; i++) { + CHECK_EQ(-i, t.i8x16_high[i]); + } + } +} + +#define CHECK_EQ_32X4(field, v0, v1, v2, v3) \ + CHECK_EQ(v0, t.field[0]); \ + CHECK_EQ(v1, t.field[1]); \ + CHECK_EQ(v2, t.field[2]); \ + CHECK_EQ(v3, t.field[3]); + +TEST(Swizzle) { + if (!CpuFeatures::IsSupported(NEON)) return; + + // Allocate an executable page of memory. + size_t actual_size; + byte* buffer = static_cast<byte*>(v8::base::OS::Allocate( + Assembler::kMinimalBufferSize, &actual_size, true)); + CHECK(buffer); + Isolate* isolate = CcTest::i_isolate(); + HandleScope handles(isolate); + MacroAssembler assembler(isolate, buffer, static_cast<int>(actual_size), + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; // Create a pointer for the __ macro. + + typedef struct { + int32_t _32x4_3210[4]; // identity + int32_t _32x4_1032[4]; // high / low swap + int32_t _32x4_0000[4]; // vdup's + int32_t _32x4_1111[4]; + int32_t _32x4_2222[4]; + int32_t _32x4_3333[4]; + int32_t _32x4_2103[4]; // rotate left + int32_t _32x4_0321[4]; // rotate right + int32_t _32x4_1132[4]; // irregular + int32_t _32x4_1132_in_place[4]; // irregular, in-place + } T; + T t; + + __ stm(db_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | lr.bit()); + + const Register kScratch = r5; + + // Make test vector [0, 1, 2, 3] + __ veor(q1, q1, q1); // Zero + for (int i = 0; i < 4; i++) { + __ mov(r4, Operand(i)); + __ ReplaceLane(q1, q1, r4, NeonS32, i); + } + __ Swizzle(q0, q1, kScratch, Neon32, 0x3210); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_3210)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x1032); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_1032)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x0000); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_0000)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x1111); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_1111)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x2222); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_2222)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x3333); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_3333)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x2103); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_2103)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x0321); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_0321)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ Swizzle(q0, q1, kScratch, Neon32, 0x1132); + __ add(r4, r0, Operand(static_cast<int32_t>(offsetof(T, _32x4_1132)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ vmov(q0, q1); + __ Swizzle(q0, q0, kScratch, Neon32, 0x1132); + __ add(r4, r0, + Operand(static_cast<int32_t>(offsetof(T, _32x4_1132_in_place)))); + __ vst1(Neon8, NeonListOperand(q0), NeonMemOperand(r4)); + + __ ldm(ia_w, sp, r4.bit() | r5.bit() | r6.bit() | r7.bit() | pc.bit()); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + F3 f = FUNCTION_CAST<F3>(code->entry()); + Object* dummy = CALL_GENERATED_CODE(isolate, f, &t, 0, 0, 0, 0); + USE(dummy); + CHECK_EQ_32X4(_32x4_3210, 0, 1, 2, 3); + CHECK_EQ_32X4(_32x4_1032, 2, 3, 0, 1); + CHECK_EQ_32X4(_32x4_0000, 0, 0, 0, 0); + CHECK_EQ_32X4(_32x4_1111, 1, 1, 1, 1); + CHECK_EQ_32X4(_32x4_2222, 2, 2, 2, 2); + CHECK_EQ_32X4(_32x4_3333, 3, 3, 3, 3); + CHECK_EQ_32X4(_32x4_2103, 3, 0, 1, 2); + CHECK_EQ_32X4(_32x4_0321, 1, 2, 3, 0); + CHECK_EQ_32X4(_32x4_1132, 2, 3, 1, 1); + CHECK_EQ_32X4(_32x4_1132_in_place, 2, 3, 1, 1); +} + #undef __ diff --git a/deps/v8/test/cctest/test-macro-assembler-mips.cc b/deps/v8/test/cctest/test-macro-assembler-mips.cc index 2f3edee7da..77cdaec72a 100644 --- a/deps/v8/test/cctest/test-macro-assembler-mips.cc +++ b/deps/v8/test/cctest/test-macro-assembler-mips.cc @@ -41,6 +41,7 @@ using namespace v8::internal; typedef void* (*F)(int x, int y, int p2, int p3, int p4); typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); +typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); #define __ masm-> @@ -282,6 +283,96 @@ TEST(jump_tables5) { } } +TEST(jump_tables6) { + // Similar to test-assembler-mips jump_tables1, with extra test for branch + // trampoline required after emission of the dd table (where trampolines are + // blocked). This test checks if number of really generated instructions is + // greater than number of counted instructions from code, as we are expecting + // generation of trampoline in this case (when number of kFillInstr + // instructions is close to 32K) + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assembler(isolate, nullptr, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; + + const int kSwitchTableCases = 40; + + const int kInstrSize = Assembler::kInstrSize; + const int kMaxBranchOffset = Assembler::kMaxBranchOffset; + const int kTrampolineSlotsSize = Assembler::kTrampolineSlotsSize; + const int kSwitchTablePrologueSize = MacroAssembler::kSwitchTablePrologueSize; + + const int kMaxOffsetForTrampolineStart = + kMaxBranchOffset - 16 * kTrampolineSlotsSize; + const int kFillInstr = (kMaxOffsetForTrampolineStart / kInstrSize) - + (kSwitchTablePrologueSize + kSwitchTableCases) - 20; + + int values[kSwitchTableCases]; + isolate->random_number_generator()->NextBytes(values, sizeof(values)); + Label labels[kSwitchTableCases]; + Label near_start, end, done; + + __ Push(ra); + __ mov(v0, zero_reg); + + int offs1 = masm->pc_offset(); + int gen_insn = 0; + + __ Branch(&end); + gen_insn += Assembler::IsCompactBranchSupported() ? 1 : 2; + __ bind(&near_start); + + // Generate slightly less than 32K instructions, which will soon require + // trampoline for branch distance fixup. + for (int i = 0; i < kFillInstr; ++i) { + __ addiu(v0, v0, 1); + } + gen_insn += kFillInstr; + + __ GenerateSwitchTable(a0, kSwitchTableCases, + [&labels](size_t i) { return labels + i; }); + gen_insn += (kSwitchTablePrologueSize + kSwitchTableCases); + + for (int i = 0; i < kSwitchTableCases; ++i) { + __ bind(&labels[i]); + __ li(v0, values[i]); + __ Branch(&done); + } + gen_insn += + ((Assembler::IsCompactBranchSupported() ? 3 : 4) * kSwitchTableCases); + + // If offset from here to first branch instr is greater than max allowed + // offset for trampoline ... + CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1); + // ... number of generated instructions must be greater then "gen_insn", + // as we are expecting trampoline generation + CHECK_LT(gen_insn, (masm->pc_offset() - offs1) / kInstrSize); + + __ bind(&done); + __ Pop(ra); + __ jr(ra); + __ nop(); + + __ bind(&end); + __ Branch(&near_start); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef OBJECT_PRINT + code->Print(std::cout); +#endif + F1 f = FUNCTION_CAST<F1>(code->entry()); + for (int i = 0; i < kSwitchTableCases; ++i) { + int res = + reinterpret_cast<int>(CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); + ::printf("f(%d) = %d\n", i, res); + CHECK_EQ(values[i], res); + } +} static uint32_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) { Isolate* isolate = CcTest::i_isolate(); @@ -439,11 +530,11 @@ TEST(cvt_s_w_Trunc_uw_s) { CcTest::InitializeVM(); FOR_UINT32_INPUTS(i, cvt_trunc_uint32_test_values) { uint32_t input = *i; - CHECK_EQ(static_cast<float>(input), - run_Cvt<uint32_t>(input, [](MacroAssembler* masm) { - __ cvt_s_w(f0, f4); - __ Trunc_uw_s(f2, f0, f1); - })); + auto fn = [](MacroAssembler* masm) { + __ cvt_s_w(f0, f4); + __ Trunc_uw_s(f2, f0, f6); + }; + CHECK_EQ(static_cast<float>(input), run_Cvt<uint32_t>(input, fn)); } } @@ -451,11 +542,11 @@ TEST(cvt_d_w_Trunc_w_d) { CcTest::InitializeVM(); FOR_INT32_INPUTS(i, cvt_trunc_int32_test_values) { int32_t input = *i; - CHECK_EQ(static_cast<double>(input), - run_Cvt<int32_t>(input, [](MacroAssembler* masm) { - __ cvt_d_w(f0, f4); - __ Trunc_w_d(f2, f0); - })); + auto fn = [](MacroAssembler* masm) { + __ cvt_d_w(f0, f4); + __ Trunc_w_d(f2, f0); + }; + CHECK_EQ(static_cast<double>(input), run_Cvt<int32_t>(input, fn)); } } @@ -937,13 +1028,13 @@ TEST(min_max_nan) { __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); - __ MinNaNCheck_d(f10, f4, f8, &handle_mind_nan); + __ Float64Min(f10, f4, f8, &handle_mind_nan); __ bind(&back_mind_nan); - __ MaxNaNCheck_d(f12, f4, f8, &handle_maxd_nan); + __ Float64Max(f12, f4, f8, &handle_maxd_nan); __ bind(&back_maxd_nan); - __ MinNaNCheck_s(f14, f2, f6, &handle_mins_nan); + __ Float32Min(f14, f2, f6, &handle_mins_nan); __ bind(&back_mins_nan); - __ MaxNaNCheck_s(f16, f2, f6, &handle_maxs_nan); + __ Float32Max(f16, f2, f6, &handle_maxs_nan); __ bind(&back_maxs_nan); __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); @@ -1041,36 +1132,39 @@ TEST(Ulh) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulh(v0, MemOperand(a0, in_offset)); - __ Ush(v0, MemOperand(a0, out_offset), v0); - })); - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulh(a0, MemOperand(a0, in_offset)); - __ Ush(a0, MemOperand(t0, out_offset), v0); - })); - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulhu(a0, MemOperand(a0, in_offset)); - __ Ush(a0, MemOperand(t0, out_offset), t1); - })); - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulhu(v0, MemOperand(a0, in_offset)); - __ Ush(v0, MemOperand(a0, out_offset), t1); - })); + auto fn_1 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulh(v0, MemOperand(a0, in_offset)); + __ Ush(v0, MemOperand(a0, out_offset), v0); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulh(a0, MemOperand(a0, in_offset)); + __ Ush(a0, MemOperand(t0, out_offset), v0); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_2)); + + auto fn_3 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulhu(a0, MemOperand(a0, in_offset)); + __ Ush(a0, MemOperand(t0, out_offset), t1); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_3)); + + auto fn_4 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulhu(v0, MemOperand(a0, in_offset)); + __ Ush(v0, MemOperand(a0, out_offset), t1); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_4)); } } } @@ -1090,39 +1184,39 @@ TEST(Ulh_bitextension) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - Label success, fail, end, different; - __ Ulh(t0, MemOperand(a0, in_offset)); - __ Ulhu(t1, MemOperand(a0, in_offset)); - __ Branch(&different, ne, t0, Operand(t1)); - - // If signed and unsigned values are same, check - // the upper bits to see if they are zero - __ sra(t0, t0, 15); - __ Branch(&success, eq, t0, Operand(zero_reg)); - __ Branch(&fail); - - // If signed and unsigned values are different, - // check that the upper bits are complementary - __ bind(&different); - __ sra(t1, t1, 15); - __ Branch(&fail, ne, t1, Operand(1)); - __ sra(t0, t0, 15); - __ addiu(t0, t0, 1); - __ Branch(&fail, ne, t0, Operand(zero_reg)); - // Fall through to success - - __ bind(&success); - __ Ulh(t0, MemOperand(a0, in_offset)); - __ Ush(t0, MemOperand(a0, out_offset), v0); - __ Branch(&end); - __ bind(&fail); - __ Ush(zero_reg, MemOperand(a0, out_offset), v0); - __ bind(&end); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + Label success, fail, end, different; + __ Ulh(t0, MemOperand(a0, in_offset)); + __ Ulhu(t1, MemOperand(a0, in_offset)); + __ Branch(&different, ne, t0, Operand(t1)); + + // If signed and unsigned values are same, check + // the upper bits to see if they are zero + __ sra(t0, t0, 15); + __ Branch(&success, eq, t0, Operand(zero_reg)); + __ Branch(&fail); + + // If signed and unsigned values are different, + // check that the upper bits are complementary + __ bind(&different); + __ sra(t1, t1, 15); + __ Branch(&fail, ne, t1, Operand(1)); + __ sra(t0, t0, 15); + __ addiu(t0, t0, 1); + __ Branch(&fail, ne, t0, Operand(zero_reg)); + // Fall through to success + + __ bind(&success); + __ Ulh(t0, MemOperand(a0, in_offset)); + __ Ush(t0, MemOperand(a0, out_offset), v0); + __ Branch(&end); + __ bind(&fail); + __ Ush(zero_reg, MemOperand(a0, out_offset), v0); + __ bind(&end); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1142,22 +1236,23 @@ TEST(Ulw) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulw(v0, MemOperand(a0, in_offset)); - __ Usw(v0, MemOperand(a0, out_offset)); - })); + auto fn_1 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulw(v0, MemOperand(a0, in_offset)); + __ Usw(v0, MemOperand(a0, out_offset)); + }; + CHECK_EQ(true, run_Unaligned<uint32_t>(buffer_middle, in_offset, + out_offset, value, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulw(a0, MemOperand(a0, in_offset)); + __ Usw(a0, MemOperand(t0, out_offset)); + }; CHECK_EQ(true, - run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, (uint32_t)value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulw(a0, MemOperand(a0, in_offset)); - __ Usw(a0, MemOperand(t0, out_offset)); - })); + run_Unaligned<uint32_t>(buffer_middle, in_offset, out_offset, + (uint32_t)value, fn_2)); } } } @@ -1177,13 +1272,13 @@ TEST(Ulwc1) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<float>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulwc1(f0, MemOperand(a0, in_offset), t0); - __ Uswc1(f0, MemOperand(a0, out_offset), t0); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulwc1(f0, MemOperand(a0, in_offset), t0); + __ Uswc1(f0, MemOperand(a0, out_offset), t0); + }; + CHECK_EQ(true, run_Unaligned<float>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1203,13 +1298,13 @@ TEST(Uldc1) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<double>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Uldc1(f0, MemOperand(a0, in_offset), t0); - __ Usdc1(f0, MemOperand(a0, out_offset), t0); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Uldc1(f0, MemOperand(a0, in_offset), t0); + __ Usdc1(f0, MemOperand(a0, out_offset), t0); + }; + CHECK_EQ(true, run_Unaligned<double>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1257,15 +1352,303 @@ TEST(Sltu) { uint32_t rs = *i; uint32_t rd = *j; - CHECK_EQ(rs < rd, run_Sltu(rs, rd, - [](MacroAssembler* masm, uint32_t imm) { - __ Sltu(v0, a0, Operand(imm)); - })); - CHECK_EQ(rs < rd, - run_Sltu(rs, rd, [](MacroAssembler* masm, - uint32_t imm) { __ Sltu(v0, a0, a1); })); + auto fn_1 = [](MacroAssembler* masm, uint32_t imm) { + __ Sltu(v0, a0, Operand(imm)); + }; + CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, uint32_t imm) { + __ Sltu(v0, a0, a1); + }; + CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_2)); } } } +template <typename T, typename Inputs, typename Results> +static ::F4 GenerateMacroFloat32MinMax(MacroAssembler* masm) { + T a = T::from_code(4); // f4 + T b = T::from_code(6); // f6 + T c = T::from_code(8); // f8 + + Label ool_min_abc, ool_min_aab, ool_min_aba; + Label ool_max_abc, ool_max_aab, ool_max_aba; + + Label done_min_abc, done_min_aab, done_min_aba; + Label done_max_abc, done_max_aab, done_max_aba; + +#define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ + __ lwc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ + __ lwc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ + __ fminmax(res, x, y, &ool); \ + __ bind(&done); \ + __ swc1(a, MemOperand(a1, offsetof(Results, res_field))) + + // a = min(b, c); + FLOAT_MIN_MAX(Float32Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); + // a = min(a, b); + FLOAT_MIN_MAX(Float32Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); + // a = min(b, a); + FLOAT_MIN_MAX(Float32Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); + + // a = max(b, c); + FLOAT_MIN_MAX(Float32Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); + // a = max(a, b); + FLOAT_MIN_MAX(Float32Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); + // a = max(b, a); + FLOAT_MIN_MAX(Float32Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); + +#undef FLOAT_MIN_MAX + + __ jr(ra); + __ nop(); + + // Generate out-of-line cases. + __ bind(&ool_min_abc); + __ Float32MinOutOfLine(a, b, c); + __ Branch(&done_min_abc); + + __ bind(&ool_min_aab); + __ Float32MinOutOfLine(a, a, b); + __ Branch(&done_min_aab); + + __ bind(&ool_min_aba); + __ Float32MinOutOfLine(a, b, a); + __ Branch(&done_min_aba); + + __ bind(&ool_max_abc); + __ Float32MaxOutOfLine(a, b, c); + __ Branch(&done_max_abc); + + __ bind(&ool_max_aab); + __ Float32MaxOutOfLine(a, a, b); + __ Branch(&done_max_aab); + + __ bind(&ool_max_aba); + __ Float32MaxOutOfLine(a, b, a); + __ Branch(&done_max_aba); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = masm->isolate()->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + return FUNCTION_CAST<::F4>(code->entry()); +} + +TEST(macro_float_minmax_f32) { + // Test the Float32Min and Float32Max macros. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assembler(isolate, NULL, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; + + struct Inputs { + float src1_; + float src2_; + }; + + struct Results { + // Check all register aliasing possibilities in order to exercise all + // code-paths in the macro assembler. + float min_abc_; + float min_aab_; + float min_aba_; + float max_abc_; + float max_aab_; + float max_aba_; + }; + + ::F4 f = GenerateMacroFloat32MinMax<FPURegister, Inputs, Results>(masm); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_MINMAX(src1, src2, min, max) \ + do { \ + Inputs inputs = {src1, src2}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + } while (0) + + float nan_a = std::numeric_limits<float>::quiet_NaN(); + float nan_b = std::numeric_limits<float>::quiet_NaN(); + + CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f); + CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f); + CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f); + CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f); + CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f); + CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f); + CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f); + CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f); + + CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f); + CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f); + CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f); + CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f); + + CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a); + CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a); + CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_MINMAX +} + +template <typename T, typename Inputs, typename Results> +static ::F4 GenerateMacroFloat64MinMax(MacroAssembler* masm) { + T a = T::from_code(4); // f4 + T b = T::from_code(6); // f6 + T c = T::from_code(8); // f8 + + Label ool_min_abc, ool_min_aab, ool_min_aba; + Label ool_max_abc, ool_max_aab, ool_max_aba; + + Label done_min_abc, done_min_aab, done_min_aba; + Label done_max_abc, done_max_aab, done_max_aba; + +#define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ + __ ldc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ + __ ldc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ + __ fminmax(res, x, y, &ool); \ + __ bind(&done); \ + __ sdc1(a, MemOperand(a1, offsetof(Results, res_field))) + + // a = min(b, c); + FLOAT_MIN_MAX(Float64Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); + // a = min(a, b); + FLOAT_MIN_MAX(Float64Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); + // a = min(b, a); + FLOAT_MIN_MAX(Float64Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); + + // a = max(b, c); + FLOAT_MIN_MAX(Float64Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); + // a = max(a, b); + FLOAT_MIN_MAX(Float64Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); + // a = max(b, a); + FLOAT_MIN_MAX(Float64Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); + +#undef FLOAT_MIN_MAX + + __ jr(ra); + __ nop(); + + // Generate out-of-line cases. + __ bind(&ool_min_abc); + __ Float64MinOutOfLine(a, b, c); + __ Branch(&done_min_abc); + + __ bind(&ool_min_aab); + __ Float64MinOutOfLine(a, a, b); + __ Branch(&done_min_aab); + + __ bind(&ool_min_aba); + __ Float64MinOutOfLine(a, b, a); + __ Branch(&done_min_aba); + + __ bind(&ool_max_abc); + __ Float64MaxOutOfLine(a, b, c); + __ Branch(&done_max_abc); + + __ bind(&ool_max_aab); + __ Float64MaxOutOfLine(a, a, b); + __ Branch(&done_max_aab); + + __ bind(&ool_max_aba); + __ Float64MaxOutOfLine(a, b, a); + __ Branch(&done_max_aba); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = masm->isolate()->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + return FUNCTION_CAST<::F4>(code->entry()); +} + +TEST(macro_float_minmax_f64) { + // Test the Float64Min and Float64Max macros. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assembler(isolate, NULL, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; + + struct Inputs { + double src1_; + double src2_; + }; + + struct Results { + // Check all register aliasing possibilities in order to exercise all + // code-paths in the macro assembler. + double min_abc_; + double min_aab_; + double min_aba_; + double max_abc_; + double max_aab_; + double max_aba_; + }; + + ::F4 f = GenerateMacroFloat64MinMax<DoubleRegister, Inputs, Results>(masm); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_MINMAX(src1, src2, min, max) \ + do { \ + Inputs inputs = {src1, src2}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + } while (0) + + double nan_a = std::numeric_limits<double>::quiet_NaN(); + double nan_b = std::numeric_limits<double>::quiet_NaN(); + + CHECK_MINMAX(1.0, -1.0, -1.0, 1.0); + CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0); + CHECK_MINMAX(0.0, -1.0, -1.0, 0.0); + CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0); + CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0); + CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0); + CHECK_MINMAX(0.0, 1.0, 0.0, 1.0); + CHECK_MINMAX(1.0, 0.0, 0.0, 1.0); + + CHECK_MINMAX(0.0, 0.0, 0.0, 0.0); + CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0); + CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0); + CHECK_MINMAX(0.0, -0.0, -0.0, 0.0); + + CHECK_MINMAX(0.0, nan_a, nan_a, nan_a); + CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a); + CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_MINMAX +} + #undef __ diff --git a/deps/v8/test/cctest/test-macro-assembler-mips64.cc b/deps/v8/test/cctest/test-macro-assembler-mips64.cc index 04811f6af5..cfcdeb2d40 100644 --- a/deps/v8/test/cctest/test-macro-assembler-mips64.cc +++ b/deps/v8/test/cctest/test-macro-assembler-mips64.cc @@ -42,6 +42,7 @@ using namespace v8::internal; typedef void* (*F)(int64_t x, int64_t y, int p2, int p3, int p4); typedef Object* (*F1)(int x, int p1, int p2, int p3, int p4); typedef Object* (*F3)(void* p, int p1, int p2, int p3, int p4); +typedef Object* (*F4)(void* p0, void* p1, int p2, int p3, int p4); #define __ masm-> @@ -350,6 +351,97 @@ TEST(jump_tables5) { } } +TEST(jump_tables6) { + // Similar to test-assembler-mips jump_tables1, with extra test for branch + // trampoline required after emission of the dd table (where trampolines are + // blocked). This test checks if number of really generated instructions is + // greater than number of counted instructions from code, as we are expecting + // generation of trampoline in this case (when number of kFillInstr + // instructions is close to 32K) + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + MacroAssembler assembler(isolate, nullptr, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; + + const int kSwitchTableCases = 40; + + const int kInstrSize = Assembler::kInstrSize; + const int kMaxBranchOffset = Assembler::kMaxBranchOffset; + const int kTrampolineSlotsSize = Assembler::kTrampolineSlotsSize; + const int kSwitchTablePrologueSize = MacroAssembler::kSwitchTablePrologueSize; + + const int kMaxOffsetForTrampolineStart = + kMaxBranchOffset - 16 * kTrampolineSlotsSize; + const int kFillInstr = (kMaxOffsetForTrampolineStart / kInstrSize) - + (kSwitchTablePrologueSize + 2 * kSwitchTableCases) - + 20; + + int values[kSwitchTableCases]; + isolate->random_number_generator()->NextBytes(values, sizeof(values)); + Label labels[kSwitchTableCases]; + Label near_start, end, done; + + __ Push(ra); + __ mov(v0, zero_reg); + + int offs1 = masm->pc_offset(); + int gen_insn = 0; + + __ Branch(&end); + gen_insn += Assembler::IsCompactBranchSupported() ? 1 : 2; + __ bind(&near_start); + + // Generate slightly less than 32K instructions, which will soon require + // trampoline for branch distance fixup. + for (int i = 0; i < kFillInstr; ++i) { + __ addiu(v0, v0, 1); + } + gen_insn += kFillInstr; + + __ GenerateSwitchTable(a0, kSwitchTableCases, + [&labels](size_t i) { return labels + i; }); + gen_insn += (kSwitchTablePrologueSize + 2 * kSwitchTableCases); + + for (int i = 0; i < kSwitchTableCases; ++i) { + __ bind(&labels[i]); + __ li(v0, values[i]); + __ Branch(&done); + } + gen_insn += + ((Assembler::IsCompactBranchSupported() ? 3 : 4) * kSwitchTableCases); + + // If offset from here to first branch instr is greater than max allowed + // offset for trampoline ... + CHECK_LT(kMaxOffsetForTrampolineStart, masm->pc_offset() - offs1); + // ... number of generated instructions must be greater then "gen_insn", + // as we are expecting trampoline generation + CHECK_LT(gen_insn, (masm->pc_offset() - offs1) / kInstrSize); + + __ bind(&done); + __ Pop(ra); + __ jr(ra); + __ nop(); + + __ bind(&end); + __ Branch(&near_start); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = isolate->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef OBJECT_PRINT + code->Print(std::cout); +#endif + F1 f = FUNCTION_CAST<F1>(code->entry()); + for (int i = 0; i < kSwitchTableCases; ++i) { + int64_t res = reinterpret_cast<int64_t>( + CALL_GENERATED_CODE(isolate, f, i, 0, 0, 0, 0)); + ::printf("f(%d) = %" PRId64 "\n", i, res); + CHECK_EQ(values[i], res); + } +} static uint64_t run_lsa(uint32_t rt, uint32_t rs, int8_t sa) { Isolate* isolate = CcTest::i_isolate(); @@ -611,12 +703,12 @@ TEST(Cvt_s_uw_Trunc_uw_s) { CcTest::InitializeVM(); FOR_UINT32_INPUTS(i, cvt_trunc_uint32_test_values) { uint32_t input = *i; - CHECK_EQ(static_cast<float>(input), - run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { - __ Cvt_s_uw(f0, a0); - __ mthc1(zero_reg, f2); - __ Trunc_uw_s(f2, f0, f1); - })); + auto fn = [](MacroAssembler* masm) { + __ Cvt_s_uw(f0, a0); + __ mthc1(zero_reg, f2); + __ Trunc_uw_s(f2, f0, f1); + }; + CHECK_EQ(static_cast<float>(input), run_Cvt<uint64_t>(input, fn)); } } @@ -624,11 +716,11 @@ TEST(Cvt_s_ul_Trunc_ul_s) { CcTest::InitializeVM(); FOR_UINT64_INPUTS(i, cvt_trunc_uint64_test_values) { uint64_t input = *i; - CHECK_EQ(static_cast<float>(input), - run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { - __ Cvt_s_ul(f0, a0); - __ Trunc_ul_s(f2, f0, f1, v0); - })); + auto fn = [](MacroAssembler* masm) { + __ Cvt_s_ul(f0, a0); + __ Trunc_ul_s(f2, f0, f1, v0); + }; + CHECK_EQ(static_cast<float>(input), run_Cvt<uint64_t>(input, fn)); } } @@ -636,11 +728,11 @@ TEST(Cvt_d_ul_Trunc_ul_d) { CcTest::InitializeVM(); FOR_UINT64_INPUTS(i, cvt_trunc_uint64_test_values) { uint64_t input = *i; - CHECK_EQ(static_cast<double>(input), - run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { - __ Cvt_d_ul(f0, a0); - __ Trunc_ul_d(f2, f0, f1, v0); - })); + auto fn = [](MacroAssembler* masm) { + __ Cvt_d_ul(f0, a0); + __ Trunc_ul_d(f2, f0, f1, v0); + }; + CHECK_EQ(static_cast<double>(input), run_Cvt<uint64_t>(input, fn)); } } @@ -648,12 +740,12 @@ TEST(cvt_d_l_Trunc_l_d) { CcTest::InitializeVM(); FOR_INT64_INPUTS(i, cvt_trunc_int64_test_values) { int64_t input = *i; - CHECK_EQ(static_cast<double>(input), - run_Cvt<int64_t>(input, [](MacroAssembler* masm) { - __ dmtc1(a0, f4); - __ cvt_d_l(f0, f4); - __ Trunc_l_d(f2, f0); - })); + auto fn = [](MacroAssembler* masm) { + __ dmtc1(a0, f4); + __ cvt_d_l(f0, f4); + __ Trunc_l_d(f2, f0); + }; + CHECK_EQ(static_cast<double>(input), run_Cvt<int64_t>(input, fn)); } } @@ -662,12 +754,12 @@ TEST(cvt_d_l_Trunc_l_ud) { FOR_INT64_INPUTS(i, cvt_trunc_int64_test_values) { int64_t input = *i; uint64_t abs_input = (input < 0) ? -input : input; - CHECK_EQ(static_cast<double>(abs_input), - run_Cvt<uint64_t>(input, [](MacroAssembler* masm) { - __ dmtc1(a0, f4); - __ cvt_d_l(f0, f4); - __ Trunc_l_ud(f2, f0, f6); - })); + auto fn = [](MacroAssembler* masm) { + __ dmtc1(a0, f4); + __ cvt_d_l(f0, f4); + __ Trunc_l_ud(f2, f0, f6); + }; + CHECK_EQ(static_cast<double>(abs_input), run_Cvt<uint64_t>(input, fn)); } } @@ -675,14 +767,14 @@ TEST(cvt_d_w_Trunc_w_d) { CcTest::InitializeVM(); FOR_INT32_INPUTS(i, cvt_trunc_int32_test_values) { int32_t input = *i; - CHECK_EQ(static_cast<double>(input), - run_Cvt<int64_t>(input, [](MacroAssembler* masm) { - __ mtc1(a0, f4); - __ cvt_d_w(f0, f4); - __ Trunc_w_d(f2, f0); - __ mfc1(v1, f2); - __ dmtc1(v1, f2); - })); + auto fn = [](MacroAssembler* masm) { + __ mtc1(a0, f4); + __ cvt_d_w(f0, f4); + __ Trunc_w_d(f2, f0); + __ mfc1(v1, f2); + __ dmtc1(v1, f2); + }; + CHECK_EQ(static_cast<double>(input), run_Cvt<int64_t>(input, fn)); } } @@ -1429,13 +1521,13 @@ TEST(min_max_nan) { __ ldc1(f8, MemOperand(a0, offsetof(TestFloat, b))); __ lwc1(f2, MemOperand(a0, offsetof(TestFloat, e))); __ lwc1(f6, MemOperand(a0, offsetof(TestFloat, f))); - __ MinNaNCheck_d(f10, f4, f8, &handle_mind_nan); + __ Float64Min(f10, f4, f8, &handle_mind_nan); __ bind(&back_mind_nan); - __ MaxNaNCheck_d(f12, f4, f8, &handle_maxd_nan); + __ Float64Max(f12, f4, f8, &handle_maxd_nan); __ bind(&back_maxd_nan); - __ MinNaNCheck_s(f14, f2, f6, &handle_mins_nan); + __ Float32Min(f14, f2, f6, &handle_mins_nan); __ bind(&back_mins_nan); - __ MaxNaNCheck_s(f16, f2, f6, &handle_maxs_nan); + __ Float32Max(f16, f2, f6, &handle_maxs_nan); __ bind(&back_maxs_nan); __ sdc1(f10, MemOperand(a0, offsetof(TestFloat, c))); __ sdc1(f12, MemOperand(a0, offsetof(TestFloat, d))); @@ -1533,36 +1625,39 @@ TEST(Ulh) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulh(v0, MemOperand(a0, in_offset)); - __ Ush(v0, MemOperand(a0, out_offset), v0); - })); - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulh(a0, MemOperand(a0, in_offset)); - __ Ush(a0, MemOperand(t0, out_offset), v0); - })); - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulhu(a0, MemOperand(a0, in_offset)); - __ Ush(a0, MemOperand(t0, out_offset), t1); - })); - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulhu(v0, MemOperand(a0, in_offset)); - __ Ush(v0, MemOperand(a0, out_offset), t1); - })); + auto fn_1 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulh(v0, MemOperand(a0, in_offset)); + __ Ush(v0, MemOperand(a0, out_offset), v0); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulh(a0, MemOperand(a0, in_offset)); + __ Ush(a0, MemOperand(t0, out_offset), v0); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_2)); + + auto fn_3 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulhu(a0, MemOperand(a0, in_offset)); + __ Ush(a0, MemOperand(t0, out_offset), t1); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_3)); + + auto fn_4 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulhu(v0, MemOperand(a0, in_offset)); + __ Ush(v0, MemOperand(a0, out_offset), t1); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn_4)); } } } @@ -1582,39 +1677,39 @@ TEST(Ulh_bitextension) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint16_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - Label success, fail, end, different; - __ Ulh(t0, MemOperand(a0, in_offset)); - __ Ulhu(t1, MemOperand(a0, in_offset)); - __ Branch(&different, ne, t0, Operand(t1)); - - // If signed and unsigned values are same, check - // the upper bits to see if they are zero - __ sra(t0, t0, 15); - __ Branch(&success, eq, t0, Operand(zero_reg)); - __ Branch(&fail); - - // If signed and unsigned values are different, - // check that the upper bits are complementary - __ bind(&different); - __ sra(t1, t1, 15); - __ Branch(&fail, ne, t1, Operand(1)); - __ sra(t0, t0, 15); - __ addiu(t0, t0, 1); - __ Branch(&fail, ne, t0, Operand(zero_reg)); - // Fall through to success - - __ bind(&success); - __ Ulh(t0, MemOperand(a0, in_offset)); - __ Ush(t0, MemOperand(a0, out_offset), v0); - __ Branch(&end); - __ bind(&fail); - __ Ush(zero_reg, MemOperand(a0, out_offset), v0); - __ bind(&end); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + Label success, fail, end, different; + __ Ulh(t0, MemOperand(a0, in_offset)); + __ Ulhu(t1, MemOperand(a0, in_offset)); + __ Branch(&different, ne, t0, Operand(t1)); + + // If signed and unsigned values are same, check + // the upper bits to see if they are zero + __ sra(t0, t0, 15); + __ Branch(&success, eq, t0, Operand(zero_reg)); + __ Branch(&fail); + + // If signed and unsigned values are different, + // check that the upper bits are complementary + __ bind(&different); + __ sra(t1, t1, 15); + __ Branch(&fail, ne, t1, Operand(1)); + __ sra(t0, t0, 15); + __ addiu(t0, t0, 1); + __ Branch(&fail, ne, t0, Operand(zero_reg)); + // Fall through to success + + __ bind(&success); + __ Ulh(t0, MemOperand(a0, in_offset)); + __ Ush(t0, MemOperand(a0, out_offset), v0); + __ Branch(&end); + __ bind(&fail); + __ Ush(zero_reg, MemOperand(a0, out_offset), v0); + __ bind(&end); + }; + CHECK_EQ(true, run_Unaligned<uint16_t>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1634,38 +1729,41 @@ TEST(Ulw) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulw(v0, MemOperand(a0, in_offset)); - __ Usw(v0, MemOperand(a0, out_offset)); - })); + auto fn_1 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulw(v0, MemOperand(a0, in_offset)); + __ Usw(v0, MemOperand(a0, out_offset)); + }; + CHECK_EQ(true, run_Unaligned<uint32_t>(buffer_middle, in_offset, + out_offset, value, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulw(a0, MemOperand(a0, in_offset)); + __ Usw(a0, MemOperand(t0, out_offset)); + }; CHECK_EQ(true, - run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, (uint32_t)value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulw(a0, MemOperand(a0, in_offset)); - __ Usw(a0, MemOperand(t0, out_offset)); - })); - CHECK_EQ(true, run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulwu(v0, MemOperand(a0, in_offset)); - __ Usw(v0, MemOperand(a0, out_offset)); - })); + run_Unaligned<uint32_t>(buffer_middle, in_offset, out_offset, + (uint32_t)value, fn_2)); + + auto fn_3 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulwu(v0, MemOperand(a0, in_offset)); + __ Usw(v0, MemOperand(a0, out_offset)); + }; + CHECK_EQ(true, run_Unaligned<uint32_t>(buffer_middle, in_offset, + out_offset, value, fn_3)); + + auto fn_4 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Ulwu(a0, MemOperand(a0, in_offset)); + __ Usw(a0, MemOperand(t0, out_offset)); + }; CHECK_EQ(true, - run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, (uint32_t)value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Ulwu(a0, MemOperand(a0, in_offset)); - __ Usw(a0, MemOperand(t0, out_offset)); - })); + run_Unaligned<uint32_t>(buffer_middle, in_offset, out_offset, + (uint32_t)value, fn_4)); } } } @@ -1685,39 +1783,39 @@ TEST(Ulw_extension) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint32_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - Label success, fail, end, different; - __ Ulw(t0, MemOperand(a0, in_offset)); - __ Ulwu(t1, MemOperand(a0, in_offset)); - __ Branch(&different, ne, t0, Operand(t1)); - - // If signed and unsigned values are same, check - // the upper bits to see if they are zero - __ dsra(t0, t0, 31); - __ Branch(&success, eq, t0, Operand(zero_reg)); - __ Branch(&fail); - - // If signed and unsigned values are different, - // check that the upper bits are complementary - __ bind(&different); - __ dsra(t1, t1, 31); - __ Branch(&fail, ne, t1, Operand(1)); - __ dsra(t0, t0, 31); - __ daddiu(t0, t0, 1); - __ Branch(&fail, ne, t0, Operand(zero_reg)); - // Fall through to success - - __ bind(&success); - __ Ulw(t0, MemOperand(a0, in_offset)); - __ Usw(t0, MemOperand(a0, out_offset)); - __ Branch(&end); - __ bind(&fail); - __ Usw(zero_reg, MemOperand(a0, out_offset)); - __ bind(&end); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + Label success, fail, end, different; + __ Ulw(t0, MemOperand(a0, in_offset)); + __ Ulwu(t1, MemOperand(a0, in_offset)); + __ Branch(&different, ne, t0, Operand(t1)); + + // If signed and unsigned values are same, check + // the upper bits to see if they are zero + __ dsra(t0, t0, 31); + __ Branch(&success, eq, t0, Operand(zero_reg)); + __ Branch(&fail); + + // If signed and unsigned values are different, + // check that the upper bits are complementary + __ bind(&different); + __ dsra(t1, t1, 31); + __ Branch(&fail, ne, t1, Operand(1)); + __ dsra(t0, t0, 31); + __ daddiu(t0, t0, 1); + __ Branch(&fail, ne, t0, Operand(zero_reg)); + // Fall through to success + + __ bind(&success); + __ Ulw(t0, MemOperand(a0, in_offset)); + __ Usw(t0, MemOperand(a0, out_offset)); + __ Branch(&end); + __ bind(&fail); + __ Usw(zero_reg, MemOperand(a0, out_offset)); + __ bind(&end); + }; + CHECK_EQ(true, run_Unaligned<uint32_t>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1737,22 +1835,23 @@ TEST(Uld) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<uint64_t>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Uld(v0, MemOperand(a0, in_offset)); - __ Usd(v0, MemOperand(a0, out_offset)); - })); + auto fn_1 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Uld(v0, MemOperand(a0, in_offset)); + __ Usd(v0, MemOperand(a0, out_offset)); + }; + CHECK_EQ(true, run_Unaligned<uint64_t>(buffer_middle, in_offset, + out_offset, value, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ mov(t0, a0); + __ Uld(a0, MemOperand(a0, in_offset)); + __ Usd(a0, MemOperand(t0, out_offset)); + }; CHECK_EQ(true, - run_Unaligned<uint64_t>( - buffer_middle, in_offset, out_offset, (uint32_t)value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ mov(t0, a0); - __ Uld(a0, MemOperand(a0, in_offset)); - __ Usd(a0, MemOperand(t0, out_offset)); - })); + run_Unaligned<uint64_t>(buffer_middle, in_offset, out_offset, + (uint32_t)value, fn_2)); } } } @@ -1772,13 +1871,13 @@ TEST(Ulwc1) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<float>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Ulwc1(f0, MemOperand(a0, in_offset), t0); - __ Uswc1(f0, MemOperand(a0, out_offset), t0); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Ulwc1(f0, MemOperand(a0, in_offset), t0); + __ Uswc1(f0, MemOperand(a0, out_offset), t0); + }; + CHECK_EQ(true, run_Unaligned<float>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1798,13 +1897,13 @@ TEST(Uldc1) { int32_t in_offset = *j1 + *k1; int32_t out_offset = *j2 + *k2; - CHECK_EQ(true, run_Unaligned<double>( - buffer_middle, in_offset, out_offset, value, - [](MacroAssembler* masm, int32_t in_offset, - int32_t out_offset) { - __ Uldc1(f0, MemOperand(a0, in_offset), t0); - __ Usdc1(f0, MemOperand(a0, out_offset), t0); - })); + auto fn = [](MacroAssembler* masm, int32_t in_offset, + int32_t out_offset) { + __ Uldc1(f0, MemOperand(a0, in_offset), t0); + __ Usdc1(f0, MemOperand(a0, out_offset), t0); + }; + CHECK_EQ(true, run_Unaligned<double>(buffer_middle, in_offset, + out_offset, value, fn)); } } } @@ -1863,15 +1962,303 @@ TEST(Sltu) { uint64_t rs = *i; uint64_t rd = *j; - CHECK_EQ(rs < rd, run_Sltu(rs, rd, - [](MacroAssembler* masm, uint64_t imm) { - __ Sltu(v0, a0, Operand(imm)); - })); - CHECK_EQ(rs < rd, - run_Sltu(rs, rd, [](MacroAssembler* masm, - uint64_t imm) { __ Sltu(v0, a0, a1); })); + auto fn_1 = [](MacroAssembler* masm, uint64_t imm) { + __ Sltu(v0, a0, Operand(imm)); + }; + CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_1)); + + auto fn_2 = [](MacroAssembler* masm, uint64_t imm) { + __ Sltu(v0, a0, a1); + }; + CHECK_EQ(rs < rd, run_Sltu(rs, rd, fn_2)); } } } +template <typename T, typename Inputs, typename Results> +static ::F4 GenerateMacroFloat32MinMax(MacroAssembler* masm) { + T a = T::from_code(4); // f4 + T b = T::from_code(6); // f6 + T c = T::from_code(8); // f8 + + Label ool_min_abc, ool_min_aab, ool_min_aba; + Label ool_max_abc, ool_max_aab, ool_max_aba; + + Label done_min_abc, done_min_aab, done_min_aba; + Label done_max_abc, done_max_aab, done_max_aba; + +#define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ + __ lwc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ + __ lwc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ + __ fminmax(res, x, y, &ool); \ + __ bind(&done); \ + __ swc1(a, MemOperand(a1, offsetof(Results, res_field))) + + // a = min(b, c); + FLOAT_MIN_MAX(Float32Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); + // a = min(a, b); + FLOAT_MIN_MAX(Float32Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); + // a = min(b, a); + FLOAT_MIN_MAX(Float32Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); + + // a = max(b, c); + FLOAT_MIN_MAX(Float32Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); + // a = max(a, b); + FLOAT_MIN_MAX(Float32Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); + // a = max(b, a); + FLOAT_MIN_MAX(Float32Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); + +#undef FLOAT_MIN_MAX + + __ jr(ra); + __ nop(); + + // Generate out-of-line cases. + __ bind(&ool_min_abc); + __ Float32MinOutOfLine(a, b, c); + __ Branch(&done_min_abc); + + __ bind(&ool_min_aab); + __ Float32MinOutOfLine(a, a, b); + __ Branch(&done_min_aab); + + __ bind(&ool_min_aba); + __ Float32MinOutOfLine(a, b, a); + __ Branch(&done_min_aba); + + __ bind(&ool_max_abc); + __ Float32MaxOutOfLine(a, b, c); + __ Branch(&done_max_abc); + + __ bind(&ool_max_aab); + __ Float32MaxOutOfLine(a, a, b); + __ Branch(&done_max_aab); + + __ bind(&ool_max_aba); + __ Float32MaxOutOfLine(a, b, a); + __ Branch(&done_max_aba); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = masm->isolate()->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + return FUNCTION_CAST<::F4>(code->entry()); +} + +TEST(macro_float_minmax_f32) { + // Test the Float32Min and Float32Max macros. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assembler(isolate, NULL, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; + + struct Inputs { + float src1_; + float src2_; + }; + + struct Results { + // Check all register aliasing possibilities in order to exercise all + // code-paths in the macro assembler. + float min_abc_; + float min_aab_; + float min_aba_; + float max_abc_; + float max_aab_; + float max_aba_; + }; + + ::F4 f = GenerateMacroFloat32MinMax<FPURegister, Inputs, Results>(masm); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_MINMAX(src1, src2, min, max) \ + do { \ + Inputs inputs = {src1, src2}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_abc_)); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aab_)); \ + CHECK_EQ(bit_cast<uint32_t>(min), bit_cast<uint32_t>(results.min_aba_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_abc_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aab_)); \ + CHECK_EQ(bit_cast<uint32_t>(max), bit_cast<uint32_t>(results.max_aba_)); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + } while (0) + + float nan_a = std::numeric_limits<float>::quiet_NaN(); + float nan_b = std::numeric_limits<float>::quiet_NaN(); + + CHECK_MINMAX(1.0f, -1.0f, -1.0f, 1.0f); + CHECK_MINMAX(-1.0f, 1.0f, -1.0f, 1.0f); + CHECK_MINMAX(0.0f, -1.0f, -1.0f, 0.0f); + CHECK_MINMAX(-1.0f, 0.0f, -1.0f, 0.0f); + CHECK_MINMAX(-0.0f, -1.0f, -1.0f, -0.0f); + CHECK_MINMAX(-1.0f, -0.0f, -1.0f, -0.0f); + CHECK_MINMAX(0.0f, 1.0f, 0.0f, 1.0f); + CHECK_MINMAX(1.0f, 0.0f, 0.0f, 1.0f); + + CHECK_MINMAX(0.0f, 0.0f, 0.0f, 0.0f); + CHECK_MINMAX(-0.0f, -0.0f, -0.0f, -0.0f); + CHECK_MINMAX(-0.0f, 0.0f, -0.0f, 0.0f); + CHECK_MINMAX(0.0f, -0.0f, -0.0f, 0.0f); + + CHECK_MINMAX(0.0f, nan_a, nan_a, nan_a); + CHECK_MINMAX(nan_a, 0.0f, nan_a, nan_a); + CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_MINMAX +} + +template <typename T, typename Inputs, typename Results> +static ::F4 GenerateMacroFloat64MinMax(MacroAssembler* masm) { + T a = T::from_code(4); // f4 + T b = T::from_code(6); // f6 + T c = T::from_code(8); // f8 + + Label ool_min_abc, ool_min_aab, ool_min_aba; + Label ool_max_abc, ool_max_aab, ool_max_aba; + + Label done_min_abc, done_min_aab, done_min_aba; + Label done_max_abc, done_max_aab, done_max_aba; + +#define FLOAT_MIN_MAX(fminmax, res, x, y, done, ool, res_field) \ + __ ldc1(x, MemOperand(a0, offsetof(Inputs, src1_))); \ + __ ldc1(y, MemOperand(a0, offsetof(Inputs, src2_))); \ + __ fminmax(res, x, y, &ool); \ + __ bind(&done); \ + __ sdc1(a, MemOperand(a1, offsetof(Results, res_field))) + + // a = min(b, c); + FLOAT_MIN_MAX(Float64Min, a, b, c, done_min_abc, ool_min_abc, min_abc_); + // a = min(a, b); + FLOAT_MIN_MAX(Float64Min, a, a, b, done_min_aab, ool_min_aab, min_aab_); + // a = min(b, a); + FLOAT_MIN_MAX(Float64Min, a, b, a, done_min_aba, ool_min_aba, min_aba_); + + // a = max(b, c); + FLOAT_MIN_MAX(Float64Max, a, b, c, done_max_abc, ool_max_abc, max_abc_); + // a = max(a, b); + FLOAT_MIN_MAX(Float64Max, a, a, b, done_max_aab, ool_max_aab, max_aab_); + // a = max(b, a); + FLOAT_MIN_MAX(Float64Max, a, b, a, done_max_aba, ool_max_aba, max_aba_); + +#undef FLOAT_MIN_MAX + + __ jr(ra); + __ nop(); + + // Generate out-of-line cases. + __ bind(&ool_min_abc); + __ Float64MinOutOfLine(a, b, c); + __ Branch(&done_min_abc); + + __ bind(&ool_min_aab); + __ Float64MinOutOfLine(a, a, b); + __ Branch(&done_min_aab); + + __ bind(&ool_min_aba); + __ Float64MinOutOfLine(a, b, a); + __ Branch(&done_min_aba); + + __ bind(&ool_max_abc); + __ Float64MaxOutOfLine(a, b, c); + __ Branch(&done_max_abc); + + __ bind(&ool_max_aab); + __ Float64MaxOutOfLine(a, a, b); + __ Branch(&done_max_aab); + + __ bind(&ool_max_aba); + __ Float64MaxOutOfLine(a, b, a); + __ Branch(&done_max_aba); + + CodeDesc desc; + masm->GetCode(&desc); + Handle<Code> code = masm->isolate()->factory()->NewCode( + desc, Code::ComputeFlags(Code::STUB), Handle<Code>()); +#ifdef DEBUG + OFStream os(stdout); + code->Print(os); +#endif + return FUNCTION_CAST<::F4>(code->entry()); +} + +TEST(macro_float_minmax_f64) { + // Test the Float64Min and Float64Max macros. + CcTest::InitializeVM(); + Isolate* isolate = CcTest::i_isolate(); + HandleScope scope(isolate); + + MacroAssembler assembler(isolate, NULL, 0, + v8::internal::CodeObjectRequired::kYes); + MacroAssembler* masm = &assembler; + + struct Inputs { + double src1_; + double src2_; + }; + + struct Results { + // Check all register aliasing possibilities in order to exercise all + // code-paths in the macro assembler. + double min_abc_; + double min_aab_; + double min_aba_; + double max_abc_; + double max_aab_; + double max_aba_; + }; + + ::F4 f = GenerateMacroFloat64MinMax<DoubleRegister, Inputs, Results>(masm); + Object* dummy = nullptr; + USE(dummy); + +#define CHECK_MINMAX(src1, src2, min, max) \ + do { \ + Inputs inputs = {src1, src2}; \ + Results results; \ + dummy = CALL_GENERATED_CODE(isolate, f, &inputs, &results, 0, 0, 0); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_abc_)); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aab_)); \ + CHECK_EQ(bit_cast<uint64_t>(min), bit_cast<uint64_t>(results.min_aba_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_abc_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aab_)); \ + CHECK_EQ(bit_cast<uint64_t>(max), bit_cast<uint64_t>(results.max_aba_)); \ + /* Use a bit_cast to correctly identify -0.0 and NaNs. */ \ + } while (0) + + double nan_a = std::numeric_limits<double>::quiet_NaN(); + double nan_b = std::numeric_limits<double>::quiet_NaN(); + + CHECK_MINMAX(1.0, -1.0, -1.0, 1.0); + CHECK_MINMAX(-1.0, 1.0, -1.0, 1.0); + CHECK_MINMAX(0.0, -1.0, -1.0, 0.0); + CHECK_MINMAX(-1.0, 0.0, -1.0, 0.0); + CHECK_MINMAX(-0.0, -1.0, -1.0, -0.0); + CHECK_MINMAX(-1.0, -0.0, -1.0, -0.0); + CHECK_MINMAX(0.0, 1.0, 0.0, 1.0); + CHECK_MINMAX(1.0, 0.0, 0.0, 1.0); + + CHECK_MINMAX(0.0, 0.0, 0.0, 0.0); + CHECK_MINMAX(-0.0, -0.0, -0.0, -0.0); + CHECK_MINMAX(-0.0, 0.0, -0.0, 0.0); + CHECK_MINMAX(0.0, -0.0, -0.0, 0.0); + + CHECK_MINMAX(0.0, nan_a, nan_a, nan_a); + CHECK_MINMAX(nan_a, 0.0, nan_a, nan_a); + CHECK_MINMAX(nan_a, nan_b, nan_a, nan_a); + CHECK_MINMAX(nan_b, nan_a, nan_b, nan_b); + +#undef CHECK_MINMAX +} + #undef __ diff --git a/deps/v8/test/cctest/test-object.cc b/deps/v8/test/cctest/test-object.cc index 396318121a..cade4284ae 100644 --- a/deps/v8/test/cctest/test-object.cc +++ b/deps/v8/test/cctest/test-object.cc @@ -6,6 +6,7 @@ #include "src/handles-inl.h" #include "src/handles.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/objects.h" #include "src/v8.h" #include "test/cctest/cctest.h" diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc index 5a5a734236..fd904b110c 100644 --- a/deps/v8/test/cctest/test-parsing.cc +++ b/deps/v8/test/cctest/test-parsing.cc @@ -40,13 +40,16 @@ #include "src/execution.h" #include "src/flags.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/objects.h" #include "src/parsing/parse-info.h" #include "src/parsing/parser.h" +#include "src/parsing/parsing.h" #include "src/parsing/preparser.h" #include "src/parsing/rewriter.h" #include "src/parsing/scanner-character-streams.h" #include "src/parsing/token.h" +#include "src/unicode-cache.h" #include "src/utils.h" #include "test/cctest/cctest.h" @@ -172,12 +175,13 @@ TEST(ScanHTMLEndComments) { scanner.Initialize(stream.get()); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::AstValueFactory ast_value_factory( - &zone, CcTest::i_isolate()->heap()->HashSeed()); + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); i::PendingCompilationErrorHandler pending_error_handler; i::PreParser preparser( - &zone, &scanner, &ast_value_factory, &pending_error_handler, - CcTest::i_isolate()->counters()->runtime_call_stats(), stack_limit); - preparser.set_allow_lazy(true); + &zone, &scanner, stack_limit, &ast_value_factory, + &pending_error_handler, + CcTest::i_isolate()->counters()->runtime_call_stats()); i::PreParser::PreParseResult result = preparser.PreParseProgram(); CHECK_EQ(i::PreParser::kPreParseSuccess, result); CHECK(!pending_error_handler.has_pending_error()); @@ -190,12 +194,13 @@ TEST(ScanHTMLEndComments) { scanner.Initialize(stream.get()); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::AstValueFactory ast_value_factory( - &zone, CcTest::i_isolate()->heap()->HashSeed()); + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); i::PendingCompilationErrorHandler pending_error_handler; i::PreParser preparser( - &zone, &scanner, &ast_value_factory, &pending_error_handler, - CcTest::i_isolate()->counters()->runtime_call_stats(), stack_limit); - preparser.set_allow_lazy(true); + &zone, &scanner, stack_limit, &ast_value_factory, + &pending_error_handler, + CcTest::i_isolate()->counters()->runtime_call_stats()); i::PreParser::PreParseResult result = preparser.PreParseProgram(); // Even in the case of a syntax error, kPreParseSuccess is returned. CHECK_EQ(i::PreParser::kPreParseSuccess, result); @@ -251,7 +256,6 @@ TEST(UsingCachedData) { v8::String::NewExternalOneByte(isolate, new ScriptResource(source, source_length)) .ToLocalChecked()); - i::FLAG_min_preparse_length = 0; v8::ScriptCompiler::Compile(isolate->GetCurrentContext(), &script_source, v8::ScriptCompiler::kProduceParserCache) .ToLocalChecked(); @@ -278,9 +282,6 @@ TEST(PreparseFunctionDataIsUsed) { // This tests that we actually do use the function data generated by the // preparser. - // Make preparsing work for short scripts. - i::FLAG_min_preparse_length = 0; - v8::Isolate* isolate = CcTest::isolate(); v8::HandleScope handles(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); @@ -365,12 +366,13 @@ TEST(StandAlonePreParser) { i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::AstValueFactory ast_value_factory( - &zone, CcTest::i_isolate()->heap()->HashSeed()); + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); i::PendingCompilationErrorHandler pending_error_handler; i::PreParser preparser( - &zone, &scanner, &ast_value_factory, &pending_error_handler, - CcTest::i_isolate()->counters()->runtime_call_stats(), stack_limit); - preparser.set_allow_lazy(true); + &zone, &scanner, stack_limit, &ast_value_factory, + &pending_error_handler, + CcTest::i_isolate()->counters()->runtime_call_stats()); preparser.set_allow_natives(true); i::PreParser::PreParseResult result = preparser.PreParseProgram(); CHECK_EQ(i::PreParser::kPreParseSuccess, result); @@ -401,12 +403,12 @@ TEST(StandAlonePreParserNoNatives) { // Preparser defaults to disallowing natives syntax. i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::AstValueFactory ast_value_factory( - &zone, CcTest::i_isolate()->heap()->HashSeed()); + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); i::PendingCompilationErrorHandler pending_error_handler; - i::PreParser preparser( - &zone, &scanner, &ast_value_factory, &pending_error_handler, - isolate->counters()->runtime_call_stats(), stack_limit); - preparser.set_allow_lazy(true); + i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory, + &pending_error_handler, + isolate->counters()->runtime_call_stats()); i::PreParser::PreParseResult result = preparser.PreParseProgram(); CHECK_EQ(i::PreParser::kPreParseSuccess, result); CHECK(pending_error_handler.has_pending_error()); @@ -468,14 +470,14 @@ TEST(RegressChromium62639) { i::Scanner scanner(CcTest::i_isolate()->unicode_cache()); scanner.Initialize(stream.get()); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); - i::AstValueFactory ast_value_factory(&zone, - CcTest::i_isolate()->heap()->HashSeed()); + i::AstValueFactory ast_value_factory( + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); i::PendingCompilationErrorHandler pending_error_handler; - i::PreParser preparser(&zone, &scanner, &ast_value_factory, - &pending_error_handler, - isolate->counters()->runtime_call_stats(), - CcTest::i_isolate()->stack_guard()->real_climit()); - preparser.set_allow_lazy(true); + i::PreParser preparser(&zone, &scanner, + CcTest::i_isolate()->stack_guard()->real_climit(), + &ast_value_factory, &pending_error_handler, + isolate->counters()->runtime_call_stats()); i::PreParser::PreParseResult result = preparser.PreParseProgram(); // Even in the case of a syntax error, kPreParseSuccess is returned. CHECK_EQ(i::PreParser::kPreParseSuccess, result); @@ -486,7 +488,6 @@ TEST(RegressChromium62639) { TEST(Regress928) { // Test only applies when lazy parsing. if (!i::FLAG_lazy) return; - i::FLAG_min_preparse_length = 0; // Tests that the first non-toplevel function is not included in the preparse // data. @@ -545,13 +546,13 @@ TEST(PreParseOverflow) { scanner.Initialize(stream.get()); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); - i::AstValueFactory ast_value_factory(&zone, - CcTest::i_isolate()->heap()->HashSeed()); + i::AstValueFactory ast_value_factory( + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); i::PendingCompilationErrorHandler pending_error_handler; - i::PreParser preparser( - &zone, &scanner, &ast_value_factory, &pending_error_handler, - isolate->counters()->runtime_call_stats(), stack_limit); - preparser.set_allow_lazy(true); + i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory, + &pending_error_handler, + isolate->counters()->runtime_call_stats()); i::PreParser::PreParseResult result = preparser.PreParseProgram(); CHECK_EQ(i::PreParser::kPreParseStackOverflow, result); } @@ -647,8 +648,9 @@ void TestScanRegExp(const char* re_source, const char* expected) { CHECK(scanner.ScanRegExpPattern()); scanner.Next(); // Current token is now the regexp literal. i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); - i::AstValueFactory ast_value_factory(&zone, - CcTest::i_isolate()->heap()->HashSeed()); + i::AstValueFactory ast_value_factory( + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); const i::AstRawString* current_symbol = scanner.CurrentSymbol(&ast_value_factory); ast_value_factory.Internalize(CcTest::i_isolate()); @@ -825,8 +827,9 @@ TEST(ScopeUsesArgumentsSuperThis) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); - CHECK(parser.Parse(&info)); + // The information we're checking is only produced when eager parsing. + info.set_allow_lazy_parsing(false); + CHECK(i::parsing::ParseProgram(&info)); CHECK(i::Rewriter::Rewrite(&info)); i::DeclarationScope::Analyze(&info, i::AnalyzeMode::kRegular); CHECK(info.literal() != NULL); @@ -1179,11 +1182,9 @@ TEST(ScopePositions) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); - parser.set_allow_lazy(true); info.set_language_mode(source_data[i].language_mode); - parser.Parse(&info); - CHECK(info.literal() != NULL); + i::parsing::ParseProgram(&info); + CHECK_NOT_NULL(info.literal()); // Check scope types and positions. i::Scope* scope = info.literal()->scope(); @@ -1228,9 +1229,7 @@ TEST(DiscardFunctionBody) { i::Handle<i::Script> script = factory->NewScript(source_code); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - info.set_allow_lazy_parsing(); - i::Parser parser(&info); - parser.Parse(&info); + i::parsing::ParseProgram(&info); function = info.literal(); CHECK_NOT_NULL(function); CHECK_NOT_NULL(function->body()); @@ -1278,15 +1277,14 @@ const char* ReadString(unsigned* start) { return result; } - enum ParserFlag { kAllowLazy, kAllowNatives, kAllowHarmonyFunctionSent, - kAllowHarmonyAsyncAwait, kAllowHarmonyRestrictiveGenerators, kAllowHarmonyTrailingCommas, kAllowHarmonyClassFields, + kAllowHarmonyObjectSpread, }; enum ParserSyncTestResult { @@ -1295,24 +1293,30 @@ enum ParserSyncTestResult { kError }; -template <typename Traits> -void SetParserFlags(i::ParserBase<Traits>* parser, - i::EnumSet<ParserFlag> flags) { - parser->set_allow_lazy(flags.Contains(kAllowLazy)); +void SetGlobalFlags(i::EnumSet<ParserFlag> flags) { + i::FLAG_allow_natives_syntax = flags.Contains(kAllowNatives); + i::FLAG_harmony_function_sent = flags.Contains(kAllowHarmonyFunctionSent); + i::FLAG_harmony_restrictive_generators = + flags.Contains(kAllowHarmonyRestrictiveGenerators); + i::FLAG_harmony_trailing_commas = flags.Contains(kAllowHarmonyTrailingCommas); + i::FLAG_harmony_class_fields = flags.Contains(kAllowHarmonyClassFields); + i::FLAG_harmony_object_spread = flags.Contains(kAllowHarmonyObjectSpread); +} + +void SetParserFlags(i::PreParser* parser, i::EnumSet<ParserFlag> flags) { parser->set_allow_natives(flags.Contains(kAllowNatives)); parser->set_allow_harmony_function_sent( flags.Contains(kAllowHarmonyFunctionSent)); - parser->set_allow_harmony_async_await( - flags.Contains(kAllowHarmonyAsyncAwait)); parser->set_allow_harmony_restrictive_generators( flags.Contains(kAllowHarmonyRestrictiveGenerators)); parser->set_allow_harmony_trailing_commas( flags.Contains(kAllowHarmonyTrailingCommas)); parser->set_allow_harmony_class_fields( flags.Contains(kAllowHarmonyClassFields)); + parser->set_allow_harmony_object_spread( + flags.Contains(kAllowHarmonyObjectSpread)); } - void TestParserSyncWithFlags(i::Handle<i::String> source, i::EnumSet<ParserFlag> flags, ParserSyncTestResult result, @@ -1333,10 +1337,11 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, i::ScannerStream::For(source)); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::AstValueFactory ast_value_factory( - &zone, CcTest::i_isolate()->heap()->HashSeed()); - i::PreParser preparser( - &zone, &scanner, &ast_value_factory, &pending_error_handler, - isolate->counters()->runtime_call_stats(), stack_limit); + &zone, CcTest::i_isolate()->ast_string_constants(), + CcTest::i_isolate()->heap()->HashSeed()); + i::PreParser preparser(&zone, &scanner, stack_limit, &ast_value_factory, + &pending_error_handler, + isolate->counters()->runtime_call_stats()); SetParserFlags(&preparser, flags); scanner.Initialize(stream.get()); i::PreParser::PreParseResult result = @@ -1350,10 +1355,10 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); - SetParserFlags(&parser, flags); + info.set_allow_lazy_parsing(flags.Contains(kAllowLazy)); + SetGlobalFlags(flags); if (is_module) info.set_module(); - parser.Parse(&info); + i::parsing::ParseProgram(&info); function = info.literal(); if (function) { parser_materialized_literals = function->materialized_literal_count(); @@ -2485,8 +2490,7 @@ TEST(DontRegressPreParserDataSizes) { i::ScriptData* sd = NULL; info.set_cached_data(&sd); info.set_compile_options(v8::ScriptCompiler::kProduceParserCache); - info.set_allow_lazy_parsing(); - i::Parser::ParseStatic(&info); + i::parsing::ParseProgram(&info); i::ParseData* pd = i::ParseData::FromCachedData(sd); if (pd->FunctionCount() != test_cases[i].functions) { @@ -2727,16 +2731,6 @@ TEST(ErrorsObjectLiteralChecking) { "x = 0", "* *x(){}", "x*(){}", - // This should fail without --harmony-async-await - "async x(){}", - NULL - }; - // clang-format on - - RunParserSyncTest(context_data, statement_data, kError); - - // clang-format off - const char* async_data[] = { "static async x(){}", "static async x : 0", "static async get x : 0", @@ -2754,9 +2748,7 @@ TEST(ErrorsObjectLiteralChecking) { }; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, async_data, kError, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(context_data, statement_data, kError); } @@ -2830,14 +2822,6 @@ TEST(NoErrorsObjectLiteralChecking) { "super: 6", "eval: 7", "arguments: 8", - NULL - }; - // clang-format on - - RunParserSyncTest(context_data, statement_data, kSuccess); - - // clang-format off - const char* async_data[] = { "async x(){}", "async 0(){}", "async get(){}", @@ -2851,9 +2835,7 @@ TEST(NoErrorsObjectLiteralChecking) { }; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, async_data, kSuccess, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(context_data, statement_data, kSuccess); } @@ -3151,7 +3133,6 @@ TEST(RegressionLazyFunctionWithErrorWithArg) { v8::HandleScope scope(isolate); LocalContext env; i::FLAG_lazy = true; - i::FLAG_min_preparse_length = 0; CompileRun("function this_is_lazy() {\n" " break p;\n" "}\n" @@ -3191,7 +3172,8 @@ TEST(SerializationOfMaybeAssignmentFlag) { i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); i::Context* context = f->context(); - i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); + i::AstValueFactory avf(&zone, isolate->ast_string_constants(), + isolate->heap()->HashSeed()); const i::AstRawString* name = avf.GetOneByteString("result"); avf.Internalize(isolate); i::Handle<i::String> str = name->string(); @@ -3220,7 +3202,6 @@ TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) { i::HandleScope scope(isolate); LocalContext env; - const char* src = "function f(x) {" " var a = arguments;" @@ -3236,12 +3217,13 @@ TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) { i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); source->PrintOn(stdout); printf("\n"); - i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); + i::Zone zone(isolate->allocator(), ZONE_NAME); v8::Local<v8::Value> v = CompileRun(src); i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); i::Context* context = f->context(); - i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); + i::AstValueFactory avf(&zone, isolate->ast_string_constants(), + isolate->heap()->HashSeed()); const i::AstRawString* name_x = avf.GetOneByteString("x"); avf.Internalize(isolate); @@ -3268,83 +3250,109 @@ TEST(InnerAssignment) { const char* prefix = "function f() {"; const char* midfix = " function g() {"; const char* suffix = "}}; f"; - struct { const char* source; bool assigned; bool strict; } outers[] = { - // Actual assignments. - { "var x; var x = 5;", true, false }, - { "var x; { var x = 5; }", true, false }, - { "'use strict'; let x; x = 6;", true, true }, - { "var x = 5; function x() {}", true, false }, - // Actual non-assignments. - { "var x;", false, false }, - { "var x = 5;", false, false }, - { "'use strict'; let x;", false, true }, - { "'use strict'; let x = 6;", false, true }, - { "'use strict'; var x = 0; { let x = 6; }", false, true }, - { "'use strict'; var x = 0; { let x; x = 6; }", false, true }, - { "'use strict'; let x = 0; { let x = 6; }", false, true }, - { "'use strict'; let x = 0; { let x; x = 6; }", false, true }, - { "var x; try {} catch (x) { x = 5; }", false, false }, - { "function x() {}", false, false }, - // Eval approximation. - { "var x; eval('');", true, false }, - { "eval(''); var x;", true, false }, - { "'use strict'; let x; eval('');", true, true }, - { "'use strict'; eval(''); let x;", true, true }, - // Non-assignments not recognized, because the analysis is approximative. - { "var x; var x;", true, false }, - { "var x = 5; var x;", true, false }, - { "var x; { var x; }", true, false }, - { "var x; function x() {}", true, false }, - { "function x() {}; var x;", true, false }, - { "var x; try {} catch (x) { var x = 5; }", true, false }, - }; - struct { const char* source; bool assigned; bool with; } inners[] = { - // Actual assignments. - { "x = 1;", true, false }, - { "x++;", true, false }, - { "++x;", true, false }, - { "x--;", true, false }, - { "--x;", true, false }, - { "{ x = 1; }", true, false }, - { "'use strict'; { let x; }; x = 0;", true, false }, - { "'use strict'; { const x = 1; }; x = 0;", true, false }, - { "'use strict'; { function x() {} }; x = 0;", true, false }, - { "with ({}) { x = 1; }", true, true }, - { "eval('');", true, false }, - { "'use strict'; { let y; eval('') }", true, false }, - { "function h() { x = 0; }", true, false }, - { "(function() { x = 0; })", true, false }, - { "(function() { x = 0; })", true, false }, - { "with ({}) (function() { x = 0; })", true, true }, - // Actual non-assignments. - { "", false, false }, - { "x;", false, false }, - { "var x;", false, false }, - { "var x = 8;", false, false }, - { "var x; x = 8;", false, false }, - { "'use strict'; let x;", false, false }, - { "'use strict'; let x = 8;", false, false }, - { "'use strict'; let x; x = 8;", false, false }, - { "'use strict'; const x = 8;", false, false }, - { "function x() {}", false, false }, - { "function x() { x = 0; }", false, false }, - { "function h(x) { x = 0; }", false, false }, - { "'use strict'; { let x; x = 0; }", false, false }, - { "{ var x; }; x = 0;", false, false }, - { "with ({}) {}", false, true }, - { "var x; { with ({}) { x = 1; } }", false, true }, - { "try {} catch(x) { x = 0; }", false, false }, - { "try {} catch(x) { with ({}) { x = 1; } }", false, true }, - // Eval approximation. - { "eval('');", true, false }, - { "function h() { eval(''); }", true, false }, - { "(function() { eval(''); })", true, false }, - // Shadowing not recognized because of eval approximation. - { "var x; eval('');", true, false }, - { "'use strict'; let x; eval('');", true, false }, - { "try {} catch(x) { eval(''); }", true, false }, - { "function x() { eval(''); }", true, false }, - { "(function(x) { eval(''); })", true, false }, + struct { + const char* source; + bool assigned; + bool strict; + } outers[] = { + // Actual assignments. + {"var x; var x = 5;", true, false}, + {"var x; { var x = 5; }", true, false}, + {"'use strict'; let x; x = 6;", true, true}, + {"var x = 5; function x() {}", true, false}, + {"var x = 4; var x = 5;", true, false}, + {"var [x, x] = [4, 5];", true, false}, + {"var x; [x, x] = [4, 5];", true, false}, + {"var {a: x, b: x} = {a: 4, b: 5};", true, false}, + {"var x = {a: 4, b: (x = 5)};", true, false}, + {"var {x=1} = {a: 4, b: (x = 5)};", true, false}, + {"var {x} = {x: 4, b: (x = 5)};", true, false}, + // Actual non-assignments. + {"var x;", false, false}, + {"var x = 5;", false, false}, + {"'use strict'; let x;", false, true}, + {"'use strict'; let x = 6;", false, true}, + {"'use strict'; var x = 0; { let x = 6; }", false, true}, + {"'use strict'; var x = 0; { let x; x = 6; }", false, true}, + {"'use strict'; let x = 0; { let x = 6; }", false, true}, + {"'use strict'; let x = 0; { let x; x = 6; }", false, true}, + {"var x; try {} catch (x) { x = 5; }", false, false}, + {"function x() {}", false, false}, + // Eval approximation. + {"var x; eval('');", true, false}, + {"eval(''); var x;", true, false}, + {"'use strict'; let x; eval('');", true, true}, + {"'use strict'; eval(''); let x;", true, true}, + // Non-assignments not recognized, because the analysis is approximative. + {"var x; var x;", true, false}, + {"var x = 5; var x;", true, false}, + {"var x; { var x; }", true, false}, + {"var x; function x() {}", true, false}, + {"function x() {}; var x;", true, false}, + {"var x; try {} catch (x) { var x = 5; }", true, false}, + }; + + // We set allow_error_in_inner_function to true in cases where our handling of + // assigned variables in lazy inner functions is currently overly pessimistic. + // FIXME(marja): remove it when no longer needed. + struct { + const char* source; + bool assigned; + bool with; + bool allow_error_in_inner_function; + } inners[] = { + // Actual assignments. + {"x = 1;", true, false, false}, + {"x++;", true, false, false}, + {"++x;", true, false, false}, + {"x--;", true, false, false}, + {"--x;", true, false, false}, + {"{ x = 1; }", true, false, false}, + {"'use strict'; { let x; }; x = 0;", true, false, false}, + {"'use strict'; { const x = 1; }; x = 0;", true, false, false}, + {"'use strict'; { function x() {} }; x = 0;", true, false, false}, + {"with ({}) { x = 1; }", true, true, false}, + {"eval('');", true, false, false}, + {"'use strict'; { let y; eval('') }", true, false, false}, + {"function h() { x = 0; }", true, false, false}, + {"(function() { x = 0; })", true, false, false}, + {"(function() { x = 0; })", true, false, false}, + {"with ({}) (function() { x = 0; })", true, true, false}, + {"for (x of [1,2,3]) {}", true, false, false}, + {"for (x in {a: 1}) {}", true, false, false}, + {"for ([x] of [[1],[2],[3]]) {}", true, false, false}, + {"for ([x] in {ab: 1}) {}", true, false, false}, + {"for ([...x] in {ab: 1}) {}", true, false, false}, + {"[x] = [1]", true, false, false}, + // Actual non-assignments. + {"", false, false, false}, + {"x;", false, false, false}, + {"var x;", false, false, false}, + {"var x = 8;", false, false, false}, + {"var x; x = 8;", false, false, false}, + {"'use strict'; let x;", false, false, false}, + {"'use strict'; let x = 8;", false, false, false}, + {"'use strict'; let x; x = 8;", false, false, false}, + {"'use strict'; const x = 8;", false, false, false}, + {"function x() {}", false, false, false}, + {"function x() { x = 0; }", false, false, true}, + {"function h(x) { x = 0; }", false, false, false}, + {"'use strict'; { let x; x = 0; }", false, false, false}, + {"{ var x; }; x = 0;", false, false, false}, + {"with ({}) {}", false, true, false}, + {"var x; { with ({}) { x = 1; } }", false, true, false}, + {"try {} catch(x) { x = 0; }", false, false, true}, + {"try {} catch(x) { with ({}) { x = 1; } }", false, true, true}, + // Eval approximation. + {"eval('');", true, false, false}, + {"function h() { eval(''); }", true, false, false}, + {"(function() { eval(''); })", true, false, false}, + // Shadowing not recognized because of eval approximation. + {"var x; eval('');", true, false, false}, + {"'use strict'; let x; eval('');", true, false, false}, + {"try {} catch(x) { eval(''); }", true, false, false}, + {"function x() { eval(''); }", true, false, false}, + {"(function(x) { eval(''); })", true, false, false}, }; int prefix_len = Utf8LengthHelper(prefix); @@ -3365,7 +3373,7 @@ TEST(InnerAssignment) { i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner, suffix); - i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); + i::Zone zone(isolate->allocator(), ZONE_NAME); std::unique_ptr<i::ParseInfo> info; if (lazy) { printf("%s\n", program.start()); @@ -3374,6 +3382,7 @@ TEST(InnerAssignment) { i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared()); info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(&zone, shared)); + CHECK(i::parsing::ParseFunction(info.get())); } else { i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); @@ -3381,9 +3390,9 @@ TEST(InnerAssignment) { printf("\n"); i::Handle<i::Script> script = factory->NewScript(source); info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(&zone, script)); + info->set_allow_lazy_parsing(false); + CHECK(i::parsing::ParseProgram(info.get())); } - i::Parser parser(info.get()); - CHECK(parser.Parse(info.get())); CHECK(i::Compiler::Analyze(info.get())); CHECK(info->literal() != NULL); @@ -3402,17 +3411,268 @@ TEST(InnerAssignment) { CHECK(var->is_used() || !expected); bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned; if (i::FLAG_lazy_inner_functions) { - // If we parse inner functions lazily, allow being pessimistic about - // maybe_assigned. - CHECK(is_maybe_assigned || (is_maybe_assigned == expected)); + CHECK(is_maybe_assigned == expected || + (is_maybe_assigned && inners[j].allow_error_in_inner_function)); } else { - CHECK(is_maybe_assigned == expected); + CHECK_EQ(is_maybe_assigned, expected); } } } } } +TEST(MaybeAssignedParameters) { + i::Isolate* isolate = CcTest::i_isolate(); + i::HandleScope scope(isolate); + LocalContext env; + + struct { + bool arg_assigned; + const char* source; + } tests[] = { + {false, "function f(arg) {}"}, + {false, "function f(arg) {g(arg)}"}, + {false, "function f(arg) {function h() { g(arg) }; h()}"}, + {false, "function f(arg) {function h() { g(arg) }; return h}"}, + {false, "function f(arg=1) {}"}, + {false, "function f(arg=1) {g(arg)}"}, + {false, "function f(arg, arguments) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, + "function f(arg, ...arguments) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, + "function f(arg, arguments=[]) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, "function f(...arg) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, + "function f(arg) {g(arg); g(function() {arguments[0] = 42}); g(arg)}"}, + + // strict arguments object + {false, "function f(arg, x=1) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, "function f(arg, ...x) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, "function f(arg=1) {g(arg); arguments[0] = 42; g(arg)}"}, + {false, + "function f(arg) {'use strict'; g(arg); arguments[0] = 42; g(arg)}"}, + {false, "function f(arg) {g(arg); f.arguments[0] = 42; g(arg)}"}, + {false, "function f(arg, args=arguments) {g(arg); args[0] = 42; g(arg)}"}, + + {true, "function f(arg) {g(arg); arg = 42; g(arg)}"}, + {true, "function f(arg) {g(arg); eval('arg = 42'); g(arg)}"}, + {true, "function f(arg) {g(arg); var arg = 42; g(arg)}"}, + {true, "function f(arg, x=1) {g(arg); arg = 42; g(arg)}"}, + {true, "function f(arg, ...x) {g(arg); arg = 42; g(arg)}"}, + {true, "function f(arg=1) {g(arg); arg = 42; g(arg)}"}, + {true, "function f(arg) {'use strict'; g(arg); arg = 42; g(arg)}"}, + {true, "function f(arg, {a=(g(arg), arg=42)}) {g(arg)}"}, + {true, "function f(arg) {g(arg); g(function() {arg = 42}); g(arg)}"}, + {true, + "function f(arg) {g(arg); g(function() {eval('arg = 42')}); g(arg)}"}, + {true, "function f(arg) {g(arg); g(() => arg = 42); g(arg)}"}, + {true, "function f(arg) {g(arg); g(() => eval('arg = 42')); g(arg)}"}, + {true, "function f(...arg) {g(arg); eval('arg = 42'); g(arg)}"}, + + // sloppy arguments object + {true, "function f(arg) {g(arg); arguments[0] = 42; g(arg)}"}, + {true, "function f(arg) {g(arg); h(arguments); g(arg)}"}, + {true, + "function f(arg) {((args) => {arguments[0] = 42})(arguments); " + "g(arg)}"}, + {true, "function f(arg) {g(arg); eval('arguments[0] = 42'); g(arg)}"}, + {true, "function f(arg) {g(arg); g(() => arguments[0] = 42); g(arg)}"}, + }; + + const char* suffix = "; f"; + + for (unsigned i = 0; i < arraysize(tests); ++i) { + bool assigned = tests[i].arg_assigned; + const char* source = tests[i].source; + for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) { + i::ScopedVector<char> program(Utf8LengthHelper(source) + + Utf8LengthHelper(suffix) + 1); + i::SNPrintF(program, "%s%s", source, suffix); + i::Zone zone(isolate->allocator(), ZONE_NAME); + std::unique_ptr<i::ParseInfo> info; + printf("%s\n", program.start()); + v8::Local<v8::Value> v = CompileRun(program.start()); + i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); + i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); + i::Handle<i::SharedFunctionInfo> shared = i::handle(f->shared()); + info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(&zone, shared)); + info->set_allow_lazy_parsing(allow_lazy); + CHECK(i::parsing::ParseFunction(info.get())); + CHECK(i::Compiler::Analyze(info.get())); + CHECK_NOT_NULL(info->literal()); + + i::Scope* scope = info->literal()->scope(); + CHECK(!scope->AsDeclarationScope()->was_lazily_parsed()); + CHECK_NULL(scope->sibling()); + CHECK(scope->is_function_scope()); + const i::AstRawString* var_name = + info->ast_value_factory()->GetOneByteString("arg"); + i::Variable* var = scope->Lookup(var_name); + CHECK(var->is_used() || !assigned); + bool is_maybe_assigned = var->maybe_assigned() == i::kMaybeAssigned; + CHECK_EQ(is_maybe_assigned, assigned); + } + } +} + +TEST(MaybeAssignedTopLevel) { + i::Isolate* isolate = CcTest::i_isolate(); + i::HandleScope scope(isolate); + LocalContext env; + i::Factory* factory = isolate->factory(); + + const char* prefixes[] = { + "let foo; ", "let foo = 0; ", + "let [foo] = [1]; ", "let {foo} = {foo: 2}; ", + "let {foo=3} = {}; ", + }; + const char* sources[] = { + "function bar() {foo = 42}; ext(bar); ext(foo)", + "ext(function() {foo++}); ext(foo)", + "bar = () => --foo; ext(bar); ext(foo)", + "function* bar() {eval(ext)}; ext(bar); ext(foo)", + }; + + for (unsigned i = 0; i < arraysize(prefixes); ++i) { + const char* prefix = prefixes[i]; + for (unsigned j = 0; j < arraysize(sources); ++j) { + const char* source = sources[j]; + i::ScopedVector<char> program(Utf8LengthHelper(prefix) + + Utf8LengthHelper(source) + 1); + i::SNPrintF(program, "%s%s", prefix, source); + i::Zone zone(isolate->allocator(), ZONE_NAME); + + i::Handle<i::String> string = + factory->InternalizeUtf8String(program.start()); + string->PrintOn(stdout); + printf("\n"); + i::Handle<i::Script> script = factory->NewScript(string); + + for (unsigned allow_lazy = 0; allow_lazy < 2; ++allow_lazy) { + for (unsigned module = 0; module < 2; ++module) { + std::unique_ptr<i::ParseInfo> info; + info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(&zone, script)); + info->set_module(module); + info->set_allow_lazy_parsing(allow_lazy); + + CHECK(i::parsing::ParseProgram(info.get())); + CHECK(i::Compiler::Analyze(info.get())); + + CHECK_NOT_NULL(info->literal()); + i::Scope* scope = info->literal()->scope(); + CHECK(!scope->AsDeclarationScope()->was_lazily_parsed()); + CHECK_NULL(scope->sibling()); + CHECK(module ? scope->is_module_scope() : scope->is_script_scope()); + + const i::AstRawString* var_name = + info->ast_value_factory()->GetOneByteString("foo"); + i::Variable* var = scope->Lookup(var_name); + CHECK(var->is_used()); + CHECK(var->maybe_assigned() == i::kMaybeAssigned); + } + } + } + } +} + +namespace { + +i::Scope* DeserializeFunctionScope(i::Isolate* isolate, i::Zone* zone, + i::Handle<i::JSObject> m, const char* name) { + i::AstValueFactory avf(zone, isolate->ast_string_constants(), + isolate->heap()->HashSeed()); + i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast( + i::JSReceiver::GetProperty(isolate, m, name).ToHandleChecked()); + i::DeclarationScope* script_scope = + new (zone) i::DeclarationScope(zone, &avf); + i::Scope* s = i::Scope::DeserializeScopeChain( + isolate, zone, f->context()->scope_info(), script_scope, &avf, + i::Scope::DeserializationMode::kIncludingVariables); + return s; +} + +} // namespace + +TEST(AsmModuleFlag) { + i::FLAG_validate_asm = false; + i::Isolate* isolate = CcTest::i_isolate(); + i::HandleScope scope(isolate); + LocalContext env; + + const char* src = + "function m() {" + " 'use asm';" + " function f() { return 0 };" + " return { f:f };" + "}" + "m();"; + + i::Zone zone(isolate->allocator(), ZONE_NAME); + v8::Local<v8::Value> v = CompileRun(src); + i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); + i::Handle<i::JSObject> m = i::Handle<i::JSObject>::cast(o); + + // The asm.js module should be marked as such. + i::Scope* s = DeserializeFunctionScope(isolate, &zone, m, "f"); + CHECK(s->IsAsmModule() && s->AsDeclarationScope()->asm_module()); + CHECK(!s->IsAsmFunction() && !s->AsDeclarationScope()->asm_function()); +} + +TEST(AsmFunctionFlag) { + i::Isolate* isolate = CcTest::i_isolate(); + i::HandleScope scope(isolate); + LocalContext env; + + const char* src = + "function m() {" + " 'use asm';" + " var x = 0;" + " function f1(a) {" + " var y = 0; return () => x + y;" + " };" + " do { function f2() {" + " var y = 0; return () => x + y;" + " } } while(false);" + " var f3 = (function() {" + " var y = 0; return () => x + y;" + " });" + " var f4 = (function() { return (function() {" + " var y = 0; return () => x + y;" + " }) })();" + " return { f1:f1(), f2:f2(), f3:f3(), f4:f4() };" + "}" + "m();"; + + i::Zone zone(isolate->allocator(), ZONE_NAME); + v8::Local<v8::Value> v = CompileRun(src); + i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); + i::Handle<i::JSObject> m = i::Handle<i::JSObject>::cast(o); + + // The asm.js function {f1} should be marked as such. + i::Scope* s1 = DeserializeFunctionScope(isolate, &zone, m, "f1"); + CHECK(!s1->IsAsmModule() && !s1->AsDeclarationScope()->asm_module()); + CHECK(s1->IsAsmFunction() && s1->AsDeclarationScope()->asm_function()); + + // The asm.js function {f2} should be marked as such. + // TODO(5653): If the block surrounding {f2} where to allocate a context we + // would actually determine {f2} not to be an asm.js function. That decision + // is fine but we should be consistent independent of whether a context is + // allocated for the surrounding block scope! + i::Scope* s2 = DeserializeFunctionScope(isolate, &zone, m, "f2"); + CHECK(!s2->IsAsmModule() && !s2->AsDeclarationScope()->asm_module()); + CHECK(s2->IsAsmFunction() && s2->AsDeclarationScope()->asm_function()); + + // The asm.js function {f3} should be marked as such. + i::Scope* s3 = DeserializeFunctionScope(isolate, &zone, m, "f3"); + CHECK(!s3->IsAsmModule() && !s3->AsDeclarationScope()->asm_module()); + CHECK(s3->IsAsmFunction() && s3->AsDeclarationScope()->asm_function()); + + // The nested function {f4} is not an asm.js function. + i::Scope* s4 = DeserializeFunctionScope(isolate, &zone, m, "f4"); + CHECK(!s4->IsAsmModule() && !s4->AsDeclarationScope()->asm_module()); + CHECK(!s4->IsAsmFunction() && !s4->AsDeclarationScope()->asm_function()); +} + namespace { int* global_use_counts = NULL; @@ -3422,8 +3682,7 @@ void MockUseCounterCallback(v8::Isolate* isolate, ++global_use_counts[feature]; } -} - +} // namespace TEST(UseAsmUseCount) { i::Isolate* isolate = CcTest::i_isolate(); @@ -3460,6 +3719,8 @@ TEST(SloppyModeUseCount) { LocalContext env; int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; global_use_counts = use_counts; + // Force eager parsing (preparser doesn't update use counts). + i::FLAG_lazy = false; CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); CompileRun("function bar() { var baz = 1; }"); CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]); @@ -3473,6 +3734,8 @@ TEST(BothModesUseCount) { LocalContext env; int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; global_use_counts = use_counts; + // Force eager parsing (preparser doesn't update use counts). + i::FLAG_lazy = false; CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); CompileRun("function bar() { 'use strict'; var baz = 1; }"); CHECK_LT(0, use_counts[v8::Isolate::kSloppyMode]); @@ -4293,13 +4556,7 @@ TEST(ClassBodyNoErrors) { "static set st\\u0061tic(v) {}", "*st\\u0061tic() {}", "static *st\\u0061tic() {}", - NULL}; - // clang-format on - RunParserSyncTest(context_data, class_body_data, kSuccess); - - // clang-format off - const char* async_data[] = { "static async x(){}", "static async(){}", "static *async(){}", @@ -4311,13 +4568,10 @@ TEST(ClassBodyNoErrors) { "async async(){}", "async(){}", "*async(){}", - NULL - }; + NULL}; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, async_data, kSuccess, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(context_data, class_body_data, kSuccess); } @@ -4445,16 +4699,6 @@ TEST(ClassFieldsNoErrors) { "yield", "yield = 0", "yield\n a", - NULL - }; - // clang-format on - - static const ParserFlag without_async[] = {kAllowHarmonyClassFields}; - RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0, - without_async, arraysize(without_async)); - - // clang-format off - const char* async_data[] = { "async;", "async = 0;", "static async;" @@ -4470,10 +4714,9 @@ TEST(ClassFieldsNoErrors) { }; // clang-format on - static const ParserFlag with_async[] = {kAllowHarmonyClassFields, - kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, async_data, kSuccess, NULL, 0, with_async, - arraysize(with_async)); + static const ParserFlag always_flags[] = {kAllowHarmonyClassFields}; + RunParserSyncTest(context_data, class_body_data, kSuccess, NULL, 0, + always_flags, arraysize(always_flags)); } TEST(ClassFieldsErrors) { @@ -4497,6 +4740,8 @@ TEST(ClassFieldsErrors) { "*a;", "get a;", "yield a;", + "async a = 0", + "async a", // ASI requires a linebreak "a b", @@ -4510,22 +4755,9 @@ TEST(ClassFieldsErrors) { }; // clang-format on - static const ParserFlag without_async[] = {kAllowHarmonyClassFields}; + static const ParserFlag always_flags[] = {kAllowHarmonyClassFields}; RunParserSyncTest(context_data, class_body_data, kError, NULL, 0, - without_async, arraysize(without_async)); - - // clang-format off - const char* async_data[] = { - "async a = 0", - "async a", - NULL - }; - // clang-format on - - static const ParserFlag with_async[] = {kAllowHarmonyClassFields, - kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, async_data, kError, NULL, 0, with_async, - arraysize(with_async)); + always_flags, arraysize(always_flags)); } TEST(ClassExpressionErrors) { @@ -4614,13 +4846,7 @@ TEST(ClassAsyncErrors) { }; // clang-format on - // All of these are illegal whether or not async functions are permitted, - // although for different reasons. RunParserSyncTest(context_data, async_data, kError); - - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, async_data, kError, NULL, 0, always_flags, - arraysize(always_flags)); } TEST(ClassNameErrors) { @@ -5646,9 +5872,8 @@ TEST(BasicImportExportParsing) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); info.set_module(); - if (!parser.Parse(&info)) { + if (!i::parsing::ParseProgram(&info)) { i::Handle<i::JSObject> exception_handle( i::JSObject::cast(isolate->pending_exception())); i::Handle<i::String> message_string = i::Handle<i::String>::cast( @@ -5672,8 +5897,7 @@ TEST(BasicImportExportParsing) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); - CHECK(!parser.Parse(&info)); + CHECK(!i::parsing::ParseProgram(&info)); isolate->clear_pending_exception(); } } @@ -5764,9 +5988,8 @@ TEST(ImportExportParsingErrors) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); info.set_module(); - CHECK(!parser.Parse(&info)); + CHECK(!i::parsing::ParseProgram(&info)); isolate->clear_pending_exception(); } } @@ -5802,9 +6025,8 @@ TEST(ModuleTopLevelFunctionDecl) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); info.set_module(); - CHECK(!parser.Parse(&info)); + CHECK(!i::parsing::ParseProgram(&info)); isolate->clear_pending_exception(); } } @@ -6001,9 +6223,8 @@ TEST(ModuleParsingInternals) { i::Handle<i::Script> script = factory->NewScript(source); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); info.set_module(); - CHECK(parser.Parse(&info)); + CHECK(i::parsing::ParseProgram(&info)); CHECK(i::Compiler::Analyze(&info)); i::FunctionLiteral* func = info.literal(); i::ModuleScope* module_scope = func->scope()->AsModuleScope(); @@ -6262,8 +6483,7 @@ void TestLanguageMode(const char* source, factory->NewScript(factory->NewStringFromAsciiChecked(source)); i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); i::ParseInfo info(&zone, script); - i::Parser parser(&info); - parser.Parse(&info); + i::parsing::ParseProgram(&info); CHECK(info.literal() != NULL); CHECK_EQ(expected_language_mode, info.literal()->language_mode()); } @@ -6362,6 +6582,94 @@ TEST(ArrowFunctionASIErrors) { RunParserSyncTest(context_data, data, kError); } +TEST(ObjectSpreadPositiveTests) { + // clang-format off + const char* context_data[][2] = { + {"x = ", ""}, + {"'use strict'; x = ", ""}, + {NULL, NULL}}; + + // clang-format off + const char* data[] = { + "{ ...y }", + "{ a: 1, ...y }", + "{ b: 1, ...y }", + "{ y, ...y}", + "{ ...z = y}", + "{ ...y, y }", + "{ ...y, ...y}", + "{ a: 1, ...y, b: 1}", + "{ ...y, b: 1}", + "{ ...1}", + "{ ...null}", + "{ ...undefined}", + "{ ...1 in {}}", + "{ ...[]}", + "{ ...async function() { }}", + "{ ...async () => { }}", + "{ ...new Foo()}", + NULL}; + + static const ParserFlag flags[] = {kAllowHarmonyObjectSpread}; + RunParserSyncTest(context_data, data, kSuccess, NULL, 0, flags, + arraysize(flags)); +} + +TEST(ObjectSpreadNegativeTests) { + { + const char* context_data[][2] = {{"x = ", ""}, + {"'use strict'; x = ", ""}, + {NULL, NULL}}; + + // clang-format off + const char* data[] = { + "{ ...var z = y}", + "{ ...var}", + "{ ...foo bar}", + NULL}; + + static const ParserFlag flags[] = {kAllowHarmonyObjectSpread}; + RunParserSyncTest(context_data, data, kError, NULL, 0, flags, + arraysize(flags)); + } + + // Destructuring tests + { + const char* context_data[][2] = { + {"var ", " = {};"}, + {"( ", " = {});"}, + {"'use strict'; const ", " = {};"}, + {"function f(", ") {}"}, + {"function f(argument1, ", ") {}"}, + {"var f = (", ") => {};"}, + {"var f = (argument1,", ") => {};"}, + {"try {} catch(", ") {}"}, + {NULL, NULL}}; + + // clang-format off + const char* data[] = { + "{ ...y }", + "{ a: 1, ...y }", + "{ b: 1, ...y }", + "{ y, ...y}", + "{ ...z = y}", + "{ ...y, y }", + "{ ...y, ...y}", + "{ a: 1, ...y, b: 1}", + "{ ...y, b: 1}", + "{ ...1}", + "{ ...null}", + "{ ...undefined}", + "{ ...unknown}", + "{ ...var z = y}", + "({ ...z = {})", + NULL}; + + static const ParserFlag flags[] = {kAllowHarmonyObjectSpread}; + RunParserSyncTest(context_data, data, kError, NULL, 0, flags, + arraysize(flags)); + } +} TEST(DestructuringPositiveTests) { const char* context_data[][2] = {{"'use strict'; let ", " = {};"}, @@ -7802,9 +8110,7 @@ TEST(AsyncAwait) { }; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, - arraysize(always_flags)); + RunParserSyncTest(context_data, data, kSuccess); // clang-format off const char* async_body_context_data[][2] = { @@ -7858,10 +8164,8 @@ TEST(AsyncAwait) { }; // clang-format on - RunParserSyncTest(async_body_context_data, body_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); - RunParserSyncTest(body_context_data, body_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(async_body_context_data, body_data, kSuccess); + RunParserSyncTest(body_context_data, body_data, kSuccess); } TEST(AsyncAwaitErrors) { @@ -7998,14 +8302,9 @@ TEST(AsyncAwaitErrors) { }; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags, - arraysize(always_flags)); - RunParserSyncTest(strict_context_data, strict_error_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); - - RunParserSyncTest(context_data, formal_parameters_data, kError, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(context_data, error_data, kError); + RunParserSyncTest(strict_context_data, strict_error_data, kError); + RunParserSyncTest(context_data, formal_parameters_data, kError); // clang-format off const char* async_body_context_data[][2] = { @@ -8046,8 +8345,7 @@ TEST(AsyncAwaitErrors) { }; // clang-format on - RunParserSyncTest(async_body_context_data, async_body_error_data, kError, - NULL, 0, always_flags, arraysize(always_flags)); + RunParserSyncTest(async_body_context_data, async_body_error_data, kError); } TEST(AsyncAwaitModule) { @@ -8065,9 +8363,8 @@ TEST(AsyncAwaitModule) { }; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, always_flags, - arraysize(always_flags), NULL, 0, false); + RunModuleParserSyncTest(context_data, data, kSuccess, NULL, 0, NULL, 0, NULL, + 0, false); } TEST(AsyncAwaitModuleErrors) { @@ -8087,10 +8384,8 @@ TEST(AsyncAwaitModuleErrors) { }; // clang-format on - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; - RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags), NULL, 0, - false); + RunModuleParserSyncTest(context_data, error_data, kError, NULL, 0, NULL, 0, + NULL, 0, false); } TEST(RestrictiveForInErrors) { @@ -8167,14 +8462,11 @@ TEST(NoDuplicateAsyncFunctionInBlock) { "async function x() {} function* x() {}", "function* x() {} async function x() {}", NULL}; - static const ParserFlag always_flags[] = {kAllowHarmonyAsyncAwait}; // The preparser doesn't enforce the restriction, so turn it off. bool test_preparser = false; - RunParserSyncTest(block_context_data, error_data, kError, NULL, 0, - always_flags, arraysize(always_flags), NULL, 0, false, - test_preparser); - RunParserSyncTest(top_level_context_data, error_data, kSuccess, NULL, 0, - always_flags, arraysize(always_flags)); + RunParserSyncTest(block_context_data, error_data, kError, NULL, 0, NULL, 0, + NULL, 0, false, test_preparser); + RunParserSyncTest(top_level_context_data, error_data, kSuccess); } TEST(TrailingCommasInParameters) { @@ -8315,3 +8607,288 @@ TEST(ArgumentsRedeclaration) { RunParserSyncTest(context_data, data, kSuccess); } } + +namespace v8 { +namespace internal { + +class ScopeTestHelper { + public: + static bool MustAllocateInContext(Variable* var) { + return var->scope()->MustAllocateInContext(var); + } +}; +} // namespace internal +} // namespace v8 + +// Test that lazily parsed inner functions don't result in overly pessimistic +// context allocations. +TEST(NoPessimisticContextAllocation) { + i::FLAG_lazy_inner_functions = true; + i::Isolate* isolate = CcTest::i_isolate(); + i::Factory* factory = isolate->factory(); + i::HandleScope scope(isolate); + LocalContext env; + + const char* prefix = "(function outer() { var my_var; "; + const char* suffix = " })();"; + int prefix_len = Utf8LengthHelper(prefix); + int suffix_len = Utf8LengthHelper(suffix); + + // Test both normal inner functions and inner arrow functions. + const char* inner_functions[] = {"function inner(%s) { %s }", + "(%s) => { %s }"}; + + struct { + const char* params; + const char* source; + bool ctxt_allocate; + } inners[] = { + // Context allocating because we need to: + {"", "my_var;", true}, + {"", "if (true) { let my_var; } my_var;", true}, + {"", "eval(\"foo\");", true}, + {"", "function inner2() { my_var; }", true}, + {"", "function inner2() { eval(\"foo\"); }", true}, + {"", "var {my_var : a} = {my_var};", true}, + {"", "let {my_var : a} = {my_var};", true}, + {"", "const {my_var : a} = {my_var};", true}, + {"a = my_var", "", true}, + {"", "function inner2(a = my_var) { }", true}, + {"", "(a = my_var) => { }", true}, + {"{a} = {a: my_var}", "", true}, + {"", "function inner2({a} = {a: my_var}) { }", true}, + {"", "({a} = {a: my_var}) => { }", true}, + {"[a] = [my_var]", "", true}, + {"", "function inner2([a] = [my_var]) { }", true}, + {"", "([a] = [my_var]) => { }", true}, + {"", "try { } catch (my_var) { } my_var;", true}, + {"", "for (my_var in {}) { my_var; }", true}, + {"", "for (my_var in {}) { }", true}, + {"", "for (my_var of []) { my_var; }", true}, + {"", "for (my_var of []) { }", true}, + {"", "for ([a, my_var, b] in {}) { my_var; }", true}, + {"", "for ([a, my_var, b] of []) { my_var; }", true}, + {"", "for ({x: my_var} in {}) { my_var; }", true}, + {"", "for ({x: my_var} of []) { my_var; }", true}, + {"", "for ({my_var} in {}) { my_var; }", true}, + {"", "for ({my_var} of []) { my_var; }", true}, + {"", "for ({y, x: my_var} in {}) { my_var; }", true}, + {"", "for ({y, x: my_var} of []) { my_var; }", true}, + {"", "for ({a, my_var} in {}) { my_var; }", true}, + {"", "for ({a, my_var} of []) { my_var; }", true}, + {"", "for (let my_var in {}) { } my_var;", true}, + {"", "for (let my_var of []) { } my_var;", true}, + {"", "for (let [a, my_var, b] in {}) { } my_var;", true}, + {"", "for (let [a, my_var, b] of []) { } my_var;", true}, + {"", "for (let {x: my_var} in {}) { } my_var;", true}, + {"", "for (let {x: my_var} of []) { } my_var;", true}, + {"", "for (let {my_var} in {}) { } my_var;", true}, + {"", "for (let {my_var} of []) { } my_var;", true}, + {"", "for (let {y, x: my_var} in {}) { } my_var;", true}, + {"", "for (let {y, x: my_var} of []) { } my_var;", true}, + {"", "for (let {a, my_var} in {}) { } my_var;", true}, + {"", "for (let {a, my_var} of []) { } my_var;", true}, + {"", "for (let my_var = 0; my_var < 1; ++my_var) { } my_var;", true}, + {"", "'use strict'; if (true) { function my_var() {} } my_var;", true}, + {"", + "'use strict'; function inner2() { if (true) { function my_var() {} } " + "my_var; }", + true}, + {"", + "function inner2() { 'use strict'; if (true) { function my_var() {} } " + "my_var; }", + true}, + {"", + "() => { 'use strict'; if (true) { function my_var() {} } my_var; }", + true}, + {"", + "if (true) { let my_var; if (true) { function my_var() {} } } my_var;", + true}, + // No pessimistic context allocation: + {"", "var my_var; my_var;", false}, + {"", "var my_var;", false}, + {"", "var my_var = 0;", false}, + {"", "if (true) { var my_var; } my_var;", false}, + {"", "let my_var; my_var;", false}, + {"", "let my_var;", false}, + {"", "let my_var = 0;", false}, + {"", "const my_var = 0; my_var;", false}, + {"", "const my_var = 0;", false}, + {"", "var [a, my_var] = [1, 2]; my_var;", false}, + {"", "let [a, my_var] = [1, 2]; my_var;", false}, + {"", "const [a, my_var] = [1, 2]; my_var;", false}, + {"", "var {a: my_var} = {a: 3}; my_var;", false}, + {"", "let {a: my_var} = {a: 3}; my_var;", false}, + {"", "const {a: my_var} = {a: 3}; my_var;", false}, + {"", "var {my_var} = {my_var: 3}; my_var;", false}, + {"", "let {my_var} = {my_var: 3}; my_var;", false}, + {"", "const {my_var} = {my_var: 3}; my_var;", false}, + {"my_var", "my_var;", false}, + {"my_var", "", false}, + {"my_var = 5", "my_var;", false}, + {"my_var = 5", "", false}, + {"...my_var", "my_var;", false}, + {"...my_var", "", false}, + {"[a, my_var, b]", "my_var;", false}, + {"[a, my_var, b]", "", false}, + {"[a, my_var, b] = [1, 2, 3]", "my_var;", false}, + {"[a, my_var, b] = [1, 2, 3]", "", false}, + {"{x: my_var}", "my_var;", false}, + {"{x: my_var}", "", false}, + {"{x: my_var} = {x: 0}", "my_var;", false}, + {"{x: my_var} = {x: 0}", "", false}, + {"{my_var}", "my_var;", false}, + {"{my_var}", "", false}, + {"{my_var} = {my_var: 0}", "my_var;", false}, + {"{my_var} = {my_var: 0}", "", false}, + {"", "function inner2(my_var) { my_var; }", false}, + {"", "function inner2(my_var) { }", false}, + {"", "function inner2(my_var = 5) { my_var; }", false}, + {"", "function inner2(my_var = 5) { }", false}, + {"", "function inner2(...my_var) { my_var; }", false}, + {"", "function inner2(...my_var) { }", false}, + {"", "function inner2([a, my_var, b]) { my_var; }", false}, + {"", "function inner2([a, my_var, b]) { }", false}, + {"", "function inner2([a, my_var, b] = [1, 2, 3]) { my_var; }", false}, + {"", "function inner2([a, my_var, b] = [1, 2, 3]) { }", false}, + {"", "function inner2({x: my_var}) { my_var; }", false}, + {"", "function inner2({x: my_var}) { }", false}, + {"", "function inner2({x: my_var} = {x: 0}) { my_var; }", false}, + {"", "function inner2({x: my_var} = {x: 0}) { }", false}, + {"", "function inner2({my_var}) { my_var; }", false}, + {"", "function inner2({my_var}) { }", false}, + {"", "function inner2({my_var} = {my_var: 8}) { my_var; } ", false}, + {"", "function inner2({my_var} = {my_var: 8}) { }", false}, + {"", "my_var => my_var;", false}, + {"", "my_var => { }", false}, + {"", "(my_var = 5) => my_var;", false}, + {"", "(my_var = 5) => { }", false}, + {"", "(...my_var) => my_var;", false}, + {"", "(...my_var) => { }", false}, + {"", "([a, my_var, b]) => my_var;", false}, + {"", "([a, my_var, b]) => { }", false}, + {"", "([a, my_var, b] = [1, 2, 3]) => my_var;", false}, + {"", "([a, my_var, b] = [1, 2, 3]) => { }", false}, + {"", "({x: my_var}) => my_var;", false}, + {"", "({x: my_var}) => { }", false}, + {"", "({x: my_var} = {x: 0}) => my_var;", false}, + {"", "({x: my_var} = {x: 0}) => { }", false}, + {"", "({my_var}) => my_var;", false}, + {"", "({my_var}) => { }", false}, + {"", "({my_var} = {my_var: 5}) => my_var;", false}, + {"", "({my_var} = {my_var: 5}) => { }", false}, + {"", "({a, my_var}) => my_var;", false}, + {"", "({a, my_var}) => { }", false}, + {"", "({a, my_var} = {a: 0, my_var: 5}) => my_var;", false}, + {"", "({a, my_var} = {a: 0, my_var: 5}) => { }", false}, + {"", "({y, x: my_var}) => my_var;", false}, + {"", "({y, x: my_var}) => { }", false}, + {"", "({y, x: my_var} = {y: 0, x: 0}) => my_var;", false}, + {"", "({y, x: my_var} = {y: 0, x: 0}) => { }", false}, + {"", "try { } catch (my_var) { my_var; }", false}, + {"", "try { } catch ([a, my_var, b]) { my_var; }", false}, + {"", "try { } catch ({x: my_var}) { my_var; }", false}, + {"", "try { } catch ({y, x: my_var}) { my_var; }", false}, + {"", "try { } catch ({my_var}) { my_var; }", false}, + {"", "for (let my_var in {}) { my_var; }", false}, + {"", "for (let my_var in {}) { }", false}, + {"", "for (let my_var of []) { my_var; }", false}, + {"", "for (let my_var of []) { }", false}, + {"", "for (let [a, my_var, b] in {}) { my_var; }", false}, + {"", "for (let [a, my_var, b] of []) { my_var; }", false}, + {"", "for (let {x: my_var} in {}) { my_var; }", false}, + {"", "for (let {x: my_var} of []) { my_var; }", false}, + {"", "for (let {my_var} in {}) { my_var; }", false}, + {"", "for (let {my_var} of []) { my_var; }", false}, + {"", "for (let {y, x: my_var} in {}) { my_var; }", false}, + {"", "for (let {y, x: my_var} of []) { my_var; }", false}, + {"", "for (let {a, my_var} in {}) { my_var; }", false}, + {"", "for (let {a, my_var} of []) { my_var; }", false}, + {"", "for (var my_var in {}) { my_var; }", false}, + {"", "for (var my_var in {}) { }", false}, + {"", "for (var my_var of []) { my_var; }", false}, + {"", "for (var my_var of []) { }", false}, + {"", "for (var [a, my_var, b] in {}) { my_var; }", false}, + {"", "for (var [a, my_var, b] of []) { my_var; }", false}, + {"", "for (var {x: my_var} in {}) { my_var; }", false}, + {"", "for (var {x: my_var} of []) { my_var; }", false}, + {"", "for (var {my_var} in {}) { my_var; }", false}, + {"", "for (var {my_var} of []) { my_var; }", false}, + {"", "for (var {y, x: my_var} in {}) { my_var; }", false}, + {"", "for (var {y, x: my_var} of []) { my_var; }", false}, + {"", "for (var {a, my_var} in {}) { my_var; }", false}, + {"", "for (var {a, my_var} of []) { my_var; }", false}, + {"", "for (var my_var in {}) { } my_var;", false}, + {"", "for (var my_var of []) { } my_var;", false}, + {"", "for (var [a, my_var, b] in {}) { } my_var;", false}, + {"", "for (var [a, my_var, b] of []) { } my_var;", false}, + {"", "for (var {x: my_var} in {}) { } my_var;", false}, + {"", "for (var {x: my_var} of []) { } my_var;", false}, + {"", "for (var {my_var} in {}) { } my_var;", false}, + {"", "for (var {my_var} of []) { } my_var;", false}, + {"", "for (var {y, x: my_var} in {}) { } my_var;", false}, + {"", "for (var {y, x: my_var} of []) { } my_var;", false}, + {"", "for (var {a, my_var} in {}) { } my_var;", false}, + {"", "for (var {a, my_var} of []) { } my_var;", false}, + {"", "for (let my_var = 0; my_var < 1; ++my_var) { my_var; }", false}, + {"", "for (var my_var = 0; my_var < 1; ++my_var) { my_var; }", false}, + {"", "for (var my_var = 0; my_var < 1; ++my_var) { } my_var; ", false}, + {"", "for (let a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }", + false}, + {"", "for (var a = 0, my_var = 0; my_var < 1; ++my_var) { my_var }", + false}, + {"", "class my_var {}; my_var; ", false}, + {"", "function my_var() {} my_var;", false}, + {"", "if (true) { function my_var() {} } my_var;", false}, + {"", "function inner2() { if (true) { function my_var() {} } my_var; }", + false}, + {"", "() => { if (true) { function my_var() {} } my_var; }", false}, + {"", + "if (true) { var my_var; if (true) { function my_var() {} } } my_var;", + false}, + }; + + for (unsigned inner_ix = 0; inner_ix < arraysize(inner_functions); + ++inner_ix) { + const char* inner_function = inner_functions[inner_ix]; + int inner_function_len = Utf8LengthHelper(inner_function) - 4; + + for (unsigned i = 0; i < arraysize(inners); ++i) { + int params_len = Utf8LengthHelper(inners[i].params); + int source_len = Utf8LengthHelper(inners[i].source); + int len = prefix_len + inner_function_len + params_len + source_len + + suffix_len; + + i::ScopedVector<char> program(len + 1); + i::SNPrintF(program, "%s", prefix); + i::SNPrintF(program + prefix_len, inner_function, inners[i].params, + inners[i].source); + i::SNPrintF( + program + prefix_len + inner_function_len + params_len + source_len, + "%s", suffix); + + i::Handle<i::String> source = + factory->InternalizeUtf8String(program.start()); + source->PrintOn(stdout); + printf("\n"); + + i::Handle<i::Script> script = factory->NewScript(source); + i::Zone zone(isolate->allocator(), ZONE_NAME); + i::ParseInfo info(&zone, script); + + CHECK(i::parsing::ParseProgram(&info)); + CHECK(i::Compiler::Analyze(&info)); + CHECK(info.literal() != NULL); + + i::Scope* scope = info.literal()->scope()->inner_scope(); + DCHECK_NOT_NULL(scope); + DCHECK_NULL(scope->sibling()); + DCHECK(scope->is_function_scope()); + const i::AstRawString* var_name = + info.ast_value_factory()->GetOneByteString("my_var"); + i::Variable* var = scope->Lookup(var_name); + CHECK_EQ(inners[i].ctxt_allocate, + i::ScopeTestHelper::MustAllocateInContext(var)); + } + } +} diff --git a/deps/v8/test/cctest/test-profile-generator.cc b/deps/v8/test/cctest/test-profile-generator.cc index b7aba6e9da..71728924db 100644 --- a/deps/v8/test/cctest/test-profile-generator.cc +++ b/deps/v8/test/cctest/test-profile-generator.cc @@ -29,6 +29,7 @@ #include "include/v8-profiler.h" #include "src/api.h" +#include "src/objects-inl.h" #include "src/profiler/cpu-profiler.h" #include "src/profiler/profile-generator-inl.h" #include "src/v8.h" diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc index a9d941d998..ee6a6c2ab7 100644 --- a/deps/v8/test/cctest/test-regexp.cc +++ b/deps/v8/test/cctest/test-regexp.cc @@ -34,10 +34,11 @@ #include "src/ast/ast.h" #include "src/char-predicates-inl.h" +#include "src/objects-inl.h" #include "src/ostreams.h" #include "src/regexp/jsregexp.h" -#include "src/regexp/regexp-macro-assembler.h" #include "src/regexp/regexp-macro-assembler-irregexp.h" +#include "src/regexp/regexp-macro-assembler.h" #include "src/regexp/regexp-parser.h" #include "src/splay-tree-inl.h" #include "src/string-stream.h" diff --git a/deps/v8/test/cctest/test-serialize.cc b/deps/v8/test/cctest/test-serialize.cc index 1b5497f772..9644d09624 100644 --- a/deps/v8/test/cctest/test-serialize.cc +++ b/deps/v8/test/cctest/test-serialize.cc @@ -285,8 +285,9 @@ static void PartiallySerializeObject(Vector<const byte>* startup_blob_out, isolate, v8::SnapshotCreator::FunctionCodeHandling::kClear); startup_serializer.SerializeStrongReferences(); - PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); - partial_serializer.Serialize(&raw_foo); + PartialSerializer partial_serializer(isolate, &startup_serializer, + v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&raw_foo, false); startup_serializer.SerializeWeakReferencesAndDeferred(); @@ -321,7 +322,9 @@ UNINITIALIZED_TEST(PartialSerializerObject) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root = deserializer.DeserializePartial(isolate, global_proxy) + root = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root->IsString()); } @@ -330,7 +333,9 @@ UNINITIALIZED_TEST(PartialSerializerObject) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root2 = deserializer.DeserializePartial(isolate, global_proxy) + root2 = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root2->IsString()); CHECK(root.is_identical_to(root2)); @@ -385,8 +390,9 @@ static void PartiallySerializeContext(Vector<const byte>* startup_blob_out, startup_serializer.SerializeStrongReferences(); SnapshotByteSink partial_sink; - PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); - partial_serializer.Serialize(&raw_context); + PartialSerializer partial_serializer(isolate, &startup_serializer, + v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&raw_context, false); startup_serializer.SerializeWeakReferencesAndDeferred(); SnapshotData startup_snapshot(&startup_serializer); @@ -419,7 +425,9 @@ UNINITIALIZED_TEST(PartialSerializerContext) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root = deserializer.DeserializePartial(isolate, global_proxy) + root = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root->IsContext()); CHECK(Handle<Context>::cast(root)->global_proxy() == *global_proxy); @@ -429,7 +437,9 @@ UNINITIALIZED_TEST(PartialSerializerContext) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root2 = deserializer.DeserializePartial(isolate, global_proxy) + root2 = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root2->IsContext()); CHECK(!root.is_identical_to(root2)); @@ -505,8 +515,9 @@ static void PartiallySerializeCustomContext( startup_serializer.SerializeStrongReferences(); SnapshotByteSink partial_sink; - PartialSerializer partial_serializer(isolate, &startup_serializer, nullptr); - partial_serializer.Serialize(&raw_context); + PartialSerializer partial_serializer(isolate, &startup_serializer, + v8::SerializeInternalFieldsCallback()); + partial_serializer.Serialize(&raw_context, false); startup_serializer.SerializeWeakReferencesAndDeferred(); SnapshotData startup_snapshot(&startup_serializer); @@ -539,7 +550,9 @@ UNINITIALIZED_TEST(PartialSerializerCustomContext) { { SnapshotData snapshot_data(partial_blob); Deserializer deserializer(&snapshot_data); - root = deserializer.DeserializePartial(isolate, global_proxy) + root = deserializer + .DeserializePartial(isolate, global_proxy, + v8::DeserializeInternalFieldsCallback()) .ToHandleChecked(); CHECK(root->IsContext()); Handle<Context> context = Handle<Context>::cast(root); @@ -1075,7 +1088,7 @@ TEST(CodeSerializerLargeCodeObject) { Vector<const uint8_t> source = ConstructSource(STATIC_CHAR_VECTOR("var j=1; if (j == 0) {"), STATIC_CHAR_VECTOR("for (let i of Object.prototype);"), - STATIC_CHAR_VECTOR("} j=7; j"), 1000); + STATIC_CHAR_VECTOR("} j=7; j"), 1050); Handle<String> source_str = isolate->factory()->NewStringFromOneByte(source).ToHandleChecked(); @@ -1771,7 +1784,6 @@ TEST(CodeSerializerEagerCompilationAndPreAge) { FLAG_serialize_toplevel = true; FLAG_serialize_age_code = true; FLAG_serialize_eager = true; - FLAG_min_preparse_length = 1; static const char* source = "function f() {" @@ -1807,10 +1819,10 @@ TEST(CodeSerializerEagerCompilationAndPreAge) { HandleScope i_scope(i_isolate); Handle<SharedFunctionInfo> toplevel = v8::Utils::OpenHandle(*unbound); Handle<Script> script(Script::cast(toplevel->script())); - WeakFixedArray::Iterator iterator(script->shared_function_infos()); // Every function has been pre-compiled from the code cache. int count = 0; - while (SharedFunctionInfo* shared = iterator.Next<SharedFunctionInfo>()) { + SharedFunctionInfo::ScriptIterator iterator(script); + while (SharedFunctionInfo* shared = iterator.Next()) { CHECK(shared->is_compiled()); CHECK_EQ(Code::kPreAgedCodeAge, shared->code()->GetAge()); count++; @@ -1821,6 +1833,7 @@ TEST(CodeSerializerEagerCompilationAndPreAge) { } TEST(Regress503552) { + if (!FLAG_incremental_marking) return; // Test that the code serializer can deal with weak cells that form a linked // list during incremental marking. CcTest::InitializeVM(); @@ -1962,19 +1975,19 @@ TEST(SnapshotCreatorMultipleContexts) { v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); CompileRun("var f = function() { return 1; }"); - CHECK_EQ(0u, creator.AddContext(context)); + creator.SetDefaultContext(context); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); CompileRun("var f = function() { return 2; }"); - CHECK_EQ(1u, creator.AddContext(context)); + CHECK_EQ(0u, creator.AddContext(context)); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = v8::Context::New(isolate); - CHECK_EQ(2u, creator.AddContext(context)); + CHECK_EQ(1u, creator.AddContext(context)); } blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); @@ -1988,22 +2001,21 @@ TEST(SnapshotCreatorMultipleContexts) { v8::Isolate::Scope isolate_scope(isolate); { v8::HandleScope handle_scope(isolate); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); ExpectInt32("f()", 1); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 1).ToLocalChecked(); + v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); v8::Context::Scope context_scope(context); ExpectInt32("f()", 2); } { v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 2).ToLocalChecked(); + v8::Context::FromSnapshot(isolate, 1).ToLocalChecked(); v8::Context::Scope context_scope(context); ExpectUndefined("this.f"); } @@ -2013,24 +2025,68 @@ TEST(SnapshotCreatorMultipleContexts) { delete[] blob.data; } -void SerializedCallback(const v8::FunctionCallbackInfo<v8::Value>& args) { +static void SerializedCallback( + const v8::FunctionCallbackInfo<v8::Value>& args) { args.GetReturnValue().Set(v8_num(42)); } -void SerializedCallbackReplacement( +static void SerializedCallbackReplacement( const v8::FunctionCallbackInfo<v8::Value>& args) { args.GetReturnValue().Set(v8_num(1337)); } +static void NamedPropertyGetterForSerialization( + v8::Local<v8::Name> name, const v8::PropertyCallbackInfo<v8::Value>& info) { + if (name->Equals(info.GetIsolate()->GetCurrentContext(), v8_str("x")) + .FromJust()) { + info.GetReturnValue().Set(v8_num(2016)); + } +} + +static void AccessorForSerialization( + v8::Local<v8::String> property, + const v8::PropertyCallbackInfo<v8::Value>& info) { + info.GetReturnValue().Set(v8_num(2017)); +} + static int serialized_static_field = 314; +class SerializedExtension : public v8::Extension { + public: + SerializedExtension() + : v8::Extension("serialized extension", + "native function g();" + "function h() { return 13; };" + "function i() { return 14; };" + "var o = { p: 7 };") {} + + virtual v8::Local<v8::FunctionTemplate> GetNativeFunctionTemplate( + v8::Isolate* isolate, v8::Local<v8::String> name) { + CHECK(name->Equals(isolate->GetCurrentContext(), v8_str("g")).FromJust()); + return v8::FunctionTemplate::New(isolate, FunctionCallback); + } + + static void FunctionCallback( + const v8::FunctionCallbackInfo<v8::Value>& args) { + args.GetReturnValue().Set(v8_num(12)); + } +}; + intptr_t original_external_references[] = { reinterpret_cast<intptr_t>(SerializedCallback), - reinterpret_cast<intptr_t>(&serialized_static_field), 0}; + reinterpret_cast<intptr_t>(&serialized_static_field), + reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization), + reinterpret_cast<intptr_t>(&AccessorForSerialization), + reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback), + 0}; intptr_t replaced_external_references[] = { reinterpret_cast<intptr_t>(SerializedCallbackReplacement), - reinterpret_cast<intptr_t>(&serialized_static_field), 0}; + reinterpret_cast<intptr_t>(&serialized_static_field), + reinterpret_cast<intptr_t>(&NamedPropertyGetterForSerialization), + reinterpret_cast<intptr_t>(&AccessorForSerialization), + reinterpret_cast<intptr_t>(&SerializedExtension::FunctionCallback), + 0}; TEST(SnapshotCreatorExternalReferences) { DisableAlwaysOpt(); @@ -2048,7 +2104,7 @@ TEST(SnapshotCreatorExternalReferences) { callback->GetFunction(context).ToLocalChecked(); CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust()); ExpectInt32("f()", 42); - CHECK_EQ(0u, creator.AddContext(context)); + creator.SetDefaultContext(context); } blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); @@ -2064,8 +2120,7 @@ TEST(SnapshotCreatorExternalReferences) { { v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); ExpectInt32("f()", 42); } @@ -2082,8 +2137,7 @@ TEST(SnapshotCreatorExternalReferences) { { v8::Isolate::Scope isolate_scope(isolate); v8::HandleScope handle_scope(isolate); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); ExpectInt32("f()", 1337); } @@ -2108,7 +2162,7 @@ TEST(SnapshotCreatorUnknownExternalReferences) { CHECK(context->Global()->Set(context, v8_str("f"), function).FromJust()); ExpectInt32("f()", 42); - CHECK_EQ(0u, creator.AddContext(context)); + creator.SetDefaultContext(context); } v8::StartupData blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); @@ -2120,22 +2174,27 @@ struct InternalFieldData { uint32_t data; }; -v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, - int index) { - InternalFieldData* data = static_cast<InternalFieldData*>( +v8::StartupData SerializeInternalFields(v8::Local<v8::Object> holder, int index, + void* data) { + CHECK_EQ(reinterpret_cast<void*>(2016), data); + InternalFieldData* internal_field = static_cast<InternalFieldData*>( holder->GetAlignedPointerFromInternalField(index)); - int size = sizeof(*data); + int size = sizeof(*internal_field); char* payload = new char[size]; // We simply use memcpy to serialize the content. - memcpy(payload, data, size); + memcpy(payload, internal_field, size); return {payload, size}; } +std::vector<InternalFieldData*> deserialized_data; + void DeserializeInternalFields(v8::Local<v8::Object> holder, int index, - v8::StartupData payload) { - InternalFieldData* data = new InternalFieldData{0}; - memcpy(data, payload.data, payload.raw_size); - holder->SetAlignedPointerInInternalField(index, data); + v8::StartupData payload, void* data) { + CHECK_EQ(reinterpret_cast<void*>(2017), data); + InternalFieldData* internal_field = new InternalFieldData{0}; + memcpy(internal_field, payload.data, payload.raw_size); + holder->SetAlignedPointerInInternalField(index, internal_field); + deserialized_data.push_back(internal_field); } TEST(SnapshotCreatorTemplates) { @@ -2159,6 +2218,8 @@ TEST(SnapshotCreatorTemplates) { global_template->Set(v8_str("f"), callback); v8::Local<v8::Context> context = v8::Context::New(isolate, no_extension, global_template); + creator.SetDefaultContext(context); + context = v8::Context::New(isolate, no_extension, global_template); v8::Local<v8::ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate); object_template->SetInternalFieldCount(3); @@ -2185,12 +2246,15 @@ TEST(SnapshotCreatorTemplates) { c->SetInternalField(2, field_external); CHECK(context->Global()->Set(context, v8_str("a"), a).FromJust()); - CHECK_EQ(0u, creator.AddContext(context)); + CHECK_EQ(0u, + creator.AddContext(context, v8::SerializeInternalFieldsCallback( + SerializeInternalFields, + reinterpret_cast<void*>(2016)))); CHECK_EQ(0u, creator.AddTemplate(callback)); CHECK_EQ(1u, creator.AddTemplate(global_template)); } - blob = creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear, - SerializeInternalFields); + blob = + creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); delete a1; delete b0; @@ -2202,7 +2266,6 @@ TEST(SnapshotCreatorTemplates) { params.snapshot_blob = &blob; params.array_buffer_allocator = CcTest::array_buffer_allocator(); params.external_references = original_external_references; - params.deserialize_internal_fields_callback = DeserializeInternalFields; v8::Isolate* isolate = v8::Isolate::New(params); { v8::Isolate::Scope isolate_scope(isolate); @@ -2210,7 +2273,11 @@ TEST(SnapshotCreatorTemplates) { // Create a new context without a new object template. v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0).ToLocalChecked(); + v8::Context::FromSnapshot( + isolate, 0, + v8::DeserializeInternalFieldsCallback( + DeserializeInternalFields, reinterpret_cast<void*>(2017))) + .ToLocalChecked(); v8::Context::Scope context_scope(context); ExpectInt32("f()", 42); @@ -2272,29 +2339,208 @@ TEST(SnapshotCreatorTemplates) { // Accessing out of bound returns empty MaybeHandle. CHECK(v8::ObjectTemplate::FromSnapshot(isolate, 2).IsEmpty()); CHECK(v8::FunctionTemplate::FromSnapshot(isolate, 2).IsEmpty()); - CHECK(v8::Context::FromSnapshot(isolate, 2).IsEmpty()); + CHECK(v8::Context::FromSnapshot(isolate, 1).IsEmpty()); - delete a1; - delete b0; - delete c0; + for (auto data : deserialized_data) delete data; + deserialized_data.clear(); } + } + isolate->Dispose(); + } + delete[] blob.data; +} + +TEST(SnapshotCreatorIncludeGlobalProxy) { + DisableAlwaysOpt(); + v8::StartupData blob; + + { + v8::SnapshotCreator creator(original_external_references); + v8::Isolate* isolate = creator.GetIsolate(); + v8::RegisterExtension(new SerializedExtension); + const char* extension_names[] = {"serialized extension"}; + v8::ExtensionConfiguration extensions(1, extension_names); + { + // Set default context. This context implicitly does *not* serialize + // the global proxy, and upon deserialization one has to be created + // in the bootstrapper from the global object template. + // Side effects from extensions are persisted though. + v8::HandleScope handle_scope(isolate); + v8::Local<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(isolate); + v8::Local<v8::FunctionTemplate> callback = + v8::FunctionTemplate::New(isolate, SerializedCallback); + global_template->Set(v8_str("f"), callback); + global_template->SetHandler(v8::NamedPropertyHandlerConfiguration( + NamedPropertyGetterForSerialization)); + v8::Local<v8::Context> context = + v8::Context::New(isolate, &extensions, global_template); + v8::Context::Scope context_scope(context); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("o.p", 7); + ExpectInt32("x", 2016); + creator.SetDefaultContext(context); + } + { + // Add additional context. This context implicitly *does* serialize + // the global proxy, and upon deserialization one has to be created + // in the bootstrapper from the global object template. + // Side effects from extensions are persisted. + v8::HandleScope handle_scope(isolate); + v8::Local<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(isolate); + v8::Local<v8::FunctionTemplate> callback = + v8::FunctionTemplate::New(isolate, SerializedCallback); + global_template->SetInternalFieldCount(3); + global_template->Set(v8_str("f"), callback); + global_template->SetHandler(v8::NamedPropertyHandlerConfiguration( + NamedPropertyGetterForSerialization)); + global_template->SetAccessor(v8_str("y"), AccessorForSerialization); + v8::Local<v8::Private> priv = + v8::Private::ForApi(isolate, v8_str("cached")); + global_template->SetAccessorProperty( + v8_str("cached"), + v8::FunctionTemplate::NewWithCache(isolate, SerializedCallback, priv, + v8::Local<v8::Value>())); + v8::Local<v8::Context> context = + v8::Context::New(isolate, &extensions, global_template); + v8::Context::Scope context_scope(context); + + CHECK(context->Global() + ->SetPrivate(context, priv, v8_str("cached string")) + .FromJust()); + v8::Local<v8::Private> hidden = + v8::Private::ForApi(isolate, v8_str("hidden")); + CHECK(context->Global() + ->SetPrivate(context, hidden, v8_str("hidden string")) + .FromJust()); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("o.p", 7); + ExpectInt32("x", 2016); + ExpectInt32("y", 2017); + CHECK(v8_str("hidden string") + ->Equals(context, context->Global() + ->GetPrivate(context, hidden) + .ToLocalChecked()) + .FromJust()); + + CHECK_EQ(0u, + creator.AddContext(context, v8::SerializeInternalFieldsCallback( + SerializeInternalFields, + reinterpret_cast<void*>(2016)))); + } + blob = + creator.CreateBlob(v8::SnapshotCreator::FunctionCodeHandling::kClear); + } + + { + v8::Isolate::CreateParams params; + params.snapshot_blob = &blob; + params.array_buffer_allocator = CcTest::array_buffer_allocator(); + params.external_references = original_external_references; + v8::Isolate* isolate = v8::Isolate::New(params); + { + v8::Isolate::Scope isolate_scope(isolate); + // We can introduce new extensions, which could override the already + // snapshotted extension. + v8::Extension* extension = new v8::Extension("new extension", + "function i() { return 24; }" + "function j() { return 25; }" + "if (o.p == 7) o.p++;"); + extension->set_auto_enable(true); + v8::RegisterExtension(extension); { - // Create a context with a new object template. It is merged into the - // deserialized global object. + // Create a new context from default context snapshot. This will + // create a new global object from a new global object template + // without the interceptor. v8::HandleScope handle_scope(isolate); - v8::ExtensionConfiguration* no_extension = nullptr; - v8::Local<v8::ObjectTemplate> global_template = - v8::ObjectTemplate::New(isolate); - global_template->Set( - v8_str("g"), - v8::FunctionTemplate::New(isolate, SerializedCallbackReplacement)); - v8::Local<v8::Context> context = - v8::Context::FromSnapshot(isolate, 0, no_extension, global_template) - .ToLocalChecked(); + v8::Local<v8::Context> context = v8::Context::New(isolate); v8::Context::Scope context_scope(context); - ExpectInt32("g()", 1337); ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("i()", 24); + ExpectInt32("j()", 25); + ExpectInt32("o.p", 8); + v8::TryCatch try_catch(isolate); + CHECK(CompileRun("x").IsEmpty()); + CHECK(try_catch.HasCaught()); + } + { + // Create a new context from first additional context snapshot. This + // will use the global object from the snapshot, including interceptor. + v8::HandleScope handle_scope(isolate); + v8::Local<v8::Context> context = + v8::Context::FromSnapshot( + isolate, 0, + v8::DeserializeInternalFieldsCallback( + DeserializeInternalFields, reinterpret_cast<void*>(2017))) + .ToLocalChecked(); + + { + v8::Context::Scope context_scope(context); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("i()", 24); + ExpectInt32("j()", 25); + ExpectInt32("o.p", 8); + ExpectInt32("x", 2016); + v8::Local<v8::Private> hidden = + v8::Private::ForApi(isolate, v8_str("hidden")); + CHECK(v8_str("hidden string") + ->Equals(context, context->Global() + ->GetPrivate(context, hidden) + .ToLocalChecked()) + .FromJust()); + ExpectString("cached", "cached string"); + } + + v8::Local<v8::Object> global = context->Global(); + CHECK_EQ(3, global->InternalFieldCount()); + context->DetachGlobal(); + + // New context, but reuse global proxy. + v8::ExtensionConfiguration* no_extensions = nullptr; + v8::Local<v8::Context> context2 = + v8::Context::FromSnapshot( + isolate, 0, + v8::DeserializeInternalFieldsCallback( + DeserializeInternalFields, reinterpret_cast<void*>(2017)), + no_extensions, global) + .ToLocalChecked(); + { + v8::Context::Scope context_scope(context2); + ExpectInt32("f()", 42); + ExpectInt32("g()", 12); + ExpectInt32("h()", 13); + ExpectInt32("i()", 24); + ExpectInt32("j()", 25); + ExpectInt32("o.p", 8); + ExpectInt32("x", 2016); + v8::Local<v8::Private> hidden = + v8::Private::ForApi(isolate, v8_str("hidden")); + CHECK(v8_str("hidden string") + ->Equals(context2, context2->Global() + ->GetPrivate(context2, hidden) + .ToLocalChecked()) + .FromJust()); + + // Set cached accessor property again. + v8::Local<v8::Private> priv = + v8::Private::ForApi(isolate, v8_str("cached")); + CHECK(context2->Global() + ->SetPrivate(context2, priv, v8_str("cached string 1")) + .FromJust()); + ExpectString("cached", "cached string 1"); + } + + CHECK(context2->Global()->Equals(context2, global).FromJust()); } } isolate->Dispose(); diff --git a/deps/v8/test/cctest/test-strings.cc b/deps/v8/test/cctest/test-strings.cc index 80c8f92ac4..d7b51f8274 100644 --- a/deps/v8/test/cctest/test-strings.cc +++ b/deps/v8/test/cctest/test-strings.cc @@ -37,6 +37,7 @@ #include "src/api.h" #include "src/factory.h" #include "src/messages.h" +#include "src/objects-inl.h" #include "src/objects.h" #include "src/unicode-decoder.h" #include "test/cctest/cctest.h" @@ -1608,3 +1609,38 @@ TEST(Regress609831) { CHECK(v8::Utils::OpenHandle(*result)->IsSeqTwoByteString()); } } + +TEST(ExternalStringIndexOf) { + CcTest::InitializeVM(); + LocalContext context; + v8::HandleScope scope(CcTest::isolate()); + + const char* raw_string = "abcdefghijklmnopqrstuvwxyz"; + v8::Local<v8::String> string = + v8::String::NewExternalOneByte(CcTest::isolate(), + new StaticOneByteResource(raw_string)) + .ToLocalChecked(); + v8::Local<v8::Object> global = context->Global(); + global->Set(context.local(), v8_str("external"), string).FromJust(); + + char source[] = "external.indexOf('%')"; + for (size_t i = 0; i < strlen(raw_string); i++) { + source[18] = raw_string[i]; + int result_position = static_cast<int>(i); + CHECK_EQ(result_position, + CompileRun(source)->Int32Value(context.local()).FromJust()); + } + CHECK_EQ(-1, + CompileRun("external.indexOf('abcdefghijklmnopqrstuvwxyz%%%%%%')") + ->Int32Value(context.local()) + .FromJust()); + CHECK_EQ(1, CompileRun("external.indexOf('', 1)") + ->Int32Value(context.local()) + .FromJust()); + CHECK_EQ(-1, CompileRun("external.indexOf('a', 1)") + ->Int32Value(context.local()) + .FromJust()); + CHECK_EQ(-1, CompileRun("external.indexOf('$')") + ->Int32Value(context.local()) + .FromJust()); +} diff --git a/deps/v8/test/cctest/test-thread-termination.cc b/deps/v8/test/cctest/test-thread-termination.cc index 523704ba69..d288eb7242 100644 --- a/deps/v8/test/cctest/test-thread-termination.cc +++ b/deps/v8/test/cctest/test-thread-termination.cc @@ -27,6 +27,7 @@ #include "src/api.h" #include "src/isolate.h" +#include "src/objects-inl.h" #include "src/v8.h" #include "test/cctest/cctest.h" @@ -529,9 +530,11 @@ void InnerTryCallTerminate(const v8::FunctionCallbackInfo<v8::Value>& args) { v8::Local<v8::Function> loop = v8::Local<v8::Function>::Cast( global->Get(CcTest::isolate()->GetCurrentContext(), v8_str("loop")) .ToLocalChecked()); + i::MaybeHandle<i::Object> exception; i::MaybeHandle<i::Object> result = i::Execution::TryCall(CcTest::i_isolate(), v8::Utils::OpenHandle((*loop)), - v8::Utils::OpenHandle((*global)), 0, NULL, NULL); + v8::Utils::OpenHandle((*global)), 0, nullptr, + i::Execution::MessageHandling::kReport, &exception); CHECK(result.is_null()); // TryCall ignores terminate execution, but rerequests the interrupt. CHECK(!args.GetIsolate()->IsExecutionTerminating()); diff --git a/deps/v8/test/cctest/test-transitions.cc b/deps/v8/test/cctest/test-transitions.cc index 2f00900057..842a6ca47f 100644 --- a/deps/v8/test/cctest/test-transitions.cc +++ b/deps/v8/test/cctest/test-transitions.cc @@ -25,25 +25,6 @@ using namespace v8::internal; // Helper functions. // -static void CheckPropertyDetailsFieldsConsistency(PropertyType type, - PropertyKind kind, - PropertyLocation location) { - int type_value = PropertyDetails::TypeField::encode(type); - int kind_location_value = PropertyDetails::KindField::encode(kind) | - PropertyDetails::LocationField::encode(location); - CHECK_EQ(type_value, kind_location_value); -} - - -TEST(PropertyDetailsFieldsConsistency) { - CheckPropertyDetailsFieldsConsistency(DATA, kData, kField); - CheckPropertyDetailsFieldsConsistency(DATA_CONSTANT, kData, kDescriptor); - CheckPropertyDetailsFieldsConsistency(ACCESSOR, kAccessor, kField); - CheckPropertyDetailsFieldsConsistency(ACCESSOR_CONSTANT, kAccessor, - kDescriptor); -} - - TEST(TransitionArray_SimpleFieldTransitions) { CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); diff --git a/deps/v8/test/cctest/test-typedarrays.cc b/deps/v8/test/cctest/test-typedarrays.cc index 348eb05a3a..10b20acfa1 100644 --- a/deps/v8/test/cctest/test-typedarrays.cc +++ b/deps/v8/test/cctest/test-typedarrays.cc @@ -9,6 +9,7 @@ #include "src/api.h" #include "src/heap/heap.h" +#include "src/objects-inl.h" #include "src/objects.h" using namespace v8::internal; diff --git a/deps/v8/test/cctest/test-unboxed-doubles.cc b/deps/v8/test/cctest/test-unboxed-doubles.cc index abaa058f85..582e2757fb 100644 --- a/deps/v8/test/cctest/test-unboxed-doubles.cc +++ b/deps/v8/test/cctest/test-unboxed-doubles.cc @@ -106,13 +106,14 @@ static Handle<DescriptorArray> CreateDescriptorArray(Isolate* isolate, TestPropertyKind kind = props[i]; if (kind == PROP_CONSTANT) { - DataConstantDescriptor d(name, func, NONE); + Descriptor d = Descriptor::DataConstant(name, func, NONE); descriptors->Append(&d); } else { - DataDescriptor f(name, next_field_offset, NONE, representations[kind]); - next_field_offset += f.GetDetails().field_width_in_words(); - descriptors->Append(&f); + Descriptor d = Descriptor::DataField(name, next_field_offset, NONE, + representations[kind]); + next_field_offset += d.GetDetails().field_width_in_words(); + descriptors->Append(&d); } } return descriptors; @@ -628,18 +629,19 @@ static Handle<LayoutDescriptor> TestLayoutDescriptorAppend( Handle<LayoutDescriptor> layout_descriptor; TestPropertyKind kind = props[i]; if (kind == PROP_CONSTANT) { - DataConstantDescriptor d(name, func, NONE); + Descriptor d = Descriptor::DataConstant(name, func, NONE); layout_descriptor = LayoutDescriptor::ShareAppend(map, d.GetDetails()); descriptors->Append(&d); } else { - DataDescriptor f(name, next_field_offset, NONE, representations[kind]); - int field_width_in_words = f.GetDetails().field_width_in_words(); + Descriptor d = Descriptor::DataField(name, next_field_offset, NONE, + representations[kind]); + int field_width_in_words = d.GetDetails().field_width_in_words(); next_field_offset += field_width_in_words; - layout_descriptor = LayoutDescriptor::ShareAppend(map, f.GetDetails()); - descriptors->Append(&f); + layout_descriptor = LayoutDescriptor::ShareAppend(map, d.GetDetails()); + descriptors->Append(&d); - int field_index = f.GetDetails().field_index(); + int field_index = d.GetDetails().field_index(); bool is_inobject = field_index < map->GetInObjectProperties(); for (int bit = 0; bit < field_width_in_words; bit++) { CHECK_EQ(is_inobject && (kind == PROP_DOUBLE), @@ -783,7 +785,7 @@ static Handle<LayoutDescriptor> TestLayoutDescriptorAppendIfFastOrUseFull( CHECK_EQ(*full_layout_descriptor, layout_desc); } else { CHECK(!switched_to_slow_mode); - if (details.type() == DATA) { + if (details.location() == kField) { nof++; int field_index = details.field_index(); int field_width_in_words = details.field_width_in_words(); @@ -1191,7 +1193,7 @@ static void TestLayoutDescriptorHelper(Isolate* isolate, int first_non_tagged_field_offset = end_offset; for (int i = 0; i < number_of_descriptors; i++) { PropertyDetails details = descriptors->GetDetails(i); - if (details.type() != DATA) continue; + if (details.location() != kField) continue; FieldIndex index = FieldIndex::ForDescriptor(*map, i); if (!index.is_inobject()) continue; all_fields_tagged &= !details.representation().IsDouble(); @@ -1532,7 +1534,7 @@ static void TestWriteBarrierObjectShiftFieldsRight( // Shift fields right by turning constant property to a field. Handle<Map> new_map = Map::ReconfigureProperty( - map, 0, kData, NONE, Representation::Tagged(), any_type, FORCE_FIELD); + map, 0, kData, NONE, Representation::Tagged(), any_type); if (write_barrier_kind == OLD_TO_NEW_WRITE_BARRIER) { TestWriteBarrier(map, new_map, 2, 1); diff --git a/deps/v8/test/cctest/test-usecounters.cc b/deps/v8/test/cctest/test-usecounters.cc index 8d4628c9f7..3482476b76 100644 --- a/deps/v8/test/cctest/test-usecounters.cc +++ b/deps/v8/test/cctest/test-usecounters.cc @@ -71,3 +71,46 @@ TEST(DefineGetterSetterThrowUseCount) { "a.__defineSetter__('b', ()=>{});"); CHECK_EQ(2, use_counts[v8::Isolate::kDefineGetterOrSetterWouldThrow]); } + +TEST(AssigmentExpressionLHSIsCall) { + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + LocalContext env; + int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; + global_use_counts = use_counts; + CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); + + // AssignmentExpressions whose LHS is not a call do not increment counters + CompileRun("function f(){ a = 0; a()[b] = 0; }"); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + CompileRun("function f(){ ++a; ++a()[b]; }"); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + CompileRun("function f(){ 'use strict'; a = 0; a()[b] = 0; }"); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + CompileRun("function f(){ 'use strict'; ++a; ++a()[b]; }"); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + + // AssignmentExpressions whose LHS is a call increment appropriate counters + CompileRun("function f(){ a() = 0; }"); + CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy] = 0; + CompileRun("function f(){ 'use strict'; a() = 0; }"); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict] = 0; + + // UpdateExpressions whose LHS is a call increment appropriate counters + CompileRun("function f(){ ++a(); }"); + CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy] = 0; + CompileRun("function f(){ 'use strict'; ++a(); }"); + CHECK_EQ(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInSloppy]); + CHECK_NE(0, use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict]); + use_counts[v8::Isolate::kAssigmentExpressionLHSIsCallInStrict] = 0; +} diff --git a/deps/v8/test/cctest/test-weakmaps.cc b/deps/v8/test/cctest/test-weakmaps.cc index eb5333f6c0..0aee37bb5a 100644 --- a/deps/v8/test/cctest/test-weakmaps.cc +++ b/deps/v8/test/cctest/test-weakmaps.cc @@ -249,6 +249,7 @@ TEST(Regress2060b) { TEST(Regress399527) { + if (!FLAG_incremental_marking) return; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); Isolate* isolate = CcTest::i_isolate(); diff --git a/deps/v8/test/cctest/wasm/OWNERS b/deps/v8/test/cctest/wasm/OWNERS index eda8deabfd..59b1e7dc7a 100644 --- a/deps/v8/test/cctest/wasm/OWNERS +++ b/deps/v8/test/cctest/wasm/OWNERS @@ -1,5 +1,6 @@ ahaas@chromium.org bradnelson@chromium.org +clemensh@chromium.org mtrofin@chromium.org rossberg@chromium.org titzer@chromium.org diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-64.cc b/deps/v8/test/cctest/wasm/test-run-wasm-64.cc index e9a2d2da47..4571364980 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-64.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-64.cc @@ -120,7 +120,7 @@ WASM_EXEC_TEST(I64Const_many) { WASM_EXEC_TEST(Return_I64) { REQUIRE(I64Return); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_RETURN1(WASM_GET_LOCAL(0))); @@ -129,29 +129,51 @@ WASM_EXEC_TEST(Return_I64) { WASM_EXEC_TEST(I64Add) { REQUIRE(I64Add); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i + *j, r.Call(*i, *j)); } } } +// The i64 add and subtract regression tests need a 64-bit value with a non-zero +// upper half. This upper half was clobbering eax, leading to the function +// returning 1 rather than 0. +const int64_t kHasBit33On = 0x100000000; + +WASM_EXEC_TEST(Regress5800_Add) { + REQUIRE(I64Add); + WasmRunner<int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_I64_EQZ(WASM_I64_ADD( + WASM_I64V(0), WASM_I64V(kHasBit33On)))), + WASM_RETURN1(WASM_I32V(0))), + WASM_I32V(0)); + CHECK_EQ(0, r.Call()); +} + WASM_EXEC_TEST(I64Sub) { REQUIRE(I64Sub); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i - *j, r.Call(*i, *j)); } } } +WASM_EXEC_TEST(Regress5800_Sub) { + REQUIRE(I64Sub); + WasmRunner<int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_I64_EQZ(WASM_I64_SUB( + WASM_I64V(0), WASM_I64V(kHasBit33On)))), + WASM_RETURN1(WASM_I32V(0))), + WASM_I32V(0)); + CHECK_EQ(0, r.Call()); +} + WASM_EXEC_TEST(I64AddUseOnlyLowWord) { REQUIRE(I64Add); REQUIRE(I32ConvertI64); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I32_CONVERT_I64( WASM_I64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_INT64_INPUTS(i) { @@ -164,8 +186,7 @@ WASM_EXEC_TEST(I64AddUseOnlyLowWord) { WASM_EXEC_TEST(I64SubUseOnlyLowWord) { REQUIRE(I64Sub); REQUIRE(I32ConvertI64); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I32_CONVERT_I64( WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_INT64_INPUTS(i) { @@ -178,8 +199,7 @@ WASM_EXEC_TEST(I64SubUseOnlyLowWord) { WASM_EXEC_TEST(I64MulUseOnlyLowWord) { REQUIRE(I64Mul); REQUIRE(I32ConvertI64); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I32_CONVERT_I64( WASM_I64_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_INT64_INPUTS(i) { @@ -192,8 +212,7 @@ WASM_EXEC_TEST(I64MulUseOnlyLowWord) { WASM_EXEC_TEST(I64ShlUseOnlyLowWord) { REQUIRE(I64Shl); REQUIRE(I32ConvertI64); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I32_CONVERT_I64( WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_INT64_INPUTS(i) { @@ -207,8 +226,7 @@ WASM_EXEC_TEST(I64ShlUseOnlyLowWord) { WASM_EXEC_TEST(I64ShrUseOnlyLowWord) { REQUIRE(I64ShrU); REQUIRE(I32ConvertI64); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I32_CONVERT_I64( WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_UINT64_INPUTS(i) { @@ -222,8 +240,7 @@ WASM_EXEC_TEST(I64ShrUseOnlyLowWord) { WASM_EXEC_TEST(I64SarUseOnlyLowWord) { REQUIRE(I64ShrS); REQUIRE(I32ConvertI64); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I32_CONVERT_I64( WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_INT64_INPUTS(i) { @@ -234,10 +251,9 @@ WASM_EXEC_TEST(I64SarUseOnlyLowWord) { } } -WASM_EXEC_TEST(I64DivS) { +WASM_EXEC_TEST_WITH_TRAP(I64DivS) { REQUIRE(I64DivS); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { @@ -252,10 +268,9 @@ WASM_EXEC_TEST(I64DivS) { } } -WASM_EXEC_TEST(I64DivS_Trap) { +WASM_EXEC_TEST_WITH_TRAP(I64DivS_Trap) { REQUIRE(I64DivS); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(0, r.Call(asi64(0), asi64(100))); CHECK_TRAP64(r.Call(asi64(100), asi64(0))); @@ -264,10 +279,10 @@ WASM_EXEC_TEST(I64DivS_Trap) { CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0))); } -WASM_EXEC_TEST(I64DivS_Byzero_Const) { +WASM_EXEC_TEST_WITH_TRAP(I64DivS_Byzero_Const) { REQUIRE(I64DivS); for (int8_t denom = -2; denom < 8; denom++) { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_DIVS(WASM_GET_LOCAL(0), WASM_I64V_1(denom))); for (int64_t val = -7; val < 8; val++) { if (denom == 0) { @@ -279,10 +294,9 @@ WASM_EXEC_TEST(I64DivS_Byzero_Const) { } } -WASM_EXEC_TEST(I64DivU) { +WASM_EXEC_TEST_WITH_TRAP(I64DivU) { REQUIRE(I64DivU); - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(), - MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { FOR_UINT64_INPUTS(j) { @@ -295,21 +309,20 @@ WASM_EXEC_TEST(I64DivU) { } } -WASM_EXEC_TEST(I64DivU_Trap) { +WASM_EXEC_TEST_WITH_TRAP(I64DivU_Trap) { REQUIRE(I64DivU); - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(), - MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - CHECK_EQ(0u, r.Call(asu64(0), asu64(100))); + CHECK_EQ(0, r.Call(asu64(0), asu64(100))); CHECK_TRAP64(r.Call(asu64(100), asu64(0))); CHECK_TRAP64(r.Call(asu64(1001), asu64(0))); CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0))); } -WASM_EXEC_TEST(I64DivU_Byzero_Const) { +WASM_EXEC_TEST_WITH_TRAP(I64DivU_Byzero_Const) { REQUIRE(I64DivU); for (uint64_t denom = 0xfffffffffffffffe; denom < 8; denom++) { - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_DIVU(WASM_GET_LOCAL(0), WASM_I64V_1(denom))); for (uint64_t val = 0xfffffffffffffff0; val < 8; val++) { @@ -322,10 +335,9 @@ WASM_EXEC_TEST(I64DivU_Byzero_Const) { } } -WASM_EXEC_TEST(I64RemS) { +WASM_EXEC_TEST_WITH_TRAP(I64RemS) { REQUIRE(I64RemS); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { @@ -338,10 +350,9 @@ WASM_EXEC_TEST(I64RemS) { } } -WASM_EXEC_TEST(I64RemS_Trap) { +WASM_EXEC_TEST_WITH_TRAP(I64RemS_Trap) { REQUIRE(I64RemS); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(33, r.Call(asi64(133), asi64(100))); CHECK_EQ(0, r.Call(std::numeric_limits<int64_t>::min(), asi64(-1))); @@ -350,10 +361,9 @@ WASM_EXEC_TEST(I64RemS_Trap) { CHECK_TRAP64(r.Call(std::numeric_limits<int64_t>::min(), asi64(0))); } -WASM_EXEC_TEST(I64RemU) { +WASM_EXEC_TEST_WITH_TRAP(I64RemU) { REQUIRE(I64RemU); - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(), - MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { FOR_UINT64_INPUTS(j) { @@ -366,12 +376,11 @@ WASM_EXEC_TEST(I64RemU) { } } -WASM_EXEC_TEST(I64RemU_Trap) { +WASM_EXEC_TEST_WITH_TRAP(I64RemU_Trap) { REQUIRE(I64RemU); - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(), - MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - CHECK_EQ(17u, r.Call(asu64(217), asu64(100))); + CHECK_EQ(17, r.Call(asu64(217), asu64(100))); CHECK_TRAP64(r.Call(asu64(100), asu64(0))); CHECK_TRAP64(r.Call(asu64(1001), asu64(0))); CHECK_TRAP64(r.Call(std::numeric_limits<uint64_t>::max(), asu64(0))); @@ -379,8 +388,7 @@ WASM_EXEC_TEST(I64RemU_Trap) { WASM_EXEC_TEST(I64And) { REQUIRE(I64And); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_AND(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ((*i) & (*j), r.Call(*i, *j)); } @@ -389,8 +397,7 @@ WASM_EXEC_TEST(I64And) { WASM_EXEC_TEST(I64Ior) { REQUIRE(I64Ior); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_IOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ((*i) | (*j), r.Call(*i, *j)); } @@ -399,8 +406,7 @@ WASM_EXEC_TEST(I64Ior) { WASM_EXEC_TEST(I64Xor) { REQUIRE(I64Xor); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ((*i) ^ (*j), r.Call(*i, *j)); } @@ -410,8 +416,7 @@ WASM_EXEC_TEST(I64Xor) { WASM_EXEC_TEST(I64Shl) { REQUIRE(I64Shl); { - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(), - MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { @@ -422,22 +427,22 @@ WASM_EXEC_TEST(I64Shl) { } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(0))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 0, r.Call(*i)); } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(32))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 32, r.Call(*i)); } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(20))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 20, r.Call(*i)); } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHL(WASM_GET_LOCAL(0), WASM_I64V_1(40))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i << 40, r.Call(*i)); } } @@ -446,8 +451,7 @@ WASM_EXEC_TEST(I64Shl) { WASM_EXEC_TEST(I64ShrU) { REQUIRE(I64ShrU); { - WasmRunner<uint64_t> r(execution_mode, MachineType::Uint64(), - MachineType::Uint64()); + WasmRunner<uint64_t, uint64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { @@ -458,22 +462,22 @@ WASM_EXEC_TEST(I64ShrU) { } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(0))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(32))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(20))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); } } { - WasmRunner<uint64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<uint64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SHR(WASM_GET_LOCAL(0), WASM_I64V_1(40))); FOR_UINT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); } } @@ -482,8 +486,7 @@ WASM_EXEC_TEST(I64ShrU) { WASM_EXEC_TEST(I64ShrS) { REQUIRE(I64ShrS); { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { @@ -494,22 +497,22 @@ WASM_EXEC_TEST(I64ShrS) { } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(0))); FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 0, r.Call(*i)); } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(32))); FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 32, r.Call(*i)); } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(20))); FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 20, r.Call(*i)); } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_SAR(WASM_GET_LOCAL(0), WASM_I64V_1(40))); FOR_INT64_INPUTS(i) { CHECK_EQ(*i >> 40, r.Call(*i)); } } @@ -517,8 +520,7 @@ WASM_EXEC_TEST(I64ShrS) { WASM_EXEC_TEST(I64Eq) { REQUIRE(I64Eq); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_EQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i == *j ? 1 : 0, r.Call(*i, *j)); } @@ -527,8 +529,7 @@ WASM_EXEC_TEST(I64Eq) { WASM_EXEC_TEST(I64Ne) { REQUIRE(I64Ne); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_NE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i != *j ? 1 : 0, r.Call(*i, *j)); } @@ -537,8 +538,7 @@ WASM_EXEC_TEST(I64Ne) { WASM_EXEC_TEST(I64LtS) { REQUIRE(I64LtS); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_LTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); } @@ -547,8 +547,7 @@ WASM_EXEC_TEST(I64LtS) { WASM_EXEC_TEST(I64LeS) { REQUIRE(I64LeS); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_LES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); } @@ -557,8 +556,7 @@ WASM_EXEC_TEST(I64LeS) { WASM_EXEC_TEST(I64LtU) { REQUIRE(I64LtU); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_LTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { FOR_UINT64_INPUTS(j) { CHECK_EQ(*i < *j ? 1 : 0, r.Call(*i, *j)); } @@ -567,8 +565,7 @@ WASM_EXEC_TEST(I64LtU) { WASM_EXEC_TEST(I64LeU) { REQUIRE(I64LeU); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_LEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { FOR_UINT64_INPUTS(j) { CHECK_EQ(*i <= *j ? 1 : 0, r.Call(*i, *j)); } @@ -577,8 +574,7 @@ WASM_EXEC_TEST(I64LeU) { WASM_EXEC_TEST(I64GtS) { REQUIRE(I64GtS); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_GTS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); } @@ -587,8 +583,7 @@ WASM_EXEC_TEST(I64GtS) { WASM_EXEC_TEST(I64GeS) { REQUIRE(I64GeS); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_GES(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); } @@ -597,8 +592,7 @@ WASM_EXEC_TEST(I64GeS) { WASM_EXEC_TEST(I64GtU) { REQUIRE(I64GtU); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_GTU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { FOR_UINT64_INPUTS(j) { CHECK_EQ(*i > *j ? 1 : 0, r.Call(*i, *j)); } @@ -607,8 +601,7 @@ WASM_EXEC_TEST(I64GtU) { WASM_EXEC_TEST(I64GeU) { REQUIRE(I64GeU); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_GEU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { FOR_UINT64_INPUTS(j) { CHECK_EQ(*i >= *j ? 1 : 0, r.Call(*i, *j)); } @@ -626,14 +619,14 @@ WASM_EXEC_TEST(I32ConvertI64) { WASM_EXEC_TEST(I64SConvertI32) { REQUIRE(I64SConvertI32); - WasmRunner<int64_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int64_t, int32_t> r(execution_mode); BUILD(r, WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); } } WASM_EXEC_TEST(I64UConvertI32) { REQUIRE(I64UConvertI32); - WasmRunner<int64_t> r(execution_mode, MachineType::Uint32()); + WasmRunner<int64_t, uint32_t> r(execution_mode); BUILD(r, WASM_I64_UCONVERT_I32(WASM_GET_LOCAL(0))); FOR_UINT32_INPUTS(i) { CHECK_EQ(static_cast<int64_t>(*i), r.Call(*i)); } } @@ -648,7 +641,7 @@ WASM_EXEC_TEST(I64Popcnt) { {26, 0x1123456782345678}, {38, 0xffedcba09edcba09}}; - WasmRunner<int64_t> r(execution_mode, MachineType::Uint64()); + WasmRunner<int64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0))); for (size_t i = 0; i < arraysize(values); i++) { CHECK_EQ(values[i].expected, r.Call(values[i].input)); @@ -657,7 +650,7 @@ WASM_EXEC_TEST(I64Popcnt) { WASM_EXEC_TEST(F32SConvertI64) { REQUIRE(F32SConvertI64); - WasmRunner<float> r(execution_mode, MachineType::Int64()); + WasmRunner<float, int64_t> r(execution_mode); BUILD(r, WASM_F32_SCONVERT_I64(WASM_GET_LOCAL(0))); FOR_INT64_INPUTS(i) { CHECK_FLOAT_EQ(static_cast<float>(*i), r.Call(*i)); } } @@ -743,7 +736,7 @@ WASM_EXEC_TEST(F32UConvertI64) { {0x8000008000000001, 0x5f000001}, {0x8000000000000400, 0x5f000000}, {0x8000000000000401, 0x5f000000}}; - WasmRunner<float> r(execution_mode, MachineType::Uint64()); + WasmRunner<float, uint64_t> r(execution_mode); BUILD(r, WASM_F32_UCONVERT_I64(WASM_GET_LOCAL(0))); for (size_t i = 0; i < arraysize(values); i++) { CHECK_EQ(bit_cast<float>(values[i].expected), r.Call(values[i].input)); @@ -752,7 +745,7 @@ WASM_EXEC_TEST(F32UConvertI64) { WASM_EXEC_TEST(F64SConvertI64) { REQUIRE(F64SConvertI64); - WasmRunner<double> r(execution_mode, MachineType::Int64()); + WasmRunner<double, int64_t> r(execution_mode); BUILD(r, WASM_F64_SCONVERT_I64(WASM_GET_LOCAL(0))); FOR_INT64_INPUTS(i) { CHECK_DOUBLE_EQ(static_cast<double>(*i), r.Call(*i)); } } @@ -837,15 +830,15 @@ WASM_EXEC_TEST(F64UConvertI64) { {0x8000008000000001, 0x43e0000010000000}, {0x8000000000000400, 0x43e0000000000000}, {0x8000000000000401, 0x43e0000000000001}}; - WasmRunner<double> r(execution_mode, MachineType::Uint64()); + WasmRunner<double, uint64_t> r(execution_mode); BUILD(r, WASM_F64_UCONVERT_I64(WASM_GET_LOCAL(0))); for (size_t i = 0; i < arraysize(values); i++) { CHECK_EQ(bit_cast<double>(values[i].expected), r.Call(values[i].input)); } } -WASM_EXEC_TEST(I64SConvertF32a) { - WasmRunner<int64_t> r(execution_mode, MachineType::Float32()); +WASM_EXEC_TEST_WITH_TRAP(I64SConvertF32a) { + WasmRunner<int64_t, float> r(execution_mode); BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -858,8 +851,8 @@ WASM_EXEC_TEST(I64SConvertF32a) { } } -WASM_EXEC_TEST(I64SConvertF64a) { - WasmRunner<int64_t> r(execution_mode, MachineType::Float64()); +WASM_EXEC_TEST_WITH_TRAP(I64SConvertF64a) { + WasmRunner<int64_t, double> r(execution_mode); BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -872,8 +865,8 @@ WASM_EXEC_TEST(I64SConvertF64a) { } } -WASM_EXEC_TEST(I64UConvertF32a) { - WasmRunner<uint64_t> r(execution_mode, MachineType::Float32()); +WASM_EXEC_TEST_WITH_TRAP(I64UConvertF32a) { + WasmRunner<uint64_t, float> r(execution_mode); BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -886,8 +879,8 @@ WASM_EXEC_TEST(I64UConvertF32a) { } } -WASM_EXEC_TEST(I64UConvertF64a) { - WasmRunner<uint64_t> r(execution_mode, MachineType::Float64()); +WASM_EXEC_TEST_WITH_TRAP(I64UConvertF64a) { + WasmRunner<uint64_t, double> r(execution_mode); BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -901,28 +894,23 @@ WASM_EXEC_TEST(I64UConvertF64a) { } WASM_EXEC_TEST(CallI64Parameter) { - // Build the target function. - LocalType param_types[20]; - for (int i = 0; i < 20; i++) param_types[i] = kAstI64; - param_types[3] = kAstI32; - param_types[4] = kAstI32; + ValueType param_types[20]; + for (int i = 0; i < 20; i++) param_types[i] = kWasmI64; + param_types[3] = kWasmI32; + param_types[4] = kWasmI32; FunctionSig sig(1, 19, param_types); for (int i = 0; i < 19; i++) { - TestingModule module(execution_mode); - WasmFunctionCompiler t(&sig, &module); - if (i == 2 || i == 3) { - continue; - } else { - BUILD(t, WASM_GET_LOCAL(i)); - } - uint32_t index = t.CompileAndAdd(); + if (i == 2 || i == 3) continue; + WasmRunner<int32_t> r(execution_mode); + // Build the target function. + WasmFunctionCompiler& t = r.NewFunction(&sig); + BUILD(t, WASM_GET_LOCAL(i)); // Build the calling function. - WasmRunner<int32_t> r(&module); BUILD( r, WASM_I32_CONVERT_I64(WASM_CALL_FUNCTION( - index, WASM_I64V_9(0xbcd12340000000b), + t.function_index(), WASM_I64V_9(0xbcd12340000000b), WASM_I64V_9(0xbcd12340000000c), WASM_I32V_1(0xd), WASM_I32_CONVERT_I64(WASM_I64V_9(0xbcd12340000000e)), WASM_I64V_9(0xbcd12340000000f), WASM_I64V_10(0xbcd1234000000010), @@ -947,8 +935,7 @@ void TestI64Binop(WasmExecutionMode execution_mode, WasmOpcode opcode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); // return a op b BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(expected, r.Call(a, b)); @@ -964,8 +951,7 @@ void TestI64Cmp(WasmExecutionMode execution_mode, WasmOpcode opcode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int32_t, int64_t, int64_t> r(execution_mode); // return a op b BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(expected, r.Call(a, b)); @@ -1068,7 +1054,7 @@ WASM_EXEC_TEST(I64Clz) { {62, 0x0000000000000002}, {63, 0x0000000000000001}, {64, 0x0000000000000000}}; - WasmRunner<int64_t> r(execution_mode, MachineType::Uint64()); + WasmRunner<int64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_CLZ(WASM_GET_LOCAL(0))); for (size_t i = 0; i < arraysize(values); i++) { CHECK_EQ(values[i].expected, r.Call(values[i].input)); @@ -1114,7 +1100,7 @@ WASM_EXEC_TEST(I64Ctz) { {2, 0x000000009afdbc84}, {1, 0x000000009afdbc82}, {0, 0x000000009afdbc81}}; - WasmRunner<int64_t> r(execution_mode, MachineType::Uint64()); + WasmRunner<int64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_CTZ(WASM_GET_LOCAL(0))); for (size_t i = 0; i < arraysize(values); i++) { CHECK_EQ(values[i].expected, r.Call(values[i].input)); @@ -1132,7 +1118,7 @@ WASM_EXEC_TEST(I64Popcnt2) { {26, 0x1123456782345678}, {38, 0xffedcba09edcba09}}; - WasmRunner<int64_t> r(execution_mode, MachineType::Uint64()); + WasmRunner<int64_t, uint64_t> r(execution_mode); BUILD(r, WASM_I64_POPCNT(WASM_GET_LOCAL(0))); for (size_t i = 0; i < arraysize(values); i++) { CHECK_EQ(values[i].expected, r.Call(values[i].input)); @@ -1150,21 +1136,19 @@ WASM_EXEC_TEST(I64WasmRunner) { } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); BUILD(r, WASM_GET_LOCAL(0)); FOR_INT64_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT64_INPUTS(i) { FOR_INT64_INPUTS(j) { CHECK_EQ(*i ^ *j, r.Call(*i, *j)); } } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64(), MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_I64_XOR(WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)))); FOR_INT64_INPUTS(i) { @@ -1176,9 +1160,7 @@ WASM_EXEC_TEST(I64WasmRunner) { } } { - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64(), MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_XOR(WASM_GET_LOCAL(0), WASM_I64_XOR(WASM_GET_LOCAL(1), WASM_I64_XOR(WASM_GET_LOCAL(2), @@ -1196,16 +1178,15 @@ WASM_EXEC_TEST(I64WasmRunner) { WASM_EXEC_TEST(Call_Int64Sub) { REQUIRE(I64Sub); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); // Build the target function. TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t(sigs.l_ll(), &module); + WasmFunctionCompiler& t = r.NewFunction(sigs.l_ll()); BUILD(t, WASM_I64_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - uint32_t index = t.CompileAndAdd(); // Build the caller function. - WasmRunner<int64_t> r(&module, MachineType::Int64(), MachineType::Int64()); - BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); + BUILD(r, WASM_CALL_FUNCTION(t.function_index(), WASM_GET_LOCAL(0), + WASM_GET_LOCAL(1))); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { @@ -1228,20 +1209,19 @@ WASM_EXEC_TEST(LoadStoreI64_sx) { kExprI64LoadMem}; for (size_t m = 0; m < arraysize(loads); m++) { - TestingModule module(execution_mode); - byte* memory = module.AddMemoryElems<byte>(16); - WasmRunner<int64_t> r(&module); + WasmRunner<int64_t> r(execution_mode); + byte* memory = r.module().AddMemoryElems<byte>(16); byte code[] = { - kExprI8Const, 8, // -- - kExprI8Const, 0, // -- + kExprI32Const, 8, // -- + kExprI32Const, 0, // -- loads[m], // -- ZERO_ALIGNMENT, // -- ZERO_OFFSET, // -- kExprI64StoreMem, // -- ZERO_ALIGNMENT, // -- ZERO_OFFSET, // -- - kExprI8Const, 0, // -- + kExprI32Const, 0, // -- loads[m], // -- ZERO_ALIGNMENT, // -- ZERO_OFFSET, // -- @@ -1252,7 +1232,7 @@ WASM_EXEC_TEST(LoadStoreI64_sx) { // Try a bunch of different negative values. for (int i = -1; i >= -128; i -= 11) { int size = 1 << m; - module.BlankMemory(); + r.module().BlankMemory(); memory[size - 1] = static_cast<byte>(i); // set the high order byte. int64_t expected = static_cast<int64_t>(i) << ((size - 1) * 8); @@ -1266,9 +1246,9 @@ WASM_EXEC_TEST(LoadStoreI64_sx) { } } -WASM_EXEC_TEST(I64SConvertF32b) { +WASM_EXEC_TEST_WITH_TRAP(I64SConvertF32b) { REQUIRE(I64SConvertF32); - WasmRunner<int64_t> r(execution_mode, MachineType::Float32()); + WasmRunner<int64_t, float> r(execution_mode); BUILD(r, WASM_I64_SCONVERT_F32(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -1281,9 +1261,9 @@ WASM_EXEC_TEST(I64SConvertF32b) { } } -WASM_EXEC_TEST(I64SConvertF64b) { +WASM_EXEC_TEST_WITH_TRAP(I64SConvertF64b) { REQUIRE(I64SConvertF64); - WasmRunner<int64_t> r(execution_mode, MachineType::Float64()); + WasmRunner<int64_t, double> r(execution_mode); BUILD(r, WASM_I64_SCONVERT_F64(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -1296,9 +1276,9 @@ WASM_EXEC_TEST(I64SConvertF64b) { } } -WASM_EXEC_TEST(I64UConvertF32b) { +WASM_EXEC_TEST_WITH_TRAP(I64UConvertF32b) { REQUIRE(I64UConvertF32); - WasmRunner<uint64_t> r(execution_mode, MachineType::Float32()); + WasmRunner<uint64_t, float> r(execution_mode); BUILD(r, WASM_I64_UCONVERT_F32(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -1310,9 +1290,9 @@ WASM_EXEC_TEST(I64UConvertF32b) { } } -WASM_EXEC_TEST(I64UConvertF64b) { +WASM_EXEC_TEST_WITH_TRAP(I64UConvertF64b) { REQUIRE(I64UConvertF64); - WasmRunner<uint64_t> r(execution_mode, MachineType::Float64()); + WasmRunner<uint64_t, double> r(execution_mode); BUILD(r, WASM_I64_UCONVERT_F64(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -1326,25 +1306,33 @@ WASM_EXEC_TEST(I64UConvertF64b) { WASM_EXEC_TEST(I64ReinterpretF64) { REQUIRE(I64ReinterpretF64); - TestingModule module(execution_mode); - int64_t* memory = module.AddMemoryElems<int64_t>(8); - WasmRunner<int64_t> r(&module); + WasmRunner<int64_t> r(execution_mode); + int64_t* memory = r.module().AddMemoryElems<int64_t>(8); BUILD(r, WASM_I64_REINTERPRET_F64( WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO))); FOR_INT32_INPUTS(i) { int64_t expected = static_cast<int64_t>(*i) * 0x300010001; - module.WriteMemory(&memory[0], expected); + r.module().WriteMemory(&memory[0], expected); CHECK_EQ(expected, r.Call()); } } +WASM_EXEC_TEST(SignallingNanSurvivesI64ReinterpretF64) { + REQUIRE(I64ReinterpretF64); + WasmRunner<int64_t> r(execution_mode); + BUILD(r, WASM_I64_REINTERPRET_F64(WASM_SEQ(kExprF64Const, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xf4, 0x7f))); + + // This is a signalling nan. + CHECK_EQ(0x7ff4000000000000, r.Call()); +} + WASM_EXEC_TEST(F64ReinterpretI64) { REQUIRE(F64ReinterpretI64); - TestingModule module(execution_mode); - int64_t* memory = module.AddMemoryElems<int64_t>(8); - WasmRunner<int64_t> r(&module, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); + int64_t* memory = r.module().AddMemoryElems<int64_t>(8); BUILD(r, WASM_STORE_MEM(MachineType::Float64(), WASM_ZERO, WASM_F64_REINTERPRET_I64(WASM_GET_LOCAL(0))), @@ -1353,47 +1341,45 @@ WASM_EXEC_TEST(F64ReinterpretI64) { FOR_INT32_INPUTS(i) { int64_t expected = static_cast<int64_t>(*i) * 0x300010001; CHECK_EQ(expected, r.Call(expected)); - CHECK_EQ(expected, module.ReadMemory<int64_t>(&memory[0])); + CHECK_EQ(expected, r.module().ReadMemory<int64_t>(&memory[0])); } } WASM_EXEC_TEST(LoadMemI64) { REQUIRE(I64LoadStore); - TestingModule module(execution_mode); - int64_t* memory = module.AddMemoryElems<int64_t>(8); - module.RandomizeMemory(1111); - WasmRunner<int64_t> r(&module); + WasmRunner<int64_t> r(execution_mode); + int64_t* memory = r.module().AddMemoryElems<int64_t>(8); + r.module().RandomizeMemory(1111); - BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_I8(0))); + BUILD(r, WASM_LOAD_MEM(MachineType::Int64(), WASM_ZERO)); - module.WriteMemory<int64_t>(&memory[0], 0x1abbccdd00112233LL); + r.module().WriteMemory<int64_t>(&memory[0], 0x1abbccdd00112233LL); CHECK_EQ(0x1abbccdd00112233LL, r.Call()); - module.WriteMemory<int64_t>(&memory[0], 0x33aabbccdd001122LL); + r.module().WriteMemory<int64_t>(&memory[0], 0x33aabbccdd001122LL); CHECK_EQ(0x33aabbccdd001122LL, r.Call()); - module.WriteMemory<int64_t>(&memory[0], 77777777); + r.module().WriteMemory<int64_t>(&memory[0], 77777777); CHECK_EQ(77777777, r.Call()); } WASM_EXEC_TEST(LoadMemI64_alignment) { REQUIRE(I64LoadStore); - TestingModule module(execution_mode); - int64_t* memory = module.AddMemoryElems<int64_t>(8); for (byte alignment = 0; alignment <= 3; alignment++) { - module.RandomizeMemory(1111); - WasmRunner<int64_t> r(&module); + WasmRunner<int64_t> r(execution_mode); + int64_t* memory = r.module().AddMemoryElems<int64_t>(8); + r.module().RandomizeMemory(1111); BUILD(r, - WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_I8(0), alignment)); + WASM_LOAD_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, alignment)); - module.WriteMemory<int64_t>(&memory[0], 0x1abbccdd00112233LL); + r.module().WriteMemory<int64_t>(&memory[0], 0x1abbccdd00112233LL); CHECK_EQ(0x1abbccdd00112233LL, r.Call()); - module.WriteMemory<int64_t>(&memory[0], 0x33aabbccdd001122LL); + r.module().WriteMemory<int64_t>(&memory[0], 0x33aabbccdd001122LL); CHECK_EQ(0x33aabbccdd001122LL, r.Call()); - module.WriteMemory<int64_t>(&memory[0], 77777777); + r.module().WriteMemory<int64_t>(&memory[0], 77777777); CHECK_EQ(77777777, r.Call()); } } @@ -1404,29 +1390,27 @@ WASM_EXEC_TEST(MemI64_Sum) { REQUIRE(I64Sub); REQUIRE(I64Phi); const int kNumElems = 20; - TestingModule module(execution_mode); - uint64_t* memory = module.AddMemoryElems<uint64_t>(kNumElems); - WasmRunner<uint64_t> r(&module, MachineType::Int32()); - const byte kSum = r.AllocateLocal(kAstI64); - - BUILD( - r, - WASM_WHILE( - WASM_GET_LOCAL(0), - WASM_BLOCK( - WASM_SET_LOCAL(kSum, - WASM_I64_ADD(WASM_GET_LOCAL(kSum), + WasmRunner<uint64_t, int32_t> r(execution_mode); + uint64_t* memory = r.module().AddMemoryElems<uint64_t>(kNumElems); + const byte kSum = r.AllocateLocal(kWasmI64); + + BUILD(r, WASM_WHILE( + WASM_GET_LOCAL(0), + WASM_BLOCK( + WASM_SET_LOCAL( + kSum, WASM_I64_ADD(WASM_GET_LOCAL(kSum), WASM_LOAD_MEM(MachineType::Int64(), WASM_GET_LOCAL(0)))), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(8))))), - WASM_GET_LOCAL(1)); + WASM_SET_LOCAL( + 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(8))))), + WASM_GET_LOCAL(1)); // Run 4 trials. for (int i = 0; i < 3; i++) { - module.RandomizeMemory(i * 33); + r.module().RandomizeMemory(i * 33); uint64_t expected = 0; for (size_t j = kNumElems - 1; j > 0; j--) { - expected += module.ReadMemory(&memory[j]); + expected += r.module().ReadMemory(&memory[j]); } uint64_t result = r.Call(8 * (kNumElems - 1)); CHECK_EQ(expected, result); @@ -1434,20 +1418,19 @@ WASM_EXEC_TEST(MemI64_Sum) { } WASM_EXEC_TEST(StoreMemI64_alignment) { - TestingModule module(execution_mode); - int64_t* memory = module.AddMemoryElems<int64_t>(4); const int64_t kWritten = 0x12345678abcd0011ll; for (byte i = 0; i <= 3; i++) { - WasmRunner<int64_t> r(&module, MachineType::Int64()); + WasmRunner<int64_t, int64_t> r(execution_mode); + int64_t* memory = r.module().AddMemoryElems<int64_t>(4); BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int64(), WASM_ZERO, i, WASM_GET_LOCAL(0)), WASM_GET_LOCAL(0)); - module.RandomizeMemory(1111); - module.WriteMemory<int64_t>(&memory[0], 0); + r.module().RandomizeMemory(1111); + r.module().WriteMemory<int64_t>(&memory[0], 0); CHECK_EQ(kWritten, r.Call(kWritten)); - CHECK_EQ(kWritten, module.ReadMemory(&memory[0])); + CHECK_EQ(kWritten, r.module().ReadMemory(&memory[0])); } } @@ -1456,16 +1439,15 @@ WASM_EXEC_TEST(I64Global) { REQUIRE(I64SConvertI32); REQUIRE(I64And); REQUIRE(DepthFirst); - TestingModule module(execution_mode); - int64_t* global = module.AddGlobal<int64_t>(kAstI64); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + int64_t* global = r.module().AddGlobal<int64_t>(); // global = global + p0 BUILD(r, WASM_SET_GLOBAL( 0, WASM_I64_AND(WASM_GET_GLOBAL(0), WASM_I64_SCONVERT_I32(WASM_GET_LOCAL(0)))), WASM_ZERO); - module.WriteMemory<int64_t>(global, 0xFFFFFFFFFFFFFFFFLL); + r.module().WriteMemory<int64_t>(global, 0xFFFFFFFFFFFFFFFFLL); for (int i = 9; i < 444444; i += 111111) { int64_t expected = *global & i; r.Call(i); @@ -1476,7 +1458,7 @@ WASM_EXEC_TEST(I64Global) { WASM_EXEC_TEST(I64Eqz) { REQUIRE(I64Eq); - WasmRunner<int32_t> r(execution_mode, MachineType::Int64()); + WasmRunner<int32_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_EQZ(WASM_GET_LOCAL(0))); FOR_INT64_INPUTS(i) { @@ -1487,8 +1469,7 @@ WASM_EXEC_TEST(I64Eqz) { WASM_EXEC_TEST(I64Ror) { REQUIRE(I64Ror); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_ROR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { @@ -1501,8 +1482,7 @@ WASM_EXEC_TEST(I64Ror) { WASM_EXEC_TEST(I64Rol) { REQUIRE(I64Rol); - WasmRunner<int64_t> r(execution_mode, MachineType::Int64(), - MachineType::Int64()); + WasmRunner<int64_t, int64_t, int64_t> r(execution_mode); BUILD(r, WASM_I64_ROL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT64_INPUTS(i) { @@ -1513,10 +1493,7 @@ WASM_EXEC_TEST(I64Rol) { } } -WASM_EXEC_TEST(StoreMem_offset_oob_i64) { - TestingModule module(execution_mode); - byte* memory = module.AddMemoryElems<byte>(32); - +WASM_EXEC_TEST_WITH_TRAP(StoreMem_offset_oob_i64) { static const MachineType machineTypes[] = { MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(), @@ -1524,8 +1501,9 @@ WASM_EXEC_TEST(StoreMem_offset_oob_i64) { MachineType::Float64()}; for (size_t m = 0; m < arraysize(machineTypes); m++) { - module.RandomizeMemory(1119 + static_cast<int>(m)); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); + WasmRunner<int32_t, uint32_t> r(execution_mode); + byte* memory = r.module().AddMemoryElems<byte>(32); + r.module().RandomizeMemory(1119 + static_cast<int>(m)); BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0), WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)), @@ -1548,36 +1526,32 @@ WASM_EXEC_TEST(StoreMem_offset_oob_i64) { for (size_t i = 0; i < sizeof(__buf); i++) vec.push_back(__buf[i]); \ } while (false) -static void CompileCallIndirectMany(LocalType param) { +static void CompileCallIndirectMany(ValueType param) { // Make sure we don't run out of registers when compiling indirect calls // with many many parameters. TestSignatures sigs; for (byte num_params = 0; num_params < 40; num_params++) { - v8::internal::AccountingAllocator allocator; - Zone zone(&allocator, ZONE_NAME); - HandleScope scope(CcTest::InitIsolateOnce()); - TestingModule module(kExecuteCompiled); - FunctionSig* sig = sigs.many(&zone, kAstStmt, param, num_params); + WasmRunner<void> r(kExecuteCompiled); + FunctionSig* sig = sigs.many(r.zone(), kWasmStmt, param, num_params); - module.AddSignature(sig); - module.AddSignature(sig); - module.AddIndirectFunctionTable(nullptr, 0); + r.module().AddSignature(sig); + r.module().AddSignature(sig); + r.module().AddIndirectFunctionTable(nullptr, 0); - WasmFunctionCompiler t(sig, &module); + WasmFunctionCompiler& t = r.NewFunction(sig); std::vector<byte> code; for (byte p = 0; p < num_params; p++) { ADD_CODE(code, kExprGetLocal, p); } - ADD_CODE(code, kExprI8Const, 0); + ADD_CODE(code, kExprI32Const, 0); ADD_CODE(code, kExprCallIndirect, 1, TABLE_ZERO); t.Build(&code[0], &code[0] + code.size()); - t.Compile(); } } -TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kAstI64); } +TEST(Compile_Wasm_CallIndirect_Many_i64) { CompileCallIndirectMany(kWasmI64); } static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { const int kExpected = 6333; @@ -1595,28 +1569,25 @@ static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { for (int which = 0; which < num_params; which++) { v8::internal::AccountingAllocator allocator; Zone zone(&allocator, ZONE_NAME); - TestingModule module(execution_mode); - module.AddMemory(1024); + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemory(1024); MachineType* memtypes = &mixed[start]; MachineType result = memtypes[which]; // ========================================================================= // Build the selector function. // ========================================================================= - uint32_t index; FunctionSig::Builder b(&zone, 1, num_params); - b.AddReturn(WasmOpcodes::LocalTypeFor(result)); + b.AddReturn(WasmOpcodes::ValueTypeFor(result)); for (int i = 0; i < num_params; i++) { - b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i])); + b.AddParam(WasmOpcodes::ValueTypeFor(memtypes[i])); } - WasmFunctionCompiler t(b.Build(), &module); + WasmFunctionCompiler& t = r.NewFunction(b.Build()); BUILD(t, WASM_GET_LOCAL(which)); - index = t.CompileAndAdd(); // ========================================================================= // Build the calling function. // ========================================================================= - WasmRunner<int32_t> r(&module); std::vector<byte> code; // Load the offset for the store. @@ -1625,11 +1596,11 @@ static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { // Load the arguments. for (int i = 0; i < num_params; i++) { int offset = (i + 1) * kElemSize; - ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset))); + ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I32V_2(offset))); } // Call the selector function. - ADD_CODE(code, kExprCallFunction, static_cast<byte>(index)); + ADD_CODE(code, WASM_CALL_FUNCTION0(t.function_index())); // Store the result in memory. ADD_CODE(code, @@ -1643,14 +1614,14 @@ static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { // Run the code. for (int t = 0; t < 10; t++) { - module.RandomizeMemory(); + r.module().RandomizeMemory(); CHECK_EQ(kExpected, r.Call()); int size = WasmOpcodes::MemSize(result); for (int i = 0; i < size; i++) { int base = (which + 1) * kElemSize; - byte expected = module.raw_mem_at<byte>(base + i); - byte result = module.raw_mem_at<byte>(i); + byte expected = r.module().raw_mem_at<byte>(base + i); + byte result = r.module().raw_mem_at<byte>(i); CHECK_EQ(expected, result); } } @@ -1661,3 +1632,19 @@ WASM_EXEC_TEST(MixedCall_i64_0) { Run_WasmMixedCall_N(execution_mode, 0); } WASM_EXEC_TEST(MixedCall_i64_1) { Run_WasmMixedCall_N(execution_mode, 1); } WASM_EXEC_TEST(MixedCall_i64_2) { Run_WasmMixedCall_N(execution_mode, 2); } WASM_EXEC_TEST(MixedCall_i64_3) { Run_WasmMixedCall_N(execution_mode, 3); } + +WASM_EXEC_TEST(Regress5874) { + REQUIRE(I32ConvertI64); + REQUIRE(I64LoadStore); + REQUIRE(I64Const); + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemoryElems<int64_t>(8); + + BUILD(r, kExprI64Const, 0x00, // -- + kExprI32ConvertI64, // -- + kExprI64Const, 0x00, // -- + kExprI64StoreMem, 0x03, 0x00, // -- + kExprI32Const, 0x00); // -- + + r.Call(); +} diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-asmjs.cc b/deps/v8/test/cctest/wasm/test-run-wasm-asmjs.cc index bd80e28f9f..38430f292c 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-asmjs.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-asmjs.cc @@ -38,9 +38,8 @@ uint32_t GetMatchingRelocInfoCount(Handle<Code> code, RelocInfo::Mode rmode) { } WASM_EXEC_TEST(Int32AsmjsDivS) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_BINOP(kExprI32AsmjsDivS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(0, r.Call(0, 100)); @@ -51,9 +50,8 @@ WASM_EXEC_TEST(Int32AsmjsDivS) { } WASM_EXEC_TEST(Int32AsmjsRemS) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_BINOP(kExprI32AsmjsRemS, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(33, r.Call(133, 100)); @@ -64,9 +62,8 @@ WASM_EXEC_TEST(Int32AsmjsRemS) { } WASM_EXEC_TEST(Int32AsmjsDivU) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_BINOP(kExprI32AsmjsDivU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(0, r.Call(0, 100)); @@ -77,9 +74,8 @@ WASM_EXEC_TEST(Int32AsmjsDivU) { } WASM_EXEC_TEST(Int32AsmjsRemU) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_BINOP(kExprI32AsmjsRemU, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(17, r.Call(217, 100)); @@ -90,9 +86,8 @@ WASM_EXEC_TEST(Int32AsmjsRemU) { } WASM_EXEC_TEST(I32AsmjsSConvertF32) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<int32_t> r(&module, MachineType::Float32()); + WasmRunner<int32_t, float> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF32, WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -102,9 +97,8 @@ WASM_EXEC_TEST(I32AsmjsSConvertF32) { } WASM_EXEC_TEST(I32AsmjsSConvertF64) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<int32_t> r(&module, MachineType::Float64()); + WasmRunner<int32_t, double> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_UNOP(kExprI32AsmjsSConvertF64, WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -114,9 +108,8 @@ WASM_EXEC_TEST(I32AsmjsSConvertF64) { } WASM_EXEC_TEST(I32AsmjsUConvertF32) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<uint32_t> r(&module, MachineType::Float32()); + WasmRunner<uint32_t, float> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF32, WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -126,9 +119,8 @@ WASM_EXEC_TEST(I32AsmjsUConvertF32) { } WASM_EXEC_TEST(I32AsmjsUConvertF64) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - WasmRunner<uint32_t> r(&module, MachineType::Float64()); + WasmRunner<uint32_t, double> r(execution_mode); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_UNOP(kExprI32AsmjsUConvertF64, WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -138,11 +130,10 @@ WASM_EXEC_TEST(I32AsmjsUConvertF64) { } WASM_EXEC_TEST(LoadMemI32_oob_asm) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); - module.RandomizeMemory(1112); + WasmRunner<int32_t, uint32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); + r.module().RandomizeMemory(1112); BUILD(r, WASM_UNOP(kExprI32AsmjsLoadMem, WASM_GET_LOCAL(0))); @@ -159,11 +150,10 @@ WASM_EXEC_TEST(LoadMemI32_oob_asm) { } WASM_EXEC_TEST(LoadMemF32_oob_asm) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - float* memory = module.AddMemoryElems<float>(8); - WasmRunner<float> r(&module, MachineType::Uint32()); - module.RandomizeMemory(1112); + WasmRunner<float, uint32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); + float* memory = r.module().AddMemoryElems<float>(8); + r.module().RandomizeMemory(1112); BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0))); @@ -180,11 +170,10 @@ WASM_EXEC_TEST(LoadMemF32_oob_asm) { } WASM_EXEC_TEST(LoadMemF64_oob_asm) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - double* memory = module.AddMemoryElems<double>(8); - WasmRunner<double> r(&module, MachineType::Uint32()); - module.RandomizeMemory(1112); + WasmRunner<double, uint32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); + double* memory = r.module().AddMemoryElems<double>(8); + r.module().RandomizeMemory(1112); BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0))); @@ -203,11 +192,10 @@ WASM_EXEC_TEST(LoadMemF64_oob_asm) { } WASM_EXEC_TEST(StoreMemI32_oob_asm) { - TestingModule module(execution_mode); - module.origin = kAsmJsOrigin; - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module, MachineType::Uint32(), MachineType::Uint32()); - module.RandomizeMemory(1112); + WasmRunner<int32_t, uint32_t, uint32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); + r.module().RandomizeMemory(1112); BUILD(r, WASM_BINOP(kExprI32AsmjsStoreMem, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); @@ -237,87 +225,78 @@ WASM_EXEC_TEST(StoreMemI32_oob_asm) { TEST_BODY(kExprI32AsmjsStoreMem16) \ TEST_BODY(kExprI32AsmjsStoreMem) -#define INT_LOAD_TEST(OP_TYPE) \ - TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) { \ - TestingModule module(kExecuteCompiled); \ - module.origin = kAsmJsOrigin; \ - WasmRunner<int32_t> r(&module, MachineType::Uint32()); \ - BUILD(r, WASM_UNOP(OP_TYPE, WASM_GET_LOCAL(0))); \ - CHECK_EQ(1u, GetMatchingRelocInfoCount(module.instance->function_code[0], \ - RelocInfo::WASM_MEMORY_REFERENCE)); \ - CHECK_NE( \ - 0u, GetMatchingRelocInfoCount(module.instance->function_code[0], \ - RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \ +#define INT_LOAD_TEST(OP_TYPE) \ + TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) { \ + WasmRunner<int32_t, uint32_t> r(kExecuteCompiled); \ + r.module().ChangeOriginToAsmjs(); \ + BUILD(r, WASM_UNOP(OP_TYPE, WASM_GET_LOCAL(0))); \ + CHECK_EQ(1, \ + GetMatchingRelocInfoCount(r.module().instance->function_code[0], \ + RelocInfo::WASM_MEMORY_REFERENCE)); \ + CHECK_NE( \ + 0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], \ + RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \ } FOREACH_INT_CHECKED_LOAD_OP(INT_LOAD_TEST) -#define INT_STORE_TEST(OP_TYPE) \ - TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) { \ - TestingModule module(kExecuteCompiled); \ - module.origin = kAsmJsOrigin; \ - WasmRunner<int32_t> r(&module, MachineType::Uint32(), \ - MachineType::Uint32()); \ - BUILD(r, WASM_BINOP(OP_TYPE, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); \ - CHECK_EQ(1u, GetMatchingRelocInfoCount(module.instance->function_code[0], \ - RelocInfo::WASM_MEMORY_REFERENCE)); \ - CHECK_NE( \ - 0u, GetMatchingRelocInfoCount(module.instance->function_code[0], \ - RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \ +#define INT_STORE_TEST(OP_TYPE) \ + TEST(RunWasm_AsmCheckedRelocInfo##OP_TYPE) { \ + WasmRunner<int32_t, uint32_t, uint32_t> r(kExecuteCompiled); \ + r.module().ChangeOriginToAsmjs(); \ + BUILD(r, WASM_BINOP(OP_TYPE, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); \ + CHECK_EQ(1, \ + GetMatchingRelocInfoCount(r.module().instance->function_code[0], \ + RelocInfo::WASM_MEMORY_REFERENCE)); \ + CHECK_NE( \ + 0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], \ + RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); \ } FOREACH_INT_CHECKED_STORE_OP(INT_STORE_TEST) TEST(RunWasm_AsmCheckedLoadFloat32RelocInfo) { - TestingModule module(kExecuteCompiled); - module.origin = kAsmJsOrigin; - WasmRunner<float> r(&module, MachineType::Uint32()); + WasmRunner<float, uint32_t> r(kExecuteCompiled); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_UNOP(kExprF32AsmjsLoadMem, WASM_GET_LOCAL(0))); - CHECK_EQ(1u, GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_REFERENCE)); - CHECK_NE(0u, - GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); + CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_REFERENCE)); + CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); } TEST(RunWasm_AsmCheckedStoreFloat32RelocInfo) { - TestingModule module(kExecuteCompiled); - module.origin = kAsmJsOrigin; - WasmRunner<float> r(&module, MachineType::Uint32(), MachineType::Float32()); + WasmRunner<float, uint32_t, float> r(kExecuteCompiled); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_BINOP(kExprF32AsmjsStoreMem, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - CHECK_EQ(1u, GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_REFERENCE)); - CHECK_NE(0u, - GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); + CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_REFERENCE)); + CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); } TEST(RunWasm_AsmCheckedLoadFloat64RelocInfo) { - TestingModule module(kExecuteCompiled); - module.origin = kAsmJsOrigin; - WasmRunner<double> r(&module, MachineType::Uint32()); + WasmRunner<double, uint32_t> r(kExecuteCompiled); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_UNOP(kExprF64AsmjsLoadMem, WASM_GET_LOCAL(0))); - CHECK_EQ(1u, GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_REFERENCE)); - CHECK_NE(0u, - GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); + CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_REFERENCE)); + CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); } TEST(RunWasm_AsmCheckedStoreFloat64RelocInfo) { - TestingModule module(kExecuteCompiled); - module.origin = kAsmJsOrigin; - WasmRunner<double> r(&module, MachineType::Uint32(), MachineType::Float64()); + WasmRunner<double, uint32_t, double> r(kExecuteCompiled); + r.module().ChangeOriginToAsmjs(); BUILD(r, WASM_BINOP(kExprF64AsmjsStoreMem, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - CHECK_EQ(1u, GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_REFERENCE)); - CHECK_NE(0u, - GetMatchingRelocInfoCount(module.instance->function_code[0], - RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); + CHECK_EQ(1, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_REFERENCE)); + CHECK_NE(0, GetMatchingRelocInfoCount(r.module().instance->function_code[0], + RelocInfo::WASM_MEMORY_SIZE_REFERENCE)); } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc b/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc index 47d97f4e48..e355b68d19 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-interpreter.cc @@ -30,20 +30,21 @@ TEST(Run_WasmInt8Const_i) { WasmRunner<int32_t> r(kExecuteInterpreted); const byte kExpectedValue = 109; // return(kExpectedValue) - BUILD(r, WASM_I8(kExpectedValue)); + BUILD(r, WASM_I32V_2(kExpectedValue)); CHECK_EQ(kExpectedValue, r.Call()); } TEST(Run_WasmIfElse) { - WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32()); - BUILD(r, WASM_IF_ELSE_I(WASM_GET_LOCAL(0), WASM_I8(9), WASM_I8(10))); + WasmRunner<int32_t, int32_t> r(kExecuteInterpreted); + BUILD(r, WASM_IF_ELSE_I(WASM_GET_LOCAL(0), WASM_I32V_1(9), WASM_I32V_1(10))); CHECK_EQ(10, r.Call(0)); CHECK_EQ(9, r.Call(1)); } TEST(Run_WasmIfReturn) { - WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32()); - BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_RETURN1(WASM_I8(77))), WASM_I8(65)); + WasmRunner<int32_t, int32_t> r(kExecuteInterpreted); + BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_RETURN1(WASM_I32V_2(77))), + WASM_I32V_2(65)); CHECK_EQ(65, r.Call(0)); CHECK_EQ(77, r.Call(1)); } @@ -54,7 +55,7 @@ TEST(Run_WasmNopsN) { for (int nops = 0; nops < kMaxNops; nops++) { byte expected = static_cast<byte>(20 + nops); memset(code, kExprNop, sizeof(code)); - code[nops] = kExprI8Const; + code[nops] = kExprI32Const; code[nops + 1] = expected; WasmRunner<int32_t> r(kExecuteInterpreted); @@ -64,13 +65,13 @@ TEST(Run_WasmNopsN) { } TEST(Run_WasmConstsN) { - const int kMaxConsts = 10; + const int kMaxConsts = 5; byte code[kMaxConsts * 3]; int32_t expected = 0; for (int count = 1; count < kMaxConsts; count++) { for (int i = 0; i < count; i++) { byte val = static_cast<byte>(count * 10 + i); - code[i * 3] = kExprI8Const; + code[i * 3] = kExprI32Const; code[i * 3 + 1] = val; if (i == (count - 1)) { code[i * 3 + 2] = kExprNop; @@ -95,7 +96,7 @@ TEST(Run_WasmBlocksN) { memset(code, kExprNop, sizeof(code)); code[0] = kExprBlock; code[1] = kLocalI32; - code[2 + nops] = kExprI8Const; + code[2 + nops] = kExprI32Const; code[2 + nops + 1] = expected; code[2 + nops + 2] = kExprEnd; @@ -108,6 +109,7 @@ TEST(Run_WasmBlocksN) { TEST(Run_WasmBlockBreakN) { const int kMaxNops = 10; const int kExtra = 6; + int run = 0; byte code[kMaxNops + kExtra]; for (int nops = 0; nops < kMaxNops; nops++) { // Place the break anywhere within the block. @@ -117,8 +119,8 @@ TEST(Run_WasmBlockBreakN) { code[1] = kLocalI32; code[sizeof(code) - 1] = kExprEnd; - int expected = nops * 11 + index; - code[2 + index + 0] = kExprI8Const; + int expected = run++; + code[2 + index + 0] = kExprI32Const; code[2 + index + 1] = static_cast<byte>(expected); code[2 + index + 2] = kExprBr; code[2 + index + 3] = 0; @@ -131,13 +133,14 @@ TEST(Run_WasmBlockBreakN) { } TEST(Run_Wasm_nested_ifs_i) { - WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(kExecuteInterpreted); - BUILD(r, WASM_IF_ELSE_I( - WASM_GET_LOCAL(0), - WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)), - WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14)))); + BUILD( + r, + WASM_IF_ELSE_I( + WASM_GET_LOCAL(0), + WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I32V_1(11), WASM_I32V_1(12)), + WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I32V_1(13), WASM_I32V_1(14)))); CHECK_EQ(11, r.Call(1, 1)); CHECK_EQ(12, r.Call(1, 0)); @@ -180,8 +183,7 @@ TEST(Breakpoint_I32Add) { Find(code, sizeof(code), kNumBreakpoints, kExprGetLocal, kExprGetLocal, kExprI32Add); - WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<int32_t, uint32_t, uint32_t> r(kExecuteInterpreted); r.Build(code, code + arraysize(code)); @@ -217,11 +219,10 @@ TEST(Breakpoint_I32Add) { } TEST(Step_I32Mul) { - static const int kTraceLength = 4; + static const int kTraceLength = 5; byte code[] = {WASM_I32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))}; - WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<int32_t, uint32_t, uint32_t> r(kExecuteInterpreted); r.Build(code, code + arraysize(code)); @@ -259,8 +260,7 @@ TEST(Breakpoint_I32And_disable) { std::unique_ptr<int[]> offsets = Find(code, sizeof(code), kNumBreakpoints, kExprI32And); - WasmRunner<int32_t> r(kExecuteInterpreted, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<int32_t, uint32_t, uint32_t> r(kExecuteInterpreted); r.Build(code, code + arraysize(code)); @@ -297,19 +297,27 @@ TEST(Breakpoint_I32And_disable) { } TEST(GrowMemory) { - TestingModule module(kExecuteInterpreted); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); - module.AddMemory(WasmModule::kPageSize); - BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0))); - CHECK_EQ(1, r.Call(1)); + { + WasmRunner<int32_t, uint32_t> r(kExecuteInterpreted); + r.module().AddMemory(WasmModule::kPageSize); + r.module().SetMaxMemPages(10); + BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0))); + CHECK_EQ(1, r.Call(1)); + } + { + WasmRunner<int32_t, uint32_t> r(kExecuteInterpreted); + r.module().AddMemory(WasmModule::kPageSize); + r.module().SetMaxMemPages(10); + BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0))); + CHECK_EQ(-1, r.Call(11)); + } } TEST(GrowMemoryPreservesData) { int32_t index = 16; int32_t value = 2335; - TestingModule module(kExecuteInterpreted); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); - module.AddMemory(WasmModule::kPageSize); + WasmRunner<int32_t, uint32_t> r(kExecuteInterpreted); + r.module().AddMemory(WasmModule::kPageSize); BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index), WASM_I32V(value)), WASM_GROW_MEMORY(WASM_GET_LOCAL(0)), WASM_DROP, @@ -320,16 +328,14 @@ TEST(GrowMemoryPreservesData) { TEST(GrowMemoryInvalidSize) { { // Grow memory by an invalid amount without initial memory. - TestingModule module(kExecuteInterpreted); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); + WasmRunner<int32_t, uint32_t> r(kExecuteInterpreted); BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0))); CHECK_EQ(-1, r.Call(1048575)); } { // Grow memory by an invalid amount without initial memory. - TestingModule module(kExecuteInterpreted); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); - module.AddMemory(WasmModule::kPageSize); + WasmRunner<int32_t, uint32_t> r(kExecuteInterpreted); + r.module().AddMemory(WasmModule::kPageSize); BUILD(r, WASM_GROW_MEMORY(WASM_GET_LOCAL(0))); CHECK_EQ(-1, r.Call(1048575)); } @@ -338,9 +344,7 @@ TEST(GrowMemoryInvalidSize) { TEST(TestPossibleNondeterminism) { { // F32Div may produced NaN - TestingModule module(kExecuteInterpreted); - WasmRunner<float> r(&module, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<float, float, float> r(kExecuteInterpreted); BUILD(r, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); r.Call(1048575.5f, 2.5f); CHECK(!r.possible_nondeterminism()); @@ -349,8 +353,7 @@ TEST(TestPossibleNondeterminism) { } { // F32Sqrt may produced NaN - TestingModule module(kExecuteInterpreted); - WasmRunner<float> r(&module, MachineType::Float32()); + WasmRunner<float, float> r(kExecuteInterpreted); BUILD(r, WASM_F32_SQRT(WASM_GET_LOCAL(0))); r.Call(16.0f); CHECK(!r.possible_nondeterminism()); @@ -359,9 +362,7 @@ TEST(TestPossibleNondeterminism) { } { // F32Mul may produced NaN - TestingModule module(kExecuteInterpreted); - WasmRunner<float> r(&module, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<float, float, float> r(kExecuteInterpreted); BUILD(r, WASM_F32_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); r.Call(1048575.5f, 2.5f); CHECK(!r.possible_nondeterminism()); @@ -370,9 +371,7 @@ TEST(TestPossibleNondeterminism) { } { // F64Div may produced NaN - TestingModule module(kExecuteInterpreted); - WasmRunner<double> r(&module, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<double, double, double> r(kExecuteInterpreted); BUILD(r, WASM_F64_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); r.Call(1048575.5, 2.5); CHECK(!r.possible_nondeterminism()); @@ -381,8 +380,7 @@ TEST(TestPossibleNondeterminism) { } { // F64Sqrt may produced NaN - TestingModule module(kExecuteInterpreted); - WasmRunner<double> r(&module, MachineType::Float64()); + WasmRunner<double, double> r(kExecuteInterpreted); BUILD(r, WASM_F64_SQRT(WASM_GET_LOCAL(0))); r.Call(1048575.5); CHECK(!r.possible_nondeterminism()); @@ -391,9 +389,7 @@ TEST(TestPossibleNondeterminism) { } { // F64Mul may produced NaN - TestingModule module(kExecuteInterpreted); - WasmRunner<double> r(&module, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<double, double, double> r(kExecuteInterpreted); BUILD(r, WASM_F64_MUL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); r.Call(1048575.5, 2.5); CHECK(!r.possible_nondeterminism()); diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-js.cc b/deps/v8/test/cctest/wasm/test-run-wasm-js.cc index 4a74128f50..ee6b066282 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-js.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-js.cc @@ -97,48 +97,36 @@ void EXPECT_CALL(double expected, Handle<JSFunction> jsfunc, double a, } // namespace TEST(Run_Int32Sub_jswrapped) { - CcTest::InitializeVM(); - TestSignatures sigs; - TestingModule module; - WasmFunctionCompiler t(sigs.i_ii(), &module); - BUILD(t, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + WasmRunner<int, int, int> r(kExecuteCompiled); + BUILD(r, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); + Handle<JSFunction> jsfunc = r.module().WrapCode(r.function()->func_index); EXPECT_CALL(33, jsfunc, 44, 11); EXPECT_CALL(-8723487, jsfunc, -8000000, 723487); } TEST(Run_Float32Div_jswrapped) { - CcTest::InitializeVM(); - TestSignatures sigs; - TestingModule module; - WasmFunctionCompiler t(sigs.f_ff(), &module); - BUILD(t, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + WasmRunner<float, float, float> r(kExecuteCompiled); + BUILD(r, WASM_F32_DIV(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); + Handle<JSFunction> jsfunc = r.module().WrapCode(r.function()->func_index); EXPECT_CALL(92, jsfunc, 46, 0.5); EXPECT_CALL(64, jsfunc, -16, -0.25); } TEST(Run_Float64Add_jswrapped) { - CcTest::InitializeVM(); - TestSignatures sigs; - TestingModule module; - WasmFunctionCompiler t(sigs.d_dd(), &module); - BUILD(t, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + WasmRunner<double, double, double> r(kExecuteCompiled); + BUILD(r, WASM_F64_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); + Handle<JSFunction> jsfunc = r.module().WrapCode(r.function()->func_index); EXPECT_CALL(3, jsfunc, 2, 1); EXPECT_CALL(-5.5, jsfunc, -5.25, -0.25); } TEST(Run_I32Popcount_jswrapped) { - CcTest::InitializeVM(); - TestSignatures sigs; - TestingModule module; - WasmFunctionCompiler t(sigs.i_i(), &module); - BUILD(t, WASM_I32_POPCNT(WASM_GET_LOCAL(0))); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + WasmRunner<int, int> r(kExecuteCompiled); + BUILD(r, WASM_I32_POPCNT(WASM_GET_LOCAL(0))); + Handle<JSFunction> jsfunc = r.module().WrapCode(r.function()->func_index); EXPECT_CALL(2, jsfunc, 9, 0); EXPECT_CALL(3, jsfunc, 11, 0); @@ -146,15 +134,13 @@ TEST(Run_I32Popcount_jswrapped) { } TEST(Run_CallJS_Add_jswrapped) { - CcTest::InitializeVM(); + WasmRunner<int, int> r(kExecuteCompiled); TestSignatures sigs; - TestingModule module; - WasmFunctionCompiler t(sigs.i_i(), &module); uint32_t js_index = - module.AddJsFunction(sigs.i_i(), "(function(a) { return a + 99; })"); - BUILD(t, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0))); + r.module().AddJsFunction(sigs.i_i(), "(function(a) { return a + 99; })"); + BUILD(r, WASM_CALL_FUNCTION(js_index, WASM_GET_LOCAL(0))); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + Handle<JSFunction> jsfunc = r.module().WrapCode(r.function()->func_index); EXPECT_CALL(101, jsfunc, 2, -8); EXPECT_CALL(199, jsfunc, 100, -1); @@ -164,16 +150,16 @@ TEST(Run_CallJS_Add_jswrapped) { void RunJSSelectTest(int which) { const int kMaxParams = 8; PredictableInputValues inputs(0x100); - LocalType type = kAstF64; - LocalType types[kMaxParams + 1] = {type, type, type, type, type, + ValueType type = kWasmF64; + ValueType types[kMaxParams + 1] = {type, type, type, type, type, type, type, type, type}; for (int num_params = which + 1; num_params < kMaxParams; num_params++) { HandleScope scope(CcTest::InitIsolateOnce()); FunctionSig sig(1, num_params, types); - TestingModule module; - uint32_t js_index = AddJSSelector(&module, &sig, which); - WasmFunctionCompiler t(&sig, &module); + WasmRunner<void> r(kExecuteCompiled); + uint32_t js_index = AddJSSelector(&r.module(), &sig, which); + WasmFunctionCompiler& t = r.NewFunction(&sig); { std::vector<byte> code; @@ -189,7 +175,7 @@ void RunJSSelectTest(int which) { t.Build(&code[0], &code[end]); } - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + Handle<JSFunction> jsfunc = r.module().WrapCode(t.function_index()); double expected = inputs.arg_d(which); EXPECT_CALL(expected, jsfunc, 0.0, 0.0); } @@ -240,15 +226,15 @@ void RunWASMSelectTest(int which) { Isolate* isolate = CcTest::InitIsolateOnce(); const int kMaxParams = 8; for (int num_params = which + 1; num_params < kMaxParams; num_params++) { - LocalType type = kAstF64; - LocalType types[kMaxParams + 1] = {type, type, type, type, type, + ValueType type = kWasmF64; + ValueType types[kMaxParams + 1] = {type, type, type, type, type, type, type, type, type}; FunctionSig sig(1, num_params, types); - TestingModule module; - WasmFunctionCompiler t(&sig, &module); + WasmRunner<void> r(kExecuteCompiled); + WasmFunctionCompiler& t = r.NewFunction(&sig); BUILD(t, WASM_GET_LOCAL(which)); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + Handle<JSFunction> jsfunc = r.module().WrapCode(t.function_index()); Handle<Object> args[] = { isolate->factory()->NewNumber(inputs.arg_d(0)), @@ -311,16 +297,16 @@ void RunWASMSelectAlignTest(int num_args, int num_params) { Isolate* isolate = CcTest::InitIsolateOnce(); const int kMaxParams = 10; DCHECK_LE(num_args, kMaxParams); - LocalType type = kAstF64; - LocalType types[kMaxParams + 1] = {type, type, type, type, type, type, + ValueType type = kWasmF64; + ValueType types[kMaxParams + 1] = {type, type, type, type, type, type, type, type, type, type, type}; FunctionSig sig(1, num_params, types); for (int which = 0; which < num_params; which++) { - TestingModule module; - WasmFunctionCompiler t(&sig, &module); + WasmRunner<void> r(kExecuteCompiled); + WasmFunctionCompiler& t = r.NewFunction(&sig); BUILD(t, WASM_GET_LOCAL(which)); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + Handle<JSFunction> jsfunc = r.module().WrapCode(t.function_index()); Handle<Object> args[] = {isolate->factory()->NewNumber(inputs.arg_d(0)), isolate->factory()->NewNumber(inputs.arg_d(1)), @@ -407,10 +393,12 @@ void RunJSSelectAlignTest(int num_args, int num_params) { const int kMaxParams = 10; CHECK_LE(num_args, kMaxParams); CHECK_LE(num_params, kMaxParams); - LocalType type = kAstF64; - LocalType types[kMaxParams + 1] = {type, type, type, type, type, type, + ValueType type = kWasmF64; + ValueType types[kMaxParams + 1] = {type, type, type, type, type, type, type, type, type, type, type}; FunctionSig sig(1, num_params, types); + i::AccountingAllocator allocator; + Zone zone(&allocator, ZONE_NAME); // Build the calling code. std::vector<byte> code; @@ -419,21 +407,21 @@ void RunJSSelectAlignTest(int num_args, int num_params) { ADD_CODE(code, WASM_GET_LOCAL(i)); } - ADD_CODE(code, kExprCallFunction, 0); + uint8_t predicted_js_index = 1; + ADD_CODE(code, kExprCallFunction, predicted_js_index); size_t end = code.size(); code.push_back(0); // Call different select JS functions. for (int which = 0; which < num_params; which++) { - HandleScope scope(isolate); - TestingModule module; - uint32_t js_index = AddJSSelector(&module, &sig, which); - CHECK_EQ(0u, js_index); - WasmFunctionCompiler t(&sig, &module); + WasmRunner<void> r(kExecuteCompiled); + uint32_t js_index = AddJSSelector(&r.module(), &sig, which); + CHECK_EQ(predicted_js_index, js_index); + WasmFunctionCompiler& t = r.NewFunction(&sig); t.Build(&code[0], &code[end]); - Handle<JSFunction> jsfunc = module.WrapCode(t.CompileAndAdd()); + Handle<JSFunction> jsfunc = r.module().WrapCode(t.function_index()); Handle<Object> args[] = { factory->NewNumber(inputs.arg_d(0)), diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-module.cc b/deps/v8/test/cctest/wasm/test-run-wasm-module.cc index 94054bd388..468dc81159 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-module.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-module.cc @@ -63,6 +63,12 @@ void TestModuleException(Zone* zone, WasmModuleBuilder* builder) { void ExportAsMain(WasmFunctionBuilder* f) { f->ExportAs(CStrVector("main")); } +#define EMIT_CODE_WITH_END(f, code) \ + do { \ + f->EmitCode(code, sizeof(code)); \ + f->Emit(kExprEnd); \ + } while (false) + } // namespace TEST(Run_WasmModule_Return114) { @@ -75,8 +81,8 @@ TEST(Run_WasmModule_Return114) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); ExportAsMain(f); - byte code[] = {WASM_I8(kReturnValue)}; - f->EmitCode(code, sizeof(code)); + byte code[] = {WASM_I32V_2(kReturnValue)}; + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, kReturnValue); } Cleanup(); @@ -95,14 +101,14 @@ TEST(Run_WasmModule_CallAdd) { uint16_t param2 = 1; byte code1[] = { WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))}; - f1->EmitCode(code1, sizeof(code1)); + EMIT_CODE_WITH_END(f1, code1); WasmFunctionBuilder* f2 = builder->AddFunction(sigs.i_v()); ExportAsMain(f2); byte code2[] = { - WASM_CALL_FUNCTION(f1->func_index(), WASM_I8(77), WASM_I8(22))}; - f2->EmitCode(code2, sizeof(code2)); + WASM_CALL_FUNCTION(f1->func_index(), WASM_I32V_2(77), WASM_I32V_1(22))}; + EMIT_CODE_WITH_END(f2, code2); TestModule(&zone, builder, 99); } Cleanup(); @@ -120,8 +126,8 @@ TEST(Run_WasmModule_ReadLoadedDataSegment) { ExportAsMain(f); byte code[] = { - WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))}; - f->EmitCode(code, sizeof(code)); + WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(kDataSegmentDest0))}; + EMIT_CODE_WITH_END(f, code); byte data[] = {0xaa, 0xbb, 0xcc, 0xdd}; builder->AddDataSegment(data, sizeof(data), kDataSegmentDest0); TestModule(&zone, builder, 0xddccbbaa); @@ -139,16 +145,17 @@ TEST(Run_WasmModule_CheckMemoryIsZero) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); - uint16_t localIndex = f->AddLocal(kAstI32); + uint16_t localIndex = f->AddLocal(kWasmI32); ExportAsMain(f); byte code[] = {WASM_BLOCK_I( WASM_WHILE( WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I32V_3(kCheckSize)), WASM_IF_ELSE( WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)), - WASM_BRV(3, WASM_I8(-1)), WASM_INC_LOCAL_BY(localIndex, 4))), - WASM_I8(11))}; - f->EmitCode(code, sizeof(code)); + WASM_BRV(3, WASM_I32V_1(-1)), + WASM_INC_LOCAL_BY(localIndex, 4))), + WASM_I32V_1(11))}; + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, 11); } Cleanup(); @@ -163,17 +170,17 @@ TEST(Run_WasmModule_CallMain_recursive) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); - uint16_t localIndex = f->AddLocal(kAstI32); + uint16_t localIndex = f->AddLocal(kWasmI32); ExportAsMain(f); byte code[] = { WASM_SET_LOCAL(localIndex, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)), - WASM_IF_ELSE_I(WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I8(5)), + WASM_IF_ELSE_I(WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I32V_1(5)), WASM_SEQ(WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_INC_LOCAL(localIndex)), WASM_CALL_FUNCTION0(0)), - WASM_I8(55))}; - f->EmitCode(code, sizeof(code)); + WASM_I32V_1(55))}; + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, 55); } Cleanup(); @@ -186,18 +193,18 @@ TEST(Run_WasmModule_Global) { TestSignatures sigs; WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); - uint32_t global1 = builder->AddGlobal(kAstI32, 0); - uint32_t global2 = builder->AddGlobal(kAstI32, 0); + uint32_t global1 = builder->AddGlobal(kWasmI32, 0); + uint32_t global2 = builder->AddGlobal(kWasmI32, 0); WasmFunctionBuilder* f1 = builder->AddFunction(sigs.i_v()); byte code1[] = { WASM_I32_ADD(WASM_GET_GLOBAL(global1), WASM_GET_GLOBAL(global2))}; - f1->EmitCode(code1, sizeof(code1)); + EMIT_CODE_WITH_END(f1, code1); WasmFunctionBuilder* f2 = builder->AddFunction(sigs.i_v()); ExportAsMain(f2); byte code2[] = {WASM_SET_GLOBAL(global1, WASM_I32V_1(56)), WASM_SET_GLOBAL(global2, WASM_I32V_1(41)), WASM_RETURN1(WASM_CALL_FUNCTION0(f1->func_index()))}; - f2->EmitCode(code2, sizeof(code2)); + EMIT_CODE_WITH_END(f2, code2); TestModule(&zone, builder, 97); } Cleanup(); @@ -211,6 +218,18 @@ class WasmSerializationTest { SetUp(); } + static void BuildWireBytes(Zone* zone, ZoneBuffer* buffer) { + WasmModuleBuilder* builder = new (zone) WasmModuleBuilder(zone); + TestSignatures sigs; + + WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i()); + byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add}; + EMIT_CODE_WITH_END(f, code); + f->ExportAs(CStrVector(kFunctionName)); + + builder->WriteTo(*buffer); + } + void ClearSerializedData() { serialized_bytes_.first = nullptr; serialized_bytes_.second = 0; @@ -239,8 +258,8 @@ class WasmSerializationTest { ErrorThrower thrower(current_isolate(), ""); v8::Local<v8::WasmCompiledModule> deserialized_module; CHECK(Deserialize().ToLocal(&deserialized_module)); - Handle<JSObject> module_object = - Handle<JSObject>::cast(v8::Utils::OpenHandle(*deserialized_module)); + Handle<WasmModuleObject> module_object = Handle<WasmModuleObject>::cast( + v8::Utils::OpenHandle(*deserialized_module)); { DisallowHeapAllocation assume_no_gc; Handle<WasmCompiledModule> compiled_part( @@ -272,6 +291,8 @@ class WasmSerializationTest { TearDown(); } + v8::Isolate* current_isolate_v8() { return current_isolate_v8_; } + private: static const char* kFunctionName; @@ -284,19 +305,17 @@ class WasmSerializationTest { return serialized_bytes_; } - v8::Isolate* current_isolate_v8() { return current_isolate_v8_; } - void SetUp() { WasmModuleBuilder* builder = new (zone()) WasmModuleBuilder(zone()); TestSignatures sigs; WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i()); byte code[] = {WASM_GET_LOCAL(0), kExprI32Const, 1, kExprI32Add}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); f->ExportAs(CStrVector(kFunctionName)); ZoneBuffer buffer(&zone_); - builder->WriteTo(buffer); + WasmSerializationTest::BuildWireBytes(zone(), &buffer); Isolate* serialization_isolate = CcTest::InitIsolateOnce(); ErrorThrower thrower(serialization_isolate, ""); @@ -315,8 +334,10 @@ class WasmSerializationTest { serialization_isolate, const_cast<WasmModule*>(decoding_result.val)); MaybeHandle<WasmCompiledModule> compiled_module = - decoding_result.val->CompileFunctions(serialization_isolate, - module_wrapper, &thrower); + decoding_result.val->CompileFunctions( + serialization_isolate, module_wrapper, &thrower, + ModuleWireBytes(buffer.begin(), buffer.end()), + Handle<Script>::null(), Vector<const byte>::empty()); CHECK(!compiled_module.is_null()); Handle<JSObject> module_obj = WasmModuleObject::New( serialization_isolate, compiled_module.ToHandleChecked()); @@ -410,6 +431,40 @@ TEST(DeserializeWireBytesAndSerializedDataInvalid) { Cleanup(); } +bool False(v8::Local<v8::Context> context) { return false; } + +TEST(BlockWasmCodeGen) { + v8::internal::AccountingAllocator allocator; + Zone zone(&allocator, ZONE_NAME); + ZoneBuffer buffer(&zone); + WasmSerializationTest::BuildWireBytes(&zone, &buffer); + Isolate* isolate = CcTest::InitIsolateOnce(); + HandleScope scope(isolate); + testing::SetupIsolateForWasmModule(isolate); + CcTest::isolate()->SetAllowCodeGenerationFromStringsCallback(False); + + ErrorThrower thrower(isolate, "block codegen"); + MaybeHandle<WasmModuleObject> ret = wasm::CreateModuleObjectFromBytes( + isolate, buffer.begin(), buffer.end(), &thrower, + wasm::ModuleOrigin::kWasmOrigin, Handle<v8::internal::Script>::null(), + Vector<const byte>::empty()); + CcTest::isolate()->SetAllowCodeGenerationFromStringsCallback(nullptr); + CHECK(ret.is_null()); + CHECK(thrower.error()); +} + +TEST(BlockWasmCodeGenAtDeserialization) { + WasmSerializationTest test; + { + HandleScope scope(test.current_isolate()); + test.current_isolate_v8()->SetAllowCodeGenerationFromStringsCallback(False); + v8::MaybeLocal<v8::WasmCompiledModule> nothing = test.Deserialize(); + CHECK(nothing.IsEmpty()); + } + Cleanup(test.current_isolate()); + Cleanup(); +} + TEST(MemorySize) { { // Initial memory size is 16, see wasm-module-builder.cc @@ -422,7 +477,7 @@ TEST(MemorySize) { WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); ExportAsMain(f); byte code[] = {WASM_MEMORY_SIZE}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, kExpectedValue); } Cleanup(); @@ -439,8 +494,9 @@ TEST(Run_WasmModule_MemSize_GrowMem) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); ExportAsMain(f); - byte code[] = {WASM_GROW_MEMORY(WASM_I8(10)), WASM_DROP, WASM_MEMORY_SIZE}; - f->EmitCode(code, sizeof(code)); + byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(10)), WASM_DROP, + WASM_MEMORY_SIZE}; + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, kExpectedValue); } Cleanup(); @@ -458,7 +514,7 @@ TEST(GrowMemoryZero) { WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); ExportAsMain(f); byte code[] = {WASM_GROW_MEMORY(WASM_I32V(0))}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, kExpectedValue); } Cleanup(); @@ -529,14 +585,14 @@ TEST(TestInterruptLoop) { WASM_I32V(InterruptThread::signal_value_)), WASM_BR(1))), WASM_I32V(121)}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); ZoneBuffer buffer(&zone); builder->WriteTo(buffer); HandleScope scope(isolate); testing::SetupIsolateForWasmModule(isolate); ErrorThrower thrower(isolate, "Test"); - const Handle<JSObject> instance = + const Handle<WasmInstanceObject> instance = testing::CompileInstantiateWasmModuleForTesting( isolate, &thrower, buffer.begin(), buffer.end(), ModuleOrigin::kWasmOrigin); @@ -568,7 +624,7 @@ TEST(Run_WasmModule_GrowMemoryInIf) { ExportAsMain(f); byte code[] = {WASM_IF_ELSE_I(WASM_I32V(0), WASM_GROW_MEMORY(WASM_I32V(1)), WASM_I32V(12))}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); TestModule(&zone, builder, 12); } Cleanup(); @@ -587,10 +643,10 @@ TEST(Run_WasmModule_GrowMemOobOffset) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_v()); ExportAsMain(f); - byte code[] = {WASM_GROW_MEMORY(WASM_I8(1)), + byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(1)), WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index), WASM_I32V(value))}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); TestModuleException(&zone, builder); } Cleanup(); @@ -613,7 +669,7 @@ TEST(Run_WasmModule_GrowMemOobFixedIndex) { WASM_STORE_MEM(MachineType::Int32(), WASM_I32V(index), WASM_I32V(value)), WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V(index))}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); HandleScope scope(isolate); ZoneBuffer buffer(&zone); @@ -657,11 +713,11 @@ TEST(Run_WasmModule_GrowMemOobVariableIndex) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i()); ExportAsMain(f); - byte code[] = {WASM_GROW_MEMORY(WASM_I8(1)), WASM_DROP, + byte code[] = {WASM_GROW_MEMORY(WASM_I32V_1(1)), WASM_DROP, WASM_STORE_MEM(MachineType::Int32(), WASM_GET_LOCAL(0), WASM_I32V(value)), WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))}; - f->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f, code); HandleScope scope(isolate); ZoneBuffer buffer(&zone); @@ -714,13 +770,13 @@ TEST(Run_WasmModule_Global_init) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); uint32_t global1 = - builder->AddGlobal(kAstI32, false, false, WasmInitExpr(777777)); + builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(777777)); uint32_t global2 = - builder->AddGlobal(kAstI32, false, false, WasmInitExpr(222222)); + builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(222222)); WasmFunctionBuilder* f1 = builder->AddFunction(sigs.i_v()); byte code[] = { WASM_I32_ADD(WASM_GET_GLOBAL(global1), WASM_GET_GLOBAL(global2))}; - f1->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f1, code); ExportAsMain(f1); TestModule(&zone, builder, 999999); } @@ -728,13 +784,13 @@ TEST(Run_WasmModule_Global_init) { } template <typename CType> -static void RunWasmModuleGlobalInitTest(LocalType type, CType expected) { +static void RunWasmModuleGlobalInitTest(ValueType type, CType expected) { { v8::internal::AccountingAllocator allocator; Zone zone(&allocator, ZONE_NAME); TestSignatures sigs; - LocalType types[] = {type}; + ValueType types[] = {type}; FunctionSig sig(1, 0, types); for (int padding = 0; padding < 5; padding++) { @@ -742,17 +798,17 @@ static void RunWasmModuleGlobalInitTest(LocalType type, CType expected) { WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); for (int i = 0; i < padding; i++) { // pad global before - builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 20000)); + builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(i + 20000)); } uint32_t global = builder->AddGlobal(type, false, false, WasmInitExpr(expected)); for (int i = 0; i < padding; i++) { // pad global after - builder->AddGlobal(kAstI32, false, false, WasmInitExpr(i + 30000)); + builder->AddGlobal(kWasmI32, false, false, WasmInitExpr(i + 30000)); } WasmFunctionBuilder* f1 = builder->AddFunction(&sig); byte code[] = {WASM_GET_GLOBAL(global)}; - f1->EmitCode(code, sizeof(code)); + EMIT_CODE_WITH_END(f1, code); ExportAsMain(f1); TestModule(&zone, builder, expected); } @@ -761,18 +817,18 @@ static void RunWasmModuleGlobalInitTest(LocalType type, CType expected) { } TEST(Run_WasmModule_Global_i32) { - RunWasmModuleGlobalInitTest<int32_t>(kAstI32, -983489); - RunWasmModuleGlobalInitTest<int32_t>(kAstI32, 11223344); + RunWasmModuleGlobalInitTest<int32_t>(kWasmI32, -983489); + RunWasmModuleGlobalInitTest<int32_t>(kWasmI32, 11223344); } TEST(Run_WasmModule_Global_f32) { - RunWasmModuleGlobalInitTest<float>(kAstF32, -983.9f); - RunWasmModuleGlobalInitTest<float>(kAstF32, 1122.99f); + RunWasmModuleGlobalInitTest<float>(kWasmF32, -983.9f); + RunWasmModuleGlobalInitTest<float>(kWasmF32, 1122.99f); } TEST(Run_WasmModule_Global_f64) { - RunWasmModuleGlobalInitTest<double>(kAstF64, -833.9); - RunWasmModuleGlobalInitTest<double>(kAstF64, 86374.25); + RunWasmModuleGlobalInitTest<double>(kWasmF64, -833.9); + RunWasmModuleGlobalInitTest<double>(kWasmF64, 86374.25); } TEST(InitDataAtTheUpperLimit) { @@ -867,7 +923,7 @@ TEST(EmptyMemoryEmptyDataSegment) { U32V_1(6), // section size ENTRY_COUNT(1), // -- 0, // linear memory index - WASM_I32V_1(24), // destination offset + WASM_I32V_1(0), // destination offset kExprEnd, U32V_1(0), // source size }; @@ -909,8 +965,8 @@ TEST(MemoryWithOOBEmptyDataSegment) { testing::CompileInstantiateWasmModuleForTesting(isolate, &thrower, data, data + arraysize(data), ModuleOrigin::kWasmOrigin); - // It should be possible to instantiate this module. - CHECK(!thrower.error()); + // It should not be possible to instantiate this module. + CHECK(thrower.error()); } Cleanup(); } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-relocation.cc b/deps/v8/test/cctest/wasm/test-run-wasm-relocation.cc index 614e9a4ba5..f34a1a323e 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-relocation.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-relocation.cc @@ -13,31 +13,29 @@ using namespace v8::internal; using namespace v8::internal::compiler; -#define FOREACH_TYPE(TEST_BODY) \ - TEST_BODY(int32_t, I32, WASM_I32_ADD) \ - TEST_BODY(int64_t, I64, WASM_I64_ADD) \ - TEST_BODY(float, F32, WASM_F32_ADD) \ - TEST_BODY(double, F64, WASM_F64_ADD) +#define FOREACH_TYPE(TEST_BODY) \ + TEST_BODY(int32_t, WASM_I32_ADD) \ + TEST_BODY(int64_t, WASM_I64_ADD) \ + TEST_BODY(float, WASM_F32_ADD) \ + TEST_BODY(double, WASM_F64_ADD) -#define LOAD_SET_GLOBAL_TEST_BODY(C_TYPE, MACHINE_TYPE, ADD) \ - TEST(WasmRelocateGlobal##MACHINE_TYPE) { \ - TestingModule module(kExecuteCompiled); \ - module.AddGlobal<C_TYPE>(kAst##MACHINE_TYPE); \ - module.AddGlobal<C_TYPE>(kAst##MACHINE_TYPE); \ +#define LOAD_SET_GLOBAL_TEST_BODY(C_TYPE, ADD) \ + TEST(WasmRelocateGlobal_##C_TYPE) { \ + WasmRunner<C_TYPE, C_TYPE> r(kExecuteCompiled); \ \ - WasmRunner<C_TYPE> r(&module, \ - WasmOpcodes::MachineTypeFor(kAst##MACHINE_TYPE)); \ + r.module().AddGlobal<C_TYPE>(); \ + r.module().AddGlobal<C_TYPE>(); \ \ /* global = global + p0 */ \ BUILD(r, WASM_SET_GLOBAL(1, ADD(WASM_GET_GLOBAL(0), WASM_GET_LOCAL(0))), \ WASM_GET_GLOBAL(0)); \ - CHECK_EQ(1u, module.instance->function_code.size()); \ + CHECK_EQ(1, r.module().instance->function_code.size()); \ \ int filter = 1 << RelocInfo::WASM_GLOBAL_REFERENCE; \ \ - Handle<Code> code = module.instance->function_code[0]; \ + Handle<Code> code = r.module().instance->function_code[0]; \ \ - Address old_start = module.instance->globals_start; \ + Address old_start = r.module().instance->globals_start; \ Address new_start = old_start + 1; \ \ Address old_addresses[4]; \ diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-simd-lowering.cc b/deps/v8/test/cctest/wasm/test-run-wasm-simd-lowering.cc index 69e770b9b8..706de8de35 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-simd-lowering.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-simd-lowering.cc @@ -15,82 +15,282 @@ using namespace v8::internal; using namespace v8::internal::compiler; using namespace v8::internal::wasm; -WASM_EXEC_TEST(Simd_I32x4_Splat) { +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Splat) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t> r(kExecuteCompiled); BUILD(r, WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(5)))); FOR_INT32_INPUTS(i) { CHECK_EQ(5, r.Call()); } } -WASM_EXEC_TEST(Simd_I32x4_Add) { +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Add) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t> r(kExecuteCompiled); BUILD(r, WASM_SIMD_I32x4_EXTRACT_LANE( 0, WASM_SIMD_I32x4_ADD(WASM_SIMD_I32x4_SPLAT(WASM_I32V(5)), WASM_SIMD_I32x4_SPLAT(WASM_I32V(6))))); FOR_INT32_INPUTS(i) { CHECK_EQ(11, r.Call()); } } -WASM_EXEC_TEST(Simd_F32x4_Splat) { +WASM_EXEC_COMPILED_TEST(Simd_F32x4_Splat) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t> r(kExecuteCompiled); BUILD(r, - WASM_IF_ELSE(WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE( - 0, WASM_SIMD_F32x4_SPLAT(WASM_F32(9.5))), - WASM_F32(9.5)), - WASM_RETURN1(WASM_I32V(1)), WASM_RETURN1(WASM_I32V(0)))); + WASM_IF_ELSE_I(WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE( + 0, WASM_SIMD_F32x4_SPLAT(WASM_F32(9.5))), + WASM_F32(9.5)), + WASM_I32V(1), WASM_I32V(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } } -WASM_EXEC_TEST(Simd_I32x4_Extract_With_F32x4) { +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Extract_With_F32x4) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); - BUILD(r, - WASM_IF_ELSE(WASM_I32_EQ(WASM_SIMD_I32x4_EXTRACT_LANE( - 0, WASM_SIMD_F32x4_SPLAT(WASM_F32(30.5))), - WASM_I32_REINTERPRET_F32(WASM_F32(30.5))), - WASM_RETURN1(WASM_I32V(1)), WASM_RETURN1(WASM_I32V(0)))); + WasmRunner<int32_t> r(kExecuteCompiled); + BUILD(r, WASM_IF_ELSE_I( + WASM_I32_EQ(WASM_SIMD_I32x4_EXTRACT_LANE( + 0, WASM_SIMD_F32x4_SPLAT(WASM_F32(30.5))), + WASM_I32_REINTERPRET_F32(WASM_F32(30.5))), + WASM_I32V(1), WASM_I32V(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } } -WASM_EXEC_TEST(Simd_F32x4_Extract_With_I32x4) { +WASM_EXEC_COMPILED_TEST(Simd_F32x4_Extract_With_I32x4) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t> r(kExecuteCompiled); BUILD(r, - WASM_IF_ELSE(WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE( - 0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(15))), - WASM_F32_REINTERPRET_I32(WASM_I32V(15))), - WASM_RETURN1(WASM_I32V(1)), WASM_RETURN1(WASM_I32V(0)))); + WASM_IF_ELSE_I(WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE( + 0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(15))), + WASM_F32_REINTERPRET_I32(WASM_I32V(15))), + WASM_I32V(1), WASM_I32V(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } } -WASM_EXEC_TEST(Simd_F32x4_Add_With_I32x4) { +WASM_EXEC_COMPILED_TEST(Simd_F32x4_Add_With_I32x4) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t> r(kExecuteCompiled); BUILD(r, - WASM_IF_ELSE( + WASM_IF_ELSE_I( WASM_F32_EQ(WASM_SIMD_F32x4_EXTRACT_LANE( 0, WASM_SIMD_F32x4_ADD( WASM_SIMD_I32x4_SPLAT(WASM_I32V(32)), WASM_SIMD_I32x4_SPLAT(WASM_I32V(19)))), WASM_F32_ADD(WASM_F32_REINTERPRET_I32(WASM_I32V(32)), WASM_F32_REINTERPRET_I32(WASM_I32V(19)))), - WASM_RETURN1(WASM_I32V(1)), WASM_RETURN1(WASM_I32V(0)))); + WASM_I32V(1), WASM_I32V(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } } -WASM_EXEC_TEST(Simd_I32x4_Add_With_F32x4) { +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Add_With_F32x4) { FLAG_wasm_simd_prototype = true; - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t> r(kExecuteCompiled); BUILD(r, - WASM_IF_ELSE( + WASM_IF_ELSE_I( WASM_I32_EQ(WASM_SIMD_I32x4_EXTRACT_LANE( 0, WASM_SIMD_I32x4_ADD( WASM_SIMD_F32x4_SPLAT(WASM_F32(21.25)), WASM_SIMD_F32x4_SPLAT(WASM_F32(31.5)))), WASM_I32_ADD(WASM_I32_REINTERPRET_F32(WASM_F32(21.25)), WASM_I32_REINTERPRET_F32(WASM_F32(31.5)))), - WASM_RETURN1(WASM_I32V(1)), WASM_RETURN1(WASM_I32V(0)))); + WASM_I32V(1), WASM_I32V(0))); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } +} + +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Local) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t> r(kExecuteCompiled); + r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))), + + WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(0))); + FOR_INT32_INPUTS(i) { CHECK_EQ(31, r.Call()); } +} + +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Replace_Lane) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t> r(kExecuteCompiled); + r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))), + WASM_SET_LOCAL(0, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_LOCAL(0), + WASM_I32V(53))), + WASM_SIMD_I32x4_EXTRACT_LANE(2, WASM_GET_LOCAL(0))); + FOR_INT32_INPUTS(i) { CHECK_EQ(53, r.Call()); } +} + +WASM_EXEC_COMPILED_TEST(Simd_F32x4_Replace_Lane) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t> r(kExecuteCompiled); + r.AllocateLocal(kWasmF32); + r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(1, WASM_SIMD_F32x4_SPLAT(WASM_F32(23.5))), + WASM_SET_LOCAL(1, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(1), + WASM_F32(65.25))), + WASM_SET_LOCAL(0, WASM_SIMD_F32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1))), + WASM_IF(WASM_F32_EQ(WASM_GET_LOCAL(0), WASM_F32(65.25)), + WASM_RETURN1(WASM_I32V(1))), + WASM_I32V(0)); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } +} + +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Splat_From_Extract) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t> r(kExecuteCompiled); + r.AllocateLocal(kWasmI32); + r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(0, WASM_SIMD_I32x4_EXTRACT_LANE( + 0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(76)))), + WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))), + WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1))); + FOR_INT32_INPUTS(i) { CHECK_EQ(76, r.Call()); } +} + +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Get_Global) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + int32_t* global = r.module().AddGlobal<int32_t>(kWasmS128); + *(global) = 0; + *(global + 1) = 1; + *(global + 2) = 2; + *(global + 3) = 3; + r.AllocateLocal(kWasmI32); + BUILD( + r, WASM_SET_LOCAL(1, WASM_I32V(1)), + WASM_IF(WASM_I32_NE(WASM_I32V(0), + WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_IF(WASM_I32_NE(WASM_I32V(1), + WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_IF(WASM_I32_NE(WASM_I32V(2), + WASM_SIMD_I32x4_EXTRACT_LANE(2, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_IF(WASM_I32_NE(WASM_I32V(3), + WASM_SIMD_I32x4_EXTRACT_LANE(3, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_GET_LOCAL(1)); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(0)); } +} + +WASM_EXEC_COMPILED_TEST(Simd_I32x4_Set_Global) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + int32_t* global = r.module().AddGlobal<int32_t>(kWasmS128); + BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_SPLAT(WASM_I32V(23))), + WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_GLOBAL(0), + WASM_I32V(34))), + WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_GLOBAL(0), + WASM_I32V(45))), + WASM_SET_GLOBAL(0, WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(0), + WASM_I32V(56))), + WASM_I32V(1)); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(0)); } + CHECK_EQ(*global, 23); + CHECK_EQ(*(global + 1), 34); + CHECK_EQ(*(global + 2), 45); + CHECK_EQ(*(global + 3), 56); +} + +WASM_EXEC_COMPILED_TEST(Simd_F32x4_Get_Global) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + float* global = r.module().AddGlobal<float>(kWasmS128); + *(global) = 0.0; + *(global + 1) = 1.5; + *(global + 2) = 2.25; + *(global + 3) = 3.5; + r.AllocateLocal(kWasmI32); + BUILD( + r, WASM_SET_LOCAL(1, WASM_I32V(1)), + WASM_IF(WASM_F32_NE(WASM_F32(0.0), + WASM_SIMD_F32x4_EXTRACT_LANE(0, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_IF(WASM_F32_NE(WASM_F32(1.5), + WASM_SIMD_F32x4_EXTRACT_LANE(1, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_IF(WASM_F32_NE(WASM_F32(2.25), + WASM_SIMD_F32x4_EXTRACT_LANE(2, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_IF(WASM_F32_NE(WASM_F32(3.5), + WASM_SIMD_F32x4_EXTRACT_LANE(3, WASM_GET_GLOBAL(0))), + WASM_SET_LOCAL(1, WASM_I32V(0))), + WASM_GET_LOCAL(1)); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(0)); } +} + +WASM_EXEC_COMPILED_TEST(Simd_F32x4_Set_Global) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + float* global = r.module().AddGlobal<float>(kWasmS128); + BUILD(r, WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_SPLAT(WASM_F32(13.5))), + WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_GLOBAL(0), + WASM_F32(45.5))), + WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_GLOBAL(0), + WASM_F32(32.25))), + WASM_SET_GLOBAL(0, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_GLOBAL(0), + WASM_F32(65.0))), + WASM_I32V(1)); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(0)); } + CHECK_EQ(*global, 13.5); + CHECK_EQ(*(global + 1), 45.5); + CHECK_EQ(*(global + 2), 32.25); + CHECK_EQ(*(global + 3), 65.0); +} + +WASM_EXEC_COMPILED_TEST(Simd_I32x4_For) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t> r(kExecuteCompiled); + r.AllocateLocal(kWasmI32); + r.AllocateLocal(kWasmS128); + BUILD(r, + + WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_I32V(31))), + WASM_SET_LOCAL(1, WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_LOCAL(1), + WASM_I32V(53))), + WASM_SET_LOCAL(1, WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_LOCAL(1), + WASM_I32V(23))), + WASM_SET_LOCAL(0, WASM_I32V(0)), + WASM_LOOP( + WASM_SET_LOCAL( + 1, WASM_SIMD_I32x4_ADD(WASM_GET_LOCAL(1), + WASM_SIMD_I32x4_SPLAT(WASM_I32V(1)))), + WASM_IF(WASM_I32_NE(WASM_INC_LOCAL(0), WASM_I32V(5)), WASM_BR(1))), + WASM_SET_LOCAL(0, WASM_I32V(1)), + WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(1)), + WASM_I32V(36)), + WASM_SET_LOCAL(0, WASM_I32V(0))), + WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(1, WASM_GET_LOCAL(1)), + WASM_I32V(58)), + WASM_SET_LOCAL(0, WASM_I32V(0))), + WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(2, WASM_GET_LOCAL(1)), + WASM_I32V(28)), + WASM_SET_LOCAL(0, WASM_I32V(0))), + WASM_IF(WASM_I32_NE(WASM_SIMD_I32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1)), + WASM_I32V(36)), + WASM_SET_LOCAL(0, WASM_I32V(0))), + WASM_GET_LOCAL(0)); + FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } +} + +WASM_EXEC_COMPILED_TEST(Simd_F32x4_For) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t> r(kExecuteCompiled); + r.AllocateLocal(kWasmI32); + r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(1, WASM_SIMD_F32x4_SPLAT(WASM_F32(21.25))), + WASM_SET_LOCAL(1, WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(1), + WASM_F32(19.5))), + WASM_SET_LOCAL(0, WASM_I32V(0)), + WASM_LOOP( + WASM_SET_LOCAL( + 1, WASM_SIMD_F32x4_ADD(WASM_GET_LOCAL(1), + WASM_SIMD_F32x4_SPLAT(WASM_F32(2.0)))), + WASM_IF(WASM_I32_NE(WASM_INC_LOCAL(0), WASM_I32V(3)), WASM_BR(1))), + WASM_SET_LOCAL(0, WASM_I32V(1)), + WASM_IF(WASM_F32_NE(WASM_SIMD_F32x4_EXTRACT_LANE(0, WASM_GET_LOCAL(1)), + WASM_F32(27.25)), + WASM_SET_LOCAL(0, WASM_I32V(0))), + WASM_IF(WASM_F32_NE(WASM_SIMD_F32x4_EXTRACT_LANE(3, WASM_GET_LOCAL(1)), + WASM_F32(25.5)), + WASM_SET_LOCAL(0, WASM_I32V(0))), + WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call()); } } diff --git a/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc b/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc index 76eac5e793..9764545d45 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm-simd.cc @@ -13,7 +13,259 @@ using namespace v8::internal; using namespace v8::internal::compiler; using namespace v8::internal::wasm; -WASM_EXEC_TEST(Splat) { +namespace { + +typedef float (*FloatUnOp)(float); +typedef float (*FloatBinOp)(float, float); +typedef int32_t (*FloatCompareOp)(float, float); +typedef int32_t (*Int32BinOp)(int32_t, int32_t); + +template <typename T> +T Negate(T a) { + return -a; +} + +template <typename T> +T Add(T a, T b) { + return a + b; +} + +template <typename T> +T Sub(T a, T b) { + return a - b; +} + +template <typename T> +int32_t Equal(T a, T b) { + return a == b ? 0xFFFFFFFF : 0; +} + +template <typename T> +int32_t NotEqual(T a, T b) { + return a != b ? 0xFFFFFFFF : 0; +} + +#if V8_TARGET_ARCH_ARM +int32_t Equal(float a, float b) { return a == b ? 0xFFFFFFFF : 0; } + +int32_t NotEqual(float a, float b) { return a != b ? 0xFFFFFFFF : 0; } +#endif // V8_TARGET_ARCH_ARM + +} // namespace + +// TODO(gdeepti): These are tests using sample values to verify functional +// correctness of opcodes, add more tests for a range of values and macroize +// tests. + +// TODO(bbudge) Figure out how to compare floats in Wasm code that can handle +// NaNs. For now, our tests avoid using NaNs. +#define WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lane_value, lane_index) \ + WASM_IF(WASM_##LANE_TYPE##_NE(WASM_GET_LOCAL(lane_value), \ + WASM_SIMD_##TYPE##_EXTRACT_LANE( \ + lane_index, WASM_GET_LOCAL(value))), \ + WASM_RETURN1(WASM_ZERO)) + +#define WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv0, lv1, lv2, lv3) \ + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv0, 0) \ + , WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv1, 1), \ + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv2, 2), \ + WASM_SIMD_CHECK_LANE(TYPE, value, LANE_TYPE, lv3, 3) + +#define WASM_SIMD_CHECK_SPLAT4(TYPE, value, LANE_TYPE, lv) \ + WASM_SIMD_CHECK4(TYPE, value, LANE_TYPE, lv, lv, lv, lv) + +#define WASM_SIMD_CHECK_F32_LANE(TYPE, value, lane_value, lane_index) \ + WASM_IF( \ + WASM_I32_NE(WASM_I32_REINTERPRET_F32(WASM_GET_LOCAL(lane_value)), \ + WASM_I32_REINTERPRET_F32(WASM_SIMD_##TYPE##_EXTRACT_LANE( \ + lane_index, WASM_GET_LOCAL(value)))), \ + WASM_RETURN1(WASM_ZERO)) + +#define WASM_SIMD_CHECK4_F32(TYPE, value, lv0, lv1, lv2, lv3) \ + WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv0, 0) \ + , WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv1, 1), \ + WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv2, 2), \ + WASM_SIMD_CHECK_F32_LANE(TYPE, value, lv3, 3) + +#define WASM_SIMD_CHECK_SPLAT4_F32(TYPE, value, lv) \ + WASM_SIMD_CHECK4_F32(TYPE, value, lv, lv, lv, lv) + +#if V8_TARGET_ARCH_ARM +WASM_EXEC_TEST(F32x4Splat) { + FLAG_wasm_simd_prototype = true; + + WasmRunner<int32_t, float> r(kExecuteCompiled); + byte lane_val = 0; + byte simd = r.AllocateLocal(kWasmS128); + BUILD(r, + WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(lane_val))), + WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, lane_val), WASM_ONE); + + FOR_FLOAT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); } +} + +WASM_EXEC_TEST(F32x4ReplaceLane) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, float, float> r(kExecuteCompiled); + byte old_val = 0; + byte new_val = 1; + byte simd = r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(old_val))), + WASM_SET_LOCAL(simd, + WASM_SIMD_F32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, old_val, old_val, old_val), + WASM_SET_LOCAL(simd, + WASM_SIMD_F32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, old_val, old_val), + WASM_SET_LOCAL(simd, + WASM_SIMD_F32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK4(F32x4, simd, F32, new_val, new_val, new_val, old_val), + WASM_SET_LOCAL(simd, + WASM_SIMD_F32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK_SPLAT4(F32x4, simd, F32, new_val), WASM_ONE); + + CHECK_EQ(1, r.Call(3.14159, -1.5)); +} + +// Tests both signed and unsigned conversion. +WASM_EXEC_TEST(F32x4FromInt32x4) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t, float, float> r(kExecuteCompiled); + byte a = 0; + byte expected_signed = 1; + byte expected_unsigned = 2; + byte simd0 = r.AllocateLocal(kWasmS128); + byte simd1 = r.AllocateLocal(kWasmS128); + byte simd2 = r.AllocateLocal(kWasmS128); + BUILD( + r, WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), + WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_FROM_I32x4(WASM_GET_LOCAL(simd0))), + WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected_signed), + WASM_SET_LOCAL(simd2, WASM_SIMD_F32x4_FROM_U32x4(WASM_GET_LOCAL(simd0))), + WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd2, expected_unsigned), WASM_ONE); + + FOR_INT32_INPUTS(i) { + CHECK_EQ(1, r.Call(*i, static_cast<float>(*i), + static_cast<float>(static_cast<uint32_t>(*i)))); + } +} + +WASM_EXEC_TEST(S32x4Select) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t, int32_t> r(kExecuteCompiled); + byte val1 = 0; + byte val2 = 1; + byte mask = r.AllocateLocal(kWasmS128); + byte src1 = r.AllocateLocal(kWasmS128); + byte src2 = r.AllocateLocal(kWasmS128); + BUILD(r, + + WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_SPLAT(WASM_ZERO)), + WASM_SET_LOCAL(src1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(val1))), + WASM_SET_LOCAL(src2, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(val2))), + WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_REPLACE_LANE( + 1, WASM_GET_LOCAL(mask), WASM_I32V(-1))), + WASM_SET_LOCAL(mask, WASM_SIMD_I32x4_REPLACE_LANE( + 2, WASM_GET_LOCAL(mask), WASM_I32V(-1))), + WASM_SET_LOCAL(mask, WASM_SIMD_S32x4_SELECT(WASM_GET_LOCAL(mask), + WASM_GET_LOCAL(src1), + WASM_GET_LOCAL(src2))), + WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 0), + WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 1), + WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val1, 2), + WASM_SIMD_CHECK_LANE(I32x4, mask, I32, val2, 3), WASM_ONE); + + CHECK_EQ(1, r.Call(0x1234, 0x5678)); +} + +void RunF32x4UnOpTest(WasmOpcode simd_op, FloatUnOp expected_op) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, float, float> r(kExecuteCompiled); + byte a = 0; + byte expected = 1; + byte simd = r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), + WASM_SET_LOCAL(simd, + WASM_SIMD_UNOP(simd_op & 0xffu, WASM_GET_LOCAL(simd))), + WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd, expected), WASM_ONE); + + FOR_FLOAT32_INPUTS(i) { + if (std::isnan(*i)) continue; + CHECK_EQ(1, r.Call(*i, expected_op(*i))); + } +} + +WASM_EXEC_TEST(F32x4Abs) { RunF32x4UnOpTest(kExprF32x4Abs, std::abs); } +WASM_EXEC_TEST(F32x4Neg) { RunF32x4UnOpTest(kExprF32x4Neg, Negate); } + +void RunF32x4BinOpTest(WasmOpcode simd_op, FloatBinOp expected_op) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, float, float, float> r(kExecuteCompiled); + byte a = 0; + byte b = 1; + byte expected = 2; + byte simd0 = r.AllocateLocal(kWasmS128); + byte simd1 = r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), + WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), + WASM_SET_LOCAL(simd1, + WASM_SIMD_BINOP(simd_op & 0xffu, WASM_GET_LOCAL(simd0), + WASM_GET_LOCAL(simd1))), + WASM_SIMD_CHECK_SPLAT4_F32(F32x4, simd1, expected), WASM_ONE); + + FOR_FLOAT32_INPUTS(i) { + if (std::isnan(*i)) continue; + FOR_FLOAT32_INPUTS(j) { + if (std::isnan(*j)) continue; + float expected = expected_op(*i, *j); + // SIMD on some platforms may handle denormalized numbers differently. + // TODO(bbudge) On platforms that flush denorms to zero, test with + // expected == 0. + if (std::fpclassify(expected) == FP_SUBNORMAL) continue; + CHECK_EQ(1, r.Call(*i, *j, expected)); + } + } +} + +WASM_EXEC_TEST(F32x4Add) { RunF32x4BinOpTest(kExprF32x4Add, Add); } +WASM_EXEC_TEST(F32x4Sub) { RunF32x4BinOpTest(kExprF32x4Sub, Sub); } + +void RunF32x4CompareOpTest(WasmOpcode simd_op, FloatCompareOp expected_op) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, float, float, int32_t> r(kExecuteCompiled); + byte a = 0; + byte b = 1; + byte expected = 2; + byte simd0 = r.AllocateLocal(kWasmS128); + byte simd1 = r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), + WASM_SET_LOCAL(simd1, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(b))), + WASM_SET_LOCAL(simd1, + WASM_SIMD_BINOP(simd_op & 0xffu, WASM_GET_LOCAL(simd0), + WASM_GET_LOCAL(simd1))), + WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), WASM_ONE); + + FOR_FLOAT32_INPUTS(i) { + if (std::isnan(*i)) continue; + FOR_FLOAT32_INPUTS(j) { + if (std::isnan(*j)) continue; + // SIMD on some platforms may handle denormalized numbers differently. + // Check for number pairs that are very close together. + if (std::fpclassify(*i - *j) == FP_SUBNORMAL) continue; + CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); + } + } +} + +WASM_EXEC_TEST(F32x4Equal) { RunF32x4CompareOpTest(kExprF32x4Eq, Equal); } +WASM_EXEC_TEST(F32x4NotEqual) { RunF32x4CompareOpTest(kExprF32x4Ne, NotEqual); } +#endif // V8_TARGET_ARCH_ARM + +WASM_EXEC_TEST(I32x4Splat) { FLAG_wasm_simd_prototype = true; // Store SIMD value in a local variable, use extract lane to check lane values @@ -26,24 +278,136 @@ WASM_EXEC_TEST(Splat) { // return 0 // // return 1 - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); - r.AllocateLocal(kAstS128); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + byte lane_val = 0; + byte simd = r.AllocateLocal(kWasmS128); BUILD(r, - WASM_BLOCK( - WASM_SET_LOCAL(1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(0))), - WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE( - 0, WASM_GET_LOCAL(1))), - WASM_RETURN1(WASM_ZERO)), - WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE( - 1, WASM_GET_LOCAL(1))), - WASM_RETURN1(WASM_ZERO)), - WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE( - 2, WASM_GET_LOCAL(1))), - WASM_RETURN1(WASM_ZERO)), - WASM_IF(WASM_I32_NE(WASM_GET_LOCAL(0), WASM_SIMD_I32x4_EXTRACT_LANE( - 3, WASM_GET_LOCAL(1))), - WASM_RETURN1(WASM_ZERO)), - WASM_RETURN1(WASM_ONE))); + WASM_SET_LOCAL(simd, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(lane_val))), + WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, lane_val), WASM_ONE); FOR_INT32_INPUTS(i) { CHECK_EQ(1, r.Call(*i)); } } + +WASM_EXEC_TEST(I32x4ReplaceLane) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t, int32_t> r(kExecuteCompiled); + byte old_val = 0; + byte new_val = 1; + byte simd = r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(simd, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(old_val))), + WASM_SET_LOCAL(simd, + WASM_SIMD_I32x4_REPLACE_LANE(0, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK4(I32x4, simd, I32, new_val, old_val, old_val, old_val), + WASM_SET_LOCAL(simd, + WASM_SIMD_I32x4_REPLACE_LANE(1, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK4(I32x4, simd, I32, new_val, new_val, old_val, old_val), + WASM_SET_LOCAL(simd, + WASM_SIMD_I32x4_REPLACE_LANE(2, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK4(I32x4, simd, I32, new_val, new_val, new_val, old_val), + WASM_SET_LOCAL(simd, + WASM_SIMD_I32x4_REPLACE_LANE(3, WASM_GET_LOCAL(simd), + WASM_GET_LOCAL(new_val))), + WASM_SIMD_CHECK_SPLAT4(I32x4, simd, I32, new_val), WASM_ONE); + + CHECK_EQ(1, r.Call(1, 2)); +} + +#if V8_TARGET_ARCH_ARM + +// Determines if conversion from float to int will be valid. +bool CanRoundToZeroAndConvert(double val, bool unsigned_integer) { + const double max_uint = static_cast<double>(0xffffffffu); + const double max_int = static_cast<double>(kMaxInt); + const double min_int = static_cast<double>(kMinInt); + + // Check for NaN. + if (val != val) { + return false; + } + + // Round to zero and check for overflow. This code works because 32 bit + // integers can be exactly represented by ieee-754 64bit floating-point + // values. + return unsigned_integer ? (val < (max_uint + 1.0)) && (val > -1) + : (val < (max_int + 1.0)) && (val > (min_int - 1.0)); +} + +int ConvertInvalidValue(double val, bool unsigned_integer) { + if (val != val) { + return 0; + } else { + if (unsigned_integer) { + return (val < 0) ? 0 : 0xffffffffu; + } else { + return (val < 0) ? kMinInt : kMaxInt; + } + } +} + +int32_t ConvertToInt(double val, bool unsigned_integer) { + int32_t result = + unsigned_integer ? static_cast<uint32_t>(val) : static_cast<int32_t>(val); + + if (!CanRoundToZeroAndConvert(val, unsigned_integer)) { + result = ConvertInvalidValue(val, unsigned_integer); + } + return result; +} + +// Tests both signed and unsigned conversion. +WASM_EXEC_TEST(I32x4FromFloat32x4) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, float, int32_t, int32_t> r(kExecuteCompiled); + byte a = 0; + byte expected_signed = 1; + byte expected_unsigned = 2; + byte simd0 = r.AllocateLocal(kWasmS128); + byte simd1 = r.AllocateLocal(kWasmS128); + byte simd2 = r.AllocateLocal(kWasmS128); + BUILD( + r, WASM_SET_LOCAL(simd0, WASM_SIMD_F32x4_SPLAT(WASM_GET_LOCAL(a))), + WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))), + WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected_signed), + WASM_SET_LOCAL(simd2, WASM_SIMD_U32x4_FROM_F32x4(WASM_GET_LOCAL(simd0))), + WASM_SIMD_CHECK_SPLAT4(I32x4, simd2, I32, expected_unsigned), WASM_ONE); + + FOR_FLOAT32_INPUTS(i) { + int32_t signed_value = ConvertToInt(*i, false); + int32_t unsigned_value = ConvertToInt(*i, true); + CHECK_EQ(1, r.Call(*i, signed_value, unsigned_value)); + } +} +#endif // V8_TARGET_ARCH_ARM + +void RunI32x4BinOpTest(WasmOpcode simd_op, Int32BinOp expected_op) { + FLAG_wasm_simd_prototype = true; + WasmRunner<int32_t, int32_t, int32_t, int32_t> r(kExecuteCompiled); + byte a = 0; + byte b = 1; + byte expected = 2; + byte simd0 = r.AllocateLocal(kWasmS128); + byte simd1 = r.AllocateLocal(kWasmS128); + BUILD(r, WASM_SET_LOCAL(simd0, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(a))), + WASM_SET_LOCAL(simd1, WASM_SIMD_I32x4_SPLAT(WASM_GET_LOCAL(b))), + WASM_SET_LOCAL(simd1, + WASM_SIMD_BINOP(simd_op & 0xffu, WASM_GET_LOCAL(simd0), + WASM_GET_LOCAL(simd1))), + WASM_SIMD_CHECK_SPLAT4(I32x4, simd1, I32, expected), WASM_ONE); + + FOR_INT32_INPUTS(i) { + FOR_INT32_INPUTS(j) { CHECK_EQ(1, r.Call(*i, *j, expected_op(*i, *j))); } + } +} + +WASM_EXEC_TEST(I32x4Add) { RunI32x4BinOpTest(kExprI32x4Add, Add); } + +WASM_EXEC_TEST(I32x4Sub) { RunI32x4BinOpTest(kExprI32x4Sub, Sub); } + +#if V8_TARGET_ARCH_ARM +WASM_EXEC_TEST(I32x4Equal) { RunI32x4BinOpTest(kExprI32x4Eq, Equal); } + +WASM_EXEC_TEST(I32x4NotEqual) { RunI32x4BinOpTest(kExprI32x4Ne, NotEqual); } +#endif // V8_TARGET_ARCH_ARM diff --git a/deps/v8/test/cctest/wasm/test-run-wasm.cc b/deps/v8/test/cctest/wasm/test-run-wasm.cc index a42a81ba27..05370b5775 100644 --- a/deps/v8/test/cctest/wasm/test-run-wasm.cc +++ b/deps/v8/test/cctest/wasm/test-run-wasm.cc @@ -25,41 +25,7 @@ using namespace v8::internal::wasm; #define B2(a, b) WASM_BLOCK(a, b) #define B3(a, b, c) WASM_BLOCK(a, b, c) #define RET(x) x, kExprReturn -#define RET_I8(x) kExprI8Const, x, kExprReturn - -WASM_EXEC_TEST(Int8Const) { - WasmRunner<int32_t> r(execution_mode); - const byte kExpectedValue = 121; - // return(kExpectedValue) - BUILD(r, WASM_I8(kExpectedValue)); - CHECK_EQ(kExpectedValue, r.Call()); -} - -WASM_EXEC_TEST(Int8Const_end) { - WasmRunner<int32_t> r(execution_mode); - const byte kExpectedValue = 121; - // return(kExpectedValue) - BUILD(r, WASM_I8(kExpectedValue), kExprEnd); - CHECK_EQ(kExpectedValue, r.Call()); -} - -WASM_EXEC_TEST(Int8Const_fallthru2) { - WasmRunner<int32_t> r(execution_mode); - const byte kExpectedValue = 123; - // -99 kExpectedValue - BUILD(r, WASM_I8(-99), WASM_DROP, WASM_I8(kExpectedValue)); - CHECK_EQ(kExpectedValue, r.Call()); -} - -WASM_EXEC_TEST(Int8Const_all) { - for (int value = -128; value <= 127; ++value) { - WasmRunner<int32_t> r(execution_mode); - // return(value) - BUILD(r, WASM_I8(value)); - int32_t result = r.Call(); - CHECK_EQ(value, result); - } -} +#define RET_I8(x) WASM_I32V_2(x), kExprReturn WASM_EXEC_TEST(Int32Const) { WasmRunner<int32_t> r(execution_mode); @@ -81,29 +47,28 @@ WASM_EXEC_TEST(Int32Const_many) { WASM_EXEC_TEST(GraphTrimming) { // This WebAssembly code requires graph trimming in the TurboFan compiler. - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, kExprGetLocal, 0, kExprGetLocal, 0, kExprGetLocal, 0, kExprI32RemS, kExprI32Eq, kExprGetLocal, 0, kExprI32DivS, kExprUnreachable); r.Call(1); } WASM_EXEC_TEST(Int32Param0) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // return(local[0]) BUILD(r, WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Int32Param0_fallthru) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // local[0] BUILD(r, WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Int32Param1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); // local[1] BUILD(r, WASM_GET_LOCAL(1)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(-111, *i)); } @@ -112,28 +77,27 @@ WASM_EXEC_TEST(Int32Param1) { WASM_EXEC_TEST(Int32Add) { WasmRunner<int32_t> r(execution_mode); // 11 + 44 - BUILD(r, WASM_I32_ADD(WASM_I8(11), WASM_I8(44))); + BUILD(r, WASM_I32_ADD(WASM_I32V_1(11), WASM_I32V_1(44))); CHECK_EQ(55, r.Call()); } WASM_EXEC_TEST(Int32Add_P) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // p0 + 13 - BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0))); + BUILD(r, WASM_I32_ADD(WASM_I32V_1(13), WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); } } WASM_EXEC_TEST(Int32Add_P_fallthru) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // p0 + 13 - BUILD(r, WASM_I32_ADD(WASM_I8(13), WASM_GET_LOCAL(0))); + BUILD(r, WASM_I32_ADD(WASM_I32V_1(13), WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i + 13, r.Call(*i)); } } static void RunInt32AddTest(WasmExecutionMode execution_mode, const byte* code, size_t size) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); r.Build(code, code + size); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { @@ -154,7 +118,7 @@ WASM_EXEC_TEST(Int32Add_P2) { WASM_EXEC_TEST(Int32Add_block1) { FLAG_wasm_mv_prototype = true; static const byte code[] = { - WASM_BLOCK_TT(kAstI32, kAstI32, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), + WASM_BLOCK_TT(kWasmI32, kWasmI32, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), kExprI32Add}; RunInt32AddTest(execution_mode, code, sizeof(code)); } @@ -162,7 +126,7 @@ WASM_EXEC_TEST(Int32Add_block1) { WASM_EXEC_TEST(Int32Add_block2) { FLAG_wasm_mv_prototype = true; static const byte code[] = { - WASM_BLOCK_TT(kAstI32, kAstI32, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), + WASM_BLOCK_TT(kWasmI32, kWasmI32, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), kExprBr, DEPTH_0), kExprI32Add}; RunInt32AddTest(execution_mode, code, sizeof(code)); @@ -171,7 +135,7 @@ WASM_EXEC_TEST(Int32Add_block2) { WASM_EXEC_TEST(Int32Add_multi_if) { FLAG_wasm_mv_prototype = true; static const byte code[] = { - WASM_IF_ELSE_TT(kAstI32, kAstI32, WASM_GET_LOCAL(0), + WASM_IF_ELSE_TT(kWasmI32, kWasmI32, WASM_GET_LOCAL(0), WASM_SEQ(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), WASM_SEQ(WASM_GET_LOCAL(1), WASM_GET_LOCAL(0))), kExprI32Add}; @@ -202,8 +166,7 @@ void TestInt32Binop(WasmExecutionMode execution_mode, WasmOpcode opcode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); // a op b BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(expected, r.Call(a, b)); @@ -252,7 +215,7 @@ void TestInt32Unop(WasmExecutionMode execution_mode, WasmOpcode opcode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // return op a BUILD(r, WASM_UNOP(opcode, WASM_GET_LOCAL(0))); CHECK_EQ(expected, r.Call(a)); @@ -348,8 +311,7 @@ WASM_EXEC_TEST(I32Eqz) { } WASM_EXEC_TEST(I32Shl) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_I32_SHL(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT32_INPUTS(i) { @@ -361,8 +323,7 @@ WASM_EXEC_TEST(I32Shl) { } WASM_EXEC_TEST(I32Shr) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_I32_SHR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_UINT32_INPUTS(i) { @@ -374,8 +335,7 @@ WASM_EXEC_TEST(I32Shr) { } WASM_EXEC_TEST(I32Sar) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_I32_SAR(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_INT32_INPUTS(i) { @@ -386,9 +346,8 @@ WASM_EXEC_TEST(I32Sar) { } } -WASM_EXEC_TEST(Int32DivS_trap) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); +WASM_EXEC_TEST_WITH_TRAP(Int32DivS_trap) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(0, r.Call(0, 100)); @@ -398,9 +357,8 @@ WASM_EXEC_TEST(Int32DivS_trap) { CHECK_TRAP(r.Call(kMin, 0)); } -WASM_EXEC_TEST(Int32RemS_trap) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); +WASM_EXEC_TEST_WITH_TRAP(Int32RemS_trap) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(33, r.Call(133, 100)); @@ -410,9 +368,8 @@ WASM_EXEC_TEST(Int32RemS_trap) { CHECK_TRAP(r.Call(kMin, 0)); } -WASM_EXEC_TEST(Int32DivU_trap) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); +WASM_EXEC_TEST_WITH_TRAP(Int32DivU_trap) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); const int32_t kMin = std::numeric_limits<int32_t>::min(); CHECK_EQ(0, r.Call(0, 100)); @@ -422,9 +379,8 @@ WASM_EXEC_TEST(Int32DivU_trap) { CHECK_TRAP(r.Call(kMin, 0)); } -WASM_EXEC_TEST(Int32RemU_trap) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); +WASM_EXEC_TEST_WITH_TRAP(Int32RemU_trap) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_I32_REMU(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(17, r.Call(217, 100)); const int32_t kMin = std::numeric_limits<int32_t>::min(); @@ -434,10 +390,10 @@ WASM_EXEC_TEST(Int32RemU_trap) { CHECK_EQ(kMin, r.Call(kMin, -1)); } -WASM_EXEC_TEST(Int32DivS_byzero_const) { +WASM_EXEC_TEST_WITH_TRAP(Int32DivS_byzero_const) { for (int8_t denom = -2; denom < 8; ++denom) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_I32_DIVS(WASM_GET_LOCAL(0), WASM_I32V_1(denom))); for (int32_t val = -7; val < 8; ++val) { if (denom == 0) { CHECK_TRAP(r.Call(val)); @@ -450,10 +406,9 @@ WASM_EXEC_TEST(Int32DivS_byzero_const) { WASM_EXEC_TEST(Int32AsmjsDivS_byzero_const) { for (int8_t denom = -2; denom < 8; ++denom) { - TestingModule module(execution_mode); - module.ChangeOriginToAsmjs(); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - BUILD(r, WASM_I32_ASMJS_DIVS(WASM_GET_LOCAL(0), WASM_I8(denom))); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); + BUILD(r, WASM_I32_ASMJS_DIVS(WASM_GET_LOCAL(0), WASM_I32V_1(denom))); FOR_INT32_INPUTS(i) { if (denom == 0) { CHECK_EQ(0, r.Call(*i)); @@ -468,10 +423,9 @@ WASM_EXEC_TEST(Int32AsmjsDivS_byzero_const) { WASM_EXEC_TEST(Int32AsmjsRemS_byzero_const) { for (int8_t denom = -2; denom < 8; ++denom) { - TestingModule module(execution_mode); - module.ChangeOriginToAsmjs(); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - BUILD(r, WASM_I32_ASMJS_REMS(WASM_GET_LOCAL(0), WASM_I8(denom))); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.module().ChangeOriginToAsmjs(); + BUILD(r, WASM_I32_ASMJS_REMS(WASM_GET_LOCAL(0), WASM_I32V_1(denom))); FOR_INT32_INPUTS(i) { if (denom == 0) { CHECK_EQ(0, r.Call(*i)); @@ -484,9 +438,9 @@ WASM_EXEC_TEST(Int32AsmjsRemS_byzero_const) { } } -WASM_EXEC_TEST(Int32DivU_byzero_const) { +WASM_EXEC_TEST_WITH_TRAP(Int32DivU_byzero_const) { for (uint32_t denom = 0xfffffffe; denom < 8; ++denom) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_I32_DIVU(WASM_GET_LOCAL(0), WASM_I32V_1(denom))); for (uint32_t val = 0xfffffff0; val < 8; ++val) { @@ -499,10 +453,9 @@ WASM_EXEC_TEST(Int32DivU_byzero_const) { } } -WASM_EXEC_TEST(Int32DivS_trap_effect) { - TestingModule module(execution_mode); - module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); +WASM_EXEC_TEST_WITH_TRAP(Int32DivS_trap_effect) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + r.module().AddMemoryElems<int32_t>(8); BUILD(r, WASM_IF_ELSE_I( WASM_GET_LOCAL(0), @@ -531,8 +484,7 @@ void TestFloat32Binop(WasmExecutionMode execution_mode, WasmOpcode opcode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<int32_t, float, float> r(execution_mode); // return a op b BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(expected, r.Call(a, b)); @@ -550,8 +502,7 @@ void TestFloat32BinopWithConvert(WasmExecutionMode execution_mode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<int32_t, float, float> r(execution_mode); // return int(a op b) BUILD(r, WASM_I32_SCONVERT_F32( WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); @@ -568,7 +519,7 @@ void TestFloat32UnopWithConvert(WasmExecutionMode execution_mode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Float32()); + WasmRunner<int32_t, float> r(execution_mode); // return int(op(a)) BUILD(r, WASM_I32_SCONVERT_F32(WASM_UNOP(opcode, WASM_GET_LOCAL(0)))); CHECK_EQ(expected, r.Call(a)); @@ -584,8 +535,7 @@ void TestFloat64Binop(WasmExecutionMode execution_mode, WasmOpcode opcode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<int32_t, double, double> r(execution_mode); // return a op b BUILD(r, WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); CHECK_EQ(expected, r.Call(a, b)); @@ -603,8 +553,7 @@ void TestFloat64BinopWithConvert(WasmExecutionMode execution_mode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<int32_t, double, double> r(execution_mode); BUILD(r, WASM_I32_SCONVERT_F64( WASM_BINOP(opcode, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); CHECK_EQ(expected, r.Call(a, b)); @@ -620,7 +569,7 @@ void TestFloat64UnopWithConvert(WasmExecutionMode execution_mode, CHECK_EQ(expected, r.Call()); } { - WasmRunner<int32_t> r(execution_mode, MachineType::Float64()); + WasmRunner<int32_t, double> r(execution_mode); // return int(op(a)) BUILD(r, WASM_I32_SCONVERT_F64(WASM_UNOP(opcode, WASM_GET_LOCAL(0)))); CHECK_EQ(expected, r.Call(a)); @@ -671,7 +620,7 @@ WASM_EXEC_TEST(Float64Unops) { } WASM_EXEC_TEST(Float32Neg) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_F32_NEG(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { @@ -681,7 +630,7 @@ WASM_EXEC_TEST(Float32Neg) { } WASM_EXEC_TEST(Float64Neg) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_F64_NEG(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { @@ -691,11 +640,11 @@ WASM_EXEC_TEST(Float64Neg) { } WASM_EXEC_TEST(IfElse_P) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // if (p0) return 11; else return 22; BUILD(r, WASM_IF_ELSE_I(WASM_GET_LOCAL(0), // -- - WASM_I8(11), // -- - WASM_I8(22))); // -- + WASM_I32V_1(11), // -- + WASM_I32V_1(22))); // -- FOR_INT32_INPUTS(i) { int32_t expected = *i ? 11 : 22; CHECK_EQ(expected, r.Call(*i)); @@ -704,50 +653,45 @@ WASM_EXEC_TEST(IfElse_P) { #define EMPTY WASM_EXEC_TEST(If_empty1) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_GET_LOCAL(0), kExprIf, kLocalVoid, kExprEnd, WASM_GET_LOCAL(1)); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 9, *i)); } } WASM_EXEC_TEST(IfElse_empty1) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_GET_LOCAL(0), kExprIf, kLocalVoid, kExprElse, kExprEnd, WASM_GET_LOCAL(1)); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 8, *i)); } } WASM_EXEC_TEST(IfElse_empty2) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_GET_LOCAL(0), kExprIf, kLocalVoid, WASM_NOP, kExprElse, kExprEnd, WASM_GET_LOCAL(1)); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 7, *i)); } } WASM_EXEC_TEST(IfElse_empty3) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_GET_LOCAL(0), kExprIf, kLocalVoid, kExprElse, WASM_NOP, kExprEnd, WASM_GET_LOCAL(1)); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i - 6, *i)); } } WASM_EXEC_TEST(If_chain1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // if (p0) 13; if (p0) 14; 15 BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_NOP), - WASM_IF(WASM_GET_LOCAL(0), WASM_NOP), WASM_I8(15)); + WASM_IF(WASM_GET_LOCAL(0), WASM_NOP), WASM_I32V_1(15)); FOR_INT32_INPUTS(i) { CHECK_EQ(15, r.Call(*i)); } } WASM_EXEC_TEST(If_chain_set) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); // if (p0) p1 = 73; if (p0) p1 = 74; p1 - BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(73))), - WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I8(74))), + BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I32V_2(73))), + WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(1, WASM_I32V_2(74))), WASM_GET_LOCAL(1)); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 74 : *i; @@ -758,17 +702,17 @@ WASM_EXEC_TEST(If_chain_set) { WASM_EXEC_TEST(IfElse_Unreachable1) { WasmRunner<int32_t> r(execution_mode); // 0 ? unreachable : 27 - BUILD(r, WASM_IF_ELSE_I(WASM_ZERO, // -- - WASM_UNREACHABLE, // -- - WASM_I8(27))); // -- + BUILD(r, WASM_IF_ELSE_I(WASM_ZERO, // -- + WASM_UNREACHABLE, // -- + WASM_I32V_1(27))); // -- CHECK_EQ(27, r.Call()); } WASM_EXEC_TEST(IfElse_Unreachable2) { WasmRunner<int32_t> r(execution_mode); // 1 ? 28 : unreachable - BUILD(r, WASM_IF_ELSE_I(WASM_I8(1), // -- - WASM_I8(28), // -- + BUILD(r, WASM_IF_ELSE_I(WASM_I32V_1(1), // -- + WASM_I32V_1(28), // -- WASM_UNREACHABLE)); // -- CHECK_EQ(28, r.Call()); } @@ -783,12 +727,12 @@ WASM_EXEC_TEST(Return12) { WASM_EXEC_TEST(Return17) { WasmRunner<int32_t> r(execution_mode); - BUILD(r, WASM_BLOCK(RET_I8(17))); + BUILD(r, WASM_BLOCK(RET_I8(17)), WASM_ZERO); CHECK_EQ(17, r.Call()); } WASM_EXEC_TEST(Return_I32) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, RET(WASM_GET_LOCAL(0))); @@ -796,7 +740,7 @@ WASM_EXEC_TEST(Return_I32) { } WASM_EXEC_TEST(Return_F32) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, RET(WASM_GET_LOCAL(0))); @@ -812,7 +756,7 @@ WASM_EXEC_TEST(Return_F32) { } WASM_EXEC_TEST(Return_F64) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, RET(WASM_GET_LOCAL(0))); @@ -828,8 +772,7 @@ WASM_EXEC_TEST(Return_F64) { } WASM_EXEC_TEST(Select_float_parameters) { - WasmRunner<float> r(execution_mode, MachineType::Float32(), - MachineType::Float32(), MachineType::Int32()); + WasmRunner<float, float, float, int32_t> r(execution_mode); // return select(11, 22, a); BUILD(r, WASM_SELECT(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), WASM_GET_LOCAL(2))); @@ -837,9 +780,9 @@ WASM_EXEC_TEST(Select_float_parameters) { } WASM_EXEC_TEST(Select) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // return select(11, 22, a); - BUILD(r, WASM_SELECT(WASM_I8(11), WASM_I8(22), WASM_GET_LOCAL(0))); + BUILD(r, WASM_SELECT(WASM_I32V_1(11), WASM_I32V_1(22), WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 11 : 22; CHECK_EQ(expected, r.Call(*i)); @@ -847,22 +790,22 @@ WASM_EXEC_TEST(Select) { } WASM_EXEC_TEST(Select_strict1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // select(a=0, a=1, a=2); return a - BUILD(r, WASM_SELECT(WASM_TEE_LOCAL(0, WASM_I8(0)), - WASM_TEE_LOCAL(0, WASM_I8(1)), - WASM_TEE_LOCAL(0, WASM_I8(2))), + BUILD(r, WASM_SELECT(WASM_TEE_LOCAL(0, WASM_ZERO), + WASM_TEE_LOCAL(0, WASM_I32V_1(1)), + WASM_TEE_LOCAL(0, WASM_I32V_1(2))), WASM_DROP, WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(2, r.Call(*i)); } } WASM_EXEC_TEST(Select_strict2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - r.AllocateLocal(kAstI32); - r.AllocateLocal(kAstI32); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.AllocateLocal(kWasmI32); + r.AllocateLocal(kWasmI32); // select(b=5, c=6, a) - BUILD(r, WASM_SELECT(WASM_TEE_LOCAL(1, WASM_I8(5)), - WASM_TEE_LOCAL(2, WASM_I8(6)), WASM_GET_LOCAL(0))); + BUILD(r, WASM_SELECT(WASM_TEE_LOCAL(1, WASM_I32V_1(5)), + WASM_TEE_LOCAL(2, WASM_I32V_1(6)), WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 5 : 6; CHECK_EQ(expected, r.Call(*i)); @@ -870,12 +813,12 @@ WASM_EXEC_TEST(Select_strict2) { } WASM_EXEC_TEST(Select_strict3) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - r.AllocateLocal(kAstI32); - r.AllocateLocal(kAstI32); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.AllocateLocal(kWasmI32); + r.AllocateLocal(kWasmI32); // select(b=5, c=6, a=b) - BUILD(r, WASM_SELECT(WASM_TEE_LOCAL(1, WASM_I8(5)), - WASM_TEE_LOCAL(2, WASM_I8(6)), + BUILD(r, WASM_SELECT(WASM_TEE_LOCAL(1, WASM_I32V_1(5)), + WASM_TEE_LOCAL(2, WASM_I32V_1(6)), WASM_TEE_LOCAL(0, WASM_GET_LOCAL(1)))); FOR_INT32_INPUTS(i) { int32_t expected = 5; @@ -884,20 +827,19 @@ WASM_EXEC_TEST(Select_strict3) { } WASM_EXEC_TEST(BrIf_strict) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BLOCK_I(WASM_BRV_IF(0, WASM_GET_LOCAL(0), - WASM_TEE_LOCAL(0, WASM_I8(99))))); + WASM_TEE_LOCAL(0, WASM_I32V_2(99))))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Br_height) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, - WASM_BLOCK_I( - WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)), - WASM_RETURN1(WASM_I8(9)), WASM_I8(7), WASM_I8(7)), - WASM_BRV(0, WASM_I8(8)))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I( + WASM_BLOCK(WASM_BRV_IFD(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)), + WASM_RETURN1(WASM_I32V_1(9))), + WASM_BRV(0, WASM_I32V_1(8)))); for (int32_t i = 0; i < 5; i++) { int32_t expected = i != 0 ? 8 : 9; @@ -906,36 +848,35 @@ WASM_EXEC_TEST(Br_height) { } WASM_EXEC_TEST(Regression_660262) { - TestingModule module(execution_mode); - module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module); - BUILD(r, kExprI8Const, 0x00, kExprI8Const, 0x00, kExprI32LoadMem, 0x00, 0x0f, - kExprBrTable, 0x00, 0x80, 0x00); // entries=0 + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemoryElems<int32_t>(8); + BUILD(r, kExprI32Const, 0x00, kExprI32Const, 0x00, kExprI32LoadMem, 0x00, + 0x0f, kExprBrTable, 0x00, 0x80, 0x00); // entries=0 r.Call(); } WASM_EXEC_TEST(BrTable0a) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0)))), - WASM_I8(91)); + WASM_I32V_2(91)); FOR_INT32_INPUTS(i) { CHECK_EQ(91, r.Call(*i)); } } WASM_EXEC_TEST(BrTable0b) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(0)))), - WASM_I8(92)); + WASM_I32V_2(92)); FOR_INT32_INPUTS(i) { CHECK_EQ(92, r.Call(*i)); } } WASM_EXEC_TEST(BrTable0c) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD( r, B1(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(0), BR_TARGET(1))), RET_I8(76))), - WASM_I8(77)); + WASM_I32V_2(77)); FOR_INT32_INPUTS(i) { int32_t expected = *i == 0 ? 76 : 77; CHECK_EQ(expected, r.Call(*i)); @@ -943,18 +884,18 @@ WASM_EXEC_TEST(BrTable0c) { } WASM_EXEC_TEST(BrTable1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 0, BR_TARGET(0))), RET_I8(93)); FOR_INT32_INPUTS(i) { CHECK_EQ(93, r.Call(*i)); } } WASM_EXEC_TEST(BrTable_loop) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B2(B1(WASM_LOOP(WASM_BR_TABLE(WASM_INC_LOCAL_BYV(0, 1), 2, BR_TARGET(2), BR_TARGET(1), BR_TARGET(0)))), RET_I8(99)), - WASM_I8(98)); + WASM_I32V_2(98)); CHECK_EQ(99, r.Call(0)); CHECK_EQ(98, r.Call(-1)); CHECK_EQ(98, r.Call(-2)); @@ -963,11 +904,11 @@ WASM_EXEC_TEST(BrTable_loop) { } WASM_EXEC_TEST(BrTable_br) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 1, BR_TARGET(1), BR_TARGET(0))), RET_I8(91)), - WASM_I8(99)); + WASM_I32V_2(99)); CHECK_EQ(99, r.Call(0)); CHECK_EQ(91, r.Call(1)); CHECK_EQ(91, r.Call(2)); @@ -975,14 +916,14 @@ WASM_EXEC_TEST(BrTable_br) { } WASM_EXEC_TEST(BrTable_br2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B2(B2(B2(B1(WASM_BR_TABLE(WASM_GET_LOCAL(0), 3, BR_TARGET(1), BR_TARGET(2), BR_TARGET(3), BR_TARGET(0))), RET_I8(85)), RET_I8(86)), RET_I8(87)), - WASM_I8(88)); + WASM_I32V_2(88)); CHECK_EQ(86, r.Call(0)); CHECK_EQ(87, r.Call(1)); CHECK_EQ(88, r.Call(2)); @@ -1004,9 +945,9 @@ WASM_EXEC_TEST(BrTable4) { RET_I8(71)), RET_I8(72)), RET_I8(73)), - WASM_I8(75)}; + WASM_I32V_2(75)}; - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); r.Build(code, code + arraysize(code)); for (int x = -3; x < 50; ++x) { @@ -1034,9 +975,9 @@ WASM_EXEC_TEST(BrTable4x4) { RET_I8(51)), RET_I8(52)), RET_I8(53)), - WASM_I8(55)}; + WASM_I32V_2(55)}; - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); r.Build(code, code + arraysize(code)); for (int x = -6; x < 47; ++x) { @@ -1061,8 +1002,7 @@ WASM_EXEC_TEST(BrTable4_fallthru) { WASM_INC_LOCAL_BY(1, 8)), WASM_GET_LOCAL(1)}; - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); r.Build(code, code + arraysize(code)); CHECK_EQ(15, r.Call(0, 0)); @@ -1079,42 +1019,49 @@ WASM_EXEC_TEST(BrTable4_fallthru) { } WASM_EXEC_TEST(F32ReinterpretI32) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module); + WasmRunner<int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); BUILD(r, WASM_I32_REINTERPRET_F32( WASM_LOAD_MEM(MachineType::Float32(), WASM_ZERO))); FOR_INT32_INPUTS(i) { int32_t expected = *i; - module.WriteMemory(&memory[0], expected); + r.module().WriteMemory(&memory[0], expected); CHECK_EQ(expected, r.Call()); } } WASM_EXEC_TEST(I32ReinterpretF32) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); BUILD(r, WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_F32_REINTERPRET_I32(WASM_GET_LOCAL(0))), - WASM_I8(107)); + WASM_I32V_2(107)); FOR_INT32_INPUTS(i) { int32_t expected = *i; CHECK_EQ(107, r.Call(expected)); - CHECK_EQ(expected, module.ReadMemory(&memory[0])); + CHECK_EQ(expected, r.module().ReadMemory(&memory[0])); } } -WASM_EXEC_TEST(LoadMaxUint32Offset) { - TestingModule module(execution_mode); - module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module); +WASM_EXEC_TEST(SignallingNanSurvivesI32ReinterpretF32) { + WasmRunner<int32_t> r(execution_mode); + + BUILD(r, WASM_I32_REINTERPRET_F32( + WASM_SEQ(kExprF32Const, 0x00, 0x00, 0xa0, 0x7f))); + + // This is a signalling nan. + CHECK_EQ(0x7fa00000, r.Call()); +} + +WASM_EXEC_TEST_WITH_TRAP(LoadMaxUint32Offset) { + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemoryElems<int32_t>(8); - BUILD(r, kExprI8Const, 0, // index + BUILD(r, kExprI32Const, 0, // index static_cast<byte>(v8::internal::wasm::WasmOpcodes::LoadStoreOpcodeOf( MachineType::Int32(), false)), // -- 0, // alignment @@ -1124,9 +1071,8 @@ WASM_EXEC_TEST(LoadMaxUint32Offset) { } WASM_EXEC_TEST(LoadStoreLoad) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module); + WasmRunner<int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); BUILD(r, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)), @@ -1134,116 +1080,112 @@ WASM_EXEC_TEST(LoadStoreLoad) { FOR_INT32_INPUTS(i) { int32_t expected = *i; - module.WriteMemory(&memory[0], expected); + r.module().WriteMemory(&memory[0], expected); CHECK_EQ(expected, r.Call()); } } WASM_EXEC_TEST(VoidReturn1) { - // We use a wrapper function because WasmRunner<void> does not exist. + const int32_t kExpected = -414444; + WasmRunner<int32_t> r(execution_mode); // Build the test function. - TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t(sigs.v_v(), &module); - BUILD(t, kExprNop); - uint32_t index = t.CompileAndAdd(); + WasmFunctionCompiler& test_func = r.NewFunction<void>(); + BUILD(test_func, kExprNop); - const int32_t kExpected = -414444; // Build the calling function. - WasmRunner<int32_t> r(&module); - BUILD(r, WASM_CALL_FUNCTION0(index), WASM_I32V_3(kExpected)); + BUILD(r, WASM_CALL_FUNCTION0(test_func.function_index()), + WASM_I32V_3(kExpected)); + // Call and check. int32_t result = r.Call(); CHECK_EQ(kExpected, result); } WASM_EXEC_TEST(VoidReturn2) { - // We use a wrapper function because WasmRunner<void> does not exist. + const int32_t kExpected = -414444; + WasmRunner<int32_t> r(execution_mode); + // Build the test function. - TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t(sigs.v_v(), &module); - BUILD(t, WASM_RETURN0); - uint32_t index = t.CompileAndAdd(); + WasmFunctionCompiler& test_func = r.NewFunction<void>(); + BUILD(test_func, WASM_RETURN0); - const int32_t kExpected = -414444; // Build the calling function. - WasmRunner<int32_t> r(&module); - BUILD(r, B1(WASM_CALL_FUNCTION0(index)), WASM_I32V_3(kExpected)); + BUILD(r, WASM_CALL_FUNCTION0(test_func.function_index()), + WASM_I32V_3(kExpected)); + // Call and check. int32_t result = r.Call(); CHECK_EQ(kExpected, result); } WASM_EXEC_TEST(BrEmpty) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BRV(0, WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(BrIfEmpty) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BRV_IF(0, WASM_GET_LOCAL(0), WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_empty) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, kExprBlock, kLocalVoid, kExprEnd, WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_empty_br1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(WASM_BR(0)), WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_empty_brif1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_ZERO)), WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_empty_brif2) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_BLOCK(WASM_BR_IF(0, WASM_GET_LOCAL(1))), WASM_GET_LOCAL(0)); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); } } WASM_EXEC_TEST(Block_i) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BLOCK_I(WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_f) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_BLOCK_F(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_d) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_BLOCK_D(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { CHECK_FLOAT_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Block_br2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BLOCK_I(WASM_BRV(0, WASM_GET_LOCAL(0)))); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, static_cast<uint32_t>(r.Call(*i))); } } WASM_EXEC_TEST(Block_If_P) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // block { if (p0) break 51; 52; } - BUILD(r, WASM_BLOCK_I( // -- - WASM_IF(WASM_GET_LOCAL(0), // -- - WASM_BRV(1, WASM_I8(51))), // -- - WASM_I8(52))); // -- + BUILD(r, WASM_BLOCK_I( // -- + WASM_IF(WASM_GET_LOCAL(0), // -- + WASM_BRV(1, WASM_I32V_1(51))), // -- + WASM_I32V_1(52))); // -- FOR_INT32_INPUTS(i) { int32_t expected = *i ? 51 : 52; CHECK_EQ(expected, r.Call(*i)); @@ -1251,51 +1193,49 @@ WASM_EXEC_TEST(Block_If_P) { } WASM_EXEC_TEST(Loop_empty) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, kExprLoop, kLocalVoid, kExprEnd, WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Loop_i) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_LOOP_I(WASM_GET_LOCAL(0))); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Loop_f) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_LOOP_F(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Loop_d) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_LOOP_D(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { CHECK_FLOAT_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Loop_empty_br1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(WASM_LOOP(WASM_BR(1))), WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Loop_empty_brif1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(WASM_LOOP(WASM_BR_IF(1, WASM_ZERO))), WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i)); } } WASM_EXEC_TEST(Loop_empty_brif2) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_LOOP_I(WASM_BRV_IF(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)))); FOR_UINT32_INPUTS(i) { CHECK_EQ(*i, r.Call(*i, *i + 1)); } } WASM_EXEC_TEST(Loop_empty_brif3) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Uint32(), - MachineType::Uint32(), MachineType::Uint32()); + WasmRunner<uint32_t, uint32_t, uint32_t, uint32_t> r(execution_mode); BUILD(r, WASM_LOOP(WASM_BRV_IFD(1, WASM_GET_LOCAL(2), WASM_GET_LOCAL(0))), WASM_GET_LOCAL(1)); FOR_UINT32_INPUTS(i) { @@ -1307,9 +1247,9 @@ WASM_EXEC_TEST(Loop_empty_brif3) { } WASM_EXEC_TEST(Block_BrIf_P) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I8(51), WASM_GET_LOCAL(0)), - WASM_I8(52))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I32V_1(51), WASM_GET_LOCAL(0)), + WASM_I32V_1(52))); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 51 : 52; CHECK_EQ(expected, r.Call(*i)); @@ -1317,12 +1257,12 @@ WASM_EXEC_TEST(Block_BrIf_P) { } WASM_EXEC_TEST(Block_IfElse_P_assign) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // { if (p0) p0 = 71; else p0 = 72; return p0; } - BUILD(r, // -- - WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- - WASM_SET_LOCAL(0, WASM_I8(71)), // -- - WASM_SET_LOCAL(0, WASM_I8(72))), // -- + BUILD(r, // -- + WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- + WASM_SET_LOCAL(0, WASM_I32V_2(71)), // -- + WASM_SET_LOCAL(0, WASM_I32V_2(72))), // -- WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 71 : 72; @@ -1331,12 +1271,13 @@ WASM_EXEC_TEST(Block_IfElse_P_assign) { } WASM_EXEC_TEST(Block_IfElse_P_return) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // if (p0) return 81; else return 82; BUILD(r, // -- WASM_IF_ELSE(WASM_GET_LOCAL(0), // -- RET_I8(81), // -- - RET_I8(82))); // -- + RET_I8(82)), // -- + WASM_ZERO); // -- FOR_INT32_INPUTS(i) { int32_t expected = *i ? 81 : 82; CHECK_EQ(expected, r.Call(*i)); @@ -1344,9 +1285,9 @@ WASM_EXEC_TEST(Block_IfElse_P_return) { } WASM_EXEC_TEST(Block_If_P_assign) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // { if (p0) p0 = 61; p0; } - BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I8(61))), + BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SET_LOCAL(0, WASM_I32V_1(61))), WASM_GET_LOCAL(0)); FOR_INT32_INPUTS(i) { int32_t expected = *i ? 61 : *i; @@ -1355,18 +1296,18 @@ WASM_EXEC_TEST(Block_If_P_assign) { } WASM_EXEC_TEST(DanglingAssign) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // { return 0; p0 = 0; } - BUILD(r, B2(RET_I8(99), WASM_SET_LOCAL(0, WASM_ZERO))); + BUILD(r, WASM_BLOCK_I(RET_I8(99), WASM_TEE_LOCAL(0, WASM_ZERO))); CHECK_EQ(99, r.Call(1)); } WASM_EXEC_TEST(ExprIf_P) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // p0 ? 11 : 22; BUILD(r, WASM_IF_ELSE_I(WASM_GET_LOCAL(0), // -- - WASM_I8(11), // -- - WASM_I8(22))); // -- + WASM_I32V_1(11), // -- + WASM_I32V_1(22))); // -- FOR_INT32_INPUTS(i) { int32_t expected = *i ? 11 : 22; CHECK_EQ(expected, r.Call(*i)); @@ -1374,11 +1315,11 @@ WASM_EXEC_TEST(ExprIf_P) { } WASM_EXEC_TEST(CountDown) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_LOOP(WASM_IFB( - WASM_GET_LOCAL(0), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))), - WASM_BR(1))), + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_LOOP(WASM_IFB(WASM_GET_LOCAL(0), + WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), + WASM_I32V_1(1))), + WASM_BR(1))), WASM_GET_LOCAL(0)); CHECK_EQ(0, r.Call(1)); CHECK_EQ(0, r.Call(10)); @@ -1386,23 +1327,24 @@ WASM_EXEC_TEST(CountDown) { } WASM_EXEC_TEST(CountDown_fallthru) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_LOOP( - WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), - WASM_BRV(2, WASM_GET_LOCAL(0))), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1))), - WASM_CONTINUE(0)), - WASM_GET_LOCAL(0)); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD( + r, + WASM_LOOP( + WASM_IF(WASM_NOT(WASM_GET_LOCAL(0)), WASM_BRV(2, WASM_GET_LOCAL(0))), + WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(1))), + WASM_CONTINUE(0)), + WASM_GET_LOCAL(0)); CHECK_EQ(0, r.Call(1)); CHECK_EQ(0, r.Call(10)); CHECK_EQ(0, r.Call(100)); } WASM_EXEC_TEST(WhileCountDown) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_WHILE( - WASM_GET_LOCAL(0), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(1)))), + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_WHILE(WASM_GET_LOCAL(0), + WASM_SET_LOCAL( + 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(1)))), WASM_GET_LOCAL(0)); CHECK_EQ(0, r.Call(1)); CHECK_EQ(0, r.Call(10)); @@ -1410,10 +1352,9 @@ WASM_EXEC_TEST(WhileCountDown) { } WASM_EXEC_TEST(Loop_if_break1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_LOOP(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(2, WASM_GET_LOCAL(1))), - WASM_SET_LOCAL(0, WASM_I8(99))), + WASM_SET_LOCAL(0, WASM_I32V_2(99))), WASM_GET_LOCAL(0)); CHECK_EQ(99, r.Call(0, 11)); CHECK_EQ(65, r.Call(3, 65)); @@ -1422,10 +1363,9 @@ WASM_EXEC_TEST(Loop_if_break1) { } WASM_EXEC_TEST(Loop_if_break2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_LOOP(WASM_BRV_IF(1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)), - WASM_DROP, WASM_SET_LOCAL(0, WASM_I8(99))), + WASM_DROP, WASM_SET_LOCAL(0, WASM_I32V_2(99))), WASM_GET_LOCAL(0)); CHECK_EQ(99, r.Call(0, 33)); CHECK_EQ(3, r.Call(1, 3)); @@ -1434,9 +1374,9 @@ WASM_EXEC_TEST(Loop_if_break2) { } WASM_EXEC_TEST(Loop_if_break_fallthru) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(WASM_LOOP(WASM_IF(WASM_GET_LOCAL(0), WASM_BR(2)), - WASM_SET_LOCAL(0, WASM_I8(93)))), + WASM_SET_LOCAL(0, WASM_I32V_2(93)))), WASM_GET_LOCAL(0)); CHECK_EQ(93, r.Call(0)); CHECK_EQ(3, r.Call(3)); @@ -1445,9 +1385,9 @@ WASM_EXEC_TEST(Loop_if_break_fallthru) { } WASM_EXEC_TEST(Loop_if_break_fallthru2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, B1(B1(WASM_LOOP(WASM_IF(WASM_GET_LOCAL(0), WASM_BR(2)), - WASM_SET_LOCAL(0, WASM_I8(93))))), + WASM_SET_LOCAL(0, WASM_I32V_2(93))))), WASM_GET_LOCAL(0)); CHECK_EQ(93, r.Call(0)); CHECK_EQ(3, r.Call(3)); @@ -1456,71 +1396,68 @@ WASM_EXEC_TEST(Loop_if_break_fallthru2) { } WASM_EXEC_TEST(IfBreak1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), WASM_UNREACHABLE)), - WASM_I8(91)); + WASM_I32V_2(91)); CHECK_EQ(91, r.Call(0)); CHECK_EQ(91, r.Call(1)); CHECK_EQ(91, r.Call(-8734)); } WASM_EXEC_TEST(IfBreak2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_BR(0), RET_I8(77))), - WASM_I8(81)); + WASM_I32V_2(81)); CHECK_EQ(81, r.Call(0)); CHECK_EQ(81, r.Call(1)); CHECK_EQ(81, r.Call(-8734)); } WASM_EXEC_TEST(LoadMemI32) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - module.RandomizeMemory(1111); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); + r.module().RandomizeMemory(1111); - BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(0))); + BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)); - module.WriteMemory(&memory[0], 99999999); + r.module().WriteMemory(&memory[0], 99999999); CHECK_EQ(99999999, r.Call(0)); - module.WriteMemory(&memory[0], 88888888); + r.module().WriteMemory(&memory[0], 88888888); CHECK_EQ(88888888, r.Call(0)); - module.WriteMemory(&memory[0], 77777777); + r.module().WriteMemory(&memory[0], 77777777); CHECK_EQ(77777777, r.Call(0)); } WASM_EXEC_TEST(LoadMemI32_alignment) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(8); for (byte alignment = 0; alignment <= 2; ++alignment) { - WasmRunner<int32_t> r(&module, MachineType::Int32()); - module.RandomizeMemory(1111); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); + r.module().RandomizeMemory(1111); BUILD(r, - WASM_LOAD_MEM_ALIGNMENT(MachineType::Int32(), WASM_I8(0), alignment)); + WASM_LOAD_MEM_ALIGNMENT(MachineType::Int32(), WASM_ZERO, alignment)); - module.WriteMemory(&memory[0], 0x1a2b3c4d); + r.module().WriteMemory(&memory[0], 0x1a2b3c4d); CHECK_EQ(0x1a2b3c4d, r.Call(0)); - module.WriteMemory(&memory[0], 0x5e6f7a8b); + r.module().WriteMemory(&memory[0], 0x5e6f7a8b); CHECK_EQ(0x5e6f7a8b, r.Call(0)); - module.WriteMemory(&memory[0], 0x7ca0b1c2); + r.module().WriteMemory(&memory[0], 0x7ca0b1c2); CHECK_EQ(0x7ca0b1c2, r.Call(0)); } } -WASM_EXEC_TEST(LoadMemI32_oob) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(8); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); - module.RandomizeMemory(1111); +WASM_EXEC_TEST_WITH_TRAP(LoadMemI32_oob) { + WasmRunner<int32_t, uint32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(8); + r.module().RandomizeMemory(1111); BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))); - module.WriteMemory(&memory[0], 88888888); + r.module().WriteMemory(&memory[0], 88888888); CHECK_EQ(88888888, r.Call(0u)); for (uint32_t offset = 29; offset < 40; ++offset) { CHECK_TRAP(r.Call(offset)); @@ -1531,10 +1468,7 @@ WASM_EXEC_TEST(LoadMemI32_oob) { } } -WASM_EXEC_TEST(LoadMem_offset_oob) { - TestingModule module(execution_mode); - module.AddMemoryElems<int32_t>(8); - +WASM_EXEC_TEST_WITH_TRAP(LoadMem_offset_oob) { static const MachineType machineTypes[] = { MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), MachineType::Uint16(), MachineType::Int32(), MachineType::Uint32(), @@ -1542,8 +1476,10 @@ WASM_EXEC_TEST(LoadMem_offset_oob) { MachineType::Float64()}; for (size_t m = 0; m < arraysize(machineTypes); ++m) { - module.RandomizeMemory(1116 + static_cast<int>(m)); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); + WasmRunner<int32_t, uint32_t> r(execution_mode); + r.module().AddMemoryElems<int32_t>(8); + r.module().RandomizeMemory(1116 + static_cast<int>(m)); + uint32_t boundary = 24 - WasmOpcodes::MemSize(machineTypes[m]); BUILD(r, WASM_LOAD_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0)), @@ -1558,46 +1494,43 @@ WASM_EXEC_TEST(LoadMem_offset_oob) { } WASM_EXEC_TEST(LoadMemI32_offset) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(4); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - module.RandomizeMemory(1111); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(4); + r.module().RandomizeMemory(1111); BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0))); - module.WriteMemory(&memory[0], 66666666); - module.WriteMemory(&memory[1], 77777777); - module.WriteMemory(&memory[2], 88888888); - module.WriteMemory(&memory[3], 99999999); + r.module().WriteMemory(&memory[0], 66666666); + r.module().WriteMemory(&memory[1], 77777777); + r.module().WriteMemory(&memory[2], 88888888); + r.module().WriteMemory(&memory[3], 99999999); CHECK_EQ(77777777, r.Call(0)); CHECK_EQ(88888888, r.Call(4)); CHECK_EQ(99999999, r.Call(8)); - module.WriteMemory(&memory[0], 11111111); - module.WriteMemory(&memory[1], 22222222); - module.WriteMemory(&memory[2], 33333333); - module.WriteMemory(&memory[3], 44444444); + r.module().WriteMemory(&memory[0], 11111111); + r.module().WriteMemory(&memory[1], 22222222); + r.module().WriteMemory(&memory[2], 33333333); + r.module().WriteMemory(&memory[3], 44444444); CHECK_EQ(22222222, r.Call(0)); CHECK_EQ(33333333, r.Call(4)); CHECK_EQ(44444444, r.Call(8)); } -WASM_EXEC_TEST(LoadMemI32_const_oob_misaligned) { +WASM_EXEC_TEST_WITH_TRAP(LoadMemI32_const_oob_misaligned) { const int kMemSize = 12; // TODO(titzer): Fix misaligned accesses on MIPS and re-enable. for (int offset = 0; offset < kMemSize + 5; ++offset) { for (int index = 0; index < kMemSize + 5; ++index) { - TestingModule module(execution_mode); - module.AddMemoryElems<byte>(kMemSize); - - WasmRunner<int32_t> r(&module); - module.RandomizeMemory(); + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemoryElems<byte>(kMemSize); + r.module().RandomizeMemory(); - BUILD(r, - WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index))); + BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, + WASM_I32V_2(index))); if ((offset + index) <= static_cast<int>((kMemSize - sizeof(int32_t)))) { - CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call()); + CHECK_EQ(r.module().raw_val_at<int32_t>(offset + index), r.Call()); } else { CHECK_TRAP(r.Call()); } @@ -1605,21 +1538,19 @@ WASM_EXEC_TEST(LoadMemI32_const_oob_misaligned) { } } -WASM_EXEC_TEST(LoadMemI32_const_oob) { +WASM_EXEC_TEST_WITH_TRAP(LoadMemI32_const_oob) { const int kMemSize = 24; for (int offset = 0; offset < kMemSize + 5; offset += 4) { for (int index = 0; index < kMemSize + 5; index += 4) { - TestingModule module(execution_mode); - module.AddMemoryElems<byte>(kMemSize); - - WasmRunner<int32_t> r(&module); - module.RandomizeMemory(); + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemoryElems<byte>(kMemSize); + r.module().RandomizeMemory(); - BUILD(r, - WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, WASM_I8(index))); + BUILD(r, WASM_LOAD_MEM_OFFSET(MachineType::Int32(), offset, + WASM_I32V_2(index))); if ((offset + index) <= static_cast<int>((kMemSize - sizeof(int32_t)))) { - CHECK_EQ(module.raw_val_at<int32_t>(offset + index), r.Call()); + CHECK_EQ(r.module().raw_val_at<int32_t>(offset + index), r.Call()); } else { CHECK_TRAP(r.Call()); } @@ -1628,27 +1559,25 @@ WASM_EXEC_TEST(LoadMemI32_const_oob) { } WASM_EXEC_TEST(StoreMemI32_alignment) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(4); const int32_t kWritten = 0x12345678; for (byte i = 0; i <= 2; ++i) { - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(4); BUILD(r, WASM_STORE_MEM_ALIGNMENT(MachineType::Int32(), WASM_ZERO, i, WASM_GET_LOCAL(0)), WASM_GET_LOCAL(0)); - module.RandomizeMemory(1111); + r.module().RandomizeMemory(1111); memory[0] = 0; CHECK_EQ(kWritten, r.Call(kWritten)); - CHECK_EQ(kWritten, module.ReadMemory(&memory[0])); + CHECK_EQ(kWritten, r.module().ReadMemory(&memory[0])); } } WASM_EXEC_TEST(StoreMemI32_offset) { - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(4); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(4); const int32_t kWritten = 0xaabbccdd; BUILD(r, WASM_STORE_MEM_OFFSET(MachineType::Int32(), 4, WASM_GET_LOCAL(0), @@ -1656,23 +1585,20 @@ WASM_EXEC_TEST(StoreMemI32_offset) { WASM_I32V_5(kWritten)); for (int i = 0; i < 2; ++i) { - module.RandomizeMemory(1111); - module.WriteMemory(&memory[0], 66666666); - module.WriteMemory(&memory[1], 77777777); - module.WriteMemory(&memory[2], 88888888); - module.WriteMemory(&memory[3], 99999999); + r.module().RandomizeMemory(1111); + r.module().WriteMemory(&memory[0], 66666666); + r.module().WriteMemory(&memory[1], 77777777); + r.module().WriteMemory(&memory[2], 88888888); + r.module().WriteMemory(&memory[3], 99999999); CHECK_EQ(kWritten, r.Call(i * 4)); - CHECK_EQ(66666666, module.ReadMemory(&memory[0])); - CHECK_EQ(i == 0 ? kWritten : 77777777, module.ReadMemory(&memory[1])); - CHECK_EQ(i == 1 ? kWritten : 88888888, module.ReadMemory(&memory[2])); - CHECK_EQ(i == 2 ? kWritten : 99999999, module.ReadMemory(&memory[3])); + CHECK_EQ(66666666, r.module().ReadMemory(&memory[0])); + CHECK_EQ(i == 0 ? kWritten : 77777777, r.module().ReadMemory(&memory[1])); + CHECK_EQ(i == 1 ? kWritten : 88888888, r.module().ReadMemory(&memory[2])); + CHECK_EQ(i == 2 ? kWritten : 99999999, r.module().ReadMemory(&memory[3])); } } -WASM_EXEC_TEST(StoreMem_offset_oob) { - TestingModule module(execution_mode); - byte* memory = module.AddMemoryElems<byte>(32); - +WASM_EXEC_TEST_WITH_TRAP(StoreMem_offset_oob) { // 64-bit cases are handled in test-run-wasm-64.cc static const MachineType machineTypes[] = { MachineType::Int8(), MachineType::Uint8(), MachineType::Int16(), @@ -1680,8 +1606,10 @@ WASM_EXEC_TEST(StoreMem_offset_oob) { MachineType::Float32(), MachineType::Float64()}; for (size_t m = 0; m < arraysize(machineTypes); ++m) { - module.RandomizeMemory(1119 + static_cast<int>(m)); - WasmRunner<int32_t> r(&module, MachineType::Uint32()); + WasmRunner<int32_t, uint32_t> r(execution_mode); + byte* memory = r.module().AddMemoryElems<byte>(32); + + r.module().RandomizeMemory(1119 + static_cast<int>(m)); BUILD(r, WASM_STORE_MEM_OFFSET(machineTypes[m], 8, WASM_GET_LOCAL(0), WASM_LOAD_MEM(machineTypes[m], WASM_ZERO)), @@ -1700,43 +1628,40 @@ WASM_EXEC_TEST(StoreMem_offset_oob) { WASM_EXEC_TEST(LoadMemI32_P) { const int kNumElems = 8; - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(kNumElems); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - module.RandomizeMemory(2222); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* memory = r.module().AddMemoryElems<int32_t>(kNumElems); + r.module().RandomizeMemory(2222); BUILD(r, WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0))); for (int i = 0; i < kNumElems; ++i) { - CHECK_EQ(module.ReadMemory(&memory[i]), r.Call(i * 4)); + CHECK_EQ(r.module().ReadMemory(&memory[i]), r.Call(i * 4)); } } WASM_EXEC_TEST(MemI32_Sum) { const int kNumElems = 20; - TestingModule module(execution_mode); - uint32_t* memory = module.AddMemoryElems<uint32_t>(kNumElems); - WasmRunner<uint32_t> r(&module, MachineType::Int32()); - const byte kSum = r.AllocateLocal(kAstI32); + WasmRunner<uint32_t, int32_t> r(execution_mode); + uint32_t* memory = r.module().AddMemoryElems<uint32_t>(kNumElems); + const byte kSum = r.AllocateLocal(kWasmI32); - BUILD( - r, - WASM_WHILE( - WASM_GET_LOCAL(0), - WASM_BLOCK( - WASM_SET_LOCAL(kSum, - WASM_I32_ADD(WASM_GET_LOCAL(kSum), + BUILD(r, WASM_WHILE( + WASM_GET_LOCAL(0), + WASM_BLOCK( + WASM_SET_LOCAL( + kSum, WASM_I32_ADD(WASM_GET_LOCAL(kSum), WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(0)))), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))), - WASM_GET_LOCAL(1)); + WASM_SET_LOCAL( + 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(4))))), + WASM_GET_LOCAL(1)); // Run 4 trials. for (int i = 0; i < 3; ++i) { - module.RandomizeMemory(i * 33); + r.module().RandomizeMemory(i * 33); uint32_t expected = 0; for (size_t j = kNumElems - 1; j > 0; --j) { - expected += module.ReadMemory(&memory[j]); + expected += r.module().ReadMemory(&memory[j]); } uint32_t result = r.Call(4 * (kNumElems - 1)); CHECK_EQ(expected, result); @@ -1745,9 +1670,8 @@ WASM_EXEC_TEST(MemI32_Sum) { WASM_EXEC_TEST(CheckMachIntsZero) { const int kNumElems = 55; - TestingModule module(execution_mode); - module.AddMemoryElems<uint32_t>(kNumElems); - WasmRunner<uint32_t> r(&module, MachineType::Int32()); + WasmRunner<uint32_t, int32_t> r(execution_mode); + r.module().AddMemoryElems<uint32_t>(kNumElems); BUILD(r, // -- /**/ kExprLoop, kLocalVoid, // -- @@ -1756,78 +1680,76 @@ WASM_EXEC_TEST(CheckMachIntsZero) { /* */ kExprGetLocal, 0, // -- /* */ kExprI32LoadMem, 0, 0, // -- /* */ kExprIf, kLocalVoid, // -- - /* */ kExprI8Const, 255, // -- + /* */ kExprI32Const, 127, // -- /* */ kExprReturn, // -- /* */ kExprEnd, // -- /* */ kExprGetLocal, 0, // -- - /* */ kExprI8Const, 4, // -- + /* */ kExprI32Const, 4, // -- /* */ kExprI32Sub, // -- /* */ kExprTeeLocal, 0, // -- /* */ kExprBr, DEPTH_0, // -- /* */ kExprEnd, // -- /**/ kExprEnd, // -- - /**/ kExprI8Const, 0); // -- + /**/ kExprI32Const, 0); // -- - module.BlankMemory(); - CHECK_EQ(0u, r.Call((kNumElems - 1) * 4)); + r.module().BlankMemory(); + CHECK_EQ(0, r.Call((kNumElems - 1) * 4)); } WASM_EXEC_TEST(MemF32_Sum) { const int kSize = 5; - TestingModule module(execution_mode); - module.AddMemoryElems<float>(kSize); - float* buffer = module.raw_mem_start<float>(); - module.WriteMemory(&buffer[0], -99.25f); - module.WriteMemory(&buffer[1], -888.25f); - module.WriteMemory(&buffer[2], -77.25f); - module.WriteMemory(&buffer[3], 66666.25f); - module.WriteMemory(&buffer[4], 5555.25f); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - const byte kSum = r.AllocateLocal(kAstF32); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.module().AddMemoryElems<float>(kSize); + float* buffer = r.module().raw_mem_start<float>(); + r.module().WriteMemory(&buffer[0], -99.25f); + r.module().WriteMemory(&buffer[1], -888.25f); + r.module().WriteMemory(&buffer[2], -77.25f); + r.module().WriteMemory(&buffer[3], 66666.25f); + r.module().WriteMemory(&buffer[4], 5555.25f); + const byte kSum = r.AllocateLocal(kWasmF32); - BUILD( - r, - WASM_WHILE( - WASM_GET_LOCAL(0), - WASM_BLOCK( - WASM_SET_LOCAL(kSum, - WASM_F32_ADD(WASM_GET_LOCAL(kSum), + BUILD(r, WASM_WHILE( + WASM_GET_LOCAL(0), + WASM_BLOCK( + WASM_SET_LOCAL( + kSum, WASM_F32_ADD(WASM_GET_LOCAL(kSum), WASM_LOAD_MEM(MachineType::Float32(), WASM_GET_LOCAL(0)))), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I8(4))))), - WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)), - WASM_GET_LOCAL(0)); + WASM_SET_LOCAL( + 0, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_I32V_1(4))))), + WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)), + WASM_GET_LOCAL(0)); CHECK_EQ(0, r.Call(4 * (kSize - 1))); - CHECK_NE(-99.25f, module.ReadMemory(&buffer[0])); - CHECK_EQ(71256.0f, module.ReadMemory(&buffer[0])); + CHECK_NE(-99.25f, r.module().ReadMemory(&buffer[0])); + CHECK_EQ(71256.0f, r.module().ReadMemory(&buffer[0])); } template <typename T> T GenerateAndRunFold(WasmExecutionMode execution_mode, WasmOpcode binop, - T* buffer, uint32_t size, LocalType astType, + T* buffer, uint32_t size, ValueType astType, MachineType memType) { - TestingModule module(execution_mode); - T* memory = module.AddMemoryElems<T>(size); + WasmRunner<int32_t, int32_t> r(execution_mode); + T* memory = r.module().AddMemoryElems<T>(size); for (uint32_t i = 0; i < size; ++i) { - module.WriteMemory(&memory[i], buffer[i]); + r.module().WriteMemory(&memory[i], buffer[i]); } - WasmRunner<int32_t> r(&module, MachineType::Int32()); const byte kAccum = r.AllocateLocal(astType); - BUILD(r, WASM_SET_LOCAL(kAccum, WASM_LOAD_MEM(memType, WASM_ZERO)), - WASM_WHILE( - WASM_GET_LOCAL(0), - WASM_BLOCK(WASM_SET_LOCAL( - kAccum, WASM_BINOP(binop, WASM_GET_LOCAL(kAccum), - WASM_LOAD_MEM( - memType, WASM_GET_LOCAL(0)))), - WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), - WASM_I8(sizeof(T)))))), - WASM_STORE_MEM(memType, WASM_ZERO, WASM_GET_LOCAL(kAccum)), - WASM_GET_LOCAL(0)); + BUILD( + r, WASM_SET_LOCAL(kAccum, WASM_LOAD_MEM(memType, WASM_ZERO)), + WASM_WHILE( + WASM_GET_LOCAL(0), + WASM_BLOCK(WASM_SET_LOCAL( + kAccum, + WASM_BINOP(binop, WASM_GET_LOCAL(kAccum), + WASM_LOAD_MEM(memType, WASM_GET_LOCAL(0)))), + WASM_SET_LOCAL(0, WASM_I32_SUB(WASM_GET_LOCAL(0), + WASM_I32V_1(sizeof(T)))))), + WASM_STORE_MEM(memType, WASM_ZERO, WASM_GET_LOCAL(kAccum)), + WASM_GET_LOCAL(0)); r.Call(static_cast<int>(sizeof(T) * (size - 1))); - return module.ReadMemory(&memory[0]); + return r.module().ReadMemory(&memory[0]); } WASM_EXEC_TEST(MemF64_Mul) { @@ -1835,20 +1757,19 @@ WASM_EXEC_TEST(MemF64_Mul) { double buffer[kSize] = {1, 2, 2, 2, 2, 2}; double result = GenerateAndRunFold<double>(execution_mode, kExprF64Mul, buffer, kSize, - kAstF64, MachineType::Float64()); + kWasmF64, MachineType::Float64()); CHECK_EQ(32, result); } WASM_EXEC_TEST(Build_Wasm_Infinite_Loop) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); // Only build the graph and compile, don't run. - BUILD(r, WASM_INFINITE_LOOP); + BUILD(r, WASM_INFINITE_LOOP, WASM_ZERO); } WASM_EXEC_TEST(Build_Wasm_Infinite_Loop_effect) { - TestingModule module(execution_mode); - module.AddMemoryElems<int8_t>(16); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.module().AddMemoryElems<int8_t>(16); // Only build the graph and compile, don't run. BUILD(r, WASM_LOOP(WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO), WASM_DROP), @@ -1856,72 +1777,83 @@ WASM_EXEC_TEST(Build_Wasm_Infinite_Loop_effect) { } WASM_EXEC_TEST(Unreachable0a) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_BRV(0, WASM_I8(9)), RET(WASM_GET_LOCAL(0)))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BRV(0, WASM_I32V_1(9)), RET(WASM_GET_LOCAL(0)))); CHECK_EQ(9, r.Call(0)); CHECK_EQ(9, r.Call(1)); } WASM_EXEC_TEST(Unreachable0b) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_BRV(0, WASM_I8(7)), WASM_UNREACHABLE)); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BRV(0, WASM_I32V_1(7)), WASM_UNREACHABLE)); CHECK_EQ(7, r.Call(0)); CHECK_EQ(7, r.Call(1)); } TEST(Build_Wasm_Unreachable1) { - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); BUILD(r, WASM_UNREACHABLE); } TEST(Build_Wasm_Unreachable2) { - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE); } TEST(Build_Wasm_Unreachable3) { - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); BUILD(r, WASM_UNREACHABLE, WASM_UNREACHABLE, WASM_UNREACHABLE); } TEST(Build_Wasm_UnreachableIf1) { - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); - BUILD(r, WASM_UNREACHABLE, WASM_IF(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0))); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + BUILD(r, WASM_UNREACHABLE, + WASM_IF(WASM_GET_LOCAL(0), WASM_SEQ(WASM_GET_LOCAL(0), WASM_DROP)), + WASM_ZERO); } TEST(Build_Wasm_UnreachableIf2) { - WasmRunner<int32_t> r(kExecuteCompiled, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); BUILD(r, WASM_UNREACHABLE, - WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE)); + WASM_IF_ELSE_I(WASM_GET_LOCAL(0), WASM_GET_LOCAL(0), WASM_UNREACHABLE)); } WASM_EXEC_TEST(Unreachable_Load) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + r.module().AddMemory(8); BUILD(r, WASM_BLOCK_I(WASM_BRV(0, WASM_GET_LOCAL(0)), WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0)))); CHECK_EQ(11, r.Call(11)); CHECK_EQ(21, r.Call(21)); } +WASM_EXEC_TEST(BrV_Fallthrough) { + WasmRunner<int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BLOCK(WASM_BRV(1, WASM_I32V_1(42))), + WASM_I32V_1(22))); + CHECK_EQ(42, r.Call()); +} + WASM_EXEC_TEST(Infinite_Loop_not_taken1) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I8(45)); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_IF(WASM_GET_LOCAL(0), WASM_INFINITE_LOOP), WASM_I32V_1(45)); // Run the code, but don't go into the infinite loop. CHECK_EQ(45, r.Call(0)); } WASM_EXEC_TEST(Infinite_Loop_not_taken2) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, - WASM_BLOCK_I(WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(45)), - WASM_INFINITE_LOOP))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I( + WASM_IF_ELSE(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I32V_1(45)), + WASM_INFINITE_LOOP), + WASM_ZERO)); // Run the code, but don't go into the infinite loop. CHECK_EQ(45, r.Call(1)); } WASM_EXEC_TEST(Infinite_Loop_not_taken2_brif) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_BRV_IF(0, WASM_I8(45), WASM_GET_LOCAL(0)), + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BRV_IF(0, WASM_I32V_1(45), WASM_GET_LOCAL(0)), WASM_INFINITE_LOOP)); // Run the code, but don't go into the infinite loop. CHECK_EQ(45, r.Call(1)); @@ -1940,13 +1872,19 @@ static void TestBuildGraphForSimpleExpression(WasmOpcode opcode) { FunctionSig* sig = WasmOpcodes::Signature(opcode); if (sig->parameter_count() == 1) { - byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode)}; + byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, static_cast<byte>(opcode), + WASM_END}; TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code, code + arraysize(code)); } else { - CHECK_EQ(2u, sig->parameter_count()); - byte code[] = {WASM_NO_LOCALS, kExprGetLocal, 0, kExprGetLocal, 1, - static_cast<byte>(opcode)}; + CHECK_EQ(2, sig->parameter_count()); + byte code[] = {WASM_NO_LOCALS, + kExprGetLocal, + 0, + kExprGetLocal, + 1, + static_cast<byte>(opcode), + WASM_END}; TestBuildingGraph(&zone, &jsgraph, nullptr, sig, nullptr, code, code + arraysize(code)); } @@ -1963,12 +1901,11 @@ TEST(Build_Wasm_SimpleExprs) { } WASM_EXEC_TEST(Int32LoadInt8_signext) { - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); const int kNumElems = 16; - int8_t* memory = module.AddMemoryElems<int8_t>(kNumElems); - module.RandomizeMemory(); + int8_t* memory = r.module().AddMemoryElems<int8_t>(kNumElems); + r.module().RandomizeMemory(); memory[0] = -1; - WasmRunner<int32_t> r(&module, MachineType::Int32()); BUILD(r, WASM_LOAD_MEM(MachineType::Int8(), WASM_GET_LOCAL(0))); for (int i = 0; i < kNumElems; ++i) { @@ -1977,12 +1914,11 @@ WASM_EXEC_TEST(Int32LoadInt8_signext) { } WASM_EXEC_TEST(Int32LoadInt8_zeroext) { - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); const int kNumElems = 16; - byte* memory = module.AddMemory(kNumElems); - module.RandomizeMemory(77); + byte* memory = r.module().AddMemory(kNumElems); + r.module().RandomizeMemory(77); memory[0] = 255; - WasmRunner<int32_t> r(&module, MachineType::Int32()); BUILD(r, WASM_LOAD_MEM(MachineType::Uint8(), WASM_GET_LOCAL(0))); for (int i = 0; i < kNumElems; ++i) { @@ -1991,12 +1927,11 @@ WASM_EXEC_TEST(Int32LoadInt8_zeroext) { } WASM_EXEC_TEST(Int32LoadInt16_signext) { - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); const int kNumBytes = 16; - byte* memory = module.AddMemory(kNumBytes); - module.RandomizeMemory(888); + byte* memory = r.module().AddMemory(kNumBytes); + r.module().RandomizeMemory(888); memory[1] = 200; - WasmRunner<int32_t> r(&module, MachineType::Int32()); BUILD(r, WASM_LOAD_MEM(MachineType::Int16(), WASM_GET_LOCAL(0))); for (int i = 0; i < kNumBytes; i += 2) { @@ -2006,12 +1941,11 @@ WASM_EXEC_TEST(Int32LoadInt16_signext) { } WASM_EXEC_TEST(Int32LoadInt16_zeroext) { - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); const int kNumBytes = 16; - byte* memory = module.AddMemory(kNumBytes); - module.RandomizeMemory(9999); + byte* memory = r.module().AddMemory(kNumBytes); + r.module().RandomizeMemory(9999); memory[1] = 204; - WasmRunner<int32_t> r(&module, MachineType::Int32()); BUILD(r, WASM_LOAD_MEM(MachineType::Uint16(), WASM_GET_LOCAL(0))); for (int i = 0; i < kNumBytes; i += 2) { @@ -2021,9 +1955,8 @@ WASM_EXEC_TEST(Int32LoadInt16_zeroext) { } WASM_EXEC_TEST(Int32Global) { - TestingModule module(execution_mode); - int32_t* global = module.AddGlobal<int32_t>(kAstI32); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* global = r.module().AddGlobal<int32_t>(); // global = global + p0 BUILD(r, WASM_SET_GLOBAL(0, WASM_I32_ADD(WASM_GET_GLOBAL(0), WASM_GET_LOCAL(0))), @@ -2039,14 +1972,13 @@ WASM_EXEC_TEST(Int32Global) { WASM_EXEC_TEST(Int32Globals_DontAlias) { const int kNumGlobals = 3; - TestingModule module(execution_mode); - int32_t* globals[] = {module.AddGlobal<int32_t>(kAstI32), - module.AddGlobal<int32_t>(kAstI32), - module.AddGlobal<int32_t>(kAstI32)}; - for (int g = 0; g < kNumGlobals; ++g) { // global = global + p0 - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + int32_t* globals[] = {r.module().AddGlobal<int32_t>(), + r.module().AddGlobal<int32_t>(), + r.module().AddGlobal<int32_t>()}; + BUILD(r, WASM_SET_GLOBAL( g, WASM_I32_ADD(WASM_GET_GLOBAL(g), WASM_GET_LOCAL(0))), WASM_GET_GLOBAL(g)); @@ -2068,9 +2000,8 @@ WASM_EXEC_TEST(Int32Globals_DontAlias) { } WASM_EXEC_TEST(Float32Global) { - TestingModule module(execution_mode); - float* global = module.AddGlobal<float>(kAstF32); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + float* global = r.module().AddGlobal<float>(); // global = global + p0 BUILD(r, WASM_SET_GLOBAL( 0, WASM_F32_ADD(WASM_GET_GLOBAL(0), @@ -2086,9 +2017,8 @@ WASM_EXEC_TEST(Float32Global) { } WASM_EXEC_TEST(Float64Global) { - TestingModule module(execution_mode); - double* global = module.AddGlobal<double>(kAstF64); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); + double* global = r.module().AddGlobal<double>(); // global = global + p0 BUILD(r, WASM_SET_GLOBAL( 0, WASM_F64_ADD(WASM_GET_GLOBAL(0), @@ -2104,16 +2034,15 @@ WASM_EXEC_TEST(Float64Global) { } WASM_EXEC_TEST(MixedGlobals) { - TestingModule module(execution_mode); - int32_t* unused = module.AddGlobal<int32_t>(kAstI32); - byte* memory = module.AddMemory(32); + WasmRunner<int32_t, int32_t> r(execution_mode); - int32_t* var_int32 = module.AddGlobal<int32_t>(kAstI32); - uint32_t* var_uint32 = module.AddGlobal<uint32_t>(kAstI32); - float* var_float = module.AddGlobal<float>(kAstF32); - double* var_double = module.AddGlobal<double>(kAstF64); + int32_t* unused = r.module().AddGlobal<int32_t>(); + byte* memory = r.module().AddMemory(32); - WasmRunner<int32_t> r(&module, MachineType::Int32()); + int32_t* var_int32 = r.module().AddGlobal<int32_t>(); + uint32_t* var_uint32 = r.module().AddGlobal<uint32_t>(); + float* var_float = r.module().AddGlobal<float>(); + double* var_double = r.module().AddGlobal<double>(); BUILD(r, WASM_SET_GLOBAL(1, WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)), WASM_SET_GLOBAL(2, WASM_LOAD_MEM(MachineType::Uint32(), WASM_ZERO)), @@ -2141,36 +2070,33 @@ WASM_EXEC_TEST(MixedGlobals) { WASM_EXEC_TEST(CallEmpty) { const int32_t kExpected = -414444; + WasmRunner<int32_t> r(execution_mode); + // Build the target function. - TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t(sigs.i_v(), &module); - BUILD(t, WASM_I32V_3(kExpected)); - uint32_t index = t.CompileAndAdd(); + WasmFunctionCompiler& target_func = r.NewFunction<int>(); + BUILD(target_func, WASM_I32V_3(kExpected)); // Build the calling function. - WasmRunner<int32_t> r(&module); - BUILD(r, WASM_CALL_FUNCTION0(index)); + BUILD(r, WASM_CALL_FUNCTION0(target_func.function_index())); int32_t result = r.Call(); CHECK_EQ(kExpected, result); } WASM_EXEC_TEST(CallF32StackParameter) { + WasmRunner<float> r(execution_mode); + // Build the target function. - LocalType param_types[20]; - for (int i = 0; i < 20; ++i) param_types[i] = kAstF32; + ValueType param_types[20]; + for (int i = 0; i < 20; ++i) param_types[i] = kWasmF32; FunctionSig sig(1, 19, param_types); - TestingModule module(execution_mode); - WasmFunctionCompiler t(&sig, &module); + WasmFunctionCompiler& t = r.NewFunction(&sig); BUILD(t, WASM_GET_LOCAL(17)); - uint32_t index = t.CompileAndAdd(); // Build the calling function. - WasmRunner<float> r(&module); BUILD(r, WASM_CALL_FUNCTION( - index, WASM_F32(1.0f), WASM_F32(2.0f), WASM_F32(4.0f), - WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f), + t.function_index(), WASM_F32(1.0f), WASM_F32(2.0f), + WASM_F32(4.0f), WASM_F32(8.0f), WASM_F32(16.0f), WASM_F32(32.0f), WASM_F32(64.0f), WASM_F32(128.0f), WASM_F32(256.0f), WASM_F32(1.5f), WASM_F32(2.5f), WASM_F32(4.5f), WASM_F32(8.5f), WASM_F32(16.5f), WASM_F32(32.5f), WASM_F32(64.5f), @@ -2181,18 +2107,17 @@ WASM_EXEC_TEST(CallF32StackParameter) { } WASM_EXEC_TEST(CallF64StackParameter) { + WasmRunner<double> r(execution_mode); + // Build the target function. - LocalType param_types[20]; - for (int i = 0; i < 20; ++i) param_types[i] = kAstF64; + ValueType param_types[20]; + for (int i = 0; i < 20; ++i) param_types[i] = kWasmF64; FunctionSig sig(1, 19, param_types); - TestingModule module(execution_mode); - WasmFunctionCompiler t(&sig, &module); + WasmFunctionCompiler& t = r.NewFunction(&sig); BUILD(t, WASM_GET_LOCAL(17)); - uint32_t index = t.CompileAndAdd(); // Build the calling function. - WasmRunner<double> r(&module); - BUILD(r, WASM_CALL_FUNCTION(index, WASM_F64(1.0), WASM_F64(2.0), + BUILD(r, WASM_CALL_FUNCTION(t.function_index(), WASM_F64(1.0), WASM_F64(2.0), WASM_F64(4.0), WASM_F64(8.0), WASM_F64(16.0), WASM_F64(32.0), WASM_F64(64.0), WASM_F64(128.0), WASM_F64(256.0), WASM_F64(1.5), WASM_F64(2.5), @@ -2205,41 +2130,39 @@ WASM_EXEC_TEST(CallF64StackParameter) { } WASM_EXEC_TEST(CallVoid) { + WasmRunner<int32_t> r(execution_mode); + const byte kMemOffset = 8; const int32_t kElemNum = kMemOffset / sizeof(int32_t); const int32_t kExpected = 414444; // Build the target function. TestSignatures sigs; - TestingModule module(execution_mode); - int32_t* memory = module.AddMemoryElems<int32_t>(16 / sizeof(int32_t)); - module.RandomizeMemory(); - WasmFunctionCompiler t(sigs.v_v(), &module); - BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I8(kMemOffset), + int32_t* memory = r.module().AddMemoryElems<int32_t>(16 / sizeof(int32_t)); + r.module().RandomizeMemory(); + WasmFunctionCompiler& t = r.NewFunction(sigs.v_v()); + BUILD(t, WASM_STORE_MEM(MachineType::Int32(), WASM_I32V_1(kMemOffset), WASM_I32V_3(kExpected))); - uint32_t index = t.CompileAndAdd(); // Build the calling function. - WasmRunner<int32_t> r(&module); - BUILD(r, WASM_CALL_FUNCTION0(index), - WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kMemOffset))); + BUILD(r, WASM_CALL_FUNCTION0(t.function_index()), + WASM_LOAD_MEM(MachineType::Int32(), WASM_I32V_1(kMemOffset))); int32_t result = r.Call(); CHECK_EQ(kExpected, result); CHECK_EQ(static_cast<int64_t>(kExpected), - static_cast<int64_t>(module.ReadMemory(&memory[kElemNum]))); + static_cast<int64_t>(r.module().ReadMemory(&memory[kElemNum]))); } WASM_EXEC_TEST(Call_Int32Add) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + // Build the target function. - TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t(sigs.i_ii(), &module); + WasmFunctionCompiler& t = r.NewFunction<int32_t, int32_t, int32_t>(); BUILD(t, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - uint32_t index = t.CompileAndAdd(); // Build the caller function. - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); - BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); + BUILD(r, WASM_CALL_FUNCTION(t.function_index(), WASM_GET_LOCAL(0), + WASM_GET_LOCAL(1))); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { @@ -2251,17 +2174,15 @@ WASM_EXEC_TEST(Call_Int32Add) { } WASM_EXEC_TEST(Call_Float32Sub) { - TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t(sigs.f_ff(), &module); + WasmRunner<float, float, float> r(execution_mode); // Build the target function. - BUILD(t, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - uint32_t index = t.CompileAndAdd(); + WasmFunctionCompiler& target_func = r.NewFunction<float, float, float>(); + BUILD(target_func, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - // Builder the caller function. - WasmRunner<float> r(&module, MachineType::Float32(), MachineType::Float32()); - BUILD(r, WASM_CALL_FUNCTION(index, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); + // Build the caller function. + BUILD(r, WASM_CALL_FUNCTION(target_func.function_index(), WASM_GET_LOCAL(0), + WASM_GET_LOCAL(1))); FOR_FLOAT32_INPUTS(i) { FOR_FLOAT32_INPUTS(j) { CHECK_FLOAT_EQ(*i - *j, r.Call(*i, *j)); } @@ -2269,27 +2190,28 @@ WASM_EXEC_TEST(Call_Float32Sub) { } WASM_EXEC_TEST(Call_Float64Sub) { - TestingModule module(execution_mode); - double* memory = module.AddMemoryElems<double>(16); - WasmRunner<int32_t> r(&module); + WasmRunner<int32_t> r(execution_mode); + double* memory = r.module().AddMemoryElems<double>(16); BUILD(r, WASM_STORE_MEM( MachineType::Float64(), WASM_ZERO, - WASM_F64_SUB(WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO), - WASM_LOAD_MEM(MachineType::Float64(), WASM_I8(8)))), - WASM_I8(107)); + WASM_F64_SUB( + WASM_LOAD_MEM(MachineType::Float64(), WASM_ZERO), + WASM_LOAD_MEM(MachineType::Float64(), WASM_I32V_1(8)))), + WASM_I32V_2(107)); FOR_FLOAT64_INPUTS(i) { FOR_FLOAT64_INPUTS(j) { - module.WriteMemory(&memory[0], *i); - module.WriteMemory(&memory[1], *j); + r.module().WriteMemory(&memory[0], *i); + r.module().WriteMemory(&memory[1], *j); double expected = *i - *j; CHECK_EQ(107, r.Call()); if (expected != expected) { - CHECK(module.ReadMemory(&memory[0]) != module.ReadMemory(&memory[0])); + CHECK(r.module().ReadMemory(&memory[0]) != + r.module().ReadMemory(&memory[0])); } else { - CHECK_EQ(expected, module.ReadMemory(&memory[0])); + CHECK_EQ(expected, r.module().ReadMemory(&memory[0])); } } } @@ -2317,28 +2239,25 @@ static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { for (int which = 0; which < num_params; ++which) { v8::internal::AccountingAllocator allocator; Zone zone(&allocator, ZONE_NAME); - TestingModule module(execution_mode); - module.AddMemory(1024); + WasmRunner<int32_t> r(execution_mode); + r.module().AddMemory(1024); MachineType* memtypes = &mixed[start]; MachineType result = memtypes[which]; // ========================================================================= // Build the selector function. // ========================================================================= - uint32_t index; FunctionSig::Builder b(&zone, 1, num_params); - b.AddReturn(WasmOpcodes::LocalTypeFor(result)); + b.AddReturn(WasmOpcodes::ValueTypeFor(result)); for (int i = 0; i < num_params; ++i) { - b.AddParam(WasmOpcodes::LocalTypeFor(memtypes[i])); + b.AddParam(WasmOpcodes::ValueTypeFor(memtypes[i])); } - WasmFunctionCompiler t(b.Build(), &module); + WasmFunctionCompiler& t = r.NewFunction(b.Build()); BUILD(t, WASM_GET_LOCAL(which)); - index = t.CompileAndAdd(); // ========================================================================= // Build the calling function. // ========================================================================= - WasmRunner<int32_t> r(&module); std::vector<byte> code; // Load the offset for the store. @@ -2347,11 +2266,11 @@ static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { // Load the arguments. for (int i = 0; i < num_params; ++i) { int offset = (i + 1) * kElemSize; - ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I8(offset))); + ADD_CODE(code, WASM_LOAD_MEM(memtypes[i], WASM_I32V_2(offset))); } // Call the selector function. - ADD_CODE(code, kExprCallFunction, static_cast<byte>(index)); + ADD_CODE(code, WASM_CALL_FUNCTION0(t.function_index())); // Store the result in memory. ADD_CODE(code, @@ -2365,14 +2284,14 @@ static void Run_WasmMixedCall_N(WasmExecutionMode execution_mode, int start) { // Run the code. for (int t = 0; t < 10; ++t) { - module.RandomizeMemory(); + r.module().RandomizeMemory(); CHECK_EQ(kExpected, r.Call()); int size = WasmOpcodes::MemSize(result); for (int i = 0; i < size; ++i) { int base = (which + 1) * kElemSize; - byte expected = module.raw_mem_at<byte>(base + i); - byte result = module.raw_mem_at<byte>(i); + byte expected = r.module().raw_mem_at<byte>(base + i); + byte result = r.module().raw_mem_at<byte>(i); CHECK_EQ(expected, result); } } @@ -2385,15 +2304,12 @@ WASM_EXEC_TEST(MixedCall_2) { Run_WasmMixedCall_N(execution_mode, 2); } WASM_EXEC_TEST(MixedCall_3) { Run_WasmMixedCall_N(execution_mode, 3); } WASM_EXEC_TEST(AddCall) { - TestSignatures sigs; - TestingModule module(execution_mode); - WasmFunctionCompiler t1(sigs.i_ii(), &module); + WasmRunner<int32_t, int32_t> r(kExecuteCompiled); + WasmFunctionCompiler& t1 = r.NewFunction<int32_t, int32_t, int32_t>(); BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t1.CompileAndAdd(); - WasmRunner<int32_t> r(&module, MachineType::Int32()); - byte local = r.AllocateLocal(kAstI32); - BUILD(r, WASM_SET_LOCAL(local, WASM_I8(99)), + byte local = r.AllocateLocal(kWasmI32); + BUILD(r, WASM_SET_LOCAL(local, WASM_I32V_2(99)), WASM_I32_ADD(WASM_CALL_FUNCTION(t1.function_index(), WASM_GET_LOCAL(0), WASM_GET_LOCAL(0)), WASM_CALL_FUNCTION(t1.function_index(), WASM_GET_LOCAL(1), @@ -2406,16 +2322,15 @@ WASM_EXEC_TEST(AddCall) { WASM_EXEC_TEST(MultiReturnSub) { FLAG_wasm_mv_prototype = true; - LocalType storage[] = {kAstI32, kAstI32, kAstI32, kAstI32}; + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); + + ValueType storage[] = {kWasmI32, kWasmI32, kWasmI32, kWasmI32}; FunctionSig sig_ii_ii(2, 2, storage); - TestingModule module(execution_mode); - WasmFunctionCompiler t1(&sig_ii_ii, &module); + WasmFunctionCompiler& t1 = r.NewFunction(&sig_ii_ii); BUILD(t1, WASM_GET_LOCAL(1), WASM_GET_LOCAL(0)); - t1.CompileAndAdd(); - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32()); - BUILD(r, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), kExprCallFunction, 0, - kExprI32Sub); + BUILD(r, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), + WASM_CALL_FUNCTION0(t1.function_index()), kExprI32Sub); FOR_INT32_INPUTS(i) { FOR_INT32_INPUTS(j) { @@ -2427,10 +2342,10 @@ WASM_EXEC_TEST(MultiReturnSub) { } template <typename T> -void RunMultiReturnSelect(WasmExecutionMode execution_mode, LocalType type, - const T* inputs) { +void RunMultiReturnSelect(WasmExecutionMode execution_mode, const T* inputs) { FLAG_wasm_mv_prototype = true; - LocalType storage[] = {type, type, type, type, type, type}; + ValueType type = WasmOpcodes::ValueTypeFor(MachineTypeForC<T>()); + ValueType storage[] = {type, type, type, type, type, type}; const size_t kNumReturns = 2; const size_t kNumParams = arraysize(storage) - kNumReturns; FunctionSig sig(kNumReturns, kNumParams, storage); @@ -2438,30 +2353,25 @@ void RunMultiReturnSelect(WasmExecutionMode execution_mode, LocalType type, for (size_t i = 0; i < kNumParams; i++) { for (size_t j = 0; j < kNumParams; j++) { for (int k = 0; k < 2; k++) { - TestingModule module(execution_mode); - WasmFunctionCompiler r1(&sig, &module); + WasmRunner<T, T, T, T, T> r(execution_mode); + WasmFunctionCompiler& r1 = r.NewFunction(&sig); BUILD(r1, WASM_GET_LOCAL(i), WASM_GET_LOCAL(j)); - r1.CompileAndAdd(); - - MachineType machine_type = WasmOpcodes::MachineTypeFor(type); - WasmRunner<T> r2(&module, machine_type, machine_type, machine_type, - machine_type); if (k == 0) { - BUILD(r2, WASM_CALL_FUNCTION(r1.function_index(), WASM_GET_LOCAL(0), - WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), - WASM_GET_LOCAL(3)), + BUILD(r, WASM_CALL_FUNCTION(r1.function_index(), WASM_GET_LOCAL(0), + WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), + WASM_GET_LOCAL(3)), WASM_DROP); } else { - BUILD(r2, WASM_CALL_FUNCTION(r1.function_index(), WASM_GET_LOCAL(0), - WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), - WASM_GET_LOCAL(3)), + BUILD(r, WASM_CALL_FUNCTION(r1.function_index(), WASM_GET_LOCAL(0), + WASM_GET_LOCAL(1), WASM_GET_LOCAL(2), + WASM_GET_LOCAL(3)), kExprSetLocal, 0, WASM_DROP, WASM_GET_LOCAL(0)); } T expected = inputs[k == 0 ? i : j]; - CHECK_EQ(expected, r2.Call(inputs[0], inputs[1], inputs[2], inputs[3])); + CHECK_EQ(expected, r.Call(inputs[0], inputs[1], inputs[2], inputs[3])); } } } @@ -2469,12 +2379,12 @@ void RunMultiReturnSelect(WasmExecutionMode execution_mode, LocalType type, WASM_EXEC_TEST(MultiReturnSelect_i32) { static const int32_t inputs[] = {3333333, 4444444, -55555555, -7777777}; - RunMultiReturnSelect<int32_t>(execution_mode, kAstI32, inputs); + RunMultiReturnSelect<int32_t>(execution_mode, inputs); } WASM_EXEC_TEST(MultiReturnSelect_f32) { static const float inputs[] = {33.33333f, 444.4444f, -55555.555f, -77777.77f}; - RunMultiReturnSelect<float>(execution_mode, kAstF32, inputs); + RunMultiReturnSelect<float>(execution_mode, inputs); } WASM_EXEC_TEST(MultiReturnSelect_i64) { @@ -2482,60 +2392,60 @@ WASM_EXEC_TEST(MultiReturnSelect_i64) { // TODO(titzer): implement int64-lowering for multiple return values static const int64_t inputs[] = {33333338888, 44444446666, -555555553333, -77777771111}; - RunMultiReturnSelect<int64_t>(execution_mode, kAstI64, inputs); + RunMultiReturnSelect<int64_t>(execution_mode, inputs); #endif } WASM_EXEC_TEST(MultiReturnSelect_f64) { static const double inputs[] = {3.333333, 44444.44, -55.555555, -7777.777}; - RunMultiReturnSelect<double>(execution_mode, kAstF64, inputs); + RunMultiReturnSelect<double>(execution_mode, inputs); } WASM_EXEC_TEST(ExprBlock2a) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), - WASM_I8(1))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I32V_1(1))), + WASM_I32V_1(1))); CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(1)); } WASM_EXEC_TEST(ExprBlock2b) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I8(1))), - WASM_I8(2))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_I32V_1(1))), + WASM_I32V_1(2))); CHECK_EQ(2, r.Call(0)); CHECK_EQ(1, r.Call(1)); } WASM_EXEC_TEST(ExprBlock2c) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I8(1), WASM_GET_LOCAL(0)), - WASM_I8(1))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I32V_1(1), WASM_GET_LOCAL(0)), + WASM_I32V_1(1))); CHECK_EQ(1, r.Call(0)); CHECK_EQ(1, r.Call(1)); } WASM_EXEC_TEST(ExprBlock2d) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I8(1), WASM_GET_LOCAL(0)), - WASM_I8(2))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I32V_1(1), WASM_GET_LOCAL(0)), + WASM_I32V_1(2))); CHECK_EQ(2, r.Call(0)); CHECK_EQ(1, r.Call(1)); } WASM_EXEC_TEST(ExprBlock_ManualSwitch) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, WASM_BLOCK_I(WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1)), - WASM_BRV(1, WASM_I8(11))), - WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2)), - WASM_BRV(1, WASM_I8(12))), - WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3)), - WASM_BRV(1, WASM_I8(13))), - WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4)), - WASM_BRV(1, WASM_I8(14))), - WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5)), - WASM_BRV(1, WASM_I8(15))), - WASM_I8(99))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I(WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(1)), + WASM_BRV(1, WASM_I32V_1(11))), + WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(2)), + WASM_BRV(1, WASM_I32V_1(12))), + WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(3)), + WASM_BRV(1, WASM_I32V_1(13))), + WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(4)), + WASM_BRV(1, WASM_I32V_1(14))), + WASM_IF(WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(5)), + WASM_BRV(1, WASM_I32V_1(15))), + WASM_I32V_2(99))); CHECK_EQ(99, r.Call(0)); CHECK_EQ(11, r.Call(1)); CHECK_EQ(12, r.Call(2)); @@ -2546,19 +2456,19 @@ WASM_EXEC_TEST(ExprBlock_ManualSwitch) { } WASM_EXEC_TEST(ExprBlock_ManualSwitch_brif) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); - BUILD(r, - WASM_BLOCK_I(WASM_BRV_IFD(0, WASM_I8(11), - WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(1))), - WASM_BRV_IFD(0, WASM_I8(12), - WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(2))), - WASM_BRV_IFD(0, WASM_I8(13), - WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(3))), - WASM_BRV_IFD(0, WASM_I8(14), - WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(4))), - WASM_BRV_IFD(0, WASM_I8(15), - WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I8(5))), - WASM_I8(99))); + WasmRunner<int32_t, int32_t> r(execution_mode); + BUILD(r, WASM_BLOCK_I( + WASM_BRV_IFD(0, WASM_I32V_1(11), + WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(1))), + WASM_BRV_IFD(0, WASM_I32V_1(12), + WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(2))), + WASM_BRV_IFD(0, WASM_I32V_1(13), + WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(3))), + WASM_BRV_IFD(0, WASM_I32V_1(14), + WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(4))), + WASM_BRV_IFD(0, WASM_I32V_1(15), + WASM_I32_EQ(WASM_GET_LOCAL(0), WASM_I32V_1(5))), + WASM_I32V_2(99))); CHECK_EQ(99, r.Call(0)); CHECK_EQ(11, r.Call(1)); CHECK_EQ(12, r.Call(2)); @@ -2569,13 +2479,14 @@ WASM_EXEC_TEST(ExprBlock_ManualSwitch_brif) { } WASM_EXEC_TEST(If_nested) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); - BUILD(r, WASM_IF_ELSE_I( - WASM_GET_LOCAL(0), - WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I8(11), WASM_I8(12)), - WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I8(13), WASM_I8(14)))); + BUILD( + r, + WASM_IF_ELSE_I( + WASM_GET_LOCAL(0), + WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I32V_1(11), WASM_I32V_1(12)), + WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_I32V_1(13), WASM_I32V_1(14)))); CHECK_EQ(11, r.Call(1, 1)); CHECK_EQ(12, r.Call(1, 0)); @@ -2584,26 +2495,25 @@ WASM_EXEC_TEST(If_nested) { } WASM_EXEC_TEST(ExprBlock_if) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32()); + WasmRunner<int32_t, int32_t> r(execution_mode); - BUILD(r, - WASM_BLOCK_I(WASM_IF_ELSE_I(WASM_GET_LOCAL(0), WASM_BRV(0, WASM_I8(11)), - WASM_BRV(1, WASM_I8(14))))); + BUILD(r, WASM_BLOCK_I(WASM_IF_ELSE_I(WASM_GET_LOCAL(0), + WASM_BRV(0, WASM_I32V_1(11)), + WASM_BRV(1, WASM_I32V_1(14))))); CHECK_EQ(11, r.Call(1)); CHECK_EQ(14, r.Call(0)); } WASM_EXEC_TEST(ExprBlock_nested_ifs) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_BLOCK_I(WASM_IF_ELSE_I( WASM_GET_LOCAL(0), - WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(11)), - WASM_BRV(1, WASM_I8(12))), - WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I8(13)), - WASM_BRV(1, WASM_I8(14)))))); + WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I32V_1(11)), + WASM_BRV(1, WASM_I32V_1(12))), + WASM_IF_ELSE_I(WASM_GET_LOCAL(1), WASM_BRV(0, WASM_I32V_1(13)), + WASM_BRV(1, WASM_I32V_1(14)))))); CHECK_EQ(11, r.Call(1, 1)); CHECK_EQ(12, r.Call(1, 0)); @@ -2611,64 +2521,66 @@ WASM_EXEC_TEST(ExprBlock_nested_ifs) { CHECK_EQ(14, r.Call(0, 0)); } -WASM_EXEC_TEST(SimpleCallIndirect) { +WASM_EXEC_TEST_WITH_TRAP(SimpleCallIndirect) { TestSignatures sigs; - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); - WasmFunctionCompiler t1(sigs.i_ii(), &module); + WasmFunctionCompiler& t1 = r.NewFunction(sigs.i_ii()); BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t1.CompileAndAdd(/*sig_index*/ 1); + t1.SetSigIndex(1); - WasmFunctionCompiler t2(sigs.i_ii(), &module); + WasmFunctionCompiler& t2 = r.NewFunction(sigs.i_ii()); BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t2.CompileAndAdd(/*sig_index*/ 1); + t2.SetSigIndex(1); // Signature table. - module.AddSignature(sigs.f_ff()); - module.AddSignature(sigs.i_ii()); - module.AddSignature(sigs.d_dd()); + r.module().AddSignature(sigs.f_ff()); + r.module().AddSignature(sigs.i_ii()); + r.module().AddSignature(sigs.d_dd()); // Function table. - uint16_t indirect_function_table[] = {0, 1}; - module.AddIndirectFunctionTable(indirect_function_table, - arraysize(indirect_function_table)); - module.PopulateIndirectFunctionTable(); + uint16_t indirect_function_table[] = { + static_cast<uint16_t>(t1.function_index()), + static_cast<uint16_t>(t2.function_index())}; + r.module().AddIndirectFunctionTable(indirect_function_table, + arraysize(indirect_function_table)); + r.module().PopulateIndirectFunctionTable(); - // Builder the caller function. - WasmRunner<int32_t> r(&module, MachineType::Int32()); - BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22))); + // Build the caller function. + BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I32V_2(66), + WASM_I32V_1(22))); CHECK_EQ(88, r.Call(0)); CHECK_EQ(44, r.Call(1)); CHECK_TRAP(r.Call(2)); } -WASM_EXEC_TEST(MultipleCallIndirect) { +WASM_EXEC_TEST_WITH_TRAP(MultipleCallIndirect) { TestSignatures sigs; - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t, int32_t, int32_t> r(execution_mode); - WasmFunctionCompiler t1(sigs.i_ii(), &module); + WasmFunctionCompiler& t1 = r.NewFunction(sigs.i_ii()); BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t1.CompileAndAdd(/*sig_index*/ 1); + t1.SetSigIndex(1); - WasmFunctionCompiler t2(sigs.i_ii(), &module); + WasmFunctionCompiler& t2 = r.NewFunction(sigs.i_ii()); BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t2.CompileAndAdd(/*sig_index*/ 1); + t2.SetSigIndex(1); // Signature table. - module.AddSignature(sigs.f_ff()); - module.AddSignature(sigs.i_ii()); - module.AddSignature(sigs.d_dd()); + r.module().AddSignature(sigs.f_ff()); + r.module().AddSignature(sigs.i_ii()); + r.module().AddSignature(sigs.d_dd()); // Function table. - uint16_t indirect_function_table[] = {0, 1}; - module.AddIndirectFunctionTable(indirect_function_table, - arraysize(indirect_function_table)); - module.PopulateIndirectFunctionTable(); - - // Builder the caller function. - WasmRunner<int32_t> r(&module, MachineType::Int32(), MachineType::Int32(), - MachineType::Int32()); + uint16_t indirect_function_table[] = { + static_cast<uint16_t>(t1.function_index()), + static_cast<uint16_t>(t2.function_index())}; + r.module().AddIndirectFunctionTable(indirect_function_table, + arraysize(indirect_function_table)); + r.module().PopulateIndirectFunctionTable(); + + // Build the caller function. BUILD(r, WASM_I32_ADD( WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_GET_LOCAL(1), WASM_GET_LOCAL(2)), @@ -2686,49 +2598,49 @@ WASM_EXEC_TEST(MultipleCallIndirect) { CHECK_TRAP(r.Call(2, 1, 0)); } -WASM_EXEC_TEST(CallIndirect_EmptyTable) { +WASM_EXEC_TEST_WITH_TRAP(CallIndirect_EmptyTable) { TestSignatures sigs; - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); // One function. - WasmFunctionCompiler t1(sigs.i_ii(), &module); + WasmFunctionCompiler& t1 = r.NewFunction(sigs.i_ii()); BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t1.CompileAndAdd(/*sig_index*/ 1); + t1.SetSigIndex(1); // Signature table. - module.AddSignature(sigs.f_ff()); - module.AddSignature(sigs.i_ii()); - module.AddIndirectFunctionTable(nullptr, 0); + r.module().AddSignature(sigs.f_ff()); + r.module().AddSignature(sigs.i_ii()); + r.module().AddIndirectFunctionTable(nullptr, 0); - // Builder the caller function. - WasmRunner<int32_t> r(&module, MachineType::Int32()); - BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(66), WASM_I8(22))); + // Build the caller function. + BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I32V_2(66), + WASM_I32V_1(22))); CHECK_TRAP(r.Call(0)); CHECK_TRAP(r.Call(1)); CHECK_TRAP(r.Call(2)); } -WASM_EXEC_TEST(CallIndirect_canonical) { +WASM_EXEC_TEST_WITH_TRAP(CallIndirect_canonical) { TestSignatures sigs; - TestingModule module(execution_mode); + WasmRunner<int32_t, int32_t> r(execution_mode); - WasmFunctionCompiler t1(sigs.i_ii(), &module); + WasmFunctionCompiler& t1 = r.NewFunction(sigs.i_ii()); BUILD(t1, WASM_I32_ADD(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t1.CompileAndAdd(/*sig_index*/ 0); + t1.SetSigIndex(0); - WasmFunctionCompiler t2(sigs.i_ii(), &module); + WasmFunctionCompiler& t2 = r.NewFunction(sigs.i_ii()); BUILD(t2, WASM_I32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t2.CompileAndAdd(/*sig_index*/ 1); + t2.SetSigIndex(1); - WasmFunctionCompiler t3(sigs.f_ff(), &module); + WasmFunctionCompiler& t3 = r.NewFunction(sigs.f_ff()); BUILD(t3, WASM_F32_SUB(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); - t3.CompileAndAdd(/*sig_index*/ 2); + t3.SetSigIndex(2); // Signature table. - module.AddSignature(sigs.i_ii()); - module.AddSignature(sigs.i_ii()); - module.AddSignature(sigs.f_ff()); + r.module().AddSignature(sigs.i_ii()); + r.module().AddSignature(sigs.i_ii()); + r.module().AddSignature(sigs.f_ff()); // Function table. uint16_t i1 = static_cast<uint16_t>(t1.function_index()); @@ -2736,13 +2648,13 @@ WASM_EXEC_TEST(CallIndirect_canonical) { uint16_t i3 = static_cast<uint16_t>(t3.function_index()); uint16_t indirect_function_table[] = {i1, i2, i3, i1, i2}; - module.AddIndirectFunctionTable(indirect_function_table, - arraysize(indirect_function_table)); - module.PopulateIndirectFunctionTable(); + r.module().AddIndirectFunctionTable(indirect_function_table, + arraysize(indirect_function_table)); + r.module().PopulateIndirectFunctionTable(); - // Builder the caller function. - WasmRunner<int32_t> r(&module, MachineType::Int32()); - BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I8(77), WASM_I8(11))); + // Build the caller function. + BUILD(r, WASM_CALL_INDIRECT2(1, WASM_GET_LOCAL(0), WASM_I32V_2(77), + WASM_I32V_1(11))); CHECK_EQ(88, r.Call(0)); CHECK_EQ(66, r.Call(1)); @@ -2753,64 +2665,63 @@ WASM_EXEC_TEST(CallIndirect_canonical) { } WASM_EXEC_TEST(F32Floor) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_F32_FLOOR(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(floorf(*i), r.Call(*i)); } } WASM_EXEC_TEST(F32Ceil) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_F32_CEIL(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(ceilf(*i), r.Call(*i)); } } WASM_EXEC_TEST(F32Trunc) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_F32_TRUNC(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(truncf(*i), r.Call(*i)); } } WASM_EXEC_TEST(F32NearestInt) { - WasmRunner<float> r(execution_mode, MachineType::Float32()); + WasmRunner<float, float> r(execution_mode); BUILD(r, WASM_F32_NEARESTINT(WASM_GET_LOCAL(0))); FOR_FLOAT32_INPUTS(i) { CHECK_FLOAT_EQ(nearbyintf(*i), r.Call(*i)); } } WASM_EXEC_TEST(F64Floor) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_F64_FLOOR(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(floor(*i), r.Call(*i)); } } WASM_EXEC_TEST(F64Ceil) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_F64_CEIL(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(ceil(*i), r.Call(*i)); } } WASM_EXEC_TEST(F64Trunc) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_F64_TRUNC(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(trunc(*i), r.Call(*i)); } } WASM_EXEC_TEST(F64NearestInt) { - WasmRunner<double> r(execution_mode, MachineType::Float64()); + WasmRunner<double, double> r(execution_mode); BUILD(r, WASM_F64_NEARESTINT(WASM_GET_LOCAL(0))); FOR_FLOAT64_INPUTS(i) { CHECK_DOUBLE_EQ(nearbyint(*i), r.Call(*i)); } } WASM_EXEC_TEST(F32Min) { - WasmRunner<float> r(execution_mode, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<float, float, float> r(execution_mode); BUILD(r, WASM_F32_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_FLOAT32_INPUTS(i) { @@ -2819,8 +2730,7 @@ WASM_EXEC_TEST(F32Min) { } WASM_EXEC_TEST(F64Min) { - WasmRunner<double> r(execution_mode, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<double, double, double> r(execution_mode); BUILD(r, WASM_F64_MIN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_FLOAT64_INPUTS(i) { @@ -2829,8 +2739,7 @@ WASM_EXEC_TEST(F64Min) { } WASM_EXEC_TEST(F32Max) { - WasmRunner<float> r(execution_mode, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<float, float, float> r(execution_mode); BUILD(r, WASM_F32_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_FLOAT32_INPUTS(i) { @@ -2839,8 +2748,7 @@ WASM_EXEC_TEST(F32Max) { } WASM_EXEC_TEST(F64Max) { - WasmRunner<double> r(execution_mode, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<double, double, double> r(execution_mode); BUILD(r, WASM_F64_MAX(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_FLOAT64_INPUTS(i) { @@ -2851,8 +2759,8 @@ WASM_EXEC_TEST(F64Max) { } } -WASM_EXEC_TEST(I32SConvertF32) { - WasmRunner<int32_t> r(execution_mode, MachineType::Float32()); +WASM_EXEC_TEST_WITH_TRAP(I32SConvertF32) { + WasmRunner<int32_t, float> r(execution_mode); BUILD(r, WASM_I32_SCONVERT_F32(WASM_GET_LOCAL(0))); // The upper bound is (INT32_MAX + 1), which is the lowest float-representable @@ -2871,8 +2779,8 @@ WASM_EXEC_TEST(I32SConvertF32) { } } -WASM_EXEC_TEST(I32SConvertF64) { - WasmRunner<int32_t> r(execution_mode, MachineType::Float64()); +WASM_EXEC_TEST_WITH_TRAP(I32SConvertF64) { + WasmRunner<int32_t, double> r(execution_mode); BUILD(r, WASM_I32_SCONVERT_F64(WASM_GET_LOCAL(0))); // The upper bound is (INT32_MAX + 1), which is the lowest double- @@ -2890,8 +2798,8 @@ WASM_EXEC_TEST(I32SConvertF64) { } } -WASM_EXEC_TEST(I32UConvertF32) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Float32()); +WASM_EXEC_TEST_WITH_TRAP(I32UConvertF32) { + WasmRunner<uint32_t, float> r(execution_mode); BUILD(r, WASM_I32_UCONVERT_F32(WASM_GET_LOCAL(0))); // The upper bound is (UINT32_MAX + 1), which is the lowest // float-representable number above UINT32_MAX which cannot be represented as @@ -2907,8 +2815,8 @@ WASM_EXEC_TEST(I32UConvertF32) { } } -WASM_EXEC_TEST(I32UConvertF64) { - WasmRunner<uint32_t> r(execution_mode, MachineType::Float64()); +WASM_EXEC_TEST_WITH_TRAP(I32UConvertF64) { + WasmRunner<uint32_t, double> r(execution_mode); BUILD(r, WASM_I32_UCONVERT_F64(WASM_GET_LOCAL(0))); // The upper bound is (UINT32_MAX + 1), which is the lowest // double-representable number above UINT32_MAX which cannot be represented as @@ -2925,8 +2833,7 @@ WASM_EXEC_TEST(I32UConvertF64) { } WASM_EXEC_TEST(F64CopySign) { - WasmRunner<double> r(execution_mode, MachineType::Float64(), - MachineType::Float64()); + WasmRunner<double, double, double> r(execution_mode); BUILD(r, WASM_F64_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_FLOAT64_INPUTS(i) { @@ -2935,8 +2842,7 @@ WASM_EXEC_TEST(F64CopySign) { } WASM_EXEC_TEST(F32CopySign) { - WasmRunner<float> r(execution_mode, MachineType::Float32(), - MachineType::Float32()); + WasmRunner<float, float, float> r(execution_mode); BUILD(r, WASM_F32_COPYSIGN(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1))); FOR_FLOAT32_INPUTS(i) { @@ -2944,44 +2850,39 @@ WASM_EXEC_TEST(F32CopySign) { } } -static void CompileCallIndirectMany(LocalType param) { +static void CompileCallIndirectMany(ValueType param) { // Make sure we don't run out of registers when compiling indirect calls // with many many parameters. TestSignatures sigs; for (byte num_params = 0; num_params < 40; ++num_params) { - v8::internal::AccountingAllocator allocator; - Zone zone(&allocator, ZONE_NAME); - HandleScope scope(CcTest::InitIsolateOnce()); - TestingModule module(kExecuteCompiled); - FunctionSig* sig = sigs.many(&zone, kAstStmt, param, num_params); + WasmRunner<void> r(kExecuteCompiled); + FunctionSig* sig = sigs.many(r.zone(), kWasmStmt, param, num_params); - module.AddSignature(sig); - module.AddSignature(sig); - module.AddIndirectFunctionTable(nullptr, 0); + r.module().AddSignature(sig); + r.module().AddSignature(sig); + r.module().AddIndirectFunctionTable(nullptr, 0); - WasmFunctionCompiler t(sig, &module); + WasmFunctionCompiler& t = r.NewFunction(sig); std::vector<byte> code; for (byte p = 0; p < num_params; ++p) { ADD_CODE(code, kExprGetLocal, p); } - ADD_CODE(code, kExprI8Const, 0); + ADD_CODE(code, kExprI32Const, 0); ADD_CODE(code, kExprCallIndirect, 1, TABLE_ZERO); t.Build(&code[0], &code[0] + code.size()); - t.Compile(); } } -TEST(Compile_Wasm_CallIndirect_Many_i32) { CompileCallIndirectMany(kAstI32); } +TEST(Compile_Wasm_CallIndirect_Many_i32) { CompileCallIndirectMany(kWasmI32); } -TEST(Compile_Wasm_CallIndirect_Many_f32) { CompileCallIndirectMany(kAstF32); } +TEST(Compile_Wasm_CallIndirect_Many_f32) { CompileCallIndirectMany(kWasmF32); } -TEST(Compile_Wasm_CallIndirect_Many_f64) { CompileCallIndirectMany(kAstF64); } +TEST(Compile_Wasm_CallIndirect_Many_f64) { CompileCallIndirectMany(kWasmF64); } -WASM_EXEC_TEST(Int32RemS_dead) { - WasmRunner<int32_t> r(execution_mode, MachineType::Int32(), - MachineType::Int32()); +WASM_EXEC_TEST_WITH_TRAP(Int32RemS_dead) { + WasmRunner<int32_t, int32_t, int32_t> r(execution_mode); BUILD(r, WASM_I32_REMS(WASM_GET_LOCAL(0), WASM_GET_LOCAL(1)), WASM_DROP, WASM_ZERO); const int32_t kMin = std::numeric_limits<int32_t>::min(); diff --git a/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc b/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc new file mode 100644 index 0000000000..d2374a44c0 --- /dev/null +++ b/deps/v8/test/cctest/wasm/test-wasm-breakpoints.cc @@ -0,0 +1,70 @@ +// Copyright 2016 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/debug/debug-interface.h" +#include "src/wasm/wasm-macro-gen.h" +#include "src/wasm/wasm-objects.h" + +#include "test/cctest/cctest.h" +#include "test/cctest/compiler/value-helper.h" +#include "test/cctest/wasm/wasm-run-utils.h" +#include "test/common/wasm/test-signatures.h" + +using namespace v8::internal; +using namespace v8::internal::wasm; +namespace debug = v8::debug; + +namespace { + +void CheckLocations( + WasmCompiledModule *compiled_module, debug::Location start, + debug::Location end, + std::initializer_list<debug::Location> expected_locations_init) { + std::vector<debug::Location> locations; + bool success = + compiled_module->GetPossibleBreakpoints(start, end, &locations); + CHECK(success); + + printf("got %d locations: ", static_cast<int>(locations.size())); + for (size_t i = 0, e = locations.size(); i != e; ++i) { + printf("%s<%d,%d>", i == 0 ? "" : ", ", locations[i].GetLineNumber(), + locations[i].GetColumnNumber()); + } + printf("\n"); + + std::vector<debug::Location> expected_locations(expected_locations_init); + CHECK_EQ(expected_locations.size(), locations.size()); + for (size_t i = 0, e = locations.size(); i != e; ++i) { + CHECK_EQ(expected_locations[i].GetLineNumber(), + locations[i].GetLineNumber()); + CHECK_EQ(expected_locations[i].GetColumnNumber(), + locations[i].GetColumnNumber()); + } +} +void CheckLocationsFail(WasmCompiledModule *compiled_module, + debug::Location start, debug::Location end) { + std::vector<debug::Location> locations; + bool success = + compiled_module->GetPossibleBreakpoints(start, end, &locations); + CHECK(!success); +} + +} // namespace + +TEST(CollectPossibleBreakpoints) { + WasmRunner<int> runner(kExecuteCompiled); + + BUILD(runner, WASM_NOP, WASM_I32_ADD(WASM_ZERO, WASM_ONE)); + + Handle<WasmInstanceObject> instance = runner.module().instance_object(); + std::vector<debug::Location> locations; + CheckLocations(instance->compiled_module(), {0, 0}, {1, 0}, + {{0, 1}, {0, 2}, {0, 4}, {0, 6}, {0, 7}}); + CheckLocations(instance->compiled_module(), {0, 2}, {0, 4}, {{0, 2}}); + CheckLocations(instance->compiled_module(), {0, 2}, {0, 5}, {{0, 2}, {0, 4}}); + CheckLocations(instance->compiled_module(), {0, 7}, {0, 8}, {{0, 7}}); + CheckLocations(instance->compiled_module(), {0, 7}, {1, 0}, {{0, 7}}); + CheckLocations(instance->compiled_module(), {0, 8}, {1, 0}, {}); + CheckLocationsFail(instance->compiled_module(), {0, 9}, {1, 0}); +} diff --git a/deps/v8/test/cctest/wasm/test-wasm-stack.cc b/deps/v8/test/cctest/wasm/test-wasm-stack.cc index a0c2e73f9d..357a4e487e 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-stack.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-stack.cc @@ -76,25 +76,22 @@ void CheckExceptionInfos(Handle<Object> exc, // Call from JS to WASM to JS and throw an Error from JS. TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) { + WasmRunner<void> r(kExecuteCompiled); TestSignatures sigs; - TestingModule module; - // Initialize WasmFunctionCompiler first, since it sets up the HandleScope. - WasmFunctionCompiler comp1(sigs.v_v(), &module); - - uint32_t js_throwing_index = module.AddJsFunction( + uint32_t js_throwing_index = r.module().AddJsFunction( sigs.v_v(), "(function js() {\n function a() {\n throw new Error(); };\n a(); })"); // Add a nop such that we don't always get position 1. - BUILD(comp1, WASM_NOP, WASM_CALL_FUNCTION0(js_throwing_index)); - uint32_t wasm_index = comp1.CompileAndAdd(); + BUILD(r, WASM_NOP, WASM_CALL_FUNCTION0(js_throwing_index)); + uint32_t wasm_index_1 = r.function()->func_index; - WasmFunctionCompiler comp2(sigs.v_v(), &module); - BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index)); - uint32_t wasm_index_2 = comp2.CompileAndAdd(); + WasmFunctionCompiler& f2 = r.NewFunction<void>("call_main"); + BUILD(f2, WASM_CALL_FUNCTION0(wasm_index_1)); + uint32_t wasm_index_2 = f2.function_index(); - Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2); + Handle<JSFunction> js_wasm_wrapper = r.module().WrapCode(wasm_index_2); Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( @@ -107,16 +104,17 @@ TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) { MaybeHandle<Object> maybe_exc; Handle<Object> args[] = {js_wasm_wrapper}; MaybeHandle<Object> returnObjMaybe = - Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); + Execution::TryCall(isolate, js_trampoline, global, 1, args, + Execution::MessageHandling::kReport, &maybe_exc); CHECK(returnObjMaybe.is_null()); // Line and column are 1-based, so add 1 for the expected wasm output. ExceptionInfo expected_exceptions[] = { - {"a", 3, 8}, // - - {"js", 4, 2}, // - - {"<WASM UNNAMED>", static_cast<int>(wasm_index) + 1, 3}, // - - {"<WASM UNNAMED>", static_cast<int>(wasm_index_2) + 1, 2}, // - - {"callFn", 1, 24} // - + {"a", 3, 8}, // - + {"js", 4, 2}, // - + {"main", static_cast<int>(wasm_index_1) + 1, 3}, // - + {"call_main", static_cast<int>(wasm_index_2) + 1, 2}, // - + {"callFn", 1, 24} // - }; CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions); } @@ -124,21 +122,18 @@ TEST(CollectDetailedWasmStack_ExplicitThrowFromJs) { // Trigger a trap in WASM, stack should be JS -> WASM -> WASM. TEST(CollectDetailedWasmStack_WasmError) { TestSignatures sigs; - TestingModule module; - - WasmFunctionCompiler comp1(sigs.i_v(), &module, - ArrayVector("exec_unreachable")); + WasmRunner<int> r(kExecuteCompiled); // Set the execution context, such that a runtime error can be thrown. - comp1.SetModuleContext(); - BUILD(comp1, WASM_UNREACHABLE); - uint32_t wasm_index = comp1.CompileAndAdd(); + r.SetModuleContext(); + + BUILD(r, WASM_UNREACHABLE); + uint32_t wasm_index_1 = r.function()->func_index; - WasmFunctionCompiler comp2(sigs.i_v(), &module, - ArrayVector("call_exec_unreachable")); - BUILD(comp2, WASM_CALL_FUNCTION0(wasm_index)); - uint32_t wasm_index_2 = comp2.CompileAndAdd(); + WasmFunctionCompiler& f2 = r.NewFunction<int>("call_main"); + BUILD(f2, WASM_CALL_FUNCTION0(0)); + uint32_t wasm_index_2 = f2.function_index(); - Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2); + Handle<JSFunction> js_wasm_wrapper = r.module().WrapCode(wasm_index_2); Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( @@ -151,14 +146,15 @@ TEST(CollectDetailedWasmStack_WasmError) { MaybeHandle<Object> maybe_exc; Handle<Object> args[] = {js_wasm_wrapper}; MaybeHandle<Object> maybe_return_obj = - Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); + Execution::TryCall(isolate, js_trampoline, global, 1, args, + Execution::MessageHandling::kReport, &maybe_exc); CHECK(maybe_return_obj.is_null()); // Line and column are 1-based, so add 1 for the expected wasm output. ExceptionInfo expected_exceptions[] = { - {"<WASM UNNAMED>", static_cast<int>(wasm_index) + 1, 2}, // - - {"<WASM UNNAMED>", static_cast<int>(wasm_index_2) + 1, 2}, // - - {"callFn", 1, 24} //- + {"main", static_cast<int>(wasm_index_1) + 1, 2}, // - + {"call_main", static_cast<int>(wasm_index_2) + 1, 2}, // - + {"callFn", 1, 24} //- }; CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions); } diff --git a/deps/v8/test/cctest/wasm/test-wasm-trap-position.cc b/deps/v8/test/cctest/wasm/test-wasm-trap-position.cc index bd4e82dc4c..0418d46bab 100644 --- a/deps/v8/test/cctest/wasm/test-wasm-trap-position.cc +++ b/deps/v8/test/cctest/wasm/test-wasm-trap-position.cc @@ -62,17 +62,15 @@ void CheckExceptionInfos(Handle<Object> exc, // Trigger a trap for executing unreachable. TEST(Unreachable) { + WasmRunner<void> r(kExecuteCompiled); TestSignatures sigs; - TestingModule module; - - WasmFunctionCompiler comp1(sigs.v_v(), &module, - ArrayVector("exec_unreachable")); // Set the execution context, such that a runtime error can be thrown. - comp1.SetModuleContext(); - BUILD(comp1, WASM_UNREACHABLE); - uint32_t wasm_index = comp1.CompileAndAdd(); + r.SetModuleContext(); + + BUILD(r, WASM_UNREACHABLE); + uint32_t wasm_index = r.function()->func_index; - Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index); + Handle<JSFunction> js_wasm_wrapper = r.module().WrapCode(wasm_index); Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( @@ -85,36 +83,37 @@ TEST(Unreachable) { MaybeHandle<Object> maybe_exc; Handle<Object> args[] = {js_wasm_wrapper}; MaybeHandle<Object> returnObjMaybe = - Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); + Execution::TryCall(isolate, js_trampoline, global, 1, args, + Execution::MessageHandling::kReport, &maybe_exc); CHECK(returnObjMaybe.is_null()); // Line and column are 1-based, so add 1 for the expected wasm output. ExceptionInfo expected_exceptions[] = { - {"<WASM UNNAMED>", static_cast<int>(wasm_index) + 1, 2}, // -- - {"callFn", 1, 24} // -- + {"main", static_cast<int>(wasm_index) + 1, 2}, // -- + {"callFn", 1, 24} // -- }; CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions); } // Trigger a trap for loading from out-of-bounds. TEST(IllegalLoad) { + WasmRunner<void> r(kExecuteCompiled); TestSignatures sigs; - TestingModule module; - - WasmFunctionCompiler comp1(sigs.v_v(), &module, ArrayVector("mem_oob")); // Set the execution context, such that a runtime error can be thrown. - comp1.SetModuleContext(); - BUILD(comp1, WASM_IF(WASM_ONE, WASM_SEQ(WASM_LOAD_MEM(MachineType::Int32(), - WASM_I32V_1(-3)), - WASM_DROP))); - uint32_t wasm_index = comp1.CompileAndAdd(); + r.SetModuleContext(); + r.module().AddMemory(0L); + + BUILD(r, WASM_IF(WASM_ONE, WASM_SEQ(WASM_LOAD_MEM(MachineType::Int32(), + WASM_I32V_1(-3)), + WASM_DROP))); + uint32_t wasm_index_1 = r.function()->func_index; - WasmFunctionCompiler comp2(sigs.v_v(), &module, ArrayVector("call_mem_oob")); + WasmFunctionCompiler& f2 = r.NewFunction<void>("call_main"); // Insert a NOP such that the position of the call is not one. - BUILD(comp2, WASM_NOP, WASM_CALL_FUNCTION0(wasm_index)); - uint32_t wasm_index_2 = comp2.CompileAndAdd(); + BUILD(f2, WASM_NOP, WASM_CALL_FUNCTION0(wasm_index_1)); + uint32_t wasm_index_2 = f2.function_index(); - Handle<JSFunction> js_wasm_wrapper = module.WrapCode(wasm_index_2); + Handle<JSFunction> js_wasm_wrapper = r.module().WrapCode(wasm_index_2); Handle<JSFunction> js_trampoline = Handle<JSFunction>::cast( v8::Utils::OpenHandle(*v8::Local<v8::Function>::Cast( @@ -127,14 +126,15 @@ TEST(IllegalLoad) { MaybeHandle<Object> maybe_exc; Handle<Object> args[] = {js_wasm_wrapper}; MaybeHandle<Object> returnObjMaybe = - Execution::TryCall(isolate, js_trampoline, global, 1, args, &maybe_exc); + Execution::TryCall(isolate, js_trampoline, global, 1, args, + Execution::MessageHandling::kReport, &maybe_exc); CHECK(returnObjMaybe.is_null()); // Line and column are 1-based, so add 1 for the expected wasm output. ExceptionInfo expected_exceptions[] = { - {"<WASM UNNAMED>", static_cast<int>(wasm_index) + 1, 8}, // -- - {"<WASM UNNAMED>", static_cast<int>(wasm_index_2) + 1, 3}, // -- - {"callFn", 1, 24} // -- + {"main", static_cast<int>(wasm_index_1) + 1, 8}, // -- + {"call_main", static_cast<int>(wasm_index_2) + 1, 3}, // -- + {"callFn", 1, 24} // -- }; CheckExceptionInfos(maybe_exc.ToHandleChecked(), expected_exceptions); } diff --git a/deps/v8/test/cctest/wasm/wasm-run-utils.h b/deps/v8/test/cctest/wasm/wasm-run-utils.h index 284b21c7c4..782e7d9635 100644 --- a/deps/v8/test/cctest/wasm/wasm-run-utils.h +++ b/deps/v8/test/cctest/wasm/wasm-run-utils.h @@ -5,9 +5,11 @@ #ifndef WASM_RUN_UTILS_H #define WASM_RUN_UTILS_H +#include <setjmp.h> #include <stdint.h> #include <stdlib.h> #include <string.h> +#include <array> #include <memory> #include "src/base/utils/random-number-generator.h" @@ -21,7 +23,8 @@ #include "src/compiler/pipeline.h" #include "src/compiler/wasm-compiler.h" #include "src/compiler/zone-stats.h" -#include "src/wasm/ast-decoder.h" +#include "src/wasm/function-body-decoder.h" +#include "src/wasm/wasm-external-refs.h" #include "src/wasm/wasm-interpreter.h" #include "src/wasm/wasm-js.h" #include "src/wasm/wasm-macro-gen.h" @@ -49,7 +52,6 @@ enum WasmExecutionMode { kExecuteInterpreted, kExecuteCompiled }; CHECK_EQ(0xdeadbeefdeadbeef, (bit_cast<uint64_t>(x)) & 0xFFFFFFFFFFFFFFFF) #define CHECK_TRAP(x) CHECK_TRAP32(x) -#define WASM_RUNNER_MAX_NUM_PARAMETERS 4 #define WASM_WRAPPER_RETURN_VALUE 8754 #define BUILD(r, ...) \ @@ -71,23 +73,26 @@ const uint32_t kMaxGlobalsSize = 128; // {WasmInstance}. class TestingModule : public ModuleEnv { public: - explicit TestingModule(WasmExecutionMode mode = kExecuteCompiled) - : execution_mode_(mode), + explicit TestingModule(Zone* zone, WasmExecutionMode mode = kExecuteCompiled) + : ModuleEnv(&module_, &instance_), + execution_mode_(mode), instance_(&module_), isolate_(CcTest::InitIsolateOnce()), global_offset(0), interpreter_(mode == kExecuteInterpreted - ? new WasmInterpreter(&instance_, &allocator_) + ? new WasmInterpreter( + ModuleBytesEnv(&module_, &instance_, + Vector<const byte>::empty()), + zone->allocator()) : nullptr) { - module = &module_; - instance = &instance_; + WasmJs::Install(isolate_); instance->module = &module_; instance->globals_start = global_data; module_.globals_size = kMaxGlobalsSize; instance->mem_start = nullptr; instance->mem_size = 0; - origin = kWasmOrigin; memset(global_data, 0, sizeof(global_data)); + instance_object_ = InitInstanceObject(); } ~TestingModule() { @@ -97,13 +102,15 @@ class TestingModule : public ModuleEnv { if (interpreter_) delete interpreter_; } - void ChangeOriginToAsmjs() { origin = kAsmJsOrigin; } + void ChangeOriginToAsmjs() { module_.origin = kAsmJsOrigin; } byte* AddMemory(uint32_t size) { + CHECK(!module_.has_memory); CHECK_NULL(instance->mem_start); - CHECK_EQ(0u, instance->mem_size); + CHECK_EQ(0, instance->mem_size); + module_.has_memory = true; instance->mem_start = reinterpret_cast<byte*>(malloc(size)); - CHECK(instance->mem_start); + CHECK(size == 0 || instance->mem_start); memset(instance->mem_start, 0, size); instance->mem_size = size; return raw_mem_start<byte>(); @@ -116,7 +123,8 @@ class TestingModule : public ModuleEnv { } template <typename T> - T* AddGlobal(LocalType type) { + T* AddGlobal( + ValueType type = WasmOpcodes::ValueTypeFor(MachineTypeForC<T>())) { const WasmGlobal* global = AddGlobal(type); return reinterpret_cast<T*>(instance->globals_start + global->offset); } @@ -176,7 +184,11 @@ class TestingModule : public ModuleEnv { rng.NextBytes(raw, end - raw); } - uint32_t AddFunction(FunctionSig* sig, Handle<Code> code) { + void SetMaxMemPages(uint32_t max_mem_pages) { + module_.max_mem_pages = max_mem_pages; + } + + uint32_t AddFunction(FunctionSig* sig, Handle<Code> code, const char* name) { if (module->functions.size() == 0) { // TODO(titzer): Reserving space here to avoid the underlying WasmFunction // structs from moving. @@ -184,6 +196,11 @@ class TestingModule : public ModuleEnv { } uint32_t index = static_cast<uint32_t>(module->functions.size()); module_.functions.push_back({sig, index, 0, 0, 0, 0, 0, false, false}); + if (name) { + Vector<const byte> name_vec = Vector<const byte>::cast(CStrVector(name)); + module_.functions.back().name_offset = AddBytes(name_vec); + module_.functions.back().name_length = name_vec.length(); + } instance->function_code.push_back(code); if (interpreter_) { const WasmFunction* function = &module->functions.back(); @@ -197,26 +214,24 @@ class TestingModule : public ModuleEnv { uint32_t AddJsFunction(FunctionSig* sig, const char* source) { Handle<JSFunction> jsfunc = Handle<JSFunction>::cast(v8::Utils::OpenHandle( *v8::Local<v8::Function>::Cast(CompileRun(source)))); - uint32_t index = AddFunction(sig, Handle<Code>::null()); - Handle<Code> code = - CompileWasmToJSWrapper(isolate_, jsfunc, sig, index, - Handle<String>::null(), Handle<String>::null()); + uint32_t index = AddFunction(sig, Handle<Code>::null(), nullptr); + Handle<Code> code = CompileWasmToJSWrapper( + isolate_, jsfunc, sig, index, Handle<String>::null(), + Handle<String>::null(), module->origin); instance->function_code[index] = code; return index; } Handle<JSFunction> WrapCode(uint32_t index) { // Wrap the code so it can be called as a JS function. - Handle<String> name = isolate_->factory()->NewStringFromStaticChars("main"); Handle<WasmInstanceObject> instance_obj(0, isolate_); Handle<Code> code = instance->function_code[index]; - WasmJs::InstallWasmMapsIfNeeded(isolate_, isolate_->native_context()); Handle<Code> ret_code = - compiler::CompileJSToWasmWrapper(isolate_, this, code, index); + compiler::CompileJSToWasmWrapper(isolate_, &module_, code, index); Handle<JSFunction> ret = WasmExportedFunction::New( - isolate_, instance_obj, name, ret_code, + isolate_, instance_obj, MaybeHandle<String>(), static_cast<int>(index), static_cast<int>(this->module->functions[index].sig->parameter_count()), - static_cast<int>(index)); + ret_code); return ret; } @@ -238,40 +253,59 @@ class TestingModule : public ModuleEnv { } instance->function_tables.push_back( - isolate_->factory()->NewFixedArray(table_size * 2)); + isolate_->factory()->NewFixedArray(table_size)); + instance->signature_tables.push_back( + isolate_->factory()->NewFixedArray(table_size)); } void PopulateIndirectFunctionTable() { + if (execution_mode_ == kExecuteInterpreted) return; // Initialize the fixed arrays in instance->function_tables. for (uint32_t i = 0; i < instance->function_tables.size(); i++) { WasmIndirectFunctionTable& table = module_.function_tables[i]; - Handle<FixedArray> array = instance->function_tables[i]; + Handle<FixedArray> function_table = instance->function_tables[i]; + Handle<FixedArray> signature_table = instance->signature_tables[i]; int table_size = static_cast<int>(table.values.size()); for (int j = 0; j < table_size; j++) { WasmFunction& function = module_.functions[table.values[j]]; - array->set(j, Smi::FromInt(table.map.Find(function.sig))); - array->set(j + table_size, - *instance->function_code[function.func_index]); + signature_table->set(j, Smi::FromInt(table.map.Find(function.sig))); + function_table->set(j, *instance->function_code[function.func_index]); } } } + uint32_t AddBytes(Vector<const byte> bytes) { + Handle<SeqOneByteString> old_bytes( + instance_object_->compiled_module()->module_bytes(), isolate_); + uint32_t old_size = static_cast<uint32_t>(old_bytes->length()); + ScopedVector<byte> new_bytes(old_size + bytes.length()); + memcpy(new_bytes.start(), old_bytes->GetChars(), old_size); + memcpy(new_bytes.start() + old_size, bytes.start(), bytes.length()); + Handle<SeqOneByteString> new_bytes_str = Handle<SeqOneByteString>::cast( + isolate_->factory()->NewStringFromOneByte(new_bytes).ToHandleChecked()); + instance_object_->compiled_module()->shared()->set_module_bytes( + *new_bytes_str); + return old_size; + } + WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; } WasmInterpreter* interpreter() { return interpreter_; } WasmExecutionMode execution_mode() { return execution_mode_; } + Isolate* isolate() { return isolate_; } + Handle<WasmInstanceObject> instance_object() { return instance_object_; } private: WasmExecutionMode execution_mode_; WasmModule module_; WasmInstance instance_; Isolate* isolate_; - v8::internal::AccountingAllocator allocator_; uint32_t global_offset; V8_ALIGNED(8) byte global_data[kMaxGlobalsSize]; // preallocated global data. WasmInterpreter* interpreter_; + Handle<WasmInstanceObject> instance_object_; - const WasmGlobal* AddGlobal(LocalType type) { + const WasmGlobal* AddGlobal(ValueType type) { byte size = WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(type)); global_offset = (global_offset + size - 1) & ~(size - 1); // align module_.globals.push_back( @@ -281,21 +315,43 @@ class TestingModule : public ModuleEnv { CHECK_LT(global_offset, kMaxGlobalsSize); return &module->globals.back(); } + + Handle<WasmInstanceObject> InitInstanceObject() { + Handle<SeqOneByteString> empty_string = Handle<SeqOneByteString>::cast( + isolate_->factory()->NewStringFromOneByte({}).ToHandleChecked()); + Handle<Managed<wasm::WasmModule>> module_wrapper = + Managed<wasm::WasmModule>::New(isolate_, &module_, false); + Handle<Script> script = + isolate_->factory()->NewScript(isolate_->factory()->empty_string()); + script->set_type(Script::TYPE_WASM); + Handle<WasmSharedModuleData> shared_module_data = + WasmSharedModuleData::New(isolate_, module_wrapper, empty_string, + script, Handle<ByteArray>::null()); + Handle<WasmCompiledModule> compiled_module = + WasmCompiledModule::New(isolate_, shared_module_data); + // Minimally initialize the compiled module such that IsWasmCompiledModule + // passes. + // If tests need more (correct) information, add it later. + compiled_module->set_min_mem_pages(0); + compiled_module->set_max_mem_pages(Smi::kMaxValue); + DCHECK(WasmCompiledModule::IsWasmCompiledModule(*compiled_module)); + return WasmInstanceObject::New(isolate_, compiled_module); + } }; inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module, FunctionSig* sig, SourcePositionTable* source_position_table, const byte* start, const byte* end) { - compiler::WasmGraphBuilder builder(zone, jsgraph, sig, source_position_table); + compiler::WasmGraphBuilder builder(module, zone, jsgraph, sig, + source_position_table); DecodeResult result = - BuildTFGraph(zone->allocator(), &builder, module, sig, start, end); + BuildTFGraph(zone->allocator(), &builder, sig, start, end); if (result.failed()) { if (!FLAG_trace_wasm_decoder) { // Retry the compilation with the tracing flag on, to help in debugging. FLAG_trace_wasm_decoder = true; - result = - BuildTFGraph(zone->allocator(), &builder, module, sig, start, end); + result = BuildTFGraph(zone->allocator(), &builder, sig, start, end); } ptrdiff_t pc = result.error_pc - result.start; @@ -307,39 +363,34 @@ inline void TestBuildingGraph(Zone* zone, JSGraph* jsgraph, ModuleEnv* module, FATAL(str.str().c_str()); } builder.Int64LoweringForTesting(); - builder.SimdScalarLoweringForTesting(); + if (!CpuFeatures::SupportsSimd128()) { + builder.SimdScalarLoweringForTesting(); + } } -template <typename ReturnType> -class WasmFunctionWrapper : public HandleAndZoneScope, - private GraphAndBuilders { +class WasmFunctionWrapper : private GraphAndBuilders { public: - WasmFunctionWrapper() - : GraphAndBuilders(main_zone()), - inner_code_node_(nullptr), - signature_(nullptr) { + explicit WasmFunctionWrapper(Zone* zone, int num_params) + : GraphAndBuilders(zone), inner_code_node_(nullptr), signature_(nullptr) { // One additional parameter for the pointer to the return value memory. - Signature<MachineType>::Builder sig_builder( - zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1); + Signature<MachineType>::Builder sig_builder(zone, 1, num_params + 1); sig_builder.AddReturn(MachineType::Int32()); - for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) { + for (int i = 0; i < num_params + 1; i++) { sig_builder.AddParam(MachineType::Pointer()); } signature_ = sig_builder.Build(); } - void Init(CallDescriptor* descriptor, MachineType p0 = MachineType::None(), - MachineType p1 = MachineType::None(), - MachineType p2 = MachineType::None(), - MachineType p3 = MachineType::None()) { - // Create the TF graph for the wrapper. The wrapper always takes four - // pointers as parameters, but may not pass the values of all pointers to - // the actual test function. + void Init(CallDescriptor* descriptor, MachineType return_type, + Vector<MachineType> param_types) { + DCHECK_NOT_NULL(descriptor); + DCHECK_EQ(signature_->parameter_count(), param_types.length() + 1); + + // Create the TF graph for the wrapper. // Function, effect, and control. - Node** parameters = - zone()->template NewArray<Node*>(WASM_RUNNER_MAX_NUM_PARAMETERS + 3); + Node** parameters = zone()->NewArray<Node*>(param_types.length() + 3); graph()->SetStart(graph()->NewNode(common()->Start(6))); Node* effect = graph()->start(); int parameter_count = 0; @@ -348,34 +399,12 @@ class WasmFunctionWrapper : public HandleAndZoneScope, inner_code_node_ = graph()->NewNode(common()->Int32Constant(0)); parameters[parameter_count++] = inner_code_node_; - if (p0 != MachineType::None()) { - parameters[parameter_count] = graph()->NewNode( - machine()->Load(p0), - graph()->NewNode(common()->Parameter(0), graph()->start()), - graph()->NewNode(common()->Int32Constant(0)), effect, - graph()->start()); - effect = parameters[parameter_count++]; - } - if (p1 != MachineType::None()) { - parameters[parameter_count] = graph()->NewNode( - machine()->Load(p1), - graph()->NewNode(common()->Parameter(1), graph()->start()), - graph()->NewNode(common()->Int32Constant(0)), effect, - graph()->start()); - effect = parameters[parameter_count++]; - } - if (p2 != MachineType::None()) { - parameters[parameter_count] = graph()->NewNode( - machine()->Load(p2), - graph()->NewNode(common()->Parameter(2), graph()->start()), - graph()->NewNode(common()->Int32Constant(0)), effect, - graph()->start()); - effect = parameters[parameter_count++]; - } - if (p3 != MachineType::None()) { + int param_idx = 0; + for (MachineType t : param_types) { + DCHECK_NE(MachineType::None(), t); parameters[parameter_count] = graph()->NewNode( - machine()->Load(p3), - graph()->NewNode(common()->Parameter(3), graph()->start()), + machine()->Load(t), + graph()->NewNode(common()->Parameter(param_idx++), graph()->start()), graph()->NewNode(common()->Int32Constant(0)), effect, graph()->start()); effect = parameters[parameter_count++]; @@ -386,14 +415,15 @@ class WasmFunctionWrapper : public HandleAndZoneScope, Node* call = graph()->NewNode(common()->Call(descriptor), parameter_count, parameters); - effect = graph()->NewNode( - machine()->Store( - StoreRepresentation(MachineTypeForC<ReturnType>().representation(), - WriteBarrierKind::kNoWriteBarrier)), - graph()->NewNode(common()->Parameter(WASM_RUNNER_MAX_NUM_PARAMETERS), - graph()->start()), - graph()->NewNode(common()->Int32Constant(0)), call, effect, - graph()->start()); + if (!return_type.IsNone()) { + effect = graph()->NewNode( + machine()->Store(StoreRepresentation( + return_type.representation(), WriteBarrierKind::kNoWriteBarrier)), + graph()->NewNode(common()->Parameter(param_types.length()), + graph()->start()), + graph()->NewNode(common()->Int32Constant(0)), call, effect, + graph()->start()); + } Node* zero = graph()->NewNode(common()->Int32Constant(0)); Node* r = graph()->NewNode( common()->Return(), zero, @@ -402,6 +432,15 @@ class WasmFunctionWrapper : public HandleAndZoneScope, graph()->SetEnd(graph()->NewNode(common()->End(2), r, graph()->start())); } + template <typename ReturnType, typename... ParamTypes> + void Init(CallDescriptor* descriptor) { + std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{ + {MachineTypeForC<ParamTypes>()...}}; + Vector<MachineType> param_vec(param_machine_types.data(), + param_machine_types.size()); + Init(descriptor, MachineTypeForC<ReturnType>(), param_vec); + } + void SetInnerCode(Handle<Code> code_handle) { NodeProperties::ChangeOp(inner_code_node_, common()->HeapConstant(code_handle)); @@ -415,12 +454,13 @@ class WasmFunctionWrapper : public HandleAndZoneScope, Linkage::GetSimplifiedCDescriptor(zone(), signature_, true); if (kPointerSize == 4) { + size_t num_params = signature_->parameter_count(); // One additional parameter for the pointer of the return value. - Signature<MachineRepresentation>::Builder rep_builder( - zone(), 1, WASM_RUNNER_MAX_NUM_PARAMETERS + 1); + Signature<MachineRepresentation>::Builder rep_builder(zone(), 1, + num_params + 1); rep_builder.AddReturn(MachineRepresentation::kWord32); - for (int i = 0; i < WASM_RUNNER_MAX_NUM_PARAMETERS + 1; i++) { + for (size_t i = 0; i < num_params + 1; i++) { rep_builder.AddParam(MachineRepresentation::kWord32); } Int64Lowering r(graph(), machine(), common(), zone(), @@ -452,129 +492,108 @@ class WasmFunctionWrapper : public HandleAndZoneScope, Signature<MachineType>* signature_; }; -// A helper for compiling WASM functions for testing. This class can create a -// standalone function if {module} is NULL or a function within a -// {TestingModule}. It contains the internal state for compilation (i.e. -// TurboFan graph) and interpretation (by adding to the interpreter manually). -class WasmFunctionCompiler : public HandleAndZoneScope, - private GraphAndBuilders { +// A helper for compiling WASM functions for testing. +// It contains the internal state for compilation (i.e. TurboFan graph) and +// interpretation (by adding to the interpreter manually). +class WasmFunctionCompiler : private GraphAndBuilders { public: - explicit WasmFunctionCompiler( - FunctionSig* sig, WasmExecutionMode mode, - Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>")) - : GraphAndBuilders(main_zone()), - execution_mode_(mode), - jsgraph(this->isolate(), this->graph(), this->common(), nullptr, - nullptr, this->machine()), - sig(sig), - descriptor_(nullptr), - testing_module_(nullptr), - debug_name_(debug_name), - local_decls(main_zone(), sig), - source_position_table_(this->graph()), - interpreter_(nullptr) { - // Create our own function. - function_ = new WasmFunction(); - function_->sig = sig; - function_->func_index = 0; - function_->sig_index = 0; - if (mode == kExecuteInterpreted) { - interpreter_ = new WasmInterpreter(nullptr, zone()->allocator()); - int index = interpreter_->AddFunctionForTesting(function_); - CHECK_EQ(0, index); - } - } - - explicit WasmFunctionCompiler( - FunctionSig* sig, TestingModule* module, - Vector<const char> debug_name = ArrayVector("<WASM UNNAMED>")) - : GraphAndBuilders(main_zone()), - execution_mode_(module->execution_mode()), - jsgraph(this->isolate(), this->graph(), this->common(), nullptr, - nullptr, this->machine()), - sig(sig), - descriptor_(nullptr), - testing_module_(module), - debug_name_(debug_name), - local_decls(main_zone(), sig), - source_position_table_(this->graph()), - interpreter_(module->interpreter()) { - // Get a new function from the testing module. - int index = module->AddFunction(sig, Handle<Code>::null()); - function_ = testing_module_->GetFunctionAt(index); - } - - ~WasmFunctionCompiler() { - if (testing_module_) return; // testing module owns the below things. - delete function_; - if (interpreter_) delete interpreter_; - } - - WasmExecutionMode execution_mode_; - JSGraph jsgraph; - FunctionSig* sig; - // The call descriptor is initialized when the function is compiled. - CallDescriptor* descriptor_; - TestingModule* testing_module_; - Vector<const char> debug_name_; - WasmFunction* function_; - LocalDeclEncoder local_decls; - SourcePositionTable source_position_table_; - WasmInterpreter* interpreter_; - - Isolate* isolate() { return main_isolate(); } + Isolate* isolate() { return testing_module_->isolate(); } Graph* graph() const { return main_graph_; } Zone* zone() const { return graph()->zone(); } CommonOperatorBuilder* common() { return &main_common_; } MachineOperatorBuilder* machine() { return &main_machine_; } - void InitializeDescriptor() { + CallDescriptor* descriptor() { if (descriptor_ == nullptr) { - descriptor_ = testing_module_->GetWasmCallDescriptor(main_zone(), sig); + descriptor_ = testing_module_->GetWasmCallDescriptor(zone(), sig); } + return descriptor_; } - CallDescriptor* descriptor() { return descriptor_; } uint32_t function_index() { return function_->func_index; } void Build(const byte* start, const byte* end) { - // Build the TurboFan graph. - local_decls.Prepend(main_zone(), &start, &end); - TestBuildingGraph(main_zone(), &jsgraph, testing_module_, sig, - &source_position_table_, start, end); + size_t locals_size = local_decls.Size(); + size_t total_size = end - start + locals_size + 1; + byte* buffer = static_cast<byte*>(zone()->New(total_size)); + // Prepend the local decls to the code. + local_decls.Emit(buffer); + // Emit the code. + memcpy(buffer + locals_size, start, end - start); + // Append an extra end opcode. + buffer[total_size - 1] = kExprEnd; + + start = buffer; + end = buffer + total_size; + + CHECK_GE(kMaxInt, end - start); + int len = static_cast<int>(end - start); + function_->code_start_offset = + testing_module_->AddBytes(Vector<const byte>(start, len)); + function_->code_end_offset = function_->code_start_offset + len; + if (interpreter_) { // Add the code to the interpreter. CHECK(interpreter_->SetFunctionCodeForTesting(function_, start, end)); + return; } + + // Build the TurboFan graph. + TestBuildingGraph(zone(), &jsgraph, testing_module_, sig, + &source_position_table_, start, end); + Handle<Code> code = Compile(); + testing_module_->SetFunctionCode(function_index(), code); } - byte AllocateLocal(LocalType type) { + byte AllocateLocal(ValueType type) { uint32_t index = local_decls.AddLocals(1, type); byte result = static_cast<byte>(index); DCHECK_EQ(index, result); return result; } + void SetSigIndex(int sig_index) { function_->sig_index = sig_index; } + + private: + friend class WasmRunnerBase; + + explicit WasmFunctionCompiler(Zone* zone, FunctionSig* sig, + TestingModule* module, const char* name) + : GraphAndBuilders(zone), + jsgraph(module->isolate(), this->graph(), this->common(), nullptr, + nullptr, this->machine()), + sig(sig), + descriptor_(nullptr), + testing_module_(module), + local_decls(zone, sig), + source_position_table_(this->graph()), + interpreter_(module->interpreter()) { + // Get a new function from the testing module. + int index = module->AddFunction(sig, Handle<Code>::null(), name); + function_ = testing_module_->GetFunctionAt(index); + } + Handle<Code> Compile() { - InitializeDescriptor(); - CallDescriptor* desc = descriptor_; + CallDescriptor* desc = descriptor(); if (kPointerSize == 4) { desc = testing_module_->GetI32WasmCallDescriptor(this->zone(), desc); } - CompilationInfo info(debug_name_, this->isolate(), this->zone(), + CompilationInfo info(CStrVector("wasm"), this->isolate(), this->zone(), Code::ComputeFlags(Code::WASM_FUNCTION)); std::unique_ptr<CompilationJob> job(Pipeline::NewWasmCompilationJob( - &info, graph(), desc, &source_position_table_)); + &info, &jsgraph, desc, &source_position_table_, nullptr, false)); if (job->ExecuteJob() != CompilationJob::SUCCEEDED || job->FinalizeJob() != CompilationJob::SUCCEEDED) return Handle<Code>::null(); Handle<Code> code = info.code(); - // Length is always 2, since usually <wasm_obj, func_index> is stored in - // the deopt data. Here, we only store the function index. + // Deopt data holds <WeakCell<wasm_instance>, func_index>. DCHECK(code->deoptimization_data() == nullptr || code->deoptimization_data()->length() == 0); Handle<FixedArray> deopt_data = isolate()->factory()->NewFixedArray(2, TENURED); + Handle<Object> weak_instance = + isolate()->factory()->NewWeakCell(testing_module_->instance_object()); + deopt_data->set(0, *weak_instance); deopt_data->set(1, Smi::FromInt(static_cast<int>(function_index()))); deopt_data->set_length(2); code->set_deoptimization_data(*deopt_data); @@ -589,76 +608,26 @@ class WasmFunctionCompiler : public HandleAndZoneScope, return code; } - uint32_t CompileAndAdd(uint16_t sig_index = 0) { - CHECK(testing_module_); - function_->sig_index = sig_index; - Handle<Code> code = Compile(); - testing_module_->SetFunctionCode(function_index(), code); - return function_index(); - } - - // Set the context, such that e.g. runtime functions can be called. - void SetModuleContext() { - if (!testing_module_->instance->context.is_null()) { - CHECK(testing_module_->instance->context.is_identical_to( - main_isolate()->native_context())); - return; - } - testing_module_->instance->context = main_isolate()->native_context(); - } + JSGraph jsgraph; + FunctionSig* sig; + // The call descriptor is initialized when the function is compiled. + CallDescriptor* descriptor_; + TestingModule* testing_module_; + Vector<const char> debug_name_; + WasmFunction* function_; + LocalDeclEncoder local_decls; + SourcePositionTable source_position_table_; + WasmInterpreter* interpreter_; }; -// A helper class to build graphs from Wasm bytecode, generate machine +// A helper class to build a module around Wasm bytecode, generate machine // code, and run that code. -template <typename ReturnType> -class WasmRunner { +class WasmRunnerBase : public HandleAndZoneScope { public: - WasmRunner(WasmExecutionMode execution_mode, - MachineType p0 = MachineType::None(), - MachineType p1 = MachineType::None(), - MachineType p2 = MachineType::None(), - MachineType p3 = MachineType::None()) - : zone(&allocator_, ZONE_NAME), - compiled_(false), - signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1, - GetParameterCount(p0, p1, p2, p3), storage_), - compiler_(&signature_, execution_mode) { - InitSigStorage(p0, p1, p2, p3); - } - - WasmRunner(TestingModule* module, MachineType p0 = MachineType::None(), - MachineType p1 = MachineType::None(), - MachineType p2 = MachineType::None(), - MachineType p3 = MachineType::None()) - : zone(&allocator_, ZONE_NAME), - compiled_(false), - signature_(MachineTypeForC<ReturnType>() == MachineType::None() ? 0 : 1, - GetParameterCount(p0, p1, p2, p3), storage_), - compiler_(&signature_, module), - possible_nondeterminism_(false) { - DCHECK(module); - InitSigStorage(p0, p1, p2, p3); - } - - void InitSigStorage(MachineType p0, MachineType p1, MachineType p2, - MachineType p3) { - int index = 0; - MachineType ret = MachineTypeForC<ReturnType>(); - if (ret != MachineType::None()) { - storage_[index++] = WasmOpcodes::LocalTypeFor(ret); - } - if (p0 != MachineType::None()) - storage_[index++] = WasmOpcodes::LocalTypeFor(p0); - if (p1 != MachineType::None()) - storage_[index++] = WasmOpcodes::LocalTypeFor(p1); - if (p2 != MachineType::None()) - storage_[index++] = WasmOpcodes::LocalTypeFor(p2); - if (p3 != MachineType::None()) - storage_[index++] = WasmOpcodes::LocalTypeFor(p3); - - compiler_.InitializeDescriptor(); - wrapper_.Init(compiler_.descriptor(), p0, p1, p2, p3); - } + explicit WasmRunnerBase(WasmExecutionMode execution_mode, int num_params) + : zone_(&allocator_, ZONE_NAME), + module_(&zone_, execution_mode), + wrapper_(&zone_, num_params) {} // Builds a graph from the given Wasm code and generates the machine // code and call wrapper for that graph. This method must not be called @@ -666,83 +635,125 @@ class WasmRunner { void Build(const byte* start, const byte* end) { CHECK(!compiled_); compiled_ = true; - compiler_.Build(start, end); + functions_[0]->Build(start, end); + } - if (!interpret()) { - // Compile machine code and install it into the module. - Handle<Code> code = compiler_.Compile(); + // Resets the state for building the next function. + // The main function called will always be the first function. + template <typename ReturnType, typename... ParamTypes> + WasmFunctionCompiler& NewFunction(const char* name = nullptr) { + return NewFunction(CreateSig<ReturnType, ParamTypes...>(), name); + } - if (compiler_.testing_module_) { - // Update the table of function code in the module. - compiler_.testing_module_->SetFunctionCode( - compiler_.function_->func_index, code); - } + // Resets the state for building the next function. + // The main function called will be the last generated function. + // Returns the index of the previously built function. + WasmFunctionCompiler& NewFunction(FunctionSig* sig, + const char* name = nullptr) { + functions_.emplace_back( + new WasmFunctionCompiler(&zone_, sig, &module_, name)); + return *functions_.back(); + } - wrapper_.SetInnerCode(code); - } + byte AllocateLocal(ValueType type) { + return functions_[0]->AllocateLocal(type); } - ReturnType Call() { - if (interpret()) { - return CallInterpreter(Vector<WasmVal>(nullptr, 0)); - } else { - return Call(0, 0, 0, 0); + WasmFunction* function() { return functions_[0]->function_; } + WasmInterpreter* interpreter() { return functions_[0]->interpreter_; } + bool possible_nondeterminism() { return possible_nondeterminism_; } + TestingModule& module() { return module_; } + Zone* zone() { return &zone_; } + + // Set the context, such that e.g. runtime functions can be called. + void SetModuleContext() { + if (!module_.instance->context.is_null()) { + CHECK(module_.instance->context.is_identical_to( + main_isolate()->native_context())); + return; } + module_.instance->context = main_isolate()->native_context(); } - template <typename P0> - ReturnType Call(P0 p0) { - if (interpret()) { - WasmVal args[] = {WasmVal(p0)}; - return CallInterpreter(ArrayVector(args)); - } else { - return Call(p0, 0, 0, 0); + private: + FunctionSig* CreateSig(MachineType return_type, + Vector<MachineType> param_types) { + int return_count = return_type.IsNone() ? 0 : 1; + int param_count = param_types.length(); + + // Allocate storage array in zone. + ValueType* sig_types = + zone_.NewArray<ValueType>(return_count + param_count); + + // Convert machine types to local types, and check that there are no + // MachineType::None()'s in the parameters. + int idx = 0; + if (return_count) sig_types[idx++] = WasmOpcodes::ValueTypeFor(return_type); + for (MachineType param : param_types) { + CHECK_NE(MachineType::None(), param); + sig_types[idx++] = WasmOpcodes::ValueTypeFor(param); } + return new (&zone_) FunctionSig(return_count, param_count, sig_types); } - template <typename P0, typename P1> - ReturnType Call(P0 p0, P1 p1) { - if (interpret()) { - WasmVal args[] = {WasmVal(p0), WasmVal(p1)}; - return CallInterpreter(ArrayVector(args)); - } else { - return Call(p0, p1, 0, 0); - } + template <typename ReturnType, typename... ParamTypes> + FunctionSig* CreateSig() { + std::array<MachineType, sizeof...(ParamTypes)> param_machine_types{ + {MachineTypeForC<ParamTypes>()...}}; + Vector<MachineType> param_vec(param_machine_types.data(), + param_machine_types.size()); + return CreateSig(MachineTypeForC<ReturnType>(), param_vec); } - template <typename P0, typename P1, typename P2> - ReturnType Call(P0 p0, P1 p1, P2 p2) { - if (interpret()) { - WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2)}; - return CallInterpreter(ArrayVector(args)); - } else { - return Call(p0, p1, p2, 0); + protected: + v8::internal::AccountingAllocator allocator_; + Zone zone_; + TestingModule module_; + std::vector<std::unique_ptr<WasmFunctionCompiler>> functions_; + WasmFunctionWrapper wrapper_; + bool compiled_ = false; + bool possible_nondeterminism_ = false; + + bool interpret() { return module_.execution_mode() == kExecuteInterpreted; } + + public: + // This field has to be static. Otherwise, gcc complains about the using in + // the lambda context below. + static jmp_buf jump_buffer; +}; + +template <typename ReturnType, typename... ParamTypes> +class WasmRunner : public WasmRunnerBase { + public: + explicit WasmRunner(WasmExecutionMode execution_mode, + const char* main_fn_name = "main") + : WasmRunnerBase(execution_mode, sizeof...(ParamTypes)) { + NewFunction<ReturnType, ParamTypes...>(main_fn_name); + if (!interpret()) { + wrapper_.Init<ReturnType, ParamTypes...>(functions_[0]->descriptor()); } } - template <typename P0, typename P1, typename P2, typename P3> - ReturnType Call(P0 p0, P1 p1, P2 p2, P3 p3) { - if (interpret()) { - WasmVal args[] = {WasmVal(p0), WasmVal(p1), WasmVal(p2), WasmVal(p3)}; - return CallInterpreter(ArrayVector(args)); - } else { - CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), - wrapper_.GetWrapperCode(), - wrapper_.signature()); - ReturnType return_value; - int32_t result = runner.Call<void*, void*, void*, void*, void*>( - &p0, &p1, &p2, &p3, &return_value); - CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); - return return_value; + ReturnType Call(ParamTypes... p) { + DCHECK(compiled_); + if (interpret()) return CallInterpreter(p...); + + // Use setjmp/longjmp to deal with traps in WebAssembly code. + ReturnType return_value = static_cast<ReturnType>(0xdeadbeefdeadbeef); + static int setjmp_ret; + setjmp_ret = setjmp(WasmRunnerBase::jump_buffer); + // setjmp returns 0 on the first return, 1 (passed to longjmp) after trap. + if (setjmp_ret == 0) { + DoCall(static_cast<void*>(&p)..., static_cast<void*>(&return_value)); } + return return_value; } - ReturnType CallInterpreter(Vector<WasmVal> args) { - CHECK_EQ(args.length(), - static_cast<int>(compiler_.function_->sig->parameter_count())); + ReturnType CallInterpreter(ParamTypes... p) { WasmInterpreter::Thread* thread = interpreter()->GetThread(0); thread->Reset(); - thread->PushFrame(compiler_.function_, args.start()); + std::array<WasmVal, sizeof...(p)> args{{WasmVal(p)...}}; + thread->PushFrame(function(), args.data()); if (thread->Run() == WasmInterpreter::FINISHED) { WasmVal val = thread->GetReturnValue(); possible_nondeterminism_ |= thread->PossibleNondeterminism(); @@ -753,49 +764,59 @@ class WasmRunner { return static_cast<ReturnType>(result); } else { // TODO(titzer): falling off end - ReturnType val = 0; - return val; + return ReturnType{0}; } } - byte AllocateLocal(LocalType type) { return compiler_.AllocateLocal(type); } - - WasmFunction* function() { return compiler_.function_; } - WasmInterpreter* interpreter() { return compiler_.interpreter_; } - bool possible_nondeterminism() { return possible_nondeterminism_; } - - protected: - v8::internal::AccountingAllocator allocator_; - Zone zone; - bool compiled_; - LocalType storage_[WASM_RUNNER_MAX_NUM_PARAMETERS]; - FunctionSig signature_; - WasmFunctionCompiler compiler_; - WasmFunctionWrapper<ReturnType> wrapper_; - bool possible_nondeterminism_; - - bool interpret() { return compiler_.execution_mode_ == kExecuteInterpreted; } - - static size_t GetParameterCount(MachineType p0, MachineType p1, - MachineType p2, MachineType p3) { - if (p0 == MachineType::None()) return 0; - if (p1 == MachineType::None()) return 1; - if (p2 == MachineType::None()) return 2; - if (p3 == MachineType::None()) return 3; - return 4; + private: + // Don't inline this function. The setjmp above should be followed immediately + // by a call. + template <typename... Ptrs> + V8_NOINLINE void DoCall(Ptrs... ptrs) { + auto trap_callback = []() -> void { + set_trap_callback_for_testing(nullptr); + longjmp(WasmRunnerBase::jump_buffer, 1); + }; + set_trap_callback_for_testing(trap_callback); + + wrapper_.SetInnerCode( + module_.GetFunctionCode(functions_[0]->function_index())); + CodeRunner<int32_t> runner(CcTest::InitIsolateOnce(), + wrapper_.GetWrapperCode(), wrapper_.signature()); + int32_t result = runner.Call(ptrs...); + // If we arrive here, no trap happened. + CHECK_EQ(WASM_WRAPPER_RETURN_VALUE, result); } }; +// Declare static variable. +jmp_buf WasmRunnerBase::jump_buffer; + // A macro to define tests that run in different engine configurations. -// Currently only supports compiled tests, but a future -// RunWasmInterpreted_##name version will allow each test to also run in the -// interpreter. #define WASM_EXEC_TEST(name) \ void RunWasm_##name(WasmExecutionMode execution_mode); \ TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \ TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \ void RunWasm_##name(WasmExecutionMode execution_mode) +#define WASM_EXEC_TEST_WITH_TRAP(name) \ + void RunWasm_##name(WasmExecutionMode execution_mode); \ + TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \ + void RunWasm_##name(WasmExecutionMode execution_mode); \ + TEST(RunWasmCompiledWithTrapIf_##name) { \ + bool trap_if = FLAG_wasm_trap_if; \ + FLAG_wasm_trap_if = true; \ + RunWasm_##name(kExecuteCompiled); \ + FLAG_wasm_trap_if = trap_if; \ + } \ + TEST(RunWasmInterpreted_##name) { RunWasm_##name(kExecuteInterpreted); } \ + void RunWasm_##name(WasmExecutionMode execution_mode) + +#define WASM_EXEC_COMPILED_TEST(name) \ + void RunWasm_##name(WasmExecutionMode execution_mode); \ + TEST(RunWasmCompiled_##name) { RunWasm_##name(kExecuteCompiled); } \ + void RunWasm_##name(WasmExecutionMode execution_mode) + } // namespace #endif |