UNSAFECSHARP Telegram 261
IL или как я разбираю джобы

Что такое IL? IL (или Intermediate Language) - это промежутный язык, который еще и не рантайм, но уже и не C#.
Его смысл в том, что это плюс-минус набор инструкций, по которым можно понять суть происходящего в методе.

Как оно выглядит?

IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 C::a
IL_0007: ldc.i4.s 10
IL_0009: cgt
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0018

IL_000f: nop
IL_0010: ldarg.0
IL_0011: call instance void C::A()
IL_0016: nop
IL_0017: nop

IL_0018: ldarg.0
IL_0019: call instance void C::A()
IL_001e: nop
IL_001f: ldarg.0
IL_0020: call instance void C::A()
IL_0025: nop
IL_0026: ret


Чем я пользуюсь? https://github.com/chromealex/ME.BECS/tree/main/Runwww.tgoop.com/Extensions/Mono.Reflection
Это не Mono.Cecil, но для моих задач подходит отлично.
Работа этой штуки сводится к тому, чтобы разобрать инструкции метода и сложить их в плюс-минус удобный список.

Давайте разберем задачу из прошлого поста:
Нам нужно посчитать количество вызовов метода.


var count = 0;
var targetMethod = typeof(Ent).GetMethod(nameof(Ent.New), ...);
var instructions = executeJobMethod.GetInstructions();
for (int i = 0; i < instructions.Count; ++i) {
var inst = instructions[i];
{
// тут можем обработать инструкцию
if (inst.Operand is System.Reflection.MethodInfo method && method == targetMethod) {
++count;
}
}
{
if (inst.Operand is System.Reflection.MethodInfo method) {
instructions.InsertRange(i + 1, method.GetInstructions());
}
}
}


Фактически в данный момент мы посчитали количество вызовов определенного метода в джобе рекурсивно заходя в каждый метод. У меня к этому коду еще добавлены различные аттрибуты, чтобы не заходить в ненужные методы и чтобы не попасть в рекурсию, но я уверен, что вы справитесь с этой задачей.

Как я говорил в прошлом посте, нам нужно считать не просто количество вызовов, но и посчитать количество вызовов в цикле (ну или определить, что они в принципе там есть).

Для этого нам нужно обратиться к OpCodes. Это по сути код операции у инструкции, которую мы сейчас обрабатываем.
Кодов очень много, но нас интересуют лишь коды бранчей.
Бранч - это ветка. Бранчи могут быть созданы в различных кейсах: это может быть if, может быть цикл foreach, for, while и т.д.
Код вида br* будет приводить к переходу (типа goto) к конкретной инструкции.
И тут начинается самое интересное. Любые циклы и условия - это одна и та же операция br*, но за одним исключением: вместе с этой операцией передается номер строки (например, IL_0007), куда нужно осуществить переход.
Так вот если адрес этого перехода меньше, чем адрес текущей инструкции - мы закончили итерацию цикла и возвращаемся назад.
А если инструкция br* ведет нас вперед, то это открытие условия или цикла.

В коде выше можно увидеть эту инструкцию в виде IL_000d: brfalse.s IL_0018. То есть мы переходим в 0018, что находится ниже, значит это условие, а не цикл.

Текущий код по поиску информации можно посмотреть здесь:
https://github.com/chromealex/ME.BECS/blob/a665a344e6957ff18945dd9862981d79910c0491/Editor/CodeGenerator/Generators/JobsEarlyInitCodeGenerator.cs#L437

#becs #il #jobs
35312🔥8👍3🤯3



tgoop.com/unsafecsharp/261
Create:
Last Update:

IL или как я разбираю джобы

Что такое IL? IL (или Intermediate Language) - это промежутный язык, который еще и не рантайм, но уже и не C#.
Его смысл в том, что это плюс-минус набор инструкций, по которым можно понять суть происходящего в методе.

Как оно выглядит?


IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 C::a
IL_0007: ldc.i4.s 10
IL_0009: cgt
IL_000b: stloc.0
IL_000c: ldloc.0
IL_000d: brfalse.s IL_0018

IL_000f: nop
IL_0010: ldarg.0
IL_0011: call instance void C::A()
IL_0016: nop
IL_0017: nop

