• 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  #if !V8_ENABLE_WEBASSEMBLY
6  #error This header should only be included if WebAssembly is enabled.
7  #endif  // !V8_ENABLE_WEBASSEMBLY
8  
9  #ifndef V8_WASM_WASM_OBJECTS_INL_H_
10  #define V8_WASM_WASM_OBJECTS_INL_H_
11  
12  #include <type_traits>
13  
14  #include "src/base/memory.h"
15  #include "src/common/ptr-compr.h"
16  #include "src/heap/heap-write-barrier-inl.h"
17  #include "src/objects/contexts-inl.h"
18  #include "src/objects/foreign.h"
19  #include "src/objects/heap-number.h"
20  #include "src/objects/js-array-buffer-inl.h"
21  #include "src/objects/js-function-inl.h"
22  #include "src/objects/js-objects-inl.h"
23  #include "src/objects/managed.h"
24  #include "src/objects/oddball-inl.h"
25  #include "src/objects/script-inl.h"
26  #include "src/roots/roots.h"
27  #include "src/wasm/wasm-code-manager.h"
28  #include "src/wasm/wasm-module.h"
29  #include "src/wasm/wasm-objects.h"
30  
31  // Has to be the last include (doesn't have include guards)
32  #include "src/objects/object-macros.h"
33  
34  namespace v8 {
35  namespace internal {
36  
37  #include "torque-generated/src/wasm/wasm-objects-tq-inl.inc"
38  
39  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmTagObject)
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmExceptionTag)40  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmExceptionTag)
41  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmCapiFunctionData)
42  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmExportedFunctionData)
43  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmGlobalObject)
44  OBJECT_CONSTRUCTORS_IMPL(WasmInstanceObject, JSObject)
45  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmObject)
46  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmMemoryObject)
47  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmModuleObject)
48  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmTableObject)
49  TQ_OBJECT_CONSTRUCTORS_IMPL(AsmWasmData)
50  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmFunctionData)
51  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmApiFunctionRef)
52  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmInternalFunction)
53  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmTypeInfo)
54  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmStruct)
55  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmArray)
56  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmContinuationObject)
57  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmSuspenderObject)
58  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmOnFulfilledData)
59  
60  CAST_ACCESSOR(WasmInstanceObject)
61  
62  #define OPTIONAL_ACCESSORS(holder, name, type, offset)                  \
63    DEF_GETTER(holder, has_##name, bool) {                                \
64      Object value = TaggedField<Object, offset>::load(cage_base, *this); \
65      return !value.IsUndefined(GetReadOnlyRoots(cage_base));             \
66    }                                                                     \
67    ACCESSORS_CHECKED2(holder, name, type, offset,                        \
68                       !value.IsUndefined(GetReadOnlyRoots(cage_base)), true)
69  
70  #define PRIMITIVE_ACCESSORS(holder, name, type, offset)               \
71    type holder::name() const {                                         \
72      return ReadMaybeUnalignedValue<type>(FIELD_ADDR(*this, offset));  \
73    }                                                                   \
74    void holder::set_##name(type value) {                               \
75      WriteMaybeUnalignedValue<type>(FIELD_ADDR(*this, offset), value); \
76    }
77  
78  #define SANDBOXED_POINTER_ACCESSORS(holder, name, type, offset)      \
79    type holder::name() const {                                        \
80      PtrComprCageBase sandbox_base = GetPtrComprCageBase(*this);      \
81      Address value = ReadSandboxedPointerField(offset, sandbox_base); \
82      return reinterpret_cast<type>(value);                            \
83    }                                                                  \
84    void holder::set_##name(type value) {                              \
85      PtrComprCageBase sandbox_base = GetPtrComprCageBase(*this);      \
86      Address addr = reinterpret_cast<Address>(value);                 \
87      WriteSandboxedPointerField(offset, sandbox_base, addr);          \
88    }
89  
90  // WasmModuleObject
91  wasm::NativeModule* WasmModuleObject::native_module() const {
92    return managed_native_module().raw();
93  }
94  const std::shared_ptr<wasm::NativeModule>&
shared_native_module()95  WasmModuleObject::shared_native_module() const {
96    return managed_native_module().get();
97  }
module()98  const wasm::WasmModule* WasmModuleObject::module() const {
99    // TODO(clemensb): Remove this helper (inline in callers).
100    return native_module()->module();
101  }
is_asm_js()102  bool WasmModuleObject::is_asm_js() {
103    bool asm_js = is_asmjs_module(module());
104    DCHECK_EQ(asm_js, script().IsUserJavaScript());
105    return asm_js;
106  }
107  
108  // WasmMemoryObject
OPTIONAL_ACCESSORS(WasmMemoryObject,instances,WeakArrayList,kInstancesOffset)109  OPTIONAL_ACCESSORS(WasmMemoryObject, instances, WeakArrayList, kInstancesOffset)
110  
111  // WasmGlobalObject
112  ACCESSORS(WasmGlobalObject, untagged_buffer, JSArrayBuffer,
113            kUntaggedBufferOffset)
114  ACCESSORS(WasmGlobalObject, tagged_buffer, FixedArray, kTaggedBufferOffset)
115  
116  wasm::ValueType WasmGlobalObject::type() const {
117    return wasm::ValueType::FromRawBitField(static_cast<uint32_t>(raw_type()));
118  }
set_type(wasm::ValueType value)119  void WasmGlobalObject::set_type(wasm::ValueType value) {
120    set_raw_type(static_cast<int>(value.raw_bit_field()));
121  }
122  
type_size()123  int WasmGlobalObject::type_size() const { return type().value_kind_size(); }
124  
address()125  Address WasmGlobalObject::address() const {
126    DCHECK_NE(type(), wasm::kWasmAnyRef);
127    DCHECK_LE(offset() + type_size(), untagged_buffer().byte_length());
128    return Address(untagged_buffer().backing_store()) + offset();
129  }
130  
GetI32()131  int32_t WasmGlobalObject::GetI32() {
132    return base::ReadUnalignedValue<int32_t>(address());
133  }
134  
GetI64()135  int64_t WasmGlobalObject::GetI64() {
136    return base::ReadUnalignedValue<int64_t>(address());
137  }
138  
GetF32()139  float WasmGlobalObject::GetF32() {
140    return base::ReadUnalignedValue<float>(address());
141  }
142  
GetF64()143  double WasmGlobalObject::GetF64() {
144    return base::ReadUnalignedValue<double>(address());
145  }
146  
GetRef()147  Handle<Object> WasmGlobalObject::GetRef() {
148    // We use this getter for externref and funcref.
149    DCHECK(type().is_reference());
150    return handle(tagged_buffer().get(offset()), GetIsolate());
151  }
152  
SetI32(int32_t value)153  void WasmGlobalObject::SetI32(int32_t value) {
154    base::WriteUnalignedValue(address(), value);
155  }
156  
SetI64(int64_t value)157  void WasmGlobalObject::SetI64(int64_t value) {
158    base::WriteUnalignedValue(address(), value);
159  }
160  
SetF32(float value)161  void WasmGlobalObject::SetF32(float value) {
162    base::WriteUnalignedValue(address(), value);
163  }
164  
SetF64(double value)165  void WasmGlobalObject::SetF64(double value) {
166    base::WriteUnalignedValue(address(), value);
167  }
168  
SetExternRef(Handle<Object> value)169  void WasmGlobalObject::SetExternRef(Handle<Object> value) {
170    DCHECK(type().is_reference_to(wasm::HeapType::kAny));
171    tagged_buffer().set(offset(), *value);
172  }
173  
SetFuncRef(Isolate * isolate,Handle<Object> value)174  bool WasmGlobalObject::SetFuncRef(Isolate* isolate, Handle<Object> value) {
175    DCHECK_EQ(type(), wasm::kWasmFuncRef);
176    if (value->IsNull() ||
177        WasmInternalFunction::FromExternal(value, isolate).ToHandle(&value)) {
178      tagged_buffer().set(offset(), *value);
179      return true;
180    }
181    return false;
182  }
183  
184  // WasmInstanceObject
SANDBOXED_POINTER_ACCESSORS(WasmInstanceObject,memory_start,byte *,kMemoryStartOffset)185  SANDBOXED_POINTER_ACCESSORS(WasmInstanceObject, memory_start, byte*,
186                              kMemoryStartOffset)
187  PRIMITIVE_ACCESSORS(WasmInstanceObject, memory_size, size_t, kMemorySizeOffset)
188  PRIMITIVE_ACCESSORS(WasmInstanceObject, isolate_root, Address,
189                      kIsolateRootOffset)
190  PRIMITIVE_ACCESSORS(WasmInstanceObject, stack_limit_address, Address,
191                      kStackLimitAddressOffset)
192  PRIMITIVE_ACCESSORS(WasmInstanceObject, real_stack_limit_address, Address,
193                      kRealStackLimitAddressOffset)
194  PRIMITIVE_ACCESSORS(WasmInstanceObject, new_allocation_limit_address, Address*,
195                      kNewAllocationLimitAddressOffset)
196  PRIMITIVE_ACCESSORS(WasmInstanceObject, new_allocation_top_address, Address*,
197                      kNewAllocationTopAddressOffset)
198  PRIMITIVE_ACCESSORS(WasmInstanceObject, old_allocation_limit_address, Address*,
199                      kOldAllocationLimitAddressOffset)
200  PRIMITIVE_ACCESSORS(WasmInstanceObject, old_allocation_top_address, Address*,
201                      kOldAllocationTopAddressOffset)
202  PRIMITIVE_ACCESSORS(WasmInstanceObject, imported_function_targets, Address*,
203                      kImportedFunctionTargetsOffset)
204  PRIMITIVE_ACCESSORS(WasmInstanceObject, globals_start, byte*,
205                      kGlobalsStartOffset)
206  PRIMITIVE_ACCESSORS(WasmInstanceObject, imported_mutable_globals, Address*,
207                      kImportedMutableGlobalsOffset)
208  PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_size, uint32_t,
209                      kIndirectFunctionTableSizeOffset)
210  PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_sig_ids,
211                      uint32_t*, kIndirectFunctionTableSigIdsOffset)
212  PRIMITIVE_ACCESSORS(WasmInstanceObject, indirect_function_table_targets,
213                      Address*, kIndirectFunctionTableTargetsOffset)
214  PRIMITIVE_ACCESSORS(WasmInstanceObject, jump_table_start, Address,
215                      kJumpTableStartOffset)
216  PRIMITIVE_ACCESSORS(WasmInstanceObject, data_segment_starts, Address*,
217                      kDataSegmentStartsOffset)
218  PRIMITIVE_ACCESSORS(WasmInstanceObject, data_segment_sizes, uint32_t*,
219                      kDataSegmentSizesOffset)
220  PRIMITIVE_ACCESSORS(WasmInstanceObject, dropped_elem_segments, byte*,
221                      kDroppedElemSegmentsOffset)
222  PRIMITIVE_ACCESSORS(WasmInstanceObject, hook_on_function_call_address, Address,
223                      kHookOnFunctionCallAddressOffset)
224  PRIMITIVE_ACCESSORS(WasmInstanceObject, tiering_budget_array, uint32_t*,
225                      kTieringBudgetArrayOffset)
226  PRIMITIVE_ACCESSORS(WasmInstanceObject, break_on_entry, uint8_t,
227                      kBreakOnEntryOffset)
228  
229  ACCESSORS(WasmInstanceObject, module_object, WasmModuleObject,
230            kModuleObjectOffset)
231  ACCESSORS(WasmInstanceObject, exports_object, JSObject, kExportsObjectOffset)
232  ACCESSORS(WasmInstanceObject, native_context, Context, kNativeContextOffset)
233  OPTIONAL_ACCESSORS(WasmInstanceObject, memory_object, WasmMemoryObject,
234                     kMemoryObjectOffset)
235  OPTIONAL_ACCESSORS(WasmInstanceObject, untagged_globals_buffer, JSArrayBuffer,
236                     kUntaggedGlobalsBufferOffset)
237  OPTIONAL_ACCESSORS(WasmInstanceObject, tagged_globals_buffer, FixedArray,
238                     kTaggedGlobalsBufferOffset)
239  OPTIONAL_ACCESSORS(WasmInstanceObject, imported_mutable_globals_buffers,
240                     FixedArray, kImportedMutableGlobalsBuffersOffset)
241  OPTIONAL_ACCESSORS(WasmInstanceObject, tables, FixedArray, kTablesOffset)
242  OPTIONAL_ACCESSORS(WasmInstanceObject, indirect_function_tables, FixedArray,
243                     kIndirectFunctionTablesOffset)
244  ACCESSORS(WasmInstanceObject, imported_function_refs, FixedArray,
245            kImportedFunctionRefsOffset)
246  OPTIONAL_ACCESSORS(WasmInstanceObject, indirect_function_table_refs, FixedArray,
247                     kIndirectFunctionTableRefsOffset)
248  OPTIONAL_ACCESSORS(WasmInstanceObject, managed_native_allocations, Foreign,
249                     kManagedNativeAllocationsOffset)
250  OPTIONAL_ACCESSORS(WasmInstanceObject, tags_table, FixedArray, kTagsTableOffset)
251  OPTIONAL_ACCESSORS(WasmInstanceObject, wasm_internal_functions, FixedArray,
252                     kWasmInternalFunctionsOffset)
253  ACCESSORS(WasmInstanceObject, managed_object_maps, FixedArray,
254            kManagedObjectMapsOffset)
255  ACCESSORS(WasmInstanceObject, feedback_vectors, FixedArray,
256            kFeedbackVectorsOffset)
257  
258  void WasmInstanceObject::clear_padding() {
259    if (FIELD_SIZE(kOptionalPaddingOffset) != 0) {
260      DCHECK_EQ(4, FIELD_SIZE(kOptionalPaddingOffset));
261      memset(reinterpret_cast<void*>(address() + kOptionalPaddingOffset), 0,
262             FIELD_SIZE(kOptionalPaddingOffset));
263    }
264  }
265  
ImportedFunctionEntry(Handle<WasmInstanceObject> instance,int index)266  ImportedFunctionEntry::ImportedFunctionEntry(
267      Handle<WasmInstanceObject> instance, int index)
268      : instance_(instance), index_(index) {
269    DCHECK_GE(index, 0);
270    DCHECK_LT(index, instance->module()->num_imported_functions);
271  }
272  
273  // WasmExceptionPackage
OBJECT_CONSTRUCTORS_IMPL(WasmExceptionPackage,JSObject)274  OBJECT_CONSTRUCTORS_IMPL(WasmExceptionPackage, JSObject)
275  CAST_ACCESSOR(WasmExceptionPackage)
276  
277  // WasmExportedFunction
278  WasmExportedFunction::WasmExportedFunction(Address ptr) : JSFunction(ptr) {
279    SLOW_DCHECK(IsWasmExportedFunction(*this));
280  }
281  CAST_ACCESSOR(WasmExportedFunction)
282  
283  // WasmFunctionData
ACCESSORS(WasmFunctionData,internal,WasmInternalFunction,kInternalOffset)284  ACCESSORS(WasmFunctionData, internal, WasmInternalFunction, kInternalOffset)
285  
286  wasm::FunctionSig* WasmExportedFunctionData::sig() const {
287    return reinterpret_cast<wasm::FunctionSig*>(signature().foreign_address());
288  }
289  
290  // WasmJSFunction
WasmJSFunction(Address ptr)291  WasmJSFunction::WasmJSFunction(Address ptr) : JSFunction(ptr) {
292    SLOW_DCHECK(IsWasmJSFunction(*this));
293  }
294  CAST_ACCESSOR(WasmJSFunction)
295  
296  // WasmJSFunctionData
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmJSFunctionData)297  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmJSFunctionData)
298  
299  // WasmCapiFunction
300  WasmCapiFunction::WasmCapiFunction(Address ptr) : JSFunction(ptr) {
301    SLOW_DCHECK(IsWasmCapiFunction(*this));
302  }
CAST_ACCESSOR(WasmCapiFunction)303  CAST_ACCESSOR(WasmCapiFunction)
304  
305  // WasmExternalFunction
306  WasmExternalFunction::WasmExternalFunction(Address ptr) : JSFunction(ptr) {
307    SLOW_DCHECK(IsWasmExternalFunction(*this));
308  }
309  CAST_ACCESSOR(WasmExternalFunction)
310  
311  // WasmIndirectFunctionTable
TQ_OBJECT_CONSTRUCTORS_IMPL(WasmIndirectFunctionTable)312  TQ_OBJECT_CONSTRUCTORS_IMPL(WasmIndirectFunctionTable)
313  PRIMITIVE_ACCESSORS(WasmIndirectFunctionTable, sig_ids, uint32_t*,
314                      kSigIdsOffset)
315  PRIMITIVE_ACCESSORS(WasmIndirectFunctionTable, targets, Address*,
316                      kTargetsOffset)
317  OPTIONAL_ACCESSORS(WasmIndirectFunctionTable, managed_native_allocations,
318                     Foreign, kManagedNativeAllocationsOffset)
319  
320  #undef OPTIONAL_ACCESSORS
321  #undef READ_PRIMITIVE_FIELD
322  #undef WRITE_PRIMITIVE_FIELD
323  #undef PRIMITIVE_ACCESSORS
324  
325  wasm::ValueType WasmTableObject::type() {
326    return wasm::ValueType::FromRawBitField(raw_type());
327  }
328  
has_maximum_pages()329  bool WasmMemoryObject::has_maximum_pages() { return maximum_pages() >= 0; }
330  
331  // static
ReadValueAt(Isolate * isolate,Handle<HeapObject> obj,wasm::ValueType type,uint32_t offset)332  Handle<Object> WasmObject::ReadValueAt(Isolate* isolate, Handle<HeapObject> obj,
333                                         wasm::ValueType type, uint32_t offset) {
334    Address field_address = obj->GetFieldAddress(offset);
335    switch (type.kind()) {
336      case wasm::kI8: {
337        int8_t value = base::Memory<int8_t>(field_address);
338        return handle(Smi::FromInt(value), isolate);
339      }
340      case wasm::kI16: {
341        int16_t value = base::Memory<int16_t>(field_address);
342        return handle(Smi::FromInt(value), isolate);
343      }
344      case wasm::kI32: {
345        int32_t value = base::Memory<int32_t>(field_address);
346        return isolate->factory()->NewNumberFromInt(value);
347      }
348      case wasm::kI64: {
349        int64_t value = base::ReadUnalignedValue<int64_t>(field_address);
350        return BigInt::FromInt64(isolate, value);
351      }
352      case wasm::kF32: {
353        float value = base::Memory<float>(field_address);
354        return isolate->factory()->NewNumber(value);
355      }
356      case wasm::kF64: {
357        double value = base::ReadUnalignedValue<double>(field_address);
358        return isolate->factory()->NewNumber(value);
359      }
360      case wasm::kS128:
361        // TODO(v8:11804): implement
362        UNREACHABLE();
363  
364      case wasm::kRef:
365      case wasm::kOptRef: {
366        ObjectSlot slot(field_address);
367        return handle(slot.load(isolate), isolate);
368      }
369  
370      case wasm::kRtt:
371        // Rtt values are not supposed to be made available to JavaScript side.
372        UNREACHABLE();
373  
374      case wasm::kVoid:
375      case wasm::kBottom:
376        UNREACHABLE();
377    }
378  }
379  
380  // static
ToWasmValue(Isolate * isolate,wasm::ValueType type,Handle<Object> value)381  MaybeHandle<Object> WasmObject::ToWasmValue(Isolate* isolate,
382                                              wasm::ValueType type,
383                                              Handle<Object> value) {
384    switch (type.kind()) {
385      case wasm::kI8:
386      case wasm::kI16:
387      case wasm::kI32:
388      case wasm::kF32:
389      case wasm::kF64:
390        return Object::ToNumber(isolate, value);
391  
392      case wasm::kI64:
393        return BigInt::FromObject(isolate, value);
394  
395      case wasm::kRef:
396      case wasm::kOptRef: {
397        // TODO(v8:11804): implement ref type check
398        UNREACHABLE();
399      }
400  
401      case wasm::kS128:
402        // TODO(v8:11804): implement
403        UNREACHABLE();
404  
405      case wasm::kRtt:
406        // Rtt values are not supposed to be made available to JavaScript side.
407        UNREACHABLE();
408  
409      case wasm::kVoid:
410      case wasm::kBottom:
411        UNREACHABLE();
412    }
413  }
414  
415  // Conversions from Numeric objects.
416  // static
417  template <typename ElementType>
FromNumber(Object value)418  ElementType WasmObject::FromNumber(Object value) {
419    // The value must already be prepared for storing to numeric fields.
420    DCHECK(value.IsNumber());
421    if (value.IsSmi()) {
422      return static_cast<ElementType>(Smi::ToInt(value));
423  
424    } else if (value.IsHeapNumber()) {
425      double double_value = HeapNumber::cast(value).value();
426      if (std::is_same<ElementType, double>::value ||
427          std::is_same<ElementType, float>::value) {
428        return static_cast<ElementType>(double_value);
429      } else {
430        CHECK(std::is_integral<ElementType>::value);
431        return static_cast<ElementType>(DoubleToInt32(double_value));
432      }
433    }
434    UNREACHABLE();
435  }
436  
437  // static
WriteValueAt(Isolate * isolate,Handle<HeapObject> obj,wasm::ValueType type,uint32_t offset,Handle<Object> value)438  void WasmObject::WriteValueAt(Isolate* isolate, Handle<HeapObject> obj,
439                                wasm::ValueType type, uint32_t offset,
440                                Handle<Object> value) {
441    Address field_address = obj->GetFieldAddress(offset);
442    switch (type.kind()) {
443      case wasm::kI8: {
444        auto scalar_value = FromNumber<int8_t>(*value);
445        base::Memory<int8_t>(field_address) = scalar_value;
446        break;
447      }
448      case wasm::kI16: {
449        auto scalar_value = FromNumber<int16_t>(*value);
450        base::Memory<int16_t>(field_address) = scalar_value;
451        break;
452      }
453      case wasm::kI32: {
454        auto scalar_value = FromNumber<int32_t>(*value);
455        base::Memory<int32_t>(field_address) = scalar_value;
456        break;
457      }
458      case wasm::kI64: {
459        int64_t scalar_value = BigInt::cast(*value).AsInt64();
460        base::WriteUnalignedValue<int64_t>(field_address, scalar_value);
461        break;
462      }
463      case wasm::kF32: {
464        auto scalar_value = FromNumber<float>(*value);
465        base::Memory<float>(field_address) = scalar_value;
466        break;
467      }
468      case wasm::kF64: {
469        auto scalar_value = FromNumber<double>(*value);
470        base::WriteUnalignedValue<double>(field_address, scalar_value);
471        break;
472      }
473      case wasm::kRef:
474      case wasm::kOptRef:
475        // TODO(v8:11804): implement
476        UNREACHABLE();
477  
478      case wasm::kS128:
479        // TODO(v8:11804): implement
480        UNREACHABLE();
481  
482      case wasm::kRtt:
483        // Rtt values are not supposed to be made available to JavaScript side.
484        UNREACHABLE();
485  
486      case wasm::kVoid:
487      case wasm::kBottom:
488        UNREACHABLE();
489    }
490  }
491  
type(Map map)492  wasm::StructType* WasmStruct::type(Map map) {
493    WasmTypeInfo type_info = map.wasm_type_info();
494    return reinterpret_cast<wasm::StructType*>(type_info.foreign_address());
495  }
496  
GcSafeType(Map map)497  wasm::StructType* WasmStruct::GcSafeType(Map map) {
498    DCHECK_EQ(WASM_STRUCT_TYPE, map.instance_type());
499    HeapObject raw = HeapObject::cast(map.constructor_or_back_pointer());
500    // The {Foreign} might be in the middle of being moved, which is why we
501    // can't read its map for a checked cast. But we can rely on its payload
502    // being intact in the old location.
503    Foreign foreign = Foreign::unchecked_cast(raw);
504    return reinterpret_cast<wasm::StructType*>(foreign.foreign_address());
505  }
506  
Size(const wasm::StructType * type)507  int WasmStruct::Size(const wasm::StructType* type) {
508    // Object size must fit into a Smi (because of filler objects), and its
509    // computation must not overflow.
510    STATIC_ASSERT(Smi::kMaxValue <= kMaxInt);
511    DCHECK_LE(type->total_fields_size(), Smi::kMaxValue - kHeaderSize);
512    return std::max(kHeaderSize + static_cast<int>(type->total_fields_size()),
513                    Heap::kMinObjectSizeInTaggedWords * kTaggedSize);
514  }
515  
516  // static
EncodeInstanceSizeInMap(int instance_size,Map map)517  void WasmStruct::EncodeInstanceSizeInMap(int instance_size, Map map) {
518    // WasmStructs can be bigger than the {map.instance_size_in_words} field
519    // can describe; yet we have to store the instance size somewhere on the
520    // map so that the GC can read it without relying on any other objects
521    // still being around. To solve this problem, we store the instance size
522    // in two other fields that are otherwise unused for WasmStructs.
523    STATIC_ASSERT(0xFFFF - kHeaderSize >
524                  wasm::kMaxValueTypeSize * wasm::kV8MaxWasmStructFields);
525    map.SetWasmByte1(instance_size & 0xFF);
526    map.SetWasmByte2(instance_size >> 8);
527  }
528  
529  // static
DecodeInstanceSizeFromMap(Map map)530  int WasmStruct::DecodeInstanceSizeFromMap(Map map) {
531    return (map.WasmByte2() << 8) | map.WasmByte1();
532  }
533  
GcSafeSize(Map map)534  int WasmStruct::GcSafeSize(Map map) { return DecodeInstanceSizeFromMap(map); }
535  
type()536  wasm::StructType* WasmStruct::type() const { return type(map()); }
537  
RawFieldAddress(int raw_offset)538  Address WasmStruct::RawFieldAddress(int raw_offset) {
539    int offset = WasmStruct::kHeaderSize + raw_offset;
540    return FIELD_ADDR(*this, offset);
541  }
542  
RawField(int raw_offset)543  ObjectSlot WasmStruct::RawField(int raw_offset) {
544    return ObjectSlot(RawFieldAddress(raw_offset));
545  }
546  
547  // static
GetField(Isolate * isolate,Handle<WasmStruct> obj,uint32_t field_index)548  Handle<Object> WasmStruct::GetField(Isolate* isolate, Handle<WasmStruct> obj,
549                                      uint32_t field_index) {
550    wasm::StructType* type = obj->type();
551    CHECK_LT(field_index, type->field_count());
552    wasm::ValueType field_type = type->field(field_index);
553    int offset = WasmStruct::kHeaderSize + type->field_offset(field_index);
554    return ReadValueAt(isolate, obj, field_type, offset);
555  }
556  
557  // static
SetField(Isolate * isolate,Handle<WasmStruct> obj,uint32_t field_index,Handle<Object> value)558  void WasmStruct::SetField(Isolate* isolate, Handle<WasmStruct> obj,
559                            uint32_t field_index, Handle<Object> value) {
560    wasm::StructType* type = obj->type();
561    CHECK_LT(field_index, type->field_count());
562    wasm::ValueType field_type = type->field(field_index);
563    int offset = WasmStruct::kHeaderSize + type->field_offset(field_index);
564    WriteValueAt(isolate, obj, field_type, offset, value);
565  }
566  
type(Map map)567  wasm::ArrayType* WasmArray::type(Map map) {
568    DCHECK_EQ(WASM_ARRAY_TYPE, map.instance_type());
569    WasmTypeInfo type_info = map.wasm_type_info();
570    return reinterpret_cast<wasm::ArrayType*>(type_info.foreign_address());
571  }
572  
GcSafeType(Map map)573  wasm::ArrayType* WasmArray::GcSafeType(Map map) {
574    DCHECK_EQ(WASM_ARRAY_TYPE, map.instance_type());
575    HeapObject raw = HeapObject::cast(map.constructor_or_back_pointer());
576    // The {Foreign} might be in the middle of being moved, which is why we
577    // can't read its map for a checked cast. But we can rely on its payload
578    // being intact in the old location.
579    Foreign foreign = Foreign::unchecked_cast(raw);
580    return reinterpret_cast<wasm::ArrayType*>(foreign.foreign_address());
581  }
582  
type()583  wasm::ArrayType* WasmArray::type() const { return type(map()); }
584  
SizeFor(Map map,int length)585  int WasmArray::SizeFor(Map map, int length) {
586    int element_size = DecodeElementSizeFromMap(map);
587    return kHeaderSize + RoundUp(element_size * length, kTaggedSize);
588  }
589  
element_offset(uint32_t index)590  uint32_t WasmArray::element_offset(uint32_t index) {
591    DCHECK_LE(index, length());
592    return WasmArray::kHeaderSize +
593           index * type()->element_type().value_kind_size();
594  }
595  
ElementAddress(uint32_t index)596  Address WasmArray::ElementAddress(uint32_t index) {
597    return ptr() + element_offset(index) - kHeapObjectTag;
598  }
599  
ElementSlot(uint32_t index)600  ObjectSlot WasmArray::ElementSlot(uint32_t index) {
601    DCHECK_LE(index, length());
602    DCHECK(type()->element_type().is_reference());
603    return RawField(kHeaderSize + kTaggedSize * index);
604  }
605  
606  // static
GetElement(Isolate * isolate,Handle<WasmArray> array,uint32_t index)607  Handle<Object> WasmArray::GetElement(Isolate* isolate, Handle<WasmArray> array,
608                                       uint32_t index) {
609    if (index >= array->length()) {
610      return isolate->factory()->undefined_value();
611    }
612    wasm::ValueType element_type = array->type()->element_type();
613    return ReadValueAt(isolate, array, element_type,
614                       array->element_offset(index));
615  }
616  
617  // static
EncodeElementSizeInMap(int element_size,Map map)618  void WasmArray::EncodeElementSizeInMap(int element_size, Map map) {
619    map.SetWasmByte1(element_size);
620  }
621  
622  // static
DecodeElementSizeFromMap(Map map)623  int WasmArray::DecodeElementSizeFromMap(Map map) { return map.WasmByte1(); }
624  
clear_foreign_address(Isolate * isolate)625  void WasmTypeInfo::clear_foreign_address(Isolate* isolate) {
626  #ifdef V8_SANDBOXED_EXTERNAL_POINTERS
627    // Due to the type-specific pointer tags for external pointers, we need to
628    // allocate an entry in the table here even though it will just store nullptr.
629    AllocateExternalPointerEntries(isolate);
630  #endif
631    set_foreign_address(isolate, 0);
632  }
633  
634  #include "src/objects/object-macros-undef.h"
635  
636  }  // namespace internal
637  }  // namespace v8
638  
639  #endif  // V8_WASM_WASM_OBJECTS_INL_H_
640