diff --git a/object.di b/object.di
index 03245ee..9d38b6d 100644
--- a/object.di
+++ b/object.di
@@ -169,6 +169,9 @@ class TypeInfo_AssociativeArray : TypeInfo
 {
     TypeInfo value;
     TypeInfo key;
+
+    //tell compiler that the new runtime function call ABI should be used
+    static const void* _new_abi;
 }
 
 class TypeInfo_Function : TypeInfo
diff --git a/tango/core/rt/compiler/dmd/object_.d b/tango/core/rt/compiler/dmd/object_.d
index 379fb73..db25a69 100644
--- a/tango/core/rt/compiler/dmd/object_.d
+++ b/tango/core/rt/compiler/dmd/object_.d
@@ -769,15 +769,8 @@ class TypeInfo_AssociativeArray : TypeInfo
 
     override hash_t getHash(in void* p)
     {
-        size_t sz = value.tsize();
-        hash_t hash = sz;
         AA aa=*cast(AA*)p;
-        size_t keysize=key.tsize();
-        int res=_aaApply2(aa, keysize, cast(dg2_t) delegate int(void *k, void *v){
-            hash+=rt_hash_combine(key.getHash(k),value.getHash(v));
-            return 0;
-        });
-        return hash;
+        return aa_hash(this, aa);
     }
 
     override size_t tsize()
@@ -788,22 +781,7 @@ class TypeInfo_AssociativeArray : TypeInfo
     {
         AA a=*cast(AA*)p1;
         AA b=*cast(AA*)p2;
-        if (cast(void*)a.a==cast(void*)b.a) return true;
-        size_t l1=_aaLen(a);
-        size_t l2=_aaLen(b);
-        if (l1!=l2) return false;
-        size_t keysize=key.tsize();
-        equals_t same=true;
-        int res=_aaApply2(a, keysize, cast(dg2_t) delegate int(void *k, void *v){
-            void* v2=_aaGetRvalue(b, key, value.tsize(), k);
-            if (v2 is null || !value.equals(v,v2)) {
-                same=false;
-                return 1;
-            }
-            ++l1;
-            return 0;
-        });
-        return same;
+        return aa_equals(this, a, b);
     }
 
     override int compare(in void* p1, in void* p2)
@@ -817,6 +795,9 @@ class TypeInfo_AssociativeArray : TypeInfo
 
     TypeInfo value;
     TypeInfo key;
+
+    //tell compiler that the new runtime function call ABI should be used
+    static const void* _new_abi;
 }
 
 class TypeInfo_Function : TypeInfo
