v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
debug-wasm-objects.cc
Go to the documentation of this file.
1// Copyright 2021 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
6
7#include <optional>
8
9#include "src/api/api-inl.h"
10#include "src/api/api-natives.h"
11#include "src/base/strings.h"
12#include "src/common/globals.h"
21#include "src/wasm/wasm-debug.h"
24#include "src/wasm/wasm-value.h"
25
26namespace v8 {
27namespace internal {
28namespace {
29
30using StringBuilder = wasm::StringBuilder;
31DirectHandle<String> ToInternalString(StringBuilder& sb, Isolate* isolate) {
32 return isolate->factory()->InternalizeString(
33 base::VectorOf(sb.start(), sb.length()));
34}
35
36enum DebugProxyId {
37 kFunctionsProxy,
38 kGlobalsProxy,
39 kMemoriesProxy,
40 kTablesProxy,
41 kLastInstanceProxyId = kTablesProxy,
42
43 kContextProxy,
44 kLocalsProxy,
45 kStackProxy,
46 kStructProxy,
47 kArrayProxy,
48 kLastProxyId = kArrayProxy,
49
50 kNumProxies = kLastProxyId + 1,
51 kNumInstanceProxies = kLastInstanceProxyId + 1
52};
53
54constexpr int kWasmValueMapIndex = kNumProxies;
55constexpr int kNumDebugMaps = kWasmValueMapIndex + 1;
56
57DirectHandle<FixedArray> GetOrCreateDebugMaps(Isolate* isolate) {
58 DirectHandle<FixedArray> maps = isolate->wasm_debug_maps();
59 if (maps->length() == 0) {
60 maps = isolate->factory()->NewFixedArrayWithHoles(kNumDebugMaps);
61 isolate->native_context()->set_wasm_debug_maps(*maps);
62 }
63 return maps;
64}
65
66// Creates a Map for the given debug proxy |id| using the |create_template_fn|
67// on-demand and caches this map in the global object. The map is derived from
68// the FunctionTemplate returned by |create_template_fn| and has its prototype
69// set to |null| and is marked non-extensible (by default).
70// TODO(bmeurer): remove the extensibility opt-out and replace it with a proper
71// way to add non-intercepted named properties.
72DirectHandle<Map> GetOrCreateDebugProxyMap(
73 Isolate* isolate, DebugProxyId id,
74 v8::Local<v8::FunctionTemplate> (*create_template_fn)(v8::Isolate*),
75 bool make_non_extensible = true) {
76 auto maps = GetOrCreateDebugMaps(isolate);
77 CHECK_LE(kNumProxies, maps->length());
78 if (!maps->is_the_hole(isolate, id)) {
79 return direct_handle(Cast<Map>(maps->get(id)), isolate);
80 }
81 auto tmp = (*create_template_fn)(reinterpret_cast<v8::Isolate*>(isolate));
82 auto fun =
84 .ToHandleChecked();
85 auto map = JSFunction::GetDerivedMap(isolate, fun, fun).ToHandleChecked();
86 Map::SetPrototype(isolate, map, isolate->factory()->null_value());
87 if (make_non_extensible) {
88 map->set_is_extensible(false);
89 }
90 maps->set(id, *map);
91 return map;
92}
93
94// Base class for debug proxies, offers indexed access. The subclasses
95// need to implement |Count| and |Get| methods appropriately.
96template <typename T, DebugProxyId id, typename Provider>
97struct IndexedDebugProxy {
98 static constexpr DebugProxyId kId = id;
99
100 static DirectHandle<JSObject> Create(Isolate* isolate,
101 DirectHandle<Provider> provider,
102 bool make_map_non_extensible = true) {
103 auto object_map = GetOrCreateDebugProxyMap(isolate, kId, &T::CreateTemplate,
104 make_map_non_extensible);
105 auto object = isolate->factory()->NewFastOrSlowJSObjectFromMap(
106 object_map, 0, AllocationType::kYoung,
108 object->SetEmbedderField(kProviderField, *provider);
109 return object;
110 }
111
112 enum {
113 kProviderField,
114 kFieldCount,
115 };
116
117 static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate) {
118 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
119 templ->SetClassName(
120 v8::String::NewFromUtf8(isolate, T::kClassName).ToLocalChecked());
121 templ->InstanceTemplate()->SetInternalFieldCount(T::kFieldCount);
122 templ->InstanceTemplate()->SetHandler(
124 &T::IndexedGetter, {}, &T::IndexedQuery, {}, &T::IndexedEnumerator,
125 {}, &T::IndexedDescriptor, {},
127 return templ;
128 }
129
130 template <typename V>
131 static Isolate* GetIsolate(const PropertyCallbackInfo<V>& info) {
132 return reinterpret_cast<Isolate*>(info.GetIsolate());
133 }
134
135 template <typename V>
136 static DirectHandle<JSObject> GetHolder(const PropertyCallbackInfo<V>& info) {
137 return Cast<JSObject>(Utils::OpenHandle(*info.HolderV2()));
138 }
139
140 static DirectHandle<Provider> GetProvider(DirectHandle<JSObject> holder,
141 Isolate* isolate) {
142 return direct_handle(
143 Cast<Provider>(holder->GetEmbedderField(kProviderField)), isolate);
144 }
145
146 template <typename V>
147 static DirectHandle<Provider> GetProvider(
148 const PropertyCallbackInfo<V>& info) {
149 return GetProvider(GetHolder(info), GetIsolate(info));
150 }
151
152 static v8::Intercepted IndexedGetter(
153 uint32_t index, const PropertyCallbackInfo<v8::Value>& info) {
154 auto isolate = GetIsolate(info);
155 auto provider = GetProvider(info);
156 if (index < T::Count(isolate, provider)) {
157 auto value = T::Get(isolate, provider, index);
158 info.GetReturnValue().Set(Utils::ToLocal(value));
160 }
162 }
163
164 static v8::Intercepted IndexedDescriptor(
165 uint32_t index, const PropertyCallbackInfo<v8::Value>& info) {
166 auto isolate = GetIsolate(info);
167 auto provider = GetProvider(info);
168 if (index < T::Count(isolate, provider)) {
169 PropertyDescriptor descriptor;
170 descriptor.set_configurable(false);
171 descriptor.set_enumerable(true);
172 descriptor.set_writable(false);
173 descriptor.set_value(Cast<JSAny>(T::Get(isolate, provider, index)));
174 info.GetReturnValue().Set(Utils::ToLocal(descriptor.ToObject(isolate)));
176 }
178 }
179
180 static v8::Intercepted IndexedQuery(
181 uint32_t index, const PropertyCallbackInfo<v8::Integer>& info) {
182 if (index < T::Count(GetIsolate(info), GetProvider(info))) {
183 info.GetReturnValue().Set(Integer::New(
184 info.GetIsolate(),
187 }
189 }
190
191 static void IndexedEnumerator(const PropertyCallbackInfo<v8::Array>& info) {
192 auto isolate = GetIsolate(info);
193 auto count = T::Count(isolate, GetProvider(info));
194 auto indices = isolate->factory()->NewFixedArray(count);
195 for (uint32_t index = 0; index < count; ++index) {
196 indices->set(index, Smi::FromInt(index));
197 }
198 info.GetReturnValue().Set(
199 Utils::ToLocal(isolate->factory()->NewJSArrayWithElements(
200 indices, PACKED_SMI_ELEMENTS)));
201 }
202};
203
204// Extends |IndexedDebugProxy| with named access, where the names are computed
205// on-demand, and all names are assumed to start with a dollar char ($). This
206// is important in order to scale to Wasm modules with hundreds of thousands
207// of functions in them.
208template <typename T, DebugProxyId id, typename Provider = WasmInstanceObject>
209struct NamedDebugProxy : IndexedDebugProxy<T, id, Provider> {
210 static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate) {
211 auto templ = IndexedDebugProxy<T, id, Provider>::CreateTemplate(isolate);
212 templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
213 &T::NamedGetter, {}, &T::NamedQuery, {}, &T::NamedEnumerator, {},
214 &T::NamedDescriptor, {}, v8::PropertyHandlerFlags::kHasNoSideEffect));
215 return templ;
216 }
217
218 static void IndexedEnumerator(const PropertyCallbackInfo<v8::Array>& info) {
219 info.GetReturnValue().Set(v8::Array::New(info.GetIsolate()));
220 }
221
222 static DirectHandle<NameDictionary> GetNameTable(
223 DirectHandle<JSObject> holder, Isolate* isolate) {
224 DirectHandle<Symbol> symbol =
225 isolate->factory()->wasm_debug_proxy_names_symbol();
226 DirectHandle<Object> table_or_undefined =
227 JSObject::GetProperty(isolate, holder, symbol).ToHandleChecked();
228 if (!IsUndefined(*table_or_undefined, isolate)) {
229 return Cast<NameDictionary>(table_or_undefined);
230 }
231 auto provider = T::GetProvider(holder, isolate);
232 auto count = T::Count(isolate, provider);
233 auto table = NameDictionary::New(isolate, count);
234 for (uint32_t index = 0; index < count; ++index) {
235 HandleScope scope(isolate);
236 auto key = T::GetName(isolate, provider, index);
237 if (table->FindEntry(isolate, key).is_found()) continue;
238 DirectHandle<Smi> value(Smi::FromInt(index), isolate);
239 table = NameDictionary::Add(isolate, table, key, value,
241 }
242 Object::SetProperty(isolate, holder, symbol, table).Check();
243 return table;
244 }
245
246 template <typename V>
247 static std::optional<uint32_t> FindName(Local<v8::Name> name,
248 const PropertyCallbackInfo<V>& info) {
249 if (!name->IsString()) return {};
250 auto name_str = Utils::OpenHandle(*name.As<v8::String>());
251 if (name_str->length() == 0 || name_str->Get(0) != '$') return {};
252 auto isolate = T::GetIsolate(info);
253 auto table = GetNameTable(T::GetHolder(info), isolate);
254 auto entry = table->FindEntry(isolate, name_str);
255 if (entry.is_found()) return Smi::ToInt(table->ValueAt(entry));
256 return {};
257 }
258
259 static v8::Intercepted NamedGetter(
260 Local<v8::Name> name, const PropertyCallbackInfo<v8::Value>& info) {
261 if (auto index = FindName(name, info)) {
262 return T::IndexedGetter(*index, info);
263 }
265 }
266
267 static v8::Intercepted NamedQuery(
268 Local<v8::Name> name, const PropertyCallbackInfo<v8::Integer>& info) {
269 if (auto index = FindName(name, info)) {
270 return T::IndexedQuery(*index, info);
271 }
273 }
274
275 static v8::Intercepted NamedDescriptor(
276 Local<v8::Name> name, const PropertyCallbackInfo<v8::Value>& info) {
277 if (auto index = FindName(name, info)) {
278 return T::IndexedDescriptor(*index, info);
279 }
281 }
282
283 static void NamedEnumerator(const PropertyCallbackInfo<v8::Array>& info) {
284 auto isolate = T::GetIsolate(info);
285 auto table = GetNameTable(T::GetHolder(info), isolate);
286 auto names = NameDictionary::IterationIndices(isolate, table);
287 for (int i = 0; i < names->length(); ++i) {
288 InternalIndex entry(Smi::ToInt(names->get(i)));
289 names->set(i, table->NameAt(entry));
290 }
291 info.GetReturnValue().Set(Utils::ToLocal(
292 isolate->factory()->NewJSArrayWithElements(names, PACKED_ELEMENTS)));
293 }
294};
295
296// This class implements the "functions" proxy.
297struct FunctionsProxy : NamedDebugProxy<FunctionsProxy, kFunctionsProxy> {
298 static constexpr char const* kClassName = "Functions";
299
300 static uint32_t Count(Isolate* isolate,
301 DirectHandle<WasmInstanceObject> instance) {
302 return static_cast<uint32_t>(instance->module()->functions.size());
303 }
304
305 static DirectHandle<Object> Get(Isolate* isolate,
306 DirectHandle<WasmInstanceObject> instance,
307 uint32_t index) {
308 DirectHandle<WasmTrustedInstanceData> trusted_data{
309 instance->trusted_data(isolate), isolate};
310 DirectHandle<WasmFuncRef> func_ref =
312 index);
313 DirectHandle<WasmInternalFunction> internal_function{
314 func_ref->internal(isolate), isolate};
315 return WasmInternalFunction::GetOrCreateExternal(internal_function);
316 }
317
318 static DirectHandle<String> GetName(Isolate* isolate,
319 DirectHandle<WasmInstanceObject> instance,
320 uint32_t index) {
322 instance->trusted_data(isolate), isolate};
323 return GetWasmFunctionDebugName(isolate, instance_data, index);
324 }
325};
326
327// This class implements the "globals" proxy.
328struct GlobalsProxy : NamedDebugProxy<GlobalsProxy, kGlobalsProxy> {
329 static constexpr char const* kClassName = "Globals";
330
331 static uint32_t Count(Isolate* isolate,
332 DirectHandle<WasmInstanceObject> instance) {
333 return static_cast<uint32_t>(instance->module()->globals.size());
334 }
335
336 static DirectHandle<Object> Get(Isolate* isolate,
337 DirectHandle<WasmInstanceObject> instance,
338 uint32_t index) {
340 isolate, instance->trusted_data(isolate)->GetGlobalValue(
341 isolate, instance->module()->globals[index]));
342 }
343
344 static DirectHandle<String> GetName(Isolate* isolate,
345 DirectHandle<WasmInstanceObject> instance,
346 uint32_t index) {
347 wasm::NamesProvider* names =
348 instance->module_object()->native_module()->GetNamesProvider();
349 StringBuilder sb;
350 names->PrintGlobalName(sb, index);
351 return ToInternalString(sb, isolate);
352 }
353};
354
355// This class implements the "memories" proxy.
356struct MemoriesProxy : NamedDebugProxy<MemoriesProxy, kMemoriesProxy> {
357 static constexpr char const* kClassName = "Memories";
358
359 static uint32_t Count(Isolate* isolate,
360 DirectHandle<WasmInstanceObject> instance) {
361 return instance->trusted_data(isolate)->memory_objects()->length();
362 }
363
364 static DirectHandle<Object> Get(Isolate* isolate,
365 DirectHandle<WasmInstanceObject> instance,
366 uint32_t index) {
367 return direct_handle(instance->trusted_data(isolate)->memory_object(index),
368 isolate);
369 }
370
371 static DirectHandle<String> GetName(Isolate* isolate,
372 DirectHandle<WasmInstanceObject> instance,
373 uint32_t index) {
374 wasm::NamesProvider* names =
375 instance->module_object()->native_module()->GetNamesProvider();
376 StringBuilder sb;
377 names->PrintMemoryName(sb, index);
378 return ToInternalString(sb, isolate);
379 }
380};
381
382// This class implements the "tables" proxy.
383struct TablesProxy : NamedDebugProxy<TablesProxy, kTablesProxy> {
384 static constexpr char const* kClassName = "Tables";
385
386 static uint32_t Count(Isolate* isolate,
387 DirectHandle<WasmInstanceObject> instance) {
388 return instance->trusted_data(isolate)->tables()->length();
389 }
390
391 static DirectHandle<Object> Get(Isolate* isolate,
392 DirectHandle<WasmInstanceObject> instance,
393 uint32_t index) {
394 return direct_handle(instance->trusted_data(isolate)->tables()->get(index),
395 isolate);
396 }
397
398 static DirectHandle<String> GetName(Isolate* isolate,
399 DirectHandle<WasmInstanceObject> instance,
400 uint32_t index) {
401 wasm::NamesProvider* names =
402 instance->module_object()->native_module()->GetNamesProvider();
403 StringBuilder sb;
404 names->PrintTableName(sb, index);
405 return ToInternalString(sb, isolate);
406 }
407};
408
409// This class implements the "locals" proxy.
410struct LocalsProxy : NamedDebugProxy<LocalsProxy, kLocalsProxy, FixedArray> {
411 static constexpr char const* kClassName = "Locals";
412
413 static DirectHandle<JSObject> Create(WasmFrame* frame) {
414 auto isolate = frame->isolate();
415 auto debug_info = frame->native_module()->GetDebugInfo();
416 // TODO(bmeurer): Check if pc is inspectable.
417 int count = debug_info->GetNumLocals(frame->pc(), isolate);
418 auto function = debug_info->GetFunctionAtAddress(frame->pc(), isolate);
419 auto values = isolate->factory()->NewFixedArray(count + 2);
420 for (int i = 0; i < count; ++i) {
421 auto value = WasmValueObject::New(
422 isolate, debug_info->GetLocalValue(i, frame->pc(), frame->fp(),
423 frame->callee_fp(), isolate));
424 values->set(i, *value);
425 }
426 values->set(count + 0, frame->wasm_instance()->module_object());
427 values->set(count + 1, Smi::FromInt(function.func_index));
428 return NamedDebugProxy::Create(isolate, values);
429 }
430
431 static uint32_t Count(Isolate* isolate, DirectHandle<FixedArray> values) {
432 return values->length() - 2;
433 }
434
435 static DirectHandle<Object> Get(Isolate* isolate,
436 DirectHandle<FixedArray> values,
437 uint32_t index) {
438 return direct_handle(values->get(index), isolate);
439 }
440
441 static DirectHandle<String> GetName(Isolate* isolate,
442 DirectHandle<FixedArray> values,
443 uint32_t index) {
444 uint32_t count = Count(isolate, values);
445 auto native_module =
446 Cast<WasmModuleObject>(values->get(count + 0))->native_module();
447 auto function_index = Smi::ToInt(Cast<Smi>(values->get(count + 1)));
448 wasm::NamesProvider* names = native_module->GetNamesProvider();
449 StringBuilder sb;
450 names->PrintLocalName(sb, function_index, index);
451 return ToInternalString(sb, isolate);
452 }
453};
454
455// This class implements the "stack" proxy (which offers only indexed access).
456struct StackProxy : IndexedDebugProxy<StackProxy, kStackProxy, FixedArray> {
457 static constexpr char const* kClassName = "Stack";
458
459 static DirectHandle<JSObject> Create(WasmFrame* frame) {
460 auto isolate = frame->isolate();
461 auto debug_info =
462 frame->trusted_instance_data()->native_module()->GetDebugInfo();
463 int count = debug_info->GetStackDepth(frame->pc(), isolate);
464 auto values = isolate->factory()->NewFixedArray(count);
465 for (int i = 0; i < count; ++i) {
466 auto value = WasmValueObject::New(
467 isolate, debug_info->GetStackValue(i, frame->pc(), frame->fp(),
468 frame->callee_fp(), isolate));
469 values->set(i, *value);
470 }
471 return IndexedDebugProxy::Create(isolate, values);
472 }
473
474 static uint32_t Count(Isolate* isolate, DirectHandle<FixedArray> values) {
475 return values->length();
476 }
477
478 static DirectHandle<Object> Get(Isolate* isolate,
479 DirectHandle<FixedArray> values,
480 uint32_t index) {
481 return direct_handle(values->get(index), isolate);
482 }
483};
484
485// Creates FixedArray with size |kNumInstanceProxies| as cache on-demand
486// on the |instance|, stored under the |wasm_debug_proxy_cache_symbol|.
487// This is used to cache the various instance debug proxies (functions,
488// globals, tables, and memories) on the WasmInstanceObject.
489DirectHandle<FixedArray> GetOrCreateInstanceProxyCache(
490 Isolate* isolate, DirectHandle<WasmInstanceObject> instance) {
491 DirectHandle<Object> cache;
492 DirectHandle<Symbol> symbol =
493 isolate->factory()->wasm_debug_proxy_cache_symbol();
494 if (!Object::GetProperty(isolate, instance, symbol).ToHandle(&cache) ||
495 IsUndefined(*cache, isolate)) {
496 cache = isolate->factory()->NewFixedArrayWithHoles(kNumInstanceProxies);
497 Object::SetProperty(isolate, instance, symbol, cache).Check();
498 }
499 return Cast<FixedArray>(cache);
500}
501
502// Creates an instance of the |Proxy| on-demand and caches that on the
503// |instance|.
504template <typename Proxy>
505DirectHandle<JSObject> GetOrCreateInstanceProxy(
506 Isolate* isolate, DirectHandle<WasmInstanceObject> instance) {
507 static_assert(Proxy::kId < kNumInstanceProxies);
508 DirectHandle<FixedArray> proxies =
509 GetOrCreateInstanceProxyCache(isolate, instance);
510 if (!proxies->is_the_hole(isolate, Proxy::kId)) {
511 return direct_handle(Cast<JSObject>(proxies->get(Proxy::kId)), isolate);
512 }
513 DirectHandle<JSObject> proxy = Proxy::Create(isolate, instance);
514 proxies->set(Proxy::kId, *proxy);
515 return proxy;
516}
517
518// This class implements the debug proxy for a given Wasm frame. The debug
519// proxy is used when evaluating JavaScript expressions on a wasm frame via
520// the inspector |Runtime.evaluateOnCallFrame()| API and enables developers
521// and extensions to inspect the WebAssembly engine state from JavaScript.
522// The proxy provides the following interface:
523//
524// type WasmValue = {
525// type: string;
526// value: number | bigint | object | string;
527// };
528// type WasmFunction = (... args : WasmValue[]) = > WasmValue;
529// interface WasmInterface {
530// $globalX: WasmValue;
531// $varX: WasmValue;
532// $funcX(a : WasmValue /*, ...*/) : WasmValue;
533// readonly $memoryX : WebAssembly.Memory;
534// readonly $tableX : WebAssembly.Table;
535//
536// readonly instance : WebAssembly.Instance;
537// readonly module : WebAssembly.Module;
538//
539// readonly memories : {[nameOrIndex:string | number] : WebAssembly.Memory};
540// readonly tables : {[nameOrIndex:string | number] : WebAssembly.Table};
541// readonly stack : WasmValue[];
542// readonly globals : {[nameOrIndex:string | number] : WasmValue};
543// readonly locals : {[nameOrIndex:string | number] : WasmValue};
544// readonly functions : {[nameOrIndex:string | number] : WasmFunction};
545// }
546//
547// The wasm index spaces memories, tables, stack, globals, locals, and
548// functions are JSObjects with interceptors that lazily produce values
549// either by index or by name (except for stack).
550// Only the names are reported by APIs such as Object.keys() and
551// Object.getOwnPropertyNames(), since the indices are not meant to be
552// used interactively by developers (in Chrome DevTools), but are provided
553// for WebAssembly language extensions. Also note that these JSObjects
554// all have null prototypes, to not confuse context lookup and to make
555// their purpose as dictionaries clear.
556//
557// See http://doc/1VZOJrU2VsqOZe3IUzbwQWQQSZwgGySsm5119Ust1gUA and
558// http://bit.ly/devtools-wasm-entities for more details.
559class ContextProxyPrototype {
560 public:
561 static DirectHandle<JSObject> Create(Isolate* isolate) {
562 auto object_map =
563 GetOrCreateDebugProxyMap(isolate, kContextProxy, &CreateTemplate);
564 return isolate->factory()->NewJSObjectFromMap(
565 object_map, AllocationType::kYoung,
567 }
568
569 private:
570 static v8::Local<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate) {
571 Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(isolate);
572 templ->InstanceTemplate()->SetHandler(v8::NamedPropertyHandlerConfiguration(
573 &NamedGetter, {}, {}, {}, {}, {}, {}, {},
574 static_cast<v8::PropertyHandlerFlags>(
575 static_cast<unsigned>(
577 static_cast<unsigned>(
579 return templ;
580 }
581
582 static MaybeDirectHandle<Object> GetNamedProperty(
583 Isolate* isolate, DirectHandle<JSObject> receiver,
584 DirectHandle<String> name) {
585 if (name->length() != 0 && name->Get(0) == '$') {
586 const char* kDelegateNames[] = {"memories", "locals", "tables",
587 "functions", "globals"};
588 for (auto delegate_name : kDelegateNames) {
589 DirectHandle<JSAny> delegate;
590 ASSIGN_RETURN_ON_EXCEPTION(isolate, delegate,
591 Cast<JSAny>(JSObject::GetProperty(
592 isolate, receiver, delegate_name)));
593 if (!IsUndefined(*delegate, isolate)) {
594 DirectHandle<Object> value;
596 isolate, value, Object::GetProperty(isolate, delegate, name));
597 if (!IsUndefined(*value, isolate)) return value;
598 }
599 }
600 }
601 return {};
602 }
603
604 static v8::Intercepted NamedGetter(
605 Local<v8::Name> name, const PropertyCallbackInfo<v8::Value>& info) {
606 auto name_string = Cast<String>(Utils::OpenHandle(*name));
607 auto isolate = reinterpret_cast<Isolate*>(info.GetIsolate());
608 auto receiver = Cast<JSObject>(Utils::OpenHandle(*info.This()));
609 DirectHandle<Object> value;
610 if (GetNamedProperty(isolate, receiver, name_string).ToHandle(&value)) {
611 info.GetReturnValue().Set(Utils::ToLocal(value));
613 }
615 }
616};
617
618class ContextProxy {
619 public:
620 static DirectHandle<JSObject> Create(WasmFrame* frame) {
621 Isolate* isolate = frame->isolate();
622 auto object = isolate->factory()->NewSlowJSObjectWithNullProto();
623 DirectHandle<WasmInstanceObject> instance(frame->wasm_instance(), isolate);
624 JSObject::AddProperty(isolate, object, "instance", instance, FROZEN);
625 DirectHandle<WasmModuleObject> module_object(instance->module_object(),
626 isolate);
627 JSObject::AddProperty(isolate, object, "module", module_object, FROZEN);
628 auto locals = LocalsProxy::Create(frame);
629 JSObject::AddProperty(isolate, object, "locals", locals, FROZEN);
630 auto stack = StackProxy::Create(frame);
631 JSObject::AddProperty(isolate, object, "stack", stack, FROZEN);
632 auto memories = GetOrCreateInstanceProxy<MemoriesProxy>(isolate, instance);
633 JSObject::AddProperty(isolate, object, "memories", memories, FROZEN);
634 auto tables = GetOrCreateInstanceProxy<TablesProxy>(isolate, instance);
635 JSObject::AddProperty(isolate, object, "tables", tables, FROZEN);
636 auto globals = GetOrCreateInstanceProxy<GlobalsProxy>(isolate, instance);
637 JSObject::AddProperty(isolate, object, "globals", globals, FROZEN);
638 auto functions =
639 GetOrCreateInstanceProxy<FunctionsProxy>(isolate, instance);
640 JSObject::AddProperty(isolate, object, "functions", functions, FROZEN);
641 DirectHandle<JSObject> prototype = ContextProxyPrototype::Create(isolate);
642 JSObject::SetPrototype(isolate, object, prototype, false, kDontThrow)
643 .Check();
644 return object;
645 }
646};
647
648class DebugWasmScopeIterator final : public debug::ScopeIterator {
649 public:
650 explicit DebugWasmScopeIterator(WasmFrame* frame)
651 : frame_(frame),
652 type_(debug::ScopeIterator::ScopeTypeWasmExpressionStack) {
653 // Skip local scope and expression stack scope if the frame is not
654 // inspectable.
655 if (!frame->is_inspectable()) {
656 type_ = debug::ScopeIterator::ScopeTypeModule;
657 }
658 }
659
660 bool Done() override { return type_ == ScopeTypeWith; }
661
662 void Advance() override {
663 DCHECK(!Done());
664 switch (type_) {
665 case ScopeTypeWasmExpressionStack:
667 break;
668 case ScopeTypeLocal:
670 break;
671 case ScopeTypeModule:
672 // We use ScopeTypeWith type as marker for done.
674 break;
675 default:
676 UNREACHABLE();
677 }
678 }
679
680 ScopeType GetType() override { return type_; }
681
682 v8::Local<v8::Object> GetObject() override {
683 Isolate* isolate = frame_->isolate();
684 switch (type_) {
686 DirectHandle<WasmInstanceObject> instance{frame_->wasm_instance(),
687 isolate};
688 DirectHandle<JSObject> object =
689 isolate->factory()->NewSlowJSObjectWithNullProto();
690 JSObject::AddProperty(isolate, object, "instance", instance, FROZEN);
691 DirectHandle<JSObject> module_object(instance->module_object(),
692 isolate);
693 JSObject::AddProperty(isolate, object, "module", module_object, FROZEN);
694 if (FunctionsProxy::Count(isolate, instance) != 0) {
696 isolate, object, "functions",
697 GetOrCreateInstanceProxy<FunctionsProxy>(isolate, instance),
698 FROZEN);
699 }
700 if (GlobalsProxy::Count(isolate, instance) != 0) {
702 isolate, object, "globals",
703 GetOrCreateInstanceProxy<GlobalsProxy>(isolate, instance),
704 FROZEN);
705 }
706 if (MemoriesProxy::Count(isolate, instance) != 0) {
708 isolate, object, "memories",
709 GetOrCreateInstanceProxy<MemoriesProxy>(isolate, instance),
710 FROZEN);
711 }
712 if (TablesProxy::Count(isolate, instance) != 0) {
714 isolate, object, "tables",
715 GetOrCreateInstanceProxy<TablesProxy>(isolate, instance), FROZEN);
716 }
717 return Utils::ToLocal(object);
718 }
720 return Utils::ToLocal(LocalsProxy::Create(frame_));
721 }
723 auto object = isolate->factory()->NewSlowJSObjectWithNullProto();
724 auto stack = StackProxy::Create(frame_);
725 JSObject::AddProperty(isolate, object, "stack", stack, FROZEN);
726 return Utils::ToLocal(object);
727 }
728 default:
729 UNREACHABLE();
730 }
731 }
732 v8::Local<v8::Value> GetFunctionDebugName() override {
733 return Utils::ToLocal(frame_->isolate()->factory()->empty_string());
734 }
735
736 int GetScriptId() override { return -1; }
737
738 bool HasLocationInfo() override { return false; }
739
740 debug::Location GetStartLocation() override { return {}; }
741
742 debug::Location GetEndLocation() override { return {}; }
743
744 bool SetVariableValue(v8::Local<v8::String> name,
745 v8::Local<v8::Value> value) override {
746 return false;
747 }
748
749 private:
750 WasmFrame* const frame_;
752};
753
754#if V8_ENABLE_DRUMBRAKE
755class DebugWasmInterpreterScopeIterator final : public debug::ScopeIterator {
756 public:
757 explicit DebugWasmInterpreterScopeIterator(WasmInterpreterEntryFrame* frame)
758 : frame_(frame), type_(debug::ScopeIterator::ScopeTypeModule) {
759 // TODO(paolosev@microsoft.com) - Enable local scopes and expression stack
760 // scopes.
761 }
762
763 bool Done() override { return type_ == ScopeTypeWith; }
764
765 void Advance() override {
766 DCHECK(!Done());
767 switch (type_) {
768 case ScopeTypeModule:
769 // We use ScopeTypeWith type as marker for done.
770 type_ = debug::ScopeIterator::ScopeTypeWith;
771 break;
772 case ScopeTypeWasmExpressionStack:
773 case ScopeTypeLocal:
774 default:
775 UNREACHABLE();
776 }
777 }
778
779 ScopeType GetType() override { return type_; }
780
781 v8::Local<v8::Object> GetObject() override {
782 Isolate* isolate = frame_->isolate();
783 switch (type_) {
784 case debug::ScopeIterator::ScopeTypeModule: {
785 DirectHandle<WasmInstanceObject> instance(frame_->wasm_instance(),
786 isolate);
787 DirectHandle<JSObject> object =
788 isolate->factory()->NewSlowJSObjectWithNullProto();
789 JSObject::AddProperty(isolate, object, "instance", instance, FROZEN);
790 DirectHandle<JSObject> module_object(instance->module_object(),
791 isolate);
792 JSObject::AddProperty(isolate, object, "module", module_object, FROZEN);
793 if (FunctionsProxy::Count(isolate, instance) != 0) {
794 JSObject::AddProperty(
795 isolate, object, "functions",
796 GetOrCreateInstanceProxy<FunctionsProxy>(isolate, instance),
797 FROZEN);
798 }
799 if (GlobalsProxy::Count(isolate, instance) != 0) {
800 JSObject::AddProperty(
801 isolate, object, "globals",
802 GetOrCreateInstanceProxy<GlobalsProxy>(isolate, instance),
803 FROZEN);
804 }
805 if (MemoriesProxy::Count(isolate, instance) != 0) {
806 JSObject::AddProperty(
807 isolate, object, "memories",
808 GetOrCreateInstanceProxy<MemoriesProxy>(isolate, instance),
809 FROZEN);
810 }
811 if (TablesProxy::Count(isolate, instance) != 0) {
812 JSObject::AddProperty(
813 isolate, object, "tables",
814 GetOrCreateInstanceProxy<TablesProxy>(isolate, instance), FROZEN);
815 }
816 return Utils::ToLocal(object);
817 }
818 case debug::ScopeIterator::ScopeTypeLocal:
819 case debug::ScopeIterator::ScopeTypeWasmExpressionStack:
820 default:
821 UNREACHABLE();
822 }
823 }
824 v8::Local<v8::Value> GetFunctionDebugName() override {
825 return Utils::ToLocal(frame_->isolate()->factory()->empty_string());
826 }
827
828 int GetScriptId() override { return -1; }
829
830 bool HasLocationInfo() override { return false; }
831
832 debug::Location GetStartLocation() override { return {}; }
833
834 debug::Location GetEndLocation() override { return {}; }
835
836 bool SetVariableValue(v8::Local<v8::String> name,
837 v8::Local<v8::Value> value) override {
838 return false;
839 }
840
841 private:
842 WasmInterpreterEntryFrame* const frame_;
844};
845#endif // V8_ENABLE_DRUMBRAKE
846
847DirectHandle<String> WasmSimd128ToString(Isolate* isolate, Simd128 s128) {
848 // We use the canonical format as described in:
849 // https://github.com/WebAssembly/simd/blob/master/proposals/simd/TextSIMD.md
850 base::EmbeddedVector<char, 50> buffer;
851 auto i32x4 = s128.to_i32x4();
852 SNPrintF(buffer, "i32x4 0x%08X 0x%08X 0x%08X 0x%08X", i32x4.val[0],
853 i32x4.val[1], i32x4.val[2], i32x4.val[3]);
854 return isolate->factory()->NewStringFromAsciiChecked(buffer.data());
855}
856
857DirectHandle<String> GetRefTypeName(Isolate* isolate,
858 wasm::CanonicalValueType type) {
859 StringBuilder name;
861 return ToInternalString(name, isolate);
862}
863
864} // namespace
865
866// static
869 DirectHandle<Object> value) {
870 auto maps = GetOrCreateDebugMaps(isolate);
871 if (maps->is_the_hole(isolate, kWasmValueMapIndex)) {
873 isolate->factory()->NewContextfulMapForCurrentContext(
874 WASM_VALUE_OBJECT_TYPE, WasmValueObject::kSize,
876 Map::EnsureDescriptorSlack(isolate, map, 2);
877 map->SetConstructor(*isolate->object_function());
878 { // type
880 isolate,
881 isolate->factory()->InternalizeString(base::StaticCharVector("type")),
883 map->AppendDescriptor(isolate, &d);
884 }
885 { // value
887 isolate,
888 isolate->factory()->InternalizeString(
889 base::StaticCharVector("value")),
891 map->AppendDescriptor(isolate, &d);
892 }
893 map->set_is_extensible(false);
894 maps->set(kWasmValueMapIndex, *map);
895 }
896 DirectHandle<Map> value_map(Cast<Map>(maps->get(kWasmValueMapIndex)),
897 isolate);
898 auto object =
899 Cast<WasmValueObject>(isolate->factory()->NewJSObjectFromMap(value_map));
900 object->set_type(*type);
901 object->set_value(*value);
902 return object;
903}
904
905// This class implements a proxy for a single inspectable Wasm struct.
906struct StructProxy : NamedDebugProxy<StructProxy, kStructProxy, WasmStruct> {
907 static constexpr char const* kClassName = "Struct";
908
911 return NamedDebugProxy::Create(isolate, value);
912 }
913
914 static uint32_t Count(Isolate* isolate, DirectHandle<WasmStruct> obj) {
915 wasm::CanonicalTypeIndex type_index =
916 obj->map()->wasm_type_info()->type().ref_index();
918 ->LookupStruct(type_index)
919 ->field_count();
920 }
921
924 uint32_t index) {
925 return WasmValueObject::New(isolate, obj->GetFieldValue(index));
926 }
927
930 uint32_t index) {
931 wasm::CanonicalTypeIndex struct_index =
932 obj->map()->wasm_type_info()->type().ref_index();
933 StringBuilder sb;
935 index);
936 return ToInternalString(sb, isolate);
937 }
938};
939
940// This class implements a proxy for a single inspectable Wasm array.
941struct ArrayProxy : IndexedDebugProxy<ArrayProxy, kArrayProxy, WasmArray> {
942 static constexpr char const* kClassName = "Array";
943
946 DirectHandle<JSObject> proxy = IndexedDebugProxy::Create(
947 isolate, value, false /* leave map extensible */);
948 uint32_t length = value->length();
949 DirectHandle<Object> length_obj =
950 isolate->factory()->NewNumberFromUint(length);
951 Object::SetProperty(isolate, proxy, isolate->factory()->length_string(),
952 length_obj, StoreOrigin::kNamed,
954 .Check();
955 return proxy;
956 }
957
960 IndexedDebugProxy::CreateTemplate(isolate);
961 templ->InstanceTemplate()->Set(isolate, "length",
962 v8::Number::New(isolate, 0));
963 return templ;
964 }
965
966 static uint32_t Count(Isolate* isolate, DirectHandle<WasmArray> array) {
967 return array->length();
968 }
969
972 uint32_t index) {
973 return WasmValueObject::New(isolate, array->GetElement(index));
974 }
975};
976
977// static
979 Isolate* isolate, const wasm::WasmValue& value) {
982 switch (value.type().kind()) {
983 case wasm::kI8: {
984 // This can't be reached for most "top-level" things, only via nested
985 // calls for struct/array fields.
986 t = isolate->factory()->InternalizeString(base::StaticCharVector("i8"));
987 v = isolate->factory()->NewNumber(value.to_i8_unchecked());
988 break;
989 }
990 case wasm::kI16: {
991 // This can't be reached for most "top-level" things, only via nested
992 // calls for struct/array fields.
993 t = isolate->factory()->InternalizeString(base::StaticCharVector("i16"));
994 v = isolate->factory()->NewNumber(value.to_i16_unchecked());
995 break;
996 }
997 case wasm::kI32: {
998 t = isolate->factory()->InternalizeString(base::StaticCharVector("i32"));
999 v = isolate->factory()->NewNumberFromInt(value.to_i32_unchecked());
1000 break;
1001 }
1002 case wasm::kI64: {
1003 t = isolate->factory()->InternalizeString(base::StaticCharVector("i64"));
1004 v = BigInt::FromInt64(isolate, value.to_i64_unchecked());
1005 break;
1006 }
1007 case wasm::kF16: {
1008 // This can't be reached for most "top-level" things, only via nested
1009 // calls for struct/array fields.
1010 t = isolate->factory()->InternalizeString(base::StaticCharVector("f16"));
1011 v = isolate->factory()->NewNumber(value.to_f16_unchecked());
1012 break;
1013 }
1014 case wasm::kF32: {
1015 t = isolate->factory()->InternalizeString(base::StaticCharVector("f32"));
1016 v = isolate->factory()->NewNumber(value.to_f32_unchecked());
1017 break;
1018 }
1019 case wasm::kF64: {
1020 t = isolate->factory()->InternalizeString(base::StaticCharVector("f64"));
1021 v = isolate->factory()->NewNumber(value.to_f64_unchecked());
1022 break;
1023 }
1024 case wasm::kS128: {
1025 t = isolate->factory()->InternalizeString(base::StaticCharVector("v128"));
1026 v = WasmSimd128ToString(isolate, value.to_s128_unchecked());
1027 break;
1028 }
1029 case wasm::kRefNull:
1030 case wasm::kRef: {
1031 DirectHandle<Object> ref = value.to_ref();
1032 if (value.type().is_reference_to(wasm::HeapType::kExn)) {
1033 t = isolate->factory()->InternalizeString(
1034 base::StaticCharVector("exnref"));
1035 v = ref;
1036 } else if (IsWasmStruct(*ref)) {
1037 Tagged<WasmTypeInfo> type_info =
1038 Cast<HeapObject>(*ref)->map()->wasm_type_info();
1039 t = GetRefTypeName(isolate, type_info->type());
1040 v = StructProxy::Create(isolate, Cast<WasmStruct>(ref));
1041 } else if (IsWasmArray(*ref)) {
1042 Tagged<WasmTypeInfo> type_info =
1043 Cast<HeapObject>(*ref)->map()->wasm_type_info();
1044 t = GetRefTypeName(isolate, type_info->type());
1045 v = ArrayProxy::Create(isolate, Cast<WasmArray>(ref));
1046 } else if (IsWasmFuncRef(*ref)) {
1048 Cast<WasmFuncRef>(*ref)->internal(isolate), isolate};
1050 t = GetRefTypeName(isolate, value.type());
1051 } else if (IsWasmNull(*ref)) {
1052 v = isolate->factory()->null_value();
1053 t = GetRefTypeName(isolate, value.type());
1054 } else if (IsJSFunction(*ref) || IsSmi(*ref) || IsNull(*ref) ||
1055 IsString(*ref) ||
1056 value.type().is_reference_to(wasm::HeapType::kExtern) ||
1057 value.type().is_reference_to(wasm::HeapType::kAny)) {
1058 t = GetRefTypeName(isolate, value.type());
1059 v = ref;
1060 } else {
1061 // Fail gracefully.
1063 int len = SNPrintF(error, "unimplemented object type: %d",
1064 Cast<HeapObject>(*ref)->map()->instance_type());
1065 t = GetRefTypeName(isolate, value.type());
1066 v = isolate->factory()->InternalizeString(error.SubVector(0, len));
1067 }
1068 break;
1069 }
1070 case wasm::kVoid:
1071 case wasm::kTop:
1072 case wasm::kBottom:
1073 UNREACHABLE();
1074 }
1075 return New(isolate, t, v);
1076}
1077
1079 return ContextProxy::Create(frame);
1080}
1081
1082std::unique_ptr<debug::ScopeIterator> GetWasmScopeIterator(WasmFrame* frame) {
1083 return std::make_unique<DebugWasmScopeIterator>(frame);
1084}
1085
1086#if V8_ENABLE_DRUMBRAKE
1087std::unique_ptr<debug::ScopeIterator> GetWasmInterpreterScopeIterator(
1088 WasmInterpreterEntryFrame* frame) {
1089 return std::make_unique<DebugWasmInterpreterScopeIterator>(frame);
1090}
1091#endif // V8_ENABLE_DRUMBRAKE
1092
1095 uint32_t func_index) {
1096 wasm::NativeModule* native_module = instance_data->native_module();
1097 wasm::NamesProvider* names = native_module->GetNamesProvider();
1098 StringBuilder sb;
1100 is_asmjs_module(native_module->module())
1103 names->PrintFunctionName(sb, func_index, behavior);
1104 return ToInternalString(sb, isolate);
1105}
1106
1111 isolate, result,
1112 isolate->factory()->NewStringFromAsciiChecked("[[Module]]"),
1113 direct_handle(instance->module_object(), isolate));
1114
1115 if (FunctionsProxy::Count(isolate, instance) != 0) {
1117 isolate, result,
1118 isolate->factory()->NewStringFromAsciiChecked("[[Functions]]"),
1119 GetOrCreateInstanceProxy<FunctionsProxy>(isolate, instance));
1120 }
1121
1122 if (GlobalsProxy::Count(isolate, instance) != 0) {
1124 isolate, result,
1125 isolate->factory()->NewStringFromAsciiChecked("[[Globals]]"),
1126 GetOrCreateInstanceProxy<GlobalsProxy>(isolate, instance));
1127 }
1128
1129 if (MemoriesProxy::Count(isolate, instance) != 0) {
1131 isolate, result,
1132 isolate->factory()->NewStringFromAsciiChecked("[[Memories]]"),
1133 GetOrCreateInstanceProxy<MemoriesProxy>(isolate, instance));
1134 }
1135
1136 if (TablesProxy::Count(isolate, instance) != 0) {
1138 isolate, result,
1139 isolate->factory()->NewStringFromAsciiChecked("[[Tables]]"),
1140 GetOrCreateInstanceProxy<TablesProxy>(isolate, instance));
1141 }
1142
1143 return result;
1144}
1145
1148 DirectHandle<WasmModuleObject> module_object) {
1150 isolate, result,
1151 isolate->factory()->NewStringFromStaticChars("[[Exports]]"),
1152 wasm::GetExports(isolate, module_object));
1154 isolate, result,
1155 isolate->factory()->NewStringFromStaticChars("[[Imports]]"),
1156 wasm::GetImports(isolate, module_object));
1157 return result;
1158}
1159
1163 int length = table->current_length();
1164 DirectHandle<FixedArray> entries = isolate->factory()->NewFixedArray(length);
1165 for (int i = 0; i < length; ++i) {
1166 DirectHandle<Object> entry = WasmTableObject::Get(isolate, table, i);
1167 const wasm::WasmModule* mod = nullptr;
1168 if (table->has_trusted_data()) {
1169 mod = table->trusted_data(isolate)->module();
1170 }
1171 wasm::WasmValue wasm_value(entry, table->canonical_type(mod));
1172 DirectHandle<Object> debug_value =
1173 WasmValueObject::New(isolate, wasm_value);
1174 entries->set(i, *debug_value);
1175 }
1176 DirectHandle<JSArray> final_entries =
1177 isolate->factory()->NewJSArrayWithElements(entries, i::PACKED_ELEMENTS,
1178 length);
1179 JSObject::SetPrototype(isolate, final_entries,
1180 isolate->factory()->null_value(), false, kDontThrow)
1181 .Check();
1182 DirectHandle<String> entries_string =
1183 isolate->factory()->NewStringFromStaticChars("[[Entries]]");
1184 result = ArrayList::Add(isolate, result, entries_string, final_entries);
1185 return result;
1186}
1187
1188} // namespace internal
1189} // namespace v8
static Local< Array > New(Isolate *isolate, int length=0)
Definition api.cc:8119
static Local< FunctionTemplate > New(Isolate *isolate, FunctionCallback callback=nullptr, Local< Value > data=Local< Value >(), Local< Signature > signature=Local< Signature >(), int length=0, ConstructorBehavior behavior=ConstructorBehavior::kAllow, SideEffectType side_effect_type=SideEffectType::kHasSideEffect, const CFunction *c_function=nullptr, uint16_t instance_type=0, uint16_t allowed_receiver_instance_type_range_start=0, uint16_t allowed_receiver_instance_type_range_end=0)
Definition api.cc:1101
static Local< Integer > New(Isolate *isolate, int32_t value)
Definition api.cc:9568
static Local< Number > New(Isolate *isolate, double value)
Definition api.cc:9557
static V8_WARN_UNUSED_RESULT MaybeLocal< String > NewFromUtf8(Isolate *isolate, const char *data, NewStringType type=NewStringType::kNormal, int length=-1)
Definition api.cc:7593
static v8::internal::Handle< To > OpenHandle(v8::Local< From > handle)
Definition api.h:274
static v8::internal::DirectHandle< To > OpenDirectHandle(v8::Local< From > handle)
Definition api.h:279
static V8_WARN_UNUSED_RESULT MaybeHandle< JSFunction > InstantiateFunction(Isolate *isolate, DirectHandle< NativeContext > native_context, DirectHandle< FunctionTemplateInfo > data, MaybeDirectHandle< Name > maybe_name={})
static V8_EXPORT_PRIVATE DirectHandle< ArrayList > Add(Isolate *isolate, DirectHandle< ArrayList > array, Tagged< Smi > obj, AllocationType allocation=AllocationType::kYoung)
static V8_EXPORT_PRIVATE Handle< BigInt > FromInt64(Isolate *isolate, int64_t n)
Definition bigint.cc:1333
static Descriptor DataField(Isolate *isolate, DirectHandle< Name > key, int field_index, PropertyAttributes attributes, Representation representation)
Definition property.cc:81
static V8_INLINE const DirectHandle null()
Definition handles.h:661
static V8_EXPORT_PRIVATE V8_WARN_UNUSED_RESULT MaybeHandle< Map > GetDerivedMap(Isolate *isolate, DirectHandle< JSFunction > constructor, DirectHandle< JSReceiver > new_target)
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetPrototype(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Object > value, bool from_javascript, ShouldThrow should_throw)
static V8_EXPORT_PRIVATE void EnsureDescriptorSlack(Isolate *isolate, DirectHandle< Map > map, int slack)
Definition map.cc:850
static V8_EXPORT_PRIVATE void SetPrototype(Isolate *isolate, DirectHandle< Map > map, DirectHandle< JSPrototype > prototype, bool enable_prototype_setup_mode=true)
Definition map.cc:2467
static V8_WARN_UNUSED_RESULT Handle< NameDictionary > New(IsolateT *isolate, int at_least_space_for, AllocationType allocation=AllocationType::kYoung, MinimumCapacity capacity_option=USE_DEFAULT_MINIMUM_CAPACITY)
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT Maybe< bool > SetProperty(LookupIterator *it, DirectHandle< Object > value, StoreOrigin store_origin, Maybe< ShouldThrow > should_throw=Nothing< ShouldThrow >())
Definition objects.cc:2439
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
Definition objects.cc:1248
static constexpr PropertyDetails Empty(PropertyCellType cell_type=PropertyCellType::kNoCell)
static constexpr Representation Tagged()
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static V8_EXPORT_PRIVATE DirectHandle< JSFunction > GetOrCreateExternal(DirectHandle< WasmInternalFunction > internal)
static V8_EXPORT_PRIVATE DirectHandle< Object > Get(Isolate *isolate, DirectHandle< WasmTableObject > table, uint32_t index)
static DirectHandle< WasmFuncRef > GetOrCreateFuncRef(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > trusted_instance_data, int function_index)
static DirectHandle< WasmValueObject > New(Isolate *isolate, DirectHandle< String > type, DirectHandle< Object > value)
void PrintValueType(StringBuilder &out, CanonicalValueType type)
void PrintFieldName(StringBuilder &out, CanonicalTypeIndex struct_index, uint32_t field_index)
const WasmModule * module() const
V8_EXPORT_PRIVATE const CanonicalStructType * LookupStruct(CanonicalTypeIndex index) const
const ObjectRef type_
uint32_t count
static constexpr DebugProxyId kId
static constexpr char const * kClassName
WasmFrame *const frame_
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:291
Isolate * isolate
TNode< Object > receiver
std::map< const std::string, const std::string > map
ZoneVector< RpoNumber > & result
ZoneVector< Entry > entries
int SNPrintF(Vector< char > str, const char *format,...)
Definition strings.cc:20
constexpr Vector< const char > StaticCharVector(const char(&array)[N])
Definition vector.h:326
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
V8_INLINE const Operation & Get(const Graph &graph, OpIndex index)
Definition graph.h:1231
WordWithBits< 128 > Simd128
Definition index.h:236
TypeCanonicalizer * GetTypeCanonicalizer()
CanonicalTypeNamesProvider * GetCanonicalTypeNamesProvider()
DirectHandle< JSArray > GetImports(Isolate *isolate, DirectHandle< WasmModuleObject > module_object)
DirectHandle< JSArray > GetExports(Isolate *isolate, DirectHandle< WasmModuleObject > module_object)
DirectHandle< ArrayList > AddWasmModuleObjectInternalProperties(Isolate *isolate, DirectHandle< ArrayList > result, DirectHandle< WasmModuleObject > module_object)
std::unique_ptr< debug::ScopeIterator > GetWasmScopeIterator(WasmFrame *frame)
kWasmInternalFunctionIndirectPointerTag instance_data
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
@ TERMINAL_FAST_ELEMENTS_KIND
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
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 name
Definition flags.cc:2086
kMemory0SizeOffset Address kNewAllocationLimitAddressOffset Address kOldAllocationLimitAddressOffset uint8_t kGlobalsStartOffset kJumpTableStartOffset std::atomic< uint32_t > kTieringBudgetArrayOffset kDataSegmentStartsOffset kElementSegmentsOffset kInstanceObjectOffset kMemoryObjectsOffset kTaggedGlobalsBufferOffset tables
DirectHandle< JSObject > GetWasmDebugProxy(WasmFrame *frame)
DirectHandle< ArrayList > AddWasmInstanceObjectInternalProperties(Isolate *isolate, DirectHandle< ArrayList > result, DirectHandle< WasmInstanceObject > instance)
DirectHandle< ArrayList > AddWasmTableObjectInternalProperties(Isolate *isolate, DirectHandle< ArrayList > result, DirectHandle< WasmTableObject > table)
return value
Definition map-inl.h:893
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
DirectHandle< String > GetWasmFunctionDebugName(Isolate *isolate, DirectHandle< WasmTrustedInstanceData > instance_data, uint32_t func_index)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
@ DontDelete
Definition v8-object.h:147
@ ReadOnly
Definition v8-object.h:143
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
PropertyHandlerFlags
Intercepted
#define UNREACHABLE()
Definition logging.h:67
#define CHECK_LE(lhs, rhs)
#define DCHECK(condition)
Definition logging.h:482
static DirectHandle< JSObject > Create(Isolate *isolate, DirectHandle< WasmArray > value)
static constexpr char const * kClassName
static DirectHandle< Object > Get(Isolate *isolate, DirectHandle< WasmArray > array, uint32_t index)
static uint32_t Count(Isolate *isolate, DirectHandle< WasmArray > array)
static v8::Local< v8::FunctionTemplate > CreateTemplate(v8::Isolate *isolate)
static constexpr char const * kClassName
static uint32_t Count(Isolate *isolate, DirectHandle< WasmStruct > obj)
static DirectHandle< String > GetName(Isolate *isolate, DirectHandle< WasmStruct > obj, uint32_t index)
static DirectHandle< JSObject > Create(Isolate *isolate, DirectHandle< WasmStruct > value)
static DirectHandle< Object > Get(Isolate *isolate, DirectHandle< WasmStruct > obj, uint32_t index)