diff options
author | Thomas Lively <7121787+tlively@users.noreply.github.com> | 2020-04-13 14:02:58 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-13 14:02:58 -0700 |
commit | c16bfeebb5879e9512f2bbf7d611b3b1e0be7dee (patch) | |
tree | b31308a321e869d2bf64ddbffc0a59e91df80d62 /src/wasm-type.h | |
parent | c45ae16497ea76ad24982813cace1927565b0d45 (diff) | |
download | binaryen-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.h | 28 |
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); |