Create generic instances cache (#3259)
* First attempt to create generic instances cache * Change TypeScope equality check and add instance cache clearing * Move instance cache clearing call to CodeCompletion Compile funciton Шаблонные типы в instance_cache не должны пересекаться для различных модулей. Для улучшения производительности вызов очистки кэша расположен перед вызовом компиляции всех модулей. * Squashed commit of the following: commit771ea7b445Author: Ivan Bondarev <ibond84@googlemail.com> Date: Sun Apr 6 14:32:17 2025 +0200 #3230 commit28a1a03e8dAuthor: Ivan Bondarev <ibond84@googlemail.com> Date: Sun Apr 6 11:35:09 2025 +0200 #3251 commitaf7abc770bAuthor: samuraiGH <87191377+samuraiGH@users.noreply.github.com> Date: Sun Apr 6 08:33:34 2025 +0300 synchronization of namespaces and folders for TeacherControlPlugin (#3262) commitaae723b982Author: AlexanderZemlyak <92867056+AlexanderZemlyak@users.noreply.github.com> Date: Thu Apr 3 12:00:04 2025 +0300 Create default syntax tree converter class (#3216) Для удобства разработчиков простых языков, которым не требуются дополнительные обходы синтаксического дерева. commitf9cc90e50fAuthor: Sun Serega <sunserega2@gmail.com> Date: Thu Apr 3 11:59:46 2025 +0300 fix errors (#3260) commitf85bfad60fAuthor: AlexanderZemlyak <92867056+AlexanderZemlyak@users.noreply.github.com> Date: Thu Apr 3 11:58:19 2025 +0300 Intellisense memory leaks fix (#3257) * Fix memory leaks found for PABCSystem.pas Memory leaks of Interface and Implementation Unit Scopes fixed * Change open_files and recomp_files variables type to be Dictionary (not HashTable) * open_files Check simplification * Move TypeTable.Clear call to CodeCompletion Compile method * Fix incorrect dictionary iteration * Add one more dictionary keys copying
This commit is contained in:
parent
69149f8c44
commit
2e27beef48
|
|
@ -120,6 +120,8 @@ namespace CodeCompletion
|
||||||
File.AppendAllText("log.txt", e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine);
|
File.AppendAllText("log.txt", e.Message + Environment.NewLine + e.StackTrace + Environment.NewLine);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypeScope.instance_cache.Clear();
|
||||||
|
|
||||||
// очистка кэша и данных от старых компиляций, чтобы при новой компиляции не появились ссылки на старые данные
|
// очистка кэша и данных от старых компиляций, чтобы при новой компиляции не появились ссылки на старые данные
|
||||||
TypeTable.Clear();
|
TypeTable.Clear();
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ namespace CodeCompletion
|
||||||
public void Convert(compilation_unit cu)
|
public void Convert(compilation_unit cu)
|
||||||
{
|
{
|
||||||
method_call_cache.Clear();
|
method_call_cache.Clear();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cu.visit(this);
|
cu.visit(this);
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,14 @@
|
||||||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
|
using PascalABCCompiler;
|
||||||
|
using PascalABCCompiler.Parsers;
|
||||||
|
using PascalABCCompiler.SyntaxTree;
|
||||||
|
using PascalABCCompiler.TreeRealization;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using SymbolTable;
|
|
||||||
using PascalABCCompiler.TreeRealization;
|
|
||||||
using PascalABCCompiler.SyntaxTree;
|
|
||||||
using PascalABCCompiler.Parsers;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using PascalABCCompiler;
|
using System.Reflection;
|
||||||
using PascalABCCompiler.TreeConverter;
|
|
||||||
|
|
||||||
namespace CodeCompletion
|
namespace CodeCompletion
|
||||||
{
|
{
|
||||||
|
|
@ -3589,8 +3586,23 @@ namespace CodeCompletion
|
||||||
|
|
||||||
public override TypeScope GetInstance(List<TypeScope> gen_args, bool exact = false)
|
public override TypeScope GetInstance(List<TypeScope> gen_args, bool exact = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
if ((elementType is UnknownScope || elementType is TemplateParameterScope) && gen_args.Count > 0)
|
if ((elementType is UnknownScope || elementType is TemplateParameterScope) && gen_args.Count > 0)
|
||||||
return new ArrayScope(gen_args[gen_args.Count-1], Rank > 1?indexes:null);
|
{
|
||||||
|
InstanceCreationContext info = new InstanceCreationContext(this, gen_args, exact);
|
||||||
|
|
||||||
|
if (instance_cache.TryGetValue(info, out var instance))
|
||||||
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
var arrayScope = new ArrayScope(gen_args[gen_args.Count - 1], Rank > 1 ? indexes : null);
|
||||||
|
|
||||||
|
instance_cache[info] = arrayScope;
|
||||||
|
|
||||||
|
return arrayScope;
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4102,6 +4114,41 @@ namespace CodeCompletion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal struct InstanceCreationContext : IEquatable<InstanceCreationContext>
|
||||||
|
{
|
||||||
|
public TypeScope originalType;
|
||||||
|
public List<TypeScope> genericArguments;
|
||||||
|
public bool exact;
|
||||||
|
|
||||||
|
public InstanceCreationContext(TypeScope originalType, List<TypeScope> genericArguments, bool exact)
|
||||||
|
{
|
||||||
|
this.originalType = originalType;
|
||||||
|
this.genericArguments = genericArguments;
|
||||||
|
this.exact = exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct ScopeComparer : IEqualityComparer<TypeScope>
|
||||||
|
{
|
||||||
|
public bool Equals(TypeScope t1, TypeScope t2) => t1.IsEqual(t2);
|
||||||
|
|
||||||
|
public int GetHashCode(TypeScope t) => t.GetDescription().GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(InstanceCreationContext otherInfo)
|
||||||
|
{
|
||||||
|
|
||||||
|
return this.originalType.IsEqual(otherInfo.originalType) &&
|
||||||
|
this.genericArguments.SequenceEqual(otherInfo.genericArguments, new ScopeComparer()) &&
|
||||||
|
this.exact == otherInfo.exact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return string.Join("", genericArguments.Select(arg => arg.si != null ? arg.GetDescription() : "")
|
||||||
|
.Concat(new string[] { originalType.GetDescription(), exact.ToString() })).GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//opisanie tipa (klassa, zapisi) ot nego est nasledniki. sdelal ih dlja udobstva.
|
//opisanie tipa (klassa, zapisi) ot nego est nasledniki. sdelal ih dlja udobstva.
|
||||||
public class TypeScope : SymScope, ITypeScope
|
public class TypeScope : SymScope, ITypeScope
|
||||||
{
|
{
|
||||||
|
|
@ -4122,7 +4169,7 @@ namespace CodeCompletion
|
||||||
public bool is_final;
|
public bool is_final;
|
||||||
public bool aliased = false;
|
public bool aliased = false;
|
||||||
internal bool lazy_instance = false;
|
internal bool lazy_instance = false;
|
||||||
private static Dictionary<TypeScope, List<TypeScope>> instance_cache = new Dictionary<TypeScope, List<TypeScope>>();
|
internal static Dictionary<InstanceCreationContext, TypeScope> instance_cache = new Dictionary<InstanceCreationContext, TypeScope>();
|
||||||
|
|
||||||
public TypeScope() { }
|
public TypeScope() { }
|
||||||
public TypeScope(SymbolKind kind, SymScope topScope, SymScope baseScope)
|
public TypeScope(SymbolKind kind, SymScope topScope, SymScope baseScope)
|
||||||
|
|
@ -4475,7 +4522,16 @@ namespace CodeCompletion
|
||||||
|
|
||||||
public virtual TypeScope GetInstance(List<TypeScope> gen_args, bool exact = false)
|
public virtual TypeScope GetInstance(List<TypeScope> gen_args, bool exact = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
InstanceCreationContext info = new InstanceCreationContext(this, gen_args, exact);
|
||||||
|
|
||||||
|
if (instance_cache.TryGetValue(info, out var instance))
|
||||||
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
TypeScope ts = new TypeScope(this.kind, this.topScope, this.baseScope);
|
TypeScope ts = new TypeScope(this.kind, this.topScope, this.baseScope);
|
||||||
|
|
||||||
ts.original_type = this;
|
ts.original_type = this;
|
||||||
ts.loc = this.loc;
|
ts.loc = this.loc;
|
||||||
ts.other_partials = this.other_partials;
|
ts.other_partials = this.other_partials;
|
||||||
|
|
@ -4590,6 +4646,9 @@ namespace CodeCompletion
|
||||||
new_ps.nextProc = procs[ps.nextProc] as ProcScope;
|
new_ps.nextProc = procs[ps.nextProc] as ProcScope;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance_cache[info] = ts;
|
||||||
|
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5784,9 +5843,17 @@ namespace CodeCompletion
|
||||||
|
|
||||||
public override TypeScope GetInstance(List<TypeScope> gen_args, bool exact = false)
|
public override TypeScope GetInstance(List<TypeScope> gen_args, bool exact = false)
|
||||||
{
|
{
|
||||||
Type t = this.ctn;
|
|
||||||
if (!ctn.IsGenericType)
|
if (!ctn.IsGenericType)
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
|
InstanceCreationContext info = new InstanceCreationContext(this, gen_args, exact);
|
||||||
|
|
||||||
|
if (instance_cache.TryGetValue(info, out var instance))
|
||||||
|
{
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type t = this.ctn;
|
||||||
if (!ctn.IsGenericTypeDefinition)
|
if (!ctn.IsGenericTypeDefinition)
|
||||||
{
|
{
|
||||||
t = PascalABCCompiler.NetHelper.NetHelper.FindType(this.ctn.Namespace + "." + this.ctn.Name);
|
t = PascalABCCompiler.NetHelper.NetHelper.FindType(this.ctn.Namespace + "." + this.ctn.Name);
|
||||||
|
|
@ -5885,6 +5952,9 @@ namespace CodeCompletion
|
||||||
for (int i = 0; i < this.implemented_interfaces.Count; i++)
|
for (int i = 0; i < this.implemented_interfaces.Count; i++)
|
||||||
sc.implemented_interfaces.Add(this.implemented_interfaces[i].GetInstance(gen_args));
|
sc.implemented_interfaces.Add(this.implemented_interfaces[i].GetInstance(gen_args));
|
||||||
sc.si.description = sc.GetDescription();
|
sc.si.description = sc.GetDescription();
|
||||||
|
|
||||||
|
instance_cache[info] = sc;
|
||||||
|
|
||||||
return sc;
|
return sc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
using Languages.Integration;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace VisualPascalABC
|
namespace VisualPascalABC
|
||||||
{
|
{
|
||||||
|
|
@ -98,7 +97,7 @@ namespace VisualPascalABC
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (string s in open_files.Keys)
|
foreach (string s in open_files.Keys.ToArray())
|
||||||
{
|
{
|
||||||
if (ProjectFactory.Instance.CurrentProject.ContainsSourceFile(s))
|
if (ProjectFactory.Instance.CurrentProject.ContainsSourceFile(s))
|
||||||
open_files[s] = true;
|
open_files[s] = true;
|
||||||
|
|
@ -147,7 +146,7 @@ namespace VisualPascalABC
|
||||||
{
|
{
|
||||||
Dictionary<string, string> recomp_files = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, string> recomp_files = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
bool is_comp = false;
|
bool is_comp = false;
|
||||||
foreach (string FileName in open_files.Keys)
|
foreach (string FileName in open_files.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
||||||
{
|
{
|
||||||
|
|
||||||
if (open_files[FileName])
|
if (open_files[FileName])
|
||||||
|
|
@ -181,7 +180,7 @@ namespace VisualPascalABC
|
||||||
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
|
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (string FileName in open_files.Keys)
|
foreach (string FileName in open_files.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
||||||
{
|
{
|
||||||
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
||||||
CodeCompletion.SymScope ss = null;
|
CodeCompletion.SymScope ss = null;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
|
||||||
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
|
||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace VisualPascalABC
|
namespace VisualPascalABC
|
||||||
{
|
{
|
||||||
|
|
@ -98,7 +98,7 @@ namespace VisualPascalABC
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
foreach (string s in open_files.Keys)
|
foreach (string s in open_files.Keys.ToArray())
|
||||||
{
|
{
|
||||||
if (ProjectFactory.Instance.CurrentProject.ContainsSourceFile(s))
|
if (ProjectFactory.Instance.CurrentProject.ContainsSourceFile(s))
|
||||||
open_files[s] = true;
|
open_files[s] = true;
|
||||||
|
|
@ -151,7 +151,7 @@ namespace VisualPascalABC
|
||||||
{
|
{
|
||||||
Dictionary<string, string> recomp_files = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
Dictionary<string, string> recomp_files = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
|
||||||
bool is_comp = false;
|
bool is_comp = false;
|
||||||
foreach (string FileName in open_files.Keys)
|
foreach (string FileName in open_files.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
||||||
{
|
{
|
||||||
|
|
||||||
if (open_files[FileName])
|
if (open_files[FileName])
|
||||||
|
|
@ -185,7 +185,7 @@ namespace VisualPascalABC
|
||||||
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
|
CodeCompletion.CodeCompletionController.comp_modules[FileName] = dc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (string FileName in open_files.Keys)
|
foreach (string FileName in open_files.Keys.ToArray()) // копирование ключей обязательно, иначе будет InvalidOperationException EVA
|
||||||
{
|
{
|
||||||
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
CodeCompletion.DomConverter dc = CodeCompletion.CodeCompletionController.comp_modules[FileName] as CodeCompletion.DomConverter;
|
||||||
CodeCompletion.SymScope ss = null;
|
CodeCompletion.SymScope ss = null;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue