Commit e0059db5 authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[turbofan] Add --trace-turbo-filter

This adds a filter option for --trace-turbo, --trace-turbo-graph
and --trace-turbo-scheduled. The filter is a pattern that matches
function names in this way:
   "*"      all; the default
   "-"      all but the top-level function
   "-name"  all but the function "name"
   ""       only the top-level function
   "name"   only the function "name"
   "name*"  only functions starting with "name"
   "~"      none; the tilde is not an identifier

Bug: v8:7761
Change-Id: I7e8e726023f2c72754b0dd691d790af20b022fd3
Reviewed-on: https://chromium-review.googlesource.com/1059774Reviewed-by: 's avatarJaroslav Sevcik <jarin@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Cr-Commit-Position: refs/heads/master@{#53201}
parent 42027031
......@@ -709,7 +709,9 @@ void CodeGenerator::AssembleSourcePosition(SourcePosition source_position) {
if (info->IsStub()) return;
std::ostringstream buffer;
buffer << "-- ";
if (FLAG_trace_turbo || FLAG_trace_turbo_graph ||
// Turbolizer only needs the source position, as it can reconstruct
// the inlining stack from other information.
if (info->trace_turbo_json_enabled() ||
tasm()->isolate()->concurrent_recompilation_enabled()) {
buffer << source_position;
} else {
......
......@@ -631,7 +631,7 @@ struct TurboJsonFile : public std::ofstream {
void TraceSchedule(OptimizedCompilationInfo* info, Isolate* isolate,
Schedule* schedule) {
if (FLAG_trace_turbo) {
if (info->trace_turbo_json_enabled()) {
AllowHandleDereference allow_deref;
TurboJsonFile json_of(info, std::ios_base::app);
json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\"";
......@@ -643,7 +643,7 @@ void TraceSchedule(OptimizedCompilationInfo* info, Isolate* isolate,
}
json_of << "\"},\n";
}
if (FLAG_trace_turbo_graph || FLAG_trace_turbo_scheduler) {
if (info->trace_turbo_graph_enabled() || FLAG_trace_turbo_scheduler) {
AllowHandleDereference allow_deref;
CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
OFStream os(tracing_scope.file());
......@@ -713,7 +713,7 @@ PipelineStatistics* CreatePipelineStatistics(Handle<Script> script,
pipeline_statistics->BeginPhaseKind("initializing");
}
if (FLAG_trace_turbo) {
if (info->trace_turbo_json_enabled()) {
TurboJsonFile json_of(info, std::ios_base::trunc);
std::unique_ptr<char[]> function_name = info->GetDebugName();
int pos =
......@@ -934,7 +934,7 @@ PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::PrepareJobImpl(
PipelineWasmCompilationJob::Status
PipelineWasmCompilationJob::ExecuteJobImpl() {
if (FLAG_trace_turbo) {
if (compilation_info()->trace_turbo_json_enabled()) {
TurboJsonFile json_of(compilation_info(), std::ios_base::trunc);
json_of << "{\"function\":\"" << compilation_info()->GetDebugName().get()
<< "\", \"source\":\"\",\n\"phases\":[";
......@@ -1753,14 +1753,14 @@ struct PrintGraphPhase {
OptimizedCompilationInfo* info = data->info();
Graph* graph = data->graph();
if (FLAG_trace_turbo) { // Print JSON.
if (info->trace_turbo_json_enabled()) { // Print JSON.
AllowHandleDereference allow_deref;
TurboJsonFile json_of(info, std::ios_base::app);
json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
<< AsJSON(*graph, data->source_positions()) << "},\n";
}
if (FLAG_trace_turbo_scheduled) { // Scheduled textual output.
if (info->trace_turbo_scheduled_enabled()) {
AccountingAllocator allocator;
Schedule* schedule = data->schedule();
if (schedule == nullptr) {
......@@ -1773,7 +1773,7 @@ struct PrintGraphPhase {
OFStream os(tracing_scope.file());
os << "-- Graph after " << phase << " -- " << std::endl;
os << AsScheduledGraph(schedule);
} else if (FLAG_trace_turbo_graph) { // Simple textual RPO.
} else if (info->trace_turbo_graph_enabled()) { // Simple textual RPO.
AllowHandleDereference allow_deref;
CodeTracer::Scope tracing_scope(data->isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
......@@ -1808,7 +1808,8 @@ struct VerifyGraphPhase {
};
void PipelineImpl::RunPrintAndVerify(const char* phase, bool untyped) {
if (FLAG_trace_turbo || FLAG_trace_turbo_graph) {
if (info()->trace_turbo_json_enabled() ||
info()->trace_turbo_graph_enabled()) {
Run<PrintGraphPhase>(phase);
}
if (FLAG_turbo_verify) {
......@@ -1821,14 +1822,15 @@ bool PipelineImpl::CreateGraph() {
data->BeginPhaseKind("graph creation");
if (FLAG_trace_turbo || FLAG_trace_turbo_graph) {
if (info()->trace_turbo_json_enabled() ||
info()->trace_turbo_graph_enabled()) {
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
os << "---------------------------------------------------\n"
<< "Begin compiling method " << info()->GetDebugName().get()
<< " using Turbofan" << std::endl;
}
if (FLAG_trace_turbo) {
if (info()->trace_turbo_json_enabled()) {
TurboCfgFile tcf(isolate());
tcf << AsC1VCompilation(info());
}
......@@ -1998,12 +2000,12 @@ Handle<Code> Pipeline::GenerateCodeForCodeStub(
PipelineImpl pipeline(&data);
DCHECK_NOT_NULL(data.schedule());
if (FLAG_trace_turbo || FLAG_trace_turbo_graph) {
if (info.trace_turbo_json_enabled() || info.trace_turbo_graph_enabled()) {
CodeTracer::Scope tracing_scope(isolate->GetCodeTracer());
OFStream os(tracing_scope.file());
os << "---------------------------------------------------\n"
<< "Begin compiling " << debug_name << " using Turbofan" << std::endl;
if (FLAG_trace_turbo) {
if (info.trace_turbo_json_enabled()) {
TurboJsonFile json_of(&info, std::ios_base::trunc);
json_of << "{\"function\":\"" << info.GetDebugName().get()
<< "\", \"source\":\"\",\n\"phases\":[";
......@@ -2067,7 +2069,7 @@ Handle<Code> Pipeline::GenerateCodeForTesting(
PipelineImpl pipeline(&data);
if (FLAG_trace_turbo) {
if (info->trace_turbo_json_enabled()) {
TurboJsonFile json_of(info, std::ios_base::trunc);
json_of << "{\"function\":\"" << info->GetDebugName().get()
<< "\", \"source\":\"\",\n\"phases\":[";
......@@ -2182,14 +2184,14 @@ bool PipelineImpl::SelectInstructions(Linkage* linkage) {
return false;
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
if (info()->trace_turbo_json_enabled() && !data->MayHaveUnverifiableGraph()) {
AllowHandleDereference allow_deref;
TurboCfgFile tcf(isolate());
tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
data->sequence());
}
if (FLAG_trace_turbo) {
if (info()->trace_turbo_json_enabled()) {
std::ostringstream source_position_output;
// Output source position information before the graph is deleted.
data_->source_positions()->Print(source_position_output);
......@@ -2265,7 +2267,7 @@ Handle<Code> PipelineImpl::FinalizeCode() {
info()->SetCode(code);
PrintCode(code, info());
if (FLAG_trace_turbo) {
if (info()->trace_turbo_json_enabled()) {
TurboJsonFile json_of(info(), std::ios_base::app);
json_of << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
#if ENABLE_DISASSEMBLER
......@@ -2281,7 +2283,8 @@ Handle<Code> PipelineImpl::FinalizeCode() {
json_of << data->source_position_output();
json_of << "}";
}
if (FLAG_trace_turbo || FLAG_trace_turbo_graph) {
if (info()->trace_turbo_json_enabled() ||
info()->trace_turbo_graph_enabled()) {
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
os << "---------------------------------------------------\n"
......@@ -2327,7 +2330,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
Run<MeetRegisterConstraintsPhase>();
Run<ResolvePhisPhase>();
Run<BuildLiveRangesPhase>();
if (FLAG_trace_turbo_graph) {
if (info()->trace_turbo_graph_enabled()) {
AllowHandleDereference allow_deref;
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
......@@ -2371,7 +2374,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
Run<LocateSpillSlotsPhase>();
if (FLAG_trace_turbo_graph) {
if (info()->trace_turbo_graph_enabled()) {
AllowHandleDereference allow_deref;
CodeTracer::Scope tracing_scope(isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
......@@ -2384,8 +2387,8 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config,
verifier->VerifyGapMoves();
}
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(data->isolate());
if (info()->trace_turbo_json_enabled() && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(isolate());
tcf << AsC1VRegisterAllocationData("CodeGen",
data->register_allocation_data());
}
......
......@@ -4717,7 +4717,17 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
//----------------------------------------------------------------------------
// Run the compilation pipeline.
//----------------------------------------------------------------------------
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
#ifdef DEBUG
EmbeddedVector<char, 32> func_name;
static unsigned id = 0;
func_name.Truncate(SNPrintF(func_name, "js-to-wasm#%d", id++));
#else
Vector<const char> func_name = CStrVector("js-to-wasm");
#endif
OptimizedCompilationInfo info(func_name, &zone, Code::JS_TO_WASM_FUNCTION);
if (info.trace_turbo_graph_enabled()) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Graph after change lowering -- " << std::endl;
os << AsRPO(graph);
......@@ -4729,15 +4739,6 @@ Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, wasm::WasmModule* module,
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, params + 1, CallDescriptor::kNoFlags);
#ifdef DEBUG
EmbeddedVector<char, 32> func_name;
static unsigned id = 0;
func_name.Truncate(SNPrintF(func_name, "js-to-wasm#%d", id++));
#else
Vector<const char> func_name = CStrVector("js-to-wasm");
#endif
OptimizedCompilationInfo info(func_name, &zone, Code::JS_TO_WASM_FUNCTION);
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, isolate, incoming, &graph);
#ifdef ENABLE_DISASSEMBLER
......@@ -4820,7 +4821,17 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
builder.set_effect_ptr(&effect);
builder.BuildWasmToJSWrapper(target, index);
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
#ifdef DEBUG
EmbeddedVector<char, 32> func_name;
static unsigned id = 0;
func_name.Truncate(SNPrintF(func_name, "wasm-to-js#%d", id++));
#else
Vector<const char> func_name = CStrVector("wasm-to-js");
#endif
OptimizedCompilationInfo info(func_name, &zone, Code::WASM_TO_JS_FUNCTION);
if (info.trace_turbo_graph_enabled()) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Graph after change lowering -- " << std::endl;
os << AsRPO(graph);
......@@ -4832,15 +4843,6 @@ Handle<Code> CompileWasmToJSWrapper(Isolate* isolate, Handle<JSReceiver> target,
incoming = GetI32WasmCallDescriptor(&zone, incoming);
}
#ifdef DEBUG
EmbeddedVector<char, 32> func_name;
static unsigned id = 0;
func_name.Truncate(SNPrintF(func_name, "wasm-to-js#%d", id++));
#else
Vector<const char> func_name = CStrVector("wasm-to-js");
#endif
OptimizedCompilationInfo info(func_name, &zone, Code::WASM_TO_JS_FUNCTION);
Handle<Code> code = Pipeline::GenerateCodeForTesting(
&info, isolate, incoming, &graph, nullptr, source_position_table);
ValidateImportWrapperReferencesImmovables(code);
......@@ -4885,12 +4887,6 @@ Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
Handle<Code> code = Handle<Code>::null();
{
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Wasm interpreter entry graph -- " << std::endl;
os << AsRPO(graph);
}
// Schedule and compile to machine code.
CallDescriptor* incoming = GetWasmCallDescriptor(&zone, sig);
if (machine.Is32()) {
......@@ -4906,6 +4902,13 @@ Handle<Code> CompileWasmInterpreterEntry(Isolate* isolate, uint32_t func_index,
OptimizedCompilationInfo info(func_name, &zone,
Code::WASM_INTERPRETER_ENTRY);
if (info.trace_turbo_graph_enabled()) { // Simple textual RPO.
OFStream os(stdout);
os << "-- Wasm interpreter entry graph -- " << std::endl;
os << AsRPO(graph);
}
code = Pipeline::GenerateCodeForTesting(&info, isolate, incoming, &graph,
nullptr);
#ifdef ENABLE_DISASSEMBLER
......@@ -4943,12 +4946,6 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
builder.set_effect_ptr(&effect);
builder.BuildCWasmEntry();
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
OFStream os(stdout);
os << "-- C Wasm entry graph -- " << std::endl;
os << AsRPO(graph);
}
// Schedule and compile to machine code.
CallDescriptor* incoming = Linkage::GetJSCallDescriptor(
&zone, false, CWasmEntryParameters::kNumParameters + 1,
......@@ -4972,6 +4969,13 @@ Handle<Code> CompileCWasmEntry(Isolate* isolate, wasm::FunctionSig* sig) {
Vector<const char> debug_name_vec(debug_name, name_len);
OptimizedCompilationInfo info(debug_name_vec, &zone, Code::C_WASM_ENTRY);
if (info.trace_turbo_graph_enabled()) { // Simple textual RPO.
OFStream os(stdout);
os << "-- C Wasm entry graph -- " << std::endl;
os << AsRPO(graph);
}
Handle<Code> code =
Pipeline::GenerateCodeForTesting(&info, isolate, incoming, &graph);
#ifdef ENABLE_DISASSEMBLER
......
......@@ -400,6 +400,8 @@ DEFINE_STRING(turbo_filter, "*", "optimization filter for TurboFan compiler")
DEFINE_BOOL(trace_turbo, false, "trace generated TurboFan IR")
DEFINE_STRING(trace_turbo_path, nullptr,
"directory to dump generated TurboFan IR to")
DEFINE_STRING(trace_turbo_filter, "*",
"filter for tracing turbofan compilation")
DEFINE_BOOL(trace_turbo_graph, false, "trace generated TurboFan graphs")
DEFINE_BOOL(trace_turbo_scheduled, false, "trace TurboFan IR with schedule")
DEFINE_IMPLICATION(trace_turbo_scheduled, trace_turbo_graph)
......
......@@ -13699,40 +13699,10 @@ SharedFunctionInfo::SideEffectState SharedFunctionInfo::GetSideEffectState(
return static_cast<SideEffectState>(info->side_effect_state());
}
// The filter is a pattern that matches function names in this way:
// "*" all; the default
// "-" all but the top-level function
// "-name" all but the function "name"
// "" only the top-level function
// "name" only the function "name"
// "name*" only functions starting with "name"
// "~" none; the tilde is not an identifier
bool SharedFunctionInfo::PassesFilter(const char* raw_filter) {
if (*raw_filter == '*') return true;
String* name = DebugName();
Vector<const char> filter = CStrVector(raw_filter);
if (filter.length() == 0) return name->length() == 0;
if (filter[0] == '-') {
// Negative filter.
if (filter.length() == 1) {
return (name->length() != 0);
} else if (name->IsUtf8EqualTo(filter.SubVector(1, filter.length()))) {
return false;
}
if (filter[filter.length() - 1] == '*' &&
name->IsUtf8EqualTo(filter.SubVector(1, filter.length() - 1), true)) {
return false;
}
return true;
} else if (name->IsUtf8EqualTo(filter)) {
return true;
}
if (filter[filter.length() - 1] == '*' &&
name->IsUtf8EqualTo(filter.SubVector(0, filter.length() - 1), true)) {
return true;
}
return false;
std::unique_ptr<char[]> cstrname(DebugName()->ToCString());
return v8::internal::PassesFilter(CStrVector(cstrname.get()), filter);
}
bool SharedFunctionInfo::HasSourceCode() const {
......
......@@ -42,6 +42,8 @@ OptimizedCompilationInfo::OptimizedCompilationInfo(
if (isolate->NeedsSourcePositionsForProfiling()) {
MarkAsSourcePositionsEnabled();
}
SetTracingFlags(shared->PassesFilter(FLAG_trace_turbo_filter));
}
OptimizedCompilationInfo::OptimizedCompilationInfo(
......@@ -58,6 +60,8 @@ OptimizedCompilationInfo::OptimizedCompilationInfo(
}
#endif
#endif
SetTracingFlags(
PassesFilter(debug_name, CStrVector(FLAG_trace_turbo_filter)));
}
OptimizedCompilationInfo::OptimizedCompilationInfo(
......@@ -167,5 +171,12 @@ int OptimizedCompilationInfo::AddInlinedFunction(
return id;
}
void OptimizedCompilationInfo::SetTracingFlags(bool passes_filter) {
if (!passes_filter) return;
if (FLAG_trace_turbo) SetFlag(kTraceTurboJson);
if (FLAG_trace_turbo_graph) SetFlag(kTraceTurboGraph);
if (FLAG_trace_turbo_scheduled) SetFlag(kTraceTurboScheduled);
}
} // namespace internal
} // namespace v8
......@@ -52,6 +52,9 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
kPoisonRegisterArguments = 1 << 11,
kAllocationFoldingEnabled = 1 << 12,
kAnalyzeEnvironmentLiveness = 1 << 13,
kTraceTurboJson = 1 << 14,
kTraceTurboGraph = 1 << 15,
kTraceTurboScheduled = 1 << 16,
};
// TODO(mtrofin): investigate if this might be generalized outside wasm, with
......@@ -170,6 +173,14 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
return GetFlag(kAnalyzeEnvironmentLiveness);
}
bool trace_turbo_json_enabled() const { return GetFlag(kTraceTurboJson); }
bool trace_turbo_graph_enabled() const { return GetFlag(kTraceTurboGraph); }
bool trace_turbo_scheduled_enabled() const {
return GetFlag(kTraceTurboScheduled);
}
// Code getters and setters.
void SetCode(Handle<Code> code) { code_ = code; }
......@@ -267,6 +278,8 @@ class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
void SetFlag(Flag flag) { flags_ |= flag; }
bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
void SetTracingFlags(bool passes_filter);
// Compilation flags.
unsigned flags_;
PoisoningMitigationLevel poisoning_level_ =
......
......@@ -442,6 +442,53 @@ bool DoubleToBoolean(double d) {
return true;
}
// The filter is a pattern that matches function names in this way:
// "*" all; the default
// "-" all but the top-level function
// "-name" all but the function "name"
// "" only the top-level function
// "name" only the function "name"
// "name*" only functions starting with "name"
// "~" none; the tilde is not an identifier
bool PassesFilter(Vector<const char> name, Vector<const char> filter) {
if (filter.size() == 0) return name.size() == 0;
auto filter_it = filter.begin();
bool positive_filter = true;
if (*filter_it == '-') {
++filter_it;
positive_filter = false;
}
if (filter_it == filter.end()) return name.size() != 0;
if (*filter_it == '*') return positive_filter;
if (*filter_it == '~') return !positive_filter;
bool prefix_match = filter[filter.size() - 1] == '*';
size_t min_match_length = filter.size();
if (!positive_filter) min_match_length--; // Subtract 1 for leading '-'.
if (prefix_match) min_match_length--; // Subtract 1 for trailing '*'.
if (name.size() < min_match_length) return !positive_filter;
// TODO(sigurds): Use the new version of std::mismatch here, once we
// can assume C++14.
auto res = std::mismatch(filter_it, filter.end(), name.begin());
if (res.first == filter.end()) {
if (res.second == name.end()) {
// The strings match, so {name} passes if we have a {positive_filter}.
return positive_filter;
}
// {name} is longer than the filter, so {name} passes if we don't have a
// {positive_filter}.
return !positive_filter;
}
if (*res.first == '*') {
// We matched up to the wildcard, so {name} passes if we have a
// {positive_filter}.
return positive_filter;
}
// We don't match, so {name} passes if we don't have a {positive_filter}.
return !positive_filter;
}
} // namespace internal
} // namespace v8
......@@ -1818,6 +1818,9 @@ class ThreadedListZoneEntry final : public ZoneObject {
DISALLOW_COPY_AND_ASSIGN(ThreadedListZoneEntry);
};
V8_EXPORT_PRIVATE bool PassesFilter(Vector<const char> name,
Vector<const char> filter);
} // namespace internal
} // namespace v8
......
......@@ -109,5 +109,28 @@ TYPED_TEST(UtilsTest, SaturateAdd) {
}
}
TYPED_TEST(UtilsTest, PassesFilterTest) {
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("abcdefg")));
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("abcdefg*")));
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("abc*")));
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("*")));
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("-~")));
EXPECT_TRUE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abcdefgh")));
EXPECT_TRUE(PassesFilter(CStrVector("abdefg"), CStrVector("-")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abcdefg")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abcdefg*")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-abc*")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("-*")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("~")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("")));
EXPECT_FALSE(PassesFilter(CStrVector("abcdefg"), CStrVector("abcdefgh")));
EXPECT_TRUE(PassesFilter(CStrVector(""), CStrVector("")));
EXPECT_TRUE(PassesFilter(CStrVector(""), CStrVector("*")));
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("-")));
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("-*")));
EXPECT_FALSE(PassesFilter(CStrVector(""), CStrVector("a")));
}
} // namespace internal
} // namespace v8
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment