| 70 | |
| 71 | |
| 72 | class LogTraceEventTransform(IRTransform): |
| 73 | def __init__(self, builder: LowLevelIRBuilder, fullname: str) -> None: |
| 74 | super().__init__(builder) |
| 75 | self.fullname = fullname.encode("utf-8") |
| 76 | |
| 77 | def visit_call(self, op: Call) -> Value: |
| 78 | # TODO: Use different op name when constructing an instance |
| 79 | return self.log(op, "call", op.fn.fullname) |
| 80 | |
| 81 | def visit_primitive_op(self, op: PrimitiveOp) -> Value: |
| 82 | value = self.log(op, "primitive_op", op.desc.name) |
| 83 | if op.desc.name in primitives_that_inc_ref: |
| 84 | self.log_inc_ref(value) |
| 85 | return value |
| 86 | |
| 87 | def visit_call_c(self, op: CallC) -> Value: |
| 88 | if global_name := get_load_global_name(op): |
| 89 | return self.log(op, "globals_dict_get_item", global_name) |
| 90 | |
| 91 | func_name = op.function_name |
| 92 | if func_name == "PyObject_Vectorcall" and isinstance(op.args[0], CallC): |
| 93 | if global_name := get_load_global_name(op.args[0]): |
| 94 | return self.log(op, "python_call_global", global_name) |
| 95 | elif func_name == "CPyObject_GetAttr" and isinstance(op.args[1], LoadLiteral): |
| 96 | return self.log(op, "python_get_attr", str(op.args[1].value)) |
| 97 | elif func_name == "PyObject_VectorcallMethod" and isinstance(op.args[0], LoadLiteral): |
| 98 | return self.log(op, "python_call_method", str(op.args[0].value)) |
| 99 | |
| 100 | value = self.log(op, "call_c", func_name) |
| 101 | if func_name in primitives_that_inc_ref: |
| 102 | self.log_inc_ref(value) |
| 103 | return value |
| 104 | |
| 105 | def visit_get_attr(self, op: GetAttr) -> Value: |
| 106 | value = self.log(op, "get_attr", f"{op.class_type.name}.{op.attr}") |
| 107 | if not op.is_borrowed and op.type.is_refcounted: |
| 108 | self.log_inc_ref(op) |
| 109 | return value |
| 110 | |
| 111 | def visit_set_attr(self, op: SetAttr) -> Value: |
| 112 | name = "set_attr" if not op.is_init else "set_attr_init" |
| 113 | return self.log(op, name, f"{op.class_type.name}.{op.attr}") |
| 114 | |
| 115 | def visit_box(self, op: Box) -> Value: |
| 116 | if op.src.type is none_rprimitive: |
| 117 | # Boxing 'None' is a very quick operation, so we don't log it. |
| 118 | return self.add(op) |
| 119 | else: |
| 120 | return self.log(op, "box", str(op.src.type)) |
| 121 | |
| 122 | def visit_unbox(self, op: Unbox) -> Value: |
| 123 | return self.log(op, "unbox", str(op.type)) |
| 124 | |
| 125 | def visit_cast(self, op: Cast) -> Value | None: |
| 126 | value = self.log(op, "cast", str(op.type)) |
| 127 | if not op.is_borrowed: |
| 128 | self.log_inc_ref(value) |
| 129 | return value |
no outgoing calls
no test coverage detected
searching dependent graphs…