Skip to content

Latest commit

 

History

History
1400 lines (1066 loc) · 62.4 KB

File metadata and controls

1400 lines (1066 loc) · 62.4 KB

Project Planning: zevem

Zevem

Project Focus

Current area of focus so I don’t forget what I was doing.

2025/09/11 TODO: Could use org-agenda to collect the requisite headlines instead of enforcing a literal structure (by having them all under here). Yak shave that later.

Message Call

TODO: Finish refreshing myself on what I need to catch up on here.

Implementation

Opcodes

  • Stub out 40s opcodes
  • Add MSIZE with basic tests
  • Refactor memory resizing to nextOp, adapt MSTORE tests, add KECCAK test for memory resizing
  • KECCAK256 and surrounding utilities with many sanity checks along the way
  • Add MSTORE8 with basic tests
  • Add basic MLOAD with basic tests
  • Part of MLOAD, need to get laundry right now though.
  • Add GAS with tests, also correct argument ordering for recent JUMP, JUMPI, PC in expectEqual tests.
  • Add annotations for recently implemented JUMP, JUMPI, and PC.

JUMP

  • JUMP/JUMPDEST implemented with basic tests. DynamicBitSetUnmanaged to pre-scan and construct bitset of valid JUMPDEST locations.
  • More reading on JUMP and friends, yep we gotta do all the validation ourselves. Oh boy.
  • Read associated YP information, need to implement JUMPDEST too and some more logic according to 9.4.3 so will do this later.

(9.4.3) Function D determines set of valid jump destinations. To be valid:

  1. Position must be occupied by a JUMPDEST instruction.
  2. JUMPDEST must not reside within data portion of any PUSH.
  3. Must appear within explicitly defined bytecode, and not the implicit infinite STOP padding.

Zig bit sets look good for this: https://ziglang.org/documentation/0.14.1/std/#std.bit_set

Not possible to know bytecode length at comptime, could set an upperbound but would require re-compiling if block gas limits change to allow more bytecode to be executed so DynamicBitSetUnmanaged from stdlib looks like a good pre-provided data structure for this.

Is it our job (as zevem) to assert 2 and 3? That would require ahead of time scanning the entire bytecode to execute or checking left-right of JUMPDEST to see if it resides within any PUSH (at every such call)
  • State “TODO” from [2025-09-24 Wed 22:24]
    If we need to do these checks it can get complicated

YES IT’S OUR JOB

Q: Do we have to analyse ahead of time or can we do it as we go and revert then and there? Potential issues perhaps? Do the ahead of time first since it’s simpler for now. I think we will have to since there’s no guarantee all of the bytecode will be explored so trying to determine during runtime (and not ahead of time) if a JUMPDEST is actually a JUMPDEST and not a byte in the data portion of a PUSH will be quite hard and cost more computationally than looking at all of the bytecode and creating a bitmask. Benchmark later, this seems like a hyper-optimisation.

What if it wants to set a program counter above u64?

Look at (160) 9.4.3 which defines how JUMP and JUMPDEST are required to interact. Continue from there.

JUMPI

  • Add JUMPI with basic tests

PC

  • Add PC with basic tests
Is the PC prior or the current PC?
  • State “TODO” from [2025-10-21 Tue 19:11]
Yellow-paper says prior but (small) experimentation suggests current? Going with current for now, need to check this later.

Gas

Ref: YP Gas

TODO: Construct a list like this from the local subtree hierarchy here. That way I get both easy checkbox summary and state tracking via LOGBOOK which can only be done on headings.

  1. [ ] Intrinsic cost
  2. [ ] Subordinate message calls or contract creation
    • [ ] CREATE
    • [ ] CREATE2
    • [ ] CALL
    • [ ] CALLCODE
  3. [ ] Memory usage

Memory usage

C_mem(μ_i′) - C_mem(μ_i)

Comptime memory size
  • Got actual dynamic gas (based on simpler memory size changes) actually working (correctness in terms of the price it reports to be tested still).
  • Basic comptime function generation for memory size functions MVP.

Define memory size function for an opcode in the comptime MakeOpCodes tuple.

MSTORE
  • Re-aqainting myself with gas charging again; implement hardcoded dynamic gas cost for MSTORE. This will need to be made generic essentially immediately.

Misc

  • Migrate from BlockHeader struct with fields to methods on DummyEnv comptime interface

Disassembly Logging

Good-enough disassembly-type logging until “real” and “better” (perhaps structured) logging implemented once zevem is 1.0. These are the functions traceOpNew and friends.

Yellowpaper Notes

Conventions

Double-stroked N
scalars are non-negative integers.
Double-stroked B
set of all byte sequences.

If N is subscripted (e.g. N_256) it is the set of all non-negative integers smaller than 2^256. If B is subscripted (e.g. B_32) it is the set of all byte sequences of length 32.

Square brackets index into, and/or reference individual components or subsequences.

Two adjacent dots (yellowpaper mistakenly calls ellipsis) denote inclusive range.

Modified and utilisable value of a thing is denoted prime ′ and intermediate values superscript one or two asterisks.

Empty sequence denoted () and empty set ∅ and these are not equal to each other.

Structure

World State

Maps addresses (160-bit identifiers) and account states (RLP serialised data). Not stored on-chain, usually maintained in a modified Merkle Patricia tree (herein: trie) held by some database (“state database”).

Any of the formulas on page 4 which are relevant for just-the-EVM implementation.END
Account State

Accounts have four fields. Accounts are empty if they have no code, zero nonce, and zero balance (f.14).

Nonce

Scalar number of transactions sent from address. If account has associated code, number of contract-creations made by account.

Balance

Scalar amount of Wei owned by address.

Storage-root

256-bit hash for root node of trie that encodes the storage contents for account. Stylised: storageRoot.

More detailed storageRoot notes Yellowpaper pg 4 left-side.END
Code-hash

Hash of EVM code associated with account. Such code will be executed when a message call is received. Code is stored keyed by their Keccak-256 hash. Subscript c refers to the code-hash, stylised: codeHash.

Bold b refers to the concrete code. Thus KEC(b) = σ[a]_c.

If codeHash is hash of empty string (i.e. σ[a]_c = KEC(())) then the node is a simple account, aka “non-contract” account.

