[svn:parrot] r43586 - in trunk: . include/parrot src src/pmc t/native_pbc t/pmc

bacek at svn.parrot.org bacek at svn.parrot.org
Mon Jan 25 13:50:25 UTC 2010


Author: bacek
Date: Mon Jan 25 13:50:23 2010
New Revision: 43586
URL: https://trac.parrot.org/parrot/changeset/43586

Log:
Merge branch orderedhash_revamp into trunk

Modified:
   trunk/MANIFEST.SKIP
   trunk/include/parrot/hash.h
   trunk/src/pmc/orderedhash.pmc
   trunk/src/pmc/orderedhashiterator.pmc
   trunk/src/pmc/unmanagedstruct.pmc
   trunk/src/pmc_freeze.c
   trunk/t/native_pbc/annotations.pbc
   trunk/t/native_pbc/integer_1.pbc
   trunk/t/native_pbc/number_1.pbc
   trunk/t/native_pbc/string_1.pbc
   trunk/t/pmc/orderedhash.t

Modified: trunk/MANIFEST.SKIP
==============================================================================
--- trunk/MANIFEST.SKIP	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/MANIFEST.SKIP	Mon Jan 25 13:50:23 2010	(r43586)
@@ -1,6 +1,6 @@
 # ex: set ro:
 # $Id$
-# generated by tools/dev/mk_manifest_and_skip.pl Wed Dec 16 15:31:13 2009 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Sat Jan 23 10:27:18 2010 UT
 #
 # This file should contain a transcript of the svn:ignore properties
 # of the directories in the Parrot subversion repository. (Needed for
@@ -83,12 +83,6 @@
 ^myconfig/
 ^parrot$
 ^parrot/
-^parrot-nqp$
-^parrot-nqp/
-^parrot-nqp\.c$
-^parrot-nqp\.c/
-^parrot-nqp\.pbc$
-^parrot-nqp\.pbc/
 ^parrot\.ilk$
 ^parrot\.ilk/
 ^parrot\.iss$
@@ -149,16 +143,6 @@
 ^vc70\.pdb/
 ^vtable\.dump$
 ^vtable\.dump/
-# generated from svn:ignore of 'compilers/data_json/'
-^compilers/data_json/Makefile$
-^compilers/data_json/Makefile/
-^compilers/data_json/data_json\.pbc$
-^compilers/data_json/data_json\.pbc/
-# generated from svn:ignore of 'compilers/data_json/data_json/'
-^compilers/data_json/data_json/.*\.pbc$
-^compilers/data_json/data_json/.*\.pbc/
-^compilers/data_json/data_json/.*\.pir$
-^compilers/data_json/data_json/.*\.pir/
 # generated from svn:ignore of 'compilers/imcc/'
 ^compilers/imcc/.*\.flag$
 ^compilers/imcc/.*\.flag/
@@ -279,8 +263,6 @@
 ^docs/.*\.tmp/
 ^docs/Makefile$
 ^docs/Makefile/
-^docs/doc-prep$
-^docs/doc-prep/
 ^docs/html$
 ^docs/html/
 ^docs/packfile-c\.pod$
@@ -315,8 +297,8 @@
 ^examples/languages/abc/.*\.obj/
 ^examples/languages/abc/.*\.pbc$
 ^examples/languages/abc/.*\.pbc/
-^examples/languages/abc/MANIFEST$
-^examples/languages/abc/MANIFEST/
+^examples/languages/abc/Makefile$
+^examples/languages/abc/Makefile/
 ^examples/languages/abc/abc$
 ^examples/languages/abc/abc/
 ^examples/languages/abc/installable_abc$
@@ -348,10 +330,12 @@
 ^examples/languages/squaak/.*\.obj/
 ^examples/languages/squaak/.*\.pbc$
 ^examples/languages/squaak/.*\.pbc/
-^examples/languages/squaak/MANIFEST$
-^examples/languages/squaak/MANIFEST/
+^examples/languages/squaak/Makefile$
+^examples/languages/squaak/Makefile/
 ^examples/languages/squaak/installable_squaak$
 ^examples/languages/squaak/installable_squaak/
+^examples/languages/squaak/man$
+^examples/languages/squaak/man/
 ^examples/languages/squaak/squaak$
 ^examples/languages/squaak/squaak/
 # generated from svn:ignore of 'examples/languages/squaak/src/'
@@ -385,8 +369,8 @@
 ^examples/pir/befunge/.*\.obj/
 ^examples/pir/befunge/.*\.pbc$
 ^examples/pir/befunge/.*\.pbc/
-^examples/pir/befunge/MANIFEST$
-^examples/pir/befunge/MANIFEST/
+^examples/pir/befunge/Makefile$
+^examples/pir/befunge/Makefile/
 ^examples/pir/befunge/befunge$
 ^examples/pir/befunge/befunge/
 ^examples/pir/befunge/installable_befunge$
@@ -461,11 +445,6 @@
 # generated from svn:ignore of 'ext/Parrot-Embed/t/'
 ^ext/Parrot-Embed/t/.*\.pbc$
 ^ext/Parrot-Embed/t/.*\.pbc/
-# generated from svn:ignore of 'ext/nqp-rx/'
-^ext/nqp-rx/.*\.pbc$
-^ext/nqp-rx/.*\.pbc/
-^ext/nqp-rx/Makefile$
-^ext/nqp-rx/Makefile/
 # generated from svn:ignore of 'include/parrot/'
 ^include/parrot/.*\.tmp$
 ^include/parrot/.*\.tmp/
@@ -498,9 +477,6 @@
 ^include/parrot/oplib/.*_ops_switch\.h/
 ^include/parrot/oplib/ops\.h$
 ^include/parrot/oplib/ops\.h/
-# generated from svn:ignore of 'include/pmc/'
-^include/pmc/.*\.h$
-^include/pmc/.*\.h/
 # generated from svn:ignore of 'lib/'
 ^lib/DumbLink\.pm$
 ^lib/DumbLink\.pm/
@@ -578,9 +554,6 @@
 # generated from svn:ignore of 'runtime/parrot/library/Config/'
 ^runtime/parrot/library/Config/.*\.pbc$
 ^runtime/parrot/library/Config/.*\.pbc/
-# generated from svn:ignore of 'runtime/parrot/library/Configure/'
-^runtime/parrot/library/Configure/.*\.pbc$
-^runtime/parrot/library/Configure/.*\.pbc/
 # generated from svn:ignore of 'runtime/parrot/library/Data/'
 ^runtime/parrot/library/Data/.*\.pbc$
 ^runtime/parrot/library/Data/.*\.pbc/
@@ -694,8 +667,6 @@
 ^src/atomic/.*\.o$
 ^src/atomic/.*\.o/
 # generated from svn:ignore of 'src/call/'
-^src/call/.*\.o$
-^src/call/.*\.o/
 ^src/call/.*\.obj$
 ^src/call/.*\.obj/
 ^src/call/.*\.str$
