Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename resize_memory to grow_memory, following the design. #134

Merged
merged 4 commits into from
Oct 14, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ml-proto/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ expr:
( <type>.<cvtop>/<type> <expr> )
( page_size )
( memory_size )
( resize_memory <expr> )
( grow_memory <expr> )

case:
( case <value> <expr>* fallthrough? ) ;; = (case <int> (block <expr>*) fallthrough?)
Expand Down
2 changes: 1 addition & 1 deletion ml-proto/TestingTodo.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Linear memory semantics:
- test loading "uninitialized" things from aliased stack frames return what's there
- test that loadwithoffset traps in overflow cases
- test that newly allocated memory is zeroed
- test that resize_memory does a full 32-bit unsigned check for page_size divisibility
- test that grow_memory does a full 32-bit unsigned check for page_size divisibility
- test that load/store addreses are full int32 (or int64), and not OCaml int
- test that when allocating 4GiB, accessing index -1 fails

Expand Down
2 changes: 1 addition & 1 deletion ml-proto/host/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ rule token = parse

| "page_size" { PAGE_SIZE }
| "memory_size" { MEMORY_SIZE }
| "resize_memory" { RESIZE_MEMORY }
| "grow_memory" { GROW_MEMORY }

| "func" { FUNC }
| "param" { PARAM }
Expand Down
4 changes: 2 additions & 2 deletions ml-proto/host/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ let anon_label c = {c with labels = VarMap.map ((+) 1) c.labels}
%token GET_LOCAL SET_LOCAL LOAD STORE
%token CONST UNARY BINARY COMPARE CONVERT
%token FUNC PARAM RESULT LOCAL MODULE MEMORY SEGMENT IMPORT EXPORT TABLE
%token PAGE_SIZE MEMORY_SIZE RESIZE_MEMORY
%token PAGE_SIZE MEMORY_SIZE GROW_MEMORY
%token ASSERT_INVALID ASSERT_RETURN ASSERT_RETURN_NAN ASSERT_TRAP INVOKE
%token EOF

Expand Down Expand Up @@ -202,7 +202,7 @@ expr1 :
| CONVERT expr { fun c -> convert ($1, $2 c) }
| PAGE_SIZE { fun c -> host (PageSize, []) }
| MEMORY_SIZE { fun c -> host (MemorySize, []) }
| RESIZE_MEMORY expr { fun c -> host (ResizeMemory, [$2 c]) }
| GROW_MEMORY expr { fun c -> host (GrowMemory, [$2 c]) }
;
expr_opt :
| /* empty */ { fun c -> None }
Expand Down
2 changes: 1 addition & 1 deletion ml-proto/spec/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type wrapop = {memop : memop; sz : Memory.mem_size}
type hostop =
| PageSize (* inquire host-defined page size *)
| MemorySize (* inquire current size of linear memory *)
| ResizeMemory (* resize linear memory *)
| GrowMemory (* grow linear memory *)


(* Expressions *)
Expand Down
2 changes: 1 addition & 1 deletion ml-proto/spec/check.ml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ let type_cvt at = function
let type_hostop = function
| PageSize -> {ins = []; out = Some Int32Type}
| MemorySize -> {ins = []; out = Some Int32Type}
| ResizeMemory -> {ins = [Int32Type]; out = None}
| GrowMemory -> {ins = [Int32Type]; out = None}


let type_func f =
Expand Down
28 changes: 20 additions & 8 deletions ml-proto/spec/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ end

let memory_error at = function
| Memory.Bounds -> error at "runtime: out of bounds memory access"
| Memory.Address -> error at "runtime: illegal address value"
| Memory.SizeOverflow -> error at "runtime: memory size overflow"
| exn -> raise exn

let type_error at v t =
Expand Down Expand Up @@ -104,6 +104,13 @@ let mem_size v at =
let i64 = Int64.of_int32 i32 in
Int64.shift_right_logical (Int64.shift_left i64 32) 32

(*
* Test whether x has a value which is an overflow in the memory type. Since
* we currently only support i32, just test that.
*)
let mem_overflow x =
I64.gt_u x (Int64.of_int32 Int32.max_int)

let callstack_exhaustion at =
error at ("runtime: callstack exhausted")

