-
Notifications
You must be signed in to change notification settings - Fork 683
Array.prototype.sort() should sort in place. #335
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
Conversation
|
||
if (ecma_is_value_undefined (values_buffer[index])) | ||
{ | ||
ECMA_TRY_CATCH (del_value, ecma_op_object_delete (obj_p, index_string_p, true), ret_value); |
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.
What is the reason to have empty TRY/FINALIZE block?
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.
In my opinion this look cleaner than using if/else to check/free.
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.
Also, this is current common style.
Maybe, this could be encoded in a more convenient way. I think, in the case it is better to change all the places at once.
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.
I see
No other questions. Good to me. |
|
||
// Sorting sparse array | ||
var array = [1,,2,,3,,4,undefined,5]; | ||
var expected = [1,2,3,4,5,,,,]; |
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.
Seems that expected.length
is 8, and array.length
is 9. Maybe, it is incorrect.
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.
Could you, please, check whether conditions in the following loop should be true
?
for (i = 0; i < array.length; i++)
{
assert (expected.hasOwnProperty (i) == array.hasOwnProperty (i));
}
Currently, some of them are not true
.
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.
expected
has 5 numbers, and then 4 empty places after those, that should be 9. Nevertheless, there's an assert for this in line 57
below.
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.
The following test case print 8
:
var expected = [1,2,3,4,5,,,,];
print (expected.length);
By the way, assertion at line 57 is incorrect, as it performs assignment, instead of comparison.
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.
The issue with hasOwnProperty
is related with #319, in particular, the problem is that we currently can't distinguish between "empty" values that are unset, and explicitly defined undefined
values, currently both are undefined
. If we do it by the standard, then empty values should be deleted, but currently that also deletes the set undefined
value.
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.
My mistake, let me re-check.
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.
To distinguish between undefined properties and properties with undefined values, we can use ecma_op_object_get_property (...) != NULL
.
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.
Yes, initially. But we copy the values into a local array, so that we can sort them. When we do this both will become undefined, since we don't have a way to represent them differently.
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.
I think, this is because values are copied to simple array of values without additional information.
It seems that the way also can lead to out-of-memory in case of sparse arrays. For example:
a = new Array ();
a[100000] = 1;
a[1000000] = 2;
a.sort ();
Is it correct? If so, maybe we should use some another way of intermediate value storage during operation of sort
.
1d1fb9f
to
0231028
Compare
@ruben-ayrapetyan , I've updated the PR. We no longer copy undefined properties. |
uint32_t copied_num = 0; | ||
|
||
/* Copy unsorted array into a native c array. */ | ||
for (uint32_t index = 0; index < len && ecma_is_completion_value_empty (ret_value); index++) | ||
{ | ||
ecma_string_t *index_string_p = ecma_new_ecma_string_from_uint32 (index); | ||
ECMA_TRY_CATCH (index_value, ecma_op_object_get (obj_p, index_string_p), ret_value); | ||
if (ecma_op_object_get_property (obj_p, index_string_p) != NULL) |
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.
The test would be executed too long, because of iteration over all values in [0.. len)
:
var a = new Array ();
a[100000] = 1;
a[1000000] = 2;
a.sort ();
There are also another places with the issue. For example, ecma_op_array_object_define_own_property
.
Could you, please, raise an issue about this, with references to known places with the issue, and add FIXME
to the code part, referencing the issue?
After raising the issue and adding |
@dbatyai, could you, please, rebase to master? |
0231028
to
5fb673e
Compare
@ruben-ayrapetyan, rebased. |
@dbatyai, thank you! |
@@ -962,6 +962,9 @@ ecma_builtin_array_prototype_object_index_of (ecma_value_t this_arg, /**< this a | |||
{ | |||
JERRY_ASSERT (from_idx < len); | |||
|
|||
/* FIXME: Iterating over the whole lenght is unnecessary in case of sparse arrays, | |||
* and could take a long time if len is large. We should only iterate | |||
* over defined array indexes. */ |
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.
I think there is a TODO () or similar macro somewhere.
I agree that the real index based sorting should be replaced by a virtual index based sorting. What is the sorting algorithm? Quick-sort? |
After fixing |
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
5fb673e
to
65b2361
Compare
@zherczeg, current algorithm is heapsort. |
65b2361
to
6331555
Compare
@ruben-ayrapetyan, please re-check |
6331555
to
92cde9d
Compare
@ruben-ayrapetyan, @zherczeg, I've updated the PR. |
ECMA_FINALIZE (del_value); | ||
} | ||
|
||
property_p = next_prop; |
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.
The code infitely loops for the following example:
Array.prototype.sort();
Reason is that property_p
is not updated for internal properties.
It's better to put property_p = next_prop
into for
's increment section.
After fixing, the changes would look good to me. |
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com
92cde9d
to
eca1ec4
Compare
Looks good to me |
LGTM |
I'll merge. |
Merged a2c6663 |
Array.prototype.sort() should sort in place instead of creating a new Array with the sorted elements.
JerryScript-DCO-1.0-Signed-off-by: Dániel Bátyai dbatyai.u-szeged@partner.samsung.com