@@ -814,8 +785,6 @@
 ^src/gc/Makefile$
 ^src/gc/Makefile/
 # generated from svn:ignore of 'src/interp/'
-^src/interp/.*\.o$
-^src/interp/.*\.o/
 ^src/interp/.*\.str$
 ^src/interp/.*\.str/
 # generated from svn:ignore of 'src/io/'
@@ -854,13 +823,6 @@
 ^src/pmc/.*\.tmp/
 ^src/pmc/Makefile$
 ^src/pmc/Makefile/
-# generated from svn:ignore of 'src/runcore/'
-^src/runcore/.*\.o$
-^src/runcore/.*\.o/
-^src/runcore/.*\.obj$
-^src/runcore/.*\.obj/
-^src/runcore/.*\.str$
-^src/runcore/.*\.str/
 # generated from svn:ignore of 'src/string/'
 ^src/string/.*\.o$
 ^src/string/.*\.o/

Modified: trunk/include/parrot/hash.h
==============================================================================
--- trunk/include/parrot/hash.h	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/include/parrot/hash.h	Mon Jan 25 13:50:23 2010	(r43586)
@@ -80,6 +80,16 @@
 
 typedef void (*value_free)(void *);
 
+/* To avoid creating OrderedHashItem PMC we reuse FixedPMCArray PMC */
+/* So, there is indexes to avoid using of "magick constants" */
+enum ORDERED_HASH_ITEM_PART {
+    ORDERED_HASH_ITEM_KEY   = 0,
+    ORDERED_HASH_ITEM_VALUE = 1,
+    ORDERED_HASH_ITEM_PREV  = 2,
+    ORDERED_HASH_ITEM_NEXT  = 3,
+    ORDERED_HASH_ITEM_MAX   = 4,
+};
+
 /* HEADERIZER BEGIN: src/hash.c */
 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
 

Modified: trunk/src/pmc/orderedhash.pmc
==============================================================================
--- trunk/src/pmc/orderedhash.pmc	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/src/pmc/orderedhash.pmc	Mon Jan 25 13:50:23 2010	(r43586)
@@ -8,28 +8,66 @@
 
 =head1 DESCRIPTION
 
-C<OrderedHash> extends C<Hash> to provide the interfaces of C<array> and
-C<hash>. To achieve ordering, hash there are a few restrictions:
-C<delete_keyed> never removes items; they are just nulled.
-
-Please note that if values are set via integer idx, these indices have to be in
-strict order. Using C<push_xx> simplifies this task.  This creates a key
-"\1idx" for C<idx> and is therefore not fully transparent.
+C<OrderedHash> provide the interfaces of C<array> and
+C<hash>.
 
-There are two iterator interfaces:
+Some limitations:
 
 =over 4
 
-=item * retrieve values (in creation order)
+=item *
 
-Please note that after a C<delete_keyed> operation, iterating over
-values doesn't work any more.  You'll get an error 'No such key'.
+Keys are always STRING*.
 
-=item * retrieve keys (in creation order)
+=item *
+
+Values are always PMC*.
+
+=back
+
+To archive ordering for each item we store:
+
+=over 4
+
+=item * C<key>
+
+Original key
+
+=item * C<value>
+
+Original value
+
+=item * C<next>
+
+Pointer to next C<item>
+
+=item * C<prev>
+
+Pointer to previous C<item>
+
+=back
+
+OrderedHash stores next things:
+
+=over 4
+
+=item * C<hash>
+
+Lookup hash for values.
+
+=item * C<first>
+
+Pointer to first inserted value.
+
+=item * C<last>
+
+Pointer to last inserter value.
 
 =back
 
-See F<t/pmc/orderedhash.t>.
+See F<t/pmc/orderedhash.t> for test cases.
+
+Overall design heavily inspired by C<Tie::StoredOrderHash>.
 
 =head2 Methods
 
@@ -39,39 +77,127 @@
 
 */
 
