Make tifast print the values of 'jvalue' arguments

By printing out the contents of 'jvalue' arguments one can get a
better idea of the data an agent is seeing and what the program is
doing.

Test: java -agentpath:$ANDROID_HOST_OUT/lib64/libtifastd.so=log,MethodExit ...
Change-Id: I7266feeff1adaf5598458e12d07b1913e2a09687
diff --git a/tools/ti-fast/tifast.cc b/tools/ti-fast/tifast.cc
index 8a6ac36..677823a 100644
--- a/tools/ti-fast/tifast.cc
+++ b/tools/ti-fast/tifast.cc
@@ -21,6 +21,7 @@
 #include <iomanip>
 #include <jni.h>
 #include <jvmti.h>
+#include <limits>
 #include <memory>
 #include <string>
 #include <sstream>
@@ -461,9 +462,26 @@
   PrintRest(jvmti, jni, args...);
 }
 
-template<typename ...Args>
-void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jvalue v ATTRIBUTE_UNUSED, Args... args) {
-  stream << ", jvalue[<UNION>]";
+template<typename... Args>
+void LogPrinter::PrintRest(jvmtiEnv* jvmti, JNIEnv* jni, jvalue v, Args... args) {
+  std::ostringstream hex;
+  hex << std::hex << v.j;
+  std::ostringstream char_val;
+  if (std::isprint(v.c) && v.c < std::numeric_limits<unsigned char>::max()) {
+    char_val << "'" << static_cast<unsigned char>(v.c) << "'";
+  } else {
+    char_val << "0x" << std::hex << reinterpret_cast<uint16_t>(v.c);
+  }
+  stream << ", jvalue[{<hex: 0x" << hex.str() << ">"
+         << ", .z=" << (v.z ? "true" : "false")
+         << ", .b=" << static_cast<int32_t>(v.b)
+         << ", .c=" << char_val.str()
+         << ", .s=" << static_cast<int32_t>(v.s)
+         << ", .i=" << v.i
+         << ", .j=" << v.j
+         << ", .f=" << v.f
+         << ", .d=" << v.d
+         << ", .l=" << v.l << "}]";
   PrintRest(jvmti, jni, args...);
 }