Commit 1ff071c1 authored by Bill Budge's avatar Bill Budge Committed by Commit Bot

Revert "[dict-proto] C++ implementation of SwissNameDictionary, pt. 3"

This reverts commit 2f8a7561.

Reason for revert: Speculative revert, lots of segfaults on Arm:
https://ci.chromium.org/p/v8/builders/ci/V8%20Arm%20-%20debug/17781

Original change's description:
> [dict-proto] C++ implementation of SwissNameDictionary, pt. 3
>
> This CL is part of a series that adds the C++ implementation of
> SwissNameDictionary, a deterministic property backing store based on
> Swiss Tables.
>
> This CL adds the initialization code, factory functions and a
> canonical SwissNameDictionary plus all helpers required for that.
>
> Bug: v8:11388
> Change-Id: I6bb92740afefc7d05433cfa62023e6da5e8213c7
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2688058
> Reviewed-by: Igor Sheludko <ishell@chromium.org>
> Reviewed-by: Marja Hölttä <marja@chromium.org>
> Reviewed-by: Ulan Degenbaev <ulan@chromium.org>
> Commit-Queue: Frank Emrich <emrich@google.com>
> Cr-Commit-Position: refs/heads/master@{#72824}

Bug: v8:11388
Change-Id: Ia5dae584b0fb452b12c5d64ee63ffa418c83f91b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2698758
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: 's avatarBill Budge <bbudge@chromium.org>
Commit-Queue: Bill Budge <bbudge@chromium.org>
Cr-Commit-Position: refs/heads/master@{#72829}
parent 6a358500
......@@ -22,7 +22,6 @@
#include "src/objects/source-text-module.h"
#include "src/objects/string-inl.h"
#include "src/objects/string.h"
#include "src/objects/swiss-name-dictionary-inl.h"
#include "src/objects/template-objects-inl.h"
namespace v8 {
......@@ -849,43 +848,6 @@ HeapObject FactoryBase<Impl>::AllocateRaw(int size, AllocationType allocation,
return impl()->AllocateRaw(size, allocation, alignment);
}
template <typename Impl>
Handle<SwissNameDictionary>
FactoryBase<Impl>::NewSwissNameDictionaryWithCapacity(
int capacity, AllocationType allocation) {
DCHECK(SwissNameDictionary::IsValidCapacity(capacity));
if (capacity == 0) {
DCHECK_NE(read_only_roots().at(RootIndex::kEmptySwissPropertyDictionary),
kNullAddress);
return read_only_roots().empty_swiss_property_dictionary_handle();
}
if (capacity > SwissNameDictionary::MaxCapacity()) {
isolate()->FatalProcessOutOfHeapMemory("invalid table size");
}
int meta_table_length = SwissNameDictionary::MetaTableSizeFor(capacity);
Handle<ByteArray> meta_table =
impl()->NewByteArray(meta_table_length, allocation);
Map map = read_only_roots().swiss_name_dictionary_map();
int size = SwissNameDictionary::SizeFor(capacity);
HeapObject result = AllocateRawWithImmortalMap(size, allocation, map);
Handle<SwissNameDictionary> table(SwissNameDictionary::cast(result),
isolate());
table->Initialize(isolate(), *meta_table, capacity);
return table;
}
template <typename Impl>
Handle<SwissNameDictionary> FactoryBase<Impl>::NewSwissNameDictionary(
int at_least_space_for, AllocationType allocation) {
return NewSwissNameDictionaryWithCapacity(
SwissNameDictionary::CapacityFor(at_least_space_for), allocation);
}
// Instantiate FactoryBase for the two variants we want.
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE) FactoryBase<Factory>;
template class EXPORT_TEMPLATE_DEFINE(V8_EXPORT_PRIVATE)
......
......@@ -221,13 +221,6 @@ class EXPORT_TEMPLATE_DECLARE(V8_EXPORT_PRIVATE) FactoryBase
Handle<ClassPositions> NewClassPositions(int start, int end);
Handle<SwissNameDictionary> NewSwissNameDictionary(
int at_least_space_for = kSwissNameDictionaryInitialCapacity,
AllocationType allocation = AllocationType::kYoung);
Handle<SwissNameDictionary> NewSwissNameDictionaryWithCapacity(
int capacity, AllocationType allocation);
protected:
// Allocate memory for an uninitialized array (e.g., a FixedArray or similar).
HeapObject AllocateRawArray(int size, AllocationType allocation);
......
......@@ -553,27 +553,6 @@ Handle<PropertyDescriptorObject> Factory::NewPropertyDescriptorObject() {
return object;
}
Handle<SwissNameDictionary> Factory::CreateCanonicalEmptySwissNameDictionary() {
// This function is only supposed to be used to create the canonical empty
// version and should not be used afterwards.
DCHECK_EQ(kNullAddress, ReadOnlyRoots(isolate()).at(
RootIndex::kEmptySwissPropertyDictionary));
ReadOnlyRoots roots(isolate());
Handle<ByteArray> empty_meta_table =
NewByteArray(SwissNameDictionary::kMetaTableEnumerationTableStartOffset,
AllocationType::kReadOnly);
Map map = roots.swiss_name_dictionary_map();
int size = SwissNameDictionary::SizeFor(0);
HeapObject obj =
AllocateRawWithImmortalMap(size, AllocationType::kReadOnly, map);
SwissNameDictionary result = SwissNameDictionary::cast(obj);
result.Initialize(isolate(), *empty_meta_table, 0);
return handle(result, isolate());
}
// Internalized strings are created in the old generation (data space).
Handle<String> Factory::InternalizeUtf8String(
const Vector<const char>& string) {
......
......@@ -171,8 +171,6 @@ class V8_EXPORT_PRIVATE Factory : public FactoryBase<Factory> {
int capacity = kSmallOrderedHashMapMinCapacity,
AllocationType allocation = AllocationType::kYoung);
Handle<SwissNameDictionary> CreateCanonicalEmptySwissNameDictionary();
// Create a new PrototypeInfo struct.
Handle<PrototypeInfo> NewPrototypeInfo();
......
......@@ -819,11 +819,6 @@ void Heap::CreateInitialObjects() {
.ToHandleChecked();
set_empty_ordered_property_dictionary(*empty_ordered_property_dictionary);
// Allocate the empty SwissNameDictionary
Handle<SwissNameDictionary> empty_swiss_property_dictionary =
factory->CreateCanonicalEmptySwissNameDictionary();
set_empty_swiss_property_dictionary(*empty_swiss_property_dictionary);
// Allocate the empty FeedbackMetadata.
Handle<FeedbackMetadata> empty_feedback_metadata =
factory->NewFeedbackMetadata(0, 0, AllocationType::kReadOnly);
......
......@@ -5,8 +5,6 @@
#ifndef V8_OBJECTS_SWISS_NAME_DICTIONARY_INL_H_
#define V8_OBJECTS_SWISS_NAME_DICTIONARY_INL_H_
#include <algorithm>
#include "src/base/macros.h"
#include "src/execution/isolate-utils-inl.h"
#include "src/heap/heap.h"
......@@ -28,41 +26,10 @@ namespace internal {
CAST_ACCESSOR(SwissNameDictionary)
OBJECT_CONSTRUCTORS_IMPL(SwissNameDictionary, HeapObject)
const swiss_table::ctrl_t* SwissNameDictionary::CtrlTable() {
return reinterpret_cast<ctrl_t*>(
field_address(CtrlTableStartOffset(Capacity())));
}
int SwissNameDictionary::Capacity() {
return ReadField<int32_t>(CapacityOffset());
}
void SwissNameDictionary::SetCapacity(int capacity) {
DCHECK(IsValidCapacity(capacity));
WriteField(CapacityOffset(), capacity);
}
int SwissNameDictionary::NumberOfElements() {
return GetMetaTableField(kMetaTableElementCountOffset);
}
int SwissNameDictionary::NumberOfDeletedElements() {
return GetMetaTableField(kMetaTableDeletedElementCountOffset);
}
void SwissNameDictionary::SetNumberOfElements(int elements) {
SetMetaTableField(kMetaTableElementCountOffset, elements);
}
void SwissNameDictionary::SetNumberOfDeletedElements(int deleted_elements) {
SetMetaTableField(kMetaTableDeletedElementCountOffset, deleted_elements);
}
int SwissNameDictionary::UsedCapacity() {
return NumberOfElements() + NumberOfDeletedElements();
}
// static
constexpr bool SwissNameDictionary::IsValidCapacity(int capacity) {
return capacity == 0 || (capacity >= kInitialCapacity &&
......@@ -88,180 +55,6 @@ constexpr int SwissNameDictionary::SizeFor(int capacity) {
return PropertyDetailsTableStartOffset(capacity) + capacity;
}
// We use 7/8th as maximum load factor for non-special cases.
// For 16-wide groups, that gives an average of two empty slots per group.
// Similar to Abseil's CapacityToGrowth.
// static
constexpr int SwissNameDictionary::MaxUsableCapacity(int capacity) {
CONSTEXPR_DCHECK(IsValidCapacity(capacity));
if (Group::kWidth == 8 && capacity == 4) {
// If the group size is 16 we can fully utilize capacity 4: There will be
// enough kEmpty entries in the ctrl table.
return 3;
}
return capacity - capacity / 8;
}
// Returns |at_least_space_for| * 8/7 for non-special cases. Similar to Abseil's
// GrowthToLowerboundCapacity.
// static
int SwissNameDictionary::CapacityFor(int at_least_space_for) {
if (at_least_space_for <= 4) {
if (at_least_space_for == 0) {
return 0;
} else if (at_least_space_for < 4) {
return 4;
} else if (kGroupWidth == 16) {
DCHECK_EQ(4, at_least_space_for);
return 4;
} else if (kGroupWidth == 8) {
DCHECK_EQ(4, at_least_space_for);
return 8;
}
}
int non_normalized = at_least_space_for + at_least_space_for / 7;
return base::bits::RoundUpToPowerOfTwo32(non_normalized);
}
void SwissNameDictionary::SetMetaTableField(int field_index, int value) {
// See the STATIC_ASSERTs on |kMax1ByteMetaTableCapacity| and
// |kMax2ByteMetaTableCapacity| in the .cc file for an explanation of these
// constants.
int capacity = Capacity();
ByteArray meta_table = this->meta_table();
if (capacity <= kMax1ByteMetaTableCapacity) {
SetMetaTableField<uint8_t>(meta_table, field_index, value);
} else if (capacity <= kMax2ByteMetaTableCapacity) {
SetMetaTableField<uint16_t>(meta_table, field_index, value);
} else {
SetMetaTableField<uint32_t>(meta_table, field_index, value);
}
}
int SwissNameDictionary::GetMetaTableField(int field_index) {
// See the STATIC_ASSERTs on |kMax1ByteMetaTableCapacity| and
// |kMax2ByteMetaTableCapacity| in the .cc file for an explanation of these
// constants.
int capacity = Capacity();
ByteArray meta_table = this->meta_table();
if (capacity <= kMax1ByteMetaTableCapacity) {
return GetMetaTableField<uint8_t>(meta_table, field_index);
} else if (capacity <= kMax2ByteMetaTableCapacity) {
return GetMetaTableField<uint16_t>(meta_table, field_index);
} else {
return GetMetaTableField<uint32_t>(meta_table, field_index);
}
}
// static
template <typename T>
void SwissNameDictionary::SetMetaTableField(ByteArray meta_table,
int field_index, int value) {
STATIC_ASSERT((std::is_same<T, uint8_t>::value) ||
(std::is_same<T, uint16_t>::value) ||
(std::is_same<T, uint32_t>::value));
DCHECK_LE(value, std::numeric_limits<T>::max());
DCHECK_LT(meta_table.GetDataStartAddress() + field_index * sizeof(T),
meta_table.GetDataEndAddress());
T* raw_data = reinterpret_cast<T*>(meta_table.GetDataStartAddress());
raw_data[field_index] = value;
}
// static
template <typename T>
int SwissNameDictionary::GetMetaTableField(ByteArray meta_table,
int field_index) {
STATIC_ASSERT((std::is_same<T, uint8_t>::value) ||
(std::is_same<T, uint16_t>::value) ||
(std::is_same<T, uint32_t>::value));
DCHECK_LT(meta_table.GetDataStartAddress() + field_index * sizeof(T),
meta_table.GetDataEndAddress());
T* raw_data = reinterpret_cast<T*>(meta_table.GetDataStartAddress());
return raw_data[field_index];
}
constexpr int SwissNameDictionary::MetaTableSizePerEntryFor(int capacity) {
CONSTEXPR_DCHECK(IsValidCapacity(capacity));
// See the STATIC_ASSERTs on |kMax1ByteMetaTableCapacity| and
// |kMax2ByteMetaTableCapacity| in the .cc file for an explanation of these
// constants.
if (capacity <= kMax1ByteMetaTableCapacity) {
return sizeof(uint8_t);
} else if (capacity <= kMax2ByteMetaTableCapacity) {
return sizeof(uint16_t);
} else {
return sizeof(uint32_t);
}
}
constexpr int SwissNameDictionary::MetaTableSizeFor(int capacity) {
CONSTEXPR_DCHECK(IsValidCapacity(capacity));
int per_entry_size = MetaTableSizePerEntryFor(capacity);
// The enumeration table only needs to have as many slots as there can be
// present + deleted entries in the hash table (= maximum load factor *
// capactiy). Two more slots to store the number of present and deleted
// entries.
return per_entry_size * (MaxUsableCapacity(capacity) + 2);
}
template <typename LocalIsolate>
void SwissNameDictionary::Initialize(LocalIsolate* isolate,
ByteArray meta_table, int capacity) {
DCHECK(IsValidCapacity(capacity));
DisallowHeapAllocation no_gc;
ReadOnlyRoots roots(isolate);
SetCapacity(capacity);
SetHash(PropertyArray::kNoHashSentinel);
ctrl_t* ctrl_table = reinterpret_cast<ctrl_t*>(
field_address(CtrlTableStartOffset(Capacity())));
memset(ctrl_table, Ctrl::kEmpty, CtrlTableSize(capacity));
MemsetTagged(RawField(DataTableStartOffset()), roots.the_hole_value(),
capacity * kDataTableEntryCount);
set_meta_table(meta_table);
SetNumberOfElements(0);
SetNumberOfDeletedElements(0);
// We leave the enumeration table PropertyDetails table and uninitialized.
}
void SwissNameDictionary::SetHash(int32_t hash) {
WriteField(PrefixOffset(), hash);
}
int SwissNameDictionary::Hash() { return ReadField<int32_t>(PrefixOffset()); }
// static
constexpr int SwissNameDictionary::MaxCapacity() {
int const_size =
DataTableStartOffset() + ByteArray::kHeaderSize +
// Size for present and deleted element count at max capacity:
2 * sizeof(uint32_t);
int per_entry_size =
// size of data table entries:
kDataTableEntryCount * kTaggedSize +
// ctrl table entry size:
kOneByteSize +
// PropertyDetails table entry size:
kOneByteSize +
// Enumeration table entry size at maximum capacity:
sizeof(uint32_t);
int result = (FixedArray::kMaxSize - const_size) / per_entry_size;
CONSTEXPR_DCHECK(result <= Smi::kMaxValue);
return result;
}
// static
constexpr int SwissNameDictionary::PrefixOffset() {
return HeapObject::kHeaderSize;
......@@ -298,10 +91,6 @@ constexpr int SwissNameDictionary::PropertyDetailsTableStartOffset(
return CtrlTableStartOffset(capacity) + CtrlTableSize(capacity);
}
ACCESSORS_CHECKED2(SwissNameDictionary, meta_table, ByteArray,
MetaTablePointerOffset(), true,
value.length() >= kMetaTableEnumerationTableStartOffset)
} // namespace internal
} // namespace v8
......
......@@ -8,30 +8,5 @@
#include "src/objects/swiss-name-dictionary-inl.h"
namespace v8 {
namespace internal {
// The largest value we ever have to store in the enumeration table is
// Capacity() - 1. The largest value we ever have to store for the present or
// deleted element count is MaxUsableCapacity(Capacity()). All data in the
// meta table is unsigned. Using this, we verify the values of the constants
// |kMax1ByteMetaTableCapacity| and |kMax2ByteMetaTableCapacity|.
STATIC_ASSERT(SwissNameDictionary::kMax1ByteMetaTableCapacity - 1 <=
std::numeric_limits<uint8_t>::max());
STATIC_ASSERT(SwissNameDictionary::MaxUsableCapacity(
SwissNameDictionary::kMax1ByteMetaTableCapacity) <=
std::numeric_limits<uint8_t>::max());
STATIC_ASSERT(SwissNameDictionary::kMax2ByteMetaTableCapacity - 1 <=
std::numeric_limits<uint16_t>::max());
STATIC_ASSERT(SwissNameDictionary::MaxUsableCapacity(
SwissNameDictionary::kMax2ByteMetaTableCapacity) <=
std::numeric_limits<uint16_t>::max());
template void SwissNameDictionary::Initialize(Isolate* isolate,
ByteArray meta_table,
int capacity);
template void SwissNameDictionary::Initialize(LocalIsolate* isolate,
ByteArray meta_table,
int capacity);
} // namespace internal
namespace internal {} // namespace internal
} // namespace v8
......@@ -40,6 +40,7 @@ namespace internal {
// identity hash: 4 bytes, raw int32_t
// Meta table pointer: kTaggedSize bytes.
// See below for explanation of the meta table.
// For capacity 0, this contains the Smi |kNoMetaTableSentinel| instead.
// Data table:
// For each logical bucket of the hash table, contains the corresponding key
// and value.
......@@ -72,40 +73,16 @@ class SwissNameDictionary : public HeapObject {
public:
using Group = swiss_table::Group;
inline int NumberOfElements();
inline int NumberOfDeletedElements();
inline int Capacity();
inline int UsedCapacity();
template <typename LocalIsolate>
void Initialize(LocalIsolate* isolate, ByteArray meta_table, int capacity);
inline void SetHash(int hash);
inline int Hash();
inline static constexpr bool IsValidCapacity(int capacity);
inline static int CapacityFor(int at_least_space_for);
// Given a capacity, how much of it can we fill before resizing?
inline static constexpr int MaxUsableCapacity(int capacity);
// The maximum allowed capacity for any SwissNameDictionary.
inline static constexpr int MaxCapacity();
// Returns total size in bytes required for a table of given capacity.
inline static constexpr int SizeFor(int capacity);
inline static constexpr int MetaTableSizePerEntryFor(int capacity);
inline static constexpr int MetaTableSizeFor(int capacity);
inline static constexpr int DataTableSize(int capacity);
inline static constexpr int CtrlTableSize(int capacity);
// Indicates that IterateEntries() returns entries ordered.
static constexpr bool kIsOrderedDictionaryType = true;
static const int kGroupWidth = Group::kWidth;
// TODO(v8:11388) This is a temporary placeholder for the actual value, which
// is added here in a follow-up CL.
static const int kGroupWidth = 8;
class BodyDescriptor;
......@@ -116,19 +93,9 @@ class SwissNameDictionary : public HeapObject {
// Defines how many kTaggedSize sized values are associcated which each entry
// in the data table.
static constexpr int kDataTableEntryCount = 2;
static constexpr int kDataTableKeyEntryIndex = 0;
static constexpr int kDataTableValueEntryIndex = kDataTableKeyEntryIndex + 1;
static constexpr int kMetaTableElementCountOffset = 0;
static constexpr int kMetaTableDeletedElementCountOffset = 1;
static constexpr int kMetaTableEnumerationTableStartOffset = 2;
// The maximum capacity of any SwissNameDictionary whose meta table can use 1
// byte per entry.
static constexpr int kMax1ByteMetaTableCapacity = (1 << 8);
// The maximum capacity of any SwissNameDictionary whose meta table can use 2
// bytes per entry.
static constexpr int kMax2ByteMetaTableCapacity = (1 << 16);
inline static constexpr int DataTableSize(int capacity);
inline static constexpr int CtrlTableSize(int capacity);
// TODO(v8:11388) We would like to use Torque-generated constants here, but
// those are currently incorrect.
......@@ -147,28 +114,6 @@ class SwissNameDictionary : public HeapObject {
DECL_PRINTER(SwissNameDictionary)
DECL_CAST(SwissNameDictionary)
OBJECT_CONSTRUCTORS(SwissNameDictionary, HeapObject);
private:
using ctrl_t = swiss_table::ctrl_t;
using Ctrl = swiss_table::Ctrl;
// Not intended for modification, use set_ctrl instead to get correct copying
// of first group.
inline const ctrl_t* CtrlTable();
inline void SetCapacity(int capacity);
inline void SetNumberOfElements(int elements);
inline void SetNumberOfDeletedElements(int deleted_elements);
DECL_ACCESSORS(meta_table, ByteArray)
inline void SetMetaTableField(int field_index, int value);
inline int GetMetaTableField(int field_index);
template <typename T>
inline static void SetMetaTableField(ByteArray meta_table, int field_index,
int value);
template <typename T>
inline static int GetMetaTableField(ByteArray meta_table, int field_index);
};
} // namespace internal
......
......@@ -167,8 +167,6 @@ class Symbol;
V(NameDictionary, empty_property_dictionary, EmptyPropertyDictionary) \
V(OrderedNameDictionary, empty_ordered_property_dictionary, \
EmptyOrderedPropertyDictionary) \
V(SwissNameDictionary, empty_swiss_property_dictionary, \
EmptySwissPropertyDictionary) \
V(InterceptorInfo, noop_interceptor_info, NoOpInterceptorInfo) \
V(WeakFixedArray, empty_weak_fixed_array, EmptyWeakFixedArray) \
V(WeakArrayList, empty_weak_array_list, EmptyWeakArrayList) \
......
......@@ -275,7 +275,6 @@ v8_source_set("cctest_sources") {
"test-smi-lexicographic-compare.cc",
"test-strings.cc",
"test-strtod.cc",
"test-swiss-name-dictionary.cc",
"test-symbols.cc",
"test-thread-termination.cc",
"test-threads.cc",
......
// Copyright 2021 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/objects/swiss-name-dictionary-inl.h"
#include "test/cctest/cctest.h"
namespace v8 {
namespace internal {
namespace test_swiss_hash_table {
TEST(CapacityFor) {
for (int elements = 0; elements <= 32; elements++) {
int capacity = SwissNameDictionary::CapacityFor(elements);
if (elements == 0) {
CHECK_EQ(0, capacity);
} else if (elements <= 3) {
CHECK_EQ(4, capacity);
} else if (elements == 4) {
CHECK_IMPLIES(SwissNameDictionary::kGroupWidth == 8, capacity == 8);
CHECK_IMPLIES(SwissNameDictionary::kGroupWidth == 16, capacity == 4);
} else if (elements <= 7) {
CHECK_EQ(8, capacity);
} else if (elements <= 14) {
CHECK_EQ(16, capacity);
} else if (elements <= 28) {
CHECK_EQ(32, capacity);
} else if (elements <= 32) {
CHECK_EQ(64, capacity);
}
}
}
TEST(MaxUsableCapacity) {
CHECK_EQ(0, SwissNameDictionary::MaxUsableCapacity(0));
CHECK_IMPLIES(SwissNameDictionary::kGroupWidth == 8,
SwissNameDictionary::MaxUsableCapacity(4) == 3);
CHECK_IMPLIES(SwissNameDictionary::kGroupWidth == 16,
SwissNameDictionary::MaxUsableCapacity(4) == 4);
CHECK_EQ(7, SwissNameDictionary::MaxUsableCapacity(8));
CHECK_EQ(14, SwissNameDictionary::MaxUsableCapacity(16));
CHECK_EQ(28, SwissNameDictionary::MaxUsableCapacity(32));
}
TEST(SizeFor) {
int baseline = HeapObject::kHeaderSize +
// prefix:
4 +
// capacity:
4 +
// meta table:
kTaggedSize;
int size_0 = baseline +
// ctrl table:
SwissNameDictionary::kGroupWidth;
int size_4 = baseline +
// data table:
4 * 2 * kTaggedSize +
// ctrl table:
4 + SwissNameDictionary::kGroupWidth +
// property details table:
4;
int size_8 = baseline +
// data table:
8 * 2 * kTaggedSize +
// ctrl table:
8 + SwissNameDictionary::kGroupWidth +
// property details table:
8;
CHECK_EQ(SwissNameDictionary::SizeFor(0), size_0);
CHECK_EQ(SwissNameDictionary::SizeFor(4), size_4);
CHECK_EQ(SwissNameDictionary::SizeFor(8), size_8);
}
} // namespace test_swiss_hash_table
} // namespace internal
} // namespace v8
This diff is collapsed.
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