-pmclass OrderedHash extends Hash provides array provides hash {
+/* Create new stored item. FixedPMCArray of (key, value, prev, next). */
+static PMC*
+create_item(PARROT_INTERP, ARGIN(PMC *key), ARGIN(PMC *value)) {
+    PMC *ret = pmc_new(interp, enum_class_FixedPMCArray);
+    VTABLE_set_integer_native(interp, ret, ORDERED_HASH_ITEM_MAX);
+
+    VTABLE_set_pmc_keyed_int(interp, ret, ORDERED_HASH_ITEM_KEY, key);
+    VTABLE_set_pmc_keyed_int(interp, ret, ORDERED_HASH_ITEM_VALUE, value);
+    return ret;
+};
+
+/* Get list_item by index */
+static PMC*
+get_list_item(PARROT_INTERP, ARGIN(PMC *self), INTVAL idx) {
+    Parrot_OrderedHash_attributes *attrs = PARROT_ORDEREDHASH(self);
+    INTVAL                         n = VTABLE_elements(interp, attrs->hash);
+    INTVAL                         pos;
+    PMC                           *list_entry = attrs->first;
+
+    if (idx < -n)
+        idx = -idx - n - 1;
+    else if (idx < 0)
+        idx += n;
+
+    /* Iterate over linked list to get list_item */
+    for (pos = 0; pos < idx; ++pos) {
+        list_entry = VTABLE_get_pmc_keyed_int(interp, list_entry, ORDERED_HASH_ITEM_NEXT);
+    }
+    return list_entry;
+}
+
+/* Find first/last in cloned/thawed OrderedHash */
+/* Parameter C<pmc_hash> is Hash, not OrderedHash */
+static void
+find_bounds(PARROT_INTERP, PMC *pmc_hash, PMC **first, PMC **last) {
+    PMC *iter = VTABLE_get_iter(interp, pmc_hash);
+    while (VTABLE_get_bool(interp, iter)) {
+        PMC *item  = VTABLE_shift_pmc(interp, iter);
+        PMC *entry = VTABLE_get_pmc_keyed(interp, pmc_hash, item);
+        /* First entry doesn't have prev */
+        PMC *tmp   = VTABLE_get_pmc_keyed_int(interp, entry, ORDERED_HASH_ITEM_PREV);
+        if (PMC_IS_NULL(tmp))
+            *first = entry;
+        /* Last entry doesn't have next */
+        tmp   = VTABLE_get_pmc_keyed_int(interp, entry, ORDERED_HASH_ITEM_NEXT);
+        if (PMC_IS_NULL(tmp))
+            *last = entry;
+    }
+}
+
+/* Helpers for boxing values */
+static PMC*
+box_string(PARROT_INTERP, STRING *str) {
+    PMC * const ret = pmc_new(interp, Parrot_get_ctx_HLL_type(interp,
+                enum_class_String));
+    VTABLE_set_string_native(interp, ret, str);
+    return ret;
+}
+
+static PMC*
+box_integer(PARROT_INTERP, INTVAL val) {
+    PMC * const ret = pmc_new(interp, Parrot_get_ctx_HLL_type(interp,
+                enum_class_Integer));
+    VTABLE_set_integer_native(interp, ret, val);
+    return ret;
+}
+
+static PMC*
+box_number(PARROT_INTERP, FLOATVAL val) {
+    PMC * const ret = pmc_new(interp, Parrot_get_ctx_HLL_type(interp,
+                enum_class_Float));
+    VTABLE_set_number_native(interp, ret, val);
+    return ret;
+}
+
+
+pmclass OrderedHash need_ext provides array provides hash {
+    ATTR PMC    *hash;   /* key to item tuple */
+    ATTR PMC    *first;  /* Pointer to first inserted value  */
+    ATTR PMC    *last;   /* Pointer to last inserted value   */
 
 /*
 
-=item C<void mark()>
+=item C<void init()>
 
-Marks the OrderedHash as live.
+Create new instance of OrderedHash.
 
 =cut
 
 */
 
-    VTABLE void mark() {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        INTVAL  i;
+    VTABLE void init() {
+        Parrot_OrderedHash_attributes * const attrs =
+                mem_allocate_zeroed_typed(Parrot_OrderedHash_attributes);
 
-        if (!h)
-            return;
+        PMC_data(SELF)  = attrs;
+        attrs->hash     = pmc_new(INTERP, enum_class_Hash);
+        attrs->first    = PMCNULL;
+        attrs->last     = PMCNULL;
 
-        for (i = h->mask; i >= 0; --i) {
-            HashBucket *b = h->bi[i];
+        PObj_custom_mark_destroy_SETALL(SELF);
+    }
 
-            while (b) {
+/*
 
-                if (b->key) {
-                    Parrot_gc_mark_PObj_alive(interp, (PObj *)b->key);
-                    if (b->value)
-                        Parrot_gc_mark_PObj_alive(interp, (PObj *)b->value);
-                }
+=item C<void mark()>
 
-                b = b->next;
-            }
-        }
+Marks the OrderedHash as live.
+
+=cut
+
+*/
+
+    VTABLE void mark() {
+        Parrot_OrderedHash_attributes * const attrs =
+                PARROT_ORDEREDHASH(SELF);
+
+        if (attrs->hash)
+            Parrot_gc_mark_PObj_alive(INTERP, (PObj *)attrs->hash);
+
+        /* Don't mark C<first> and C<last>. They are in lookup hash anyway */
     }
 
 /*
@@ -90,195 +216,247 @@
 
 /*
 
-=item C<PMC *get_pmc_keyed(PMC *key)>
+=item C<INTVAL elements()>
 
-=item C<PMC *get_pmc_keyed_int(INTVAL key)>
+=item C<INTVAL get_integer()>
 
-=item C<PMC *get_pmc_keyed_str(STRING *key)>
+=item C<FLOATVAL get_number()>
+
+Returns the size of the hash.
 
 =cut
 
 */
 
-    VTABLE PMC *get_pmc_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
-        HashBucket *b;
+    VTABLE INTVAL get_integer() {
+        return STATICSELF.elements();
+    }
 
-        if (idx < 0)
-            idx += n;
+    VTABLE FLOATVAL get_number() {
+        return SELF.get_integer();
+    }
 
-        if (idx < 0 || idx >= n)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
-                "OrderedHash: index out of bounds!");
+    VTABLE INTVAL elements() {
+        return VTABLE_elements(INTERP, PARROT_ORDEREDHASH(SELF)->hash);
+    }
 
-        b = h->bs + idx;
+/*
 
-        if (b->key)
-            return (PMC *)b->value;
+=item C<set_pmc_keyed(PMC *key, PMC *value)>
 
-        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
-            "OrderedHash: No such key");
-    }
+Main set function.
 
-    VTABLE PMC *get_pmc_keyed(PMC *key) {
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
-            PMC * const item = SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
-            PMC * const next = VTABLE_shift_pmc(INTERP, key);
+=cut
 
-            if (!next)
-                return item;
+*/
+    VTABLE void set_pmc_keyed(PMC *key, PMC *value) {
+        Parrot_OrderedHash_attributes *attrs =
+                PARROT_ORDEREDHASH(SELF);
 
-            return VTABLE_get_pmc_keyed(INTERP, item, next);
+        /* Check for old entry */
+        PMC *list_entry = VTABLE_get_pmc_keyed(INTERP, attrs->hash, key);
+        if (!PMC_IS_NULL(list_entry)) {
+            /* We have old entry. Just update value */
+            PMC *nextkey = key_next(INTERP, key);
+            if (nextkey) {
+                PMC *old_value = VTABLE_get_pmc_keyed_int(INTERP, list_entry,
+                        ORDERED_HASH_ITEM_VALUE);
+                VTABLE_set_pmc_keyed(INTERP, value, nextkey, value);
+            }
+            else
+                VTABLE_set_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_VALUE, value);
+            return;
         }
 
-        return INTERP->vtables[enum_class_Hash]->get_pmc_keyed(INTERP, SELF, key);
-    }
+        /* Create new entry */
+        list_entry = pmc_new(INTERP, enum_class_FixedPMCArray);
+        VTABLE_set_integer_native(INTERP, list_entry, ORDERED_HASH_ITEM_MAX);
+        VTABLE_set_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_VALUE, value);
+        VTABLE_set_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_KEY, key);
+
+        /* .. and link it */
+        if (!PMC_IS_NULL(attrs->last)) {
+            VTABLE_set_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_PREV, attrs->last);
+            VTABLE_set_pmc_keyed_int(INTERP, attrs->last, ORDERED_HASH_ITEM_NEXT, list_entry);
+        }
+        attrs->last = list_entry;
+        if (PMC_IS_NULL(attrs->first))
+            attrs->first = list_entry;
 
+        /* .. and store it */
+        VTABLE_set_pmc_keyed(INTERP, attrs->hash, key, list_entry);
+    }
 /*
 
-=item C<STRING *get_string_keyed(PMC *key)>
+=item C<void set_integer_keyed(INTVAL key, INTVAL value)>
 
-=item C<STRING *get_string_keyed_int(INTVAL key)>
+=item C<void set_number_keyed(INTVAL key, FLOATVAL value)>
 
-=item C<STRING *get_string_keyed_str(STRING *key)>
+=item C<void set_string_keyed(INTVAL key, STRING *value)>
+
+Sets the PMC value of the element at index C<key> to C<val>.
 
 =cut
 
 */
 
-    VTABLE STRING *get_string_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
+    VTABLE void set_integer_keyed(PMC *key, INTVAL value) {
+        PMC * const v = box_integer(INTERP, value);
+        SELF.set_pmc_keyed(key, v);
+    }
 