diff --git a/tango/core/rt/compiler/dmd/rt/aaA.d b/tango/core/rt/compiler/dmd/rt/aaA.d
index 9c0e04c..374bdaf 100644
--- a/tango/core/rt/compiler/dmd/rt/aaA.d
+++ b/tango/core/rt/compiler/dmd/rt/aaA.d
@@ -37,6 +37,7 @@ private
 {
     import tango.stdc.stdarg;
     import tango.stdc.string: memcmp,memcpy;
+    import rt.compiler.util.hash;
 
     enum BlkAttr : uint
     {
@@ -49,6 +50,8 @@ private
     extern (C) void*  gc_malloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
     extern (C) void*  gc_calloc( size_t sz, uint ba = 0, PointerMap bitMask = PointerMap.init);
     extern (C) void  gc_free( void* p );
+
+    extern (C) ArrayRet_t _d_newarray(TypeInfo ti, size_t length);
 }
 
 // Auto-rehash and pre-allocate - Dave Fladebo
@@ -68,6 +71,8 @@ static size_t[] prime_list = [
  * It should be a type that is returned in registers.
  * Although DMD will return types of Array in registers,
  * gcc will not, so we instead use a 'long'.
+ *
+ * Actually, this seems to be dmd's problem. Works with long, fails with Array.
  */
 alias long ArrayRet_t;
 
@@ -77,6 +82,29 @@ struct Array
     void* ptr;
 }
 
+/**********************************
+ * Align to next pointer boundary, so that
+ * GC won't be faced with misaligned pointers
+ * in value.
+ */
+
+size_t aligntsize(size_t tsize)
+{
+    // Is pointer alignment on the x64 4 bytes or 8?
+    return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
+}
+
+extern (C):
+
+version (D_NewAA) {
+} else {
+    version = NotNewAA;
+}
+
+version (NotNewAA) {
+
+//------------- start legacy stuff
+
 struct aaA
 {
     aaA *left;
@@ -102,88 +130,6 @@ struct AA
     BB* a;
 }
 
-/**********************************
- * Align to next pointer boundary, so that
- * GC won't be faced with misaligned pointers
- * in value.
- */
-
-size_t aligntsize(size_t tsize)
-{
-    // Is pointer alignment on the x64 4 bytes or 8?
-    return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
-}
-
-extern (C):
-
-/*************************************************
- * Invariant for aa.
- */
-
-/+
-void _aaInvAh(aaA*[] aa)
-{
-    for (size_t i = 0; i < aa.length; i++)
-    {
-        if (aa[i])
-            _aaInvAh_x(aa[i]);
-    }
-}
-
-private int _aaCmpAh_x(aaA *e1, aaA *e2)
-{   int c;
-
-    c = e1.hash - e2.hash;
-    if (c == 0)
-    {
-        c = e1.key.length - e2.key.length;
-        if (c == 0)
-            c = memcmp((char *)e1.key, (char *)e2.key, e1.key.length);
-    }
-    return c;
-}
-
-private void _aaInvAh_x(aaA *e)
-{
-    hash_t key_hash;
-    aaA *e1;
-    aaA *e2;
-
-    key_hash = getHash(e.key);
-    assert(key_hash == e.hash);
-
-    while (1)
-    {   int c;
-
-        e1 = e.left;
-        if (e1)
-        {
-            _aaInvAh_x(e1);             // ordinary recursion
-            do
-            {
-                c = _aaCmpAh_x(e1, e);
-                assert(c < 0);
-                e1 = e1.right;
-            } while (e1 != null);
-        }
-
-        e2 = e.right;
-        if (e2)
-        {
-            do
-            {
-                c = _aaCmpAh_x(e, e2);
-                assert(c < 0);
-                e2 = e2.left;
-            } while (e2 != null);
-            e = e.right;                // tail recursion
-        }
-        else
-            break;
-    }
-}
-+/
-
 /****************************************************
  * Determine number of entries in associative array.
  */
@@ -231,7 +177,6 @@ body
     return aa.a ? aa.a.nodes : 0;
 }
 
-
 /*************************************************
  * Get pointer to value in associative array indexed by key.
  * Add entry for key if it is not already there.
@@ -312,11 +257,17 @@ Lret:
 
 void* _aaGetRvalue(AA aa, TypeInfo keyti, size_t valuesize, ...)
 {
+    auto pkey = cast(void *)(&valuesize + 1);
+    return _aaGetRvalueGODDAMIT(aa, keyti, valuesize, pkey);
+}
+
+//temporary hack for aa_equals
+void* _aaGetRvalueGODDAMIT(AA aa, TypeInfo keyti, size_t valuesize, void* pkey)
+{
     //printf("_aaGetRvalue(valuesize = %u)\n", valuesize);
     if (!aa.a)
         return null;
 
-    auto pkey = cast(void *)(&valuesize + 1);
     auto keysize = aligntsize(keyti.tsize());
     auto len = aa.a.b.length;
 
@@ -696,7 +647,7 @@ ArrayRet_t _aaKeys(AA aa, size_t keysize)
  */
 
 // dg is D, but _aaApply() is C
-extern (D) typedef int delegate(void *) dg_t;
+extern (D) alias int delegate(void *) dg_t;
 
 int _aaApply(AA aa, size_t keysize, dg_t dg)
 in
@@ -749,7 +700,7 @@ body
 }
 
 // dg is D, but _aaApply2() is C