Expand Down Expand Up @@ -269,18 +276,23 @@ and coerce et vo =
and eval_hostop host mem hostop vs at =
match hostop, vs with
| PageSize, [] ->
assert (I64.lt_u host.page_size (Int64.of_int32 Int32.max_int));
Some (Int32 (Int64.to_int32 host.page_size))

| MemorySize, [] ->
assert (Memory.size mem < Int64.of_int32 Int32.max_int);
assert (I64.lt_u (Memory.size mem) (Int64.of_int32 Int32.max_int));
Some (Int32 (Int64.to_int32 (Memory.size mem)))

| ResizeMemory, [v] ->
let sz = mem_size v at in
if Int64.rem sz host.page_size <> 0L then
error at "runtime: resize_memory operand not multiple of page_size";
Memory.resize mem sz;
None
| GrowMemory, [v] ->
let delta = mem_size v at in
if I64.rem_u delta host.page_size <> 0L then
error at "runtime: grow_memory operand not multiple of page_size";
if I64.lt_u (Int64.add (Memory.size mem) delta) (Memory.size mem) then
error at "runtime: grow_memory overflow";
if mem_overflow (Int64.add (Memory.size mem) delta) then
error at "runtime: grow_memory overflow";
Memory.grow mem delta;
None;

| _, _ ->
error at "runtime: invalid invocation of host operator"
Expand Down
13 changes: 8 additions & 5 deletions ml-proto/spec/memory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ type t = memory

exception Type
exception Bounds
exception Address
exception SizeOverflow


(*
Expand Down Expand Up @@ -70,10 +70,13 @@ let init mem segs =
let size mem =
int64_of_host_size (Array1.dim !mem)

let resize mem n =
let after = create' n in
let min = host_index_of_int64 (min (size mem) n) 0 in
Array1.blit (Array1.sub !mem 0 min) (Array1.sub after 0 min);
let grow mem n =
let old_size = size mem in
let new_size = Int64.add old_size n in
if I64.gt_u old_size new_size then raise SizeOverflow else
let after = create' new_size in
let host_old_size = host_size_of_int64 old_size in
Array1.blit (Array1.sub !mem 0 host_old_size) (Array1.sub after 0 host_old_size);
mem := after

let rec loadn mem n a =
Expand Down
4 changes: 2 additions & 2 deletions ml-proto/spec/memory.mli
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ type value = Values.value

exception Type
exception Bounds
exception Address
exception SizeOverflow

val create : size -> memory
val init : memory -> segment list -> unit
val size : memory -> size
val resize : memory -> size -> unit
val grow : memory -> size -> unit
val load : memory -> address -> value_type -> value
val store : memory -> address -> value -> unit
val load_extend :
Expand Down
12 changes: 12 additions & 0 deletions ml-proto/test/memory_trap.wast
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@

(export "load" $load)
(func $load (param $i i32) (result i32) (i32.load (i32.add (memory_size) (get_local $i))))

(export "grow_memory" $grow_memory)
(func $grow_memory (param $i i32) (grow_memory (get_local $i)))

(export "overflow_memory_size" $overflow_memory_size)
(func $overflow_memory_size
(grow_memory (i32.xor (i32.const -1) (i32.sub (page_size) (i32.const 1))))
)
)

