Контекстно-независимый межпроцедурный анализ

Опубликовано: 23 Февраля, 2023

Контекстно-независимый межпроцедурный анализ — это метод прогнозирования поведения программ во время выполнения. Он использовался при проектировании компиляторов для повышения производительности, но еще не нашел широкого применения в других приложениях, таких как оптимизация запросов к базе данных.

Эффекты вызова метода:

Эффекты вызова метода — это эффекты тела метода плюс любые другие методы, которые вызываются телом метода. Сайт вызова — это потенциально исполняемая инструкция в объектном файле или исполняемой программе. Виртуальный сайт вызова — это потенциально исполняемая инструкция в объектном файле или исполняемой программе, которая не содержит ссылок на какие-либо базовые классы (т. е. классы, производные непосредственно от объекта).

Влияние каждого сайта вызова на его вызывающую сторону зависит от того, какой вид анализа потока управления использовался для определения его порядка выполнения: статический анализ одиночного присваивания (SSA), частичное упорядочение с глобальными переменными, порядок оценки первого порядка на основе ограничений приоритета и т. д. .

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

Эффект от вызовов методов, сделанных телом метода, определяется анализом потока управления. Анализ потока управления выполняется для того, чтобы определить, какие инструкции будут выполняться и когда. Анализ потока управления может использовать следующую информацию:

  1. Тип каждого выражения и значения, которые оно принимает во время выполнения.
  2. Любой код, который уже был выполнен в теле метода (т. е. вызовы базового класса).
  3. Любые методы, на которые ссылаются другие методы того же класса (или любого другого класса).

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

Обнаружение графика вызовов в журнале данных:

Datalog — это язык декларативного логического программирования, который использует факты и правила для описания и решения проблем. Он также используется в аналитике данных, где его можно использовать в качестве языка запросов для баз данных.

Синтаксис Datalog подобен другим SQL-подобным языкам, но имеет некоторые уникальные особенности:

Типы данных определяются с помощью списков терминов, а не литералов; поэтому вам не нужно указывать тип каждой переменной при их объявлении (см. «Списки терминов» ниже).

Термины имеют фиксированную арность (количество аргументов), что упрощает написание рекурсивных предикатов по сравнению с другими языками, такими как Prolog или основанная на терминах модель Haskell; однако, в отличие от тех других языков, где переменные могут представлять любое значение в любое время во время выполнения (даже если они еще не были объявлены), переменные всегда существуют до тех пор, пока они не будут перезаписаны другой переменной, названной в их честь в вашей программе.

Журнал данных является декларативным, что означает, что программист сообщает системе, что делать, а не как это делать. Синтаксис Datalog очень похож на SQL; однако вместо операторов обработки данных (SELECT, INSERT) или операторов управления потоком (IF-THEN-ELSE) вы используете правила и факты.

Ниже приведены примеры некоторых правил и фактов:

Rule1: Person(name) ← male, female. 
Rule2: Person(name) ← age, height. 
Fact: John is a person who is 35 years old and 6 feet tall.

Динамическая загрузка и отражение:

Динамическая загрузка — это метод доступа к объекту во время выполнения. Мы обсудим, как вы можете использовать отражение для вызова методов и вызова статических членов класса, используя следующие шаги:

Используйте динамическую загрузку, чтобы определить тип определенного объекта, просматривая информацию о его типе в файле архива или предоставляя дополнительную контекстно-зависимую информацию в зависимости от того, откуда он был загружен.

Используйте рекурсию, чтобы просмотреть граф вызовов и определить, есть ли какие-либо рекурсивные вызовы, которые необходимо выполнить, прежде чем продолжить поток выполнения вашей программы. Рекурсия позволяет таким программам, как компиляторы или интерпретаторы (например), выполнять такие задачи, как вычисление выражений; эти задачи могут включать несколько уровней косвенности (ссылок), если они были написаны на другом языке, кроме Java!

Используйте API отражения для вызова методов и вызова статических членов класса. API Javareflection позволяет вам вызывать методы и вызывать статические члены класса во время выполнения.

Это полезно, когда пользователи хотят написать общий код, который работает с объектами любого типа, а также позволяет Java-программам проводить самоанализ. Чтобы использовать API отражения в программе, сначала загрузите в память экземпляр класса, к членам которого вы хотите получить доступ. Затем вызовите один из методов класса java.lang.reflect.

Класс для доступа к членам. Используйте отражение различными способами, в том числе:

  1. Определите, какие методы доступны для данного класса или интерфейса во время выполнения.
  2. Вызовите методы для объектов, созданных вами динамически — возможно, с параметрами, которые зависят от информации, собранной во время выполнения.

Вывод:

Использование контекстно-независимого межпроцедурного анализа является важным инструментом для разработчиков компиляторов, которые хотят сделать свои программы более эффективными. Это позволяет им анализировать поведение программы во время выполнения, не зная полного графа потока управления. В этом посте мы обсудили, как можно использовать эту технику, и несколько примеров того, где она полезна.