-        HashBucket *b;
+    VTABLE void set_number_keyed(PMC *key, FLOATVAL value) {
+        PMC * const v = box_number(INTERP, value);
+        SELF.set_pmc_keyed(key, v);
+    }
 
-        if (idx < 0)
-            idx += n;
+    VTABLE void set_string_keyed(PMC *key, STRING *value) {
+        PMC * const v = box_string(INTERP, value);
+        SELF.set_pmc_keyed(key, v);
+    }
 
-        if (idx < 0 || idx >= n)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
-                "OrderedHash: index out of bounds!");
+/*
 
-        b = h->bs + idx;
+=item C<void set_pmc_keyed_str(STRING *key, PMC *val)>
 
-        if (b->key)
-            return VTABLE_get_string(INTERP, (PMC *)b->value);
+=item C<void set_integer_keyed_str(STRING *key, INTVAL value)>
 
-        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
-            "OrderedHash: No such key");
-    }
+=item C<void set_number_keyed_str(STRING *key, FLOATVAL value)>
 
-    VTABLE STRING *get_string_keyed(PMC *key) {
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
-            PMC * const item = SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
-            PMC * const next = VTABLE_shift_pmc(INTERP, key);
+=item C<void set_string_keyed_str(STRING *key, STRING *value)>
 
-            if (!next)
-                return VTABLE_get_string(INTERP, item);
+Sets the PMC value of the element at index C<key> to C<val>.
 
-            return VTABLE_get_string_keyed(INTERP, item, next);
-        }
+=cut
+
+*/
 
-        return INTERP->vtables[enum_class_Hash]->get_string_keyed(INTERP, SELF, key);
+    VTABLE void set_pmc_keyed_str(STRING *key, PMC *value) {
+        PMC *pkey = box_string(INTERP, key);
+        VTABLE_set_pmc_keyed(INTERP, SELF, pkey, value);
     }
-/*
 
-=item C<INTVAL get_integer_keyed(PMC *key)>
+    VTABLE void set_string_keyed_str(STRING *key, STRING *value) {
+        PMC * const v = box_string(INTERP, value);
+        STATICSELF.set_pmc_keyed_str(key, v);
+    }
 
-=item C<INTVAL get_integer_keyed_str(STRING *key)>
+    VTABLE void set_integer_keyed_str(STRING *key, INTVAL value) {
+        PMC * const v = box_integer(INTERP, value);
+        STATICSELF.set_pmc_keyed_str(key, v);
+    }
 
-=item C<INTVAL get_integer_keyed_int(INTVAL key)>
+    VTABLE void set_number_keyed_str(STRING *key, FLOATVAL value) {
+        PMC * const v = box_number(INTERP, value);
+        STATICSELF.set_pmc_keyed_str(key, v);
+    }
 
-Returns the integer value associated with C<key>.
+/*
+
+=item C<PMC *get_pmc_keyed(PMC *key)>
+
+=item C<PMC *get_pmc_keyed_int(INTVAL key)>
+
+=item C<PMC *get_pmc_keyed_str(STRING *key)>
 
 =cut
 
 */
 
-    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
-        HashBucket *b;
+    VTABLE PMC *get_pmc_keyed_int(INTVAL idx) {
+        PMC *list_entry = get_list_item(INTERP, SELF, idx);
 
-        if (idx < 0)
-            idx += n;
+        if (PMC_IS_NULL(list_entry))
+            return PMCNULL;
 
-        if (idx < 0 || idx >= n)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
-                "OrderedHash: index out of bounds!");
+        return VTABLE_get_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_VALUE);
+    }
 
-        b = h->bs + idx;
+    VTABLE PMC *get_pmc_keyed(PMC *key) {
+        PMC * item;
+        /* Access by integer index */
+        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
+            return SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
+        }
 
-        if (b->key)
-            return VTABLE_get_integer(INTERP, (PMC *)b->value);
+        item = VTABLE_get_pmc_keyed(INTERP, PARROT_ORDEREDHASH(SELF)->hash, key);
+        if (PMC_IS_NULL(item))
+            return PMCNULL;
+        return VTABLE_get_pmc_keyed_int(INTERP, item, ORDERED_HASH_ITEM_VALUE);
+    }
 
-        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
-            "OrderedHash: No such key");
+    VTABLE PMC *get_pmc_keyed_str(STRING *key) {
+        PMC *pkey = pmc_new(interp, Parrot_get_ctx_HLL_type(interp, enum_class_String));
+        VTABLE_set_string_native(INTERP, pkey, key);
+        return STATICSELF.get_pmc_keyed(pkey);
     }
+/*
 
-    VTABLE INTVAL get_integer_keyed(PMC *key) {
+=item C<STRING *get_string_keyed(PMC *key)>
 
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
-            PMC * const item = SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
-            PMC * const next = VTABLE_shift_pmc(INTERP, key);
+=item C<STRING *get_string_keyed_int(INTVAL key)>
 
-            if (!next)
-                return VTABLE_get_integer(INTERP, item);
+=item C<STRING *get_string_keyed_str(STRING *key)>
 
-            return VTABLE_get_integer_keyed(INTERP, item, next);
-        }
+=cut
+
+*/
 
-        return INTERP->vtables[enum_class_Hash]->get_integer_keyed(INTERP, SELF, key);
+    VTABLE STRING *get_string_keyed_int(INTVAL idx) {
+        PMC * const item = VTABLE_get_pmc_keyed_int(INTERP, SELF, idx);
+        return VTABLE_get_string(INTERP, item);
     }
 
+    VTABLE STRING *get_string_keyed(PMC *key) {
+        PMC * const item = VTABLE_get_pmc_keyed(INTERP, SELF, key);
+        return VTABLE_get_string(INTERP, item);
+    }
 /*
 
-=item C<FLOATVAL get_number_keyed(PMC *key)>
+=item C<INTVAL get_integer_keyed(PMC *key)>
 
-=item C<FLOATVAL get_number_keyed_int(INTVAL key)>
+=item C<INTVAL get_integer_keyed_str(STRING *key)>
 
-=item C<FLOATVAL get_number_keyed_str(STRING *key)>
+=item C<INTVAL get_integer_keyed_int(INTVAL key)>
 
-Returns the floating-point value for the element at C<key>.
+Returns the integer value associated with C<key>.
 
 =cut
 
 */
 
-    VTABLE FLOATVAL get_number_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
-        HashBucket *b;
+    VTABLE INTVAL get_integer_keyed_int(INTVAL idx) {
+        PMC * const item = VTABLE_get_pmc_keyed_int(INTERP, SELF, idx);
+        return VTABLE_get_integer(INTERP, item);
+    }
 
-        if (idx < 0)
-            idx += n;
+    VTABLE INTVAL get_integer_keyed(PMC *key) {
+        PMC * const item = VTABLE_get_pmc_keyed(INTERP, SELF, key);
+        return VTABLE_get_integer(INTERP, item);
+    }
 
