v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-struct.cc
Go to the documentation of this file.
1// Copyright 2022 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 <unordered_set>
6
10
11namespace v8 {
12namespace internal {
13
14constexpr int kMaxJSStructFields = 999;
15// Note: For Wasm structs, we currently allow 2000 fields, because there was
16// specific demand for that. Ideally we'd have the same limit, but JS structs
17// rely on DescriptorArrays and are hence limited to 1020 fields at most.
19
20namespace {
21
22struct NameHandleHasher {
23 size_t operator()(IndirectHandle<Name> name) const { return name->hash(); }
24};
25
26struct UniqueNameHandleEqual {
27 bool operator()(IndirectHandle<Name> x, IndirectHandle<Name> y) const {
30 return *x == *y;
31 }
32};
33
34using UniqueNameHandleSet =
35 std::unordered_set<IndirectHandle<Name>, NameHandleHasher,
36 UniqueNameHandleEqual>;
37
38} // namespace
39
40BUILTIN(SharedSpaceJSObjectHasInstance) {
41 HandleScope scope(isolate);
42 DirectHandle<Object> constructor = args.receiver();
43 if (!IsJSFunction(*constructor)) {
44 return *isolate->factory()->false_value();
45 }
46
47 bool result;
49 isolate, result,
51 Cast<JSFunction>(constructor),
52 args.atOrUndefined(isolate, 1)));
53 return *isolate->factory()->ToBoolean(result);
54}
55
56namespace {
57Maybe<bool> CollectFieldsAndElements(Isolate* isolate,
58 DirectHandle<JSReceiver> property_names,
59 int num_properties,
60 DirectHandleVector<Name>& field_names,
61 std::set<uint32_t>& element_names) {
62 Handle<Object> raw_property_name;
63 Handle<Name> property_name;
64 UniqueNameHandleSet field_names_set;
65 for (int i = 0; i < num_properties; i++) {
67 isolate, raw_property_name,
68 JSReceiver::GetElement(isolate, property_names, i), Nothing<bool>());
69 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, property_name,
70 Object::ToName(isolate, raw_property_name),
72
73 bool is_duplicate;
74 size_t index;
75 if (!property_name->AsIntegerIndex(&index) ||
77 property_name = isolate->factory()->InternalizeName(property_name);
78
79 // TODO(v8:12547): Support Symbols?
80 if (IsSymbol(*property_name)) {
82 isolate, NewTypeError(MessageTemplate::kSymbolToString),
84 }
85
86 is_duplicate = !field_names_set.insert(property_name).second;
87 // Keep the field names in the original order.
88 if (!is_duplicate) field_names.push_back(property_name);
89 } else {
90 is_duplicate = !element_names.insert(static_cast<uint32_t>(index)).second;
91 }
92
93 if (is_duplicate) {
95 isolate,
96 NewTypeError(MessageTemplate::kDuplicateTemplateProperty,
97 property_name),
99 }
100 }
101
102 return Just(true);
103}
104} // namespace
105
106BUILTIN(SharedStructTypeConstructor) {
107 DCHECK(v8_flags.shared_string_table);
108
109 HandleScope scope(isolate);
110 auto* factory = isolate->factory();
111
112 DirectHandle<Map> instance_map;
113
114 {
115 // Step 1: Collect the struct's property names and create the instance map.
116
117 DirectHandle<JSReceiver> property_names_arg;
118 if (!IsJSReceiver(*args.atOrUndefined(isolate, 1))) {
120 isolate,
121 NewTypeError(MessageTemplate::kArgumentIsNonObject,
122 factory->NewStringFromAsciiChecked("property names")));
123 }
124 property_names_arg = args.at<JSReceiver>(1);
125
126 // Treat property_names_arg as arraylike.
127 DirectHandle<Object> raw_length_number;
129 isolate, raw_length_number,
130 Object::GetLengthFromArrayLike(isolate, property_names_arg));
131 double num_properties_double = Object::NumberValue(*raw_length_number);
132 if (num_properties_double < 0 ||
133 num_properties_double > kMaxJSStructFields) {
135 isolate, NewRangeError(MessageTemplate::kStructFieldCountOutOfRange));
136 }
137 int num_properties = static_cast<int>(num_properties_double);
138
139 DirectHandleVector<Name> field_names(isolate);
140 std::set<uint32_t> element_names;
141 if (num_properties != 0) {
143 CollectFieldsAndElements(isolate, property_names_arg, num_properties,
144 field_names, element_names),
145 ReadOnlyRoots(isolate).exception());
146 }
147
148 if (IsUndefined(*args.atOrUndefined(isolate, 2), isolate)) {
149 // Create a new instance map if this type isn't registered.
151 isolate, base::VectorOf(field_names), element_names, {});
152 } else {
153 // Otherwise, get the canonical map.
154 if (!IsString(*args.atOrUndefined(isolate, 2))) {
156 isolate, NewTypeError(MessageTemplate::kArgumentIsNonString,
157 factory->NewStringFromAsciiChecked(
158 "type registry key")));
159 }
161 isolate, instance_map,
162 isolate->shared_struct_type_registry()->Register(
163 isolate, args.at<String>(2), base::VectorOf(field_names),
164 element_names));
165 }
166 }
167
168 // Step 2: Creat the JSFunction constructor. This is always created anew,
169 // regardless of whether the type is registered.
171 isolate->factory()->NewSharedFunctionInfoForBuiltin(
172 isolate->factory()->empty_string(), Builtin::kSharedStructConstructor,
173 0, kAdapt);
174
175 DirectHandle<JSFunction> constructor =
177 .set_map(isolate->strict_function_with_readonly_prototype_map())
178 .Build();
179 constructor->set_prototype_or_initial_map(*instance_map, kReleaseStore);
180
182 isolate, constructor, factory->has_instance_symbol(),
184 isolate->native_context()->shared_space_js_object_has_instance(),
185 isolate),
187
188 return *constructor;
189}
190
191BUILTIN(SharedStructConstructor) {
192 HandleScope scope(isolate);
193 DirectHandle<JSFunction> constructor(args.target());
194 DirectHandle<Map> instance_map(constructor->initial_map(), isolate);
195 return *isolate->factory()->NewJSSharedStruct(
196 args.target(),
197 JSSharedStruct::GetElementsTemplate(isolate, *instance_map));
198}
199
200BUILTIN(SharedStructTypeIsSharedStruct) {
201 HandleScope scope(isolate);
202 return isolate->heap()->ToBoolean(
203 IsJSSharedStruct(*args.atOrUndefined(isolate, 1)));
204}
205
206BUILTIN(AtomicsMutexIsMutex) {
207 HandleScope scope(isolate);
208 return isolate->heap()->ToBoolean(
209 IsJSAtomicsMutex(*args.atOrUndefined(isolate, 1)));
210}
211
212BUILTIN(AtomicsConditionIsCondition) {
213 HandleScope scope(isolate);
214 return isolate->heap()->ToBoolean(
215 IsJSAtomicsCondition(*args.atOrUndefined(isolate, 1)));
216}
217
218} // namespace internal
219} // namespace v8
#define BUILTIN(name)
static Maybe< bool > HasInstance(Isolate *isolate, DirectHandle< JSFunction > constructor, DirectHandle< Object > object)
Definition js-struct.cc:96
JSFunctionBuilder & set_map(DirectHandle< Map > v)
Definition factory.h:1116
V8_WARN_UNUSED_RESULT Handle< JSFunction > Build()
Definition factory.cc:4732
Handle< NativeContext > native_context()
Definition isolate-inl.h:48
static V8_EXPORT_PRIVATE void AddProperty(Isolate *isolate, DirectHandle< JSObject > object, DirectHandle< Name > name, DirectHandle< Object > value, PropertyAttributes attributes)
static constexpr uint32_t kMaxElementIndex
Definition js-objects.h:924
static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetElement(Isolate *isolate, DirectHandle< JSReceiver > receiver, uint32_t index)
static MaybeDirectHandle< NumberDictionary > GetElementsTemplate(Isolate *isolate, Tagged< Map > instance_map)
Definition js-struct.cc:293
static DirectHandle< Map > CreateInstanceMap(Isolate *isolate, const base::Vector< const DirectHandle< Name > > field_names, const std::set< uint32_t > &element_names, MaybeDirectHandle< String > maybe_registry_key)
Definition js-struct.cc:165
static double NumberValue(Tagged< Number > obj)
static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > GetLengthFromArrayLike(Isolate *isolate, DirectHandle< JSReceiver > object)
Definition objects.cc:1238
static V8_WARN_UNUSED_RESULT HandleType< Name >::MaybeType ToName(Isolate *isolate, HandleType< Object > input)
Handle< SharedFunctionInfo > info
#define THROW_NEW_ERROR_RETURN_VALUE(isolate, call, value)
Definition isolate.h:300
#define ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:284
#define ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, dst, call, value)
Definition isolate.h:276
#define THROW_NEW_ERROR_RETURN_FAILURE(isolate, call)
Definition isolate.h:294
#define MAYBE_RETURN(call, value)
Definition isolate.h:408
#define MAYBE_ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:448
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
Isolate * isolate
ZoneVector< RpoNumber > & result
int x
constexpr Vector< T > VectorOf(T *start, size_t size)
Definition vector.h:360
V8_INLINE DirectHandle< T > direct_handle(Tagged< T > object, Isolate *isolate)
static const int kMaxNumberOfDescriptors
constexpr AdaptArguments kAdapt
Definition globals.h:2775
V8_EXPORT_PRIVATE FlagValues v8_flags
constexpr int kMaxJSStructFields
bool IsUniqueName(Tagged< Name > obj)
Tagged< To > Cast(Tagged< From > value, const v8::SourceLocation &loc=INIT_SOURCE_LOCATION_IN_DEBUG)
Definition casting.h:150
static constexpr ReleaseStoreTag kReleaseStore
Definition globals.h:2910
Maybe< T > Nothing()
Definition v8-maybe.h:112
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define DCHECK(condition)
Definition logging.h:482