-extern (D) typedef int delegate(void *, void *) dg2_t;
+extern (D) alias int delegate(void *, void *) dg2_t;
 
 int _aaApply2(AA aa, size_t keysize, dg2_t dg)
 in
@@ -885,3 +836,531 @@ BB* _d_assocarrayliteralT(TypeInfo_AssociativeArray ti, size_t length, ...)
     }
     return result;
 }
+
+extern (D) equals_t aa_equals(TypeInfo_AssociativeArray ti, AA a, AA b)
+{
+    //taken from object.di/TypeInfo_AssociativeArray.equals()
+    if (cast(void*)a.a==cast(void*)b.a) return true;
+    size_t l1=_aaLen(a);
+    size_t l2=_aaLen(b);
+    if (l1!=l2) return false;
+    size_t keysize=aligntsize(ti.key.tsize());
+    equals_t same=true;
+    int res=_aaApply2(a, keysize, delegate int(void *k, void *v){
+        //this doesn't work, k gets pushed as pointer, not as value
+        //void* v2=_aaGetRvalue(b, ti.key, ti.value.tsize(), k);
+        //thus, a terrible hack was born
+        void* v2=_aaGetRvalueGODDAMIT(b, ti.key, ti.value.tsize(), k);
+        if (v2 is null || !ti.value.equals(v,v2)) {
+            same=false;
+            return 1;
+        }
+        ++l1;
+        return 0;
+    });
+    return same;
+}
+
+extern (D) hash_t aa_hash(TypeInfo_AssociativeArray ti, AA aa)
+{
+    //taken from object.di/TypeInfo_AssociativeArray.getHash()
+    size_t sz = ti.value.tsize();
+    hash_t hash = sz;
+    size_t keysize=ti.key.tsize();
+    int res=_aaApply2(aa, keysize, cast(dg2_t) delegate int(void *k, void *v){
+        hash+=rt_hash_combine(ti.key.getHash(k),ti.value.getHash(v));
+        return 0;
+    });
+    return hash;
+}
+
+/***********************************
+ * Compare AA contents for equality.
+ * Returns:
+ *      1       equal
+ *      0       not equal
+ */
+int _aaEqual(TypeInfo_AssociativeArray ti, AA e1, AA e2)
+{
+    return aa_equals(ti, e1, e2);
+}
+
+//------------- end legacy stuff
+
+} else {
+//D_NewAA
+
+struct PMCache
+{
+    TypeInfo_AssociativeArray ti;
+    PointerMap pm;
+}
+
+/*
+ * Cache for the PointerMaps for aaA nodes.
+ * The cache is here for the following reasons:
+ *  1. reduce memory/performance overhead for creating a PointerMap on each
+ *     AA creation (you need to fill in BB.node_pm somehow)
+ *  2. avoid that the GC will collect the heap allocated PointerMaps (the GC
+ *     may collect a PM even if it's in use by the GC - the user has to make
+ *     sure the PMs are reachable by the rootset)
+ */
+extern (D) private PMCache[] g_pm_cache;
+
+struct aaA
+{
+    aaA *next;
+    hash_t hash;
+    /* key   */
+    /* value */
+}
+
+struct BB
+{
+    aaA*[] b;
+    size_t nodes;       // total number of aaA nodes
+    TypeInfo_AssociativeArray ti;
+    PointerMap node_pm; //PM for aaA nodes
+    aaA*[4] binit;      // initial value of b[]
+}
+
+/* This is the type actually seen by the programmer, although
+ * it is completely opaque.
+ */
+
+struct AA
+{
+    BB* a;
+}
+
+/****************************************************
+ * Determine number of entries in associative array.
+ */
+
+size_t _d_aaLen(TypeInfo_AssociativeArray ti, AA aa)
+out (result)
+{
+    size_t len = 0;
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            while (e)
+            {   len++;
+                e = e.next;
+            }
+        }
+    }
+    assert(len == result);
+}
+body
+{
+    return aa.a ? aa.a.nodes : 0;
+}
+
+extern (D) private AA aa_new(TypeInfo_AssociativeArray ti)
+{
+    AA aa;
+    aa.a = new BB();
+    aa.a.b = aa.a.binit;
+    aa.a.ti = ti;
+
+    //set pm (accesses globally shared g_pm_cache => lock)
+    synchronized (typeid(AA))
+    {
+        foreach (ref c; g_pm_cache)
+        {
+            if (c.ti is ti)
+            {
+                aa.a.node_pm = c.pm;
+                goto L_done;
+            }
+        }
+
+        //doesn't exist? create one
+        auto keysize = aligntsize(ti.key.tsize());
+        auto valuesize = ti.value.tsize();
+        size_t size = aaA.sizeof + keysize + valuesize;
+        PointerMapBuilder build;
+        build.size = size;
+        build.inlineAt(0, typeid(aaA).pointermap());
+        if (ti.key.flags() & 1)
+            build.inlineAt(aaA.sizeof, ti.key.pointermap());
+        if (ti.value.flags() & 1)
+            build.inlineAt(aaA.sizeof + keysize, ti.value.pointermap());
+        PointerMap pm = build.convertToPointerMap();
+
+        //and add
+        g_pm_cache ~= PMCache(ti, pm);
+
+        aa.a.node_pm = pm;
+
+    L_done: ;
+    }
+
+    return aa;
+}
+
+//return pointer to value
+//if the entry doesn't exist:
+//  if create is false, return null
+//  if create is true, create the entry and return pointer to new, uninitialized value
+extern (D) private void* aa_get(TypeInfo_AssociativeArray ti, AA* aa, void* pkey, bool create)
+{
+    size_t i;
+    aaA *e;
+    auto keysize = aligntsize(ti.key.tsize());
+    auto valuesize = ti.value.tsize();
+
+    if (!aa.a)
+    {
+        if (!create)
+            return null;
+        *aa = aa_new(ti);
+    }
+
+    auto key_hash = ti.key.getHash(pkey);
+    i = key_hash % aa.a.b.length;
+    auto pe = &aa.a.b[i];
+    while ((e = *pe) !is null)
+    {
+        if (key_hash == e.hash)
+        {
+            auto c = ti.key.compare(pkey, e + 1);
+            if (c == 0)
+                goto Lret;
+        }
+        pe = &e.next;
+    }
+
+    if (!create)
+        return null;
+
+    // Not found, create new elem
+    size_t size = aaA.sizeof + keysize + valuesize;
+    e = cast(aaA *) gc_calloc(size, 0, aa.a.node_pm);
+    memcpy(e + 1, pkey, keysize);
+    e.hash = key_hash;
+    *pe = e;
+
+    auto nodes = ++aa.a.nodes;
+    if (nodes > aa.a.b.length * 4)
+    {
+        _d_aaRehash(ti, aa);
+    }
+
+Lret:
+    return cast(void *)(e + 1) + keysize;
+}
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Add entry for key if it is not already there.
+ */
+
+void* _d_aaGet(TypeInfo_AssociativeArray ti, AA* aa, void* pkey)
+in
+{
+    assert(aa);
+}
+out (result)
+{
+    assert(result);
+    assert(aa.a);
+    assert(aa.a.b.length);
+    //assert(_aaInAh(*aa.a, key));
+}
+body
+{
+    return aa_get(ti, aa, pkey, true);
+}
+
+
+/*************************************************
+ * Get pointer to value in associative array indexed by key.
+ * Returns null if it is not already there.
+ */
+
+void* _d_aaGetRvalue(TypeInfo_AssociativeArray ti, AA aa, void* pkey)
+{
+    return aa_get(ti, &aa, pkey, false);
+}
+
+
+/*************************************************
+ * Determine if key is in aa.
+ * Returns:
+ *      null    not in aa
+ *      !=null  in aa, return pointer to value
+ */
+
+void* _d_aaIn(TypeInfo_AssociativeArray ti, AA aa, void* pkey)
+{
+    return aa_get(ti, &aa, pkey, false);
+}
+
+/*************************************************
+ * Delete key entry in aa[].
+ * If key is not in aa[], do nothing.
+ */
+
+void _d_aaDel(TypeInfo_AssociativeArray ti, AA aa, void* pkey)
+{
+    aaA *e;
+
+    if (aa.a && aa.a.b.length)
+    {
+        auto key_hash = ti.key.getHash(pkey);
+        //printf("hash = %d\n", key_hash);
+        size_t i = key_hash % aa.a.b.length;
+        auto pe = &aa.a.b[i];
+        while ((e = *pe) !is null) // null means not found
+        {
+            if (key_hash == e.hash)
+            {
+                auto c = ti.key.compare(pkey, e + 1);
+                if (c == 0)
+                {
+                    *pe = e.next;
+                    aa.a.nodes--;
+                    gc_free(e);
+                    break;
+                }
+            }
+            pe = &e.next;
+        }
+    }
+}
+
+//get array of values (item is ti.value) or keys (item is ti.key)
+extern (D) private ArrayRet_t aa_createarray(TypeInfo_AssociativeArray ti, AA aa, TypeInfo item)
+{
+    assert(item is ti.key || item is ti.value);
+
+    auto len = _d_aaLen(ti, aa);
+    if (!len)
+        return ArrayRet_t.init;
+
+    //_d_newarray is for types with zero initializer => slightly incorrect
+    //actually, we want an array as uninitialized as possible
+    //the runtime really should provide and export a routine to do this correctly
+    ArrayRet_t a_ = _d_newarray(item, len);
+    Array a = *cast(Array*)(&a_);
+
+    size_t resi = 0;
+    size_t skip = item is ti.key ? 0 : aligntsize(ti.key.tsize());
+    size_t itemsize = item.tsize();
+    foreach (aaA* e; aa.a.b)
+    {
+        while (e)
+        {
+            memcpy(a.ptr + resi * itemsize, cast(void*)(e + 1) + skip, itemsize);
+            resi++;
+            e = e.next;
+        }
+    }
+    assert(resi == len);
+
+    return *cast(ArrayRet_t*)(&a);
+}
+
+/********************************************
+ * Produce array of values from aa.
+ */
+
+ArrayRet_t _d_aaValues(TypeInfo_AssociativeArray ti, AA aa)
+{
+    return aa_createarray(ti, aa, ti.value);
+}
+
+
+/********************************************
+ * Produce array of N byte keys from aa.
+ */
+
+ArrayRet_t _d_aaKeys(TypeInfo_AssociativeArray ti, AA aa)
+{
+    return aa_createarray(ti, aa, ti.key);
+}
+
+
+/********************************************
+ * Rehash an array.
+ */
+
+void* _d_aaRehash(TypeInfo_AssociativeArray ti, AA* paa)
+{
+    if (paa.a)
+    {
+        BB newb = *paa.a;
+        auto aa = paa.a;
+        auto len = _d_aaLen(ti, *paa);
+        if (len)
+        {   size_t i;
+
+            for (i = 0; i < prime_list.length - 1; i++)
+            {
+                if (len <= prime_list[i])
+                    break;
+            }
+            len = prime_list[i];
+            newb.b = new aaA*[len];
+
+            foreach (e; aa.b)
+            {
+                while (e)
+                {   auto enext = e.next;
+                    auto j = e.hash % len;
+                    e.next = newb.b[j];
+                    newb.b[j] = e;
+                    e = enext;
+                }
+            }
+            if (aa.b.ptr == aa.binit.ptr)
+                aa.binit[] = null;
+            else
+                delete aa.b;
+
+            newb.nodes = aa.nodes;
+        }
+
+        *paa.a = newb;
+    }
+    return (*paa).a;
+}
+
+
+/**********************************************
+ * 'apply' for associative arrays - to support foreach
+ */
+
+// dg is D, but _aaApply() is C
+extern (D) alias int delegate(void *) dg_t;
+
+int _d_aaApply(TypeInfo_AssociativeArray ti, AA aa, dg_t dg)
+{
+    auto keysize = aligntsize(ti.key.tsize());
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            while (e)
+            {
+                auto result = dg(cast(void *)(e + 1) + keysize);
+                if (result)
+                    return result;
+                e = e.next;
+            }
+        }
+    }
+    return 0;
+}
+
+// dg is D, but _aaApply2() is C
+extern (D) alias int delegate(void *, void *) dg2_t;
+
+int _d_aaApply2(TypeInfo_AssociativeArray ti, AA aa, dg2_t dg)
+{
+    auto keysize = aligntsize(ti.key.tsize());
+
+    if (aa.a)
+    {
+        foreach (e; aa.a.b)
+        {
+            while (e)
+            {
+                auto result = dg(cast(void *)(e + 1), cast(void *)(e + 1) + keysize);
+                if (result)
+                    return result;
+                e = e.next;
+            }
+        }
+    }
+    return 0;
+}
+
+/***********************************
+ * Construct an associative array of type ti from
+ * length pairs of key/value pairs.
+ */
+
+BB* _d_aaLiteral(TypeInfo_AssociativeArray ti, size_t length, void *keys, void *values)
+{
+    AA aa;
+
+    void* pkey = keys;
+    void* pvalue = values;
+
+    auto valuesize = ti.value.tsize();
+    auto keysize = ti.key.tsize();
+
+    for (size_t i = 0; i < length; i++)
+    {
+        void* nval = _d_aaGet(ti, &aa, pkey);
+        memcpy(nval, pvalue, ti.value.tsize());
+
+        pkey += keysize;
+        pvalue += valuesize;
+    }
+
+    return aa.a;
+}
+
+/***********************************
+ * Compare AA contents for equality.
+ * Returns:
+ *      1       equal
+ *      0       not equal
+ */
+int _d_aaEqual(TypeInfo_AssociativeArray ti, AA e1, AA e2)
+{
+    if (e1.a is e2.a)
+        return 1;
+
+    if (_d_aaLen(ti, e1) != _d_aaLen(ti, e2))
+        return 0;
+
+    /* Algorithm: Visit each key/value pair in e1. If that key doesn't exist
+     * in e2, or if the value in e1 doesn't match the one in e2, the arrays
+     * are not equal, and exit early.
+     * After all pairs are checked, the arrays must be equal.
+     */
+
+    int equal = 1;
+
+    _d_aaApply2(ti, e1,
+        (void* pkey, void* pvalue)
+        {
+            void *pvalue2 = _d_aaGetRvalue(ti, e2, pkey);
+            if (!pvalue2 || ti.value.equals(pvalue, pvalue2) == 0)
+            {
+                equal = 0;
+                return 1;
+            }
+            return 0;
+        }
+    );
+
+    return equal;
+}
+
+extern (D) equals_t aa_equals(TypeInfo_AssociativeArray ti, AA a, AA b)
+{
+    return _d_aaEqual(ti, a, b);
+}
+
+extern (D) hash_t aa_hash(TypeInfo_AssociativeArray ti, AA a)
+{
+    hash_t hash = ti.value.tsize();
+    _d_aaApply2(ti, a,
+        (void* pkey, void* pvalue) {
+            hash += rt_hash_combine(ti.key.getHash(pkey), ti.value.getHash(pvalue));
+            return 0;
+        }
+    );
+    return hash;
+}
+
+}
diff --git a/tango/core/rt/compiler/dmd/rt/lifetime.d b/tango/core/rt/compiler/dmd/rt/lifetime.d
index 0caf5db..1b65905 100644
--- a/tango/core/rt/compiler/dmd/rt/lifetime.d
+++ b/tango/core/rt/compiler/dmd/rt/lifetime.d
@@ -186,19 +186,13 @@ extern (C) void _d_delclass(Object* p)
     }
 }
 