What is “node” here?? bottom of page 4 in ypEND

Machine State

Machine state notesEND

μ_i: bottom of page 29 is the maximum number of words of active memory, and pg15 9.4.1 m: memory contents, a series of zeroes of size 2^256. i: active number of words in memory, counting continuously from zero.

Transaction

Single cryptographically-signed instruction. Sender cannot be a contract. EIP-2718 introduces different transaction types (via a transaction envelope).

0
legacy
1
EIP-2930
2
EIP-1559

Transactions can create new accounts with associated code (informally “contract creation”), or result in message calls.

Common Transaction Fields

All transactions have common fields:

type

EIP-2718 transaction type.

nonce

Scalar number of transactions sent by sender.

gasLimit

Scalar maximum amount of gas which could be used in executing this transaction. Paid up-front before any computation. Immutable during transaction.

to

160-bit address of the message call’s recipient. If contract creation then ∅ which here represents B_0 (set of all byte sequences of length zero).

value

Scalar amount of Wei to transfer to message call’s recipient. If contract creation then an endowment to newly created account.

r

Signature of transaction.

And for s, see Appendix F of yp for these definitions see also bottom left of page 5 of ypEND
s

Sender of transaction.

Legacy Transaction Fields
w

Scalar encoding of Y parity, and possibly chain ID. This is essentially the chainId and yParity fields but for legacy transactions. See EIP-155.

EIP-2930, EIP-1559 Transaction Fields
accessList

List of access entries to warm up.

What does that mean? Plus notes on the tuple information there.END
chainId

Chain ID, must be equal to network chain ID denoted β.

yParity

Signature Y parity.

What? yp pg5 left side.END
Gas Pricing

Type 2 transactions specify gas pricing differently to type 0 and type 1.

Legacy, EIP-2930 Gas Pricing

Single field.

gasPrice

Scalar maximum amount of Wei payable per unit of gas for all computation costs relating to execution of this transaction.

EIP-1559 Gas Pricing

Two fields related to gas intended to explicitly limit priority fee magnitude.

maxFeePerGas

Scalar maximum amount of Wei payable per unit of gas for all computation costs relating to execution of this transaction.

maxPriorityFeePerGas

Scalar maximum amount of Wei payable to block’s fee recipient as an incentive to include the transaction.

Contract Creation Fields

Regardless of transaction type, a contract creation transaction has the field:

init

Unlimited size byte array of EVM bytecode for account initialisation procedure. Specifically, init is a code-fragment which returns a body (a second fragment of code); the body is executed each time the account receives a message call (whether from a transaction, or internal execution).

So, init is only executed once (at contract creation) and is discarded immediately thereafter.

Message Call Fields

For all transaction types which are message calls, there will be the field:

data

Unlimited size byte array specifying input data of the message call.

Gas and Payment

Fee schedule (Appendix G). The gasLimit T_g of a transaction is implicitly purchased from the sender’s account balance at the effective gas price before any computation is performed. At the end of the transaction any unused gas is refunded (at the same rate of purchase) to the sender’s account.

If this implicit purchase can not be made (not enough account balance) then the transaction is invalid.

effective gas price section 6ENDgas does not exist outside of the execution of a transaction i get that but what does the following (bottom-right pg8) then mean: Thus for accounts with trusted code associated, a relatively high gas limit may be set and left alone.END

Since EIP-1559 every transaction must pay a base fee which is specified in Wei per unit of gas consumed and is immutable during each transaction in a given block. The Wei paid to meet the base fee is burned.

The base fee adjusts dynamically based on the previous block’s gas consumption relative to it’s gas target. The gas target is adjustable by validators.

If the previous block’s total gas consumption exceeds it’s gas target (i.e. high demand) the base fee is increased, and vice versa.

section 4.4 outlines how the base fee is set in detailEND

To incentivise validators to include transactions a priority fee, also specified in Wei per unit of gas consumed, is payable. The total fee for a transaction is the sum of the base fee and priority fee then multiplied by the total gas consumed. The priority fee is paid to a beneficiary address.

EIP-1559 transaction fields maxPriorityFeePerGas (maximum priority fee willing to pay), and maxFeePerGas (max total fee willing to pay, inclusive of priority and base fee). maxFeePerGas must be at least as high as the base fee to be included in a block. maxPriorityFeePerGas must not exceed maxFeePerGas.

Legacy, and EIP-2930 transaction field gasPrice (which also must be at least as high as the base fee for block inclusion) supplements base and priority fees (with less control). The extent to which gasPrice exceeds the base fee represents the implicit priority fee.

Transaction Execution

NotesEND

Cancun EVM

TLOAD, TSTORE: https://eips.ethereum.org/EIPS/eip-1153 Same stack arguments as SLOAD and SSTORE.

MCOPY: https://eips.ethereum.org/EIPS/eip-5656

BLOBHASH: https://eips.ethereum.org/EIPS/eip-4844

BLOBBASEFEE: https://eips.ethereum.org/EIPS/eip-7516

Gas

Opcodes can have associated constant and/or dynamic gas prices and (with rare exceptions) are checked prior to opcode execution.

such exceptions are?END

Appendix G defines tuples of constant gas fees and associated operations. Appendix H.1 concretely defines the gas cost function which covers all EVM instructions however further investigation per-opcode via Appendix H.2 (the EVM instruction set) is required to finally determine all associated gas fees for an opcode.

Section 9.2 outlines three circumstances where gas is payable:

  1. Intrinsic cost (usually constant, Appendices G, H.1).
  2. Subordinate message calls or contract creation (CREATE, CREATE2, CALL, CALLCODE).
  3. Increase in usage of memory.

(pg14 9.2) Opcodes which alter memory size pay gas according to the magnitude of memory modified in proportion to the smallest multiple of 32-bytes (i.e. WORD) required such that all indices (whether read or write) are included in said range. Essentially, any access to an area of memory 32-bytes greater than any previously indexed memory will incur a gas cost.

ROUGH: pg30 330: memory-expansion function M used to determine the new u_i size, some opcodes (e.g. MSTORE) have a specific function defined at their definition within H.2 for what u_i should be instead. Not all opcodes use M, or have their own inline u_i definition. pg29 328: memory-cost function C_mem simply computes the gas cost given memory size SOURCE?: Memory is byte-aligned (2^8) and not u256 aligned.

