diff options
author | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2012-07-16 11:22:40 +0200 |
---|---|---|
committer | Grzegorz Kossakowski <grzegorz.kossakowski@gmail.com> | 2012-07-16 11:26:21 +0200 |
commit | 2ae253bea6401f26dddf0c3b78b4e40aefbd0b18 (patch) | |
tree | b4b9cfc2ddf7e5e8a22ab638c0ee4b39c8327ed3 /src/partest/scala/tools/partest/javaagent/ProfilerVisitor.java | |
parent | 39dfdb7cca23d109d07edc5884f8fb871cd0c582 (diff) | |
download | scala-2ae253bea6401f26dddf0c3b78b4e40aefbd0b18.tar.gz scala-2ae253bea6401f26dddf0c3b78b4e40aefbd0b18.tar.bz2 scala-2ae253bea6401f26dddf0c3b78b4e40aefbd0b18.zip |
Partest: add `instrumented` test category.
---
(taken from README)
Tests in `instrumented/` directory are executed the same way as in `run/` but
they have additional byte-code instrumentation performed for profiling. You
should put your tests in `instrumented/` directory if you are interested in
method call counts. Examples include tests for specialization (you want to
count boxing and unboxing method calls) or high-level tests for optimizer
where you are interested if methods are successfuly inlined (so they should
not be called at runtime) or closures are eliminated (so no constructors
of closures are called).
Check `scala.tools.partest.instrumented.Instrumentation` to learn how to
use the instrumentation infrastructure.
The instrumentation itself is achieved by attaching a Java agent to the
forked VM process that injects calls to profiler. Check
`scala.tools.partest.javaagent.ProfilingAgent` for details.
---
A few notes on low-level details of this change:
* Partest now depends on asm library for byte-code instrumentation
(`build.xml`)
* Build additional jar called `scala-partest-javaagent.jar` that is
used with `-javaagent:` option. (`build.xml`)
* Set `-javaagent:` option for all tests in `instrumented/` directory.
(`RunnerManger.scala`)
* Introduce a new category of tests called `instrumented`.
* Add one instrumented test to demonstrate usage and test new
infrastructure itself. (`InstrumentationTest.scala`)
Review by @phaller.
Diffstat (limited to 'src/partest/scala/tools/partest/javaagent/ProfilerVisitor.java')
-rw-r--r-- | src/partest/scala/tools/partest/javaagent/ProfilerVisitor.java | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/src/partest/scala/tools/partest/javaagent/ProfilerVisitor.java b/src/partest/scala/tools/partest/javaagent/ProfilerVisitor.java new file mode 100644 index 0000000000..f3a25e87d9 --- /dev/null +++ b/src/partest/scala/tools/partest/javaagent/ProfilerVisitor.java @@ -0,0 +1,46 @@ +/* NEST (New Scala Test) + * Copyright 2007-2012 LAMP/EPFL + * @author Grzegorz Kossakowski + */ + +package scala.tools.partest.javaagent; + +import scala.tools.asm.ClassVisitor; +import scala.tools.asm.MethodVisitor; +import scala.tools.asm.Opcodes; + +public class ProfilerVisitor extends ClassVisitor implements Opcodes { + + private static String profilerClass = "scala/tools/partest/instrumented/Profiler"; + + public ProfilerVisitor(final ClassVisitor cv) { + super(ASM4, cv); + } + + private String className = null; + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + className = name; + super.visit(version, access, name, signature, superName, interfaces); + } + + public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { + // delegate the method call to the next + // chained visitor + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); + if (!profilerClass.equals(className)) { + // only instrument non-abstract methods + if((access & ACC_ABSTRACT) == 0) { + assert(className != null); + mv.visitLdcInsn(className); + mv.visitLdcInsn(name); + mv.visitLdcInsn(desc); + mv.visitMethodInsn(INVOKESTATIC, profilerClass, "methodCalled", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V"); + } + } + return mv; + } + +} |