Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Optimize compilation of large literal arrays #9721

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

Merged
merged 2 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions benchmark/array_large_literal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
prelude: |
def def_array(size)
Object.class_eval(<<-END)
def array_#{size}
x = 1
[#{(['x'] * size).join(',')}]
end
END
end
def_array(100)
def_array(1000)
def_array(10000)
def_array(100000)
benchmark:
array_100: array_100
array_1000: array_1000
array_10000: array_10000
array_100000: array_100000

27 changes: 14 additions & 13 deletions compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4815,8 +4815,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
*
* [x1,x2,...,x10000] =>
* push x1 ; push x2 ; ...; push x256; newarray 256;
* push x257; push x258; ...; push x512; newarray 256; concatarray;
* push x513; push x514; ...; push x768; newarray 256; concatarray;
* push x257; push x258; ...; push x512; pushtoarray 256;
* push x513; push x514; ...; push x768; pushtoarray 256;
* ...
*
* - Long subarray can be optimized by pre-allocating a hidden array.
Expand All @@ -4826,8 +4826,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
*
* [x, 1,2,3,...,100, z] =>
* push x; newarray 1;
* putobject [1,2,3,...,100] (<- hidden array); concatarray;
* push z; newarray 1; concatarray
* putobject [1,2,3,...,100] (<- hidden array); concattoarray;
* push z; pushtoarray 1;
*
* - If the last element is a keyword, newarraykwsplat should be emitted
* to check and remove empty keyword arguments hash from array.
Expand All @@ -4842,11 +4842,11 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
int stack_len = 0;
int first_chunk = 1;

/* Convert pushed elements to an array, and concatarray if needed */
#define FLUSH_CHUNK(newarrayinsn) \
/* Either create a new array, or push to the existing array */
#define FLUSH_CHUNK \
if (stack_len) { \
ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \
if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \
if (first_chunk) ADD_INSN1(ret, line_node, newarray, INT2FIX(stack_len)); \
else ADD_INSN1(ret, line_node, pushtoarray, INT2FIX(stack_len)); \
first_chunk = stack_len = 0; \
}

Expand All @@ -4870,14 +4870,14 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop
OBJ_FREEZE(ary);

/* Emit optimized code */
FLUSH_CHUNK(newarray);
FLUSH_CHUNK;
if (first_chunk) {
ADD_INSN1(ret, line_node, duparray, ary);
first_chunk = 0;
}
else {
ADD_INSN1(ret, line_node, putobject, ary);
ADD_INSN(ret, line_node, concatarray);
ADD_INSN(ret, line_node, concattoarray);
}
RB_OBJ_WRITTEN(iseq, Qundef, ary);
}
Expand All @@ -4894,16 +4894,17 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop

if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) {
/* Reached the end, and the last element is a keyword */
FLUSH_CHUNK(newarraykwsplat);
ADD_INSN1(ret, line_node, newarraykwsplat, INT2FIX(stack_len));
if (!first_chunk) ADD_INSN(ret, line_node, concattoarray);
return 1;
}

/* If there are many pushed elements, flush them to avoid stack overflow */
if (stack_len >= max_stack_len) FLUSH_CHUNK(newarray);
if (stack_len >= max_stack_len) FLUSH_CHUNK;
}
}

FLUSH_CHUNK(newarray);
FLUSH_CHUNK;
#undef FLUSH_CHUNK
return 1;
}
Expand Down