Skip to content

Commit

Permalink
C++ is a peculiar language
Browse files Browse the repository at this point in the history
  • Loading branch information
SGrondin committed Jan 21, 2023
1 parent 4e87c08 commit 695e90a
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 65 deletions.
8 changes: 4 additions & 4 deletions src/quickjs/dune
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,22 @@
(rule
(targets quickjs.h)
(action (bash "
cp %{project_root}/../../quickjs/quickjs.h quickjs.h
cp %{project_root}/../../quickjs/quickjs.h .
"))
(mode standard)
)
(rule
(targets libquickjs.a)
(action (bash "
cp %{project_root}/../../quickjs/libquickjs.a libquickjs.a
cp %{project_root}/../../quickjs/libquickjs.a .
"))
(mode standard)
)
(rule
(targets libomp.a)
(action (bash "
cp /usr/local/Cellar/libomp/14.0.6/lib/libomp.a libomp.a &> /dev/null \
|| cp /usr/lib/libgomp.a libomp.a
cp /usr/local/Cellar/libomp/14.0.6/lib/libomp.a . &> /dev/null \
|| cp /usr/lib/libgomp.a .
"))
(mode standard)
)
40 changes: 15 additions & 25 deletions src/quickjs/mlffi.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,7 @@ value v_ok_of_v(value v_ret, value v_ok)
CAMLreturn (v_ret);
}

value v_error_of_cstring(value v_ret, value v_field, const char* error)
{
CAMLparam2(v_ret, v_field);
v_field = caml_alloc_initialized_string(strlen(error), error);
// Size 1, tag 1 (Error)
v_ret = caml_alloc_small(1, 1);
Field(v_ret, 0) = v_field;
CAMLreturn (v_ret);
}

value v_error_of_string(value v_ret, value v_field, string &error)
value v_error_of_string(value v_ret, value v_field, const string& error)
{
CAMLparam2(v_ret, v_field);
v_field = caml_alloc_initialized_string(error.length(), error.c_str());
Expand All @@ -42,33 +32,33 @@ value v_error_of_string(value v_ret, value v_field, string &error)
CAMLreturn (v_ret);
}

string stringify_prop(JSContext *ctx, JSValue &js, const char *prop_name) {
JSValue prop = JS_GetPropertyStr(ctx, js, prop_name);
string stringify_prop(JSContext* const ctx, const JSValue& js, const char* const prop_name) {
JSValue prop { JS_GetPropertyStr(ctx, js, prop_name) };
if (!JS_IsUndefined(prop)) {
size_t len;
const char *str = JS_ToCStringLen(ctx, &len, prop);
if (str == nullptr) {
return string("<null>");
size_t len {};
const char* str { JS_ToCStringLen(ctx, &len, prop) };
if (!str) {
return string { "<null>" };
} else {
string ret(str, len);
string ret { str, len };
JS_FreeCString(ctx, str);
return ret;
}
}
return string("<undefined>");
return string { "<undefined>" };
}

string stringify_exn(JSContext *ctx) {
JSValue exception_val = JS_GetException(ctx);
ostringstream ss;
string stringify_exn(JSContext* const ctx) {
JSValue exception_val { JS_GetException(ctx) };
ostringstream ss {};

if (JS_IsError(ctx, exception_val)) {
ss << stringify_prop(ctx, exception_val, "message");
ss << stringify_prop(ctx, exception_val, "stack");
} else {
size_t len;
const char *str = JS_ToCStringLen(ctx, &len, exception_val);
ss << string(str, len);
size_t len {};
const char* str { JS_ToCStringLen(ctx, &len, exception_val) };
ss << string { str, len };
JS_FreeCString(ctx, str);
}

Expand Down
71 changes: 35 additions & 36 deletions src/quickjs/quickjs.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "mlffi.h"

#include "runtime.h"

vector<JSContext*> contexts;
Expand All @@ -9,26 +8,27 @@ value stub_init_contexts(value v_num_threads)
{
CAMLparam1(v_num_threads);
CAMLlocal2(v_ret, v_field);
int num_threads = Int_val(v_num_threads);
int num_threads { Int_val(v_num_threads) };

caml_enter_blocking_section();

contexts.reserve(num_threads);
vector<string> errors(num_threads, string(""));
vector<string> errors {};
errors.reserve(num_threads);

#pragma omp parallel for
for (int i = 0; i < num_threads; i++) {
JSRuntime *rt = JS_NewRuntime();
if (rt == NULL) {
errors[i] = string("JS_NewRuntime failure");
JSRuntime* rt { JS_NewRuntime() };
if (!rt) {
errors[i] = string { "JS_NewRuntime failure" };
} else {
JSContext *ctx = JS_NewContext(rt);
if (ctx == NULL) {
JSContext* ctx { JS_NewContext(rt) };
if (!ctx) {
JS_FreeRuntime(rt);
errors[i] = string("JS_NewContext failure");
errors[i] = string { "JS_NewContext failure" };
} else {
JSValue bc = JS_ReadObject(ctx, qjsc_runtime, qjsc_runtime_size, JS_READ_OBJ_BYTECODE);
JSValue ret_val = JS_EvalFunction(ctx, bc);
JSValue bc { JS_ReadObject(ctx, qjsc_runtime, qjsc_runtime_size, JS_READ_OBJ_BYTECODE) };
JSValue ret_val { JS_EvalFunction(ctx, bc) };

if (JS_IsException(ret_val)) {
errors[i] = stringify_exn(ctx);
Expand All @@ -37,15 +37,15 @@ value stub_init_contexts(value v_num_threads)
JS_FreeRuntime(rt);
} else {
JS_FreeValue(ctx, ret_val);
contexts[i] = ctx;
contexts[i] = move(ctx);
}
}
}
}

caml_leave_blocking_section();

for (int i = 0; i < num_threads; i++) {
for (int i { 0 }; i < num_threads; i++) {
if (errors[i].length() > 0) {
CAMLreturn (v_error_of_string(v_ret, v_field, errors[i]));
}
Expand All @@ -54,22 +54,22 @@ value stub_init_contexts(value v_num_threads)
CAMLreturn (v_ok_of_v(v_ret, Val_unit));
}

value convert_string_array(JSContext *ctx, JSValue jspair, string key, value v_ret, value v_field) {
value convert_string_array(JSContext* const ctx, const JSValue& jspair, const string& key, value v_ret, value v_field) {
CAMLparam2(v_ret, v_field);
JSValue jsarray = JS_GetPropertyStr(ctx, jspair, key.c_str());
JSValue prop_len = JS_GetPropertyStr(ctx, jsarray, "length");
int64_t len;
JSValue jsarray { JS_GetPropertyStr(ctx, jspair, key.c_str()) };
JSValue prop_len { JS_GetPropertyStr(ctx, jsarray, "length") };
int64_t len {};
if (JS_ToInt64(ctx, &len, prop_len)) {
JS_FreeValue(ctx, prop_len);
JS_FreeValue(ctx, jsarray);
CAMLreturn (v_error_of_cstring(v_ret, v_field, "Could not get results length, please report this bug."));
CAMLreturn (v_error_of_string(v_ret, v_field, string { "Could not get results length, please report this bug." }));
}

v_field = caml_alloc(len, 0);
for (int i = 0; i < len; i++) {
JSValue prop_str = JS_GetPropertyUint32(ctx, jsarray, i);
size_t str_len;
const char* str = JS_ToCStringLen(ctx, &str_len, prop_str);
for (int i { 0 }; i < len; i++) {
JSValue prop_str { JS_GetPropertyUint32(ctx, jsarray, i) };
size_t str_len {};
const char* str { JS_ToCStringLen(ctx, &str_len, prop_str) };
Store_field(v_field, i, caml_alloc_initialized_string(str_len, str));
JS_FreeCString(ctx, str);
JS_FreeValue(ctx, prop_str);
Expand All @@ -86,39 +86,38 @@ value stub_extract(value v_id, value v_code, value v_fn_name)
{
CAMLparam3(v_id, v_code, v_fn_name);
CAMLlocal4(v_ret, v_field, v_arr1, v_arr2);
int id = Int_val(v_id);
string code(String_val(v_code), caml_string_length(v_code));
string fn_name(String_val(v_fn_name), caml_string_length(v_fn_name));
int id { Int_val(v_id) };
string code { String_val(v_code), caml_string_length(v_code) };
string fn_name { String_val(v_fn_name), caml_string_length(v_fn_name) };

caml_enter_blocking_section();

JSContext *ctx = contexts[id];
if (ctx == NULL) {
JSContext* ctx { contexts[id] };
if (!ctx) {
caml_leave_blocking_section();
CAMLreturn (v_error_of_cstring(v_ret, v_field, "Could not find context, please report this bug."));
CAMLreturn (v_error_of_string(v_ret, v_field, string { "Could not find context, please report this bug." }));
}
JS_UpdateStackTop(JS_GetRuntime(ctx));

JSValue code_val = JS_NewStringLen(ctx, code.c_str(), code.length());
JSValue global_obj = JS_GetGlobalObject(ctx);
JSValue fun = JS_GetPropertyStr(ctx, global_obj, fn_name.c_str());
JSValue ret_val = JS_Call(ctx, fun, JS_NULL, 1, &code_val);
JSValue code_val { JS_NewStringLen(ctx, code.c_str(), code.length()) };
JSValue global_obj { JS_GetGlobalObject(ctx) };
JSValue fun { JS_GetPropertyStr(ctx, global_obj, fn_name.c_str()) };
JSValue ret_val { JS_Call(ctx, fun, JS_NULL, 1, &code_val) };
JS_FreeValue(ctx, fun);
JS_FreeValue(ctx, global_obj);
JS_FreeValue(ctx, code_val);

if (JS_IsException(ret_val)) {
caml_leave_blocking_section();
string error = stringify_exn(ctx);
v_ret = v_error_of_string(v_ret, v_field, error);
v_ret = v_error_of_string(v_ret, v_field, stringify_exn(ctx));
JS_FreeValue(ctx, ret_val);
CAMLreturn (v_ret);
};

caml_leave_blocking_section();

v_arr1 = convert_string_array(ctx, ret_val, "strings", v_ret, v_field);
v_arr2 = convert_string_array(ctx, ret_val, "possibleScripts", v_ret, v_field);
v_arr1 = convert_string_array(ctx, ret_val, string { "strings" }, v_ret, v_field);
v_arr2 = convert_string_array(ctx, ret_val, string { "possibleScripts" }, v_ret, v_field);
if (Tag_val(v_arr1) == 0 && Tag_val(v_arr2) == 0) {
// Ok, Ok
// Tuple2
Expand Down

0 comments on commit 695e90a

Please sign in to comment.