Skip to content

Commit

Permalink
因为xlua.util.hotfix_state已经可以达成类似的效果,所以直接去掉Stateful方式,简化设计。
Browse files Browse the repository at this point in the history
  • Loading branch information
chexiongsheng committed Apr 28, 2018
1 parent bff34d0 commit a58c268
Show file tree
Hide file tree
Showing 8 changed files with 17 additions and 78 deletions.
18 changes: 3 additions & 15 deletions Assets/XLua/Doc/hotfix.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,11 @@ public static class HotfixCfg

Hotfix标签可以设置一些标志位对生成代码及插桩定制化

* Stateless
* Stateless、Stateful

Stateless和Stateful的区别请看下下节
遗留设置,Stateful方式在新版本已经删除,因为这种方式可以用xlua.util.hotfix_state接口达到类似的效果,该接口的使用可以看下HotfixTest2.cs里的示例代码

* Stateful

同上。
由于没Stateful,默认就是Stateless,所以也没必要设置该标志位。

* ValueTypeBoxing

Expand Down Expand Up @@ -184,16 +182,6 @@ xlua.hotfix(CS.HotfixTest, 'Update', function(self)
* 业务代码、引擎API、系统API,需要在Lua补丁里头高性能访问的类型,加上LuaCallCSharp;
* 引擎API、系统API可能被代码剪裁调(C#无引用的地方都会被剪裁),如果觉得可能会新增C#代码之外的API调用,这些API所在的类型要么加LuaCallCSharp,要么加ReflectionUse;

## Stateless和Stateful

打Hotfix标签时,默认、也建议是Stateless方式,而Stateful方式是对Stateless的补充。

Stateful方式的区别是你可以在Lua的构造函数返回一个table,该table后续可以通过self.__HotfixTable访问这个table(self指的是该C#对象),这个table可以存一些和该对象相关的信息。

Stateful方式还可以用xlua.util.hotfix_state(csobj, state)来避免显式访问self.__HotfixTable,使用该api后,self.xxx 将会优先访问state里头的字段。不仅美观,而且性能也会更好。(参见HotfixTest2.cs)

Stateful的代价是会在类增加一个LuaTable类型的字段(中间层面增加,不会改源代码)。而且,执行xlua.hotfix之前就new好的对象,__HotfixTable会是空,所以需要重启,在一开始就执行替换。

## 打补丁

xlua可以用lua函数替换C#的构造函数,函数,属性,事件的替换。lua实现都是函数,比如属性对于一个getter函数和一个setter函数,事件对应一个add函数和一个remove函数。
Expand Down
4 changes: 2 additions & 2 deletions Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public string Proxy()
}
}

[Hotfix(HotfixFlag.Stateful)]
[Hotfix]
public struct GenericStruct<T>
{
T a;
Expand Down Expand Up @@ -282,7 +282,7 @@ void Start () {
local util = require 'xlua.util'
xlua.hotfix(CS.StatefullTest, {
['.ctor'] = function(csobj)
return util.hotfix_state(csobj, {evt = {}, start = 0, prop = 0})
util.hotfix_state(csobj, {evt = {}, start = 0, prop = 0})
end;
set_AProp = function(self, v)
print('set_AProp', v)
Expand Down
3 changes: 1 addition & 2 deletions Assets/XLua/Examples/08_Hotfix/StatefullTest.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using UnityEngine;
using System.Collections;

[XLua.Hotfix(XLua.HotfixFlag.Stateful)]
[XLua.Hotfix]
public class StatefullTest {
public StatefullTest()
{
Expand Down
6 changes: 1 addition & 5 deletions Assets/XLua/Src/Editor/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -767,13 +767,10 @@ static bool hasGenericParameter(Type type)

static MethodInfoSimulation makeHotfixMethodInfoSimulation(MethodBase hotfixMethod, HotfixFlag hotfixType)
{
bool isStateful = hotfixType.HasFlag(HotfixFlag.Stateful);
bool ignoreValueType = hotfixType.HasFlag(HotfixFlag.ValueTypeBoxing);
//isStateful = false;
//ignoreValueType = true;

Type retTypeExpect = (isStateful && hotfixMethod.IsConstructor && !hotfixMethod.IsStatic)
? typeof(LuaTable) : (hotfixMethod.IsConstructor ? typeof(void) : (hotfixMethod as MethodInfo).ReturnType);
Type retTypeExpect = (hotfixMethod.IsConstructor ? typeof(void) : (hotfixMethod as MethodInfo).ReturnType);
int hashCode = retTypeExpect.GetHashCode();
List<ParameterInfoSimulation> paramsExpect = new List<ParameterInfoSimulation>();
if (!hotfixMethod.IsStatic) // add self
Expand Down Expand Up @@ -855,7 +852,6 @@ public int GetHashCode(MethodInfoSimulation obj)
static bool injectByGeneric(MethodBase method, HotfixFlag hotfixType)
{
bool ignoreValueType = hotfixType.HasFlag(HotfixFlag.ValueTypeBoxing);
//isStateful = false;
//ignoreValueType = true;

if (!method.IsConstructor && (isNotPublic((method as MethodInfo).ReturnType) || hasGenericParameter((method as MethodInfo).ReturnType))) return true;
Expand Down
63 changes: 9 additions & 54 deletions Assets/XLua/Src/Editor/Hotfix.cs
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,12 @@ static bool isSameType(TypeReference left, TypeReference right)

bool findHotfixDelegate(MethodDefinition method, out MethodReference invoke, HotfixFlagInTool hotfixType)
{
bool isStateful = hotfixType.HasFlag(HotfixFlagInTool.Stateful);
bool ignoreValueType = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing);

for (int i = 0; i < hotfixBridgesDef.Count; i++)
{
MethodDefinition hotfixBridgeDef = hotfixBridgesDef[i];
var returnType = (isStateful && method.IsConstructor && !method.IsStatic) ? luaTableType : method.ReturnType;
var returnType = method.ReturnType;
if (isSameType(returnType, hotfixBridgeDef.ReturnType))
{
var parametersOfDelegate = hotfixBridgeDef.Parameters;
Expand Down Expand Up @@ -532,7 +531,6 @@ public bool InjectType(TypeReference hotfixAttributeType, TypeDefinition type)
hotfixType = (HotfixFlagInTool)hotfixCfg[type.FullName];
}

bool isStateful = hotfixType.HasFlag(HotfixFlagInTool.Stateful);
bool ignoreProperty = hotfixType.HasFlag(HotfixFlagInTool.IgnoreProperty);
bool ignoreNotPublic = hotfixType.HasFlag(HotfixFlagInTool.IgnoreNotPublic);
bool isInline = hotfixType.HasFlag(HotfixFlagInTool.Inline);
Expand All @@ -543,18 +541,6 @@ public bool InjectType(TypeReference hotfixAttributeType, TypeDefinition type)
}
//isIntKey = !type.HasGenericParameters;

FieldReference stateTable = null;
if (isStateful)
{
if (type.IsAbstract && type.IsSealed)
{
throw new InvalidOperationException(type.FullName + " is static, can not be mark as Stateful!");
}
var stateTableDefinition = new FieldDefinition("__HotfixTable", Mono.Cecil.FieldAttributes.Private, luaTableType);
type.Fields.Add(stateTableDefinition);
stateTable = stateTableDefinition.GetGeneric();
}

foreach (var method in type.Methods)
{
if (ignoreNotPublic && !method.IsPublic)
Expand All @@ -569,8 +555,8 @@ public bool InjectType(TypeReference hotfixAttributeType, TypeDefinition type)
{
//Debug.Log(method);
if ((isInline || method.HasGenericParameters || genericInOut(method, hotfixType))
? !injectGenericMethod(method, hotfixType, stateTable) :
!injectMethod(method, hotfixType, stateTable))
? !injectGenericMethod(method, hotfixType) :
!injectMethod(method, hotfixType))
{
return false;
}
Expand Down Expand Up @@ -924,7 +910,7 @@ static MethodDefinition tryAddBaseProxy(TypeDefinition type, MethodDefinition me
return null;
}

bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType, FieldReference stateTable)
bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType)
{
var type = method.DeclaringType;

Expand Down Expand Up @@ -974,9 +960,7 @@ bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType, FieldRef
fieldReference = fieldDefinition.GetGeneric();
}

bool isStateful = hotfixType.HasFlag(HotfixFlagInTool.Stateful);
bool ignoreValueType = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing);
bool statefulConstructor = isStateful && method.IsConstructor && !method.IsStatic;

var insertPoint = method.Body.Instructions[0];
var processor = method.Body.GetILProcessor();
Expand All @@ -1001,10 +985,6 @@ bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType, FieldRef
}
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Brfalse, insertPoint));

if (statefulConstructor)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
}
if (isIntKey)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldc_I4, bridgeIndexByKey.Count));
Expand Down Expand Up @@ -1053,16 +1033,7 @@ bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType, FieldRef
}

processor.InsertBefore(insertPoint, processor.Create(OpCodes.Call, invoke));
if (statefulConstructor)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
}
if (isFinalize && isStateful)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldnull));
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
}

if (!method.IsConstructor && !isFinalize)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ret));
Expand Down Expand Up @@ -1090,7 +1061,7 @@ bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType, FieldRef
return true;
}

bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType, FieldReference stateTable)
bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType)
{
var type = method.DeclaringType;

Expand Down Expand Up @@ -1129,8 +1100,6 @@ bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType, F
insertPoint = findNextRet(method.Body.Instructions, insertPoint);
}

bool isStateful = hotfixType.HasFlag(HotfixFlagInTool.Stateful);

while (insertPoint != null)
{
if (isIntKey)
Expand All @@ -1154,9 +1123,7 @@ bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType, F

processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, invokeSessionStart));

bool statefulConstructor = isStateful && method.IsConstructor && !method.IsStatic;

TypeReference returnType = statefulConstructor ? luaTableType : method.ReturnType;
TypeReference returnType = method.ReturnType;

bool isVoid = returnType.FullName == "System.Void";

Expand Down Expand Up @@ -1255,10 +1222,7 @@ bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType, F
outPos++;
}
}
if (statefulConstructor)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
}

processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldloc, injection));
if (isVoid)
{
Expand All @@ -1268,16 +1232,7 @@ bool injectGenericMethod(MethodDefinition method, HotfixFlagInTool hotfixType, F
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Callvirt, invokeSessionEndWithResult.MakeGenericMethod(returnType)));
}
if (statefulConstructor)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
}
if (isFinalize && isStateful)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldarg_0));
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ldnull));
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Stfld, stateTable));
}

if (!method.IsConstructor && !isFinalize)
{
processor.InsertBefore(insertPoint, processor.Create(OpCodes.Ret));
Expand Down
1 change: 1 addition & 0 deletions Assets/XLua/Src/GenAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ public class AdditionalPropertiesAttribute : Attribute
public enum HotfixFlag
{
Stateless = 0,
[Obsolete("use xlua.util.hotfix_state instead!", true)]
Stateful = 1,
ValueTypeBoxing = 2,
IgnoreProperty = 4,
Expand Down
Binary file modified Tools/XLuaHotfixInject.exe
Binary file not shown.
Binary file modified Tools/XLuaHotfixInject.pdb
Binary file not shown.

0 comments on commit a58c268

Please sign in to comment.