Skip to content
This repository was archived by the owner on Mar 8, 2020. It is now read-only.

Commit 43c3a4e

Browse files
committed
v2: implement encoding from JVM
Signed-off-by: Alexander Bezzubov <[email protected]>
1 parent c8091e6 commit 43c3a4e

11 files changed

+237
-124
lines changed

src/main/native/jni_utils.cc

+6-4
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ JNIEnv *getJNIEnv() {
2020
return pEnv;
2121
}
2222

23+
// Class fully qualified names
2324
const char CLS_NODE[] = "org/bblfsh/client/v2/Node";
24-
const char CLS_CTX[] = "org/bblfsh/client/v2/Context";
25+
const char CLS_CTX[] = "org/bblfsh/client/v2/ContextExt";
2526
const char CLS_OBJ[] = "java/lang/Object";
2627
const char CLS_RE[] = "java/lang/RuntimeException";
2728
const char CLS_JNODE[] = "org/bblfsh/client/v2/JNode";
@@ -34,6 +35,7 @@ const char CLS_JUINT[] = "org/bblfsh/client/v2/JUint";
3435
const char CLS_JARR[] = "org/bblfsh/client/v2/JArray";
3536
const char CLS_JOBJ[] = "org/bblfsh/client/v2/JObject";
3637

38+
// Method signatures
3739
const char METHOD_JNODE_KEY_AT[] = "(I)Ljava/lang/String;";
3840
const char METHOD_JNODE_VALUE_AT[] = "(I)Lorg/bblfsh/client/v2/JNode;";
3941
const char METHOD_JOBJ_ADD[] =
@@ -126,8 +128,8 @@ jfieldID getField(JNIEnv *env, jobject obj, const char *name) {
126128
return jfid;
127129
}
128130