Datastructures

Opcodes, Gas cost, Stack deltas

An enum of opcodes tagged with a u8 provides constant time lookup, but how to associate gas cost and stack deltas without going crazy on the size of the datastructure.

Is a multiarraylist but keyed by an enum an option?

Zig

Datastructures

Enums

EnumMap

A map keyed by an enum, backed by a bitfield and a dense array. If the enum is exhaustive but not dense, a mapping will be constructed from enum values to dense indices. This type does no dynamic allocation and can be copied by value.

EnumArray

An array keyed by an enum, backed by a dense array. If the enum is not dense, a mapping will be constructed from enum values to dense indices. This type does no dynamic allocation and can be copied by value.

EnumMultiset

A multiset of enum elements up to a count of usize. Backed by an EnumArray. This type does no dynamic allocation and can be copied by value.

EnumSet

A set of enum elements, backed by a bitfield. If the enum is exhaustive but not dense, a mapping will be constructed from enum values to dense indices. This type does no dynamic allocation and can be copied by value.

BoundedEnumMultiset

A multiset of enum elements up to CountSize. Backed by an EnumArray. This type does no dynamic allocation and can be copied by value.

Tracing

Zone Naming and Statistics

Calling Tracy as follows:

fn someFunction() {
    const zone = tracy.initZone(@src(), .{ .name = "foobar" });
}

Will compute statistics for a zone named foobar as expected. If calling Tracy like this however:

fn someFunction() {
    const zone = tracy.initZone(@src(), .{});
    zone.name("foobar");
}

Then the zone will be doubly-named as someFunction (from its enclosing scope) and foobar however statistics will only be computed under the someFunction name. This isn’t important in this simple example but imagine now a parameter is given to set the zone name:

fn someFunction(name: []const u8) {
    const zone = tracy.initZone(@src(), .{});
    zone.name(name);
}

This will result in zones named as expected but no statistics will be computed for each name, they will all be under (statistically) the someFunction moniker. This can be beneficial in some scenarios, if statistics per name are desired Tracy must be called as:

fn someFunction(name: []const u8) {
   const zone = tracy.initZone(@src(), .{ .name = name });
}

Building

Zig Build Modes

Docs: https://ziglang.org/documentation/0.14.0/#toc-Build-Mode

ModeOptimiseSafetyRuntime Sp.Repro.Bin Size
DebugOffOnSlowNoLarge
ReleaseFastOnOffFastYesLarge
ReleaseSafeOnOnMediumYesLarge
ReleaseSmallOn (size)OffMediumYesSmall

Zig Build System

Docs: https://ziglang.org/documentation/0.14.0/#Zig-Build-System Docs: https://ziglang.org/learn/build-system/

Zig 0.14.0 Update & Notes

It currently does run correctly, but things like GPA being renamed and ArrayLists being unmanaged by default now and the like need to be accounted for.

Release notes: https://ziglang.org/download/0.14.0/release-notes.html

Misc

Deprecation list: https://ziglang.org/download/0.14.0/release-notes.html#List-of-Deprecations

Language

Labelled Switch

https://ziglang.org/download/0.14.0/release-notes.html#Labeled-Switch

Already in-use, some central notes though:

  • switch statement can be labeled, continue within such statements takes single operand which is treated as replacement for enclosing switch expressions operand thus explicitly stating the next prong to execute.
  • Can break from labeled switch which terminates its evaluation causing it to result in the given value to break. The break must be given the switch’s label to target it similarly to breaking out of blocks.
  • Labeled switches are not implicitly evaluated at comptime but such can be forced with the comptime keyword.
  • Semantically equivalent to switch inside a loop where a variable tracks switch operand and said variable is modified in each prong to control the subsequent prong to be executed.

Labeled switch designed to improve code-generation for hot loops such as those which dispatch instructions.

If operand to continue is comptime-known it is translated to an unconditional branch; this is a “perfectly predicted” branch and is very fast.

If operand to continue is runtime-known each continue can become a seperate conditional branch (ideally via shared jump table) back to the same set of conditional branch targets. This aids the CPU branch predictor by associating different branch instructions and their prediction data.

Zig’s tokeniser is 13% faster with labeled switches: ziglang/zig#21367

How to check and force that the jump table is shared for labeled switch runtime-known conditional branches?

Is the only implication of it NOT being shared that the binary size is larger due to duplicated jump tables? It should still be just as fast since it’s the same jump table data-wise no?

Decl Literals

https://ziglang.org/download/0.14.0/release-notes.html#Decl-Literals

READ NEXT AFTER TODOs CREATED.

@export Operand Pointer

https://ziglang.org/download/0.14.0/release-notes.html#export-Operand-is-Now-a-Pointer

@branchHint Replaces @setCold

https://ziglang.org/download/0.14.0/release-notes.html#New-branchHint-Builtin-Replacing-setCold

Remove Anonymous Struct Types, Unify Tuples

https://ziglang.org/download/0.14.0/release-notes.html#Remove-Anonymous-Struct-Types-Unify-Tuples

@FieldType Builtin

https://ziglang.org/download/0.14.0/release-notes.html#FieldType-builtin

Similar to std.meta.FieldType, give a type and the name of one of it’s fields and get back the type of that field.

@memcpy Rules Adjusted

https://ziglang.org/download/0.14.0/release-notes.html#memcpy-Rules-Adjusted

Standard Library

GeneralPurposeAllocator is now DebugAllocator

https://ziglang.org/download/0.14.0/release-notes.html#DebugAllocator

GeneralPurposeAllocator used to rely on compile-time known page size (now removed as nonsensical). Now rewritten to make fewer active mappings and have better performance it is also renamed DebugAllocator.

Note: initialise with .init declaration literal and not .{} now.

SmpAllocator

https://ziglang.org/download/0.14.0/release-notes.html#SmpAllocator

Allocator API

https://ziglang.org/download/0.14.0/release-notes.html#Allocator-API-Changes-remap

Zon Parsing

https://ziglang.org/download/0.14.0/release-notes.html#ZON-Parsing-and-Serialization

