From cde56ef83d6f39d3e9d26fdeed1dc3e523432116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:06:28 +0200 Subject: [PATCH 01/16] asm marks --- lib/fizzy/execute.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 379abcb74..7cbbf7b3b 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -889,6 +889,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_eq: { + asm("/*i32_eq*/"); comparison_op(stack, std::equal_to()); break; } @@ -944,6 +945,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_eq: { + asm("/*i64_eq*/"); comparison_op(stack, std::equal_to()); break; } @@ -1057,6 +1059,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_clz: { + asm("/*i32_clz*/"); unary_op(stack, clz32); break; } @@ -1072,6 +1075,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_add: { + asm("/*i32_add*/"); binary_op(stack, add); break; } @@ -1167,6 +1171,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_clz: { + asm("/*i64_clz*/"); unary_op(stack, clz64); break; } @@ -1182,6 +1187,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_add: { + asm("/*i64_add*/"); binary_op(stack, add); break; } From b5ad06735054ad0988d9ebfc10bdf6ff1cae4f19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:07:43 +0200 Subject: [PATCH 02/16] unary_op --- lib/fizzy/execute.cpp | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 7cbbf7b3b..15c0ee583 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -154,11 +154,11 @@ inline void reinterpret(OperandStack& stack) noexcept } template -inline void unary_op(OperandStack& stack, Op op) noexcept +inline void unary_op(Value* sp, Op op) noexcept { using T = decltype(op({})); - const auto result = op(stack.top().as()); - stack.top() = Value{result}; // Convert to Value, also from signed integer types. + const auto result = op(sp->as()); + *sp = Value{result}; // Convert to Value, also from signed integer types. } template @@ -1060,17 +1060,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_clz: { asm("/*i32_clz*/"); - unary_op(stack, clz32); + unary_op(&stack.top(), clz32); break; } case Instr::i32_ctz: { - unary_op(stack, ctz32); + unary_op(&stack.top(), ctz32); break; } case Instr::i32_popcnt: { - unary_op(stack, popcnt32); + unary_op(&stack.top(), popcnt32); break; } case Instr::i32_add: @@ -1172,17 +1172,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_clz: { asm("/*i64_clz*/"); - unary_op(stack, clz64); + unary_op(&stack.top(), clz64); break; } case Instr::i64_ctz: { - unary_op(stack, ctz64); + unary_op(&stack.top(), ctz64); break; } case Instr::i64_popcnt: { - unary_op(stack, popcnt64); + unary_op(&stack.top(), popcnt64); break; } case Instr::i64_add: @@ -1283,37 +1283,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f32_abs: { - unary_op(stack, fabs); + unary_op(&stack.top(), fabs); break; } case Instr::f32_neg: { - unary_op(stack, fneg); + unary_op(&stack.top(), fneg); break; } case Instr::f32_ceil: { - unary_op(stack, fceil); + unary_op(&stack.top(), fceil); break; } case Instr::f32_floor: { - unary_op(stack, ffloor); + unary_op(&stack.top(), ffloor); break; } case Instr::f32_trunc: { - unary_op(stack, ftrunc); + unary_op(&stack.top(), ftrunc); break; } case Instr::f32_nearest: { - unary_op(stack, fnearest); + unary_op(&stack.top(), fnearest); break; } case Instr::f32_sqrt: { - unary_op(stack, static_cast(std::sqrt)); + unary_op(&stack.top(), static_cast(std::sqrt)); break; } @@ -1355,37 +1355,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f64_abs: { - unary_op(stack, fabs); + unary_op(&stack.top(), fabs); break; } case Instr::f64_neg: { - unary_op(stack, fneg); + unary_op(&stack.top(), fneg); break; } case Instr::f64_ceil: { - unary_op(stack, fceil); + unary_op(&stack.top(), fceil); break; } case Instr::f64_floor: { - unary_op(stack, ffloor); + unary_op(&stack.top(), ffloor); break; } case Instr::f64_trunc: { - unary_op(stack, ftrunc); + unary_op(&stack.top(), ftrunc); break; } case Instr::f64_nearest: { - unary_op(stack, fnearest); + unary_op(&stack.top(), fnearest); break; } case Instr::f64_sqrt: { - unary_op(stack, static_cast(std::sqrt)); + unary_op(&stack.top(), static_cast(std::sqrt)); break; } From d478dbb6e024e7cc8954f4e3113055c1b828056e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:18:03 +0200 Subject: [PATCH 03/16] binops --- lib/fizzy/execute.cpp | 81 ++++++++++++++++++++++--------------------- lib/fizzy/stack.hpp | 2 ++ 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 15c0ee583..4b554a0c1 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -162,13 +162,14 @@ inline void unary_op(Value* sp, Op op) noexcept } template -inline void binary_op(OperandStack& stack, Op op) noexcept +inline void binary_op(Value*& sp, Op op) noexcept { using T = decltype(op({}, {})); - const auto val2 = stack.pop().as(); - const auto val1 = stack.top().as(); + const auto val2 = sp->as(); + --sp; + const auto val1 = sp->as(); const auto result = op(val1, val2); - stack.top() = Value{result}; // Convert to Value, also from signed integer types. + *sp = Value{result}; // Convert to Value, also from signed integer types. } template class Op> @@ -1076,17 +1077,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_add: { asm("/*i32_add*/"); - binary_op(stack, add); + binary_op(stack.sp(), add); break; } case Instr::i32_sub: { - binary_op(stack, sub); + binary_op(stack.sp(), sub); break; } case Instr::i32_mul: { - binary_op(stack, mul); + binary_op(stack.sp(), mul); break; } case Instr::i32_div_s: @@ -1130,42 +1131,42 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_and: { - binary_op(stack, std::bit_and()); + binary_op(stack.sp(), std::bit_and()); break; } case Instr::i32_or: { - binary_op(stack, std::bit_or()); + binary_op(stack.sp(), std::bit_or()); break; } case Instr::i32_xor: { - binary_op(stack, std::bit_xor()); + binary_op(stack.sp(), std::bit_xor()); break; } case Instr::i32_shl: { - binary_op(stack, shift_left); + binary_op(stack.sp(), shift_left); break; } case Instr::i32_shr_s: { - binary_op(stack, shift_right); + binary_op(stack.sp(), shift_right); break; } case Instr::i32_shr_u: { - binary_op(stack, shift_right); + binary_op(stack.sp(), shift_right); break; } case Instr::i32_rotl: { - binary_op(stack, rotl); + binary_op(stack.sp(), rotl); break; } case Instr::i32_rotr: { - binary_op(stack, rotr); + binary_op(stack.sp(), rotr); break; } @@ -1188,17 +1189,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_add: { asm("/*i64_add*/"); - binary_op(stack, add); + binary_op(stack.sp(), add); break; } case Instr::i64_sub: { - binary_op(stack, sub); + binary_op(stack.sp(), sub); break; } case Instr::i64_mul: { - binary_op(stack, mul); + binary_op(stack.sp(), mul); break; } case Instr::i64_div_s: @@ -1242,42 +1243,42 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_and: { - binary_op(stack, std::bit_and()); + binary_op(stack.sp(), std::bit_and()); break; } case Instr::i64_or: { - binary_op(stack, std::bit_or()); + binary_op(stack.sp(), std::bit_or()); break; } case Instr::i64_xor: { - binary_op(stack, std::bit_xor()); + binary_op(stack.sp(), std::bit_xor()); break; } case Instr::i64_shl: { - binary_op(stack, shift_left); + binary_op(stack.sp(), shift_left); break; } case Instr::i64_shr_s: { - binary_op(stack, shift_right); + binary_op(stack.sp(), shift_right); break; } case Instr::i64_shr_u: { - binary_op(stack, shift_right); + binary_op(stack.sp(), shift_right); break; } case Instr::i64_rotl: { - binary_op(stack, rotl); + binary_op(stack.sp(), rotl); break; } case Instr::i64_rotr: { - binary_op(stack, rotr); + binary_op(stack.sp(), rotr); break; } @@ -1319,37 +1320,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f32_add: { - binary_op(stack, add); + binary_op(stack.sp(), add); break; } case Instr::f32_sub: { - binary_op(stack, sub); + binary_op(stack.sp(), sub); break; } case Instr::f32_mul: { - binary_op(stack, mul); + binary_op(stack.sp(), mul); break; } case Instr::f32_div: { - binary_op(stack, fdiv); + binary_op(stack.sp(), fdiv); break; } case Instr::f32_min: { - binary_op(stack, fmin); + binary_op(stack.sp(), fmin); break; } case Instr::f32_max: { - binary_op(stack, fmax); + binary_op(stack.sp(), fmax); break; } case Instr::f32_copysign: { - binary_op(stack, fcopysign); + binary_op(stack.sp(), fcopysign); break; } @@ -1391,37 +1392,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f64_add: { - binary_op(stack, add); + binary_op(stack.sp(), add); break; } case Instr::f64_sub: { - binary_op(stack, sub); + binary_op(stack.sp(), sub); break; } case Instr::f64_mul: { - binary_op(stack, mul); + binary_op(stack.sp(), mul); break; } case Instr::f64_div: { - binary_op(stack, fdiv); + binary_op(stack.sp(), fdiv); break; } case Instr::f64_min: { - binary_op(stack, fmin); + binary_op(stack.sp(), fmin); break; } case Instr::f64_max: { - binary_op(stack, fmax); + binary_op(stack.sp(), fmax); break; } case Instr::f64_copysign: { - binary_op(stack, fcopysign); + binary_op(stack.sp(), fcopysign); break; } diff --git a/lib/fizzy/stack.hpp b/lib/fizzy/stack.hpp index 5b11b78e2..203d1647d 100644 --- a/lib/fizzy/stack.hpp +++ b/lib/fizzy/stack.hpp @@ -138,6 +138,8 @@ class OperandStack return *m_top; } + Value*& sp() noexcept { return m_top; } + /// Returns the reference to the stack item on given position from the stack top. /// Requires index < size(). Value& operator[](size_t index) noexcept From fa840fb2dbfae210f1c555a601fb2cb738801859 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:21:32 +0200 Subject: [PATCH 04/16] cmp --- lib/fizzy/execute.cpp | 73 ++++++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 4b554a0c1..0da06a64e 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -173,11 +173,12 @@ inline void binary_op(Value*& sp, Op op) noexcept } template class Op> -inline void comparison_op(OperandStack& stack, Op op) noexcept +inline void comparison_op(Value*& sp, Op op) noexcept { - const auto val2 = stack.pop().as(); - const auto val1 = stack.top().as(); - stack.top() = uint32_t{op(val1, val2)}; + const auto val2 = sp->as(); + --sp; + const auto val1 = sp->as(); + *sp = uint32_t{op(val1, val2)}; } template @@ -891,52 +892,52 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_eq: { asm("/*i32_eq*/"); - comparison_op(stack, std::equal_to()); + comparison_op(stack.sp(), std::equal_to()); break; } case Instr::i32_ne: { - comparison_op(stack, std::not_equal_to()); + comparison_op(stack.sp(), std::not_equal_to()); break; } case Instr::i32_lt_s: { - comparison_op(stack, std::less()); + comparison_op(stack.sp(), std::less()); break; } case Instr::i32_lt_u: { - comparison_op(stack, std::less()); + comparison_op(stack.sp(), std::less()); break; } case Instr::i32_gt_s: { - comparison_op(stack, std::greater()); + comparison_op(stack.sp(), std::greater()); break; } case Instr::i32_gt_u: { - comparison_op(stack, std::greater()); + comparison_op(stack.sp(), std::greater()); break; } case Instr::i32_le_s: { - comparison_op(stack, std::less_equal()); + comparison_op(stack.sp(), std::less_equal()); break; } case Instr::i32_le_u: { - comparison_op(stack, std::less_equal()); + comparison_op(stack.sp(), std::less_equal()); break; } case Instr::i32_ge_s: { - comparison_op(stack, std::greater_equal()); + comparison_op(stack.sp(), std::greater_equal()); break; } case Instr::i32_ge_u: { - comparison_op(stack, std::greater_equal()); + comparison_op(stack.sp(), std::greater_equal()); break; } case Instr::i64_eqz: @@ -947,114 +948,114 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_eq: { asm("/*i64_eq*/"); - comparison_op(stack, std::equal_to()); + comparison_op(stack.sp(), std::equal_to()); break; } case Instr::i64_ne: { - comparison_op(stack, std::not_equal_to()); + comparison_op(stack.sp(), std::not_equal_to()); break; } case Instr::i64_lt_s: { - comparison_op(stack, std::less()); + comparison_op(stack.sp(), std::less()); break; } case Instr::i64_lt_u: { - comparison_op(stack, std::less()); + comparison_op(stack.sp(), std::less()); break; } case Instr::i64_gt_s: { - comparison_op(stack, std::greater()); + comparison_op(stack.sp(), std::greater()); break; } case Instr::i64_gt_u: { - comparison_op(stack, std::greater()); + comparison_op(stack.sp(), std::greater()); break; } case Instr::i64_le_s: { - comparison_op(stack, std::less_equal()); + comparison_op(stack.sp(), std::less_equal()); break; } case Instr::i64_le_u: { - comparison_op(stack, std::less_equal()); + comparison_op(stack.sp(), std::less_equal()); break; } case Instr::i64_ge_s: { - comparison_op(stack, std::greater_equal()); + comparison_op(stack.sp(), std::greater_equal()); break; } case Instr::i64_ge_u: { - comparison_op(stack, std::greater_equal()); + comparison_op(stack.sp(), std::greater_equal()); break; } case Instr::f32_eq: { - comparison_op(stack, std::equal_to()); + comparison_op(stack.sp(), std::equal_to()); break; } case Instr::f32_ne: { - comparison_op(stack, std::not_equal_to()); + comparison_op(stack.sp(), std::not_equal_to()); break; } case Instr::f32_lt: { - comparison_op(stack, std::less()); + comparison_op(stack.sp(), std::less()); break; } case Instr::f32_gt: { - comparison_op(stack, std::greater()); + comparison_op(stack.sp(), std::greater()); break; } case Instr::f32_le: { - comparison_op(stack, std::less_equal()); + comparison_op(stack.sp(), std::less_equal()); break; } case Instr::f32_ge: { - comparison_op(stack, std::greater_equal()); + comparison_op(stack.sp(), std::greater_equal()); break; } case Instr::f64_eq: { - comparison_op(stack, std::equal_to()); + comparison_op(stack.sp(), std::equal_to()); break; } case Instr::f64_ne: { - comparison_op(stack, std::not_equal_to()); + comparison_op(stack.sp(), std::not_equal_to()); break; } case Instr::f64_lt: { - comparison_op(stack, std::less()); + comparison_op(stack.sp(), std::less()); break; } case Instr::f64_gt: { - comparison_op(stack, std::greater()); + comparison_op(stack.sp(), std::greater()); break; } case Instr::f64_le: { - comparison_op(stack, std::less_equal()); + comparison_op(stack.sp(), std::less_equal()); break; } case Instr::f64_ge: { - comparison_op(stack, std::greater_equal()); + comparison_op(stack.sp(), std::greater_equal()); break; } From 57f86d278b8790c3c2af8846d53b260dd9675ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:22:30 +0200 Subject: [PATCH 05/16] sp var --- lib/fizzy/execute.cpp | 155 +++++++++++++++++++++--------------------- 1 file changed, 79 insertions(+), 76 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 0da06a64e..efd67715d 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -539,6 +539,9 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const Instr* pc = code.instructions.data(); const uint8_t* immediates = code.immediates.data(); + // FIXME: Remove reference. + auto& sp = stack.sp(); + while (true) { const auto instruction = *pc++; @@ -892,52 +895,52 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_eq: { asm("/*i32_eq*/"); - comparison_op(stack.sp(), std::equal_to()); + comparison_op(sp, std::equal_to()); break; } case Instr::i32_ne: { - comparison_op(stack.sp(), std::not_equal_to()); + comparison_op(sp, std::not_equal_to()); break; } case Instr::i32_lt_s: { - comparison_op(stack.sp(), std::less()); + comparison_op(sp, std::less()); break; } case Instr::i32_lt_u: { - comparison_op(stack.sp(), std::less()); + comparison_op(sp, std::less()); break; } case Instr::i32_gt_s: { - comparison_op(stack.sp(), std::greater()); + comparison_op(sp, std::greater()); break; } case Instr::i32_gt_u: { - comparison_op(stack.sp(), std::greater()); + comparison_op(sp, std::greater()); break; } case Instr::i32_le_s: { - comparison_op(stack.sp(), std::less_equal()); + comparison_op(sp, std::less_equal()); break; } case Instr::i32_le_u: { - comparison_op(stack.sp(), std::less_equal()); + comparison_op(sp, std::less_equal()); break; } case Instr::i32_ge_s: { - comparison_op(stack.sp(), std::greater_equal()); + comparison_op(sp, std::greater_equal()); break; } case Instr::i32_ge_u: { - comparison_op(stack.sp(), std::greater_equal()); + comparison_op(sp, std::greater_equal()); break; } case Instr::i64_eqz: @@ -948,114 +951,114 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_eq: { asm("/*i64_eq*/"); - comparison_op(stack.sp(), std::equal_to()); + comparison_op(sp, std::equal_to()); break; } case Instr::i64_ne: { - comparison_op(stack.sp(), std::not_equal_to()); + comparison_op(sp, std::not_equal_to()); break; } case Instr::i64_lt_s: { - comparison_op(stack.sp(), std::less()); + comparison_op(sp, std::less()); break; } case Instr::i64_lt_u: { - comparison_op(stack.sp(), std::less()); + comparison_op(sp, std::less()); break; } case Instr::i64_gt_s: { - comparison_op(stack.sp(), std::greater()); + comparison_op(sp, std::greater()); break; } case Instr::i64_gt_u: { - comparison_op(stack.sp(), std::greater()); + comparison_op(sp, std::greater()); break; } case Instr::i64_le_s: { - comparison_op(stack.sp(), std::less_equal()); + comparison_op(sp, std::less_equal()); break; } case Instr::i64_le_u: { - comparison_op(stack.sp(), std::less_equal()); + comparison_op(sp, std::less_equal()); break; } case Instr::i64_ge_s: { - comparison_op(stack.sp(), std::greater_equal()); + comparison_op(sp, std::greater_equal()); break; } case Instr::i64_ge_u: { - comparison_op(stack.sp(), std::greater_equal()); + comparison_op(sp, std::greater_equal()); break; } case Instr::f32_eq: { - comparison_op(stack.sp(), std::equal_to()); + comparison_op(sp, std::equal_to()); break; } case Instr::f32_ne: { - comparison_op(stack.sp(), std::not_equal_to()); + comparison_op(sp, std::not_equal_to()); break; } case Instr::f32_lt: { - comparison_op(stack.sp(), std::less()); + comparison_op(sp, std::less()); break; } case Instr::f32_gt: { - comparison_op(stack.sp(), std::greater()); + comparison_op(sp, std::greater()); break; } case Instr::f32_le: { - comparison_op(stack.sp(), std::less_equal()); + comparison_op(sp, std::less_equal()); break; } case Instr::f32_ge: { - comparison_op(stack.sp(), std::greater_equal()); + comparison_op(sp, std::greater_equal()); break; } case Instr::f64_eq: { - comparison_op(stack.sp(), std::equal_to()); + comparison_op(sp, std::equal_to()); break; } case Instr::f64_ne: { - comparison_op(stack.sp(), std::not_equal_to()); + comparison_op(sp, std::not_equal_to()); break; } case Instr::f64_lt: { - comparison_op(stack.sp(), std::less()); + comparison_op(sp, std::less()); break; } case Instr::f64_gt: { - comparison_op(stack.sp(), std::greater()); + comparison_op(sp, std::greater()); break; } case Instr::f64_le: { - comparison_op(stack.sp(), std::less_equal()); + comparison_op(sp, std::less_equal()); break; } case Instr::f64_ge: { - comparison_op(stack.sp(), std::greater_equal()); + comparison_op(sp, std::greater_equal()); break; } @@ -1078,17 +1081,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_add: { asm("/*i32_add*/"); - binary_op(stack.sp(), add); + binary_op(sp, add); break; } case Instr::i32_sub: { - binary_op(stack.sp(), sub); + binary_op(sp, sub); break; } case Instr::i32_mul: { - binary_op(stack.sp(), mul); + binary_op(sp, mul); break; } case Instr::i32_div_s: @@ -1097,7 +1100,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto lhs = stack.top().as(); if (rhs == 0 || (lhs == std::numeric_limits::min() && rhs == -1)) goto trap; - stack.top() = div(lhs, rhs); + *sp = div(lhs, rhs); break; } case Instr::i32_div_u: @@ -1106,7 +1109,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (rhs == 0) goto trap; const auto lhs = stack.top().as(); - stack.top() = div(lhs, rhs); + *sp = div(lhs, rhs); break; } case Instr::i32_rem_s: @@ -1118,7 +1121,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (lhs == std::numeric_limits::min() && rhs == -1) stack.top() = 0; else - stack.top() = rem(lhs, rhs); + *sp = rem(lhs, rhs); break; } case Instr::i32_rem_u: @@ -1127,47 +1130,47 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (rhs == 0) goto trap; const auto lhs = stack.top().as(); - stack.top() = rem(lhs, rhs); + *sp = rem(lhs, rhs); break; } case Instr::i32_and: { - binary_op(stack.sp(), std::bit_and()); + binary_op(sp, std::bit_and()); break; } case Instr::i32_or: { - binary_op(stack.sp(), std::bit_or()); + binary_op(sp, std::bit_or()); break; } case Instr::i32_xor: { - binary_op(stack.sp(), std::bit_xor()); + binary_op(sp, std::bit_xor()); break; } case Instr::i32_shl: { - binary_op(stack.sp(), shift_left); + binary_op(sp, shift_left); break; } case Instr::i32_shr_s: { - binary_op(stack.sp(), shift_right); + binary_op(sp, shift_right); break; } case Instr::i32_shr_u: { - binary_op(stack.sp(), shift_right); + binary_op(sp, shift_right); break; } case Instr::i32_rotl: { - binary_op(stack.sp(), rotl); + binary_op(sp, rotl); break; } case Instr::i32_rotr: { - binary_op(stack.sp(), rotr); + binary_op(sp, rotr); break; } @@ -1190,17 +1193,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_add: { asm("/*i64_add*/"); - binary_op(stack.sp(), add); + binary_op(sp, add); break; } case Instr::i64_sub: { - binary_op(stack.sp(), sub); + binary_op(sp, sub); break; } case Instr::i64_mul: { - binary_op(stack.sp(), mul); + binary_op(sp, mul); break; } case Instr::i64_div_s: @@ -1209,7 +1212,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto lhs = stack.top().as(); if (rhs == 0 || (lhs == std::numeric_limits::min() && rhs == -1)) goto trap; - stack.top() = div(lhs, rhs); + *sp = div(lhs, rhs); break; } case Instr::i64_div_u: @@ -1218,7 +1221,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (rhs == 0) goto trap; const auto lhs = stack.top().i64; - stack.top() = div(lhs, rhs); + *sp = div(lhs, rhs); break; } case Instr::i64_rem_s: @@ -1230,7 +1233,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (lhs == std::numeric_limits::min() && rhs == -1) stack.top() = 0; else - stack.top() = rem(lhs, rhs); + *sp = rem(lhs, rhs); break; } case Instr::i64_rem_u: @@ -1239,47 +1242,47 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (rhs == 0) goto trap; const auto lhs = stack.top().i64; - stack.top() = rem(lhs, rhs); + *sp = rem(lhs, rhs); break; } case Instr::i64_and: { - binary_op(stack.sp(), std::bit_and()); + binary_op(sp, std::bit_and()); break; } case Instr::i64_or: { - binary_op(stack.sp(), std::bit_or()); + binary_op(sp, std::bit_or()); break; } case Instr::i64_xor: { - binary_op(stack.sp(), std::bit_xor()); + binary_op(sp, std::bit_xor()); break; } case Instr::i64_shl: { - binary_op(stack.sp(), shift_left); + binary_op(sp, shift_left); break; } case Instr::i64_shr_s: { - binary_op(stack.sp(), shift_right); + binary_op(sp, shift_right); break; } case Instr::i64_shr_u: { - binary_op(stack.sp(), shift_right); + binary_op(sp, shift_right); break; } case Instr::i64_rotl: { - binary_op(stack.sp(), rotl); + binary_op(sp, rotl); break; } case Instr::i64_rotr: { - binary_op(stack.sp(), rotr); + binary_op(sp, rotr); break; } @@ -1321,37 +1324,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f32_add: { - binary_op(stack.sp(), add); + binary_op(sp, add); break; } case Instr::f32_sub: { - binary_op(stack.sp(), sub); + binary_op(sp, sub); break; } case Instr::f32_mul: { - binary_op(stack.sp(), mul); + binary_op(sp, mul); break; } case Instr::f32_div: { - binary_op(stack.sp(), fdiv); + binary_op(sp, fdiv); break; } case Instr::f32_min: { - binary_op(stack.sp(), fmin); + binary_op(sp, fmin); break; } case Instr::f32_max: { - binary_op(stack.sp(), fmax); + binary_op(sp, fmax); break; } case Instr::f32_copysign: { - binary_op(stack.sp(), fcopysign); + binary_op(sp, fcopysign); break; } @@ -1393,37 +1396,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f64_add: { - binary_op(stack.sp(), add); + binary_op(sp, add); break; } case Instr::f64_sub: { - binary_op(stack.sp(), sub); + binary_op(sp, sub); break; } case Instr::f64_mul: { - binary_op(stack.sp(), mul); + binary_op(sp, mul); break; } case Instr::f64_div: { - binary_op(stack.sp(), fdiv); + binary_op(sp, fdiv); break; } case Instr::f64_min: { - binary_op(stack.sp(), fmin); + binary_op(sp, fmin); break; } case Instr::f64_max: { - binary_op(stack.sp(), fmax); + binary_op(sp, fmax); break; } case Instr::f64_copysign: { - binary_op(stack.sp(), fcopysign); + binary_op(sp, fcopysign); break; } From 3e459a4ae6b1f3a66badc962fd0fef45da64d73c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:28:09 +0200 Subject: [PATCH 06/16] branch --- lib/fizzy/execute.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index efd67715d..db299cbbd 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -458,7 +458,7 @@ __attribute__((no_sanitize("float-cast-overflow"))) inline constexpr float demot return static_cast(value); } -void branch(const Code& code, OperandStack& stack, const Instr*& pc, const uint8_t*& immediates, +void branch(const Code& code, Value*& sp, const Instr*& pc, const uint8_t*& immediates, uint32_t arity) noexcept { const auto code_offset = read(immediates); @@ -470,16 +470,16 @@ void branch(const Code& code, OperandStack& stack, const Instr*& pc, const uint8 // When branch is taken, additional stack items must be dropped. assert(static_cast(stack_drop) >= 0); - assert(stack.size() >= stack_drop + arity); + // assert(stack.size() >= stack_drop + arity); if (arity != 0) { assert(arity == 1); - const auto result = stack.top(); - stack.drop(stack_drop); - stack.top() = result; + const auto result = *sp; + sp -= stack_drop; + *sp = result; } else - stack.drop(stack_drop); + sp -= stack_drop; } template @@ -599,7 +599,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, break; } - branch(code, stack, pc, immediates, arity); + branch(code, sp, pc, immediates, arity); break; } case Instr::br_table: @@ -614,7 +614,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, br_table_size * BranchImmediateSize; immediates += label_idx_offset; - branch(code, stack, pc, immediates, arity); + branch(code, sp, pc, immediates, arity); break; } case Instr::call: From 461ac43de69fb0738384962858be4a949d7b7c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:29:01 +0200 Subject: [PATCH 07/16] sp var --- lib/fizzy/execute.cpp | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index db299cbbd..60ed00d37 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -1065,17 +1065,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_clz: { asm("/*i32_clz*/"); - unary_op(&stack.top(), clz32); + unary_op(sp, clz32); break; } case Instr::i32_ctz: { - unary_op(&stack.top(), ctz32); + unary_op(sp, ctz32); break; } case Instr::i32_popcnt: { - unary_op(&stack.top(), popcnt32); + unary_op(sp, popcnt32); break; } case Instr::i32_add: @@ -1177,17 +1177,17 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i64_clz: { asm("/*i64_clz*/"); - unary_op(&stack.top(), clz64); + unary_op(sp, clz64); break; } case Instr::i64_ctz: { - unary_op(&stack.top(), ctz64); + unary_op(sp, ctz64); break; } case Instr::i64_popcnt: { - unary_op(&stack.top(), popcnt64); + unary_op(sp, popcnt64); break; } case Instr::i64_add: @@ -1288,37 +1288,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f32_abs: { - unary_op(&stack.top(), fabs); + unary_op(sp, fabs); break; } case Instr::f32_neg: { - unary_op(&stack.top(), fneg); + unary_op(sp, fneg); break; } case Instr::f32_ceil: { - unary_op(&stack.top(), fceil); + unary_op(sp, fceil); break; } case Instr::f32_floor: { - unary_op(&stack.top(), ffloor); + unary_op(sp, ffloor); break; } case Instr::f32_trunc: { - unary_op(&stack.top(), ftrunc); + unary_op(sp, ftrunc); break; } case Instr::f32_nearest: { - unary_op(&stack.top(), fnearest); + unary_op(sp, fnearest); break; } case Instr::f32_sqrt: { - unary_op(&stack.top(), static_cast(std::sqrt)); + unary_op(sp, static_cast(std::sqrt)); break; } @@ -1360,37 +1360,37 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::f64_abs: { - unary_op(&stack.top(), fabs); + unary_op(sp, fabs); break; } case Instr::f64_neg: { - unary_op(&stack.top(), fneg); + unary_op(sp, fneg); break; } case Instr::f64_ceil: { - unary_op(&stack.top(), fceil); + unary_op(sp, fceil); break; } case Instr::f64_floor: { - unary_op(&stack.top(), ffloor); + unary_op(sp, ffloor); break; } case Instr::f64_trunc: { - unary_op(&stack.top(), ftrunc); + unary_op(sp, ftrunc); break; } case Instr::f64_nearest: { - unary_op(&stack.top(), fnearest); + unary_op(sp, fnearest); break; } case Instr::f64_sqrt: { - unary_op(&stack.top(), static_cast(std::sqrt)); + unary_op(sp, static_cast(std::sqrt)); break; } From 23829bb0a3d94e15c59bb4a5cf84b9ed374d1697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:36:17 +0200 Subject: [PATCH 08/16] free stack.top() --- lib/fizzy/execute.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 60ed00d37..bb73d9424 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -683,7 +683,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::local_tee: { const auto idx = read(immediates); - stack.local(idx) = stack.top(); + stack.local(idx) = *sp; break; } case Instr::global_get: @@ -1515,7 +1515,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::f32_demote_f64: { - stack.top() = demote(stack.top().f64); + *sp = demote(sp->f64); break; } case Instr::f64_convert_i32_s: @@ -1540,7 +1540,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::f64_promote_f32: { - stack.top() = double{stack.top().f32}; + *sp = double{sp->f32}; break; } case Instr::i32_reinterpret_f32: From 4d4d8019b7089929d92a95935f1f8dd749479f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:39:00 +0200 Subject: [PATCH 09/16] memory --- lib/fizzy/execute.cpp | 56 +++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index bb73d9424..ac0e6a540 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -63,10 +63,9 @@ inline constexpr DstT extend(SrcT in) noexcept } template -inline bool load_from_memory( - bytes_view memory, OperandStack& stack, const uint8_t*& immediates) noexcept +inline bool load_from_memory(bytes_view memory, Value* sp, const uint8_t*& immediates) noexcept { - const auto address = stack.top().as(); + const auto address = sp->as(); // NOTE: alignment is dropped by the parser const auto offset = read(immediates); // Addressing is 32-bit, but we keep the value as 64-bit to detect overflows. @@ -74,7 +73,7 @@ inline bool load_from_memory( return false; const auto ret = load(memory, address + offset); - stack.top() = extend(ret); + *sp = extend(ret); return true; } @@ -93,11 +92,10 @@ inline constexpr DstT shrink(Value value) noexcept } template -inline bool store_into_memory( - bytes& memory, OperandStack& stack, const uint8_t*& immediates) noexcept +inline bool store_into_memory(bytes& memory, Value*& sp, const uint8_t*& immediates) noexcept { - const auto value = shrink(stack.pop()); - const auto address = stack.pop().as(); + const auto value = shrink(*sp--); + const auto address = sp--->as(); // NOTE: alignment is dropped by the parser const auto offset = read(immediates); // Addressing is 32-bit, but we keep the value as 64-bit to detect overflows. @@ -721,129 +719,129 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_load: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::f32_load: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::f64_load: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_load8_s: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_load8_u: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_load16_s: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_load16_u: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load8_s: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load8_u: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load16_s: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load16_u: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load32_s: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_load32_u: { - if (!load_from_memory(*memory, stack, immediates)) + if (!load_from_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_store: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_store: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } case Instr::f32_store: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } case Instr::f64_store: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_store8: case Instr::i64_store8: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i32_store16: case Instr::i64_store16: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } case Instr::i64_store32: { - if (!store_into_memory(*memory, stack, immediates)) + if (!store_into_memory(*memory, sp, immediates)) goto trap; break; } From 6c0d42d7afb01c4206fca471953552185813a7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:41:24 +0200 Subject: [PATCH 10/16] convert --- lib/fizzy/execute.cpp | 56 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index ac0e6a540..cb1ed468f 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -108,19 +108,19 @@ inline bool store_into_memory(bytes& memory, Value*& sp, const uint8_t*& immedia /// Converts the top stack item by truncating a float value to an integer value. template -inline bool trunc(OperandStack& stack) noexcept +inline bool trunc(Value* sp) noexcept { static_assert(std::is_floating_point_v); static_assert(std::is_integral_v); using boundaries = trunc_boundaries; - const auto input = stack.top().as(); + const auto input = sp->as(); if (input > boundaries::lower && input < boundaries::upper) { assert(!std::isnan(input)); assert(input != std::numeric_limits::infinity()); assert(input != -std::numeric_limits::infinity()); - stack.top() = static_cast(input); + *sp = static_cast(input); return true; } return false; @@ -128,11 +128,11 @@ inline bool trunc(OperandStack& stack) noexcept /// Converts the top stack item from an integer value to a float value. template -inline void convert(OperandStack& stack) noexcept +inline void convert(Value* sp) noexcept { static_assert(std::is_integral_v); static_assert(std::is_floating_point_v); - stack.top() = static_cast(stack.top().as()); + *sp = static_cast(sp->as()); } /// Performs a bit_cast from SrcT type to DstT type. @@ -140,15 +140,15 @@ inline void convert(OperandStack& stack) noexcept /// This should be optimized to empty function in assembly. Except for f32 -> i32 where pushing /// the result i32 value to the stack requires zero-extension to 64-bit. template -inline void reinterpret(OperandStack& stack) noexcept +inline void reinterpret(Value* sp) noexcept { static_assert(std::is_integral_v == std::is_floating_point_v || std::is_floating_point_v == std::is_integral_v); static_assert(sizeof(SrcT) == sizeof(DstT)); - const auto src = stack.top().as(); + const auto src = sp->as(); DstT dst; __builtin_memcpy(&dst, &src, sizeof(dst)); - stack.top() = dst; + *sp = dst; } template @@ -1435,25 +1435,25 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_trunc_f32_s: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::i32_trunc_f32_u: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::i32_trunc_f64_s: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::i32_trunc_f64_u: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } @@ -1469,46 +1469,46 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_trunc_f32_s: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::i64_trunc_f32_u: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::i64_trunc_f64_s: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::i64_trunc_f64_u: { - if (!trunc(stack)) + if (!trunc(sp)) goto trap; break; } case Instr::f32_convert_i32_s: { - convert(stack); + convert(sp); break; } case Instr::f32_convert_i32_u: { - convert(stack); + convert(sp); break; } case Instr::f32_convert_i64_s: { - convert(stack); + convert(sp); break; } case Instr::f32_convert_i64_u: { - convert(stack); + convert(sp); break; } case Instr::f32_demote_f64: @@ -1518,22 +1518,22 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::f64_convert_i32_s: { - convert(stack); + convert(sp); break; } case Instr::f64_convert_i32_u: { - convert(stack); + convert(sp); break; } case Instr::f64_convert_i64_s: { - convert(stack); + convert(sp); break; } case Instr::f64_convert_i64_u: { - convert(stack); + convert(sp); break; } case Instr::f64_promote_f32: @@ -1543,22 +1543,22 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_reinterpret_f32: { - reinterpret(stack); + reinterpret(sp); break; } case Instr::i64_reinterpret_f64: { - reinterpret(stack); + reinterpret(sp); break; } case Instr::f32_reinterpret_i32: { - reinterpret(stack); + reinterpret(sp); break; } case Instr::f64_reinterpret_i64: { - reinterpret(stack); + reinterpret(sp); break; } From a0660a61435de369be201eb53d99533f7f1a2937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:43:28 +0200 Subject: [PATCH 11/16] free stack.pop() --- lib/fizzy/execute.cpp | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index cb1ed468f..c75235ad3 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -553,7 +553,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, break; case Instr::if_: { - if (stack.pop().as() != 0) + if (sp--->as() != 0) immediates += 2 * sizeof(uint32_t); // Skip the immediates for else instruction. else { @@ -591,7 +591,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto arity = read(immediates); // Check condition for br_if. - if (instruction == Instr::br_if && stack.pop().as() == 0) + if (instruction == Instr::br_if && sp--->as() == 0) { immediates += BranchImmediateSize; break; @@ -605,7 +605,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto br_table_size = read(immediates); const auto arity = read(immediates); - const auto br_table_idx = stack.pop().as(); + const auto br_table_idx = sp--->as(); const auto label_idx_offset = br_table_idx < br_table_size ? br_table_idx * BranchImmediateSize : @@ -631,7 +631,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto expected_type_idx = read(immediates); assert(expected_type_idx < instance.module->typesec.size()); - const auto elem_idx = stack.pop().as(); + const auto elem_idx = sp--->as(); if (elem_idx >= instance.table->size()) goto trap; @@ -651,15 +651,15 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::drop: { - stack.pop(); + --sp; break; } case Instr::select: { - const auto condition = stack.pop().as(); + const auto condition = sp--->as(); // NOTE: these two are the same type (ensured by validation) - const auto val2 = stack.pop(); - const auto val1 = stack.pop(); + const auto val2 = *sp--; + const auto val1 = *sp--; if (condition == 0) stack.push(val2); else @@ -675,7 +675,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::local_set: { const auto idx = read(immediates); - stack.local(idx) = stack.pop(); + stack.local(idx) = *sp--; break; } case Instr::local_tee: @@ -706,14 +706,14 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (idx < instance.imported_globals.size()) { assert(instance.imported_globals[idx].type.is_mutable); - *instance.imported_globals[idx].value = stack.pop(); + *instance.imported_globals[idx].value = *sp--; } else { const auto module_global_idx = idx - instance.imported_globals.size(); assert(module_global_idx < instance.module->globalsec.size()); assert(instance.module->globalsec[module_global_idx].type.is_mutable); - instance.globals[module_global_idx] = stack.pop(); + instance.globals[module_global_idx] = *sp--; } break; } @@ -852,7 +852,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::memory_grow: { - const auto delta = stack.pop().as(); + const auto delta = sp--->as(); const auto cur_pages = memory->size() / PageSize; assert(cur_pages <= size_t(std::numeric_limits::max())); const auto new_pages = cur_pages + delta; @@ -887,7 +887,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_eqz: { - stack.top() = uint32_t{stack.top().as() == 0}; + *sp = uint32_t{sp->as() == 0}; break; } case Instr::i32_eq: @@ -943,7 +943,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_eqz: { - stack.top() = uint32_t{stack.top().i64 == 0}; + *sp = uint32_t{sp->i64 == 0}; break; } case Instr::i64_eq: @@ -1117,7 +1117,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, goto trap; const auto lhs = stack.top().as(); if (lhs == std::numeric_limits::min() && rhs == -1) - stack.top() = 0; + *sp = 0; else *sp = rem(lhs, rhs); break; @@ -1229,7 +1229,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, goto trap; const auto lhs = stack.top().as(); if (lhs == std::numeric_limits::min() && rhs == -1) - stack.top() = 0; + *sp = 0; else *sp = rem(lhs, rhs); break; @@ -1430,7 +1430,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::i32_wrap_i64: { - stack.top() = static_cast(stack.top().i64); + *sp = static_cast(sp->i64); break; } case Instr::i32_trunc_f32_s: @@ -1459,7 +1459,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_extend_i32_s: { - stack.top() = int64_t{stack.top().as()}; + *sp = int64_t{sp->as()}; break; } case Instr::i64_extend_i32_u: @@ -1572,7 +1572,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, assert(pc == &code.instructions[code.instructions.size()]); // End of code must be reached. assert(stack.size() == instance.module->get_function_type(func_idx).outputs.size()); - return stack.size() != 0 ? ExecutionResult{stack.top()} : Void; + return stack.size() != 0 ? ExecutionResult{*sp} : Void; trap: return Trap; From 5f560139b17148351320713037d9355438340f5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:51:12 +0200 Subject: [PATCH 12/16] free stack.push() --- lib/fizzy/execute.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index c75235ad3..5247ce511 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -661,15 +661,15 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto val2 = *sp--; const auto val1 = *sp--; if (condition == 0) - stack.push(val2); + *++sp = (val2); else - stack.push(val1); + *++sp = (val1); break; } case Instr::local_get: { const auto idx = read(immediates); - stack.push(stack.local(idx)); + *++sp = (stack.local(idx)); break; } case Instr::local_set: @@ -690,13 +690,13 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, assert(idx < instance.imported_globals.size() + instance.globals.size()); if (idx < instance.imported_globals.size()) { - stack.push(*instance.imported_globals[idx].value); + *++sp = (*instance.imported_globals[idx].value); } else { const auto module_global_idx = idx - instance.imported_globals.size(); assert(module_global_idx < instance.module->globalsec.size()); - stack.push(instance.globals[module_global_idx]); + *++sp = (instance.globals[module_global_idx]); } break; } @@ -847,7 +847,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::memory_size: { - stack.push(static_cast(memory->size() / PageSize)); + *++sp = (static_cast(memory->size() / PageSize)); break; } case Instr::memory_grow: @@ -868,21 +868,21 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, { ret = static_cast(-1); } - stack.push(ret); + *++sp = (ret); break; } case Instr::i32_const: case Instr::f32_const: { const auto value = read(immediates); - stack.push(value); + *++sp = (value); break; } case Instr::i64_const: case Instr::f64_const: { const auto value = read(immediates); - stack.push(value); + *++sp = (value); break; } case Instr::i32_eqz: From 868e24af7d9da35c7c172ad8ef7b6021d29d62ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:55:34 +0200 Subject: [PATCH 13/16] invoke --- lib/fizzy/execute.cpp | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 5247ce511..f44e6e3f7 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -482,18 +482,17 @@ void branch(const Code& code, Value*& sp, const Instr*& pc, const uint8_t*& imme template inline bool invoke_function( - const FuncType& func_type, const F& func, Instance& instance, OperandStack& stack, int depth) + const FuncType& func_type, const F& func, Instance& instance, Value*& sp, int depth) { const auto num_args = func_type.inputs.size(); - assert(stack.size() >= num_args); - const auto call_args = stack.rend() - num_args; + const auto call_args = sp + 1 - num_args; const auto ret = func(instance, call_args, depth + 1); // Bubble up traps if (ret.trapped) return false; - stack.drop(num_args); + sp -= num_args; const auto num_outputs = func_type.outputs.size(); // NOTE: we can assume these two from validation @@ -501,18 +500,18 @@ inline bool invoke_function( assert(ret.has_value == (num_outputs == 1)); // Push back the result if (num_outputs != 0) - stack.push(ret.value); + *++sp = (ret.value); return true; } -inline bool invoke_function(const FuncType& func_type, uint32_t func_idx, Instance& instance, - OperandStack& stack, int depth) +inline bool invoke_function( + const FuncType& func_type, uint32_t func_idx, Instance& instance, Value*& sp, int depth) { const auto func = [func_idx](Instance& _instance, const Value* args, int _depth) { return execute(_instance, func_idx, args, _depth); }; - return invoke_function(func_type, func, instance, stack, depth); + return invoke_function(func_type, func, instance, sp, depth); } } // namespace @@ -620,7 +619,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto called_func_idx = read(immediates); const auto& called_func_type = instance.module->get_function_type(called_func_idx); - if (!invoke_function(called_func_type, called_func_idx, instance, stack, depth)) + if (!invoke_function(called_func_type, called_func_idx, instance, sp, depth)) goto trap; break; } @@ -645,7 +644,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, if (expected_type != actual_type) goto trap; - if (!invoke_function(actual_type, called_func->function, instance, stack, depth)) + if (!invoke_function(actual_type, called_func->function, instance, sp, depth)) goto trap; break; } From 32d2872ccb3b77af25d1889d9f8523091e0695e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:56:45 +0200 Subject: [PATCH 14/16] bottom --- lib/fizzy/execute.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index f44e6e3f7..019f372b2 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -538,6 +538,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, // FIXME: Remove reference. auto& sp = stack.sp(); + const auto bottom = sp; while (true) { @@ -1571,7 +1572,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, assert(pc == &code.instructions[code.instructions.size()]); // End of code must be reached. assert(stack.size() == instance.module->get_function_type(func_idx).outputs.size()); - return stack.size() != 0 ? ExecutionResult{*sp} : Void; + return sp != bottom ? ExecutionResult{*sp} : Void; trap: return Trap; From 60fadd3c4fb16bfc2bc54703586a385bc3a57446 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 20:59:23 +0200 Subject: [PATCH 15/16] _stack --- lib/fizzy/execute.cpp | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index 019f372b2..c759f99b2 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -530,14 +530,14 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const auto& code = instance.module->get_code(func_idx); auto* const memory = instance.memory.get(); - OperandStack stack(args, func_type.inputs.size(), code.local_count, + OperandStack _stack(args, func_type.inputs.size(), code.local_count, static_cast(code.max_stack_height)); const Instr* pc = code.instructions.data(); const uint8_t* immediates = code.immediates.data(); // FIXME: Remove reference. - auto& sp = stack.sp(); + auto& sp = _stack.sp(); const auto bottom = sp; while (true) @@ -669,19 +669,19 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, case Instr::local_get: { const auto idx = read(immediates); - *++sp = (stack.local(idx)); + *++sp = (_stack.local(idx)); break; } case Instr::local_set: { const auto idx = read(immediates); - stack.local(idx) = *sp--; + _stack.local(idx) = *sp--; break; } case Instr::local_tee: { const auto idx = read(immediates); - stack.local(idx) = *sp; + _stack.local(idx) = *sp; break; } case Instr::global_get: @@ -1094,8 +1094,8 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_div_s: { - const auto rhs = stack.pop().as(); - const auto lhs = stack.top().as(); + const auto rhs = sp--->as(); + const auto lhs = sp->as(); if (rhs == 0 || (lhs == std::numeric_limits::min() && rhs == -1)) goto trap; *sp = div(lhs, rhs); @@ -1103,19 +1103,19 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_div_u: { - const auto rhs = stack.pop().as(); + const auto rhs = sp--->as(); if (rhs == 0) goto trap; - const auto lhs = stack.top().as(); + const auto lhs = sp->as(); *sp = div(lhs, rhs); break; } case Instr::i32_rem_s: { - const auto rhs = stack.pop().as(); + const auto rhs = sp--->as(); if (rhs == 0) goto trap; - const auto lhs = stack.top().as(); + const auto lhs = sp->as(); if (lhs == std::numeric_limits::min() && rhs == -1) *sp = 0; else @@ -1124,10 +1124,10 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i32_rem_u: { - const auto rhs = stack.pop().as(); + const auto rhs = sp--->as(); if (rhs == 0) goto trap; - const auto lhs = stack.top().as(); + const auto lhs = sp->as(); *sp = rem(lhs, rhs); break; } @@ -1206,8 +1206,8 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_div_s: { - const auto rhs = stack.pop().as(); - const auto lhs = stack.top().as(); + const auto rhs = sp--->as(); + const auto lhs = sp->as(); if (rhs == 0 || (lhs == std::numeric_limits::min() && rhs == -1)) goto trap; *sp = div(lhs, rhs); @@ -1215,19 +1215,19 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_div_u: { - const auto rhs = stack.pop().i64; + const auto rhs = sp--->i64; if (rhs == 0) goto trap; - const auto lhs = stack.top().i64; + const auto lhs = sp->i64; *sp = div(lhs, rhs); break; } case Instr::i64_rem_s: { - const auto rhs = stack.pop().as(); + const auto rhs = sp--->as(); if (rhs == 0) goto trap; - const auto lhs = stack.top().as(); + const auto lhs = sp->as(); if (lhs == std::numeric_limits::min() && rhs == -1) *sp = 0; else @@ -1236,10 +1236,10 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, } case Instr::i64_rem_u: { - const auto rhs = stack.pop().i64; + const auto rhs = sp--->i64; if (rhs == 0) goto trap; - const auto lhs = stack.top().i64; + const auto lhs = sp->i64; *sp = rem(lhs, rhs); break; } @@ -1570,7 +1570,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, end: assert(pc == &code.instructions[code.instructions.size()]); // End of code must be reached. - assert(stack.size() == instance.module->get_function_type(func_idx).outputs.size()); + // assert(stack.size() == instance.module->get_function_type(func_idx).outputs.size()); return sp != bottom ? ExecutionResult{*sp} : Void; From 4f86b8b804eb8ab0a6de8b4586755ba32fde21ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 5 Oct 2020 21:00:05 +0200 Subject: [PATCH 16/16] remove ref --- lib/fizzy/execute.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index c759f99b2..d1f725571 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -537,7 +537,7 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, const Value* args, const uint8_t* immediates = code.immediates.data(); // FIXME: Remove reference. - auto& sp = _stack.sp(); + auto sp = _stack.sp(); const auto bottom = sp; while (true)