Оптимизация foreach в for для многократного ускорения цикла для IList<T> (массивов, списков)
Не работает в лямбдах! (техническое ограничение) Плагин запуска ILDasm
This commit is contained in:
parent
3d845a4e80
commit
c94b1037cc
|
|
@ -15,7 +15,7 @@ internal static class RevisionClass
|
|||
public const string Major = "3";
|
||||
public const string Minor = "5";
|
||||
public const string Build = "1";
|
||||
public const string Revision = "2281";
|
||||
public const string Revision = "2287";
|
||||
|
||||
public const string MainVersion = Major + "." + Minor;
|
||||
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%MINOR%=5
|
||||
%REVISION%=2281
|
||||
%REVISION%=2287
|
||||
%COREVERSION%=1
|
||||
%MAJOR%=3
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.5.1.2281
|
||||
3.5.1.2287
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
!define VERSION '3.5.1.2281'
|
||||
!define VERSION '3.5.1.2287'
|
||||
|
|
|
|||
26
TestSuite/Foreach_to_for.pas
Normal file
26
TestSuite/Foreach_to_for.pas
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
type Person = class
|
||||
|
||||
end;
|
||||
|
||||
procedure P(a: array of Person);
|
||||
begin
|
||||
var s: Person;
|
||||
foreach var x in a do
|
||||
s := x;
|
||||
end;
|
||||
|
||||
procedure P<T>(a: array of T);
|
||||
begin
|
||||
var s: T;
|
||||
foreach var x in a do
|
||||
s := x;
|
||||
end;
|
||||
|
||||
begin
|
||||
var n := 5000;
|
||||
var a := ArrFill(n,1);
|
||||
var s := 0;
|
||||
foreach var x in a do
|
||||
s += x;
|
||||
Assert(s = n);
|
||||
end.
|
||||
|
|
@ -13,6 +13,22 @@ namespace PascalABCCompiler.TreeConverter
|
|||
|
||||
public override void visit(foreach_stmt _foreach_stmt)
|
||||
{
|
||||
// SSM 24.12.19 lambda_capture_foreach_counter.pas не проходит если откомментировать эти 2 строки
|
||||
// Причина - лямбда уже начала разбираться
|
||||
// Пробую сделать так: если foreach в лямбде, то оптимизация не делается, а если нет, то делается
|
||||
|
||||
syntax_tree_node p = _foreach_stmt;
|
||||
do
|
||||
{
|
||||
p = p.Parent;
|
||||
} while (!(p == null || p is procedure_definition || p is function_lambda_definition));
|
||||
|
||||
if (!(p is function_lambda_definition)) // тогда оптимизируем
|
||||
{
|
||||
var feWhat = convert_strong(_foreach_stmt.in_what);
|
||||
if (OptimizeForeachInCase1DArray(_foreach_stmt, feWhat)) return;
|
||||
}
|
||||
|
||||
statements_list sl2 = new statements_list(get_location(_foreach_stmt));
|
||||
convertion_data_and_alghoritms.statement_list_stack_push(sl2);
|
||||
|
||||
|
|
@ -120,6 +136,35 @@ namespace PascalABCCompiler.TreeConverter
|
|||
}
|
||||
|
||||
|
||||
private bool IsIList(expression_node en)
|
||||
{
|
||||
var ii = en.type.ImplementingInterfaces;
|
||||
foreach (var itn in ii)
|
||||
{
|
||||
System.Type tt = null;
|
||||
if (itn is compiled_type_node ctn)
|
||||
{
|
||||
tt = ctn.compiled_type;
|
||||
if (tt.IsGenericType)
|
||||
tt = tt.GetGenericTypeDefinition();
|
||||
if (tt == typeof(System.Collections.Generic.IList<>))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (itn is compiled_generic_instance_type_node itnc)
|
||||
{
|
||||
tt = (itnc.original_generic as compiled_type_node).compiled_type;
|
||||
if (tt == typeof(System.Collections.Generic.IList<>))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Преобразует foreach в for, если коллекция это одномерный массив.
|
||||
|
|
@ -141,13 +186,14 @@ namespace PascalABCCompiler.TreeConverter
|
|||
if (comtn != null && comtn.internal_type_special_kind == type_special_kind.array_kind &&
|
||||
comtn.rank == 1)
|
||||
{
|
||||
is1dimdynarr = true;
|
||||
is1dimdynarr = true;
|
||||
}
|
||||
}
|
||||
|
||||
var il = IsIList(in_what);
|
||||
|
||||
// SSM 23.08.16 Закомментировал оптимизацию. Не работает с лямбдами. Лямбды обходят старое дерево. А заменить foreach на for на этом этапе пока не получается - не развита инфраструктура
|
||||
|
||||
// SSM 24.12.19 Раскомментировал оптимизацию, но только если foreach не вложен в лямбду
|
||||
if (is1dimdynarr) // Замена foreach на for для массива
|
||||
{
|
||||
// сгенерировать код для for и вызвать соответствующий visit
|
||||
|
|
@ -175,7 +221,7 @@ namespace PascalABCCompiler.TreeConverter
|
|||
var newbody = _foreach_stmt.stmt.ToStatementList();
|
||||
newbody.AddFirst(vd);
|
||||
|
||||
var high = arrid.dot_node("Length").Minus(1);
|
||||
var high = arrid.dot_node("Count").Minus(1);
|
||||
|
||||
var fornode = new for_node(i, 0, high, newbody, for_cycle_type.to, null, null, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -120,8 +120,10 @@ namespace VisualPascalABCPlugins
|
|||
try
|
||||
{
|
||||
string s;
|
||||
if((s= GetVS8Dir())==null) return null;
|
||||
s = s + "\\SDK\\v2.0\\bin\\ildasm.exe";
|
||||
//if((s= GetVS8Dir())==null) return null;
|
||||
string program_files_x86_folder = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
|
||||
s = program_files_x86_folder+"\\ILSpy\\ILSpy.exe";
|
||||
//s = s + "\\SDK\\v2.0\\bin\\ildasm.exe";
|
||||
if (System.IO.File.Exists(s))
|
||||
return s;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue