Optimised T0 generated code: when possible (at most 256 words), word calls are encoded over one byte, even in the 128..255 range.

This commit is contained in:
Thomas Pornin 2016-12-12 19:58:49 +01:00
parent e61ad42191
commit fb7052216d
8 changed files with 114 additions and 20 deletions

View file

@ -30,7 +30,7 @@ abstract class CodeElement {
internal int LastLength { get; set; } internal int LastLength { get; set; }
internal abstract int Length { get; } // internal abstract int Length { get; }
internal CodeElement() internal CodeElement()
{ {
@ -42,7 +42,19 @@ abstract class CodeElement {
throw new Exception("Code element accepts no target"); 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) internal static int Encode7EUnsigned(uint val, BlobWriter bw)
{ {

View file

@ -34,6 +34,7 @@ class CodeElementJump : CodeElement {
this.jumpType = jumpType; this.jumpType = jumpType;
} }
/* obsolete
internal override int Length { internal override int Length {
get { get {
int len = Encode7EUnsigned(jumpType, null); int len = Encode7EUnsigned(jumpType, null);
@ -46,6 +47,19 @@ class CodeElementJump : CodeElement {
return len; 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) 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) { 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; int joff = JumpOff;
if (joff == Int32.MinValue) { if (joff == Int32.MinValue) {
throw new Exception("Unresolved addresses"); throw new Exception("Unresolved addresses");

View file

@ -33,14 +33,23 @@ class CodeElementUInt : CodeElement {
this.val = val; this.val = val;
} }
/* obsolete
internal override int Length { internal override int Length {
get { get {
return Encode7EUnsigned(val, null); 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);
} }
} }

View file

@ -38,16 +38,26 @@ class CodeElementUIntExpr : CodeElement {
this.off = off; this.off = off;
} }
/* obsolete
internal override int Length { internal override int Length {
get { get {
return Encode7EUnsigned(val, null) return Encode7EUnsigned(val, null)
+ (cx.GetMaxBitLength(off) + 6) / 7; + (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; int len2 = (cx.GetMaxBitLength(off) + 6) / 7;
bw.Append(String.Format("T0_INT{0}({1})", bw.Append(String.Format("T0_INT{0}({1})",
len2, cx.ToCExpr(off))); len2, cx.ToCExpr(off)));

View file

@ -35,16 +35,26 @@ class CodeElementUIntInt : CodeElement {
this.val2 = val2; this.val2 = val2;
} }
/* obsolete
internal override int Length { internal override int Length {
get { get {
return Encode7EUnsigned(val1, null) return Encode7EUnsigned(val1, null)
+ Encode7ESigned(val2, 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); len += Encode7ESigned(val2, bw);
return len; return len;
} }

View file

@ -34,16 +34,26 @@ class CodeElementUIntUInt : CodeElement {
this.val2 = val2; this.val2 = val2;
} }
/* obsolete
internal override int Length { internal override int Length {
get { get {
return Encode7EUnsigned(val1, null) return Encode7EUnsigned(val1, null)
+ Encode7EUnsigned(val2, 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); len += Encode7EUnsigned(val2, bw);
return len; return len;
} }

View file

@ -1626,6 +1626,20 @@ public class T0Comp {
} }
CodeElement[] gcode = gcodeList.ToArray(); 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 * Compute all addresses and offsets. This loops until
* the addresses stabilize. * the addresses stabilize.
@ -1634,7 +1648,7 @@ public class T0Comp {
int[] gcodeLen = new int[gcode.Length]; int[] gcodeLen = new int[gcode.Length];
for (;;) { for (;;) {
for (int i = 0; i < gcode.Length; i ++) { for (int i = 0; i < gcode.Length; i ++) {
gcodeLen[i] = gcode[i].Length; gcodeLen[i] = gcode[i].GetLength(oneByteCode);
} }
int off = 0; int off = 0;
for (int i = 0; i < gcode.Length; i ++) { 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[] = {"); tw.Write("static const uint8_t t0_codeblock[] = {");
bw = new BlobWriter(tw, 78, 1); bw = new BlobWriter(tw, 78, 1);
foreach (CodeElement ce in gcode) { foreach (CodeElement ce in gcode) {
ce.Encode(bw); ce.Encode(bw, oneByteCode);
} }
tw.WriteLine(); tw.WriteLine();
tw.WriteLine("};"); tw.WriteLine("};");
@ -1805,6 +1819,14 @@ name(void *ctx) \
wordSet[ep].Slot); wordSet[ep].Slot);
} }
tw.WriteLine(); 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("void");
tw.WriteLine("{0}_run(void *t0ctx)", coreRun); tw.WriteLine("{0}_run(void *t0ctx)", coreRun);
tw.WriteLine("{0}", tw.WriteLine("{0}",
@ -1853,15 +1875,17 @@ name(void *ctx) \
#define T0_CO() do { \ #define T0_CO() do { \
goto t0_exit; \ goto t0_exit; \
} while (0) } while (0)
#define T0_RET() break #define T0_RET() goto t0_next
dp = ((t0_context *)t0ctx)->dp; dp = ((t0_context *)t0ctx)->dp;
rp = ((t0_context *)t0ctx)->rp; rp = ((t0_context *)t0ctx)->rp;
ip = ((t0_context *)t0ctx)->ip; ip = ((t0_context *)t0ctx)->ip;
goto t0_next;
for (;;) { for (;;) {
uint32_t t0x; uint32_t t0x;
t0x = t0_parse7E_unsigned(&ip); t0_next:
t0x = T0_NEXT(&ip);
if (t0x < T0_INTERPRETED) { if (t0x < T0_INTERPRETED) {
switch (t0x) { switch (t0x) {
int32_t t0off; int32_t t0off;
@ -1932,7 +1956,7 @@ t0_exit:
int codeLen = 0; int codeLen = 0;
foreach (CodeElement ce in gcode) { foreach (CodeElement ce in gcode) {
codeLen += ce.Length; codeLen += ce.GetLength(oneByteCode);
} }
int dataBlockLen = 0; int dataBlockLen = 0;
foreach (ConstData cd in blocks.Values) { foreach (ConstData cd in blocks.Values) {
@ -1944,8 +1968,8 @@ t0_exit:
*/ */
Console.WriteLine("code length: {0,6} byte(s)", codeLen); Console.WriteLine("code length: {0,6} byte(s)", codeLen);
Console.WriteLine("data length: {0,6} byte(s)", dataLen); Console.WriteLine("data length: {0,6} byte(s)", dataLen);
Console.WriteLine("interpreted words: {0}", Console.WriteLine("total words: {0} (interpreted: {1})",
interpretedEntry.Length); slotInterpreted + numInterpreted, numInterpreted);
} }
internal Word Lookup(string name) internal Word Lookup(string name)

Binary file not shown.