Loops e Guardas
O que são guardas?
Seção intitulada “O que são guardas?”Os Hooks deliberadamente não são Turing Completos. Isso significa que loops arbitrários são proibidos. Em vez disso, você deve guardar seus loops com um limite rígido de “iteração máxima”.
Uma guarda é um marcador colocado no seu código no início de cada loop. O marcador informa ao Xahau qual é o limite superior do seu loop em todos os cenários possíveis. Assim, se o seu loop normalmente executa duas vezes, mas às vezes executa 500 vezes, sua guarda dirá 500.
As guardas são usadas pelo Xahau para determinar o pior tempo de execução (em instruções) do seu Hook antes da execução. Esta é a base para a taxa que o Xahau cobra pela execução de um Hook e torna os tempos de execução previsíveis e controláveis.
A função guard
Seção intitulada “A função guard”A função guard informa ao ledger o número máximo de iterações que um loop realizará. Especificamente, a função aceita dois argumentos:
int32_t _g (uint32_t id, uint32_t maxiter);O primeiro argumento id é o identificador para esta guarda. Esta é uma constante única escolhida pelo desenvolvedor; tipicamente o número da linha no arquivo fonte é usado.
O segundo argumento maxiter é uma promessa que o desenvolvedor faz ao ledger de que esta guarda não será acionada mais de maxiter vezes durante a execução do Hook. Se a chamada da guarda for executada mais do que esse número de vezes, o Hook fará automaticamente rollback com um GUARD_VIOLATION (códigos de retorno da API de Hook). Como a guarda será acionada antes que a condição do loop seja verificada, é importante adicionar um ao número total de iterações esperadas. (Nota: A macro GUARD() já adiciona um).
Aplicação das guardas
Seção intitulada “Aplicação das guardas”Considere o seguinte for-loop em C:
#define GUARD(maxiter) _g(__LINE__, (maxiter)+1)for (int i = 0; GUARD(3), i < 3; ++i){ ...}Em C, o operador vírgula executa cada expressão em uma lista de expressões (por exemplo, A, B, C) e retorna a última expressão (por exemplo, C). Assim, a condição acima ainda é i < 3, mas a guarda é chamada antes que a condição seja verificada. Esta é a única forma de satisfazer a regra da guarda ao usar um for-loop em C.
Abaixo aparece a saída webassembly quando o código acima é compilado. Note a função guard sendo chamada no início do loop. As únicas instruções permitidas antes desta chamada são instruções sem branch (tipicamente manipulando constantes).
block ;; label = @1 loop ;; label = @2 i32.const 3 i32.const 14=====> call $_g <===== drop ...Loops Aninhados
Seção intitulada “Loops Aninhados”Ao usar loops aninhados, o argumento maxiter deve refletir o número total de vezes que a guarda será acionada. Isso significa que você deve multiplicar os aninhamentos juntos.
Considere o exemplo abaixo:
#define GUARD(maxiter) _g(__LINE__, (maxiter)+1)for (int i = 0; GUARD(3), i < 3; ++i){ for (int j = 0; GUARD(15), j < 5; ++j) { ... }}Note que a guarda do loop interno está definida como 15. Você deve multiplicar os loops juntos para calcular o número máximo de vezes que uma guarda interna será acionada durante a execução do Hook.
Sem recursão
Seção intitulada “Sem recursão”Chamadas a funções que não são da API de Hook são proibidas na emenda de Hooks. Todo o código do usuário deve caber dentro das duas funções Hook permitidas cbak e hook.