LCOV - code coverage report
Current view: top level - src/runtime - runtime-classes.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 292 299 97.7 %
Date: 2019-02-19 Functions: 35 47 74.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/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          27 : RUNTIME_FUNCTION(Runtime_ThrowUnsupportedSuperError) {
      29          27 :   HandleScope scope(isolate);
      30             :   DCHECK_EQ(0, args.length());
      31          54 :   THROW_NEW_ERROR_RETURN_FAILURE(
      32          27 :       isolate, NewReferenceError(MessageTemplate::kUnsupportedSuper));
      33             : }
      34             : 
      35             : 
      36         430 : RUNTIME_FUNCTION(Runtime_ThrowConstructorNonCallableError) {
      37         430 :   HandleScope scope(isolate);
      38             :   DCHECK_EQ(1, args.length());
      39         860 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 0);
      40         860 :   Handle<String> name(constructor->shared()->Name(), isolate);
      41         860 :   THROW_NEW_ERROR_RETURN_FAILURE(
      42         430 :       isolate, NewTypeError(MessageTemplate::kConstructorNonCallable, name));
      43             : }
      44             : 
      45             : 
      46          72 : RUNTIME_FUNCTION(Runtime_ThrowStaticPrototypeError) {
      47          72 :   HandleScope scope(isolate);
      48             :   DCHECK_EQ(0, args.length());
      49         144 :   THROW_NEW_ERROR_RETURN_FAILURE(
      50          72 :       isolate, NewTypeError(MessageTemplate::kStaticPrototype));
      51             : }
      52             : 
      53          84 : RUNTIME_FUNCTION(Runtime_ThrowSuperAlreadyCalledError) {
      54          84 :   HandleScope scope(isolate);
      55             :   DCHECK_EQ(0, args.length());
      56         168 :   THROW_NEW_ERROR_RETURN_FAILURE(
      57          84 :       isolate, NewReferenceError(MessageTemplate::kSuperAlreadyCalled));
      58             : }
      59             : 
      60         193 : RUNTIME_FUNCTION(Runtime_ThrowSuperNotCalled) {
      61         193 :   HandleScope scope(isolate);
      62             :   DCHECK_EQ(0, args.length());
      63         386 :   THROW_NEW_ERROR_RETURN_FAILURE(
      64         193 :       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         216 :   if (constructor->IsJSFunction()) {
      73         189 :     super_name = handle(Handle<JSFunction>::cast(constructor)->shared()->Name(),
      74         126 :                         isolate);
      75          90 :   } 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         108 : RUNTIME_FUNCTION(Runtime_ThrowNotSuperConstructor) {
     101         108 :   HandleScope scope(isolate);
     102             :   DCHECK_EQ(2, args.length());
     103         108 :   CONVERT_ARG_HANDLE_CHECKED(Object, constructor, 0);
     104         216 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, function, 1);
     105         108 :   return ThrowNotSuperConstructor(isolate, constructor, function);
     106             : }
     107             : 
     108         135 : 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        2891 :   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      478292 : inline void SetHomeObject(Isolate* isolate, JSFunction method,
     131             :                           JSObject home_object) {
     132      478292 :   if (method->shared()->needs_home_object()) {
     133             :     const int kPropertyIndex = JSFunction::kMaybeHomeObjectDescriptorIndex;
     134       20685 :     CHECK_EQ(method->map()->instance_descriptors()->GetKey(kPropertyIndex),
     135             :              ReadOnlyRoots(isolate).home_object_symbol());
     136             : 
     137             :     FieldIndex field_index =
     138        6895 :         FieldIndex::ForDescriptor(method->map(), kPropertyIndex);
     139        6895 :     method->RawFastPropertyAtPut(field_index, home_object);
     140             :   }
     141      478292 : }
     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      184320 : 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      184320 :   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      183774 :   SetHomeObject(isolate, *method, *home_object);
     165             : 
     166      183774 :   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        3197 :     Handle<Name> name = KeyToName<Dictionary>(isolate, key);
     173        3197 :     if (!JSFunction::SetName(method, name, name_prefix)) {
     174           0 :       return MaybeHandle<Object>();
     175             :     }
     176             :   }
     177      183774 :   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      348222 : Object GetMethodWithSharedNameAndSetHomeObject(Isolate* isolate,
     189             :                                                Arguments& args, Object index,
     190             :                                                JSObject home_object) {
     191             :   DisallowHeapAllocation no_gc;
     192      348222 :   int int_index = Smi::ToInt(index);
     193             : 
     194             :   // Class constructor and prototype values do not require post processing.
     195      348222 :   if (int_index < ClassBoilerplate::kFirstDynamicArgumentIndex) {
     196             :     return args[int_index];
     197             :   }
     198             : 
     199             :   Handle<JSFunction> method = args.at<JSFunction>(int_index);
     200             : 
     201      294518 :   SetHomeObject(isolate, *method, home_object);
     202             : 
     203             :   DCHECK(method->shared()->HasSharedName());
     204      294518 :   return *method;
     205             : }
     206             : 
     207             : template <typename Dictionary>
     208        6660 : Handle<Dictionary> ShallowCopyDictionaryTemplate(
     209             :     Isolate* isolate, Handle<Dictionary> dictionary_template) {
     210             :   Handle<Map> dictionary_map(dictionary_template->map(), isolate);
     211             :   Handle<Dictionary> dictionary =
     212             :       Handle<Dictionary>::cast(isolate->factory()->CopyFixedArrayWithMap(
     213        6660 :           dictionary_template, dictionary_map));
     214             :   // Clone all AccessorPairs in the dictionary.
     215        6660 :   int capacity = dictionary->Capacity();
     216      435222 :   for (int i = 0; i < capacity; i++) {
     217      428562 :     Object value = dictionary->ValueAt(i);
     218      428562 :     if (value->IsAccessorPair()) {
     219             :       Handle<AccessorPair> pair(AccessorPair::cast(value), isolate);
     220         279 :       pair = AccessorPair::Copy(isolate, pair);
     221         558 :       dictionary->ValueAtPut(i, *pair);
     222             :     }
     223             :   }
     224        6660 :   return dictionary;
     225             : }
     226             : 
     227             : template <typename Dictionary>
     228        3528 : 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        3528 :   int capacity = dictionary->Capacity();
     235             :   ReadOnlyRoots roots(isolate);
     236      419796 :   for (int i = 0; i < capacity; i++) {
     237      416268 :     Object maybe_key = dictionary->KeyAt(i);
     238      640143 :     if (!Dictionary::IsKey(roots, maybe_key)) continue;
     239      292987 :     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      384786 :     Handle<Object> value(dictionary->ValueAt(i), isolate);
     245      384786 :     if (value->IsAccessorPair()) {
     246        2948 :       Handle<AccessorPair> pair = Handle<AccessorPair>::cast(value);
     247        2948 :       Object tmp = pair->getter();
     248        2948 :       if (tmp->IsSmi()) {
     249             :         Handle<Object> result;
     250        5518 :         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        2759 :         pair->set_getter(*result);
     257             :       }
     258        2948 :       tmp = pair->setter();
     259        2948 :       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      378890 :     } else if (value->IsSmi()) {
     270             :       Handle<Object> result;
     271      362690 :       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      362690 :       dictionary->ValueAtPut(i, *result);
     278             :     }
     279             :   }
     280             :   return true;
     281             : }
     282             : 
     283      103208 : 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      103208 :   int nof_descriptors = descriptors_template->number_of_descriptors();
     289             : 
     290             :   Handle<DescriptorArray> descriptors =
     291      103208 :       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      103208 :                                           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      648439 :     for (int i = 0; i < nof_descriptors; i++) {
     308      545231 :       PropertyDetails details = descriptors_template->GetDetails(i);
     309     1090462 :       if (details.location() == kDescriptor && details.kind() == kData) {
     310      394408 :         count++;
     311             :       }
     312             :     }
     313      103208 :     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      648439 :   for (int i = 0; i < nof_descriptors; i++) {
     320     1090462 :     Object value = descriptors_template->GetStrongValue(i);
     321      545231 :     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      545231 :     Name name = descriptors_template->GetKey(i);
     328             :     DCHECK(name->IsUniqueName());
     329      545231 :     PropertyDetails details = descriptors_template->GetDetails(i);
     330      545231 :     if (details.location() == kDescriptor) {
     331      545231 :       if (details.kind() == kData) {
     332      394408 :         if (value->IsSmi()) {
     333             :           value = GetMethodWithSharedNameAndSetHomeObject(isolate, args, value,
     334      343860 :                                                           *receiver);
     335             :         }
     336             :         details =
     337      394408 :             details.CopyWithRepresentation(value->OptimalRepresentation());
     338             :       } else {
     339             :         DCHECK_EQ(kAccessor, details.kind());
     340      150823 :         if (value->IsAccessorPair()) {
     341        4212 :           AccessorPair pair = AccessorPair::cast(value);
     342        4212 :           Object tmp = pair->getter();
     343        4212 :           if (tmp->IsSmi()) {
     344             :             pair->set_getter(GetMethodWithSharedNameAndSetHomeObject(
     345        2347 :                 isolate, args, tmp, *receiver));
     346             :           }
     347        4212 :           tmp = pair->setter();
     348        4212 :           if (tmp->IsSmi()) {
     349             :             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     1090462 :     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      394408 :       property_array->set(field_index, value);
     367      394408 :       field_index++;
     368             :       descriptors->Set(i, name, MaybeObject::FromObject(FieldType::Any()),
     369      788816 :                        details);
     370             :     } else {
     371      150823 :       descriptors->Set(i, name, MaybeObject::FromObject(value), details);
     372             :     }
     373             :   }
     374             : 
     375             :   map->InitializeDescriptors(isolate, *descriptors,
     376      103208 :                              LayoutDescriptor::FastPointerLayout());
     377      103208 :   if (elements_dictionary->NumberOfElements() > 0) {
     378          72 :     if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
     379          72 :                                             receiver, args)) {
     380             :       return false;
     381             :     }
     382          72 :     map->set_elements_kind(DICTIONARY_ELEMENTS);
     383             :   }
     384             : 
     385             :   // Atomically commit the changes.
     386      103208 :   receiver->synchronized_set_map(*map);
     387      103208 :   if (elements_dictionary->NumberOfElements() > 0) {
     388         144 :     receiver->set_elements(*elements_dictionary);
     389             :   }
     390      103208 :   if (property_array->length() > 0) {
     391      206416 :     receiver->SetProperties(*property_array);
     392             :   }
     393             :   return true;
     394             : }
     395             : 
     396        3294 : 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        3294 :       ShallowCopyDictionaryTemplate(isolate, properties_dictionary_template);
     407             :   Handle<NumberDictionary> elements_dictionary =
     408        3294 :       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        9893 :   while (i < computed_properties_length) {
     417        6610 :     int flags = Smi::ToInt(computed_properties->get(i++));
     418             : 
     419        3305 :     ValueKind value_kind = ComputedEntryFlags::ValueKindBits::decode(flags);
     420        3305 :     int key_index = ComputedEntryFlags::KeyIndexBits::decode(flags);
     421        6610 :     Object value = Smi::FromInt(key_index + 1);  // Value follows name.
     422             : 
     423        3305 :     Handle<Object> key = args.at<Object>(key_index);
     424             :     DCHECK(key->IsName());
     425             :     uint32_t element;
     426        3305 :     Handle<Name> name = Handle<Name>::cast(key);
     427        3305 :     if (name->AsArrayIndex(&element)) {
     428             :       ClassBoilerplate::AddToElementsTemplate(
     429         306 :           isolate, elements_dictionary, element, key_index, value_kind, value);
     430             : 
     431             :     } else {
     432        2999 :       name = isolate->factory()->InternalizeName(name);
     433             :       ClassBoilerplate::AddToPropertiesTemplate(
     434        2999 :           isolate, properties_dictionary, name, key_index, value_kind, value);
     435             :     }
     436             :   }
     437             : 
     438             :   // Replace all indices with proper methods.
     439        3294 :   if (!SubstituteValues<NameDictionary>(isolate, properties_dictionary,
     440             :                                         receiver, args,
     441        3294 :                                         &install_name_accessor)) {
     442             :     return false;
     443             :   }
     444        3294 :   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        2649 :         isolate->factory()->function_name_accessor(), details);
     451        7947 :     CHECK_EQ(*dict, *properties_dictionary);
     452             :   }
     453             : 
     454        3294 :   if (elements_dictionary->NumberOfElements() > 0) {
     455         162 :     if (!SubstituteValues<NumberDictionary>(isolate, elements_dictionary,
     456         162 :                                             receiver, args)) {
     457             :       return false;
     458             :     }
     459         162 :     map->set_elements_kind(DICTIONARY_ELEMENTS);
     460             :   }
     461             : 
     462             :   // Atomically commit the changes.
     463        3294 :   receiver->synchronized_set_map(*map);
     464        6588 :   receiver->set_raw_properties_or_hash(*properties_dictionary);
     465        3294 :   if (elements_dictionary->NumberOfElements() > 0) {
     466         324 :     receiver->set_elements(*elements_dictionary);
     467             :   }
     468             :   return true;
     469             : }
     470             : 
     471       53251 : 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       53251 :     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       53251 :   return factory->NewJSObjectFromMap(map);
     492             : }
     493             : 
     494       53251 : bool InitClassPrototype(Isolate* isolate,
     495             :                         Handle<ClassBoilerplate> class_boilerplate,
     496             :                         Handle<JSObject> prototype,
     497             :                         Handle<Object> prototype_parent,
     498             :                         Handle<JSFunction> constructor, Arguments& args) {
     499             :   Handle<Map> map(prototype->map(), isolate);
     500       53251 :   map = Map::CopyDropDescriptors(isolate, map);
     501             :   map->set_is_prototype_map(true);
     502       53251 :   Map::SetPrototype(isolate, map, prototype_parent);
     503      106502 :   constructor->set_prototype_or_initial_map(*prototype);
     504      106502 :   map->SetConstructor(*constructor);
     505             :   Handle<FixedArray> computed_properties(
     506      106502 :       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      106502 :   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       52660 :         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       52660 :                                     args);
     539             :   }
     540             : }
     541             : 
     542       53251 : bool InitClassConstructor(Isolate* isolate,
     543             :                           Handle<ClassBoilerplate> class_boilerplate,
     544             :                           Handle<Object> constructor_parent,
     545             :                           Handle<JSFunction> constructor, Arguments& args) {
     546             :   Handle<Map> map(constructor->map(), isolate);
     547       53251 :   map = Map::CopyDropDescriptors(isolate, map);
     548             :   DCHECK(map->is_prototype_map());
     549             : 
     550       53251 :   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       15123 :     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      106502 :       class_boilerplate->static_computed_properties(), isolate);
     561             : 
     562             :   Handle<Object> properties_template(
     563             :       class_boilerplate->static_properties_template(), isolate);
     564             : 
     565      106502 :   if (properties_template->IsNameDictionary()) {
     566             :     Handle<NameDictionary> properties_dictionary_template =
     567        2703 :         Handle<NameDictionary>::cast(properties_template);
     568             : 
     569        2703 :     map->set_is_dictionary_map(true);
     570             :     map->InitializeDescriptors(isolate,
     571             :                                ReadOnlyRoots(isolate).empty_descriptor_array(),
     572        2703 :                                LayoutDescriptor::FastPointerLayout());
     573        2703 :     map->set_is_migration_target(false);
     574        2703 :     map->set_may_have_interesting_symbols(true);
     575        2703 :     map->set_construction_counter(Map::kNoSlackTracking);
     576             : 
     577             :     bool install_name_accessor =
     578        2703 :         class_boilerplate->install_class_name_accessor() != 0;
     579             : 
     580             :     return AddDescriptorsByTemplate(
     581             :         isolate, map, properties_dictionary_template,
     582             :         elements_dictionary_template, computed_properties, constructor,
     583        5406 :         install_name_accessor, args);
     584             :   } else {
     585             :     Handle<DescriptorArray> descriptors_template =
     586       50548 :         Handle<DescriptorArray>::cast(properties_template);
     587             : 
     588             :     return AddDescriptorsByTemplate(isolate, map, descriptors_template,
     589             :                                     elements_dictionary_template, constructor,
     590       50548 :                                     args);
     591             :   }
     592             : }
     593             : 
     594       54312 : 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<Object> constructor_parent;
     601             : 
     602      106988 :   if (super_class->IsTheHole(isolate)) {
     603       37873 :     prototype_parent = isolate->initial_object_prototype();
     604             :   } else {
     605       31242 :     if (super_class->IsNull(isolate)) {
     606             :       prototype_parent = isolate->factory()->null_value();
     607       30732 :     } else if (super_class->IsConstructor()) {
     608             :       DCHECK(!super_class->IsJSFunction() ||
     609             :              !IsResumableFunction(
     610             :                  Handle<JSFunction>::cast(super_class)->shared()->kind()));
     611       30336 :       ASSIGN_RETURN_ON_EXCEPTION(
     612             :           isolate, prototype_parent,
     613             :           Runtime::GetObjectProperty(isolate, super_class,
     614             :                                      isolate->factory()->prototype_string()),
     615             :           Object);
     616       60654 :       if (!prototype_parent->IsNull(isolate) &&
     617       30318 :           !prototype_parent->IsJSReceiver()) {
     618          45 :         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       15123 :       constructor_parent = handle(*super_class, isolate);
     627             :     } else {
     628         198 :       THROW_NEW_ERROR(isolate,
     629             :                       NewTypeError(MessageTemplate::kExtendsValueNotConstructor,
     630             :                                    super_class),
     631             :                       Object);
     632             :     }
     633             :   }
     634             : 
     635       53251 :   Handle<JSObject> prototype = CreateClassPrototype(isolate);
     636             :   DCHECK_EQ(*constructor, args[ClassBoilerplate::kConstructorArgumentIndex]);
     637             :   args.set_at(ClassBoilerplate::kPrototypeArgumentIndex, *prototype);
     638             : 
     639       53251 :   if (!InitClassConstructor(isolate, class_boilerplate, constructor_parent,
     640      106502 :                             constructor, args) ||
     641             :       !InitClassPrototype(isolate, class_boilerplate, prototype,
     642       53251 :                           prototype_parent, constructor, args)) {
     643             :     DCHECK(isolate->has_pending_exception());
     644           0 :     return MaybeHandle<Object>();
     645             :   }
     646       53251 :   if (FLAG_trace_maps) {
     647        1227 :     LOG(isolate,
     648             :         MapEvent("InitialMap", Map(), constructor->map(),
     649             :                  "init class constructor", constructor->shared()->DebugName()));
     650         818 :     LOG(isolate, MapEvent("InitialMap", Map(), prototype->map(),
     651             :                           "init class prototype"));
     652             :   }
     653             : 
     654       53251 :   return prototype;
     655             : }
     656             : 
     657             : }  // namespace
     658             : 
     659       53494 : RUNTIME_FUNCTION(Runtime_DefineClass) {
     660       53494 :   HandleScope scope(isolate);
     661             :   DCHECK_LE(ClassBoilerplate::kFirstDynamicArgumentIndex, args.length());
     662      106988 :   CONVERT_ARG_HANDLE_CHECKED(ClassBoilerplate, class_boilerplate, 0);
     663      106988 :   CONVERT_ARG_HANDLE_CHECKED(JSFunction, constructor, 1);
     664       53494 :   CONVERT_ARG_HANDLE_CHECKED(Object, super_class, 2);
     665             :   DCHECK_EQ(class_boilerplate->arguments_count(), args.length());
     666             : 
     667      106988 :   RETURN_RESULT_OR_FAILURE(
     668             :       isolate,
     669       53494 :       DefineClass(isolate, class_boilerplate, super_class, constructor, args));
     670             : }
     671             : 
     672             : namespace {
     673             : 
     674             : enum class SuperMode { kLoad, kStore };
     675             : 
     676       13627 : MaybeHandle<JSReceiver> GetSuperHolder(
     677             :     Isolate* isolate, Handle<Object> receiver, Handle<JSObject> home_object,
     678             :     SuperMode mode, MaybeHandle<Name> maybe_name, uint32_t index) {
     679       27254 :   if (home_object->IsAccessCheckNeeded() &&
     680           0 :       !isolate->MayAccess(handle(isolate->context(), isolate), home_object)) {
     681           0 :     isolate->ReportFailedAccessCheck(home_object);
     682           0 :     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, JSReceiver);
     683             :   }
     684             : 
     685       13627 :   PrototypeIterator iter(isolate, home_object);
     686             :   Handle<Object> proto = PrototypeIterator::GetCurrent(iter);
     687       27254 :   if (!proto->IsJSReceiver()) {
     688             :     MessageTemplate message = mode == SuperMode::kLoad
     689             :                                   ? MessageTemplate::kNonObjectPropertyLoad
     690          72 :                                   : MessageTemplate::kNonObjectPropertyStore;
     691             :     Handle<Name> name;
     692          72 :     if (!maybe_name.ToHandle(&name)) {
     693          36 :       name = isolate->factory()->Uint32ToString(index);
     694             :     }
     695          72 :     THROW_NEW_ERROR(isolate, NewTypeError(message, name, proto), JSReceiver);
     696             :   }
     697       13555 :   return Handle<JSReceiver>::cast(proto);
     698             : }
     699             : 
     700       11668 : MaybeHandle<Object> LoadFromSuper(Isolate* isolate, Handle<Object> receiver,
     701             :                                   Handle<JSObject> home_object,
     702             :                                   Handle<Name> name) {
     703             :   Handle<JSReceiver> holder;
     704       23336 :   ASSIGN_RETURN_ON_EXCEPTION(
     705             :       isolate, holder,
     706             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad, name, 0),
     707             :       Object);
     708       11650 :   LookupIterator it(receiver, name, holder);
     709             :   Handle<Object> result;
     710       23300 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
     711       11650 :   return result;
     712             : }
     713             : 
     714         522 : MaybeHandle<Object> LoadElementFromSuper(Isolate* isolate,
     715             :                                          Handle<Object> receiver,
     716             :                                          Handle<JSObject> home_object,
     717             :                                          uint32_t index) {
     718             :   Handle<JSReceiver> holder;
     719        1044 :   ASSIGN_RETURN_ON_EXCEPTION(
     720             :       isolate, holder,
     721             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kLoad,
     722             :                      MaybeHandle<Name>(), index),
     723             :       Object);
     724             :   LookupIterator it(isolate, receiver, index, holder);
     725             :   Handle<Object> result;
     726        1008 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, result, Object::GetProperty(&it), Object);
     727         504 :   return result;
     728             : }
     729             : 
     730             : }  // anonymous namespace
     731             : 
     732       11146 : RUNTIME_FUNCTION(Runtime_LoadFromSuper) {
     733       11146 :   HandleScope scope(isolate);
     734             :   DCHECK_EQ(3, args.length());
     735       11146 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     736       22292 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     737       22292 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     738             : 
     739       22292 :   RETURN_RESULT_OR_FAILURE(isolate,
     740       11146 :                            LoadFromSuper(isolate, receiver, home_object, name));
     741             : }
     742             : 
     743             : 
     744        1062 : RUNTIME_FUNCTION(Runtime_LoadKeyedFromSuper) {
     745        1062 :   HandleScope scope(isolate);
     746             :   DCHECK_EQ(3, args.length());
     747        1062 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     748        2124 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     749        1062 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     750             : 
     751        1062 :   uint32_t index = 0;
     752             : 
     753        1062 :   if (key->ToArrayIndex(&index)) {
     754         990 :     RETURN_RESULT_OR_FAILURE(
     755             :         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
     756             :   }
     757             : 
     758             :   Handle<Name> name;
     759        1134 :   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
     760             :                                      Object::ToName(isolate, key));
     761             :   // TODO(verwaest): Unify using LookupIterator.
     762         549 :   if (name->AsArrayIndex(&index)) {
     763          54 :     RETURN_RESULT_OR_FAILURE(
     764             :         isolate, LoadElementFromSuper(isolate, receiver, home_object, index));
     765             :   }
     766        1044 :   RETURN_RESULT_OR_FAILURE(isolate,
     767        1062 :                            LoadFromSuper(isolate, receiver, home_object, name));
     768             : }
     769             : 
     770             : namespace {
     771             : 
     772         996 : MaybeHandle<Object> StoreToSuper(Isolate* isolate, Handle<JSObject> home_object,
     773             :                                  Handle<Object> receiver, Handle<Name> name,
     774             :                                  Handle<Object> value) {
     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(Object::SetSuperProperty(&it, value, StoreOrigin::kNamed),
     782             :                MaybeHandle<Object>());
     783         793 :   return value;
     784             : }
     785             : 
     786         441 : MaybeHandle<Object> StoreElementToSuper(Isolate* isolate,
     787             :                                         Handle<JSObject> home_object,
     788             :                                         Handle<Object> receiver, uint32_t index,
     789             :                                         Handle<Object> value) {
     790             :   Handle<JSReceiver> holder;
     791         882 :   ASSIGN_RETURN_ON_EXCEPTION(
     792             :       isolate, holder,
     793             :       GetSuperHolder(isolate, receiver, home_object, SuperMode::kStore,
     794             :                      MaybeHandle<Name>(), index),
     795             :       Object);
     796             :   LookupIterator it(isolate, receiver, index, holder);
     797         423 :   MAYBE_RETURN(Object::SetSuperProperty(&it, value, StoreOrigin::kMaybeKeyed),
     798             :                MaybeHandle<Object>());
     799         333 :   return value;
     800             : }
     801             : 
     802             : }  // anonymous namespace
     803             : 
     804         537 : RUNTIME_FUNCTION(Runtime_StoreToSuper) {
     805         537 :   HandleScope scope(isolate);
     806             :   DCHECK_EQ(4, args.length());
     807         537 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     808        1074 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     809        1074 :   CONVERT_ARG_HANDLE_CHECKED(Name, name, 2);
     810         537 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     811             : 
     812        1074 :   RETURN_RESULT_OR_FAILURE(
     813         537 :       isolate, StoreToSuper(isolate, home_object, receiver, name, value));
     814             : }
     815             : 
     816         918 : static MaybeHandle<Object> StoreKeyedToSuper(Isolate* isolate,
     817             :                                              Handle<JSObject> home_object,
     818             :                                              Handle<Object> receiver,
     819             :                                              Handle<Object> key,
     820             :                                              Handle<Object> value) {
     821         918 :   uint32_t index = 0;
     822             : 
     823        1836 :   if (key->ToArrayIndex(&index)) {
     824         423 :     return StoreElementToSuper(isolate, home_object, receiver, index, value);
     825             :   }
     826             :   Handle<Name> name;
     827         990 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, name, Object::ToName(isolate, key),
     828             :                              Object);
     829             :   // TODO(verwaest): Unify using LookupIterator.
     830         477 :   if (name->AsArrayIndex(&index)) {
     831          18 :     return StoreElementToSuper(isolate, home_object, receiver, index, value);
     832             :   }
     833         459 :   return StoreToSuper(isolate, home_object, receiver, name, value);
     834             : }
     835             : 
     836         918 : RUNTIME_FUNCTION(Runtime_StoreKeyedToSuper) {
     837         918 :   HandleScope scope(isolate);
     838             :   DCHECK_EQ(4, args.length());
     839         918 :   CONVERT_ARG_HANDLE_CHECKED(Object, receiver, 0);
     840        1836 :   CONVERT_ARG_HANDLE_CHECKED(JSObject, home_object, 1);
     841         918 :   CONVERT_ARG_HANDLE_CHECKED(Object, key, 2);
     842         918 :   CONVERT_ARG_HANDLE_CHECKED(Object, value, 3);
     843             : 
     844        1836 :   RETURN_RESULT_OR_FAILURE(
     845         918 :       isolate, StoreKeyedToSuper(isolate, home_object, receiver, key, value));
     846             : }
     847             : 
     848             : }  // namespace internal
     849      178779 : }  // namespace v8

Generated by: LCOV version 1.10