v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
c-api.cc
Go to the documentation of this file.
1// Copyright 2019 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// This implementation is originally from
6// https://github.com/WebAssembly/wasm-c-api/:
7
8// Copyright 2019 Andreas Rossberg
9//
10// Licensed under the Apache License, Version 2.0 (the "License");
11// you may not use this file except in compliance with the License.
12// You may obtain a copy of the License at
13//
14// http://www.apache.org/licenses/LICENSE-2.0
15//
16// Unless required by applicable law or agreed to in writing, software
17// distributed under the License is distributed on an "AS IS" BASIS,
18// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19// See the License for the specific language governing permissions and
20// limitations under the License.
21
22#include "src/wasm/c-api.h"
23
24#include <cstring>
25#include <iomanip>
26#include <iostream>
27
30#include "src/api/api-inl.h"
33#include "src/flags/flags.h"
37#include "src/wasm/leb-helper.h"
46#include "third_party/wasm-api/wasm.h"
47
48#ifdef V8_OS_WIN
49
50// Setup for Windows DLL export/import. When building the V8 DLL the
51// BUILDING_V8_SHARED needs to be defined. When building a program which uses
52// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8
53// static library or building a program which uses the V8 static library neither
54// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined.
55#if !defined(LIBWASM_STATIC) && defined(USING_V8_SHARED)
56#define WASM_EXPORT __declspec(dllimport)
57#elif !defined(LIBWASM_STATIC)
58#define WASM_EXPORT __declspec(dllexport)
59#else
60#define WASM_EXPORT
61#endif // BUILDING_V8_SHARED
62
63#else // V8_OS_WIN
64
65// Setup for Linux shared library export.
66#if V8_HAS_ATTRIBUTE_VISIBILITY && \
67 (defined(BUILDING_V8_SHARED) || defined(USING_V8_SHARED))
68#define WASM_EXPORT __attribute__((visibility("default")))
69#else
70#define WASM_EXPORT
71#endif // V8_HAS_ATTRIBUTE_VISIBILITY && ...
72
73#endif // V8_OS_WIN
74
75#ifdef ENABLE_VTUNE_JIT_INTERFACE
76#include "third_party/vtune/v8-vtune.h"
77#endif
78
79#ifdef WASM_API_DEBUG
80#error "WASM_API_DEBUG is unsupported"
81#endif
82
83// If you want counters support (what --dump-counters does for the d8 shell),
84// then set this to 1 (in here, or via -DDUMP_COUNTERS=1 compiler argument).
85#define DUMP_COUNTERS 0
86
87namespace wasm {
88
89namespace {
90
91// Multi-cage pointer compression mode related note.
92// Wasm C-Api is allowed to be used from a thread that's not bound to any
93// Isolate. As a result, in a multi-cage pointer compression mode it's not
94// guaranteed that current pointer compression cage base value is initialized
95// for current thread (see V8HeapCompressionScheme::base_) which makes it
96// impossible to read compressed pointers from V8 heap objects.
97// This scope ensures that the pointer compression base value is set according
98// to respective Wasm C-Api object.
99// For all other configurations this scope is a no-op.
100using PtrComprCageAccessScope = i::PtrComprCageAccessScope;
101
102auto ReadLebU64(const byte_t** pos) -> uint64_t {
103 uint64_t n = 0;
104 uint64_t shift = 0;
105 byte_t b;
106 do {
107 b = **pos;
108 (*pos)++;
109 n += (b & 0x7f) << shift;
110 shift += 7;
111 } while ((b & 0x80) != 0);
112 return n;
113}
114
115template <typename T>
116ValKind V8ValueTypeToWasm(T v8_valtype)
117 requires(std::is_same_v<T, i::wasm::ValueType> ||
118 std::is_same_v<T, i::wasm::CanonicalValueType>)
119{
120 switch (v8_valtype.kind()) {
121 case i::wasm::kI32:
122 return ValKind::I32;
123 case i::wasm::kI64:
124 return ValKind::I64;
125 case i::wasm::kF32:
126 return ValKind::F32;
127 case i::wasm::kF64:
128 return ValKind::F64;
129 case i::wasm::kRef:
130 case i::wasm::kRefNull:
131 switch (v8_valtype.heap_representation()) {
132 case i::wasm::HeapType::kFunc:
133 return ValKind::FUNCREF;
134 case i::wasm::HeapType::kExtern:
135 return ValKind::EXTERNREF;
136 default:
137 UNREACHABLE();
138 }
139 default:
140 UNREACHABLE();
141 }
142}
143
144i::wasm::ValueType WasmValKindToV8(ValKind kind) {
145 switch (kind) {
146 case ValKind::I32:
147 return i::wasm::kWasmI32;
148 case ValKind::I64:
149 return i::wasm::kWasmI64;
150 case ValKind::F32:
151 return i::wasm::kWasmF32;
152 case ValKind::F64:
153 return i::wasm::kWasmF64;
154 case ValKind::FUNCREF:
155 return i::wasm::kWasmFuncRef;
156 case ValKind::EXTERNREF:
157 return i::wasm::kWasmExternRef;
158 default:
159 // TODO(wasm+): support new value types
160 UNREACHABLE();
161 }
162}
163
164Name GetNameFromWireBytes(const i::wasm::WireBytesRef& ref,
166 DCHECK_LE(ref.offset(), wire_bytes.length());
167 DCHECK_LE(ref.end_offset(), wire_bytes.length());
168 if (ref.length() == 0) return Name::make();
169 Name name = Name::make_uninitialized(ref.length());
170 std::memcpy(name.get(), wire_bytes.begin() + ref.offset(), ref.length());
171 return name;
172}
173
174own<FuncType> FunctionSigToFuncType(const i::wasm::FunctionSig* sig) {
175 size_t param_count = sig->parameter_count();
176 ownvec<ValType> params = ownvec<ValType>::make_uninitialized(param_count);
177 for (size_t i = 0; i < param_count; i++) {
178 params[i] = ValType::make(V8ValueTypeToWasm(sig->GetParam(i)));
179 }
180 size_t return_count = sig->return_count();
181 ownvec<ValType> results = ownvec<ValType>::make_uninitialized(return_count);
182 for (size_t i = 0; i < return_count; i++) {
183 results[i] = ValType::make(V8ValueTypeToWasm(sig->GetReturn(i)));
184 }
185 return FuncType::make(std::move(params), std::move(results));
186}
187
188own<ExternType> GetImportExportType(const i::wasm::WasmModule* module,
189 const i::wasm::ImportExportKindCode kind,
190 const uint32_t index) {
191 switch (kind) {
192 case i::wasm::kExternalFunction: {
193 return FunctionSigToFuncType(module->functions[index].sig);
194 }
195 case i::wasm::kExternalTable: {
196 const i::wasm::WasmTable& table = module->tables[index];
197 own<ValType> elem = ValType::make(V8ValueTypeToWasm(table.type));
198 Limits limits(table.initial_size,
199 table.has_maximum_size
200 ? v8::base::checked_cast<int32_t>(table.maximum_size)
201 : -1);
202 return TableType::make(std::move(elem), limits);
203 }
204 case i::wasm::kExternalMemory: {
205 const i::wasm::WasmMemory& memory = module->memories[index];
206 Limits limits(memory.initial_pages,
207 memory.has_maximum_pages
208 ? v8::base::checked_cast<int32_t>(memory.maximum_pages)
209 : -1);
210 return MemoryType::make(limits);
211 }
212 case i::wasm::kExternalGlobal: {
213 const i::wasm::WasmGlobal& global = module->globals[index];
214 own<ValType> content = ValType::make(V8ValueTypeToWasm(global.type));
215 Mutability mutability =
216 global.mutability ? Mutability::VAR : Mutability::CONST;
217 return GlobalType::make(std::move(content), mutability);
218 }
219 case i::wasm::kExternalTag:
220 UNREACHABLE();
221 }
222}
223
224} // namespace
225
227
229// Auxiliaries
230
231[[noreturn]] void WASM_UNIMPLEMENTED(const char* s) {
232 std::cerr << "Wasm API: " << s << " not supported yet!\n";
233 exit(1);
234}
235
236template <class T>
237void ignore(T) {}
238
239template <class C>
241
242template <class C>
243auto impl(C* x) -> typename implement<C>::type* {
244 return reinterpret_cast<typename implement<C>::type*>(x);
245}
246
247template <class C>
248auto impl(const C* x) -> const typename implement<C>::type* {
249 return reinterpret_cast<const typename implement<C>::type*>(x);
250}
251
252template <class C>
253auto seal(typename implement<C>::type* x) -> C* {
254 return reinterpret_cast<C*>(x);
255}
256
257template <class C>
258auto seal(const typename implement<C>::type* x) -> const C* {
259 return reinterpret_cast<const C*>(x);
260}
261
263// Runtime Environment
264
265// Configuration
266
267struct ConfigImpl {};
268
269template <>
270struct implement<Config> {
272};
273
274WASM_EXPORT void Config::destroy() { delete impl(this); }
275
276WASM_EXPORT auto Config::make() -> own<Config> {
277 return own<Config>(seal<Config>(new (std::nothrow) ConfigImpl()));
278}
279
280// Engine
281
282#if DUMP_COUNTERS
283class Counter {
284 public:
285 static const int kMaxNameSize = 64;
286 int32_t* Bind(const char* name, bool is_histogram) {
287 int i;
288 for (i = 0; i < kMaxNameSize - 1 && name[i]; i++) {
289 name_[i] = static_cast<char>(name[i]);
290 }
291 name_[i] = '\0';
292 is_histogram_ = is_histogram;
293 return ptr();
294 }
295 int32_t* ptr() { return &count_; }
296 int32_t count() { return count_; }
297 int32_t sample_total() { return sample_total_; }
298 bool is_histogram() { return is_histogram_; }
299 void AddSample(int32_t sample) {
300 count_++;
301 sample_total_ += sample;
302 }
303
304 private:
306 int32_t sample_total_;
307 bool is_histogram_;
308 uint8_t name_[kMaxNameSize];
309};
310
311class CounterCollection {
312 public:
313 CounterCollection() = default;
314 Counter* GetNextCounter() {
315 if (counters_in_use_ == kMaxCounters) return nullptr;
316 return &counters_[counters_in_use_++];
317 }
318
319 private:
320 static const unsigned kMaxCounters = 512;
321 uint32_t counters_in_use_{0};
322 Counter counters_[kMaxCounters];
323};
324
325using CounterMap = std::unordered_map<std::string, Counter*>;
326
327#endif
328
330 static bool created;
331
332 std::unique_ptr<v8::Platform> platform;
333
334#if DUMP_COUNTERS
335 static CounterCollection counters_;
336 static CounterMap* counter_map_;
337
338 static Counter* GetCounter(const char* name, bool is_histogram) {
339 auto map_entry = counter_map_->find(name);
340 Counter* counter =
341 map_entry != counter_map_->end() ? map_entry->second : nullptr;
342
343 if (counter == nullptr) {
344 counter = counters_.GetNextCounter();
345 if (counter != nullptr) {
346 (*counter_map_)[name] = counter;
347 counter->Bind(name, is_histogram);
348 }
349 } else {
350 DCHECK(counter->is_histogram() == is_histogram);
351 }
352 return counter;
353 }
354
355 static int* LookupCounter(const char* name) {
356 Counter* counter = GetCounter(name, false);
357
358 if (counter != nullptr) {
359 return counter->ptr();
360 } else {
361 return nullptr;
362 }
363 }
364
365 static void* CreateHistogram(const char* name, int min, int max,
366 size_t buckets) {
367 return GetCounter(name, true);
368 }
369
370 static void AddHistogramSample(void* histogram, int sample) {
371 Counter* counter = reinterpret_cast<Counter*>(histogram);
372 counter->AddSample(sample);
373 }
374#endif
375
377 assert(!created);
378 created = true;
379#if DUMP_COUNTERS
380 counter_map_ = new CounterMap();
381#endif
382 }
383
385#if DUMP_COUNTERS
386 std::vector<std::pair<std::string, Counter*>> counters(
387 counter_map_->begin(), counter_map_->end());
388 std::sort(counters.begin(), counters.end());
389 // Dump counters in formatted boxes.
390 constexpr int kNameBoxSize = 64;
391 constexpr int kValueBoxSize = 13;
392 std::cout << "+" << std::string(kNameBoxSize, '-') << "+"
393 << std::string(kValueBoxSize, '-') << "+\n";
394 std::cout << "| Name" << std::string(kNameBoxSize - 5, ' ') << "| Value"
395 << std::string(kValueBoxSize - 6, ' ') << "|\n";
396 std::cout << "+" << std::string(kNameBoxSize, '-') << "+"
397 << std::string(kValueBoxSize, '-') << "+\n";
398 for (const auto& pair : counters) {
399 std::string key = pair.first;
400 Counter* counter = pair.second;
401 if (counter->is_histogram()) {
402 std::cout << "| c:" << std::setw(kNameBoxSize - 4) << std::left << key
403 << " | " << std::setw(kValueBoxSize - 2) << std::right
404 << counter->count() << " |\n";
405 std::cout << "| t:" << std::setw(kNameBoxSize - 4) << std::left << key
406 << " | " << std::setw(kValueBoxSize - 2) << std::right
407 << counter->sample_total() << " |\n";
408 } else {
409 std::cout << "| " << std::setw(kNameBoxSize - 2) << std::left << key
410 << " | " << std::setw(kValueBoxSize - 2) << std::right
411 << counter->count() << " |\n";
412 }
413 }
414 std::cout << "+" << std::string(kNameBoxSize, '-') << "+"
415 << std::string(kValueBoxSize, '-') << "+\n";
416 delete counter_map_;
417#endif
420 }
421};
422
423bool EngineImpl::created = false;
424
425#if DUMP_COUNTERS
426CounterCollection EngineImpl::counters_;
427CounterMap* EngineImpl::counter_map_;
428#endif
429
430template <>
431struct implement<Engine> {
433};
434
435WASM_EXPORT void Engine::destroy() { delete impl(this); }
436
437WASM_EXPORT auto Engine::make(own<Config>&& config) -> own<Engine> {
438 auto engine = new (std::nothrow) EngineImpl;
439 if (!engine) return own<Engine>();
440 engine->platform = i::v8_flags.single_threaded
442 : v8::platform::NewDefaultPlatform(
443 i::v8_flags.wasm_capi_thread_pool_size);
444 v8::V8::InitializePlatform(engine->platform.get());
446
447 if (i::v8_flags.prof) {
448 i::PrintF(
449 "--prof is currently unreliable for V8's Wasm-C-API due to "
450 "fast-c-calls.\n");
451 }
452
453 return make_own(seal<Engine>(engine));
454}
455
456// This should be called somewhat regularly, especially on potentially hot
457// sections of pure C++ execution. To achieve that, we call it on API entry
458// points that heap-allocate but don't call into generated code.
459// For example, finalization of incremental marking is relying on it.
461 i::StackLimitCheck check(isolate);
462 if (check.InterruptRequested()) {
463 isolate->stack_guard()->HandleInterrupts();
464 }
465}
466
467// Stores
468
469void StoreImpl::destroy() { delete this; }
470
472 {
473 v8::Isolate::Scope isolate_scope(isolate_);
474#ifdef DEBUG
475 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate_);
477 i::GCFlag::kForced, i::GarbageCollectionReason::kTesting,
479#endif
480 context()->Exit();
481 }
482 isolate_->Dispose();
484}
485
488
489 ManagedData(void* info, void (*finalizer)(void*))
490 : info(info), finalizer(finalizer) {}
491
493 if (finalizer) (*finalizer)(info);
494 }
495
496 void* info;
497 void (*finalizer)(void*);
498};
499
501 void (*finalizer)(void*)) {
502 v8::Isolate::Scope isolate_scope(isolate());
503 i::HandleScope scope(i_isolate());
504 // Ideally we would specify the total size kept alive by {info} here,
505 // but all we get from the embedder is a {void*}, so our best estimate
506 // is the size of the metadata.
507 size_t estimated_size = sizeof(ManagedData);
509 i_isolate(), estimated_size,
510 std::make_shared<ManagedData>(info, finalizer));
511 int32_t hash = i::Object::GetOrCreateHash(*object, i_isolate()).value();
512 i::JSWeakCollection::Set(host_info_map_, object, wrapper, hash);
513}
514
516 PtrComprCageAccessScope ptr_compr_cage_access_scope(i_isolate());
519 if (IsTheHole(raw, i_isolate())) return nullptr;
520 return i::Cast<i::Managed<ManagedData>>(raw)->raw()->info;
521}
522
523template <>
524struct implement<Store> {
526};
527
528WASM_EXPORT void Store::destroy() { delete impl(this); }
529
530WASM_EXPORT auto Store::make(Engine*) -> own<Store> {
531 auto store = make_own(new (std::nothrow) StoreImpl());
532 if (!store) return own<Store>();
533
534 // Create isolate.
535 store->create_params_.array_buffer_allocator =
537#ifdef ENABLE_VTUNE_JIT_INTERFACE
538 store->create_params_.code_event_handler = vTune::GetVtuneCodeEventHandler();
539#endif
540#if DUMP_COUNTERS
541 store->create_params_.counter_lookup_callback = EngineImpl::LookupCounter;
542 store->create_params_.create_histogram_callback = EngineImpl::CreateHistogram;
543 store->create_params_.add_histogram_sample_callback =
544 EngineImpl::AddHistogramSample;
545#endif
546 v8::Isolate* isolate = v8::Isolate::New(store->create_params_);
547 if (!isolate) return own<Store>();
548 store->isolate_ = isolate;
549 isolate->SetData(0, store.get());
550 // We intentionally do not call isolate->Enter() here, because that would
551 // prevent embedders from using stores with overlapping but non-nested
552 // lifetimes. The consequence is that Isolate::Current() is dysfunctional
553 // and hence must not be called by anything reachable via this file.
554
555 {
556 v8::Isolate::Scope isolate_scope(isolate);
557 v8::HandleScope handle_scope(isolate);
558
559 // Create context.
560 v8::Local<v8::Context> context = v8::Context::New(isolate);
561 if (context.IsEmpty()) return own<Store>();
562 context->Enter(); // The Exit() call is in ~StoreImpl.
563 store->context_ = v8::Eternal<v8::Context>(isolate, context);
564
565 // Create weak map for Refs with host info.
566 i::Isolate* i_isolate = reinterpret_cast<i::Isolate*>(isolate);
567 store->host_info_map_ = i_isolate->global_handles()->Create(
568 *i_isolate->factory()->NewJSWeakMap());
569 }
570 // We want stack traces for traps.
571 constexpr int kStackLimit = 10;
572 isolate->SetCaptureStackTraceForUncaughtExceptions(true, kStackLimit,
574
575 return make_own(seal<Store>(store.release()));
576}
577
579// Type Representations
580
581// Value Types
582
584 ValKind kind;
585
586 explicit ValTypeImpl(ValKind kind) : kind(kind) {}
587};
588
589template <>
590struct implement<ValType> {
592};
593
598ValTypeImpl* valtype_externref = new ValTypeImpl(ValKind::EXTERNREF);
599ValTypeImpl* valtype_funcref = new ValTypeImpl(ValKind::FUNCREF);
600
601WASM_EXPORT void ValType::destroy() { this->~ValType(); }
602
603WASM_EXPORT own<ValType> ValType::make(ValKind k) {
604 ValTypeImpl* valtype;
605 switch (k) {
606 case ValKind::I32:
607 valtype = valtype_i32;
608 break;
609 case ValKind::I64:
610 valtype = valtype_i64;
611 break;
612 case ValKind::F32:
613 valtype = valtype_f32;
614 break;
615 case ValKind::F64:
616 valtype = valtype_f64;
617 break;
618 case ValKind::EXTERNREF:
619 valtype = valtype_externref;
620 break;
621 case ValKind::FUNCREF:
622 valtype = valtype_funcref;
623 break;
624 default:
625 // TODO(wasm+): support new value types
626 UNREACHABLE();
627 }
628 return own<ValType>(seal<ValType>(valtype));
629}
630
631WASM_EXPORT auto ValType::copy() const -> own<ValType> { return make(kind()); }
632
633WASM_EXPORT auto ValType::kind() const -> ValKind { return impl(this)->kind; }
634
635// Extern Types
636
638 ExternKind kind;
639
640 explicit ExternTypeImpl(ExternKind kind) : kind(kind) {}
641 virtual ~ExternTypeImpl() = default;
642};
643
644template <>
645struct implement<ExternType> {
647};
648
649WASM_EXPORT void ExternType::destroy() { delete impl(this); }
650
651WASM_EXPORT auto ExternType::copy() const -> own<ExternType> {
652 switch (kind()) {
653 case ExternKind::FUNC:
654 return func()->copy();
655 case ExternKind::GLOBAL:
656 return global()->copy();
657 case ExternKind::TABLE:
658 return table()->copy();
659 case ExternKind::MEMORY:
660 return memory()->copy();
661 }
662}
663
664WASM_EXPORT auto ExternType::kind() const -> ExternKind {
665 return impl(this)->kind;
666}
667
668// Function Types
669
671 ownvec<ValType> params;
672 ownvec<ValType> results;
673
674 FuncTypeImpl(ownvec<ValType>& params, ownvec<ValType>& results)
675 : ExternTypeImpl(ExternKind::FUNC),
676 params(std::move(params)),
677 results(std::move(results)) {}
678};
679
680template <>
681struct implement<FuncType> {
683};
684
685WASM_EXPORT void FuncType::destroy() { delete impl(this); }
686
687WASM_EXPORT auto FuncType::make(ownvec<ValType>&& params,
688 ownvec<ValType>&& results) -> own<FuncType> {
689 return params && results
690 ? own<FuncType>(seal<FuncType>(new (std::nothrow)
691 FuncTypeImpl(params, results)))
692 : own<FuncType>();
693}
694
695WASM_EXPORT auto FuncType::copy() const -> own<FuncType> {
696 return make(params().deep_copy(), results().deep_copy());
697}
698
699WASM_EXPORT auto FuncType::params() const -> const ownvec<ValType>& {
700 return impl(this)->params;
701}
702
703WASM_EXPORT auto FuncType::results() const -> const ownvec<ValType>& {
704 return impl(this)->results;
705}
706
707WASM_EXPORT auto ExternType::func() -> FuncType* {
708 return kind() == ExternKind::FUNC
709 ? seal<FuncType>(static_cast<FuncTypeImpl*>(impl(this)))
710 : nullptr;
711}
712
713WASM_EXPORT auto ExternType::func() const -> const FuncType* {
714 return kind() == ExternKind::FUNC
715 ? seal<FuncType>(static_cast<const FuncTypeImpl*>(impl(this)))
716 : nullptr;
717}
718
719// Global Types
720
722 own<ValType> content;
723 Mutability mutability;
724
725 GlobalTypeImpl(own<ValType>& content, Mutability mutability)
726 : ExternTypeImpl(ExternKind::GLOBAL),
727 content(std::move(content)),
729
730 ~GlobalTypeImpl() override = default;
731};
732
733template <>
734struct implement<GlobalType> {
736};
737
738void GlobalType::destroy() { delete impl(this); }
739
740auto GlobalType::make(own<ValType>&& content, Mutability mutability)
741 -> own<GlobalType> {
742 return content ? own<GlobalType>(seal<GlobalType>(
743 new (std::nothrow) GlobalTypeImpl(content, mutability)))
744 : own<GlobalType>();
745}
746
747auto GlobalType::copy() const -> own<GlobalType> {
748 return make(content()->copy(), mutability());
749}
750
751auto GlobalType::content() const -> const ValType* {
752 return impl(this)->content.get();
753}
754
755auto GlobalType::mutability() const -> Mutability {
756 return impl(this)->mutability;
757}
758
759auto ExternType::global() -> GlobalType* {
760 return kind() == ExternKind::GLOBAL
761 ? seal<GlobalType>(static_cast<GlobalTypeImpl*>(impl(this)))
762 : nullptr;
763}
764
765auto ExternType::global() const -> const GlobalType* {
766 return kind() == ExternKind::GLOBAL
767 ? seal<GlobalType>(static_cast<const GlobalTypeImpl*>(impl(this)))
768 : nullptr;
769}
770
771// Table Types
772
774 own<ValType> element;
775 Limits limits;
776
777 TableTypeImpl(own<ValType>& element, Limits limits)
778 : ExternTypeImpl(ExternKind::TABLE),
779 element(std::move(element)),
780 limits(limits) {}
781
782 ~TableTypeImpl() override = default;
783};
784
785template <>
786struct implement<TableType> {
788};
789
790WASM_EXPORT void TableType::destroy() { delete impl(this); }
791
792WASM_EXPORT auto TableType::make(own<ValType>&& element, Limits limits)
793 -> own<TableType> {
794 return element ? own<TableType>(seal<TableType>(
795 new (std::nothrow) TableTypeImpl(element, limits)))
796 : own<TableType>();
797}
798
799WASM_EXPORT auto TableType::copy() const -> own<TableType> {
800 return make(element()->copy(), limits());
801}
802
803WASM_EXPORT auto TableType::element() const -> const ValType* {
804 return impl(this)->element.get();
805}
806
807WASM_EXPORT auto TableType::limits() const -> const Limits& {
808 return impl(this)->limits;
809}
810
811WASM_EXPORT auto ExternType::table() -> TableType* {
812 return kind() == ExternKind::TABLE
813 ? seal<TableType>(static_cast<TableTypeImpl*>(impl(this)))
814 : nullptr;
815}
816
817WASM_EXPORT auto ExternType::table() const -> const TableType* {
818 return kind() == ExternKind::TABLE
819 ? seal<TableType>(static_cast<const TableTypeImpl*>(impl(this)))
820 : nullptr;
821}
822
823// Memory Types
824
826 Limits limits;
827
828 explicit MemoryTypeImpl(Limits limits)
829 : ExternTypeImpl(ExternKind::MEMORY), limits(limits) {}
830
831 ~MemoryTypeImpl() override = default;
832};
833
834template <>
835struct implement<MemoryType> {
837};
838
839WASM_EXPORT auto MemoryType::make(Limits limits) -> own<MemoryType> {
840 return own<MemoryType>(
841 seal<MemoryType>(new (std::nothrow) MemoryTypeImpl(limits)));
842}
843
844void MemoryType::destroy() { delete impl(this); }
845
846WASM_EXPORT auto MemoryType::copy() const -> own<MemoryType> {
847 return MemoryType::make(limits());
848}
849
850WASM_EXPORT auto MemoryType::limits() const -> const Limits& {
851 return impl(this)->limits;
852}
853
854WASM_EXPORT auto ExternType::memory() -> MemoryType* {
855 return kind() == ExternKind::MEMORY
856 ? seal<MemoryType>(static_cast<MemoryTypeImpl*>(impl(this)))
857 : nullptr;
858}
859
860WASM_EXPORT auto ExternType::memory() const -> const MemoryType* {
861 return kind() == ExternKind::MEMORY
862 ? seal<MemoryType>(static_cast<const MemoryTypeImpl*>(impl(this)))
863 : nullptr;
864}
865
866// Import Types
867
869 Name module;
870 Name name;
871 own<ExternType> type;
872
873 ImportTypeImpl(Name& module, Name& name, own<ExternType>& type)
874 : module(std::move(module)),
875 name(std::move(name)),
876 type(std::move(type)) {}
877};
878
879template <>
880struct implement<ImportType> {
882};
883
884WASM_EXPORT void ImportType::destroy() { delete impl(this); }
885
886WASM_EXPORT auto ImportType::make(Name&& module, Name&& name,
887 own<ExternType>&& type) -> own<ImportType> {
888 return module && name && type
889 ? own<ImportType>(seal<ImportType>(
890 new (std::nothrow) ImportTypeImpl(module, name, type)))
891 : own<ImportType>();
892}
893
894WASM_EXPORT auto ImportType::copy() const -> own<ImportType> {
895 return make(module().copy(), name().copy(), type()->copy());
896}
897
898WASM_EXPORT auto ImportType::module() const -> const Name& {
899 return impl(this)->module;
900}
901
902WASM_EXPORT auto ImportType::name() const -> const Name& {
903 return impl(this)->name;
904}
905
906WASM_EXPORT auto ImportType::type() const -> const ExternType* {
907 return impl(this)->type.get();
908}
909
910// Export Types
911
913 Name name;
914 own<ExternType> type;
915
916 ExportTypeImpl(Name& name, own<ExternType>& type)
917 : name(std::move(name)), type(std::move(type)) {}
918};
919
920template <>
921struct implement<ExportType> {
923};
924
925WASM_EXPORT void ExportType::destroy() { delete impl(this); }
926
927WASM_EXPORT auto ExportType::make(Name&& name, own<ExternType>&& type)
928 -> own<ExportType> {
929 return name && type ? own<ExportType>(seal<ExportType>(
930 new (std::nothrow) ExportTypeImpl(name, type)))
931 : own<ExportType>();
932}
933
934WASM_EXPORT auto ExportType::copy() const -> own<ExportType> {
935 return make(name().copy(), type()->copy());
936}
937
938WASM_EXPORT auto ExportType::name() const -> const Name& {
939 return impl(this)->name;
940}
941
942WASM_EXPORT auto ExportType::type() const -> const ExternType* {
943 return impl(this)->type.get();
944}
945
947 const vec<byte_t>& chars) {
948 size_t length = chars.size();
949 // Some, but not all, {chars} vectors we get here are null-terminated,
950 // so let's be robust to that.
951 if (length > 0 && chars[length - 1] == 0) length--;
952 return isolate->factory()
953 ->NewStringFromUtf8({chars.get(), length})
954 .ToHandleChecked();
955}
956
957// References
958
959template <class Ref, class JSType>
960class RefImpl {
961 public:
962 static own<Ref> make(StoreImpl* store, i::DirectHandle<JSType> obj) {
963 RefImpl* self = new (std::nothrow) RefImpl();
964 if (!self) return nullptr;
965 self->store_ = store;
966 v8::Isolate::Scope isolate_scope(store->isolate());
967 self->val_ = store->i_isolate()->global_handles()->Create(*obj);
968 return make_own(seal<Ref>(self));
969 }
970
971 ~RefImpl() { i::GlobalHandles::Destroy(location()); }
972
973 own<Ref> copy() const {
974 v8::Isolate::Scope isolate_scope(store()->isolate());
975 return make(store(), v8_object());
976 }
977
978 StoreImpl* store() const { return store_; }
979
980 i::Isolate* isolate() const { return store()->i_isolate(); }
981
983
984 void* get_host_info() const {
985 v8::Isolate::Scope isolate_scope(store()->isolate());
986 return store()->GetHostInfo(v8_object());
987 }
988
989 void set_host_info(void* info, void (*finalizer)(void*)) {
990 v8::Isolate::Scope isolate_scope(store()->isolate());
991 store()->SetHostInfo(v8_object(), info, finalizer);
992 }
993
994 private:
995 RefImpl() = default;
996
998 return reinterpret_cast<i::Address*>(val_.address());
999 }
1000
1003};
1004
1005template <>
1009
1010WASM_EXPORT void Ref::destroy() { delete impl(this); }
1011
1012WASM_EXPORT auto Ref::copy() const -> own<Ref> { return impl(this)->copy(); }
1013
1014WASM_EXPORT auto Ref::same(const Ref* that) const -> bool {
1015 i::Isolate* isolate = impl(this)->isolate();
1016 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1017 i::HandleScope handle_scope(isolate);
1018 return i::Object::SameValue(*impl(this)->v8_object(),
1019 *impl(that)->v8_object());
1020}
1021
1022WASM_EXPORT auto Ref::get_host_info() const -> void* {
1023 return impl(this)->get_host_info();
1024}
1025
1026WASM_EXPORT void Ref::set_host_info(void* info, void (*finalizer)(void*)) {
1027 impl(this)->set_host_info(info, finalizer);
1028}
1029
1031// Runtime Objects
1032
1033// Frames
1034
1035namespace {
1036
1037struct FrameImpl {
1038 FrameImpl(own<Instance>&& instance, uint32_t func_index, size_t func_offset,
1039 size_t module_offset)
1040 : instance(std::move(instance)),
1041 func_index(func_index),
1042 func_offset(func_offset),
1043 module_offset(module_offset) {}
1044
1045 own<Instance> instance;
1046 uint32_t func_index;
1047 size_t func_offset;
1048 size_t module_offset;
1049};
1050
1051} // namespace
1052
1053template <>
1054struct implement<Frame> {
1055 using type = FrameImpl;
1056};
1057
1058WASM_EXPORT void Frame::destroy() { delete impl(this); }
1059
1060WASM_EXPORT own<Frame> Frame::copy() const {
1061 auto self = impl(this);
1062 return own<Frame>(seal<Frame>(
1063 new (std::nothrow) FrameImpl(self->instance->copy(), self->func_index,
1064 self->func_offset, self->module_offset)));
1065}
1066
1067WASM_EXPORT Instance* Frame::instance() const {
1068 return impl(this)->instance.get();
1069}
1070
1071WASM_EXPORT uint32_t Frame::func_index() const {
1072 return impl(this)->func_index;
1073}
1074
1075WASM_EXPORT size_t Frame::func_offset() const {
1076 return impl(this)->func_offset;
1077}
1078
1079WASM_EXPORT size_t Frame::module_offset() const {
1080 return impl(this)->module_offset;
1081}
1082
1083// Traps
1084
1085template <>
1086struct implement<Trap> {
1088};
1089
1090WASM_EXPORT void Trap::destroy() { delete impl(this); }
1091
1092WASM_EXPORT auto Trap::copy() const -> own<Trap> { return impl(this)->copy(); }
1093
1094WASM_EXPORT auto Trap::make(Store* store_abs, const Message& message)
1095 -> own<Trap> {
1096 auto store = impl(store_abs);
1097 i::Isolate* isolate = store->i_isolate();
1098 v8::Isolate::Scope isolate_scope(store->isolate());
1099 i::HandleScope handle_scope(isolate);
1100 i::DirectHandle<i::String> string = VecToString(isolate, message);
1102 isolate->factory()->NewError(isolate->error_function(), string);
1103 i::JSObject::AddProperty(isolate, exception,
1104 isolate->factory()->wasm_uncatchable_symbol(),
1105 isolate->factory()->true_value(), i::NONE);
1106 return implement<Trap>::type::make(store, exception);
1107}
1108
1109WASM_EXPORT auto Trap::message() const -> Message {
1110 auto isolate = impl(this)->isolate();
1111 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1112 i::HandleScope handle_scope(isolate);
1113
1115 isolate->CreateMessage(impl(this)->v8_object(), nullptr);
1117 i::MessageHandler::GetMessage(isolate, message);
1118 result = i::String::Flatten(isolate, result); // For performance.
1119 size_t length = 0;
1120 std::unique_ptr<char[]> utf8 = result->ToCString(&length);
1121 return vec<byte_t>::adopt(length, utf8.release());
1122}
1123
1124namespace {
1125
1126own<Instance> GetInstance(StoreImpl* store,
1128
1129own<Frame> CreateFrameFromInternal(i::DirectHandle<i::FixedArray> frames,
1130 int index, i::Isolate* isolate,
1131 StoreImpl* store) {
1132 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1134 i::Cast<i::CallSiteInfo>(frames->get(index)), isolate);
1135 i::DirectHandle<i::WasmInstanceObject> instance(frame->GetWasmInstance(),
1136 isolate);
1137 uint32_t func_index = frame->GetWasmFunctionIndex();
1138 size_t module_offset = i::CallSiteInfo::GetSourcePosition(frame);
1139 size_t func_offset = module_offset - i::wasm::GetWasmFunctionOffset(
1140 instance->module(), func_index);
1141 return own<Frame>(seal<Frame>(new (std::nothrow) FrameImpl(
1142 GetInstance(store, instance), func_index, func_offset, module_offset)));
1143}
1144
1145} // namespace
1146
1147own<Frame> Trap::origin() const {
1148 i::Isolate* isolate = impl(this)->isolate();
1149 PtrComprCageAccessScope ptr_compr_cage_access_scope(impl(this)->isolate());
1150 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1151 i::HandleScope handle_scope(isolate);
1152
1154 isolate->GetSimpleStackTrace(impl(this)->v8_object());
1155 if (frames->length() == 0) {
1156 return own<Frame>();
1157 }
1158 return CreateFrameFromInternal(frames, 0, isolate, impl(this)->store());
1159}
1160
1161ownvec<Frame> Trap::trace() const {
1162 i::Isolate* isolate = impl(this)->isolate();
1163 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1164 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1165 i::HandleScope handle_scope(isolate);
1166
1168 isolate->GetSimpleStackTrace(impl(this)->v8_object());
1169 int num_frames = frames->length();
1170 // {num_frames} can be 0; the code below can handle that case.
1171 ownvec<Frame> result = ownvec<Frame>::make_uninitialized(num_frames);
1172 for (int i = 0; i < num_frames; i++) {
1173 result[i] =
1174 CreateFrameFromInternal(frames, i, isolate, impl(this)->store());
1175 }
1176 return result;
1177}
1178
1179// Foreign Objects
1180
1181template <>
1182struct implement<Foreign> {
1184};
1185
1186WASM_EXPORT void Foreign::destroy() { delete impl(this); }
1187
1188WASM_EXPORT auto Foreign::copy() const -> own<Foreign> {
1189 return impl(this)->copy();
1190}
1191
1192WASM_EXPORT auto Foreign::make(Store* store_abs) -> own<Foreign> {
1193 StoreImpl* store = impl(store_abs);
1194 v8::Isolate::Scope isolate_scope(store->isolate());
1195 i::Isolate* isolate = store->i_isolate();
1196 i::HandleScope handle_scope(isolate);
1197
1199 isolate->factory()->NewJSObject(isolate->object_function());
1200 return implement<Foreign>::type::make(store, obj);
1201}
1202
1203// Modules
1204
1205template <>
1209
1210WASM_EXPORT void Module::destroy() { delete impl(this); }
1211
1212WASM_EXPORT auto Module::copy() const -> own<Module> {
1213 return impl(this)->copy();
1214}
1215
1216WASM_EXPORT auto Module::validate(Store* store_abs, const vec<byte_t>& binary)
1217 -> bool {
1218 i::Isolate* isolate = impl(store_abs)->i_isolate();
1219 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1220 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1221 i::HandleScope scope(isolate);
1223 reinterpret_cast<const uint8_t*>(binary.get()), binary.size());
1224 i::wasm::WasmEnabledFeatures features =
1225 i::wasm::WasmEnabledFeatures::FromIsolate(isolate);
1226 i::wasm::CompileTimeImports imports;
1227 return i::wasm::GetWasmEngine()->SyncValidate(isolate, features,
1228 std::move(imports), bytes);
1229}
1230
1231WASM_EXPORT auto Module::make(Store* store_abs, const vec<byte_t>& binary)
1232 -> own<Module> {
1233 StoreImpl* store = impl(store_abs);
1234 i::Isolate* isolate = store->i_isolate();
1235 v8::Isolate::Scope isolate_scope(store->isolate());
1236 i::HandleScope scope(isolate);
1237 CheckAndHandleInterrupts(isolate);
1239 reinterpret_cast<const uint8_t*>(binary.get()), binary.size());
1240 i::wasm::WasmEnabledFeatures features =
1241 i::wasm::WasmEnabledFeatures::FromIsolate(isolate);
1242 i::wasm::CompileTimeImports imports;
1243 i::wasm::ErrorThrower thrower(isolate, "ignored");
1245 if (!i::wasm::GetWasmEngine()
1246 ->SyncCompile(isolate, features, std::move(imports), &thrower,
1247 std::move(bytes))
1248 .ToHandle(&module)) {
1249 thrower.Reset(); // The API provides no way to expose the error.
1250 return nullptr;
1251 }
1252 return implement<Module>::type::make(store, module);
1253}
1254
1255WASM_EXPORT auto Module::imports() const -> ownvec<ImportType> {
1256 const i::wasm::NativeModule* native_module =
1257 impl(this)->v8_object()->native_module();
1258 const i::wasm::WasmModule* module = native_module->module();
1259 const v8::base::Vector<const uint8_t> wire_bytes =
1260 native_module->wire_bytes();
1261 const std::vector<i::wasm::WasmImport>& import_table = module->import_table;
1262 size_t size = import_table.size();
1263 ownvec<ImportType> imports = ownvec<ImportType>::make_uninitialized(size);
1264 for (uint32_t i = 0; i < size; i++) {
1265 const i::wasm::WasmImport& imp = import_table[i];
1266 Name module_name = GetNameFromWireBytes(imp.module_name, wire_bytes);
1267 Name name = GetNameFromWireBytes(imp.field_name, wire_bytes);
1268 own<ExternType> type = GetImportExportType(module, imp.kind, imp.index);
1269 imports[i] = ImportType::make(std::move(module_name), std::move(name),
1270 std::move(type));
1271 }
1272 return imports;
1273}
1274
1275ownvec<ExportType> ExportsImpl(
1277 const i::wasm::NativeModule* native_module = module_obj->native_module();
1278 const i::wasm::WasmModule* module = native_module->module();
1279 const v8::base::Vector<const uint8_t> wire_bytes =
1280 native_module->wire_bytes();
1281 const std::vector<i::wasm::WasmExport>& export_table = module->export_table;
1282 size_t size = export_table.size();
1283 ownvec<ExportType> exports = ownvec<ExportType>::make_uninitialized(size);
1284 for (uint32_t i = 0; i < size; i++) {
1285 const i::wasm::WasmExport& exp = export_table[i];
1286 Name name = GetNameFromWireBytes(exp.name, wire_bytes);
1287 own<ExternType> type = GetImportExportType(module, exp.kind, exp.index);
1288 exports[i] = ExportType::make(std::move(name), std::move(type));
1289 }
1290 return exports;
1291}
1292
1293WASM_EXPORT auto Module::exports() const -> ownvec<ExportType> {
1294 i::Isolate* isolate = impl(this)->isolate();
1295 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1296 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1297 return ExportsImpl(impl(this)->v8_object());
1298}
1299
1300// We tier up all functions to TurboFan, and then serialize all TurboFan code.
1301// If no TurboFan code existed before calling this function, then the call to
1302// {serialize} may take a long time.
1303WASM_EXPORT auto Module::serialize() const -> vec<byte_t> {
1304 i::Isolate* isolate = impl(this)->isolate();
1305 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1306 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1307 i::wasm::NativeModule* native_module =
1308 impl(this)->v8_object()->native_module();
1309 native_module->compilation_state()->TierUpAllFunctions();
1310 v8::base::Vector<const uint8_t> wire_bytes = native_module->wire_bytes();
1311 size_t binary_size = wire_bytes.size();
1312 i::wasm::WasmSerializer serializer(native_module);
1313 size_t serial_size = serializer.GetSerializedNativeModuleSize();
1314 size_t size_size = i::wasm::LEBHelper::sizeof_u64v(binary_size);
1315 vec<byte_t> buffer =
1316 vec<byte_t>::make_uninitialized(size_size + binary_size + serial_size);
1317 byte_t* ptr = buffer.get();
1318 i::wasm::LEBHelper::write_u64v(reinterpret_cast<uint8_t**>(&ptr),
1319 binary_size);
1320 std::memcpy(ptr, wire_bytes.begin(), binary_size);
1321 ptr += binary_size;
1322 if (!serializer.SerializeNativeModule(
1323 {reinterpret_cast<uint8_t*>(ptr), serial_size})) {
1324 // Serialization fails if no TurboFan code is present. This may happen
1325 // because the module does not have any functions, or because another thread
1326 // modifies the {NativeModule} concurrently. In this case, the serialized
1327 // module just contains the wire bytes.
1328 buffer = vec<byte_t>::make_uninitialized(size_size + binary_size);
1329 byte_t* pointer = buffer.get();
1330 i::wasm::LEBHelper::write_u64v(reinterpret_cast<uint8_t**>(&pointer),
1331 binary_size);
1332 std::memcpy(pointer, wire_bytes.begin(), binary_size);
1333 }
1334 return buffer;
1335}
1336
1337WASM_EXPORT auto Module::deserialize(Store* store_abs,
1338 const vec<byte_t>& serialized)
1339 -> own<Module> {
1340 StoreImpl* store = impl(store_abs);
1341 i::Isolate* isolate = store->i_isolate();
1342 v8::Isolate::Scope isolate_scope(store->isolate());
1343 i::HandleScope handle_scope(isolate);
1344 const byte_t* ptr = serialized.get();
1345 uint64_t binary_size = ReadLebU64(&ptr);
1346 ptrdiff_t size_size = ptr - serialized.get();
1347 size_t serial_size = serialized.size() - size_size - binary_size;
1349 if (serial_size > 0) {
1350 size_t data_size = static_cast<size_t>(binary_size);
1351 i::wasm::CompileTimeImports compile_imports{};
1352 if (!i::wasm::DeserializeNativeModule(
1353 isolate,
1354 {reinterpret_cast<const uint8_t*>(ptr + data_size), serial_size},
1355 {reinterpret_cast<const uint8_t*>(ptr), data_size},
1356 compile_imports, {})
1357 .ToHandle(&module_obj)) {
1358 // We were given a serialized module, but failed to deserialize. Report
1359 // this as an error.
1360 return nullptr;
1361 }
1362 } else {
1363 // No serialized module was given. This is fine, just create a module from
1364 // scratch.
1365 vec<byte_t> binary = vec<byte_t>::make_uninitialized(binary_size);
1366 std::memcpy(binary.get(), ptr, binary_size);
1367 return make(store_abs, binary);
1368 }
1369 return implement<Module>::type::make(store, module_obj);
1370}
1371
1372// TODO(v8): do better when V8 can do better.
1373template <>
1374struct implement<Shared<Module>> {
1375 using type = vec<byte_t>;
1376};
1377
1378WASM_EXPORT void Shared<Module>::destroy() { delete impl(this); }
1379
1380WASM_EXPORT auto Module::share() const -> own<Shared<Module>> {
1381 auto shared = seal<Shared<Module>>(new vec<byte_t>(serialize()));
1382 return make_own(shared);
1383}
1384
1385WASM_EXPORT auto Module::obtain(Store* store, const Shared<Module>* shared)
1386 -> own<Module> {
1387 return Module::deserialize(store, *impl(shared));
1388}
1389
1390// Externals
1391
1392template <>
1393struct implement<Extern> {
1395};
1396
1397WASM_EXPORT void Extern::destroy() { delete impl(this); }
1398
1399WASM_EXPORT auto Extern::copy() const -> own<Extern> {
1400 return impl(this)->copy();
1401}
1402
1403WASM_EXPORT auto Extern::kind() const -> ExternKind {
1404 i::Isolate* isolate = impl(this)->isolate();
1405 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1406 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1407
1408 i::DirectHandle<i::JSReceiver> obj = impl(this)->v8_object();
1409 if (i::WasmExternalFunction::IsWasmExternalFunction(*obj)) {
1410 return wasm::ExternKind::FUNC;
1411 }
1412 if (IsWasmGlobalObject(*obj)) return wasm::ExternKind::GLOBAL;
1413 if (IsWasmTableObject(*obj)) return wasm::ExternKind::TABLE;
1414 if (IsWasmMemoryObject(*obj)) return wasm::ExternKind::MEMORY;
1415 UNREACHABLE();
1416}
1417
1418WASM_EXPORT auto Extern::type() const -> own<ExternType> {
1419 switch (kind()) {
1420 case ExternKind::FUNC:
1421 return func()->type();
1422 case ExternKind::GLOBAL:
1423 return global()->type();
1424 case ExternKind::TABLE:
1425 return table()->type();
1426 case ExternKind::MEMORY:
1427 return memory()->type();
1428 }
1429}
1430
1431WASM_EXPORT auto Extern::func() -> Func* {
1432 return kind() == ExternKind::FUNC ? static_cast<Func*>(this) : nullptr;
1433}
1434
1435WASM_EXPORT auto Extern::global() -> Global* {
1436 return kind() == ExternKind::GLOBAL ? static_cast<Global*>(this) : nullptr;
1437}
1438
1439WASM_EXPORT auto Extern::table() -> Table* {
1440 return kind() == ExternKind::TABLE ? static_cast<Table*>(this) : nullptr;
1441}
1442
1443WASM_EXPORT auto Extern::memory() -> Memory* {
1444 return kind() == ExternKind::MEMORY ? static_cast<Memory*>(this) : nullptr;
1445}
1446
1447WASM_EXPORT auto Extern::func() const -> const Func* {
1448 return kind() == ExternKind::FUNC ? static_cast<const Func*>(this) : nullptr;
1449}
1450
1451WASM_EXPORT auto Extern::global() const -> const Global* {
1452 return kind() == ExternKind::GLOBAL ? static_cast<const Global*>(this)
1453 : nullptr;
1454}
1455
1456WASM_EXPORT auto Extern::table() const -> const Table* {
1457 return kind() == ExternKind::TABLE ? static_cast<const Table*>(this)
1458 : nullptr;
1459}
1460
1461WASM_EXPORT auto Extern::memory() const -> const Memory* {
1462 return kind() == ExternKind::MEMORY ? static_cast<const Memory*>(this)
1463 : nullptr;
1464}
1465
1467 return impl(ex)->v8_object();
1468}
1469
1470// Function Instances
1471
1472template <>
1473struct implement<Func> {
1475};
1476
1477WASM_EXPORT void Func::destroy() { delete impl(this); }
1478
1479WASM_EXPORT auto Func::copy() const -> own<Func> { return impl(this)->copy(); }
1480
1481struct FuncData {
1483
1484 Store* store;
1485 own<FuncType> type;
1487 union {
1488 Func::callback callback;
1489 Func::callback_with_env callback_with_env;
1490 };
1491 void (*finalizer)(void*);
1492 void* env;
1493
1494 FuncData(Store* store, const FuncType* type, Kind kind)
1495 : store(store),
1496 type(type->copy()),
1497 kind(kind),
1498 finalizer(nullptr),
1499 env(nullptr) {}
1500
1502 if (finalizer) (*finalizer)(env);
1503 }
1504
1505 static i::Address v8_callback(i::Address host_data_foreign, i::Address argv);
1506};
1507
1508namespace {
1509
1510class SignatureHelper : public i::AllStatic {
1511 public:
1512 static const i::wasm::CanonicalTypeIndex Canonicalize(FuncType* type) {
1513 std::vector<i::wasm::ValueType> types;
1514 types.reserve(type->results().size() + type->params().size());
1515
1516 // TODO(jkummerow): Consider making vec<> range-based for-iterable.
1517 for (size_t i = 0; i < type->results().size(); i++) {
1518 types.push_back(WasmValKindToV8(type->results()[i]->kind()));
1519 }
1520 for (size_t i = 0; i < type->params().size(); i++) {
1521 types.push_back(WasmValKindToV8(type->params()[i]->kind()));
1522 }
1523
1524 i::wasm::FunctionSig non_canonical_sig{type->results().size(),
1525 type->params().size(), types.data()};
1526 return i::wasm::GetTypeCanonicalizer()->AddRecursiveGroup(
1527 &non_canonical_sig);
1528 }
1529
1530 static own<FuncType> FromV8Sig(const i::wasm::CanonicalSig* sig) {
1531 int result_arity = static_cast<int>(sig->return_count());
1532 int param_arity = static_cast<int>(sig->parameter_count());
1533 ownvec<ValType> results = ownvec<ValType>::make_uninitialized(result_arity);
1534 ownvec<ValType> params = ownvec<ValType>::make_uninitialized(param_arity);
1535
1536 for (int i = 0; i < result_arity; ++i) {
1537 results[i] = ValType::make(V8ValueTypeToWasm(sig->GetReturn(i)));
1538 }
1539 for (int i = 0; i < param_arity; ++i) {
1540 params[i] = ValType::make(V8ValueTypeToWasm(sig->GetParam(i)));
1541 }
1542 return FuncType::make(std::move(params), std::move(results));
1543 }
1544
1545 static const i::wasm::CanonicalSig* GetSig(
1547 return i::Cast<i::WasmCapiFunction>(*function)->sig();
1548 }
1549
1550#if V8_ENABLE_SANDBOX
1551 // Wraps {FuncType} so it has the same interface as {v8::internal::Signature}.
1552 struct FuncTypeAdapter {
1553 const FuncType* type = nullptr;
1554 size_t parameter_count() const { return type->params().size(); }
1555 size_t return_count() const { return type->results().size(); }
1556 i::wasm::ValueType GetParam(size_t i) const {
1557 return WasmValKindToV8(type->params()[i]->kind());
1558 }
1559 i::wasm::ValueType GetReturn(size_t i) const {
1560 return WasmValKindToV8(type->results()[i]->kind());
1561 }
1562 };
1563 static uint64_t Hash(FuncType* type) {
1564 FuncTypeAdapter adapter{type};
1565 return i::wasm::SignatureHasher::Hash(&adapter);
1566 }
1567#endif
1568};
1569
1570auto make_func(Store* store_abs, std::shared_ptr<FuncData> data) -> own<Func> {
1571 auto store = impl(store_abs);
1572 i::Isolate* isolate = store->i_isolate();
1573 v8::Isolate::Scope isolate_scope(store->isolate());
1574 i::HandleScope handle_scope(isolate);
1575 CheckAndHandleInterrupts(isolate);
1577 i::Managed<FuncData>::From(isolate, sizeof(FuncData), data);
1578 i::wasm::CanonicalTypeIndex sig_index =
1579 SignatureHelper::Canonicalize(data->type.get());
1580 const i::wasm::CanonicalSig* sig =
1581 i::wasm::GetTypeCanonicalizer()->LookupFunctionSignature(sig_index);
1582 i::DirectHandle<i::WasmCapiFunction> function = i::WasmCapiFunction::New(
1583 isolate, reinterpret_cast<i::Address>(&FuncData::v8_callback),
1584 embedder_data, sig_index, sig);
1586 function->shared()->wasm_capi_function_data()->internal()->implicit_arg())
1587 ->set_callable(*function);
1588 auto func = implement<Func>::type::make(store, function);
1589 return func;
1590}
1591
1592} // namespace
1593
1594WASM_EXPORT auto Func::make(Store* store, const FuncType* type,
1595 Func::callback callback) -> own<Func> {
1596 auto data = std::make_shared<FuncData>(store, type, FuncData::kCallback);
1597 data->callback = callback;
1598 return make_func(store, data);
1599}
1600
1601WASM_EXPORT auto Func::make(Store* store, const FuncType* type,
1602 callback_with_env callback, void* env,
1603 void (*finalizer)(void*)) -> own<Func> {
1604 auto data =
1605 std::make_shared<FuncData>(store, type, FuncData::kCallbackWithEnv);
1606 data->callback_with_env = callback;
1607 data->env = env;
1608 data->finalizer = finalizer;
1609 return make_func(store, data);
1610}
1611
1612WASM_EXPORT auto Func::type() const -> own<FuncType> {
1613 i::Isolate* isolate = impl(this)->isolate();
1614 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1615 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1616 i::DirectHandle<i::JSFunction> func = impl(this)->v8_object();
1617 if (i::WasmCapiFunction::IsWasmCapiFunction(*func)) {
1618 return SignatureHelper::FromV8Sig(SignatureHelper::GetSig(func));
1619 }
1620 DCHECK(i::WasmExportedFunction::IsWasmExportedFunction(*func));
1621 auto function = i::Cast<i::WasmExportedFunction>(func);
1622 auto data = function->shared()->wasm_exported_function_data();
1623 return FunctionSigToFuncType(
1624 data->instance_data()->module()->functions[data->function_index()].sig);
1625}
1626
1627WASM_EXPORT auto Func::param_arity() const -> size_t {
1628 i::Isolate* isolate = impl(this)->isolate();
1629 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1630 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1631 i::DirectHandle<i::JSFunction> func = impl(this)->v8_object();
1632 if (i::WasmCapiFunction::IsWasmCapiFunction(*func)) {
1633 return SignatureHelper::GetSig(func)->parameter_count();
1634 }
1635 DCHECK(i::WasmExportedFunction::IsWasmExportedFunction(*func));
1636 auto function = i::Cast<i::WasmExportedFunction>(func);
1637 auto data = function->shared()->wasm_exported_function_data();
1638 const i::wasm::FunctionSig* sig =
1639 data->instance_data()->module()->functions[data->function_index()].sig;
1640 return sig->parameter_count();
1641}
1642
1643WASM_EXPORT auto Func::result_arity() const -> size_t {
1644 i::Isolate* isolate = impl(this)->isolate();
1645 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
1646 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
1647 i::DirectHandle<i::JSFunction> func = impl(this)->v8_object();
1648 if (i::WasmCapiFunction::IsWasmCapiFunction(*func)) {
1649 return SignatureHelper::GetSig(func)->return_count();
1650 }
1651 DCHECK(i::WasmExportedFunction::IsWasmExportedFunction(*func));
1652 auto function = i::Cast<i::WasmExportedFunction>(func);
1653 auto data = function->shared()->wasm_exported_function_data();
1654 const i::wasm::FunctionSig* sig =
1655 data->instance_data()->module()->functions[data->function_index()].sig;
1656 return sig->return_count();
1657}
1658
1659namespace {
1660
1661own<Ref> V8RefValueToWasm(StoreImpl* store, i::DirectHandle<i::Object> value) {
1662 if (IsNull(*value, store->i_isolate())) return nullptr;
1664}
1665
1666i::DirectHandle<i::Object> WasmRefToV8(i::Isolate* isolate, const Ref* ref) {
1667 if (ref == nullptr) return isolate->factory()->null_value();
1668 return impl(ref)->v8_object();
1669}
1670
1671void PrepareFunctionData(
1672 i::Isolate* isolate,
1674 const i::wasm::CanonicalSig* sig) {
1675 // If the data is already populated, return immediately.
1676 // TODO(saelo): We need to use full pointer comparison here while not all Code
1677 // objects have migrated into trusted space.
1679 if (!function_data->c_wrapper_code(isolate).SafeEquals(
1680 *BUILTIN_CODE(isolate, Illegal))) {
1681 return;
1682 }
1683 // Compile wrapper code.
1684 i::DirectHandle<i::Code> wrapper_code =
1685 i::compiler::CompileCWasmEntry(isolate, sig);
1686 function_data->set_c_wrapper_code(*wrapper_code);
1687 // Compute packed args size.
1688 function_data->set_packed_args_size(
1689 i::wasm::CWasmArgumentsPacker::TotalSize(sig));
1690}
1691
1692void PushArgs(const i::wasm::CanonicalSig* sig, const vec<Val>& args,
1693 i::wasm::CWasmArgumentsPacker* packer, StoreImpl* store) {
1694 for (size_t i = 0; i < sig->parameter_count(); i++) {
1695 i::wasm::CanonicalValueType type = sig->GetParam(i);
1696 switch (type.kind()) {
1697 case i::wasm::kI32:
1698 packer->Push(args[i].i32());
1699 break;
1700 case i::wasm::kI64:
1701 packer->Push(args[i].i64());
1702 break;
1703 case i::wasm::kF32:
1704 packer->Push(args[i].f32());
1705 break;
1706 case i::wasm::kF64:
1707 packer->Push(args[i].f64());
1708 break;
1709 case i::wasm::kRef:
1710 case i::wasm::kRefNull:
1711 // TODO(14034): Make sure this works for all heap types.
1712 packer->Push((*WasmRefToV8(store->i_isolate(), args[i].ref())).ptr());
1713 break;
1714 case i::wasm::kS128:
1715 // TODO(14034): Implement.
1716 UNIMPLEMENTED();
1717 case i::wasm::kI8:
1718 case i::wasm::kI16:
1719 case i::wasm::kF16:
1720 case i::wasm::kVoid:
1721 case i::wasm::kTop:
1722 case i::wasm::kBottom:
1723 UNREACHABLE();
1724 }
1725 }
1726}
1727
1728void PopArgs(const i::wasm::CanonicalSig* sig, vec<Val>& results,
1729 i::wasm::CWasmArgumentsPacker* packer, StoreImpl* store) {
1730 packer->Reset();
1731 for (size_t i = 0; i < sig->return_count(); i++) {
1732 i::wasm::CanonicalValueType type = sig->GetReturn(i);
1733 switch (type.kind()) {
1734 case i::wasm::kI32:
1735 results[i] = Val(packer->Pop<int32_t>());
1736 break;
1737 case i::wasm::kI64:
1738 results[i] = Val(packer->Pop<int64_t>());
1739 break;
1740 case i::wasm::kF32:
1741 results[i] = Val(packer->Pop<float>());
1742 break;
1743 case i::wasm::kF64:
1744 results[i] = Val(packer->Pop<double>());
1745 break;
1746 case i::wasm::kRef:
1747 case i::wasm::kRefNull: {
1748 // TODO(14034): Make sure this works for all heap types.
1749 i::Address raw = packer->Pop<i::Address>();
1751 store->i_isolate());
1752 results[i] = Val(V8RefValueToWasm(store, obj));
1753 break;
1754 }
1755 case i::wasm::kS128:
1756 // TODO(14034): Implement.
1757 UNIMPLEMENTED();
1758 case i::wasm::kI8:
1759 case i::wasm::kI16:
1760 case i::wasm::kF16:
1761 case i::wasm::kVoid:
1762 case i::wasm::kTop:
1763 case i::wasm::kBottom:
1764 UNREACHABLE();
1765 }
1766 }
1767}
1768
1769own<Trap> CallWasmCapiFunction(i::Tagged<i::WasmCapiFunctionData> data,
1770 const vec<Val>& args, vec<Val>& results) {
1771 FuncData* func_data =
1772 i::Cast<i::Managed<FuncData>>(data->embedder_data())->raw();
1773 if (func_data->kind == FuncData::kCallback) {
1774 return (func_data->callback)(args, results);
1775 }
1776 DCHECK(func_data->kind == FuncData::kCallbackWithEnv);
1777 return (func_data->callback_with_env)(func_data->env, args, results);
1778}
1779
1780i::DirectHandle<i::JSReceiver> GetProperException(
1781 i::Isolate* isolate, i::DirectHandle<i::Object> maybe_exception) {
1782 if (IsJSReceiver(*maybe_exception)) {
1783 return i::Cast<i::JSReceiver>(maybe_exception);
1784 }
1785 if (v8::internal::IsTerminationException(*maybe_exception)) {
1787 isolate->factory()->NewStringFromAsciiChecked("TerminationException");
1788 return isolate->factory()->NewError(isolate->error_function(), string);
1789 }
1790 i::MaybeDirectHandle<i::String> maybe_string =
1791 i::Object::ToString(isolate, maybe_exception);
1792 i::DirectHandle<i::String> string = isolate->factory()->empty_string();
1793 if (!maybe_string.ToHandle(&string)) {
1794 // If converting the {maybe_exception} to string threw another exception,
1795 // just give up and leave {string} as the empty string.
1796 isolate->clear_exception();
1797 }
1798 // {NewError} cannot fail when its input is a plain String, so we always
1799 // get an Error object here.
1801 isolate->factory()->NewError(isolate->error_function(), string));
1802}
1803
1804} // namespace
1805
1806WASM_EXPORT auto Func::call(const vec<Val>& args, vec<Val>& results) const
1807 -> own<Trap> {
1808 auto func = impl(this);
1809 auto store = func->store();
1810 auto isolate = store->i_isolate();
1811 v8::Isolate::Scope isolate_scope(store->isolate());
1812 i::HandleScope handle_scope(isolate);
1813 i::Tagged<i::Object> raw_function_data =
1814 func->v8_object()->shared()->GetTrustedData(isolate);
1815
1816 // WasmCapiFunctions can be called directly.
1817 if (IsWasmCapiFunctionData(raw_function_data)) {
1818 return CallWasmCapiFunction(
1819 i::Cast<i::WasmCapiFunctionData>(raw_function_data), args, results);
1820 }
1821
1822 SBXCHECK(IsWasmExportedFunctionData(raw_function_data));
1824 i::Cast<i::WasmExportedFunctionData>(raw_function_data), isolate};
1826 function_data->instance_data(), isolate};
1827 int function_index = function_data->function_index();
1828 const i::wasm::WasmModule* module = instance_data->module();
1829 // Caching {sig} would reduce overhead substantially.
1830 const i::wasm::CanonicalSig* sig =
1831 i::wasm::GetTypeCanonicalizer()->LookupFunctionSignature(
1832 module->canonical_sig_id(
1833 module->functions[function_index].sig_index));
1834 PrepareFunctionData(isolate, function_data, sig);
1835 i::DirectHandle<i::Code> wrapper_code(function_data->c_wrapper_code(isolate),
1836 isolate);
1837 i::WasmCodePointer call_target = function_data->internal()->call_target();
1838
1839 i::wasm::CWasmArgumentsPacker packer(function_data->packed_args_size());
1840 PushArgs(sig, args, &packer, store);
1841
1842 i::DirectHandle<i::Object> object_ref;
1843 if (function_index < static_cast<int>(module->num_imported_functions)) {
1844 object_ref = i::direct_handle(
1845 instance_data->dispatch_table_for_imports()->implicit_arg(
1846 function_index),
1847 isolate);
1848 if (IsWasmImportData(*object_ref)) {
1850 i::Cast<i::WasmImportData>(*object_ref)->callable());
1851 i::Tagged<i::Object> data = jsfunc->shared()->GetTrustedData(isolate);
1852 if (IsWasmCapiFunctionData(data)) {
1853 return CallWasmCapiFunction(i::Cast<i::WasmCapiFunctionData>(data),
1854 args, results);
1855 }
1856 // TODO(jkummerow): Imported and then re-exported JavaScript functions
1857 // are not supported yet. If we support C-API + JavaScript, we'll need
1858 // to call those here.
1859 UNIMPLEMENTED();
1860 } else {
1861 // A WasmFunction from another module.
1862 DCHECK(IsWasmInstanceObject(*object_ref));
1863 }
1864 } else {
1865 // TODO(42204563): Avoid crashing if the instance object is not available.
1866 CHECK(instance_data->has_instance_object());
1867 object_ref = direct_handle(instance_data->instance_object(), isolate);
1868 }
1869
1870 i::Execution::CallWasm(isolate, wrapper_code, call_target, object_ref,
1871 packer.argv());
1872
1873 if (isolate->has_exception()) {
1874 i::DirectHandle<i::Object> exception(isolate->exception(), isolate);
1875 isolate->clear_exception();
1876 return implement<Trap>::type::make(store,
1877 GetProperException(isolate, exception));
1878 }
1879
1880 PopArgs(sig, results, &packer, store);
1881 return nullptr;
1882}
1883
1885 i::Address argv) {
1886 FuncData* self =
1888 ->raw();
1889 StoreImpl* store = impl(self->store);
1890 i::Isolate* isolate = store->i_isolate();
1891 v8::Isolate::Scope isolate_scope(store->isolate());
1892 i::HandleScope scope(isolate);
1893
1894 isolate->set_context(*v8::Utils::OpenDirectHandle(*store->context()));
1895
1896 const ownvec<ValType>& param_types = self->type->params();
1897 const ownvec<ValType>& result_types = self->type->results();
1898
1899 int num_param_types = static_cast<int>(param_types.size());
1900 int num_result_types = static_cast<int>(result_types.size());
1901
1902 auto params = vec<Val>::make_uninitialized(num_param_types);
1903 auto results = vec<Val>::make_uninitialized(num_result_types);
1904 i::Address p = argv;
1905 for (int i = 0; i < num_param_types; ++i) {
1906 switch (param_types[i]->kind()) {
1907 case ValKind::I32:
1908 params[i] = Val(v8::base::ReadUnalignedValue<int32_t>(p));
1909 p += 4;
1910 break;
1911 case ValKind::I64:
1912 params[i] = Val(v8::base::ReadUnalignedValue<int64_t>(p));
1913 p += 8;
1914 break;
1915 case ValKind::F32:
1917 p += 4;
1918 break;
1919 case ValKind::F64:
1921 p += 8;
1922 break;
1923 case ValKind::EXTERNREF:
1924 case ValKind::FUNCREF: {
1926 p += sizeof(raw);
1928 params[i] = Val(V8RefValueToWasm(store, obj));
1929 break;
1930 }
1931 }
1932 }
1933
1934 own<Trap> trap;
1935 if (self->kind == kCallbackWithEnv) {
1936 trap = self->callback_with_env(self->env, params, results);
1937 } else {
1938 trap = self->callback(params, results);
1939 }
1940
1941 if (trap) {
1942 isolate->Throw(*impl(trap.get())->v8_object());
1943 i::Tagged<i::Object> ex = isolate->exception();
1944 isolate->clear_exception();
1945 return ex.ptr();
1946 }
1947
1948 p = argv;
1949 for (int i = 0; i < num_result_types; ++i) {
1950 switch (result_types[i]->kind()) {
1951 case ValKind::I32:
1952 v8::base::WriteUnalignedValue(p, results[i].i32());
1953 p += 4;
1954 break;
1955 case ValKind::I64:
1956 v8::base::WriteUnalignedValue(p, results[i].i64());
1957 p += 8;
1958 break;
1959 case ValKind::F32:
1960 v8::base::WriteUnalignedValue(p, results[i].f32());
1961 p += 4;
1962 break;
1963 case ValKind::F64:
1964 v8::base::WriteUnalignedValue(p, results[i].f64());
1965 p += 8;
1966 break;
1967 case ValKind::EXTERNREF:
1968 case ValKind::FUNCREF: {
1970 p, (*WasmRefToV8(isolate, results[i].ref())).ptr());
1971 p += sizeof(i::Address);
1972 break;
1973 }
1974 }
1975 }
1976 return i::kNullAddress;
1977}
1978
1979// Global Instances
1980
1981template <>
1985
1986WASM_EXPORT void Global::destroy() { delete (this); }
1987
1988WASM_EXPORT auto Global::copy() const -> own<Global> {
1989 return impl(this)->copy();
1990}
1991
1992WASM_EXPORT auto Global::make(Store* store_abs, const GlobalType* type,
1993 const Val& val) -> own<Global> {
1994 StoreImpl* store = impl(store_abs);
1995 v8::Isolate::Scope isolate_scope(store->isolate());
1996 i::Isolate* isolate = store->i_isolate();
1997 i::HandleScope handle_scope(isolate);
1998 CheckAndHandleInterrupts(isolate);
1999
2000 DCHECK_EQ(type->content()->kind(), val.kind());
2001
2002 i::wasm::ValueType i_type = WasmValKindToV8(type->content()->kind());
2003 bool is_mutable = (type->mutability() == Mutability::VAR);
2004 const int32_t offset = 0;
2006 i::WasmGlobalObject::New(
2009 i::MaybeDirectHandle<i::FixedArray>(), i_type, offset, is_mutable)
2010 .ToHandleChecked();
2011
2012 auto global = implement<Global>::type::make(store, obj);
2013 assert(global);
2014 global->set(val);
2015 return global;
2016}
2017
2018WASM_EXPORT auto Global::type() const -> own<GlobalType> {
2019 i::DirectHandle<i::WasmGlobalObject> v8_global = impl(this)->v8_object();
2020 ValKind kind = V8ValueTypeToWasm(v8_global->type());
2021 Mutability mutability =
2022 v8_global->is_mutable() ? Mutability::VAR : Mutability::CONST;
2023 return GlobalType::make(ValType::make(kind), mutability);
2024}
2025
2026WASM_EXPORT auto Global::get() const -> Val {
2027 i::Isolate* isolate = impl(this)->isolate();
2028 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2029 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
2030 i::DirectHandle<i::WasmGlobalObject> v8_global = impl(this)->v8_object();
2031 switch (v8_global->type().kind()) {
2032 case i::wasm::kI32:
2033 return Val(v8_global->GetI32());
2034 case i::wasm::kI64:
2035 return Val(v8_global->GetI64());
2036 case i::wasm::kF32:
2037 return Val(v8_global->GetF32());
2038 case i::wasm::kF64:
2039 return Val(v8_global->GetF64());
2040 case i::wasm::kRef:
2041 case i::wasm::kRefNull: {
2042 // TODO(14034): Handle types other than funcref and externref if needed.
2043 StoreImpl* store = impl(this)->store();
2044 i::HandleScope scope(store->i_isolate());
2045 i::DirectHandle<i::Object> result = v8_global->GetRef();
2046 if (IsWasmFuncRef(*result)) {
2047 result = i::WasmInternalFunction::GetOrCreateExternal(i::direct_handle(
2048 i::Cast<i::WasmFuncRef>(*result)->internal(store->i_isolate()),
2049 store->i_isolate()));
2050 }
2051 if (IsWasmNull(*result)) {
2052 result = v8_global->GetIsolate()->factory()->null_value();
2053 }
2054 return Val(V8RefValueToWasm(store, result));
2055 }
2056 case i::wasm::kS128:
2057 // TODO(14034): Implement these.
2058 UNIMPLEMENTED();
2059 case i::wasm::kI8:
2060 case i::wasm::kI16:
2061 case i::wasm::kF16:
2062 case i::wasm::kVoid:
2063 case i::wasm::kTop:
2064 case i::wasm::kBottom:
2065 UNREACHABLE();
2066 }
2067}
2068
2069WASM_EXPORT void Global::set(const Val& val) {
2070 v8::Isolate::Scope isolate_scope(impl(this)->store()->isolate());
2071 i::DirectHandle<i::WasmGlobalObject> v8_global = impl(this)->v8_object();
2072 switch (val.kind()) {
2073 case ValKind::I32:
2074 return v8_global->SetI32(val.i32());
2075 case ValKind::I64:
2076 return v8_global->SetI64(val.i64());
2077 case ValKind::F32:
2078 return v8_global->SetF32(val.f32());
2079 case ValKind::F64:
2080 return v8_global->SetF64(val.f64());
2081 case ValKind::EXTERNREF:
2082 return v8_global->SetRef(
2083 WasmRefToV8(impl(this)->store()->i_isolate(), val.ref()));
2084 case ValKind::FUNCREF: {
2085 i::Isolate* isolate = impl(this)->store()->i_isolate();
2086 auto external = WasmRefToV8(impl(this)->store()->i_isolate(), val.ref());
2087 const char* error_message;
2088 auto internal = i::wasm::JSToWasmObject(isolate, nullptr, external,
2089 v8_global->type(), &error_message)
2090 .ToHandleChecked();
2091 v8_global->SetRef(internal);
2092 return;
2093 }
2094 default:
2095 // TODO(wasm+): support new value types
2096 UNREACHABLE();
2097 }
2098}
2099
2100// Table Instances
2101
2102template <>
2106
2107WASM_EXPORT void Table::destroy() { delete impl(this); }
2108
2109WASM_EXPORT auto Table::copy() const -> own<Table> {
2110 return impl(this)->copy();
2111}
2112
2113WASM_EXPORT auto Table::make(Store* store_abs, const TableType* type,
2114 const Ref* ref) -> own<Table> {
2115 StoreImpl* store = impl(store_abs);
2116 i::Isolate* isolate = store->i_isolate();
2117 v8::Isolate::Scope isolate_scope(store->isolate());
2118 i::HandleScope scope(isolate);
2119 CheckAndHandleInterrupts(isolate);
2120
2121 // Get "element".
2122 i::wasm::ValueType i_type;
2123 i::wasm::CanonicalValueType canonical_type;
2124 switch (type->element()->kind()) {
2125 case ValKind::FUNCREF:
2126 i_type = i::wasm::kWasmFuncRef;
2127 canonical_type = i::wasm::kWasmFuncRef;
2128 break;
2129 case ValKind::EXTERNREF:
2130 // See Engine::make().
2131 i_type = i::wasm::kWasmExternRef;
2132 canonical_type = i::wasm::kWasmExternRef;
2133 break;
2134 default:
2135 UNREACHABLE();
2136 }
2137
2138 const Limits& limits = type->limits();
2139 uint32_t minimum = limits.min;
2140 if (minimum > i::wasm::max_table_init_entries()) return nullptr;
2141 uint32_t maximum = limits.max;
2142 bool has_maximum = false;
2143 if (maximum != Limits(0).max) {
2144 has_maximum = true;
2145 if (maximum < minimum) return nullptr;
2146 if (maximum > i::wasm::max_table_init_entries()) return nullptr;
2147 }
2148
2149 i::DirectHandle<i::WasmTableObject> table_obj = i::WasmTableObject::New(
2151 canonical_type, minimum, has_maximum, maximum,
2152 isolate->factory()->null_value(), i::wasm::AddressType::kI32);
2153
2154 if (ref) {
2155 i::DirectHandle<i::JSReceiver> init = impl(ref)->v8_object();
2156 for (uint32_t i = 0; i < minimum; i++) {
2157 table_obj->Set(isolate, table_obj, i, init);
2158 }
2159 }
2160 return implement<Table>::type::make(store, table_obj);
2161}
2162
2163WASM_EXPORT auto Table::type() const -> own<TableType> {
2164 i::DirectHandle<i::WasmTableObject> table = impl(this)->v8_object();
2165 uint32_t min = table->current_length();
2166 // Note: The C-API is not updated for memory64 yet; limits use uint32_t. Thus
2167 // truncate the actual declared maximum to kMaxUint32.
2168 uint32_t max = static_cast<uint32_t>(std::min<uint64_t>(
2169 i::kMaxUInt32, table->maximum_length_u64().value_or(i::kMaxUInt32)));
2170 ValKind kind;
2171 switch (table->unsafe_type().heap_representation()) {
2172 case i::wasm::HeapType::kFunc:
2173 kind = ValKind::FUNCREF;
2174 break;
2175 case i::wasm::HeapType::kExtern:
2176 kind = ValKind::EXTERNREF;
2177 break;
2178 default:
2179 UNREACHABLE();
2180 }
2181 return TableType::make(ValType::make(kind), Limits(min, max));
2182}
2183
2184// TODO(14034): Handle types other than funcref and externref if needed.
2185WASM_EXPORT auto Table::get(size_t index) const -> own<Ref> {
2186 i::Isolate* isolate = impl(this)->isolate();
2187 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2188 i::DirectHandle<i::WasmTableObject> table = impl(this)->v8_object();
2189 if (index >= static_cast<size_t>(table->current_length())) return own<Ref>();
2190 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
2191 i::HandleScope handle_scope(isolate);
2193 i::WasmTableObject::Get(isolate, table, static_cast<uint32_t>(index));
2194 if (IsWasmFuncRef(*result)) {
2195 result = i::WasmInternalFunction::GetOrCreateExternal(i::direct_handle(
2196 i::Cast<i::WasmFuncRef>(*result)->internal(isolate), isolate));
2197 }
2198 if (IsWasmNull(*result)) {
2199 result = isolate->factory()->null_value();
2200 }
2201 DCHECK(IsNull(*result, isolate) || IsJSReceiver(*result));
2202 return V8RefValueToWasm(impl(this)->store(), result);
2203}
2204
2205WASM_EXPORT auto Table::set(size_t index, const Ref* ref) -> bool {
2206 i::Isolate* isolate = impl(this)->isolate();
2207 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2208 i::DirectHandle<i::WasmTableObject> table = impl(this)->v8_object();
2209 if (index >= static_cast<size_t>(table->current_length())) return false;
2210 i::HandleScope handle_scope(isolate);
2211 i::DirectHandle<i::Object> obj = WasmRefToV8(isolate, ref);
2212 const char* error_message;
2213 // We can use `table->unsafe_type()` and `module == nullptr` here as long
2214 // as the C-API doesn't support indexed types.
2215 DCHECK(!table->unsafe_type().has_index());
2216 i::DirectHandle<i::Object> obj_as_wasm =
2217 i::wasm::JSToWasmObject(isolate, nullptr, obj, table->unsafe_type(),
2218 &error_message)
2219 .ToHandleChecked();
2220 i::WasmTableObject::Set(isolate, table, static_cast<uint32_t>(index),
2221 obj_as_wasm);
2222 return true;
2223}
2224
2225// TODO(jkummerow): Having Table::size_t shadowing "std" size_t is ugly.
2226WASM_EXPORT auto Table::size() const -> size_t {
2227 i::Isolate* isolate = impl(this)->isolate();
2228 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2229 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
2230 return impl(this)->v8_object()->current_length();
2231}
2232
2233WASM_EXPORT auto Table::grow(size_t delta, const Ref* ref) -> bool {
2234 i::Isolate* isolate = impl(this)->isolate();
2235 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2236 i::DirectHandle<i::WasmTableObject> table = impl(this)->v8_object();
2237 i::HandleScope scope(isolate);
2238 i::DirectHandle<i::Object> obj = WasmRefToV8(isolate, ref);
2239 const char* error_message;
2240 // We can use `table->unsafe_type()` and `module == nullptr` here as long
2241 // as the C-API doesn't support indexed types.
2242 DCHECK(!table->unsafe_type().has_index());
2243 i::DirectHandle<i::Object> obj_as_wasm =
2244 i::wasm::JSToWasmObject(isolate, nullptr, obj, table->unsafe_type(),
2245 &error_message)
2246 .ToHandleChecked();
2247 int result = i::WasmTableObject::Grow(
2248 isolate, table, static_cast<uint32_t>(delta), obj_as_wasm);
2249 return result >= 0;
2250}
2251
2252// Memory Instances
2253
2254template <>
2258
2259WASM_EXPORT void Memory::destroy() { delete impl(this); }
2260
2261WASM_EXPORT auto Memory::copy() const -> own<Memory> {
2262 return impl(this)->copy();
2263}
2264
2265WASM_EXPORT auto Memory::make(Store* store_abs, const MemoryType* type)
2266 -> own<Memory> {
2267 StoreImpl* store = impl(store_abs);
2268 i::Isolate* isolate = store->i_isolate();
2269 v8::Isolate::Scope isolate_scope(store->isolate());
2270 i::HandleScope scope(isolate);
2271 CheckAndHandleInterrupts(isolate);
2272
2273 const Limits& limits = type->limits();
2274 uint32_t minimum = limits.min;
2275 // The max_mem_pages limit is only spec'ed for JS embeddings, so we'll
2276 // directly use the maximum pages limit here.
2277 if (minimum > i::wasm::kSpecMaxMemory32Pages) return nullptr;
2278 uint32_t maximum = limits.max;
2279 if (maximum != Limits(0).max) {
2280 if (maximum < minimum) return nullptr;
2281 if (maximum > i::wasm::kSpecMaxMemory32Pages) return nullptr;
2282 }
2283 // TODO(wasm+): Support shared memory and memory64.
2284 i::SharedFlag shared = i::SharedFlag::kNotShared;
2285 i::wasm::AddressType address_type = i::wasm::AddressType::kI32;
2287 if (!i::WasmMemoryObject::New(isolate, minimum, maximum, shared, address_type)
2288 .ToHandle(&memory_obj)) {
2289 return own<Memory>();
2290 }
2291 return implement<Memory>::type::make(store, memory_obj);
2292}
2293
2294WASM_EXPORT auto Memory::type() const -> own<MemoryType> {
2295 PtrComprCageAccessScope ptr_compr_cage_access_scope(impl(this)->isolate());
2296 i::DirectHandle<i::WasmMemoryObject> memory = impl(this)->v8_object();
2297 uint32_t min = static_cast<uint32_t>(memory->array_buffer()->byte_length() /
2298 i::wasm::kWasmPageSize);
2299 uint32_t max =
2300 memory->has_maximum_pages() ? memory->maximum_pages() : 0xFFFFFFFFu;
2301 return MemoryType::make(Limits(min, max));
2302}
2303
2304WASM_EXPORT auto Memory::data() const -> byte_t* {
2305 i::Isolate* isolate = impl(this)->isolate();
2306 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2307 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
2308 return reinterpret_cast<byte_t*>(
2309 impl(this)->v8_object()->array_buffer()->backing_store());
2310}
2311
2312WASM_EXPORT auto Memory::data_size() const -> size_t {
2313 i::Isolate* isolate = impl(this)->isolate();
2314 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2315 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
2316 return impl(this)->v8_object()->array_buffer()->byte_length();
2317}
2318
2319WASM_EXPORT auto Memory::size() const -> pages_t {
2320 i::Isolate* isolate = impl(this)->isolate();
2321 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2322 PtrComprCageAccessScope ptr_compr_cage_access_scope(isolate);
2323 return static_cast<pages_t>(
2324 impl(this)->v8_object()->array_buffer()->byte_length() /
2325 i::wasm::kWasmPageSize);
2326}
2327
2328WASM_EXPORT auto Memory::grow(pages_t delta) -> bool {
2329 i::Isolate* isolate = impl(this)->isolate();
2330 v8::Isolate::Scope isolate_scope(reinterpret_cast<v8::Isolate*>(isolate));
2331 i::HandleScope handle_scope(isolate);
2332 i::DirectHandle<i::WasmMemoryObject> memory = impl(this)->v8_object();
2333 int32_t old = i::WasmMemoryObject::Grow(isolate, memory, delta);
2334 return old != -1;
2335}
2336
2337// Module Instances
2338
2339template <>
2343
2344WASM_EXPORT void Instance::destroy() { delete impl(this); }
2345WASM_EXPORT auto Instance::copy() const -> own<Instance> {
2346 return impl(this)->copy();
2347}
2348
2349WASM_EXPORT own<Instance> Instance::make(Store* store_abs,
2350 const Module* module_abs,
2351 const vec<Extern*>& imports,
2352 own<Trap>* trap) {
2353 StoreImpl* store = impl(store_abs);
2354 const implement<Module>::type* module = impl(module_abs);
2355 i::Isolate* isolate = store->i_isolate();
2356 v8::Isolate::Scope isolate_scope(store->isolate());
2357 i::HandleScope handle_scope(isolate);
2358 CheckAndHandleInterrupts(isolate);
2359
2360 DCHECK_EQ(module->v8_object()->GetIsolate(), isolate);
2361
2362 if (trap) *trap = nullptr;
2363 ownvec<ImportType> import_types = module_abs->imports();
2364 i::DirectHandle<i::JSObject> imports_obj =
2365 isolate->factory()->NewJSObject(isolate->object_function());
2366 for (size_t i = 0; i < import_types.size(); ++i) {
2367 ImportType* type = import_types[i].get();
2368 i::DirectHandle<i::String> module_str =
2369 VecToString(isolate, type->module());
2370 i::DirectHandle<i::String> name_str = VecToString(isolate, type->name());
2371
2373 i::LookupIterator module_it(isolate, imports_obj, module_str,
2374 i::LookupIterator::OWN_SKIP_INTERCEPTOR);
2375 if (i::JSObject::HasProperty(&module_it).ToChecked()) {
2376 module_obj = i::Cast<i::JSObject>(
2377 i::Object::GetProperty(&module_it).ToHandleChecked());
2378 } else {
2379 module_obj = isolate->factory()->NewJSObject(isolate->object_function());
2380 ignore(
2381 i::Object::SetProperty(isolate, imports_obj, module_str, module_obj));
2382 }
2383 ignore(i::Object::SetProperty(isolate, module_obj, name_str,
2384 impl(imports[i])->v8_object()));
2385 }
2386 i::wasm::ErrorThrower thrower(isolate, "instantiation");
2388 i::wasm::GetWasmEngine()->SyncInstantiate(
2389 isolate, &thrower, module->v8_object(), imports_obj,
2391 if (trap) {
2392 if (thrower.error()) {
2394 store, GetProperException(isolate, thrower.Reify()));
2395 DCHECK(!thrower.error()); // Reify() called Reset().
2396 DCHECK(!isolate->has_exception()); // Hasn't been thrown yet.
2397 return own<Instance>();
2398 } else if (isolate->has_exception()) {
2399 i::DirectHandle<i::Object> maybe_exception(isolate->exception(), isolate);
2401 store, GetProperException(isolate, maybe_exception));
2402 isolate->clear_exception();
2403 return own<Instance>();
2404 }
2405 } else if (instance_obj.is_null()) {
2406 // If no {trap} output is specified, silently swallow all errors.
2407 thrower.Reset();
2408 isolate->clear_exception();
2409 return own<Instance>();
2410 }
2411 return implement<Instance>::type::make(store, instance_obj.ToHandleChecked());
2412}
2413
2414namespace {
2415
2416own<Instance> GetInstance(StoreImpl* store,
2418 return implement<Instance>::type::make(store, instance);
2419}
2420
2421} // namespace
2422
2423WASM_EXPORT auto Instance::exports() const -> ownvec<Extern> {
2424 const implement<Instance>::type* instance = impl(this);
2425 StoreImpl* store = instance->store();
2426 i::Isolate* isolate = store->i_isolate();
2427 v8::Isolate::Scope isolate_scope(store->isolate());
2428 i::HandleScope handle_scope(isolate);
2429 CheckAndHandleInterrupts(isolate);
2430 i::DirectHandle<i::WasmInstanceObject> instance_obj = instance->v8_object();
2431 i::DirectHandle<i::WasmModuleObject> module_obj(instance_obj->module_object(),
2432 isolate);
2433 i::DirectHandle<i::JSObject> exports_obj(instance_obj->exports_object(),
2434 isolate);
2435
2436 ownvec<ExportType> export_types = ExportsImpl(module_obj);
2437 ownvec<Extern> exports =
2438 ownvec<Extern>::make_uninitialized(export_types.size());
2439 if (!exports) return ownvec<Extern>::invalid();
2440
2441 for (size_t i = 0; i < export_types.size(); ++i) {
2442 auto& name = export_types[i]->name();
2443 i::DirectHandle<i::String> name_str = VecToString(isolate, name);
2445 i::Object::GetProperty(isolate, exports_obj, name_str)
2446 .ToHandleChecked();
2447
2448 const ExternType* type = export_types[i]->type();
2449 switch (type->kind()) {
2450 case ExternKind::FUNC: {
2451 DCHECK(i::WasmExternalFunction::IsWasmExternalFunction(*obj));
2452 exports[i] = implement<Func>::type::make(
2454 } break;
2455 case ExternKind::GLOBAL: {
2457 store, i::Cast<i::WasmGlobalObject>(obj));
2458 } break;
2459 case ExternKind::TABLE: {
2461 store, i::Cast<i::WasmTableObject>(obj));
2462 } break;
2463 case ExternKind::MEMORY: {
2465 store, i::Cast<i::WasmMemoryObject>(obj));
2466 } break;
2467 }
2468 }
2469
2470 return exports;
2471}
2472
2474
2475} // namespace wasm
2476
2477// BEGIN FILE wasm-c.cc
2478
2479extern "C" {
2480
2482// Auxiliaries
2483
2484// Backing implementation
2485
2486extern "C++" {
2487
2488template <class T>
2490 wasm::vec<T> it;
2491 explicit borrowed_vec(wasm::vec<T>&& v) : it(std::move(v)) {}
2492 borrowed_vec(borrowed_vec<T>&& that) : it(std::move(that.it)) {}
2493 ~borrowed_vec() { it.release(); }
2494};
2495
2496} // extern "C++"
2497
2498#define WASM_DEFINE_OWN(name, Name) \
2499 struct wasm_##name##_t : Name {}; \
2500 \
2501 void wasm_##name##_delete(wasm_##name##_t* x) { delete x; } \
2502 \
2503 extern "C++" inline auto hide_##name(Name* x)->wasm_##name##_t* { \
2504 return static_cast<wasm_##name##_t*>(x); \
2505 } \
2506 extern "C++" inline auto hide_##name(const Name* x) \
2507 ->const wasm_##name##_t* { \
2508 return static_cast<const wasm_##name##_t*>(x); \
2509 } \
2510 extern "C++" inline auto reveal_##name(wasm_##name##_t* x)->Name* { \
2511 return x; \
2512 } \
2513 extern "C++" inline auto reveal_##name(const wasm_##name##_t* x) \
2514 ->const Name* { \
2515 return x; \
2516 } \
2517 extern "C++" inline auto get_##name(wasm::own<Name>& x)->wasm_##name##_t* { \
2518 return hide_##name(x.get()); \
2519 } \
2520 extern "C++" inline auto get_##name(const wasm::own<Name>& x) \
2521 ->const wasm_##name##_t* { \
2522 return hide_##name(x.get()); \
2523 } \
2524 extern "C++" inline auto release_##name(wasm::own<Name>&& x) \
2525 ->wasm_##name##_t* { \
2526 return hide_##name(x.release()); \
2527 } \
2528 extern "C++" inline auto adopt_##name(wasm_##name##_t* x)->wasm::own<Name> { \
2529 return make_own(x); \
2530 }
2531
2532// Vectors
2533
2534#ifdef V8_GC_MOLE
2535#define ASSERT_VEC_BASE_SIZE(name, Name, vec, ptr_or_none)
2536
2537#else
2538#define ASSERT_VEC_BASE_SIZE(name, Name, vec, ptr_or_none) \
2539 static_assert(sizeof(wasm_##name##_vec_t) == sizeof(vec<Name>), \
2540 "C/C++ incompatibility"); \
2541 static_assert( \
2542 sizeof(wasm_##name##_t ptr_or_none) == sizeof(vec<Name>::elem_type), \
2543 "C/C++ incompatibility");
2544#endif
2545
2546#define WASM_DEFINE_VEC_BASE(name, Name, vec, ptr_or_none) \
2547 ASSERT_VEC_BASE_SIZE(name, Name, vec, ptr_or_none) \
2548 extern "C++" inline auto hide_##name##_vec(vec<Name>& v) \
2549 ->wasm_##name##_vec_t* { \
2550 return reinterpret_cast<wasm_##name##_vec_t*>(&v); \
2551 } \
2552 extern "C++" inline auto hide_##name##_vec(const vec<Name>& v) \
2553 ->const wasm_##name##_vec_t* { \
2554 return reinterpret_cast<const wasm_##name##_vec_t*>(&v); \
2555 } \
2556 extern "C++" inline auto hide_##name##_vec(vec<Name>::elem_type* v) \
2557 ->wasm_##name##_t ptr_or_none* { \
2558 return reinterpret_cast<wasm_##name##_t ptr_or_none*>(v); \
2559 } \
2560 extern "C++" inline auto hide_##name##_vec(const vec<Name>::elem_type* v) \
2561 ->wasm_##name##_t ptr_or_none const* { \
2562 return reinterpret_cast<wasm_##name##_t ptr_or_none const*>(v); \
2563 } \
2564 extern "C++" inline auto reveal_##name##_vec(wasm_##name##_t ptr_or_none* v) \
2565 ->vec<Name>::elem_type* { \
2566 return reinterpret_cast<vec<Name>::elem_type*>(v); \
2567 } \
2568 extern "C++" inline auto reveal_##name##_vec( \
2569 wasm_##name##_t ptr_or_none const* v) \
2570 ->const vec<Name>::elem_type* { \
2571 return reinterpret_cast<const vec<Name>::elem_type*>(v); \
2572 } \
2573 extern "C++" inline auto get_##name##_vec(vec<Name>& v) \
2574 ->wasm_##name##_vec_t { \
2575 wasm_##name##_vec_t v2 = {v.size(), hide_##name##_vec(v.get())}; \
2576 return v2; \
2577 } \
2578 extern "C++" inline auto get_##name##_vec(const vec<Name>& v) \
2579 ->const wasm_##name##_vec_t { \
2580 wasm_##name##_vec_t v2 = { \
2581 v.size(), \
2582 const_cast<wasm_##name##_t ptr_or_none*>(hide_##name##_vec(v.get()))}; \
2583 return v2; \
2584 } \
2585 extern "C++" inline auto release_##name##_vec(vec<Name>&& v) \
2586 ->wasm_##name##_vec_t { \
2587 wasm_##name##_vec_t v2 = {v.size(), hide_##name##_vec(v.release())}; \
2588 return v2; \
2589 } \
2590 extern "C++" inline auto adopt_##name##_vec(wasm_##name##_vec_t* v) \
2591 ->vec<Name> { \
2592 return vec<Name>::adopt(v->size, reveal_##name##_vec(v->data)); \
2593 } \
2594 extern "C++" inline auto adopt_##name##_vec(const wasm_##name##_vec_t* v) \
2595 ->const vec<Name> { \
2596 return vec<Name>::adopt(v->size, reveal_##name##_vec(v->data)); \
2597 } \
2598 extern "C++" inline auto borrow_##name##_vec(const wasm_##name##_vec_t* v) \
2599 ->borrowed_vec<vec<Name>::elem_type> { \
2600 return borrowed_vec<vec<Name>::elem_type>( \
2601 vec<Name>::adopt(v->size, reveal_##name##_vec(v->data))); \
2602 } \
2603 \
2604 void wasm_##name##_vec_new_uninitialized(wasm_##name##_vec_t* out, \
2605 size_t size) { \
2606 *out = release_##name##_vec(vec<Name>::make_uninitialized(size)); \
2607 } \
2608 void wasm_##name##_vec_new_empty(wasm_##name##_vec_t* out) { \
2609 wasm_##name##_vec_new_uninitialized(out, 0); \
2610 } \
2611 \
2612 void wasm_##name##_vec_delete(wasm_##name##_vec_t* v) { \
2613 adopt_##name##_vec(v); \
2614 }
2615
2616// Vectors with no ownership management of elements
2617#define WASM_DEFINE_VEC_PLAIN(name, Name) \
2618 WASM_DEFINE_VEC_BASE(name, Name, \
2619 wasm::vec, ) /* NOLINT(whitespace/parens) */ \
2620 \
2621 void wasm_##name##_vec_new(wasm_##name##_vec_t* out, size_t size, \
2622 const wasm_##name##_t data[]) { \
2623 auto v2 = wasm::vec<Name>::make_uninitialized(size); \
2624 if (v2.size() != 0) { \
2625 memcpy(v2.get(), data, size * sizeof(wasm_##name##_t)); \
2626 } \
2627 *out = release_##name##_vec(std::move(v2)); \
2628 } \
2629 \
2630 WASM_API_EXTERN void wasm_##name##_vec_copy(wasm_##name##_vec_t* out, \
2631 const wasm_##name##_vec_t* v) { \
2632 wasm_##name##_vec_new(out, v->size, v->data); \
2633 }
2634
2635// Vectors that own their elements
2636#define WASM_DEFINE_VEC_OWN(name, Name) \
2637 WASM_DEFINE_VEC_BASE(name, Name, wasm::ownvec, *) \
2638 \
2639 void wasm_##name##_vec_new(wasm_##name##_vec_t* out, size_t size, \
2640 wasm_##name##_t* const data[]) { \
2641 auto v2 = wasm::ownvec<Name>::make_uninitialized(size); \
2642 for (size_t i = 0; i < v2.size(); ++i) { \
2643 v2[i] = adopt_##name(data[i]); \
2644 } \
2645 *out = release_##name##_vec(std::move(v2)); \
2646 } \
2647 \
2648 WASM_API_EXTERN void wasm_##name##_vec_copy(wasm_##name##_vec_t* out, \
2649 const wasm_##name##_vec_t* v) { \
2650 auto v2 = wasm::ownvec<Name>::make_uninitialized(v->size); \
2651 for (size_t i = 0; i < v2.size(); ++i) { \
2652 v2[i] = adopt_##name(wasm_##name##_copy(v->data[i])); \
2653 } \
2654 *out = release_##name##_vec(std::move(v2)); \
2655 }
2656
2657extern "C++" {
2658template <class T>
2659inline auto is_empty(T* p) -> bool {
2660 return !p;
2661}
2662}
2663
2664// Byte vectors
2665
2666WASM_DEFINE_VEC_PLAIN(byte, byte_t)
2667
2668
2669// Runtime Environment
2670
2671// Configuration
2672
2673WASM_DEFINE_OWN(config, wasm::Config)
2674
2675wasm_config_t* wasm_config_new() {
2676 return release_config(wasm::Config::make());
2677}
2678
2679// Engine
2680
2681WASM_DEFINE_OWN(engine, wasm::Engine)
2682
2683wasm_engine_t* wasm_engine_new() {
2684 return release_engine(wasm::Engine::make());
2685}
2686
2687wasm_engine_t* wasm_engine_new_with_config(wasm_config_t* config) {
2688 return release_engine(wasm::Engine::make(adopt_config(config)));
2689}
2690
2691// Stores
2692
2693WASM_DEFINE_OWN(store, wasm::Store)
2694
2695wasm_store_t* wasm_store_new(wasm_engine_t* engine) {
2696 return release_store(wasm::Store::make(engine));
2697}
2698
2700// Type Representations
2701
2702// Type attributes
2703
2704extern "C++" inline auto hide_mutability(wasm::Mutability mutability)
2705 -> wasm_mutability_t {
2706 return static_cast<wasm_mutability_t>(mutability);
2707}
2708
2709extern "C++" inline auto reveal_mutability(wasm_mutability_t mutability)
2710 -> wasm::Mutability {
2711 return static_cast<wasm::Mutability>(mutability);
2712}
2713
2714extern "C++" inline auto hide_limits(const wasm::Limits& limits)
2715 -> const wasm_limits_t* {
2716 return reinterpret_cast<const wasm_limits_t*>(&limits);
2717}
2718
2719extern "C++" inline auto reveal_limits(wasm_limits_t limits) -> wasm::Limits {
2720 return wasm::Limits(limits.min, limits.max);
2721}
2722
2723extern "C++" inline auto hide_valkind(wasm::ValKind kind) -> wasm_valkind_t {
2724 return static_cast<wasm_valkind_t>(kind);
2725}
2726
2727extern "C++" inline auto reveal_valkind(wasm_valkind_t kind) -> wasm::ValKind {
2728 return static_cast<wasm::ValKind>(kind);
2729}
2730
2731extern "C++" inline auto hide_externkind(wasm::ExternKind kind)
2732 -> wasm_externkind_t {
2733 return static_cast<wasm_externkind_t>(kind);
2734}
2735
2736extern "C++" inline auto reveal_externkind(wasm_externkind_t kind)
2737 -> wasm::ExternKind {
2738 return static_cast<wasm::ExternKind>(kind);
2739}
2740
2741// Generic
2742
2743#define WASM_DEFINE_TYPE(name, Name) \
2744 WASM_DEFINE_OWN(name, Name) \
2745 WASM_DEFINE_VEC_OWN(name, Name) \
2746 \
2747 WASM_API_EXTERN wasm_##name##_t* wasm_##name##_copy( \
2748 const wasm_##name##_t* t) { \
2749 return release_##name(t->copy()); \
2750 }
2751
2752// Value Types
2753
2754WASM_DEFINE_TYPE(valtype, wasm::ValType)
2755
2756wasm_valtype_t* wasm_valtype_new(wasm_valkind_t k) {
2757 return release_valtype(wasm::ValType::make(reveal_valkind(k)));
2758}
2759
2760wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t* t) {
2761 return hide_valkind(t->kind());
2762}
2763
2764// Function Types
2765
2766WASM_DEFINE_TYPE(functype, wasm::FuncType)
2767
2768wasm_functype_t* wasm_functype_new(wasm_valtype_vec_t* params,
2769 wasm_valtype_vec_t* results) {
2770 return release_functype(wasm::FuncType::make(adopt_valtype_vec(params),
2771 adopt_valtype_vec(results)));
2772}
2773
2774const wasm_valtype_vec_t* wasm_functype_params(const wasm_functype_t* ft) {
2775 return hide_valtype_vec(ft->params());
2776}
2777
2778const wasm_valtype_vec_t* wasm_functype_results(const wasm_functype_t* ft) {
2779 return hide_valtype_vec(ft->results());
2780}
2781
2782// Global Types
2783
2784WASM_DEFINE_TYPE(globaltype, wasm::GlobalType)
2785
2786wasm_globaltype_t* wasm_globaltype_new(wasm_valtype_t* content,
2787 wasm_mutability_t mutability) {
2788 return release_globaltype(wasm::GlobalType::make(
2789 adopt_valtype(content), reveal_mutability(mutability)));
2790}
2791
2792const wasm_valtype_t* wasm_globaltype_content(const wasm_globaltype_t* gt) {
2793 return hide_valtype(gt->content());
2794}
2795
2796wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t* gt) {
2797 return hide_mutability(gt->mutability());
2798}
2799
2800// Table Types
2801
2802WASM_DEFINE_TYPE(tabletype, wasm::TableType)
2803
2804wasm_tabletype_t* wasm_tabletype_new(wasm_valtype_t* element,
2805 const wasm_limits_t* limits) {
2806 return release_tabletype(
2807 wasm::TableType::make(adopt_valtype(element), reveal_limits(*limits)));
2808}
2809
2810const wasm_valtype_t* wasm_tabletype_element(const wasm_tabletype_t* tt) {
2811 return hide_valtype(tt->element());
2812}
2813
2814const wasm_limits_t* wasm_tabletype_limits(const wasm_tabletype_t* tt) {
2815 return hide_limits(tt->limits());
2816}
2817
2818// Memory Types
2819
2820WASM_DEFINE_TYPE(memorytype, wasm::MemoryType)
2821
2822wasm_memorytype_t* wasm_memorytype_new(const wasm_limits_t* limits) {
2823 return release_memorytype(wasm::MemoryType::make(reveal_limits(*limits)));
2824}
2825
2826const wasm_limits_t* wasm_memorytype_limits(const wasm_memorytype_t* mt) {
2827 return hide_limits(mt->limits());
2828}
2829
2830// Extern Types
2831
2832WASM_DEFINE_TYPE(externtype, wasm::ExternType)
2833
2834wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t* et) {
2835 return hide_externkind(et->kind());
2836}
2837
2838wasm_externtype_t* wasm_functype_as_externtype(wasm_functype_t* ft) {
2839 return hide_externtype(static_cast<wasm::ExternType*>(ft));
2840}
2841wasm_externtype_t* wasm_globaltype_as_externtype(wasm_globaltype_t* gt) {
2842 return hide_externtype(static_cast<wasm::ExternType*>(gt));
2843}
2844wasm_externtype_t* wasm_tabletype_as_externtype(wasm_tabletype_t* tt) {
2845 return hide_externtype(static_cast<wasm::ExternType*>(tt));
2846}
2847wasm_externtype_t* wasm_memorytype_as_externtype(wasm_memorytype_t* mt) {
2848 return hide_externtype(static_cast<wasm::ExternType*>(mt));
2849}
2850
2851const wasm_externtype_t* wasm_functype_as_externtype_const(
2852 const wasm_functype_t* ft) {
2853 return hide_externtype(static_cast<const wasm::ExternType*>(ft));
2854}
2856 const wasm_globaltype_t* gt) {
2857 return hide_externtype(static_cast<const wasm::ExternType*>(gt));
2858}
2859const wasm_externtype_t* wasm_tabletype_as_externtype_const(
2860 const wasm_tabletype_t* tt) {
2861 return hide_externtype(static_cast<const wasm::ExternType*>(tt));
2862}
2864 const wasm_memorytype_t* mt) {
2865 return hide_externtype(static_cast<const wasm::ExternType*>(mt));
2866}
2867
2868wasm_functype_t* wasm_externtype_as_functype(wasm_externtype_t* et) {
2869 return et->kind() == wasm::ExternKind::FUNC
2870 ? hide_functype(
2871 static_cast<wasm::FuncType*>(reveal_externtype(et)))
2872 : nullptr;
2873}
2874wasm_globaltype_t* wasm_externtype_as_globaltype(wasm_externtype_t* et) {
2875 return et->kind() == wasm::ExternKind::GLOBAL
2876 ? hide_globaltype(
2877 static_cast<wasm::GlobalType*>(reveal_externtype(et)))
2878 : nullptr;
2879}
2880wasm_tabletype_t* wasm_externtype_as_tabletype(wasm_externtype_t* et) {
2881 return et->kind() == wasm::ExternKind::TABLE
2882 ? hide_tabletype(
2883 static_cast<wasm::TableType*>(reveal_externtype(et)))
2884 : nullptr;
2885}
2886wasm_memorytype_t* wasm_externtype_as_memorytype(wasm_externtype_t* et) {
2887 return et->kind() == wasm::ExternKind::MEMORY
2888 ? hide_memorytype(
2889 static_cast<wasm::MemoryType*>(reveal_externtype(et)))
2890 : nullptr;
2891}
2892
2894 const wasm_externtype_t* et) {
2895 return et->kind() == wasm::ExternKind::FUNC
2896 ? hide_functype(
2897 static_cast<const wasm::FuncType*>(reveal_externtype(et)))
2898 : nullptr;
2899}
2901 const wasm_externtype_t* et) {
2902 return et->kind() == wasm::ExternKind::GLOBAL
2903 ? hide_globaltype(
2904 static_cast<const wasm::GlobalType*>(reveal_externtype(et)))
2905 : nullptr;
2906}
2908 const wasm_externtype_t* et) {
2909 return et->kind() == wasm::ExternKind::TABLE
2910 ? hide_tabletype(
2911 static_cast<const wasm::TableType*>(reveal_externtype(et)))
2912 : nullptr;
2913}
2915 const wasm_externtype_t* et) {
2916 return et->kind() == wasm::ExternKind::MEMORY
2917 ? hide_memorytype(
2918 static_cast<const wasm::MemoryType*>(reveal_externtype(et)))
2919 : nullptr;
2920}
2921
2922// Import Types
2923
2924WASM_DEFINE_TYPE(importtype, wasm::ImportType)
2925
2926wasm_importtype_t* wasm_importtype_new(wasm_name_t* module, wasm_name_t* name,
2927 wasm_externtype_t* type) {
2928 return release_importtype(wasm::ImportType::make(
2929 adopt_byte_vec(module), adopt_byte_vec(name), adopt_externtype(type)));
2930}
2931
2932const wasm_name_t* wasm_importtype_module(const wasm_importtype_t* it) {
2933 return hide_byte_vec(it->module());
2934}
2935
2936const wasm_name_t* wasm_importtype_name(const wasm_importtype_t* it) {
2937 return hide_byte_vec(it->name());
2938}
2939
2940const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t* it) {
2941 return hide_externtype(it->type());
2942}
2943
2944// Export Types
2945
2946WASM_DEFINE_TYPE(exporttype, wasm::ExportType)
2947
2948wasm_exporttype_t* wasm_exporttype_new(wasm_name_t* name,
2949 wasm_externtype_t* type) {
2950 return release_exporttype(
2951 wasm::ExportType::make(adopt_byte_vec(name), adopt_externtype(type)));
2952}
2953
2954const wasm_name_t* wasm_exporttype_name(const wasm_exporttype_t* et) {
2955 return hide_byte_vec(et->name());
2956}
2957
2958const wasm_externtype_t* wasm_exporttype_type(const wasm_exporttype_t* et) {
2959 return hide_externtype(et->type());
2960}
2961
2963// Runtime Values
2964
2965// References
2966
2967#define WASM_DEFINE_REF_BASE(name, Name) \
2968 WASM_DEFINE_OWN(name, Name) \
2969 \
2970 wasm_##name##_t* wasm_##name##_copy(const wasm_##name##_t* t) { \
2971 return release_##name(t->copy()); \
2972 } \
2973 \
2974 bool wasm_##name##_same(const wasm_##name##_t* t1, \
2975 const wasm_##name##_t* t2) { \
2976 return t1->same(t2); \
2977 } \
2978 \
2979 void* wasm_##name##_get_host_info(const wasm_##name##_t* r) { \
2980 return r->get_host_info(); \
2981 } \
2982 void wasm_##name##_set_host_info(wasm_##name##_t* r, void* info) { \
2983 r->set_host_info(info); \
2984 } \
2985 void wasm_##name##_set_host_info_with_finalizer( \
2986 wasm_##name##_t* r, void* info, void (*finalizer)(void*)) { \
2987 r->set_host_info(info, finalizer); \
2988 }
2989
2990#define WASM_DEFINE_REF(name, Name) \
2991 WASM_DEFINE_REF_BASE(name, Name) \
2992 \
2993 wasm_ref_t* wasm_##name##_as_ref(wasm_##name##_t* r) { \
2994 return hide_ref(static_cast<wasm::Ref*>(reveal_##name(r))); \
2995 } \
2996 wasm_##name##_t* wasm_ref_as_##name(wasm_ref_t* r) { \
2997 return hide_##name(static_cast<Name*>(reveal_ref(r))); \
2998 } \
2999 \
3000 const wasm_ref_t* wasm_##name##_as_ref_const(const wasm_##name##_t* r) { \
3001 return hide_ref(static_cast<const wasm::Ref*>(reveal_##name(r))); \
3002 } \
3003 const wasm_##name##_t* wasm_ref_as_##name##_const(const wasm_ref_t* r) { \
3004 return hide_##name(static_cast<const Name*>(reveal_ref(r))); \
3005 }
3006
3007#define WASM_DEFINE_SHARABLE_REF(name, Name) \
3008 WASM_DEFINE_REF(name, Name) \
3009 WASM_DEFINE_OWN(shared_##name, wasm::Shared<Name>)
3010
3011WASM_DEFINE_REF_BASE(ref, wasm::Ref)
3012
3013// Values
3014
3015extern "C++" {
3016
3017inline auto is_empty(wasm_val_t v) -> bool {
3018 return !is_ref(reveal_valkind(v.kind)) || !v.of.ref;
3019}
3020
3021inline auto hide_val(wasm::Val v) -> wasm_val_t {
3022 wasm_val_t v2 = {hide_valkind(v.kind()), {}};
3023 switch (v.kind()) {
3024 case wasm::ValKind::I32:
3025 v2.of.i32 = v.i32();
3026 break;
3027 case wasm::ValKind::I64:
3028 v2.of.i64 = v.i64();
3029 break;
3030 case wasm::ValKind::F32:
3031 v2.of.f32 = v.f32();
3032 break;
3033 case wasm::ValKind::F64:
3034 v2.of.f64 = v.f64();
3035 break;
3036 case wasm::ValKind::EXTERNREF:
3037 case wasm::ValKind::FUNCREF:
3038 v2.of.ref = hide_ref(v.ref());
3039 break;
3040 default:
3041 UNREACHABLE();
3042 }
3043 return v2;
3044}
3045
3046inline auto release_val(wasm::Val v) -> wasm_val_t {
3047 wasm_val_t v2 = {hide_valkind(v.kind()), {}};
3048 switch (v.kind()) {
3049 case wasm::ValKind::I32:
3050 v2.of.i32 = v.i32();
3051 break;
3052 case wasm::ValKind::I64:
3053 v2.of.i64 = v.i64();
3054 break;
3055 case wasm::ValKind::F32:
3056 v2.of.f32 = v.f32();
3057 break;
3058 case wasm::ValKind::F64:
3059 v2.of.f64 = v.f64();
3060 break;
3061 case wasm::ValKind::EXTERNREF:
3062 case wasm::ValKind::FUNCREF:
3063 v2.of.ref = release_ref(v.release_ref());
3064 break;
3065 default:
3066 UNREACHABLE();
3067 }
3068 return v2;
3069}
3070
3071inline auto adopt_val(wasm_val_t v) -> wasm::Val {
3072 switch (reveal_valkind(v.kind)) {
3073 case wasm::ValKind::I32:
3074 return wasm::Val(v.of.i32);
3075 case wasm::ValKind::I64:
3076 return wasm::Val(v.of.i64);
3077 case wasm::ValKind::F32:
3078 return wasm::Val(v.of.f32);
3079 case wasm::ValKind::F64:
3080 return wasm::Val(v.of.f64);
3081 case wasm::ValKind::EXTERNREF:
3082 case wasm::ValKind::FUNCREF:
3083 return wasm::Val(adopt_ref(v.of.ref));
3084 default:
3085 UNREACHABLE();
3086 }
3087}
3088
3090 wasm::Val it;
3091 explicit borrowed_val(wasm::Val&& v) : it(std::move(v)) {}
3092 borrowed_val(borrowed_val&& that) : it(std::move(that.it)) {}
3094 if (it.is_ref()) it.release_ref().release();
3095 }
3096};
3097
3098inline auto borrow_val(const wasm_val_t* v) -> borrowed_val {
3099 wasm::Val v2;
3100 switch (reveal_valkind(v->kind)) {
3101 case wasm::ValKind::I32:
3102 v2 = wasm::Val(v->of.i32);
3103 break;
3104 case wasm::ValKind::I64:
3105 v2 = wasm::Val(v->of.i64);
3106 break;
3107 case wasm::ValKind::F32:
3108 v2 = wasm::Val(v->of.f32);
3109 break;
3110 case wasm::ValKind::F64:
3111 v2 = wasm::Val(v->of.f64);
3112 break;
3113 case wasm::ValKind::EXTERNREF:
3114 case wasm::ValKind::FUNCREF:
3115 v2 = wasm::Val(adopt_ref(v->of.ref));
3116 break;
3117 default:
3118 UNREACHABLE();
3119 }
3120 return borrowed_val(std::move(v2));
3121}
3122
3123} // extern "C++"
3124
3125WASM_DEFINE_VEC_BASE(val, wasm::Val, wasm::vec, )
3126
3127void wasm_val_vec_new(wasm_val_vec_t* out, size_t size,
3128 wasm_val_t const data[]) {
3129 auto v2 = wasm::vec<wasm::Val>::make_uninitialized(size);
3130 for (size_t i = 0; i < v2.size(); ++i) {
3131 v2[i] = adopt_val(data[i]);
3132 }
3133 *out = release_val_vec(std::move(v2));
3134}
3135
3136void wasm_val_vec_copy(wasm_val_vec_t* out, const wasm_val_vec_t* v) {
3137 auto v2 = wasm::vec<wasm::Val>::make_uninitialized(v->size);
3138 for (size_t i = 0; i < v2.size(); ++i) {
3139 wasm_val_t val;
3140 wasm_val_copy(&v->data[i], &val);
3141 v2[i] = adopt_val(val);
3142 }
3143 *out = release_val_vec(std::move(v2));
3144}
3145
3146void wasm_val_delete(wasm_val_t* v) {
3147 if (is_ref(reveal_valkind(v->kind))) {
3148 adopt_ref(v->of.ref);
3149 }
3150}
3151
3152void wasm_val_copy(wasm_val_t* out, const wasm_val_t* v) {
3153 *out = *v;
3154 if (is_ref(reveal_valkind(v->kind))) {
3155 out->of.ref = v->of.ref ? release_ref(v->of.ref->copy()) : nullptr;
3156 }
3157}
3158
3160// Runtime Objects
3161
3162// Frames
3163
3164WASM_DEFINE_OWN(frame, wasm::Frame)
3165WASM_DEFINE_VEC_OWN(frame, wasm::Frame)
3166
3167wasm_frame_t* wasm_frame_copy(const wasm_frame_t* frame) {
3168 return release_frame(frame->copy());
3169}
3170
3171wasm_instance_t* wasm_frame_instance(const wasm_frame_t* frame);
3172// Defined below along with wasm_instance_t.
3173
3174uint32_t wasm_frame_func_index(const wasm_frame_t* frame) {
3175 return reveal_frame(frame)->func_index();
3176}
3177
3178size_t wasm_frame_func_offset(const wasm_frame_t* frame) {
3179 return reveal_frame(frame)->func_offset();
3180}
3181
3182size_t wasm_frame_module_offset(const wasm_frame_t* frame) {
3183 return reveal_frame(frame)->module_offset();
3184}
3185
3186// Traps
3187
3188WASM_DEFINE_REF(trap, wasm::Trap)
3189
3190wasm_trap_t* wasm_trap_new(wasm_store_t* store, const wasm_message_t* message) {
3191 auto message_ = borrow_byte_vec(message);
3192 return release_trap(wasm::Trap::make(store, message_.it));
3193}
3194
3195void wasm_trap_message(const wasm_trap_t* trap, wasm_message_t* out) {
3196 *out = release_byte_vec(reveal_trap(trap)->message());
3197}
3198
3199wasm_frame_t* wasm_trap_origin(const wasm_trap_t* trap) {
3200 return release_frame(reveal_trap(trap)->origin());
3201}
3202
3203void wasm_trap_trace(const wasm_trap_t* trap, wasm_frame_vec_t* out) {
3204 *out = release_frame_vec(reveal_trap(trap)->trace());
3205}
3206
3207// Foreign Objects
3208
3209WASM_DEFINE_REF(foreign, wasm::Foreign)
3210
3211wasm_foreign_t* wasm_foreign_new(wasm_store_t* store) {
3212 return release_foreign(wasm::Foreign::make(store));
3213}
3214
3215// Modules
3216
3217WASM_DEFINE_SHARABLE_REF(module, wasm::Module)
3218
3219bool wasm_module_validate(wasm_store_t* store, const wasm_byte_vec_t* binary) {
3220 auto binary_ = borrow_byte_vec(binary);
3221 return wasm::Module::validate(store, binary_.it);
3222}
3223
3224wasm_module_t* wasm_module_new(wasm_store_t* store,
3225 const wasm_byte_vec_t* binary) {
3226 auto binary_ = borrow_byte_vec(binary);
3227 return release_module(wasm::Module::make(store, binary_.it));
3228}
3229
3230void wasm_module_imports(const wasm_module_t* module,
3231 wasm_importtype_vec_t* out) {
3232 *out = release_importtype_vec(reveal_module(module)->imports());
3233}
3234
3235void wasm_module_exports(const wasm_module_t* module,
3236 wasm_exporttype_vec_t* out) {
3237 *out = release_exporttype_vec(reveal_module(module)->exports());
3238}
3239
3240void wasm_module_serialize(const wasm_module_t* module, wasm_byte_vec_t* out) {
3241 *out = release_byte_vec(reveal_module(module)->serialize());
3242}
3243
3244wasm_module_t* wasm_module_deserialize(wasm_store_t* store,
3245 const wasm_byte_vec_t* binary) {
3246 auto binary_ = borrow_byte_vec(binary);
3247 return release_module(wasm::Module::deserialize(store, binary_.it));
3248}
3249
3250wasm_shared_module_t* wasm_module_share(const wasm_module_t* module) {
3251 return release_shared_module(reveal_module(module)->share());
3252}
3253
3254wasm_module_t* wasm_module_obtain(wasm_store_t* store,
3255 const wasm_shared_module_t* shared) {
3256 return release_module(wasm::Module::obtain(store, shared));
3257}
3258
3259// Function Instances
3260
3261WASM_DEFINE_REF(func, wasm::Func)
3262
3263extern "C++" {
3264
3265auto wasm_callback(void* env, const wasm::vec<wasm::Val>& args,
3266 wasm::vec<wasm::Val>& results) -> wasm::own<wasm::Trap> {
3267 auto f = reinterpret_cast<wasm_func_callback_t>(env);
3268 return adopt_trap(f(hide_val_vec(args), hide_val_vec(results)));
3269}
3270
3272 wasm_func_callback_with_env_t callback;
3273 void* env;
3274 void (*finalizer)(void*);
3275};
3276
3277auto wasm_callback_with_env(void* env, const wasm::vec<wasm::Val>& args,
3278 wasm::vec<wasm::Val>& results)
3279 -> wasm::own<wasm::Trap> {
3280 auto t = static_cast<wasm_callback_env_t*>(env);
3281 return adopt_trap(
3282 t->callback(t->env, hide_val_vec(args), hide_val_vec(results)));
3283}
3284
3286 auto t = static_cast<wasm_callback_env_t*>(env);
3287 if (t->finalizer) t->finalizer(t->env);
3288 delete t;
3289}
3290
3291} // extern "C++"
3292
3293wasm_func_t* wasm_func_new(wasm_store_t* store, const wasm_functype_t* type,
3294 wasm_func_callback_t callback) {
3295 return release_func(wasm::Func::make(store, type, wasm_callback,
3296 reinterpret_cast<void*>(callback)));
3297}
3298
3299wasm_func_t* wasm_func_new_with_env(wasm_store_t* store,
3300 const wasm_functype_t* type,
3301 wasm_func_callback_with_env_t callback,
3302 void* env, void (*finalizer)(void*)) {
3303 auto env2 = new wasm_callback_env_t{callback, env, finalizer};
3304 return release_func(wasm::Func::make(store, type, wasm_callback_with_env,
3306}
3307
3308wasm_functype_t* wasm_func_type(const wasm_func_t* func) {
3309 return release_functype(func->type());
3310}
3311
3312size_t wasm_func_param_arity(const wasm_func_t* func) {
3313 return func->param_arity();
3314}
3315
3316size_t wasm_func_result_arity(const wasm_func_t* func) {
3317 return func->result_arity();
3318}
3319
3320WASM_API_EXTERN wasm_trap_t* wasm_func_call(const wasm_func_t* func,
3321 const wasm_val_vec_t* args,
3322 wasm_val_vec_t* results) {
3323 auto v8_results = adopt_val_vec(results);
3324 auto ret = release_trap(func->call(adopt_val_vec(args), v8_results));
3325 *results = release_val_vec(std::move(v8_results));
3326
3327 return ret;
3328}
3329
3330// Global Instances
3331
3332WASM_DEFINE_REF(global, wasm::Global)
3333
3334wasm_global_t* wasm_global_new(wasm_store_t* store,
3335 const wasm_globaltype_t* type,
3336 const wasm_val_t* val) {
3337 auto val_ = borrow_val(val);
3338 return release_global(wasm::Global::make(store, type, val_.it));
3339}
3340
3341wasm_globaltype_t* wasm_global_type(const wasm_global_t* global) {
3342 return release_globaltype(global->type());
3343}
3344
3345void wasm_global_get(const wasm_global_t* global, wasm_val_t* out) {
3346 *out = release_val(global->get());
3347}
3348
3349void wasm_global_set(wasm_global_t* global, const wasm_val_t* val) {
3350 auto val_ = borrow_val(val);
3351 global->set(val_.it);
3352}
3353
3354// Table Instances
3355
3356WASM_DEFINE_REF(table, wasm::Table)
3357
3358wasm_table_t* wasm_table_new(wasm_store_t* store, const wasm_tabletype_t* type,
3359 wasm_ref_t* ref) {
3360 return release_table(wasm::Table::make(store, type, ref));
3361}
3362
3363wasm_tabletype_t* wasm_table_type(const wasm_table_t* table) {
3364 return release_tabletype(table->type());
3365}
3366
3367wasm_ref_t* wasm_table_get(const wasm_table_t* table, wasm_table_size_t index) {
3368 return release_ref(table->get(index));
3369}
3370
3371bool wasm_table_set(wasm_table_t* table, wasm_table_size_t index,
3372 wasm_ref_t* ref) {
3373 return table->set(index, ref);
3374}
3375
3376wasm_table_size_t wasm_table_size(const wasm_table_t* table) {
3377 return table->size();
3378}
3379
3380bool wasm_table_grow(wasm_table_t* table, wasm_table_size_t delta,
3381 wasm_ref_t* ref) {
3382 return table->grow(delta, ref);
3383}
3384
3385// Memory Instances
3386
3387WASM_DEFINE_REF(memory, wasm::Memory)
3388
3389wasm_memory_t* wasm_memory_new(wasm_store_t* store,
3390 const wasm_memorytype_t* type) {
3391 return release_memory(wasm::Memory::make(store, type));
3392}
3393
3394wasm_memorytype_t* wasm_memory_type(const wasm_memory_t* memory) {
3395 return release_memorytype(memory->type());
3396}
3397
3398wasm_byte_t* wasm_memory_data(wasm_memory_t* memory) { return memory->data(); }
3399
3400size_t wasm_memory_data_size(const wasm_memory_t* memory) {
3401 return memory->data_size();
3402}
3403
3404wasm_memory_pages_t wasm_memory_size(const wasm_memory_t* memory) {
3405 return memory->size();
3406}
3407
3408bool wasm_memory_grow(wasm_memory_t* memory, wasm_memory_pages_t delta) {
3409 return memory->grow(delta);
3410}
3411
3412// Externals
3413
3414WASM_DEFINE_REF(extern, wasm::Extern)
3415WASM_DEFINE_VEC_OWN(extern, wasm::Extern)
3416
3417wasm_externkind_t wasm_extern_kind(const wasm_extern_t* external) {
3418 return hide_externkind(external->kind());
3419}
3420wasm_externtype_t* wasm_extern_type(const wasm_extern_t* external) {
3421 return release_externtype(external->type());
3422}
3423
3424wasm_extern_t* wasm_func_as_extern(wasm_func_t* func) {
3425 return hide_extern(static_cast<wasm::Extern*>(reveal_func(func)));
3426}
3427wasm_extern_t* wasm_global_as_extern(wasm_global_t* global) {
3428 return hide_extern(static_cast<wasm::Extern*>(reveal_global(global)));
3429}
3430wasm_extern_t* wasm_table_as_extern(wasm_table_t* table) {
3431 return hide_extern(static_cast<wasm::Extern*>(reveal_table(table)));
3432}
3433wasm_extern_t* wasm_memory_as_extern(wasm_memory_t* memory) {
3434 return hide_extern(static_cast<wasm::Extern*>(reveal_memory(memory)));
3435}
3436
3437const wasm_extern_t* wasm_func_as_extern_const(const wasm_func_t* func) {
3438 return hide_extern(static_cast<const wasm::Extern*>(reveal_func(func)));
3439}
3440const wasm_extern_t* wasm_global_as_extern_const(const wasm_global_t* global) {
3441 return hide_extern(static_cast<const wasm::Extern*>(reveal_global(global)));
3442}
3443const wasm_extern_t* wasm_table_as_extern_const(const wasm_table_t* table) {
3444 return hide_extern(static_cast<const wasm::Extern*>(reveal_table(table)));
3445}
3446const wasm_extern_t* wasm_memory_as_extern_const(const wasm_memory_t* memory) {
3447 return hide_extern(static_cast<const wasm::Extern*>(reveal_memory(memory)));
3448}
3449
3450wasm_func_t* wasm_extern_as_func(wasm_extern_t* external) {
3451 return hide_func(external->func());
3452}
3453wasm_global_t* wasm_extern_as_global(wasm_extern_t* external) {
3454 return hide_global(external->global());
3455}
3456wasm_table_t* wasm_extern_as_table(wasm_extern_t* external) {
3457 return hide_table(external->table());
3458}
3459wasm_memory_t* wasm_extern_as_memory(wasm_extern_t* external) {
3460 return hide_memory(external->memory());
3461}
3462
3463const wasm_func_t* wasm_extern_as_func_const(const wasm_extern_t* external) {
3464 return hide_func(external->func());
3465}
3466const wasm_global_t* wasm_extern_as_global_const(
3467 const wasm_extern_t* external) {
3468 return hide_global(external->global());
3469}
3470const wasm_table_t* wasm_extern_as_table_const(const wasm_extern_t* external) {
3471 return hide_table(external->table());
3472}
3473const wasm_memory_t* wasm_extern_as_memory_const(
3474 const wasm_extern_t* external) {
3475 return hide_memory(external->memory());
3476}
3477
3478// Module Instances
3479
3480WASM_DEFINE_REF(instance, wasm::Instance)
3481
3482WASM_API_EXTERN wasm_instance_t* wasm_instance_new(
3483 wasm_store_t* store, const wasm_module_t* module,
3484 const wasm_extern_vec_t* imports, wasm_trap_t** trap) {
3485 wasm::own<wasm::Trap> error;
3486
3487 size_t size = 0;
3488 if (imports->data && imports->size > 0) {
3489 size = imports->size;
3490 }
3491
3492 auto v8_imports = wasm::vec<wasm::Extern*>::make_uninitialized(size);
3493
3494 for (size_t i = 0; i < v8_imports.size(); i++) {
3495 v8_imports[i] = reveal_extern(imports->data[i]);
3496 }
3497
3498 wasm_instance_t* instance =
3499 release_instance(wasm::Instance::make(store, module, v8_imports, &error));
3500 if (trap) *trap = hide_trap(error.release());
3501 return instance;
3502}
3503
3504void wasm_instance_exports(const wasm_instance_t* instance,
3505 wasm_extern_vec_t* out) {
3506 *out = release_extern_vec(instance->exports());
3507}
3508
3509wasm_instance_t* wasm_frame_instance(const wasm_frame_t* frame) {
3510 return hide_instance(reveal_frame(frame)->instance());
3511}
3512
3513#undef WASM_DEFINE_OWN
3514#undef WASM_DEFINE_VEC_BASE
3515#undef WASM_DEFINE_VEC_PLAIN
3516#undef WASM_DEFINE_VEC_OWN
3517#undef WASM_DEFINE_TYPE
3518#undef WASM_DEFINE_REF_BASE
3519#undef WASM_DEFINE_REF
3520#undef WASM_DEFINE_SHARABLE_REF
3521
3522} // extern "C"
int16_t parameter_count
Definition builtins.cc:67
const char * name
Definition builtins.cc:39
Builtins::Kind kind
Definition builtins.cc:40
#define BUILTIN_CODE(isolate, name)
Definition builtins.h:45
const wasm_limits_t * wasm_memorytype_limits(const wasm_memorytype_t *mt)
Definition c-api.cc:2826
uint32_t wasm_frame_func_index(const wasm_frame_t *frame)
Definition c-api.cc:3174
wasm_ref_t * wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
Definition c-api.cc:3367
#define WASM_DEFINE_REF(name, Name)
Definition c-api.cc:2990
const wasm_tabletype_t * wasm_externtype_as_tabletype_const(const wasm_externtype_t *et)
Definition c-api.cc:2907
const wasm_externtype_t * wasm_tabletype_as_externtype_const(const wasm_tabletype_t *tt)
Definition c-api.cc:2859
wasm_memory_t * wasm_memory_new(wasm_store_t *store, const wasm_memorytype_t *type)
Definition c-api.cc:3389
const wasm_func_t * wasm_extern_as_func_const(const wasm_extern_t *external)
Definition c-api.cc:3463
wasm_byte_t * wasm_memory_data(wasm_memory_t *memory)
Definition c-api.cc:3398
const wasm_memory_t * wasm_extern_as_memory_const(const wasm_extern_t *external)
Definition c-api.cc:3473
const wasm_externtype_t * wasm_functype_as_externtype_const(const wasm_functype_t *ft)
Definition c-api.cc:2851
wasm_externkind_t wasm_externtype_kind(const wasm_externtype_t *et)
Definition c-api.cc:2834
auto hide_val(wasm::Val v) -> wasm_val_t
Definition c-api.cc:3021
auto hide_valkind(wasm::ValKind kind) -> wasm_valkind_t
Definition c-api.cc:2723
#define WASM_DEFINE_VEC_PLAIN(name, Name)
Definition c-api.cc:2617
bool wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary)
Definition c-api.cc:3219
wasm_global_t * wasm_extern_as_global(wasm_extern_t *external)
Definition c-api.cc:3453
void wasm_module_imports(const wasm_module_t *module, wasm_importtype_vec_t *out)
Definition c-api.cc:3230
auto borrow_val(const wasm_val_t *v) -> borrowed_val
Definition c-api.cc:3098
wasm_table_t * wasm_table_new(wasm_store_t *store, const wasm_tabletype_t *type, wasm_ref_t *ref)
Definition c-api.cc:3358
const wasm_externtype_t * wasm_memorytype_as_externtype_const(const wasm_memorytype_t *mt)
Definition c-api.cc:2863
void wasm_trap_message(const wasm_trap_t *trap, wasm_message_t *out)
Definition c-api.cc:3195
wasm_externkind_t wasm_extern_kind(const wasm_extern_t *external)
Definition c-api.cc:3417
const wasm_functype_t * wasm_externtype_as_functype_const(const wasm_externtype_t *et)
Definition c-api.cc:2893
const wasm_externtype_t * wasm_importtype_type(const wasm_importtype_t *it)
Definition c-api.cc:2940
wasm_module_t * wasm_module_obtain(wasm_store_t *store, const wasm_shared_module_t *shared)
Definition c-api.cc:3254
wasm_memory_pages_t wasm_memory_size(const wasm_memory_t *memory)
Definition c-api.cc:3404
const wasm_valtype_t * wasm_globaltype_content(const wasm_globaltype_t *gt)
Definition c-api.cc:2792
wasm_tabletype_t * wasm_externtype_as_tabletype(wasm_externtype_t *et)
Definition c-api.cc:2880
#define WASM_DEFINE_VEC_BASE(name, Name, vec, ptr_or_none)
Definition c-api.cc:2546
const wasm_name_t * wasm_importtype_module(const wasm_importtype_t *it)
Definition c-api.cc:2932
void wasm_val_vec_new(wasm_val_vec_t *out, size_t size, wasm_val_t const data[])
Definition c-api.cc:3127
wasm_store_t * wasm_store_new(wasm_engine_t *engine)
Definition c-api.cc:2695
wasm_externtype_t * wasm_functype_as_externtype(wasm_functype_t *ft)
Definition c-api.cc:2838
wasm_mutability_t wasm_globaltype_mutability(const wasm_globaltype_t *gt)
Definition c-api.cc:2796
wasm_tabletype_t * wasm_table_type(const wasm_table_t *table)
Definition c-api.cc:3363
const wasm_extern_t * wasm_global_as_extern_const(const wasm_global_t *global)
Definition c-api.cc:3440
auto reveal_limits(wasm_limits_t limits) -> wasm::Limits
Definition c-api.cc:2719
auto adopt_val(wasm_val_t v) -> wasm::Val
Definition c-api.cc:3071
auto reveal_mutability(wasm_mutability_t mutability) -> wasm::Mutability
Definition c-api.cc:2709
const wasm_externtype_t * wasm_globaltype_as_externtype_const(const wasm_globaltype_t *gt)
Definition c-api.cc:2855
WASM_API_EXTERN wasm_trap_t * wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *args, wasm_val_vec_t *results)
Definition c-api.cc:3320
wasm_externtype_t * wasm_tabletype_as_externtype(wasm_tabletype_t *tt)
Definition c-api.cc:2844
wasm_valtype_t * wasm_valtype_new(wasm_valkind_t k)
Definition c-api.cc:2756
const wasm_valtype_vec_t * wasm_functype_params(const wasm_functype_t *ft)
Definition c-api.cc:2774
wasm_func_t * wasm_func_new_with_env(wasm_store_t *store, const wasm_functype_t *type, wasm_func_callback_with_env_t callback, void *env, void(*finalizer)(void *))
Definition c-api.cc:3299
const wasm_extern_t * wasm_memory_as_extern_const(const wasm_memory_t *memory)
Definition c-api.cc:3446
#define WASM_DEFINE_VEC_OWN(name, Name)
Definition c-api.cc:2636
void wasm_callback_env_finalizer(void *env)
Definition c-api.cc:3285
wasm_engine_t * wasm_engine_new()
Definition c-api.cc:2683
void wasm_val_vec_copy(wasm_val_vec_t *out, const wasm_val_vec_t *v)
Definition c-api.cc:3136
size_t wasm_memory_data_size(const wasm_memory_t *memory)
Definition c-api.cc:3400
#define WASM_DEFINE_SHARABLE_REF(name, Name)
Definition c-api.cc:3007
wasm_extern_t * wasm_table_as_extern(wasm_table_t *table)
Definition c-api.cc:3430
#define WASM_DEFINE_REF_BASE(name, Name)
Definition c-api.cc:2967
auto reveal_valkind(wasm_valkind_t kind) -> wasm::ValKind
Definition c-api.cc:2727
size_t wasm_func_result_arity(const wasm_func_t *func)
Definition c-api.cc:3316
size_t wasm_func_param_arity(const wasm_func_t *func)
Definition c-api.cc:3312
void wasm_val_copy(wasm_val_t *out, const wasm_val_t *v)
Definition c-api.cc:3152
wasm_functype_t * wasm_externtype_as_functype(wasm_externtype_t *et)
Definition c-api.cc:2868
wasm_extern_t * wasm_memory_as_extern(wasm_memory_t *memory)
Definition c-api.cc:3433
wasm_functype_t * wasm_func_type(const wasm_func_t *func)
Definition c-api.cc:3308
wasm_func_t * wasm_extern_as_func(wasm_extern_t *external)
Definition c-api.cc:3450
wasm_global_t * wasm_global_new(wasm_store_t *store, const wasm_globaltype_t *type, const wasm_val_t *val)
Definition c-api.cc:3334
wasm_externtype_t * wasm_globaltype_as_externtype(wasm_globaltype_t *gt)
Definition c-api.cc:2841
wasm_shared_module_t * wasm_module_share(const wasm_module_t *module)
Definition c-api.cc:3250
auto reveal_externkind(wasm_externkind_t kind) -> wasm::ExternKind
Definition c-api.cc:2736
void wasm_global_set(wasm_global_t *global, const wasm_val_t *val)
Definition c-api.cc:3349
void wasm_instance_exports(const wasm_instance_t *instance, wasm_extern_vec_t *out)
Definition c-api.cc:3504
const wasm_name_t * wasm_importtype_name(const wasm_importtype_t *it)
Definition c-api.cc:2936
wasm_exporttype_t * wasm_exporttype_new(wasm_name_t *name, wasm_externtype_t *type)
Definition c-api.cc:2948
wasm_table_t * wasm_extern_as_table(wasm_extern_t *external)
Definition c-api.cc:3456
wasm_globaltype_t * wasm_externtype_as_globaltype(wasm_externtype_t *et)
Definition c-api.cc:2874
wasm_globaltype_t * wasm_global_type(const wasm_global_t *global)
Definition c-api.cc:3341
wasm_engine_t * wasm_engine_new_with_config(wasm_config_t *config)
Definition c-api.cc:2687
wasm_extern_t * wasm_global_as_extern(wasm_global_t *global)
Definition c-api.cc:3427
const wasm_extern_t * wasm_func_as_extern_const(const wasm_func_t *func)
Definition c-api.cc:3437
bool wasm_memory_grow(wasm_memory_t *memory, wasm_memory_pages_t delta)
Definition c-api.cc:3408
wasm_table_size_t wasm_table_size(const wasm_table_t *table)
Definition c-api.cc:3376
wasm_memorytype_t * wasm_externtype_as_memorytype(wasm_externtype_t *et)
Definition c-api.cc:2886
auto wasm_callback(void *env, const wasm::vec< wasm::Val > &args, wasm::vec< wasm::Val > &results) -> wasm::own< wasm::Trap >
Definition c-api.cc:3265
void wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
Definition c-api.cc:3235
wasm_module_t * wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
Definition c-api.cc:3224
void wasm_global_get(const wasm_global_t *global, wasm_val_t *out)
Definition c-api.cc:3345
wasm_foreign_t * wasm_foreign_new(wasm_store_t *store)
Definition c-api.cc:3211
bool wasm_table_set(wasm_table_t *table, wasm_table_size_t index, wasm_ref_t *ref)
Definition c-api.cc:3371
const wasm_externtype_t * wasm_exporttype_type(const wasm_exporttype_t *et)
Definition c-api.cc:2958
#define WASM_EXPORT
Definition c-api.cc:70
bool wasm_table_grow(wasm_table_t *table, wasm_table_size_t delta, wasm_ref_t *ref)
Definition c-api.cc:3380
wasm_config_t * wasm_config_new()
Definition c-api.cc:2675
const wasm_globaltype_t * wasm_externtype_as_globaltype_const(const wasm_externtype_t *et)
Definition c-api.cc:2900
const wasm_valtype_t * wasm_tabletype_element(const wasm_tabletype_t *tt)
Definition c-api.cc:2810
wasm_memorytype_t * wasm_memorytype_new(const wasm_limits_t *limits)
Definition c-api.cc:2822
wasm_globaltype_t * wasm_globaltype_new(wasm_valtype_t *content, wasm_mutability_t mutability)
Definition c-api.cc:2786
wasm_functype_t * wasm_functype_new(wasm_valtype_vec_t *params, wasm_valtype_vec_t *results)
Definition c-api.cc:2768
WASM_API_EXTERN wasm_instance_t * wasm_instance_new(wasm_store_t *store, const wasm_module_t *module, const wasm_extern_vec_t *imports, wasm_trap_t **trap)
Definition c-api.cc:3482
void wasm_module_serialize(const wasm_module_t *module, wasm_byte_vec_t *out)
Definition c-api.cc:3240
wasm_extern_t * wasm_func_as_extern(wasm_func_t *func)
Definition c-api.cc:3424
void wasm_val_delete(wasm_val_t *v)
Definition c-api.cc:3146
wasm_externtype_t * wasm_extern_type(const wasm_extern_t *external)
Definition c-api.cc:3420
wasm_importtype_t * wasm_importtype_new(wasm_name_t *module, wasm_name_t *name, wasm_externtype_t *type)
Definition c-api.cc:2926
wasm_memory_t * wasm_extern_as_memory(wasm_extern_t *external)
Definition c-api.cc:3459
auto release_val(wasm::Val v) -> wasm_val_t
Definition c-api.cc:3046
const wasm_table_t * wasm_extern_as_table_const(const wasm_extern_t *external)
Definition c-api.cc:3470
wasm_func_t * wasm_func_new(wasm_store_t *store, const wasm_functype_t *type, wasm_func_callback_t callback)
Definition c-api.cc:3293
const wasm_memorytype_t * wasm_externtype_as_memorytype_const(const wasm_externtype_t *et)
Definition c-api.cc:2914
wasm_tabletype_t * wasm_tabletype_new(wasm_valtype_t *element, const wasm_limits_t *limits)
Definition c-api.cc:2804
wasm_trap_t * wasm_trap_new(wasm_store_t *store, const wasm_message_t *message)
Definition c-api.cc:3190
wasm_memorytype_t * wasm_memory_type(const wasm_memory_t *memory)
Definition c-api.cc:3394
const wasm_limits_t * wasm_tabletype_limits(const wasm_tabletype_t *tt)
Definition c-api.cc:2814
wasm_valkind_t wasm_valtype_kind(const wasm_valtype_t *t)
Definition c-api.cc:2760
auto hide_externkind(wasm::ExternKind kind) -> wasm_externkind_t
Definition c-api.cc:2731
#define WASM_DEFINE_OWN(name, Name)
Definition c-api.cc:2498
auto hide_limits(const wasm::Limits &limits) -> const wasm_limits_t *
Definition c-api.cc:2714
const wasm_name_t * wasm_exporttype_name(const wasm_exporttype_t *et)
Definition c-api.cc:2954
wasm_instance_t * wasm_frame_instance(const wasm_frame_t *frame)
Definition c-api.cc:3509
wasm_frame_t * wasm_trap_origin(const wasm_trap_t *trap)
Definition c-api.cc:3199
size_t wasm_frame_func_offset(const wasm_frame_t *frame)
Definition c-api.cc:3178
auto hide_mutability(wasm::Mutability mutability) -> wasm_mutability_t
Definition c-api.cc:2704
#define WASM_DEFINE_TYPE(name, Name)
Definition c-api.cc:2743
auto wasm_callback_with_env(void *env, const wasm::vec< wasm::Val > &args, wasm::vec< wasm::Val > &results) -> wasm::own< wasm::Trap >
Definition c-api.cc:3277
const wasm_valtype_vec_t * wasm_functype_results(const wasm_functype_t *ft)
Definition c-api.cc:2778
void wasm_trap_trace(const wasm_trap_t *trap, wasm_frame_vec_t *out)
Definition c-api.cc:3203
wasm_externtype_t * wasm_memorytype_as_externtype(wasm_memorytype_t *mt)
Definition c-api.cc:2847
const wasm_global_t * wasm_extern_as_global_const(const wasm_extern_t *external)
Definition c-api.cc:3466
size_t wasm_frame_module_offset(const wasm_frame_t *frame)
Definition c-api.cc:3182
const wasm_extern_t * wasm_table_as_extern_const(const wasm_table_t *table)
Definition c-api.cc:3443
wasm_frame_t * wasm_frame_copy(const wasm_frame_t *frame)
Definition c-api.cc:3167
wasm_module_t * wasm_module_deserialize(wasm_store_t *store, const wasm_byte_vec_t *binary)
Definition c-api.cc:3244
#define SBXCHECK(condition)
Definition check.h:61
SourcePosition pos
static Allocator * NewDefaultAllocator()
Definition api.cc:8923
static Local< Context > New(Isolate *isolate, ExtensionConfiguration *extensions=nullptr, MaybeLocal< ObjectTemplate > global_template=MaybeLocal< ObjectTemplate >(), MaybeLocal< Value > global_object=MaybeLocal< Value >(), DeserializeInternalFieldsCallback internal_fields_deserializer=DeserializeInternalFieldsCallback(), MicrotaskQueue *microtask_queue=nullptr, DeserializeContextDataCallback context_data_deserializer=DeserializeContextDataCallback(), DeserializeAPIWrapperCallback api_wrapper_deserializer=DeserializeAPIWrapperCallback())
Definition api.cc:6778
void Exit()
Definition api.cc:829
void Dispose()
Definition api.cc:10100
static Isolate * New(const CreateParams &params)
Definition api.cc:10089
static v8::internal::DirectHandle< To > OpenDirectHandle(v8::Local< From > handle)
Definition api.h:279
static void DisposePlatform()
Definition api.cc:6389
static void InitializePlatform(Platform *platform)
Definition api.cc:6385
static V8_INLINE bool Initialize()
static bool Dispose()
Definition api.cc:6513
int length() const
Definition vector.h:64
constexpr size_t size() const
Definition vector.h:70
constexpr T * begin() const
Definition vector.h:96
Isolate * isolate() const
Definition factory.h:1281
Handle< JSWeakMap > NewJSWeakMap()
Definition factory.cc:3338
IndirectHandle< Object > Create(Tagged< Object > value)
V8_EXPORT_PRIVATE void PreciseCollectAllGarbage(GCFlags gc_flags, GarbageCollectionReason gc_reason, const GCCallbackFlags gc_callback_flags=kNoGCCallbackFlags)
Definition heap.cc:1411
GlobalHandles * global_handles() const
Definition isolate.h:1416
v8::internal::Factory * factory()
Definition isolate.h:1527
V8_INLINE DirectHandle< T > ToHandleChecked() const
V8_WARN_UNUSED_RESULT V8_INLINE bool ToHandle(DirectHandle< S > *out) const
V8_INLINE bool is_null() const
V8_INLINE constexpr StorageType ptr() const
void set_host_info(void *info, void(*finalizer)(void *))
Definition c-api.cc:989
void * get_host_info() const
Definition c-api.cc:984
RefImpl()=default
StoreImpl * store_
Definition c-api.cc:1002
i::Isolate * isolate() const
Definition c-api.cc:980
static own< Ref > make(StoreImpl *store, i::DirectHandle< JSType > obj)
Definition c-api.cc:962
i::DirectHandle< JSType > v8_object() const
Definition c-api.cc:982
own< Ref > copy() const
Definition c-api.cc:973
i::Address * location() const
Definition c-api.cc:997
i::IndirectHandle< i::JSReceiver > val_
Definition c-api.cc:1001
StoreImpl * store() const
Definition c-api.cc:978
void destroy()
Definition c-api.cc:469
i::IndirectHandle< i::JSWeakMap > host_info_map_
Definition c-api.h:62
v8::Isolate * isolate() const
Definition c-api.h:38
i::Isolate * i_isolate() const
Definition c-api.h:39
v8::Isolate::CreateParams create_params_
Definition c-api.h:59
void SetHostInfo(i::DirectHandle< i::Object > object, void *info, void(*finalizer)(void *))
Definition c-api.cc:500
void * GetHostInfo(i::DirectHandle< i::Object > key)
Definition c-api.cc:515
v8::Local< v8::Context > context() const
Definition c-api.h:43
v8::Isolate * isolate_
Definition c-api.h:60
MachineType mt
size_t count_
Definition sweeper.cc:55
bool is_empty
Definition sweeper.cc:229
uint32_t count
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
too high values may cause the compiler to set high thresholds for inlining to as much as possible avoid inlined allocation of objects that cannot escape trace load stores from virtual maglev objects use TurboFan fast string builder analyze liveness of environment slots and zap dead values trace TurboFan load elimination emit data about basic block usage in builtins to this enable builtin reordering when run mksnapshot flag for emit warnings when applying builtin profile data verify register allocation in TurboFan randomly schedule instructions to stress dependency tracking enable store store elimination in TurboFan rewrite far to near simulate GC compiler thread race related to allow float parameters to be passed in simulator mode JS Wasm Run additional turbo_optimize_inlined_js_wasm_wrappers enable experimental feedback collection in generic lowering enable Turboshaft s WasmLoadElimination enable Turboshaft s low level load elimination for JS enable Turboshaft s escape analysis for string concatenation use enable Turbolev features that we want to ship in the not too far future trace individual Turboshaft reduction steps trace intermediate Turboshaft reduction steps invocation count threshold for early optimization Enables optimizations which favor memory size over execution speed Enables sampling allocation profiler with X as a sample interval min size of a semi the new space consists of two semi spaces max size of the Collect garbage after Collect garbage after keeps maps alive for< n > old space garbage collections print one detailed trace line in allocation gc speed threshold for starting incremental marking via a task in percent of available threshold for starting incremental marking immediately in percent of available Use a single schedule for determining a marking schedule between JS and C objects schedules the minor GC task with kUserVisible priority max worker number of concurrent for NumberOfWorkerThreads start background threads that allocate memory concurrent_array_buffer_sweeping use parallel threads to clear weak refs in the atomic pause trace progress of the incremental marking trace object counts and memory usage report a tick only when allocated zone memory changes by this amount TracingFlags::gc_stats store(v8::tracing::TracingCategoryObserver::ENABLED_BY_NATIVE)) DEFINE_GENERIC_IMPLICATION(trace_gc_object_stats
Isolate * isolate
int32_t offset
TNode< Object > callback
ZoneVector< RpoNumber > & result
std::optional< OolTrapLabel > trap
int x
const char * name_
Counters * counters_
int n
Definition mul-fft.cc:296
STL namespace.
int int32_t
Definition unicode.cc:40
static V ReadUnalignedValue(Address p)
Definition memory.h:28
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
static void WriteUnalignedValue(Address p, V value)
Definition memory.h:41
OwnedVector< T > OwnedCopyOf(const T *data, size_t size)
Definition vector.h:383
void PrintF(const char *format,...)
Definition utils.cc:39
Tagged(T object) -> Tagged< T >
kWasmInternalFunctionIndirectPointerTag instance_data
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr bool kAllCodeObjectsLiveInTrustedSpace
static constexpr Address kNullAddress
Definition v8-internal.h:53
constexpr uint32_t kMaxUInt32
Definition globals.h:387
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
std::unique_ptr< v8::Platform > NewSingleThreadedDefaultPlatform(IdleTaskSupport idle_task_support, InProcessStackDumping in_process_stack_dumping, std::unique_ptr< v8::TracingController > tracing_controller)
@ kNoGCCallbackFlags
std::unordered_map< std::string, Counter * > CounterMap
Definition d8.h:86
Definition c-api.cc:87
ValTypeImpl * valtype_funcref
Definition c-api.cc:599
void ignore(T)
Definition c-api.cc:237
ownvec< ExportType > ExportsImpl(i::DirectHandle< i::WasmModuleObject > module_obj)
Definition c-api.cc:1275
ValTypeImpl * valtype_i32
Definition c-api.cc:594
auto extern_to_v8(const Extern *ex) -> i::DirectHandle< i::JSReceiver >
Definition c-api.cc:1466
ValTypeImpl * valtype_i64
Definition c-api.cc:595
void CheckAndHandleInterrupts(i::Isolate *isolate)
Definition c-api.cc:460
auto seal(typename implement< C >::type *x) -> C *
Definition c-api.cc:253
void WASM_UNIMPLEMENTED(const char *s)
BEGIN FILE wasm-v8.cc.
Definition c-api.cc:231
ValTypeImpl * valtype_externref
Definition c-api.cc:598
auto impl(C *x) -> typename implement< C >::type *
Definition c-api.cc:243
i::DirectHandle< i::String > VecToString(i::Isolate *isolate, const vec< byte_t > &chars)
Definition c-api.cc:946
ValTypeImpl * valtype_f64
Definition c-api.cc:597
ValTypeImpl * valtype_f32
Definition c-api.cc:596
#define UNREACHABLE()
Definition logging.h:67
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define CHECK(condition)
Definition logging.h:124
#define UNIMPLEMENTED()
Definition logging.h:66
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
borrowed_val(borrowed_val &&that)
Definition c-api.cc:3092
wasm::Val it
Definition c-api.cc:3090
borrowed_val(wasm::Val &&v)
Definition c-api.cc:3091
wasm::vec< T > it
Definition c-api.cc:2490
borrowed_vec(borrowed_vec< T > &&that)
Definition c-api.cc:2492
borrowed_vec(wasm::vec< T > &&v)
Definition c-api.cc:2491
ArrayBuffer::Allocator * array_buffer_allocator
Definition v8-isolate.h:326
static bool created
Definition c-api.cc:330
std::unique_ptr< v8::Platform > platform
Definition c-api.cc:332
ExportTypeImpl(Name &name, own< ExternType > &type)
Definition c-api.cc:916
own< ExternType > type
Definition c-api.cc:914
virtual ~ExternTypeImpl()=default
ExternTypeImpl(ExternKind kind)
Definition c-api.cc:640
ExternKind kind
Definition c-api.cc:638
static i::Address v8_callback(i::Address host_data_foreign, i::Address argv)
Definition c-api.cc:1884
FuncData(Store *store, const FuncType *type, Kind kind)
Definition c-api.cc:1494
Store * store
Definition c-api.cc:1484
Func::callback callback
Definition c-api.cc:1488
enum wasm::FuncData::Kind kind
Func::callback_with_env callback_with_env
Definition c-api.cc:1489
own< FuncType > type
Definition c-api.cc:1485
static constexpr i::ExternalPointerTag kManagedTag
Definition c-api.cc:1482
void(* finalizer)(void *)
Definition c-api.cc:1491
FuncTypeImpl(ownvec< ValType > &params, ownvec< ValType > &results)
Definition c-api.cc:674
ownvec< ValType > params
Definition c-api.cc:671
ownvec< ValType > results
Definition c-api.cc:672
~GlobalTypeImpl() override=default
Mutability mutability
Definition c-api.cc:723
GlobalTypeImpl(own< ValType > &content, Mutability mutability)
Definition c-api.cc:725
own< ValType > content
Definition c-api.cc:722
ImportTypeImpl(Name &module, Name &name, own< ExternType > &type)
Definition c-api.cc:873
own< ExternType > type
Definition c-api.cc:871
void(* finalizer)(void *)
Definition c-api.cc:497
static constexpr i::ExternalPointerTag kManagedTag
Definition c-api.cc:487
ManagedData(void *info, void(*finalizer)(void *))
Definition c-api.cc:489
MemoryTypeImpl(Limits limits)
Definition c-api.cc:828
~MemoryTypeImpl() override=default
own< ValType > element
Definition c-api.cc:774
~TableTypeImpl() override=default
TableTypeImpl(own< ValType > &element, Limits limits)
Definition c-api.cc:777
ValTypeImpl(ValKind kind)
Definition c-api.cc:586
RefImpl< Instance, i::WasmInstanceObject > type
Definition c-api.cc:2341
RefImpl< Module, i::WasmModuleObject > type
Definition c-api.cc:1207
void(* finalizer)(void *)
Definition c-api.cc:3274
wasm_func_callback_with_env_t callback
Definition c-api.cc:3272
std::unique_ptr< ValueMirror > key
#define FUNC
Definition value-type.h:156
wasm::ValueType type