Line data Source code
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 : #include "src/wasm/module-instantiate.h"
6 :
7 : #include "src/asmjs/asm-js.h"
8 : #include "src/conversions-inl.h"
9 : #include "src/property-descriptor.h"
10 : #include "src/utils.h"
11 : #include "src/wasm/js-to-wasm-wrapper-cache-inl.h"
12 : #include "src/wasm/module-compiler.h"
13 : #include "src/wasm/wasm-import-wrapper-cache-inl.h"
14 : #include "src/wasm/wasm-module.h"
15 : #include "src/wasm/wasm-objects-inl.h"
16 :
17 : #define TRACE(...) \
18 : do { \
19 : if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
20 : } while (false)
21 :
22 : namespace v8 {
23 : namespace internal {
24 : namespace wasm {
25 :
26 : namespace {
27 : byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
28 8414 : return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
29 : }
30 :
31 5766 : uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance,
32 : const WasmInitExpr& expr) {
33 5766 : switch (expr.kind) {
34 : case WasmInitExpr::kI32Const:
35 4350 : return expr.val.i32_const;
36 : case WasmInitExpr::kGlobalIndex: {
37 : uint32_t offset =
38 4248 : instance->module()->globals[expr.val.global_index].offset;
39 : auto raw_addr =
40 : reinterpret_cast<Address>(
41 1416 : instance->untagged_globals_buffer()->backing_store()) +
42 1416 : offset;
43 : return ReadLittleEndianValue<uint32_t>(raw_addr);
44 : }
45 : default:
46 0 : UNREACHABLE();
47 : }
48 : }
49 : } // namespace
50 :
51 : // A helper class to simplify instantiating a module from a module object.
52 : // It closes over the {Isolate}, the {ErrorThrower}, etc.
53 273184 : class InstanceBuilder {
54 : public:
55 : InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
56 : Handle<WasmModuleObject> module_object,
57 : MaybeHandle<JSReceiver> ffi,
58 : MaybeHandle<JSArrayBuffer> memory);
59 :
60 : // Build an instance, in all of its glory.
61 : MaybeHandle<WasmInstanceObject> Build();
62 : // Run the start function, if any.
63 : bool ExecuteStartFunction();
64 :
65 : private:
66 : // A pre-evaluated value to use in import binding.
67 : struct SanitizedImport {
68 : Handle<String> module_name;
69 : Handle<String> import_name;
70 : Handle<Object> value;
71 : };
72 :
73 : Isolate* isolate_;
74 : const WasmFeatures enabled_;
75 : const WasmModule* const module_;
76 : ErrorThrower* thrower_;
77 : Handle<WasmModuleObject> module_object_;
78 : MaybeHandle<JSReceiver> ffi_;
79 : MaybeHandle<JSArrayBuffer> memory_;
80 : Handle<JSArrayBuffer> untagged_globals_;
81 : Handle<FixedArray> tagged_globals_;
82 : std::vector<Handle<WasmExceptionObject>> exception_wrappers_;
83 : Handle<WasmExportedFunction> start_function_;
84 : JSToWasmWrapperCache js_to_wasm_cache_;
85 : std::vector<SanitizedImport> sanitized_imports_;
86 :
87 : UseTrapHandler use_trap_handler() const {
88 515723 : return module_object_->native_module()->use_trap_handler() ? kUseTrapHandler
89 257861 : : kNoTrapHandler;
90 : }
91 :
92 : // Helper routines to print out errors with imports.
93 : #define ERROR_THROWER_WITH_MESSAGE(TYPE) \
94 : void Report##TYPE(const char* error, uint32_t index, \
95 : Handle<String> module_name, Handle<String> import_name) { \
96 : thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s", \
97 : index, module_name->ToCString().get(), \
98 : import_name->ToCString().get(), error); \
99 : } \
100 : \
101 : MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index, \
102 : Handle<String> module_name) { \
103 : thrower_->TYPE("Import #%d module=\"%s\" error: %s", index, \
104 : module_name->ToCString().get(), error); \
105 : return MaybeHandle<Object>(); \
106 : }
107 :
108 10806 : ERROR_THROWER_WITH_MESSAGE(LinkError)
109 1504 : ERROR_THROWER_WITH_MESSAGE(TypeError)
110 :
111 : #undef ERROR_THROWER_WITH_MESSAGE
112 :
113 : // Look up an import value in the {ffi_} object.
114 : MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
115 : Handle<String> import_name);
116 :
117 : // Look up an import value in the {ffi_} object specifically for linking an
118 : // asm.js module. This only performs non-observable lookups, which allows
119 : // falling back to JavaScript proper (and hence re-executing all lookups) if
120 : // module instantiation fails.
121 : MaybeHandle<Object> LookupImportAsm(uint32_t index,
122 : Handle<String> import_name);
123 :
124 : // Load data segments into the memory.
125 : void LoadDataSegments(Handle<WasmInstanceObject> instance);
126 :
127 : void WriteGlobalValue(const WasmGlobal& global, double value);
128 : void WriteGlobalValue(const WasmGlobal& global, int64_t num);
129 : void WriteGlobalValue(const WasmGlobal& global,
130 : Handle<WasmGlobalObject> value);
131 :
132 : void WriteGlobalAnyRef(const WasmGlobal& global, Handle<Object> value);
133 :
134 : void SanitizeImports();
135 :
136 : // Find the imported memory buffer if there is one. This is used to see if we
137 : // need to recompile with bounds checks before creating the instance.
138 : MaybeHandle<JSArrayBuffer> FindImportedMemoryBuffer() const;
139 :
140 : // Processes a single imported function.
141 : bool ProcessImportedFunction(Handle<WasmInstanceObject> instance,
142 : int import_index, int func_index,
143 : Handle<String> module_name,
144 : Handle<String> import_name,
145 : Handle<Object> value);
146 :
147 : // Process a single imported table.
148 : bool ProcessImportedTable(Handle<WasmInstanceObject> instance,
149 : int import_index, int table_index,
150 : Handle<String> module_name,
151 : Handle<String> import_name, Handle<Object> value);
152 :
153 : // Process a single imported memory.
154 : bool ProcessImportedMemory(Handle<WasmInstanceObject> instance,
155 : int import_index, Handle<String> module_name,
156 : Handle<String> import_name, Handle<Object> value);
157 :
158 : // Process a single imported global.
159 : bool ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
160 : int import_index, int global_index,
161 : Handle<String> module_name,
162 : Handle<String> import_name, Handle<Object> value);
163 :
164 : // Process a single imported WasmGlobalObject.
165 : bool ProcessImportedWasmGlobalObject(Handle<WasmInstanceObject> instance,
166 : int import_index,
167 : Handle<String> module_name,
168 : Handle<String> import_name,
169 : const WasmGlobal& global,
170 : Handle<WasmGlobalObject> global_object);
171 :
172 : // Process the imports, including functions, tables, globals, and memory, in
173 : // order, loading them from the {ffi_} object. Returns the number of imported
174 : // functions.
175 : int ProcessImports(Handle<WasmInstanceObject> instance);
176 :
177 : template <typename T>
178 : T* GetRawGlobalPtr(const WasmGlobal& global);
179 :
180 : // Process initialization of globals.
181 : void InitGlobals();
182 :
183 : // Allocate memory for a module instance as a new JSArrayBuffer.
184 : Handle<JSArrayBuffer> AllocateMemory(uint32_t initial_pages,
185 : uint32_t maximum_pages);
186 :
187 : bool NeedsWrappers() const;
188 :
189 : // Process the exports, creating wrappers for functions, tables, memories,
190 : // and globals.
191 : void ProcessExports(Handle<WasmInstanceObject> instance);
192 :
193 : void InitializeTables(Handle<WasmInstanceObject> instance);
194 :
195 : void LoadTableSegments(Handle<WasmInstanceObject> instance);
196 :
197 : // Creates new exception tags for all exceptions. Note that some tags might
198 : // already exist if they were imported, those tags will be re-used.
199 : void InitializeExceptions(Handle<WasmInstanceObject> instance);
200 : };
201 :
202 136589 : MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
203 : Isolate* isolate, ErrorThrower* thrower,
204 : Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
205 : MaybeHandle<JSArrayBuffer> memory) {
206 273179 : InstanceBuilder builder(isolate, thrower, module_object, imports, memory);
207 136595 : auto instance = builder.Build();
208 136589 : if (!instance.is_null() && builder.ExecuteStartFunction()) {
209 133774 : return instance;
210 : }
211 : DCHECK(isolate->has_pending_exception() || thrower->error());
212 2816 : return {};
213 : }
214 :
215 136589 : InstanceBuilder::InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
216 : Handle<WasmModuleObject> module_object,
217 : MaybeHandle<JSReceiver> ffi,
218 : MaybeHandle<JSArrayBuffer> memory)
219 : : isolate_(isolate),
220 273178 : enabled_(module_object->native_module()->enabled_features()),
221 273180 : module_(module_object->module()),
222 : thrower_(thrower),
223 : module_object_(module_object),
224 : ffi_(ffi),
225 546360 : memory_(memory) {
226 136591 : sanitized_imports_.reserve(module_->import_table.size());
227 136595 : }
228 :
229 : // Build an instance, in all of its glory.
230 136591 : MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
231 409774 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "InstanceBuilder::Build");
232 : // Check that an imports argument was provided, if the module requires it.
233 : // No point in continuing otherwise.
234 258595 : if (!module_->import_table.empty() && ffi_.is_null()) {
235 93 : thrower_->TypeError(
236 93 : "Imports argument must be present and must be an object");
237 93 : return {};
238 : }
239 :
240 136498 : SanitizeImports();
241 136499 : if (thrower_->error()) return {};
242 :
243 : // From here on, we expect the build pipeline to run without exiting to JS.
244 272208 : DisallowJavascriptExecution no_js(isolate_);
245 : // Record build time into correct bucket, then build instance.
246 272208 : TimedHistogramScope wasm_instantiate_module_time_scope(SELECT_WASM_COUNTER(
247 136104 : isolate_->counters(), module_->origin, wasm_instantiate, module_time));
248 :
249 : //--------------------------------------------------------------------------
250 : // Allocate the memory array buffer.
251 : //--------------------------------------------------------------------------
252 : // We allocate the memory buffer before cloning or reusing the compiled module
253 : // so we will know whether we need to recompile with bounds checks.
254 136108 : uint32_t initial_pages = module_->initial_pages;
255 140964 : auto initial_pages_counter = SELECT_WASM_COUNTER(
256 : isolate_->counters(), module_->origin, wasm, min_mem_pages_count);
257 136108 : initial_pages_counter->AddSample(initial_pages);
258 136108 : if (module_->has_maximum_pages) {
259 : DCHECK_EQ(kWasmOrigin, module_->origin);
260 : auto max_pages_counter =
261 3767 : isolate_->counters()->wasm_wasm_max_mem_pages_count();
262 3767 : max_pages_counter->AddSample(module_->maximum_pages);
263 : }
264 : // Asm.js has memory_ already set at this point, so we don't want to
265 : // overwrite it.
266 136108 : if (memory_.is_null()) {
267 134868 : memory_ = FindImportedMemoryBuffer();
268 : }
269 136108 : if (!memory_.is_null()) {
270 : // Set externally passed ArrayBuffer non detachable.
271 : Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
272 : memory->set_is_detachable(false);
273 :
274 : DCHECK_IMPLIES(use_trap_handler(), module_->origin == kAsmJsOrigin ||
275 : memory->is_wasm_memory() ||
276 : memory->backing_store() == nullptr);
277 257097 : } else if (initial_pages > 0 || use_trap_handler()) {
278 : // We need to unconditionally create a guard region if using trap handlers,
279 : // even when the size is zero to prevent null-dereference issues
280 : // (e.g. https://crbug.com/769637).
281 : // Allocate memory if the initial size is more than 0 pages.
282 130417 : memory_ = AllocateMemory(initial_pages, module_->maximum_pages);
283 130417 : if (memory_.is_null()) {
284 : // failed to allocate memory
285 : DCHECK(isolate_->has_pending_exception() || thrower_->error());
286 16 : return {};
287 : }
288 : }
289 :
290 : //--------------------------------------------------------------------------
291 : // Recompile module if using trap handlers but could not get guarded memory
292 : //--------------------------------------------------------------------------
293 267327 : if (module_->origin == kWasmOrigin && use_trap_handler()) {
294 : // Make sure the memory has suitable guard regions.
295 : WasmMemoryTracker* const memory_tracker =
296 131183 : isolate_->wasm_engine()->memory_tracker();
297 :
298 131183 : if (!memory_tracker->HasFullGuardRegions(
299 : memory_.ToHandleChecked()->backing_store())) {
300 38 : if (!FLAG_wasm_trap_handler_fallback) {
301 0 : thrower_->LinkError(
302 : "Provided memory is lacking guard regions but fallback was "
303 0 : "disabled.");
304 0 : return {};
305 : }
306 :
307 : TRACE("Recompiling module without bounds checks\n");
308 76 : ErrorThrower thrower(isolate_, "recompile");
309 38 : auto native_module = module_object_->native_module();
310 38 : CompileNativeModuleWithExplicitBoundsChecks(isolate_, &thrower, module_,
311 38 : native_module);
312 38 : if (thrower.error()) {
313 0 : return {};
314 : }
315 : DCHECK(!native_module->use_trap_handler());
316 : }
317 : }
318 :
319 : //--------------------------------------------------------------------------
320 : // Create the WebAssembly.Instance object.
321 : //--------------------------------------------------------------------------
322 136091 : NativeModule* native_module = module_object_->native_module();
323 : TRACE("New module instantiation for %p\n", native_module);
324 : Handle<WasmInstanceObject> instance =
325 136092 : WasmInstanceObject::New(isolate_, module_object_);
326 272177 : NativeModuleModificationScope native_modification_scope(native_module);
327 :
328 : //--------------------------------------------------------------------------
329 : // Set up the globals for the new instance.
330 : //--------------------------------------------------------------------------
331 136086 : uint32_t untagged_globals_buffer_size = module_->untagged_globals_buffer_size;
332 136086 : if (untagged_globals_buffer_size > 0) {
333 6526 : void* backing_store = isolate_->array_buffer_allocator()->Allocate(
334 6526 : untagged_globals_buffer_size);
335 3263 : if (backing_store == nullptr) {
336 0 : thrower_->RangeError("Out of memory: wasm globals");
337 0 : return {};
338 : }
339 3263 : untagged_globals_ = isolate_->factory()->NewJSArrayBuffer(
340 3263 : SharedFlag::kNotShared, AllocationType::kOld);
341 : constexpr bool is_external = false;
342 : constexpr bool is_wasm_memory = false;
343 3263 : JSArrayBuffer::Setup(untagged_globals_, isolate_, is_external,
344 : backing_store, untagged_globals_buffer_size,
345 3263 : SharedFlag::kNotShared, is_wasm_memory);
346 3263 : if (untagged_globals_.is_null()) {
347 0 : thrower_->RangeError("Out of memory: wasm globals");
348 0 : return {};
349 : }
350 : instance->set_globals_start(
351 : reinterpret_cast<byte*>(untagged_globals_->backing_store()));
352 3263 : instance->set_untagged_globals_buffer(*untagged_globals_);
353 : }
354 :
355 136086 : uint32_t tagged_globals_buffer_size = module_->tagged_globals_buffer_size;
356 136086 : if (tagged_globals_buffer_size > 0) {
357 192 : tagged_globals_ = isolate_->factory()->NewFixedArray(
358 384 : static_cast<int>(tagged_globals_buffer_size));
359 192 : instance->set_tagged_globals_buffer(*tagged_globals_);
360 : }
361 :
362 : //--------------------------------------------------------------------------
363 : // Set up the array of references to imported globals' array buffers.
364 : //--------------------------------------------------------------------------
365 136086 : if (module_->num_imported_mutable_globals > 0) {
366 : // TODO(binji): This allocates one slot for each mutable global, which is
367 : // more than required if multiple globals are imported from the same
368 : // module.
369 208 : Handle<FixedArray> buffers_array = isolate_->factory()->NewFixedArray(
370 416 : module_->num_imported_mutable_globals, AllocationType::kOld);
371 208 : instance->set_imported_mutable_globals_buffers(*buffers_array);
372 : }
373 :
374 : //--------------------------------------------------------------------------
375 : // Set up the exception table used for exception tag checks.
376 : //--------------------------------------------------------------------------
377 272172 : int exceptions_count = static_cast<int>(module_->exceptions.size());
378 136086 : if (exceptions_count > 0) {
379 408 : Handle<FixedArray> exception_table = isolate_->factory()->NewFixedArray(
380 408 : exceptions_count, AllocationType::kOld);
381 408 : instance->set_exceptions_table(*exception_table);
382 408 : exception_wrappers_.resize(exceptions_count);
383 : }
384 :
385 : //--------------------------------------------------------------------------
386 : // Set up table storage space.
387 : //--------------------------------------------------------------------------
388 272172 : int table_count = static_cast<int>(module_->tables.size());
389 136086 : Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count);
390 137487 : for (int i = module_->num_imported_tables; i < table_count; i++) {
391 1401 : const WasmTable& table = module_->tables[i];
392 : Handle<WasmTableObject> table_obj = WasmTableObject::New(
393 2802 : isolate_, table.type, table.initial_size, table.has_maximum_size,
394 4203 : table.maximum_size, nullptr);
395 2802 : tables->set(i, *table_obj);
396 : }
397 136086 : instance->set_tables(*tables);
398 :
399 : //--------------------------------------------------------------------------
400 : // Process the imports for the module.
401 : //--------------------------------------------------------------------------
402 136091 : int num_imported_functions = ProcessImports(instance);
403 136089 : if (num_imported_functions < 0) return {};
404 :
405 : //--------------------------------------------------------------------------
406 : // Process the initialization for the module's globals.
407 : //--------------------------------------------------------------------------
408 134108 : InitGlobals();
409 :
410 : //--------------------------------------------------------------------------
411 : // Initialize the indirect tables.
412 : //--------------------------------------------------------------------------
413 134109 : if (table_count > 0) {
414 2393 : InitializeTables(instance);
415 : }
416 :
417 : //--------------------------------------------------------------------------
418 : // Initialize the exceptions table.
419 : //--------------------------------------------------------------------------
420 134105 : if (exceptions_count > 0) {
421 368 : InitializeExceptions(instance);
422 : }
423 :
424 : //--------------------------------------------------------------------------
425 : // Create the WebAssembly.Memory object.
426 : //--------------------------------------------------------------------------
427 134105 : if (module_->has_memory) {
428 13544 : if (!instance->has_memory_object()) {
429 : // No memory object exists. Create one.
430 : Handle<WasmMemoryObject> memory_object = WasmMemoryObject::New(
431 : isolate_, memory_,
432 9247 : module_->maximum_pages != 0 ? module_->maximum_pages : -1);
433 9248 : instance->set_memory_object(*memory_object);
434 : }
435 :
436 : // Add the instance object to the list of instances for this memory.
437 13545 : Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate_);
438 13543 : WasmMemoryObject::AddInstance(isolate_, memory_object, instance);
439 :
440 13548 : if (!memory_.is_null()) {
441 : // Double-check the {memory} array buffer matches the instance.
442 : Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
443 13536 : CHECK_EQ(instance->memory_size(), memory->byte_length());
444 13536 : CHECK_EQ(instance->memory_start(), memory->backing_store());
445 : }
446 : }
447 :
448 : //--------------------------------------------------------------------------
449 : // Check that indirect function table segments are within bounds.
450 : //--------------------------------------------------------------------------
451 134109 : for (const WasmElemSegment& elem_segment : module_->elem_segments) {
452 2169 : if (!elem_segment.active) continue;
453 : DCHECK_LT(elem_segment.table_index, table_count);
454 2129 : uint32_t base = EvalUint32InitExpr(instance, elem_segment.offset);
455 : // Because of imported tables, {table_size} has to come from the table
456 : // object itself.
457 : auto table_object = handle(WasmTableObject::cast(instance->tables()->get(
458 2129 : elem_segment.table_index)),
459 4258 : isolate_);
460 2129 : size_t table_size = table_object->elements()->length();
461 4258 : if (!IsInBounds(base, elem_segment.entries.size(), table_size)) {
462 120 : thrower_->LinkError("table initializer is out of bounds");
463 120 : return {};
464 : }
465 : }
466 :
467 : //--------------------------------------------------------------------------
468 : // Check that memory segments are within bounds.
469 : //--------------------------------------------------------------------------
470 133989 : for (const WasmDataSegment& seg : module_->data_segments) {
471 1004 : if (!seg.active) continue;
472 964 : uint32_t base = EvalUint32InitExpr(instance, seg.dest_addr);
473 1928 : if (!IsInBounds(base, seg.source.length(), instance->memory_size())) {
474 144 : thrower_->LinkError("data segment is out of bounds");
475 144 : return {};
476 : }
477 : }
478 :
479 : //--------------------------------------------------------------------------
480 : // Set up the exports object for the new instance.
481 : //--------------------------------------------------------------------------
482 133845 : ProcessExports(instance);
483 133845 : if (thrower_->error()) return {};
484 :
485 : //--------------------------------------------------------------------------
486 : // Initialize the indirect function tables.
487 : //--------------------------------------------------------------------------
488 133845 : if (table_count > 0) {
489 2265 : LoadTableSegments(instance);
490 : }
491 :
492 : //--------------------------------------------------------------------------
493 : // Initialize the memory by loading data segments.
494 : //--------------------------------------------------------------------------
495 267690 : if (module_->data_segments.size() > 0) {
496 620 : LoadDataSegments(instance);
497 : }
498 :
499 : //--------------------------------------------------------------------------
500 : // Debugging support.
501 : //--------------------------------------------------------------------------
502 : // Set all breakpoints that were set on the shared module.
503 133845 : WasmModuleObject::SetBreakpointsOnNewInstance(module_object_, instance);
504 :
505 : //--------------------------------------------------------------------------
506 : // Create a wrapper for the start function.
507 : //--------------------------------------------------------------------------
508 133841 : if (module_->start_function_index >= 0) {
509 : int start_index = module_->start_function_index;
510 5019 : auto& function = module_->functions[start_index];
511 : Handle<Code> wrapper_code = js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
512 5019 : isolate_, function.sig, function.imported);
513 : // TODO(clemensh): Don't generate an exported function for the start
514 : // function. Use CWasmEntry instead.
515 : start_function_ = WasmExportedFunction::New(
516 : isolate_, instance, MaybeHandle<String>(), start_index,
517 5019 : static_cast<int>(function.sig->parameter_count()), wrapper_code);
518 : }
519 :
520 : DCHECK(!isolate_->has_pending_exception());
521 : TRACE("Successfully built instance for module %p\n",
522 : module_object_->native_module());
523 133841 : return instance;
524 : }
525 :
526 133842 : bool InstanceBuilder::ExecuteStartFunction() {
527 401526 : TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
528 : "InstanceBuilder::ExecuteStartFunction");
529 133842 : if (start_function_.is_null()) return true; // No start function.
530 :
531 5019 : HandleScope scope(isolate_);
532 : // Call the JS function.
533 5019 : Handle<Object> undefined = isolate_->factory()->undefined_value();
534 : MaybeHandle<Object> retval =
535 5019 : Execution::Call(isolate_, start_function_, undefined, 0, nullptr);
536 :
537 5019 : if (retval.is_null()) {
538 : DCHECK(isolate_->has_pending_exception());
539 : return false;
540 : }
541 4951 : return true;
542 : }
543 :
544 : // Look up an import value in the {ffi_} object.
545 123299 : MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
546 : Handle<String> module_name,
547 :
548 : Handle<String> import_name) {
549 : // We pre-validated in the js-api layer that the ffi object is present, and
550 : // a JSObject, if the module has imports.
551 : DCHECK(!ffi_.is_null());
552 : // Look up the module first.
553 : MaybeHandle<Object> result = Object::GetPropertyOrElement(
554 123299 : isolate_, ffi_.ToHandleChecked(), module_name);
555 123297 : if (result.is_null()) {
556 16 : return ReportTypeError("module not found", index, module_name);
557 : }
558 :
559 : Handle<Object> module = result.ToHandleChecked();
560 :
561 : // Look up the value in the module.
562 123281 : if (!module->IsJSReceiver()) {
563 : return ReportTypeError("module is not an object or function", index,
564 360 : module_name);
565 : }
566 :
567 122921 : result = Object::GetPropertyOrElement(isolate_, module, import_name);
568 122925 : if (result.is_null()) {
569 0 : ReportLinkError("import not found", index, module_name, import_name);
570 0 : return MaybeHandle<JSFunction>();
571 : }
572 :
573 122925 : return result;
574 : }
575 :
576 : // Look up an import value in the {ffi_} object specifically for linking an
577 : // asm.js module. This only performs non-observable lookups, which allows
578 : // falling back to JavaScript proper (and hence re-executing all lookups) if
579 : // module instantiation fails.
580 4779 : MaybeHandle<Object> InstanceBuilder::LookupImportAsm(
581 : uint32_t index, Handle<String> import_name) {
582 : // Check that a foreign function interface object was provided.
583 4779 : if (ffi_.is_null()) {
584 0 : return ReportLinkError("missing imports object", index, import_name);
585 : }
586 :
587 : // Perform lookup of the given {import_name} without causing any observable
588 : // side-effect. We only accept accesses that resolve to data properties,
589 : // which is indicated by the asm.js spec in section 7 ("Linking") as well.
590 : Handle<Object> result;
591 : LookupIterator it = LookupIterator::PropertyOrElement(
592 4779 : isolate_, ffi_.ToHandleChecked(), import_name);
593 : switch (it.state()) {
594 : case LookupIterator::ACCESS_CHECK:
595 : case LookupIterator::INTEGER_INDEXED_EXOTIC:
596 : case LookupIterator::INTERCEPTOR:
597 : case LookupIterator::JSPROXY:
598 : case LookupIterator::ACCESSOR:
599 : case LookupIterator::TRANSITION:
600 18 : return ReportLinkError("not a data property", index, import_name);
601 : case LookupIterator::NOT_FOUND:
602 : // Accepting missing properties as undefined does not cause any
603 : // observable difference from JavaScript semantics, we are lenient.
604 72 : result = isolate_->factory()->undefined_value();
605 72 : break;
606 : case LookupIterator::DATA:
607 4689 : result = it.GetDataValue();
608 4689 : break;
609 : }
610 :
611 4761 : return result;
612 : }
613 :
614 : // Load data segments into the memory.
615 620 : void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
616 : Vector<const uint8_t> wire_bytes =
617 1240 : module_object_->native_module()->wire_bytes();
618 620 : for (const WasmDataSegment& segment : module_->data_segments) {
619 : uint32_t source_size = segment.source.length();
620 : // Segments of size == 0 are just nops.
621 852 : if (source_size == 0) continue;
622 : // Passive segments are not copied during instantiation.
623 720 : if (!segment.active) continue;
624 680 : uint32_t dest_offset = EvalUint32InitExpr(instance, segment.dest_addr);
625 : DCHECK(IsInBounds(dest_offset, source_size, instance->memory_size()));
626 680 : byte* dest = instance->memory_start() + dest_offset;
627 680 : const byte* src = wire_bytes.start() + segment.source.offset();
628 680 : memcpy(dest, src, source_size);
629 : }
630 620 : }
631 :
632 2219 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
633 : TRACE("init [globals_start=%p + %u] = %lf, type = %s\n",
634 : reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
635 : global.offset, num, ValueTypes::TypeName(global.type));
636 2219 : switch (global.type) {
637 : case kWasmI32:
638 1807 : WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
639 : DoubleToInt32(num));
640 : break;
641 : case kWasmI64:
642 : // The Wasm-BigInt proposal currently says that i64 globals may
643 : // only be initialized with BigInts. See:
644 : // https://github.com/WebAssembly/JS-BigInt-integration/issues/12
645 0 : UNREACHABLE();
646 : break;
647 : case kWasmF32:
648 40 : WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
649 : DoubleToFloat32(num));
650 : break;
651 : case kWasmF64:
652 372 : WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
653 : break;
654 : default:
655 0 : UNREACHABLE();
656 : }
657 2219 : }
658 :
659 24 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, int64_t num) {
660 : TRACE("init [globals_start=%p + %u] = %" PRId64 ", type = %s\n",
661 : reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
662 : global.offset, num, ValueTypes::TypeName(global.type));
663 : DCHECK_EQ(kWasmI64, global.type);
664 24 : WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
665 24 : }
666 :
667 48 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
668 : Handle<WasmGlobalObject> value) {
669 : TRACE("init [globals_start=%p + %u] = ",
670 : reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
671 : global.offset);
672 48 : switch (global.type) {
673 : case kWasmI32: {
674 64 : int32_t num = value->GetI32();
675 32 : WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global), num);
676 : TRACE("%d", num);
677 : break;
678 : }
679 : case kWasmI64: {
680 16 : int64_t num = value->GetI64();
681 8 : WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
682 : TRACE("%" PRId64, num);
683 : break;
684 : }
685 : case kWasmF32: {
686 16 : float num = value->GetF32();
687 8 : WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global), num);
688 : TRACE("%f", num);
689 : break;
690 : }
691 : case kWasmF64: {
692 0 : double num = value->GetF64();
693 0 : WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
694 : TRACE("%lf", num);
695 : break;
696 : }
697 : default:
698 0 : UNREACHABLE();
699 : }
700 : TRACE(", type = %s (from WebAssembly.Global)\n",
701 : ValueTypes::TypeName(global.type));
702 48 : }
703 :
704 0 : void InstanceBuilder::WriteGlobalAnyRef(const WasmGlobal& global,
705 : Handle<Object> value) {
706 144 : tagged_globals_->set(global.offset, *value, UPDATE_WRITE_BARRIER);
707 0 : }
708 :
709 136496 : void InstanceBuilder::SanitizeImports() {
710 : Vector<const uint8_t> wire_bytes =
711 272993 : module_object_->native_module()->wire_bytes();
712 656049 : for (size_t index = 0; index < module_->import_table.size(); ++index) {
713 : const WasmImport& import = module_->import_table[index];
714 :
715 : Handle<String> module_name;
716 : MaybeHandle<String> maybe_module_name =
717 : WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
718 128077 : import.module_name);
719 128079 : if (!maybe_module_name.ToHandle(&module_name)) {
720 0 : thrower_->LinkError("Could not resolve module name for import %zu",
721 0 : index);
722 0 : return;
723 : }
724 :
725 : Handle<String> import_name;
726 : MaybeHandle<String> maybe_import_name =
727 : WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
728 128079 : import.field_name);
729 128080 : if (!maybe_import_name.ToHandle(&import_name)) {
730 0 : thrower_->LinkError("Could not resolve import name for import %zu",
731 0 : index);
732 0 : return;
733 : }
734 :
735 : int int_index = static_cast<int>(index);
736 : MaybeHandle<Object> result =
737 128080 : module_->origin == kAsmJsOrigin
738 4779 : ? LookupImportAsm(int_index, import_name)
739 132859 : : LookupImport(int_index, module_name, import_name);
740 128080 : if (thrower_->error()) {
741 394 : thrower_->LinkError("Could not find value for import %zu", index);
742 394 : return;
743 : }
744 : Handle<Object> value = result.ToHandleChecked();
745 255371 : sanitized_imports_.push_back({module_name, import_name, value});
746 : }
747 : }
748 :
749 134868 : MaybeHandle<JSArrayBuffer> InstanceBuilder::FindImportedMemoryBuffer() const {
750 : DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
751 626163 : for (size_t index = 0; index < module_->import_table.size(); index++) {
752 : const WasmImport& import = module_->import_table[index];
753 :
754 123622 : if (import.kind == kExternalMemory) {
755 : const auto& value = sanitized_imports_[index].value;
756 4813 : if (!value->IsWasmMemoryObject()) {
757 416 : return {};
758 : }
759 : auto memory = Handle<WasmMemoryObject>::cast(value);
760 4397 : Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
761 4397 : return buffer;
762 : }
763 : }
764 130055 : return {};
765 : }
766 :
767 118081 : bool InstanceBuilder::ProcessImportedFunction(
768 : Handle<WasmInstanceObject> instance, int import_index, int func_index,
769 : Handle<String> module_name, Handle<String> import_name,
770 : Handle<Object> value) {
771 : // Function imports must be callable.
772 118081 : if (!value->IsCallable()) {
773 400 : ReportLinkError("function import requires a callable", import_index,
774 400 : module_name, import_name);
775 400 : return false;
776 : }
777 117681 : auto js_receiver = Handle<JSReceiver>::cast(value);
778 235362 : FunctionSig* expected_sig = module_->functions[func_index].sig;
779 117681 : auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig,
780 235362 : enabled_.bigint);
781 117681 : switch (kind) {
782 : case compiler::WasmImportCallKind::kLinkError:
783 160 : ReportLinkError("imported function does not match the expected type",
784 160 : import_index, module_name, import_name);
785 160 : return false;
786 : case compiler::WasmImportCallKind::kWasmToWasm: {
787 : // The imported function is a WASM function from another instance.
788 : auto imported_function = Handle<WasmExportedFunction>::cast(value);
789 : Handle<WasmInstanceObject> imported_instance(
790 321288 : imported_function->instance(), isolate_);
791 : // The import reference is the instance object itself.
792 107096 : Address imported_target = imported_function->GetWasmCallTarget();
793 : ImportedFunctionEntry entry(instance, func_index);
794 107096 : entry.SetWasmToWasm(*imported_instance, imported_target);
795 : break;
796 : }
797 : default: {
798 : // The imported function is a callable.
799 10425 : NativeModule* native_module = instance->module_object()->native_module();
800 : WasmCode* wasm_code = native_module->import_wrapper_cache()->GetOrCompile(
801 20850 : isolate_->wasm_engine(), isolate_->counters(), kind, expected_sig);
802 : ImportedFunctionEntry entry(instance, func_index);
803 10425 : if (wasm_code->kind() == WasmCode::kWasmToJsWrapper) {
804 : // Wasm to JS wrappers are treated specially in the import table.
805 10201 : entry.SetWasmToJs(isolate_, js_receiver, wasm_code);
806 : } else {
807 : // Wasm math intrinsics are compiled as regular Wasm functions.
808 : DCHECK(kind >= compiler::WasmImportCallKind::kFirstMathIntrinsic &&
809 : kind <= compiler::WasmImportCallKind::kLastMathIntrinsic);
810 224 : entry.SetWasmToWasm(*instance, wasm_code->instruction_start());
811 : }
812 : break;
813 : }
814 : }
815 : return true;
816 : }
817 :
818 1536 : bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
819 : int import_index, int table_index,
820 : Handle<String> module_name,
821 : Handle<String> import_name,
822 : Handle<Object> value) {
823 1536 : if (!value->IsWasmTableObject()) {
824 344 : ReportLinkError("table import requires a WebAssembly.Table", import_index,
825 344 : module_name, import_name);
826 344 : return false;
827 : }
828 1192 : const WasmTable& table = module_->tables[table_index];
829 :
830 1192 : instance->tables()->set(table_index, *value);
831 : auto table_object = Handle<WasmTableObject>::cast(value);
832 :
833 : int imported_table_size = table_object->elements().length();
834 1192 : if (imported_table_size < static_cast<int>(table.initial_size)) {
835 40 : thrower_->LinkError("table import %d is smaller than initial %d, got %u",
836 40 : import_index, table.initial_size, imported_table_size);
837 40 : return false;
838 : }
839 :
840 1152 : if (table.has_maximum_size) {
841 1728 : if (table_object->maximum_length()->IsUndefined(isolate_)) {
842 16 : thrower_->LinkError("table import %d has no maximum length, expected %d",
843 32 : import_index, table.maximum_size);
844 16 : return false;
845 : }
846 848 : int64_t imported_maximum_size = table_object->maximum_length()->Number();
847 848 : if (imported_maximum_size < 0) {
848 0 : thrower_->LinkError("table import %d has no maximum length, expected %d",
849 0 : import_index, table.maximum_size);
850 0 : return false;
851 : }
852 848 : if (imported_maximum_size > table.maximum_size) {
853 48 : thrower_->LinkError("table import %d has a larger maximum size %" PRIx64
854 : " than the module's declared maximum %u",
855 : import_index, imported_maximum_size,
856 48 : table.maximum_size);
857 48 : return false;
858 : }
859 : }
860 :
861 : // Allocate a new dispatch table.
862 1088 : if (!instance->has_indirect_function_table()) {
863 1064 : WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
864 1064 : instance, imported_table_size);
865 : }
866 : // Initialize the dispatch table with the (foreign) JS functions
867 : // that are already in the table.
868 4220576 : for (int i = 0; i < imported_table_size; ++i) {
869 : bool is_valid;
870 : bool is_null;
871 2109744 : MaybeHandle<WasmInstanceObject> maybe_target_instance;
872 : int function_index;
873 2109744 : WasmTableObject::GetFunctionTableEntry(isolate_, table_object, i, &is_valid,
874 : &is_null, &maybe_target_instance,
875 2109744 : &function_index);
876 2109744 : if (!is_valid) {
877 0 : thrower_->LinkError("table import %d[%d] is not a wasm function",
878 0 : import_index, i);
879 0 : return false;
880 : }
881 4216664 : if (is_null) continue;
882 :
883 : Handle<WasmInstanceObject> target_instance =
884 : maybe_target_instance.ToHandleChecked();
885 5648 : FunctionSig* sig = target_instance->module_object()
886 : ->module()
887 2824 : ->functions[function_index]
888 2824 : .sig;
889 :
890 : // Look up the signature's canonical id. If there is no canonical
891 : // id, then the signature does not appear at all in this module,
892 : // so putting {-1} in the table will cause checks to always fail.
893 : IndirectFunctionTableEntry(instance, i)
894 5648 : .Set(module_->signature_map.Find(*sig), target_instance,
895 5648 : function_index);
896 : }
897 : return true;
898 : }
899 :
900 4802 : bool InstanceBuilder::ProcessImportedMemory(Handle<WasmInstanceObject> instance,
901 : int import_index,
902 : Handle<String> module_name,
903 : Handle<String> import_name,
904 : Handle<Object> value) {
905 : // Validation should have failed if more than one memory object was
906 : // provided.
907 : DCHECK(!instance->has_memory_object());
908 4802 : if (!value->IsWasmMemoryObject()) {
909 408 : ReportLinkError("memory import must be a WebAssembly.Memory object",
910 408 : import_index, module_name, import_name);
911 408 : return false;
912 : }
913 : auto memory = Handle<WasmMemoryObject>::cast(value);
914 4394 : instance->set_memory_object(*memory);
915 4396 : Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
916 : // memory_ should have already been assigned in Build().
917 : DCHECK_EQ(*memory_.ToHandleChecked(), *buffer);
918 : uint32_t imported_cur_pages =
919 4396 : static_cast<uint32_t>(buffer->byte_length() / kWasmPageSize);
920 4396 : if (imported_cur_pages < module_->initial_pages) {
921 24 : thrower_->LinkError("memory import %d is smaller than initial %u, got %u",
922 : import_index, module_->initial_pages,
923 24 : imported_cur_pages);
924 24 : return false;
925 : }
926 : int32_t imported_maximum_pages = memory->maximum_pages();
927 4372 : if (module_->has_maximum_pages) {
928 1459 : if (imported_maximum_pages < 0) {
929 8 : thrower_->LinkError(
930 : "memory import %d has no maximum limit, expected at most %u",
931 8 : import_index, imported_maximum_pages);
932 8 : return false;
933 : }
934 1451 : if (static_cast<uint32_t>(imported_maximum_pages) >
935 1451 : module_->maximum_pages) {
936 40 : thrower_->LinkError(
937 : "memory import %d has a larger maximum size %u than the "
938 : "module's declared maximum %u",
939 40 : import_index, imported_maximum_pages, module_->maximum_pages);
940 40 : return false;
941 : }
942 : }
943 8648 : if (module_->has_shared_memory != buffer->is_shared()) {
944 16 : thrower_->LinkError(
945 : "mismatch in shared state of memory, declared = %d, imported = %d",
946 16 : module_->has_shared_memory, buffer->is_shared());
947 16 : return false;
948 : }
949 :
950 : return true;
951 : }
952 :
953 344 : bool InstanceBuilder::ProcessImportedWasmGlobalObject(
954 : Handle<WasmInstanceObject> instance, int import_index,
955 : Handle<String> module_name, Handle<String> import_name,
956 : const WasmGlobal& global, Handle<WasmGlobalObject> global_object) {
957 344 : if (global_object->type() != global.type) {
958 8 : ReportLinkError("imported global does not match the expected type",
959 8 : import_index, module_name, import_name);
960 8 : return false;
961 : }
962 336 : if (global_object->is_mutable() != global.mutability) {
963 32 : ReportLinkError("imported global does not match the expected mutability",
964 32 : import_index, module_name, import_name);
965 32 : return false;
966 : }
967 304 : if (global.mutability) {
968 : DCHECK_LT(global.index, module_->num_imported_mutable_globals);
969 : Handle<Object> buffer;
970 : Address address_or_offset;
971 256 : if (ValueTypes::IsReferenceType(global.type)) {
972 : static_assert(sizeof(global_object->offset()) <= sizeof(Address),
973 : "The offset into the globals buffer does not fit into "
974 : "the imported_mutable_globals array");
975 112 : buffer = handle(global_object->tagged_buffer(), isolate_);
976 : // For anyref globals we use a relative offset, not an absolute address.
977 112 : address_or_offset = static_cast<Address>(global_object->offset());
978 : } else {
979 144 : buffer = handle(global_object->untagged_buffer(), isolate_);
980 : // It is safe in this case to store the raw pointer to the buffer
981 : // since the backing store of the JSArrayBuffer will not be
982 : // relocated.
983 : address_or_offset = reinterpret_cast<Address>(raw_buffer_ptr(
984 144 : Handle<JSArrayBuffer>::cast(buffer), global_object->offset()));
985 : }
986 512 : instance->imported_mutable_globals_buffers()->set(global.index, *buffer);
987 256 : instance->imported_mutable_globals()[global.index] = address_or_offset;
988 : return true;
989 : }
990 :
991 48 : WriteGlobalValue(global, global_object);
992 48 : return true;
993 : }
994 :
995 3056 : bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
996 : int import_index, int global_index,
997 : Handle<String> module_name,
998 : Handle<String> import_name,
999 : Handle<Object> value) {
1000 : // Immutable global imports are converted to numbers and written into
1001 : // the {untagged_globals_} array buffer.
1002 : //
1003 : // Mutable global imports instead have their backing array buffers
1004 : // referenced by this instance, and store the address of the imported
1005 : // global in the {imported_mutable_globals_} array.
1006 3056 : const WasmGlobal& global = module_->globals[global_index];
1007 :
1008 : // The mutable-global proposal allows importing i64 values, but only if
1009 : // they are passed as a WebAssembly.Global object.
1010 : //
1011 : // However, the bigint proposal allows importing constant i64 values,
1012 : // as non WebAssembly.Global object.
1013 3104 : if (global.type == kWasmI64 && !enabled_.bigint &&
1014 : !value->IsWasmGlobalObject()) {
1015 32 : ReportLinkError("global import cannot have type i64", import_index,
1016 32 : module_name, import_name);
1017 32 : return false;
1018 : }
1019 3024 : if (module_->origin == kAsmJsOrigin) {
1020 : // Accepting {JSFunction} on top of just primitive values here is a
1021 : // workaround to support legacy asm.js code with broken binding. Note
1022 : // that using {NaN} (or Smi::kZero) here is what using the observable
1023 : // conversion via {ToPrimitive} would produce as well.
1024 : // TODO(mstarzinger): Still observable if Function.prototype.valueOf
1025 : // or friends are patched, we might need to check for that as well.
1026 1208 : if (value->IsJSFunction()) value = isolate_->factory()->nan_value();
1027 2407 : if (value->IsPrimitive() && !value->IsSymbol()) {
1028 1195 : if (global.type == kWasmI32) {
1029 855 : value = Object::ToInt32(isolate_, value).ToHandleChecked();
1030 : } else {
1031 680 : value = Object::ToNumber(isolate_, value).ToHandleChecked();
1032 : }
1033 : }
1034 : }
1035 :
1036 3024 : if (value->IsWasmGlobalObject()) {
1037 344 : auto global_object = Handle<WasmGlobalObject>::cast(value);
1038 : return ProcessImportedWasmGlobalObject(instance, import_index, module_name,
1039 344 : import_name, global, global_object);
1040 : }
1041 :
1042 2680 : if (global.mutability) {
1043 16 : ReportLinkError(
1044 : "imported mutable global must be a WebAssembly.Global object",
1045 16 : import_index, module_name, import_name);
1046 16 : return false;
1047 : }
1048 :
1049 5328 : if (ValueTypes::IsReferenceType(global.type)) {
1050 : // There shouldn't be any null-ref globals.
1051 : DCHECK_NE(ValueType::kWasmNullRef, global.type);
1052 80 : if (global.type == ValueType::kWasmAnyFunc) {
1053 64 : if (!value->IsNull(isolate_) &&
1054 16 : !WasmExportedFunction::IsWasmExportedFunction(*value)) {
1055 8 : ReportLinkError(
1056 : "imported anyfunc global must be null or an exported function",
1057 8 : import_index, module_name, import_name);
1058 8 : return false;
1059 : }
1060 : }
1061 : WriteGlobalAnyRef(global, value);
1062 72 : return true;
1063 : }
1064 :
1065 2584 : if (value->IsNumber() && global.type != kWasmI64) {
1066 2219 : WriteGlobalValue(global, value->Number());
1067 2219 : return true;
1068 : }
1069 :
1070 365 : if (enabled_.bigint && global.type == kWasmI64) {
1071 : Handle<BigInt> bigint;
1072 :
1073 48 : if (!BigInt::FromObject(isolate_, value).ToHandle(&bigint)) {
1074 : return false;
1075 : }
1076 24 : WriteGlobalValue(global, bigint->AsInt64());
1077 24 : return true;
1078 : }
1079 :
1080 341 : ReportLinkError("global import must be a number or WebAssembly.Global object",
1081 341 : import_index, module_name, import_name);
1082 341 : return false;
1083 : }
1084 :
1085 : // Process the imports, including functions, tables, globals, and memory, in
1086 : // order, loading them from the {ffi_} object. Returns the number of imported
1087 : // functions.
1088 136089 : int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
1089 : int num_imported_functions = 0;
1090 : int num_imported_tables = 0;
1091 :
1092 : DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
1093 272178 : int num_imports = static_cast<int>(module_->import_table.size());
1094 387257 : for (int index = 0; index < num_imports; ++index) {
1095 127561 : const WasmImport& import = module_->import_table[index];
1096 :
1097 127561 : Handle<String> module_name = sanitized_imports_[index].module_name;
1098 127561 : Handle<String> import_name = sanitized_imports_[index].import_name;
1099 127561 : Handle<Object> value = sanitized_imports_[index].value;
1100 :
1101 127561 : switch (import.kind) {
1102 : case kExternalFunction: {
1103 118081 : uint32_t func_index = import.index;
1104 : DCHECK_EQ(num_imported_functions, func_index);
1105 118081 : if (!ProcessImportedFunction(instance, index, func_index, module_name,
1106 : import_name, value)) {
1107 1981 : return -1;
1108 : }
1109 117521 : num_imported_functions++;
1110 117521 : break;
1111 : }
1112 : case kExternalTable: {
1113 1536 : uint32_t table_index = import.index;
1114 : DCHECK_EQ(table_index, num_imported_tables);
1115 1536 : if (!ProcessImportedTable(instance, index, table_index, module_name,
1116 : import_name, value)) {
1117 : return -1;
1118 : }
1119 : num_imported_tables++;
1120 : break;
1121 : }
1122 : case kExternalMemory: {
1123 4800 : if (!ProcessImportedMemory(instance, index, module_name, import_name,
1124 : value)) {
1125 : return -1;
1126 : }
1127 : break;
1128 : }
1129 : case kExternalGlobal: {
1130 3056 : if (!ProcessImportedGlobal(instance, index, import.index, module_name,
1131 : import_name, value)) {
1132 : return -1;
1133 : }
1134 : break;
1135 : }
1136 : case kExternalException: {
1137 88 : if (!value->IsWasmExceptionObject()) {
1138 32 : ReportLinkError("exception import requires a WebAssembly.Exception",
1139 32 : index, module_name, import_name);
1140 32 : return -1;
1141 : }
1142 : Handle<WasmExceptionObject> imported_exception =
1143 : Handle<WasmExceptionObject>::cast(value);
1144 56 : if (!imported_exception->IsSignatureEqual(
1145 112 : module_->exceptions[import.index].sig)) {
1146 8 : ReportLinkError("imported exception does not match the expected type",
1147 8 : index, module_name, import_name);
1148 8 : return -1;
1149 : }
1150 48 : Object exception_tag = imported_exception->exception_tag();
1151 : DCHECK(instance->exceptions_table()->get(import.index)->IsUndefined());
1152 96 : instance->exceptions_table()->set(import.index, exception_tag);
1153 96 : exception_wrappers_[import.index] = imported_exception;
1154 48 : break;
1155 : }
1156 : default:
1157 0 : UNREACHABLE();
1158 : break;
1159 : }
1160 : }
1161 : return num_imported_functions;
1162 : }
1163 :
1164 : template <typename T>
1165 8158 : T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) {
1166 16316 : return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset));
1167 : }
1168 :
1169 : // Process initialization of globals.
1170 134108 : void InstanceBuilder::InitGlobals() {
1171 134108 : for (auto global : module_->globals) {
1172 8774 : if (global.mutability && global.imported) {
1173 : continue;
1174 : }
1175 :
1176 8518 : switch (global.init.kind) {
1177 : case WasmInitExpr::kI32Const:
1178 4737 : WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
1179 : global.init.val.i32_const);
1180 : break;
1181 : case WasmInitExpr::kI64Const:
1182 88 : WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
1183 : global.init.val.i64_const);
1184 : break;
1185 : case WasmInitExpr::kF32Const:
1186 188 : WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
1187 : global.init.val.f32_const);
1188 : break;
1189 : case WasmInitExpr::kF64Const:
1190 854 : WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
1191 : global.init.val.f64_const);
1192 : break;
1193 : case WasmInitExpr::kRefNullConst:
1194 : DCHECK(enabled_.anyref || enabled_.eh);
1195 232 : if (global.imported) break; // We already initialized imported globals.
1196 :
1197 696 : tagged_globals_->set(global.offset,
1198 696 : ReadOnlyRoots(isolate_).null_value(),
1199 232 : SKIP_WRITE_BARRIER);
1200 232 : break;
1201 : case WasmInitExpr::kGlobalIndex: {
1202 56 : if (global.type == ValueType::kWasmAnyRef) {
1203 : DCHECK(enabled_.anyref);
1204 : int other_offset =
1205 0 : module_->globals[global.init.val.global_index].offset;
1206 :
1207 0 : tagged_globals_->set(global.offset,
1208 : tagged_globals_->get(other_offset),
1209 0 : SKIP_WRITE_BARRIER);
1210 : }
1211 : // Initialize with another global.
1212 : uint32_t new_offset = global.offset;
1213 : uint32_t old_offset =
1214 112 : module_->globals[global.init.val.global_index].offset;
1215 : TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
1216 56 : size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
1217 : ? sizeof(double)
1218 56 : : sizeof(int32_t);
1219 56 : memcpy(raw_buffer_ptr(untagged_globals_, new_offset),
1220 56 : raw_buffer_ptr(untagged_globals_, old_offset), size);
1221 56 : break;
1222 : }
1223 : case WasmInitExpr::kNone:
1224 : // Happens with imported globals.
1225 : break;
1226 : default:
1227 0 : UNREACHABLE();
1228 : break;
1229 : }
1230 : }
1231 134108 : }
1232 :
1233 : // Allocate memory for a module instance as a new JSArrayBuffer.
1234 130417 : Handle<JSArrayBuffer> InstanceBuilder::AllocateMemory(uint32_t initial_pages,
1235 : uint32_t maximum_pages) {
1236 130417 : if (initial_pages > max_mem_pages()) {
1237 16 : thrower_->RangeError("Out of memory: wasm memory too large");
1238 : return Handle<JSArrayBuffer>::null();
1239 : }
1240 130401 : const bool is_shared_memory = module_->has_shared_memory && enabled_.threads;
1241 : Handle<JSArrayBuffer> mem_buffer;
1242 130401 : if (is_shared_memory) {
1243 508 : if (!NewSharedArrayBuffer(isolate_, initial_pages * kWasmPageSize,
1244 254 : maximum_pages * kWasmPageSize)
1245 : .ToHandle(&mem_buffer)) {
1246 0 : thrower_->RangeError("Out of memory: wasm shared memory");
1247 : }
1248 : } else {
1249 260294 : if (!NewArrayBuffer(isolate_, initial_pages * kWasmPageSize)
1250 : .ToHandle(&mem_buffer)) {
1251 0 : thrower_->RangeError("Out of memory: wasm memory");
1252 : }
1253 : }
1254 130400 : return mem_buffer;
1255 : }
1256 :
1257 0 : bool InstanceBuilder::NeedsWrappers() const {
1258 133842 : if (module_->num_exported_functions > 0) return true;
1259 4304 : for (auto& table : module_->tables) {
1260 784 : if (table.type == kWasmAnyFunc) return true;
1261 : }
1262 : return false;
1263 : }
1264 :
1265 : // Process the exports, creating wrappers for functions, tables, memories,
1266 : // globals, and exceptions.
1267 133843 : void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
1268 : Handle<FixedArray> export_wrappers(module_object_->export_wrappers(),
1269 133843 : isolate_);
1270 133842 : if (NeedsWrappers()) {
1271 : // If an imported WebAssembly function gets exported, the exported function
1272 : // has to be identical to to imported function. Therefore we cache all
1273 : // imported WebAssembly functions in the instance.
1274 254973 : for (int index = 0, end = static_cast<int>(module_->import_table.size());
1275 254973 : index < end; ++index) {
1276 124647 : const WasmImport& import = module_->import_table[index];
1277 124647 : if (import.kind == kExternalFunction) {
1278 117241 : Handle<Object> value = sanitized_imports_[index].value;
1279 117241 : if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
1280 107056 : WasmInstanceObject::SetWasmExportedFunction(
1281 107056 : isolate_, instance, import.index,
1282 107056 : Handle<WasmExportedFunction>::cast(value));
1283 : }
1284 : }
1285 : }
1286 : }
1287 :
1288 : Handle<JSObject> exports_object;
1289 : bool is_asm_js = false;
1290 133843 : switch (module_->origin) {
1291 : case kWasmOrigin: {
1292 : // Create the "exports" object.
1293 129000 : exports_object = isolate_->factory()->NewJSObjectWithNullProto();
1294 129000 : break;
1295 : }
1296 : case kAsmJsOrigin: {
1297 : Handle<JSFunction> object_function = Handle<JSFunction>(
1298 14529 : isolate_->native_context()->object_function(), isolate_);
1299 4843 : exports_object = isolate_->factory()->NewJSObject(object_function);
1300 : is_asm_js = true;
1301 : break;
1302 : }
1303 : default:
1304 0 : UNREACHABLE();
1305 : }
1306 133843 : instance->set_exports_object(*exports_object);
1307 :
1308 : Handle<String> single_function_name =
1309 133845 : isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName);
1310 :
1311 : PropertyDescriptor desc;
1312 : desc.set_writable(is_asm_js);
1313 : desc.set_enumerable(true);
1314 : desc.set_configurable(is_asm_js);
1315 :
1316 : // Process each export in the export table.
1317 : int export_index = 0; // Index into {export_wrappers}.
1318 133851 : for (const WasmExport& exp : module_->export_table) {
1319 458520 : Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
1320 229262 : isolate_, module_object_, exp.name)
1321 : .ToHandleChecked();
1322 : Handle<JSObject> export_to;
1323 237496 : if (is_asm_js && exp.kind == kExternalFunction &&
1324 8238 : String::Equals(isolate_, name, single_function_name)) {
1325 : export_to = instance;
1326 : } else {
1327 : export_to = exports_object;
1328 : }
1329 :
1330 229258 : switch (exp.kind) {
1331 : case kExternalFunction: {
1332 : // Wrap and export the code as a JSFunction.
1333 : // TODO(wasm): reduce duplication with LoadElemSegment() further below
1334 226262 : const WasmFunction& function = module_->functions[exp.index];
1335 : MaybeHandle<WasmExportedFunction> wasm_exported_function =
1336 : WasmInstanceObject::GetWasmExportedFunction(isolate_, instance,
1337 226262 : exp.index);
1338 226264 : if (wasm_exported_function.is_null()) {
1339 : // Wrap the exported code as a JSFunction.
1340 : Handle<Code> export_code =
1341 451944 : export_wrappers->GetValueChecked<Code>(isolate_, export_index);
1342 225974 : MaybeHandle<String> func_name;
1343 225974 : if (is_asm_js) {
1344 : // For modules arising from asm.js, honor the names section.
1345 8218 : WireBytesRef func_name_ref = module_->LookupFunctionName(
1346 : ModuleWireBytes(module_object_->native_module()->wire_bytes()),
1347 24654 : function.func_index);
1348 16436 : func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
1349 8218 : isolate_, module_object_, func_name_ref)
1350 8218 : .ToHandleChecked();
1351 : }
1352 : wasm_exported_function = WasmExportedFunction::New(
1353 225974 : isolate_, instance, func_name, function.func_index,
1354 451948 : static_cast<int>(function.sig->parameter_count()), export_code);
1355 225972 : WasmInstanceObject::SetWasmExportedFunction(
1356 225972 : isolate_, instance, exp.index,
1357 225972 : wasm_exported_function.ToHandleChecked());
1358 : }
1359 : desc.set_value(wasm_exported_function.ToHandleChecked());
1360 226264 : export_index++;
1361 : break;
1362 : }
1363 : case kExternalTable: {
1364 560 : desc.set_value(handle(instance->tables()->get(exp.index), isolate_));
1365 560 : break;
1366 : }
1367 : case kExternalMemory: {
1368 : // Export the memory as a WebAssembly.Memory object. A WasmMemoryObject
1369 : // should already be available if the module has memory, since we always
1370 : // create or import it when building an WasmInstanceObject.
1371 : DCHECK(instance->has_memory_object());
1372 1644 : desc.set_value(
1373 : Handle<WasmMemoryObject>(instance->memory_object(), isolate_));
1374 1644 : break;
1375 : }
1376 : case kExternalGlobal: {
1377 680 : const WasmGlobal& global = module_->globals[exp.index];
1378 : Handle<JSArrayBuffer> untagged_buffer;
1379 : Handle<FixedArray> tagged_buffer;
1380 : uint32_t offset;
1381 :
1382 680 : if (global.mutability && global.imported) {
1383 : Handle<FixedArray> buffers_array(
1384 88 : instance->imported_mutable_globals_buffers(), isolate_);
1385 176 : if (ValueTypes::IsReferenceType(global.type)) {
1386 : tagged_buffer = buffers_array->GetValueChecked<FixedArray>(
1387 96 : isolate_, global.index);
1388 : // For anyref globals we store the relative offset in the
1389 : // imported_mutable_globals array instead of an absolute address.
1390 48 : Address addr = instance->imported_mutable_globals()[global.index];
1391 : DCHECK_LE(addr, static_cast<Address>(
1392 : std::numeric_limits<uint32_t>::max()));
1393 48 : offset = static_cast<uint32_t>(addr);
1394 : } else {
1395 : untagged_buffer = buffers_array->GetValueChecked<JSArrayBuffer>(
1396 80 : isolate_, global.index);
1397 : Address global_addr =
1398 40 : instance->imported_mutable_globals()[global.index];
1399 :
1400 : size_t buffer_size = untagged_buffer->byte_length();
1401 : Address backing_store =
1402 : reinterpret_cast<Address>(untagged_buffer->backing_store());
1403 40 : CHECK(global_addr >= backing_store &&
1404 : global_addr < backing_store + buffer_size);
1405 40 : offset = static_cast<uint32_t>(global_addr - backing_store);
1406 : }
1407 : } else {
1408 1184 : if (ValueTypes::IsReferenceType(global.type)) {
1409 104 : tagged_buffer = handle(instance->tagged_globals_buffer(), isolate_);
1410 : } else {
1411 : untagged_buffer =
1412 488 : handle(instance->untagged_globals_buffer(), isolate_);
1413 : }
1414 592 : offset = global.offset;
1415 : }
1416 :
1417 : // Since the global's array untagged_buffer is always provided,
1418 : // allocation should never fail.
1419 : Handle<WasmGlobalObject> global_obj =
1420 1360 : WasmGlobalObject::New(isolate_, untagged_buffer, tagged_buffer,
1421 2040 : global.type, offset, global.mutability)
1422 : .ToHandleChecked();
1423 : desc.set_value(global_obj);
1424 : break;
1425 : }
1426 : case kExternalException: {
1427 112 : const WasmException& exception = module_->exceptions[exp.index];
1428 112 : Handle<WasmExceptionObject> wrapper = exception_wrappers_[exp.index];
1429 112 : if (wrapper.is_null()) {
1430 : Handle<HeapObject> exception_tag(
1431 : HeapObject::cast(instance->exceptions_table()->get(exp.index)),
1432 96 : isolate_);
1433 : wrapper =
1434 96 : WasmExceptionObject::New(isolate_, exception.sig, exception_tag);
1435 192 : exception_wrappers_[exp.index] = wrapper;
1436 : }
1437 : desc.set_value(wrapper);
1438 : break;
1439 : }
1440 : default:
1441 0 : UNREACHABLE();
1442 : break;
1443 : }
1444 :
1445 : v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
1446 229260 : isolate_, export_to, name, &desc, Just(kThrowOnError));
1447 229254 : if (!status.IsJust()) {
1448 : DisallowHeapAllocation no_gc;
1449 0 : TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>(no_gc));
1450 0 : thrower_->LinkError("export of %.*s failed.", trunc_name.length(),
1451 0 : trunc_name.start());
1452 : return;
1453 : }
1454 : }
1455 : DCHECK_EQ(export_index, export_wrappers->length());
1456 :
1457 133843 : if (module_->origin == kWasmOrigin) {
1458 : v8::Maybe<bool> success =
1459 128999 : JSReceiver::SetIntegrityLevel(exports_object, FROZEN, kDontThrow);
1460 : DCHECK(success.FromMaybe(false));
1461 : USE(success);
1462 : }
1463 : }
1464 :
1465 2393 : void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
1466 2393 : size_t table_count = module_->tables.size();
1467 7355 : for (size_t index = 0; index < table_count; ++index) {
1468 2481 : const WasmTable& table = module_->tables[index];
1469 :
1470 3826 : if (!instance->has_indirect_function_table() &&
1471 1345 : table.type == kWasmAnyFunc) {
1472 : WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
1473 1345 : instance, table.initial_size);
1474 : }
1475 : }
1476 2393 : }
1477 :
1478 : namespace {
1479 4082 : Handle<WasmExportedFunction> CreateWasmExportedFunctionForAsm(
1480 : Isolate* isolate, Handle<WasmInstanceObject> instance,
1481 : const WasmModule* module, uint32_t func_index,
1482 : JSToWasmWrapperCache* js_to_wasm_cache) {
1483 4082 : const WasmFunction* function = &module->functions[func_index];
1484 : DCHECK_EQ(module->origin, kAsmJsOrigin);
1485 :
1486 : Handle<Code> wrapper_code = js_to_wasm_cache->GetOrCompileJSToWasmWrapper(
1487 4082 : isolate, function->sig, function->imported);
1488 : auto module_object =
1489 : Handle<WasmModuleObject>(instance->module_object(), isolate);
1490 : WireBytesRef func_name_ref = module->LookupFunctionName(
1491 : ModuleWireBytes(module_object->native_module()->wire_bytes()),
1492 8164 : func_index);
1493 8164 : auto func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
1494 : isolate, module_object, func_name_ref)
1495 : .ToHandleChecked();
1496 : auto wasm_exported_function = WasmExportedFunction::New(
1497 : isolate, instance, func_name, func_index,
1498 8164 : static_cast<int>(function->sig->parameter_count()), wrapper_code);
1499 : WasmInstanceObject::SetWasmExportedFunction(isolate, instance, func_index,
1500 4082 : wasm_exported_function);
1501 4082 : return wasm_exported_function;
1502 : }
1503 : } // namespace
1504 :
1505 2225 : bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
1506 : Handle<WasmTableObject> table_object,
1507 : JSToWasmWrapperCache* js_to_wasm_cache,
1508 : const WasmElemSegment& elem_segment, uint32_t dst,
1509 : uint32_t src, size_t count) {
1510 : // TODO(wasm): Move this functionality into wasm-objects, since it is used
1511 : // for both instantiation and in the implementation of the table.init
1512 : // instruction.
1513 : bool ok =
1514 2225 : ClampToBounds<size_t>(dst, &count, table_object->elements()->length());
1515 : // Use & instead of && so the clamp is not short-circuited.
1516 2225 : ok &= ClampToBounds<size_t>(src, &count, elem_segment.entries.size());
1517 :
1518 2225 : const WasmModule* module = instance->module();
1519 22163 : for (size_t i = 0; i < count; ++i) {
1520 19938 : uint32_t func_index = elem_segment.entries[src + i];
1521 9969 : int entry_index = static_cast<int>(dst + i);
1522 :
1523 9969 : if (func_index == WasmElemSegment::kNullIndex) {
1524 8 : IndirectFunctionTableEntry(instance, entry_index).clear();
1525 8 : WasmTableObject::Set(isolate, table_object, entry_index,
1526 8 : isolate->factory()->null_value());
1527 : continue;
1528 : }
1529 :
1530 9961 : const WasmFunction* function = &module->functions[func_index];
1531 :
1532 : // Update the local dispatch table first.
1533 19922 : uint32_t sig_id = module->signature_ids[function->sig_index];
1534 : IndirectFunctionTableEntry(instance, entry_index)
1535 19922 : .Set(sig_id, instance, func_index);
1536 :
1537 : // Update the table object's other dispatch tables.
1538 : MaybeHandle<WasmExportedFunction> wasm_exported_function =
1539 : WasmInstanceObject::GetWasmExportedFunction(isolate, instance,
1540 9961 : func_index);
1541 9961 : if (wasm_exported_function.is_null()) {
1542 : // No JSFunction entry yet exists for this function. Create a {Tuple2}
1543 : // holding the information to lazily allocate one (or eagerly allocate
1544 : // one for asm.js code).
1545 7102 : if (module->origin == kAsmJsOrigin) {
1546 : Handle<WasmExportedFunction> function =
1547 : CreateWasmExportedFunctionForAsm(isolate, instance, module,
1548 4082 : func_index, js_to_wasm_cache);
1549 8164 : table_object->elements()->set(entry_index, *function);
1550 : } else {
1551 : WasmTableObject::SetFunctionTablePlaceholder(
1552 3020 : isolate, table_object, entry_index, instance, func_index);
1553 : }
1554 : } else {
1555 8577 : table_object->elements()->set(entry_index,
1556 2859 : *wasm_exported_function.ToHandleChecked());
1557 : }
1558 : // UpdateDispatchTables() updates all other dispatch tables, since
1559 : // we have not yet added the dispatch table we are currently building.
1560 : WasmTableObject::UpdateDispatchTables(isolate, table_object, entry_index,
1561 9961 : function->sig, instance, func_index);
1562 : }
1563 2225 : return ok;
1564 : }
1565 :
1566 2265 : void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
1567 2265 : for (auto& elem_segment : module_->elem_segments) {
1568 : // Passive segments are not copied during instantiation.
1569 2033 : if (!elem_segment.active) continue;
1570 :
1571 1993 : uint32_t dst = EvalUint32InitExpr(instance, elem_segment.offset);
1572 : uint32_t src = 0;
1573 : size_t count = elem_segment.entries.size();
1574 :
1575 5979 : bool success = LoadElemSegmentImpl(
1576 : isolate_, instance,
1577 : handle(WasmTableObject::cast(
1578 1993 : instance->tables()->get(elem_segment.table_index)),
1579 : isolate_),
1580 1993 : &js_to_wasm_cache_, elem_segment, dst, src, count);
1581 1993 : CHECK(success);
1582 : }
1583 :
1584 4530 : int table_count = static_cast<int>(module_->tables.size());
1585 6971 : for (int index = 0; index < table_count; ++index) {
1586 4706 : if (module_->tables[index].type == kWasmAnyFunc) {
1587 : auto table_object = handle(
1588 4674 : WasmTableObject::cast(instance->tables()->get(index)), isolate_);
1589 :
1590 : // Add the new dispatch table at the end to avoid redundant lookups.
1591 2337 : WasmTableObject::AddDispatchTable(isolate_, table_object, instance,
1592 2337 : index);
1593 : }
1594 : }
1595 2265 : }
1596 :
1597 368 : void InstanceBuilder::InitializeExceptions(
1598 : Handle<WasmInstanceObject> instance) {
1599 368 : Handle<FixedArray> exceptions_table(instance->exceptions_table(), isolate_);
1600 1280 : for (int index = 0; index < exceptions_table->length(); ++index) {
1601 960 : if (!exceptions_table->get(index)->IsUndefined(isolate_)) continue;
1602 : Handle<WasmExceptionTag> exception_tag =
1603 408 : WasmExceptionTag::New(isolate_, index);
1604 816 : exceptions_table->set(index, *exception_tag);
1605 : }
1606 368 : }
1607 :
1608 232 : bool LoadElemSegment(Isolate* isolate, Handle<WasmInstanceObject> instance,
1609 : uint32_t table_index, uint32_t segment_index, uint32_t dst,
1610 : uint32_t src, uint32_t count) {
1611 : JSToWasmWrapperCache js_to_wasm_cache;
1612 :
1613 696 : auto& elem_segment = instance->module()->elem_segments[segment_index];
1614 232 : return LoadElemSegmentImpl(
1615 : isolate, instance,
1616 : handle(WasmTableObject::cast(instance->tables()->get(table_index)),
1617 : isolate),
1618 464 : &js_to_wasm_cache, elem_segment, dst, src, count);
1619 : }
1620 :
1621 : } // namespace wasm
1622 : } // namespace internal
1623 120216 : } // namespace v8
1624 :
1625 : #undef TRACE
|