[ENOMEM] handle allocation failures during page compaction.
This commit is contained in:
parent
a4c3732f59
commit
0ba73e980c
@ -389,6 +389,11 @@ struct hb_set_t
|
|||||||
{
|
{
|
||||||
if (ds <= de)
|
if (ds <= de)
|
||||||
{
|
{
|
||||||
|
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||||
|
// before attempting to rewrite the page map.
|
||||||
|
hb_vector_t<uint32_t> compact_workspace;
|
||||||
|
if (unlikely (!allocate_compact_workspace (&compact_workspace))) return;
|
||||||
|
|
||||||
unsigned int write_index = 0;
|
unsigned int write_index = 0;
|
||||||
for (unsigned int i = 0; i < page_map.length; i++)
|
for (unsigned int i = 0; i < page_map.length; i++)
|
||||||
{
|
{
|
||||||
@ -396,11 +401,12 @@ struct hb_set_t
|
|||||||
if (m < ds || de < m)
|
if (m < ds || de < m)
|
||||||
page_map[write_index++] = page_map[i];
|
page_map[write_index++] = page_map[i];
|
||||||
}
|
}
|
||||||
compact (write_index);
|
compact (&compact_workspace, write_index);
|
||||||
resize (write_index);
|
resize (write_index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
void del_range (hb_codepoint_t a, hb_codepoint_t b)
|
||||||
{
|
{
|
||||||
@ -512,18 +518,35 @@ struct hb_set_t
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compact (unsigned int length)
|
bool allocate_compact_workspace(hb_vector_t<uint32_t>* workspace)
|
||||||
{
|
{
|
||||||
hb_vector_t<uint32_t> old_index_to_page_map_index;
|
if (unlikely(!workspace->resize (pages.length)))
|
||||||
// TODO(grieger): need to handle resize failure here.
|
{
|
||||||
old_index_to_page_map_index.resize(pages.length);
|
successful = false;
|
||||||
for (uint32_t i = 0; i < old_index_to_page_map_index.length; i++)
|
return false;
|
||||||
old_index_to_page_map_index[i] = 0xFFFFFFFF;
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* workspace should be a pre-sized vector allocated to hold at exactly pages.length
|
||||||
|
* elements.
|
||||||
|
*/
|
||||||
|
void compact (hb_vector_t<uint32_t>* workspace,
|
||||||
|
unsigned int length)
|
||||||
|
{
|
||||||
|
assert(workspace->length == pages.length);
|
||||||
|
hb_vector_t<uint32_t>* old_index_to_page_map_index = workspace;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < old_index_to_page_map_index->length; i++)
|
||||||
|
(*old_index_to_page_map_index)[i] = 0xFFFFFFFF;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < length; i++)
|
for (uint32_t i = 0; i < length; i++)
|
||||||
old_index_to_page_map_index[page_map[i].index] = i;
|
(*old_index_to_page_map_index)[page_map[i].index] = i;
|
||||||
|
|
||||||
compact_pages (old_index_to_page_map_index);
|
compact_pages (*old_index_to_page_map_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void compact_pages (const hb_vector_t<uint32_t>& old_index_to_page_map_index)
|
void compact_pages (const hb_vector_t<uint32_t>& old_index_to_page_map_index)
|
||||||
@ -555,6 +578,12 @@ struct hb_set_t
|
|||||||
unsigned int count = 0, newCount = 0;
|
unsigned int count = 0, newCount = 0;
|
||||||
unsigned int a = 0, b = 0;
|
unsigned int a = 0, b = 0;
|
||||||
unsigned int write_index = 0;
|
unsigned int write_index = 0;
|
||||||
|
|
||||||
|
// Pre-allocate the workspace that compact() will need so we can bail on allocation failure
|
||||||
|
// before attempting to rewrite the page map.
|
||||||
|
hb_vector_t<uint32_t> compact_workspace;
|
||||||
|
if (!Op::passthru_left && unlikely (!allocate_compact_workspace (&compact_workspace))) return;
|
||||||
|
|
||||||
for (; a < na && b < nb; )
|
for (; a < na && b < nb; )
|
||||||
{
|
{
|
||||||
if (page_map[a].major == other->page_map[b].major)
|
if (page_map[a].major == other->page_map[b].major)
|
||||||
@ -596,11 +625,10 @@ struct hb_set_t
|
|||||||
{
|
{
|
||||||
na = write_index;
|
na = write_index;
|
||||||
next_page = write_index;
|
next_page = write_index;
|
||||||
compact (write_index);
|
compact (&compact_workspace, write_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!resize (count))
|
if (!resize (count))
|
||||||
// TODO(grieger): does this leave us in an invalid state?
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
newCount = count;
|
newCount = count;
|
||||||
|
Loading…
Reference in New Issue
Block a user