From 5f757be3130c627fa3e8f9717c791b6be2a78124 Mon Sep 17 00:00:00 2001 From: ChanyaKushima Date: Sat, 24 Jul 2021 16:13:44 +0900 Subject: [PATCH] Improved compilation speed. --- .../Editor/Editors/EasyEventEditor.cs | 2 +- .../Editors/UdonSharpBehaviourEditor.cs | 20 +--- .../UdonSharp/Editor/Editors/UdonSharpGUI.cs | 6 +- .../Editor/Editors/UdonTypeExposureTree.cs | 46 ++++----- .../UdonSharpBehaviourFormatterEmitter.cs | 4 +- .../UdonVariableStorageInterface.cs | 2 +- .../UdonSharp/Editor/UdonSharpASTVisitor.cs | 16 ++-- .../Editor/UdonSharpAssetCompileWatcher.cs | 17 +--- .../Editor/UdonSharpCompilationModule.cs | 2 +- Assets/UdonSharp/Editor/UdonSharpCompiler.cs | 10 +- .../Editor/UdonSharpEditorManager.cs | 8 +- .../Editor/UdonSharpExpressionCapture.cs | 95 ++++++++----------- .../UdonSharp/Editor/UdonSharpFieldVisitor.cs | 2 +- .../Editor/UdonSharpResolverContext.cs | 22 ++--- .../UdonSharp/Editor/UdonSharpSymbolTable.cs | 50 +++++----- .../UdonSharp/Editor/UdonSharpSyntaxWalker.cs | 2 +- Assets/UdonSharp/Editor/UdonSharpUtils.cs | 84 ++++++++++++---- .../UdonSharp/Scripts/UdonSharpBehaviour.cs | 2 +- 18 files changed, 206 insertions(+), 184 deletions(-) diff --git a/Assets/UdonSharp/Editor/Editors/EasyEventEditor.cs b/Assets/UdonSharp/Editor/Editors/EasyEventEditor.cs index cfe68bb6..99e8a023 100644 --- a/Assets/UdonSharp/Editor/Editors/EasyEventEditor.cs +++ b/Assets/UdonSharp/Editor/Editors/EasyEventEditor.cs @@ -1131,7 +1131,7 @@ void FindValidMethods(Object targetObject, PersistentListenerMode listenerMode, // For some reason BindingFlags.FlattenHierarchy does not seem to work, so we manually traverse the base types instead while (objectType != null) { - MethodInfo[] foundMethodsOnType = objectType.GetMethods(BindingFlags.Public | (cachedSettings.showPrivateMembers ? BindingFlags.NonPublic : BindingFlags.Default) | BindingFlags.Instance); + MethodInfo[] foundMethodsOnType = UdonSharpUtils.GetTypeMethods(objectType,BindingFlags.Public | (cachedSettings.showPrivateMembers ? BindingFlags.NonPublic : BindingFlags.Default) | BindingFlags.Instance); foundMethods.AddRange(foundMethodsOnType); diff --git a/Assets/UdonSharp/Editor/Editors/UdonSharpBehaviourEditor.cs b/Assets/UdonSharp/Editor/Editors/UdonSharpBehaviourEditor.cs index 46fc9b23..d74130b8 100644 --- a/Assets/UdonSharp/Editor/Editors/UdonSharpBehaviourEditor.cs +++ b/Assets/UdonSharp/Editor/Editors/UdonSharpBehaviourEditor.cs @@ -171,10 +171,7 @@ public static void OverrideUdonBehaviourDrawer() System.Type fieldType = customEditorField.FieldType; - removeTypeMethod = fieldType.GetMethods(BindingFlags.Public | BindingFlags.Instance) - .FirstOrDefault(e => e.Name == "Remove" && - e.GetParameters().Length == 1 && - e.GetParameters()[0].ParameterType == typeof(System.Type)); + removeTypeMethod = fieldType.GetMethod("Remove", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(System.Type) }, null); monoEditorTypeType = editorAttributesClass.GetNestedType("MonoEditorType", BindingFlags.NonPublic); monoEditorTypeInspectedTypeField = monoEditorTypeType.GetField("m_InspectedType", BindingFlags.Public | BindingFlags.Instance); @@ -183,20 +180,11 @@ public static void OverrideUdonBehaviourDrawer() monoEditorTypeListType = typeof(List<>).MakeGenericType(monoEditorTypeType); - addTypeMethod = fieldType.GetMethods(BindingFlags.Public | BindingFlags.Instance) - .FirstOrDefault(e => e.Name == "Add" && - e.GetParameters().Length == 2 && - e.GetParameters()[0].ParameterType == typeof(System.Type) && - e.GetParameters()[1].ParameterType == monoEditorTypeListType); + addTypeMethod = fieldType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { typeof(System.Type), monoEditorTypeListType }, null); - listAddTypeMethod = monoEditorTypeListType.GetMethods(BindingFlags.Public | BindingFlags.Instance) - .FirstOrDefault(e => e.Name == "Add" && - e.GetParameters().Length == 1 && - e.GetParameters()[0].ParameterType == monoEditorTypeType); + listAddTypeMethod = monoEditorTypeListType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance, null, new Type[] { monoEditorTypeType }, null); - listClearMethod = monoEditorTypeListType.GetMethods(BindingFlags.Public | BindingFlags.Instance) - .FirstOrDefault(e => e.Name == "Clear" && - e.GetParameters().Length == 0); + listClearMethod = monoEditorTypeListType.GetMethod("Clear", BindingFlags.Public | BindingFlags.Instance, null, Array.Empty(), null); customEditorDictionary = customEditorField.GetValue(null); diff --git a/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs b/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs index b7dc28a9..86ea2449 100644 --- a/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs +++ b/Assets/UdonSharp/Editor/Editors/UdonSharpGUI.cs @@ -224,7 +224,7 @@ void ShowDropDown(Rect controlRect, Vector2 size) popupLocationArray.SetValue(4, 1); // PopupLocation.Overlay } - MethodInfo showAsDropDownMethod = typeof(EditorWindow).GetMethods(BindingFlags.NonPublic | BindingFlags.Instance).First(e => e.GetParameters().Length == 3); + MethodInfo showAsDropDownMethod = UdonSharpUtils.GetTypeMethods(typeof(EditorWindow), BindingFlags.NonPublic | BindingFlags.Instance).First(e => e.GetParameters().Length == 3); showAsDropDownMethod.Invoke(this, new object[] { controlRect, size, popupLocationArray }); } @@ -546,7 +546,7 @@ private static object DrawUnityObjectField(GUIContent fieldName, string symbol, if (IsNormalUnityObject(declaredType, fieldDefinition)) return EditorGUILayout.ObjectField(fieldName, (UnityEngine.Object)value, declaredType, true); - MethodInfo doObjectFieldMethod = typeof(EditorGUI).GetMethods(BindingFlags.Static | BindingFlags.NonPublic).Where(e => e.Name == "DoObjectField" && e.GetParameters().Length == 8).FirstOrDefault(); + MethodInfo doObjectFieldMethod = UdonSharpUtils.GetTypeMethods(typeof(EditorGUI), BindingFlags.Static | BindingFlags.NonPublic).FirstOrDefault(e => e.Name == "DoObjectField" && e.GetParameters().Length == 8); if (doObjectFieldMethod == null) throw new System.Exception("Could not find DoObjectField() method"); @@ -1622,7 +1622,7 @@ public static bool DrawConvertToUdonBehaviourButton(UnityEngine.Object[] targets EditorGUI.BeginDisabledGroup(EditorApplication.isPlaying); if (GUILayout.Button("Convert to UdonBehaviour", GUILayout.Height(25))) { - UdonSharpEditorUtility.ConvertToUdonBehavioursInternal(Array.ConvertAll(targets, e => e as UdonSharpBehaviour).Where(e => e != null && !UdonSharpEditorUtility.IsProxyBehaviour(e)).ToArray(), true, true, true); + UdonSharpEditorUtility.ConvertToUdonBehavioursInternal(targets.Select(e => e as UdonSharpBehaviour).Where(e => e != null && !UdonSharpEditorUtility.IsProxyBehaviour(e)).ToArray(), true, true, true); EditorGUI.EndDisabledGroup(); return true; diff --git a/Assets/UdonSharp/Editor/Editors/UdonTypeExposureTree.cs b/Assets/UdonSharp/Editor/Editors/UdonTypeExposureTree.cs index 45c3847f..02182a06 100644 --- a/Assets/UdonSharp/Editor/Editors/UdonTypeExposureTree.cs +++ b/Assets/UdonSharp/Editor/Editors/UdonTypeExposureTree.cs @@ -138,16 +138,16 @@ private string GetMemberUdonName(TreeViewItem item, ExposureLookupType lookupTyp if (member.MemberType == MemberTypes.Constructor || member.MemberType == MemberTypes.Method) { - return resolver.GetUdonMethodName((MethodBase)member, false); + return ResolverContext.GetUdonMethodName((MethodBase)member, false); } else if (member.MemberType == MemberTypes.Property) { string udonNames = ""; if (((PropertyInfo)member).GetGetMethod() != null) - udonNames = resolver.GetUdonMethodName(((PropertyInfo)member).GetGetMethod(), false); + udonNames = ResolverContext.GetUdonMethodName(((PropertyInfo)member).GetGetMethod(), false); if (((PropertyInfo)member).GetSetMethod() != null) - udonNames += "\n" + resolver.GetUdonMethodName(((PropertyInfo)member).GetSetMethod(), false); + udonNames += "\n" + ResolverContext.GetUdonMethodName(((PropertyInfo)member).GetSetMethod(), false); return udonNames; } @@ -270,7 +270,7 @@ bool ShouldHideMember(MemberInfo memberInfo) if (memberInfo is MethodInfo methodInfo) { - string methodUdonName = resolver.GetUdonMethodName(methodInfo, false); + string methodUdonName = ResolverContext.GetUdonMethodName(methodInfo, false); //if (resolver.IsValidUdonMethod(methodUdonName)) { @@ -295,7 +295,7 @@ bool ShouldHideMember(MemberInfo memberInfo) } else if (memberInfo is PropertyInfo propertyInfo) { - string propertyName = resolver.GetUdonMethodName(propertyInfo.GetGetMethod(), false); + string propertyName = ResolverContext.GetUdonMethodName(propertyInfo.GetGetMethod(), false); //if (resolver.IsValidUdonMethod(propertyName)) shouldHide &= ShouldHideType(propertyInfo.PropertyType); @@ -359,7 +359,7 @@ private void AddChildNode(TreeViewItem parentItem, MemberInfo memberInfo, ref in { case MemberTypes.Constructor: case MemberTypes.Method: - itemMetadata.exposed = resolver.IsValidUdonMethod(resolver.GetUdonMethodName((MethodBase)memberInfo, false)); + itemMetadata.exposed = resolver.IsValidUdonMethod(ResolverContext.GetUdonMethodName((MethodBase)memberInfo, false)); break; case MemberTypes.Field: string getAccessor = resolver.GetUdonFieldAccessorName((FieldInfo)memberInfo, FieldAccessorType.Get, false); @@ -370,12 +370,12 @@ private void AddChildNode(TreeViewItem parentItem, MemberInfo memberInfo, ref in itemMetadata.exposed = resolver.IsValidUdonMethod(getAccessor); break; case MemberTypes.Property: - string getProperty = resolver.GetUdonMethodName(((PropertyInfo)memberInfo).GetGetMethod(), false); + string getProperty = ResolverContext.GetUdonMethodName(((PropertyInfo)memberInfo).GetGetMethod(), false); exposedUdonExterns.Remove(getProperty); if (((PropertyInfo)memberInfo).GetSetMethod() != null) { - string setProperty = resolver.GetUdonMethodName(((PropertyInfo)memberInfo).GetSetMethod(), false); + string setProperty = ResolverContext.GetUdonMethodName(((PropertyInfo)memberInfo).GetSetMethod(), false); exposedUdonExterns.Remove(setProperty); } @@ -514,7 +514,7 @@ private void BuildExposedTypeList() if (type.IsByRef) continue; - string typeName = resolver.GetUdonTypeName(type); + string typeName = ResolverContext.GetUdonTypeName(type); if (resolver.ValidateUdonTypeName(typeName, UdonReferenceType.Type) || resolver.ValidateUdonTypeName(typeName, UdonReferenceType.Variable) || UdonEditorManager.Instance.GetTypeFromTypeString(typeName) != null) @@ -525,11 +525,11 @@ private void BuildExposedTypeList() exposedTypeSet.Add(type.MakeArrayType()); } - MethodInfo[] methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); + MethodInfo[] methods = UdonSharpUtils.GetTypeMethods(type, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static); foreach (MethodInfo method in methods) { - if (resolver.IsValidUdonMethod(resolver.GetUdonMethodName(method, false))) + if (resolver.IsValidUdonMethod(ResolverContext.GetUdonMethodName(method, false))) { exposedTypeSet.Add(method.DeclaringType); @@ -559,13 +559,13 @@ private void BuildExposedTypeList() } } - foreach (PropertyInfo property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) + foreach (PropertyInfo property in UdonSharpUtils.GetTypeProperties(type, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static)) { MethodInfo propertyGetter = property.GetGetMethod(); if (propertyGetter == null) continue; - if (resolver.IsValidUdonMethod(resolver.GetUdonMethodName(propertyGetter, false))) + if (resolver.IsValidUdonMethod(ResolverContext.GetUdonMethodName(propertyGetter, false))) { System.Type returnType = propertyGetter.ReturnType; @@ -679,35 +679,35 @@ protected override TreeViewItem BuildRoot() namespaceParent.AddChild(typeParent); itemMetadatas.Add(typeParent, new TypeItemMetadata() { isType = true }); - exposedUdonExterns.Remove("Variable_" + resolver.GetUdonTypeName(type)); - exposedUdonExterns.Remove("Const_" + resolver.GetUdonTypeName(type)); - exposedUdonExterns.Remove("Type_" + resolver.GetUdonTypeName(type)); - exposedUdonExterns.Remove("Type_" + resolver.GetUdonTypeName(type.MakeByRefType())); + exposedUdonExterns.Remove("Variable_" + ResolverContext.GetUdonTypeName(type)); + exposedUdonExterns.Remove("Const_" + ResolverContext.GetUdonTypeName(type)); + exposedUdonExterns.Remove("Type_" + ResolverContext.GetUdonTypeName(type)); + exposedUdonExterns.Remove("Type_" + ResolverContext.GetUdonTypeName(type.MakeByRefType())); //if (!type.IsEnum) //{ // // Variable definition // TreeViewItem variableDef = new TreeViewItem(currentID++, typeParent.depth + 1, " " + type.Name); // typeParent.AddChild(variableDef); - // itemMetadatas.Add(variableDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(resolver.GetUdonTypeName(type), UdonReferenceType.Variable) }); + // itemMetadatas.Add(variableDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(ResolverContext.GetUdonTypeName(type), UdonReferenceType.Variable) }); //} // Type definition //TreeViewItem typeDef = new TreeViewItem(currentID++, typeParent.depth + 1, " " + type.Name); //typeParent.AddChild(typeDef); - //itemMetadatas.Add(typeDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(resolver.GetUdonTypeName(type), UdonReferenceType.Type) }); + //itemMetadatas.Add(typeDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(ResolverContext.GetUdonTypeName(type), UdonReferenceType.Type) }); // Internal type TreeViewItem internalTypeDef = new TreeViewItem(currentID++, typeParent.depth + 1, " " + type.Name); typeParent.AddChild(internalTypeDef); - itemMetadatas.Add(internalTypeDef, new TypeItemMetadata() { exposed = UdonEditorManager.Instance.GetTypeFromTypeString(resolver.GetUdonTypeName(type)) != null }); + itemMetadatas.Add(internalTypeDef, new TypeItemMetadata() { exposed = UdonEditorManager.Instance.GetTypeFromTypeString(ResolverContext.GetUdonTypeName(type)) != null }); // Const definition //if (!type.IsArray && !type.IsEnum) //{ // TreeViewItem constDef = new TreeViewItem(currentID++, typeParent.depth + 1, " " + type.Name); // typeParent.AddChild(constDef); - // itemMetadatas.Add(constDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(resolver.GetUdonTypeName(type), UdonReferenceType.Const) }); + // itemMetadatas.Add(constDef, new TypeItemMetadata() { exposed = resolver.ValidateUdonTypeName(ResolverContext.GetUdonTypeName(type), UdonReferenceType.Const) }); //} BindingFlags bindingFlags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static; @@ -724,14 +724,14 @@ protected override TreeViewItem BuildRoot() AddChildNode(typeParent, field, ref currentID); } - foreach (PropertyInfo property in type.GetProperties(bindingFlags)) + foreach (PropertyInfo property in UdonSharpUtils.GetTypeProperties(type, bindingFlags)) { AddChildNode(typeParent, property, ref currentID); } if (!type.IsEnum) { - foreach (MethodInfo method in type.GetMethods(bindingFlags).Where(e => (!type.IsArray || e.Name != "Address"))) + foreach (MethodInfo method in UdonSharpUtils.GetTypeMethods(type, bindingFlags).Where(e => (!type.IsArray || e.Name != "Address"))) { if (method.IsSpecialName && !method.Name.StartsWith("op_")) continue; diff --git a/Assets/UdonSharp/Editor/Serialization/Formatters/UdonSharpBehaviourFormatterEmitter.cs b/Assets/UdonSharp/Editor/Serialization/Formatters/UdonSharpBehaviourFormatterEmitter.cs index 33dae587..ebcefc3c 100644 --- a/Assets/UdonSharp/Editor/Serialization/Formatters/UdonSharpBehaviourFormatterEmitter.cs +++ b/Assets/UdonSharp/Editor/Serialization/Formatters/UdonSharpBehaviourFormatterEmitter.cs @@ -185,7 +185,7 @@ public static Formatter GetFormatter() where T : UdonSharpBehaviour // Read { System.Type readDelegateType = typeof(ReadDataMethodDelegate<>).MakeGenericType(typeof(T)); - MethodInfo readDataMethod = formatterType.GetMethods(Flags.InstancePublic).Where(e => e.Name == "Read" && e.GetParameters().Length == 2).First(); + MethodInfo readDataMethod = UdonSharpUtils.GetTypeMethods(formatterType, Flags.InstancePublic).First(e => e.Name == "Read" && e.GetParameters().Length == 2); DynamicMethod readMethod = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Read", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true); foreach (ParameterInfo param in readDataMethod.GetParameters()) @@ -199,7 +199,7 @@ public static Formatter GetFormatter() where T : UdonSharpBehaviour // Write { System.Type writeDelegateType = typeof(WriteDataMethodDelegate<>).MakeGenericType(typeof(T)); - MethodInfo writeDataMethod = formatterType.GetMethods(Flags.InstancePublic).Where(e => e.Name == "Write" && e.GetParameters().Length == 2).First(); + MethodInfo writeDataMethod = UdonSharpUtils.GetTypeMethods(formatterType, Flags.InstancePublic).First(e => e.Name == "Write" && e.GetParameters().Length == 2); DynamicMethod writeMethod = new DynamicMethod($"Dynamic_{typeof(T).GetCompilableNiceFullName()}_Write", null, new[] { typeof(IValueStorage[]), typeof(T).MakeByRefType(), typeof(bool) }, true); foreach (ParameterInfo param in writeDataMethod.GetParameters()) diff --git a/Assets/UdonSharp/Editor/Serialization/StorageInterfaces/UdonVariableStorageInterface.cs b/Assets/UdonSharp/Editor/Serialization/StorageInterfaces/UdonVariableStorageInterface.cs index 04244d9f..f0d6f4fc 100644 --- a/Assets/UdonSharp/Editor/Serialization/StorageInterfaces/UdonVariableStorageInterface.cs +++ b/Assets/UdonSharp/Editor/Serialization/StorageInterfaces/UdonVariableStorageInterface.cs @@ -116,7 +116,7 @@ private System.Type GetElementType(string elementKey) programTypeLookup = new Dictionary(); foreach (FieldDefinition def in programAsset.fieldDefinitions.Values) { - if (def.fieldSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Public) || def.fieldSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Private)) + if (def.fieldSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Public) || def.fieldSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Private)) programTypeLookup.Add(def.fieldSymbol.symbolOriginalName, def.fieldSymbol.symbolCsType); } variableTypeLookup.Add(programAsset, programTypeLookup); diff --git a/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs b/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs index 7152533f..1158df1b 100644 --- a/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs +++ b/Assets/UdonSharp/Editor/UdonSharpASTVisitor.cs @@ -310,7 +310,7 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) bool hasRecursiveMethods = false; foreach (MethodDefinition definition in visitorContext.definedMethods) { - if (definition.declarationFlags.HasFlag(MethodDeclFlags.RecursiveMethod)) + if (definition.declarationFlags.HasFlagFaster(MethodDeclFlags.RecursiveMethod)) { hasRecursiveMethods = true; break; @@ -383,7 +383,7 @@ public override void VisitPropertyDeclaration(PropertyDeclarationSyntax node) if (node.Initializer != null) throw new System.NotSupportedException("UdonSharp does not currently support initializers on properties."); - PropertyDefinition definition = visitorContext.definedProperties.Where(e => e.originalPropertyName == node.Identifier.ValueText).First(); + PropertyDefinition definition = visitorContext.definedProperties.First(e => e.originalPropertyName == node.Identifier.ValueText); if (definition.getter != null) { @@ -739,12 +739,12 @@ public override void VisitArrayCreationExpression(ArrayCreationExpressionSyntax } } - if (hasInitializer && arrayRankSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && ((int)arrayRankSymbol.symbolDefaultValue) != node.Initializer.Expressions.Count) + if (hasInitializer && arrayRankSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && ((int)arrayRankSymbol.symbolDefaultValue) != node.Initializer.Expressions.Count) { UpdateSyntaxNode(node.Initializer); throw new System.ArgumentException($"An array initializer of length '{(int)arrayRankSymbol.symbolDefaultValue}' is expected"); } - else if (hasInitializer && !arrayRankSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant)) + else if (hasInitializer && !arrayRankSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant)) { throw new System.ArgumentException("A constant value is expected"); } @@ -1303,9 +1303,9 @@ public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { UpdateSyntaxNode(node); - MethodDefinition definition = visitorContext.definedMethods.Where(e => e.originalMethodName == node.Identifier.ValueText).First(); + MethodDefinition definition = visitorContext.definedMethods.First(e => e.originalMethodName == node.Identifier.ValueText); - visitorContext.isRecursiveMethod = definition.declarationFlags.HasFlag(MethodDeclFlags.RecursiveMethod); + visitorContext.isRecursiveMethod = definition.declarationFlags.HasFlagFaster(MethodDeclFlags.RecursiveMethod); string functionName = node.Identifier.ValueText; bool isBuiltinEvent = visitorContext.resolverContext.ReplaceInternalEventName(ref functionName); @@ -1798,8 +1798,8 @@ public override void VisitBinaryExpression(BinaryExpressionSyntax node) if (operatorType == BuiltinOperatorType.Equality || operatorType == BuiltinOperatorType.Inequality) { - bool lhsNull = lhsValue.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && lhsValue.symbolDefaultValue == null; - bool rhsNull = rhsValue.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && rhsValue.symbolDefaultValue == null; + bool lhsNull = lhsValue.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && lhsValue.symbolDefaultValue == null; + bool rhsNull = rhsValue.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && rhsValue.symbolDefaultValue == null; if (lhsNull && !rhsNull) { diff --git a/Assets/UdonSharp/Editor/UdonSharpAssetCompileWatcher.cs b/Assets/UdonSharp/Editor/UdonSharpAssetCompileWatcher.cs index f4036784..18aa0ddb 100644 --- a/Assets/UdonSharp/Editor/UdonSharpAssetCompileWatcher.cs +++ b/Assets/UdonSharp/Editor/UdonSharpAssetCompileWatcher.cs @@ -61,22 +61,15 @@ static void SetupWatchers() string[] directories = Directory.GetDirectories("Assets/", "*", SearchOption.AllDirectories).Append("Assets/") .Select(e => e.Replace('\\', '/')) - .Where(e => !blacklistedDirectories.Any(name => name.TrimEnd('/') == e.TrimEnd('/') || e.StartsWith(name))) + .Where(e => !blacklistedDirectories.Any(name => name.TrimEnd('/') == e.TrimEnd('/') || e.StartsWith(name)) + && Directory.GetFiles(e, "*.cs").Length > 0) .ToArray(); - List sourceDirectories = new List(); - - foreach (string directory in directories) - { - if (Directory.GetFiles(directory, "*.cs").Length > 0) - sourceDirectories.Add(directory); - } - - fileSystemWatchers = new FileSystemWatcher[sourceDirectories.Count]; + fileSystemWatchers = new FileSystemWatcher[directories.Length]; - for (int i = 0; i < sourceDirectories.Count; ++i) + for (int i = 0; i < directories.Length; ++i) { - FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(sourceDirectories[i], "*.cs"); + FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(directories[i], "*.cs"); fileSystemWatcher.IncludeSubdirectories = false; fileSystemWatcher.InternalBufferSize = 1024; // Someone would need to modify 64 files in a single directory at once to hit this diff --git a/Assets/UdonSharp/Editor/UdonSharpCompilationModule.cs b/Assets/UdonSharp/Editor/UdonSharpCompilationModule.cs index 618f6dd6..add33e04 100644 --- a/Assets/UdonSharp/Editor/UdonSharpCompilationModule.cs +++ b/Assets/UdonSharp/Editor/UdonSharpCompilationModule.cs @@ -201,7 +201,7 @@ private string BuildHeapDataBlock() foreach (SymbolDefinition symbol in allSymbols) { - if (symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Public) && !symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Readonly)) + if (symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Public) && !symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Readonly)) builder.AppendLine($".export {symbol.symbolUniqueName}", 1); } diff --git a/Assets/UdonSharp/Editor/UdonSharpCompiler.cs b/Assets/UdonSharp/Editor/UdonSharpCompiler.cs index 9c22c5b2..2d0e1ee7 100644 --- a/Assets/UdonSharp/Editor/UdonSharpCompiler.cs +++ b/Assets/UdonSharp/Editor/UdonSharpCompiler.cs @@ -147,8 +147,8 @@ public void Compile() EditorUtility.DisplayProgressBar("UdonSharp Compile", "Parsing Syntax Trees...", 0f); object syntaxTreeLock = new object(); - List<(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)> programsAndSyntaxTrees = new List<(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)>(); - Dictionary syntaxTreeSourceLookup = new Dictionary(); + List<(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)> programsAndSyntaxTrees = new List<(UdonSharpProgramAsset, Microsoft.CodeAnalysis.SyntaxTree)>(programAssetsAndPaths.Count); + Dictionary syntaxTreeSourceLookup = new Dictionary(programAssetsAndPaths.Count); string[] defines = UdonSharpUtils.GetProjectDefines(isEditorBuild); @@ -431,7 +431,7 @@ public int AssignHeapConstants() { program.Heap.SetHeapVariable(symbolAddress, symbol.symbolDefaultValue, symbol.symbolCsType); } - else if (symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Public)) // Initialize null array fields to a 0-length array like Unity does + else if (symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Public)) // Initialize null array fields to a 0-length array like Unity does { if (symbol.symbolCsType.IsArray) program.Heap.SetHeapVariable(symbolAddress, System.Activator.CreateInstance(symbol.symbolCsType, new object[] { 0 }), symbol.symbolCsType); @@ -463,7 +463,7 @@ public int AssignHeapConstants() { uint symbolAddress = program.SymbolTable.GetAddressFromSymbol(symbol.symbolUniqueName); - if (symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Public)) // Initialize null array fields to a 0-length array like Unity does + if (symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Public)) // Initialize null array fields to a 0-length array like Unity does { if (symbol.symbolCsType.IsArray) { @@ -483,7 +483,7 @@ public int AssignHeapConstants() // Default to empty string on synced strings to prevent Udon sync from throwing errors if (symbol.symbolCsType == typeof(string) && - symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Private) && + symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Private) && symbol.syncMode != UdonSyncMode.NotSynced) { if (program.Heap.GetHeapVariable(symbolAddress) == null) diff --git a/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs b/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs index d064de2f..2208b589 100644 --- a/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs +++ b/Assets/UdonSharp/Editor/UdonSharpEditorManager.cs @@ -93,7 +93,7 @@ void InjectEvent(System.Type behaviourType, string eventName) { const BindingFlags eventBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly; - MethodInfo eventInfo = behaviourType.GetMethods(eventBindingFlags).FirstOrDefault(e => e.Name == eventName && e.ReturnType == typeof(void)); + MethodInfo eventInfo = UdonSharpUtils.GetTypeMethods(behaviourType, eventBindingFlags).FirstOrDefault(e => e.Name == eventName && e.ReturnType == typeof(void)); try { @@ -176,7 +176,7 @@ void InjectEvent(System.Type behaviourType, string eventName) InjectedMethods.shouldSkipEventsMethod = (Func)Delegate.CreateDelegate(typeof(Func), typeof(UdonSharpBehaviour).GetMethod("ShouldSkipEvents", BindingFlags.Static | BindingFlags.NonPublic)); // Patch GUI object field drawer - MethodInfo doObjectFieldMethod = typeof(EditorGUI).GetMethods(BindingFlags.Static | BindingFlags.NonPublic).FirstOrDefault(e => e.Name == "DoObjectField" && e.GetParameters().Length == 9); + MethodInfo doObjectFieldMethod = UdonSharpUtils.GetTypeMethods(typeof(EditorGUI), BindingFlags.Static | BindingFlags.NonPublic).FirstOrDefault(e => e.Name == "DoObjectField" && e.GetParameters().Length == 9); HarmonyMethod objectFieldProxy = new HarmonyMethod(typeof(InjectedMethods).GetMethod(nameof(InjectedMethods.DoObjectFieldProxy))); harmony.Patch(doObjectFieldMethod, objectFieldProxy); @@ -190,7 +190,7 @@ void InjectEvent(System.Type behaviourType, string eventName) InjectedMethods.crossSceneRefCheckMethod = (Func)Delegate.CreateDelegate(typeof(Func), crossSceneRefCheckMethod); // Patch post BuildAssetBundles fixup function - MethodInfo buildAssetbundlesMethod = typeof(BuildPipeline).GetMethods(BindingFlags.NonPublic | BindingFlags.Static).First(e => e.Name == "BuildAssetBundles" && e.GetParameters().Length == 5); + MethodInfo buildAssetbundlesMethod = UdonSharpUtils.GetTypeMethods(typeof(BuildPipeline), BindingFlags.NonPublic | BindingFlags.Static).First(e => e.Name == "BuildAssetBundles" && e.GetParameters().Length == 5); MethodInfo postBuildMethod = typeof(InjectedMethods).GetMethod(nameof(InjectedMethods.PostBuildAssetBundles), BindingFlags.Public | BindingFlags.Static); HarmonyMethod postBuildHarmonyMethod = new HarmonyMethod(postBuildMethod); @@ -884,7 +884,7 @@ static void UpdatePublicVariables(List udonBehaviours) } // Field was exported at one point, but is no longer. So we need to remove it from the behaviour - if (!fieldDefinition.fieldSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Public)) + if (!fieldDefinition.fieldSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Public)) { updatedBehaviourVariables++; publicVariables.RemoveVariable(variableSymbol); diff --git a/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs b/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs index 7676c054..409b9b9d 100644 --- a/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs +++ b/Assets/UdonSharp/Editor/UdonSharpExpressionCapture.cs @@ -458,7 +458,7 @@ public SymbolDefinition ExecuteGet() outSymbol = AllocateOutputSymbol(getMethod.ReturnType); - string methodUdonString = visitorContext.resolverContext.GetUdonMethodName(getMethod); + string methodUdonString = ResolverContext.GetUdonMethodName(getMethod); if (!getMethod.IsStatic) { @@ -553,7 +553,7 @@ public SymbolDefinition ExecuteGet() if (arraySymbolType == typeof(string)) { // udon-workaround: This is where support for Udon's string indexer would go, IF IT HAD ONE - //getIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(arraySymbol.symbolCsType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == "get_Chars").First()); + //getIndexerUdonName = ResolverContext.GetUdonMethodName(arraySymbol.symbolCsType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == "get_Chars").First()); elementType = typeof(char); @@ -576,7 +576,7 @@ public SymbolDefinition ExecuteGet() subStrCharArrSymbol = charArrScope.Invoke(new SymbolDefinition[] { }); } - getIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(typeof(char[]).GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Get")); + getIndexerUdonName = ResolverContext.GetUdonMethodName(typeof(char[]).GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)); visitorContext.uasmBuilder.AddPush(subStrCharArrSymbol); visitorContext.uasmBuilder.AddPush(visitorContext.topTable.CreateConstSymbol(typeof(int), 0)); // 0 index } @@ -587,7 +587,7 @@ public SymbolDefinition ExecuteGet() { elementType = typeof(float); - getIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(arraySymbolType.GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "get_Item" && e.GetParameters().Length == 1)); + getIndexerUdonName = ResolverContext.GetUdonMethodName(arraySymbolType.GetMethod("get_Item", BindingFlags.Public | BindingFlags.Instance, null, new System.Type[] { typeof(int) }, null)); visitorContext.uasmBuilder.AddPush(arraySymbol); visitorContext.uasmBuilder.AddPush(arrayIndexerIndexValue.symbol); @@ -597,9 +597,9 @@ public SymbolDefinition ExecuteGet() // udon-workaround: VRC scans UnityEngine.Object arrays in their respective methods, so those methods are useless since they get disproportionately expensive the larger the array is. // Instead use the object[] indexer for these objects since it does not get scanned if (arraySymbolType.GetElementType() == typeof(UnityEngine.Object) || arraySymbolType.GetElementType().IsSubclassOf(typeof(UnityEngine.Object))) - getIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(typeof(object[]).GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Get")); + getIndexerUdonName = ResolverContext.GetUdonMethodName(typeof(object[]).GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)); else - getIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(arraySymbolType.GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Get")); + getIndexerUdonName = ResolverContext.GetUdonMethodName(arraySymbolType.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)); elementType = arraySymbol.userCsType.GetElementType(); @@ -636,7 +636,7 @@ public SymbolDefinition destinationSymbolForSet { { if (captureArchetype == ExpressionCaptureArchetype.LocalSymbol) { - if (captureLocalSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) || captureLocalSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.This)) + if (captureLocalSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) || captureLocalSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.This)) return null; return captureLocalSymbol; @@ -670,7 +670,7 @@ public void ExecuteSet(SymbolDefinition value, bool explicitCast = false) if (setMethod == null) throw new System.MemberAccessException($"Property or indexer '{captureProperty.DeclaringType.Name}.{captureProperty.Name}' cannot be assigned to -- it is read only or doesn't exist"); - string udonMethodString = visitorContext.resolverContext.GetUdonMethodName(setMethod); + string udonMethodString = ResolverContext.GetUdonMethodName(setMethod); if (!setMethod.IsStatic) { @@ -767,16 +767,16 @@ public void ExecuteSet(SymbolDefinition value, bool explicitCast = false) arraySymbolType == typeof(Vector4) || arraySymbolType == typeof(Matrix4x4)) { - setIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(arraySymbol.symbolCsType.GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "set_Item" && e.GetParameters().Length == 2)); + setIndexerUdonName = ResolverContext.GetUdonMethodName(UdonSharpUtils.GetTypeMethods(arraySymbol.symbolCsType, BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "set_Item" && e.GetParameters().Length == 2)); } else { // udon-workaround: VRC scans UnityEngine.Object arrays in their respective methods, so those methods are useless since they get disproportionately expensive the larger the array is. // Instead use the object[] indexer for these objects since it does not get scanned if (arraySymbolType.GetElementType() == typeof(UnityEngine.Object) || arraySymbolType.GetElementType().IsSubclassOf(typeof(UnityEngine.Object))) - setIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(typeof(object[]).GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Set")); + setIndexerUdonName = ResolverContext.GetUdonMethodName(typeof(object[]).GetMethod("Set", BindingFlags.Public | BindingFlags.Instance)); else - setIndexerUdonName = visitorContext.resolverContext.GetUdonMethodName(arraySymbolType.GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Set")); + setIndexerUdonName = ResolverContext.GetUdonMethodName(arraySymbolType.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance)); } visitorContext.uasmBuilder.AddPush(arraySymbol); @@ -892,7 +892,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T bool isObjectAssignable = !targetType.IsValueType && sourceSymbol.symbolCsType == typeof(object); bool isNumericCastValid = UdonSharpUtils.IsNumericImplicitCastValid(targetType, sourceSymbol.symbolCsType) || - (sourceSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && sourceSymbol.symbolCsType == typeof(int)); // Handle Roslyn giving us ints constant expressions + (sourceSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && sourceSymbol.symbolCsType == typeof(int)); // Handle Roslyn giving us ints constant expressions if ((!isExplicit && !targetType.IsImplicitlyAssignableFrom(sourceSymbol.userCsType)) && !isObjectAssignable && !isNumericCastValid) @@ -937,7 +937,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T visitorContext.uasmBuilder.AddPush(sourceNumericSymbol); visitorContext.uasmBuilder.AddPush(castOutput); - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(conversionFunction)); + visitorContext.uasmBuilder.AddExternCall(ResolverContext.GetUdonMethodName(conversionFunction)); return castOutput; } @@ -957,7 +957,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T foreach (System.Type operatorType in operatorTypes) { - IEnumerable methods = operatorType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Implicit"); + IEnumerable methods = UdonSharpUtils.GetTypeMethods(operatorType, BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Implicit"); foreach (MethodInfo methodInfo in methods) { @@ -978,7 +978,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T visitorContext.uasmBuilder.AddPush(sourceSymbol); visitorContext.uasmBuilder.AddPush(castOutput); - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(foundConversion)); + visitorContext.uasmBuilder.AddExternCall(ResolverContext.GetUdonMethodName(foundConversion)); return castOutput; } @@ -988,7 +988,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T { foreach (System.Type operatorType in operatorTypes) { - IEnumerable methods = operatorType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Explicit"); + IEnumerable methods = UdonSharpUtils.GetTypeMethods(operatorType, BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Explicit"); foreach (MethodInfo methodInfo in methods) { @@ -1009,7 +1009,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T visitorContext.uasmBuilder.AddPush(sourceSymbol); visitorContext.uasmBuilder.AddPush(castOutput); - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(foundConversion)); + visitorContext.uasmBuilder.AddExternCall(ResolverContext.GetUdonMethodName(foundConversion)); return castOutput; } @@ -1023,7 +1023,7 @@ public SymbolDefinition CastSymbolToType(SymbolDefinition sourceSymbol, System.T SymbolDefinition castOutput = requestedDestination != null ? requestedDestination : visitorContext.topTable.CreateUnnamedSymbol(targetType, SymbolDeclTypeFlags.Internal); - string objArrayGetMethod = visitorContext.resolverContext.GetUdonMethodName(typeof(object[]).GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Get")); + string objArrayGetMethod = ResolverContext.GetUdonMethodName(typeof(object[]).GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)); visitorContext.uasmBuilder.AddPush(enumArraySymbol); visitorContext.uasmBuilder.AddPush(indexSymbol); @@ -1176,7 +1176,7 @@ private MethodInfo ConvertGetComponentToGetComponents(MethodInfo targetMethod) targetParameters = new System.Type[] { typeof(System.Type) }.Concat(targetParameters).ToArray(); } - MethodInfo[] foundMethods = declaringType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == searchString && AllMethodParametersMatch(e, targetParameters)).ToArray(); + MethodInfo[] foundMethods = UdonSharpUtils.GetTypeMethods(declaringType, BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == searchString && AllMethodParametersMatch(e, targetParameters)).ToArray(); if (foundMethods.Length != 1) { @@ -1574,7 +1574,7 @@ private SymbolDefinition HandleGenericUSharpGetComponent(MethodInfo targetMethod visitorContext.uasmBuilder.AddPush(resultComponents); - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(targetMethod)); + visitorContext.uasmBuilder.AddExternCall(ResolverContext.GetUdonMethodName(targetMethod)); if (isArray) { @@ -1748,7 +1748,8 @@ private void PopRecursiveStack(SymbolDefinition[] popSymbols) visitorContext.uasmBuilder.AddPush(visitorContext.artificalStackSymbol); visitorContext.uasmBuilder.AddPush(visitorContext.stackAddressSymbol); visitorContext.uasmBuilder.AddPush(paramCOWVal.symbol); - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(typeof(object[]).GetMethods(BindingFlags.Public | BindingFlags.Instance).First(e => e.Name == "Get"))); + string externCall = ResolverContext.GetUdonMethodName(typeof(object[]).GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)); + visitorContext.uasmBuilder.AddExternCall(externCall); paramCOWVal.Dispose(); } @@ -1776,7 +1777,7 @@ private SymbolDefinition InvokeExtern(SymbolDefinition[] invokeParams) // We use void as a placeholder for a null constant value getting passed in, if null is passed in and the target type is a reference type then we assume they are compatible List typeList = invokeParams.Select(e => { - if (e.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && + if (e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && e.symbolCsType == typeof(object) && e.symbolDefaultValue == null) return typeof(void); @@ -1802,13 +1803,13 @@ private SymbolDefinition InvokeExtern(SymbolDefinition[] invokeParams) { if (targetMethod != null) { - throw new System.Exception($"Method is not exposed to Udon: {targetMethod}, Udon signature: {visitorContext.resolverContext.GetUdonMethodName(targetMethod, false)}"); + throw new System.Exception($"Method is not exposed to Udon: {targetMethod}, Udon signature: {ResolverContext.GetUdonMethodName(targetMethod, false)}"); } string udonFilteredMethods = ""; udonFilteredMethods = string.Join("\n", captureMethods - .Select(e => new System.Tuple(e, visitorContext.resolverContext.GetUdonMethodName(e, false))) + .Select(e => new System.Tuple(e, ResolverContext.GetUdonMethodName(e, false))) .Where(e => !visitorContext.resolverContext.IsValidUdonMethod(e.Item2)) .Select(e => e.Item1)); @@ -1855,7 +1856,7 @@ private SymbolDefinition InvokeExtern(SymbolDefinition[] invokeParams) visitorContext.uasmBuilder.AddPush(accessSymbol); visitorContext.uasmBuilder.AddPush(outputTransformComponent); - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(getTransformMethod), "GetComponent strongbox mismatch fix"); + visitorContext.uasmBuilder.AddExternCall(ResolverContext.GetUdonMethodName(getTransformMethod), "GetComponent strongbox mismatch fix"); visitorContext.uasmBuilder.AddPush(outputTransformComponent); } @@ -1931,7 +1932,7 @@ private SymbolDefinition InvokeExtern(SymbolDefinition[] invokeParams) visitorContext.uasmBuilder.AddPush(returnSymbol); } - visitorContext.uasmBuilder.AddExternCall(visitorContext.resolverContext.GetUdonMethodName(targetMethod, true, genericTypeArguments)); + visitorContext.uasmBuilder.AddExternCall(ResolverContext.GetUdonMethodName(targetMethod, true, genericTypeArguments)); if (isPotentiallyRecursive && !shouldSkipRecursivePush) PopRecursiveStack(symbolsToPush); @@ -2280,7 +2281,7 @@ public bool DoesReturnIntermediateSymbol() public bool IsConstExpression() { // Only basic handling for local symbols for now since we can directly reference them - if (IsLocalSymbol() && ExecuteGet().declarationType.HasFlag(SymbolDeclTypeFlags.Constant)) + if (IsLocalSymbol() && ExecuteGet().declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant)) return true; return false; @@ -2456,26 +2457,14 @@ private bool HandleLocalPropertyLookup(string localPropertyName) return true; } - private MethodInfo[] GetTypeMethods(System.Type type, BindingFlags bindingFlags) - { - MethodInfo[] methods; - if (!visitorContext.typeMethodCache.TryGetValue((type, bindingFlags), out methods)) - { - methods = type.GetMethods(bindingFlags); - visitorContext.typeMethodCache.Add((type, bindingFlags), methods); - } - - return methods; - } - private bool HandleLocalUdonBehaviourMethodLookup(string localUdonMethodName) { - List methods = new List(GetTypeMethods(typeof(VRC.Udon.Common.Interfaces.IUdonEventReceiver), BindingFlags.Instance | BindingFlags.Public)); - methods.AddRange(GetTypeMethods(typeof(Component), BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)); - methods.AddRange(GetTypeMethods(typeof(Object), BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)); + List methods = new List(UdonSharpUtils.GetTypeMethods(typeof(VRC.Udon.Common.Interfaces.IUdonEventReceiver), BindingFlags.Instance | BindingFlags.Public)); + methods.AddRange(UdonSharpUtils.GetTypeMethods(typeof(Component), BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)); + methods.AddRange(UdonSharpUtils.GetTypeMethods(typeof(Object), BindingFlags.Instance | BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy)); if (localUdonMethodName == "VRCInstantiate") - methods.AddRange(GetTypeMethods(typeof(UdonSharpBehaviour), BindingFlags.Static | BindingFlags.Public)); + methods.AddRange(UdonSharpUtils.GetTypeMethods(typeof(UdonSharpBehaviour), BindingFlags.Static | BindingFlags.Public)); else if (localUdonMethodName == "SetProgramVariable" || localUdonMethodName == "GetProgramVariable") methods.Add(typeof(UdonSharpBehaviour).GetMethod(localUdonMethodName, BindingFlags.Instance | BindingFlags.Public)); @@ -2492,10 +2481,10 @@ private bool HandleLocalUdonBehaviourMethodLookup(string localUdonMethodName) } private static readonly PropertyInfo[] _componentProperties = - typeof(Component).GetProperties(BindingFlags.Instance | BindingFlags.Public); + UdonSharpUtils.GetTypeProperties(typeof(Component), BindingFlags.Instance | BindingFlags.Public); private static readonly PropertyInfo[] _udonEventReceiverProperties = - typeof(VRC.Udon.Common.Interfaces.IUdonEventReceiver).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); + UdonSharpUtils.GetTypeProperties(typeof(VRC.Udon.Common.Interfaces.IUdonEventReceiver), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); private bool HandleLocalUdonBehaviourPropertyLookup(string localUdonPropertyName) { @@ -2595,7 +2584,7 @@ private bool HandleStaticMethodLookup(string methodToken) if (captureArchetype != ExpressionCaptureArchetype.Type) throw new System.Exception("Static method lookup only supported on Type archetypes"); - MethodInfo[] methods = captureType.GetMethods(BindingFlags.Static | BindingFlags.Public).Where(e => e.Name == methodToken).ToArray(); + MethodInfo[] methods = UdonSharpUtils.GetTypeMethods(captureType, BindingFlags.Static | BindingFlags.Public).Where(e => e.Name == methodToken).ToArray(); if (methods.Length == 0) return false; @@ -2684,14 +2673,14 @@ private bool HandleMemberPropertyAccess(string propertyToken) System.Type currentReturnType = GetReturnType(); - PropertyInfo[] foundProperties = currentReturnType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == propertyToken).ToArray(); + PropertyInfo[] foundProperties = UdonSharpUtils.GetTypeProperties(currentReturnType, BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == propertyToken).ToArray(); if (propertyToken == "enabled" && (currentReturnType == typeof(VRC.Udon.UdonBehaviour) || currentReturnType == typeof(UdonSharpBehaviour) || currentReturnType.IsSubclassOf(typeof(UdonSharpBehaviour)))) { - foundProperties = typeof(VRC.Udon.Common.Interfaces.IUdonEventReceiver).GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(e => e.Name == propertyToken).ToArray(); + foundProperties = UdonSharpUtils.GetTypeProperties(typeof(VRC.Udon.Common.Interfaces.IUdonEventReceiver), BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Where(e => e.Name == propertyToken).ToArray(); } if (foundProperties.Length == 0) @@ -2747,7 +2736,7 @@ private bool HandleMemberFieldAccess(string fieldToken) } private static readonly MethodInfo[] _objectMethods = - typeof(object).GetMethods(BindingFlags.Public | BindingFlags.Instance); + UdonSharpUtils.GetTypeMethods(typeof(object), BindingFlags.Public | BindingFlags.Instance); private bool HandleMemberMethodLookup(string methodToken) { @@ -2763,7 +2752,7 @@ private bool HandleMemberMethodLookup(string methodToken) System.Type returnType = GetReturnType(); - List foundMethodInfos = new List(returnType.GetMethods(BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == methodToken)); + List foundMethodInfos = new List(UdonSharpUtils.GetTypeMethods(returnType, BindingFlags.Public | BindingFlags.Instance).Where(e => e.Name == methodToken)); if (returnType != typeof(object)) foundMethodInfos.AddRange(_objectMethods.Where(e => e.Name == methodToken)); @@ -2792,7 +2781,7 @@ private bool HandleExternUserFieldLookup(string fieldToken) if (externClass == null) return false; - FieldDefinition foundDefinition = externClass.fieldDefinitions.Find(e => e.fieldSymbol.symbolOriginalName == fieldToken && e.fieldSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Public)); + FieldDefinition foundDefinition = externClass.fieldDefinitions.Find(e => e.fieldSymbol.symbolOriginalName == fieldToken && e.fieldSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Public)); if (foundDefinition == null) return false; @@ -2817,7 +2806,7 @@ private bool HandleExternUserMethodLookup(string methodToken) if (externClass == null) return false; - MethodDefinition foundDefinition = externClass.methodDefinitions.Find(e => e.originalMethodName == methodToken && e.declarationFlags.HasFlag(MethodDeclFlags.Public)); + MethodDefinition foundDefinition = externClass.methodDefinitions.Find(e => e.originalMethodName == methodToken && e.declarationFlags.HasFlagFaster(MethodDeclFlags.Public)); if (foundDefinition == null) return false; @@ -2842,7 +2831,7 @@ private bool HandleExternUserPropertyLookup(string propertyToken) if (externClass == null) return false; - PropertyDefinition foundDefinition = externClass.propertyDefinitions.Find(e => e.originalPropertyName == propertyToken && e.declarationFlags.HasFlag(PropertyDeclFlags.Public)); + PropertyDefinition foundDefinition = externClass.propertyDefinitions.Find(e => e.originalPropertyName == propertyToken && e.declarationFlags.HasFlagFaster(PropertyDeclFlags.Public)); if (foundDefinition == null) return false; diff --git a/Assets/UdonSharp/Editor/UdonSharpFieldVisitor.cs b/Assets/UdonSharp/Editor/UdonSharpFieldVisitor.cs index bbcac6d6..7fa2ce72 100644 --- a/Assets/UdonSharp/Editor/UdonSharpFieldVisitor.cs +++ b/Assets/UdonSharp/Editor/UdonSharpFieldVisitor.cs @@ -225,7 +225,7 @@ private UdonSyncMode GetSyncAttributeValue(FieldDeclarationSyntax node) SymbolDefinition attrSymbol = attributeCapture.ExecuteGet(); - if (!attrSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant)) + if (!attrSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant)) { throw new System.ArgumentException("Attributes do not support non-constant expressions"); } diff --git a/Assets/UdonSharp/Editor/UdonSharpResolverContext.cs b/Assets/UdonSharp/Editor/UdonSharpResolverContext.cs index 0d33af47..4d44ef87 100644 --- a/Assets/UdonSharp/Editor/UdonSharpResolverContext.cs +++ b/Assets/UdonSharp/Editor/UdonSharpResolverContext.cs @@ -49,7 +49,7 @@ public class ResolverContext { "void", "System.Void" } // void might need to be revisited since it could mess with something }; - private Dictionary typeLookupCache = new Dictionary(); + private Dictionary typeLookupCache = new Dictionary(128); private static HashSet nodeDefinitionLookup; @@ -239,7 +239,7 @@ public MethodInfo ResolveMemberMethod(System.Type lhsType, string methodName, Sy public IEnumerable ResolveMemberMethods(System.Type type, string methodName) { - return type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(e => e.Name == methodName); + return UdonSharpUtils.GetTypeMethods(type, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static).Where(e => e.Name == methodName); } public string ParseBuiltinTypeAlias(string typeName) @@ -338,7 +338,7 @@ public System.Type ResolveExternType(string qualifiedTypeName) return null; } - public string SanitizeTypeName(string typeName) + public static string SanitizeTypeName(string typeName) { return typeName.Replace(",", "") .Replace(".", "") @@ -354,7 +354,7 @@ public string SanitizeTypeName(string typeName) /// Skips remapping base VRCSDK types, this is primarily used for VRCSDK function return value types since they may point to the base type and we want to maintain that. /// The Udon type name string if it is a valid Udon type, /// or null if it is not a valid Udon type. - public string GetUdonTypeName(System.Type externType, bool skipBaseTypeRemap = false) + public static string GetUdonTypeName(System.Type externType, bool skipBaseTypeRemap = false) { if (!skipBaseTypeRemap) externType = UdonSharpUtils.RemapBaseType(externType); @@ -413,7 +413,7 @@ public string GetUdonTypeName(System.Type externType, bool skipBaseTypeRemap = f /// /// /// - public string GetUdonMethodName(MethodBase externMethod, bool validate = true, List genericArguments = null) + public static string GetUdonMethodName(MethodBase externMethod, bool validate = true, List genericArguments = null) { System.Type methodSourceType = externMethod.ReflectedType; @@ -707,7 +707,7 @@ public MethodBase FindBestOverloadFunction(MethodBase[] methods, List 0 && genericCount > 0) - validMethods = validMethods.Where(e => !e.IsGenericMethod).ToList(); + validMethods.RemoveAll(e => !e.IsGenericMethod); if (validMethods.Count == 1) return validMethods.First(); @@ -723,7 +723,7 @@ public MethodBase FindBestOverloadFunction(MethodBase[] methods, List 0 && udonSharpOperatorCount > 0) - validMethods = validMethods.Where(e => !(e is OperatorMethodInfo)).ToList(); + validMethods.RemoveAll(e => !(e is OperatorMethodInfo)); // Count the params using methods in this pass // todo: this still needs a chunk of work to handle when users don't pass anything for params along with handling default arguments before the params args, @@ -744,10 +744,10 @@ public MethodBase FindBestOverloadFunction(MethodBase[] methods, List 0 && nonParamsArgCount > 0) { - validMethods = validMethods.Where(e => { + validMethods.RemoveAll(e => { ParameterInfo[] parameters = e.GetParameters(); return parameters.Length == 0 || !parameters.Last().HasParamsParameter() || parameters.Last().ParameterType.IsImplicitlyAssignableFrom(methodArgs.Last()); - }).ToList(); + }); } if (validMethods.Count == 1) @@ -767,10 +767,10 @@ public MethodBase FindBestOverloadFunction(MethodBase[] methods, List 0 && fullySatisfiedArgMethodCount > 0) { - validMethods = validMethods.Where(e => { + validMethods.RemoveAll(e => { ParameterInfo[] methodParams = e.GetParameters(); return methodParams.Length == 0 || !methodParams.Last().HasDefaultValue; - }).ToList(); + }); } if (validMethods.Count == 1) diff --git a/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs b/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs index b9990b3c..20a7ef26 100644 --- a/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs +++ b/Assets/UdonSharp/Editor/UdonSharpSymbolTable.cs @@ -381,7 +381,7 @@ public void ExitExpressionScope() public IEnumerable GetOpenCOWSymbols() { - return scopeCOWValues.Where(e => e.symbol != null && e.referenceCount > 0 && !e.symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) && !e.symbol.declarationType.HasFlag(SymbolDeclTypeFlags.Readonly)).Select(e => e.symbol); + return scopeCOWValues.Where(e => e.symbol != null && e.referenceCount > 0 && !e.symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && !e.symbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Readonly)).Select(e => e.symbol); } internal void AddSymbolCOW(SymbolDefinition.COWValueInternal value) @@ -494,7 +494,7 @@ public List GetLocalSymbols() while (!currentTable.IsGlobalSymbolTable) { - localSymbolDefinitions.AddRange(currentTable.symbolDefinitions.Where(e => e.declarationType.HasFlag(SymbolDeclTypeFlags.Local))); + localSymbolDefinitions.AddRange(currentTable.symbolDefinitions.Where(e => e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Local))); currentTable = currentTable.parentSymbolTable; } @@ -509,7 +509,7 @@ public List GetAllSymbols(bool includeInternal = false) while (currentTable != null) { - foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => includeInternal ? true : !e.declarationType.HasFlag(SymbolDeclTypeFlags.Internal))); + foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => includeInternal ? true : !e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Internal))); currentTable = currentTable.parentSymbolTable; } @@ -524,7 +524,7 @@ public List GetAllLocalSymbols() while (currentTable != null && !currentTable.IsGlobalSymbolTable) { - foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => !e.declarationType.HasFlag(SymbolDeclTypeFlags.Internal) && e.declarationType.HasFlag(SymbolDeclTypeFlags.Local))); + foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => !e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Internal) && e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Local))); currentTable = currentTable.parentSymbolTable; } @@ -539,7 +539,7 @@ public List GetAllRecursiveSymbols() while (currentTable != null && !currentTable.IsGlobalSymbolTable) { - foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => (!e.declarationType.HasFlag(SymbolDeclTypeFlags.Internal) || e.declarationType.HasFlag(SymbolDeclTypeFlags.NeedsRecursivePush)) && e.declarationType.HasFlag(SymbolDeclTypeFlags.Local))); + foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => (!e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Internal) || e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.NeedsRecursivePush)) && e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Local))); currentTable = currentTable.parentSymbolTable; } @@ -554,7 +554,7 @@ public List GetCurrentMethodParameters() while (currentTable != null && !currentTable.IsGlobalSymbolTable) { - foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => e.declarationType.HasFlag(SymbolDeclTypeFlags.MethodParameter))); + foundSymbols.AddRange(currentTable.symbolDefinitions.Where(e => e.declarationType.HasFlagFaster(SymbolDeclTypeFlags.MethodParameter))); currentTable = currentTable.parentSymbolTable; } @@ -614,7 +614,7 @@ public SymbolDefinition GetReflectionSymbol(string name, System.Type type) foreach (SymbolDefinition currentSymbol in globalSymbols.symbolDefinitions) { - if (currentSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Reflection) && + if (currentSymbol.declarationType.HasFlagFaster(SymbolDeclTypeFlags.Reflection) && currentSymbol.symbolOriginalName == name && currentSymbol.symbolCsType == type) { @@ -650,7 +650,7 @@ public SymbolDefinition CreateThisSymbol(System.Type type) foreach (SymbolDefinition definition in globalSymTable.symbolDefinitions) { - if (definition.declarationType.HasFlag(SymbolDeclTypeFlags.This) && (definition.symbolCsType == udonType)) + if (definition.declarationType.HasFlagFaster(SymbolDeclTypeFlags.This) && (definition.symbolCsType == udonType)) return definition; } @@ -723,7 +723,7 @@ private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Typ if (resolvedSymbolType == null || symbolName == null) throw new System.ArgumentNullException(); - if (!declType.HasFlag(SymbolDeclTypeFlags.Internal) && !declType.HasFlag(SymbolDeclTypeFlags.BuiltinVar) && symbolName.StartsWith("__")) + if (!declType.HasFlagFaster(SymbolDeclTypeFlags.Internal) && !declType.HasFlagFaster(SymbolDeclTypeFlags.BuiltinVar) && symbolName.StartsWith("__")) { throw new System.ArgumentException($"Symbol {symbolName} cannot have name starting with \"__\", this naming is reserved for internal variables."); } @@ -732,39 +732,39 @@ private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Typ bool hasGlobalDeclaration = false; - if (declType.HasFlag(SymbolDeclTypeFlags.Internal)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.Internal)) { uniqueSymbolName = $"intnl_{uniqueSymbolName}"; } - if (declType.HasFlag(SymbolDeclTypeFlags.Constant)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.Constant)) { uniqueSymbolName = $"const_{uniqueSymbolName}"; hasGlobalDeclaration = true; } - if (declType.HasFlag(SymbolDeclTypeFlags.MethodParameter)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.MethodParameter)) { uniqueSymbolName = $"mp_{uniqueSymbolName}"; } - if (declType.HasFlag(SymbolDeclTypeFlags.This)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.This)) { uniqueSymbolName = $"this_{uniqueSymbolName}"; hasGlobalDeclaration = true; } - if (declType.HasFlag(SymbolDeclTypeFlags.PropertyBackingField)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.PropertyBackingField)) { uniqueSymbolName = $"bf_{uniqueSymbolName}"; } - if (declType.HasFlag(SymbolDeclTypeFlags.Reflection)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.Reflection)) { uniqueSymbolName = $"__refl_{uniqueSymbolName}"; hasGlobalDeclaration = true; } - if (!declType.HasFlag(SymbolDeclTypeFlags.Public) && !declType.HasFlag(SymbolDeclTypeFlags.Private) && !declType.HasFlag(SymbolDeclTypeFlags.Reflection)) + if (!declType.HasFlagFaster(SymbolDeclTypeFlags.Public) && !declType.HasFlagFaster(SymbolDeclTypeFlags.Private) && !declType.HasFlagFaster(SymbolDeclTypeFlags.Reflection)) { if (appendType) { - string sanitizedName = resolver.SanitizeTypeName(resolvedSymbolType.Name); + string sanitizedName = ResolverContext.SanitizeTypeName(resolvedSymbolType.Name); uniqueSymbolName += $"_{sanitizedName}"; } @@ -776,7 +776,7 @@ private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Typ System.Type typeForName = UdonSharpUtils.UserTypeToUdonType(resolvedSymbolType); - string udonTypeName = resolver.GetUdonTypeName(typeForName); + string udonTypeName = ResolverContext.GetUdonTypeName(typeForName); if (udonTypeName == null) throw new System.ArgumentException($"Could not locate Udon type for system type {resolvedSymbolType.FullName}"); @@ -822,10 +822,10 @@ private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Typ if (anyChildTableOpen) { - if (!declType.HasFlag(SymbolDeclTypeFlags.Reflection) && - !declType.HasFlag(SymbolDeclTypeFlags.Constant) && - !declType.HasFlag(SymbolDeclTypeFlags.This) && - !declType.HasFlag(SymbolDeclTypeFlags.BuiltinVar)) + if (!declType.HasFlagFaster(SymbolDeclTypeFlags.Reflection) && + !declType.HasFlagFaster(SymbolDeclTypeFlags.Constant) && + !declType.HasFlagFaster(SymbolDeclTypeFlags.This) && + !declType.HasFlagFaster(SymbolDeclTypeFlags.BuiltinVar)) throw new Exception($"Cannot add symbol {symbolDefinition} to root table while other tables are in use."); } } @@ -838,7 +838,7 @@ private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Typ public SymbolDefinition CreateNamedSymbol(string symbolName, string symbolType, SymbolDeclTypeFlags declType) { System.Type resolvedType = resolver.ResolveExternType(symbolType); - if (declType.HasFlag(SymbolDeclTypeFlags.Array)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.Array)) resolvedType = resolvedType.MakeArrayType(); return CreateNamedSymbol(symbolName, resolvedType, declType); @@ -879,7 +879,7 @@ public SymbolDefinition FindUserDefinedSymbol(string symbolName) public SymbolDefinition CreateUnnamedSymbol(string symbolType, SymbolDeclTypeFlags declType) { System.Type resolvedType = resolver.ResolveExternType(symbolType); - if (declType.HasFlag(SymbolDeclTypeFlags.Array)) + if (declType.HasFlagFaster(SymbolDeclTypeFlags.Array)) resolvedType = resolvedType.MakeArrayType(); return CreateUnnamedSymbol(resolvedType, declType); @@ -887,7 +887,7 @@ public SymbolDefinition CreateUnnamedSymbol(string symbolType, SymbolDeclTypeFla public SymbolDefinition CreateUnnamedSymbol(System.Type type, SymbolDeclTypeFlags declType) { - string typeName = resolver.GetUdonTypeName(type); + string typeName = ResolverContext.GetUdonTypeName(type); if (type.IsArray) declType |= SymbolDeclTypeFlags.Array; diff --git a/Assets/UdonSharp/Editor/UdonSharpSyntaxWalker.cs b/Assets/UdonSharp/Editor/UdonSharpSyntaxWalker.cs index 76353e93..412c3b60 100644 --- a/Assets/UdonSharp/Editor/UdonSharpSyntaxWalker.cs +++ b/Assets/UdonSharp/Editor/UdonSharpSyntaxWalker.cs @@ -457,7 +457,7 @@ protected List HandleVariableDeclaration(VariableDeclarationSy // Run the initializer if it exists // Todo: Run the set on the new symbol scope from within the initializer scope for direct setting - if (variableDeclarator.Initializer != null && symbolType.HasFlag(SymbolDeclTypeFlags.Local)) + if (variableDeclarator.Initializer != null && symbolType.HasFlagFaster(SymbolDeclTypeFlags.Local)) { using (ExpressionCaptureScope initializerCapture = new ExpressionCaptureScope(visitorContext, null, newSymbol)) { diff --git a/Assets/UdonSharp/Editor/UdonSharpUtils.cs b/Assets/UdonSharp/Editor/UdonSharpUtils.cs index a3025d3d..f554d4dd 100644 --- a/Assets/UdonSharp/Editor/UdonSharpUtils.cs +++ b/Assets/UdonSharp/Editor/UdonSharpUtils.cs @@ -4,8 +4,10 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; +using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; +using UdonSharp.Compiler; namespace UdonSharp { @@ -171,19 +173,10 @@ public static System.Type GetNextHighestNumericPrecision(System.Type type) public static MethodInfo GetNumericConversionMethod(System.Type targetType, System.Type sourceType) { - IEnumerable foundMethods = typeof(System.Convert) - .GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(e => e.Name == $"To{targetType.Name}") - .Where(e => e.GetParameters().FirstOrDefault().ParameterType == sourceType); + Type[] argumentTypes = new Type[] { sourceType.IsEnum ? typeof(object) : sourceType }; + MethodInfo foundMethod = typeof(System.Convert).GetMethod($"To{targetType.Name}", BindingFlags.Public | BindingFlags.Static, null, argumentTypes, null); - if (sourceType.IsEnum) - { - foundMethods = typeof(System.Convert).GetMethods(BindingFlags.Static | BindingFlags.Public) - .Where(e => e.Name == $"To{targetType.Name}") - .Where(e => e.GetParameters().FirstOrDefault().ParameterType == typeof(object)); - } - - return foundMethods.FirstOrDefault(); + return foundMethod; } public static bool IsNumericExplicitCastValid(System.Type targetType, System.Type sourceType) @@ -226,7 +219,7 @@ public static bool IsImplicitlyAssignableFrom(this System.Type targetType, Syste foreach (System.Type operatorType in operatorTypes) { - IEnumerable methods = operatorType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Implicit"); + IEnumerable methods = UdonSharpUtils.GetTypeMethods(operatorType, BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Implicit"); foreach (MethodInfo methodInfo in methods) { @@ -269,7 +262,7 @@ public static bool IsExplicitlyAssignableFrom(this System.Type targetType, Syste foreach (System.Type operatorType in operatorTypes) { - IEnumerable methods = operatorType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Implicit"); + IEnumerable methods = UdonSharpUtils.GetTypeMethods(operatorType, BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Implicit"); foreach (MethodInfo methodInfo in methods) { @@ -280,7 +273,7 @@ public static bool IsExplicitlyAssignableFrom(this System.Type targetType, Syste foreach (System.Type operatorType in operatorTypes) { - IEnumerable methods = operatorType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Explicit"); + IEnumerable methods = UdonSharpUtils.GetTypeMethods(operatorType, BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == "op_Explicit"); foreach (MethodInfo methodInfo in methods) { @@ -398,7 +391,7 @@ public static MethodInfo[] GetOperators(System.Type type, BuiltinOperatorType bu while (currentType != null) { - foundOperators.AddRange(currentType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == operatorName)); + foundOperators.AddRange(UdonSharpUtils.GetTypeMethods(currentType, BindingFlags.Public | BindingFlags.Static).Where(e => e.Name == operatorName)); currentType = currentType.BaseType; } @@ -718,6 +711,65 @@ internal static Assembly[] GetLoadedEditorAssemblies() return (Assembly[])getLoadedAssembliesProp.GetValue(null); } + private static Dictionary<(Type, BindingFlags), MethodInfo[]> typeMethodCache = new Dictionary<(Type, BindingFlags), MethodInfo[]>(512); + + public static MethodInfo[] GetTypeMethods(Type type, BindingFlags bindingFlags) + { + MethodInfo[] methods; + if (!typeMethodCache.TryGetValue((type, bindingFlags), out methods)) + { + methods = type.GetMethods(bindingFlags); + lock (typeMethodCache) + { + if (!typeMethodCache.ContainsKey((type, bindingFlags))) + { + typeMethodCache.Add((type, bindingFlags), methods); + } + } + } + + return methods; + } + + + private static Dictionary<(Type, BindingFlags), PropertyInfo[]> typePropertyCache = new Dictionary<(Type, BindingFlags), PropertyInfo[]>(512); + + public static PropertyInfo[] GetTypeProperties(Type type, BindingFlags bindingFlags) + { + PropertyInfo[] properties; + if (!typePropertyCache.TryGetValue((type, bindingFlags), out properties)) + { + properties = type.GetProperties(bindingFlags); + lock (typePropertyCache) + { + if (!typePropertyCache.ContainsKey((type, bindingFlags))) + { + typePropertyCache.Add((type, bindingFlags), properties); + } + } + } + + return properties; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasFlagFaster(this SymbolDeclTypeFlags value, SymbolDeclTypeFlags flag) + { + return (value & flag) == flag; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasFlagFaster(this MethodDeclFlags value, MethodDeclFlags flag) + { + return (value & flag) == flag; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static bool HasFlagFaster(this PropertyDeclFlags value, PropertyDeclFlags flag) + { + return (value & flag) == flag; + } + /// /// Used to prevent Odin's DefaultSerializationBinder from getting a callback to register an assembly in specific cases where it will explode due to https://github.com/mono/mono/issues/20968 /// diff --git a/Assets/UdonSharp/Scripts/UdonSharpBehaviour.cs b/Assets/UdonSharp/Scripts/UdonSharpBehaviour.cs index 475ee2ed..3ed9c5f1 100644 --- a/Assets/UdonSharp/Scripts/UdonSharpBehaviour.cs +++ b/Assets/UdonSharp/Scripts/UdonSharpBehaviour.cs @@ -70,7 +70,7 @@ public void SendCustomEvent(string eventName) } #endif - MethodInfo eventmethod = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(e => e.Name == eventName && e.GetParameters().Length == 0); + MethodInfo eventmethod = GetType().GetMethod(eventName, BindingFlags.Public | BindingFlags.Instance, null, Array.Empty(), null); if (eventmethod != null) {