-
-/**
- * Allocate a new array of length elements.
- * ti is the type of the resulting array, or pointer to element.
- * (For when the array is initialized to 0)
- */
-extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length)
+//same as _d_newarrayT, except ti is the element type, not the array type
+extern (C) ulong _d_newarray(TypeInfo ti, size_t length)
 {
     void* p;
     ulong result;
-    auto size = ti.next.tsize();                // array element size
+    auto size = ti.tsize();                // array element size
 
-    debug(PRINTF) printf("_d_newarrayT(length = x%x, size = %d)\n", length, size);
     if (length == 0 || size == 0)
         result = 0;
     else
@@ -217,9 +211,9 @@ extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length)
             size *= length;
         PointerMap pm;
         version (D_HavePointerMap) {
-            pm = ti.next.pointermap();
+            pm = ti.pointermap();
         }
-        p = gc_malloc(size + 1, !(ti.next.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm);
+        p = gc_malloc(size + 1, !(ti.flags() & 1) ? BlkAttr.NO_SCAN : 0, pm);
         debug(PRINTF) printf(" p = %p\n", p);
         memset(p, 0, size);
         result = cast(ulong)length + (cast(ulong)cast(uint)p << 32);
@@ -231,6 +225,16 @@ Loverflow:
 }
 
 /**
+ * Allocate a new array of length elements.
+ * ti is the type of the resulting array, or pointer to element.
+ * (For when the array is initialized to 0)
+ */
+extern (C) ulong _d_newarrayT(TypeInfo ti, size_t length)
+{
+    return _d_newarray(ti.next, length);
+}
+
+/**
  * For when the array has a non-zero initializer.
  */
 extern (C) ulong _d_newarrayiT(TypeInfo ti, size_t length)
