LCOV - code coverage report
Current view: top level - src/runtime - runtime-classes.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 302 310 97.4 %
Date: 2019-01-20 Functions: 37 51 72.5 %

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

Generated by: LCOV version 1.10