Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
YottaChain
YTBP
提交
fd15199b
Y
YTBP
项目概览
YottaChain
/
YTBP
通知
0
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Y
YTBP
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
fd15199b
编写于
11月 15, 2017
作者:
B
Bart Wyatt
浏览文件
操作
浏览文件
下载
差异文件
start of the new intrinsic interface
上级
895deb04
23b8c2ad
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
390 addition
and
29 deletion
+390
-29
libraries/chain/include/eosio/chain/wasm_interface.hpp
libraries/chain/include/eosio/chain/wasm_interface.hpp
+2
-0
libraries/chain/include/eosio/chain/wasm_interface_private.hpp
...ries/chain/include/eosio/chain/wasm_interface_private.hpp
+322
-0
libraries/chain/wasm_interface.cpp
libraries/chain/wasm_interface.cpp
+66
-29
未找到文件。
libraries/chain/include/eosio/chain/wasm_interface.hpp
浏览文件 @
fd15199b
...
...
@@ -9,6 +9,7 @@ namespace Runtime {
namespace
eosio
{
namespace
chain
{
class
apply_context
;
class
intrinsics_accessor
;
/**
* @class wasm_interface
...
...
@@ -62,6 +63,7 @@ namespace eosio { namespace chain {
private:
wasm_interface
();
unique_ptr
<
struct
wasm_interface_impl
>
my
;
friend
class
eosio
::
chain
::
intrinsics_accessor
;
};
...
...
libraries/chain/include/eosio/chain/wasm_interface_private.hpp
0 → 100644
浏览文件 @
fd15199b
#pragma once
#include <eosio/chain/wasm_interface.hpp>
#include "Runtime/Runtime.h"
#include "IR/Types.h"
namespace
eosio
{
namespace
chain
{
using
namespace
IR
;
using
namespace
Runtime
;
struct
module_state
{
ModuleInstance
*
instance
=
nullptr
;
Module
*
module
=
nullptr
;
apply_context
*
context
=
nullptr
;
int
mem_start
=
0
;
int
mem_end
=
1
<<
16
;
vector
<
char
>
init_memory
;
fc
::
sha256
code_version
;
};
struct
wasm_interface_impl
{
map
<
digest_type
,
module_state
>
code_cache
;
module_state
*
current_state
=
nullptr
;
};
wasm_interface
::
wasm_interface
()
:
my
(
new
wasm_interface_impl
()
)
{
}
class
intrinsics_accessor
{
public:
static
module_state
&
get_module_state
(
wasm_interface
&
wasm
)
{
FC_ASSERT
(
wasm
.
my
->
current_state
!=
nullptr
);
return
*
wasm
.
my
->
current_state
;
}
};
/**
* class to represent an in-wasm-memory array
* it is a hint to the transcriber that the next parameter will
* be a size and that the pair are validated together
* @tparam T
*/
template
<
typename
T
>
struct
array_ptr
{
typename
std
::
add_lvalue_reference
<
T
>::
type
operator
*
()
const
{
return
*
value
;
}
T
*
operator
->
()
const
noexcept
{
return
value
;
}
template
<
typename
U
>
operator
U
*
()
const
{
return
static_cast
<
U
*>
(
value
);
}
T
*
value
;
};
/**
* template that maps native types to WASM VM types
* @tparam T the native type
*/
template
<
typename
T
>
struct
native_to_wasm
{
using
type
=
void
;
};
/**
* specialization for maping pointers to int32's
*/
template
<
typename
T
>
struct
native_to_wasm
<
T
*>
{
using
type
=
I32
;
};
/**
* Mappings for native types
*/
template
<
>
struct
native_to_wasm
<
int32_t
>
{
using
type
=
I32
;
};
template
<
>
struct
native_to_wasm
<
uint32_t
>
{
using
type
=
I32
;
};
template
<
>
struct
native_to_wasm
<
int64_t
>
{
using
type
=
I64
;
};
template
<
>
struct
native_to_wasm
<
uint64_t
>
{
using
type
=
I64
;
};
template
<
>
struct
native_to_wasm
<
name
>
{
using
type
=
I64
;
};
template
<
>
struct
native_to_wasm
<
bool
>
{
using
type
=
I32
;
};
// convenience alias
template
<
typename
T
>
using
native_to_wasm_t
=
typename
native_to_wasm
<
T
>::
type
;
template
<
typename
T
>
struct
wasm_to_value_type
;
template
<
>
struct
wasm_to_value_type
<
I32
>
{
static
constexpr
auto
value
=
ValueType
::
i32
;
};
template
<
>
struct
wasm_to_value_type
<
I64
>
{
static
constexpr
auto
value
=
ValueType
::
i64
;
};
template
<
typename
T
>
constexpr
auto
wasm_to_value_type_v
=
wasm_to_value_type
<
T
>::
value
;
template
<
typename
T
>
struct
wasm_to_rvalue_type
;
template
<
>
struct
wasm_to_rvalue_type
<
I32
>
{
static
constexpr
auto
value
=
ResultType
::
i32
;
};
template
<
>
struct
wasm_to_rvalue_type
<
I64
>
{
static
constexpr
auto
value
=
ResultType
::
i64
;
};
template
<
typename
T
>
constexpr
auto
wasm_to_rvalue_type_v
=
wasm_to_rvalue_type
<
T
>::
value
;
/**
* Forward delclaration of the invoker type which transcribes arguments to/from a native method
* and injects the appropriate checks
*
* @tparam Ret - the return type of the native function
* @tparam NativeParameters - a std::tuple of the remaining native parameters to transcribe
* @tparam WasmParameters - a std::tuple of the transribed parameters
*/
template
<
typename
Ret
,
typename
NativeParameters
,
typename
WasmParameters
>
struct
intrinsic_invoker_impl
;
/**
* specialization fo the fully transcribed signature
* @tparam Ret - the return type of the native function
* @tparam Translated - the arguments to the wasm function
*/
template
<
typename
Ret
,
typename
...
Translated
>
struct
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<>
,
std
::
tuple
<
Translated
...
>>
{
static
const
FunctionType
*
wasm_function_type
()
{
return
FunctionType
::
get
(
wasm_to_rvalue_type_v
<
Ret
>
,
{
wasm_to_value_type_v
<
Translated
>
...
});
}
using
wasm_method_type
=
Ret
(
*
)(
wasm_interface
&
,
Translated
...);
template
<
wasm_method_type
Method
>
static
Ret
invoke
(
Translated
...
translated
)
{
wasm_interface
&
wasm
=
wasm_interface
::
get
();
return
native_to_wasm_t
<
Ret
>
(
Method
(
wasm
,
translated
...));
}
template
<
wasm_method_type
Method
>
static
const
auto
fn
()
{
return
invoke
<
Method
>
;
}
};
/**
* specialization of the fully transcribed signature for void return values
* @tparam Translated - the arguments to the wasm function
*/
template
<
typename
...
Translated
>
struct
intrinsic_invoker_impl
<
void
,
std
::
tuple
<>
,
std
::
tuple
<
Translated
...
>>
{
static
const
FunctionType
*
wasm_function_type
()
{
return
FunctionType
::
get
(
ResultType
::
none
,
{
wasm_to_value_type_v
<
Translated
>
...
});
}
using
wasm_method_type
=
void
(
*
)(
wasm_interface
&
,
Translated
...);
template
<
wasm_method_type
Method
>
static
void
invoke
(
Translated
...
translated
)
{
wasm_interface
&
wasm
=
wasm_interface
::
get
();
Method
(
wasm
,
translated
...);
}
template
<
wasm_method_type
Method
>
static
const
auto
fn
()
{
return
invoke
<
Method
>
;
}
};
/**
* Sepcialization for transcribing a simple type in the native method signature
* @tparam Ret - the return type of the native method
* @tparam Input - the type of the native parameter to transcribe
* @tparam Inputs - the remaining native parameters to transcribe
* @tparam Translated - the list of transcribed wasm parameters
*/
template
<
typename
Ret
,
typename
Input
,
typename
...
Inputs
,
typename
...
Translated
>
struct
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
Input
,
Inputs
...
>
,
std
::
tuple
<
Translated
...
>>
{
using
translated_type
=
native_to_wasm_t
<
Input
>
;
using
next_step
=
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
Inputs
...
>
,
std
::
tuple
<
Translated
...,
translated_type
>>
;
static
const
FunctionType
*
wasm_function_type
()
{
return
next_step
::
wasm_function_type
();
}
using
then_type
=
Ret
(
*
)(
wasm_interface
&
,
Input
,
Inputs
...,
Translated
...);
template
<
then_type
Then
>
static
Ret
translate_one
(
wasm_interface
&
wasm
,
Inputs
...
rest
,
Translated
...
translated
,
translated_type
last
)
{
auto
native
=
Input
(
last
);
return
Then
(
wasm
,
native
,
rest
...,
translated
...);
};
template
<
then_type
Then
>
static
const
auto
fn
()
{
return
next_step
::
template
fn
<
translate_one
<
Then
>
>
();
}
};
/**
* Specialization for transcribing a array_ptr type in the native method signature
* This type transcribes into 2 wasm parameters: a pointer and length and checks the validity of that memory
* range before dispatching to the native method
*
* @tparam Ret - the return type of the native method
* @tparam Inputs - the remaining native parameters to transcribe
* @tparam Translated - the list of transcribed wasm parameters
*/
template
<
typename
T
,
typename
Ret
,
typename
...
Inputs
,
typename
...
Translated
>
struct
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
array_ptr
<
T
>
,
size_t
,
Inputs
...
>
,
std
::
tuple
<
Translated
...
>>
{
using
next_step
=
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
Inputs
...
>
,
std
::
tuple
<
Translated
...,
I32
,
I32
>>
;
static
const
FunctionType
*
wasm_function_type
()
{
return
next_step
::
wasm_function_type
();
}
using
then_type
=
Ret
(
*
)(
wasm_interface
&
,
array_ptr
<
T
>
,
size_t
,
Inputs
...,
Translated
...);
template
<
then_type
Then
>
static
Ret
translate_one
(
wasm_interface
&
wasm
,
Inputs
...
rest
,
Translated
...
translated
,
I32
ptr
,
I32
size
)
{
auto
mem
=
getDefaultMemory
(
intrinsics_accessor
::
get_module_state
(
wasm
).
instance
);
size_t
length
=
size_t
(
size
);
T
*
base
=
memoryArrayPtr
<
T
>
(
mem
,
ptr
,
length
);
return
Then
(
wasm
,
array_ptr
<
T
>
{
base
},
length
,
rest
...,
translated
...);
};
template
<
then_type
Then
>
static
const
auto
fn
()
{
return
next_step
::
template
fn
<
translate_one
<
Then
>
>
();
}
};
/**
* Specialization for transcribing a pointer type in the native method signature
* This type transcribes into an int32 pointer checks the validity of that memory
* range before dispatching to the native method
*
* @tparam Ret - the return type of the native method
* @tparam Inputs - the remaining native parameters to transcribe
* @tparam Translated - the list of transcribed wasm parameters
*/
template
<
typename
T
,
typename
Ret
,
typename
...
Inputs
,
typename
...
Translated
>
struct
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
T
*
,
Inputs
...
>
,
std
::
tuple
<
Translated
...
>>
{
using
next_step
=
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
Inputs
...
>
,
std
::
tuple
<
Translated
...,
I32
>>
;
static
const
FunctionType
*
wasm_function_type
()
{
return
next_step
::
wasm_function_type
();
}
using
then_type
=
Ret
(
*
)(
wasm_interface
&
,
T
*
,
Inputs
...,
Translated
...);
template
<
then_type
Then
>
static
Ret
translate_one
(
wasm_interface
&
wasm
,
Inputs
...
rest
,
Translated
...
translated
,
I32
ptr
)
{
auto
mem
=
getDefaultMemory
(
intrinsics_accessor
::
get_module_state
(
wasm
).
instance
);
T
*
base
=
memoryArrayPtr
<
T
>
(
mem
,
ptr
,
1
);
return
Then
(
wasm
,
base
,
rest
...,
translated
...);
};
template
<
then_type
Then
>
static
const
auto
fn
()
{
return
next_step
::
template
fn
<
translate_one
<
Then
>
>
;
}
};
/**
* Specialization for transcribing a reference type in the native method signature
* This type transcribes into an int32 pointer checks the validity of that memory
* range before dispatching to the native method
*
* @tparam Ret - the return type of the native method
* @tparam Inputs - the remaining native parameters to transcribe
* @tparam Translated - the list of transcribed wasm parameters
*/
template
<
typename
T
,
typename
Ret
,
typename
...
Inputs
,
typename
...
Translated
>
struct
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
T
&
,
Inputs
...
>
,
std
::
tuple
<
Translated
...
>>
{
using
next_step
=
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
Inputs
...
>
,
std
::
tuple
<
Translated
...,
I32
>>
;
static
const
FunctionType
*
wasm_function_type
()
{
return
next_step
::
wasm_function_type
();
}
using
then_type
=
Ret
(
*
)(
wasm_interface
&
,
T
&
,
Inputs
...,
Translated
...);
template
<
then_type
Then
>
static
Ret
translate_one
(
wasm_interface
&
wasm
,
Inputs
...
rest
,
Translated
...
translated
,
I32
ptr
)
{
// references cannot be created for null pointers
FC_ASSERT
(
ptr
!=
0
);
auto
mem
=
getDefaultMemory
(
intrinsics_accessor
::
get_module_state
(
wasm
).
instance
);
T
&
base
=
memoryRef
<
T
>
(
mem
,
ptr
);
return
Then
(
wasm
,
base
,
rest
...,
translated
...);
}
template
<
then_type
Then
>
static
const
auto
fn
()
{
return
next_step
::
template
fn
<
translate_one
<
Then
>
>
;
}
};
/**
* forward declaration of a wrapper class to call methods of the class
*/
template
<
typename
T
>
struct
intrinsic_function_invoker
;
template
<
typename
Cls
,
typename
Ret
,
typename
...
Params
>
struct
intrinsic_function_invoker
<
Ret
(
Cls
::*
)(
Params
...)
>
{
using
impl
=
intrinsic_invoker_impl
<
Ret
,
std
::
tuple
<
Params
...
>
,
std
::
tuple
<>>
;
static
const
FunctionType
*
wasm_function_type
()
{
return
impl
::
wasm_function_type
();
}
template
<
Ret
(
Cls
::*
Method
)(
Params
...)
>
static
Ret
wrapper
(
wasm_interface
&
wasm
,
Params
...
params
)
{
return
(
Cls
(
wasm
).
*
Method
)(
params
...);
}
template
<
Ret
(
Cls
::*
Method
)(
Params
...)
>
static
const
auto
fn
()
{
return
impl
::
template
fn
<
wrapper
<
Method
>
>
();
}
};
#define _REGISTER_INTRINSIC(R, CLS, METHOD)\
{\
std::piecewise_construct,\
std::forward_as_tuple(#METHOD),\
std::forward_as_tuple(\
#METHOD,\
eosio::chain::intrinsic_function_invoker<decltype(&CLS::METHOD)>::wasm_function_type(),\
(void *)eosio::chain::intrinsic_function_invoker<decltype(&CLS::METHOD)>::fn<&CLS::METHOD>()\
)\
},
#define REGISTER_INTRINSICS(CLS, MEMBERS)\
BOOST_PP_SEQ_FOR_EACH(_REGISTER_INTRINSIC, CLS, MEMBERS)
}
};
\ No newline at end of file
libraries/chain/wasm_interface.cpp
浏览文件 @
fd15199b
#include <eosio/chain/wasm_interface.hpp>
#include <eosio/chain/apply_context.hpp>
#include <boost/core/ignore_unused.hpp>
#include <eosio/chain/wasm_interface_private.hpp>
#include <fc/exception/exception.hpp>
#include <Runtime/Runtime.h>
#include "IR/Module.h"
...
...
@@ -12,51 +14,41 @@
#include "IR/Module.h"
#include "IR/Operators.h"
#include "IR/Validate.h"
#include "IR/Types.h"
#include <mutex>
using
namespace
IR
;
using
namespace
Runtime
;
namespace
eosio
{
namespace
chain
{
using
namespace
IR
;
using
namespace
Runtime
;
namespace
eosio
{
namespace
chain
{
struct
module_state
{
Runtime
::
ModuleInstance
*
instance
=
nullptr
;
IR
::
Module
*
module
=
nullptr
;
int
mem_start
=
0
;
int
mem_end
=
1
<<
16
;
vector
<
char
>
init_memory
;
fc
::
sha256
code_version
;
};
FunctionInstance
*
resolve_intrinsic
(
const
string
&
name
);
struct
root_resolver
:
Runtime
::
Resolver
{
bool
resolve
(
const
string
&
modname
,
const
string
&
exportname
,
bool
resolve
(
const
string
&
mod
_
name
,
const
string
&
export
_
name
,
ObjectType
type
,
ObjectInstance
*&
out
)
override
{
// Try to resolve an intrinsic first.
if
(
IntrinsicResolver
::
singleton
.
resolve
(
modname
,
exportname
,
type
,
out
))
{
return
true
;
}
FC_ASSERT
(
!
"unresolvable"
,
"${module}.${export}"
,
(
"module"
,
modname
)(
"export"
,
exportname
)
);
return
false
;
if
(
mod_name
==
"env"
&&
type
.
kind
==
ObjectKind
::
function
)
{
try
{
auto
*
intrinsic
=
resolve_intrinsic
(
export_name
);
if
(
intrinsic
!=
nullptr
)
{
out
=
asObject
(
intrinsic
);
return
true
;
}
}
FC_RETHROW_EXCEPTIONS
(
error
,
"unresolvable symbol ${module}.${export}"
,
(
"module"
,
mod_name
)(
"export"
,
export_name
));
}
return
false
;
}
};
std
::
mutex
global_load_mutex
;
struct
wasm_interface_impl
{
map
<
digest_type
,
module_state
>
code_cache
;
module_state
*
current_state
=
nullptr
;
};
wasm_interface
::
wasm_interface
()
:
my
(
new
wasm_interface_impl
()
)
{
}
wasm_interface
&
wasm_interface
::
get
()
{
static
bool
init_once
=
[](){
Runtime
::
init
();
return
true
;
}();
boost
::
ignore_unused
(
init_once
);
...
...
@@ -169,8 +161,10 @@ namespace eosio { namespace chain {
memcpy
(
memstart
,
state
.
init_memory
.
data
(),
state
.
mem_end
);
//checktimeStart = fc::time_point::now();
my
->
current_state
->
context
=
&
context
;
Runtime
::
invokeFunction
(
call
,
args
);
my
->
current_state
->
context
=
nullptr
;
}
catch
(
const
Runtime
::
Exception
&
e
)
{
edump
((
std
::
string
(
describeExceptionCause
(
e
.
cause
))));
edump
((
e
.
callStack
));
...
...
@@ -185,7 +179,8 @@ namespace eosio { namespace chain {
return
Runtime
::
getDefaultMemorySize
(
my
->
current_state
->
instance
);
}
DEFINE_INTRINSIC_FUNCTION2
(
env
,
assert
,
assert
,
none
,
i32
,
test
,
i32
,
msg
)
{
#if 0
DEFINE_INTRINSIC_FUNCTION2(env,assert,assert,none,i32,test,i32,msg) {
elog( "assert" );
/*
const char* m = &Runtime::memoryRef<char>( wasm_interface::get().current_memory, msg );
...
...
@@ -322,6 +317,48 @@ DEFINE_INTRINSIC_FUNCTION0(env,checktime,checktime,none) {
}
*/
}
#endif
#if defined(assert)
#undef assert
#endif
class
intrinsics
{
public:
intrinsics
(
wasm_interface
&
wasm
)
:
wasm
(
wasm
)
,
context
(
*
intrinsics_accessor
::
get_module_state
(
wasm
).
context
)
{}
int
read_action
(
array_ptr
<
char
>
memory
,
size_t
size
)
{
FC_ASSERT
(
size
>
0
);
int
minlen
=
std
::
min
<
int
>
(
context
.
act
.
data
.
size
(),
size
);
memcpy
((
void
*
)
memory
,
context
.
act
.
data
.
data
(),
minlen
);
return
minlen
;
}
void
assert
(
bool
condition
,
char
const
*
str
)
{
std
::
string
message
(
str
);
if
(
!
condition
)
edump
((
message
));
FC_ASSERT
(
condition
,
"assertion failed: ${s}"
,
(
"s"
,
message
));
}
private:
wasm_interface
&
wasm
;
apply_context
&
context
;
};
map
<
string
,
Intrinsics
::
Function
>
intrinsic_registry
=
{
REGISTER_INTRINSICS
(
intrinsics
,
(
read_action
)(
assert
))
};
FunctionInstance
*
resolve_intrinsic
(
const
string
&
name
)
{
auto
iter
=
intrinsic_registry
.
find
(
name
);
if
(
iter
!=
intrinsic_registry
.
end
())
{
return
(
iter
->
second
).
function
;
}
return
nullptr
;
}
}
}
/// eosio::chain
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录