Skip to content

Commit 0b07415

Browse files
authored
Merge pull request #52 from Akeit0/optimize
Large Optimization
2 parents af3a8df + ce0d636 commit 0b07415

29 files changed

+2645
-1082
lines changed

src/Lua/CodeAnalysis/Compilation/FunctionCompilationContext.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@ internal static FunctionCompilationContext Create(ScopeCompilationContext? paren
6565
FastListCore<BreakDescription> breakQueue;
6666
FastListCore<GotoDescription> gotoQueue;
6767

68+
/// <summary>
69+
/// Maximum local stack size
70+
/// </summary>
71+
public byte MaxStackPosition { get; set; }
72+
6873
/// <summary>
6974
/// Chunk name (for debug)
7075
/// </summary>
@@ -415,6 +420,7 @@ public Chunk ToChunk()
415420
UpValues = upvalues.AsSpan().ToArray(),
416421
Functions = functions.AsSpan().ToArray(),
417422
ParameterCount = ParameterCount,
423+
MaxStackPosition = MaxStackPosition,
418424
};
419425

420426
foreach (var function in functions.AsSpan())
@@ -444,6 +450,7 @@ public void Reset()
444450
LoopLevel = 0;
445451
ParameterCount = 0;
446452
HasVariableArguments = false;
453+
MaxStackPosition = 0;
447454
}
448455

449456
/// <summary>

src/Lua/CodeAnalysis/Compilation/LuaCompiler.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,8 +619,16 @@ public bool VisitFunctionDeclarationStatementNode(FunctionDeclarationStatementNo
619619
// push closure instruction
620620
context.PushInstruction(Instruction.Closure(context.StackPosition, funcIndex), node.Position, true);
621621

622-
// assign global variable
623-
context.PushInstruction(Instruction.SetTabUp(0, (ushort)(index + 256), (ushort)(context.StackPosition - 1)), node.Position);
622+
if (context.TryGetLocalVariableInThisScope(node.Name, out var variable))
623+
{
624+
// assign local variable
625+
context.PushInstruction(Instruction.Move(variable.RegisterIndex, (ushort)(context.StackPosition - 1)), node.Position, true);
626+
}
627+
else
628+
{
629+
// assign global variable
630+
context.PushInstruction(Instruction.SetTabUp(0, (ushort)(index + 256), (ushort)(context.StackPosition - 1)), node.Position);
631+
}
624632

625633
return true;
626634
}

src/Lua/CodeAnalysis/Compilation/ScopeCompilationContext.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ public void PushInstruction(in Instruction instruction, SourcePosition position,
7979
{
8080
StackPosition++;
8181
}
82+
Function.MaxStackPosition = Math.Max(Function.MaxStackPosition, StackPosition);
8283
}
8384

8485
[MethodImpl(MethodImplOptions.AggressiveInlining)]

src/Lua/Exceptions.cs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@
44

55
namespace Lua;
66

7-
public class LuaException(string message) : Exception(message);
7+
public class LuaException : Exception
8+
{
9+
protected LuaException(Exception innerException) : base(innerException.Message, innerException)
10+
{
11+
}
12+
13+
public LuaException(string message) : base(message)
14+
{
15+
}
16+
}
817

