// Copyright 2019 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // The C++ style guide recommends using instead of . However, the // former isn't available in V8. #include // NOLINT(build/c++11) #include #include "src/codegen/arm64/register-arm64.h" #include "test/cctest/cctest.h" #include "test/cctest/disasm-regex-helper.h" namespace v8 { namespace internal { namespace { // Poison register. const int kPRegCode = kSpeculationPoisonRegister.code(); const std::string kPReg = // NOLINT(runtime/string) "x" + std::to_string(kPRegCode); } // namespace TEST(DisasmPoisonMonomorphicLoad) { #ifdef ENABLE_DISASSEMBLER if (i::FLAG_always_opt || !i::FLAG_opt) return; // TODO(9684): Re-enable for TurboProp if necessary. if (i::FLAG_turboprop) return; i::FLAG_allow_natives_syntax = true; i::FLAG_untrusted_code_mitigations = true; i::FLAG_debug_code = false; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); CompileRun( "function mono(o) { return o.x; };" "%PrepareFunctionForOptimization(mono);" "mono({ x : 1 });" "mono({ x : 1 });" "%OptimizeFunctionOnNextCall(mono);" "mono({ x : 1 });"); // Matches that the property access sequence is instrumented with // poisoning. #if defined(V8_COMPRESS_POINTERS) std::vector patterns_array = { "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load expected map "cmp <>, <>", // compare maps "b.ne", // deopt if different "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur w<>, \\[<>, #[0-9]+\\]", // load the field "and x<>, x<>, " + kPReg, // apply the poison }; #else std::vector patterns_array = { "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load expected map "cmp <>, <>", // compare maps "b.ne", // deopt if different "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur <>, \\[<>, #[0-9]+\\]", // load the field "and <>, <>, " + kPReg, // apply the poison }; #endif CHECK(CheckDisassemblyRegexPatterns("mono", patterns_array)); #endif // ENABLE_DISASSEMBLER } TEST(DisasmPoisonPolymorphicLoad) { #ifdef ENABLE_DISASSEMBLER if (i::FLAG_always_opt || !i::FLAG_opt) return; // TODO(9684): Re-enable for TurboProp if necessary. if (i::FLAG_turboprop) return; i::FLAG_allow_natives_syntax = true; i::FLAG_untrusted_code_mitigations = true; i::FLAG_debug_code = false; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); CompileRun( "function poly(o) { return o.x + 1; };" "let o1 = { x : 1 };" "let o2 = { y : 1 };" "o2.x = 2;" "%PrepareFunctionForOptimization(poly);" "poly(o2);" "poly(o1);" "poly(o2);" "%OptimizeFunctionOnNextCall(poly);" "poly(o1);"); // Matches that the property access sequence is instrumented with // poisoning. #if defined(V8_COMPRESS_POINTERS) std::vector patterns_array = { "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load map const #1 "cmp <>, <>", // compare maps "b.eq", // ? go to the load "csel " + kPReg + ", xzr, " + kPReg + ", eq", // update the poison "csdb", // spec. barrier "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load map const #2 "cmp <>, <>", // compare maps "b.ne", // deopt if different "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur w<>, \\[<>, #[0-9]+\\]", // load the field "and x<>, x<>, " + kPReg, // apply the poison "asr w[0-9]+, w<>, #1", // untag "b", // goto merge point // Lcase1: "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur w<>, \\[<>, #[0-9]+\\]", // load backing store // branchful decompress "add x<>, x2[68], x<>", // Add root to ref "and x<>, x<>, " + kPReg, // apply the poison "ldur w<>, \\[x<>, #[0-9]+\\]", // load the property "and x<>, x<>, " + kPReg, // apply the poison // Ldone: }; #else std::vector patterns_array = { "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load map const #1 "cmp <>, <>", // compare maps "b.eq", // ? go to the load "csel " + kPReg + ", xzr, " + kPReg + ", eq", // update the poison "csdb", // spec. barrier "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load map const #2 "cmp <>, <>", // compare maps "b.ne", // deopt if different "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur x<>, \\[<>, #[0-9]+\\]", // load the field "and x<>, x<>, " + kPReg, // apply the poison #ifdef V8_31BIT_SMIS_ON_64BIT_ARCH "asr w<>, w<>, #1", // untag #else "asr x[0-9]+, x<>, #32", // untag #endif "b", // goto merge point // Lcase1: "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur <>, \\[<>, #[0-9]+\\]", // load backing store "and <>, <>, " + kPReg, // apply the poison "ldur <>, \\[<>, #[0-9]+\\]", // load the property "and <>, <>, " + kPReg, // apply the poison // Ldone: }; #endif CHECK(CheckDisassemblyRegexPatterns("poly", patterns_array)); #endif // ENABLE_DISASSEMBLER } TEST(DisasmPoisonMonomorphicLoadFloat64) { #ifdef ENABLE_DISASSEMBLER if (i::FLAG_always_opt || !i::FLAG_opt) return; // TODO(9684): Re-enable for TurboProp if necessary. if (i::FLAG_turboprop) return; i::FLAG_allow_natives_syntax = true; i::FLAG_untrusted_code_mitigations = true; CcTest::InitializeVM(); v8::HandleScope scope(CcTest::isolate()); CompileRun( "function mono(o) { return o.x; }" "%PrepareFunctionForOptimization(mono);" "mono({ x : 1.1 });" "mono({ x : 1.1 });" "%OptimizeFunctionOnNextCall(mono);" "mono({ x : 1.1 });"); // Matches that the property access sequence is instrumented with // poisoning. #if defined(V8_COMPRESS_POINTERS) std::vector patterns_array = { "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load expected map "cmp <>, <>", // compare maps "b.ne", // deopt if differ "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur w<>, \\[<>, #11\\]", // load heap number "add x<>, x2[68], x<>", // Decompress ref "and x<>, x<>, " + kPReg, // apply the poison "add <>, x<>, #0x[0-9a-f]+", // addr. calculation "and <>, <>, " + kPReg, // apply the poison "ldr d[0-9]+, \\[<>\\]", // load Float64 }; #else std::vector patterns_array = { "ldur <>, \\[<>, #-1\\]", // load map "ldr <>, pc", // load expected map "cmp <>, <>", // compare maps "b.ne", // deopt if differ "csel " + kPReg + ", xzr, " + kPReg + ", ne", // update the poison "csdb", // spec. barrier "ldur <>, \\[<>, #23\\]", // load heap number "and <>, <>, " + kPReg, // apply the poison "add <>, <>, #0x7", // addr. calculation "and <>, <>, " + kPReg, // apply the poison "ldr d[0-9]+, \\[<>\\]", // load Float64 }; #endif CHECK(CheckDisassemblyRegexPatterns("mono", patterns_array)); #endif // ENABLE_DISASSEMBLER } } // namespace internal } // namespace v8