[DTrace-devel] [PATCH] Optimize dt_cg_store_val() for string values
Kris Van Hees
kris.van.hees at oracle.com
Mon Nov 15 17:31:12 UTC 2021
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_cg.c | 48 +++++++++++++----------------------------------
1 file changed, 13 insertions(+), 35 deletions(-)
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 455e5440..930355f8 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -958,9 +958,6 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
return 0;
} else if (dt_node_is_string(dnp)) {
- uint_t size_ok = dt_irlist_label(dlp);
- int reg;
-
dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
TRACE_REGSET("store_val(): Begin ");
@@ -968,49 +965,30 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
size + DT_STRLEN_BYTES + 1, 1, pfp, arg);
/*
- * Retrieve the length of the string, limit it to the maximum
- * string size, and store it in the buffer at [%r9 + off].
+ * Copy the length of the string from the source string as a
+ * half-word (2 bytes) into the buffer at [%r9 + off].
*/
- reg = dt_regset_alloc(drp);
- if (reg == -1)
- longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
- dt_cg_strlen(dlp, drp, reg, dnp->dn_reg);
- dt_regset_xalloc(drp, BPF_REG_0);
- emit(dlp, BPF_BRANCH_IMM(BPF_JLT, reg, size, size_ok));
- emit(dlp, BPF_MOV_IMM(reg, size));
- emitl(dlp, size_ok,
- BPF_MOV_REG(BPF_REG_0, reg));
- emit(dlp, BPF_ALU64_IMM(BPF_RSH, BPF_REG_0, 8));
- emit(dlp, BPF_STORE(BPF_B, BPF_REG_9, off, BPF_REG_0));
- emit(dlp, BPF_STORE(BPF_B, BPF_REG_9, off + 1, reg));
- dt_regset_free(drp, BPF_REG_0);
+ emit(dlp, BPF_LOAD(BPF_H, BPF_REG_0, dnp->dn_reg, 0));
+ emit(dlp, BPF_STORE(BPF_H, BPF_REG_9, off, BPF_REG_0));
/*
- * Copy the string to the output buffer at
- * [%r9 + off + DT_STRLEN_BYTES] because we need to skip the
- * length prefix.
+ * Copy the string data (no more than STRSIZE + 1 bytes) to the
+ * buffer at [%r9 + off + DT_STRLEN_BYTES]. We (ab)use the
+ * fact that probe_read_str) stops at the terminating NUL byte.
*/
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
- emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
- emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off + DT_STRLEN_BYTES));
- emit(dlp, BPF_MOV_REG(BPF_REG_2, reg));
- dt_regset_free(drp, reg);
- emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, BPF_REG_9));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_1, off + DT_STRLEN_BYTES));
+ emit(dlp, BPF_MOV_IMM(BPF_REG_2, size + 1));
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, dnp->dn_reg));
dt_regset_free(drp, dnp->dn_reg);
dt_cg_tstring_free(pcb, dnp);
- emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, DT_STRLEN_BYTES));
+ emit(dlp, BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, DT_STRLEN_BYTES));
dt_regset_xalloc(drp, BPF_REG_0);
- emit(dlp, BPF_CALL_HELPER(BPF_FUNC_probe_read));
+ emit(dlp, BPF_CALL_HELPER(BPF_FUNC_probe_read_str));
dt_regset_free_args(drp);
-
- /*
- * Write the NUL terminating byte.
- */
- emit(dlp, BPF_MOV_REG(BPF_REG_0, BPF_REG_9));
- emit(dlp, BPF_ALU64_REG(BPF_ADD, BPF_REG_0, reg));
- emit(dlp, BPF_STORE_IMM(BPF_B, BPF_REG_0, off + DT_STRLEN_BYTES, 0));
dt_regset_free(drp, BPF_REG_0);
TRACE_REGSET("store_val(): End ");
--
2.33.0
More information about the DTrace-devel
mailing list