-        if (idx < 0 || idx >= n)
-            Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
-                "OrderedHash: index out of bounds!");
+/*
 
-        b = h->bs + idx;
+=item C<FLOATVAL get_number_keyed(PMC *key)>
 
-        if (b->key)
-            return VTABLE_get_number(INTERP, (PMC *)b->value);
+=item C<FLOATVAL get_number_keyed_int(INTVAL key)>
 
-        Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_KEY_NOT_FOUND,
-            "OrderedHash: No such key");
-    }
+=item C<FLOATVAL get_number_keyed_str(STRING *key)>
 
-    VTABLE FLOATVAL get_number_keyed(PMC *key) {
-        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
-            PMC * const item = SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
-            PMC * const next = VTABLE_shift_pmc(INTERP, key);
+Returns the floating-point value for the element at C<key>.
 
-            if (!next)
-                return VTABLE_get_number(INTERP, item);
+=cut
 
-            return VTABLE_get_number_keyed(INTERP, item, next);
-        }
+*/
 
-        return SUPER(key);
+    VTABLE FLOATVAL get_number_keyed_int(INTVAL idx) {
+        PMC * const item = VTABLE_get_pmc_keyed_int(INTERP, SELF, idx);
+        return VTABLE_get_number(INTERP, item);
+    }
+
+    VTABLE FLOATVAL get_number_keyed(PMC *key) {
+        PMC * const item = VTABLE_get_pmc_keyed(INTERP, SELF, key);
+        return VTABLE_get_number(INTERP, item);
     }
 
 /*
@@ -299,9 +477,10 @@
 */
 
     VTABLE void set_pmc_keyed_int(INTVAL idx, PMC *val) {
-        Hash * const     h = (Hash *)SELF.get_pointer();
-        const INTVAL     n = h->entries;
+        const INTVAL   n   = STATICSELF.elements();
         STRING * const fmt = CONST_STRING(INTERP, "\1%d");
+        PMC           *list_entry;
+        INTVAL         pos;
 
         if (idx < -n)
             idx = -idx - n - 1;
@@ -314,12 +493,9 @@
             SELF.set_pmc_keyed_str(key, val);
         }
         else {
-            HashBucket * const b = h->bs + idx;
-
-            if (!b->key)
-                b->key = Parrot_sprintf_s(INTERP, fmt, idx);
-
-            b->value     = val;
+            list_entry = get_list_item(INTERP, SELF, idx);
+            PARROT_ASSERT(!PMC_IS_NULL(list_entry));
+            VTABLE_set_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_VALUE, val);
         }
     }
 
@@ -390,60 +566,26 @@
 */
 
     VTABLE INTVAL exists_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
-        HashBucket  *b;
-
-        if (idx < 0)
-            idx += n;
-
-        if (idx < 0 || idx >= n)
-            return 0;
-
-        b = h->bs + idx;
-
-        if (b->key)
-            return 1;
-
-        return 0;
+        return (idx >= 0) && (idx < STATICSELF.elements());
     }
 
     VTABLE INTVAL exists_keyed(PMC *key) {
-        if (PObj_get_FLAGS(key) & KEY_integer_FLAG) {
-            PMC        *item, *next;
-            HashBucket *b;
-            Hash       * const h   = (Hash *)SELF.get_pointer();
-            INTVAL             idx = VTABLE_get_integer(INTERP, key);
-            const INTVAL       n   = h->entries;
-
-            if (idx < 0)
-                idx += n;
-
-            if (idx < 0 || idx >= n)
-                return 0;
-
-            b = h->bs + idx;
-
-            if (!b->key)
-                return 0;
-
-            item = (PMC *)b->value;
-            next = VTABLE_shift_pmc(INTERP, key);
+        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
+            /* Don't fetch item prematurely. It's costy */
+            INTVAL    intval = VTABLE_get_integer(INTERP, key);
+            PMC * const next = VTABLE_shift_pmc(INTERP, key);
 
             if (!next)
-                return 1;
+                return STATICSELF.exists_keyed_int(intval);
 
-            return VTABLE_exists_keyed(INTERP, item, next);
+            return VTABLE_exists_keyed(INTERP, STATICSELF.get_pmc_keyed_int(intval), next);
         }
 
-        return SUPER(key);
+        return VTABLE_exists_keyed_str(INTERP, SELF, VTABLE_get_string(INTERP, key));
     }
 
     VTABLE INTVAL exists_keyed_str(STRING *key) {
-        const Hash       * const h = (Hash *)SELF.get_pointer();
-        const HashBucket * const b = parrot_hash_get_bucket(INTERP, h, key);
-
-        return (b && b->key);
+        return VTABLE_exists_keyed_str(INTERP, PARROT_ORDEREDHASH(SELF)->hash, key);
     }
 
 /*
@@ -459,55 +601,32 @@
 */
 
     VTABLE INTVAL defined_keyed(PMC *key) {
-        if (PObj_get_FLAGS(key) & KEY_integer_FLAG) {
-            Hash * const h   = (Hash *)SELF.get_pointer();
-            INTVAL       idx = VTABLE_get_integer(INTERP, key);
-            const INTVAL n   = h->entries;
-
-            HashBucket *b;
-            PMC        *item, *next;
-
-            if (idx < 0)
-                idx += n;
-
-            /* XXX non-existent is undefined - is this correct */
-            if (idx < 0 || idx >= n)
-                return 0;
-
-            b = h->bs + idx;
-
-            if (!b->key)
-                return 0;
-
-            item = (PMC *)b->value;
-            next = VTABLE_shift_pmc(INTERP, key);
-
-            if (!next)
-                return VTABLE_defined(INTERP, item);
-
-            return VTABLE_defined_keyed(INTERP, item, next);
-        }
+        /* We store list_item (which is defined). So fetch original PMC and check it */
+        PMC * const item = STATICSELF.get_pmc_keyed(key);
+        if (PMC_IS_NULL(item))
+            return 0;
+        return VTABLE_defined(INTERP, item);
+    }
 
-        return SUPER(key);
+    VTABLE INTVAL defined_keyed_str(STRING *key) {
+        PMC * const item = STATICSELF.get_pmc_keyed_str(key);
+        if (PMC_IS_NULL(item))
+            return 0;
+        return VTABLE_defined(INTERP, item);
     }
 
     VTABLE INTVAL defined_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
-        HashBucket  *b;
-
-        if (idx < 0)
-            idx += n;
-
-        if (idx < 0 || idx >= n)
+        PMC * item;
+        /* If item doesn't exists it's undefined */
+        if (!STATICSELF.exists_keyed_int(idx))
             return 0;
 
-        b = h->bs + idx;
-
-        if (b->key)
-            return VTABLE_defined(INTERP, (PMC *)b->value);
+        /* Null is undefined */
+        item = STATICSELF.get_pmc_keyed_int(idx);
+        if (PMC_IS_NULL(item))
+            return 0;
 
