wasm_memory.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759
  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. return ret;
  541. }
  542. #else
  543. bool
  544. wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
  545. {
  546. WASMMemoryInstance *memory = wasm_get_default_memory(module);
  547. uint32 num_bytes_per_page, total_size_old;
  548. uint32 cur_page_count, max_page_count, total_page_count;
  549. uint64 total_size_new;
  550. if (!memory)
  551. return false;
  552. num_bytes_per_page = memory->num_bytes_per_page;
  553. cur_page_count = memory->cur_page_count;
  554. max_page_count = memory->max_page_count;
  555. total_size_old = num_bytes_per_page * cur_page_count;
  556. total_page_count = inc_page_count + cur_page_count;
  557. total_size_new = num_bytes_per_page * (uint64)total_page_count;
  558. if (inc_page_count <= 0)
  559. /* No need to enlarge memory */
  560. return true;
  561. if (total_page_count < cur_page_count /* integer overflow */
  562. || total_page_count > max_page_count) {
  563. return false;
  564. }
  565. bh_assert(total_size_new <= 4 * (uint64)BH_GB);
  566. if (total_size_new > UINT32_MAX) {
  567. /* Resize to 1 page with size 4G-1 */
  568. num_bytes_per_page = UINT32_MAX;
  569. total_page_count = max_page_count = 1;
  570. total_size_new = UINT32_MAX;
  571. }
  572. #ifdef BH_PLATFORM_WINDOWS
  573. if (!os_mem_commit(memory->memory_data_end,
  574. (uint32)total_size_new - total_size_old,
  575. MMAP_PROT_READ | MMAP_PROT_WRITE)) {
  576. return false;
  577. }
  578. #endif
  579. if (os_mprotect(memory->memory_data_end,
  580. (uint32)total_size_new - total_size_old,
  581. MMAP_PROT_READ | MMAP_PROT_WRITE)
  582. != 0) {
  583. #ifdef BH_PLATFORM_WINDOWS
  584. os_mem_decommit(memory->memory_data_end,
  585. (uint32)total_size_new - total_size_old);
  586. #endif
  587. return false;
  588. }
  589. /* The increased pages are filled with zero by the OS when os_mmap,
  590. no need to memset it again here */
  591. memory->num_bytes_per_page = num_bytes_per_page;
  592. memory->cur_page_count = total_page_count;
  593. memory->max_page_count = max_page_count;
  594. memory->memory_data_size = (uint32)total_size_new;
  595. memory->memory_data_end = memory->memory_data + (uint32)total_size_new;
  596. #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 || WASM_ENABLE_AOT != 0
  597. memory->mem_bound_check_1byte.u64 = total_size_new - 1;
  598. memory->mem_bound_check_2bytes.u64 = total_size_new - 2;
  599. memory->mem_bound_check_4bytes.u64 = total_size_new - 4;
  600. memory->mem_bound_check_8bytes.u64 = total_size_new - 8;
  601. memory->mem_bound_check_16bytes.u64 = total_size_new - 16;
  602. #endif
  603. return true;
  604. }
  605. #endif /* end of OS_ENABLE_HW_BOUND_CHECK */
  606. bool
  607. wasm_enlarge_memory(WASMModuleInstance *module, uint32 inc_page_count)
  608. {
  609. bool ret = false;
  610. #if WASM_ENABLE_SHARED_MEMORY != 0
  611. WASMSharedMemNode *node =
  612. wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
  613. if (node)
  614. os_mutex_lock(&node->shared_mem_lock);
  615. #endif
  616. ret = wasm_enlarge_memory_internal(module, inc_page_count);
  617. #if WASM_ENABLE_SHARED_MEMORY != 0
  618. if (node)
  619. os_mutex_unlock(&node->shared_mem_lock);
  620. #endif
  621. return ret;
  622. }
  623. #if !defined(OS_ENABLE_HW_BOUND_CHECK) \
  624. || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
  625. || WASM_ENABLE_BULK_MEMORY != 0
  626. uint32
  627. wasm_get_num_bytes_per_page(WASMMemoryInstance *memory, void *node)
  628. {
  629. uint32 num_bytes_per_page;
  630. #if WASM_ENABLE_SHARED_MEMORY != 0
  631. if (node)
  632. os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  633. #endif
  634. num_bytes_per_page = memory->num_bytes_per_page;
  635. #if WASM_ENABLE_SHARED_MEMORY != 0
  636. if (node)
  637. os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  638. #endif
  639. return num_bytes_per_page;
  640. }
  641. uint32
  642. wasm_get_linear_memory_size(WASMMemoryInstance *memory, void *node)
  643. {
  644. uint32 linear_mem_size;
  645. #if WASM_ENABLE_SHARED_MEMORY != 0
  646. if (node)
  647. os_mutex_lock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  648. #endif
  649. linear_mem_size = memory->num_bytes_per_page * memory->cur_page_count;
  650. #if WASM_ENABLE_SHARED_MEMORY != 0
  651. if (node)
  652. os_mutex_unlock(&((WASMSharedMemNode *)node)->shared_mem_lock);
  653. #endif
  654. return linear_mem_size;
  655. }
  656. #endif