Skip to content

Commit c5efd40

Browse files
committed
WIP
1 parent 8b48667 commit c5efd40

File tree

1 file changed

+51
-24
lines changed
  • dd-java-agent/instrumentation/jetty-common/src/main/java/datadog/trace/instrumentation/jetty9

1 file changed

+51
-24
lines changed

dd-java-agent/instrumentation/jetty-common/src/main/java/datadog/trace/instrumentation/jetty9/HandleVisitor.java

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
package datadog.trace.instrumentation.jetty9;
22

3+
import static java.lang.Math.max;
4+
import static net.bytebuddy.jar.asm.Opcodes.ALOAD;
5+
import static net.bytebuddy.jar.asm.Opcodes.ASTORE;
6+
import static net.bytebuddy.jar.asm.Opcodes.DUP;
7+
import static net.bytebuddy.jar.asm.Opcodes.F_SAME;
8+
import static net.bytebuddy.jar.asm.Opcodes.GOTO;
9+
import static net.bytebuddy.jar.asm.Opcodes.H_INVOKESTATIC;
10+
311
import datadog.context.Context;
412
import datadog.trace.api.gateway.Flow;
513
import datadog.trace.bootstrap.instrumentation.api.AgentSpan;
@@ -10,7 +18,6 @@
1018
import java.io.OutputStreamWriter;
1119
import java.util.ArrayList;
1220
import java.util.List;
13-
import java.util.function.Function;
1421
import net.bytebuddy.jar.asm.Handle;
1522
import net.bytebuddy.jar.asm.Label;
1623
import net.bytebuddy.jar.asm.MethodVisitor;
@@ -84,9 +91,13 @@
8491
*/
8592
public class HandleVisitor extends MethodVisitor {
8693
private static final Logger log = LoggerFactory.getLogger(HandleVisitor.class);
94+
private static final int CONTEXT_VAR = 100;
8795

96+
/** Whether the next store is supposed to store the Context variable. */
8897
private boolean lookForStore;
89-
private int contextVar = -1;
98+
/** Whether the Context variable was stored to local index {@link #CONTEXT_VAR}. */
99+
private boolean contextStored;
100+
/** Whether the handle() method injection was successful .*/
90101
private boolean success;
91102
private final String methodName;
92103

@@ -118,14 +129,22 @@ DelayCertainInsMethodVisitor delayVisitorDelegate() {
118129
return (DelayCertainInsMethodVisitor) this.mv;
119130
}
120131

132+
@Override
133+
public void visitLocalVariable(String name, String descriptor, String signature, Label start, Label end, int index) {
134+
if (contextStored && index == CONTEXT_VAR) {
135+
super.visitLocalVariable("context", Type.getDescriptor(Context.class), null, start, end, CONTEXT_VAR);
136+
}
137+
super.visitLocalVariable(name, descriptor, signature, start, end, index);
138+
}
139+
121140
@Override
122141
public void visitMethodInsn(
123142
int opcode, String owner, String name, String descriptor, boolean isInterface) {
124143
debug("visitMethodInsn");
125-
debug(">> contextVar: " + contextVar);
144+
debug(">> contextStored: " + contextStored);
126145
debug(">> success: " + success);
127146
debug(">> opcode: " + opcode + ", owner: " + owner + ", name: " + name + ", descriptor: " + descriptor);
128-
if (contextVar == -1) {
147+
if (!contextStored) {
129148
lookForStore =
130149
!lookForStore
131150
&& opcode == Opcodes.INVOKEVIRTUAL
@@ -159,21 +178,21 @@ public void visitMethodInsn(
159178
// Declare label to insert after Server.handle() call
160179
Label afterHandle = new Label();
161180
// Inject blocking helper call
162-
super.visitVarInsn(Opcodes.ALOAD, 0);
181+
super.visitVarInsn(ALOAD, 0);
163182
super.visitMethodInsn(
164183
Opcodes.INVOKEVIRTUAL,
165184
"org/eclipse/jetty/server/HttpChannel",
166185
"getRequest",
167186
"()Lorg/eclipse/jetty/server/Request;",
168187
false);
169-
super.visitVarInsn(Opcodes.ALOAD, 0);
188+
super.visitVarInsn(ALOAD, 0);
170189
super.visitMethodInsn(
171190
Opcodes.INVOKEVIRTUAL,
172191
"org/eclipse/jetty/server/HttpChannel",
173192
"getResponse",
174193
"()Lorg/eclipse/jetty/server/Response;",
175194
false);
176-
super.visitVarInsn(Opcodes.ALOAD, contextVar);
195+
super.visitVarInsn(ALOAD, CONTEXT_VAR);
177196
super.visitMethodInsn(
178197
Opcodes.INVOKESTATIC,
179198
Type.getInternalName(JettyBlockingHelper.class),
@@ -189,7 +208,7 @@ public void visitMethodInsn(
189208
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
190209
// Inject label after Server.handle() call to jump here when blocked
191210
super.visitLabel(afterHandle);
192-
super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
211+
super.visitFrame(F_SAME, 0, null, 0, null);
193212
debug("handle bytecode injected");
194213
this.success = true;
195214
return;
@@ -224,48 +243,48 @@ public void visitMethodInsn(
224243
Label beforeRegularDispatch = new Label();
225244
Label afterRegularDispatch = new Label();
226245

227-
super.visitVarInsn(Opcodes.ALOAD, contextVar);
246+
super.visitVarInsn(ALOAD, CONTEXT_VAR);
228247
super.visitJumpInsn(Opcodes.IFNULL, beforeRegularDispatch);
229-
super.visitVarInsn(Opcodes.ALOAD, contextVar);
248+
super.visitVarInsn(ALOAD, CONTEXT_VAR);
230249
super.visitMethodInsn(
231250
Opcodes.INVOKEINTERFACE,
232251
"datadog/trace/bootstrap/instrumentation/api/AgentSpan",
233252
"getRequestBlockingAction",
234253
"()" + Type.getDescriptor(Flow.Action.RequestBlockingAction.class),
235254
true);
236255
super.visitJumpInsn(Opcodes.IFNONNULL, doBlockLabel);
237-
super.visitJumpInsn(Opcodes.GOTO, beforeRegularDispatch);
256+
super.visitJumpInsn(GOTO, beforeRegularDispatch);
238257

239258
super.visitLabel(doBlockLabel);
240-
super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
259+
super.visitFrame(F_SAME, 0, null, 0, null);
241260
// dispatch with a Dispatchable created from JettyBlockingHelper::block
242261
// first set up the first two arguments to dispatch (this and DispatcherType.REQUEST)
243262
List<Runnable> loadThisAndEnum = new ArrayList<>(savedVisitations.subList(0, 2));
244263
mv.commitVisitations(loadThisAndEnum);
245264
// set up the arguments to the method underlying the lambda (Request, Response,
246265
// RequestBlockingAction, AgentSpan)
247-
super.visitVarInsn(Opcodes.ALOAD, 0);
266+
super.visitVarInsn(ALOAD, 0);
248267
super.visitMethodInsn(
249268
Opcodes.INVOKEVIRTUAL,
250269
"org/eclipse/jetty/server/HttpChannel",
251270
"getRequest",
252271
"()Lorg/eclipse/jetty/server/Request;",
253272
false);
254-
super.visitVarInsn(Opcodes.ALOAD, 0);
273+
super.visitVarInsn(ALOAD, 0);
255274
super.visitMethodInsn(
256275
Opcodes.INVOKEVIRTUAL,
257276
"org/eclipse/jetty/server/HttpChannel",
258277
"getResponse",
259278
"()Lorg/eclipse/jetty/server/Response;",
260279
false);
261-
super.visitVarInsn(Opcodes.ALOAD, contextVar);
280+
super.visitVarInsn(ALOAD, CONTEXT_VAR);
262281
super.visitMethodInsn(
263282
Opcodes.INVOKEINTERFACE,
264283
"datadog/trace/bootstrap/instrumentation/api/AgentSpan",
265284
"getRequestBlockingAction",
266285
"()" + Type.getDescriptor(Flow.Action.RequestBlockingAction.class),
267286
true);
268-
super.visitVarInsn(Opcodes.ALOAD, contextVar);
287+
super.visitVarInsn(ALOAD, CONTEXT_VAR);
269288

270289
// create the lambda
271290
super.visitInvokeDynamicInsn(
@@ -275,15 +294,15 @@ public void visitMethodInsn(
275294
+ Type.getDescriptor(AgentSpan.class)
276295
+ ")Lorg/eclipse/jetty/server/HttpChannel$Dispatchable;",
277296
new Handle(
278-
Opcodes.H_INVOKESTATIC,
297+
H_INVOKESTATIC,
279298
"java/lang/invoke/LambdaMetafactory",
280299
"metafactory",
281300
"(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;",
282301
false),
283302
new Object[] {
284303
Type.getType("()V"),
285304
new Handle(
286-
Opcodes.H_INVOKESTATIC,
305+
H_INVOKESTATIC,
287306
Type.getInternalName(JettyBlockingHelper.class),
288307
"blockAndThrowOnFailure",
289308
"(Lorg/eclipse/jetty/server/Request;Lorg/eclipse/jetty/server/Response;"
@@ -297,14 +316,14 @@ public void visitMethodInsn(
297316
// invoke the dispatch method
298317
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
299318

300-
super.visitJumpInsn(Opcodes.GOTO, afterRegularDispatch);
319+
super.visitJumpInsn(GOTO, afterRegularDispatch);
301320

302321
super.visitLabel(beforeRegularDispatch);
303-
super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
322+
super.visitFrame(F_SAME, 0, null, 0, null);
304323
mv.commitVisitations(savedVisitations);
305324
super.visitMethodInsn(opcode, owner, name, descriptor, isInterface);
306325
super.visitLabel(afterRegularDispatch);
307-
super.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
326+
super.visitFrame(F_SAME, 0, null, 0, null);
308327
this.success = true;
309328
return;
310329
}
@@ -346,15 +365,23 @@ private boolean checkDispatchMethodState(final List<Runnable> savedVisitations)
346365

347366
@Override
348367
public void visitVarInsn(int opcode, int varIndex) {
349-
if (lookForStore && opcode == Opcodes.ASTORE) {
368+
if (lookForStore && opcode == ASTORE) {
350369
debug("Found context");
351-
contextVar = varIndex;
370+
contextStored = true;
352371
lookForStore = false;
372+
// Duplicate on stack and store to its own local var
373+
super.visitInsn(DUP);
374+
super.visitVarInsn(ASTORE, CONTEXT_VAR);
353375
}
354-
355376
super.visitVarInsn(opcode, varIndex);
356377
}
357378

379+
@Override
380+
public void visitMaxs(int maxStack, int maxLocals) {
381+
debug("VisitMaxs stack: " + maxStack + ", locals: " + maxLocals);
382+
super.visitMaxs(maxStack, max(maxLocals, CONTEXT_VAR + 1));
383+
}
384+
358385
@Override
359386
public void visitEnd() {
360387
if (!success && !"run".equals(methodName)) {

0 commit comments

Comments
 (0)