Runtime Page Size

https://ziglang.org/download/0.14.0/release-notes.html#Runtime-Page-Size

process.Child.collectOutput API

https://ziglang.org/download/0.14.0/release-notes.html#processChildcollectOutput-API-Changed

LLVM Builder API

https://ziglang.org/download/0.14.0/release-notes.html#LLVM-Builder-API

Zig’s LLVM bitcode builder is now available at std.zig.llvm. Note that everything in the std.zig namespace is an implementation detail of the Zig compiler and isn’t subject to the same API stability and deprecation norms as the rest of std.

Unmanaged Containers

https://ziglang.org/download/0.14.0/release-notes.html#Embracing-Unmanaged-Style-Containers

  • Managed container types (which internally associate an allocator for their lifetime) are deprecated and will be removed in the next Zig version (0.15.0).
  • Unmanaged container types are now the norm and require passing (the same) allocator at every callsite where such a method requires it.
  • Zig stdlib ArrayHashMapWithAllocator happens to have an implementation of a “traditional” managed-style approach which (I think) is intended for the future. Unsure if that will also be discouraged / deprecated in 0.15.0 (as in, within stdlib itself). As users we’re free to create our own managed-style approaches.

Better Binary Search API

ziglang/zig#20927

For: std.sort.binarySort, std.sort.lowerBound, std.sort.upperBound, and std.sort.equalRange.

std.hash_map Rehash Method

https://ziglang.org/download/0.14.0/release-notes.html#stdhash_map-gains-a-rehash-method

Currently unordered hash maps become slow when items are removed from them, in future Zig versions this will be fixed.

Array hash maps are free of this flaw.

Build System

https://ziglang.org/download/0.14.0/release-notes.html#Build-System https://ziglang.org/learn/build-system/

READ THIS ONE WHEN DONE MAKING TODOs:

  • File System Watching
  • New Package Hash Format
  • WriteFile Step
  • RemoveDir Step
  • Fmt Step

Creating Artifacts from Existing Modules

https://ziglang.org/download/0.14.0/release-notes.html#Creating-Artifacts-from-Existing-Modules

Compile steps can be created from existing std.Build.Module objects. Easier to re-use now, e.g. a module which is a dependency of another can more easily have a test step created for it.

New APIs change usage of addExecutable, addTest etc. No longer pass root_source_file, target, optimize (etc) directly but a *std.Build.Module to the root_module field with said module taking aforementioned options instead.

Allow Packages to Expose Arbitrary LazyPaths by Name

addLibrary Function

https://ziglang.org/download/0.14.0/release-notes.html#addLibrary-Function

addLibrary replaces addSharedLibrary and addStaticLibrary.

Compiler

https://ziglang.org/download/0.14.0/release-notes.html#Compiler

  • Comptime import ZON.
  • tokenizer: simplification and spec conformance

Linker

https://ziglang.org/download/0.14.0/release-notes.html#Linker

Fuzzer

https://ziglang.org/download/0.14.0/release-notes.html#Fuzzer

UBSan Runtime

https://ziglang.org/download/0.14.0/release-notes.html#UBSan-Runtime

Maybe (if things like tracy or valgrind for whatever reason aren’t good enough, which I doubt) how UBSan modifies things at compile time could be an approach for instrumentation etc etc. Again, doubt it since tracy/valgrind.

Misc TODOs

ArrayHashMapWithAllocator inspiration potential custom wrapper type

  • State “TODO” from [2025-09-05 Fri 03:28]
    Prior comment on EVM.mem

Zig 0.14.0 deprecates managed container types. Unmanaged container types must pass the same allocator at the callsite for methods which require it and do so every time. Perhaps create a wrapper (or appropriate custom type) later on to ease this (potential) burden. Zig std ArrayHashMapWithAllocator is an example of such.

Look at using the Writer API style for things like output

  • State “TODO” from [2025-08-12 Tue 19:11]

Can have a reader/writer and write into it (doesn’t have to be stdout) but any data structure I think. This could be a nice pattern to investigate using later.

Scoped logging, custom logger

  • State “TODO” from [2025-08-12 Tue 19:42]

See test runners for an example API with the writing and in terms of logging scope the following resources:

Unbreak CI from types changes in commit: 3375a031342a3b19e80dc25b66ceeacb1827b7fc

  • State “DONE” from “TODO” [2025-08-12 Tue 19:12]

Update to Zig 0.14.1

  • State “DONE” from “TODO” [2025-08-24 Sun 18:17]

Would keccak_p.zig benefit from the labelled switch api changes?

See: https://ziglang.org/documentation/master/std/#src/std/crypto/keccak_p.zig

The State function loops over some enums, that to function could use a labelled switch instead?

Any of that snapshot testing for everyone from tigerbeetle appropriate for our opcode unit tests later on?

See: https://tigerbeetle.com/blog/2024-05-14-snapshot-testing-for-the-masses/

Add custom EvmError errors and use those instead

Perhaps as a tagged enum? I forgot the proper term for this, have to double check notes. Either way want to replace the implicit error return of EVM.execute() from !void to somethin explicit.

Maybe a less verbose and/or more detailed tracing guide in zevem README

It’s fine for now probably.

Perhaps bench the old decodeOp before the change to log opcode via tracy

Yeah some overhead is added but how much idk, use poop or something to retroactively do this. Circa 2025-04-01 is when change to decodeOp occured (with tracy addition and so on).

Add a just recipe for andrewrk’s basic zig benchmark tool

It’s called poop or something, get a recipe for that and execute it to start basic benchmarking shit.

Have a look at Zig’s source code for labelled switch usage

As part of adding tracy have a look at any non-trivial ways Zig’s own source is using labelled switches, mostly I’m curious about putting things like stack variable checks in what is currently decodeOp which is run as part of (almost) every continue statement. In that sense it functions similarly to the top of a while loop which is followed by a switch statement, except our usage of a labelled switch here keeps cpu branch predictability performance gains.

Finish Jam script

It’s fine for now, mostly a skeleton and should probably symlink to a central one for sharing and/or make it a little CLI tool for easier consumption. We’ll see.

Custom error added on POP instruction, but do we want such errors?

