From 68b15db229ce66e0a72ade6246751ae25e4e9c88 Mon Sep 17 00:00:00 2001 From: Chip Bradford Date: Thu, 14 Jul 2016 21:02:37 -0700 Subject: [PATCH 1/4] Fixed duplicate ArgMarkers KOSArgMarker lacked an Equals override so every occurrence of "push ArgMarker" would add another copy of the value to the arguments section of a KSM file. --- src/kOS.Safe/Execution/KOSArgMarkerType.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/kOS.Safe/Execution/KOSArgMarkerType.cs b/src/kOS.Safe/Execution/KOSArgMarkerType.cs index db081402bc..8b161277d2 100644 --- a/src/kOS.Safe/Execution/KOSArgMarkerType.cs +++ b/src/kOS.Safe/Execution/KOSArgMarkerType.cs @@ -10,6 +10,13 @@ namespace kOS.Safe.Execution /// public class KOSArgMarkerType { + // all instances of KOSArgMarkerType should be considered identical: + public override bool Equals(object o) + { + return o is KOSArgMarkerType; + } + + public override int GetHashCode() { return 0; } public override string ToString() { return "_KOSArgMarker_"; From 118f7021eb1b329f132d039dae5e86045db0127a Mon Sep 17 00:00:00 2001 From: Chip Bradford Date: Thu, 14 Jul 2016 21:08:38 -0700 Subject: [PATCH 2/4] Fixed an issue with previousLabel tracking previousLabel wasn't reset after generating args and before generating the actual code which could have caused issues in the unlikely event that the first instruction's label was the natural successor to the last instruction's label --- src/kOS.Safe/Compilation/CompiledObject.cs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/kOS.Safe/Compilation/CompiledObject.cs b/src/kOS.Safe/Compilation/CompiledObject.cs index ec7f7f9e05..eb15ea97d3 100644 --- a/src/kOS.Safe/Compilation/CompiledObject.cs +++ b/src/kOS.Safe/Compilation/CompiledObject.cs @@ -168,7 +168,9 @@ public static ulong DecodeNumberFromBytes(byte[] encodedForm) /// private static Dictionary argumentPackFinder; - private static string previousLabel = "######"; // bogus value that is ensured to differ from any real value the first time through. + private const string LABEL_INIT = "######"; // bogus value that is ensured to differ from any real value the first time through. + + private static string previousLabel = LABEL_INIT; /// /// Returns the compiled program's opcodes packed into a tight form, that is a direct @@ -185,7 +187,7 @@ public static byte[] Pack(List program) argumentPackLogicalLength = 0; // nothing in the argumentPack yet. argumentPackFinder = new Dictionary(); lineMap = new DebugLineMap(); - previousLabel = "######"; // bogus value that is ensured to differ from any real value the first time through. + previousLabel = LABEL_INIT; for (int index = 0 ; index < program.Count ; ++index) // --. This can be replaced with a { // |--- foreach. I do it this way so I @@ -208,6 +210,7 @@ public static byte[] Pack(List program) headBuff.AddRange(truncatedArgumentPack); + previousLabel = LABEL_INIT; for (int index = 0 ; index < program.Count ; ++index) // --. This can be replaced with a { // |--- foreach. I do it this way so I CodePart codePart = program[index]; // --' can print the index in debugging. @@ -487,8 +490,8 @@ public static List UnPack(GlobalPath path, string prefix, byte[] conte int argIndexSize; Dictionary arguments = ReadArgumentPack(reader, out argIndexSize); lineMap = new DebugLineMap(); - - previousLabel = "######"; // bogus value that is ensured to differ from any real value the first time through. + + previousLabel = LABEL_INIT; int codeStart = 0; From a3f1d65baba0b4c14e85eb25ed345a07fdaddf98 Mon Sep 17 00:00:00 2001 From: Chip Bradford Date: Thu, 14 Jul 2016 21:13:11 -0700 Subject: [PATCH 3/4] Optimize argument indexes Switched to using the argument ordinal rather than byte offset to index arguments for each opcode. This allows upto 256 arguments before switching to 2-byte indexes for every opcode, regardless of how long those arguments actually are. If an average encoded argument is 10 bytes long, this will allow 10x as many arguments before hitting the 2-byte threshold, which can translate to several hundred bytes saves in medium sized KSM files. --- src/kOS.Safe/Compilation/CompiledObject.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/kOS.Safe/Compilation/CompiledObject.cs b/src/kOS.Safe/Compilation/CompiledObject.cs index eb15ea97d3..17161092dc 100644 --- a/src/kOS.Safe/Compilation/CompiledObject.cs +++ b/src/kOS.Safe/Compilation/CompiledObject.cs @@ -200,7 +200,7 @@ public static byte[] Pack(List program) // Now that we've seen every argument, we know how many bytes are needed // to store the argumentPack, and thus the largest possible index into it. // This will be how many bytes our indeces will be in this packed ML file. - int numArgIndexBytes = FewestBytesToHold(argumentPackLogicalLength); + int numArgIndexBytes = FewestBytesToHold(argumentPackFinder.Count); headBuff.Add((byte)'%'); headBuff.Add((byte)'A'); headBuff.Add(((byte)numArgIndexBytes)); @@ -346,8 +346,6 @@ private static byte[] PackCode(List fragment, int argIndexSize, int star /// byte index of where it starts in the argument pack. private static int PackedArgumentLocation(object argument) { - const int LABEL_OFFSET = 3; // Account for the %An at the front of the argument pack. - object arg = argument ?? new PseudoNull(); int returnValue; // bogus starting value before it's calculated. @@ -360,8 +358,8 @@ private static int PackedArgumentLocation(object argument) // When it gets added, it's going to be tacked on right at the end. // We already know that, se let's get that populated now: - argumentPackFinder.Add(arg, LABEL_OFFSET + argumentPackLogicalLength); - returnValue = LABEL_OFFSET + argumentPackLogicalLength; + returnValue = argumentPackFinder.Count; + argumentPackFinder.Add(arg, returnValue); // Borrow C#'s Binary IO writer to pack the object into the byte form, // rather than writing our own for each type: @@ -565,7 +563,7 @@ private static Dictionary ReadArgumentPack(BinaryReader reader, out if (typeFromId.TryGetValue(argTypeId, out argCSharpType)) { object arg = ReadSomeBinaryPrimitive(reader, argCSharpType); - returnArgs.Add(offsetLocation,arg); + returnArgs.Add(returnArgs.Count,arg); } else { From d8e49d80730c9849cd3c1ec9c5d918f715683419 Mon Sep 17 00:00:00 2001 From: Chip Bradford Date: Thu, 14 Jul 2016 21:14:06 -0700 Subject: [PATCH 4/4] Remove dead code This is no longer needed --- src/kOS.Safe/Compilation/CompiledObject.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/kOS.Safe/Compilation/CompiledObject.cs b/src/kOS.Safe/Compilation/CompiledObject.cs index 17161092dc..745f281de1 100644 --- a/src/kOS.Safe/Compilation/CompiledObject.cs +++ b/src/kOS.Safe/Compilation/CompiledObject.cs @@ -556,7 +556,6 @@ private static Dictionary ReadArgumentPack(BinaryReader reader, out bool sectionEnded = false; while (reader.BaseStream.Position < reader.BaseStream.Length && !(sectionEnded)) { - int offsetLocation = (int)(reader.BaseStream.Position) - startPos; byte argTypeId = reader.ReadByte(); Type argCSharpType;