Skip to content
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

PoC: precompute embeded string literals hash code #553

Closed
wants to merge 1 commit into from
Closed
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
2 changes: 1 addition & 1 deletion compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -10588,7 +10588,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no
case NODE_STR:{
debugp_param("nd_lit", get_string_value(node));
if (!popped) {
VALUE lit = get_string_value(node);
VALUE lit = rb_str_precompute_hash(get_string_value(node));
switch (ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) {
case ISEQ_FROZEN_STRING_LITERAL_UNSET:
ADD_INSN1(ret, node, putchilledstring, lit);
Expand Down
1 change: 1 addition & 0 deletions internal/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ VALUE rb_str_concat_literals(size_t num, const VALUE *strary);
VALUE rb_str_eql(VALUE str1, VALUE str2);
VALUE rb_id_quote_unprintable(ID);
VALUE rb_sym_proc_call(ID mid, int argc, const VALUE *argv, int kw_splat, VALUE passed_proc);
VALUE rb_str_precompute_hash(VALUE);

struct rb_execution_context_struct;
VALUE rb_ec_str_resurrect(struct rb_execution_context_struct *ec, VALUE str, bool chilled);
Expand Down
21 changes: 21 additions & 0 deletions string.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ VALUE rb_cSymbol;
* another string (the shared root).
* 3: STR_CHILLED (will be frozen in a future version)
* The string appears frozen but can be mutated with a warning.
* 4: STR_PRECOMPUTED_HASH
* TODO: doc
* 5: STR_SHARED_ROOT
* Other strings may point to the contents of this string. When this
* flag is set, STR_SHARED must not be set.
Expand Down Expand Up @@ -116,6 +118,7 @@ VALUE rb_cSymbol;
*/

#define RUBY_MAX_CHAR_LEN 16
#define STR_PRECOMPUTED_HASH FL_USER4
#define STR_SHARED_ROOT FL_USER5
#define STR_BORROWED FL_USER6
#define STR_TMPLOCK FL_USER7
Expand Down Expand Up @@ -401,6 +404,20 @@ fstr_update_callback(st_data_t *key, st_data_t *value, st_data_t data, int exist
}
}

VALUE
rb_str_precompute_hash(VALUE str)
{
if (!FL_TEST_RAW(str, STR_PRECOMPUTED_HASH) && STR_EMBED_P(str)) {
size_t used_bytes = (RSTRING_LEN(str) + TERM_LEN(str));
size_t free_bytes = str_embed_capa(str) - used_bytes;
if (free_bytes >= sizeof(st_index_t)) {
*(st_index_t *)(RSTRING_PTR(str) + used_bytes) = rb_str_hash(str);
FL_SET(str, STR_PRECOMPUTED_HASH);
}
}
return str;
}

VALUE
rb_fstring(VALUE str)
{
Expand Down Expand Up @@ -3655,6 +3672,10 @@ rb_str_prepend_multi(int argc, VALUE *argv, VALUE str)
st_index_t
rb_str_hash(VALUE str)
{
if (FL_TEST_RAW(str, STR_PRECOMPUTED_HASH)) {
return *(st_index_t *)(RSTRING_END(str) + TERM_LEN(str));
}

st_index_t h = rb_memhash((const void *)RSTRING_PTR(str), RSTRING_LEN(str));
int e = RSTRING_LEN(str) ? ENCODING_GET(str) : 0;
if (e && !is_ascii_string(str)) {
Expand Down