Commit 9ad4062f authored by Sigurd Schneider's avatar Sigurd Schneider Committed by Commit Bot

[wasm] Rename WasmTableObject field 'elements' to 'entries'

This ensures that the parent class' field 'elements' is not shadowed.

Bug: v8:9194
Change-Id: Ibb53dedc0205cbb4c61e810e2d5822a94843c605
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1593076
Commit-Queue: Sigurd Schneider <sigurds@chromium.org>
Reviewed-by: 's avatarAndreas Haas <ahaas@chromium.org>
Cr-Commit-Position: refs/heads/master@{#61181}
parent afb19c2e
...@@ -1098,7 +1098,7 @@ extern class WasmModuleObject extends JSObject { ...@@ -1098,7 +1098,7 @@ extern class WasmModuleObject extends JSObject {
} }
extern class WasmTableObject extends JSObject { extern class WasmTableObject extends JSObject {
elements: FixedArray; entries: FixedArray;
maximum_length: Smi | HeapNumber | Undefined; maximum_length: Smi | HeapNumber | Undefined;
dispatch_tables: FixedArray; dispatch_tables: FixedArray;
raw_type: Smi; raw_type: Smi;
......
...@@ -3373,10 +3373,10 @@ void WasmGraphBuilder::BoundsCheckTable(uint32_t table_index, Node* entry_index, ...@@ -3373,10 +3373,10 @@ void WasmGraphBuilder::BoundsCheckTable(uint32_t table_index, Node* entry_index,
Node* tables = LOAD_INSTANCE_FIELD(Tables, MachineType::TaggedPointer()); Node* tables = LOAD_INSTANCE_FIELD(Tables, MachineType::TaggedPointer());
Node* table = LOAD_FIXED_ARRAY_SLOT_ANY(tables, table_index); Node* table = LOAD_FIXED_ARRAY_SLOT_ANY(tables, table_index);
int storage_field_size = WasmTableObject::kElementsOffsetEnd - int storage_field_size =
WasmTableObject::kElementsOffset + 1; WasmTableObject::kEntriesOffsetEnd - WasmTableObject::kEntriesOffset + 1;
Node* storage = LOAD_RAW( Node* storage = LOAD_RAW(
table, wasm::ObjectAccess::ToTagged(WasmTableObject::kElementsOffset), table, wasm::ObjectAccess::ToTagged(WasmTableObject::kEntriesOffset),
assert_size(storage_field_size, MachineType::TaggedPointer())); assert_size(storage_field_size, MachineType::TaggedPointer()));
int length_field_size = int length_field_size =
......
...@@ -432,7 +432,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() { ...@@ -432,7 +432,7 @@ MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
auto table_object = handle(WasmTableObject::cast(instance->tables()->get( auto table_object = handle(WasmTableObject::cast(instance->tables()->get(
elem_segment.table_index)), elem_segment.table_index)),
isolate_); isolate_);
size_t table_size = table_object->elements()->length(); size_t table_size = table_object->entries()->length();
if (!IsInBounds(base, elem_segment.entries.size(), table_size)) { if (!IsInBounds(base, elem_segment.entries.size(), table_size)) {
thrower_->LinkError("table initializer is out of bounds"); thrower_->LinkError("table initializer is out of bounds");
return {}; return {};
...@@ -816,7 +816,7 @@ bool InstanceBuilder::ProcessImportedFunction( ...@@ -816,7 +816,7 @@ bool InstanceBuilder::ProcessImportedFunction(
bool InstanceBuilder::InitializeImportedIndirectFunctionTable( bool InstanceBuilder::InitializeImportedIndirectFunctionTable(
Handle<WasmInstanceObject> instance, int import_index, Handle<WasmInstanceObject> instance, int import_index,
Handle<WasmTableObject> table_object) { Handle<WasmTableObject> table_object) {
int imported_table_size = table_object->elements().length(); int imported_table_size = table_object->entries().length();
// Allocate a new dispatch table. // Allocate a new dispatch table.
if (!instance->has_indirect_function_table()) { if (!instance->has_indirect_function_table()) {
WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize( WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
...@@ -871,7 +871,7 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance, ...@@ -871,7 +871,7 @@ bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
instance->tables()->set(table_index, *value); instance->tables()->set(table_index, *value);
auto table_object = Handle<WasmTableObject>::cast(value); auto table_object = Handle<WasmTableObject>::cast(value);
int imported_table_size = table_object->elements().length(); int imported_table_size = table_object->entries().length();
if (imported_table_size < static_cast<int>(table.initial_size)) { if (imported_table_size < static_cast<int>(table.initial_size)) {
thrower_->LinkError("table import %d is smaller than initial %d, got %u", thrower_->LinkError("table import %d is smaller than initial %d, got %u",
import_index, table.initial_size, imported_table_size); import_index, table.initial_size, imported_table_size);
...@@ -1495,7 +1495,7 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance, ...@@ -1495,7 +1495,7 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
// for both instantiation and in the implementation of the table.init // for both instantiation and in the implementation of the table.init
// instruction. // instruction.
bool ok = bool ok =
ClampToBounds<size_t>(dst, &count, table_object->elements()->length()); ClampToBounds<size_t>(dst, &count, table_object->entries()->length());
// Use & instead of && so the clamp is not short-circuited. // Use & instead of && so the clamp is not short-circuited.
ok &= ClampToBounds<size_t>(src, &count, elem_segment.entries.size()); ok &= ClampToBounds<size_t>(src, &count, elem_segment.entries.size());
...@@ -1528,8 +1528,8 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance, ...@@ -1528,8 +1528,8 @@ bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
WasmTableObject::SetFunctionTablePlaceholder( WasmTableObject::SetFunctionTablePlaceholder(
isolate, table_object, entry_index, instance, func_index); isolate, table_object, entry_index, instance, func_index);
} else { } else {
table_object->elements()->set(entry_index, table_object->entries()->set(entry_index,
*wasm_exported_function.ToHandleChecked()); *wasm_exported_function.ToHandleChecked());
} }
// UpdateDispatchTables() updates all other dispatch tables, since // UpdateDispatchTables() updates all other dispatch tables, since
// we have not yet added the dispatch table we are currently building. // we have not yet added the dispatch table we are currently building.
......
...@@ -117,7 +117,7 @@ bool WasmModuleObject::is_asm_js() { ...@@ -117,7 +117,7 @@ bool WasmModuleObject::is_asm_js() {
} }
// WasmTableObject // WasmTableObject
ACCESSORS(WasmTableObject, elements, FixedArray, kElementsOffset) ACCESSORS(WasmTableObject, entries, FixedArray, kEntriesOffset)
ACCESSORS(WasmTableObject, maximum_length, Object, kMaximumLengthOffset) ACCESSORS(WasmTableObject, maximum_length, Object, kMaximumLengthOffset)
ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset) ACCESSORS(WasmTableObject, dispatch_tables, FixedArray, kDispatchTablesOffset)
SMI_ACCESSORS(WasmTableObject, raw_type, kRawTypeOffset) SMI_ACCESSORS(WasmTableObject, raw_type, kRawTypeOffset)
...@@ -322,7 +322,7 @@ OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entry_map, Managed<wasm::SignatureMap>, ...@@ -322,7 +322,7 @@ OPTIONAL_ACCESSORS(WasmDebugInfo, c_wasm_entry_map, Managed<wasm::SignatureMap>,
#undef WRITE_PRIMITIVE_FIELD #undef WRITE_PRIMITIVE_FIELD
#undef PRIMITIVE_ACCESSORS #undef PRIMITIVE_ACCESSORS
uint32_t WasmTableObject::current_length() { return elements()->length(); } uint32_t WasmTableObject::current_length() { return entries()->length(); }
wasm::ValueType WasmTableObject::type() { wasm::ValueType WasmTableObject::type() {
return static_cast<wasm::ValueType>(raw_type()); return static_cast<wasm::ValueType>(raw_type());
......
...@@ -782,7 +782,7 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, ...@@ -782,7 +782,7 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate,
wasm::ValueType type, wasm::ValueType type,
uint32_t initial, bool has_maximum, uint32_t initial, bool has_maximum,
uint32_t maximum, uint32_t maximum,
Handle<FixedArray>* elements) { Handle<FixedArray>* entries) {
Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(initial); Handle<FixedArray> backing_store = isolate->factory()->NewFixedArray(initial);
Object null = ReadOnlyRoots(isolate).null_value(); Object null = ReadOnlyRoots(isolate).null_value();
for (int i = 0; i < static_cast<int>(initial); ++i) { for (int i = 0; i < static_cast<int>(initial); ++i) {
...@@ -795,7 +795,7 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, ...@@ -795,7 +795,7 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate,
isolate->factory()->NewJSObject(table_ctor)); isolate->factory()->NewJSObject(table_ctor));
table_obj->set_raw_type(static_cast<int>(type)); table_obj->set_raw_type(static_cast<int>(type));
table_obj->set_elements(*backing_store); table_obj->set_entries(*backing_store);
Handle<Object> max; Handle<Object> max;
if (has_maximum) { if (has_maximum) {
max = isolate->factory()->NewNumberFromUint(maximum); max = isolate->factory()->NewNumberFromUint(maximum);
...@@ -805,8 +805,8 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate, ...@@ -805,8 +805,8 @@ Handle<WasmTableObject> WasmTableObject::New(Isolate* isolate,
table_obj->set_maximum_length(*max); table_obj->set_maximum_length(*max);
table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array()); table_obj->set_dispatch_tables(ReadOnlyRoots(isolate).empty_fixed_array());
if (elements != nullptr) { if (entries != nullptr) {
*elements = backing_store; *entries = backing_store;
} }
return Handle<WasmTableObject>::cast(table_obj); return Handle<WasmTableObject>::cast(table_obj);
} }
...@@ -850,9 +850,9 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -850,9 +850,9 @@ int WasmTableObject::Grow(Isolate* isolate, Handle<WasmTableObject> table,
uint32_t new_size = old_size + count; uint32_t new_size = old_size + count;
auto new_store = isolate->factory()->CopyFixedArrayAndGrow( auto new_store = isolate->factory()->CopyFixedArrayAndGrow(
handle(table->elements(), isolate), count); handle(table->entries(), isolate), count);
table->set_elements(*new_store, WriteBarrierMode::UPDATE_WRITE_BARRIER); table->set_entries(*new_store, WriteBarrierMode::UPDATE_WRITE_BARRIER);
Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate); Handle<FixedArray> dispatch_tables(table->dispatch_tables(), isolate);
DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements); DCHECK_EQ(0, dispatch_tables->length() % kDispatchTableNumElements);
...@@ -882,41 +882,41 @@ bool WasmTableObject::IsInBounds(Isolate* isolate, ...@@ -882,41 +882,41 @@ bool WasmTableObject::IsInBounds(Isolate* isolate,
uint32_t entry_index) { uint32_t entry_index) {
return (entry_index < return (entry_index <
static_cast<uint32_t>(std::numeric_limits<int>::max()) && static_cast<uint32_t>(std::numeric_limits<int>::max()) &&
static_cast<int>(entry_index) < table->elements()->length()); static_cast<int>(entry_index) < table->entries()->length());
} }
bool WasmTableObject::IsValidElement(Isolate* isolate, bool WasmTableObject::IsValidElement(Isolate* isolate,
Handle<WasmTableObject> table, Handle<WasmTableObject> table,
Handle<Object> element) { Handle<Object> entry) {
// Anyref tables take everything. // Anyref tables take everything.
if (table->type() == wasm::kWasmAnyRef) return true; if (table->type() == wasm::kWasmAnyRef) return true;
// Anyfunc tables can store {null} or {WasmExportedFunction} objects. // Anyfunc tables can store {null} or {WasmExportedFunction} objects.
if (element->IsNull(isolate)) return true; if (entry->IsNull(isolate)) return true;
return WasmExportedFunction::IsWasmExportedFunction(*element); return WasmExportedFunction::IsWasmExportedFunction(*entry);
} }
void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table, void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
uint32_t index, Handle<Object> element) { uint32_t index, Handle<Object> entry) {
// Callers need to perform bounds checks, type check, and error handling. // Callers need to perform bounds checks, type check, and error handling.
DCHECK(IsInBounds(isolate, table, index)); DCHECK(IsInBounds(isolate, table, index));
DCHECK(IsValidElement(isolate, table, element)); DCHECK(IsValidElement(isolate, table, entry));
Handle<FixedArray> elements(table->elements(), isolate); Handle<FixedArray> entries(table->entries(), isolate);
// The FixedArray is addressed with int's. // The FixedArray is addressed with int's.
int entry_index = static_cast<int>(index); int entry_index = static_cast<int>(index);
if (table->type() == wasm::kWasmAnyRef) { if (table->type() == wasm::kWasmAnyRef) {
elements->set(entry_index, *element); entries->set(entry_index, *entry);
return; return;
} }
if (element->IsNull(isolate)) { if (entry->IsNull(isolate)) {
ClearDispatchTables(isolate, table, entry_index); // Degenerate case. ClearDispatchTables(isolate, table, entry_index); // Degenerate case.
elements->set(entry_index, ReadOnlyRoots(isolate).null_value()); entries->set(entry_index, ReadOnlyRoots(isolate).null_value());
return; return;
} }
DCHECK(WasmExportedFunction::IsWasmExportedFunction(*element)); DCHECK(WasmExportedFunction::IsWasmExportedFunction(*entry));
auto exported_function = Handle<WasmExportedFunction>::cast(element); auto exported_function = Handle<WasmExportedFunction>::cast(entry);
Handle<WasmInstanceObject> target_instance(exported_function->instance(), Handle<WasmInstanceObject> target_instance(exported_function->instance(),
isolate); isolate);
int func_index = exported_function->function_index(); int func_index = exported_function->function_index();
...@@ -926,47 +926,46 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table, ...@@ -926,47 +926,46 @@ void WasmTableObject::Set(Isolate* isolate, Handle<WasmTableObject> table,
UpdateDispatchTables(isolate, table, entry_index, wasm_function->sig, UpdateDispatchTables(isolate, table, entry_index, wasm_function->sig,
handle(exported_function->instance(), isolate), handle(exported_function->instance(), isolate),
func_index); func_index);
elements->set(entry_index, *element); entries->set(entry_index, *entry);
} }
Handle<Object> WasmTableObject::Get(Isolate* isolate, Handle<Object> WasmTableObject::Get(Isolate* isolate,
Handle<WasmTableObject> table, Handle<WasmTableObject> table,
uint32_t index) { uint32_t index) {
Handle<FixedArray> elements(table->elements(), isolate); Handle<FixedArray> entries(table->entries(), isolate);
// Callers need to perform bounds checks and error handling. // Callers need to perform bounds checks and error handling.
DCHECK(IsInBounds(isolate, table, index)); DCHECK(IsInBounds(isolate, table, index));
// The FixedArray is addressed with int's. // The FixedArray is addressed with int's.
int entry_index = static_cast<int>(index); int entry_index = static_cast<int>(index);
Handle<Object> element(elements->get(entry_index), isolate); Handle<Object> entry(entries->get(entry_index), isolate);
// First we handle the easy anyref table case. // First we handle the easy anyref table case.
if (table->type() == wasm::kWasmAnyRef) return element; if (table->type() == wasm::kWasmAnyRef) return entry;
// Now we handle the anyfunc case. // Now we handle the anyfunc case.
if (WasmExportedFunction::IsWasmExportedFunction(*element)) { if (WasmExportedFunction::IsWasmExportedFunction(*entry)) {
return element; return entry;
} }
if (element->IsNull(isolate)) { if (entry->IsNull(isolate)) {
return element; return entry;
} }
// {element} is not a valid entry in the table. It has to be a placeholder // {entry} is not a valid entry in the table. It has to be a placeholder
// for lazy initialization. // for lazy initialization.
Handle<Tuple2> tuple = Handle<Tuple2>::cast(element); Handle<Tuple2> tuple = Handle<Tuple2>::cast(entry);
auto instance = handle(WasmInstanceObject::cast(tuple->value1()), isolate); auto instance = handle(WasmInstanceObject::cast(tuple->value1()), isolate);
int function_index = Smi::cast(tuple->value2()).value(); int function_index = Smi::cast(tuple->value2()).value();
// Check if we already compiled a wrapper for the function but did not store // Check if we already compiled a wrapper for the function but did not store
// it in the table slot yet. // it in the table slot yet.
MaybeHandle<Object> maybe_element = MaybeHandle<Object> maybe_entry = WasmInstanceObject::GetWasmExportedFunction(
WasmInstanceObject::GetWasmExportedFunction(isolate, instance, isolate, instance, function_index);
function_index); if (maybe_entry.ToHandle(&entry)) {
if (maybe_element.ToHandle(&element)) { entries->set(entry_index, *entry);
elements->set(entry_index, *element); return entry;
return element;
} }
const WasmModule* module = instance->module_object()->module(); const WasmModule* module = instance->module_object()->module();
...@@ -984,7 +983,7 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate, ...@@ -984,7 +983,7 @@ Handle<Object> WasmTableObject::Get(Isolate* isolate,
isolate, instance, function_name, function_index, isolate, instance, function_name, function_index,
static_cast<int>(function.sig->parameter_count()), wrapper_code); static_cast<int>(function.sig->parameter_count()), wrapper_code);
elements->set(entry_index, *result); entries->set(entry_index, *result);
WasmInstanceObject::SetWasmExportedFunction(isolate, instance, function_index, WasmInstanceObject::SetWasmExportedFunction(isolate, instance, function_index,
result); result);
return result; return result;
...@@ -1044,7 +1043,7 @@ void WasmTableObject::SetFunctionTablePlaceholder( ...@@ -1044,7 +1043,7 @@ void WasmTableObject::SetFunctionTablePlaceholder(
Handle<Tuple2> tuple = isolate->factory()->NewTuple2( Handle<Tuple2> tuple = isolate->factory()->NewTuple2(
instance, Handle<Smi>(Smi::FromInt(func_index), isolate), instance, Handle<Smi>(Smi::FromInt(func_index), isolate),
AllocationType::kYoung); AllocationType::kYoung);
table->elements()->set(entry_index, *tuple); table->entries()->set(entry_index, *tuple);
} }
void WasmTableObject::GetFunctionTableEntry( void WasmTableObject::GetFunctionTableEntry(
...@@ -1052,10 +1051,10 @@ void WasmTableObject::GetFunctionTableEntry( ...@@ -1052,10 +1051,10 @@ void WasmTableObject::GetFunctionTableEntry(
bool* is_valid, bool* is_null, MaybeHandle<WasmInstanceObject>* instance, bool* is_valid, bool* is_null, MaybeHandle<WasmInstanceObject>* instance,
int* function_index) { int* function_index) {
DCHECK_EQ(table->type(), wasm::kWasmAnyFunc); DCHECK_EQ(table->type(), wasm::kWasmAnyFunc);
DCHECK_LT(entry_index, table->elements()->length()); DCHECK_LT(entry_index, table->entries()->length());
// We initialize {is_valid} with {true}. We may change it later. // We initialize {is_valid} with {true}. We may change it later.
*is_valid = true; *is_valid = true;
Handle<Object> element(table->elements()->get(entry_index), isolate); Handle<Object> element(table->entries()->get(entry_index), isolate);
*is_null = element->IsNull(isolate); *is_null = element->IsNull(isolate);
if (*is_null) return; if (*is_null) return;
...@@ -1693,12 +1692,12 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate, ...@@ -1693,12 +1692,12 @@ bool WasmInstanceObject::CopyTableEntries(Isolate* isolate,
WasmTableObject::cast(instance->tables()->get(table_src_index)), isolate); WasmTableObject::cast(instance->tables()->get(table_src_index)), isolate);
if (copy_backward) { if (copy_backward) {
for (uint32_t i = count; i > 0; i--) { for (uint32_t i = count; i > 0; i--) {
dst_table->elements()->set(dst + i - 1, dst_table->entries()->set(dst + i - 1,
src_table->elements()->get(src + i - 1)); src_table->entries()->get(src + i - 1));
} }
} else { } else {
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
dst_table->elements()->set(dst + i, src_table->elements()->get(src + i)); dst_table->entries()->set(dst + i, src_table->entries()->get(src + i));
} }
} }
return ok; return ok;
......
...@@ -247,7 +247,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject { ...@@ -247,7 +247,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject {
public: public:
DECL_CAST(WasmTableObject) DECL_CAST(WasmTableObject)
DECL_ACCESSORS(elements, FixedArray) DECL_ACCESSORS(entries, FixedArray)
// TODO(titzer): introduce DECL_I64_ACCESSORS macro // TODO(titzer): introduce DECL_I64_ACCESSORS macro
DECL_ACCESSORS(maximum_length, Object) DECL_ACCESSORS(maximum_length, Object)
DECL_ACCESSORS(dispatch_tables, FixedArray) DECL_ACCESSORS(dispatch_tables, FixedArray)
...@@ -269,7 +269,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject { ...@@ -269,7 +269,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject {
static Handle<WasmTableObject> New(Isolate* isolate, wasm::ValueType type, static Handle<WasmTableObject> New(Isolate* isolate, wasm::ValueType type,
uint32_t initial, bool has_maximum, uint32_t initial, bool has_maximum,
uint32_t maximum, uint32_t maximum,
Handle<FixedArray>* elements); Handle<FixedArray>* entries);
static void AddDispatchTable(Isolate* isolate, Handle<WasmTableObject> table, static void AddDispatchTable(Isolate* isolate, Handle<WasmTableObject> table,
Handle<WasmInstanceObject> instance, Handle<WasmInstanceObject> instance,
...@@ -282,7 +282,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject { ...@@ -282,7 +282,7 @@ class V8_EXPORT_PRIVATE WasmTableObject : public JSObject {
Handle<Object> entry); Handle<Object> entry);
static void Set(Isolate* isolate, Handle<WasmTableObject> table, static void Set(Isolate* isolate, Handle<WasmTableObject> table,
uint32_t index, Handle<Object> element); uint32_t index, Handle<Object> entry);
static Handle<Object> Get(Isolate* isolate, Handle<WasmTableObject> table, static Handle<Object> Get(Isolate* isolate, Handle<WasmTableObject> table,
uint32_t index); uint32_t index);
......
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