Do we expect that any bytecode given to us is free from such errors and simply crash hard if encountered or do we surface those to the host? The compiled code is already going to check since Zig by default provides that orelse unreachable if we don’t specify anything. This could be a compile option (our custom errors) if there is in-fact any overhead and if in-fact we want to continue down that path.

Another thing to note is that.. what makes POP so special? What about DUP now.. what about every single other opcode? I think for now I may remove the POP custom error logic because it feels like the compiler that is feeding us bytecode, or the adept user who is handwriting such, should be responsible for that.

Things like trying to expand memory and that being an error we do surface (RETURN/REVERT) because that’s our job as the VM – thus, a difference in semantics I suppose.

Comptime test generation for opcodes?

E.g. generate tests for all of the N-style opcodes PUSH-N, DUP-N etc. Doesn’t really feel worth it versus literally writing them.

Test cases described in Zon?

Maybe something like:

.{
    // .bc for bytecode, .s for stack .s.l stack length, .s.i stack items from top etc.
    .bc = "5f600a8100",
    .s = .{
        .l = 0,
        .i = .{ 0, 0xa }
    }
}

Containerfile appropriate for Linux hosts too

All the uid mapping shit probably not required on Linux hosts since it’s not going macOS <==> Linux-VM <==> container with the macOS uid/gid being the ones we want to maintain.

Maybe change to using Just for project commands

Problem is when you want to do a lot of shell-stuff Just executes each line of the recipe in it’s own shell so if you have variables, or need the output of a prior command you need to have a recipe that is basically a heredoc shell script by adding #!/usr/bin/env bash to it.. at that point I’d rather just use a shell script directly.

Fuzzing with AFL++

Haven’t looked into fuzzing approaches yet; just found this while browsing other Zig things and it could be beneficial later: https://github.com/AFLplusplus/AFLplusplus and for Zig: https://github.com/kristoff-it/zig-afl-kit?tab=readme-ov-file

Ziggy on-disk test cases for bytecode and what not

  • State “TODO” from [2025-08-15 Fri 16:50]

Instead of evmBasicBytecode or most manual literal tests in source, perhaps replace them with test files on-disk which are read to execute EVM instructions and then the unit test in Zig code is about asserting expected values.

This feels like more of an experiment since the value in doing so is perhaps dubious versus in-source tests. Have to investigate. Not very important.

Columnar disassembly output hacking

  • State “TODO” from [2025-08-30 Sat 17:45]

Could do this to get nice auto-column aligned output wihtout having to write too much custom stuff.

0:0021(33)   60 PUSH1   gas=(3, 0, 78994)
0:0023(35)   7f PUSH32  gas=(3, 0, 78991)

printf '%s\n' $'0:0021(33)|60 PUSH1|gas=(3, 0, 78994)\n0:0023(35)|7f PUSH32|gas=(3, 0, 78991)\n0 -> left=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' | column -t -s '|'


                  0 -> left=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff


printf '%s\n' $'0:0021(33)|60|PUSH1   gas=(3, 0, 78994)\n0:0023(35)|7faa|PUSH32  gas=(3, 0, 78991)\n| | |0 -> left=ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff' | column -t -s '|'

Old project-todo.org file contents dumped within

  • Tramp using which instead of looping to find commands (as container now has it?)
  • Tramp environment variables for container?
  • Tramp use workdir argument for podmancp (make my own external method since a lot of customiation wanted here).
  • Tramp gpg-agent
  • Tramp git config
  • Tramp magit signed commits and authenticated git remotes
  • Tramp per container history file (i.e. don’t clobber general, global history file)
  • Additionally, tramp history in its own history file to better distinguish user commands vs tramps?
  • Tramp homedir for jam stuff, have it use a default username etc.
  • What is this, looking for git repo? Stop it going up and up and up? seems to be when tramp runs `tramp_bundle_read_file_names` i.e. tramp-send-command (6) tramp_bundle_read_file_names

( (”home/jammy/project/build.zig” t t nil) (“/home/jammy/project.git” t t t) (”home/jammy” t t t) (“/home/jammy.git” nil nil nil) (“/.git” nil nil nil) )

echo “(” while read file; do quoted=`echo “$file” | sed -e “s/"\\\\"”` printf “(%b” “"$quoted"” if test -e “$file”; then printf ” %b” t; else printf ” %b” nil; fi if test -r “$file”; then printf ” %b” t; else printf ” %b” nil; fi if test -d “$file”; then printf ” %b) ” t; else printf ” %b) ” nil; fi done echo “)” } 2>/dev/null; echo tramp_exit_status $?

so with tramp_bundle_read_file_names is vc.el asking it to check those paths? Cos it looks like the tramp command is GIVEN the paths home/jammy/project/build.zig and /home/jammy/project.git and home/jammy and /home/jammy.git and /.git but what is giving it those paths in the first place?

purpose of LOGNAME env var?

git –no-pager ls-files -c -z – build.zig

Emacs environment replacement, what is $d used for after a remote connection has been established?

Better function for tramp_bundle_read_file_names called by tramp-maybe-send-script

tramp-maybe-open-connection # Setup connection for tramp-open-shell # Opening remote shell tramp-open-connection-setup-interactive-shell # Setting up remote shell environment and # Setting default environment

Stretch goal:

  • Email tramp-devel and suggest using printf instead of echo, and suggest using $() instead of “ syntax.

perl script completions, find out what these tuples are. The script it sends for tramp-send-command #tramp_perl_file_name_all_completions /home/jammy example output is: ( (“./” ”home/jammy.” t t t) (“../” ”home/jammy..” t t t) (“.bash_history” ”home/jammy.bash_history” nil t t) (“.bashrc” ”home/jammy.bashrc” nil t t) (“.bash_profile” ”home/jammy.bash_profile” nil t t) (“project/” ”home/jammy/project” t t t) (“.bash_logout” “/home/jammy.bash_logout” nil t t) )

