LCOV - code coverage report
Current view: top level - src - api-natives.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 238 263 90.5 %
Date: 2019-01-20 Functions: 27 28 96.4 %

          Line data    Source code
       1             : // Copyright 2015 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/api-natives.h"
       6             : 
       7             : #include "src/api-inl.h"
       8             : #include "src/isolate-inl.h"
       9             : #include "src/lookup.h"
      10             : #include "src/message-template.h"
      11             : #include "src/objects/api-callbacks.h"
      12             : #include "src/objects/hash-table-inl.h"
      13             : #include "src/objects/property-cell.h"
      14             : #include "src/objects/templates.h"
      15             : 
      16             : namespace v8 {
      17             : namespace internal {
      18             : 
      19             : 
      20             : namespace {
      21             : 
      22             : class InvokeScope {
      23             :  public:
      24             :   explicit InvokeScope(Isolate* isolate)
      25     2377934 :       : isolate_(isolate), save_context_(isolate) {}
      26     4755860 :   ~InvokeScope() {
      27     2377918 :     bool has_exception = isolate_->has_pending_exception();
      28     2377940 :     if (has_exception) {
      29           0 :       isolate_->ReportPendingMessages();
      30             :     } else {
      31     2377940 :       isolate_->clear_pending_message();
      32             :     }
      33     2377943 :   }
      34             : 
      35             :  private:
      36             :   Isolate* isolate_;
      37             :   SaveContext save_context_;
      38             : };
      39             : 
      40             : MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
      41             :                                         Handle<ObjectTemplateInfo> data,
      42             :                                         Handle<JSReceiver> new_target,
      43             :                                         bool is_hidden_prototype,
      44             :                                         bool is_prototype);
      45             : 
      46             : MaybeHandle<JSFunction> InstantiateFunction(
      47             :     Isolate* isolate, Handle<FunctionTemplateInfo> data,
      48             :     MaybeHandle<Name> maybe_name = MaybeHandle<Name>());
      49             : 
      50     2781959 : MaybeHandle<Object> Instantiate(
      51             :     Isolate* isolate, Handle<Object> data,
      52             :     MaybeHandle<Name> maybe_name = MaybeHandle<Name>()) {
      53     5563918 :   if (data->IsFunctionTemplateInfo()) {
      54             :     return InstantiateFunction(
      55     2250464 :         isolate, Handle<FunctionTemplateInfo>::cast(data), maybe_name);
      56     1062990 :   } else if (data->IsObjectTemplateInfo()) {
      57             :     return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
      58      415212 :                              Handle<JSReceiver>(), false, false);
      59             :   } else {
      60      116283 :     return data;
      61             :   }
      62             : }
      63             : 
      64         144 : MaybeHandle<Object> DefineAccessorProperty(
      65             :     Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
      66             :     Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes,
      67             :     bool force_instantiate) {
      68             :   DCHECK(!getter->IsFunctionTemplateInfo() ||
      69             :          !FunctionTemplateInfo::cast(*getter)->do_not_cache());
      70             :   DCHECK(!setter->IsFunctionTemplateInfo() ||
      71             :          !FunctionTemplateInfo::cast(*setter)->do_not_cache());
      72         144 :   if (force_instantiate) {
      73           0 :     if (getter->IsFunctionTemplateInfo()) {
      74           0 :       ASSIGN_RETURN_ON_EXCEPTION(
      75             :           isolate, getter,
      76             :           InstantiateFunction(isolate,
      77             :                               Handle<FunctionTemplateInfo>::cast(getter)),
      78             :           Object);
      79             :     }
      80           0 :     if (setter->IsFunctionTemplateInfo()) {
      81           0 :       ASSIGN_RETURN_ON_EXCEPTION(
      82             :           isolate, setter,
      83             :           InstantiateFunction(isolate,
      84             :                               Handle<FunctionTemplateInfo>::cast(setter)),
      85             :           Object);
      86             :     }
      87             :   }
      88         288 :   RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
      89             :                                                         setter, attributes),
      90             :                       Object);
      91         144 :   return object;
      92             : }
      93             : 
      94             : 
      95     2781959 : MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
      96             :                                        Handle<JSObject> object,
      97             :                                        Handle<Name> name,
      98             :                                        Handle<Object> prop_data,
      99             :                                        PropertyAttributes attributes) {
     100             :   Handle<Object> value;
     101     5563918 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
     102             :                              Instantiate(isolate, prop_data, name), Object);
     103             : 
     104             :   LookupIterator it = LookupIterator::PropertyOrElement(
     105     2781959 :       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
     106             : 
     107             : #ifdef DEBUG
     108             :   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     109             :   DCHECK(maybe.IsJust());
     110             :   if (it.IsFound()) {
     111             :     THROW_NEW_ERROR(
     112             :         isolate,
     113             :         NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
     114             :         Object);
     115             :   }
     116             : #endif
     117             : 
     118     2781959 :   MAYBE_RETURN_NULL(Object::AddDataProperty(
     119             :       &it, value, attributes, kThrowOnError, StoreOrigin::kNamed));
     120     2781959 :   return value;
     121             : }
     122             : 
     123             : 
     124         232 : void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     125             :   Handle<Map> old_map(object->map(), isolate);
     126             :   // Copy map so it won't interfere constructor's initial map.
     127         232 :   Handle<Map> new_map = Map::Copy(isolate, old_map, "DisableAccessChecks");
     128             :   new_map->set_is_access_check_needed(false);
     129         232 :   JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
     130         232 : }
     131             : 
     132             : 
     133         232 : void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     134             :   Handle<Map> old_map(object->map(), isolate);
     135             :   // Copy map so it won't interfere constructor's initial map.
     136         232 :   Handle<Map> new_map = Map::Copy(isolate, old_map, "EnableAccessChecks");
     137             :   new_map->set_is_access_check_needed(true);
     138         232 :   new_map->set_may_have_interesting_symbols(true);
     139         232 :   JSObject::MigrateToMap(object, new_map);
     140         232 : }
     141             : 
     142             : 
     143             : class AccessCheckDisableScope {
     144             :  public:
     145     4482950 :   AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
     146             :       : isolate_(isolate),
     147             :         disabled_(obj->map()->is_access_check_needed()),
     148     8965905 :         obj_(obj) {
     149     4482955 :     if (disabled_) {
     150         232 :       DisableAccessChecks(isolate_, obj_);
     151             :     }
     152     4482955 :   }
     153             :   ~AccessCheckDisableScope() {
     154     4482958 :     if (disabled_) {
     155         232 :       EnableAccessChecks(isolate_, obj_);
     156             :     }
     157             :   }
     158             : 
     159             :  private:
     160             :   Isolate* isolate_;
     161             :   const bool disabled_;
     162             :   Handle<JSObject> obj_;
     163             : };
     164             : 
     165          60 : Object GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
     166          60 :   Handle<Context> native_context = isolate->native_context();
     167             :   DCHECK(!native_context.is_null());
     168          60 :   switch (intrinsic) {
     169             : #define GET_INTRINSIC_VALUE(name, iname) \
     170             :   case v8::k##name:                      \
     171             :     return native_context->iname();
     172          60 :     V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
     173             : #undef GET_INTRINSIC_VALUE
     174             :   }
     175           0 :   return Object();
     176             : }
     177             : 
     178             : template <typename TemplateInfoT>
     179     4482955 : MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
     180             :                                         Handle<TemplateInfoT> data,
     181             :                                         bool is_hidden_prototype) {
     182             :   HandleScope scope(isolate);
     183             :   // Disable access checks while instantiating the object.
     184     4482955 :   AccessCheckDisableScope access_check_scope(isolate, obj);
     185             : 
     186             :   // Walk the inheritance chain and copy all accessors to current object.
     187             :   int max_number_of_properties = 0;
     188     4482949 :   TemplateInfoT info = *data;
     189    13449288 :   while (!info.is_null()) {
     190     4483374 :     Object props = info->property_accessors();
     191     4483386 :     if (!props->IsUndefined(isolate)) {
     192       52023 :       max_number_of_properties += TemplateList::cast(props)->length();
     193             :     }
     194     4483386 :     info = info->GetParent(isolate);
     195             :   }
     196             : 
     197     4482965 :   if (max_number_of_properties > 0) {
     198             :     int valid_descriptors = 0;
     199             :     // Use a temporary FixedArray to accumulate unique accessors.
     200             :     Handle<FixedArray> array =
     201       52005 :         isolate->factory()->NewFixedArray(max_number_of_properties);
     202             : 
     203      104082 :     for (Handle<TemplateInfoT> temp(*data, isolate); !temp->is_null();
     204      104154 :          temp = handle(temp->GetParent(isolate), isolate)) {
     205             :       // Accumulate accessors.
     206       52077 :       Object maybe_properties = temp->property_accessors();
     207       52077 :       if (!maybe_properties->IsUndefined(isolate)) {
     208       52023 :         valid_descriptors = AccessorInfo::AppendUnique(
     209             :             isolate, handle(maybe_properties, isolate), array,
     210             :             valid_descriptors);
     211             :       }
     212             :     }
     213             : 
     214             :     // Install accumulated accessors.
     215       52296 :     for (int i = 0; i < valid_descriptors; i++) {
     216             :       Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)), isolate);
     217      104592 :       Handle<Name> name(Name::cast(accessor->name()), isolate);
     218             :       JSObject::SetAccessor(obj, name, accessor,
     219      104592 :                             accessor->initial_property_attributes())
     220       52296 :           .Assert();
     221             :     }
     222             :   }
     223             : 
     224     4482939 :   Object maybe_property_list = data->property_list();
     225     4482958 :   if (maybe_property_list->IsUndefined(isolate)) return obj;
     226             :   Handle<TemplateList> properties(TemplateList::cast(maybe_property_list),
     227             :                                   isolate);
     228      367784 :   if (properties->length() == 0) return obj;
     229             : 
     230             :   int i = 0;
     231     5931990 :   for (int c = 0; c < data->number_of_properties(); c++) {
     232     8346309 :     auto name = handle(Name::cast(properties->get(i++)), isolate);
     233     5564206 :     Object bit = properties->get(i++);
     234     2782103 :     if (bit->IsSmi()) {
     235             :       PropertyDetails details(Smi::cast(bit));
     236             :       PropertyAttributes attributes = details.attributes();
     237             :       PropertyKind kind = details.kind();
     238             : 
     239     2782043 :       if (kind == kData) {
     240     8345697 :         auto prop_data = handle(properties->get(i++), isolate);
     241     5563798 :         RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     242             :                                                         prop_data, attributes),
     243             :                             JSObject);
     244             :       } else {
     245         432 :         auto getter = handle(properties->get(i++), isolate);
     246         432 :         auto setter = handle(properties->get(i++), isolate);
     247         288 :         RETURN_ON_EXCEPTION(
     248             :             isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
     249             :                                             attributes, is_hidden_prototype),
     250             :             JSObject);
     251             :       }
     252             :     } else {
     253             :       // Intrinsic data property --- Get appropriate value from the current
     254             :       // context.
     255         180 :       PropertyDetails details(Smi::cast(properties->get(i++)));
     256             :       PropertyAttributes attributes = details.attributes();
     257             :       DCHECK_EQ(kData, details.kind());
     258             : 
     259             :       v8::Intrinsic intrinsic =
     260         120 :           static_cast<v8::Intrinsic>(Smi::ToInt(properties->get(i++)));
     261         120 :       auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
     262             : 
     263         120 :       RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     264             :                                                       prop_data, attributes),
     265             :                           JSObject);
     266             :     }
     267             :   }
     268      367784 :   return obj;
     269             : }
     270             : 
     271             : // Whether or not to cache every instance: when we materialize a getter or
     272             : // setter from an lazy AccessorPair, we rely on this cache to be able to always
     273             : // return the same getter or setter. However, objects will be cloned anyways,
     274             : // so it's not observable if we didn't cache an instance. Furthermore, a badly
     275             : // behaved embedder might create an unlimited number of objects, so we limit
     276             : // the cache for those cases.
     277             : enum class CachingMode { kLimited, kUnlimited };
     278             : 
     279     4822445 : MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate,
     280             :                                                int serial_number,
     281             :                                                CachingMode caching_mode) {
     282             :   DCHECK_LE(1, serial_number);
     283     4822445 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     284             :     Handle<FixedArray> fast_cache =
     285     4744851 :         isolate->fast_template_instantiations_cache();
     286     9489704 :     return fast_cache->GetValue<JSObject>(isolate, serial_number - 1);
     287      155188 :   } else if (caching_mode == CachingMode::kUnlimited ||
     288       77594 :              (serial_number <=
     289             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     290             :     Handle<SimpleNumberDictionary> slow_cache =
     291       77594 :         isolate->slow_template_instantiations_cache();
     292      155188 :     int entry = slow_cache->FindEntry(isolate, serial_number);
     293       77594 :     if (entry == SimpleNumberDictionary::kNotFound) {
     294       74527 :       return MaybeHandle<JSObject>();
     295             :     }
     296        6134 :     return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate);
     297             :   } else {
     298           0 :     return MaybeHandle<JSObject>();
     299             :   }
     300             : }
     301             : 
     302     3988203 : void CacheTemplateInstantiation(Isolate* isolate, int serial_number,
     303             :                                 CachingMode caching_mode,
     304             :                                 Handle<JSObject> object) {
     305             :   DCHECK_LE(1, serial_number);
     306     3988203 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     307             :     Handle<FixedArray> fast_cache =
     308     3913694 :         isolate->fast_template_instantiations_cache();
     309             :     Handle<FixedArray> new_cache =
     310     3913695 :         FixedArray::SetAndGrow(isolate, fast_cache, serial_number - 1, object);
     311     3913692 :     if (*new_cache != *fast_cache) {
     312           0 :       isolate->native_context()->set_fast_template_instantiations_cache(
     313           0 :           *new_cache);
     314             :     }
     315      149018 :   } else if (caching_mode == CachingMode::kUnlimited ||
     316       74509 :              (serial_number <=
     317             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     318             :     Handle<SimpleNumberDictionary> cache =
     319       74509 :         isolate->slow_template_instantiations_cache();
     320             :     auto new_cache =
     321       74509 :         SimpleNumberDictionary::Set(isolate, cache, serial_number, object);
     322       74509 :     if (*new_cache != *cache) {
     323           0 :       isolate->native_context()->set_slow_template_instantiations_cache(
     324           0 :           *new_cache);
     325             :     }
     326             :   }
     327     3988201 : }
     328             : 
     329           0 : void UncacheTemplateInstantiation(Isolate* isolate, int serial_number,
     330             :                                   CachingMode caching_mode) {
     331             :   DCHECK_LE(1, serial_number);
     332           0 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     333             :     Handle<FixedArray> fast_cache =
     334           0 :         isolate->fast_template_instantiations_cache();
     335             :     DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate));
     336           0 :     fast_cache->set_undefined(serial_number - 1);
     337           0 :   } else if (caching_mode == CachingMode::kUnlimited ||
     338           0 :              (serial_number <=
     339             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     340             :     Handle<SimpleNumberDictionary> cache =
     341           0 :         isolate->slow_template_instantiations_cache();
     342           0 :     int entry = cache->FindEntry(isolate, serial_number);
     343             :     DCHECK_NE(SimpleNumberDictionary::kNotFound, entry);
     344           0 :     cache = SimpleNumberDictionary::DeleteEntry(isolate, cache, entry);
     345           0 :     isolate->native_context()->set_slow_template_instantiations_cache(*cache);
     346             :   }
     347           0 : }
     348             : 
     349      332840 : bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo info,
     350             :                            JSReceiver new_target) {
     351             :   DisallowHeapAllocation no_gc;
     352             : 
     353      332841 :   if (!new_target->IsJSFunction()) return false;
     354      332840 :   JSFunction fun = JSFunction::cast(new_target);
     355      665684 :   if (fun->shared()->function_data() != info->constructor()) return false;
     356        2889 :   if (info->immutable_proto()) return false;
     357        5766 :   return fun->context()->native_context() == isolate->raw_native_context();
     358             : }
     359             : 
     360      965118 : MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
     361             :                                         Handle<ObjectTemplateInfo> info,
     362             :                                         Handle<JSReceiver> new_target,
     363             :                                         bool is_hidden_prototype,
     364             :                                         bool is_prototype) {
     365             :   Handle<JSFunction> constructor;
     366      965127 :   int serial_number = Smi::ToInt(info->serial_number());
     367      965134 :   if (!new_target.is_null()) {
     368      332841 :     if (IsSimpleInstantiation(isolate, *info, *new_target)) {
     369        2883 :       constructor = Handle<JSFunction>::cast(new_target);
     370             :     } else {
     371             :       // Disable caching for subclass instantiation.
     372             :       serial_number = 0;
     373             :     }
     374             :   }
     375             :   // Fast path.
     376             :   Handle<JSObject> result;
     377      965138 :   if (serial_number) {
     378      476284 :     if (ProbeInstantiationsCache(isolate, serial_number, CachingMode::kLimited)
     379      952568 :             .ToHandle(&result)) {
     380      209714 :       return isolate->factory()->CopyJSObject(result);
     381             :     }
     382             :   }
     383             : 
     384      755424 :   if (constructor.is_null()) {
     385      753858 :     Object maybe_constructor_info = info->constructor();
     386      753859 :     if (maybe_constructor_info->IsUndefined(isolate)) {
     387      587166 :       constructor = isolate->object_function();
     388             :     } else {
     389             :       // Enter a new scope.  Recursion could otherwise create a lot of handles.
     390             :       HandleScope scope(isolate);
     391             :       Handle<FunctionTemplateInfo> cons_templ(
     392             :           FunctionTemplateInfo::cast(maybe_constructor_info), isolate);
     393             :       Handle<JSFunction> tmp_constructor;
     394      333386 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor,
     395             :                                  InstantiateFunction(isolate, cons_templ),
     396             :                                  JSObject);
     397      166693 :       constructor = scope.CloseAndEscape(tmp_constructor);
     398             :     }
     399             : 
     400      753858 :     if (new_target.is_null()) new_target = constructor;
     401             :   }
     402             : 
     403             :   Handle<JSObject> object;
     404     1510846 :   ASSIGN_RETURN_ON_EXCEPTION(
     405             :       isolate, object,
     406             :       JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
     407             :       JSObject);
     408             : 
     409      755422 :   if (is_prototype) JSObject::OptimizeAsPrototype(object);
     410             : 
     411     1510820 :   ASSIGN_RETURN_ON_EXCEPTION(
     412             :       isolate, result,
     413             :       ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
     414      755401 :   if (info->immutable_proto()) {
     415          24 :     JSObject::SetImmutableProto(object);
     416             :   }
     417      755413 :   if (!is_prototype) {
     418             :     // Keep prototypes in slow-mode. Let them be lazily turned fast later on.
     419             :     // TODO(dcarney): is this necessary?
     420      649464 :     JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
     421             :     // Don't cache prototypes.
     422      649452 :     if (serial_number) {
     423             :       CacheTemplateInstantiation(isolate, serial_number, CachingMode::kLimited,
     424      265854 :                                  result);
     425      265854 :       result = isolate->factory()->CopyJSObject(result);
     426             :     }
     427             :   }
     428             : 
     429      755401 :   return result;
     430             : }
     431             : 
     432             : namespace {
     433         249 : MaybeHandle<Object> GetInstancePrototype(Isolate* isolate,
     434             :                                          Object function_template) {
     435             :   // Enter a new scope.  Recursion could otherwise create a lot of handles.
     436             :   HandleScope scope(isolate);
     437             :   Handle<JSFunction> parent_instance;
     438         747 :   ASSIGN_RETURN_ON_EXCEPTION(
     439             :       isolate, parent_instance,
     440             :       InstantiateFunction(
     441             :           isolate,
     442             :           handle(FunctionTemplateInfo::cast(function_template), isolate)),
     443             :       JSFunction);
     444             :   Handle<Object> instance_prototype;
     445             :   // TODO(cbruni): decide what to do here.
     446         498 :   ASSIGN_RETURN_ON_EXCEPTION(
     447             :       isolate, instance_prototype,
     448             :       JSObject::GetProperty(isolate, parent_instance,
     449             :                             isolate->factory()->prototype_string()),
     450             :       JSFunction);
     451         249 :   return scope.CloseAndEscape(instance_prototype);
     452             : }
     453             : }  // namespace
     454             : 
     455     4351349 : MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
     456             :                                             Handle<FunctionTemplateInfo> data,
     457             :                                             MaybeHandle<Name> maybe_name) {
     458     4351349 :   int serial_number = Smi::ToInt(data->serial_number());
     459     4351351 :   if (serial_number) {
     460             :     Handle<JSObject> result;
     461     4346161 :     if (ProbeInstantiationsCache(isolate, serial_number,
     462             :                                  CachingMode::kUnlimited)
     463     8692323 :             .ToHandle(&result)) {
     464      623810 :       return Handle<JSFunction>::cast(result);
     465             :     }
     466             :   }
     467             :   Handle<Object> prototype;
     468     3727540 :   if (!data->remove_prototype()) {
     469     3722684 :     Object prototype_templ = data->GetPrototypeTemplate();
     470     3722682 :     if (prototype_templ->IsUndefined(isolate)) {
     471     3616733 :       Object protoype_provider_templ = data->GetPrototypeProviderTemplate();
     472     3616734 :       if (protoype_provider_templ->IsUndefined(isolate)) {
     473     3616729 :         prototype = isolate->factory()->NewJSObject(isolate->object_function());
     474             :       } else {
     475          10 :         ASSIGN_RETURN_ON_EXCEPTION(
     476             :             isolate, prototype,
     477             :             GetInstancePrototype(isolate, protoype_provider_templ), JSFunction);
     478             :       }
     479             :     } else {
     480      317847 :       ASSIGN_RETURN_ON_EXCEPTION(
     481             :           isolate, prototype,
     482             :           InstantiateObject(
     483             :               isolate,
     484             :               handle(ObjectTemplateInfo::cast(prototype_templ), isolate),
     485             :               Handle<JSReceiver>(), data->hidden_prototype(), true),
     486             :           JSFunction);
     487             :     }
     488     3722679 :     Object parent = data->GetParentTemplate();
     489     3722682 :     if (!parent->IsUndefined(isolate)) {
     490             :       Handle<Object> parent_prototype;
     491         488 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, parent_prototype,
     492             :                                  GetInstancePrototype(isolate, parent),
     493             :                                  JSFunction);
     494             :       JSObject::ForceSetPrototype(Handle<JSObject>::cast(prototype),
     495         244 :                                   parent_prototype);
     496             :     }
     497             :   }
     498             :   InstanceType function_type =
     499    11182382 :       (!data->needs_access_check() &&
     500    11181176 :        data->GetNamedPropertyHandler()->IsUndefined(isolate) &&
     501     7453870 :        data->GetIndexedPropertyHandler()->IsUndefined(isolate))
     502             :           ? JS_API_OBJECT_TYPE
     503     3727538 :           : JS_SPECIAL_API_OBJECT_TYPE;
     504             : 
     505             :   Handle<JSFunction> function = ApiNatives::CreateApiFunction(
     506     3727538 :       isolate, data, prototype, function_type, maybe_name);
     507     3727540 :   if (serial_number) {
     508             :     // Cache the function.
     509             :     CacheTemplateInstantiation(isolate, serial_number, CachingMode::kUnlimited,
     510     3722350 :                                function);
     511             :   }
     512             :   MaybeHandle<JSObject> result =
     513     7455073 :       ConfigureInstance(isolate, function, data, data->hidden_prototype());
     514     3727539 :   if (result.is_null()) {
     515             :     // Uncache on error.
     516           0 :     if (serial_number) {
     517             :       UncacheTemplateInstantiation(isolate, serial_number,
     518           0 :                                    CachingMode::kUnlimited);
     519             :     }
     520           0 :     return MaybeHandle<JSFunction>();
     521             :   }
     522     3727539 :   return function;
     523             : }
     524             : 
     525             : 
     526     1956653 : void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
     527             :                                int length, Handle<Object>* data) {
     528     1956653 :   Object maybe_list = templ->property_list();
     529             :   Handle<TemplateList> list;
     530     1956653 :   if (maybe_list->IsUndefined(isolate)) {
     531      313721 :     list = TemplateList::New(isolate, length);
     532             :   } else {
     533             :     list = handle(TemplateList::cast(maybe_list), isolate);
     534             :   }
     535     1956653 :   templ->set_number_of_properties(templ->number_of_properties() + 1);
     536     7826776 :   for (int i = 0; i < length; i++) {
     537             :     Handle<Object> value =
     538     5870123 :         data[i].is_null()
     539             :             ? Handle<Object>::cast(isolate->factory()->undefined_value())
     540     5870182 :             : data[i];
     541     5870123 :     list = TemplateList::Add(isolate, list, value);
     542             :   }
     543     3913306 :   templ->set_property_list(*list);
     544     1956653 : }
     545             : 
     546             : }  // namespace
     547             : 
     548     1933944 : MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
     549             :     Handle<FunctionTemplateInfo> data, MaybeHandle<Name> maybe_name) {
     550             :   Isolate* isolate = data->GetIsolate();
     551             :   InvokeScope invoke_scope(isolate);
     552     1933945 :   return ::v8::internal::InstantiateFunction(isolate, data, maybe_name);
     553             : }
     554             : 
     555      443965 : MaybeHandle<JSObject> ApiNatives::InstantiateObject(
     556             :     Isolate* isolate, Handle<ObjectTemplateInfo> data,
     557             :     Handle<JSReceiver> new_target) {
     558             :   InvokeScope invoke_scope(isolate);
     559             :   return ::v8::internal::InstantiateObject(isolate, data, new_target, false,
     560      443972 :                                            false);
     561             : }
     562             : 
     563          26 : MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject(
     564             :     Handle<ObjectTemplateInfo> data) {
     565             :   Isolate* isolate = data->GetIsolate();
     566             :   InvokeScope invoke_scope(isolate);
     567             : 
     568             :   Handle<FunctionTemplateInfo> constructor(
     569          52 :       FunctionTemplateInfo::cast(data->constructor()), isolate);
     570             :   Handle<Map> object_map = isolate->factory()->NewMap(
     571             :       JS_SPECIAL_API_OBJECT_TYPE,
     572             :       JSObject::kHeaderSize +
     573          52 :           data->embedder_field_count() * kEmbedderDataSlotSize,
     574          26 :       TERMINAL_FAST_ELEMENTS_KIND);
     575          52 :   object_map->SetConstructor(*constructor);
     576             :   object_map->set_is_access_check_needed(true);
     577          26 :   object_map->set_may_have_interesting_symbols(true);
     578             : 
     579          26 :   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(object_map);
     580          26 :   JSObject::ForceSetPrototype(object, isolate->factory()->null_value());
     581             : 
     582          26 :   return object;
     583             : }
     584             : 
     585     1956489 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     586             :                                  Handle<Name> name, Handle<Object> value,
     587             :                                  PropertyAttributes attributes) {
     588             :   PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
     589             :   auto details_handle = handle(details.AsSmi(), isolate);
     590     1956489 :   Handle<Object> data[] = {name, details_handle, value};
     591     1956489 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     592     1956489 : }
     593             : 
     594             : 
     595          55 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     596             :                                  Handle<Name> name, v8::Intrinsic intrinsic,
     597             :                                  PropertyAttributes attributes) {
     598          55 :   auto value = handle(Smi::FromInt(intrinsic), isolate);
     599             :   auto intrinsic_marker = isolate->factory()->true_value();
     600             :   PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
     601             :   auto details_handle = handle(details.AsSmi(), isolate);
     602             :   Handle<Object> data[] = {name, intrinsic_marker, details_handle, value};
     603          55 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     604          55 : }
     605             : 
     606             : 
     607         109 : void ApiNatives::AddAccessorProperty(Isolate* isolate,
     608             :                                      Handle<TemplateInfo> info,
     609             :                                      Handle<Name> name,
     610             :                                      Handle<FunctionTemplateInfo> getter,
     611             :                                      Handle<FunctionTemplateInfo> setter,
     612             :                                      PropertyAttributes attributes) {
     613             :   PropertyDetails details(kAccessor, attributes, PropertyCellType::kNoCell);
     614             :   auto details_handle = handle(details.AsSmi(), isolate);
     615             :   Handle<Object> data[] = {name, details_handle, getter, setter};
     616         109 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     617         109 : }
     618             : 
     619             : 
     620       52207 : void ApiNatives::AddNativeDataProperty(Isolate* isolate,
     621             :                                        Handle<TemplateInfo> info,
     622             :                                        Handle<AccessorInfo> property) {
     623       52207 :   Object maybe_list = info->property_accessors();
     624             :   Handle<TemplateList> list;
     625       52207 :   if (maybe_list->IsUndefined(isolate)) {
     626       51958 :     list = TemplateList::New(isolate, 1);
     627             :   } else {
     628             :     list = handle(TemplateList::cast(maybe_list), isolate);
     629             :   }
     630       52207 :   list = TemplateList::Add(isolate, list, property);
     631      104414 :   info->set_property_accessors(*list);
     632       52207 : }
     633             : 
     634     3836165 : Handle<JSFunction> ApiNatives::CreateApiFunction(
     635             :     Isolate* isolate, Handle<FunctionTemplateInfo> obj,
     636             :     Handle<Object> prototype, InstanceType type, MaybeHandle<Name> maybe_name) {
     637             :   Handle<SharedFunctionInfo> shared =
     638             :       FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj,
     639     3836165 :                                                           maybe_name);
     640             :   // To simplify things, API functions always have shared name.
     641             :   DCHECK(shared->HasSharedName());
     642             : 
     643             :   Handle<JSFunction> result =
     644             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     645     7672335 :           shared, isolate->native_context());
     646             : 
     647     3836167 :   if (obj->remove_prototype()) {
     648             :     DCHECK(prototype.is_null());
     649             :     DCHECK(result->shared()->IsApiFunction());
     650             :     DCHECK(!result->IsConstructor());
     651             :     DCHECK(!result->has_prototype_slot());
     652        4856 :     return result;
     653             :   }
     654             : 
     655             :   // Down from here is only valid for API functions that can be used as a
     656             :   // constructor (don't set the "remove prototype" flag).
     657             :   DCHECK(result->has_prototype_slot());
     658             : 
     659     3831311 :   if (obj->read_only_prototype()) {
     660     3948162 :     result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
     661             :   }
     662             : 
     663     7662622 :   if (prototype->IsTheHole(isolate)) {
     664      108628 :     prototype = isolate->factory()->NewFunctionPrototype(result);
     665     7445365 :   } else if (obj->GetPrototypeProviderTemplate()->IsUndefined(isolate)) {
     666             :     JSObject::AddProperty(isolate, Handle<JSObject>::cast(prototype),
     667             :                           isolate->factory()->constructor_string(), result,
     668     3722676 :                           DONT_ENUM);
     669             :   }
     670             : 
     671             :   int embedder_field_count = 0;
     672             :   bool immutable_proto = false;
     673     7662621 :   if (!obj->GetInstanceTemplate()->IsUndefined(isolate)) {
     674             :     Handle<ObjectTemplateInfo> GetInstanceTemplate = Handle<ObjectTemplateInfo>(
     675      541134 :         ObjectTemplateInfo::cast(obj->GetInstanceTemplate()), isolate);
     676      270567 :     embedder_field_count = GetInstanceTemplate->embedder_field_count();
     677      270567 :     immutable_proto = GetInstanceTemplate->immutable_proto();
     678             :   }
     679             : 
     680             :   // JS_FUNCTION_TYPE requires information about the prototype slot.
     681             :   DCHECK_NE(JS_FUNCTION_TYPE, type);
     682     3831312 :   int instance_size = JSObject::GetHeaderSize(type) +
     683     3831310 :                       kEmbedderDataSlotSize * embedder_field_count;
     684             : 
     685             :   Handle<Map> map = isolate->factory()->NewMap(type, instance_size,
     686     3831310 :                                                TERMINAL_FAST_ELEMENTS_KIND);
     687     7662620 :   JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
     688             : 
     689             :   // Mark as undetectable if needed.
     690     3831309 :   if (obj->undetectable()) {
     691             :     // We only allow callable undetectable receivers here, since this whole
     692             :     // undetectable business is only to support document.all, which is both
     693             :     // undetectable and callable. If we ever see the need to have an object
     694             :     // that is undetectable but not callable, we need to update the types.h
     695             :     // to allow encoding this.
     696         304 :     CHECK(!obj->GetInstanceCallHandler()->IsUndefined(isolate));
     697             :     map->set_is_undetectable(true);
     698             :   }
     699             : 
     700             :   // Mark as needs_access_check if needed.
     701     3831309 :   if (obj->needs_access_check()) {
     702             :     map->set_is_access_check_needed(true);
     703         355 :     map->set_may_have_interesting_symbols(true);
     704             :   }
     705             : 
     706             :   // Set interceptor information in the map.
     707     7662621 :   if (!obj->GetNamedPropertyHandler()->IsUndefined(isolate)) {
     708             :     map->set_has_named_interceptor(true);
     709        1118 :     map->set_may_have_interesting_symbols(true);
     710             :   }
     711     7662622 :   if (!obj->GetIndexedPropertyHandler()->IsUndefined(isolate)) {
     712             :     map->set_has_indexed_interceptor(true);
     713             :   }
     714             : 
     715             :   // Mark instance as callable in the map.
     716     7662624 :   if (!obj->GetInstanceCallHandler()->IsUndefined(isolate)) {
     717             :     map->set_is_callable(true);
     718         402 :     map->set_is_constructor(!obj->undetectable());
     719             :   }
     720             : 
     721     3831330 :   if (immutable_proto) map->set_is_immutable_proto(true);
     722             : 
     723     3831312 :   return result;
     724             : }
     725             : 
     726             : }  // namespace internal
     727      183867 : }  // namespace v8

Generated by: LCOV version 1.10