diff --git a/tango/text/convert/Layout.d b/tango/text/convert/Layout.d
index fe475e7..49267ae 100644
--- a/tango/text/convert/Layout.d
+++ b/tango/text/convert/Layout.d
@@ -527,6 +527,31 @@ version (WithVariant)
                                 else 
                                 if (_ti.classinfo.name.length is 25 && _ti.classinfo.name[9..$] == "AssociativeArray")
                                    {
+version (D_NewAA)
+{ //somewhat sane version
+                                    auto tiAsso = cast(TypeInfo_AssociativeArray)_ti;
+                                    auto tiKey = tiAsso.key;
+                                    auto tiVal = tiAsso.value;
+                                    auto aa = cast(void**)_arg;
+
+                                    length += sink ("{");
+                                    bool first = true;
+
+                                    _d_aaApply2(tiAsso, *aa,
+                                        (void* pk, void* pv) {
+                                            if (!first)
+                                                length += sink (", ");
+                                            process (tiKey, pk);
+                                            length += sink (" => ");
+                                            process (tiVal, pv);
+                                            first = false;
+                                            return 0;
+                                        }
+                                    );
+                                    length += sink ("}");
+}
+else
+{ //wtf omg (was there even a reason not to use _aaApply2)
                                    auto tiAsso = cast(TypeInfo_AssociativeArray)_ti;
                                    auto tiKey = tiAsso.key;
                                    auto tiVal = tiAsso.next();
@@ -559,6 +584,7 @@ version (WithVariant)
                                            first = false;
                                            }
                                    length += sink ("}");
+}
                                    }
                                 else 
                                 if (_ti.classinfo.name[9] is TypeCode.ARRAY)
