wasm_memory.c 23 KB

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