summaryrefslogtreecommitdiffhomepage
path: root/src/symbol.c
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2013-12-24 08:27:42 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2013-12-24 08:27:42 +0900
commitbc7a6e88a17e89e14de7cb4cbbd6ca19c4daa620 (patch)
tree07ed8473d511e903f8463cb7045160da1a3e58d0 /src/symbol.c
parent9fab01caeed5697e30e30daef3a845f33dcfefaf (diff)
downloadmruby-bc7a6e88a17e89e14de7cb4cbbd6ca19c4daa620.tar.gz
mruby-bc7a6e88a17e89e14de7cb4cbbd6ca19c4daa620.zip
zero copy C literal strings in symbol table
Diffstat (limited to 'src/symbol.c')
-rw-r--r--src/symbol.c47
1 files changed, 39 insertions, 8 deletions
diff --git a/src/symbol.c b/src/symbol.c
index 12f65d7e5..5ced22461 100644
--- a/src/symbol.c
+++ b/src/symbol.c
@@ -13,7 +13,8 @@
/* ------------------------------------------------------ */
typedef struct symbol_name {
- size_t len;
+ mrb_bool lit;
+ uint16_t len;
const char *name;
} symbol_name;
@@ -34,8 +35,8 @@ sym_hash_func(mrb_state *mrb, const symbol_name s)
KHASH_DECLARE(n2s, symbol_name, mrb_sym, 1)
KHASH_DEFINE (n2s, symbol_name, mrb_sym, 1, sym_hash_func, sym_hash_equal)
/* ------------------------------------------------------ */
-mrb_sym
-mrb_intern(mrb_state *mrb, const char *name, size_t len)
+static mrb_sym
+sym_intern(mrb_state *mrb, const char *name, size_t len, int lit)
{
khash_t(n2s) *h = mrb->name2sym;
symbol_name sname;
@@ -43,6 +44,10 @@ mrb_intern(mrb_state *mrb, const char *name, size_t len)
mrb_sym sym;
char *p;
+ if (len > UINT16_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ }
+ sname.lit = lit;
sname.len = len;
sname.name = name;
k = kh_get(n2s, mrb, h, sname);
@@ -50,10 +55,15 @@ mrb_intern(mrb_state *mrb, const char *name, size_t len)
return kh_value(h, k);
sym = ++mrb->symidx;
- p = (char *)mrb_malloc(mrb, len+1);
- memcpy(p, name, len);
- p[len] = 0;
- sname.name = (const char*)p;
+ if (lit) {
+ sname.name = name;
+ }
+ else {
+ p = (char *)mrb_malloc(mrb, len+1);
+ memcpy(p, name, len);
+ p[len] = 0;
+ sname.name = (const char*)p;
+ }
k = kh_put(n2s, mrb, h, sname);
kh_value(h, k) = sym;
@@ -61,6 +71,18 @@ mrb_intern(mrb_state *mrb, const char *name, size_t len)
}
mrb_sym
+mrb_intern(mrb_state *mrb, const char *name, size_t len)
+{
+ return sym_intern(mrb, name, len, 0);
+}
+
+mrb_sym
+mrb_intern_literal(mrb_state *mrb, const char *name, size_t len)
+{
+ return sym_intern(mrb, name, len, 1);
+}
+
+mrb_sym
mrb_intern_cstr(mrb_state *mrb, const char *name)
{
return mrb_intern(mrb, name, strlen(name));
@@ -79,6 +101,9 @@ mrb_check_intern(mrb_state *mrb, const char *name, size_t len)
symbol_name sname;
khiter_t k;
+ if (len > UINT16_MAX) {
+ mrb_raise(mrb, E_ARGUMENT_ERROR, "symbol length too long");
+ }
sname.len = len;
sname.name = name;
@@ -129,7 +154,13 @@ mrb_free_symtbl(mrb_state *mrb)
khiter_t k;
for (k = kh_begin(h); k != kh_end(h); k++)
- if (kh_exist(h, k)) mrb_free(mrb, (char*)kh_key(h, k).name);
+ if (kh_exist(h, k)) {
+ symbol_name s = kh_key(h, k);
+
+ if (!s.lit) {
+ mrb_free(mrb, (char*)s.name);
+ }
+ }
kh_destroy(n2s, mrb, mrb->name2sym);
}