-        return 0;
+        return VTABLE_defined(INTERP, item);
     }
 
 /*
@@ -525,56 +644,55 @@
 */
 
     VTABLE void delete_keyed(PMC *key) {
-        PMC * const next = key_next(INTERP, key);
+        Parrot_OrderedHash_attributes *attrs =
+                PARROT_ORDEREDHASH(SELF);
+        PMC *list_entry, *prev, *next;
+        if ((PObj_get_FLAGS(key) & KEY_type_FLAGS) == KEY_integer_FLAG) {
+            INTVAL    intval = VTABLE_get_integer(INTERP, key);
+            PMC * const next = VTABLE_shift_pmc(INTERP, key);
 
-        if (PObj_get_FLAGS(key) & KEY_integer_FLAG) {
-            if (next) {
-                PMC * const item = SELF.get_pmc_keyed_int(VTABLE_get_integer(INTERP, key));
-                VTABLE_delete_keyed(INTERP, item, next);
-                return;
-            }
+            if (!next)
+                return STATICSELF.delete_keyed_int(intval);
 
-            SELF.delete_keyed_int(VTABLE_get_integer(INTERP, key));
+            return VTABLE_delete_keyed(INTERP, STATICSELF.get_pmc_keyed_int(intval), next);
         }
-        else {
-            if (next) {
-                PMC * const item = SELF.get_pmc_keyed_str(VTABLE_get_string(INTERP, key));
-                VTABLE_delete_keyed(INTERP, item, next);
-                return;
-            }
-            SELF.delete_keyed_str(VTABLE_get_string(INTERP, key));
-        }
-    }
-
-    VTABLE void delete_keyed_int(INTVAL idx) {
-        Hash * const h = (Hash *)SELF.get_pointer();
-        const INTVAL n = h->entries;
-        HashBucket  *b;
-
-        if (idx < 0)
-            idx += n;
 
-        if (idx < 0 || idx >= n)
+        list_entry = VTABLE_get_pmc_keyed(INTERP, attrs->hash, key);
+        if (PMC_IS_NULL(list_entry))
             return;
 
-        b = h->bs + idx;
+        /* Unlink entry */
+        next = VTABLE_get_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_NEXT);
+        prev = VTABLE_get_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_PREV);
+
+        if (attrs->first == list_entry)
+            attrs->first = next;
+
+        if (attrs->last == list_entry)
+            attrs->last = prev;
+
+        /* C<prev> and C<next> are list entries (FPA) */
+        if (!PMC_IS_NULL(prev))
+            VTABLE_set_pmc_keyed_int(INTERP, prev, ORDERED_HASH_ITEM_NEXT, next);
+        if (!PMC_IS_NULL(next))
+            VTABLE_set_pmc_keyed_int(INTERP, next, ORDERED_HASH_ITEM_PREV, prev);
 
-        if (!b)
-            return;
-
-        b->key       = NULL;
-        b->value     = NULL;
+        /* And finally delete it */
+        return VTABLE_delete_keyed(INTERP, PARROT_ORDEREDHASH(SELF)->hash, key);
     }
 
     VTABLE void delete_keyed_str(STRING *key) {
-        const Hash * const h = (Hash *)SELF.get_pointer();
-        HashBucket * const b = parrot_hash_get_bucket(INTERP, h, key);
+        return STATICSELF.delete_keyed(box_string(INTERP, key));
+    }
 
-        if (!b)
+    VTABLE void delete_keyed_int(INTVAL idx) {
+        PMC *list_entry;
+        if (!STATICSELF.exists_keyed_int(idx))
             return;
 
-        b->key       = NULL;
-        b->value     = NULL;
+        list_entry = get_list_item(INTERP, SELF, idx);
+        STATICSELF.delete_keyed(
+            VTABLE_get_pmc_keyed_int(INTERP, list_entry, ORDERED_HASH_ITEM_KEY));
     }
 
 /*
@@ -590,18 +708,11 @@
 
     VTABLE PMC *clone() {
         PMC  * const dest   = pmc_new(INTERP, SELF->vtable->base_type);
-        Hash * const hash   = (Hash *)SELF.get_pointer();
-        Hash * const h_dest = (Hash *)VTABLE_get_pointer(INTERP, dest);
-        UINTVAL     i;
-
-        for (i = 0; i <= N_BUCKETS(hash->mask-1); i++) {
-            HashBucket * const b      = hash->bs + i;
-            void       * const key    = b->key;
-
-            if (key)
-                parrot_hash_put(INTERP, h_dest, key,
-                    (void *)VTABLE_clone(INTERP, (PMC *)b->value));
-        }
+        Parrot_OrderedHash_attributes *clone_attrs =
+                PARROT_ORDEREDHASH(dest);
+
+        clone_attrs->hash   = VTABLE_clone(INTERP, PARROT_ORDEREDHASH(SELF)->hash);
+        find_bounds(INTERP, clone_attrs->hash, &clone_attrs->first, &clone_attrs->last);
 
         return dest;
     }
@@ -619,43 +730,35 @@
 
 Used to unarchive the hash.
 
-Freeze/thaw are inherited from hash.  Only thaw.visit is special, as we have to
-preserve key/value order.
-
 =cut
 
 */
 
     VTABLE void visit(visit_info *info) {
-        switch (VTABLE_get_integer(INTERP, info)) {
-          case VISIT_THAW_NORMAL:
-            SUPER(info);
-            break;
-
-          case VISIT_FREEZE_NORMAL:
-            {
-                Hash     * const hash = (Hash *)SELF.get_pointer();
-                const UINTVAL entries = hash->entries;
-                UINTVAL i;
-
-                for (i = 0; i < entries; i++) {
-                    HashBucket * const b   = hash->bs + i;
-
-                    if (b) {
-                        STRING * const key = (STRING *)b->key;
-                        if (key) {
-                            VTABLE_push_string(interp, info, key);
-                            (info->visit_pmc_now)(interp, (PMC *)b->value, info);
-                        }
-                    }
-                }
-            }
-            break;
-          default:
-            Parrot_ex_throw_from_c_args(interp, NULL,
-                    EXCEPTION_INVALID_OPERATION,
-                    "unhandled visit action (%d)", VTABLE_get_integer(INTERP, info));
-        }
+        VISIT_PMC_ATTR(INTERP, info, SELF, OrderedHash, hash);
+        SUPER(info);
+    }
+
+    VTABLE void thawfinish(visit_info *info) {
+        Parrot_OrderedHash_attributes *attrs = PARROT_ORDEREDHASH(SELF);
+        find_bounds(INTERP, attrs->hash, &attrs->first, &attrs->last);
+        SUPER(info);
+    }
+
+/*
+
+=item C<get_pmc()>
+
+Get underlying regular Hash. Used in UnManagedStruct.
+
+=cut
+
+*/
+
+    VTABLE PMC* get_pmc() {
+        PMC *hash;
+        GET_ATTR_hash(INTERP, SELF, hash);
+        return hash;
     }
 }
 

