Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/libdyntype_ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ jobs:

- name: Dyntype Build
run: |
git pull --recurse-submodules
git submodule update --remote --recursive
mkdir build && cd build
cmake .. && make

Expand Down
4 changes: 2 additions & 2 deletions doc/libdyntype_api_spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ These APIs are required by `dynamic types`, the absence of this set of APIs woul
- **Parameters**
- `externref`: the dyntype context
- `i32`: the class name (string)
- `arrayref`: rest parameters array
- `externref`: rest parameters array
- **Return**
- `externref`: the created object

Expand Down Expand Up @@ -495,7 +495,7 @@ These APIs are required by `dynamic types`, the absence of this set of APIs woul
- `externref`: the dyntype context
- `i32`: method name (string)
- `externref`: the given dynamic object
- `arrayref`: the arguments array
- `externref`: the arguments array
- **Return**
- `externref`: the return value

Expand Down
3 changes: 3 additions & 0 deletions lib/builtin/builtin_name.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export namespace BuiltinNames {
// export const builtinFileNames = ['lib.type.d.ts'];
export const builtinFileNames = [builtinTypeName, builtinImplementFileName];

// builtin function name
export const globalInitFuncName = 'global|init|func';

// builtin globals
export const builtinTypeManglePrefix = 'lib/builtin/lib.type.d';
export const nanName = `${builtinTypeManglePrefix}|NaN`;
Expand Down
30 changes: 23 additions & 7 deletions runtime-library/libdyntype/dynamic/object.c
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ dynamic_parse_json(dyn_ctx_t ctx, const char *str)
}

dyn_value_t
dynamic_new_array_with_length(dyn_ctx_t ctx, int len)
dynamic_new_array(dyn_ctx_t ctx, int len)
{
JSValue v = JS_NewArray(ctx->js_ctx);
if (JS_IsException(v)) {
Expand All @@ -323,12 +323,6 @@ dynamic_new_array_with_length(dyn_ctx_t ctx, int len)
return dynamic_dup_value(ctx->js_ctx, v);
}

dyn_value_t
dynamic_new_array(dyn_ctx_t ctx)
{
return dynamic_new_array_with_length(ctx, 0);
}

dyn_value_t
dynamic_get_global(dyn_ctx_t ctx, const char *name)
{
Expand Down Expand Up @@ -1044,3 +1038,25 @@ dynamic_throw_exception(dyn_ctx_t ctx, dyn_value_t obj)

return dynamic_dup_value(ctx->js_ctx, js_exception);
}

/******************* Special Property Access *******************/

int
dynamic_get_array_length(dyn_ctx_t ctx, dyn_value_t obj)
{
dyn_value_t length_value = NULL;
int length = 0;

length_value = dynamic_get_property(ctx, obj, "length");
if (!JS_IsNumber(*(JSValue *)length_value)) {
return -DYNTYPE_TYPEERR;
}
length = JS_VALUE_GET_TAG(*(JSValue *)length_value) == JS_TAG_INT
? JS_VALUE_GET_INT(*(JSValue *)length_value)
: -DYNTYPE_TYPEERR;
if (length_value) {
js_free(ctx->js_ctx, length_value);
}

return length;
}
8 changes: 5 additions & 3 deletions runtime-library/libdyntype/dynamic/pure_dynamic.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,14 @@ dyn_value_t
dynamic_invoke(dyn_ctx_t ctx, const char *name, dyn_value_t this_obj, int argc,
dyn_value_t *args);

dyn_value_t
dynamic_call_func(dyn_ctx_t ctx, dyn_value_t obj, int argc, dyn_value_t *args);

dyn_value_t
dynamic_get_global(dyn_ctx_t ctx, const char *name);

/******************* Special Property Access *******************/

int
dynamic_get_array_length(dyn_ctx_t ctx, dyn_value_t obj);

#ifdef __cplusplus
}
#endif
Expand Down
44 changes: 27 additions & 17 deletions runtime-library/libdyntype/lib_dyntype_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -568,17 +568,21 @@ dyntype_get_global_wrapper(wasm_exec_env_t exec_env, wasm_anyref_obj_t ctx,
wasm_anyref_obj_t
dyntype_new_object_with_class_wrapper(wasm_exec_env_t exec_env,
wasm_anyref_obj_t ctx, const char *name,
wasm_struct_obj_t args_array)
wasm_anyref_obj_t args_array)
{
wasm_array_obj_t arr_ref = { 0 };
dyn_value_t ret = NULL;
dyn_value_t dyn_args = UNBOX_ANYREF(args_array);
dyn_value_t dyn_ctx = UNBOX_ANYREF(ctx);
dyn_value_t *argv = NULL;
wasm_value_t tmp;
int argc = 0;
int i = 0;

arr_ref = get_array_ref(args_array);
argc = get_array_length(args_array);
argc = dyntype_get_array_length(dyn_ctx, dyn_args);
if (argc < 0) {
wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env),
"array length is less than 0");
return NULL;
}
if (argc) {
argv = wasm_runtime_malloc(sizeof(dyn_value_t) * argc);
if (!argv) {
Expand All @@ -589,42 +593,46 @@ dyntype_new_object_with_class_wrapper(wasm_exec_env_t exec_env,
}

for (i = 0; i < argc; i++) {
wasm_array_obj_get_elem(arr_ref, i, false, &tmp);
argv[i] = (dyn_value_t)UNBOX_ANYREF(tmp.gc_obj);
argv[i] = dyntype_get_elem(dyn_ctx, dyn_args, i);
}

ret = dyntype_new_object_with_class(UNBOX_ANYREF(ctx), name, argc, argv);
ret = dyntype_new_object_with_class(dyn_ctx, name, argc, argv);

if (!ret) {
wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env),
"dyntype_new_object_with_class failed");
return NULL;
}
if (argv) {
for (i = 0; i < argc; i++) {
dyntype_release(dyn_ctx, argv[i]);
}
wasm_runtime_free(argv);
}