and the script is: \perl -e ’ $dir = $ARGV[0]; if ($dir ne “/”) { $dir =~ s#/+$##; } opendir(d, $dir) || die(“$dir: $!\nfail\n”); @files = readdir(d); closedir(d); print “(\n”; foreach $f (@files) { ($p = $f) =~ s/"\"/g; ($q = “$dir/$f”) =~ s"/\"/g; print “(“, ((-d “$q”) ? “"$p/" "$q" t” : “"$p" "$q" nil”), ((-e “$q”) ? ” t” : ” nil”), ((-r “$q”) ? ” t” : ” nil”), “)\n”; } print “)\n”; ’ “$1” 2>/dev/null } 2>/dev/null; echo tramp_exit_status $?

18:52:25.142228 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager ls-tree –name-only -z HEAD – project-todo.org </dev/null 2>/dev/null; echo tramp_exit_status $? )

What is `uncompface` that it tries to execute? lone `nil` text in Messages and vc refresh error, the tramp logs for these lines in Messages: File is missing: podmancp:jammy@jam-zevem:/home/jammy/project.gitmodules nil

Tramp: Inserting ‘/podmancp:jammy@jam-zevem:/home/jammy/project/project-todo.org’…done End of file during parsing: End of file during parsing,

VC refresh error: (end-of-file “”)

Tramp: Checking ‘vc-registered’ for /podmancp:jammy@jam-zevem:/home/jammy/project/project-todo.org…done

