Skip to content

Commit

Permalink
Merge branch 'master' into optfix
Browse files Browse the repository at this point in the history
  • Loading branch information
ike709 authored Oct 24, 2024
2 parents 9803027 + b974c59 commit 0690c21
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 77 deletions.
10 changes: 5 additions & 5 deletions DMCompiler/Bytecode/DreamProcOpcode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,9 @@ public enum DreamProcOpcode : byte {
[OpcodeMetadata]
Abs = 0x83,
// Peephole optimization opcodes
[OpcodeMetadata(0, OpcodeArgType.Reference, OpcodeArgType.Label)]
PushRefandJumpIfNotNull = 0x84,
//0x84
[OpcodeMetadata(-1, OpcodeArgType.Reference)]
AssignPop = 0x85,
AssignNoPush = 0x85,
[OpcodeMetadata(1, OpcodeArgType.Reference, OpcodeArgType.String)]
PushRefAndDereferenceField = 0x86,
[OpcodeMetadata(true, 0, OpcodeArgType.Int)]
Expand Down Expand Up @@ -285,14 +284,15 @@ public enum DreamProcOpcode : byte {
CreateListNResources = 0x92,
[OpcodeMetadata(0, OpcodeArgType.String, OpcodeArgType.Label)]
SwitchOnString = 0x93,
[OpcodeMetadata(1, OpcodeArgType.Label)]
JumpIfNotNull = 0x94,
//0x94
[OpcodeMetadata(0, OpcodeArgType.TypeId)]
IsTypeDirect = 0x95,
[OpcodeMetadata(0, OpcodeArgType.Reference)]
NullRef = 0x96,
[OpcodeMetadata(0, OpcodeArgType.Reference)]
ReturnReferenceValue = 0x97,
[OpcodeMetadata(0, OpcodeArgType.Float)]
ReturnFloat = 0x98,
}
// ReSharper restore MissingBlankLines

Expand Down
28 changes: 23 additions & 5 deletions DMCompiler/Optimizer/PeepholeOptimizations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ namespace DMCompiler.Optimizer;

// Assign [ref]
// Pop
// -> AssignPop [ref]
internal sealed class AssignPop : IPeepholeOptimization {
// -> AssignNoPush [ref]
internal sealed class AssignNoPush : IPeepholeOptimization {
public ReadOnlySpan<DreamProcOpcode> GetOpcodes() {
return [
DreamProcOpcode.Assign,
Expand All @@ -22,18 +22,18 @@ public void Apply(List<IAnnotatedBytecode> input, int index) {
AnnotatedBytecodeReference assignTarget = firstInstruction.GetArg<AnnotatedBytecodeReference>(0);

input.RemoveRange(index, 2);
input.Insert(index, new AnnotatedBytecodeInstruction(DreamProcOpcode.AssignPop, [assignTarget]));
input.Insert(index, new AnnotatedBytecodeInstruction(DreamProcOpcode.AssignNoPush, [assignTarget]));
}
}

// PushNull
// AssignPop [ref]
// AssignNoPush [ref]
// -> AssignNull [ref]
internal sealed class AssignNull : IPeepholeOptimization {
public ReadOnlySpan<DreamProcOpcode> GetOpcodes() {
return [
DreamProcOpcode.PushNull,
DreamProcOpcode.AssignPop
DreamProcOpcode.AssignNoPush
];
}

Expand Down Expand Up @@ -101,6 +101,24 @@ public void Apply(List<IAnnotatedBytecode> input, int index) {
}
}

// PushFloat [float]
// Return
// -> ReturnFloat [float]
internal class ReturnFloat : IPeepholeOptimization {
public ReadOnlySpan<DreamProcOpcode> GetOpcodes() {
return [
DreamProcOpcode.PushFloat,
DreamProcOpcode.Return
];
}

public void Apply(List<IAnnotatedBytecode> input, int index) {
var firstInstruction = IPeepholeOptimization.GetInstructionAndValue(input[index], out var pushVal);
IPeepholeOptimization.ReplaceInstructions(input, index, 2,
new AnnotatedBytecodeInstruction(DreamProcOpcode.ReturnFloat, [new AnnotatedBytecodeFloat(pushVal, firstInstruction.Location)]));
}
}

// PushReferenceValue [ref]
// JumpIfFalse [label]
// -> JumpIfReferenceFalse [ref] [label]
Expand Down
65 changes: 31 additions & 34 deletions OpenDreamRuntime/DreamValue.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using Dependency = Robust.Shared.IoC.DependencyAttribute;
using Dependency = Robust.Shared.IoC.DependencyAttribute;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
Expand Down Expand Up @@ -45,7 +46,6 @@ public enum DreamValueTypeFlag {
// @formatter:on
}


public static DreamValue Null {
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => new DreamValue((DreamObject?) null);
Expand Down Expand Up @@ -112,9 +112,9 @@ public bool IsNull {
get => Type == DreamValueType.DreamObject && (_refValue == null || Unsafe.As<DreamObject>(_refValue).Deleted);
}

public override string ToString() {
public readonly override string ToString() {
if (Type == DreamValueType.Float)
return _floatValue.ToString();
return _floatValue.ToString(CultureInfo.InvariantCulture);
else if (Type == 0)
return "<Uninitialized DreamValue>";
else if (_refValue == null) {
Expand Down Expand Up @@ -160,7 +160,7 @@ public int GetValueAsInteger() {
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetValueAsInteger(out int value) {
public readonly bool TryGetValueAsInteger(out int value) {
value = (int)_floatValue;
return Type == DreamValueType.Float;
}
Expand All @@ -182,7 +182,7 @@ public float UnsafeGetValueAsFloat() {
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool TryGetValueAsFloat(out float value) {
public readonly bool TryGetValueAsFloat(out float value) {
value = _floatValue;
return Type == DreamValueType.Float;
}
Expand All @@ -200,7 +200,7 @@ private void ThrowInvalidCastFloat() {
throw new InvalidCastException($"Value {this} was not the expected type of float");
}

public bool TryGetValueAsDreamResource([NotNullWhen(true)] out DreamResource? value) {
public readonly bool TryGetValueAsDreamResource([NotNullWhen(true)] out DreamResource? value) {
if (Type == DreamValueType.DreamResource) {
value = Unsafe.As<DreamResource>(_refValue)!;
return true;
Expand All @@ -214,6 +214,7 @@ public DreamResource MustGetValueAsDreamResource() {
if (Type == DreamValueType.DreamResource) {
return Unsafe.As<DreamResource>(_refValue)!;
}

throw new InvalidCastException("Value " + this + " was not the expected type of DreamResource");
}

Expand Down Expand Up @@ -249,7 +250,7 @@ public bool IsDreamObject<T>() where T : DreamObject {
return _refValue is T;
}

public bool TryGetValueAsDreamObject<T>([NotNullWhen(true)] out T? dreamObject) where T : DreamObject {
public readonly bool TryGetValueAsDreamObject<T>([NotNullWhen(true)] out T? dreamObject) where T : DreamObject {
if (_refValue is T dreamObjectValue) {
dreamObject = dreamObjectValue;
return true;
Expand All @@ -259,7 +260,7 @@ public bool TryGetValueAsDreamObject<T>([NotNullWhen(true)] out T? dreamObject)
return false;
}

public bool TryGetValueAsDreamList([NotNullWhen(true)] out DreamList? list) {
public readonly bool TryGetValueAsDreamList([NotNullWhen(true)] out DreamList? list) {
return TryGetValueAsDreamObject(out list);
}

Expand All @@ -277,16 +278,15 @@ private void ThrowInvalidCastList() {
throw new InvalidCastException("Value " + this + " was not the expected type of DreamList");
}

public bool TryGetValueAsType([NotNullWhen(true)] out TreeEntry? type) {
public readonly bool TryGetValueAsType([NotNullWhen(true)] out TreeEntry? type) {
if (Type == DreamValueType.DreamType) {
type = Unsafe.As<TreeEntry>(_refValue)!;

return true;
} else {
type = null;

return false;
}

type = null;
return false;
}

public TreeEntry MustGetValueAsType() {
Expand All @@ -296,26 +296,26 @@ public TreeEntry MustGetValueAsType() {
return Unsafe.As<TreeEntry>(_refValue)!;
}

public bool TryGetValueAsProc([NotNullWhen(true)] out DreamProc? proc) {
public readonly bool TryGetValueAsProc([NotNullWhen(true)] out DreamProc? proc) {
if (Type == DreamValueType.DreamProc) {
proc = Unsafe.As<DreamProc>(_refValue)!;

return true;
} else {
proc = null;

return false;
}

proc = null;
return false;
}

public DreamProc MustGetValueAsProc() {
if (Type == DreamValueType.DreamProc) {
return Unsafe.As<DreamProc>(_refValue)!;
}

throw new InvalidCastException("Value " + this + " was not the expected type of DreamProc");
}

public bool TryGetValueAsAppearance([NotNullWhen(true)] out IconAppearance? args) {
public readonly bool TryGetValueAsAppearance([NotNullWhen(true)] out IconAppearance? args) {
if (Type == DreamValueType.Appearance) {
args = Unsafe.As<IconAppearance>(_refValue)!;

Expand All @@ -330,6 +330,7 @@ public IconAppearance MustGetValueAsAppearance() {
if (Type == DreamValueType.Appearance) {
return Unsafe.As<IconAppearance>(_refValue)!;
}

throw new InvalidCastException("Value " + this + " was not the expected type of Appearance");
}

Expand Down Expand Up @@ -365,18 +366,18 @@ public string Stringify() {
return floatValue.ToString("g6");
}

// ReSharper disable once CompareOfFloatsByEqualityOperator
if (floatValue >= 1000000 && ((int)floatValue == floatValue)) {
return floatValue.ToString("g8");
}

return floatValue.ToString("g6");

case DreamValueType.DreamResource:
TryGetValueAsDreamResource(out var rscPath);
return rscPath.ResourcePath;
var rsc = MustGetValueAsDreamResource();
return rsc.ResourcePath ?? rsc.Id.ToString();
case DreamValueType.DreamType:
TryGetValueAsType(out var type);
return type.Path;
return MustGetValueAsType().Path;
case DreamValueType.DreamProc:
var proc = MustGetValueAsProc();

Expand Down Expand Up @@ -437,6 +438,7 @@ public override int GetHashCode() {
}

#region Serialization

public sealed class DreamValueJsonConverter : JsonConverter<DreamValue> {
[Dependency] private readonly DreamObjectTree _objectTree = default!;
[Dependency] private readonly DreamResourceManager _resourceManager = default!;
Expand Down Expand Up @@ -536,12 +538,9 @@ public override DreamValue Read(ref Utf8JsonReader reader, Type typeToConvert, J
// The following allows for serializing using DreamValues with ISerializationManager
// Currently only implemented to the point that they can be used for DreamFilters

public sealed class DreamValueDataNode : DataNode<DreamValueDataNode>, IEquatable<DreamValueDataNode> {
public DreamValueDataNode(DreamValue value) : base(NodeMark.Invalid, NodeMark.Invalid) {
Value = value;
}

public DreamValue Value { get; set; }
public sealed class DreamValueDataNode(DreamValue value)
: DataNode<DreamValueDataNode>(NodeMark.Invalid, NodeMark.Invalid), IEquatable<DreamValueDataNode> {
public DreamValue Value { get; set; } = value;
public override bool IsEmpty => false;

public override DreamValueDataNode Copy() {
Expand Down Expand Up @@ -667,7 +666,6 @@ public ValidationNode Validate(ISerializationManager serializationManager,
}
}


[TypeSerializer]
public sealed class DreamValueIconSerializer : ITypeReader<int, DreamValueDataNode> {
private readonly DreamResourceManager _dreamResourceManager = IoCManager.Resolve<DreamResourceManager>();
Expand Down Expand Up @@ -717,7 +715,6 @@ public ValidationNode Validate(ISerializationManager serializationManager,
}
}


[TypeSerializer]
public sealed class DreamValueColorMatrixSerializer : ITypeReader<ColorMatrix, DreamValueDataNode>, ITypeCopyCreator<ColorMatrix> {
public ColorMatrix Read(ISerializationManager serializationManager,
Expand All @@ -743,7 +740,6 @@ public ValidationNode Validate(ISerializationManager serializationManager,
DreamValueDataNode node,
IDependencyCollection dependencies,
ISerializationContext? context = null) {

if (node.Value.TryGetValueAsDreamList(out var _))
return new ValidatedValueNode(node);
//TODO: Improve validation
Expand All @@ -757,4 +753,5 @@ public ColorMatrix CreateCopy(ISerializationManager serializationManager, ColorM
return new(source);
}
}
#endregion Serialization

#endregion Serialization
35 changes: 7 additions & 28 deletions OpenDreamRuntime/Procs/DMOpcodeHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2867,32 +2867,17 @@ private static DreamValue IconOperationAdd(DMProcState state, DreamValue icon, D
DreamProcNativeIcon.Blend(iconObj.Icon, blend, DreamIconOperationBlend.BlendType.Add, 0, 0);
return new DreamValue(iconObj);
}

#endregion Helpers

#region Peephole Optimizations

public static ProcStatus PushReferenceAndJumpIfNotNull(DMProcState state) {
DreamReference reference = state.ReadReference();
int jumpTo = state.ReadInt();

DreamValue value = state.GetReferenceValue(reference);

if (!value.IsNull) {
state.Push(value);
state.Jump(jumpTo);
} else {
state.Push(DreamValue.Null);
}

return ProcStatus.Continue;
}

public static ProcStatus NullRef(DMProcState state) {
state.AssignReference(state.ReadReference(), DreamValue.Null);
return ProcStatus.Continue;
}

public static ProcStatus AssignPop(DMProcState state) {
public static ProcStatus AssignNoPush(DMProcState state) {
DreamReference reference = state.ReadReference();
DreamValue value = state.Pop();

Expand Down Expand Up @@ -3085,17 +3070,6 @@ public static ProcStatus CreateListNResources(DMProcState state) {
return ProcStatus.Continue;
}

public static ProcStatus JumpIfNotNull(DMProcState state) {
int position = state.ReadInt();

if (!state.Peek().IsNull) {
state.PopDrop();
state.Jump(position);
}

return ProcStatus.Continue;
}

public static ProcStatus IsTypeDirect(DMProcState state) {
DreamValue value = state.Pop();
int typeId = state.ReadInt();
Expand All @@ -3110,6 +3084,11 @@ public static ProcStatus IsTypeDirect(DMProcState state) {
return ProcStatus.Continue;
}

public static ProcStatus ReturnFloat(DMProcState state) {
state.SetReturn(new DreamValue(state.ReadFloat()));
return ProcStatus.Returned;
}

#endregion
}
}
Loading

0 comments on commit 0690c21

Please sign in to comment.