summaryrefslogtreecommitdiff
path: root/src/wasm-type.h
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2020-04-13 14:02:58 -0700
committerGitHub <noreply@github.com>2020-04-13 14:02:58 -0700
commitc16bfeebb5879e9512f2bbf7d611b3b1e0be7dee (patch)
treeb31308a321e869d2bf64ddbffc0a59e91df80d62 /src/wasm-type.h
parentc45ae16497ea76ad24982813cace1927565b0d45 (diff)
downloadbinaryen-c16bfeebb5879e9512f2bbf7d611b3b1e0be7dee.tar.gz
binaryen-c16bfeebb5879e9512f2bbf7d611b3b1e0be7dee.tar.bz2
binaryen-c16bfeebb5879e9512f2bbf7d611b3b1e0be7dee.zip
Use direct pointers as Type IDs (#2745)
Instead of using indices into the global interned type table. This means that a lock is *never* needed to access an expanded Type. The Type lock is now only acquired when a complex Type is created. On a real-world wasm2js workload this improves wall clock time by 23% on my machine with 72 cores and makes traffic on the Type lock entirely insignificant. **Before** 72 cores real 0m6.914s user 184.014s sys 0m3.995s 1 core real 0m25.903s user 0m25.658s sys 0m0.253s **After** 72 cores real 5.349s user 70.309s sys 9.691s 1 core real 25.859s user 25.615s sys 0.253s
Diffstat (limited to 'src/wasm-type.h')
-rw-r--r--src/wasm-type.h28
1 files changed, 13 insertions, 15 deletions
diff --git a/src/wasm-type.h b/src/wasm-type.h
index 05cfeaef5..6e74f0338 100644
--- a/src/wasm-type.h
+++ b/src/wasm-type.h
@@ -24,11 +24,11 @@
namespace wasm {
class Type {
- // enough for the limit of 1000 function arguments
- static constexpr unsigned SIZE_BITS = 10;
- static constexpr unsigned ID_BITS = 32 - SIZE_BITS;
- unsigned id : ID_BITS;
- unsigned _size : SIZE_BITS;
+ // The `id` uniquely represents each type, so type equality is just a
+ // comparison of the ids. For basic types the `id` is just the `ValueType`
+ // enum value below, and for constructed types the `id` is the address of the
+ // canonical representation of the type, making lookups cheap for all types.
+ uintptr_t id;
void init(const std::vector<Type>&);
public:
@@ -44,20 +44,16 @@ public:
anyref,
nullref,
exnref,
+ _last_value_type = exnref
};
-private:
- // Not in the enum because we don't want to have to have a case for it
- static constexpr uint32_t last_value_type = exnref;
-
-public:
Type() = default;
// ValueType can be implicitly upgraded to Type
- constexpr Type(ValueType id) : id(id), _size(id == none ? 0 : 1){};
+ constexpr Type(ValueType id) : id(id){};
// But converting raw uint32_t is more dangerous, so make it explicit
- explicit Type(uint32_t id);
+ explicit Type(uint64_t id) : id(id){};
// Construct from lists of elementary types
Type(std::initializer_list<Type> types);
@@ -68,8 +64,10 @@ public:
const std::vector<Type>& expand() const;
// Predicates
- constexpr bool isSingle() const { return id >= i32 && id <= last_value_type; }
- constexpr bool isMulti() const { return id > last_value_type; }
+ constexpr bool isSingle() const {
+ return id >= i32 && id <= _last_value_type;
+ }
+ constexpr bool isMulti() const { return id > _last_value_type; }
constexpr bool isConcrete() const { return id >= i32; }
constexpr bool isInteger() const { return id == i32 || id == i64; }
constexpr bool isFloat() const { return id == f32 || id == f64; }
@@ -91,7 +89,7 @@ public:
bool hasVector() { return hasPredicate<&Type::isVector>(); }
bool hasRef() { return hasPredicate<&Type::isRef>(); }
- constexpr uint32_t getID() const { return id; }
+ constexpr uint64_t getID() const { return id; }
constexpr ValueType getSingle() const {
assert(!isMulti() && "Unexpected multivalue type");
return static_cast<ValueType>(id);