# `nupp.profile.trace` Stable identities shared by static trace checking and the opt-in runtime collector. The recorder's strings are presentation, not API. A trace event is first interpreted under the exact VM profile that emitted it, then mapped to one of the identities here. Static checks use those same records, which is what keeps a bytecode finding, an `@jit` contract error and an observed abort from acquiring three explanations. ```nupp local trace = nupp.profile.trace local reason = trace.forOpcode("FNEW") print(reason.id, reason.repair) ``` See [LuaJIT trace checking](../../../../learn/performance/jit-trace-checking/index.html) for the static side of this, and `nupp.profile` for the collector that reports the runtime side. ## Types ### `Profile` _type_ ```nupp type trace.Profile = { id: string, luajitRevision: string, luajitVersion: integer, architecture: string, operatingSystem: string, enabledRecorderFeatures: {string}, bytecodeSchema: string, supported: boolean } ``` The recorder a trace event has to be interpreted under. Reasons are mapped from VM text and bytecode numbering, and both move between builds, so an event is only comparable to another taken under the same `id`. ### `Reason` _type_ ```nupp type trace.Reason = { id: string, class: 'blocker' | 'risk' | 'stop', opcodes: {[string]: boolean}?, source: {[string]: boolean}?, runtime: {string}?, explanation: string?, repair: string?, lint: string?, contractSeverity: string? } ``` One stable reason the JIT declined to record, however it was observed. `class` is what the reason is worth acting on: a `blocker` cannot record at all, a `risk` may or may not sit on a hot path, and a `stop` is trace formation working as designed. The three index fields are the routes to it, from a bytecode name, from a static finding, and from the VM's own runtime text. ## Functions ### `trace.forOpcode` _function_ ```nupp function trace.forOpcode(opcode: string): trace.Reason? ``` Answers the record for a bytecode LuaJIT has no recorder for. #### Arguments | Name | Type | Description | | --- | --- | --- | | `opcode` | `string` | the bytecode's name, as `opcodeName` renders it | #### Returns | Type | Description | | --- | --- | | `trace.Reason?` | the record, or nil when that bytecode records | ### `trace.forSource` _function_ ```nupp function trace.forSource(source: string): trace.Reason? ``` Answers the record a static finding maps to. This is what keeps a checker finding and an observed abort from explaining the same thing two different ways. #### Arguments | Name | Type | Description | | --- | --- | --- | | `source` | `string` | the static finding's name | #### Returns | Type | Description | | --- | --- | | `trace.Reason?` | the record, or nil when the finding has no runtime counterpart | ### `trace.opcodeName` _function_ ```nupp function trace.opcodeName(opcode: integer): string ``` Renders a bytecode number as the name LuaJIT knows it by. #### Arguments | Name | Type | Description | | --- | --- | --- | | `opcode` | `integer` | the number the VM reported | #### Returns | Type | Description | | --- | --- | | `string` | the trimmed name | ### `trace.profile` _function_ ```nupp function trace.profile(): trace.Profile ``` Describes the recorder this process is running. #### Returns | Type | Description | | --- | --- | | `trace.Profile` | the profile every event from this process is interpreted under | ### `trace.reason` _function_ ```nupp function trace.reason(id: string): trace.Reason? ``` Answers the record filed under one stable identity. #### Arguments | Name | Type | Description | | --- | --- | --- | | `id` | `string` | the identity, as a report or a diagnostic carries it | #### Returns | Type | Description | | --- | --- | | `trace.Reason?` | the record, or nil when nothing is filed under it | ### `trace.records` _function_ ```nupp function trace.records(): {trace.Reason} ``` Answers every record, in registry order. The list is a copy, so a caller sorting or filtering it cannot disturb the registry the checker reads. #### Returns | Type | Description | | --- | --- | | `{trace.Reason}` | one entry per known reason | ### `trace.runtime` _function_ ```nupp function trace.runtime(errorCode: integer?, errorArg: number | string | nil): trace.Reason, string ``` Interprets one raw abort the VM reported. An abort naming an unrecordable bytecode is routed by that opcode rather than by its text, so it lands on the same record a static check would have found. Anything unrecognized answers `jit/runtime-unknown` rather than nothing. #### Arguments | Name | Type | Description | | --- | --- | --- | | `errorCode` | `integer?` | the VM's trace error number, or nil | | `errorArg` | `number | string | nil` | whatever the VM passed beside it | #### Returns | Type | Description | | --- | --- | | `trace.Reason` | the record it maps to | | `string` | the rendered text, for display |