[svn:parrot] r48846 - in branches/hash_inlined_func: compilers/imcc include/parrot src src/pmc
luben at svn.parrot.org
luben at svn.parrot.org
Wed Sep 8 01:16:54 UTC 2010
Author: luben
Date: Wed Sep 8 01:16:54 2010
New Revision: 48846
URL: https://trac.parrot.org/parrot/changeset/48846
Log:
Merge branch 'fixes2-inlined' into hash_inlined_func
Modified:
branches/hash_inlined_func/compilers/imcc/imcparser.h
branches/hash_inlined_func/compilers/imcc/pbc.c
branches/hash_inlined_func/include/parrot/hash.h
branches/hash_inlined_func/src/hash.c
branches/hash_inlined_func/src/pmc/addrregistry.pmc
branches/hash_inlined_func/src/pmc/callcontext.pmc
branches/hash_inlined_func/src/pmc/class.pmc
branches/hash_inlined_func/src/pmc/hash.pmc
branches/hash_inlined_func/src/pmc/stringbuilder.pmc
Modified: branches/hash_inlined_func/compilers/imcc/imcparser.h
==============================================================================
--- branches/hash_inlined_func/compilers/imcc/imcparser.h Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/compilers/imcc/imcparser.h Wed Sep 8 01:16:54 2010 (r48846)
@@ -9,13 +9,12 @@
*/
/* HEADERIZER HFILE: none */
/* HEADERIZER STOP */
-
-/* A Bison parser, made by GNU Bison 2.4.1. */
+/* A Bison parser, made by GNU Bison 2.4.3. */
/* Skeleton interface for Bison's Yacc-like parsers in C
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2009, 2010 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -295,7 +294,7 @@
typedef union YYSTYPE
{
-/* Line 1676 of yacc.c */
+/* Line 1685 of yacc.c */
#line 1071 "compilers/imcc/imcc.y"
IdList * idlist;
@@ -306,8 +305,8 @@
-/* Line 1676 of yacc.c */
-#line 300 "compilers/imcc/imcparser.h"
+/* Line 1685 of yacc.c */
+#line 299 "compilers/imcc/imcparser.h"
} YYSTYPE;
# define YYSTYPE_IS_TRIVIAL 1
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
Modified: branches/hash_inlined_func/compilers/imcc/pbc.c
==============================================================================
--- branches/hash_inlined_func/compilers/imcc/pbc.c Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/compilers/imcc/pbc.c Wed Sep 8 01:16:54 2010 (r48846)
@@ -362,8 +362,8 @@
/* initialize rlookup cache */
interp->code->const_table->string_hash =
Parrot_pmc_new_init_int(interp, enum_class_Hash, enum_type_INTVAL);
- ((Hash *)VTABLE_get_pointer(interp, interp->code->const_table->string_hash))->compare =
- (hash_comp_fn)hash_compare_string_distinct_enc;
+ ((Hash *)VTABLE_get_pointer(interp, interp->code->const_table->string_hash))->key_type =
+ Hash_key_type_STRING_enc;
interp->code->const_table->constants =
mem_gc_allocate_n_zeroed_typed(interp, newcount, PackFile_Constant);
Modified: branches/hash_inlined_func/include/parrot/hash.h
==============================================================================
--- branches/hash_inlined_func/include/parrot/hash.h Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/include/parrot/hash.h Wed Sep 8 01:16:54 2010 (r48846)
@@ -26,16 +26,15 @@
#define HASH_ALLOC_SIZE(n) (N_BUCKETS(n) * sizeof (HashBucket) + \
(n) * sizeof (HashBucket *))
-typedef int (*hash_comp_fn)(PARROT_INTERP, ARGIN(const void *), ARGIN(const void *));
-typedef size_t (*hash_hash_key_fn)(PARROT_INTERP, ARGIN(const void *), size_t seed);
-
/* &gen_from_enum(hash_key_type.pasm) */
typedef enum {
Hash_key_type_int,
Hash_key_type_cstring,
Hash_key_type_STRING,
Hash_key_type_PMC,
- Hash_key_type_ptr
+ Hash_key_type_ptr,
+ Hash_key_type_PMC_ptr,
+ Hash_key_type_STRING_enc,
} Hash_key_type;
/* &end_gen */
@@ -69,12 +68,6 @@
/* Random seed value for seeding hash algorithms */
size_t seed;
-
- /* Comparison function pointer. Returns 0 if elements are equal */
- hash_comp_fn compare;
-
- /* Function pointer to generate a hash value for the object */
- hash_hash_key_fn hash_val;
};
/* Utility macros - use them, do not reinvent the wheel */
@@ -86,10 +79,8 @@
UINTVAL _found = 0; \
while (_found < (_hash)->entries){ \
if (_bucket->key){ \
+ _code \
_found++; \
- { \
- _code \
- } \
} \
_bucket++; \
} \
@@ -234,25 +225,30 @@
__attribute__nonnull__(1);
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
int hash_compare_int(SHIM_INTERP,
ARGIN_NULLOK(const void *a),
ARGIN_NULLOK(const void *b));
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
int hash_compare_pmc(PARROT_INTERP, ARGIN(PMC *a), ARGIN(PMC *b))
__attribute__nonnull__(1)
__attribute__nonnull__(2)
__attribute__nonnull__(3);
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
int hash_compare_pointer(SHIM_INTERP,
ARGIN_NULLOK(const void *a),
ARGIN_NULLOK(const void *b));
PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
int hash_compare_string(PARROT_INTERP,
ARGIN(const void *search_key),
ARGIN_NULLOK(const void *bucket_key))
@@ -260,7 +256,7 @@
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
-int hash_compare_string_distinct_enc(PARROT_INTERP,
+int hash_compare_string_enc(PARROT_INTERP,
ARGIN(const void *search_key),
ARGIN(const void *bucket_key))
__attribute__nonnull__(1)
@@ -364,21 +360,23 @@
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
size_t key_hash_int(SHIM_INTERP,
ARGIN_NULLOK(const void *value),
size_t seed);
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
size_t key_hash_PMC(PARROT_INTERP, ARGIN(PMC *value), NULLOK(size_t seed))
__attribute__nonnull__(1)
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
-size_t key_hash_STRING(PARROT_INTERP,
- ARGMOD(STRING *s),
- NULLOK(size_t seed))
+PARROT_PURE_FUNCTION
+PARROT_INLINE
+size_t key_hash_STRING(PARROT_INTERP, ARGMOD(STRING *s), size_t seed)
__attribute__nonnull__(1)
__attribute__nonnull__(2)
FUNC_MODIFIES(*s);
@@ -401,12 +399,8 @@
PARROT_MALLOC
Hash * parrot_create_hash(PARROT_INTERP,
PARROT_DATA_TYPE val_type,
- Hash_key_type hkey_type,
- NOTNULL(hash_comp_fn compare),
- NOTNULL(hash_hash_key_fn keyhash))
- __attribute__nonnull__(1)
- __attribute__nonnull__(4)
- __attribute__nonnull__(5);
+ Hash_key_type hkey_type)
+ __attribute__nonnull__(1);
PARROT_CANNOT_RETURN_NULL
PARROT_WARN_UNUSED_RESULT
@@ -414,12 +408,8 @@
Hash * parrot_create_hash_sized(PARROT_INTERP,
PARROT_DATA_TYPE val_type,
Hash_key_type hkey_type,
- NOTNULL(hash_comp_fn compare),
- NOTNULL(hash_hash_key_fn keyhash),
UINTVAL size)
- __attribute__nonnull__(1)
- __attribute__nonnull__(4)
- __attribute__nonnull__(5);
+ __attribute__nonnull__(1);
void parrot_hash_clone_prunable(PARROT_INTERP,
ARGIN(const Hash *hash),
@@ -494,8 +484,7 @@
#define ASSERT_ARGS_hash_compare_string __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(search_key))
-#define ASSERT_ARGS_hash_compare_string_distinct_enc \
- __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+#define ASSERT_ARGS_hash_compare_string_enc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(search_key) \
, PARROT_ASSERT_ARG(bucket_key))
@@ -559,13 +548,9 @@
, PARROT_ASSERT_ARG(hash) \
, PARROT_ASSERT_ARG(func))
#define ASSERT_ARGS_parrot_create_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(compare) \
- , PARROT_ASSERT_ARG(keyhash))
+ PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_parrot_create_hash_sized __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(interp) \
- , PARROT_ASSERT_ARG(compare) \
- , PARROT_ASSERT_ARG(keyhash))
+ PARROT_ASSERT_ARG(interp))
#define ASSERT_ARGS_parrot_hash_clone_prunable __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(hash) \
Modified: branches/hash_inlined_func/src/hash.c
==============================================================================
--- branches/hash_inlined_func/src/hash.c Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/src/hash.c Wed Sep 8 01:16:54 2010 (r48846)
@@ -55,6 +55,19 @@
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
+static int hash_compare(PARROT_INTERP,
+ ARGIN(const Hash *hash),
+ ARGIN(void *a),
+ ARGIN(void *b))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3)
+ __attribute__nonnull__(4);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
static int hash_compare_cstring(SHIM_INTERP,
ARGIN(const char *a),
ARGIN(const char *b))
@@ -63,13 +76,25 @@
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
+static size_t key_hash(PARROT_INTERP,
+ ARGIN(const Hash *hash),
+ ARGIN(void *key))
+ __attribute__nonnull__(1)
+ __attribute__nonnull__(2)
+ __attribute__nonnull__(3);
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
static size_t key_hash_cstring(SHIM_INTERP,
ARGIN(const void *value),
size_t seed)
__attribute__nonnull__(2);
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
static size_t key_hash_pointer(SHIM_INTERP,
ARGIN(const void *value),
size_t seed)
@@ -97,9 +122,18 @@
#define ASSERT_ARGS_get_string_pmc __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(value))
+#define ASSERT_ARGS_hash_compare __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(hash) \
+ , PARROT_ASSERT_ARG(a) \
+ , PARROT_ASSERT_ARG(b))
#define ASSERT_ARGS_hash_compare_cstring __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(a) \
, PARROT_ASSERT_ARG(b))
+#define ASSERT_ARGS_key_hash __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
+ PARROT_ASSERT_ARG(interp) \
+ , PARROT_ASSERT_ARG(hash) \
+ , PARROT_ASSERT_ARG(key))
#define ASSERT_ARGS_key_hash_cstring __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_key_hash_pointer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
@@ -116,8 +150,6 @@
/* Don't modify between HEADERIZER BEGIN / HEADERIZER END. Your changes will be lost. */
/* HEADERIZER END: static */
-
-
/*
=item C<size_t key_hash_STRING(PARROT_INTERP, STRING *s, size_t seed)>
@@ -130,15 +162,22 @@
PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
size_t
-key_hash_STRING(PARROT_INTERP, ARGMOD(STRING *s), SHIM(size_t seed))
+key_hash_STRING(PARROT_INTERP, ARGMOD(STRING *s), size_t seed)
{
ASSERT_ARGS(key_hash_STRING)
+ size_t hashval = seed;
if (s->hashval)
return s->hashval;
-
- return Parrot_str_to_hashval(interp, s);
+ else if (!STRING_IS_NULL(s)) {
+ if (s->strlen)
+ return Parrot_str_to_hashval(interp, s);
+ s->hashval = seed;
+ }
+ return seed;
}
@@ -154,6 +193,8 @@
*/
PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
int
hash_compare_string(PARROT_INTERP, ARGIN(const void *search_key),
ARGIN_NULLOK(const void *bucket_key))
@@ -164,15 +205,20 @@
if (s1->hashval != s2->hashval)
return 1;
-
- return STRING_compare(interp, s1, s2);
+ if (s1->encoding == s2->encoding)
+ if (s1->bufused != s2->bufused)
+ return 1;
+ else
+ return memcmp(s1->strstart, s2->strstart, s1->bufused);
+ else
+ return STRING_compare(interp, s1, s2);
}
/*
-=item C<int hash_compare_string_distinct_enc(PARROT_INTERP, const void
-*search_key, const void *bucket_key)>
+=item C<int hash_compare_string_enc(PARROT_INTERP, const void *search_key, const
+void *bucket_key)>
Compare two strings. Returns 0 if they are identical. Considers differing
charset or encoding to be distinct.
@@ -181,17 +227,19 @@
PARROT_WARN_UNUSED_RESULT
int
-hash_compare_string_distinct_enc(PARROT_INTERP, ARGIN(const void *search_key),
- ARGIN(const void *bucket_key))
+hash_compare_string_enc(PARROT_INTERP, ARGIN(const void *search_key),
+ ARGIN(const void *bucket_key))
{
- ASSERT_ARGS(hash_compare_string_distinct_enc)
+ ASSERT_ARGS(hash_compare_string_enc)
STRING const *s1 = (STRING const *)search_key;
STRING const *s2 = (STRING const *)bucket_key;
+ if (s1->hashval != s2->hashval)
+ return 1;
if (s1 && s2 && s1->encoding != s2->encoding)
return 1;
-
- return hash_compare_string(interp, search_key, bucket_key);
+ else
+ return memcmp(s1->strstart, s2->strstart, s1->bufused);
}
@@ -206,7 +254,8 @@
*/
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
int
hash_compare_pointer(SHIM_INTERP, ARGIN_NULLOK(const void *a), ARGIN_NULLOK(const void *b))
{
@@ -227,7 +276,8 @@
*/
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
static size_t
key_hash_pointer(SHIM_INTERP, ARGIN(const void *value), size_t seed)
{
@@ -254,18 +304,18 @@
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
static size_t
key_hash_cstring(SHIM_INTERP, ARGIN(const void *value), size_t seed)
{
ASSERT_ARGS(key_hash_cstring)
- const unsigned char * p = (const unsigned char *) value;
- register size_t h = seed;
-
+ const char * p = (const char *) value;
+ register size_t h = seed;
+ size_t len = strlen(p);
while (*p) {
h += h << 5;
h += *p++;
}
-
return h;
}
@@ -284,6 +334,7 @@
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
static int
hash_compare_cstring(SHIM_INTERP, ARGIN(const char *a), ARGIN(const char *b))
{
@@ -304,6 +355,7 @@
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
size_t
key_hash_PMC(PARROT_INTERP, ARGIN(PMC *value), SHIM(size_t seed))
{
@@ -324,6 +376,7 @@
PARROT_WARN_UNUSED_RESULT
PARROT_PURE_FUNCTION
+PARROT_INLINE
int
hash_compare_pmc(PARROT_INTERP, ARGIN(PMC *a), ARGIN(PMC *b))
{
@@ -351,7 +404,8 @@
*/
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
size_t
key_hash_int(SHIM_INTERP, ARGIN_NULLOK(const void *value), size_t seed)
{
@@ -372,7 +426,8 @@
*/
PARROT_WARN_UNUSED_RESULT
-PARROT_CONST_FUNCTION
+PARROT_PURE_FUNCTION
+PARROT_INLINE
int
hash_compare_int(SHIM_INTERP, ARGIN_NULLOK(const void *a), ARGIN_NULLOK(const void *b))
{
@@ -382,6 +437,79 @@
/*
+=item C<static size_t key_hash(PARROT_INTERP, const Hash *hash, void *key)>
+
+Generic function to get the hashvalue of a given key. It may dispatches to
+key_hash_STRING, key_hash_cstring, etc. depending on hash->key_type.
+
+=cut
+
+*/
+
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
+static size_t
+key_hash(PARROT_INTERP, ARGIN(const Hash *hash), ARGIN(void *key))
+{
+ ASSERT_ARGS(key_hash)
+
+ if (hash->key_type == Hash_key_type_STRING
+ || hash->key_type == Hash_key_type_STRING_enc)
+ return key_hash_STRING(interp, (STRING *)key, hash->seed);
+
+ if (hash->key_type == Hash_key_type_cstring)
+ return key_hash_cstring(interp, (char *)key, hash->seed);
+
+ if (hash->key_type == Hash_key_type_PMC)
+ return VTABLE_hashvalue(interp, (PMC *)key);
+
+ return ((size_t) key) ^ hash->seed;
+
+}
+
+/*
+
+=item C<static int hash_compare(PARROT_INTERP, const Hash *hash, void *a, void
+*b)>
+
+Generic function to compare values. It may dispatches to
+hash_compare_string, hash_compare_cstring, etc. depending on hash->key_type.
+
+=cut
+
+*/
+
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_PURE_FUNCTION
+PARROT_INLINE
+static int
+hash_compare(PARROT_INTERP, ARGIN(const Hash *hash), ARGIN(void *a), ARGIN(void *b))
+{
+ ASSERT_ARGS(hash_compare)
+
+ if (a == b)
+ return 0;
+
+ if (hash->key_type == Hash_key_type_STRING)
+ return hash_compare_string(interp, (STRING *)a, (STRING *)b);
+
+ if (hash->key_type == Hash_key_type_STRING_enc)
+ return hash_compare_string_enc(interp, (STRING *)a, (STRING *)b);
+
+ if (hash->key_type == Hash_key_type_cstring)
+ return strcmp((char *)a, (char *)b);
+
+ if (hash->key_type == Hash_key_type_PMC)
+ return hash_compare_pmc(interp, (PMC *)a, (PMC *) b);
+
+ return 1;
+}
+
+/*
+
=item C<void parrot_dump_hash(PARROT_INTERP, const Hash *hash)>
Prints out the hash in human-readable form, at least once someone implements
@@ -423,7 +551,9 @@
mark_value = 1;
if (hash->key_type == Hash_key_type_STRING
- || hash->key_type == Hash_key_type_PMC)
+ || hash->key_type == Hash_key_type_STRING_enc
+ || hash->key_type == Hash_key_type_PMC
+ || hash->key_type == Hash_key_type_PMC_ptr)
mark_key = 1;
if (mark_key) {
@@ -524,34 +654,7 @@
const Hash_key_type key_type = (Hash_key_type)VTABLE_shift_integer(interp, info);
const PARROT_DATA_TYPE entry_type = (PARROT_DATA_TYPE)VTABLE_shift_integer(interp, info);
size_t entry_index;
- Hash *hash;
-
- {
- hash_comp_fn cmp_fn;
- hash_hash_key_fn key_fn;
-
- switch (key_type) {
- case Hash_key_type_int:
- key_fn = (hash_hash_key_fn)key_hash_int;
- cmp_fn = (hash_comp_fn)hash_compare_int;
- break;
- case Hash_key_type_STRING:
- key_fn = (hash_hash_key_fn)key_hash_STRING;
- cmp_fn = (hash_comp_fn)hash_compare_string;
- break;
- case Hash_key_type_PMC:
- key_fn = (hash_hash_key_fn)key_hash_PMC;
- cmp_fn = (hash_comp_fn)hash_compare_pmc;
- break;
- default:
- Parrot_ex_throw_from_c_args(interp, NULL, 1,
- "unimplemented key type");
- break;
- }
-
- hash = parrot_create_hash_sized(interp, entry_type, key_type, cmp_fn, key_fn, num_entries);
-
- }
+ Hash *hash = parrot_create_hash_sized(interp, entry_type, key_type, num_entries);
/* special case for great speed */
if (key_type == Hash_key_type_STRING
@@ -576,12 +679,14 @@
}
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
{
STRING * const s_key = VTABLE_shift_string(interp, info);
key = (void *)s_key;
}
break;
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
{
PMC * const p_key = VTABLE_shift_pmc(interp, info);
key = (void *)p_key;
@@ -655,9 +760,11 @@
VTABLE_push_integer(interp, info, (INTVAL)_bucket->key);
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
VTABLE_push_string(interp, info, (STRING *)_bucket->key);
break;
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
VTABLE_push_pmc(interp, info, (PMC *)_bucket->key);
break;
default:
@@ -718,20 +825,18 @@
expand_hash(PARROT_INTERP, ARGMOD(Hash *hash))
{
ASSERT_ARGS(expand_hash)
- HashBucket **old_bi, **new_bi;
- HashBucket *bs, *b, *new_mem;
- HashBucket * const old_offset = (HashBucket *)((char *)hash + sizeof (Hash));
+ HashBucket **new_index, **index;
+ HashBucket *new_buckets, *bucket;
+ HashBucket * const initial_offset = (HashBucket *)((char *)hash + sizeof (Hash));
+
+ void * new_mem;
void * const old_mem = hash->buckets;
const UINTVAL old_size = hash->mask + 1;
- const UINTVAL new_size = old_size << 1; /* Double. Right-shift is 2x */
- const UINTVAL old_nb = N_BUCKETS(old_size);
- const UINTVAL new_nb = N_BUCKETS(new_size);
+ const UINTVAL new_size = old_size << 1; /* Double. Right-shift is 2x */
+ const UINTVAL new_mask = new_size - 1;
size_t offset, i;
- const hash_hash_key_fn hash_val_func = hash->hash_val;
- const int is_string_key = (hash_val_func == (hash_hash_key_fn)key_hash_STRING);
-
/*
allocate some less buckets
e.g. 3 buckets, 4 pointers:
@@ -744,86 +849,103 @@
*/
/* resize mem */
- if (old_offset != old_mem) {
+ if (initial_offset != old_mem) {
/* This buffer has been reallocated at least once before. */
- new_mem = (HashBucket *)Parrot_gc_reallocate_memory_chunk_with_interior_pointers(
- interp, old_mem, HASH_ALLOC_SIZE(new_size), HASH_ALLOC_SIZE(old_size));
+ new_mem = Parrot_gc_reallocate_memory_chunk_with_interior_pointers(
+ interp, old_mem,
+ HASH_ALLOC_SIZE(new_size),
+ HASH_ALLOC_SIZE(old_size));
+
+ new_buckets = (HashBucket *) new_mem;
+ new_index = (HashBucket **)(new_buckets + N_BUCKETS(new_size));
+
+ offset = (char *)new_mem - (char *)old_mem;
+
+ /* old index is here */
+ index = (HashBucket **)(new_buckets + N_BUCKETS(old_size));
+ /* reallocate index */
+ mem_sys_memcopy(new_index, index, sizeof (HashBucket *) * old_size);
+
+ /* clear second half of the buckets, freed by old the index */
+ memset(new_buckets + N_BUCKETS(old_size), 0,
+ sizeof (HashBucket *) * old_size);
}
else {
/* Allocate a new buffer. */
- new_mem = (HashBucket *)Parrot_gc_allocate_memory_chunk_with_interior_pointers(
+ new_mem = Parrot_gc_allocate_memory_chunk_with_interior_pointers(
interp, HASH_ALLOC_SIZE(new_size));
- memcpy(new_mem, old_mem, HASH_ALLOC_SIZE(old_size));
+
+ new_buckets = (HashBucket *) new_mem;
+ new_index = (HashBucket **)(new_buckets + N_BUCKETS(new_size));
+
+ offset = (char *)new_buckets - (char *)hash->buckets;
+
+ mem_sys_memcopy(new_buckets, hash->buckets ,
+ N_BUCKETS(old_size) * sizeof (HashBucket));
+ mem_sys_memcopy(new_index, hash->index,
+ sizeof (HashBucket *) * old_size);
}
+
/*
+---+---+---+---+---+---+-+-+-+-+-+-+-+-+
- | buckets | old_bi | new_bi |
+ | buckets | old_index | new_index |
+---+---+---+---+---+---+-+-+-+-+-+-+-+-+
^ ^
| new_mem | hash->index
*/
- bs = new_mem;
- old_bi = (HashBucket **)(bs + old_nb);
- new_bi = (HashBucket **)(bs + new_nb);
-
- /* things can have moved by this offset */
- offset = (char *)new_mem - (char *)old_mem;
-
- /* relocate the bucket index */
- mem_sys_memmove(new_bi, old_bi, old_size * sizeof (HashBucket *));
-
/* update hash data */
- hash->index = new_bi;
- hash->buckets = bs;
- hash->mask = new_size - 1;
-
- /* clear freshly allocated bucket index */
- memset(new_bi + old_size, 0, sizeof (HashBucket *) * (new_size - old_size));
+ hash->index = new_index;
+ hash->buckets = new_buckets;
+ hash->mask = new_mask;
/* reloc pointers and recalc bucket indices */
for (i = 0; i < old_size; ++i) {
- HashBucket **next_p = new_bi + i;
+ index = new_index + i;
- while (*next_p != NULL) {
+ while (*index != NULL) {
size_t new_loc;
size_t hashval;
- b = (HashBucket *)((char *)*next_p + offset);
+ bucket = (HashBucket *)((char *)*index + offset);
/* rehash the bucket */
- if (is_string_key) {
- STRING *s = (STRING *)b->key;
+ if (hash->key_type == Hash_key_type_STRING
+ || hash->key_type == Hash_key_type_STRING_enc) {
+ STRING *s = (STRING *)bucket->key;
hashval = s->hashval;
}
else {
- hashval = hash_val_func(interp, b->key, hash->seed);
+ hashval = key_hash(interp, hash, bucket->key);
}
- new_loc = hashval & (new_size - 1);
+ new_loc = hashval & new_mask;
if (i != new_loc) {
- *next_p = b->next;
- b->next = new_bi[new_loc];
- new_bi[new_loc] = b;
+ *index = bucket->next;
+ bucket->next = new_index[new_loc];
+ new_index[new_loc] = bucket;
}
else {
- *next_p = b;
- next_p = &b->next;
+ *index = bucket;
+ index = &bucket->next;
}
}
}
/* add new buckets to free_list
* lowest bucket is top on free list and will be used first */
- for (b = bs + old_nb; b < bs + new_nb - 1; ++b) {
- b->next = b + 1;
- b->key = b->value = NULL;
+
+ bucket = new_buckets + N_BUCKETS(old_size);
+
+ for (; bucket < new_buckets + N_BUCKETS(new_size) - 1; ++bucket) {
+ bucket->next = bucket + 1;
+ bucket->key = bucket->value = NULL;
}
- b->next = hash->free_list;
- hash->free_list = bs + old_nb;
+ hash->free_list = new_buckets + N_BUCKETS(old_size);
+ bucket->next = NULL;
}
@@ -845,9 +967,7 @@
ASSERT_ARGS(parrot_new_hash)
return parrot_create_hash(interp,
enum_type_PMC,
- Hash_key_type_STRING,
- hash_compare_string,
- (hash_hash_key_fn)key_hash_STRING);
+ Hash_key_type_STRING);
}
@@ -869,9 +989,7 @@
ASSERT_ARGS(parrot_new_cstring_hash)
return parrot_create_hash(interp,
enum_type_PMC,
- Hash_key_type_cstring,
- (hash_comp_fn)hash_compare_cstring,
- (hash_hash_key_fn)key_hash_cstring);
+ Hash_key_type_cstring);
}
@@ -893,9 +1011,7 @@
ASSERT_ARGS(parrot_new_pointer_hash)
return parrot_create_hash(interp,
enum_type_ptr,
- Hash_key_type_ptr,
- hash_compare_pointer,
- key_hash_pointer);
+ Hash_key_type_ptr);
}
@@ -920,15 +1036,13 @@
ASSERT_ARGS(parrot_new_intval_hash)
return parrot_create_hash(interp,
enum_type_INTVAL,
- Hash_key_type_int,
- hash_compare_int,
- key_hash_int);
+ Hash_key_type_int);
}
/*
=item C<Hash * parrot_create_hash(PARROT_INTERP, PARROT_DATA_TYPE val_type,
-Hash_key_type hkey_type, hash_comp_fn compare, hash_hash_key_fn keyhash)>
+Hash_key_type hkey_type)>
Creates and initializes a hash. Function pointers determine its behaviors.
@@ -942,12 +1056,10 @@
PARROT_WARN_UNUSED_RESULT
PARROT_MALLOC
Hash *
-parrot_create_hash(PARROT_INTERP, PARROT_DATA_TYPE val_type, Hash_key_type hkey_type,
- NOTNULL(hash_comp_fn compare), NOTNULL(hash_hash_key_fn keyhash))
+parrot_create_hash(PARROT_INTERP, PARROT_DATA_TYPE val_type, Hash_key_type hkey_type)
{
ASSERT_ARGS(parrot_create_hash)
- return parrot_create_hash_sized(interp, val_type, hkey_type, compare, keyhash,
- INITIAL_SIZE);
+ return parrot_create_hash_sized(interp, val_type, hkey_type, INITIAL_SIZE);
}
@@ -974,8 +1086,7 @@
/*
=item C<Hash * parrot_create_hash_sized(PARROT_INTERP, PARROT_DATA_TYPE
-val_type, Hash_key_type hkey_type, hash_comp_fn compare, hash_hash_key_fn
-keyhash, UINTVAL size)>
+val_type, Hash_key_type hkey_type, UINTVAL size)>
Creates and initializes a hash, similar to C<parrot_create_hash>.
@@ -990,7 +1101,7 @@
PARROT_MALLOC
Hash *
parrot_create_hash_sized(PARROT_INTERP, PARROT_DATA_TYPE val_type, Hash_key_type hkey_type,
- NOTNULL(hash_comp_fn compare), NOTNULL(hash_hash_key_fn keyhash), UINTVAL size)
+ UINTVAL size)
{
ASSERT_ARGS(parrot_create_hash_sized)
UINTVAL initial_buckets = size > INITIAL_SIZE ? round_up_pow2(size) : INITIAL_SIZE;
@@ -1002,8 +1113,6 @@
PARROT_ASSERT(initial_buckets % 4 == 0);
- hash->compare = compare;
- hash->hash_val = keyhash;
hash->entry_type = val_type;
hash->key_type = hkey_type;
hash->seed = interp->hash_seed;
@@ -1145,57 +1254,56 @@
parrot_hash_get_bucket(PARROT_INTERP, ARGIN(const Hash *hash), ARGIN_NULLOK(const void *key))
{
ASSERT_ARGS(parrot_hash_get_bucket)
- UINTVAL hashval;
+ DECL_CONST_CAST;
+
+ size_t hashval;
HashBucket *bucket;
- const hash_hash_key_fn hash_val = hash->hash_val;
- const hash_comp_fn compare = hash->compare;
if (hash->entries <= 0)
return NULL;
- if (hash_val == (hash_hash_key_fn)key_hash_STRING
- && compare == hash_compare_string) {
- /* fast path for string keys */
- DECL_CONST_CAST;
+ if (hash->key_type == Hash_key_type_STRING)
+ {
STRING * const s = (STRING *)PARROT_const_cast(void *, key);
- if (s->hashval)
- hashval = s->hashval;
- else
- hashval = Parrot_str_to_hashval(interp, s);
-
- bucket = hash->index[hashval & hash->mask];
+ hashval = key_hash_STRING(interp, s, hash->seed);
+ bucket = hash->index[hashval & hash->mask];
while (bucket) {
const STRING *s2 = (const STRING *)bucket->key;
- if (s == s2
- || (hashval == s2->hashval
- && STRING_compare(interp, s, s2) == 0))
- return bucket;
-
+ if (s == s2)
+ break;
+ /* manually inline hash_compare_string */
+ if (hashval == s2->hashval){
+ if (s->encoding == s2->encoding){
+ if ((s->bufused == s2->bufused)
+ && (memcmp(s->strstart, s2->strstart, s->bufused) == 0))
+ break;
+ }
+ else
+ if (STRING_compare(interp, s, s2) == 0)
+ break;
+ }
bucket = bucket->next;
}
}
else {
- hashval = hash_val(interp, key, hash->seed);
+ hashval = key_hash(interp, hash, PARROT_const_cast(void *, key));
bucket = hash->index[hashval & hash->mask];
while (bucket) {
- /* key equality is always a match, so it's worth checking */
- if (bucket->key == key
-
- /* ... but the slower comparison is more accurate */
- || ((compare)(interp, key, bucket->key) == 0))
- return bucket;
+ if (hash_compare(interp, hash,
+ PARROT_const_cast(void *, key),
+ bucket->key) == 0)
+ break;
bucket = bucket->next;
}
}
- return NULL;
+ return bucket;
}
-
/*
=item C<void * parrot_hash_get(PARROT_INTERP, const Hash *hash, const void
@@ -1259,42 +1367,39 @@
ARGIN_NULLOK(void *key), ARGIN_NULLOK(void *value))
{
ASSERT_ARGS(parrot_hash_put)
- UINTVAL hashval;
+ size_t hashval;
HashBucket *bucket;
- const hash_hash_key_fn hash_val = hash->hash_val;
- const hash_comp_fn compare = hash->compare;
- if (hash_val == (hash_hash_key_fn)key_hash_STRING
- && compare == hash_compare_string) {
- /* fast path for string keys */
+ if (hash->key_type == Hash_key_type_STRING)
+ {
STRING *s = (STRING *)key;
-
- if (s->hashval)
- hashval = s->hashval;
- else
- hashval = Parrot_str_to_hashval(interp, s);
-
- bucket = hash->index[hashval & hash->mask];
+ hashval = key_hash_STRING(interp, s, hash->seed);
+ bucket = hash->index[hashval & hash->mask];
while (bucket) {
const STRING *s2 = (const STRING *)bucket->key;
-
- if (s == s2
- || (hashval == s2->hashval
- && STRING_compare(interp, s, s2) == 0))
+ if (s == s2)
break;
-
+ /* manually inline hash_compare_string */
+ if (hashval == s2->hashval){
+ if (s->encoding == s2->encoding){
+ if ((s->bufused == s2->bufused)
+ && (memcmp(s->strstart, s2->strstart, s->bufused) == 0))
+ break;
+ }
+ else
+ if (STRING_compare(interp, s, s2) == 0)
+ break;
+ }
bucket = bucket->next;
}
}
else {
- hashval = hash_val(interp, key, hash->seed);
+ hashval = key_hash(interp, hash, key);
bucket = hash->index[hashval & hash->mask];
- /* See if we have an existing value for this key */
while (bucket) {
- /* store hash_val or not */
- if (compare(interp, key, bucket->key) == 0)
+ if (hash_compare(interp, hash, key, bucket->key) == 0)
break;
bucket = bucket->next;
}
@@ -1307,11 +1412,10 @@
else {
/* Get a new bucket off the free list. If the free list is empty, we
expand the hash so we get more items on the free list */
- bucket = hash->free_list;
- if (!bucket) {
+ if (!hash->free_list)
expand_hash(interp, hash);
- bucket = hash->free_list;
- }
+
+ bucket = hash->free_list;
/* Add the value to the new bucket, increasing the count of elements */
++hash->entries;
@@ -1341,13 +1445,12 @@
parrot_hash_delete(PARROT_INTERP, ARGMOD(Hash *hash), ARGIN(void *key))
{
ASSERT_ARGS(parrot_hash_delete)
- const UINTVAL hashval = (hash->hash_val)(interp, key, hash->seed) & hash->mask;
+ const UINTVAL hashval = key_hash(interp, hash, key) & hash->mask;
HashBucket **prev = &hash->index[hashval];
if (*prev) {
- const hash_comp_fn compare = hash->compare;
for (; *prev; prev = &(*prev)->next) {
HashBucket *current = *prev;
- if ((compare)(interp, key, current->key) == 0) {
+ if (hash_compare(interp, hash, key, current->key) == 0) {
*prev = current->next;
--hash->entries;
current->next = hash->free_list;
@@ -1402,12 +1505,6 @@
void * const key = _bucket->key;
switch (hash->entry_type) {
- case enum_type_undef:
- case enum_type_ptr:
- case enum_type_INTVAL:
- valtmp = (void *)_bucket->value;
- break;
-
case enum_type_STRING:
valtmp = _bucket->value;
break;
@@ -1422,6 +1519,12 @@
valtmp = _bucket->value;
break;
+ case enum_type_undef:
+ case enum_type_ptr:
+ case enum_type_INTVAL:
+ valtmp = (void *)_bucket->value;
+ break;
+
default:
valtmp = NULL; /* avoid warning */
Parrot_ex_throw_from_c_args(interp, NULL, -1,
@@ -1529,9 +1632,11 @@
break;
/* Currently PMCs are stringified */
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
ret = (void *)get_integer_pmc(interp, key);
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
ret = (void *)Parrot_str_from_int(interp, key);
break;
default:
@@ -1568,10 +1673,12 @@
}
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
ret = get_string_pmc(interp, key);
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
ret = key;
break;
@@ -1606,6 +1713,7 @@
break;
}
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
{
/* Extract real value from Key (and box it if nessary) */
if (key->vtable->base_type == enum_class_Key)
@@ -1634,6 +1742,7 @@
break;
}
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
{
STRING * const tmp = VTABLE_get_string(interp, key);
if (STRING_IS_NULL(tmp))
@@ -1669,9 +1778,11 @@
ret = (INTVAL)key;
break;
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
ret = VTABLE_get_integer(interp, (PMC *)key);
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
ret = Parrot_str_to_int(interp, (STRING *)key);
break;
default:
@@ -1703,10 +1814,12 @@
break;
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
ret = VTABLE_get_string(interp, (PMC *)key);
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
ret = (STRING *)key;
break;
@@ -1738,9 +1851,11 @@
ret = get_integer_pmc(interp, (INTVAL)key);
break;
case Hash_key_type_PMC:
+ case Hash_key_type_PMC_ptr:
ret = (PMC*)key;
break;
case Hash_key_type_STRING:
+ case Hash_key_type_STRING_enc:
ret = get_string_pmc(interp, (STRING*)key);
break;
default:
Modified: branches/hash_inlined_func/src/pmc/addrregistry.pmc
==============================================================================
--- branches/hash_inlined_func/src/pmc/addrregistry.pmc Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/src/pmc/addrregistry.pmc Wed Sep 8 01:16:54 2010 (r48846)
@@ -46,9 +46,7 @@
VTABLE void init() {
Hash *registry = parrot_create_hash(INTERP,
enum_type_int,
- Hash_key_type_PMC,
- hash_compare_int,
- key_hash_int);
+ Hash_key_type_PMC_ptr);
SET_ATTR_hash(INTERP, SELF, registry);
PObj_custom_mark_destroy_SETALL(SELF);
Modified: branches/hash_inlined_func/src/pmc/callcontext.pmc
==============================================================================
--- branches/hash_inlined_func/src/pmc/callcontext.pmc Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/src/pmc/callcontext.pmc Wed Sep 8 01:16:54 2010 (r48846)
@@ -390,9 +390,7 @@
if (!hash) {
hash = parrot_create_hash(interp,
enum_type_ptr,
- Hash_key_type_STRING,
- hash_compare_string,
- (hash_hash_key_fn)key_hash_STRING);
+ Hash_key_type_STRING);
SETATTR_CallContext_hash(interp, SELF, hash);
}
Modified: branches/hash_inlined_func/src/pmc/class.pmc
==============================================================================
--- branches/hash_inlined_func/src/pmc/class.pmc Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/src/pmc/class.pmc Wed Sep 8 01:16:54 2010 (r48846)
@@ -141,11 +141,6 @@
__attribute__nonnull__(3)
__attribute__nonnull__(4);
-static size_t key_hash_pointer(SHIM_INTERP,
- ARGIN(const void *value),
- size_t seed)
- __attribute__nonnull__(2);
-
PARROT_CANNOT_RETURN_NULL
static STRING * make_class_name(PARROT_INTERP, ARGIN(PMC *SELF))
__attribute__nonnull__(1)
@@ -174,8 +169,6 @@
, PARROT_ASSERT_ARG(object) \
, PARROT_ASSERT_ARG(all_parents) \
, PARROT_ASSERT_ARG(init))
-#define ASSERT_ARGS_key_hash_pointer __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
- PARROT_ASSERT_ARG(value))
#define ASSERT_ARGS_make_class_name __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
PARROT_ASSERT_ARG(interp) \
, PARROT_ASSERT_ARG(SELF))
@@ -184,22 +177,6 @@
/*
-=item C<static size_t key_hash_pointer(PARROT_INTERP, const void *value, size_t
-seed)>
-
-=cut
-
-*/
-
-static size_t
-key_hash_pointer(SHIM_INTERP, ARGIN(const void *value), size_t seed)
-{
- ASSERT_ARGS(key_hash_pointer)
- return ((size_t) value ^ seed);
-}
-
-/*
-
=item C<static int cache_class_attribs(PARROT_INTERP, PMC *cur_class, PMC
*attrib_index, PMC *cache, int cur_index)>
@@ -685,9 +662,10 @@
_class->vtable_overrides = Parrot_pmc_new(INTERP, enum_class_Hash);
_class->parent_overrides = Parrot_pmc_new(INTERP, enum_class_Hash);
+
_class->isa_cache = parrot_create_hash(INTERP,
- enum_type_INTVAL, Hash_key_type_PMC,
- (hash_comp_fn)hash_compare_pointer, (hash_hash_key_fn)key_hash_pointer);
+ enum_type_INTVAL, Hash_key_type_PMC_ptr);
+
/* We put ourself on the all parents list. */
VTABLE_push_pmc(INTERP, _class->all_parents, SELF);
Modified: branches/hash_inlined_func/src/pmc/hash.pmc
==============================================================================
--- branches/hash_inlined_func/src/pmc/hash.pmc Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/src/pmc/hash.pmc Wed Sep 8 01:16:54 2010 (r48846)
@@ -141,9 +141,7 @@
attr->hash = parrot_create_hash(INTERP,
(PARROT_DATA_TYPE)value_type,
- Hash_key_type_STRING,
- hash_compare_string,
- (hash_hash_key_fn)key_hash_STRING);
+ Hash_key_type_STRING);
PObj_custom_mark_destroy_SETALL(SELF);
}
@@ -233,23 +231,17 @@
if (type == Hash_key_type_STRING)
new_hash = parrot_create_hash(INTERP,
entry_type,
- Hash_key_type_STRING,
- hash_compare_string,
- (hash_hash_key_fn)key_hash_STRING);
+ Hash_key_type_STRING);
else if (type == Hash_key_type_int)
/* new_int_hash set BOTH keys and values to INTVAL */
new_hash = parrot_create_hash(INTERP,
entry_type,
- Hash_key_type_int,
- hash_compare_int,
- key_hash_int);
+ Hash_key_type_int);
else if (type == Hash_key_type_PMC)
/* new_int_hash set BOTH keys and values to INTVAL */
new_hash = parrot_create_hash(INTERP,
entry_type,
- Hash_key_type_PMC,
- (hash_comp_fn)hash_compare_pmc,
- (hash_hash_key_fn)key_hash_PMC);
+ Hash_key_type_PMC);
else
/* We probably will not implement other types of keys. They are way
* too dangerous to use from PIR */
@@ -310,9 +302,7 @@
case enum_type_PMC:
new_hash = parrot_create_hash(INTERP,
(PARROT_DATA_TYPE)type,
- old_hash ? old_hash->key_type : Hash_key_type_STRING,
- old_hash ? old_hash->compare : hash_compare_string,
- old_hash ? old_hash->hash_val : (hash_hash_key_fn)key_hash_STRING);
+ old_hash ? old_hash->key_type : Hash_key_type_STRING);
break;
default:
Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_UNIMPLEMENTED,
Modified: branches/hash_inlined_func/src/pmc/stringbuilder.pmc
==============================================================================
--- branches/hash_inlined_func/src/pmc/stringbuilder.pmc Wed Sep 8 01:12:20 2010 (r48845)
+++ branches/hash_inlined_func/src/pmc/stringbuilder.pmc Wed Sep 8 01:16:54 2010 (r48846)
@@ -139,7 +139,7 @@
*/
VTABLE STRING *get_string() {
- STRING *buffer;
+ STRING *buffer, *result;
GET_ATTR_buffer(INTERP, SELF, buffer);
/* We need to build a new string because outside of StringBuilder
* strings are immutable. */
More information about the parrot-commits
mailing list