678afa3c04
Currently, GetConsName incorrectly includes the null terminator as part of the length used in the string's hash. Exclude this to be consistent with GetCopy, GetName, etc. and permit coalescing. Bug: v8:0 Change-Id: I1e8a4eb7055637f3ed178014725b44e84d7788b6 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2578192 Reviewed-by: Peter Marshall <petermarshall@chromium.org> Commit-Queue: Andrew Comminos <acomminos@fb.com> Cr-Commit-Position: refs/heads/master@{#71667}
174 lines
5.2 KiB
C++
174 lines
5.2 KiB
C++
// Copyright 2018 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/profiler/strings-storage.h"
|
|
|
|
#include <cstdio>
|
|
|
|
#include "test/unittests/test-utils.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
using StringsStorageWithIsolate = TestWithIsolate;
|
|
|
|
bool StringEq(const char* left, const char* right) {
|
|
return strcmp(left, right) == 0;
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, GetNameFromString) {
|
|
StringsStorage storage;
|
|
|
|
// One char strings are canonical on the v8 heap so use a 2 char string here.
|
|
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("xy");
|
|
const char* stored_str = storage.GetName(*str);
|
|
CHECK(StringEq("xy", stored_str));
|
|
|
|
// The storage should de-duplicate the underlying char arrays and return the
|
|
// exact same pointer for equivalent input strings.
|
|
const char* stored_str_twice = storage.GetName(*str);
|
|
CHECK_EQ(stored_str, stored_str_twice);
|
|
|
|
// Even if the input string was a different one on the v8 heap, if the char
|
|
// array is the same, it should be de-duplicated.
|
|
Handle<String> str2 = isolate()->factory()->NewStringFromAsciiChecked("xy");
|
|
CHECK_NE(*str, *str2);
|
|
const char* stored_str_thrice = storage.GetName(*str2);
|
|
CHECK_EQ(stored_str_twice, stored_str_thrice);
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, GetNameFromSymbol) {
|
|
StringsStorage storage;
|
|
|
|
Handle<Symbol> symbol = isolate()->factory()->NewSymbol();
|
|
const char* stored_symbol = storage.GetName(*symbol);
|
|
CHECK(StringEq("<symbol>", stored_symbol));
|
|
|
|
Handle<Symbol> symbol2 = isolate()->factory()->NewSymbol();
|
|
CHECK_NE(*symbol, *symbol2);
|
|
const char* stored_symbol2 = storage.GetName(*symbol2);
|
|
CHECK_EQ(stored_symbol, stored_symbol2);
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, GetConsName) {
|
|
StringsStorage storage;
|
|
|
|
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("xy");
|
|
|
|
const char* empty_prefix_str = storage.GetConsName("", *str);
|
|
CHECK(StringEq("xy", empty_prefix_str));
|
|
|
|
const char* get_str = storage.GetConsName("get ", *str);
|
|
CHECK(StringEq("get xy", get_str));
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, GetNameFromInt) {
|
|
StringsStorage storage;
|
|
|
|
const char* stored_str = storage.GetName(0);
|
|
CHECK(StringEq("0", stored_str));
|
|
|
|
stored_str = storage.GetName(2147483647);
|
|
CHECK(StringEq("2147483647", stored_str));
|
|
|
|
stored_str = storage.GetName(std::numeric_limits<int>::min());
|
|
char str_negative_int[12];
|
|
snprintf(str_negative_int, sizeof(str_negative_int), "%d",
|
|
std::numeric_limits<int>::min());
|
|
CHECK(StringEq(str_negative_int, stored_str));
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, Format) {
|
|
StringsStorage storage;
|
|
|
|
const char* xy = "xy";
|
|
const char* stored_str = storage.GetFormatted("%s", xy);
|
|
CHECK(StringEq("xy", stored_str));
|
|
// Check that the string is copied.
|
|
CHECK_NE(xy, stored_str);
|
|
|
|
const char* formatted_str = storage.GetFormatted("%s / %s", xy, xy);
|
|
CHECK(StringEq("xy / xy", formatted_str));
|
|
|
|
// A different format specifier that results in the same string should share
|
|
// the string in storage.
|
|
const char* formatted_str2 = storage.GetFormatted("%s", "xy / xy");
|
|
CHECK_EQ(formatted_str, formatted_str2);
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, FormatAndGetShareStorage) {
|
|
StringsStorage storage;
|
|
|
|
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("xy");
|
|
const char* stored_str = storage.GetName(*str);
|
|
|
|
const char* formatted_str = storage.GetFormatted("%s", "xy");
|
|
CHECK_EQ(stored_str, formatted_str);
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, Refcounting) {
|
|
StringsStorage storage;
|
|
|
|
const char* a = storage.GetCopy("12");
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
|
|
const char* b = storage.GetCopy("12");
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
|
|
// Ensure that we deduplicate the string.
|
|
CHECK_EQ(a, b);
|
|
|
|
CHECK(storage.Release(a));
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
CHECK(storage.Release(b));
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 0);
|
|
#if !DEBUG
|
|
CHECK(!storage.Release("12"));
|
|
#endif // !DEBUG
|
|
|
|
// Verify that other constructors refcount as intended.
|
|
const char* c = storage.GetFormatted("%d", 12);
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
|
|
const char* d = storage.GetName(12);
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
|
|
CHECK_EQ(c, d);
|
|
|
|
CHECK(storage.Release(c));
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
CHECK(storage.Release(d));
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 0);
|
|
#if !DEBUG
|
|
CHECK(!storage.Release("12"));
|
|
#endif // !DEBUG
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, InvalidRelease) {
|
|
StringsStorage storage;
|
|
|
|
// If a refcount becomes invalid, throw in debug builds.
|
|
#ifdef DEBUG
|
|
ASSERT_DEATH_IF_SUPPORTED(storage.Release("12"), "check failed");
|
|
#else
|
|
CHECK(!storage.Release("12"));
|
|
#endif // DEBUG
|
|
}
|
|
|
|
TEST_F(StringsStorageWithIsolate, CopyAndConsShareStorage) {
|
|
StringsStorage storage;
|
|
|
|
Handle<String> str = isolate()->factory()->NewStringFromAsciiChecked("foo");
|
|
|
|
const char* copy_str = storage.GetCopy("get foo");
|
|
const char* cons_str = storage.GetConsName("get ", *str);
|
|
|
|
CHECK_EQ(storage.GetStringCountForTesting(), 1);
|
|
CHECK_EQ(copy_str, cons_str);
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|