LCOV - code coverage report
Current view: top level - src/runtime - runtime-classes.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 245 252 97.2 %
Date: 2019-04-18 Functions: 34 46 73.9 %

          Line data    Source code
       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 "src/runtime/runtime-utils.h"
       6             : 
       7             : #include <stdlib.h>
       8             : #include <limits>
       9             : 
      10             : #include "src/accessors.h"
      11             : #include "src/arguments-inl.h"
      12             : #include "src/counters.h"
      13             : #include "src/debug/debug.h"
      14             : #include "src/elements.h"
      15             : #include "src/isolate-inl.h"
      16             : #include "src/log.h"
      17             : #include "src/message-template.h"
      18             : #include "src/objects/hash-table-inl.h"
      19             : #include "src/objects/literal-objects-inl.h"
      20             : #include "src/objects/smi.h"
      21             : #include "src/objects/struct-inl.h"
      22             : #include "src/runtime/runtime.h"
      23             : 
      24             : namespace v8 {
      25             : namespace internal {
      26             : 
      27             : 
      28          54 : RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
      29             :   HandleScope scope(isolate);
      30             :   DCHECK_EQ(0, args.length());
      31          54 :   THROW_NEW_ERROR_RETURN_FAILURE(
      32             :       isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
      33             : }
      34             : 
      35             : 
      36         860 : RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
      37             :   HandleScope scope(isolate);
      38             :   DCHECK_EQ(1, args.length());
      39         430 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
      40         860 :   Handle<String> name(constructor->shared()->Name(), isolate);
      41         860 :   THROW_NEW_ERROR_RETURN_FAILURE(
      42             :       isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name));
      43             : }
      44             : 
      45             : 
      46         144 : RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
      47             :   HandleScope scope(isolate);
      48             :   DCHECK_EQ(0, args.length());
      49         144 :   THROW_NEW_ERROR_RETURN_FAILURE(
      50             :       isolate, NewTypeError(MessageTemplate::kStaticPrototype));
      51             : }
      52             : 
      53         168 : RUNTIME_FUNCTION(Runtime_ThrowSuperAlreadyCalledError) {
      54             :   HandleScope scope(isolate);
      55             :   DCHECK_EQ(0, args.length());
      56         168 :   THROW_NEW_ERROR_RETURN_FAILURE(
      57             :       isolate, NewReferenceError(MessageTemplate::kSuperAlreadyCalled));
      58             : }
      59             : 
      60         386 : RUNTIME_FUNCTION(Runtime_ThrowSuperNotCalled) {
      61             :   HandleScope scope(isolate);
      62             :   DCHECK_EQ(0, args.length());
      63         386 :   THROW_NEW_ERROR_RETURN_FAILURE(
      64             :       isolate, NewReferenceError(MessageTemplate::kSuperNotCalled));
      65             : }
      66             : 
      67             : namespace {
      68             : 
      69         108 : Object ThrowNotSuperConstructor(Isolate* isolate, Handle<Object> constructor,
      70             :                                 Handle<JSFunction> function) {
      71             :   Handle<String> super_name;
      72         108 :   if (constructor->IsJSFunction()) {
      73         126 :     super_name = handle(Handle<JSFunction>::cast(constructor)->shared()->Name(),
      74          63 :                         isolate);
      75          45 :   } else if (constructor->IsOddball()) {
      76             :     DCHECK(constructor->IsNull(isolate));
      77             :     super_name = isolate->factory()->null_string();
      78             :   } else {
      79           0 :     super_name = Object::NoSideEffectsToString(isolate, constructor);
      80             :   }
      81             :   // null constructor
      82         108 :   if (super_name->length() == 0) {
      83             :     super_name = isolate->factory()->null_string();
      84             :   }
      85         216 :   Handle<String> function_name(function->shared()->Name(), isolate);
      86             :   // anonymous class
      87         108 :   if (function_name->length() == 0) {
      88          72 :     THROW_NEW_ERROR_RETURN_FAILURE(
      89             :         isolate,
      90             :         NewTypeError(MessageTemplate::kNotSuperConstructorAnonymousClass,
      91             :                      super_name));
      92             :   }
      93         144 :   THROW_NEW_ERROR_RETURN_FAILURE(
      94             :       isolate, NewTypeError(MessageTemplate::kNotSuperConstructor, super_name,
      95             :                             function_name));
      96             : }
      97             : 
      98             : }  // namespace
      99             : 
     100         216 : RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
     101             :   HandleScope scope(isolate);
     102             :   DCHECK_EQ(2, args.length());
     103             :   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
     104         108 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
     105         108 :   return ThrowNotSuperConstructor(isolate, constructor, function);
     106             : }
     107             : 
     108         270 : RUNTIME_FUNCTION(Runtime_HomeObjectSymbol) {
     109             :   DCHECK_EQ(0, args.length());
     110             :   return ReadOnlyRoots(isolate).home_object_symbol();
     111             : }
     112             : 
     113             : namespace {
     114             : 
     115             : template <typename Dictionary>
     116             : Handle<Name> KeyToName(Isolate* isolate, Handle<Object> key);
     117             : 
     118             : template <>
     119             : Handle<Name> KeyToName<NameDictionary>(Isolate* isolate, Handle<Object> key) {
     120             :   DCHECK(key->IsName());
     121             :   return Handle<Name>::cast(key);
     122             : }
     123             : 
     124             : template <>
     125             : Handle<Name> KeyToName<NumberDictionary>(Isolate* isolate, Handle<Object> key) {
     126             :   DCHECK(key->IsNumber());
     127         306 :   return isolate->factory()->NumberToString(key);
     128             : }
     129             : 
     130      508189 : inline void SetHomeObject(Isolate* isolate, JSFunction method,
     131             :                           JSObject home_object) {
     132      508189 :   if (method->shared()->needs_home_object()) {
     133             :     const int kPropertyIndex = JSFunction::kMaybeHomeObjectDescriptorIndex;
     134        6922 :     CHECK_EQ(method->map()->instance_descriptors()->GetKey(kPropertyIndex),
     135             :              ReadOnlyRoots(isolate).home_object_symbol());
     136             : 
     137             :     FieldIndex field_index =
     138        6922 :         FieldIndex::ForDescriptor(method->map(), kPropertyIndex);
     139        6922 :     method->RawFastPropertyAtPut(field_index, home_object);
     140             :   }
     141      508189 : }
     142             : 
     143             : // Gets |index|'th argument which may be a class constructor object, a class
     144             : // prototype object or a class method. In the latter case the following
     145             : // post-processing may be required:
     146             : // 1) set [[HomeObject]] slot to given |home_object| value if the method's
     147             : //    shared function info indicates that the method requires that;
     148             : // 2) set method's name to a concatenation of |name_prefix| and |key| if the
     149             : //    method's shared function info indicates that method does not have a
     150             : //    shared name.
     151             : template <typename Dictionary>
     152      184365 : MaybeHandle<Object> GetMethodAndSetHomeObjectAndName(
     153             :     Isolate* isolate, Arguments& args, Smi index, Handle<JSObject> home_object,
     154             :     Handle<String> name_prefix, Handle<Object> key) {
     155             :   int int_index = index.value();
     156             : 
     157             :   // Class constructor and prototype values do not require post processing.
     158      184365 :   if (int_index < ClassBoilerplate::kFirstDynamicArgumentIndex) {
     159         546 :     return args.at<Object>(int_index);
     160             :   }
     161             : 
     162             :   Handle<JSFunction> method = args.at<JSFunction>(int_index);
     163             : 
     164      183819 :   SetHomeObject(isolate, *method, *home_object);
     165             : 
     166      183819 :   if (!method->shared()->HasSharedName()) {
     167             :     // TODO(ishell): method does not have a shared name at this point only if
     168             :     // the key is a computed property name. However, the bytecode generator
     169             :     // explicitly generates ToName bytecodes to ensure that the computed
     170             :     // property name is properly converted to Name. So, we can actually be smart
     171             :     // here and avoid converting Smi keys back to Name.
     172        3233 :     Handle<Name> name = KeyToName<Dictionary>(isolate, key);
     173        3233 :     if (!JSFunction::SetName(method, name, name_prefix)) {
     174           0 :       return MaybeHandle<Object>();
     175             :     }
     176             :   }
     177      183819 :   return method;
     178             : }
     179             : 
     180             : // Gets |index|'th argument which may be a class constructor object, a class
     181             : // prototype object or a class method. In the latter case the following
     182             : // post-processing may be required:
     183             : // 1) set [[HomeObject]] slot to given |home_object| value if the method's
     184             : //    shared function info indicates that the method requires that;
     185             : // This is a simplified version of GetMethodWithSharedNameAndSetHomeObject()
     186             : // function above that is used when it's guaranteed that the method has
     187             : // shared name.
     188      379756 : Object GetMethodWithSharedNameAndSetHomeObject(Isolate* isolate,
     189             :                                                Arguments& args, Object index,
     190             :                                                JSObject home_object) {
     191             :   DisallowHeapAllocation no_gc;
     192             :   int int_index = Smi::ToInt(index);
     193             : 
     194             :   // Class constructor and prototype values do not require post processing.
     195      379756 :   if (int_index < ClassBoilerplate::kFirstDynamicArgumentIndex) {
     196             :     return args[int_index];
     197             :   }
     198             : 
     199             :   Handle<JSFunction> method = args.at<JSFunction>(int_index);
     200             : 
     201      324370 :   SetHomeObject(isolate, *method, home_object);
     202             : 
     203             :   DCHECK(method->shared()->HasSharedName());
     204      324370 :   return *method;
     205             : }
     206             : 
     207             : template <typename Dictionary>
     208        6750 : Handle<Dictionary> ShallowCopyDictionaryTemplate(
     209             :     Isolate* isolate, Handle<Dictionary> dictionary_template) {
     210             :   Handle<Map> dictionary_map(dictionary_template->map(), isolate);
     211             :   Handle<Dictionary> dictionary =
     212        6750 :       Handle<Dictionary>::cast(isolate->factory()->CopyFixedArrayWithMap(
     213             :           dictionary_template, dictionary_map));
     214             :   // Clone all AccessorPairs in the dictionary.
     215             :   int capacity = dictionary->Capacity();
     216      865674 :   for (int i = 0; i < capacity; i++) {
     217             :     Object value = dictionary->ValueAt(i);
     218      429462 :     if (value->IsAccessorPair()) {
     219             :       Handle<AccessorPair> pair(AccessorPair::cast(value), isolate);
     220         306 :       pair = AccessorPair::Copy(isolate, pair);
     221         612 :       dictionary->ValueAtPut(i, *pair);
     222             :     }
     223             :   }
     224        6750 :   return dictionary;
     225             : }
     226             : 
     227             : template <typename Dictionary>
     228        3573 : bool SubstituteValues(Isolate* isolate, Handle<Dictionary> dictionary,
     229             :                       Handle<JSObject> receiver, Arguments& args,
     230             :                       bool* install_name_accessor = nullptr) {
     231             :   Handle<Name> name_string = isolate->factory()->name_string();
     232             : 
     233             :   // Replace all indices with proper methods.
     234             :   int capacity = dictionary->Capacity();
     235             :   ReadOnlyRoots roots(isolate);
     236      837549 :   for (int i = 0; i < capacity; i++) {
     237             :     Object maybe_key = dictionary->KeyAt(i);
     238      641448 :     if (!Dictionary::IsKey(roots, maybe_key)) continue;
     239      293221 :     if (install_name_accessor && *install_name_accessor &&
     240             :         (maybe_key == *name_string)) {
     241          18 :       *install_name_accessor = false;
     242             :     }
     243             :     Handle<Object> key(maybe_key, isolate);
     244             :     Handle<Object> value(dictionary->ValueAt(i), isolate);
     245      192528 :     if (value->IsAccessorPair()) {
     246             :       Handle<AccessorPair> pair = Handle<AccessorPair>::cast(value);
     247             :       Object tmp = pair->getter();
     248        2984 :       if (tmp->IsSmi()) {
     249             :         Handle<Object> result;
     250        5590 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     251             :             isolate, result,
     252             :             GetMethodAndSetHomeObjectAndName<Dictionary>(
     253             :                 isolate, args, Smi::cast(tmp), receiver,
     254             :                 isolate->factory()->get_string(), key),
     255             :             false);
     256        2795 :         pair->set_getter(*result);
     257             :       }
     258             :       tmp = pair->setter();
     259        2984 :       if (tmp->IsSmi()) {
     260             :         Handle<Object> result;
     261         432 :         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     262             :             isolate, result,
     263             :             GetMethodAndSetHomeObjectAndName<Dictionary>(
     264             :                 isolate, args, Smi::cast(tmp), receiver,
     265             :                 isolate->factory()->set_string(), key),
     266             :             false);
     267         216 :         pair->set_setter(*result);
     268             :       }
     269      189544 :     } else if (value->IsSmi()) {
     270             :       Handle<Object> result;
     271      362708 :       ASSIGN_RETURN_ON_EXCEPTION_VALUE(
     272             :           isolate, result,
     273             :           GetMethodAndSetHomeObjectAndName<Dictionary>(
     274             :               isolate, args, Smi::cast(*value), receiver,
     275             :               isolate->factory()->empty_string(), key),
     276             :           false);
     277      362708 :       dictionary->ValueAtPut(i, *result);
     278             :     }
     279             :   }
     280             :   return true;
     281             : }
     282             : 
     283      106527 : bool AddDescriptorsByTemplate(
     284             :     Isolate* isolate, Handle<Map> map,
     285             :     Handle<DescriptorArray> descriptors_template,
     286             :     Handle<NumberDictionary> elements_dictionary_template,
     287             :     Handle<JSObject> receiver, Arguments& args) {
     288      106527 :   int nof_descriptors = descriptors_template->number_of_descriptors();
     289             : 
     290             :   Handle<DescriptorArray> descriptors =
     291      106527 :       DescriptorArray::Allocate(isolate, nof_descriptors, 0);
     292             : 
     293             :   Handle<NumberDictionary> elements_dictionary =
     294             :       *elements_dictionary_template ==
     295             :               ReadOnlyRoots(isolate).empty_slow_element_dictionary()
     296             :           ? elements_dictionary_template
     297             :           : ShallowCopyDictionaryTemplate(isolate,
     298      106527 :                                           elements_dictionary_template);
     299             : 
     300             :   Handle<PropertyArray> property_array =
     301             :       isolate->factory()->empty_property_array();
     302             :   if (FLAG_track_constant_fields) {
     303             :     // If we store constants in instances, count the number of properties
     304             :     // that must be in the instance and create the property array to
     305             :     // hold the constants.
     306             :     int count = 0;
     307     1272861 :     for (int i = 0; i < nof_descriptors; i++) {
     308      583167 :       PropertyDetails details = descriptors_template->GetDetails(i);
     309     1166334 :       if (details.location() == kDescriptor && details.kind() == kData) {
     310      427579 :         count++;
     311             :       }
     312             :     }
     313      106527 :     property_array = isolate->factory()->NewPropertyArray(count);
     314             :   }
     315             : 
     316             :   // Read values from |descriptors_template| and store possibly post-processed
     317             :   // values into "instantiated" |descriptors| array.
     318             :   int field_index = 0;
     319     1272861 :   for (int i = 0; i < nof_descriptors; i++) {
     320      583167 :     Object value = descriptors_template->GetStrongValue(i);
     321      583167 :     if (value->IsAccessorPair()) {
     322             :       Handle<AccessorPair> pair = AccessorPair::Copy(
     323        4212 :           isolate, handle(AccessorPair::cast(value), isolate));
     324        4212 :       value = *pair;
     325             :     }
     326             :     DisallowHeapAllocation no_gc;
     327      583167 :     Name name = descriptors_template->GetKey(i);
     328             :     DCHECK(name->IsUniqueName());
     329      583167 :     PropertyDetails details = descriptors_template->GetDetails(i);
     330      583167 :     if (details.location() == kDescriptor) {
     331      583167 :       if (details.kind() == kData) {
     332      427579 :         if (value->IsSmi()) {
     333             :           value = GetMethodWithSharedNameAndSetHomeObject(isolate, args, value,
     334      375394 :                                                           *receiver);
     335             :         }
     336             :         details =
     337      427579 :             details.CopyWithRepresentation(value->OptimalRepresentation());
     338             :       } else {
     339             :         DCHECK_EQ(kAccessor, details.kind());
     340      155588 :         if (value->IsAccessorPair()) {
     341        4212 :           AccessorPair pair = AccessorPair::cast(value);
     342             :           Object tmp = pair->getter();
     343        4212 :           if (tmp->IsSmi()) {
     344        2347 :             pair->set_getter(GetMethodWithSharedNameAndSetHomeObject(
     345        2347 :                 isolate, args, tmp, *receiver));
     346             :           }
     347             :           tmp = pair->setter();
     348        4212 :           if (tmp->IsSmi()) {
     349        2015 :             pair->set_setter(GetMethodWithSharedNameAndSetHomeObject(
     350        2015 :                 isolate, args, tmp, *receiver));
     351             :           }
     352             :         }
     353             :       }
     354             :     } else {
     355           0 :       UNREACHABLE();
     356             :     }
     357             :     DCHECK(value->FitsRepresentation(details.representation()));
     358             :     // With constant field tracking, we store the values in the instance.
     359     1166334 :     if (FLAG_track_constant_fields && details.location() == kDescriptor &&
     360             :         details.kind() == kData) {
     361             :       details = PropertyDetails(details.kind(), details.attributes(), kField,
     362             :                                 PropertyConstness::kConst,
     363             :                                 details.representation(), field_index)
     364             :                     .set_pointer(details.pointer());
     365             : 
     366      427579 :       property_array->set(field_index, value);
     367      427579 :       field_index++;
     368     1282737 :       descriptors->Set(i, name, MaybeObject::FromObject(FieldType::Any()),
     369      427579 :                        details);
     370             :     } else {
     371      155588 :       descriptors->Set(i, name, MaybeObject::FromObject(value), details);
     372             :     }
     373             :   }
     374             : 
     375      213054 :   map->InitializeDescriptors(isolate, *descriptors,
     376      106527 :                              LayoutDescriptor::FastPointerLayout());
     377      106527 :   if (elements_dictionary->NumberOfElements() > 0) {
     378          72 :     if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
     379             :                                             receiver, args)) {
     380             :       return false;
     381             :     }
     382          72 :     map->set_elements_kind(DICTIONARY_ELEMENTS);
     383             :   }
     384             : 
     385             :   // Atomically commit the changes.
     386      106527 :   receiver->synchronized_set_map(*map);
     387      106527 :   if (elements_dictionary->NumberOfElements() > 0) {
     388         144 :     receiver->set_elements(*elements_dictionary);
     389             :   }
     390      106527 :   if (property_array->length() > 0) {
     391      213054 :     receiver->SetProperties(*property_array);
     392             :   }
     393             :   return true;
     394             : }
     395             : 
     396        3339 : bool AddDescriptorsByTemplate(
     397             :     Isolate* isolate, Handle<Map> map,
     398             :     Handle<NameDictionary> properties_dictionary_template,
     399             :     Handle<NumberDictionary> elements_dictionary_template,
     400             :     Handle<FixedArray> computed_properties, Handle<JSObject> receiver,
     401             :     bool install_name_accessor, Arguments& args) {
     402             :   int computed_properties_length = computed_properties->length();
     403             : 
     404             :   // Shallow-copy properties template.
     405             :   Handle<NameDictionary> properties_dictionary =
     406        3339 :       ShallowCopyDictionaryTemplate(isolate, properties_dictionary_template);
     407             :   Handle<NumberDictionary> elements_dictionary =
     408        3339 :       ShallowCopyDictionaryTemplate(isolate, elements_dictionary_template);
     409             : 
     410             :   typedef ClassBoilerplate::ValueKind ValueKind;
     411             :   typedef ClassBoilerplate::ComputedEntryFlags ComputedEntryFlags;
     412             : 
     413             :   // Merge computed properties with properties and elements dictionary
     414             :   // templates.
     415             :   int i = 0;
     416       10057 :   while (i < computed_properties_length) {
     417        3359 :     int flags = Smi::ToInt(computed_properties->get(i++));
     418             : 
     419        3359 :     ValueKind value_kind = ComputedEntryFlags::ValueKindBits::decode(flags);
     420        3359 :     int key_index = ComputedEntryFlags::KeyIndexBits::decode(flags);
     421        6718 :     Object value = Smi::FromInt(key_index + 1);  // Value follows name.
     422             : 
     423             :     Handle<Object> key = args.at<Object>(key_index);
     424             :     DCHECK(key->IsName());
     425             :     uint32_t element;
     426             :     Handle<Name> name = Handle<Name>::cast(key);
     427        3359 :     if (name->AsArrayIndex(&element)) {
     428             :       ClassBoilerplate::AddToElementsTemplate(
     429         306 :           isolate, elements_dictionary, element, key_index, value_kind, value);
     430             : 
     431             :     } else {
     432        3053 :       name = isolate->factory()->InternalizeName(name);
     433             :       ClassBoilerplate::AddToPropertiesTemplate(
     434        3053 :           isolate, properties_dictionary, name, key_index, value_kind, value);
     435             :     }
     436             :   }
     437             : 
     438             :   // Replace all indices with proper methods.
     439        3339 :   if (!SubstituteValues<NameDictionary>(isolate, properties_dictionary,
     440             :                                         receiver, args,
     441             :                                         &install_name_accessor)) {
     442             :     return false;
     443             :   }
     444        3339 :   if (install_name_accessor) {
     445             :     PropertyAttributes attribs =
     446             :         static_cast<PropertyAttributes>(DONT_ENUM | READ_ONLY);
     447             :     PropertyDetails details(kAccessor, attribs, PropertyCellType::kNoCell);
     448             :     Handle<NameDictionary> dict = NameDictionary::Add(
     449             :         isolate, properties_dictionary, isolate->factory()->name_string(),
     450        2694 :         isolate->factory()->function_name_accessor(), details);
     451        2694 :     CHECK_EQ(*dict, *properties_dictionary);
     452             :   }
     453             : 
     454        3339 :   if (elements_dictionary->NumberOfElements() > 0) {
     455         162 :     if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
     456             :                                             receiver, args)) {
     457             :       return false;
     458             :     }
     459         162 :     map->set_elements_kind(DICTIONARY_ELEMENTS);
     460             :   }
     461             : 
     462             :   // Atomically commit the changes.
     463        3339 :   receiver->synchronized_set_map(*map);
     464        6678 :   receiver->set_raw_properties_or_hash(*properties_dictionary);
     465        3339 :   if (elements_dictionary->NumberOfElements() > 0) {
     466         324 :     receiver->set_elements(*elements_dictionary);
     467             :   }
     468             :   return true;
     469             : }
     470             : 
     471       54933 : Handle<JSObject> CreateClassPrototype(Isolate* isolate) {
     472             :   Factory* factory = isolate->factory();
     473             : 
     474             :   const int kInobjectFields = 0;
     475             : 
     476             :   Handle<Map> map;
     477             :   if (FLAG_track_constant_fields) {
     478             :     // For constant tracking we want to avoid tha hassle of handling
     479             :     // in-object properties, so create a map with no in-object
     480             :     // properties.
     481             : 
     482             :     // TODO(ishell) Support caching of zero in-object properties map
     483             :     // by ObjectLiteralMapFromCache().
     484       54933 :     map = Map::Create(isolate, 0);
     485             :   } else {
     486             :     // Just use some JSObject map of certain size.
     487             :     map = factory->ObjectLiteralMapFromCache(isolate->native_context(),
     488             :                                              kInobjectFields);
     489             :   }
     490             : 
     491       54933 :   return factory->NewJSObjectFromMap(map);
     492             : }
     493             : 
     494       54933 : bool InitClassPrototype(Isolate* isolate,
     495             :                         Handle<ClassBoilerplate> class_boilerplate,
     496             :                         Handle<JSObject> prototype,
     497             :                         Handle<HeapObject> prototype_parent,
     498             :                         Handle<JSFunction> constructor, Arguments& args) {
     499             :   Handle<Map> map(prototype->map(), isolate);
     500       54933 :   map = Map::CopyDropDescriptors(isolate, map);
     501             :   map->set_is_prototype_map(true);
     502       54933 :   Map::SetPrototype(isolate, map, prototype_parent);
     503      109866 :   constructor->set_prototype_or_initial_map(*prototype);
     504      109866 :   map->SetConstructor(*constructor);
     505             :   Handle<FixedArray> computed_properties(
     506             :       class_boilerplate->instance_computed_properties(), isolate);
     507             :   Handle<NumberDictionary> elements_dictionary_template(
     508             :       NumberDictionary::cast(class_boilerplate->instance_elements_template()),
     509             :       isolate);
     510             : 
     511             :   Handle<Object> properties_template(
     512             :       class_boilerplate->instance_properties_template(), isolate);
     513       54933 :   if (properties_template->IsNameDictionary()) {
     514             :     Handle<NameDictionary> properties_dictionary_template =
     515         591 :         Handle<NameDictionary>::cast(properties_template);
     516             : 
     517         591 :     map->set_is_dictionary_map(true);
     518         591 :     map->set_is_migration_target(false);
     519         591 :     map->set_may_have_interesting_symbols(true);
     520         591 :     map->set_construction_counter(Map::kNoSlackTracking);
     521             : 
     522             :     // We care about name property only for class constructor.
     523             :     const bool install_name_accessor = false;
     524             : 
     525             :     return AddDescriptorsByTemplate(
     526             :         isolate, map, properties_dictionary_template,
     527             :         elements_dictionary_template, computed_properties, prototype,
     528         591 :         install_name_accessor, args);
     529             :   } else {
     530             :     Handle<DescriptorArray> descriptors_template =
     531       54342 :         Handle<DescriptorArray>::cast(properties_template);
     532             : 
     533             :     // The size of the prototype object is known at this point.
     534             :     // So we can create it now and then add the rest instance methods to the
     535             :     // map.
     536             :     return AddDescriptorsByTemplate(isolate, map, descriptors_template,
     537             :                                     elements_dictionary_template, prototype,
     538       54342 :                                     args);
     539             :   }
     540             : }
     541             : 
     542       54933 : bool InitClassConstructor(Isolate* isolate,
     543             :                           Handle<ClassBoilerplate> class_boilerplate,
     544             :                           Handle<HeapObject> constructor_parent,
     545             :                           Handle<JSFunction> constructor, Arguments& args) {
     546             :   Handle<Map> map(constructor->map(), isolate);
     547       54933 :   map = Map::CopyDropDescriptors(isolate, map);
     548             :   DCHECK(map->is_prototype_map());
     549             : 
     550       54933 :   if (!constructor_parent.is_null()) {
     551             :     // Set map's prototype without enabling prototype setup mode for superclass
     552             :     // because it does not make sense.
     553       13058 :     Map::SetPrototype(isolate, map, constructor_parent, false);
     554             :   }
     555             : 
     556             :   Handle<NumberDictionary> elements_dictionary_template(
     557             :       NumberDictionary::cast(class_boilerplate->static_elements_template()),
     558             :       isolate);
     559             :   Handle<FixedArray> computed_properties(
     560             :       class_boilerplate->static_computed_properties(), isolate);
     561             : 
     562             :   Handle<Object> properties_template(
     563             :       class_boilerplate->static_properties_template(), isolate);
     564             : 
     565       54933 :   if (properties_template->IsNameDictionary()) {
     566             :     Handle<NameDictionary> properties_dictionary_template =
     567        2748 :         Handle<NameDictionary>::cast(properties_template);
     568             : 
     569        2748 :     map->set_is_dictionary_map(true);
     570        5496 :     map->InitializeDescriptors(isolate,
     571             :                                ReadOnlyRoots(isolate).empty_descriptor_array(),
     572        2748 :                                LayoutDescriptor::FastPointerLayout());
     573        2748 :     map->set_is_migration_target(false);
     574        2748 :     map->set_may_have_interesting_symbols(true);
     575        2748 :     map->set_construction_counter(Map::kNoSlackTracking);
     576             : 
     577             :     bool install_name_accessor =
     578             :         class_boilerplate->install_class_name_accessor() != 0;
     579             : 
     580        5496 :     return AddDescriptorsByTemplate(
     581             :         isolate, map, properties_dictionary_template,
     582             :         elements_dictionary_template, computed_properties, constructor,
     583        2748 :         install_name_accessor, args);
     584             :   } else {
     585             :     Handle<DescriptorArray> descriptors_template =
     586       52185 :         Handle<DescriptorArray>::cast(properties_template);
     587             : 
     588       52185 :     return AddDescriptorsByTemplate(isolate, map, descriptors_template,
     589             :                                     elements_dictionary_template, constructor,
     590       52185 :                                     args);
     591             :   }
     592             : }
     593             : 
     594       55176 : MaybeHandle<Object> DefineClass(Isolate* isolate,
     595             :                                 Handle<ClassBoilerplate> class_boilerplate,
     596             :                                 Handle<Object> super_class,
     597             :                                 Handle<JSFunction> constructor,
     598             :                                 Arguments& args) {
     599             :   Handle<Object> prototype_parent;
     600             :   Handle<HeapObject> constructor_parent;
     601             : 
     602       55176 :   if (super_class->IsTheHole(isolate)) {
     603       41620 :     prototype_parent = isolate->initial_object_prototype();
     604             :   } else {
     605       13556 :     if (super_class->IsNull(isolate)) {
     606             :       prototype_parent = isolate->factory()->null_value();
     607       13301 :     } else if (super_class->IsConstructor()) {
     608             :       DCHECK(!super_class->IsJSFunction() ||
     609             :              !IsResumableFunction(
     610             :                  Handle<JSFunction>::cast(super_class)->shared()->kind()));
     611       26206 :       ASSIGN_RETURN_ON_EXCEPTION(
     612             :           isolate, prototype_parent,
     613             :           Runtime::GetObjectProperty(isolate, super_class,
     614             :                                      isolate->factory()->prototype_string()),
     615             :           Object);
     616       26188 :       if (!prototype_parent->IsNull(isolate) &&
     617             :           !prototype_parent->IsJSReceiver()) {
     618          90 :         THROW_NEW_ERROR(
     619             :             isolate, NewTypeError(MessageTemplate::kPrototypeParentNotAnObject,
     620             :                                   prototype_parent),
     621             :             Object);
     622             :       }
     623             :       // Create new handle to avoid |constructor_parent| corruption because of
     624             :       // |super_class| handle value overwriting via storing to
     625             :       // args[ClassBoilerplate::kPrototypeArgumentIndex] below.
     626       13058 :       constructor_parent = handle(HeapObject::cast(*super_class), isolate);
     627             :     } else {
     628         396 :       THROW_NEW_ERROR(isolate,
     629             :                       NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
     630             :                                    super_class),
     631             :                       Object);
     632             :     }
     633             :   }
     634             : 
     635       54933 :   Handle<JSObject> prototype = CreateClassPrototype(isolate);
     636             :   DCHECK_EQ(*constructor, args[ClassBoilerplate::kConstructorArgumentIndex]);
     637             :   args.set_at(ClassBoilerplate::kPrototypeArgumentIndex, *prototype);
     638             : 
     639      109866 :   if (!InitClassConstructor(isolate, class_boilerplate, constructor_parent,
     640      109866 :                             constructor, args) ||
     641       54933 :       !InitClassPrototype(isolate, class_boilerplate, prototype,
     642             :                           Handle<HeapObject>::cast(prototype_parent),
     643             :                           constructor, args)) {
     644             :     DCHECK(isolate->has_pending_exception());
     645           0 :     return MaybeHandle<Object>();
     646             :   }
     647       54933 :   if (FLAG_trace_maps) {
     648        1227 :     LOG(isolate,
     649             :         MapEvent("InitialMap", Map(), constructor->map(),
     650             :                  "init class constructor", constructor->shared()->DebugName()));
     651         818 :     LOG(isolate, MapEvent("InitialMap", Map(), prototype->map(),
     652             :                           "init class prototype"));
     653             :   }
     654             : 
     655       54933 :   return prototype;
     656             : }
     657             : 
     658             : }  // namespace
     659             : 
     660      110352 : RUNTIME_FUNCTION(Runtime_DefineClass) {
     661             :   HandleScope scope(isolate);
     662             :   DCHECK_LE(ClassBoilerplate::kFirstDynamicArgumentIndex, args.length());
     663       55176 :   CONVERT_ARG_HANDLE_CHECKED(ClassBoilerplate, class_boilerplate, 0);
     664       55176 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 1);
     665             :   CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 2);
     666             :   DCHECK_EQ(class_boilerplate->arguments_count(), args.length());
     667             : 
     668      110352 :   RETURN_RESULT_OR_FAILURE(
     669             :       isolate,
     670             :       DefineClass(isolate, class_boilerplate, super_class, constructor, args));
     671             : }
     672             : 
     673             : namespace {
     674             : 
     675             : enum class SuperMode { kLoad, kStore };
     676             : 
     677       13645 : MaybeHandle<JSReceiver> GetSuperHolder(
     678             :     Isolate* isolate, Handle<Object> receiver, Handle<JSObject> home_object,
     679             :     SuperMode mode, MaybeHandle<Name> maybe_name, uint32_t index) {
     680       13645 :   if (home_object->IsAccessCheckNeeded() &&
     681           0 :       !isolate->MayAccess(handle(isolate->context(), isolate), home_object)) {
     682           0 :     isolate->ReportFailedAccessCheck(home_object);
     683           0 :     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, JSReceiver);
     684             :   }
     685             : 
     686       13645 :   PrototypeIterator iter(isolate, home_object);
     687             :   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
     688       13645 :   if (!proto->IsJSReceiver()) {
     689             :     MessageTemplate message = mode == SuperMode::kLoad
     690             :                                   ? MessageTemplate::kNonObjectPropertyLoad
     691          72 :                                   : MessageTemplate::kNonObjectPropertyStore;
     692             :     Handle<Name> name;
     693          72 :     if (!maybe_name.ToHandle(&name)) {
     694          36 :       name = isolate->factory()->Uint32ToString(index);
     695             :     }
     696         144 :     THROW_NEW_ERROR(isolate, NewTypeError(message, name, proto), JSReceiver);
     697             :   }
     698       13573 :   return Handle<JSReceiver>::cast(proto);
     699             : }
     700             : 
     701       11686 : MaybeHandle<Object> LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
     702             :                                   Handle<JSObject> home_object,
     703             :                                   Handle<Name> name) {
     704             :   Handle<JSReceiver> holder;
     705       23372 :   ASSIGN_RETURN_ON_EXCEPTION(
     706             :       isolate, holder,
     707             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad, name, 0),
     708             :       Object);
     709             :   LookupIterator it(receiver, name, holder);
     710             :   Handle<Object> result;
     711       23336 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
     712       11668 :   return result;
     713             : }
     714             : 
     715         522 : MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
     716             :                                          Handle<Object> receiver,
     717             :                                          Handle<JSObject> home_object,
     718             :                                          uint32_t index) {
     719             :   Handle<JSReceiver> holder;
     720        1044 :   ASSIGN_RETURN_ON_EXCEPTION(
     721             :       isolate, holder,
     722             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad,
     723             :                      MaybeHandle<Name>(), index),
     724             :       Object);
     725             :   LookupIterator it(isolate, receiver, index, holder);
     726             :   Handle<Object> result;
     727        1008 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
     728         504 :   return result;
     729             : }
     730             : 
     731             : }  // anonymous namespace
     732             : 
     733       22328 : RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
     734             :   HandleScope scope(isolate);
     735             :   DCHECK_EQ(3, args.length());
     736             :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     737       11164 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     738       11164 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     739             : 
     740       22328 :   RETURN_RESULT_OR_FAILURE(isolate,
     741             :                            LoadFromSuper(isolate, receiver, home_object, name));
     742             : }
     743             : 
     744             : 
     745        2124 : RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
     746             :   HandleScope scope(isolate);
     747             :   DCHECK_EQ(3, args.length());
     748             :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     749        1062 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     750             :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     751             : 
     752        1062 :   uint32_t index = 0;
     753             : 
     754        2124 :   if (key->ToArrayIndex(&index)) {
     755         990 :     RETURN_RESULT_OR_FAILURE(
     756             :         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
     757             :   }
     758             : 
     759             :   Handle<Name> name;
     760        1134 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     761             :                                      Object::ToName(isolate, key));
     762             :   // TODO(verwaest): Unify using LookupIterator.
     763         549 :   if (name->AsArrayIndex(&index)) {
     764          54 :     RETURN_RESULT_OR_FAILURE(
     765             :         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
     766             :   }
     767        1044 :   RETURN_RESULT_OR_FAILURE(isolate,
     768             :                            LoadFromSuper(isolate, receiver, home_object, name));
     769             : }
     770             : 
     771             : namespace {
     772             : 
     773         996 : MaybeHandle<Object> StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
     774             :                                  Handle<Object> receiver, Handle<Name> name,
     775             :                                  Handle<Object> value) {
     776             :   Handle<JSReceiver> holder;
     777        1992 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, holder,
     778             :                              GetSuperHolder(isolate, receiver, home_object,
     779             :                                             SuperMode::kStore, name, 0),
     780             :                              Object);
     781             :   LookupIterator it(receiver, name, holder);
     782        1956 :   MAYBE_RETURN(Object::SetSuperProperty(&it, value, StoreOrigin::kNamed),
     783             :                MaybeHandle<Object>());
     784         793 :   return value;
     785             : }
     786             : 
     787         441 : MaybeHandle<Object> StoreElementToSuper(Isolate* isolate,
     788             :                                         Handle<JSObject> home_object,
     789             :                                         Handle<Object> receiver, uint32_t index,
     790             :                                         Handle<Object> value) {
     791             :   Handle<JSReceiver> holder;
     792         882 :   ASSIGN_RETURN_ON_EXCEPTION(
     793             :       isolate, holder,
     794             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kStore,
     795             :                      MaybeHandle<Name>(), index),
     796             :       Object);
     797             :   LookupIterator it(isolate, receiver, index, holder);
     798         846 :   MAYBE_RETURN(Object::SetSuperProperty(&it, value, StoreOrigin::kMaybeKeyed),
     799             :                MaybeHandle<Object>());
     800         333 :   return value;
     801             : }
     802             : 
     803             : }  // anonymous namespace
     804             : 
     805        1074 : RUNTIME_FUNCTION(Runtime_StoreToSuper) {
     806             :   HandleScope scope(isolate);
     807             :   DCHECK_EQ(4, args.length());
     808             :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     809         537 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     810         537 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     811             :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     812             : 
     813        1074 :   RETURN_RESULT_OR_FAILURE(
     814             :       isolate, StoreToSuper(isolate, home_object, receiver, name, value));
     815             : }
     816             : 
     817         918 : static MaybeHandle<Object> StoreKeyedToSuper(Isolate* isolate,
     818             :                                              Handle<JSObject> home_object,
     819             :                                              Handle<Object> receiver,
     820             :                                              Handle<Object> key,
     821             :                                              Handle<Object> value) {
     822         918 :   uint32_t index = 0;
     823             : 
     824        1836 :   if (key->ToArrayIndex(&index)) {
     825         423 :     return StoreElementToSuper(isolate, home_object, receiver, index, value);
     826             :   }
     827             :   Handle<Name> name;
     828         990 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
     829             :                              Object);
     830             :   // TODO(verwaest): Unify using LookupIterator.
     831         477 :   if (name->AsArrayIndex(&index)) {
     832          18 :     return StoreElementToSuper(isolate, home_object, receiver, index, value);
     833             :   }
     834         459 :   return StoreToSuper(isolate, home_object, receiver, name, value);
     835             : }
     836             : 
     837        1836 : RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper) {
     838             :   HandleScope scope(isolate);
     839             :   DCHECK_EQ(4, args.length());
     840             :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     841         918 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     842             :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     843             :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     844             : 
     845        1836 :   RETURN_RESULT_OR_FAILURE(
     846             :       isolate, StoreKeyedToSuper(isolate, home_object, receiver, key, value));
     847             : }
     848             : 
     849             : }  // namespace internal
     850      122036 : }  // namespace v8

Generated by: LCOV version 1.10