(assert_return (invoke "store" (i32.const -4) (i32.const 42)) (i32.const 42))
Expand All @@ -18,3 +26,7 @@
(assert_trap (invoke "load" (i32.const -1)) "runtime: out of bounds memory access")
(assert_trap (invoke "store" (i32.const 0) (i32.const 13)) "runtime: out of bounds memory access")
(assert_trap (invoke "load" (i32.const 0)) "runtime: out of bounds memory access")
(assert_trap (invoke "store" (i32.const 0x80000000) (i32.const 13)) "runtime: out of bounds memory access")
(assert_trap (invoke "load" (i32.const 0x80000000)) "runtime: out of bounds memory access")
(assert_trap (invoke "grow_memory" (i32.const 3)) "runtime: grow_memory operand not multiple of page_size")
(assert_trap (invoke "overflow_memory_size") "runtime: grow_memory overflow")
67 changes: 44 additions & 23 deletions ml-proto/test/resizing.wast
Original file line number Diff line number Diff line change
@@ -1,32 +1,53 @@
(module
(memory 4096)
(memory 0)

(export "load" $load)
(func $load (param $i i32) (result i32) (i32.load (get_local $i)))
(export "round_up_to_page" $round_up_to_page)
(func $round_up_to_page (param i32) (result i32)
(i32.and (i32.add (get_local 0) (i32.sub (page_size) (i32.const 1)))
(i32.sub (i32.const 0) (page_size)))
)

(export "store" $store)
(func $store (param $i i32) (param $v i32) (result i32) (i32.store (get_local $i) (get_local $v)))
(export "load_at_zero" $load_at_zero)
(func $load_at_zero (result i32) (i32.load (i32.const 0)))

(export "resize" $resize)
(func $resize (param $sz i32) (resize_memory (get_local $sz)))
(export "store_at_zero" $store_at_zero)
(func $store_at_zero (result i32) (i32.store (i32.const 0) (i32.const 2)))

(export "load_at_page_size" $load_at_page_size)
(func $load_at_page_size (result i32) (i32.load (page_size)))

(export "store_at_page_size" $store_at_page_size)
(func $store_at_page_size (result i32) (i32.store (page_size) (i32.const 3)))

(export "grow" $grow)
(func $grow (param $sz i32)
(grow_memory (call $round_up_to_page (get_local $sz)))
)

(export "size_at_least" $size_at_least)
(func $size_at_least (param i32) (result i32) (i32.ge_u (memory_size) (get_local 0)))

(export "size" $size)
(func $size (result i32) (memory_size))
)

(assert_return (invoke "size") (i32.const 4096))
(assert_return (invoke "store" (i32.const 0) (i32.const 42)) (i32.const 42))
(assert_return (invoke "load" (i32.const 0)) (i32.const 42))
(assert_trap (invoke "store" (i32.const 4096) (i32.const 42)) "runtime: out of bounds memory access")
(assert_trap (invoke "load" (i32.const 4096)) "runtime: out of bounds memory access")
(invoke "resize" (i32.const 8192))
(assert_return (invoke "size") (i32.const 8192))
(assert_return (invoke "load" (i32.const 0)) (i32.const 42))
(assert_return (invoke "load" (i32.const 4096)) (i32.const 0))
(assert_return (invoke "store" (i32.const 4096) (i32.const 43)) (i32.const 43))
(assert_return (invoke "load" (i32.const 4096)) (i32.const 43))
(invoke "resize" (i32.const 4096))
(assert_return (invoke "size") (i32.const 4096))
(assert_return (invoke "load" (i32.const 0)) (i32.const 42))
(assert_trap (invoke "store" (i32.const 4096) (i32.const 42)) "runtime: out of bounds memory access")
(assert_trap (invoke "load" (i32.const 4096)) "runtime: out of bounds memory access")
(assert_return (invoke "size") (i32.const 0))
(assert_return (invoke "size_at_least" (i32.const 0)) (i32.const 1))
(assert_trap (invoke "store_at_zero") "runtime: out of bounds memory access")
(assert_trap (invoke "load_at_zero") "runtime: out of bounds memory access")
(assert_trap (invoke "store_at_page_size") "runtime: out of bounds memory access")
(assert_trap (invoke "load_at_page_size") "runtime: out of bounds memory access")
(invoke "grow" (i32.const 4))
(assert_return (invoke "size_at_least" (i32.const 4)) (i32.const 1))
(assert_return (invoke "load_at_zero") (i32.const 0))
(assert_return (invoke "store_at_zero") (i32.const 2))
(assert_return (invoke "load_at_zero") (i32.const 2))
(assert_trap (invoke "store_at_page_size") "runtime: out of bounds memory access")
(assert_trap (invoke "load_at_page_size") "runtime: out of bounds memory access")
(invoke "grow" (i32.const 4))
(assert_return (invoke "size_at_least" (i32.const 8)) (i32.const 1))
(assert_return (invoke "load_at_zero") (i32.const 2))
(assert_return (invoke "store_at_zero") (i32.const 2))
(assert_return (invoke "load_at_page_size") (i32.const 0))
(assert_return (invoke "store_at_page_size") (i32.const 3))
(assert_return (invoke "load_at_page_size") (i32.const 3))