Weaver: WeaverLists renamed to SyncVarAccessLists because that's what it's for

This commit is contained in:
vis2k 2021-09-20 19:11:20 +08:00
parent 3dbab83615
commit 37af48b83e
6 changed files with 35 additions and 35 deletions

View File

@ -16,7 +16,7 @@ class NetworkBehaviourProcessor
{ {
AssemblyDefinition assembly; AssemblyDefinition assembly;
WeaverTypes weaverTypes; WeaverTypes weaverTypes;
WeaverLists weaverLists; SyncVarAccessLists syncVarAccessLists;
SyncVarProcessor syncVarProcessor; SyncVarProcessor syncVarProcessor;
Writers writers; Writers writers;
Readers readers; Readers readers;
@ -47,15 +47,15 @@ public struct ClientRpcResult
public bool includeOwner; public bool includeOwner;
} }
public NetworkBehaviourProcessor(AssemblyDefinition assembly, WeaverTypes weaverTypes, WeaverLists weaverLists, Writers writers, Readers readers, Logger Log, TypeDefinition td) public NetworkBehaviourProcessor(AssemblyDefinition assembly, WeaverTypes weaverTypes, SyncVarAccessLists syncVarAccessLists, Writers writers, Readers readers, Logger Log, TypeDefinition td)
{ {
this.assembly = assembly; this.assembly = assembly;
this.weaverTypes = weaverTypes; this.weaverTypes = weaverTypes;
this.weaverLists = weaverLists; this.syncVarAccessLists = syncVarAccessLists;
this.writers = writers; this.writers = writers;
this.readers = readers; this.readers = readers;
this.Log = Log; this.Log = Log;
syncVarProcessor = new SyncVarProcessor(assembly, weaverTypes, weaverLists, Log); syncVarProcessor = new SyncVarProcessor(assembly, weaverTypes, syncVarAccessLists, Log);
netBehaviourSubclass = td; netBehaviourSubclass = td;
} }
@ -453,7 +453,7 @@ void GenerateSerialization(ref bool WeavingFailed)
// generate a writer call for any dirty variable in this class // generate a writer call for any dirty variable in this class
// start at number of syncvars in parent // start at number of syncvars in parent
int dirtyBit = weaverLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName); int dirtyBit = syncVarAccessLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName);
foreach (FieldDefinition syncVar in syncVars) foreach (FieldDefinition syncVar in syncVars)
{ {
Instruction varLabel = worker.Create(OpCodes.Nop); Instruction varLabel = worker.Create(OpCodes.Nop);
@ -865,7 +865,7 @@ void GenerateDeSerialization(ref bool WeavingFailed)
// conditionally read each syncvar // conditionally read each syncvar
// start at number of syncvars in parent // start at number of syncvars in parent
int dirtyBit = weaverLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName); int dirtyBit = syncVarAccessLists.GetSyncVarStart(netBehaviourSubclass.BaseType.FullName);
foreach (FieldDefinition syncVar in syncVars) foreach (FieldDefinition syncVar in syncVars)
{ {
Instruction varLabel = serWorker.Create(OpCodes.Nop); Instruction varLabel = serWorker.Create(OpCodes.Nop);

View File

@ -11,7 +11,7 @@ namespace Mirror.Weaver
public static class SyncVarAccessReplacer public static class SyncVarAccessReplacer
{ {
// process the module // process the module
public static void Process(ModuleDefinition moduleDef, WeaverLists weaverLists) public static void Process(ModuleDefinition moduleDef, SyncVarAccessLists syncVarAccessLists)
{ {
DateTime startTime = DateTime.Now; DateTime startTime = DateTime.Now;
@ -20,31 +20,31 @@ public static void Process(ModuleDefinition moduleDef, WeaverLists weaverLists)
{ {
if (td.IsClass) if (td.IsClass)
{ {
ProcessClass(weaverLists, td); ProcessClass(syncVarAccessLists, td);
} }
} }
Console.WriteLine($" ProcessSitesModule {moduleDef.Name} elapsed time:{(DateTime.Now - startTime)}"); Console.WriteLine($" ProcessSitesModule {moduleDef.Name} elapsed time:{(DateTime.Now - startTime)}");
} }
static void ProcessClass(WeaverLists weaverLists, TypeDefinition td) static void ProcessClass(SyncVarAccessLists syncVarAccessLists, TypeDefinition td)
{ {
//Console.WriteLine(" ProcessClass " + td); //Console.WriteLine(" ProcessClass " + td);
// process all methods in this class // process all methods in this class
foreach (MethodDefinition md in td.Methods) foreach (MethodDefinition md in td.Methods)
{ {
ProcessMethod(weaverLists, md); ProcessMethod(syncVarAccessLists, md);
} }
// processes all nested classes in this class recursively // processes all nested classes in this class recursively
foreach (TypeDefinition nested in td.NestedTypes) foreach (TypeDefinition nested in td.NestedTypes)
{ {
ProcessClass(weaverLists, nested); ProcessClass(syncVarAccessLists, nested);
} }
} }
static void ProcessMethod(WeaverLists weaverLists, MethodDefinition md) static void ProcessMethod(SyncVarAccessLists syncVarAccessLists, MethodDefinition md)
{ {
// process all references to replaced members with properties // process all references to replaced members with properties
//Weaver.DLog(td, " ProcessSiteMethod " + md); //Weaver.DLog(td, " ProcessSiteMethod " + md);
@ -67,24 +67,24 @@ static void ProcessMethod(WeaverLists weaverLists, MethodDefinition md)
for (int i = 0; i < md.Body.Instructions.Count;) for (int i = 0; i < md.Body.Instructions.Count;)
{ {
Instruction instr = md.Body.Instructions[i]; Instruction instr = md.Body.Instructions[i];
i += ProcessInstruction(weaverLists, md, instr, i); i += ProcessInstruction(syncVarAccessLists, md, instr, i);
} }
} }
} }
static int ProcessInstruction(WeaverLists weaverLists, MethodDefinition md, Instruction instr, int iCount) static int ProcessInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction instr, int iCount)
{ {
// stfld (sets value of a field)? // stfld (sets value of a field)?
if (instr.OpCode == OpCodes.Stfld && instr.Operand is FieldDefinition opFieldst) if (instr.OpCode == OpCodes.Stfld && instr.Operand is FieldDefinition opFieldst)
{ {
ProcessSetInstruction(weaverLists, md, instr, opFieldst); ProcessSetInstruction(syncVarAccessLists, md, instr, opFieldst);
} }
// ldfld (load value of a field)? // ldfld (load value of a field)?
if (instr.OpCode == OpCodes.Ldfld && instr.Operand is FieldDefinition opFieldld) if (instr.OpCode == OpCodes.Ldfld && instr.Operand is FieldDefinition opFieldld)
{ {
// this instruction gets the value of a field. cache the field reference. // this instruction gets the value of a field. cache the field reference.
ProcessGetInstruction(weaverLists, md, instr, opFieldld); ProcessGetInstruction(syncVarAccessLists, md, instr, opFieldld);
} }
// ldflda (load field address aka reference) // ldflda (load field address aka reference)
@ -92,7 +92,7 @@ static int ProcessInstruction(WeaverLists weaverLists, MethodDefinition md, Inst
{ {
// watch out for initobj instruction // watch out for initobj instruction
// see https://github.com/vis2k/Mirror/issues/696 // see https://github.com/vis2k/Mirror/issues/696
return ProcessLoadAddressInstruction(weaverLists, md, instr, opFieldlda, iCount); return ProcessLoadAddressInstruction(syncVarAccessLists, md, instr, opFieldlda, iCount);
} }
// we processed one instruction (instr) // we processed one instruction (instr)
@ -100,14 +100,14 @@ static int ProcessInstruction(WeaverLists weaverLists, MethodDefinition md, Inst
} }
// replaces syncvar write access with the NetworkXYZ.set property calls // replaces syncvar write access with the NetworkXYZ.set property calls
static void ProcessSetInstruction(WeaverLists weaverLists, MethodDefinition md, Instruction i, FieldDefinition opField) static void ProcessSetInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction i, FieldDefinition opField)
{ {
// don't replace property call sites in constructors // don't replace property call sites in constructors
if (md.Name == ".ctor") if (md.Name == ".ctor")
return; return;
// does it set a field that we replaced? // does it set a field that we replaced?
if (weaverLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement)) if (syncVarAccessLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement))
{ {
//replace with property //replace with property
//DLog(td, " replacing " + md.Name + ":" + i); //DLog(td, " replacing " + md.Name + ":" + i);
@ -118,14 +118,14 @@ static void ProcessSetInstruction(WeaverLists weaverLists, MethodDefinition md,
} }
// replaces syncvar read access with the NetworkXYZ.get property calls // replaces syncvar read access with the NetworkXYZ.get property calls
static void ProcessGetInstruction(WeaverLists weaverLists, MethodDefinition md, Instruction i, FieldDefinition opField) static void ProcessGetInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction i, FieldDefinition opField)
{ {
// don't replace property call sites in constructors // don't replace property call sites in constructors
if (md.Name == ".ctor") if (md.Name == ".ctor")
return; return;
// does it set a field that we replaced? // does it set a field that we replaced?
if (weaverLists.replacementGetterProperties.TryGetValue(opField, out MethodDefinition replacement)) if (syncVarAccessLists.replacementGetterProperties.TryGetValue(opField, out MethodDefinition replacement))
{ {
//replace with property //replace with property
//DLog(td, " replacing " + md.Name + ":" + i); //DLog(td, " replacing " + md.Name + ":" + i);
@ -135,14 +135,14 @@ static void ProcessGetInstruction(WeaverLists weaverLists, MethodDefinition md,
} }
} }
static int ProcessLoadAddressInstruction(WeaverLists weaverLists, MethodDefinition md, Instruction instr, FieldDefinition opField, int iCount) static int ProcessLoadAddressInstruction(SyncVarAccessLists syncVarAccessLists, MethodDefinition md, Instruction instr, FieldDefinition opField, int iCount)
{ {
// don't replace property call sites in constructors // don't replace property call sites in constructors
if (md.Name == ".ctor") if (md.Name == ".ctor")
return 1; return 1;
// does it set a field that we replaced? // does it set a field that we replaced?
if (weaverLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement)) if (syncVarAccessLists.replacementSetterProperties.TryGetValue(opField, out MethodDefinition replacement))
{ {
// we have a replacement for this property // we have a replacement for this property
// is the next instruction a initobj? // is the next instruction a initobj?

View File

@ -14,17 +14,17 @@ public class SyncVarProcessor
AssemblyDefinition assembly; AssemblyDefinition assembly;
WeaverTypes weaverTypes; WeaverTypes weaverTypes;
WeaverLists weaverLists; SyncVarAccessLists syncVarAccessLists;
Logger Log; Logger Log;
string HookParameterMessage(string hookName, TypeReference ValueType) => string HookParameterMessage(string hookName, TypeReference ValueType) =>
$"void {hookName}({ValueType} oldValue, {ValueType} newValue)"; $"void {hookName}({ValueType} oldValue, {ValueType} newValue)";
public SyncVarProcessor(AssemblyDefinition assembly, WeaverTypes weaverTypes, WeaverLists weaverLists, Logger Log) public SyncVarProcessor(AssemblyDefinition assembly, WeaverTypes weaverTypes, SyncVarAccessLists syncVarAccessLists, Logger Log)
{ {
this.assembly = assembly; this.assembly = assembly;
this.weaverTypes = weaverTypes; this.weaverTypes = weaverTypes;
this.weaverLists = weaverLists; this.syncVarAccessLists = syncVarAccessLists;
this.Log = Log; this.Log = Log;
} }
@ -342,7 +342,7 @@ public void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, Dictionary<Fie
td.Methods.Add(get); td.Methods.Add(get);
td.Methods.Add(set); td.Methods.Add(set);
td.Properties.Add(propertyDefinition); td.Properties.Add(propertyDefinition);
weaverLists.replacementSetterProperties[fd] = set; syncVarAccessLists.replacementSetterProperties[fd] = set;
// replace getter field if GameObject/NetworkIdentity so it uses // replace getter field if GameObject/NetworkIdentity so it uses
// netId instead // netId instead
@ -350,7 +350,7 @@ public void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, Dictionary<Fie
// end up in recursion. // end up in recursion.
if (fd.FieldType.IsNetworkIdentityField()) if (fd.FieldType.IsNetworkIdentityField())
{ {
weaverLists.replacementGetterProperties[fd] = get; syncVarAccessLists.replacementGetterProperties[fd] = get;
} }
} }
@ -361,7 +361,7 @@ public void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, Dictionary<Fie
// the mapping of dirtybits to sync-vars is implicit in the order of the fields here. this order is recorded in m_replacementProperties. // the mapping of dirtybits to sync-vars is implicit in the order of the fields here. this order is recorded in m_replacementProperties.
// start assigning syncvars at the place the base class stopped, if any // start assigning syncvars at the place the base class stopped, if any
int dirtyBitCounter = weaverLists.GetSyncVarStart(td.BaseType.FullName); int dirtyBitCounter = syncVarAccessLists.GetSyncVarStart(td.BaseType.FullName);
// find syncvars // find syncvars
foreach (FieldDefinition fd in td.Fields) foreach (FieldDefinition fd in td.Fields)
@ -408,7 +408,7 @@ public void ProcessSyncVar(TypeDefinition td, FieldDefinition fd, Dictionary<Fie
{ {
td.Fields.Add(fd); td.Fields.Add(fd);
} }
weaverLists.SetNumSyncVars(td.FullName, syncVars.Count); syncVarAccessLists.SetNumSyncVars(td.FullName, syncVars.Count);
return (syncVars, syncVarNetIds); return (syncVars, syncVarNetIds);
} }

View File

@ -4,7 +4,7 @@
namespace Mirror.Weaver namespace Mirror.Weaver
{ {
// This data is flushed each time - if we are run multiple times in the same process/domain // This data is flushed each time - if we are run multiple times in the same process/domain
public class WeaverLists public class SyncVarAccessLists
{ {
// setter functions that replace [SyncVar] member variable references. dict<field, replacement> // setter functions that replace [SyncVar] member variable references. dict<field, replacement>
public Dictionary<FieldDefinition, MethodDefinition> replacementSetterProperties = public Dictionary<FieldDefinition, MethodDefinition> replacementSetterProperties =

View File

@ -20,7 +20,7 @@ internal class Weaver
public const string MirrorAssemblyName = "Mirror"; public const string MirrorAssemblyName = "Mirror";
WeaverTypes weaverTypes; WeaverTypes weaverTypes;
WeaverLists weaverLists; SyncVarAccessLists syncVarAccessLists;
IAssemblyResolver Resolver; IAssemblyResolver Resolver;
AssemblyDefinition CurrentAssembly; AssemblyDefinition CurrentAssembly;
Writers writers; Writers writers;
@ -78,7 +78,7 @@ bool WeaveNetworkBehavior(TypeDefinition td)
bool modified = false; bool modified = false;
foreach (TypeDefinition behaviour in behaviourClasses) foreach (TypeDefinition behaviour in behaviourClasses)
{ {
modified |= new NetworkBehaviourProcessor(CurrentAssembly, weaverTypes, weaverLists, writers, readers, Log, behaviour).Process(ref WeavingFailed); modified |= new NetworkBehaviourProcessor(CurrentAssembly, weaverTypes, syncVarAccessLists, writers, readers, Log, behaviour).Process(ref WeavingFailed);
} }
return modified; return modified;
} }
@ -159,7 +159,7 @@ public bool Weave(AssemblyDefinition assembly, IAssemblyResolver resolver, out b
CreateGeneratedCodeClass(); CreateGeneratedCodeClass();
// WeaverList depends on WeaverTypes setup because it uses Import // WeaverList depends on WeaverTypes setup because it uses Import
weaverLists = new WeaverLists(); syncVarAccessLists = new SyncVarAccessLists();
// initialize readers & writers with this assembly. // initialize readers & writers with this assembly.
// we need to do this in every Process() call. // we need to do this in every Process() call.
@ -187,7 +187,7 @@ public bool Weave(AssemblyDefinition assembly, IAssemblyResolver resolver, out b
if (modified) if (modified)
{ {
SyncVarAccessReplacer.Process(moduleDefinition, weaverLists); SyncVarAccessReplacer.Process(moduleDefinition, syncVarAccessLists);
// add class that holds read/write functions // add class that holds read/write functions
moduleDefinition.Types.Add(GeneratedCodeClass); moduleDefinition.Types.Add(GeneratedCodeClass);