Init
This commit is contained in:
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
|
||||
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
|
||||
* which is part of this source code package.
|
||||
*/
|
||||
#if USE_WASM3
|
||||
#include "WasmJsFunctionParams.h"
|
||||
#include "ContainerMeta.h"
|
||||
#include "Misc/FileHelper.h"
|
||||
#include "Serialization/JsonReader.h"
|
||||
#include "WasmRuntime.h"
|
||||
#include "V8Utils.h"
|
||||
#include "JSLogger.h"
|
||||
#include "../ObjectMapper.h"
|
||||
#include "UECompatible.h"
|
||||
#include "WasmModuleInstance.h"
|
||||
#include "GenericPlatform/GenericPlatformMemory.h"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
static void NormalInstanceCall(const v8::FunctionCallbackInfo<v8::Value>& Info)
|
||||
{
|
||||
IM3Function _Function = static_cast<IM3Function>((v8::Local<v8::External>::Cast(Info.Data()))->Value());
|
||||
int argCount = _Function->funcType->numArgs;
|
||||
check(Info.Length() >= argCount);
|
||||
|
||||
auto Isolate = Info.GetIsolate();
|
||||
auto Context = Isolate->GetCurrentContext();
|
||||
int64* args = (int64*) FMemory_Alloca(sizeof(int64) * argCount);
|
||||
void** argsPointer = (void**) FMemory_Alloca(sizeof(void*) * argCount);
|
||||
for (int Index = 0; Index < argCount; Index++)
|
||||
{
|
||||
const int type = _Function->funcType->types[_Function->funcType->numRets + Index];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
check(Info[Index]->IsNumber());
|
||||
*((int*) (args + Index)) = Info[Index]->Int32Value(Context).ToChecked();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
check(Info[Index]->IsBigInt());
|
||||
*(args + Index) = Info[Index]->ToBigInt(Context).ToLocalChecked()->Int64Value();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
check(Info[Index]->IsNumber());
|
||||
*((float*) (args + Index)) = (float) Info[Index]->NumberValue(Context).ToChecked();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
check(Info[Index]->IsNumber());
|
||||
*((double*) (args + Index)) = Info[Index]->NumberValue(Context).ToChecked();
|
||||
argsPointer[Index] = args + Index;
|
||||
break;
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
if (Export_m3_Call(_Function, argCount, (const void**) argsPointer))
|
||||
{
|
||||
check(_Function->funcType->numRets <= 1);
|
||||
if (_Function->funcType->numRets == 1)
|
||||
{
|
||||
int64 RetValue;
|
||||
void* ret[1] = {&RetValue};
|
||||
if (Export_m3_GetResults(_Function, 1, (const void**) ret))
|
||||
{
|
||||
const int type = _Function->funcType->types[0];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
Info.GetReturnValue().Set(*((int*) (&RetValue)));
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
Info.GetReturnValue().Set(v8::BigInt::New(Isolate, RetValue));
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
Info.GetReturnValue().Set(*((float*) (&RetValue)));
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
Info.GetReturnValue().Set(*((double*) (&RetValue)));
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "call wasm get results failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FV8Utils::ThrowException(Isolate, "call wasm failed");
|
||||
}
|
||||
}
|
||||
|
||||
static const void* NormalInstanceLink(IM3Runtime runtime, IM3ImportContext _ctx, uint64_t* _sp, void* _mem)
|
||||
{
|
||||
IM3Function _Function = _ctx->function;
|
||||
WasmNormalLinkInfo* _Info = (WasmNormalLinkInfo*) _ctx->userdata;
|
||||
check(_Function->funcType->numRets <= 1);
|
||||
uint64_t* raw_sp = _sp;
|
||||
if (_Function->funcType->numRets > 0)
|
||||
{
|
||||
_sp++;
|
||||
}
|
||||
TArray<v8::Local<v8::Value>, TInlineAllocator<20>> Params;
|
||||
check(_Function->funcType->numArgs < 20);
|
||||
for (int i = 0; i < _Function->funcType->numArgs; i++)
|
||||
{
|
||||
const int type = _Function->funcType->types[_Function->funcType->numRets + i];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
Params.Add(v8::Int32::New(_Info->Isolate, *((int32*) (_sp + i))));
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
Params.Add(v8::BigInt::New(_Info->Isolate, *(_sp + i)));
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
Params.Add(v8::Number::New(_Info->Isolate, *((float*) (_sp + i))));
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
Params.Add(v8::Number::New(_Info->Isolate, *((double*) (_sp + i))));
|
||||
break;
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
v8::TryCatch TryCatch(_Info->Isolate);
|
||||
auto Ret = _Info->CachedFunction.Get(_Info->Isolate)
|
||||
->Call(_Info->Isolate->GetCurrentContext(), v8::Undefined(_Info->Isolate), Params.Num(), Params.GetData());
|
||||
if (TryCatch.HasCaught())
|
||||
{
|
||||
UE_LOG(Puerts, Error, TEXT("%s"), *FV8Utils::TryCatchToString(_Info->Isolate, &TryCatch));
|
||||
return "some error";
|
||||
}
|
||||
if (_Function->funcType->numRets == 1)
|
||||
{
|
||||
v8::Local<v8::Value> RetValue = Ret.ToLocalChecked();
|
||||
const int type = _Function->funcType->types[0];
|
||||
switch (type)
|
||||
{
|
||||
case c_m3Type_i32:
|
||||
check(RetValue->IsNumber());
|
||||
*((int*) (raw_sp)) = RetValue->Int32Value(_Info->Isolate->GetCurrentContext()).ToChecked();
|
||||
break;
|
||||
case c_m3Type_i64:
|
||||
check(RetValue->IsBigInt());
|
||||
*raw_sp = RetValue->ToBigInt(_Info->Isolate->GetCurrentContext()).ToLocalChecked()->Int64Value();
|
||||
break;
|
||||
case c_m3Type_f32:
|
||||
check(RetValue->IsNumber());
|
||||
*((float*) (raw_sp)) = RetValue->NumberValue(_Info->Isolate->GetCurrentContext()).ToChecked();
|
||||
break;
|
||||
case c_m3Type_f64:
|
||||
check(RetValue->IsNumber());
|
||||
*((double*) (raw_sp)) = RetValue->NumberValue(_Info->Isolate->GetCurrentContext()).ToChecked();
|
||||
break;
|
||||
default:
|
||||
check(0);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
WasmRuntime* NormalInstanceModule(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, TArray<uint8>& InData,
|
||||
v8::Local<v8::Object>& ExportsObject, v8::Local<v8::Value> ImportsValue,
|
||||
const TArray<std::shared_ptr<WasmRuntime>>& RuntimeList, TArray<WasmNormalLinkInfo*>& CachedLinkFunctionList)
|
||||
{
|
||||
WasmRuntime* UsedRuntime = RuntimeList[0].get();
|
||||
|
||||
v8::Local<v8::Object> MemoryObject;
|
||||
v8::Local<v8::Object> ImportsObject;
|
||||
//需要同时支持使用js mem以及 env memory
|
||||
if (ImportsValue->IsObject())
|
||||
{
|
||||
v8::Local<v8::Object> EnvObject;
|
||||
ImportsObject = ImportsValue.As<v8::Object>();
|
||||
{
|
||||
auto MaybeEnvValue = ImportsObject->Get(Context, FV8Utils::ToV8String(Isolate, "env"));
|
||||
if (!MaybeEnvValue.IsEmpty())
|
||||
{
|
||||
auto EnvValue = MaybeEnvValue.ToLocalChecked();
|
||||
if (EnvValue->IsObject())
|
||||
{
|
||||
EnvObject = EnvValue.As<v8::Object>();
|
||||
|
||||
auto MaybeMemory = EnvObject->Get(Context, FV8Utils::ToV8String(Isolate, "memory"));
|
||||
if (!MaybeMemory.IsEmpty())
|
||||
{
|
||||
auto MemoryValue = MaybeMemory.ToLocalChecked();
|
||||
if (MemoryValue->IsObject())
|
||||
{
|
||||
MemoryObject = MemoryValue.As<v8::Object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (EnvObject.IsEmpty())
|
||||
{
|
||||
auto MaybeEnvValue = ImportsObject->Get(Context, FV8Utils::ToV8String(Isolate, "js"));
|
||||
if (!MaybeEnvValue.IsEmpty())
|
||||
{
|
||||
auto EnvValue = MaybeEnvValue.ToLocalChecked();
|
||||
if (EnvValue->IsObject())
|
||||
{
|
||||
EnvObject = EnvValue.As<v8::Object>();
|
||||
|
||||
auto MaybeMemory = EnvObject->Get(Context, FV8Utils::ToV8String(Isolate, "mem"));
|
||||
if (!MaybeMemory.IsEmpty())
|
||||
{
|
||||
auto MemoryValue = MaybeMemory.ToLocalChecked();
|
||||
if (MemoryValue->IsObject())
|
||||
{
|
||||
MemoryObject = MemoryValue.As<v8::Object>();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//默认情况下使用第一个runtime,其他情况使用memory里面指定的
|
||||
if (!MemoryObject.IsEmpty())
|
||||
{
|
||||
int Seq =
|
||||
MemoryObject->Get(Context, FV8Utils::ToV8String(Isolate, "_Seq")).ToLocalChecked()->Int32Value(Context).ToChecked();
|
||||
for (auto r : RuntimeList)
|
||||
{
|
||||
if (r->GetRuntimeSeq() == Seq)
|
||||
{
|
||||
UsedRuntime = r.get();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto CustomLinkFunc = [&](IM3Module _Module) -> bool
|
||||
{
|
||||
if (!ImportsObject.IsEmpty())
|
||||
{
|
||||
auto ModuleNames = ImportsObject->GetOwnPropertyNames(Context).ToLocalChecked();
|
||||
for (decltype(ModuleNames->Length()) j = 0; j < ModuleNames->Length(); ++j)
|
||||
{
|
||||
v8::Local<v8::Value> ModuleName;
|
||||
v8::Local<v8::Value> ModuleValue;
|
||||
if (ModuleNames->Get(Context, j).ToLocal(&ModuleName) &&
|
||||
ImportsObject->Get(Context, ModuleName).ToLocal(&ModuleValue))
|
||||
{
|
||||
auto Module = ModuleValue.As<v8::Object>();
|
||||
v8::String::Utf8Value UtfModuleName(Isolate, ModuleName);
|
||||
auto FunctionNames = Module->GetOwnPropertyNames(Context).ToLocalChecked();
|
||||
for (decltype(FunctionNames->Length()) i = 0; i < FunctionNames->Length(); ++i)
|
||||
{
|
||||
v8::Local<v8::Value> FunctionName;
|
||||
v8::Local<v8::Value> FunctionValue;
|
||||
if (FunctionNames->Get(Context, i).ToLocal(&FunctionName) &&
|
||||
Module->Get(Context, FunctionName).ToLocal(&FunctionValue))
|
||||
{
|
||||
if (FunctionValue->IsFunction())
|
||||
{
|
||||
WasmNormalLinkInfo* NewInfo = new WasmNormalLinkInfo();
|
||||
NewInfo->CachedFunction.Reset(Isolate, FunctionValue.As<v8::Function>());
|
||||
NewInfo->Isolate = Isolate;
|
||||
CachedLinkFunctionList.Add(NewInfo);
|
||||
if (!Export_m3_LinkRawFunctionEx(_Module, *UtfModuleName,
|
||||
(*(v8::String::Utf8Value(Isolate, FunctionName))), nullptr, &NormalInstanceLink, NewInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
WasmModuleInstance* NewInstance = new WasmModuleInstance(InData);
|
||||
if (NewInstance->ParseModule(UsedRuntime->GetEnv()))
|
||||
{
|
||||
//如果没有指明需要import memory,那么使用默认的runtime即可,即便外面传入了memory也不生效
|
||||
if (!NewInstance->GetModule()->memoryImported)
|
||||
{
|
||||
UsedRuntime = RuntimeList[0].get();
|
||||
}
|
||||
|
||||
if (!NewInstance->LoadModule(UsedRuntime, 0, CustomLinkFunc))
|
||||
{
|
||||
delete NewInstance;
|
||||
NewInstance = nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
delete NewInstance;
|
||||
NewInstance = nullptr;
|
||||
}
|
||||
if (NewInstance && NewInstance->GetAllExportFunctions().Num())
|
||||
{
|
||||
IM3Module _Module = NewInstance->GetModule();
|
||||
for (uint32 i = 0; i < _Module->numFunctions; ++i)
|
||||
{
|
||||
IM3Function f = &_Module->functions[i];
|
||||
if (f->compiled && f->export_name && *(f->export_name))
|
||||
{
|
||||
auto Data = v8::External::New(Isolate, f);
|
||||
auto Func = v8::Function::New(Context, NormalInstanceCall, Data).ToLocalChecked();
|
||||
Func->Set(Context, FV8Utils::ToV8String(Isolate, M3_FUNCTION_KEY), Data);
|
||||
(void) ExportsObject->Set(Context, FV8Utils::ToV8String(Isolate, f->export_name), Func);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (NewInstance->GetModule()->memoryExportName)
|
||||
{
|
||||
(void) ExportsObject->Set(Context, FV8Utils::ToV8String(Isolate, "__memoryExport"),
|
||||
FV8Utils::ToV8String(Isolate, NewInstance->GetModule()->memoryExportName));
|
||||
}
|
||||
if (NewInstance->GetModule()->tableExportName)
|
||||
{
|
||||
(void) ExportsObject->Set(Context, FV8Utils::ToV8String(Isolate, "__tableExport"),
|
||||
FV8Utils::ToV8String(Isolate, NewInstance->GetModule()->tableExportName));
|
||||
(void) ExportsObject->Set(
|
||||
Context, FV8Utils::ToV8String(Isolate, "__moduleIndex"), v8::Integer::New(Isolate, NewInstance->Index));
|
||||
}
|
||||
return UsedRuntime;
|
||||
}
|
||||
|
||||
} // namespace PUERTS_NAMESPACE
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
|
||||
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
|
||||
* which is part of this source code package.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#if USE_WASM3
|
||||
#include "CoreMinimal.h"
|
||||
#include "WasmModule.h"
|
||||
#include "PuertsNamespaceDef.h"
|
||||
|
||||
PRAGMA_DISABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
#pragma warning(push, 0)
|
||||
#include "libplatform/libplatform.h"
|
||||
#include "v8.h"
|
||||
#pragma warning(pop)
|
||||
PRAGMA_ENABLE_UNDEFINED_IDENTIFIER_WARNINGS
|
||||
|
||||
#include "WasmFunction.h"
|
||||
|
||||
#define M3_FUNCTION_KEY "__puerts_inner_m3_func"
|
||||
|
||||
namespace PUERTS_NAMESPACE
|
||||
{
|
||||
struct WasmNormalLinkInfo
|
||||
{
|
||||
v8::UniquePersistent<v8::Function> CachedFunction;
|
||||
v8::Isolate* Isolate;
|
||||
};
|
||||
|
||||
WasmRuntime* NormalInstanceModule(v8::Isolate* Isolate, v8::Local<v8::Context>& Context, TArray<uint8>& InData,
|
||||
v8::Local<v8::Object>& ExportsObject, v8::Local<v8::Value> ImportsValue,
|
||||
const TArray<std::shared_ptr<WasmRuntime>>& RuntimeList, TArray<WasmNormalLinkInfo*>& CachedLinkFunctionList);
|
||||
}; // namespace PUERTS_NAMESPACE
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
|
||||
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
|
||||
* which is part of this source code package.
|
||||
*/
|
||||
|
||||
#if USE_WASM3
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include "WasmRuntime.h"
|
||||
#include "WasmModule.h"
|
||||
#include "WasmFunction.h"
|
||||
#include "WasmStaticLink.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Binding.hpp"
|
||||
#include "UEDataBinding.hpp"
|
||||
|
||||
struct AutoRegisterForWasmExtension
|
||||
{
|
||||
};
|
||||
AutoRegisterForWasmExtension __AutoRegisterForWasmExtension__;
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Tencent is pleased to support the open source community by making Puerts available.
|
||||
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
|
||||
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
|
||||
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
|
||||
* which is part of this source code package.
|
||||
*/
|
||||
|
||||
#if USE_WASM3
|
||||
#include <array>
|
||||
#include <tuple>
|
||||
#include "WasmRuntime.h"
|
||||
#include "WasmModule.h"
|
||||
#include "WasmFunction.h"
|
||||
#include "WasmStaticLink.h"
|
||||
#include "CoreMinimal.h"
|
||||
#include "Binding.hpp"
|
||||
#include "UEDataBinding.hpp"
|
||||
#include "Kismet/KismetMathLibrary.h"
|
||||
|
||||
float atan2_ue_bind(float X, float Y)
|
||||
{
|
||||
return UKismetMathLibrary::Atan2(X, Y);
|
||||
}
|
||||
|
||||
WASM_BEGIN_LINK_GLOBAL(TestMath, 0)
|
||||
WASM_LINK_GLOBAL(atan2_ue_bind)
|
||||
WASM_END_LINK_GLOBAL(TestMath, 0)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user