Appear to be: 18:07:54.913758 tramp-send-command (6) # tramp_bundle_read_file_names <<’e7381d37826e413f7338377bdf35cb06’ 2>/dev/null; echo tramp_exit_status $? home/jammy/project/build.zig /home/jammy/project.git home/jammy /home/jammy.git /.git e7381d37826e413f7338377bdf35cb06 18:07:54.974272 tramp-wait-for-regexp (6) # ( (”home/jammy/project/build.zig” t t nil) (“/home/jammy/project.git” t t t) (”home/jammy” t t t) (“/home/jammy.git” nil nil nil) (“/.git” nil nil nil) ) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:54.976193 tramp-send-command (6) # test -d /home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:07:54.977196 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:54.977565 tramp-send-command (6) # test -r home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:07:54.978462 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:54.979600 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager ls-files -c -z – build.zig </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:07:54.986324 tramp-wait-for-regexp (6) # build.zigtramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:54.987902 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager status –porcelain -z –untracked-files –ignored – build.zig </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:07:54.999060 tramp-wait-for-regexp (6) # M build.zigtramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:54.999826 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager rev-parse HEAD </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:07:55.007882 tramp-wait-for-regexp (6) # 47266d8c0325949983854befec584523792ca0ff tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:55.008593 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager symbolic-ref HEAD </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:07:55.016174 tramp-wait-for-regexp (6) # refs/heads/master tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ —FOR JORDAN: Why is tramp sending this command, why is `nil` not captured by TRAMP? –It wants to know if home/jammy/project is a symbolic link, but why? 18:07:57.201283 tramp-send-command (6) # (if test -h “/home/jammy/project”; then echo t; else echo nil; fi) && \readlink –canonicalize-missing home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:07:57.221485 tramp-wait-for-regexp (6) # nil /home/jammy/project tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:57.222096 tramp-do-file-attributes-with-stat (5) # file attributes with stat: home/jammy/project 18:07:57.222283 tramp-send-command (6) # tramp_stat_file_attributes home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:07:57.244174 tramp-wait-for-regexp (6) # ((“‘/home/jammy/project/’”) 18 (“jammy” . 501) (“nobody” . 65534) 1737190886 1737190886 1737190886 576 “drwxr-xr-x” t 14741195 -1) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ –FOR JORDAN: Why is tramp trying to insert .gitmodules, is this vc.el doing weirdo shit or something? 18:07:57.306162 tramp-handle-insert-file-contents (3) # Inserting ‘/podmancp:jammy@jam-zevem:/home/jammy/project/.gitmodules’… 18:07:57.310576 tramp-send-command (6) # (if test -h ”home/jammy/project.gitmodules”; then echo t; else echo nil; fi) && \readlink –canonicalize-missing home/jammy/project.gitmodules 2>/dev/null; echo tramp_exit_status $? 18:07:57.322958 tramp-wait-for-regexp (6) # nil home/jammy/project.gitmodules tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:57.323568 tramp-do-file-attributes-with-stat (5) # file attributes with stat: home/jammy/project.gitmodules 18:07:57.323693 tramp-send-command (6) # tramp_stat_file_attributes home/jammy/project.gitmodules 2>/dev/null; echo tramp_exit_status $? 18:07:57.342970 tramp-wait-for-regexp (6) # nil tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:57.343297 tramp-sh-handle-file-local-copy (1) # error: “” nil 18:07:57.343574 tramp-sh-handle-file-local-copy (1) # File is missing: podmancp:jammy@jam-zevem:/home/jammy/project.gitmodules nil 18:07:57.343654 tramp-handle-insert-file-contents (3) # Inserting ‘/podmancp:jammy@jam-zevem:/home/jammy/project/.gitmodules’…failed 18:07:57.346150 tramp-handle-insert-file-contents (1) # File is missing: podmancp:jammy@jam-zevem:/home/jammy/project.gitmodules nil 18:07:57.354952 tramp-handle-insert-file-contents (1) # File is missing: podmancp:jammy@jam-zevem:/home/jammy/project.gitmodules nil 18:07:57.356977 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre LC_MESSAGES\=C git –no-pager ls-files -z -c –exclude-standard –sparse -o </dev/null; echo tramp_exit_status $? ) 18:07:57.392766 tramp-wait-for-regexp (6) # ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:59.917603 tramp-send-command (6) # tramp_bundle_read_file_names <<’e7381d37826e413f7338377bdf35cb06’ 2>/dev/null; echo tramp_exit_status $? home/jammy/project/build.zig /home/jammy/project.git home/jammy /home/jammy.git /.git e7381d37826e413f7338377bdf35cb06 18:07:59.970888 tramp-wait-for-regexp (6) # ( (”home/jammy/project/build.zig” t t nil) (“/home/jammy/project.git” t t t) (”home/jammy” t t t) (“/home/jammy.git” nil nil nil) (“/.git” nil nil nil) ) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:59.972690 tramp-send-command (6) # test -d /home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:07:59.973805 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:59.974197 tramp-send-command (6) # test -r home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:07:59.975137 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:59.976377 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager ls-files -c -z – build.zig </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:07:59.984180 tramp-wait-for-regexp (6) # build.zigtramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:59.985826 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager status –porcelain -z –untracked-files –ignored – build.zig </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:07:59.996906 tramp-wait-for-regexp (6) # M build.zigtramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:07:59.997682 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager rev-parse HEAD </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:08:00.005694 tramp-wait-for-regexp (6) # 47266d8c0325949983854befec584523792ca0ff tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:00.006383 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 GIT_OPTIONAL_LOCKS\=0 git –no-pager symbolic-ref HEAD </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:08:00.013911 tramp-wait-for-regexp (6) # refs/heads/master tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:03.931978 tramp-send-command (6) # test -d /home/jammy/project/project-todo.org 2>/dev/null; echo tramp_exit_status $? 18:08:03.939407 tramp-wait-for-regexp (6) # tramp_exit_status 1 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:03.940345 tramp-send-command (6) # (if test -h “/home/jammy/project/project-todo.org”; then echo t; else echo nil; fi) && \readlink –canonicalize-missing /home/jammy/project/project-todo.org 2>/dev/null; echo tramp_exit_status $? 18:08:03.956192 tramp-wait-for-regexp (6) # nil /home/jammy/project/project-todo.org tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:03.956991 tramp-do-file-attributes-with-stat (5) # file attributes with stat: /home/jammy/project/project-todo.org 18:08:03.957199 tramp-send-command (6) # tramp_stat_file_attributes /home/jammy/project/project-todo.org 2>/dev/null; echo tramp_exit_status $? 18:08:03.975846 tramp-wait-for-regexp (6) # ((“‘/home/jammy/project/project-todo.org’”) 1 (“jammy” . 501) (“nobody” . 65534) 1734160437 1734160437 1734160437 0 “-rw-r–r–” t 14753690 -1) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:03.977813 tramp-handle-insert-file-contents (3) # Inserting ‘/podmancp:jammy@jam-zevem:/home/jammy/project/project-todo.org’… 18:08:03.981640 tramp-handle-insert-file-contents (3) # Inserting ‘/podmancp:jammy@jam-zevem:/home/jammy/project/project-todo.org’…done 18:08:03.982978 tramp-do-file-attributes-with-stat (5) # file attributes with stat: /home/jammy/project/project-todo.org 18:08:03.983119 tramp-send-command (6) # tramp_stat_file_attributes /home/jammy/project/project-todo.org 2>/dev/null; echo tramp_exit_status $? 18:08:03.996119 tramp-wait-for-regexp (6) # ((“‘/home/jammy/project/project-todo.org’”) 1 (“jammy” . 501) (“nobody” . 65534) 1734160437 1734160437 1734160437 0 “-rw-r–r–” t 14753690 -1) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:04.779999 tramp-send-command (6) # ( cd home/jammy/project && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre /bin/sh -c uncompface </dev/null; echo tramp_exit_status $? ) 18:08:04.800194 tramp-wait-for-regexp (6) # /bin/sh: line 1: uncompface: command not found tramp_exit_status 127 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:04.929145 tramp-send-command (6) # test -e /home/jammy/project/project-todo.org 2>/dev/null; echo tramp_exit_status $? 18:08:04.930612 tramp-send-command (6) # tramp_bundle_read_file_names &lt;&lt;’e7381d37826e413f7338377bdf35cb06’ 2&gt;/dev/null; echo tramp_exit_status $? home/jammy/project/build.zig /home/jammy/project.git home/jammy /home/jammy.git /.git e7381d37826e413f7338377bdf35cb06 18:08:04.930967 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:04.931090 tramp-bundle-read-file-names (1) # End of file during parsing: End of file during parsing, 18:08:04.976428 tramp-wait-for-regexp (6) # ( (”home/jammy/project/build.zig” t t nil) (“/home/jammy/project.git” t t t) (”home/jammy” t t t) (“/home/jammy.git” nil nil nil) (“/.git” nil nil nil) ) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:04.976882 tramp-do-file-attributes-with-stat (5) # file attributes with stat: /home/jammy/project/project-todo.org 18:08:04.977042 tramp-send-command (6) # tramp_stat_file_attributes /home/jammy/project/project-todo.org 2>/dev/null; echo tramp_exit_status $? 18:08:04.986392 tramp-wait-for-regexp (6) # ((“‘/home/jammy/project/project-todo.org’”) 1 (“jammy” . 501) (“nobody” . 65534) 1734160437 1734160437 1734160437 0 “-rw-r–r–” t 14753690 -1) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:04.999333 tramp-sh-handle-vc-registered (3) # Checking ‘vc-registered’ for /podmancp:jammy@jam-zevem:/home/jammy/project/project-todo.org… 18:08:05.005068 tramp-send-command (6) # tramp_bundle_read_file_names <<’e7381d37826e413f7338377bdf35cb06’ 2>/dev/null; echo tramp_exit_status $? home/jammy/project/project-todo.org /home/jammy/project.git home/jammy /home/jammy.git /.git e7381d37826e413f7338377bdf35cb06 18:08:05.031867 tramp-wait-for-regexp (6) # ( (”home/jammy/project/project-todo.org” t t nil) (“/home/jammy/project.git” t t t) (”home/jammy” t t t) (“/home/jammy.git” nil nil nil) (“/.git” nil nil nil) ) tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:05.033491 tramp-send-command (6) # test -d /home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:08:05.034439 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:05.034724 tramp-send-command (6) # test -r home/jammy/project 2>/dev/null; echo tramp_exit_status $? 18:08:05.035616 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:05.036587 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 git –no-pager ls-files -c -z – project-todo.org </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:08:05.043148 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:05.043795 tramp-send-command (6) # ( cd home/jammy/project && unset GIT_DIR && env INSIDE_EMACS\=31.0.50\,tramp\:2.8.0-pre GIT_LITERAL_PATHSPECS\=1 git –no-pager ls-tree –name-only -z HEAD – project-todo.org </dev/null 2>/dev/null; echo tramp_exit_status $? ) 18:08:05.054050 tramp-wait-for-regexp (6) # tramp_exit_status 0 ///94b4655c39f14eb594acd8c8e974e8cd#$ 18:08:05.054335 tramp-sh-handle-vc-registered (3) # Checking ‘vc-registered’ for /podmancp:jammy@jam-zevem:/home/jammy/project/project-todo.org…done – END

