Контекст
Мой вопрос двоякий (на самом деле два вопроса), но довольно простой *. Но сначала я покажу соответствующий код для некоторого контекста. Для TL; DR «мясо и картофель» перейдите к нижней части для фактических вопросов.
*(Я предполагаю, что отвечающие знают о том, что происходит/как работает виртуальная машина, прежде чем пытаться ответить).
Как уже упоминалось, я пишу (игрушечную) виртуальную машину, которая выполняет пользовательский набор инструкций байт-кода.
(многоточие здесь означает пропуск некоторых случаев)
Вот фрагмент моего кода:
for (ip = 0; (ip < _PROGRAM_SIZE || !cstackempty); ip++) {
if (breakPending) { break; }
switch (_instr) {
case INST::PUSH: {
AssertAbort(wontoverflow(1), "Stack overflow (1 byte)");
cmd_ "PUSH";
push(_incbyte);
printStack();
break;
}
...
case INST::ADD: {
AssertAbort(stackhas(2), "Can't pop stack to add 2 bytes. Stack does not contain 2 bytes");
cmd_ "ADD";
byte popped8_a = pop();
byte popped8_b = pop();
byte result = popped8_a + popped8_b;
push(result);
cmd_ " "; cmd_(byte)result;
printStack();
break;
}
case INST::ADD16: {
AssertAbort(stackhas(4), "Can't pop stack to add 4 bytes. Stack does not contain 4 bytes");
cmd_ "ADD16";
u16 popped16_a = pop16();
u16 popped16_b = pop16();
u16 result = popped16_a + popped16_b;
push16(result);
cmd << " "; cmd << (u16)result;
printStack();
break;
}
...
}
}
Только потому, что это уместно, я упомяну, что _cstack
это стек вызовов, отсюда и макрос !cstackempty
, который проверяет, пуст ли вызов перед вызовом выхода (выход из цикл for) только потому, что это последняя выполняемая инструкция (потому что эта последняя инструкция может быть частью функции или даже возвратом). Кроме того, ip
(указатель инструкции) — это просто unsigned long long (u64), как и _PROGRAM_SIZE
(размер программы в байтах). instr
является байтом и является ссылкой на текущую инструкцию (1 байт).
Мясо и картофель
Вопрос 1. Поскольку я инициализирую два новых целых числа переменного размера для каждого блока/кейса (сегментированных на блоки, чтобы избежать ошибок повторного объявления и т. д.), объявление их над циклом for
будет полезно с точки зрения скорости , задержка назначения, размер программы и т. д.?
Вопрос 2. Будет ли continue
быстрее, чем break
в этом случае, и есть ли более быстрый способ выполнить такой условный цикл, например какой-нибудь переход от указателя к метке, как в этот пост, который не зависит от реализации, или как-то избежать затрат на continue
или break
?
Подводя итог, мои приоритеты: скорость, затем затраты на память (скорость, эффективность), затем размер файла (ВМ).