-
Notifications
You must be signed in to change notification settings - Fork 172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Store ref in ArrayMixed #6565
Store ref in ArrayMixed #6565
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,7 @@ ArrayMixed::ArrayMixed(Allocator& a) | |
, m_ints(a) | ||
, m_int_pairs(a) | ||
, m_strings(a) | ||
, m_refs(a) | ||
{ | ||
m_composite.set_parent(this, payload_idx_type); | ||
} | ||
|
@@ -45,6 +46,7 @@ void ArrayMixed::init_from_mem(MemRef mem) noexcept | |
m_ints.detach(); | ||
m_int_pairs.detach(); | ||
m_strings.detach(); | ||
m_refs.detach(); | ||
} | ||
|
||
void ArrayMixed::add(Mixed value) | ||
|
@@ -63,7 +65,15 @@ void ArrayMixed::set(size_t ndx, Mixed value) | |
set_null(ndx); | ||
return; | ||
} | ||
erase_linked_payload(ndx); | ||
auto old_type = get_type(ndx); | ||
// If we replace a collections ref value with one of the | ||
// same type, then it is just an update of of the | ||
// ref stored in the parent. If the new type is a different | ||
// type then it means that we are overwriting a collection | ||
// with some other value and hence the collection must be | ||
// destroyed. | ||
bool destroy_collection = old_type != value.get_type(); | ||
erase_linked_payload(ndx, destroy_collection); | ||
m_composite.set(ndx, store(value)); | ||
} | ||
|
||
|
@@ -80,7 +90,7 @@ void ArrayMixed::set_null(size_t ndx) | |
{ | ||
auto val = m_composite.get(ndx); | ||
if (val) { | ||
erase_linked_payload(ndx); | ||
erase_linked_payload(ndx, true); | ||
m_composite.set(ndx, 0); | ||
} | ||
} | ||
|
@@ -163,6 +173,10 @@ Mixed ArrayMixed::get(size_t ndx) const | |
return Mixed(UUID(bytes)); | ||
} | ||
default: | ||
if (size_t((val & s_payload_idx_mask) >> s_payload_idx_shift) == payload_idx_ref) { | ||
ensure_ref_array(); | ||
return Mixed(m_refs.get(payload_ndx), CollectionType(int(type))); | ||
} | ||
break; | ||
} | ||
} | ||
|
@@ -176,25 +190,19 @@ void ArrayMixed::clear() | |
m_ints.destroy(); | ||
m_int_pairs.destroy(); | ||
m_strings.destroy(); | ||
m_refs.destroy_deep(); | ||
Array::set(payload_idx_int, 0); | ||
Array::set(payload_idx_pair, 0); | ||
Array::set(payload_idx_str, 0); | ||
Array::set(payload_idx_ref, 0); | ||
} | ||
|
||
void ArrayMixed::erase(size_t ndx) | ||
{ | ||
erase_linked_payload(ndx); | ||
erase_linked_payload(ndx, true); | ||
m_composite.erase(ndx); | ||
} | ||
|
||
void ArrayMixed::truncate_and_destroy_children(size_t ndx) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why removing this? Truncating seems a reasonable thing to... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not used |
||
{ | ||
for (size_t i = size(); i > ndx; i--) { | ||
erase_linked_payload(i - 1); | ||
} | ||
m_composite.truncate(ndx); | ||
} | ||
|
||
void ArrayMixed::move(ArrayMixed& dst, size_t ndx) | ||
{ | ||
auto sz = size(); | ||
|
@@ -204,7 +212,7 @@ void ArrayMixed::move(ArrayMixed& dst, size_t ndx) | |
dst.add(val); | ||
} | ||
while (i > ndx) { | ||
erase_linked_payload(--i); | ||
erase_linked_payload(--i, false); | ||
} | ||
m_composite.truncate(ndx); | ||
} | ||
|
@@ -239,7 +247,7 @@ void ArrayMixed::ensure_array_accessor(Array& arr, size_t ndx_in_parent) const | |
arr.init_from_ref(ref); | ||
} | ||
else { | ||
arr.create(type_Normal); | ||
arr.create(ndx_in_parent == payload_idx_ref ? type_HasRefs : type_Normal); | ||
arr.update_parent(); | ||
} | ||
} | ||
|
@@ -270,6 +278,14 @@ void ArrayMixed::ensure_string_array() const | |
} | ||
} | ||
|
||
void ArrayMixed::ensure_ref_array() const | ||
{ | ||
while (Array::size() < payload_idx_ref + 1) { | ||
const_cast<ArrayMixed*>(this)->Array::add(0); | ||
} | ||
ensure_array_accessor(m_refs, payload_idx_ref); | ||
} | ||
|
||
void ArrayMixed::replace_index(size_t old_ndx, size_t new_ndx, size_t payload_arr_index) | ||
{ | ||
if (old_ndx != new_ndx) { | ||
|
@@ -285,7 +301,7 @@ void ArrayMixed::replace_index(size_t old_ndx, size_t new_ndx, size_t payload_ar | |
} | ||
} | ||
|
||
void ArrayMixed::erase_linked_payload(size_t ndx) | ||
void ArrayMixed::erase_linked_payload(size_t ndx, bool free_linked_arrays) | ||
{ | ||
auto val = m_composite.get(ndx); | ||
auto payload_arr_index = size_t((val & s_payload_idx_mask) >> s_payload_idx_shift); | ||
|
@@ -330,6 +346,19 @@ void ArrayMixed::erase_linked_payload(size_t ndx) | |
m_int_pairs.truncate(last_ndx); | ||
break; | ||
} | ||
case payload_idx_ref: { | ||
ensure_ref_array(); | ||
last_ndx = m_refs.size() - 1; | ||
auto old_ref = m_refs.get(erase_ndx); | ||
if (erase_ndx != last_ndx) { | ||
m_refs.set(erase_ndx, m_refs.get(last_ndx)); | ||
replace_index(last_ndx, erase_ndx, payload_arr_index); | ||
} | ||
m_refs.erase(last_ndx); | ||
if (old_ref && free_linked_arrays) | ||
Array::destroy_deep(old_ref, m_composite.get_alloc()); | ||
break; | ||
} | ||
default: | ||
break; | ||
} | ||
|
@@ -440,7 +469,11 @@ int64_t ArrayMixed::store(const Mixed& value) | |
break; | ||
} | ||
default: | ||
val = 0; | ||
REALM_ASSERT(type == type_List || type == type_Dictionary || type == type_Set); | ||
ensure_ref_array(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd prefer not to assume that if we don't match any type, then it is a collection. Although it is impossible to end up in such scenario, since we control the types in mixed, it is easy to make a mistake if you don't know the code very well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added an assertion. |
||
size_t ndx = m_refs.size(); | ||
m_refs.add(value.get_ref()); | ||
val = int64_t(ndx << s_data_shift) | (payload_idx_ref << s_payload_idx_shift); | ||
break; | ||
} | ||
return val + int(type) + 1; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing to do with this PR, but why we don't clear also
payload_idx_type
andpayload_idx_size
here?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure what you mean.