-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Increase wasm (smart contract) max memory to 33MiB #1459
Changes from all commits
6db8bc6
9084170
9bfdcc6
2d4baa0
709a68e
9a071d0
00f8100
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -34,31 +34,39 @@ namespace eosio { | |
|
||
memory* next_active_heap() | ||
{ | ||
constexpr uint32_t wasm_page_size = 64*1024; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. define the |
||
memory* const current_memory = _available_heaps + _active_heap; | ||
|
||
// make sure we will not exceed the 1M limit (needs to match wasm_interface.cpp _max_memory) | ||
auto remaining = 1024 * 1024 - reinterpret_cast<int32_t>(sbrk(0)); | ||
if (remaining <= 0) | ||
{ | ||
const uint32_t current_memory_size = reinterpret_cast<uint32_t>(sbrk(0)); | ||
if(static_cast<int32_t>(current_memory_size) < 0) | ||
return nullptr; | ||
|
||
//grab up to the end of the current WASM memory page provided that it has 1KiB remaining, otherwise | ||
// grow to end of next page | ||
uint32_t heap_adj; | ||
if(current_memory_size % wasm_page_size <= wasm_page_size-1024) | ||
heap_adj = (current_memory_size + wasm_page_size) - (current_memory_size % wasm_page_size) - current_memory_size; | ||
else | ||
heap_adj = (current_memory_size + wasm_page_size*2) - (current_memory_size % (wasm_page_size*2)) - current_memory_size; | ||
char* new_memory_start = reinterpret_cast<char*>(sbrk(heap_adj)); | ||
if(reinterpret_cast<int32_t>(new_memory_start) == -1) { | ||
// ensure that any remaining unallocated memory gets cleaned up | ||
current_memory->cleanup_remaining(); | ||
++_active_heap; | ||
_heaps_actual_size = _active_heap; | ||
return nullptr; | ||
} | ||
|
||
const uint32_t new_heap_size = uint32_t(remaining) > _new_heap_size ? _new_heap_size : uint32_t(remaining); | ||
char* new_memory_start = static_cast<char*>(sbrk(new_heap_size)); | ||
// if we can expand the current memory, keep working with it | ||
if (current_memory->expand_memory(new_memory_start, new_heap_size)) | ||
if (current_memory->expand_memory(new_memory_start, heap_adj)) | ||
return current_memory; | ||
|
||
// ensure that any remaining unallocated memory gets cleaned up | ||
current_memory->cleanup_remaining(); | ||
|
||
++_active_heap; | ||
memory* const next = _available_heaps + _active_heap; | ||
next->init(new_memory_start, new_heap_size); | ||
next->init(new_memory_start, heap_adj); | ||
|
||
return next; | ||
} | ||
|
@@ -460,7 +468,6 @@ namespace eosio { | |
static const uint32_t _mem_block = 8; | ||
static const uint32_t _rem_mem_block_mask = _mem_block - 1; | ||
static const uint32_t _initial_heap_size = 8192;//32768; | ||
static const uint32_t _new_heap_size = 65536; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
// if sbrk is not called outside of this file, then this is the max times we can call it | ||
static const uint32_t _heaps_size = 16; | ||
char _initial_heap[_initial_heap_size]; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
#set the MAX_MEMORY to 1MB for these tests; there were lots of memory unit tests that assume such | ||
|
||
add_wast_executable(TARGET test_api | ||
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}" | ||
LIBRARIES libc++ libc eosiolib | ||
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR} | ||
MAX_MEMORY 1048576 | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,8 @@ | ||
#set the MAX_MEMORY to 1MB for these tests; there were lots of memory unit tests that assume such | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1048576 = 1024*1024 = 2^20, the comment should be |
||
|
||
add_wast_executable( TARGET test_api_mem | ||
INCLUDE_FOLDERS "${STANDARD_INCLUDE_FOLDERS}" | ||
LIBRARIES eosiolib | ||
DESTINATION_FOLDER ${CMAKE_CURRENT_BINARY_DIR} | ||
MAX_MEMORY 1048576 | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,11 +7,17 @@ namespace IR { | |
namespace eosio { namespace chain { | ||
|
||
namespace wasm_constraints { | ||
//Be aware that some of these are required to be a multiple of some internal number | ||
constexpr unsigned maximum_linear_memory = 1024*1024; //bytes | ||
constexpr unsigned maximum_mutable_globals = 1024; //bytes | ||
constexpr unsigned maximum_table_elements = 1024; //elements | ||
constexpr unsigned maximum_linear_memory_init = 64*1024; //bytes | ||
constexpr unsigned maximum_linear_memory = 33*1024*1024;//bytes | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. under |
||
constexpr unsigned maximum_mutable_globals = 1024; //bytes | ||
constexpr unsigned maximum_table_elements = 1024; //elements | ||
constexpr unsigned maximum_linear_memory_init = 64*1024; //bytes | ||
|
||
static constexpr unsigned wasm_page_size = 64*1024; | ||
|
||
static_assert(maximum_linear_memory%wasm_page_size == 0, "maximum_linear_memory must be mulitple of wasm page size"); | ||
static_assert(maximum_mutable_globals%4 == 0, "maximum_mutable_globals must be mulitple of 4"); | ||
static_assert(maximum_table_elements*8%4096 == 0, "maximum_table_elements*8 must be mulitple of 4096"); | ||
static_assert(maximum_linear_memory_init%wasm_page_size == 0, "maximum_linear_memory_init must be mulitple of wasm page size"); | ||
} | ||
|
||
//Throws if something in the module violates | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1031,17 +1031,17 @@ class memory_api : public context_aware_api { | |
return (char *)::memset( dest, value, length ); | ||
} | ||
|
||
uint32_t sbrk(int num_bytes) { | ||
int sbrk(int num_bytes) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typo: the return variable There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the return type of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I changed it to int to be a more clear indicator that |
||
// sbrk should only allow for memory to grow | ||
if (num_bytes < 0) | ||
throw eosio::chain::page_memory_error(); | ||
// TODO: omitted checktime function from previous version of sbrk, may need to be put back in at some point | ||
constexpr uint32_t NBPPL2 = IR::numBytesPerPageLog2; | ||
constexpr uint32_t MAX_MEM = 1024 * 1024; | ||
constexpr uint32_t MAX_MEM = wasm_constraints::maximum_linear_memory; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. increase the |
||
|
||
MemoryInstance* default_mem = Runtime::getDefaultMemory(code.instance); | ||
if(!default_mem) | ||
throw eosio::chain::page_memory_error(); | ||
return -1; | ||
|
||
const uint32_t num_pages = Runtime::getMemoryNumPages(default_mem); | ||
const uint32_t min_bytes = (num_pages << NBPPL2) > UINT32_MAX ? UINT32_MAX : num_pages << NBPPL2; | ||
|
@@ -1051,20 +1051,21 @@ class memory_api : public context_aware_api { | |
num_bytes = (num_bytes + 7) & ~7; | ||
|
||
if ((num_bytes > 0) && (prev_num_bytes > (MAX_MEM - num_bytes))) // test if allocating too much memory (overflowed) | ||
throw eosio::chain::page_memory_error(); | ||
return -1; | ||
else if ((num_bytes < 0) && (prev_num_bytes < (min_bytes - num_bytes))) // test for underflow | ||
throw eosio::chain::page_memory_error(); | ||
|
||
// update the number of bytes allocated, and compute the number of pages needed | ||
sbrk_bytes += num_bytes; | ||
const uint32_t num_desired_pages = (sbrk_bytes + IR::numBytesPerPage - 1) >> NBPPL2; | ||
const uint32_t num_desired_pages = (sbrk_bytes + num_bytes + IR::numBytesPerPage - 1) >> NBPPL2; | ||
|
||
// grow or shrink the memory to the desired number of pages | ||
if (num_desired_pages > num_pages) | ||
Runtime::growMemory(default_mem, num_desired_pages - num_pages); | ||
if(Runtime::growMemory(default_mem, num_desired_pages - num_pages) == -1) | ||
return -1; | ||
else if (num_desired_pages < num_pages) | ||
Runtime::shrinkMemory(default_mem, num_pages - num_desired_pages); | ||
if(Runtime::shrinkMemory(default_mem, num_pages - num_desired_pages) == -1) | ||
return -1; | ||
|
||
sbrk_bytes += num_bytes; | ||
return prev_num_bytes; | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MAX_MEMORY
is assigned value ontest_api/CMakeLists.txt
andtest_api_mem/CMakeLists.txt