wasm_memory.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_runtime_common.h"
  6. #include "../interpreter/wasm_runtime.h"
  7. #include "bh_platform.h"
  8. #include "mem_alloc.h"
  9. #if WASM_ENABLE_SHARED_MEMORY != 0
  10. #include "../common/wasm_shared_memory.h"
  11. #endif
  12. typedef enum Memory_Mode {
  13. MEMORY_MODE_UNKNOWN = 0,
  14. MEMORY_MODE_POOL,
  15. MEMORY_MODE_ALLOCATOR,
  16. MEMORY_MODE_SYSTEM_ALLOCATOR
  17. } Memory_Mode;
  18. static Memory_Mode memory_mode = MEMORY_MODE_UNKNOWN;
  19. static mem_allocator_t pool_allocator = NULL;
  20. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  21. static void *allocator_user_data = NULL;
  22. static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
  23. static void *(*realloc_func)(void *user_data, void *ptr,
  24. unsigned int size) = NULL;
  25. static void (*free_func)(void *user_data, void *ptr) = NULL;
  26. #else
  27. static void *(*malloc_func)(unsigned int size) = NULL;
  28. static void *(*realloc_func)(void *ptr, unsigned int size) = NULL;
  29. static void (*free_func)(void *ptr) = NULL;
  30. #endif
  31. static unsigned int global_pool_size;
  32. static bool
  33. wasm_memory_init_with_pool(void *mem, unsigned int bytes)
  34. {
  35. mem_allocator_t _allocator = mem_allocator_create(mem, bytes);
  36. if (_allocator) {
  37. memory_mode = MEMORY_MODE_POOL;
  38. pool_allocator = _allocator;
  39. global_pool_size = bytes;
  40. return true;
  41. }
  42. LOG_ERROR("Init memory with pool (%p, %u) failed.\n", mem, bytes);
  43. return false;
  44. }
  45. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  46. static bool
  47. wasm_memory_init_with_allocator(void *_user_data, void *_malloc_func,
  48. void *_realloc_func, void *_free_func)
  49. {
  50. if (_malloc_func && _free_func && _malloc_func != _free_func) {
  51. memory_mode = MEMORY_MODE_ALLOCATOR;
  52. allocator_user_data = _user_data;
  53. malloc_func = _malloc_func;
  54. realloc_func = _realloc_func;
  55. free_func = _free_func;
  56. return true;
  57. }
  58. LOG_ERROR("Init memory with allocator (%p, %p, %p, %p) failed.\n",
  59. _user_data, _malloc_func, _realloc_func, _free_func);
  60. return false;
  61. }
  62. #else
  63. static bool
  64. wasm_memory_init_with_allocator(void *_malloc_func, void *_realloc_func,
  65. void *_free_func)
  66. {
  67. if (_malloc_func && _free_func && _malloc_func != _free_func) {
  68. memory_mode = MEMORY_MODE_ALLOCATOR;
  69. malloc_func = _malloc_func;
  70. realloc_func = _realloc_func;
  71. free_func = _free_func;
  72. return true;
  73. }
  74. LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n", _malloc_func,
  75. _realloc_func, _free_func);
  76. return false;
  77. }
  78. #endif
  79. bool
  80. wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
  81. const MemAllocOption *alloc_option)
  82. {
  83. if (mem_alloc_type == Alloc_With_Pool) {
  84. return wasm_memory_init_with_pool(alloc_option->pool.heap_buf,
  85. alloc_option->pool.heap_size);
  86. }
  87. else if (mem_alloc_type == Alloc_With_Allocator) {
  88. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  89. return wasm_memory_init_with_allocator(
  90. alloc_option->allocator.user_data,
  91. alloc_option->allocator.malloc_func,
  92. alloc_option->allocator.realloc_func,
  93. alloc_option->allocator.free_func);
  94. #else
  95. return wasm_memory_init_with_allocator(
  96. alloc_option->allocator.malloc_func,
  97. alloc_option->allocator.realloc_func,
  98. alloc_option->allocator.free_func);
  99. #endif
  100. }
  101. else if (mem_alloc_type == Alloc_With_System_Allocator) {
  102. memory_mode = MEMORY_MODE_SYSTEM_ALLOCATOR;
  103. return true;
  104. }
  105. else {
  106. return false;
  107. }
  108. }
  109. void
  110. wasm_runtime_memory_destroy()
  111. {
  112. if (memory_mode == MEMORY_MODE_POOL) {
  113. #if BH_ENABLE_GC_VERIFY == 0
  114. (void)mem_allocator_destroy(pool_allocator);
  115. #else
  116. int ret = mem_allocator_destroy(pool_allocator);
  117. if (ret != 0) {
  118. /* Memory leak detected */
  119. exit(-1);
  120. }
  121. #endif
  122. }
  123. memory_mode = MEMORY_MODE_UNKNOWN;
  124. }
  125. unsigned
  126. wasm_runtime_memory_pool_size()
  127. {
  128. if (memory_mode == MEMORY_MODE_POOL)
  129. return global_pool_size;
  130. else
  131. return UINT32_MAX;
  132. }
  133. static inline void *
  134. wasm_runtime_malloc_internal(unsigned int size)
  135. {
  136. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  137. LOG_WARNING(
  138. "wasm_runtime_malloc failed: memory hasn't been initialize.\n");
  139. return NULL;
  140. }
  141. else if (memory_mode == MEMORY_MODE_POOL) {
  142. return mem_allocator_malloc(pool_allocator, size);
  143. }
  144. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  145. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  146. return malloc_func(allocator_user_data, size);
  147. #else
  148. return malloc_func(size);
  149. #endif
  150. }
  151. else {
  152. return os_malloc(size);
  153. }
  154. }
  155. static inline void *
  156. wasm_runtime_realloc_internal(void *ptr, unsigned int size)
  157. {
  158. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  159. LOG_WARNING(
  160. "wasm_runtime_realloc failed: memory hasn't been initialize.\n");
  161. return NULL;
  162. }
  163. else if (memory_mode == MEMORY_MODE_POOL) {
  164. return mem_allocator_realloc(pool_allocator, ptr, size);
  165. }
  166. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  167. if (realloc_func)
  168. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  169. return realloc_func(allocator_user_data, ptr, size);
  170. #else
  171. return realloc_func(ptr, size);
  172. #endif
  173. else
  174. return NULL;
  175. }
  176. else {
  177. return os_realloc(ptr, size);
  178. }
  179. }
  180. static inline void
  181. wasm_runtime_free_internal(void *ptr)
  182. {
  183. if (!ptr) {
  184. LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
  185. #if BH_ENABLE_GC_VERIFY != 0
  186. exit(-1);
  187. #endif
  188. return;
  189. }
  190. if (memory_mode == MEMORY_MODE_UNKNOWN) {
  191. LOG_WARNING("warning: wasm_runtime_free failed: "
  192. "memory hasn't been initialize.\n");
  193. }
  194. else if (memory_mode == MEMORY_MODE_POOL) {
  195. mem_allocator_free(pool_allocator, ptr);
  196. }
  197. else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
  198. #if WASM_MEM_ALLOC_WITH_USER_DATA != 0
  199. free_func(allocator_user_data, ptr);
  200. #else
  201. free_func(ptr);
  202. #endif
  203. }
  204. else {
  205. os_free(ptr);
  206. }
  207. }
  208. void *
  209. wasm_runtime_malloc(unsigned int size)
  210. {
  211. if (size == 0) {
  212. LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
  213. /* At lease alloc 1 byte to avoid malloc failed */
  214. size = 1;
  215. #if BH_ENABLE_GC_VERIFY != 0
  216. exit(-1);
  217. #endif
  218. }
  219. return wasm_runtime_malloc_internal(size);
  220. }
  221. void *
  222. wasm_runtime_realloc(void *ptr, unsigned int size)
  223. {
  224. return wasm_runtime_realloc_internal(ptr, size);
  225. }
  226. void
  227. wasm_runtime_free(void *ptr)
  228. {
  229. wasm_runtime_free_internal(ptr);
  230. }
  231. bool
  232. wasm_runtime_get_mem_alloc_info(mem_alloc_info_t *mem_alloc_info)
  233. {
  234. if (memory_mode == MEMORY_MODE_POOL) {
  235. return mem_allocator_get_alloc_info(pool_allocator, mem_alloc_info);
  236. }
  237. return false;
  238. }
  239. bool
  240. wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
  241. uint32 app_offset, uint32 size)
  242. {
  243. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  244. WASMMemoryInstance *memory_inst;
  245. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  246. || module_inst_comm->module_type == Wasm_Module_AoT);
  247. memory_inst = wasm_get_default_memory(module_inst);
  248. if (!memory_inst) {
  249. goto fail;
  250. }
  251. /* integer overflow check */
  252. if (app_offset > UINT32_MAX - size) {
  253. goto fail;
  254. }
  255. if (app_offset + size <= memory_inst->memory_data_size) {
  256. return true;
  257. }
  258. fail:
  259. wasm_set_exception(module_inst, "out of bounds memory access");
  260. return false;
  261. }
  262. bool
  263. wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
  264. uint32 app_str_offset)
  265. {
  266. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  267. uint32 app_end_offset;
  268. char *str, *str_end;
  269. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  270. || module_inst_comm->module_type == Wasm_Module_AoT);
  271. if (!wasm_runtime_get_app_addr_range(module_inst_comm, app_str_offset, NULL,
  272. &app_end_offset))
  273. goto fail;
  274. str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset);
  275. str_end = str + (app_end_offset - app_str_offset);
  276. while (str < str_end && *str != '\0')
  277. str++;
  278. if (str == str_end)
  279. goto fail;
  280. return true;
  281. fail:
  282. wasm_set_exception(module_inst, "out of bounds memory access");
  283. return false;
  284. }
  285. bool
  286. wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
  287. void *native_ptr, uint32 size)
  288. {
  289. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  290. WASMMemoryInstance *memory_inst;
  291. uint8 *addr = (uint8 *)native_ptr;
  292. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  293. || module_inst_comm->module_type == Wasm_Module_AoT);
  294. memory_inst = wasm_get_default_memory(module_inst);
  295. if (!memory_inst) {
  296. goto fail;
  297. }
  298. /* integer overflow check */
  299. if ((uintptr_t)addr > UINTPTR_MAX - size) {
  300. goto fail;
  301. }
  302. if (memory_inst->memory_data <= addr
  303. && addr + size <= memory_inst->memory_data_end) {
  304. return true;
  305. }
  306. fail:
  307. wasm_set_exception(module_inst, "out of bounds memory access");
  308. return false;
  309. }
  310. void *
  311. wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst_comm,
  312. uint32 app_offset)
  313. {
  314. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  315. WASMMemoryInstance *memory_inst;
  316. uint8 *addr;
  317. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  318. || module_inst_comm->module_type == Wasm_Module_AoT);
  319. memory_inst = wasm_get_default_memory(module_inst);
  320. if (!memory_inst) {
  321. return NULL;
  322. }
  323. addr = memory_inst->memory_data + app_offset;
  324. if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
  325. return addr;
  326. return NULL;
  327. }
  328. uint32
  329. wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst_comm,
  330. void *native_ptr)
  331. {
  332. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  333. WASMMemoryInstance *memory_inst;
  334. uint8 *addr = (uint8 *)native_ptr;
  335. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  336. || module_inst_comm->module_type == Wasm_Module_AoT);
  337. memory_inst = wasm_get_default_memory(module_inst);
  338. if (!memory_inst) {
  339. return 0;
  340. }
  341. if (memory_inst->memory_data <= addr && addr < memory_inst->memory_data_end)
  342. return (uint32)(addr - memory_inst->memory_data);
  343. return 0;
  344. }
  345. bool
  346. wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst_comm,
  347. uint32 app_offset, uint32 *p_app_start_offset,
  348. uint32 *p_app_end_offset)
  349. {
  350. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  351. WASMMemoryInstance *memory_inst;
  352. uint32 memory_data_size;
  353. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  354. || module_inst_comm->module_type == Wasm_Module_AoT);
  355. memory_inst = wasm_get_default_memory(module_inst);
  356. if (!memory_inst) {
  357. return false;
  358. }
  359. memory_data_size = memory_inst->memory_data_size;
  360. if (app_offset < memory_data_size) {
  361. if (p_app_start_offset)
  362. *p_app_start_offset = 0;
  363. if (p_app_end_offset)
  364. *p_app_end_offset = memory_data_size;
  365. return true;
  366. }
  367. return false;
  368. }
  369. bool
  370. wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst_comm,
  371. uint8 *native_ptr,
  372. uint8 **p_native_start_addr,
  373. uint8 **p_native_end_addr)
  374. {
  375. WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
  376. WASMMemoryInstance *memory_inst;
  377. uint8 *addr = (uint8 *)native_ptr;
  378. bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
  379. || module_inst_comm->module_type == Wasm_Module_AoT);
  380. memory_inst = wasm_get_default_memory(module_inst);
  381. if (!memory_inst) {
  382. return false;
  383. }
  384. if (memory_inst->memory_data <= addr
  385. && addr < memory_inst->memory_data_end) {
  386. if (p_native_start_addr)
  387. *p_native_start_addr = memory_inst->memory_data;
  388. if (p_native_end_addr)
  389. *p_native_end_addr = memory_inst->memory_data_end;
  390. return true;
  391. }
  392. return false;
  393. }
  394. bool
  395. wasm_check_app_addr_and_convert(WASMModuleInstance *module_inst, bool is_str,
  396. uint32 app_buf_addr, uint32 app_buf_size,
  397. void **p_native_addr)
  398. {
  399. WASMMemoryInstance *memory_inst = wasm_get_default_memory(module_inst);
  400. uint8 *native_addr;
  401. if (!memory_inst) {
  402. goto fail;
  403. }
  404. native_addr = memory_inst->memory_data + app_buf_addr;
  405. /* No need to check the app_offset and buf_size if memory access
  406. boundary check with hardware trap is enabled */
  407. #ifndef OS_ENABLE_HW_BOUND_CHECK
  408. if (app_buf_addr >= memory_inst->memory_data_size) {
  409. goto fail;
  410. }
  411. if (!is_str) {
  412. if (app_buf_size > memory_inst->memory_data_size - app_buf_addr) {
  413. goto fail;
  414. }
  415. }
  416. else {
  417. const char *str, *str_end;
  418. /* The whole string must be in the linear memory */
  419. str = (const char *)native_addr;
  420. str_end = (const char *)memory_inst->memory_data_end;
  421. while (str < str_end && *str != '\0')
  422. str++;
  423. if (str == str_end)
  424. goto fail;
  425. }
  426. #endif
  427. *p_native_addr = (void *)native_addr;
  428. return true;
  429. fail:
  430. wasm_set_exception(module_inst, "out of bounds memory access");
  431. return false;
  432. }
  433. WASMMemoryInstance *
  434. wasm_get_default_memory(WASMModuleInstance *module_inst)
  435. {
  436. if (module_inst->memories)
  437. return module_inst->memories[0];
  438. else
  439. return NULL;
  440. }
  441. #ifndef OS_ENABLE_HW_BOUND_CHECK
  442. bool
  443. wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
  444. {
  445. WASMMemoryInstance *memory = wasm_get_default_memory(module);
  446. uint8 *memory_data_old, *memory_data_new, *heap_data_old;
  447. uint32 num_bytes_per_page, heap_size, total_size_old;
  448. uint32 cur_page_count, max_page_count, total_page_count;
  449. uint64 total_size_new;
  450. bool ret = true;
  451. if (!memory)
  452. return false;
  453. heap_data_old = memory->heap_data;
  454. heap_size = (uint32)(memory->heap_data_end - memory->heap_data);
  455. memory_data_old = memory->memory_data;
  456. total_size_old = memory->memory_data_size;
  457. num_bytes_per_page = memory->num_bytes_per_page;
  458. cur_page_count = memory->cur_page_count;
  459. max_page_count = memory->max_page_count;
  460. total_page_count = inc_page_count + cur_page_count;
  461. total_size_new = num_bytes_per_page * (uint64)total_page_count;
  462. if (inc_page_count <= 0)
  463. /* No need to enlarge memory */
  464. return true;
  465. if (total_page_count < cur_page_count /* integer overflow */
  466. || total_page_count > max_page_count) {
  467. return false;
  468. }
  469. bh_assert(total_size_new <= 4 * (uint64)BH_GB);
  470. if (total_size_new > UINT32_MAX) {
  471. /* Resize to 1 page with size 4G-1 */
  472. num_bytes_per_page = UINT32_MAX;
  473. total_page_count = max_page_count = 1;
  474. total_size_new = UINT32_MAX;
  475. }
  476. #if WASM_ENABLE_SHARED_MEMORY != 0
  477. if (memory->is_shared) {
  478. memory->num_bytes_per_page = num_bytes_per_page;
  479. memory->cur_page_count = total_page_count;
  480. memory->max_page_count = max_page_count;
  481. /* No need to update memory->memory_data_size as it is
  482. initialized with the maximum memory data size for
  483. shared memory */
  484. return true;
  485. }
  486. #endif
  487. if (heap_size > 0) {
  488. if (mem_allocator_is_heap_corrupted(memory->heap_handle)) {
  489. wasm_runtime_show_app_heap_corrupted_prompt();
  490. return false;
  491. }
  492. }
  493. if (!(memory_data_new =
  494. wasm_runtime_realloc(memory_data_old, (uint32)total_size_new))) {
  495. if (!(memory_data_new = wasm_runtime_malloc((uint32)total_size_new))) {
  496. return false;
  497. }
  498. if (memory_data_old) {
  499. bh_memcpy_s(memory_data_new, (uint32)total_size_new,
  500. memory_data_old, total_size_old);
  501. wasm_runtime_free(memory_data_old);
  502. }
  503. }
  504. memset(memory_data_new + total_size_old, 0,
  505. (uint32)total_size_new - total_size_old);
  506. if (heap_size > 0) {
  507. if (mem_allocator_migrate(memory->heap_handle,
  508. (char *)heap_data_old
  509. + (memory_data_new - memory_data_old),
  510. heap_size)
  511. != 0) {
  512. /* Don't return here as memory->memory_data is obsolete and
  513. must be updated to be correctly used later. */
  514. ret = false;
  515. }
  516. }
  517. memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
  518. memory->heap_data_end = memory->heap_data + heap_size;
  519. memory->num_bytes_per_page = num_bytes_per_page;
  520. memory->cur_page_count = total_page_count;
  521. memory->max_page_count = max_page_count;
  522. memory->memory_data_size = (uint32)total_size_new;
  523. memory->memory_data = memory_data_new;
  524. memory->memory_data_end = memory_data_new + (uint32)total_size_new;
  525. #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
  526. #if UINTPTR_MAX == UINT64_MAX
  527. memory->mem_bound_check_1byte.u64 = total_size_new - 1;
  528. memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
  529. memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
  530. memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
  531. memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
  532. #else
  533. memory->mem_bound_check_1byte.u32[0] = (uint32)total_size_new - 1;
  534. memory->mem_bound_check_2bytes.u32[0] = (uint32)total_size_new - 2;
  535. memory->mem_bound_check_4bytes.u32[0] = (uint32)total_size_new - 4;
  536. memory->mem_bound_check_8bytes.u32[0] = (uint32)total_size_new - 8;
  537. memory->mem_bound_check_16bytes.u32[0] = (uint32)total_size_new - 16;
  538. #endif
  539. #endif
  540. #if defined(os_writegsbase)
  541. /* write base addr of linear memory to GS segment register */
  542. os_writegsbase(memory_data_new);
  543. #endif
  544. return ret;
  545. }
  546. #else
  547. bool
  548. wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
  549. {
  550. WASMMemoryInstance *memory = wasm_get_default_memory(module);
  551. uint32 num_bytes_per_page, total_size_old;
  552. uint32 cur_page_count, max_page_count, total_page_count;
  553. uint64 total_size_new;
  554. if (!memory)
  555. return false;
  556. num_bytes_per_page = memory->num_bytes_per_page;
  557. cur_page_count = memory->cur_page_count;
  558. max_page_count = memory->max_page_count;
  559. total_size_old = num_bytes_per_page * cur_page_count;
  560. total_page_count = inc_page_count + cur_page_count;
  561. total_size_new = num_bytes_per_page * (uint64)total_page_count;
  562. if (inc_page_count <= 0)
  563. /* No need to enlarge memory */
  564. return true;
  565. if (total_page_count < cur_page_count /* integer overflow */
  566. || total_page_count > max_page_count) {
  567. return false;
  568. }
  569. bh_assert(total_size_new <= 4 * (uint64)BH_GB);
  570. if (total_size_new > UINT32_MAX) {
  571. /* Resize to 1 page with size 4G-1 */
  572. num_bytes_per_page = UINT32_MAX;
  573. total_page_count = max_page_count = 1;
  574. total_size_new = UINT32_MAX;
  575. }
  576. #ifdef BH_PLATFORM_WINDOWS
  577. if (!os_mem_commit(memory->memory_data_end,
  578. (uint32)total_size_new - total_size_old,
  579. MMAP_PROT_READ | MMAP_PROT_WRITE)) {
  580. return false;
  581. }
  582. #endif
  583. if (os_mprotect(memory->memory_data_end,
  584. (uint32)total_size_new - total_size_old,
  585. MMAP_PROT_READ | MMAP_PROT_WRITE)
  586. != 0) {
  587. #ifdef BH_PLATFORM_WINDOWS
  588. os_mem_decommit(memory->memory_data_end,
  589. (uint32)total_size_new - total_size_old);
  590. #endif
  591. return false;
  592. }
  593. /* The increased pages are filled with zero by the OS when os_mmap,
  594. no need to memset it again here */
  595. memory->num_bytes_per_page = num_bytes_per_page;
  596. memory->cur_page_count = total_page_count;
  597. memory->max_page_count = max_page_count;
  598. memory->memory_data_size = (uint32)total_size_new;
  599. memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
  600. #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
  601. memory->mem_bound_check_1byte.u64 = total_size_new - 1;
  602. memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
  603. memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
  604. memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
  605. memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
  606. #endif
  607. return true;
  608. }
  609. #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
  610. bool
  611. wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
  612. {
  613. bool ret = false;
  614. #if WASM_ENABLE_SHARED_MEMORY != 0
  615. WASMSharedMemNode *node =
  616. wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
  617. if (node)
  618. os_mutex_lock(&node->shared_mem_lock);
  619. #endif
  620. ret = wasm_enlarge_memory_internal(module, inc_page_count);
  621. #if WASM_ENABLE_SHARED_MEMORY != 0
  622. if (node)
  623. os_mutex_unlock(&node->shared_mem_lock);
  624. #endif
  625. return ret;
  626. }
  627. #if !defined(OS_ENABLE_HW_BOUND_CHECK) \
  628. || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
  629. || WASM_ENABLE_BULK_MEMORY != 0
  630. uint32
  631. wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node)
  632. {
  633. uint32 num_bytes_per_page;
  634. #if WASM_ENABLE_SHARED_MEMORY != 0
  635. if (node)
  636. os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  637. #endif
  638. num_bytes_per_page = memory->num_bytes_per_page;
  639. #if WASM_ENABLE_SHARED_MEMORY != 0
  640. if (node)
  641. os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  642. #endif
  643. return num_bytes_per_page;
  644. }
  645. uint32
  646. wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node)
  647. {
  648. uint32 linear_mem_size;
  649. #if WASM_ENABLE_SHARED_MEMORY != 0
  650. if (node)
  651. os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  652. #endif
  653. linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count;
  654. #if WASM_ENABLE_SHARED_MEMORY != 0
  655. if (node)
  656. os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  657. #endif
  658. return linear_mem_size;
  659. }
  660. #endif