IL_0018: ldarg.0
IL_0019: call instance void C::A()
IL_001e: nop
IL_001f: ldarg.0
IL_0020: call instance void C::A()
IL_0025: nop
IL_0026: ret


Чем я пользуюсь? https://github.com/chromealex/ME.BECS/tree/main/Runwww.tgoop.com/Extensions/Mono.Reflection
Это не Mono.Cecil, но для моих задач подходит отлично.
Работа этой штуки сводится к тому, чтобы разобрать инструкции метода и сложить их в плюс-минус удобный список.

Давайте разберем задачу из прошлого поста:
Нам нужно посчитать количество вызовов метода.


var count = 0;
var targetMethod = typeof(Ent).GetMethod(nameof(Ent.New), ...);
var instructions = executeJobMethod.GetInstructions();
for (int i = 0; i < instructions.Count; ++i) {
var inst = instructions[i];
{
// тут можем обработать инструкцию
if (inst.Operand is System.Reflection.MethodInfo method && method == targetMethod) {
++count;
}
}
{
if (inst.Operand is System.Reflection.MethodInfo method) {
instructions.InsertRange(i + 1, method.GetInstructions());
}
}
}


Фактически в данный момент мы посчитали количество вызовов определенного метода в джобе рекурсивно заходя в каждый метод. У меня к этому коду еще добавлены различные аттрибуты, чтобы не заходить в ненужные методы и чтобы не попасть в рекурсию, но я уверен, что вы справитесь с этой задачей.

Как я говорил в прошлом посте, нам нужно считать не просто количество вызовов, но и посчитать количество вызовов в цикле (ну или определить, что они в принципе там есть).

Для этого нам нужно обратиться к OpCodes. Это по сути код операции у инструкции, которую мы сейчас обрабатываем.
Кодов очень много, но нас интересуют лишь коды бранчей.
Бранч - это ветка. Бранчи могут быть созданы в различных кейсах: это может быть if, может быть цикл foreach, for, while и т.д.
Код вида br* будет приводить к переходу (типа goto) к конкретной инструкции.
И тут начинается самое интересное. Любые циклы и условия - это одна и та же операция br*, но за одним исключением: вместе с этой операцией передается номер строки (например, IL_0007), куда нужно осуществить переход.
Так вот если адрес этого перехода меньше, чем адрес текущей инструкции - мы закончили итерацию цикла и возвращаемся назад.
А если инструкция br* ведет нас вперед, то это открытие условия или цикла.

В коде выше можно увидеть эту инструкцию в виде IL_000d: brfalse.s IL_0018. То есть мы переходим в 0018, что находится ниже, значит это условие, а не цикл.

Текущий код по поиску информации можно посмотреть здесь:
https://github.com/chromealex/ME.BECS/blob/a665a344e6957ff18945dd9862981d79910c0491/Editor/CodeGenerator/Generators/JobsEarlyInitCodeGenerator.cs#L437

#becs #il #jobs

BY Unity: Всё, что вы не знали о разработке




Share with your friend now:
tgoop.com/unsafecsharp/261

View MORE
Open in Telegram


Telegram News

Date: |

The public channel had more than 109,000 subscribers, Judge Hui said. Ng had the power to remove or amend the messages in the channel, but he “allowed them to exist.” As the broader market downturn continues, yelling online has become the crypto trader’s latest coping mechanism after the rise of Goblintown Ethereum NFTs at the end of May and beginning of June, where holders made incoherent groaning sounds and role-played as urine-loving goblin creatures in late-night Twitter Spaces. Commenting about the court's concerns about the spread of false information related to the elections, Minister Fachin noted Brazil is "facing circumstances that could put Brazil's democracy at risk." During the meeting, the information technology secretary at the TSE, Julio Valente, put forward a list of requests the court believes will disinformation. Telegram channels fall into two types: During the meeting with TSE Minister Edson Fachin, Perekopsky also mentioned the TSE channel on the platform as one of the firm's key success stories. Launched as part of the company's commitments to tackle the spread of fake news in Brazil, the verified channel has attracted more than 184,000 members in less than a month.
from us


Telegram Unity: Всё, что вы не знали о разработке
FROM American