918
public class LuaParseException(string? chunkName, SourcePosition position, string message) : LuaException(message)
1019
{
@@ -44,9 +53,27 @@ public static void BreakNotInsideALoop(string? chunkName, SourcePosition positio
4453
public override string Message => $"{ChunkName}:{(Position == null ? "" : $"{Position.Value}:")} {base.Message}";
4554
}
4655

47-
public class LuaRuntimeException(Traceback traceback, string message) : LuaException(message)
56+
public class LuaRuntimeException : LuaException
4857
{
49-
public Traceback LuaTraceback { get; } = traceback;
58+
public LuaRuntimeException(Traceback traceback, Exception innerException) : base(innerException)
59+
{
60+
LuaTraceback = traceback;
61+
}
62+
63+
public LuaRuntimeException(Traceback traceback, string message) : base(message)
64+
{
65+
LuaTraceback = traceback;
66+
}
67+
68+
public LuaRuntimeException(Traceback traceback, LuaValue errorObject): base(errorObject.ToString())
69+
{
70+
LuaTraceback = traceback;
71+
ErrorObject = errorObject;
72+
}
73+
74+
public Traceback LuaTraceback { get; }
75+
76+
public LuaValue? ErrorObject { get; }
5077

5178
public static void AttemptInvalidOperation(Traceback traceback, string op, LuaValue a, LuaValue b)
5279
{

src/Lua/Internal/FastStackCore.cs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public struct FastStackCore<T>
1616
public readonly ReadOnlySpan<T> AsSpan()
1717
{
1818
if (array == null) return [];
19-
return array.AsSpan(0, tail);
19+
return array.AsSpan(0, tail)!;
2020
}
2121

2222
public readonly Span<T?> GetBuffer()
@@ -33,15 +33,14 @@ public readonly T? this[int index]
3333
}
3434
}
3535

36+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
3637
public void Push(in T item)
3738
{
3839
array ??= new T[InitialCapacity];
3940

4041
if (tail == array.Length)
4142
{
42-
var newArray = new T[tail * 2];
43-
Array.Copy(array, newArray, tail);
44-
array = newArray;
43+
Array.Resize(ref array, tail * 2);
4544
}
4645

4746
array[tail] = item;
@@ -64,9 +63,21 @@ public bool TryPop(out T value)
6463
return true;
6564
}
6665

66+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
67+
internal bool TryPop()
68+
{
69+
if (tail == 0)
70+
{
71+
return false;
72+
}
73+
array[--tail] = default;
74+
75+
return true;
76+
}
77+
6778
public T Pop()
6879
{
69-
if (!TryPop(out var result)) throw new InvalidOperationException("Empty stack");
80+
if (!TryPop(out var result)) ThrowForEmptyStack();
7081
return result;
7182
}
7283

@@ -85,7 +96,7 @@ public bool TryPeek(out T value)
8596

8697
public T Peek()
8798
{
88-
if (!TryPeek(out var result)) throw new InvalidOperationException();
99+
if (!TryPeek(out var result)) ThrowForEmptyStack();
89100
return result;
90101
}
91102

@@ -119,4 +130,9 @@ public void Clear()
119130
array.AsSpan(0, tail).Clear();
120131
tail = 0;
121132
}
122-
}
133+
134+
void ThrowForEmptyStack()
135+
{
136+
throw new InvalidOperationException("Empty stack");
137+
}
138+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
namespace Lua.Internal;
2+
3+
internal static class LuaValueArrayPool
4+
{
5+
static FastStackCore<LuaValue[]> poolOf1024;
6+
static FastStackCore<LuaValue[]> poolOf1;
7+
8+
static readonly object lockObject = new();
9+
10+
11+
public static LuaValue[] Rent1024()
12+
{
13+
lock (lockObject)
14+
{
15+
if (poolOf1024.Count > 0)
16+
{
17+
return poolOf1024.Pop();
18+
}
19+
20+
return new LuaValue[1024];
21+
}
22+
}
23+
24+
public static LuaValue[] Rent1()
25+
{
26+
lock (lockObject)
27+
{
28+
if (poolOf1.Count > 0)
29+
{
30+
return poolOf1.Pop();
31+
}
32+
33+
return new LuaValue[1];
34+
}
35+
}
36+
37+
public static void Return1024(LuaValue[] array, bool clear = false)
38+
{
39+
if (array.Length != 1024)
40+
{
41+
ThrowInvalidArraySize(array.Length, 1024);
42+
}
43+
44+
if (clear)
45+
{
46+
array.AsSpan().Clear();
47+
}
48+
lock (lockObject)
49+
{
50+
poolOf1024.Push(array);
51+
}
52+
}
53+
54+
55+
public static void Return1(LuaValue[] array)
56+
{
57+
if (array.Length != 1)
58+
{
59+
ThrowInvalidArraySize(array.Length, 1);
60+
}
61+
62+
array[0] = LuaValue.Nil;
63+
lock (lockObject)
64+
{
65+
poolOf1.Push(array);
66+
}
67+
}
68+
69+
static void ThrowInvalidArraySize(int size, int expectedSize)
70+
{
71+
throw new InvalidOperationException($"Invalid array size: {size}, expected: {expectedSize}");
72+
}
73+
}

0 commit comments

Comments
 (0)