Modified: trunk/src/pmc/orderedhashiterator.pmc
==============================================================================
--- trunk/src/pmc/orderedhashiterator.pmc	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/src/pmc/orderedhashiterator.pmc	Mon Jan 25 13:50:23 2010	(r43586)
@@ -18,12 +18,12 @@
 
 */
 
-#include "pmc/pmc_hash.h"
+#include "pmc/pmc_orderedhash.h"
 #include "pmc/pmc_hashiteratorkey.h"
 
 pmclass OrderedHashIterator extends Iterator no_ro auto_attrs {
     ATTR PMC        *pmc_hash;      /* the Hash which this Iterator iterates */
-    ATTR Hash       *parrot_hash;   /* Underlying implementation of hash */
+    ATTR PMC        *next_entry;    /* Next entry to shift/pop */
     ATTR INTVAL      pos;           /* */
     ATTR INTVAL      elements;      /* How many elements left to iterate over */
     ATTR INTVAL      reverse;       /* Direction of iteration. 1 - for reverse iteration */
@@ -44,11 +44,10 @@
            (Parrot_OrderedHashIterator_attributes *) PMC_data(SELF);
 
         attrs->pmc_hash         = hash;
-        attrs->parrot_hash      = (Hash*)VTABLE_get_pointer(INTERP, hash);
         attrs->pos              = 0;
-        /* Will be decreased on initial advance_to_next */
-        /* XXX Do we really need to support this use-case ? */
-        attrs->elements         = attrs->parrot_hash->entries;
+        attrs->elements         = VTABLE_elements(INTERP, hash);
+        attrs->next_entry       = PARROT_ORDEREDHASH(hash)->first;
+        PMC_data(SELF)          = attrs;
 
         PObj_custom_mark_SET(SELF);
     }
@@ -91,15 +90,17 @@
                 PARROT_ORDEREDHASHITERATOR(SELF);
 
         /* Restart iterator */
-        attrs->elements         = attrs->parrot_hash->entries;
+        attrs->elements = VTABLE_elements(INTERP, attrs->pmc_hash);
         if (value == ITERATE_FROM_START || value == ITERATE_FROM_START_KEYS) {
-            attrs->pos      = 0;
-            attrs->reverse  = 0;
+            attrs->pos          = 0;
+            attrs->reverse      = 0;
+            attrs->next_entry   = PARROT_ORDEREDHASH(attrs->pmc_hash)->first;
             return;
         }
         else if (value == ITERATE_FROM_END) {
-            attrs->pos      = attrs->elements;
-            attrs->reverse  = 1;
+            attrs->pos          = attrs->elements;
+            attrs->reverse      = 1;
+            attrs->next_entry   = PARROT_ORDEREDHASH(attrs->pmc_hash)->last;
             return;
         }
 
@@ -168,22 +169,18 @@
                 PARROT_ORDEREDHASHITERATOR(SELF);
 
         PMC        *ret;
-        HashBucket *bucket;
 
         if (!attrs->elements)
             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
                 "StopIteration");
 
         /* Get bucket and move to next bucket */
-        do {
-            bucket = attrs->parrot_hash->bs + attrs->pos++;
-            attrs->elements--;
-        } while (attrs->elements && !bucket->key);
-
-        /* Reuse HashIteratorKey */
-        ret = pmc_new(INTERP, enum_class_HashIteratorKey);
-        VTABLE_set_pointer_keyed_int(INTERP, ret, 0, attrs->parrot_hash);
-        VTABLE_set_pointer_keyed_int(INTERP, ret, 1, bucket);
+        ret               = VTABLE_get_pmc_keyed_int(INTERP, attrs->next_entry,
+                ORDERED_HASH_ITEM_KEY);
+        attrs->next_entry = VTABLE_get_pmc_keyed_int(INTERP, attrs->next_entry,
+                ORDERED_HASH_ITEM_NEXT);
+        attrs->pos++;
+        attrs->elements--;
 
         return ret;
     }
@@ -204,21 +201,18 @@
                 PARROT_ORDEREDHASHITERATOR(SELF);
 
         PMC        *ret;
-        HashBucket *bucket;
 
         if (!attrs->elements)
             Parrot_ex_throw_from_c_args(INTERP, NULL, EXCEPTION_OUT_OF_BOUNDS,
                 "StopIteration");
 
-        /* Get bucket and move to next bucket */
-        bucket = attrs->parrot_hash->bs + --attrs->pos;
+        ret               = VTABLE_get_pmc_keyed_int(INTERP, attrs->next_entry,
+                ORDERED_HASH_ITEM_KEY);
+        attrs->next_entry = VTABLE_get_pmc_keyed_int(INTERP, attrs->next_entry,
+                ORDERED_HASH_ITEM_PREV);
+        attrs->pos--;
         attrs->elements--;
 
-        /* Reuse HashIteratorKey */
-        ret = pmc_new(INTERP, enum_class_HashIteratorKey);
-        VTABLE_set_pointer_keyed_int(INTERP, ret, 0, attrs->parrot_hash);
-        VTABLE_set_pointer_keyed_int(INTERP, ret, 1, bucket);
-
         return ret;
     }
 

Modified: trunk/src/pmc/unmanagedstruct.pmc
==============================================================================
--- trunk/src/pmc/unmanagedstruct.pmc	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/src/pmc/unmanagedstruct.pmc	Mon Jan 25 13:50:23 2010	(r43586)
@@ -90,9 +90,10 @@
         PMC * const types = PARROT_UNMANAGEDSTRUCT(pmc)->init;
 
         if (types->vtable->base_type == enum_class_OrderedHash) {
-            Hash       * const hash = (Hash *)VTABLE_get_pointer(interp, types);
+            Hash       * const hash = (Hash *)VTABLE_get_pointer(interp,
+                    VTABLE_get_pmc(interp, types));
             HashBucket * const b    = parrot_hash_get_bucket(interp, hash,
-                VTABLE_get_string(interp, key));
+                    hash_key_from_string(interp, hash, VTABLE_get_string(interp, key)));
 
             if (!b)
                 Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_KEY_NOT_FOUND,

Modified: trunk/src/pmc_freeze.c
==============================================================================
--- trunk/src/pmc_freeze.c	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/src/pmc_freeze.c	Mon Jan 25 13:50:23 2010	(r43586)
@@ -731,7 +731,8 @@
         const INTVAL n           = Parrot_pmc_array_length(interp, finish_list);
         int          i;
 
