LCOV - code coverage report
Current view: top level - src - api-natives.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 226 251 90.0 %
Date: 2019-03-21 Functions: 26 27 96.3 %

          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     2117201 :       : isolate_(isolate), save_context_(isolate) {}
      26     4234366 :   ~InvokeScope() {
      27     2117183 :     bool has_exception = isolate_->has_pending_exception();
      28     2117183 :     if (has_exception) {
      29           0 :       isolate_->ReportPendingMessages();
      30             :     } else {
      31             :       isolate_->clear_pending_message();
      32             :     }
      33     2117191 :   }
      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     2910194 : MaybeHandle<Object> Instantiate(
      51             :     Isolate* isolate, Handle<Object> data,
      52             :     MaybeHandle<Name> maybe_name = MaybeHandle<Name>()) {
      53     2910194 :   if (data->IsFunctionTemplateInfo()) {
      54             :     return InstantiateFunction(
      55     2364545 :         isolate, Handle<FunctionTemplateInfo>::cast(data), maybe_name);
      56      545649 :   } else if (data->IsObjectTemplateInfo()) {
      57             :     return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
      58      426590 :                              Handle<JSReceiver>(), false, false);
      59             :   } else {
      60      119059 :     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     2910194 : 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     5820388 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
     102             :                              Instantiate(isolate, prop_data, name), Object);
     103             : 
     104             :   LookupIterator it = LookupIterator::PropertyOrElement(
     105     2910194 :       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     5820388 :   MAYBE_RETURN_NULL(Object::AddDataProperty(&it, value, attributes,
     119             :                                             Just(ShouldThrow::kThrowOnError),
     120             :                                             StoreOrigin::kNamed));
     121     2910194 :   return value;
     122             : }
     123             : 
     124             : 
     125         226 : void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     126             :   Handle<Map> old_map(object->map(), isolate);
     127             :   // Copy map so it won't interfere constructor's initial map.
     128         226 :   Handle<Map> new_map = Map::Copy(isolate, old_map, "DisableAccessChecks");
     129             :   new_map->set_is_access_check_needed(false);
     130         226 :   JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
     131         226 : }
     132             : 
     133             : 
     134         226 : void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     135             :   Handle<Map> old_map(object->map(), isolate);
     136             :   // Copy map so it won't interfere constructor's initial map.
     137         226 :   Handle<Map> new_map = Map::Copy(isolate, old_map, "EnableAccessChecks");
     138             :   new_map->set_is_access_check_needed(true);
     139         226 :   new_map->set_may_have_interesting_symbols(true);
     140         226 :   JSObject::MigrateToMap(object, new_map);
     141         226 : }
     142             : 
     143             : 
     144             : class AccessCheckDisableScope {
     145             :  public:
     146     4332050 :   AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
     147             :       : isolate_(isolate),
     148             :         disabled_(obj->map()->is_access_check_needed()),
     149     8664100 :         obj_(obj) {
     150     4332050 :     if (disabled_) {
     151         226 :       DisableAccessChecks(isolate_, obj_);
     152             :     }
     153     4332050 :   }
     154     4332043 :   ~AccessCheckDisableScope() {
     155     4332043 :     if (disabled_) {
     156         226 :       EnableAccessChecks(isolate_, obj_);
     157             :     }
     158             :   }
     159             : 
     160             :  private:
     161             :   Isolate* isolate_;
     162             :   const bool disabled_;
     163             :   Handle<JSObject> obj_;
     164             : };
     165             : 
     166          60 : Object GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
     167          60 :   Handle<Context> native_context = isolate->native_context();
     168             :   DCHECK(!native_context.is_null());
     169          60 :   switch (intrinsic) {
     170             : #define GET_INTRINSIC_VALUE(name, iname) \
     171             :   case v8::k##name:                      \
     172             :     return native_context->iname();
     173          60 :     V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
     174             : #undef GET_INTRINSIC_VALUE
     175             :   }
     176           0 :   return Object();
     177             : }
     178             : 
     179             : template <typename TemplateInfoT>
     180     4332051 : MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
     181             :                                         Handle<TemplateInfoT> data,
     182             :                                         bool is_hidden_prototype) {
     183             :   HandleScope scope(isolate);
     184             :   // Disable access checks while instantiating the object.
     185     4332051 :   AccessCheckDisableScope access_check_scope(isolate, obj);
     186             : 
     187             :   // Walk the inheritance chain and copy all accessors to current object.
     188             :   int max_number_of_properties = 0;
     189     4332044 :   TemplateInfoT info = *data;
     190    12996962 :   while (!info.is_null()) {
     191             :     Object props = info->property_accessors();
     192     4332460 :     if (!props->IsUndefined(isolate)) {
     193       53431 :       max_number_of_properties += TemplateList::cast(props)->length();
     194             :     }
     195     4332462 :     info = info->GetParent(isolate);
     196             :   }
     197             : 
     198     4332043 :   if (max_number_of_properties > 0) {
     199             :     int valid_descriptors = 0;
     200             :     // Use a temporary FixedArray to accumulate unique accessors.
     201             :     Handle<FixedArray> array =
     202       53413 :         isolate->factory()->NewFixedArray(max_number_of_properties);
     203             : 
     204      160371 :     for (Handle<TemplateInfoT> temp(*data, isolate); !temp->is_null();
     205      106958 :          temp = handle(temp->GetParent(isolate), isolate)) {
     206             :       // Accumulate accessors.
     207             :       Object maybe_properties = temp->property_accessors();
     208       53479 :       if (!maybe_properties->IsUndefined(isolate)) {
     209       53431 :         valid_descriptors = AccessorInfo::AppendUnique(
     210             :             isolate, handle(maybe_properties, isolate), array,
     211             :             valid_descriptors);
     212             :       }
     213             :     }
     214             : 
     215             :     // Install accumulated accessors.
     216      160773 :     for (int i = 0; i < valid_descriptors; i++) {
     217             :       Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)), isolate);
     218             :       Handle<Name> name(Name::cast(accessor->name()), isolate);
     219             :       JSObject::SetAccessor(obj, name, accessor,
     220             :                             accessor->initial_property_attributes())
     221       53680 :           .Assert();
     222             :     }
     223             :   }
     224             : 
     225             :   Object maybe_property_list = data->property_list();
     226     4332043 :   if (maybe_property_list->IsUndefined(isolate)) return obj;
     227             :   Handle<TemplateList> properties(TemplateList::cast(maybe_property_list),
     228             :                                   isolate);
     229      377647 :   if (properties->length() == 0) return obj;
     230             : 
     231             :   int i = 0;
     232     6198323 :   for (int c = 0; c < data->number_of_properties(); c++) {
     233     5820676 :     auto name = handle(Name::cast(properties->get(i++)), isolate);
     234     2910338 :     Object bit = properties->get(i++);
     235     2910338 :     if (bit->IsSmi()) {
     236             :       PropertyDetails details(Smi::cast(bit));
     237             :       PropertyAttributes attributes = details.attributes();
     238             :       PropertyKind kind = details.kind();
     239             : 
     240     2910278 :       if (kind == kData) {
     241     5820268 :         auto prop_data = handle(properties->get(i++), isolate);
     242     5820268 :         RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     243             :                                                         prop_data, attributes),
     244             :                             JSObject);
     245             :       } else {
     246         288 :         auto getter = handle(properties->get(i++), isolate);
     247         288 :         auto setter = handle(properties->get(i++), isolate);
     248         288 :         RETURN_ON_EXCEPTION(
     249             :             isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
     250             :                                             attributes, is_hidden_prototype),
     251             :             JSObject);
     252             :       }
     253             :     } else {
     254             :       // Intrinsic data property --- Get appropriate value from the current
     255             :       // context.
     256          60 :       PropertyDetails details(Smi::cast(properties->get(i++)));
     257             :       PropertyAttributes attributes = details.attributes();
     258             :       DCHECK_EQ(kData, details.kind());
     259             : 
     260             :       v8::Intrinsic intrinsic =
     261         120 :           static_cast<v8::Intrinsic>(Smi::ToInt(properties->get(i++)));
     262         120 :       auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
     263             : 
     264         120 :       RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     265             :                                                       prop_data, attributes),
     266             :                           JSObject);
     267             :     }
     268             :   }
     269      377647 :   return obj;
     270             : }
     271             : 
     272             : // Whether or not to cache every instance: when we materialize a getter or
     273             : // setter from an lazy AccessorPair, we rely on this cache to be able to always
     274             : // return the same getter or setter. However, objects will be cloned anyways,
     275             : // so it's not observable if we didn't cache an instance. Furthermore, a badly
     276             : // behaved embedder might create an unlimited number of objects, so we limit
     277             : // the cache for those cases.
     278             : enum class CachingMode { kLimited, kUnlimited };
     279             : 
     280     4722621 : MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate,
     281             :                                                int serial_number,
     282             :                                                CachingMode caching_mode) {
     283             :   DCHECK_LE(1, serial_number);
     284     4722621 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     285             :     Handle<FixedArray> fast_cache =
     286     4656324 :         isolate->fast_template_instantiations_cache();
     287     9312656 :     return fast_cache->GetValue<JSObject>(isolate, serial_number - 1);
     288      132594 :   } else if (caching_mode == CachingMode::kUnlimited ||
     289       66297 :              (serial_number <=
     290             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     291             :     Handle<SimpleNumberDictionary> slow_cache =
     292       66297 :         isolate->slow_template_instantiations_cache();
     293      132594 :     int entry = slow_cache->FindEntry(isolate, serial_number);
     294       66297 :     if (entry == SimpleNumberDictionary::kNotFound) {
     295       63362 :       return MaybeHandle<JSObject>();
     296             :     }
     297        5870 :     return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate);
     298             :   } else {
     299           0 :     return MaybeHandle<JSObject>();
     300             :   }
     301             : }
     302             : 
     303     3865119 : void CacheTemplateInstantiation(Isolate* isolate, int serial_number,
     304             :                                 CachingMode caching_mode,
     305             :                                 Handle<JSObject> object) {
     306             :   DCHECK_LE(1, serial_number);
     307     3865119 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     308             :     Handle<FixedArray> fast_cache =
     309     3801771 :         isolate->fast_template_instantiations_cache();
     310             :     Handle<FixedArray> new_cache =
     311     3801778 :         FixedArray::SetAndGrow(isolate, fast_cache, serial_number - 1, object);
     312     3801778 :     if (*new_cache != *fast_cache) {
     313           0 :       isolate->native_context()->set_fast_template_instantiations_cache(
     314           0 :           *new_cache);
     315             :     }
     316      126696 :   } else if (caching_mode == CachingMode::kUnlimited ||
     317       63348 :              (serial_number <=
     318             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     319             :     Handle<SimpleNumberDictionary> cache =
     320       63348 :         isolate->slow_template_instantiations_cache();
     321             :     auto new_cache =
     322       63348 :         SimpleNumberDictionary::Set(isolate, cache, serial_number, object);
     323       63348 :     if (*new_cache != *cache) {
     324           0 :       isolate->native_context()->set_slow_template_instantiations_cache(
     325           0 :           *new_cache);
     326             :     }
     327             :   }
     328     3865126 : }
     329             : 
     330           0 : void UncacheTemplateInstantiation(Isolate* isolate, int serial_number,
     331             :                                   CachingMode caching_mode) {
     332             :   DCHECK_LE(1, serial_number);
     333           0 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     334             :     Handle<FixedArray> fast_cache =
     335           0 :         isolate->fast_template_instantiations_cache();
     336             :     DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate));
     337           0 :     fast_cache->set_undefined(serial_number - 1);
     338           0 :   } else if (caching_mode == CachingMode::kUnlimited ||
     339           0 :              (serial_number <=
     340             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     341             :     Handle<SimpleNumberDictionary> cache =
     342           0 :         isolate->slow_template_instantiations_cache();
     343           0 :     int entry = cache->FindEntry(isolate, serial_number);
     344             :     DCHECK_NE(SimpleNumberDictionary::kNotFound, entry);
     345           0 :     cache = SimpleNumberDictionary::DeleteEntry(isolate, cache, entry);
     346           0 :     isolate->native_context()->set_slow_template_instantiations_cache(*cache);
     347             :   }
     348           0 : }
     349             : 
     350      300659 : bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo info,
     351             :                            JSReceiver new_target) {
     352             :   DisallowHeapAllocation no_gc;
     353             : 
     354      300659 :   if (!new_target->IsJSFunction()) return false;
     355             :   JSFunction fun = JSFunction::cast(new_target);
     356      300661 :   if (fun->shared()->function_data() != info->constructor()) return false;
     357        2769 :   if (info->immutable_proto()) return false;
     358        5526 :   return fun->context()->native_context() == isolate->raw_native_context();
     359             : }
     360             : 
     361      950059 : MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
     362             :                                         Handle<ObjectTemplateInfo> info,
     363             :                                         Handle<JSReceiver> new_target,
     364             :                                         bool is_hidden_prototype,
     365             :                                         bool is_prototype) {
     366             :   Handle<JSFunction> constructor;
     367             :   int serial_number = Smi::ToInt(info->serial_number());
     368      950059 :   if (!new_target.is_null()) {
     369      300660 :     if (IsSimpleInstantiation(isolate, *info, *new_target)) {
     370             :       constructor = Handle<JSFunction>::cast(new_target);
     371             :     } else {
     372             :       // Disable caching for subclass instantiation.
     373             :       serial_number = 0;
     374             :     }
     375             :   }
     376             :   // Fast path.
     377             :   Handle<JSObject> result;
     378      950060 :   if (serial_number) {
     379      978134 :     if (ProbeInstantiationsCache(isolate, serial_number, CachingMode::kLimited)
     380             :             .ToHandle(&result)) {
     381      215428 :       return isolate->factory()->CopyJSObject(result);
     382             :     }
     383             :   }
     384             : 
     385      734632 :   if (constructor.is_null()) {
     386             :     Object maybe_constructor_info = info->constructor();
     387      733216 :     if (maybe_constructor_info->IsUndefined(isolate)) {
     388      561660 :       constructor = isolate->object_function();
     389             :     } else {
     390             :       // Enter a new scope.  Recursion could otherwise create a lot of handles.
     391             :       HandleScope scope(isolate);
     392             :       Handle<FunctionTemplateInfo> cons_templ(
     393             :           FunctionTemplateInfo::cast(maybe_constructor_info), isolate);
     394             :       Handle<JSFunction> tmp_constructor;
     395      343112 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor,
     396             :                                  InstantiateFunction(isolate, cons_templ),
     397             :                                  JSObject);
     398      171556 :       constructor = scope.CloseAndEscape(tmp_constructor);
     399             :     }
     400             : 
     401      733224 :     if (new_target.is_null()) new_target = constructor;
     402             :   }
     403             : 
     404             :   Handle<JSObject> object;
     405     1469275 :   ASSIGN_RETURN_ON_EXCEPTION(
     406             :       isolate, object,
     407             :       JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
     408             :       JSObject);
     409             : 
     410      734635 :   if (is_prototype) JSObject::OptimizeAsPrototype(object);
     411             : 
     412     1469261 :   ASSIGN_RETURN_ON_EXCEPTION(
     413             :       isolate, result,
     414             :       ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
     415      734626 :   if (info->immutable_proto()) {
     416          24 :     JSObject::SetImmutableProto(object);
     417             :   }
     418      734628 :   if (!is_prototype) {
     419             :     // Keep prototypes in slow-mode. Let them be lazily turned fast later on.
     420             :     // TODO(dcarney): is this necessary?
     421      625912 :     JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
     422             :     // Don't cache prototypes.
     423      625908 :     if (serial_number) {
     424             :       CacheTemplateInstantiation(isolate, serial_number, CachingMode::kLimited,
     425      272917 :                                  result);
     426      272917 :       result = isolate->factory()->CopyJSObject(result);
     427             :     }
     428             :   }
     429             : 
     430      734624 :   return result;
     431             : }
     432             : 
     433             : namespace {
     434         243 : MaybeHandle<Object> GetInstancePrototype(Isolate* isolate,
     435             :                                          Object function_template) {
     436             :   // Enter a new scope.  Recursion could otherwise create a lot of handles.
     437             :   HandleScope scope(isolate);
     438             :   Handle<JSFunction> parent_instance;
     439         729 :   ASSIGN_RETURN_ON_EXCEPTION(
     440             :       isolate, parent_instance,
     441             :       InstantiateFunction(
     442             :           isolate,
     443             :           handle(FunctionTemplateInfo::cast(function_template), isolate)),
     444             :       JSFunction);
     445             :   Handle<Object> instance_prototype;
     446             :   // TODO(cbruni): decide what to do here.
     447         486 :   ASSIGN_RETURN_ON_EXCEPTION(
     448             :       isolate, instance_prototype,
     449             :       JSObject::GetProperty(isolate, parent_instance,
     450             :                             isolate->factory()->prototype_string()),
     451             :       JSFunction);
     452         243 :   return scope.CloseAndEscape(instance_prototype);
     453             : }
     454             : }  // namespace
     455             : 
     456     4238765 : MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
     457             :                                             Handle<FunctionTemplateInfo> data,
     458             :                                             MaybeHandle<Name> maybe_name) {
     459             :   int serial_number = Smi::ToInt(data->serial_number());
     460     4238765 :   if (serial_number) {
     461             :     Handle<JSObject> result;
     462     8467113 :     if (ProbeInstantiationsCache(isolate, serial_number,
     463             :                                  CachingMode::kUnlimited)
     464             :             .ToHandle(&result)) {
     465      641339 :       return Handle<JSFunction>::cast(result);
     466             :     }
     467             :   }
     468             :   Handle<Object> prototype;
     469     3597429 :   if (!data->remove_prototype()) {
     470     3592546 :     Object prototype_templ = data->GetPrototypeTemplate();
     471     3592546 :     if (prototype_templ->IsUndefined(isolate)) {
     472     3483831 :       Object protoype_provider_templ = data->GetPrototypeProviderTemplate();
     473     3483831 :       if (protoype_provider_templ->IsUndefined(isolate)) {
     474     3483826 :         prototype = isolate->factory()->NewJSObject(isolate->object_function());
     475             :       } else {
     476          10 :         ASSIGN_RETURN_ON_EXCEPTION(
     477             :             isolate, prototype,
     478             :             GetInstancePrototype(isolate, protoype_provider_templ), JSFunction);
     479             :       }
     480             :     } else {
     481      326145 :       ASSIGN_RETURN_ON_EXCEPTION(
     482             :           isolate, prototype,
     483             :           InstantiateObject(
     484             :               isolate,
     485             :               handle(ObjectTemplateInfo::cast(prototype_templ), isolate),
     486             :               Handle<JSReceiver>(), data->hidden_prototype(), true),
     487             :           JSFunction);
     488             :     }
     489     3592532 :     Object parent = data->GetParentTemplate();
     490     3592532 :     if (!parent->IsUndefined(isolate)) {
     491             :       Handle<Object> parent_prototype;
     492         476 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, parent_prototype,
     493             :                                  GetInstancePrototype(isolate, parent),
     494             :                                  JSFunction);
     495             :       JSObject::ForceSetPrototype(Handle<JSObject>::cast(prototype),
     496         238 :                                   parent_prototype);
     497             :     }
     498             :   }
     499             :   InstanceType function_type =
     500     3597189 :       (!data->needs_access_check() &&
     501    10790845 :        data->GetNamedPropertyHandler()->IsUndefined(isolate) &&
     502     7193655 :        data->GetIndexedPropertyHandler()->IsUndefined(isolate))
     503             :           ? JS_API_OBJECT_TYPE
     504     3597415 :           : JS_SPECIAL_API_OBJECT_TYPE;
     505             : 
     506             :   Handle<JSFunction> function = ApiNatives::CreateApiFunction(
     507     3597414 :       isolate, data, prototype, function_type, maybe_name);
     508     3597421 :   if (serial_number) {
     509             :     // Cache the function.
     510     3592208 :     CacheTemplateInstantiation(isolate, serial_number, CachingMode::kUnlimited,
     511     3592204 :                                function);
     512             :   }
     513             :   MaybeHandle<JSObject> result =
     514     7194850 :       ConfigureInstance(isolate, function, data, data->hidden_prototype());
     515     3597410 :   if (result.is_null()) {
     516             :     // Uncache on error.
     517           0 :     if (serial_number) {
     518             :       UncacheTemplateInstantiation(isolate, serial_number,
     519           0 :                                    CachingMode::kUnlimited);
     520             :     }
     521           0 :     return MaybeHandle<JSFunction>();
     522             :   }
     523     3597410 :   return function;
     524             : }
     525             : 
     526             : 
     527     2062149 : void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
     528             :                                int length, Handle<Object>* data) {
     529             :   Object maybe_list = templ->property_list();
     530             :   Handle<TemplateList> list;
     531     2062149 :   if (maybe_list->IsUndefined(isolate)) {
     532      322131 :     list = TemplateList::New(isolate, length);
     533             :   } else {
     534             :     list = handle(TemplateList::cast(maybe_list), isolate);
     535             :   }
     536     2062149 :   templ->set_number_of_properties(templ->number_of_properties() + 1);
     537    14435371 :   for (int i = 0; i < length; i++) {
     538             :     Handle<Object> value =
     539     6186611 :         data[i].is_null()
     540             :             ? Handle<Object>::cast(isolate->factory()->undefined_value())
     541     6186670 :             : data[i];
     542     6186611 :     list = TemplateList::Add(isolate, list, value);
     543             :   }
     544     4124298 :   templ->set_property_list(*list);
     545     2062149 : }
     546             : 
     547             : }  // namespace
     548             : 
     549     1702420 : MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
     550             :     Handle<FunctionTemplateInfo> data, MaybeHandle<Name> maybe_name) {
     551             :   Isolate* isolate = data->GetIsolate();
     552     1702405 :   InvokeScope invoke_scope(isolate);
     553     3404837 :   return ::v8::internal::InstantiateFunction(isolate, data, maybe_name);
     554             : }
     555             : 
     556      414755 : MaybeHandle<JSObject> ApiNatives::InstantiateObject(
     557             :     Isolate* isolate, Handle<ObjectTemplateInfo> data,
     558             :     Handle<JSReceiver> new_target) {
     559      414747 :   InvokeScope invoke_scope(isolate);
     560             :   return ::v8::internal::InstantiateObject(isolate, data, new_target, false,
     561      829514 :                                            false);
     562             : }
     563             : 
     564          26 : MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject(
     565             :     Handle<ObjectTemplateInfo> data) {
     566             :   Isolate* isolate = data->GetIsolate();
     567          26 :   InvokeScope invoke_scope(isolate);
     568             : 
     569             :   Handle<FunctionTemplateInfo> constructor(
     570             :       FunctionTemplateInfo::cast(data->constructor()), isolate);
     571             :   Handle<Map> object_map = isolate->factory()->NewMap(
     572             :       JS_SPECIAL_API_OBJECT_TYPE,
     573             :       JSObject::kHeaderSize +
     574          26 :           data->embedder_field_count() * kEmbedderDataSlotSize,
     575          26 :       TERMINAL_FAST_ELEMENTS_KIND);
     576          52 :   object_map->SetConstructor(*constructor);
     577             :   object_map->set_is_access_check_needed(true);
     578          26 :   object_map->set_may_have_interesting_symbols(true);
     579             : 
     580          26 :   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(object_map);
     581          26 :   JSObject::ForceSetPrototype(object, isolate->factory()->null_value());
     582             : 
     583          52 :   return object;
     584             : }
     585             : 
     586     2061985 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     587             :                                  Handle<Name> name, Handle<Object> value,
     588             :                                  PropertyAttributes attributes) {
     589             :   PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
     590             :   auto details_handle = handle(details.AsSmi(), isolate);
     591     2061985 :   Handle<Object> data[] = {name, details_handle, value};
     592     2061985 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     593     2061985 : }
     594             : 
     595             : 
     596          55 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     597             :                                  Handle<Name> name, v8::Intrinsic intrinsic,
     598             :                                  PropertyAttributes attributes) {
     599          55 :   auto value = handle(Smi::FromInt(intrinsic), isolate);
     600             :   auto intrinsic_marker = isolate->factory()->true_value();
     601             :   PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
     602             :   auto details_handle = handle(details.AsSmi(), isolate);
     603             :   Handle<Object> data[] = {name, intrinsic_marker, details_handle, value};
     604          55 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     605          55 : }
     606             : 
     607             : 
     608         109 : void ApiNatives::AddAccessorProperty(Isolate* isolate,
     609             :                                      Handle<TemplateInfo> info,
     610             :                                      Handle<Name> name,
     611             :                                      Handle<FunctionTemplateInfo> getter,
     612             :                                      Handle<FunctionTemplateInfo> setter,
     613             :                                      PropertyAttributes attributes) {
     614             :   PropertyDetails details(kAccessor, attributes, PropertyCellType::kNoCell);
     615             :   auto details_handle = handle(details.AsSmi(), isolate);
     616             :   Handle<Object> data[] = {name, details_handle, getter, setter};
     617         109 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     618         109 : }
     619             : 
     620             : 
     621       53609 : void ApiNatives::AddNativeDataProperty(Isolate* isolate,
     622             :                                        Handle<TemplateInfo> info,
     623             :                                        Handle<AccessorInfo> property) {
     624             :   Object maybe_list = info->property_accessors();
     625             :   Handle<TemplateList> list;
     626       53609 :   if (maybe_list->IsUndefined(isolate)) {
     627       53372 :     list = TemplateList::New(isolate, 1);
     628             :   } else {
     629             :     list = handle(TemplateList::cast(maybe_list), isolate);
     630             :   }
     631       53609 :   list = TemplateList::Add(isolate, list, property);
     632      107218 :   info->set_property_accessors(*list);
     633       53609 : }
     634             : 
     635     3708949 : Handle<JSFunction> ApiNatives::CreateApiFunction(
     636             :     Isolate* isolate, Handle<FunctionTemplateInfo> obj,
     637             :     Handle<Object> prototype, InstanceType type, MaybeHandle<Name> maybe_name) {
     638             :   Handle<SharedFunctionInfo> shared =
     639             :       FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj,
     640     3708949 :                                                           maybe_name);
     641             :   // To simplify things, API functions always have shared name.
     642             :   DCHECK(shared->HasSharedName());
     643             : 
     644             :   Handle<JSFunction> result =
     645             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     646     7417894 :           shared, isolate->native_context());
     647             : 
     648     3708961 :   if (obj->remove_prototype()) {
     649             :     DCHECK(prototype.is_null());
     650             :     DCHECK(result->shared()->IsApiFunction());
     651             :     DCHECK(!result->IsConstructor());
     652             :     DCHECK(!result->has_prototype_slot());
     653        4884 :     return result;
     654             :   }
     655             : 
     656             :   // Down from here is only valid for API functions that can be used as a
     657             :   // constructor (don't set the "remove prototype" flag).
     658             :   DCHECK(result->has_prototype_slot());
     659             : 
     660     3704077 :   if (obj->read_only_prototype()) {
     661     3488138 :     result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
     662             :   }
     663             : 
     664     3704067 :   if (prototype->IsTheHole(isolate)) {
     665      111528 :     prototype = isolate->factory()->NewFunctionPrototype(result);
     666     7185083 :   } else if (obj->GetPrototypeProviderTemplate()->IsUndefined(isolate)) {
     667     3592533 :     JSObject::AddProperty(isolate, Handle<JSObject>::cast(prototype),
     668             :                           isolate->factory()->constructor_string(), result,
     669     3592539 :                           DONT_ENUM);
     670             :   }
     671             : 
     672             :   int embedder_field_count = 0;
     673             :   bool immutable_proto = false;
     674     7408132 :   if (!obj->GetInstanceTemplate()->IsUndefined(isolate)) {
     675             :     Handle<ObjectTemplateInfo> GetInstanceTemplate = Handle<ObjectTemplateInfo>(
     676      555458 :         ObjectTemplateInfo::cast(obj->GetInstanceTemplate()), isolate);
     677             :     embedder_field_count = GetInstanceTemplate->embedder_field_count();
     678             :     immutable_proto = GetInstanceTemplate->immutable_proto();
     679             :   }
     680             : 
     681             :   // JS_FUNCTION_TYPE requires information about the prototype slot.
     682             :   DCHECK_NE(JS_FUNCTION_TYPE, type);
     683     3704066 :   int instance_size = JSObject::GetHeaderSize(type) +
     684     3704060 :                       kEmbedderDataSlotSize * embedder_field_count;
     685             : 
     686             :   Handle<Map> map = isolate->factory()->NewMap(type, instance_size,
     687     3704060 :                                                TERMINAL_FAST_ELEMENTS_KIND);
     688     3704068 :   JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
     689             : 
     690             :   // Mark as undetectable if needed.
     691     3704059 :   if (obj->undetectable()) {
     692             :     // We only allow callable undetectable receivers here, since this whole
     693             :     // undetectable business is only to support document.all, which is both
     694             :     // undetectable and callable. If we ever see the need to have an object
     695             :     // that is undetectable but not callable, we need to update the types.h
     696             :     // to allow encoding this.
     697         298 :     CHECK(!obj->GetInstanceCallHandler()->IsUndefined(isolate));
     698             :     map->set_is_undetectable(true);
     699             :   }
     700             : 
     701             :   // Mark as needs_access_check if needed.
     702     3704059 :   if (obj->needs_access_check()) {
     703             :     map->set_is_access_check_needed(true);
     704         349 :     map->set_may_have_interesting_symbols(true);
     705             :   }
     706             : 
     707             :   // Set interceptor information in the map.
     708     7408113 :   if (!obj->GetNamedPropertyHandler()->IsUndefined(isolate)) {
     709             :     map->set_has_named_interceptor(true);
     710        1096 :     map->set_may_have_interesting_symbols(true);
     711             :   }
     712     7408116 :   if (!obj->GetIndexedPropertyHandler()->IsUndefined(isolate)) {
     713             :     map->set_has_indexed_interceptor(true);
     714             :   }
     715             : 
     716             :   // Mark instance as callable in the map.
     717     7408125 :   if (!obj->GetInstanceCallHandler()->IsUndefined(isolate)) {
     718             :     map->set_is_callable(true);
     719         197 :     map->set_is_constructor(!obj->undetectable());
     720             :   }
     721             : 
     722     3704081 :   if (immutable_proto) map->set_is_immutable_proto(true);
     723             : 
     724     3704063 :   return result;
     725             : }
     726             : 
     727             : }  // namespace internal
     728      120216 : }  // namespace v8

Generated by: LCOV version 1.10