Skip to content

Lazily create code object co_code attribute. #85

Closed
@markshannon

Description

@markshannon

When code is quickened we have two copies of the bytecode instructions.

  1. code->co_code (a bytearray object)
  2. code->co_firstinstr (an array of instructions).

Apart from its length (which would be trivial to add to the code object), code->co_code can be reconstructed from code->co_firstinstr.

I propose changing the code object as follows:

Current:

    ...
    _Py_CODEUNIT *co_firstinstr;
    ...
    PyObject *co_code; /* Points to bytes object */
    ...
    union _cache_or_instruction *co_quickened;
}

Proposed:

    int code_length;
    ...
    /* Remove pointer to first instruction */
    ...
    PyObject *co_code; /* Initially NULL, lazily initialized */
    ...
    _Py_CODEUNIT co_instructions[1];
}

Apart from the obvious memory saving, this also allows us to streamline the interpreter a bit.

Pseudo code for generating co_code:

co_code = bytearray(len=co.code_length*2)
index = 0
for inst in co.co_instructions:
     opcode = OPCODE_TO_BASE_MAP[inst.opcode]
     if has_specialized_cache(inst.opcode):
           oparg = get_specialized_cache(inst).original_oparg
      elif has_oparg(inst.opcode):
           oparg = inst.oparg
      else:
           oparg = 0
      co_code[index] = opcode
      co_code[index+1] = oparg
      index += 1
return bytes(co_code)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions