Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/wabt/interp/interp-inl.h
1 /* 2 * Copyright 2020 WebAssembly Community Group participants 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <cassert> 18 #include <limits> 19 #include <string> 20 21 namespace wabt { 22 namespace interp { 23 24 //// Ref //// 25 inline Ref::Ref(size_t index) : index(index) {} 26 27 inline bool operator==(Ref lhs, Ref rhs) { 28 return lhs.index == rhs.index; 29 } 30 31 inline bool operator!=(Ref lhs, Ref rhs) { 32 return lhs.index != rhs.index; 33 } 34 35 //// ExternType //// 36 inline ExternType::ExternType(ExternKind kind) : kind(kind) {} 37 38 //// FuncType //// 39 // static 40 inline bool FuncType::classof(const ExternType* type) { 41 return type->kind == skind; 42 } 43 44 inline FuncType::FuncType(ValueTypes params, ValueTypes results) 45 : ExternType(ExternKind::Func), params(params), results(results) {} 46 47 //// TableType //// 48 // static 49 inline bool TableType::classof(const ExternType* type) { 50 return type->kind == skind; 51 } 52 53 inline TableType::TableType(ValueType element, Limits limits) 54 : ExternType(ExternKind::Table), element(element), limits(limits) { 55 // Always set max. 56 if (!limits.has_max) { 57 this->limits.max = std::numeric_limits<u32>::max(); 58 } 59 } 60 61 //// MemoryType //// 62 // static 63 inline bool MemoryType::classof(const ExternType* type) { 64 return type->kind == skind; 65 } 66 67 inline MemoryType::MemoryType(Limits limits) 68 : ExternType(ExternKind::Memory), limits(limits) { 69 // Always set max. 70 if (!limits.has_max) { 71 this->limits.max = limits.is_64 ? WABT_MAX_PAGES64 : WABT_MAX_PAGES32; 72 } 73 } 74 75 //// GlobalType //// 76 // static 77 inline bool GlobalType::classof(const ExternType* type) { 78 return type->kind == skind; 79 } 80 81 inline GlobalType::GlobalType(ValueType type, Mutability mut) 82 : ExternType(ExternKind::Global), type(type), mut(mut) {} 83 84 //// TagType //// 85 // static 86 inline bool TagType::classof(const ExternType* type) { 87 return type->kind == skind; 88 } 89 90 inline TagType::TagType(TagAttr attr, const ValueTypes& signature) 91 : ExternType(ExternKind::Tag), attr(attr), signature(signature) {} 92 93 //// ImportType //// 94 inline ImportType::ImportType(std::string module, 95 std::string name, 96 std::unique_ptr<ExternType> type) 97 : module(module), name(name), type(std::move(type)) {} 98 99 inline ImportType::ImportType(const ImportType& other) 100 : module(other.module), name(other.name), type(other.type->Clone()) {} 101 102 inline ImportType& ImportType::operator=(const ImportType& other) { 103 if (this != &other) { 104 module = other.module; 105 name = other.name; 106 type = other.type->Clone(); 107 } 108 return *this; 109 } 110 111 //// ExportType //// 112 inline ExportType::ExportType(std::string name, 113 std::unique_ptr<ExternType> type) 114 : name(name), type(std::move(type)) {} 115 116 inline ExportType::ExportType(const ExportType& other) 117 : name(other.name), type(other.type->Clone()) {} 118 119 inline ExportType& ExportType::operator=(const ExportType& other) { 120 if (this != &other) { 121 name = other.name; 122 type = other.type->Clone(); 123 } 124 return *this; 125 } 126 127 //// Frame //// 128 inline Frame::Frame(Ref func, 129 u32 values, 130 u32 exceptions, 131 u32 offset, 132 Instance* inst, 133 Module* mod) 134 : func(func), 135 values(values), 136 exceptions(exceptions), 137 offset(offset), 138 inst(inst), 139 mod(mod) {} 140 141 //// FreeList //// 142 template <> 143 inline bool FreeList<Ref>::IsUsed(Index index) const { 144 return (list_[index].index & refFreeBit) == 0; 145 } 146 147 template <> 148 inline FreeList<Ref>::~FreeList() {} 149 150 template <> 151 template <typename... Args> 152 auto FreeList<Ref>::New(Args&&... args) -> Index { 153 if (free_head_ == 0) { 154 list_.push_back(Ref(std::forward<Args>(args)...)); 155 return list_.size() - 1; 156 } 157 158 Index index = free_head_ - 1; 159 160 assert(!IsUsed(index)); 161 assert(free_items_ > 0); 162 163 free_head_ = list_[index].index & (refFreeBit - 1); 164 list_[index] = Ref(std::forward<Args>(args)...); 165 free_items_--; 166 return index; 167 } 168 169 template <> 170 inline void FreeList<Ref>::Delete(Index index) { 171 assert(IsUsed(index)); 172 173 list_[index].index = free_head_ | refFreeBit; 174 free_head_ = index + 1; 175 free_items_++; 176 } 177 178 template <typename T> 179 bool FreeList<T>::IsUsed(Index index) const { 180 return (reinterpret_cast<uintptr_t>(list_[index]) & ptrFreeBit) == 0; 181 } 182 183 template <typename T> 184 FreeList<T>::~FreeList() { 185 for (auto object : list_) { 186 if ((reinterpret_cast<uintptr_t>(object) & ptrFreeBit) == 0) { 187 delete object; 188 } 189 } 190 } 191 192 template <typename T> 193 template <typename... Args> 194 auto FreeList<T>::New(Args&&... args) -> Index { 195 if (free_head_ == 0) { 196 list_.push_back(T(std::forward<Args>(args)...)); 197 return list_.size() - 1; 198 } 199 200 Index index = free_head_ - 1; 201 202 assert(!IsUsed(index)); 203 assert(free_items_ > 0); 204 205 free_head_ = reinterpret_cast<uintptr_t>(list_[index]) >> ptrFreeShift; 206 list_[index] = T(std::forward<Args>(args)...); 207 free_items_--; 208 return index; 209 } 210 211 template <typename T> 212 void FreeList<T>::Delete(Index index) { 213 assert(IsUsed(index)); 214 215 delete list_[index]; 216 list_[index] = reinterpret_cast<T>((free_head_ << ptrFreeShift) | ptrFreeBit); 217 free_head_ = index + 1; 218 free_items_++; 219 } 220 221 template <typename T> 222 const T& FreeList<T>::Get(Index index) const { 223 assert(IsUsed(index)); 224 return list_[index]; 225 } 226 227 template <typename T> 228 T& FreeList<T>::Get(Index index) { 229 assert(IsUsed(index)); 230 return list_[index]; 231 } 232 233 template <typename T> 234 auto FreeList<T>::size() const -> Index { 235 return list_.size(); 236 } 237 238 template <typename T> 239 auto FreeList<T>::count() const -> Index { 240 return list_.size() - free_items_; 241 } 242 243 //// RefPtr //// 244 template <typename T> 245 RefPtr<T>::RefPtr() : obj_(nullptr), store_(nullptr), root_index_(0) {} 246 247 template <typename T> 248 RefPtr<T>::RefPtr(Store& store, Ref ref) { 249 #ifndef NDEBUG 250 if (!store.Is<T>(ref)) { 251 ObjectKind ref_kind; 252 if (ref == Ref::Null) { 253 ref_kind = ObjectKind::Null; 254 } else { 255 ref_kind = store.objects_.Get(ref.index)->kind(); 256 } 257 fprintf(stderr, "Invalid conversion from Ref (%s) to RefPtr<%s>!\n", 258 GetName(ref_kind), T::GetTypeName()); 259 abort(); 260 } 261 #endif 262 root_index_ = store.NewRoot(ref); 263 obj_ = static_cast<T*>(store.objects_.Get(ref.index)); 264 store_ = &store; 265 } 266 267 template <typename T> 268 RefPtr<T>::RefPtr(const RefPtr& other) 269 : obj_(other.obj_), store_(other.store_) { 270 root_index_ = store_ ? store_->CopyRoot(other.root_index_) : 0; 271 } 272 273 template <typename T> 274 RefPtr<T>& RefPtr<T>::operator=(const RefPtr& other) { 275 obj_ = other.obj_; 276 store_ = other.store_; 277 root_index_ = store_ ? store_->CopyRoot(other.root_index_) : 0; 278 return *this; 279 } 280 281 template <typename T> 282 RefPtr<T>::RefPtr(RefPtr&& other) 283 : obj_(other.obj_), store_(other.store_), root_index_(other.root_index_) { 284 other.obj_ = nullptr; 285 other.store_ = nullptr; 286 other.root_index_ = 0; 287 } 288 289 template <typename T> 290 RefPtr<T>& RefPtr<T>::operator=(RefPtr&& other) { 291 obj_ = other.obj_; 292 store_ = other.store_; 293 root_index_ = other.root_index_; 294 other.obj_ = nullptr; 295 other.store_ = nullptr; 296 other.root_index_ = 0; 297 return *this; 298 } 299 300 template <typename T> 301 RefPtr<T>::~RefPtr() { 302 reset(); 303 } 304 305 template <typename T> 306 template <typename U> 307 RefPtr<T>::RefPtr(const RefPtr<U>& other) 308 : obj_(other.obj_), store_(other.store_) { 309 root_index_ = store_ ? store_->CopyRoot(other.root_index_) : 0; 310 } 311 312 template <typename T> 313 template <typename U> 314 RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& other) { 315 obj_ = other.obj_; 316 store_ = other.store_; 317 root_index_ = store_ ? store_->CopyRoot(other.root_index_) : 0; 318 return *this; 319 } 320 321 template <typename T> 322 template <typename U> 323 RefPtr<T>::RefPtr(RefPtr&& other) 324 : obj_(other.obj_), store_(other.store_), root_index_(other.root_index_) { 325 other.obj_ = nullptr; 326 other.store_ = nullptr; 327 other.root_index_ = 0; 328 } 329 330 template <typename T> 331 template <typename U> 332 RefPtr<T>& RefPtr<T>::operator=(RefPtr&& other) { 333 obj_ = other.obj_; 334 store_ = other.store_; 335 root_index_ = other.root_index_; 336 other.obj_ = nullptr; 337 other.store_ = nullptr; 338 other.root_index_ = 0; 339 return *this; 340 } 341 342 template <typename T> 343 template <typename U> 344 RefPtr<U> RefPtr<T>::As() { 345 static_assert(std::is_base_of<T, U>::value, "T must be base class of U"); 346 assert(store_->Is<U>(obj_->self())); 347 RefPtr<U> result; 348 result.obj_ = static_cast<U*>(obj_); 349 result.store_ = store_; 350 result.root_index_ = store_->CopyRoot(root_index_); 351 return result; 352 } 353 354 template <typename T> 355 bool RefPtr<T>::empty() const { 356 return obj_ == nullptr; 357 } 358 359 template <typename T> 360 void RefPtr<T>::reset() { 361 if (obj_) { 362 store_->DeleteRoot(root_index_); 363 obj_ = nullptr; 364 root_index_ = 0; 365 store_ = nullptr; 366 } 367 } 368 369 template <typename T> 370 T* RefPtr<T>::get() const { 371 return obj_; 372 } 373 374 template <typename T> 375 T* RefPtr<T>::operator->() const { 376 return obj_; 377 } 378 379 template <typename T> 380 T& RefPtr<T>::operator*() const { 381 return *obj_; 382 } 383 384 template <typename T> 385 RefPtr<T>::operator bool() const { 386 return obj_ != nullptr; 387 } 388 389 template <typename T> 390 Ref RefPtr<T>::ref() const { 391 return store_ ? store_->roots_.Get(root_index_) : Ref::Null; 392 } 393 394 template <typename T> 395 Store* RefPtr<T>::store() const { 396 return store_; 397 } 398 399 template <typename U, typename V> 400 bool operator==(const RefPtr<U>& lhs, const RefPtr<V>& rhs) { 401 return lhs.obj_->self() == rhs.obj_->self(); 402 } 403 404 template <typename U, typename V> 405 bool operator!=(const RefPtr<U>& lhs, const RefPtr<V>& rhs) { 406 return lhs.obj_->self() != rhs.obj_->self(); 407 } 408 409 //// ValueType //// 410 inline bool IsReference(ValueType type) { return type.IsRef(); } 411 template <> inline bool HasType<s32>(ValueType type) { return type == ValueType::I32; } 412 template <> inline bool HasType<u32>(ValueType type) { return type == ValueType::I32; } 413 template <> inline bool HasType<s64>(ValueType type) { return type == ValueType::I64; } 414 template <> inline bool HasType<u64>(ValueType type) { return type == ValueType::I64; } 415 template <> inline bool HasType<f32>(ValueType type) { return type == ValueType::F32; } 416 template <> inline bool HasType<f64>(ValueType type) { return type == ValueType::F64; } 417 template <> inline bool HasType<Ref>(ValueType type) { return IsReference(type); } 418 419 template <typename T> 420 void RequireType(ValueType type) { 421 assert(HasType<T>(type)); 422 } 423 424 inline bool TypesMatch(ValueType expected, ValueType actual) { 425 // Currently there is no subtyping, so expected and actual must match 426 // exactly. In the future this may be expanded. 427 return expected == actual; 428 } 429 430 //// Value //// 431 inline Value WABT_VECTORCALL Value::Make(s32 val) { Value res; res.i32_ = val; res.SetType(ValueType::I32); return res; } 432 inline Value WABT_VECTORCALL Value::Make(u32 val) { Value res; res.i32_ = val; res.SetType(ValueType::I32); return res; } 433 inline Value WABT_VECTORCALL Value::Make(s64 val) { Value res; res.i64_ = val; res.SetType(ValueType::I64); return res; } 434 inline Value WABT_VECTORCALL Value::Make(u64 val) { Value res; res.i64_ = val; res.SetType(ValueType::I64); return res; } 435 inline Value WABT_VECTORCALL Value::Make(f32 val) { Value res; res.f32_ = val; res.SetType(ValueType::F32); return res; } 436 inline Value WABT_VECTORCALL Value::Make(f64 val) { Value res; res.f64_ = val; res.SetType(ValueType::F64); return res; } 437 inline Value WABT_VECTORCALL Value::Make(v128 val) { Value res; res.v128_ = val; res.SetType(ValueType::V128); return res; } 438 inline Value WABT_VECTORCALL Value::Make(Ref val) { Value res; res.ref_ = val; res.SetType(ValueType::ExternRef); return res; } 439 template <typename T, u8 L> 440 Value WABT_VECTORCALL Value::Make(Simd<T, L> val) { 441 Value res; 442 res.v128_ = Bitcast<v128>(val); 443 res.SetType(ValueType::V128); 444 return res; 445 } 446 447 template <> inline s8 WABT_VECTORCALL Value::Get<s8>() const { CheckType(ValueType::I32); return i32_; } 448 template <> inline u8 WABT_VECTORCALL Value::Get<u8>() const { CheckType(ValueType::I32); return i32_; } 449 template <> inline s16 WABT_VECTORCALL Value::Get<s16>() const { CheckType(ValueType::I32); return i32_; } 450 template <> inline u16 WABT_VECTORCALL Value::Get<u16>() const { CheckType(ValueType::I32); return i32_; } 451 template <> inline s32 WABT_VECTORCALL Value::Get<s32>() const { CheckType(ValueType::I32); return i32_; } 452 template <> inline u32 WABT_VECTORCALL Value::Get<u32>() const { CheckType(ValueType::I32); return i32_; } 453 template <> inline s64 WABT_VECTORCALL Value::Get<s64>() const { CheckType(ValueType::I64); return i64_; } 454 template <> inline u64 WABT_VECTORCALL Value::Get<u64>() const { CheckType(ValueType::I64); return i64_; } 455 template <> inline f32 WABT_VECTORCALL Value::Get<f32>() const { CheckType(ValueType::F32); return f32_; } 456 template <> inline f64 WABT_VECTORCALL Value::Get<f64>() const { CheckType(ValueType::F64); return f64_; } 457 template <> inline v128 WABT_VECTORCALL Value::Get<v128>() const { CheckType(ValueType::V128); return v128_; } 458 template <> inline Ref WABT_VECTORCALL Value::Get<Ref>() const { CheckType(ValueType::ExternRef); return ref_; } 459 460 template <> inline s8x16 WABT_VECTORCALL Value::Get<s8x16>() const { CheckType(ValueType::V128); return Bitcast<s8x16>(v128_); } 461 template <> inline u8x16 WABT_VECTORCALL Value::Get<u8x16>() const { CheckType(ValueType::V128); return Bitcast<u8x16>(v128_); } 462 template <> inline s16x8 WABT_VECTORCALL Value::Get<s16x8>() const { CheckType(ValueType::V128); return Bitcast<s16x8>(v128_); } 463 template <> inline u16x8 WABT_VECTORCALL Value::Get<u16x8>() const { CheckType(ValueType::V128); return Bitcast<u16x8>(v128_); } 464 template <> inline s32x4 WABT_VECTORCALL Value::Get<s32x4>() const { CheckType(ValueType::V128); return Bitcast<s32x4>(v128_); } 465 template <> inline u32x4 WABT_VECTORCALL Value::Get<u32x4>() const { CheckType(ValueType::V128); return Bitcast<u32x4>(v128_); } 466 template <> inline s64x2 WABT_VECTORCALL Value::Get<s64x2>() const { CheckType(ValueType::V128); return Bitcast<s64x2>(v128_); } 467 template <> inline u64x2 WABT_VECTORCALL Value::Get<u64x2>() const { CheckType(ValueType::V128); return Bitcast<u64x2>(v128_); } 468 template <> inline f32x4 WABT_VECTORCALL Value::Get<f32x4>() const { CheckType(ValueType::V128); return Bitcast<f32x4>(v128_); } 469 template <> inline f64x2 WABT_VECTORCALL Value::Get<f64x2>() const { CheckType(ValueType::V128); return Bitcast<f64x2>(v128_); } 470 471 template <> inline void WABT_VECTORCALL Value::Set<s32>(s32 val) { i32_ = val; SetType(ValueType::I32); } 472 template <> inline void WABT_VECTORCALL Value::Set<u32>(u32 val) { i32_ = val; SetType(ValueType::I32); } 473 template <> inline void WABT_VECTORCALL Value::Set<s64>(s64 val) { i64_ = val; SetType(ValueType::I64); } 474 template <> inline void WABT_VECTORCALL Value::Set<u64>(u64 val) { i64_ = val; SetType(ValueType::I64); } 475 template <> inline void WABT_VECTORCALL Value::Set<f32>(f32 val) { f32_ = val; SetType(ValueType::F32); } 476 template <> inline void WABT_VECTORCALL Value::Set<f64>(f64 val) { f64_ = val; SetType(ValueType::F64); } 477 template <> inline void WABT_VECTORCALL Value::Set<v128>(v128 val) { v128_ = val; SetType(ValueType::V128); } 478 template <> inline void WABT_VECTORCALL Value::Set<Ref>(Ref val) { ref_ = val; SetType(ValueType::ExternRef); } 479 480 //// Store //// 481 inline bool Store::IsValid(Ref ref) const { 482 return objects_.IsUsed(ref.index) && objects_.Get(ref.index); 483 } 484 485 template <typename T> 486 bool Store::Is(Ref ref) const { 487 return objects_.IsUsed(ref.index) && isa<T>(objects_.Get(ref.index)); 488 } 489 490 template <typename T> 491 Result Store::Get(Ref ref, RefPtr<T>* out) { 492 if (Is<T>(ref)) { 493 *out = RefPtr<T>(*this, ref); 494 return Result::Ok; 495 } 496 return Result::Error; 497 } 498 499 template <typename T> 500 RefPtr<T> Store::UnsafeGet(Ref ref) { 501 return RefPtr<T>(*this, ref); 502 } 503 504 template <typename T, typename... Args> 505 RefPtr<T> Store::Alloc(Args&&... args) { 506 Ref ref{objects_.New(new T(std::forward<Args>(args)...))}; 507 RefPtr<T> ptr{*this, ref}; 508 ptr->self_ = ref; 509 return ptr; 510 } 511 512 inline Store::ObjectList::Index Store::object_count() const { 513 return objects_.count(); 514 } 515 516 inline const Features& Store::features() const { 517 return features_; 518 } 519 520 inline std::set<Thread*>& Store::threads() { 521 return threads_; 522 } 523 524 //// Object //// 525 // static 526 inline bool Object::classof(const Object* obj) { 527 return true; 528 } 529 530 inline Object::Object(ObjectKind kind) : kind_(kind) {} 531 532 inline ObjectKind Object::kind() const { 533 return kind_; 534 } 535 536 inline Ref Object::self() const { 537 return self_; 538 } 539 540 inline void* Object::host_info() const { 541 return host_info_; 542 } 543 544 inline void Object::set_host_info(void* host_info) { 545 host_info_ = host_info; 546 } 547 548 inline Finalizer Object::get_finalizer() const { 549 return finalizer_; 550 } 551 552 inline void Object::set_finalizer(Finalizer finalizer) { 553 finalizer_ = finalizer; 554 } 555 556 //// Foreign //// 557 // static 558 inline bool Foreign::classof(const Object* obj) { 559 return obj->kind() == skind; 560 } 561 562 // static 563 inline Foreign::Ptr Foreign::New(Store& store, void* ptr) { 564 return store.Alloc<Foreign>(store, ptr); 565 } 566 567 inline void* Foreign::ptr() { 568 return ptr_; 569 } 570 571 //// Trap //// 572 // static 573 inline bool Trap::classof(const Object* obj) { 574 return obj->kind() == skind; 575 } 576 577 // static 578 inline Trap::Ptr Trap::New(Store& store, 579 const std::string& msg, 580 const std::vector<Frame>& trace) { 581 return store.Alloc<Trap>(store, msg, trace); 582 } 583 584 inline std::string Trap::message() const { 585 return message_; 586 } 587 588 //// Exception //// 589 // static 590 inline bool Exception::classof(const Object* obj) { 591 return obj->kind() == skind; 592 } 593 594 // static 595 inline Exception::Ptr Exception::New(Store& store, Ref tag, Values& args) { 596 return store.Alloc<Exception>(store, tag, args); 597 } 598 599 inline Ref Exception::tag() const { 600 return tag_; 601 } 602 603 inline Values& Exception::args() { 604 return args_; 605 } 606 607 //// Extern //// 608 // static 609 inline bool Extern::classof(const Object* obj) { 610 switch (obj->kind()) { 611 case ObjectKind::DefinedFunc: 612 case ObjectKind::HostFunc: 613 case ObjectKind::Table: 614 case ObjectKind::Memory: 615 case ObjectKind::Global: 616 case ObjectKind::Tag: 617 return true; 618 default: 619 return false; 620 } 621 } 622 623 inline Extern::Extern(ObjectKind kind) : Object(kind) {} 624 625 //// Func //// 626 // static 627 inline bool Func::classof(const Object* obj) { 628 switch (obj->kind()) { 629 case ObjectKind::DefinedFunc: 630 case ObjectKind::HostFunc: 631 return true; 632 default: 633 return false; 634 } 635 } 636 637 inline const ExternType& Func::extern_type() { 638 return type_; 639 } 640 641 inline const FuncType& Func::type() const { 642 return type_; 643 } 644 645 //// DefinedFunc //// 646 // static 647 inline bool DefinedFunc::classof(const Object* obj) { 648 return obj->kind() == skind; 649 } 650 651 // static 652 inline DefinedFunc::Ptr DefinedFunc::New(Store& store, 653 Ref instance, 654 FuncDesc desc) { 655 return store.Alloc<DefinedFunc>(store, instance, desc); 656 } 657 658 inline Ref DefinedFunc::instance() const { 659 return instance_; 660 } 661 662 inline const FuncDesc& DefinedFunc::desc() const { 663 return desc_; 664 } 665 666 //// HostFunc //// 667 // static 668 inline bool HostFunc::classof(const Object* obj) { 669 return obj->kind() == skind; 670 } 671 672 // static 673 inline HostFunc::Ptr HostFunc::New(Store& store, FuncType type, Callback cb) { 674 return store.Alloc<HostFunc>(store, type, cb); 675 } 676 677 //// Table //// 678 // static 679 inline bool Table::classof(const Object* obj) { 680 return obj->kind() == skind; 681 } 682 683 // static 684 inline Table::Ptr Table::New(Store& store, TableType type) { 685 return store.Alloc<Table>(store, type); 686 } 687 688 inline const ExternType& Table::extern_type() { 689 return type_; 690 } 691 692 inline const TableType& Table::type() const { 693 return type_; 694 } 695 696 inline const RefVec& Table::elements() const { 697 return elements_; 698 } 699 700 inline u32 Table::size() const { 701 return static_cast<u32>(elements_.size()); 702 } 703 704 //// Memory //// 705 // static 706 inline bool Memory::classof(const Object* obj) { 707 return obj->kind() == skind; 708 } 709 710 // static 711 inline Memory::Ptr Memory::New(interp::Store& store, MemoryType type) { 712 return store.Alloc<Memory>(store, type); 713 } 714 715 inline bool Memory::IsValidAccess(u64 offset, u64 addend, u64 size) const { 716 // FIXME: make this faster. 717 return offset <= data_.size() && addend <= data_.size() && 718 size <= data_.size() && offset + addend + size <= data_.size(); 719 } 720 721 inline bool Memory::IsValidAtomicAccess(u64 offset, 722 u64 addend, 723 u64 size) const { 724 return IsValidAccess(offset, addend, size) && 725 ((offset + addend) & (size - 1)) == 0; 726 } 727 728 template <typename T> 729 Result Memory::Load(u64 offset, u64 addend, T* out) const { 730 if (!IsValidAccess(offset, addend, sizeof(T))) { 731 return Result::Error; 732 } 733 MemcpyEndianAware(out, data_.data(), sizeof(T), data_.size(), 0, 734 offset + addend, sizeof(T)); 735 return Result::Ok; 736 } 737 738 template <typename T> 739 T WABT_VECTORCALL Memory::UnsafeLoad(u64 offset, u64 addend) const { 740 assert(IsValidAccess(offset, addend, sizeof(T))); 741 T val; 742 MemcpyEndianAware(&val, data_.data(), sizeof(T), data_.size(), 0, 743 offset + addend, sizeof(T)); 744 return val; 745 } 746 747 template <typename T> 748 Result WABT_VECTORCALL Memory::Store(u64 offset, u64 addend, T val) { 749 if (!IsValidAccess(offset, addend, sizeof(T))) { 750 return Result::Error; 751 } 752 MemcpyEndianAware(data_.data(), &val, data_.size(), sizeof(T), 753 offset + addend, 0, sizeof(T)); 754 return Result::Ok; 755 } 756 757 template <typename T> 758 Result Memory::AtomicLoad(u64 offset, u64 addend, T* out) const { 759 if (!IsValidAtomicAccess(offset, addend, sizeof(T))) { 760 return Result::Error; 761 } 762 MemcpyEndianAware(out, data_.data(), sizeof(T), data_.size(), 0, 763 offset + addend, sizeof(T)); 764 return Result::Ok; 765 } 766 767 template <typename T> 768 Result Memory::AtomicStore(u64 offset, u64 addend, T val) { 769 if (!IsValidAtomicAccess(offset, addend, sizeof(T))) { 770 return Result::Error; 771 } 772 MemcpyEndianAware(data_.data(), &val, data_.size(), sizeof(T), 773 offset + addend, 0, sizeof(T)); 774 return Result::Ok; 775 } 776 777 template <typename T, typename F> 778 Result Memory::AtomicRmw(u64 offset, u64 addend, T rhs, F&& func, T* out) { 779 T lhs; 780 CHECK_RESULT(AtomicLoad(offset, addend, &lhs)); 781 CHECK_RESULT(AtomicStore(offset, addend, func(lhs, rhs))); 782 *out = lhs; 783 return Result::Ok; 784 } 785 786 template <typename T> 787 Result Memory::AtomicRmwCmpxchg(u64 offset, 788 u64 addend, 789 T expect, 790 T replace, 791 T* out) { 792 T read; 793 CHECK_RESULT(AtomicLoad(offset, addend, &read)); 794 if (read == expect) { 795 CHECK_RESULT(AtomicStore(offset, addend, replace)); 796 } 797 *out = read; 798 return Result::Ok; 799 } 800 801 inline u8* Memory::UnsafeData() { 802 return data_.data(); 803 } 804 805 inline u64 Memory::ByteSize() const { 806 return data_.size(); 807 } 808 809 inline u64 Memory::PageSize() const { 810 return pages_; 811 } 812 813 inline const ExternType& Memory::extern_type() { 814 return type_; 815 } 816 817 inline const MemoryType& Memory::type() const { 818 return type_; 819 } 820 821 //// Global //// 822 // static 823 inline bool Global::classof(const Object* obj) { 824 return obj->kind() == skind; 825 } 826 827 // static 828 inline Global::Ptr Global::New(Store& store, GlobalType type, Value value) { 829 return store.Alloc<Global>(store, type, value); 830 } 831 832 inline Value Global::Get() const { 833 return value_; 834 } 835 836 template <typename T> 837 Result Global::Get(T* out) const { 838 if (HasType<T>(type_.type)) { 839 *out = value_.Get<T>(); 840 return Result::Ok; 841 } 842 return Result::Error; 843 } 844 845 template <typename T> 846 T WABT_VECTORCALL Global::UnsafeGet() const { 847 RequireType<T>(type_.type); 848 return value_.Get<T>(); 849 } 850 851 template <typename T> 852 Result WABT_VECTORCALL Global::Set(T val) { 853 if (type_.mut == Mutability::Var && HasType<T>(type_.type)) { 854 value_.Set(val); 855 return Result::Ok; 856 } 857 return Result::Error; 858 } 859 860 inline const ExternType& Global::extern_type() { 861 return type_; 862 } 863 864 inline const GlobalType& Global::type() const { 865 return type_; 866 } 867 868 //// Tag //// 869 // static 870 inline bool Tag::classof(const Object* obj) { 871 return obj->kind() == skind; 872 } 873 874 // static 875 inline Tag::Ptr Tag::New(Store& store, TagType type) { 876 return store.Alloc<Tag>(store, type); 877 } 878 879 inline const ExternType& Tag::extern_type() { 880 return type_; 881 } 882 883 inline const TagType& Tag::type() const { 884 return type_; 885 } 886 887 //// ElemSegment //// 888 inline void ElemSegment::Drop() { 889 elements_.clear(); 890 } 891 892 inline const ElemDesc& ElemSegment::desc() const { 893 return *desc_; 894 } 895 896 inline const RefVec& ElemSegment::elements() const { 897 return elements_; 898 } 899 900 inline u32 ElemSegment::size() const { 901 return elements_.size(); 902 } 903 904 //// DataSegment //// 905 inline void DataSegment::Drop() { 906 size_ = 0; 907 } 908 909 inline const DataDesc& DataSegment::desc() const { 910 return *desc_; 911 } 912 913 inline u64 DataSegment::size() const { 914 return size_; 915 } 916 917 //// Module //// 918 // static 919 inline bool Module::classof(const Object* obj) { 920 return obj->kind() == skind; 921 } 922 923 // static 924 inline Module::Ptr Module::New(Store& store, ModuleDesc desc) { 925 return store.Alloc<Module>(store, std::move(desc)); 926 } 927 928 inline const ModuleDesc& Module::desc() const { 929 return desc_; 930 } 931 932 inline const std::vector<ImportType>& Module::import_types() const { 933 return import_types_; 934 } 935 936 inline const std::vector<ExportType>& Module::export_types() const { 937 return export_types_; 938 } 939 940 //// Instance //// 941 // static 942 inline bool Instance::classof(const Object* obj) { 943 return obj->kind() == skind; 944 } 945 946 inline Ref Instance::module() const { 947 return module_; 948 } 949 950 inline const RefVec& Instance::imports() const { 951 return imports_; 952 } 953 954 inline const RefVec& Instance::funcs() const { 955 return funcs_; 956 } 957 958 inline const RefVec& Instance::tables() const { 959 return tables_; 960 } 961 962 inline const RefVec& Instance::memories() const { 963 return memories_; 964 } 965 966 inline const RefVec& Instance::globals() const { 967 return globals_; 968 } 969 970 inline const RefVec& Instance::tags() const { 971 return tags_; 972 } 973 974 inline const RefVec& Instance::exports() const { 975 return exports_; 976 } 977 978 inline const std::vector<ElemSegment>& Instance::elems() const { 979 return elems_; 980 } 981 982 inline std::vector<ElemSegment>& Instance::elems() { 983 return elems_; 984 } 985 986 inline const std::vector<DataSegment>& Instance::datas() const { 987 return datas_; 988 } 989 990 inline std::vector<DataSegment>& Instance::datas() { 991 return datas_; 992 } 993 994 //// Thread //// 995 inline Store& Thread::store() { 996 return store_; 997 } 998 999 } // namespace interp 1000 } // namespace wabt