Optimised T0 generated code: when possible (at most 256 words), word calls are encode...
authorThomas Pornin <pornin@bolet.org>
Mon, 12 Dec 2016 18:58:49 +0000 (19:58 +0100)
committerThomas Pornin <pornin@bolet.org>
Mon, 12 Dec 2016 18:58:49 +0000 (19:58 +0100)
T0/CodeElement.cs
T0/CodeElementJump.cs
T0/CodeElementUInt.cs
T0/CodeElementUIntExpr.cs
T0/CodeElementUIntInt.cs
T0/CodeElementUIntUInt.cs
T0/T0Comp.cs
T0Comp.exe

index 5731c5a..471a61f 100644 (file)
@@ -30,7 +30,7 @@ abstract class CodeElement {
 
        internal int LastLength { get; set; }
 
-       internal abstract int Length { get; }
+       // internal abstract int Length { get; }
 
        internal CodeElement()
        {
@@ -42,7 +42,19 @@ abstract class CodeElement {
                throw new Exception("Code element accepts no target");
        }
 
-       internal abstract int Encode(BlobWriter bw);
+       internal abstract int GetLength(bool oneByteCode);
+
+       internal abstract int Encode(BlobWriter bw, bool oneByteCode);
+
+       internal static int EncodeOneByte(uint val, BlobWriter bw)
+       {
+               if (val > 255) {
+                       throw new Exception(string.Format(
+                               "Cannot encode '{0}' over one byte", val));
+               }
+               bw.Append((byte)val);
+               return 1;
+       }
 
        internal static int Encode7EUnsigned(uint val, BlobWriter bw)
        {
index 5abd7eb..4dae0bc 100644 (file)
@@ -34,6 +34,7 @@ class CodeElementJump : CodeElement {
                this.jumpType = jumpType;
        }
 
+       /* obsolete
        internal override int Length {
                get {
                        int len = Encode7EUnsigned(jumpType, null);
@@ -46,6 +47,19 @@ class CodeElementJump : CodeElement {
                        return len;
                }
        }
+       */
+
+       internal override int GetLength(bool oneByteCode)
+       {
+               int len = oneByteCode ? 1 : Encode7EUnsigned(jumpType, null);
+               int joff = JumpOff;
+               if (joff == Int32.MinValue) {
+                       len ++;
+               } else {
+                       len += Encode7ESigned(joff, null);
+               }
+               return len;
+       }
 
        internal override void SetJumpTarget(CodeElement target)
        {
@@ -63,12 +77,17 @@ class CodeElementJump : CodeElement {
                }
        }
 
-       internal override int Encode(BlobWriter bw)
+       internal override int Encode(BlobWriter bw, bool oneByteCode)
        {
                if (bw == null) {
-                       return Length;
+                       return GetLength(oneByteCode);
+               }
+               int len;
+               if (oneByteCode) {
+                       len = EncodeOneByte(jumpType, bw);
+               } else {
+                       len = Encode7EUnsigned(jumpType, bw);
                }
-               int len = Encode7EUnsigned(jumpType, bw);
                int joff = JumpOff;
                if (joff == Int32.MinValue) {
                        throw new Exception("Unresolved addresses");
index e5f3607..049cdad 100644 (file)
@@ -33,14 +33,23 @@ class CodeElementUInt : CodeElement {
                this.val = val;
        }
 
+       /* obsolete
        internal override int Length {
                get {
                        return Encode7EUnsigned(val, null);
                }
        }
+       */
 
-       internal override int Encode(BlobWriter bw)
+       internal override int GetLength(bool oneByteCode)
        {
-               return Encode7EUnsigned(val, bw);
+               return oneByteCode ? 1 : Encode7EUnsigned(val, null);
+       }
+
+       internal override int Encode(BlobWriter bw, bool oneByteCode)
+       {
+               return oneByteCode
+                       ? EncodeOneByte(val, bw)
+                       : Encode7EUnsigned(val, bw);
        }
 }
index d24ba58..8dd55a5 100644 (file)
@@ -38,16 +38,26 @@ class CodeElementUIntExpr : CodeElement {
                this.off = off;
        }
 
+       /* obsolete
        internal override int Length {
                get {
                        return Encode7EUnsigned(val, null)
                                + (cx.GetMaxBitLength(off) + 6) / 7;
                }
        }
+       */
 
-       internal override int Encode(BlobWriter bw)
+       internal override int GetLength(bool oneByteCode)
        {
-               int len1 = Encode7EUnsigned(val, bw);
+               int len = oneByteCode ? 1 : Encode7EUnsigned(val, null);
+               return len + (cx.GetMaxBitLength(off) + 6) / 7;
+       }
+
+       internal override int Encode(BlobWriter bw, bool oneByteCode)
+       {
+               int len1 = oneByteCode
+                       ? EncodeOneByte(val, bw)
+                       : Encode7EUnsigned(val, bw);
                int len2 = (cx.GetMaxBitLength(off) + 6) / 7;
                bw.Append(String.Format("T0_INT{0}({1})",
                        len2, cx.ToCExpr(off)));
index 022ffb8..0223e27 100644 (file)
@@ -35,16 +35,26 @@ class CodeElementUIntInt : CodeElement {
                this.val2 = val2;
        }
 
+       /* obsolete
        internal override int Length {
                get {
                        return Encode7EUnsigned(val1, null)
                                + Encode7ESigned(val2, null);
                }
        }
+       */
 
-       internal override int Encode(BlobWriter bw)
+       internal override int GetLength(bool oneByteCode)
        {
-               int len = Encode7EUnsigned(val1, bw);
+               return (oneByteCode ? 1 : Encode7EUnsigned(val1, null))
+                       + Encode7ESigned(val2, null);
+       }
+
+       internal override int Encode(BlobWriter bw, bool oneByteCode)
+       {
+               int len = oneByteCode
+                       ? EncodeOneByte(val1, bw)
+                       : Encode7EUnsigned(val1, bw);
                len += Encode7ESigned(val2, bw);
                return len;
        }
index 3d4ee33..6f94de5 100644 (file)
@@ -34,16 +34,26 @@ class CodeElementUIntUInt : CodeElement {
                this.val2 = val2;
        }
 
+       /* obsolete
        internal override int Length {
                get {
                        return Encode7EUnsigned(val1, null)
                                + Encode7EUnsigned(val2, null);
                }
        }
+       */
 
-       internal override int Encode(BlobWriter bw)
+       internal override int GetLength(bool oneByteCode)
        {
-               int len = Encode7EUnsigned(val1, bw);
+               return (oneByteCode ? 1 : Encode7EUnsigned(val1, null))
+                       + Encode7EUnsigned(val2, null);
+       }
+
+       internal override int Encode(BlobWriter bw, bool oneByteCode)
+       {
+               int len = oneByteCode
+                       ? EncodeOneByte(val1, bw)
+                       : Encode7EUnsigned(val1, bw);
                len += Encode7EUnsigned(val2, bw);
                return len;
        }
index 143badb..20adc04 100644 (file)
@@ -1626,6 +1626,20 @@ public class T0Comp {
                }
                CodeElement[] gcode = gcodeList.ToArray();
 
+               /*
+                * If there are less than 256 words in total (C +
+                * interpreted) then we can use "one-byte code" which is
+                * more compact when the number of words is in the
+                * 128..255 range.
+                */
+               bool oneByteCode;
+               if (slotInterpreted + numInterpreted >= 256) {
+                       Console.WriteLine("WARNING: more than 255 words");
+                       oneByteCode = false;
+               } else {
+                       oneByteCode = true;
+               }
+
                /*
                 * Compute all addresses and offsets. This loops until
                 * the addresses stabilize.
@@ -1634,7 +1648,7 @@ public class T0Comp {
                int[] gcodeLen = new int[gcode.Length];
                for (;;) {
                        for (int i = 0; i < gcode.Length; i ++) {
-                               gcodeLen[i] = gcode[i].Length;
+                               gcodeLen[i] = gcode[i].GetLength(oneByteCode);
                        }
                        int off = 0;
                        for (int i = 0; i < gcode.Length; i ++) {
@@ -1756,7 +1770,7 @@ static const uint8_t t0_datablock[];
                        tw.Write("static const uint8_t t0_codeblock[] = {");
                        bw = new BlobWriter(tw, 78, 1);
                        foreach (CodeElement ce in gcode) {
-                               ce.Encode(bw);
+                               ce.Encode(bw, oneByteCode);
                        }
                        tw.WriteLine();
                        tw.WriteLine("};");
@@ -1805,6 +1819,14 @@ name(void *ctx) \
                                        wordSet[ep].Slot);
                        }
                        tw.WriteLine();
+                       if (oneByteCode) {
+                               tw.WriteLine("{0}",
+@"#define T0_NEXT(t0ipp)   (*(*(t0ipp)) ++)");
+                       } else {
+                               tw.WriteLine("{0}",
+@"#define T0_NEXT(t0ipp)   t0_parse7E_unsigned(t0ipp)");
+                       }
+                       tw.WriteLine();
                        tw.WriteLine("void");
                        tw.WriteLine("{0}_run(void *t0ctx)", coreRun);
                        tw.WriteLine("{0}",
@@ -1853,15 +1875,17 @@ name(void *ctx) \
 #define T0_CO()         do { \
        goto t0_exit; \
 } while (0)
-#define T0_RET()        break
+#define T0_RET()        goto t0_next
 
        dp = ((t0_context *)t0ctx)->dp;
        rp = ((t0_context *)t0ctx)->rp;
        ip = ((t0_context *)t0ctx)->ip;
+       goto t0_next;
        for (;;) {
                uint32_t t0x;
 
-               t0x = t0_parse7E_unsigned(&ip);
+       t0_next:
+               t0x = T0_NEXT(&ip);
                if (t0x < T0_INTERPRETED) {
                        switch (t0x) {
                                int32_t t0off;
@@ -1932,7 +1956,7 @@ t0_exit:
 
                int codeLen = 0;
                foreach (CodeElement ce in gcode) {
-                       codeLen += ce.Length;
+                       codeLen += ce.GetLength(oneByteCode);
                }
                int dataBlockLen = 0;
                foreach (ConstData cd in blocks.Values) {
@@ -1944,8 +1968,8 @@ t0_exit:
                 */
                Console.WriteLine("code length: {0,6} byte(s)", codeLen);
                Console.WriteLine("data length: {0,6} byte(s)", dataLen);
-               Console.WriteLine("interpreted words: {0}",
-                       interpretedEntry.Length);
+               Console.WriteLine("total words: {0} (interpreted: {1})",
+                       slotInterpreted + numInterpreted, numInterpreted);
        }
 
        internal Word Lookup(string name)
index 411645c..b951fab 100755 (executable)
Binary files a/T0Comp.exe and b/T0Comp.exe differ