-        for (i = 0; i < n ; ++i) {
+        /* Thaw in reverse order. We have to fully thaw younger PMCs before use them in older */
+        for (i = n-1; i >= 0; --i) {
             current = *(PMC**)Parrot_pmc_array_get(interp, finish_list, i, enum_type_PMC);
             if (!PMC_IS_NULL(current))
                 VTABLE_thawfinish(interp, current, info);

Modified: trunk/t/native_pbc/annotations.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/native_pbc/integer_1.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/native_pbc/number_1.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/native_pbc/string_1.pbc
==============================================================================
Binary file (source and/or target). No diff available.

Modified: trunk/t/pmc/orderedhash.t
==============================================================================
--- trunk/t/pmc/orderedhash.t	Mon Jan 25 10:57:11 2010	(r43585)
+++ trunk/t/pmc/orderedhash.t	Mon Jan 25 13:50:23 2010	(r43586)
@@ -6,7 +6,7 @@
 use warnings;
 use lib qw( . lib ../lib ../../lib );
 use Test::More;
-use Parrot::Test tests => 28;
+use Parrot::Test tests => 23;
 
 =head1 NAME
 
@@ -310,16 +310,10 @@
     print I0
     exists I0, P0["ghi"]
     print I0
-    exists I0, P0[0]
-    print I0
-    exists I0, P0[1]
-    print I0
-    exists I0, P0[2]
-    print I0
     print "\n"
     end
 CODE
-101101
+101
 OUTPUT
 
 pasm_output_like( <<'CODE', '/[axj]/', "iterate over keys" );
@@ -636,113 +630,6 @@
 ok 4
 OUTPUT
 
-pasm_output_is( <<'CODE', <<'OUTPUT', "set/get compound key" );
-    new P0, ['OrderedHash']
-    set P0["a"], "Foo\n"
-    new P1, ['Hash']
-    set P1['foo'], "bar\n"
-    set P0["b"], P1
-    set P2, P0['b'; 'foo']
-    print P2
-    set P0['b'; 'foo'], "baz\n"
-    set P0['b'; 'quux'], "xyzzy\n"
-    set P2, P0['b'; 'foo']
-    print P2
-    set P2, P0['b'; 'quux']
-    print P2
-    print "--\n"
-    set P2, P0[0]
-    print P2
-    end
-CODE
-bar
-baz
-xyzzy
---
-Foo
-OUTPUT
-
-pasm_output_is( <<'CODE', <<'OUTPUT', "exists compound key" );
-    new P0, ['OrderedHash']
-    set P0["a"], "Foo"
-    new P1, ['Hash']
-    set P1['foo'], "bar\n"
-    set P0["b"], P1
-    set P0['b'; 'quux'], "xyzzy\n"
-    exists I0, P0['a']
-    print I0
-    exists I0, P0['b'; 'foo']
-    print I0
-    exists I0, P0['b'; 'quux']
-    print I0
-    exists I0, P0['b'; 'nada']
-    print I0
-    exists I0, P0['c']
-    print I0
-    print "\n--\n"
-    exists I0, P0[0]
-    print I0
-    exists I0, P0[1; 'foo']
-    print I0
-    exists I0, P0[1; 'quux']
-    print I0
-    exists I0, P0[1; 'nada']
-    print I0
-    exists I0, P0[2]
-    print I0
-    print "\n"
-    end
-CODE
-11100
---
-11100
-OUTPUT
-
-pasm_output_is( <<'CODE', <<'OUTPUT', "delete compound key" );
-    new P0, ['OrderedHash']
-    set P0["a"], "Foo"
-    new P1, ['Hash']
-    set P1['foo'], "bar\n"
-    set P0["b"], P1
-    set P0['b'; 'quux'], "xyzzy\n"
-    delete  P0['b'; 'foo']
-    exists I0, P0['a']
-    print I0
-    exists I0, P0['b'; 'foo']
-    print I0
-    exists I0, P0['b'; 'quux']
-    print I0
-    exists I0, P0['b'; 'nada']
-    print I0
-    exists I0, P0['c']
-    print I0
-    print "\n--\n"
-    exists I0, P0[0]
-    print I0
-    exists I0, P0[1; 'foo']
-    print I0
-    exists I0, P0[1; 'quux']
-    print I0
-    exists I0, P0[1; 'nada']
-    print I0
-    exists I0, P0[2]
-    print I0
-    print "\n--\n"
-    delete P0[1; 'quux']
-    exists I0, P0['b'; 'quux']
-    print I0
-    exists I0, P0[1; 'quux']
-    print I0
-    print "\n"
-    end
-CODE
-10100
---
-10100
---
-00
-OUTPUT
-
 pasm_output_is( <<'CODE', <<'OUTPUT', "freeze/thaw 1" );
     new P0, ['OrderedHash']
     set P0["a"], "Foo\n"
@@ -767,104 +654,6 @@
 Bar
 OUTPUT
 
-pasm_output_is( <<'CODE', <<'OUTPUT', "freeze/thaw 2" );
-    new P0, ['OrderedHash']
-    set P0["a"], "Foo\n"
-    new P1, ['Hash']
-    set P1['foo'], "bar\n"
-    set P0["b"], P1
-    set P0['b'; 'quux'], "xyzzy\n"
-
-    freeze S0, P0
-    thaw P1, S0
-    set P2, P1["a"]
-    print P2
-    set P2, P1[0]
-    print P2
-    set P2, P1["b";"foo"]
-    print P2
-    set P2, P1[1; "foo"]
-    print P2
-    set P2, P1["b";"quux"]
-    print P2
-    set P2, P1[1; "quux"]
-    print P2
-
-    end
-CODE
-Foo
-Foo
-bar
-bar
-xyzzy
-xyzzy
-OUTPUT
-
-pir_output_is( <<'CODE', <<'OUTPUT', 'freeze/thaw 3' );
-.sub main :main
-    .local string frozen
-    frozen = get_frozen_hash()
-
-    sweep 1
-
-    .local pmc parent
-    parent = thaw frozen
-    $S0 = parent['a']
-    say $S0
-
-    $S0 = parent[0]
-    say $S0
-
-    .local pmc child
-    child = parent[1]
-    $S0   = child[0]
-    say $S0
-
-    $S0   = child['foo']
-    say $S0
-
-    $S0   = parent[1; 'foo']
-    say $S0
-
-    $S0   = parent['b'; 'foo']
-    say $S0
-
-    $S0   = parent['b'; 'quux']
-    say $S0
-
-    $S0   = parent['b'; 2]
-    say $S0
-    end
-.end
-
-.sub get_frozen_hash
-    .local pmc parent
-    parent      = new ['OrderedHash']
-    parent['a'] = 'Foo'
-
-    .local pmc child
-    child        = new ['OrderedHash']
-    child['foo'] = 'bar'
-    push child, 'baz'
-
-    parent['b']         = child
-    parent['b'; 'quux'] = 'qaax'
-
-    .local string frozen
-    frozen = freeze parent
-    .return( frozen )
-.end
-CODE
-Foo
-Foo
-bar
-bar
-bar
-bar
-qaax
-qaax
-OUTPUT
-
 # Local Variables:
 #   mode: cperl
 #   cperl-indent-level: 4


More information about the parrot-commits mailing list