• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef V8_WASM_WASM_VALUE_H_
6 #define V8_WASM_WASM_VALUE_H_
7 
8 #include "src/base/memory.h"
9 #include "src/handles/handles.h"
10 #include "src/utils/boxed-float.h"
11 #include "src/wasm/wasm-opcodes.h"
12 #include "src/zone/zone-containers.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace wasm {
17 
18 #define FOREACH_SIMD_TYPE(V)  \
19   V(double, float2, f64x2, 2) \
20   V(float, float4, f32x4, 4)  \
21   V(int64_t, int2, i64x2, 2)  \
22   V(int32_t, int4, i32x4, 4)  \
23   V(int16_t, int8, i16x8, 8)  \
24   V(int8_t, int16, i8x16, 16)
25 
26 #define DEFINE_SIMD_TYPE(cType, sType, name, kSize) \
27   struct sType {                                    \
28     cType val[kSize];                               \
29   };
FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE)30 FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE)
31 #undef DEFINE_SIMD_TYPE
32 
33 class Simd128 {
34  public:
35   Simd128() = default;
36 
37 #define DEFINE_SIMD_TYPE_SPECIFIC_METHODS(cType, sType, name, size)          \
38   explicit Simd128(sType val) {                                              \
39     base::WriteUnalignedValue<sType>(reinterpret_cast<Address>(val_), val);  \
40   }                                                                          \
41   sType to_##name() {                                                        \
42     return base::ReadUnalignedValue<sType>(reinterpret_cast<Address>(val_)); \
43   }
44   FOREACH_SIMD_TYPE(DEFINE_SIMD_TYPE_SPECIFIC_METHODS)
45 #undef DEFINE_SIMD_TYPE_SPECIFIC_METHODS
46 
47   const uint8_t* bytes() { return val_; }
48 
49   template <typename T>
50   inline T to();
51 
52  private:
53   uint8_t val_[16] = {0};
54 };
55 
56 #define DECLARE_CAST(cType, sType, name, size) \
57   template <>                                  \
58   inline sType Simd128::to() {                 \
59     return to_##name();                        \
60   }
61 FOREACH_SIMD_TYPE(DECLARE_CAST)
62 #undef DECLARE_CAST
63 
64 // Macro for defining WasmValue methods for different types.
65 // Elements:
66 // - name (for to_<name>() method)
67 // - wasm type
68 // - c type
69 #define FOREACH_WASMVAL_TYPE(V)   \
70   V(i32, kWasmI32, int32_t)       \
71   V(u32, kWasmI32, uint32_t)      \
72   V(i64, kWasmI64, int64_t)       \
73   V(u64, kWasmI64, uint64_t)      \
74   V(f32, kWasmF32, float)         \
75   V(f32_boxed, kWasmF32, Float32) \
76   V(f64, kWasmF64, double)        \
77   V(f64_boxed, kWasmF64, Float64) \
78   V(s128, kWasmS128, Simd128)     \
79   V(externref, kWasmExternRef, Handle<Object>)
80 
81 ASSERT_TRIVIALLY_COPYABLE(Handle<Object>);
82 
83 // A wasm value with type information.
84 class WasmValue {
85  public:
WasmValue()86   WasmValue() : type_(kWasmStmt), bit_pattern_{} {}
87 
88 #define DEFINE_TYPE_SPECIFIC_METHODS(name, localtype, ctype)                  \
89   explicit WasmValue(ctype v) : type_(localtype), bit_pattern_{} {            \
90     static_assert(sizeof(ctype) <= sizeof(bit_pattern_),                      \
91                   "size too big for WasmValue");                              \
92     base::WriteUnalignedValue<ctype>(reinterpret_cast<Address>(bit_pattern_), \
93                                      v);                                      \
94   }                                                                           \
95   ctype to_##name() const {                                                   \
96     DCHECK_EQ(localtype, type_);                                              \
97     return to_##name##_unchecked();                                           \
98   }                                                                           \
99   ctype to_##name##_unchecked() const {                                       \
100     return base::ReadUnalignedValue<ctype>(                                   \
101         reinterpret_cast<Address>(bit_pattern_));                             \
102   }
FOREACH_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS)103   FOREACH_WASMVAL_TYPE(DEFINE_TYPE_SPECIFIC_METHODS)
104 #undef DEFINE_TYPE_SPECIFIC_METHODS
105 
106   ValueType type() const { return type_; }
107 
108   // Checks equality of type and bit pattern (also for float and double values).
109   bool operator==(const WasmValue& other) const {
110     return type_ == other.type_ &&
111            !memcmp(bit_pattern_, other.bit_pattern_, 16);
112   }
113 
114   template <typename T>
115   inline T to() const;
116 
117   template <typename T>
118   inline T to_unchecked() const;
119 
ForUintPtr(uintptr_t value)120   static WasmValue ForUintPtr(uintptr_t value) {
121     using type =
122         std::conditional<kSystemPointerSize == 8, uint64_t, uint32_t>::type;
123     return WasmValue{type{value}};
124   }
125 
126  private:
127   ValueType type_;
128   uint8_t bit_pattern_[16];
129 };
130 
131 #define DECLARE_CAST(name, localtype, ctype, ...) \
132   template <>                                     \
133   inline ctype WasmValue::to_unchecked() const {  \
134     return to_##name##_unchecked();               \
135   }                                               \
136   template <>                                     \
137   inline ctype WasmValue::to() const {            \
138     return to_##name();                           \
139   }
140 FOREACH_WASMVAL_TYPE(DECLARE_CAST)
141 #undef DECLARE_CAST
142 
143 }  // namespace wasm
144 }  // namespace internal
145 }  // namespace v8
146 
147 #endif  // V8_WASM_WASM_VALUE_H_
148