summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-19 05:53:00 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2014-09-19 05:53:00 +0000
commitabac84856448e8a15e941cce8c1e48f891e83a3c (patch)
treeb2e152124af84f23be18ae6e3a18ccfdcafaab35
parent990845662cd4284a73ecc926c33cd1c8efb82354 (diff)
string.c: rb_str_new_static
* string.c (rb_str_new_static): create string object with static buffer. incorporated from mruby. * string.c (rb_{usascii,utf8,enc}_str_new_static): ditto with encodings. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@47639 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--include/ruby/encoding.h9
-rw-r--r--include/ruby/intern.h28
-rw-r--r--string.c77
3 files changed, 105 insertions, 9 deletions
diff --git a/include/ruby/encoding.h b/include/ruby/encoding.h
index 4a5324d62e..7d33e538de 100644
--- a/include/ruby/encoding.h
+++ b/include/ruby/encoding.h
@@ -91,6 +91,7 @@ void rb_enc_copy(VALUE dst, VALUE src);
VALUE rb_enc_str_new(const char*, long, rb_encoding*);
VALUE rb_enc_str_new_cstr(const char*, rb_encoding*);
+VALUE rb_enc_str_new_static(const char*, long, rb_encoding*);
VALUE rb_enc_reg_new(const char*, long, rb_encoding*, int);
PRINTF_ARGS(VALUE rb_enc_sprintf(rb_encoding *, const char*, ...), 2, 3);
VALUE rb_enc_vsprintf(rb_encoding *, const char*, va_list);
@@ -106,10 +107,16 @@ VALUE rb_str_conv_enc(VALUE str, rb_encoding *from, rb_encoding *to);
VALUE rb_str_conv_enc_opts(VALUE str, rb_encoding *from, rb_encoding *to, int ecflags, VALUE ecopts);
#if defined(__GNUC__) && !defined(__PCC__)
+#define rb_enc_str_new(str, len, enc) __extension__ ( \
+{ \
+ (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
+ rb_enc_str_new_static((str), (len), (enc)) : \
+ rb_enc_str_new((str), (len), (enc)); \
+})
#define rb_enc_str_new_cstr(str, enc) __extension__ ( \
{ \
(__builtin_constant_p(str)) ? \
- rb_enc_str_new((str), (long)strlen(str), (enc)) : \
+ rb_enc_str_new_static((str), (long)strlen(str), (enc)) : \
rb_enc_str_new_cstr((str), (enc)); \
})
#endif
diff --git a/include/ruby/intern.h b/include/ruby/intern.h
index ecb4ba7781..b8377bc5b2 100644
--- a/include/ruby/intern.h
+++ b/include/ruby/intern.h
@@ -710,6 +710,9 @@ VALUE rb_usascii_str_new(const char*, long);
VALUE rb_usascii_str_new_cstr(const char*);
VALUE rb_utf8_str_new(const char*, long);
VALUE rb_utf8_str_new_cstr(const char*);
+VALUE rb_str_new_static(const char *, long);
+VALUE rb_usascii_str_new_static(const char *, long);
+VALUE rb_utf8_str_new_static(const char *, long);
void rb_str_free(VALUE);
void rb_str_shared_replace(VALUE, VALUE);
VALUE rb_str_buf_append(VALUE, VALUE);
@@ -771,13 +774,32 @@ long rb_str_offset(VALUE, long);
size_t rb_str_capacity(VALUE);
VALUE rb_str_ellipsize(VALUE, long);
VALUE rb_str_scrub(VALUE, VALUE);
+
#if defined(__GNUC__) && !defined(__PCC__)
+#define rb_str_new(str, len) __extension__ ( \
+{ \
+ (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
+ rb_str_new_static((str), (len)) : \
+ rb_str_new((str), (len)); \
+})
#define rb_str_new_cstr(str) __extension__ ( \
{ \
(__builtin_constant_p(str)) ? \
- rb_str_new((str), (long)strlen(str)) : \
+ rb_str_new_static((str), (long)strlen(str)) : \
rb_str_new_cstr(str); \
})
+#define rb_usascii_str_new(str, len) __extension__ ( \
+{ \
+ (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
+ rb_usascii_str_new_static((str), (len)) : \
+ rb_usascii_str_new((str), (len)); \
+})
+#define rb_utf8_str_new(str, len) __extension__ ( \
+{ \
+ (__builtin_constant_p(str) && __builtin_constant_p(len)) ? \
+ rb_utf8_str_new_static((str), (len)) : \
+ rb_utf8_str_new((str), (len)); \
+})
#define rb_tainted_str_new_cstr(str) __extension__ ( \
{ \
(__builtin_constant_p(str)) ? \
@@ -787,13 +809,13 @@ VALUE rb_str_scrub(VALUE, VALUE);
#define rb_usascii_str_new_cstr(str) __extension__ ( \
{ \
(__builtin_constant_p(str)) ? \
- rb_usascii_str_new((str), (long)strlen(str)) : \
+ rb_usascii_str_new_static((str), (long)strlen(str)) : \
rb_usascii_str_new_cstr(str); \
})
#define rb_utf8_str_new_cstr(str) __extension__ ( \
{ \
(__builtin_constant_p(str)) ? \
- rb_utf8_str_new((str), (long)strlen(str)) : \
+ rb_utf8_str_new_static((str), (long)strlen(str)) : \
rb_utf8_str_new_cstr(str); \
})
#define rb_external_str_new_cstr(str) __extension__ ( \
diff --git a/string.c b/string.c
index 9c562ff78d..d67d57dd64 100644
--- a/string.c
+++ b/string.c
@@ -31,6 +31,10 @@
#define STRING_ENUMERATORS_WANTARRAY 0 /* next major */
+#undef rb_str_new
+#undef rb_usascii_str_new
+#undef rb_utf8_str_new
+#undef rb_enc_str_new
#undef rb_str_new_cstr
#undef rb_tainted_str_new_cstr
#undef rb_usascii_str_new_cstr
@@ -52,6 +56,7 @@ VALUE rb_cSymbol;
#define RUBY_MAX_CHAR_LEN 16
#define STR_TMPLOCK FL_USER7
+#define STR_NOFREE FL_USER18
#define STR_SET_NOEMBED(str) do {\
FL_SET((str), STR_NOEMBED);\
@@ -507,7 +512,7 @@ rb_str_capacity(VALUE str)
if (STR_EMBED_P(str)) {
return RSTRING_EMBED_LEN_MAX;
}
- else if (FL_TEST(str, STR_SHARED)) {
+ else if (FL_TEST(str, STR_SHARED|STR_NOFREE)) {
return RSTRING(str)->as.heap.len;
}
else {
@@ -642,6 +647,57 @@ rb_enc_str_new_cstr(const char *ptr, rb_encoding *enc)
return rb_enc_str_new(ptr, strlen(ptr), enc);
}
+static VALUE
+str_new_static(VALUE klass, const char *ptr, long len, int encindex)
+{
+ VALUE str;
+
+ if (len < 0) {
+ rb_raise(rb_eArgError, "negative string size (or size too big)");
+ }
+
+ if (!ptr) {
+ str = str_new(klass, ptr, len);
+ }
+ else {
+ if (RUBY_DTRACE_STRING_CREATE_ENABLED()) {
+ RUBY_DTRACE_STRING_CREATE(len, rb_sourcefile(), rb_sourceline());
+ }
+ str = str_alloc(klass);
+ RSTRING(str)->as.heap.len = len;
+ RSTRING(str)->as.heap.ptr = (char *)ptr;
+ RSTRING(str)->as.heap.aux.capa = len;
+ STR_SET_NOEMBED(str);
+ RBASIC(str)->flags |= STR_NOFREE;
+ }
+ rb_enc_associate_index(str, encindex);
+ return str;
+}
+
+VALUE
+rb_str_new_static(const char *ptr, long len)
+{
+ return str_new_static(rb_cString, ptr, len, 0);
+}
+
+VALUE
+rb_usascii_str_new_static(const char *ptr, long len)
+{
+ return str_new_static(rb_cString, ptr, len, ENCINDEX_US_ASCII);
+}
+
+VALUE
+rb_utf8_str_new_static(const char *ptr, long len)
+{
+ return str_new_static(rb_cString, ptr, len, ENCINDEX_UTF_8);
+}
+
+VALUE
+rb_enc_str_new_static(const char *ptr, long len, rb_encoding *enc)
+{
+ return str_new_static(rb_cString, ptr, len, rb_enc_to_index(enc));
+}
+
VALUE
rb_tainted_str_new(const char *ptr, long len)
{
@@ -892,6 +948,8 @@ rb_str_new_frozen(VALUE orig)
RSTRING(str)->as.heap.len = RSTRING_LEN(orig);
RSTRING(str)->as.heap.ptr = RSTRING_PTR(orig);
RSTRING(str)->as.heap.aux.capa = RSTRING(orig)->as.heap.aux.capa;
+ RBASIC(str)->flags |= RBASIC(orig)->flags & STR_NOFREE;
+ RBASIC(orig)->flags &= ~STR_NOFREE;
STR_SET_SHARED(orig, str);
}
}
@@ -977,7 +1035,7 @@ rb_str_free(VALUE str)
st_delete(rb_vm_fstring_table(), &fstr, NULL);
}
- if (!STR_EMBED_P(str) && !FL_TEST(str, STR_SHARED)) {
+ if (!STR_EMBED_P(str) && !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
ruby_sized_xfree(STR_HEAP_PTR(str), STR_HEAP_SIZE(str));
}
}
@@ -985,7 +1043,7 @@ rb_str_free(VALUE str)
RUBY_FUNC_EXPORTED size_t
rb_str_memsize(VALUE str)
{
- if (FL_TEST(str, STR_NOEMBED|STR_SHARED) == STR_NOEMBED) {
+ if (FL_TEST(str, STR_NOEMBED|STR_SHARED|STR_NOFREE) == STR_NOEMBED) {
return STR_HEAP_SIZE(str);
}
else {
@@ -1488,7 +1546,7 @@ static inline int
str_independent(VALUE str)
{
str_modifiable(str);
- if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED)) {
+ if (STR_EMBED_P(str) || !FL_TEST(str, STR_SHARED|STR_NOFREE)) {
return 1;
}
else {
@@ -1505,6 +1563,15 @@ str_make_independent_expand(VALUE str, long expand)
long capa = len + expand;
if (len > capa) len = capa;
+
+ if (capa <= RSTRING_EMBED_LEN_MAX && !STR_EMBED_P(str)) {
+ ptr = RSTRING(str)->as.heap.ptr;
+ STR_SET_EMBED(str);
+ memcpy(RSTRING(str)->as.ary, ptr, len);
+ STR_SET_EMBED_LEN(str, len);
+ return;
+ }
+
ptr = ALLOC_N(char, capa + termlen);
if (RSTRING_PTR(str)) {
memcpy(ptr, RSTRING_PTR(str), len);
@@ -3600,7 +3667,7 @@ rb_str_drop_bytes(VALUE str, long len)
nlen = olen - len;
if (nlen <= RSTRING_EMBED_LEN_MAX) {
char *oldptr = ptr;
- int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED));
+ int fl = (int)(RBASIC(str)->flags & (STR_NOEMBED|STR_SHARED|STR_NOFREE));
STR_SET_EMBED(str);
STR_SET_EMBED_LEN(str, nlen);
ptr = RSTRING(str)->as.ary;