From 78c42a1f8e5c82a165884cb787b80c344e599271 Mon Sep 17 00:00:00 2001 From: Camillo Bruni Date: Thu, 24 Sep 2020 09:39:15 +0200 Subject: [PATCH] [log] Support logging two-byte characters MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: chromium:1130673 Change-Id: I78ae388daa1c4c2b594981bdadd201c2dfb39eb0 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2426618 Reviewed-by: Marja Hölttä Commit-Queue: Camillo Bruni Cr-Commit-Position: refs/heads/master@{#70116} --- src/logging/log-utils.cc | 25 +++++++++++++++---- src/logging/log-utils.h | 3 ++- src/logging/log.cc | 4 +-- src/logging/log.h | 2 +- src/parsing/parser.cc | 2 +- src/parsing/preparser.cc | 4 ++- test/mjsunit/tools/log_two_byte.js | 40 ++++++++++++++++++++++++++++++ 7 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 test/mjsunit/tools/log_two_byte.js diff --git a/src/logging/log-utils.cc b/src/logging/log-utils.cc index 6b830ca31d..aaf7a37618 100644 --- a/src/logging/log-utils.cc +++ b/src/logging/log-utils.cc @@ -128,12 +128,19 @@ void Log::MessageBuilder::AppendString(const char* str) { AppendString(str, strlen(str)); } -void Log::MessageBuilder::AppendString(const char* str, size_t length) { +void Log::MessageBuilder::AppendString(const char* str, size_t length, + bool is_one_byte) { if (str == nullptr) return; - - for (size_t i = 0; i < length; i++) { - DCHECK_NE(str[i], '\0'); - AppendCharacter(str[i]); + if (is_one_byte) { + for (size_t i = 0; i < length; i++) { + DCHECK_IMPLIES(is_one_byte, str[i] != '\0'); + AppendCharacter(str[i]); + } + } else { + DCHECK_EQ(length % 2, 0); + for (size_t i = 0; i + 1 < length; i += 2) { + AppendTwoByteCharacter(str[i], str[i + 1]); + } } } @@ -148,6 +155,14 @@ void Log::MessageBuilder::AppendFormatString(const char* format, ...) { } } +void Log::MessageBuilder::AppendTwoByteCharacter(char c1, char c2) { + if (c2 == 0) { + AppendCharacter(c1); + } else { + // Escape non-printable characters. + AppendRawFormatString("\\u%02x%02x", c1 & 0xFF, c2 & 0xFF); + } +} void Log::MessageBuilder::AppendCharacter(char c) { if (c >= 32 && c <= 126) { if (c == ',') { diff --git a/src/logging/log-utils.h b/src/logging/log-utils.h index f45b0e5f44..47abf927f1 100644 --- a/src/logging/log-utils.h +++ b/src/logging/log-utils.h @@ -69,9 +69,10 @@ class Log { base::Optional length_limit = base::nullopt); void AppendString(Vector str); void AppendString(const char* str); - void AppendString(const char* str, size_t length); + void AppendString(const char* str, size_t length, bool is_one_byte = true); void PRINTF_FORMAT(2, 3) AppendFormatString(const char* format, ...); void AppendCharacter(char c); + void AppendTwoByteCharacter(char c1, char c2); void AppendSymbolName(Symbol symbol); // Delegate insertion to the underlying {log_}. diff --git a/src/logging/log.cc b/src/logging/log.cc index 2f87940c60..efd7c2b5f3 100644 --- a/src/logging/log.cc +++ b/src/logging/log.cc @@ -1602,7 +1602,7 @@ void Logger::FunctionEvent(const char* reason, int script_id, double time_delta, void Logger::FunctionEvent(const char* reason, int script_id, double time_delta, int start_position, int end_position, const char* function_name, - size_t function_name_length) { + size_t function_name_length, bool is_one_byte) { if (!FLAG_log_function_events) return; std::unique_ptr msg_ptr = log_->NewMessageBuilder(); if (!msg_ptr) return; @@ -1610,7 +1610,7 @@ void Logger::FunctionEvent(const char* reason, int script_id, double time_delta, AppendFunctionMessage(msg, reason, script_id, time_delta, start_position, end_position, &timer_); if (function_name_length > 0) { - msg.AppendString(function_name, function_name_length); + msg.AppendString(function_name, function_name_length, is_one_byte); } msg.WriteToLogFile(); } diff --git a/src/logging/log.h b/src/logging/log.h index 12d3f0a53b..aa9b0c4237 100644 --- a/src/logging/log.h +++ b/src/logging/log.h @@ -170,7 +170,7 @@ class Logger : public CodeEventListener { void FunctionEvent(const char* reason, int script_id, double time_delta_ms, int start_position, int end_position, const char* function_name = nullptr, - size_t function_name_length = 0); + size_t function_name_length = 0, bool is_one_byte = true); void CompilationCacheEvent(const char* action, const char* cache_type, SharedFunctionInfo sfi); diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc index e8a8e60589..b05ae32bba 100644 --- a/src/parsing/parser.cc +++ b/src/parsing/parser.cc @@ -2507,7 +2507,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral( event_name, flags().script_id(), ms, scope->start_position(), scope->end_position(), reinterpret_cast(function_name->raw_data()), - function_name->byte_length()); + function_name->byte_length(), function_name->is_one_byte()); } if (V8_UNLIKELY(TracingFlags::is_runtime_stats_enabled()) && did_preparse_successfully) { diff --git a/src/parsing/preparser.cc b/src/parsing/preparser.cc index 6da0faa74a..2764e00a8b 100644 --- a/src/parsing/preparser.cc +++ b/src/parsing/preparser.cc @@ -347,14 +347,16 @@ PreParser::Expression PreParser::ParseFunctionLiteral( // reconstructed from the script id and the byte range in the log processor. const char* name = ""; size_t name_byte_length = 0; + bool is_one_byte = true; const AstRawString* string = function_name.string_; if (string != nullptr) { name = reinterpret_cast(string->raw_data()); name_byte_length = string->byte_length(); + is_one_byte = string->is_one_byte(); } logger_->FunctionEvent( event_name, flags().script_id(), ms, function_scope->start_position(), - function_scope->end_position(), name, name_byte_length); + function_scope->end_position(), name, name_byte_length, is_one_byte); } return Expression::Default(); diff --git a/test/mjsunit/tools/log_two_byte.js b/test/mjsunit/tools/log_two_byte.js new file mode 100644 index 0000000000..676325b4ae --- /dev/null +++ b/test/mjsunit/tools/log_two_byte.js @@ -0,0 +1,40 @@ +// Copyright 2020 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --logfile='+' --log --log-code --log-function-events --no-stress-opt + +let twoByteName = "twoByteName_🍕" +let o = { + [twoByteName](obj) { + return obj.a + } +} +function testFunctionWithFunnyName(o) { + return o.a; +} + +(function testLoopWithFunnyName() { + let object = {a:1}; + let result = 0; + for (let i = 0; i < 1000; i++) { + result += o[twoByteName](object); + } + console.log(result); + console.log(twoByteName); + +})(); + +var __v_3 = {}; +({})['foobar\u2653'] = null; +eval('__v_3 = function foobar() { return foobar };'); +__v_3(); + +const log = d8.log.getAndStop(); +console.log(log) +// Check that we have a minimally working log file. +assertTrue(log.length > 0); +assertTrue(log.indexOf('v8-version') == 0); +assertTrue(log.indexOf('testFunctionWithFunnyName') >= 10); +assertTrue(log.indexOf("twoByteName") >= 10); +assertTrue(log.indexOf('testLoopWithFunnyName') >= 10);