RETURN_BOX_ANYREF(ret, UNBOX_ANYREF(ctx));
RETURN_BOX_ANYREF(ret, dyn_ctx);
}

/******************* Function callback *******************/
wasm_anyref_obj_t
dyntype_invoke_wrapper(wasm_exec_env_t exec_env, wasm_anyref_obj_t ctx,
const char *name, wasm_anyref_obj_t obj,
wasm_struct_obj_t args_array)
wasm_anyref_obj_t args_array)
{
int i = 0;
uint32_t argc = 0;
dyn_value_t dyn_ctx = UNBOX_ANYREF(ctx);
dyn_value_t dyn_obj = UNBOX_ANYREF(obj);
dyn_value_t dyn_args = UNBOX_ANYREF(args_array);
dyn_value_t *func_args = NULL;
dyn_value_t func_ret = NULL;
wasm_array_obj_t arr_ref = { 0 };
wasm_value_t tmp_arg = { 0 };

arr_ref = get_array_ref(args_array);
argc = get_array_length(args_array);

argc = dyntype_get_array_length(dyn_ctx, dyn_args);
if (argc < 0) {
wasm_runtime_set_exception(wasm_runtime_get_module_inst(exec_env),
"array length is less than 0");
return NULL;
}
if (argc > 0) {
func_args = wasm_runtime_malloc(sizeof(dyn_value_t) * argc);
if (!func_args) {
Expand All @@ -636,13 +644,15 @@ dyntype_invoke_wrapper(wasm_exec_env_t exec_env, wasm_anyref_obj_t ctx,
}

for (i = 0; i < argc; i++) {
wasm_array_obj_get_elem(arr_ref, i, false, &tmp_arg);
func_args[i] = (dyn_value_t)UNBOX_ANYREF(tmp_arg.gc_obj);
func_args[i] = dyntype_get_elem(dyn_ctx, dyn_args, i);
}

func_ret = dyntype_invoke(dyn_ctx, name, dyn_obj, argc, func_args);

if (func_args) {
for (i = 0; i < argc; i++) {
dyntype_release(dyn_ctx, func_args[i]);
}
wasm_runtime_free(func_args);
}

Expand Down
6 changes: 6 additions & 0 deletions runtime-library/libdyntype/libdyntype.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,9 @@ dyntype_get_global(dyn_ctx_t ctx, const char *name)
{
return dynamic_get_global(ctx, name);
}

int
dyntype_get_array_length(dyn_ctx_t ctx, dyn_value_t obj)
{
return dynamic_get_array_length(ctx, obj);
}
9 changes: 9 additions & 0 deletions runtime-library/libdyntype/libdyntype_export.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,15 @@ dyntype_release(dyn_ctx_t ctx, dyn_value_t obj);
void
dyntype_collect(dyn_ctx_t ctx);

/**
* @brief Get array's length
*
* @param ctx the dynamic type system context
* @param obj the dynamic value
* @return On success, this function return the array's length.
*/
int
dyntype_get_array_length(dyn_ctx_t ctx, dyn_value_t obj);

#ifdef __cplusplus
}
Expand Down
25 changes: 17 additions & 8 deletions src/backend/binaryen/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,8 @@ export class WASMGen extends Ts2wasmBackend {
currentFuncCtx?: WASMFunctionContext;
dataSegmentContext?: DataSegmentContext;

public globalInitFuncCtx: WASMFunctionContext;

private globalInitFuncName = 'global|init|func';
public globalInitArray: Array<binaryen.ExpressionRef> = [];
private debugFileIndex = new Map<string, number>();
Expand All @@ -294,6 +296,10 @@ export class WASMGen extends Ts2wasmBackend {
this._wasmExprCompiler = new WASMExpressionGen(this);
this._wasmStmtCompiler = new WASMStatementGen(this);
this.dataSegmentContext = new DataSegmentContext();
this.globalInitFuncCtx = new WASMFunctionContext(
this,
this._semanticModule.globalInitFunc!,
);
}

get module(): binaryen.Module {
Expand Down Expand Up @@ -407,7 +413,7 @@ export class WASMGen extends Ts2wasmBackend {
callBuiltInAPIs(this.module);
if (!getConfig().disableAny) {
importAnyLibAPI(this.module);
this.globalInitArray.push(generateDynContext(this.module));
this.globalInitFuncCtx.insert(generateDynContext(this.module));
}
if (!getConfig().disableInterface) {
importInfcLibAPI(this.module);
Expand Down Expand Up @@ -458,11 +464,7 @@ export class WASMGen extends Ts2wasmBackend {
BuiltinNames.JSGlobalObjects.forEach((key) => {
generateGlobalJSObject(this.module, key);
/* Insert at the second slot (right after dyntype context initialized) */
this.globalInitArray.splice(
1,
0,
this.genrateInitJSGlobalObject(key),
);
this.globalInitFuncCtx.insert(this.genrateInitJSGlobalObject(key));
BuiltinNames.JSGlobalObjects.delete(key);
});

Expand Down Expand Up @@ -961,12 +963,19 @@ export class WASMGen extends Ts2wasmBackend {
}

private initEnv() {
const backendLocalVars =
this.globalInitFuncCtx.getAllFuncVarsTypeRefs();
/** sort the local variables array by index */
backendLocalVars.sort((a, b) => {
return a.index - b.index;
});
const allVarsTypeRefs = backendLocalVars.map((value) => value.type);
this.module.addFunction(
this.globalInitFuncName,
binaryen.none,
binaryen.none,
[],
this.module.block(null, this.globalInitArray),
allVarsTypeRefs,
this.module.block(null, this.globalInitFuncCtx.exitScope()),
);
}

Expand Down
47 changes: 30 additions & 17 deletions src/backend/binaryen/wasm_expr_gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1222,14 +1222,14 @@ export class WASMExpressionGen {
private wasmAnyCall(value: AnyCallValue) {
/* call dynamic js function, which will callback to wasm finally */
const anyFuncRef = this.wasmExprGen(value.anyFunc);
const argStruct = this.generateArgStruct(value.parameters);
const dynamicArg = this.generateDynamicArg(value.parameters);
return this.module.call(
dyntype.dyntype_invoke,
[
FunctionalFuncs.getDynContextRef(this.module),
this.module.i32.const(0),
anyFuncRef,
argStruct,
dynamicArg,
],
binaryen.anyref,
);
Expand Down Expand Up @@ -3587,7 +3587,7 @@ export class WASMExpressionGen {
}
}

private generateArgStruct(args?: Array<SemanticsValue>) {
private generateDynamicArg(args?: Array<SemanticsValue>) {
const restArgs = args
? args.map((a) => {
return FunctionalFuncs.boxToAny(
Expand All @@ -3597,20 +3597,33 @@ export class WASMExpressionGen {
);
})
: [];
const argArray = binaryenCAPI._BinaryenArrayNewFixed(
this.module.ptr,
anyArrayTypeInfo.heapTypeRef,
arrayToPtr(restArgs).ptr,
restArgs.length,
const tmpArgVar = this.wasmCompiler.currentFuncCtx!.insertTmpVar(
dyntype.dyn_value_t,
);
const arrayStructType = generateArrayStructTypeInfo(anyArrayTypeInfo);
const arrayStruct = binaryenCAPI._BinaryenStructNew(
this.module.ptr,
arrayToPtr([argArray, this.module.i32.const(restArgs.length)]).ptr,
2,
arrayStructType.heapTypeRef,
const createDynObjOps: binaryen.ExpressionRef[] = [];
const setDynamicArg = this.module.local.set(
tmpArgVar.index,
FunctionalFuncs.generateDynArray(
this.module,
this.module.i32.const(restArgs.length),
),
);
return arrayStruct;
createDynObjOps.push(setDynamicArg);
for (let i = 0; i < restArgs.length; i++) {
createDynObjOps.push(
FunctionalFuncs.setDynArrElem(
this.module,
this.module.local.get(tmpArgVar.index, dyntype.dyn_value_t),
this.module.i32.const(i),
restArgs[i],
),
);
}
this.wasmCompiler.currentFuncCtx!.insert(
this.module.block(null, createDynObjOps),
);

return this.module.local.get(tmpArgVar.index, dyntype.dyn_value_t);
}

/** the dynamic object will fallback to libdyntype */
Expand All @@ -3623,7 +3636,7 @@ export class WASMExpressionGen {
const thisArg = !isNew
? this.wasmExprGen(args.splice(0, 1)[0])
: undefined;
const arrayStruct = this.generateArgStruct(args);
const dynamicArg = this.generateDynamicArg(args);
const finalArgs = [
FunctionalFuncs.getDynContextRef(this.module),
this.module.i32.const(namePointer),
Expand All @@ -3633,7 +3646,7 @@ export class WASMExpressionGen {
finalArgs.push(thisArg!);
}

finalArgs.push(arrayStruct);
finalArgs.push(dynamicArg);

const res = this.module.call(
isNew
Expand Down
Loading