WebAssembly Micro Runtime first version

This commit is contained in:
Wang Xin
2019-05-07 10:18:18 +08:00
parent 15aa50914b
commit a75a5f0f41
252 changed files with 33487 additions and 0 deletions

View File

@ -0,0 +1,67 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_platform.h"
#include "bh_assert.h"
#include <stdarg.h>
#ifdef BH_TEST
#include <setjmp.h>
#endif
#ifdef BH_TEST
/* for exception throwing */
jmp_buf bh_test_jb;
#endif
void bh_assert_internal(int v, const char *file_name, int line_number,
const char *expr_string)
{
if (v)
return;
if (!file_name)
file_name = "NULL FILENAME";
if (!expr_string)
expr_string = "NULL EXPR_STRING";
printf("\nASSERTION FAILED: %s, at FILE=%s, LINE=%d\n", expr_string,
file_name, line_number);
#ifdef BH_TEST
longjmp(bh_test_jb, 1);
#endif
abort();
}
void bh_debug_internal(const char *file_name, int line_number, const char *fmt,
...)
{
#ifndef JEFF_TEST_VERIFIER
va_list args;
va_start(args, fmt);
bh_assert(file_name);
printf("\nDebug info FILE=%s, LINE=%d: ", file_name, line_number);
vprintf(fmt, args);
va_end(args);
printf("\n");
#endif
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_definition.h"
int bh_return(int ret)
{
return ret;
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _BH_PLATFORM_H
#define _BH_PLATFORM_H
#include "bh_config.h"
#include "bh_types.h"
#ifndef NVALGRIND
#define NVALGRIND
#endif
/* Reserve bytes on applet stack for native functions called from
* Java methods to avoid undetectable stack overflow.
*/
#ifndef APPLET_PRESERVED_STACK_SIZE
#define APPLET_PRESERVED_STACK_SIZE (16 * BH_KB)
#endif
typedef unsigned __int64 uint64;
typedef __int64 int64;
extern void DEBUGME(void);
#define DIE do{bh_debug("Die here\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); DEBUGME(void); while(1);}while(0)
#ifndef BH_INVALID_HANDLE
#define BH_INVALID_HANDLE NULL
#endif
#define BH_PLATFORM "AMULET"
#include <stdarg.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define _STACK_SIZE_ADJUSTMENT (32 * 1024)
/* Stack size of applet manager thread. */
#define BH_APPLET_MANAGER_THREAD_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Stack size of HMC thread. */
#define BH_HMC_THREAD_STACK_SIZE (4 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Stack size of watchdog thread. */
#define BH_WATCHDOG_THREAD_SIZE (4 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Stack size of applet threads's native part. */
#define BH_APPLET_PRESERVED_STACK_SIZE (8 * 1024 + _STACK_SIZE_ADJUSTMENT)
/* Maximal recursion depth of interpreter. */
#define BH_MAX_INTERP_RECURSION_DEPTH 8
#define wa_malloc bh_malloc
#define wa_free bh_free
#define snprintf _snprintf
#define BH_ROUTINE_MODIFIER __stdcall
typedef void *korp_tid;
#define INVALID_THREAD_ID 0
typedef void *korp_mutex;
typedef void *korp_sem;
typedef struct {
korp_sem s;
unsigned waiting_count;
} korp_cond;
typedef void* (BH_ROUTINE_MODIFIER *thread_start_routine_t)(void*);
#endif

View File

@ -0,0 +1,39 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "bh_platform.h"
void bh_log_emit(const char *fmt, va_list ap)
{
vprintf(fmt, ap);
fflush(stdout);
}
int bh_fprintf(FILE *stream, const char *fmt, ...)
{
int ret;
va_list ap;
va_start(ap, fmt);
ret = vfprintf(stream ? stream : stdout, fmt, ap);
va_end(ap);
return ret;
}
int bh_fflush(void *stream)
{
return fflush(stream ? stream : stdout);
}

View File

@ -0,0 +1,342 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "bh_thread.h"
#include "bh_assert.h"
#include "bh_log.h"
#include "bh_memory.h"
#include <windows.h>
#include <process.h>
#ifdef _DEBUG
#define THREAD_STACK_ADJUSTMENT (32 * 1024)
#else
#define THREAD_STACK_ADJUSTMENT 0
#endif
static korp_mutex thread_list_lock;
static DWORD tls_indexes[BH_MAX_TLS_NUM];
typedef struct {
int zero_padding;
thread_start_routine_t start;
void* stack;
void* args;
int stack_size;
} vm_thread_block;
static DWORD tb_index;
int _vm_thread_sys_init()
{
unsigned int i;
for (i = 0; i < BH_MAX_TLS_NUM; i++) {
tls_indexes[i] = TlsAlloc();
if (tls_indexes[i] == TLS_OUT_OF_INDEXES)
return BHT_ERROR;
}
tb_index = TlsAlloc();
if (tb_index == TLS_OUT_OF_INDEXES)
return BHT_ERROR;
return vm_mutex_init(&thread_list_lock);
}
static unsigned int BH_ROUTINE_MODIFIER beihai_starter(void* arg)
{
vm_thread_block* tb = (vm_thread_block*) arg;
TlsSetValue(tb_index, tb);
tb->stack = (void *) &arg;
tb->start(tb->args);
return 0;
}
int _vm_thread_create(korp_tid *tid, thread_start_routine_t start, void *arg,
unsigned int stack_size)
{
unsigned int default_stack_size = 20 * 1024;
vm_thread_block* tb;
bh_assert(tid);
bh_assert(start);
if (stack_size == 0)
stack_size = default_stack_size;
#ifdef _DEBUG
stack_size = THREAD_STACK_ADJUSTMENT + stack_size*3;
#endif
tb = (vm_thread_block*) bh_malloc(sizeof(*tb));
if (tb == NULL)
return BHT_ERROR;
memset(tb, 0, sizeof(*tb));
tb->start = start;
tb->stack_size = stack_size;
tb->args = arg;
*tid = (korp_tid) _beginthreadex(NULL, stack_size, beihai_starter,
(void*) tb, 0, NULL);
/* TODO: to deal with the handle; how to close it? */
return (*tid == INVALID_THREAD_ID) ? BHT_ERROR : BHT_OK;
}
korp_tid _vm_self_thread()
{
return (korp_tid) GetCurrentThread();
}
void vm_thread_exit(void *code)
{
vm_thread_block *tb = (vm_thread_block*) TlsGetValue(tb_index);
bh_free(tb);
_endthreadex((unsigned int) code);
}
void* vm_get_stackaddr()
{
vm_thread_block *tb = (vm_thread_block*) TlsGetValue(tb_index);
return (char *) tb->stack + THREAD_STACK_ADJUSTMENT - tb->stack_size;
}
void *_vm_tls_get(unsigned idx)
{
bh_assert(idx < BH_MAX_TLS_NUM);
return TlsGetValue(tls_indexes[idx]);
}
int _vm_tls_put(unsigned idx, void *tls)
{
BOOL r;
bh_assert(idx < BH_MAX_TLS_NUM);
r = TlsSetValue(tls_indexes[idx], tls);
return (r == FALSE) ? BHT_ERROR : BHT_OK;
}
int _vm_mutex_init(korp_mutex *mutex)
{
bh_assert(mutex);
*mutex = CreateMutex(NULL, FALSE, NULL);
return (*mutex == 0) ? BHT_ERROR : BHT_OK;
}
int _vm_mutex_destroy(korp_mutex *mutex)
{
return BHT_OK;
}
/* Returned error (e.g. ERROR_INVALID_HANDLE) from
locking the mutex indicates some logic error present in
the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_lock(korp_mutex *mutex)
{
DWORD ret;
bh_assert(mutex);
ret = WaitForSingleObject(*mutex, INFINITE);
if (WAIT_FAILED == ret) {
LOG_FATAL("vm mutex lock failed (ret=%d)!\n", GetLastError());
exit(-1);
}
}
int vm_mutex_trylock(korp_mutex *mutex)
{
DWORD ret;
bh_assert(mutex);
ret = WaitForSingleObject(*mutex, 0);
if (WAIT_FAILED == ret) {
LOG_FATAL("vm mutex lock failed (ret=%d)!\n", GetLastError());
exit(-1);
}
return ret == WAIT_OBJECT_0 ? BHT_OK : BHT_ERROR;
}
/* Returned error (e.g. ERROR_INVALID_HANDLE) from
unlocking the mutex indicates some logic error present
in the program somewhere.
Don't try to recover error for an existing unknown error.*/
void vm_mutex_unlock(korp_mutex *mutex)
{
BOOL ret;
bh_assert(mutex);
ret = ReleaseMutex(*mutex);
if (FALSE == ret) {
LOG_FATAL("vm mutex unlock failed (ret=%d)!\n", GetLastError());
exit(-1);
}
}
#define BH_SEM_COUNT_MAX 0xFFFF
int _vm_sem_init(korp_sem *sem, unsigned int count)
{
bh_assert(sem);
bh_assert(count <= BH_SEM_COUNT_MAX);
*sem = CreateSemaphore(NULL, count, BH_SEM_COUNT_MAX, NULL);
return (*sem == NULL) ? BHT_ERROR : BHT_OK;
}
int _vm_sem_destroy(korp_sem *sem)
{
return BHT_OK;
}
int _vm_sem_P(korp_sem *sem)
{
DWORD r;
bh_assert(sem);
r = WaitForSingleObject(*sem, INFINITE);
return (r == WAIT_FAILED) ? BHT_ERROR : BHT_OK;
}
int _vm_sem_reltimedP(korp_sem *sem, int mills)
{
DWORD r;
bh_assert(sem);
if (mills == BHT_WAIT_FOREVER)
mills = INFINITE;
r = WaitForSingleObject(*sem, (unsigned int) mills);
switch (r) {
case WAIT_OBJECT_0:
return BHT_OK;
case WAIT_TIMEOUT:
return BHT_TIMEDOUT;
default:
return BHT_ERROR;
}
}
int _vm_sem_V(korp_sem *sem)
{
BOOL r;
bh_assert(sem);
r = ReleaseSemaphore(*sem, 1, NULL);
return (r == FALSE) ? BHT_ERROR : BHT_OK;
}
int _vm_cond_init(korp_cond *cond)
{
bh_assert(cond);
cond->waiting_count = 0;
return vm_sem_init(&cond->s, 0);
}
int _vm_cond_destroy(korp_cond *cond)
{
bh_assert(cond);
return vm_sem_destroy(&cond->s);
}
int _vm_cond_wait(korp_cond *cond, korp_mutex *mutex)
{
bh_assert(cond);
bh_assert(mutex);
cond->waiting_count++;
vm_mutex_unlock(mutex);
if (vm_sem_P(&cond->s) != BHT_OK)
return BHT_ERROR;
vm_mutex_lock(mutex);
cond->waiting_count--;
return BHT_OK;
}
int _vm_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, int mills)
{
int r;
bh_assert(cond);
bh_assert(mutex);
cond->waiting_count++;
vm_mutex_unlock(mutex);
r = vm_sem_reltimedP(&cond->s, mills);
if ((r != BHT_OK) && (r != BHT_TIMEDOUT))
return BHT_ERROR;
vm_mutex_lock(mutex);
cond->waiting_count--;
return r;
}
int _vm_cond_signal(korp_cond *cond)
{
bh_assert(cond);
if (cond->waiting_count == 0)
return BHT_OK;
if (vm_sem_V(&cond->s) != BHT_OK)
return BHT_ERROR;
return BHT_OK;
}
int _vm_cond_broadcast(korp_cond *cond)
{
/* FIXME: use pthread's API to implement this and above
functions. */
unsigned count = cond->waiting_count;
for (; count > 0; count--)
vm_sem_V(&cond->s);
return BHT_OK;
}
int _vm_thread_cancel(korp_tid thread)
{
/* FIXME: implement this with Windows API. */
return 0;
}
int _vm_thread_join(korp_tid thread, void **value_ptr)
{
/* FIXME: implement this with Windows API. */
return 0;
}
int _vm_thread_detach(korp_tid thread)
{
/* FIXME: implement this with Windows API. */
return 0;
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include "bh_time.h"
#include <time.h>
#include <sys/timeb.h>
/* Since GetTickCount64 is not supported on Windows XP, use a temporary method
* to solve the issue. However, GetTickCount return a DWORD value and overflow
* may happen (http://msdn.microsoft.com/en-us/library/ms724408(v=vs.85).aspx).
*
* TODO: Implement GetTickCount64 on Windows XP by self or check overflow issues.
*/
#if (WINVER >= 0x0600)
extern uint64 __stdcall GetTickCount64(void);
#else
extern uint32 __stdcall GetTickCount(void);
#endif
/*
* This function returns milliseconds per tick.
* @return milliseconds per tick.
*/
uint64 _bh_time_get_tick_millisecond()
{
return 5;
}
/*
* This function returns milliseconds after boot.
* @return milliseconds after boot.
*/
uint64 _bh_time_get_boot_millisecond()
{
/* Since GetTickCount64 is not supported on Windows XP, use a temporary method
* to solve the issue. However, GetTickCount return a DWORD value and overflow
* may happen (http://msdn.microsoft.com/en-us/library/ms724408(v=vs.85).aspx).
*
* TODO: Implement GetTickCount64 on Windows XP by self or check overflow issues.
*/
#if (WINVER >= 0x0600)
return GetTickCount64();
#else
return GetTickCount();
#endif
}
/*
* This function returns GMT time milliseconds since from 1970.1.1, AKA UNIX time.
* @return milliseconds since from 1970.1.1.
*/
uint64 _bh_time_get_millisecond_from_1970()
{
struct timeb tp;
ftime(&tp);
return ((uint64) tp.time) * 1000 + tp.millitm
- (tp.dstflag == 0 ? 0 : 60 * 60 * 1000) + tp.timezone * 60 * 1000;
}
size_t bh_time_strftime(char *s, size_t max, const char *format, int64 time)
{
time_t time_sec = time / 1000;
struct timeb tp;
struct tm local_time;
if (NULL == s)
return 0;
ftime(&tp);
time_sec -= tp.timezone * 60;
if (localtime_s(&local_time, &time_sec) != 0)
return 0;
return strftime(s, max, format, &local_time);
}
int bh_time_get(uint8 *timeoff_info, int16 timeoff_info_len, uint32* time)
{
return BH_UNIMPLEMENTED;
}
int bh_time_set(uint32 ntp, uint8 *timeoff_info)
{
return BH_UNIMPLEMENTED;
}