@@ -810,6 +810,21 @@ out doRestart
810810 continue ;
811811 }
812812
813+ // Lua 5.2 only invokes __eq for tables/userdata of the
814+ // same type. Primitive inequality needs no slow-path call.
815+ if (
816+ vb . Type != vc . Type
817+ || vb . Type is not ( LuaValueType . Table or LuaValueType . UserData )
818+ )
819+ {
820+ if ( iA == 1 )
821+ {
822+ context . Pc ++ ;
823+ }
824+
825+ continue ;
826+ }
827+
813828 if (
814829 ExecuteCompareOperationMetaMethod (
815830 vb ,
@@ -950,7 +965,7 @@ out doRestart
950965 var step = Unsafe . Add ( ref indexRef , 2 ) . UnsafeReadDouble ( ) ;
951966 var index = indexRef . UnsafeReadDouble ( ) + step ;
952967
953- if ( step >= 0 ? index <= limit : limit <= index )
968+ if ( step > 0 ? index <= limit : limit <= index )
954969 {
955970 context . Pc += instruction . SBx ;
956971 indexRef = index ;
@@ -1128,13 +1143,9 @@ OpCode opcode
11281143 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
11291144 internal static double Mod ( double a , double b )
11301145 {
1131- var mod = a % b ;
1132- if ( ( b > 0 && mod < 0 ) || ( b < 0 && mod > 0 ) )
1133- {
1134- mod += b ;
1135- }
1136-
1137- return mod ;
1146+ // Lua 5.2 uses this expression, including its floating-point rounding.
1147+ // A sign-adjusted remainder differs for values such as 5 and 0.1.
1148+ return a - ( Math . Floor ( a / b ) * b ) ;
11381149 }
11391150
11401151 static void SelfPostOperation (
@@ -2810,6 +2821,32 @@ CancellationToken cancellationToken
28102821 }
28112822 }
28122823
2824+ static bool TryGetCompareMetamethod(
2825+ LuaGlobalState state,
2826+ LuaValue left,
2827+ LuaValue right,
2828+ string name,
2829+ out LuaValue metamethod
2830+ )
2831+ {
2832+ if ( name == Metamethods. Eq)
2833+ {
2834+ metamethod = default ;
2835+ return left. Type == right. Type
2836+ && left. Type is LuaValueType. Table or LuaValueType. UserData
2837+ && state. TryGetMetatable( left, out var leftMetatable)
2838+ && leftMetatable. TryGetValue( name, out metamethod)
2839+ && state. TryGetMetatable( right, out var rightMetatable)
2840+ && (
2841+ leftMetatable == rightMetatable
2842+ || rightMetatable. TryGetValue( name, out var other) && metamethod == other
2843+ ) ;
2844+ }
2845+
2846+ return left. TryGetMetamethod( state, name, out metamethod)
2847+ || right. TryGetMetamethod( state, name, out metamethod) ;
2848+ }
2849+
28132850 [ MethodImpl( MethodImplOptions. NoInlining) ]
28142851 static bool ExecuteCompareOperationMetaMethod(
28152852 LuaValue vb,
@@ -2823,10 +2860,7 @@ out bool doRestart
28232860 doRestart = false;
28242861 var reverseLe = false;
28252862 ReCheck:
2826- if (
2827- vb. TryGetMetamethod( context. GlobalState, name, out var metamethod)
2828- || vc. TryGetMetamethod( context. GlobalState, name, out metamethod)
2829- )
2863+ if ( TryGetCompareMetamethod( context. GlobalState, vb, vc, name, out var metamethod) )
28302864 {
28312865 var stack = context. Stack;
28322866 var newBase = stack. Count;
@@ -2959,10 +2993,7 @@ CancellationToken cancellationToken
29592993 var ( name, description) = opCode. GetNameAndDescription( ) ;
29602994 var reverseLe = false;
29612995 ReCheck:
2962- if (
2963- vb. TryGetMetamethod( state. GlobalState, name, out var metamethod)
2964- || vc. TryGetMetamethod( state. GlobalState, name, out metamethod)
2965- )
2996+ if ( TryGetCompareMetamethod( state. GlobalState, vb, vc, name, out var metamethod) )
29662997 {
29672998 var stack = state. Stack;
29682999 var top = stack. Count;
0 commit comments