@@ -938,7 +964,18 @@ private enum TypeCode
         IREAL = 'j'  
 }
 
+version (D_NewAA)
+{
+
+//from tango/core/rt/compiler/dmd/rt/aaA.d
+//this should be an exported standard runtime function
+
+extern (D) alias int delegate(void *, void *) dg2_t;
+extern (C) int _d_aaApply2(TypeInfo_AssociativeArray ti, AA aa, dg2_t dg);
 
+alias void* AA;
+
+}
 
 /*******************************************************************************
 
diff --git a/testaa.d b/testaa.d
new file mode 100644
index 0000000..be3f223
--- /dev/null
+++ b/testaa.d
@@ -0,0 +1,108 @@
+import tango.io.Stdout;
+import tango.text.convert.Format;
+
+struct X {
+    int a;
+    char[] toString() {
+        return Format("{}", a);
+    }
+}
+
+short[long] liter(byte x, long y) {
+    return [ x: 523, y : 789, 43: 3455 ];
+}
+
+/+
+extern(C)
+void* _d_aaLiteral(TypeInfo_AssociativeArray ti, size_t length, void *keys, void *values)
+{
+    Stdout.formatln("ti={} len={} keys={}", ti, length, keys);
+    auto pk = cast(long*)keys;
+    auto pv = cast(short*)values;
+    Stdout.formatln("1stkey={} 1stval={}", *pk, *pv);
+    pk++; pv++;
+    Stdout.formatln("2ndtkey={} 2ndval={}", *pk, *pv);
+    return null;
+}
++/
+
+void cmp(T)(T a, T b, bool equal) {
+    if (equal) {
+        assert(a == b);
+        TypeInfo ti = typeid(T);
+        assert(ti.equals(&a, &b));
+        assert(ti.getHash(&a) == ti.getHash(&b));
+    } else {
+        assert(a != b);
+        TypeInfo ti = typeid(T);
+        assert(!ti.equals(&a, &b));
+        if (ti.getHash(&a) == ti.getHash(&b))
+            Stdout.formatln("Unlikely hash collision!");
+    }
+}
+
+bool same_set(T)(T[] a, T[] b) {
+    if (a.length != b.length)
+        return false;
+    foreach (x; a) {
+        bool is_in;
+        foreach (y; b) {
+            if (y == x) {
+                is_in = true;
+                break;
+            }
+        }
+        if (!is_in)
+            return false;
+    }
+    return true;
+}
+
+void main() {
+    int[X] aa;
+    aa[X(1)] = 5;
+    assert(Format("{}", aa) == "{1 => 5}");
+    short[long] x;
+    x[43] = 3455;
+    x[123] = 523;
+    x[53] = 789;
+    assert(x[43] == 3455);
+    assert(x[123] == 523);
+    assert(x[53] == 789);
+    assert(x.length == 3);
+    cmp(x, x, true);
+    short[long] x2;
+    x2[43] = 3455;
+    x2[123] = 523;
+    x2[53] = 789;
+    cmp(x, x2, true);
+    auto y = liter(123, 53);
+    cmp(y, x, true);
+    short[long] x3;
+    x3[43] = 3455;
+    x3[123] = 524;
+    x3[53] = 789;
+    cmp(x2, x3, false);
+    short[long] x4;
+    x4[43] = 3455;
+    x4[122] = 523;
+    x4[53] = 789;
+    cmp(x2, x4, false);
+    assert(same_set(x4.values, [cast(short)3455, 523, 789]));
+    assert(same_set(x4.keys, [cast(long)43, 122, 53]));
+    x2.remove(42);
+    cmp(x, x2, true);
+    x2.remove(43);
+    cmp(x, x2, false);
+    short[byte] ba;
+    ba[2] = 523;
+    assert(Format("{}", ba) == "{2 => 523}");
+    //AA literals (yes they are different, at least the old impl.)
+    short[byte] ba2 = [ 2: 523 ];
+    assert(Format("{}", ba2) == "{2 => 523}");
+    cmp(ba, ba2, true);
+    assert(ba.values == [cast(short)523]);
+    assert(ba.keys == [cast(byte)2]);
+    Stdout.formatln("all passed!");
+}
+
