LCOV - code coverage report
Current view: top level - src - api-natives.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 227 248 91.5 %
Date: 2019-04-17 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     2141288 :       : isolate_(isolate), save_context_(isolate) {}
      26     4282558 :   ~InvokeScope() {
      27     2141279 :     bool has_exception = isolate_->has_pending_exception();
      28     2141279 :     if (has_exception) {
      29           0 :       isolate_->ReportPendingMessages();
      30             :     } else {
      31             :       isolate_->clear_pending_message();
      32             :     }
      33     2141281 :   }
      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     2992086 : MaybeHandle<Object> Instantiate(
      51             :     Isolate* isolate, Handle<Object> data,
      52             :     MaybeHandle<Name> maybe_name = MaybeHandle<Name>()) {
      53     2992086 :   if (data->IsFunctionTemplateInfo()) {
      54             :     return InstantiateFunction(
      55     2441141 :         isolate, Handle<FunctionTemplateInfo>::cast(data), maybe_name);
      56      550945 :   } else if (data->IsObjectTemplateInfo()) {
      57             :     return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
      58      430830 :                              Handle<JSReceiver>(), false, false);
      59             :   } else {
      60      120115 :     return data;
      61             :   }
      62             : }
      63             : 
      64         149 : 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         149 :   if (getter->IsFunctionTemplateInfo()) {
      73         447 :     if (force_instantiate ||
      74         447 :         FunctionTemplateInfo::cast(*getter)->BreakAtEntry()) {
      75          10 :       ASSIGN_RETURN_ON_EXCEPTION(
      76             :           isolate, getter,
      77             :           InstantiateFunction(isolate,
      78             :                               Handle<FunctionTemplateInfo>::cast(getter)),
      79             :           Object);
      80             :     }
      81             :   }
      82         149 :   if (setter->IsFunctionTemplateInfo()) {
      83         207 :     if (force_instantiate ||
      84         207 :         FunctionTemplateInfo::cast(*setter)->BreakAtEntry()) {
      85          10 :       ASSIGN_RETURN_ON_EXCEPTION(
      86             :           isolate, setter,
      87             :           InstantiateFunction(isolate,
      88             :                               Handle<FunctionTemplateInfo>::cast(setter)),
      89             :           Object);
      90             :     }
      91             :   }
      92         298 :   RETURN_ON_EXCEPTION(
      93             :       isolate,
      94             :       JSObject::DefineAccessor(object, name, getter, setter, attributes),
      95             :       Object);
      96         149 :   return object;
      97             : }
      98             : 
      99             : 
     100     2992086 : MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
     101             :                                        Handle<JSObject> object,
     102             :                                        Handle<Name> name,
     103             :                                        Handle<Object> prop_data,
     104             :                                        PropertyAttributes attributes) {
     105             :   Handle<Object> value;
     106     5984172 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
     107             :                              Instantiate(isolate, prop_data, name), Object);
     108             : 
     109             :   LookupIterator it = LookupIterator::PropertyOrElement(
     110     2992086 :       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
     111             : 
     112             : #ifdef DEBUG
     113             :   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     114             :   DCHECK(maybe.IsJust());
     115             :   if (it.IsFound()) {
     116             :     THROW_NEW_ERROR(
     117             :         isolate,
     118             :         NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
     119             :         Object);
     120             :   }
     121             : #endif
     122             : 
     123     5984172 :   MAYBE_RETURN_NULL(Object::AddDataProperty(&it, value, attributes,
     124             :                                             Just(ShouldThrow::kThrowOnError),
     125             :                                             StoreOrigin::kNamed));
     126     2992086 :   return value;
     127             : }
     128             : 
     129             : 
     130         226 : void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     131             :   Handle<Map> old_map(object->map(), isolate);
     132             :   // Copy map so it won't interfere constructor's initial map.
     133         226 :   Handle<Map> new_map = Map::Copy(isolate, old_map, "DisableAccessChecks");
     134             :   new_map->set_is_access_check_needed(false);
     135         226 :   JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
     136         226 : }
     137             : 
     138             : 
     139         226 : void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     140             :   Handle<Map> old_map(object->map(), isolate);
     141             :   // Copy map so it won't interfere constructor's initial map.
     142         226 :   Handle<Map> new_map = Map::Copy(isolate, old_map, "EnableAccessChecks");
     143             :   new_map->set_is_access_check_needed(true);
     144         226 :   new_map->set_may_have_interesting_symbols(true);
     145         226 :   JSObject::MigrateToMap(object, new_map);
     146         226 : }
     147             : 
     148             : 
     149             : class AccessCheckDisableScope {
     150             :  public:
     151     4431375 :   AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
     152             :       : isolate_(isolate),
     153             :         disabled_(obj->map()->is_access_check_needed()),
     154     8862750 :         obj_(obj) {
     155     4431375 :     if (disabled_) {
     156         226 :       DisableAccessChecks(isolate_, obj_);
     157             :     }
     158     4431375 :   }
     159     4431377 :   ~AccessCheckDisableScope() {
     160     4431377 :     if (disabled_) {
     161         226 :       EnableAccessChecks(isolate_, obj_);
     162             :     }
     163             :   }
     164             : 
     165             :  private:
     166             :   Isolate* isolate_;
     167             :   const bool disabled_;
     168             :   Handle<JSObject> obj_;
     169             : };
     170             : 
     171          60 : Object GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
     172          60 :   Handle<Context> native_context = isolate->native_context();
     173             :   DCHECK(!native_context.is_null());
     174          60 :   switch (intrinsic) {
     175             : #define GET_INTRINSIC_VALUE(name, iname) \
     176             :   case v8::k##name:                      \
     177             :     return native_context->iname();
     178          60 :     V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
     179             : #undef GET_INTRINSIC_VALUE
     180             :   }
     181           0 :   return Object();
     182             : }
     183             : 
     184             : template <typename TemplateInfoT>
     185     4431377 : MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
     186             :                                         Handle<TemplateInfoT> data,
     187             :                                         bool is_hidden_prototype) {
     188             :   HandleScope scope(isolate);
     189             :   // Disable access checks while instantiating the object.
     190     4431377 :   AccessCheckDisableScope access_check_scope(isolate, obj);
     191             : 
     192             :   // Walk the inheritance chain and copy all accessors to current object.
     193             :   int max_number_of_properties = 0;
     194      736785 :   TemplateInfoT info = *data;
     195     9600034 :   while (!info.is_null()) {
     196             :     Object props = info->property_accessors();
     197     4431788 :     if (!props->IsUndefined(isolate)) {
     198       53959 :       max_number_of_properties += TemplateList::cast(props)->length();
     199             :     }
     200      736869 :     info = info->GetParent(isolate);
     201             :   }
     202             : 
     203     4431377 :   if (max_number_of_properties > 0) {
     204             :     int valid_descriptors = 0;
     205             :     // Use a temporary FixedArray to accumulate unique accessors.
     206             :     Handle<FixedArray> array =
     207       53941 :         isolate->factory()->NewFixedArray(max_number_of_properties);
     208             : 
     209      161949 :     for (Handle<TemplateInfoT> temp(*data, isolate); !temp->is_null();
     210      108002 :          temp = handle(temp->GetParent(isolate), isolate)) {
     211             :       // Accumulate accessors.
     212             :       Object maybe_properties = temp->property_accessors();
     213       54007 :       if (!maybe_properties->IsUndefined(isolate)) {
     214       53959 :         valid_descriptors = AccessorInfo::AppendUnique(
     215             :             isolate, handle(maybe_properties, isolate), array,
     216             :             valid_descriptors);
     217             :       }
     218             :     }
     219             : 
     220             :     // Install accumulated accessors.
     221      162357 :     for (int i = 0; i < valid_descriptors; i++) {
     222             :       Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)), isolate);
     223             :       Handle<Name> name(Name::cast(accessor->name()), isolate);
     224             :       JSObject::SetAccessor(obj, name, accessor,
     225             :                             accessor->initial_property_attributes())
     226       54208 :           .Assert();
     227             :     }
     228             :   }
     229             : 
     230             :   Object maybe_property_list = data->property_list();
     231     4431377 :   if (maybe_property_list->IsUndefined(isolate)) return obj;
     232             :   Handle<TemplateList> properties(TemplateList::cast(maybe_property_list),
     233             :                                   isolate);
     234      381372 :   if (properties->length() == 0) return obj;
     235             : 
     236             :   int i = 0;
     237     6365842 :   for (int c = 0; c < data->number_of_properties(); c++) {
     238     5984470 :     auto name = handle(Name::cast(properties->get(i++)), isolate);
     239     2992235 :     Object bit = properties->get(i++);
     240     2992235 :     if (bit->IsSmi()) {
     241             :       PropertyDetails details(Smi::cast(bit));
     242             :       PropertyAttributes attributes = details.attributes();
     243             :       PropertyKind kind = details.kind();
     244             : 
     245     2992175 :       if (kind == kData) {
     246     5984052 :         auto prop_data = handle(properties->get(i++), isolate);
     247     5984052 :         RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     248             :                                                         prop_data, attributes),
     249             :                             JSObject);
     250             :       } else {
     251         298 :         auto getter = handle(properties->get(i++), isolate);
     252         298 :         auto setter = handle(properties->get(i++), isolate);
     253         298 :         RETURN_ON_EXCEPTION(
     254             :             isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
     255             :                                             attributes, is_hidden_prototype),
     256             :             JSObject);
     257             :       }
     258             :     } else {
     259             :       // Intrinsic data property --- Get appropriate value from the current
     260             :       // context.
     261          60 :       PropertyDetails details(Smi::cast(properties->get(i++)));
     262             :       PropertyAttributes attributes = details.attributes();
     263             :       DCHECK_EQ(kData, details.kind());
     264             : 
     265             :       v8::Intrinsic intrinsic =
     266         120 :           static_cast<v8::Intrinsic>(Smi::ToInt(properties->get(i++)));
     267         120 :       auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
     268             : 
     269         120 :       RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     270             :                                                       prop_data, attributes),
     271             :                           JSObject);
     272             :     }
     273             :   }
     274      381372 :   return obj;
     275             : }
     276             : 
     277             : // Whether or not to cache every instance: when we materialize a getter or
     278             : // setter from an lazy AccessorPair, we rely on this cache to be able to always
     279             : // return the same getter or setter. However, objects will be cloned anyways,
     280             : // so it's not observable if we didn't cache an instance. Furthermore, a badly
     281             : // behaved embedder might create an unlimited number of objects, so we limit
     282             : // the cache for those cases.
     283             : enum class CachingMode { kLimited, kUnlimited };
     284             : 
     285     4830097 : MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate,
     286             :                                                int serial_number,
     287             :                                                CachingMode caching_mode) {
     288             :   DCHECK_LE(1, serial_number);
     289     4830097 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     290             :     Handle<FixedArray> fast_cache =
     291     4763472 :         isolate->fast_template_instantiations_cache();
     292     9526950 :     return fast_cache->GetValue<JSObject>(isolate, serial_number - 1);
     293      133250 :   } else if (caching_mode == CachingMode::kUnlimited ||
     294       66625 :              (serial_number <=
     295             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     296             :     Handle<SimpleNumberDictionary> slow_cache =
     297       66625 :         isolate->slow_template_instantiations_cache();
     298      133250 :     int entry = slow_cache->FindEntry(isolate, serial_number);
     299       66625 :     if (entry == SimpleNumberDictionary::kNotFound) {
     300       63672 :       return MaybeHandle<JSObject>();
     301             :     }
     302        2953 :     return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate);
     303             :   } else {
     304           0 :     return MaybeHandle<JSObject>();
     305             :   }
     306             : }
     307             : 
     308     3964776 : void CacheTemplateInstantiation(Isolate* isolate, int serial_number,
     309             :                                 CachingMode caching_mode,
     310             :                                 Handle<JSObject> object) {
     311             :   DCHECK_LE(1, serial_number);
     312     3964776 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     313             :     Handle<FixedArray> fast_cache =
     314     3901118 :         isolate->fast_template_instantiations_cache();
     315             :     Handle<FixedArray> new_cache =
     316     3901118 :         FixedArray::SetAndGrow(isolate, fast_cache, serial_number - 1, object);
     317     3901122 :     if (*new_cache != *fast_cache) {
     318           0 :       isolate->native_context()->set_fast_template_instantiations_cache(
     319           0 :           *new_cache);
     320             :     }
     321      127316 :   } else if (caching_mode == CachingMode::kUnlimited ||
     322       63658 :              (serial_number <=
     323             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     324             :     Handle<SimpleNumberDictionary> cache =
     325       63658 :         isolate->slow_template_instantiations_cache();
     326             :     auto new_cache =
     327       63658 :         SimpleNumberDictionary::Set(isolate, cache, serial_number, object);
     328       63658 :     if (*new_cache != *cache) {
     329           0 :       isolate->native_context()->set_slow_template_instantiations_cache(
     330           0 :           *new_cache);
     331             :     }
     332             :   }
     333     3964780 : }
     334             : 
     335           0 : void UncacheTemplateInstantiation(Isolate* isolate, int serial_number,
     336             :                                   CachingMode caching_mode) {
     337             :   DCHECK_LE(1, serial_number);
     338           0 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     339             :     Handle<FixedArray> fast_cache =
     340           0 :         isolate->fast_template_instantiations_cache();
     341             :     DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate));
     342           0 :     fast_cache->set_undefined(serial_number - 1);
     343           0 :   } else if (caching_mode == CachingMode::kUnlimited ||
     344           0 :              (serial_number <=
     345             :               TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
     346             :     Handle<SimpleNumberDictionary> cache =
     347           0 :         isolate->slow_template_instantiations_cache();
     348           0 :     int entry = cache->FindEntry(isolate, serial_number);
     349             :     DCHECK_NE(SimpleNumberDictionary::kNotFound, entry);
     350           0 :     cache = SimpleNumberDictionary::DeleteEntry(isolate, cache, entry);
     351           0 :     isolate->native_context()->set_slow_template_instantiations_cache(*cache);
     352             :   }
     353           0 : }
     354             : 
     355      298554 : bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo info,
     356             :                            JSReceiver new_target) {
     357             :   DisallowHeapAllocation no_gc;
     358             : 
     359      298554 :   if (!new_target->IsJSFunction()) return false;
     360             :   JSFunction fun = JSFunction::cast(new_target);
     361      298554 :   if (fun->shared()->function_data() != info->constructor()) return false;
     362        2764 :   if (info->immutable_proto()) return false;
     363             :   return fun->context()->native_context() == isolate->raw_native_context();
     364             : }
     365             : 
     366      954337 : MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
     367             :                                         Handle<ObjectTemplateInfo> info,
     368             :                                         Handle<JSReceiver> new_target,
     369             :                                         bool is_hidden_prototype,
     370             :                                         bool is_prototype) {
     371             :   Handle<JSFunction> constructor;
     372             :   int serial_number = Smi::ToInt(info->serial_number());
     373      954337 :   if (!new_target.is_null()) {
     374      298554 :     if (IsSimpleInstantiation(isolate, *info, *new_target)) {
     375             :       constructor = Handle<JSFunction>::cast(new_target);
     376             :     } else {
     377             :       // Disable caching for subclass instantiation.
     378             :       serial_number = 0;
     379             :     }
     380             :   }
     381             :   // Fast path.
     382             :   Handle<JSObject> result;
     383      954337 :   if (serial_number) {
     384      987686 :     if (ProbeInstantiationsCache(isolate, serial_number, CachingMode::kLimited)
     385             :             .ToHandle(&result)) {
     386      217548 :       return isolate->factory()->CopyJSObject(result);
     387             :     }
     388             :   }
     389             : 
     390      736789 :   if (constructor.is_null()) {
     391             :     Object maybe_constructor_info = info->constructor();
     392      735378 :     if (maybe_constructor_info->IsUndefined(isolate)) {
     393      562664 :       constructor = isolate->object_function();
     394             :     } else {
     395             :       // Enter a new scope.  Recursion could otherwise create a lot of handles.
     396             :       HandleScope scope(isolate);
     397             :       Handle<FunctionTemplateInfo> cons_templ(
     398             :           FunctionTemplateInfo::cast(maybe_constructor_info), isolate);
     399             :       Handle<JSFunction> tmp_constructor;
     400      345428 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor,
     401             :                                  InstantiateFunction(isolate, cons_templ),
     402             :                                  JSObject);
     403      172714 :       constructor = scope.CloseAndEscape(tmp_constructor);
     404             :     }
     405             : 
     406      735378 :     if (new_target.is_null()) new_target = constructor;
     407             :   }
     408             : 
     409             :   Handle<JSObject> object;
     410     1473574 :   ASSIGN_RETURN_ON_EXCEPTION(
     411             :       isolate, object,
     412             :       JSObject::New(constructor, new_target, Handle<AllocationSite>::null()),
     413             :       JSObject);
     414             : 
     415      736785 :   if (is_prototype) JSObject::OptimizeAsPrototype(object);
     416             : 
     417     1473569 :   ASSIGN_RETURN_ON_EXCEPTION(
     418             :       isolate, result,
     419             :       ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
     420      736784 :   if (info->immutable_proto()) {
     421          24 :     JSObject::SetImmutableProto(object);
     422             :   }
     423      736784 :   if (!is_prototype) {
     424             :     // Keep prototypes in slow-mode. Let them be lazily turned fast later on.
     425             :     // TODO(dcarney): is this necessary?
     426      627005 :     JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
     427             :     // Don't cache prototypes.
     428      627005 :     if (serial_number) {
     429             :       CacheTemplateInstantiation(isolate, serial_number, CachingMode::kLimited,
     430      275573 :                                  result);
     431      275573 :       result = isolate->factory()->CopyJSObject(result);
     432             :     }
     433             :   }
     434             : 
     435      736784 :   return result;
     436             : }
     437             : 
     438             : namespace {
     439         243 : MaybeHandle<Object> GetInstancePrototype(Isolate* isolate,
     440             :                                          Object function_template) {
     441             :   // Enter a new scope.  Recursion could otherwise create a lot of handles.
     442             :   HandleScope scope(isolate);
     443             :   Handle<JSFunction> parent_instance;
     444         729 :   ASSIGN_RETURN_ON_EXCEPTION(
     445             :       isolate, parent_instance,
     446             :       InstantiateFunction(
     447             :           isolate,
     448             :           handle(FunctionTemplateInfo::cast(function_template), isolate)),
     449             :       JSFunction);
     450             :   Handle<Object> instance_prototype;
     451             :   // TODO(cbruni): decide what to do here.
     452         486 :   ASSIGN_RETURN_ON_EXCEPTION(
     453             :       isolate, instance_prototype,
     454             :       JSObject::GetProperty(isolate, parent_instance,
     455             :                             isolate->factory()->prototype_string()),
     456             :       JSFunction);
     457         243 :   return scope.CloseAndEscape(instance_prototype);
     458             : }
     459             : }  // namespace
     460             : 
     461     4341642 : MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
     462             :                                             Handle<FunctionTemplateInfo> data,
     463             :                                             MaybeHandle<Name> maybe_name) {
     464             :   int serial_number = Smi::ToInt(data->serial_number());
     465     4341642 :   if (serial_number) {
     466             :     Handle<JSObject> result;
     467     8672510 :     if (ProbeInstantiationsCache(isolate, serial_number,
     468             :                                  CachingMode::kUnlimited)
     469             :             .ToHandle(&result)) {
     470      647047 :       return Handle<JSFunction>::cast(result);
     471             :     }
     472             :   }
     473             :   Handle<Object> prototype;
     474     3694597 :   if (!data->remove_prototype()) {
     475             :     Object prototype_templ = data->GetPrototypeTemplate();
     476     3689704 :     if (prototype_templ->IsUndefined(isolate)) {
     477             :       Object protoype_provider_templ = data->GetPrototypeProviderTemplate();
     478     3579925 :       if (protoype_provider_templ->IsUndefined(isolate)) {
     479     3579920 :         prototype = isolate->factory()->NewJSObject(isolate->object_function());
     480             :       } else {
     481          10 :         ASSIGN_RETURN_ON_EXCEPTION(
     482             :             isolate, prototype,
     483             :             GetInstancePrototype(isolate, protoype_provider_templ), JSFunction);
     484             :       }
     485             :     } else {
     486      329337 :       ASSIGN_RETURN_ON_EXCEPTION(
     487             :           isolate, prototype,
     488             :           InstantiateObject(
     489             :               isolate,
     490             :               handle(ObjectTemplateInfo::cast(prototype_templ), isolate),
     491             :               Handle<JSReceiver>(), data->hidden_prototype(), true),
     492             :           JSFunction);
     493             :     }
     494             :     Object parent = data->GetParentTemplate();
     495     3689700 :     if (!parent->IsUndefined(isolate)) {
     496             :       Handle<Object> parent_prototype;
     497         476 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, parent_prototype,
     498             :                                  GetInstancePrototype(isolate, parent),
     499             :                                  JSFunction);
     500         238 :       CHECK(parent_prototype->IsHeapObject());
     501             :       JSObject::ForceSetPrototype(Handle<JSObject>::cast(prototype),
     502         238 :                                   Handle<HeapObject>::cast(parent_prototype));
     503             :     }
     504             :   }
     505             :   InstanceType function_type =
     506     3694366 :       (!data->needs_access_check() &&
     507     3693414 :        data->GetNamedPropertyHandler()->IsUndefined(isolate) &&
     508             :        data->GetIndexedPropertyHandler()->IsUndefined(isolate))
     509             :           ? JS_API_OBJECT_TYPE
     510     3694592 :           : JS_SPECIAL_API_OBJECT_TYPE;
     511             : 
     512             :   Handle<JSFunction> function = ApiNatives::CreateApiFunction(
     513     3694592 :       isolate, data, prototype, function_type, maybe_name);
     514     3694590 :   if (serial_number) {
     515             :     // Cache the function.
     516     3689205 :     CacheTemplateInstantiation(isolate, serial_number, CachingMode::kUnlimited,
     517     3689205 :                                function);
     518             :   }
     519             :   MaybeHandle<JSObject> result =
     520     7389180 :       ConfigureInstance(isolate, function, data, data->hidden_prototype());
     521     3694591 :   if (result.is_null()) {
     522             :     // Uncache on error.
     523           0 :     if (serial_number) {
     524             :       UncacheTemplateInstantiation(isolate, serial_number,
     525           0 :                                    CachingMode::kUnlimited);
     526             :     }
     527           0 :     return MaybeHandle<JSFunction>();
     528             :   }
     529     3694591 :   return function;
     530             : }
     531             : 
     532             : 
     533     2135586 : void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
     534             :                                int length, Handle<Object>* data) {
     535             :   Object maybe_list = templ->property_list();
     536             :   Handle<TemplateList> list;
     537     2135586 :   if (maybe_list->IsUndefined(isolate)) {
     538      325320 :     list = TemplateList::New(isolate, length);
     539             :   } else {
     540             :     list = handle(TemplateList::cast(maybe_list), isolate);
     541             :   }
     542     2135586 :   templ->set_number_of_properties(templ->number_of_properties() + 1);
     543    14949440 :   for (int i = 0; i < length; i++) {
     544             :     Handle<Object> value =
     545     6406927 :         data[i].is_null()
     546             :             ? Handle<Object>::cast(isolate->factory()->undefined_value())
     547     6406986 :             : data[i];
     548     6406927 :     list = TemplateList::Add(isolate, list, value);
     549             :   }
     550     4271172 :   templ->set_property_list(*list);
     551     2135586 : }
     552             : 
     553             : }  // namespace
     554             : 
     555     1727535 : MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
     556             :     Handle<FunctionTemplateInfo> data, MaybeHandle<Name> maybe_name) {
     557             :   Isolate* isolate = data->GetIsolate();
     558     1727530 :   InvokeScope invoke_scope(isolate);
     559     3455063 :   return ::v8::internal::InstantiateFunction(isolate, data, maybe_name);
     560             : }
     561             : 
     562      413727 : MaybeHandle<JSObject> ApiNatives::InstantiateObject(
     563             :     Isolate* isolate, Handle<ObjectTemplateInfo> data,
     564             :     Handle<JSReceiver> new_target) {
     565      413723 :   InvokeScope invoke_scope(isolate);
     566             :   return ::v8::internal::InstantiateObject(isolate, data, new_target, false,
     567      827453 :                                            false);
     568             : }
     569             : 
     570          26 : MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject(
     571             :     Handle<ObjectTemplateInfo> data) {
     572             :   Isolate* isolate = data->GetIsolate();
     573          26 :   InvokeScope invoke_scope(isolate);
     574             : 
     575             :   Handle<FunctionTemplateInfo> constructor(
     576             :       FunctionTemplateInfo::cast(data->constructor()), isolate);
     577             :   Handle<Map> object_map = isolate->factory()->NewMap(
     578             :       JS_SPECIAL_API_OBJECT_TYPE,
     579             :       JSObject::kHeaderSize +
     580             :           data->embedder_field_count() * kEmbedderDataSlotSize,
     581          26 :       TERMINAL_FAST_ELEMENTS_KIND);
     582          52 :   object_map->SetConstructor(*constructor);
     583             :   object_map->set_is_access_check_needed(true);
     584          26 :   object_map->set_may_have_interesting_symbols(true);
     585             : 
     586          26 :   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(object_map);
     587          26 :   JSObject::ForceSetPrototype(object, isolate->factory()->null_value());
     588             : 
     589          52 :   return object;
     590             : }
     591             : 
     592     2135417 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     593             :                                  Handle<Name> name, Handle<Object> value,
     594             :                                  PropertyAttributes attributes) {
     595             :   PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
     596             :   auto details_handle = handle(details.AsSmi(), isolate);
     597     2135417 :   Handle<Object> data[] = {name, details_handle, value};
     598     2135417 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     599     2135417 : }
     600             : 
     601             : 
     602          55 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     603             :                                  Handle<Name> name, v8::Intrinsic intrinsic,
     604             :                                  PropertyAttributes attributes) {
     605          55 :   auto value = handle(Smi::FromInt(intrinsic), isolate);
     606             :   auto intrinsic_marker = isolate->factory()->true_value();
     607             :   PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
     608             :   auto details_handle = handle(details.AsSmi(), isolate);
     609             :   Handle<Object> data[] = {name, intrinsic_marker, details_handle, value};
     610          55 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     611          55 : }
     612             : 
     613             : 
     614         114 : void ApiNatives::AddAccessorProperty(Isolate* isolate,
     615             :                                      Handle<TemplateInfo> info,
     616             :                                      Handle<Name> name,
     617             :                                      Handle<FunctionTemplateInfo> getter,
     618             :                                      Handle<FunctionTemplateInfo> setter,
     619             :                                      PropertyAttributes attributes) {
     620             :   PropertyDetails details(kAccessor, attributes, PropertyCellType::kNoCell);
     621             :   auto details_handle = handle(details.AsSmi(), isolate);
     622             :   Handle<Object> data[] = {name, details_handle, getter, setter};
     623         114 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     624         114 : }
     625             : 
     626             : 
     627       54137 : void ApiNatives::AddNativeDataProperty(Isolate* isolate,
     628             :                                        Handle<TemplateInfo> info,
     629             :                                        Handle<AccessorInfo> property) {
     630             :   Object maybe_list = info->property_accessors();
     631             :   Handle<TemplateList> list;
     632       54137 :   if (maybe_list->IsUndefined(isolate)) {
     633       53900 :     list = TemplateList::New(isolate, 1);
     634             :   } else {
     635             :     list = handle(TemplateList::cast(maybe_list), isolate);
     636             :   }
     637       54137 :   list = TemplateList::Add(isolate, list, property);
     638      108274 :   info->set_property_accessors(*list);
     639       54137 : }
     640             : 
     641     3807190 : Handle<JSFunction> ApiNatives::CreateApiFunction(
     642             :     Isolate* isolate, Handle<FunctionTemplateInfo> obj,
     643             :     Handle<Object> prototype, InstanceType type, MaybeHandle<Name> maybe_name) {
     644             :   Handle<SharedFunctionInfo> shared =
     645             :       FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj,
     646     3807190 :                                                           maybe_name);
     647             :   // To simplify things, API functions always have shared name.
     648             :   DCHECK(shared->HasSharedName());
     649             : 
     650             :   Handle<JSFunction> result =
     651             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     652     7614393 :           shared, isolate->native_context());
     653             : 
     654     3807194 :   if (obj->remove_prototype()) {
     655             :     DCHECK(prototype.is_null());
     656             :     DCHECK(result->shared()->IsApiFunction());
     657             :     DCHECK(!result->IsConstructor());
     658             :     DCHECK(!result->has_prototype_slot());
     659        4892 :     return result;
     660             :   }
     661             : 
     662             :   // Down from here is only valid for API functions that can be used as a
     663             :   // constructor (don't set the "remove prototype" flag).
     664             :   DCHECK(result->has_prototype_slot());
     665             : 
     666     3802302 :   if (obj->read_only_prototype()) {
     667     3539447 :     result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
     668             :   }
     669             : 
     670     3802300 :   if (prototype->IsTheHole(isolate)) {
     671      112600 :     prototype = isolate->factory()->NewFunctionPrototype(result);
     672     3689700 :   } else if (obj->GetPrototypeProviderTemplate()->IsUndefined(isolate)) {
     673     3689690 :     JSObject::AddProperty(isolate, Handle<JSObject>::cast(prototype),
     674             :                           isolate->factory()->constructor_string(), result,
     675     3689696 :                           DONT_ENUM);
     676             :   }
     677             : 
     678             :   int embedder_field_count = 0;
     679             :   bool immutable_proto = false;
     680     3802294 :   if (!obj->GetInstanceTemplate()->IsUndefined(isolate)) {
     681             :     Handle<ObjectTemplateInfo> GetInstanceTemplate = Handle<ObjectTemplateInfo>(
     682             :         ObjectTemplateInfo::cast(obj->GetInstanceTemplate()), isolate);
     683             :     embedder_field_count = GetInstanceTemplate->embedder_field_count();
     684             :     immutable_proto = GetInstanceTemplate->immutable_proto();
     685             :   }
     686             : 
     687             :   // JS_FUNCTION_TYPE requires information about the prototype slot.
     688             :   DCHECK_NE(JS_FUNCTION_TYPE, type);
     689     3802294 :   int instance_size = JSObject::GetHeaderSize(type) +
     690     3802295 :                       kEmbedderDataSlotSize * embedder_field_count;
     691             : 
     692             :   Handle<Map> map = isolate->factory()->NewMap(type, instance_size,
     693     3802295 :                                                TERMINAL_FAST_ELEMENTS_KIND);
     694     3802301 :   JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
     695             : 
     696             :   // Mark as undetectable if needed.
     697     3802298 :   if (obj->undetectable()) {
     698             :     // We only allow callable undetectable receivers here, since this whole
     699             :     // undetectable business is only to support document.all, which is both
     700             :     // undetectable and callable. If we ever see the need to have an object
     701             :     // that is undetectable but not callable, we need to update the types.h
     702             :     // to allow encoding this.
     703         149 :     CHECK(!obj->GetInstanceCallHandler()->IsUndefined(isolate));
     704             :     map->set_is_undetectable(true);
     705             :   }
     706             : 
     707             :   // Mark as needs_access_check if needed.
     708     3802298 :   if (obj->needs_access_check()) {
     709             :     map->set_is_access_check_needed(true);
     710         349 :     map->set_may_have_interesting_symbols(true);
     711             :   }
     712             : 
     713             :   // Set interceptor information in the map.
     714     3802298 :   if (!obj->GetNamedPropertyHandler()->IsUndefined(isolate)) {
     715             :     map->set_has_named_interceptor(true);
     716        1096 :     map->set_may_have_interesting_symbols(true);
     717             :   }
     718     3802298 :   if (!obj->GetIndexedPropertyHandler()->IsUndefined(isolate)) {
     719             :     map->set_has_indexed_interceptor(true);
     720             :   }
     721             : 
     722             :   // Mark instance as callable in the map.
     723     3802298 :   if (!obj->GetInstanceCallHandler()->IsUndefined(isolate)) {
     724             :     map->set_is_callable(true);
     725         197 :     map->set_is_constructor(!obj->undetectable());
     726             :   }
     727             : 
     728     3802316 :   if (immutable_proto) map->set_is_immutable_proto(true);
     729             : 
     730     3802298 :   return result;
     731             : }
     732             : 
     733             : }  // namespace internal
     734      121996 : }  // namespace v8

Generated by: LCOV version 1.10