Fix optimization for collapse operators.

This commit is contained in:
2023-04-04 22:08:38 +08:00
parent 676d19f452
commit c877437ab6

View File

@@ -17,7 +17,7 @@ namespace Cryville.Common.Pdt {
readonly StackFrame[] _stack = new StackFrame[256]; readonly StackFrame[] _stack = new StackFrame[256];
readonly byte[] _mem = new byte[0x100000]; readonly byte[] _mem = new byte[0x100000];
bool _revokepttconst; bool _revokepttconst;
LinkedListNode<PdtInstruction> _rip; LinkedListNode<PdtInstruction> _ip;
/// <summary> /// <summary>
/// Evaluates an expression and passes the result to a target operator. /// Evaluates an expression and passes the result to a target operator.
/// </summary> /// </summary>
@@ -28,8 +28,8 @@ namespace Cryville.Common.Pdt {
_framecount = 0; _framecount = 0;
_goffset = 0; _goffset = 0;
_revokepttconst = false; _revokepttconst = false;
for (_rip = exp.Instructions.First; _rip != null; _rip = _rip.Next) for (_ip = exp.Instructions.First; _ip != null; _ip = _ip.Next)
_rip.Value.Execute(this); _ip.Value.Execute(this);
if (exp.IsPotentialConstant) { if (exp.IsPotentialConstant) {
exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst; exp.IsConstant = exp.IsPotentialConstant = !_revokepttconst;
} }
@@ -55,8 +55,10 @@ namespace Cryville.Common.Pdt {
List<PdtInstruction.Collapse> ct; List<PdtInstruction.Collapse> ct;
var cols = new Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>>(); var cols = new Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>>();
var il = exp.Instructions; var il = exp.Instructions;
for (_rip = il.First; _rip != null; _rip = _rip == null ? il.First : _rip.Next) { _ip = il.First;
var i = _rip.Value; while (_ip != null) {
bool nextFlag = false;
var i = _ip.Value;
if (i is PdtInstruction.Operate) { if (i is PdtInstruction.Operate) {
int fc0 = _framecount; int fc0 = _framecount;
int fc1 = ((PdtInstruction.Operate)i).Signature.ParamCount; int fc1 = ((PdtInstruction.Operate)i).Signature.ParamCount;
@@ -72,29 +74,36 @@ namespace Cryville.Common.Pdt {
} }
else { else {
var frame = _stack[_framecount - 1]; var frame = _stack[_framecount - 1];
_rip = il.AddAfter(_rip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length)); ReplaceIP(il, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
for (var j = 0; j <= fc1; j++) il.Remove(_rip.Previous); for (var j = 0; j < fc1; j++) il.Remove(_ip.Previous);
} }
} }
else if (i is PdtInstruction.Collapse) { else if (i is PdtInstruction.Collapse) {
var t = (PdtInstruction.Collapse)i; var t = (PdtInstruction.Collapse)i;
try { try {
var pins = _rip; var pins = _ip;
i.Execute(this); i.Execute(this);
if (_rip == pins) { if (_stack[_framecount - 1].Type == PdtInternalType.Error) {
_rip = _rip.Next; throw new EvaluationFailureException();
il.Remove(_rip.Previous); }
il.Remove(_rip.Previous); if (_ip == pins) {
_rip = _rip.Previous; _ip = _ip.Next;
il.Remove(_ip.Previous);
il.Remove(_ip.Previous);
_ip = _ip.Previous;
if (_ip == null) {
_ip = il.First;
nextFlag = true;
}
} }
else { else {
_rip = pins.Previous; _ip = pins.Previous;
while (_rip.Next != t.Target) il.Remove(_rip.Next); while (_ip.Next != t.Target) il.Remove(_ip.Next);
il.Remove(_rip.Next); il.Remove(_ip.Next);
if (cols.TryGetValue(t.Target, out ct)) { if (cols.TryGetValue(t.Target, out ct)) {
foreach (var u in ct) u.Target = _rip; foreach (var u in ct) u.Target = _ip;
cols.Remove(t.Target); cols.Remove(t.Target);
cols.Add(_rip, ct); cols.Add(_ip, ct);
} }
} }
} }
@@ -107,12 +116,11 @@ namespace Cryville.Common.Pdt {
i.Execute(this); i.Execute(this);
var frame = _stack[_framecount - 1]; var frame = _stack[_framecount - 1];
if (frame.Type != PdtInternalType.Undefined && frame.Type != PdtInternalType.Error) { if (frame.Type != PdtInternalType.Undefined && frame.Type != PdtInternalType.Error) {
_rip = il.AddAfter(_rip, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length)); ReplaceIP(il, new PdtInstruction.PushConstant(frame.Type, _mem, frame.Offset, frame.Length), cols);
il.Remove(_rip.Previous);
} }
} }
else i.Execute(this); else i.Execute(this);
if (_rip != null && cols.TryGetValue(_rip, out ct)) { if (_ip != null && cols.TryGetValue(_ip, out ct)) {
unsafe { unsafe {
fixed (StackFrame* frame = &_stack[_framecount - 1]) { fixed (StackFrame* frame = &_stack[_framecount - 1]) {
frame->Type = PdtInternalType.Error; frame->Type = PdtInternalType.Error;
@@ -121,6 +129,7 @@ namespace Cryville.Common.Pdt {
} }
} }
} }
if (!nextFlag) _ip = _ip.Next;
} }
exp.IsConstant = true; exp.IsConstant = true;
exp.IsPotentialConstant = true; exp.IsPotentialConstant = true;
@@ -134,6 +143,13 @@ namespace Cryville.Common.Pdt {
} }
} }
} }
void ReplaceIP(LinkedList<PdtInstruction> il, PdtInstruction ins, Dictionary<LinkedListNode<PdtInstruction>, List<PdtInstruction.Collapse>> cols) {
List<PdtInstruction.Collapse> cins;
if (cols.TryGetValue(_ip, out cins)) cols.Remove(_ip);
_ip = il.AddAfter(_ip, ins);
il.Remove(_ip.Previous);
if (cins != null) cols.Add(_ip, cins);
}
/// <summary> /// <summary>
/// Revokes the potential constant mark of the current expression. /// Revokes the potential constant mark of the current expression.
/// </summary> /// </summary>
@@ -207,12 +223,12 @@ namespace Cryville.Common.Pdt {
var frame = _stack[--_framecount]; var frame = _stack[--_framecount];
if (frame.Type == PdtInternalType.Error) { if (frame.Type == PdtInternalType.Error) {
_stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 }; _stack[_framecount++] = new StackFrame { Type = PdtInternalType.Error, Offset = _goffset, Length = 0 };
_rip = target; _ip = target;
return; return;
} }
if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) { if (Collapse(name, new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length))) {
_framecount++; _framecount++;
_rip = target; _ip = target;
} }
} }
} }