------ONE 2% - vc-working-revision 56 2% - vc-call-backend 56 2% - vc-git-working-revision 56 2% - vc-git–rev-parse 56 2% - vc-git–out-ok 56 2% - vc-git–call 56 2% - process-file 56 2% - tramp-file-name-handler 56 2% - apply 56 2% - tramp-sh-file-name-handler 56 2% - tramp-sh-handle-process-file 55 2% - tramp-send-command-and-check 55 2% - tramp-send-command 51 2% - tramp-wait-for-output 51 2% - tramp-wait-for-regexp 31 1% - tramp-accept-process-output 31 1% accept-process-output 20 0% sit-for 4 0% - tramp-message 4 0% - apply 4 0% - tramp-debug-message 4 0% write-region 1 0% - expand-file-name 1 0% - tramp-file-name-handler 1 0% - apply 1 0% - tramp-sh-file-name-handler 1 0% - tramp-sh-handle-expand-file-name 1 0% - tramp-drop-volume-letter 1 0% - replace-regexp-in-string 1 0% concat 1 ------/

-----TWO

  • vc-mode-line 52 2% - vc-call-backend 52 2% - vc-git-mode-line-string 52 2% - vc-git–symbolic-ref 52 2% - vc-git–run-command-string 51 2% - vc-git–out-ok 51 2% - vc-git–call 51 2% - process-file 51 2% - tramp-file-name-handler 51 2% - apply 51 2% - tramp-sh-file-name-handler 51 2% - tramp-sh-handle-process-file 51 2% - tramp-send-command-and-check 49 2% - tramp-send-command 45 2% - tramp-wait-for-output 45 2% - tramp-wait-for-regexp 28 1% - tramp-accept-process-output 28 1% accept-process-output 14 0% sit-for 3 0% - tramp-message 3 0% - apply 3 0% - tramp-debug-message 3 0% write-region 4 0% - tramp-message 4 0% - apply 4 0% - tramp-debug-message 4 0% write-region 1 0%

------/

------THREE

  • vc-call-backend 85 4% - vc-git-find-file-hook 85 4% - vc-state 85 4% - vc-state-refresh 85 4% - vc-call-backend 85 4% - vc-git-state 85 4% - vc-git–run-command-string 81 3% - vc-git–out-ok 81 3% - vc-git–call 81 3% - process-file 81 3% - tramp-file-name-handler 81 3% - apply 81 3% - tramp-sh-file-name-handler 81 3% - tramp-sh-handle-process-file 81 3% - tramp-send-command-and-check 81 3% - tramp-send-command 79 3% - tramp-wait-for-output 79 3% - tramp-wait-for-regexp 54 2% - tramp-accept-process-output 54 2% - accept-process-output 1 0% syntax-ppss-flush-cache 25 1% sit-for 2 0% - tramp-message 2 0% - apply 2 0% - tramp-debug-message 2 0%

-----/

-----FOUR

  • tramp-run-real-handler

179 8% - vc-registered 177 8% - mapc 177 8% - #<byte-code-function 6D0> 177 8% - vc-call-backend 177 8% - vc-git-registered 144 7% - vc-git–out-ok 144 7% - vc-git–call 144 7% - process-file 144 7% - tramp-file-name-handler 144 7% - apply 144 7% - tramp-sh-file-name-handler 144 7% - tramp-sh-handle-process-file 143 6% - tramp-send-command-and-check 143 6% - tramp-send-command 134 6% - tramp-wait-for-output 134 6% - tramp-wait-for-regexp 71 3% - tramp-accept-process-output 71 3% accept-process-output 60 2% sit-for 2 0% - tramp-message 2 0% - apply 2 0% - tramp-debug-message 2 0% write-region 1 0% - tramp-check-for-regexp 1 0% tramp-search-regexp 9 0% - tramp-message 9 0% - apply 9 0% - tramp-debug-message 6 0% write-region 2 0% whitespace–update-bob-eob 1 0% - tramp-get-debug-buffer 1 0% - tramp-debug-buffer-name 1 0% --------/

------FIVE

  • timer-event-handler 793 38% - apply 791 38% - auto-revert-buffers 791 38% - apply 791 38% - auto-revert-buffers@buffer-list-filter 791 38% - if 791 38% - funcall 791 38% - #<native-comp-function auto-revert-buffers> 784 38% - auto-revert-buffer 784 38% - auto-revert-handler 784 38% - vc-refresh-state 647 31% - vc-backend 646 31% - vc-registered 642 31% - tramp-file-name-handler 642 31% - apply 642 31% - tramp-sh-file-name-handler 642 31% - tramp-sh-handle-vc-registered 463 22% - tramp-bundle-read-file-names 463 22% - tramp-send-command-and-check 463 22% - tramp-send-command 454 22% - tramp-wait-for-output 454 22% - tramp-wait-for-regexp 266 12% - tramp-accept-process-output 261 12% accept-process-output 2 0% - tramp-get-connection-property 1 0% tramp-file-name-unify 1 0% - #<byte-code-function EF0> 1 0% - tramp-flush-connection-property 1 0% tramp-get-hash-table 182 8% sit-for 5 0% - tramp-check-for-regexp 5 0% tramp-search-regexp 1 0% - tramp-message 1 0% - apply 1 0% - tramp-debug-message 1 0% write-region 8 0% - tramp-message 8 0% - apply 8 0% - tramp-debug-message 7 0% - write-region 5 0% - select-safe-coding-system 5 0% - find-auto-coding 5 0% auto-coding-alist-lookup 1 0% - tramp-maybe-open-connection 1 0% - tramp-get-connection-process 1 0% - tramp-get-connection-name 1 0% - tramp-buffer-name 1 0% tramp-file-name-host-port 179 8%

---------/

tramp-list-connections tramp-compat-seq-keep apply fun to seq and return non-nil results fun: the lambda defined there seq: (hash-table-keys tramp-cache-data)

tramp-vc-registered-file-names