129-
static jmethodID MethodID(JNIEnv *env, const char *method,
130-
const char *signature, const char *className) {
131+
jmethodID MethodID(JNIEnv *env, const char *method, const char *signature,
132+
const char *className) {
131133
jclass cls = env->FindClass(className);
132134
checkJvmException(std::string("failed to find a class ").append(className));
133135

@@ -171,7 +173,7 @@ jobject ObjectMethod(JNIEnv *env, const char *method, const char *signature,
171173
va_start(varargs, object);
172174
jobject res = env->CallObjectMethodV(*object, mId, varargs);
173175
va_end(varargs);
174-
checkJvmException(std::string("failed get varargs for ")
176+
checkJvmException(std::string("failed to get varargs for ")
175177
.append(className)
176178
.append(".")
177179
.append(method));

src/main/native/jni_utils.h

+1
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ jint IntMethod(JNIEnv *, const char *, const char *, const char *,
4444
jobject ObjectMethod(JNIEnv *, const char *, const char *, const char *,
4545
const jobject *, ...);
4646

47+
jmethodID MethodID(JNIEnv *, const char *, const char *, const char *);
4748
#endif

src/main/native/org_bblfsh_client_v2_Context.h

+10-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/native/org_bblfsh_client_v2_ContextExt.h

+45
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/main/native/org_bblfsh_client_v2_libuast_Libuast.cc

+87-45
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "jni_utils.h"
44
#include "org_bblfsh_client_v2_Context.h"
5+
#include "org_bblfsh_client_v2_ContextExt.h"
56
#include "org_bblfsh_client_v2_Context__.h"
67
#include "org_bblfsh_client_v2_Node.h"
78
#include "org_bblfsh_client_v2_libuast_Libuast.h"
@@ -72,9 +73,7 @@ class ContextExt {
7273

7374
JNIEnv *env = getJNIEnv();
7475
jclass cls = env->FindClass(CLS_NODE);
75-
if (env->ExceptionOccurred() || !cls) {
76-
return 0;
77-
}
76+
checkJvmException("failed to find class " + std::string(CLS_NODE));
7877

7978
if (!env->IsInstanceOf(obj, cls)) {
8079
const char *err = "ContextExt.toHandle() called not on Node type";
@@ -84,9 +83,7 @@ class ContextExt {
8483

8584
auto handle =
8685
(NodeHandle)env->GetLongField(obj, getField(env, obj, "handle"));
87-
if (env->ExceptionOccurred() || !handle) {
88-
return 0;
89-
}
86+
checkJvmException("failed to get field Node.handle");
9087

9188
return handle;
9289
}
@@ -103,11 +100,12 @@ class ContextExt {
103100
return toJ(root);
104101
}
105102

106-
// Encode serializes external UAST.
103+
// Encode serializes the external UAST.
107104
// Borrows the reference.
108105
jobject Encode(jobject node, UastFormat format) {
109-
NodeHandle h = toHandle(node);
110-
uast::Buffer data = ctx->Encode(h, format);
106+
// if (!assertNotContext(node)) return nullptr;
107+
108+
uast::Buffer data = ctx->Encode(toHandle(node), format);
111109
return asJvmBuffer(data);
112110
}
113111
};
@@ -131,7 +129,7 @@ class Node : public uast::Node<Node *> {
131129
static NodeKind kindOf(jobject obj) {
132130
JNIEnv *env = getJNIEnv();
133131
// TODO(bzz): expose JNode.kind & replace type comparison \w a string test
134-
if (!obj) {
132+
if (!obj || env->IsInstanceOf(obj, env->FindClass(CLS_JNULL))) {
135133
return NODE_NULL;
136134
} else if (env->IsInstanceOf(obj, env->FindClass(CLS_JSTR))) {
137135
return NODE_STRING;
@@ -189,49 +187,71 @@ class Node : public uast::Node<Node *> {
189187

190188
NodeKind Kind() { return kind; }
191189

192-
// TODO(#90): implement and test (all 'As*' are unused stubs for now)
193-
std::string *AsString() {
190+
std::string *AsString() { // new ref
194191
if (!str) {
192+
const char methodName[] = "str";
195193
JNIEnv *env = getJNIEnv();
196-
const char *utf = env->GetStringUTFChars((jstring)obj, 0);
194+
jstring jstr = (jstring)ObjectMethod(
195+
env, methodName, "()Ljava/lang/String;", CLS_JSTR, &obj);
196+
197+
const char *utf = env->GetStringUTFChars(jstr, 0);
197198
str = new std::string(utf);
198-
env->ReleaseStringUTFChars((jstring)obj, utf);
199+
env->ReleaseStringUTFChars(jstr, utf);
199200
}
200201

201202
std::string *s = new std::string(*str);
202203
return s;
203204
}
204205
int64_t AsInt() {
206+
const char methodName[] = "num";
205207
JNIEnv *env = getJNIEnv();
206-
jclass cls = env->FindClass("java/lang/Integer");
207-
jmethodID valueId = env->GetMethodID(cls, "longValue", "()J");
208-
long long value = (long long)env->CallLongMethod(obj, valueId);
208+
jmethodID mID = MethodID(env, methodName, "()J", CLS_JINT);
209+
210+
long long value = (long long)env->CallLongMethod(obj, mID);
211+
checkJvmException(std::string("failed to call ")
212+
.append(CLS_JINT)
213+
.append(".")
214+
.append(methodName)
215+
.append(" at Node::AsInt()"));
209216
return (int64_t)(value);
210217
}
211218
uint64_t AsUint() {
219+
const char methodName[] = "get";
212220
JNIEnv *env = getJNIEnv();
213-
jclass cls = env->FindClass("java/lang/Integer");
214-
jmethodID valueId = env->GetMethodID(cls, "intValue", "()I");
215-
jlong value = env->CallIntMethod(obj, valueId);
221+
jmethodID mID = MethodID(env, methodName, "()J", CLS_JUINT);
216222

217-
jmethodID mId = env->GetMethodID(cls, "toUnsignedLong", "(I)J");
218-
jlong v = env->CallLongMethod(obj, mId, value);
219-
220-
return (uint64_t)(v);
223+
jlong value = env->CallLongMethod(obj, mID);
224+
checkJvmException(std::string("failed to call ")
225+
.append(CLS_JUINT)
226+
.append(".")
227+
.append(methodName)
228+
.append(" at Node::AsUint()"));
229+
return (uint64_t)(value);
221230
}
222231
double AsFloat() {
232+
const char methodName[] = "num";
223233
JNIEnv *env = getJNIEnv();
224-
jclass cls = env->FindClass("java/lang/Double");
225-
jmethodID valueId = env->GetMethodID(cls, "floatValue", "()F");
226-
float value = (float)env->CallFloatMethod(obj, valueId);
234+
jmethodID mID = MethodID(env, methodName, "()D", CLS_JFLT);
235+
236+
double value = (double)env->CallDoubleMethod(obj, mID);
237+
checkJvmException(std::string("failed to call ")
238+
.append(CLS_JFLT)
239+
.append(".")
240+
.append(methodName)
241+
.append(" at Node::AsFloat()"));
227242
return value;
228243
}
229244
bool AsBool() {
245+
const char methodName[] = "value";
230246
JNIEnv *env = getJNIEnv();
231-
// TODO(bzz) check failures, cache classes, read 'value' filed
232-
jclass cls = env->FindClass("java/lang/Boolean");
233-
jmethodID valueId = env->GetMethodID(cls, "booleanValue", "()Z");
234-
bool value = (bool)env->CallBooleanMethod(obj, valueId);
247+
jmethodID mID = MethodID(env, methodName, "()Z", CLS_JBOL);
248+
249+
bool value = (bool)env->CallBooleanMethod(obj, mID);
250+
checkJvmException(std::string("failed to call ")
251+
.append(CLS_JBOL)
252+
.append(".")
253+
.append(methodName)
254+
.append(" at Node::AsBool()"));
235255
return value;
236256
}
237257
size_t Size() {
@@ -245,7 +265,7 @@ class Node : public uast::Node<Node *> {
245265

246266
JNIEnv *env = getJNIEnv();
247267
jstring key = (jstring)ObjectMethod(env, "keyAt", METHOD_JNODE_KEY_AT,
248-
CLS_JNODE, &obj);
268+
CLS_JNODE, &obj, i);
249269

250270
const char *k = env->GetStringUTFChars(key, 0);
251271
std::string *s = new std::string(k);
@@ -258,7 +278,7 @@ class Node : public uast::Node<Node *> {
258278

259279
JNIEnv *env = getJNIEnv();
260280
jobject val =
261-
ObjectMethod(env, "valueAt", METHOD_JNODE_VALUE_AT, CLS_JNODE, &obj);
281+
ObjectMethod(env, "valueAt", METHOD_JNODE_VALUE_AT, CLS_JNODE, &obj, i);
262282
return lookupOrCreate(env->NewGlobalRef(val)); // new ref
263283
}
264284

@@ -287,8 +307,7 @@ class Node : public uast::Node<Node *> {
287307

288308
jstring k = env->NewStringUTF(key.data());
289309

290-
jobject res =
291-
ObjectMethod(env, "add", METHOD_JOBJ_ADD, CLS_JOBJ, &obj, k, v);
310+
ObjectMethod(env, "add", METHOD_JOBJ_ADD, CLS_JOBJ, &obj, k, v);
292311
checkJvmException(
293312
std::string("failed to call JObject.add() from Node::SetKeyValue(")
294313
.append(key)
@@ -404,6 +423,9 @@ class Context {
404423
if (node == nullptr) return nullptr;
405424
return iface->toJ(node);
406425
}
426+
// toNode returns a node associated with a JVM object.
427+
// Returns a new reference.
428+
Node *toNode(jobject obj) { return iface->lookupOrCreate(obj); }
407429

408430
public:
409431
Context() {
@@ -427,6 +449,16 @@ class Context {
427449
return toJ(root); // new ref
428450
}
429451

452+
// Encode serializes UAST.
453+
// Creates a new reference.
454+
jobject Encode(jobject node, UastFormat format) {
455+
// if (!assertNotContext(node)) return nullptr;
456+
457+
Node *n = toNode(node);
458+
uast::Buffer data = ctx->Encode(n, format);
459+
return asJvmBuffer(data);
460+
}
461+
430462
jobject LoadFrom(jobject src) { // JNode
431463
JNIEnv *env = getJNIEnv();
432464

@@ -474,13 +506,13 @@ JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_libuast_Libuast_decode(
474506
jCtxExt = nullptr;
475507
delete (ctx);
476508
delete (p);
477-
checkJvmException("failed to instantiate Context class");
509+
checkJvmException("failed to instantiate ContextExt class");
478510
}
479511

480512
return jCtxExt;
481513
}
482514

483-
// TODO(#86): implement
515+
// TODO(#83): implement
484516
JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_libuast_Libuast_filter(
485517
JNIEnv *, jobject, jobject, jstring) {
486518
return nullptr;
@@ -490,30 +522,40 @@ JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_libuast_Libuast_filter(
490522
// v2.Context()
491523
// ==========================================
492524

525+
JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_Context_encode(
526+
JNIEnv *env, jobject self, jobject node) {
527+
UastFormat fmt = UAST_BINARY; // TODO(bzz): make it argument
528+
529+
Context *p = getHandle<Context>(env, self, nativeContext);
530+
return p->Encode(node, fmt);
531+
}
532+
493533
JNIEXPORT jlong JNICALL
494534
Java_org_bblfsh_client_v2_Context_00024_create(JNIEnv *env, jobject self) {
495535
auto c = new Context();
496-
uast::Context<NodeHandle> *ctx; // TODO(#90): init from c on encode() impl
497-
auto p = new ContextExt(ctx);
498-
return (long)p;
536+
return (long)c;
499537
}
500538

501-
JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_Context_root(JNIEnv *env,
502-
jobject self) {
539+
// ==========================================
540+
// v2.ContextExt()
541+
// ==========================================
542+
543+
JNIEXPORT jobject JNICALL
544+
Java_org_bblfsh_client_v2_ContextExt_root(JNIEnv *env, jobject self) {
503545
ContextExt *p = getHandle<ContextExt>(env, self, nativeContext);
504546
return p->RootNode();
505547
}
506548

507-
JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_Context_encode(
549+
JNIEXPORT jobject JNICALL Java_org_bblfsh_client_v2_ContextExt_encode(
508550
JNIEnv *env, jobject self, jobject node) {
509551
UastFormat fmt = UAST_BINARY; // TODO(bzz): make it argument & enum
510552

511553
ContextExt *p = getHandle<ContextExt>(env, self, nativeContext);
512554
return p->Encode(node, fmt);
513555
}
514556

515-
JNIEXPORT void JNICALL Java_org_bblfsh_client_v2_Context_dispose(JNIEnv *env,
516-
jobject self) {
557+
JNIEXPORT void JNICALL
558+
Java_org_bblfsh_client_v2_ContextExt_dispose(JNIEnv *env, jobject self) {
517559
ContextExt *p = getHandle<ContextExt>(env, self, nativeContext);
518560
setHandle<ContextExt>(env, self, 0, nativeContext);
519561
delete p;

0 commit comments

Comments
 (0)