Skip to content

Commit 0f02c76

Browse files
committed
Name variable indices to make bytecode generation easier to read
1 parent f8dda05 commit 0f02c76

File tree

1 file changed

+75
-46
lines changed

1 file changed

+75
-46
lines changed

class-inject/src/glue/java/datadog/instrument/glue/DefineClassGlueGenerator.java

Lines changed: 75 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -122,101 +122,124 @@ private static byte[] generateBytecode(String unsafeNamespace) {
122122
mv.visitMaxs(1, 1);
123123
mv.visitEnd();
124124

125-
// main function which accepts a map of class-names to bytecode and returns the defined classes
125+
// main function that accepts a map of class-names to bytecode as well as
126+
// a class-loader or protection-domain, and returns the defined classes
126127
mv = cw.visitMethod(ACC_PUBLIC, "apply", BIFUNCTION_APPLY_DESCRIPTOR, null, null);
127128

128-
Label skipProtectionDomain = new Label();
129-
Label checkBootClassLoader = new Label();
130-
Label hasNextNonBootClass = new Label();
131-
Label classLoaderLocked = new Label();
132-
Label storeNonBootClass = new Label();
133-
Label classLoaderUnlocked = new Label();
134-
Label unlockClassLoaderAndThrow = new Label();
135-
Label setupUnsafeDefiner = new Label();
136-
Label hasNextBootClass = new Label();
137-
Label returnDefinedClasses = new Label();
129+
// bytecode positions
130+
final Label skipProtectionDomain = new Label();
131+
final Label checkBootClassLoader = new Label();
132+
final Label hasNextNonBootClass = new Label();
133+
final Label classLoaderLocked = new Label();
134+
final Label storeNonBootClass = new Label();
135+
final Label classLoaderUnlocked = new Label();
136+
final Label unlockClassLoaderAndThrow = new Label();
137+
final Label setupUnsafeDefiner = new Label();
138+
final Label hasNextBootClass = new Label();
139+
final Label returnDefinedClasses = new Label();
140+
141+
// common bytecode variables
142+
final int bytecodeMap = 1;
143+
final int protectionDomainOrClassLoader = 2;
144+
final int definedClasses = 3;
145+
final int mapEntrySetIterator = 4;
146+
final int protectionDomain = 5;
147+
final int classLoader = 6;
148+
149+
// bytecode variables for non-boot classes
150+
final int classLoadingLock = 7;
151+
final int bytecodeMapEntry = 8;
152+
final int className = 9;
153+
154+
// bytecode variables for boot classes
155+
final int unsafeInstance = 7;
138156

139157
mv.visitCode();
140158

141159
// make sure we unlock the class-loader if an exception occurs while defining a class
142160
mv.visitTryCatchBlock(classLoaderLocked, classLoaderUnlocked, unlockClassLoaderAndThrow, null);
143161

162+
// -------- SHARED SETUP CODE --------
163+
144164
// store the defined classes in a list
145165
mv.visitTypeInsn(NEW, "java/util/ArrayList");
146166
mv.visitInsn(DUP);
147167
mv.visitMethodInsn(INVOKESPECIAL, "java/util/ArrayList", "<init>", "()V", false);
148-
mv.visitVarInsn(ASTORE, 3);
168+
mv.visitVarInsn(ASTORE, definedClasses);
149169

150-
// iterate over the map entries
151-
mv.visitVarInsn(ALOAD, 1);
170+
// get entry set iterator from the bytecode map
171+
mv.visitVarInsn(ALOAD, bytecodeMap);
152172
mv.visitMethodInsn(INVOKEINTERFACE, MAP_CLASS, "entrySet", "()L" + SET_CLASS + ";", true);
153173
mv.visitMethodInsn(INVOKEINTERFACE, SET_CLASS, "iterator", "()L" + ITERATOR_CLASS + ";", true);
154-
mv.visitVarInsn(ASTORE, 4);
174+
mv.visitVarInsn(ASTORE, mapEntrySetIterator);
155175

156-
mv.visitVarInsn(ALOAD, 2);
176+
// check if second argument is a protection domain or class-loader
177+
mv.visitVarInsn(ALOAD, protectionDomainOrClassLoader);
157178
mv.visitTypeInsn(INSTANCEOF, PROTECTIONDOMAIN_CLASS);
158179
mv.visitJumpInsn(IFEQ, skipProtectionDomain);
159180

160181
// extract class-loader from protection domain
161-
mv.visitVarInsn(ALOAD, 2);
182+
mv.visitVarInsn(ALOAD, protectionDomainOrClassLoader);
162183
mv.visitTypeInsn(CHECKCAST, PROTECTIONDOMAIN_CLASS);
163184
mv.visitInsn(DUP);
164-
mv.visitVarInsn(ASTORE, 5);
185+
mv.visitVarInsn(ASTORE, protectionDomain);
165186
mv.visitMethodInsn(
166187
INVOKEVIRTUAL,
167188
PROTECTIONDOMAIN_CLASS,
168189
"getClassLoader",
169190
"()L" + CLASSLOADER_CLASS + ";",
170191
false);
171-
mv.visitVarInsn(ASTORE, 6);
192+
mv.visitVarInsn(ASTORE, classLoader);
172193
mv.visitJumpInsn(GOTO, checkBootClassLoader);
173194

174195
// only have class-loader, no protection domain
175196
mv.visitLabel(skipProtectionDomain);
176197
mv.visitInsn(ACONST_NULL);
177-
mv.visitVarInsn(ASTORE, 5);
178-
mv.visitVarInsn(ALOAD, 2);
198+
mv.visitVarInsn(ASTORE, protectionDomain);
199+
mv.visitVarInsn(ALOAD, protectionDomainOrClassLoader);
179200
mv.visitTypeInsn(CHECKCAST, CLASSLOADER_CLASS);
180-
mv.visitVarInsn(ASTORE, 6);
201+
mv.visitVarInsn(ASTORE, classLoader);
181202

182203
// boot classes can only be defined via Unsafe
183204
mv.visitLabel(checkBootClassLoader);
184-
mv.visitVarInsn(ALOAD, 6);
205+
mv.visitVarInsn(ALOAD, classLoader);
185206
mv.visitJumpInsn(IFNULL, setupUnsafeDefiner);
186207

208+
// -------- LOOP TO DEFINE NON-BOOT CLASSES --------
209+
187210
// check if we've defined all the given bytecode
188211
mv.visitLabel(hasNextNonBootClass);
189-
mv.visitVarInsn(ALOAD, 4);
212+
mv.visitVarInsn(ALOAD, mapEntrySetIterator);
190213
mv.visitMethodInsn(INVOKEINTERFACE, ITERATOR_CLASS, "hasNext", "()Z", true);
191214
mv.visitJumpInsn(IFEQ, returnDefinedClasses);
192215

193216
// extract the name of the next class to define
194-
mv.visitVarInsn(ALOAD, 4);
217+
mv.visitVarInsn(ALOAD, mapEntrySetIterator);
195218
mv.visitMethodInsn(INVOKEINTERFACE, ITERATOR_CLASS, "next", "()L" + OBJECT_CLASS + ";", true);
196219
mv.visitInsn(DUP);
197-
mv.visitVarInsn(ASTORE, 8);
220+
mv.visitVarInsn(ASTORE, bytecodeMapEntry);
198221
mv.visitMethodInsn(
199222
INVOKEINTERFACE, MAP_ENTRY_CLASS, "getKey", "()L" + OBJECT_CLASS + ";", true);
200223
mv.visitTypeInsn(CHECKCAST, STRING_CLASS);
201-
mv.visitVarInsn(ASTORE, 9);
224+
mv.visitVarInsn(ASTORE, className);
202225

203226
// lock the class-loader
204-
mv.visitVarInsn(ALOAD, 6);
205-
mv.visitVarInsn(ALOAD, 9);
227+
mv.visitVarInsn(ALOAD, classLoader);
228+
mv.visitVarInsn(ALOAD, className);
206229
mv.visitMethodInsn(
207230
INVOKEVIRTUAL,
208231
CLASSLOADER_CLASS,
209232
"getClassLoadingLock",
210233
"(L" + STRING_CLASS + ";)L" + OBJECT_CLASS + ";",
211234
false);
212235
mv.visitInsn(DUP);
213-
mv.visitVarInsn(ASTORE, 7);
236+
mv.visitVarInsn(ASTORE, classLoadingLock);
214237
mv.visitInsn(MONITORENTER);
215238
mv.visitLabel(classLoaderLocked);
216239

217240
// check in case the class has already been defined
218-
mv.visitVarInsn(ALOAD, 6);
219-
mv.visitVarInsn(ALOAD, 9);
241+
mv.visitVarInsn(ALOAD, classLoader);
242+
mv.visitVarInsn(ALOAD, className);
220243
mv.visitMethodInsn(
221244
INVOKEVIRTUAL,
222245
CLASSLOADER_CLASS,
@@ -228,55 +251,58 @@ private static byte[] generateBytecode(String unsafeNamespace) {
228251

229252
// define the class using the given class-name and bytecode
230253
mv.visitInsn(POP);
231-
mv.visitVarInsn(ALOAD, 6);
232-
mv.visitVarInsn(ALOAD, 9);
233-
mv.visitVarInsn(ALOAD, 8);
254+
mv.visitVarInsn(ALOAD, classLoader);
255+
mv.visitVarInsn(ALOAD, className);
256+
mv.visitVarInsn(ALOAD, bytecodeMapEntry);
234257
mv.visitMethodInsn(
235258
INVOKEINTERFACE, MAP_ENTRY_CLASS, "getValue", "()L" + OBJECT_CLASS + ";", true);
236259
mv.visitTypeInsn(CHECKCAST, BYTE_ARRAY);
237260
mv.visitInsn(DUP);
238261
mv.visitInsn(ARRAYLENGTH);
239262
mv.visitInsn(ICONST_0);
240263
mv.visitInsn(SWAP);
241-
mv.visitVarInsn(ALOAD, 5);
264+
mv.visitVarInsn(ALOAD, protectionDomain);
242265
mv.visitMethodInsn(
243266
INVOKEVIRTUAL, CLASSLOADER_CLASS, "defineClass", CLASSLOADER_DEFINECLASS_DESCRIPTOR, false);
244267

245268
// store the class in the list whether we defined it or it already existed
246269
mv.visitLabel(storeNonBootClass);
247-
mv.visitVarInsn(ALOAD, 3);
270+
mv.visitVarInsn(ALOAD, definedClasses);
248271
mv.visitInsn(SWAP);
249272
mv.visitMethodInsn(INVOKEVIRTUAL, ARRAYLIST_CLASS, "add", "(L" + OBJECT_CLASS + ";)Z", false);
250273
mv.visitInsn(POP);
251274

252275
// unlock the class-loader
253-
mv.visitVarInsn(ALOAD, 7);
276+
mv.visitVarInsn(ALOAD, classLoadingLock);
254277
mv.visitInsn(MONITOREXIT);
255278
mv.visitLabel(classLoaderUnlocked);
256279

280+
// check again if we've defined all the given bytecode
257281
mv.visitJumpInsn(GOTO, hasNextNonBootClass);
258282

259283
// unlock the class-loader if something goes wrong
260284
mv.visitLabel(unlockClassLoaderAndThrow);
261285
mv.visitInsn(DUP);
262-
mv.visitVarInsn(ALOAD, 7);
286+
mv.visitVarInsn(ALOAD, classLoadingLock);
263287
mv.visitInsn(MONITOREXIT);
264288
mv.visitInsn(ATHROW);
265289

290+
// -------- LOOP TO DEFINE BOOT CLASSES --------
291+
266292
// load Unsafe field into local variable for performance
267293
mv.visitLabel(setupUnsafeDefiner);
268294
mv.visitFieldInsn(GETSTATIC, DEFINECLASS_GLUE_CLASS, "UNSAFE", unsafeDescriptor);
269-
mv.visitVarInsn(ASTORE, 7);
295+
mv.visitVarInsn(ASTORE, unsafeInstance);
270296

271297
// check if we've defined all the given bytecode
272298
mv.visitLabel(hasNextBootClass);
273-
mv.visitVarInsn(ALOAD, 4);
299+
mv.visitVarInsn(ALOAD, mapEntrySetIterator);
274300
mv.visitMethodInsn(INVOKEINTERFACE, ITERATOR_CLASS, "hasNext", "()Z", true);
275301
mv.visitJumpInsn(IFEQ, returnDefinedClasses);
276302

277303
// define the class using the given class-name and bytecode
278-
mv.visitVarInsn(ALOAD, 7);
279-
mv.visitVarInsn(ALOAD, 4);
304+
mv.visitVarInsn(ALOAD, unsafeInstance);
305+
mv.visitVarInsn(ALOAD, mapEntrySetIterator);
280306
mv.visitMethodInsn(INVOKEINTERFACE, ITERATOR_CLASS, "next", "()L" + OBJECT_CLASS + ";", true);
281307
mv.visitInsn(DUP);
282308
mv.visitMethodInsn(
@@ -291,21 +317,24 @@ private static byte[] generateBytecode(String unsafeNamespace) {
291317
mv.visitInsn(ICONST_0);
292318
mv.visitInsn(SWAP);
293319
mv.visitInsn(ACONST_NULL);
294-
mv.visitVarInsn(ALOAD, 5);
320+
mv.visitVarInsn(ALOAD, protectionDomain);
295321
mv.visitMethodInsn(
296322
INVOKEVIRTUAL, unsafeClass, "defineClass", UNSAFE_DEFINECLASS_DESCRIPTOR, false);
297323

298324
// store the class in the list
299-
mv.visitVarInsn(ALOAD, 3);
325+
mv.visitVarInsn(ALOAD, definedClasses);
300326
mv.visitInsn(SWAP);
301327
mv.visitMethodInsn(INVOKEVIRTUAL, ARRAYLIST_CLASS, "add", "(L" + OBJECT_CLASS + ";)Z", false);
302328
mv.visitInsn(POP);
303329

330+
// check again if we've defined all the given bytecode
304331
mv.visitJumpInsn(GOTO, hasNextBootClass);
305332

333+
// -------- SHARED RETURN CODE --------
334+
306335
// return the defined classes
307336
mv.visitLabel(returnDefinedClasses);
308-
mv.visitVarInsn(ALOAD, 3);
337+
mv.visitVarInsn(ALOAD, definedClasses);
309338
mv.visitInsn(ARETURN);
310339

311340
mv.visitMaxs(-1, -1);

0 commit comments

Comments
 (0)