Created
May 3, 2017 17:29
-
-
Save frsyuki/c428f119226790ffdf8ddc11c1a0b9fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/msgpack/buffer.h b/ext/msgpack/buffer.h | |
index 9387254..bcbe99b 100644 | |
--- a/ext/msgpack/buffer.h | |
+++ b/ext/msgpack/buffer.h | |
@@ -424,22 +424,61 @@ static inline VALUE _msgpack_buffer_refer_head_mapped_string(msgpack_buffer_t* b | |
return rb_str_substr(b->head->mapped_string, offset, length); | |
} | |
-static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool will_be_frozen) | |
+#ifdef COMPAT_HAVE_ENCODING | |
+#ifdef HAVE_RB_FSTRING_ENC_NEW | |
+#ifndef DISABLE_HASH_KEY_FSTRING | |
+extern VALUE rb_fstring_enc_new(const char *ptr, long len, rb_encoding *enc); | |
+#endif | |
+#endif | |
+#endif | |
+ | |
+static inline VALUE msgpack_buffer_read_top_as_string(msgpack_buffer_t* b, size_t length, bool frozen, bool string_enc) | |
{ | |
#ifndef DISABLE_BUFFER_READ_REFERENCE_OPTIMIZE | |
/* optimize */ | |
- if(!will_be_frozen && | |
+ /* don't use _msgpack_buffer_refer_head_mapped_string optimization for | |
+ * frozen strings because freezing strings cause copying */ | |
+ if(!frozen && | |
b->head->mapped_string != NO_MAPPED_STRING && | |
length >= b->read_reference_threshold) { | |
VALUE result = _msgpack_buffer_refer_head_mapped_string(b, length); | |
+ ENCODING_SET(result, | |
+ string_enc ? msgpack_rb_encindex_utf8 : msgpack_rb_encindex_ascii8bit); | |
_msgpack_buffer_consumed(b, length); | |
return result; | |
} | |
#endif | |
+#ifdef COMPAT_HAVE_ENCODING | |
+#ifdef HAVE_RB_FSTRING_ENC_NEW | |
+#ifndef DISABLE_HASH_KEY_FSTRING | |
+ /* optimize */ | |
+ if(frozen) { | |
+ VALUE fstring = rb_fstring_enc_new(b->read_buffer, length, | |
+ rb_enc_from_index(string_enc ? msgpack_rb_encindex_utf8 : msgpack_rb_encindex_ascii8bit)); | |
+ _msgpack_buffer_consumed(b, length); | |
+ return fstring; | |
+ } | |
+#endif | |
+#endif | |
+ | |
+ VALUE result = rb_str_new(b->read_buffer, length); | |
+ ENCODING_SET(result, | |
+ string_enc ? msgpack_rb_encindex_utf8 : msgpack_rb_encindex_ascii8bit); | |
+ if(frozen) { | |
+ rb_obj_freeze(result); | |
+ } | |
+ _msgpack_buffer_consumed(b, length); | |
+ return result; | |
+ | |
+#else | |
VALUE result = rb_str_new(b->read_buffer, length); | |
_msgpack_buffer_consumed(b, length); | |
+ if(frozen) { | |
+ rb_obj_freeze(result); | |
+ } | |
return result; | |
+#endif | |
} | |
diff --git a/ext/msgpack/extconf.rb b/ext/msgpack/extconf.rb | |
index 4ca8cda..fb72137 100644 | |
--- a/ext/msgpack/extconf.rb | |
+++ b/ext/msgpack/extconf.rb | |
@@ -6,6 +6,7 @@ have_func("rb_str_replace", ["ruby.h"]) | |
have_func("rb_intern_str", ["ruby.h"]) | |
have_func("rb_sym2str", ["ruby.h"]) | |
have_func("rb_str_intern", ["ruby.h"]) | |
+have_func("rb_fstring_enc_new", ["ruby.h"]) | |
have_func("rb_block_lambda", ["ruby.h"]) | |
have_func("rb_hash_dup", ["ruby.h"]) | |
have_func("rb_hash_clear", ["ruby.h"]) | |
@@ -17,6 +18,7 @@ end | |
#$CFLAGS << %[ -DDISABLE_RMEM_REUSE_INTERNAL_FRAGMENT] | |
#$CFLAGS << %[ -DDISABLE_BUFFER_READ_REFERENCE_OPTIMIZE] | |
#$CFLAGS << %[ -DDISABLE_BUFFER_READ_TO_S_OPTIMIZE] | |
+#$CFLAGS << %[ -DDISABLE_HASH_KEY_FSTRING] | |
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'rbx' | |
# msgpack-ruby doesn't modify data came from RSTRING_PTR(str) | |
diff --git a/ext/msgpack/unpacker.c b/ext/msgpack/unpacker.c | |
index 8b1f699..54faaa4 100644 | |
--- a/ext/msgpack/unpacker.c | |
+++ b/ext/msgpack/unpacker.c | |
@@ -163,12 +163,8 @@ static inline int object_complete_binary(msgpack_unpacker_t* uk, VALUE str) | |
return object_complete(uk, str); | |
} | |
-static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str) | |
+static inline int object_complete_ext2(msgpack_unpacker_t* uk, int ext_type, VALUE str) | |
{ | |
-#ifdef COMPAT_HAVE_ENCODING | |
- ENCODING_SET(str, msgpack_rb_encindex_ascii8bit); | |
-#endif | |
- | |
VALUE proc = msgpack_unpacker_ext_registry_lookup(&uk->ext_registry, ext_type); | |
if(proc != Qnil) { | |
VALUE obj = rb_funcall(proc, s_call, 1, str); | |
@@ -183,6 +179,14 @@ static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALU | |
return PRIMITIVE_UNEXPECTED_EXT_TYPE; | |
} | |
+static inline int object_complete_ext(msgpack_unpacker_t* uk, int ext_type, VALUE str) | |
+{ | |
+#ifdef COMPAT_HAVE_ENCODING | |
+ ENCODING_SET(str, msgpack_rb_encindex_ascii8bit); | |
+#endif | |
+ return object_complete_ext2(uk, ext_type, str); | |
+} | |
+ | |
/* stack funcs */ | |
static inline msgpack_unpacker_stack_t* _msgpack_unpacker_stack_top(msgpack_unpacker_t* uk) | |
{ | |
@@ -288,20 +292,16 @@ static inline int read_raw_body_begin(msgpack_unpacker_t* uk, int raw_type) | |
/* try optimized read */ | |
size_t length = uk->reading_raw_remaining; | |
if(length <= msgpack_buffer_top_readable_size(UNPACKER_BUFFER_(uk))) { | |
- /* don't use zerocopy for hash keys but get a frozen string directly | |
- * because rb_hash_aset freezes keys and it causes copying */ | |
- bool will_freeze = is_reading_map_key(uk); | |
- VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, will_freeze); | |
+ bool frozen = is_reading_map_key(uk); | |
+ VALUE string = msgpack_buffer_read_top_as_string(UNPACKER_BUFFER_(uk), length, | |
+ frozen, raw_type == RAW_TYPE_STRING); | |
int ret; | |
if(raw_type == RAW_TYPE_STRING) { | |
- ret = object_complete_string(uk, string); | |
+ ret = object_complete(uk, string); | |
} else if(raw_type == RAW_TYPE_BINARY) { | |
- ret = object_complete_binary(uk, string); | |
+ ret = object_complete(uk, string); | |
} else { | |
- ret = object_complete_ext(uk, raw_type, string); | |
- } | |
- if(will_freeze) { | |
- rb_obj_freeze(string); | |
+ ret = object_complete_ext2(uk, raw_type, string); | |
} | |
uk->reading_raw_remaining = 0; | |
return ret; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment