v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
runtime-classes.cc
Go to the documentation of this file.
1// Copyright 2014 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 <stdlib.h>
6
7#include <limits>
8
10#include "src/common/globals.h"
14#include "src/logging/log.h"
18#include "src/objects/smi.h"
19#include "src/runtime/runtime.h"
20
21namespace v8 {
22namespace internal {
23
24
25RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
26 HandleScope scope(isolate);
27 DCHECK_EQ(0, args.length());
29 isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
30}
31
32
33RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
34 HandleScope scope(isolate);
35 DCHECK_EQ(1, args.length());
36 DirectHandle<JSFunction> constructor = args.at<JSFunction>(0);
37 DirectHandle<String> name(constructor->shared()->Name(), isolate);
38
39 DirectHandle<Context> context(constructor->native_context(), isolate);
40 DCHECK(IsNativeContext(*context));
41 DirectHandle<JSFunction> realm_type_error_function(
42 Cast<JSFunction>(context->get(Context::TYPE_ERROR_FUNCTION_INDEX)),
43 isolate);
44 if (name->length() == 0) {
46 isolate, NewError(realm_type_error_function,
47 MessageTemplate::kAnonymousConstructorNonCallable));
48 }
50 isolate, NewError(realm_type_error_function,
51 MessageTemplate::kConstructorNonCallable, name));
52}
53
54
55RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
56 HandleScope scope(isolate);
57 DCHECK_EQ(0, args.length());
59 isolate, NewTypeError(MessageTemplate::kStaticPrototype));
60}
61
62RUNTIME_FUNCTION(Runtime_ThrowSuperAlreadyCalledError) {
63 HandleScope scope(isolate);
64 DCHECK_EQ(0, args.length());
66 isolate, NewReferenceError(MessageTemplate::kSuperAlreadyCalled));
67}
68
69RUNTIME_FUNCTION(Runtime_ThrowSuperNotCalled) {
70 HandleScope scope(isolate);
71 DCHECK_EQ(0, args.length());
73 isolate, NewReferenceError(MessageTemplate::kSuperNotCalled));
74}
75
76namespace {
77
78Tagged<Object> ThrowNotSuperConstructor(Isolate* isolate,
79 DirectHandle<Object> constructor,
80 DirectHandle<JSFunction> function) {
81 DirectHandle<String> super_name;
82 if (IsJSFunction(*constructor)) {
83 super_name =
84 direct_handle(Cast<JSFunction>(constructor)->shared()->Name(), isolate);
85 } else if (IsOddball(*constructor)) {
86 DCHECK(IsNull(*constructor, isolate));
87 super_name = isolate->factory()->null_string();
88 } else {
89 super_name = Object::NoSideEffectsToString(isolate, constructor);
90 }
91 // null constructor
92 if (super_name->length() == 0) {
93 super_name = isolate->factory()->null_string();
94 }
95 Handle<String> function_name(function->shared()->Name(), isolate);
96 // anonymous class
97 if (function_name->length() == 0) {
99 isolate,
100 NewTypeError(MessageTemplate::kNotSuperConstructorAnonymousClass,
101 super_name));
102 }
104 isolate, NewTypeError(MessageTemplate::kNotSuperConstructor, super_name,
105 function_name));
106}
107
108} // namespace
109
110RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
111 HandleScope scope(isolate);
112 DCHECK_EQ(2, args.length());
113 DirectHandle<Object> constructor = args.at(0);
114 DirectHandle<JSFunction> function = args.at<JSFunction>(1);
115 return ThrowNotSuperConstructor(isolate, constructor, function);
116}
117
118namespace {
119
120template <typename Dictionary>
121Handle<Name> KeyToName(Isolate* isolate, Handle<Object> key) {
122 static_assert((std::is_same_v<Dictionary, SwissNameDictionary> ||
123 std::is_same_v<Dictionary, NameDictionary>));
124 DCHECK(IsName(*key));
125 return Cast<Name>(key);
126}
127
128template <>
129Handle<Name> KeyToName<NumberDictionary>(Isolate* isolate, Handle<Object> key) {
131 return isolate->factory()->NumberToString(key);
132}
133
134// Gets |index|'th argument which may be a class constructor object, a class
135// prototype object or a class method. In the latter case the following
136// post-processing may be required:
137// 1) set method's name to a concatenation of |name_prefix| and |key| if the
138// method's shared function info indicates that method does not have a
139// shared name.
140template <typename Dictionary>
141MaybeDirectHandle<Object> GetMethodAndSetName(Isolate* isolate,
143 Tagged<Smi> index,
144 DirectHandle<String> name_prefix,
145 Handle<Object> key) {
146 int int_index = index.value();
147
148 // Class constructor and prototype values do not require post processing.
150 return args.at<Object>(int_index);
151 }
152
153 DirectHandle<JSFunction> method = args.at<JSFunction>(int_index);
154
155 if (!method->shared()->HasSharedName()) {
156 // TODO(ishell): method does not have a shared name at this point only if
157 // the key is a computed property name. However, the bytecode generator
158 // explicitly generates ToName bytecodes to ensure that the computed
159 // property name is properly converted to Name. So, we can actually be smart
160 // here and avoid converting Smi keys back to Name.
161 DirectHandle<Name> name = KeyToName<Dictionary>(isolate, key);
162 if (!JSFunction::SetName(method, name, name_prefix)) {
163 return MaybeDirectHandle<Object>();
164 }
165 }
166 return method;
167}
168
169// Gets |index|'th argument which may be a class constructor object, a class
170// prototype object or a class method.
171// This is a simplified version of GetMethodAndSetName()
172// function above that is used when it's guaranteed that the method has
173// shared name.
174Tagged<Object> GetMethodWithSharedName(Isolate* isolate, RuntimeArguments& args,
175 Tagged<Object> index) {
177 int int_index = Smi::ToInt(index);
178
179 // Class constructor and prototype values do not require post processing.
181 return args[int_index];
182 }
183
184 DirectHandle<JSFunction> method = args.at<JSFunction>(int_index);
185 DCHECK(method->shared()->HasSharedName());
186 return *method;
187}
188
189template <typename Dictionary>
190Handle<Dictionary> ShallowCopyDictionaryTemplate(
191 Isolate* isolate, DirectHandle<Dictionary> dictionary_template) {
192 Handle<Dictionary> dictionary =
193 Dictionary::ShallowCopy(isolate, dictionary_template);
194 // Clone all AccessorPairs in the dictionary.
195 for (InternalIndex i : dictionary->IterateEntries()) {
196 Tagged<Object> value = dictionary->ValueAt(i);
197 if (IsAccessorPair(value)) {
198 DirectHandle<AccessorPair> pair(Cast<AccessorPair>(value), isolate);
199 pair = AccessorPair::Copy(isolate, pair);
200 dictionary->ValueAtPut(i, *pair);
201 }
202 }
203 return dictionary;
204}
205
206template <typename Dictionary>
207bool SubstituteValues(Isolate* isolate, DirectHandle<Dictionary> dictionary,
209 // Replace all indices with proper methods.
210 ReadOnlyRoots roots(isolate);
211 for (InternalIndex i : dictionary->IterateEntries()) {
212 Tagged<Object> maybe_key = dictionary->KeyAt(i);
213 if (!Dictionary::IsKey(roots, maybe_key)) continue;
214 Handle<Object> key(maybe_key, isolate);
215 Handle<Object> value(dictionary->ValueAt(i), isolate);
216 if (IsAccessorPair(*value)) {
217 auto pair = Cast<AccessorPair>(value);
218 Tagged<Object> tmp = pair->getter();
219 if (IsSmi(tmp)) {
220 DirectHandle<Object> result;
222 isolate, result,
223 GetMethodAndSetName<Dictionary>(isolate, args, Cast<Smi>(tmp),
224 isolate->factory()->get_string(),
225 key),
226 false);
227 pair->set_getter(*result);
228 }
229 tmp = pair->setter();
230 if (IsSmi(tmp)) {
231 DirectHandle<Object> result;
233 isolate, result,
234 GetMethodAndSetName<Dictionary>(isolate, args, Cast<Smi>(tmp),
235 isolate->factory()->set_string(),
236 key),
237 false);
238 pair->set_setter(*result);
239 }
240 } else if (IsSmi(*value)) {
241 DirectHandle<Object> result;
243 isolate, result,
244 GetMethodAndSetName<Dictionary>(isolate, args, Cast<Smi>(*value),
245 isolate->factory()->empty_string(),
246 key),
247 false);
248 dictionary->ValueAtPut(i, *result);
249 }
250 }
251 return true;
252}
253
254template <typename Dictionary>
255void UpdateProtectors(Isolate* isolate, DirectHandle<JSObject> receiver,
256 DirectHandle<Dictionary> properties_dictionary) {
257 ReadOnlyRoots roots(isolate);
258 for (InternalIndex i : properties_dictionary->IterateEntries()) {
259 Tagged<Object> maybe_key = properties_dictionary->KeyAt(i);
260 if (!Dictionary::IsKey(roots, maybe_key)) continue;
261 DirectHandle<Name> name(Cast<Name>(maybe_key), isolate);
263 }
264}
265
266void UpdateProtectors(Isolate* isolate, DirectHandle<JSObject> receiver,
267 DirectHandle<DescriptorArray> properties_template) {
268 int nof_descriptors = properties_template->number_of_descriptors();
269 for (InternalIndex i : InternalIndex::Range(nof_descriptors)) {
270 DirectHandle<Name> name(properties_template->GetKey(i), isolate);
272 }
273}
274
275bool AddDescriptorsByTemplate(
276 Isolate* isolate, DirectHandle<Map> map,
277 DirectHandle<DescriptorArray> descriptors_template,
278 DirectHandle<NumberDictionary> elements_dictionary_template,
279 DirectHandle<JSObject> receiver, RuntimeArguments& args) {
280 int nof_descriptors = descriptors_template->number_of_descriptors();
281
282 DirectHandle<DescriptorArray> descriptors =
283 DescriptorArray::Allocate(isolate, nof_descriptors, 0);
284
285 DirectHandle<NumberDictionary> elements_dictionary =
286 *elements_dictionary_template ==
287 ReadOnlyRoots(isolate).empty_slow_element_dictionary()
288 ? elements_dictionary_template
289 : ShallowCopyDictionaryTemplate(isolate,
290 elements_dictionary_template);
291
292 // Count the number of properties that must be in the instance and
293 // create the property array to hold the constants.
294 int count = 0;
295 for (InternalIndex i : InternalIndex::Range(nof_descriptors)) {
296 PropertyDetails details = descriptors_template->GetDetails(i);
297 if (details.location() == PropertyLocation::kDescriptor &&
298 details.kind() == PropertyKind::kData) {
299 count++;
300 }
301 }
302 DirectHandle<PropertyArray> property_array =
303 isolate->factory()->NewPropertyArray(count);
304
305 // Read values from |descriptors_template| and store possibly post-processed
306 // values into "instantiated" |descriptors| array.
307 int field_index = 0;
308 for (InternalIndex i : InternalIndex::Range(nof_descriptors)) {
309 Tagged<Object> value = descriptors_template->GetStrongValue(i);
310 if (IsAccessorPair(value)) {
311 DirectHandle<AccessorPair> pair = AccessorPair::Copy(
312 isolate, direct_handle(Cast<AccessorPair>(value), isolate));
313 value = *pair;
314 }
316 Tagged<Name> name = descriptors_template->GetKey(i);
317 // TODO(v8:5799): consider adding a ClassBoilerplate flag
318 // "has_interesting_properties".
319 if (name->IsInteresting(isolate)) {
320 map->set_may_have_interesting_properties(true);
321 }
322 DCHECK(IsUniqueName(name));
323 PropertyDetails details = descriptors_template->GetDetails(i);
324 if (details.location() == PropertyLocation::kDescriptor) {
325 if (details.kind() == PropertyKind::kData) {
326 if (IsSmi(value)) {
327 value = GetMethodWithSharedName(isolate, args, value);
328 }
329 details = details.CopyWithRepresentation(
330 Object::OptimalRepresentation(value, isolate));
331 } else {
332 DCHECK_EQ(PropertyKind::kAccessor, details.kind());
333 if (IsAccessorPair(value)) {
335 Tagged<Object> tmp = pair->getter();
336 if (IsSmi(tmp)) {
337 pair->set_getter(GetMethodWithSharedName(isolate, args, tmp));
338 }
339 tmp = pair->setter();
340 if (IsSmi(tmp)) {
341 pair->set_setter(GetMethodWithSharedName(isolate, args, tmp));
342 }
343 }
344 }
345 } else {
346 UNREACHABLE();
347 }
348 DCHECK(Object::FitsRepresentation(value, details.representation()));
349 if (details.location() == PropertyLocation::kDescriptor &&
350 details.kind() == PropertyKind::kData) {
351 details =
352 PropertyDetails(details.kind(), details.attributes(),
354 details.representation(), field_index)
355 .set_pointer(details.pointer());
356
357 property_array->set(field_index, value);
358 field_index++;
359 descriptors->Set(i, name, FieldType::Any(), details);
360 } else {
361 descriptors->Set(i, name, value, details);
362 }
363 }
364
365 UpdateProtectors(isolate, receiver, descriptors_template);
366
367 map->InitializeDescriptors(isolate, *descriptors);
368 if (elements_dictionary->NumberOfElements() > 0) {
369 if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
370 args)) {
371 return false;
372 }
373 map->set_elements_kind(DICTIONARY_ELEMENTS);
374 }
375
376 // Atomically commit the changes.
377 receiver->set_map(isolate, *map, kReleaseStore);
378 if (elements_dictionary->NumberOfElements() > 0) {
379 receiver->set_elements(*elements_dictionary);
380 }
381 if (property_array->length() > 0) {
382 receiver->SetProperties(*property_array);
383 }
384 return true;
385}
386
387// TODO(v8:7569): This is a workaround for the Handle vs MaybeHandle difference
388// in the return types of the different Add functions:
389// OrderedNameDictionary::Add returns MaybeHandle, NameDictionary::Add returns
390// Handle.
391template <typename T>
392DirectHandle<T> ToHandle(Handle<T> h) {
393 return h;
394}
395template <typename T>
396DirectHandle<T> ToHandle(MaybeHandle<T> h) {
397 return h.ToHandleChecked();
398}
399
400template <typename Dictionary>
401bool AddDescriptorsByTemplate(
402 Isolate* isolate, DirectHandle<Map> map,
403 DirectHandle<Dictionary> properties_dictionary_template,
404 DirectHandle<NumberDictionary> elements_dictionary_template,
405 DirectHandle<FixedArray> computed_properties,
406 DirectHandle<JSObject> receiver, RuntimeArguments& args) {
407 int computed_properties_length = computed_properties->length();
408
409 // Shallow-copy properties template.
410 Handle<Dictionary> properties_dictionary =
411 ShallowCopyDictionaryTemplate(isolate, properties_dictionary_template);
412 Handle<NumberDictionary> elements_dictionary =
413 ShallowCopyDictionaryTemplate(isolate, elements_dictionary_template);
414
416 using ComputedEntryFlags = ClassBoilerplate::ComputedEntryFlags;
417
418 // Merge computed properties with properties and elements dictionary
419 // templates.
420 int i = 0;
421 while (i < computed_properties_length) {
422 int flags = Smi::ToInt(computed_properties->get(i++));
423
424 ValueKind value_kind = ComputedEntryFlags::ValueKindBits::decode(flags);
425 int key_index = ComputedEntryFlags::KeyIndexBits::decode(flags);
426 Tagged<Smi> value = Smi::FromInt(key_index + 1); // Value follows name.
427
428 Handle<Object> key = args.at(key_index);
429 DCHECK(IsName(*key));
430 uint32_t element;
432 if (name->AsArrayIndex(&element)) {
434 isolate, elements_dictionary, element, key_index, value_kind, value);
435
436 } else {
437 name = isolate->factory()->InternalizeName(name);
439 isolate, properties_dictionary, name, key_index, value_kind, value);
440 if (name->IsInteresting(isolate)) {
441 // TODO(pthier): Add flags to swiss dictionaries.
443 properties_dictionary->set_may_have_interesting_properties(true);
444 }
445 }
446 }
447 }
448
449 // Replace all indices with proper methods.
450 if (!SubstituteValues<Dictionary>(isolate, properties_dictionary, args)) {
451 return false;
452 }
453
454 UpdateProtectors(isolate, receiver,
455 DirectHandle<Dictionary>(properties_dictionary));
456
457 if (elements_dictionary->NumberOfElements() > 0) {
458 if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
459 args)) {
460 return false;
461 }
462 map->set_elements_kind(DICTIONARY_ELEMENTS);
463 }
464
465 // Atomically commit the changes.
466 receiver->set_map(isolate, *map, kReleaseStore);
467 receiver->set_raw_properties_or_hash(*properties_dictionary, kRelaxedStore);
468 if (elements_dictionary->NumberOfElements() > 0) {
469 receiver->set_elements(*elements_dictionary);
470 }
471 return true;
472}
473
474DirectHandle<JSObject> CreateClassPrototype(Isolate* isolate) {
475 // For constant tracking we want to avoid the hassle of handling
476 // in-object properties, so create a map with no in-object
477 // properties.
478
479 // TODO(ishell) Support caching of zero in-object properties map
480 // by ObjectLiteralMapFromCache().
481 DirectHandle<Map> map = Map::Create(isolate, 0);
482 return isolate->factory()->NewJSObjectFromMap(map);
483}
484
485bool InitClassPrototype(Isolate* isolate,
486 DirectHandle<ClassBoilerplate> class_boilerplate,
487 DirectHandle<JSObject> prototype,
488 DirectHandle<JSPrototype> prototype_parent,
489 DirectHandle<JSFunction> constructor,
491 DirectHandle<Map> map(prototype->map(), isolate);
492 map = Map::CopyDropDescriptors(isolate, map);
493 map->set_is_prototype_map(true);
494 Map::SetPrototype(isolate, map, prototype_parent);
495 isolate->UpdateProtectorsOnSetPrototype(prototype, prototype_parent);
496 constructor->set_prototype_or_initial_map(*prototype, kReleaseStore);
497 map->SetConstructor(*constructor);
498 DirectHandle<FixedArray> computed_properties(
499 class_boilerplate->instance_computed_properties(), isolate);
500 DirectHandle<NumberDictionary> elements_dictionary_template(
501 Cast<NumberDictionary>(class_boilerplate->instance_elements_template()),
502 isolate);
503
504 Handle<Object> properties_template(
505 class_boilerplate->instance_properties_template(), isolate);
506
507 if (IsDescriptorArray(*properties_template)) {
508 auto descriptors_template = Cast<DescriptorArray>(properties_template);
509
510 // The size of the prototype object is known at this point.
511 // So we can create it now and then add the rest instance methods to the
512 // map.
513 return AddDescriptorsByTemplate(isolate, map, descriptors_template,
514 elements_dictionary_template, prototype,
515 args);
516 } else {
517 map->set_is_dictionary_map(true);
518 map->set_is_migration_target(false);
519 map->set_may_have_interesting_properties(true);
520 map->set_construction_counter(Map::kNoSlackTracking);
521
522 DirectHandle<PropertyDictionary> properties_dictionary_template =
523 Cast<PropertyDictionary>(properties_template);
524 return AddDescriptorsByTemplate(
525 isolate, map, properties_dictionary_template,
526 elements_dictionary_template, computed_properties, prototype, args);
527 }
528}
529
530bool InitClassConstructor(Isolate* isolate,
531 DirectHandle<ClassBoilerplate> class_boilerplate,
532 DirectHandle<JSPrototype> constructor_parent,
533 DirectHandle<JSFunction> constructor,
535 DirectHandle<Map> map(constructor->map(), isolate);
536 map = Map::CopyDropDescriptors(isolate, map);
537 DCHECK(map->is_prototype_map());
538
539 if (!constructor_parent.is_null()) {
540 // Set map's prototype without enabling prototype setup mode for superclass
541 // because it does not make sense.
542 Map::SetPrototype(isolate, map, constructor_parent, false);
543 // Ensure that setup mode will never be enabled for superclass.
544 JSObject::MakePrototypesFast(constructor_parent, kStartAtReceiver, isolate);
545 }
546
547 DirectHandle<NumberDictionary> elements_dictionary_template(
548 Cast<NumberDictionary>(class_boilerplate->static_elements_template()),
549 isolate);
550 DirectHandle<FixedArray> computed_properties(
551 class_boilerplate->static_computed_properties(), isolate);
552
553 Handle<Object> properties_template(
554 class_boilerplate->static_properties_template(), isolate);
555
556 if (IsDescriptorArray(*properties_template)) {
557 auto descriptors_template = Cast<DescriptorArray>(properties_template);
558
559 return AddDescriptorsByTemplate(isolate, map, descriptors_template,
560 elements_dictionary_template, constructor,
561 args);
562 } else {
563 map->set_is_dictionary_map(true);
564 map->InitializeDescriptors(isolate,
565 ReadOnlyRoots(isolate).empty_descriptor_array());
566 map->set_is_migration_target(false);
567 map->set_may_have_interesting_properties(true);
568 map->set_construction_counter(Map::kNoSlackTracking);
569
571 DirectHandle<SwissNameDictionary> properties_dictionary_template =
572 Cast<SwissNameDictionary>(properties_template);
573
574 return AddDescriptorsByTemplate(
575 isolate, map, properties_dictionary_template,
576 elements_dictionary_template, computed_properties, constructor, args);
577 } else {
578 DirectHandle<NameDictionary> properties_dictionary_template =
579 Cast<NameDictionary>(properties_template);
580 return AddDescriptorsByTemplate(
581 isolate, map, properties_dictionary_template,
582 elements_dictionary_template, computed_properties, constructor, args);
583 }
584 }
585}
586
587MaybeDirectHandle<Object> DefineClass(
588 Isolate* isolate, DirectHandle<ClassBoilerplate> class_boilerplate,
589 DirectHandle<Object> super_class, DirectHandle<JSFunction> constructor,
591 DirectHandle<JSPrototype> prototype_parent;
592 DirectHandle<JSPrototype> constructor_parent;
593
594 if (IsTheHole(*super_class, isolate)) {
595 prototype_parent = isolate->initial_object_prototype();
596 } else {
597 if (IsNull(*super_class, isolate)) {
598 prototype_parent = isolate->factory()->null_value();
599 } else if (IsConstructor(*super_class)) {
600 DCHECK(!IsJSFunction(*super_class) ||
602 Cast<JSFunction>(super_class)->shared()->kind()));
603 DirectHandle<Object> maybe_prototype_parent;
605 isolate, maybe_prototype_parent,
606 Runtime::GetObjectProperty(isolate, Cast<JSAny>(super_class),
607 isolate->factory()->prototype_string()));
608 if (!TryCast(maybe_prototype_parent, &prototype_parent)) {
610 isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
611 maybe_prototype_parent));
612 }
613 // Create new handle to avoid |constructor_parent| corruption because of
614 // |super_class| handle value overwriting via storing to
615 // args[ClassBoilerplate::kPrototypeArgumentIndex] below.
616 constructor_parent =
617 direct_handle(Cast<JSPrototype>(*super_class), isolate);
618 } else {
619 THROW_NEW_ERROR(isolate,
620 NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
621 super_class));
622 }
623 }
624
625 DirectHandle<JSObject> prototype = CreateClassPrototype(isolate);
627 // Temporarily change ClassBoilerplate::kPrototypeArgumentIndex for the
628 // subsequent calls, but use a scope to make sure to change it back before
629 // returning, to not corrupt the caller's argument frame (in particular, for
630 // the interpreter, to not clobber the register frame).
631 RuntimeArguments::ChangeValueScope set_prototype_value_scope(
632 isolate, &args, ClassBoilerplate::kPrototypeArgumentIndex, *prototype);
633
634 if (!InitClassConstructor(isolate, class_boilerplate, constructor_parent,
635 constructor, args) ||
636 !InitClassPrototype(isolate, class_boilerplate, prototype,
637 prototype_parent, constructor, args)) {
638 DCHECK(isolate->has_exception());
639 return MaybeDirectHandle<Object>();
640 }
641 if (v8_flags.log_maps) {
642 DirectHandle<Map> empty_map;
643 LOG(isolate,
644 MapEvent("InitialMap", empty_map,
645 direct_handle(constructor->map(), isolate),
646 "init class constructor",
648 isolate, direct_handle(constructor->shared(), isolate))));
649 LOG(isolate, MapEvent("InitialMap", empty_map,
650 direct_handle(prototype->map(), isolate),
651 "init class prototype"));
652 }
653
654 return prototype;
655}
656
657} // namespace
658
659RUNTIME_FUNCTION(Runtime_DefineClass) {
660 HandleScope scope(isolate);
662 DirectHandle<ClassBoilerplate> class_boilerplate =
663 args.at<ClassBoilerplate>(0);
664 DirectHandle<JSFunction> constructor = args.at<JSFunction>(1);
665 DirectHandle<Object> super_class = args.at(2);
666 DCHECK_EQ(class_boilerplate->arguments_count(), args.length());
667
669 isolate,
670 DefineClass(isolate, class_boilerplate, super_class, constructor, args));
671}
672
673namespace {
674
675enum class SuperMode { kLoad, kStore };
676
677MaybeDirectHandle<JSReceiver> GetSuperHolder(Isolate* isolate,
678 DirectHandle<JSObject> home_object,
679 SuperMode mode, PropertyKey* key) {
680 if (IsAccessCheckNeeded(*home_object) &&
681 !isolate->MayAccess(isolate->native_context(), home_object)) {
682 RETURN_ON_EXCEPTION(isolate, isolate->ReportFailedAccessCheck(home_object));
683 UNREACHABLE();
684 }
685
686 PrototypeIterator iter(isolate, home_object);
687 DirectHandle<Object> proto = PrototypeIterator::GetCurrent(iter);
688 if (!IsJSReceiver(*proto)) {
689 MessageTemplate message =
690 mode == SuperMode::kLoad
691 ? MessageTemplate::kNonObjectPropertyLoadWithProperty
692 : MessageTemplate::kNonObjectPropertyStoreWithProperty;
693 DirectHandle<Name> name = key->GetName(isolate);
694 THROW_NEW_ERROR(isolate, NewTypeError(message, proto, name));
695 }
696 return Cast<JSReceiver>(proto);
697}
698
699MaybeDirectHandle<Object> LoadFromSuper(Isolate* isolate,
700 DirectHandle<JSAny> receiver,
701 DirectHandle<JSObject> home_object,
702 PropertyKey* key) {
703 DirectHandle<JSReceiver> holder;
705 isolate, holder,
706 GetSuperHolder(isolate, home_object, SuperMode::kLoad, key));
707 LookupIterator it(isolate, receiver, *key, holder);
708 DirectHandle<Object> result;
710 return result;
711}
712
713} // anonymous namespace
714
715RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
716 HandleScope scope(isolate);
717 DCHECK_EQ(3, args.length());
719 DirectHandle<JSObject> home_object = args.at<JSObject>(1);
720 DirectHandle<Name> name = args.at<Name>(2);
721
722 PropertyKey key(isolate, name);
723
725 LoadFromSuper(isolate, receiver, home_object, &key));
726}
727
728
729RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
730 HandleScope scope(isolate);
731 DCHECK_EQ(3, args.length());
733 DirectHandle<JSObject> home_object = args.at<JSObject>(1);
734 // TODO(ishell): To improve performance, consider performing the to-string
735 // conversion of {key} before calling into the runtime.
737
738 bool success;
739 PropertyKey lookup_key(isolate, key, &success);
740 if (!success) return ReadOnlyRoots(isolate).exception();
741
743 isolate, LoadFromSuper(isolate, receiver, home_object, &lookup_key));
744}
745
746namespace {
747
748MaybeDirectHandle<Object> StoreToSuper(Isolate* isolate,
749 DirectHandle<JSObject> home_object,
750 DirectHandle<JSAny> receiver,
751 PropertyKey* key,
752 DirectHandle<Object> value,
753 StoreOrigin store_origin) {
754 DirectHandle<JSReceiver> holder;
756 isolate, holder,
757 GetSuperHolder(isolate, home_object, SuperMode::kStore, key));
758 LookupIterator it(isolate, receiver, *key, holder);
759 MAYBE_RETURN(Object::SetSuperProperty(&it, value, store_origin),
760 MaybeDirectHandle<Object>());
761 return value;
762}
763
764} // anonymous namespace
765
766RUNTIME_FUNCTION(Runtime_StoreToSuper) {
767 HandleScope scope(isolate);
768 DCHECK_EQ(4, args.length());
770 DirectHandle<JSObject> home_object = args.at<JSObject>(1);
771 DirectHandle<Name> name = args.at<Name>(2);
772 DirectHandle<Object> value = args.at(3);
773
774 PropertyKey key(isolate, name);
775
777 isolate, StoreToSuper(isolate, home_object, receiver, &key, value,
779}
780
781RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper) {
782 HandleScope scope(isolate);
783 DCHECK_EQ(4, args.length());
785 DirectHandle<JSObject> home_object = args.at<JSObject>(1);
786 // TODO(ishell): To improve performance, consider performing the to-string
787 // conversion of {key} before calling into the runtime.
789 DirectHandle<Object> value = args.at(3);
790
791 bool success;
792 PropertyKey lookup_key(isolate, key, &success);
793 if (!success) return ReadOnlyRoots(isolate).exception();
794
796 isolate, StoreToSuper(isolate, home_object, receiver, &lookup_key, value,
798}
799
800} // namespace internal
801} // namespace v8
Builtins::Kind kind
Definition builtins.cc:40
static NEVER_READ_ONLY_SPACE DirectHandle< AccessorPair > Copy(Isolate *isolate, DirectHandle< AccessorPair > pair)
Definition objects.cc:4004
static void AddToPropertiesTemplate(IsolateT *isolate, Handle< Dictionary > dictionary, Handle< Name > name, int key_index, ValueKind value_kind, Tagged< Smi > value)
static void AddToElementsTemplate(IsolateT *isolate, Handle< NumberDictionary > dictionary, uint32_t key, int key_index, ValueKind value_kind, Tagged< Smi > value)
static V8_EXPORT_PRIVATE Handle< DescriptorArray > Allocate(IsolateT *isolate, int nof_descriptors, int slack, AllocationType allocation=AllocationType::kYoung)
static V8_EXPORT_PRIVATE Tagged< FieldType > Any()
Definition field-type.cc:22
static V8_WARN_UNUSED_RESULT bool SetName(DirectHandle< JSFunction > function, DirectHandle< Name > name, DirectHandle< String > prefix)
static void MakePrototypesFast(DirectHandle< Object > receiver, WhereToStart where_to_start, Isolate *isolate)
static V8_EXPORT_PRIVATE Handle< Map > Create(Isolate *isolate, int inobject_properties)
Definition map.cc:1824
static const int kNoSlackTracking
Definition map.h:349
static Handle< Map > CopyDropDescriptors(Isolate *isolate, DirectHandle< Map > map)
Definition map.cc:1480
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_EXPORT_PRIVATE DirectHandle< String > NoSideEffectsToString(Isolate *isolate, DirectHandle< Object > input)
Definition objects.cc:687
static Representation OptimalRepresentation(Tagged< Object > obj, PtrComprCageBase cage_base)
static V8_WARN_UNUSED_RESULT Maybe< bool > SetSuperProperty(LookupIterator *it, DirectHandle< Object > value, StoreOrigin store_origin, Maybe< ShouldThrow > should_throw=Nothing< ShouldThrow >())
Definition objects.cc:2455
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeHandle< Object > GetProperty(LookupIterator *it, bool is_global_reference=false)
Definition objects.cc:1248
static bool FitsRepresentation(Tagged< Object > obj, Representation representation, bool allow_coercion=true)
Tagged< T > GetCurrent() const
Definition prototype.h:52
V8_EXPORT_PRIVATE static V8_WARN_UNUSED_RESULT MaybeDirectHandle< Object > GetObjectProperty(Isolate *isolate, DirectHandle< JSAny > lookup_start_object, DirectHandle< Object > key, DirectHandle< JSAny > receiver={}, bool *is_found=nullptr)
static Handle< String > DebugName(Isolate *isolate, DirectHandle< SharedFunctionInfo > shared)
static constexpr int ToInt(const Tagged< Object > object)
Definition smi.h:33
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
#define V8_ENABLE_SWISS_NAME_DICTIONARY_BOOL
Definition globals.h:242
#define RUNTIME_FUNCTION(Name)
Definition arguments.h:162
#define RETURN_ON_EXCEPTION(isolate, call)
Definition isolate.h:395
#define ASSIGN_RETURN_ON_EXCEPTION(isolate, dst, call)
Definition isolate.h:291
#define THROW_NEW_ERROR(isolate, call)
Definition isolate.h:307
#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 RETURN_RESULT_OR_FAILURE(isolate, call)
Definition isolate.h:264
base::Vector< const DirectHandle< Object > > args
Definition execution.cc:74
TNode< Context > context
TNode< Object > receiver
SharedFunctionInfoRef shared
std::map< const std::string, const std::string > map
ZoneVector< RpoNumber > & result
#define LOG(isolate, Call)
Definition log.h:78
bool TryCast(Tagged< From > value, Tagged< To > *out)
Definition casting.h:77
PerThreadAssertScopeDebugOnly< false, SAFEPOINTS_ASSERT, HEAP_ALLOCATION_ASSERT > DisallowGarbageCollection
bool IsNumber(Tagged< Object > obj)
Tagged(T object) -> Tagged< T >
bool IsResumableFunction(FunctionKind kind)
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:665
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
return Cast< NumberDictionary >(elements(cage_base))
V8_EXPORT_PRIVATE FlagValues v8_flags
bool IsUniqueName(Tagged< Name > obj)
return value
Definition map-inl.h:893
Arguments< ArgumentsType::kRuntime > RuntimeArguments
Definition globals.h:1047
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset IsNull(value)||IsJSProxy(value)||IsWasmObject(value)||(IsJSObject(value) &&(HeapLayout
Definition map-inl.h:70
kInstanceDescriptorsOffset kTransitionsOrPrototypeInfoOffset prototype
Definition map-inl.h:69
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
Local< T > Handle
static constexpr RelaxedStoreTag kRelaxedStore
Definition globals.h:2911
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
Symbol method