LCOV - code coverage report
Current view: top level - src - api-natives.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 203 223 91.0 %
Date: 2017-04-26 Functions: 25 26 96.2 %

          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.h"
       8             : #include "src/isolate-inl.h"
       9             : #include "src/lookup.h"
      10             : #include "src/messages.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : 
      16             : namespace {
      17             : 
      18             : class InvokeScope {
      19             :  public:
      20             :   explicit InvokeScope(Isolate* isolate)
      21     1928067 :       : isolate_(isolate), save_context_(isolate) {}
      22     3856129 :   ~InvokeScope() {
      23     1928064 :     bool has_exception = isolate_->has_pending_exception();
      24     1928065 :     if (has_exception) {
      25           0 :       isolate_->ReportPendingMessages();
      26             :     } else {
      27     1928065 :       isolate_->clear_pending_message();
      28             :     }
      29     1928065 :   }
      30             : 
      31             :  private:
      32             :   Isolate* isolate_;
      33             :   SaveContext save_context_;
      34             : };
      35             : 
      36             : MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
      37             :                                         Handle<ObjectTemplateInfo> data,
      38             :                                         Handle<JSReceiver> new_target,
      39             :                                         bool is_hidden_prototype,
      40             :                                         bool is_prototype);
      41             : 
      42             : MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
      43             :                                             Handle<FunctionTemplateInfo> data,
      44             :                                             Handle<Name> name = Handle<Name>());
      45             : 
      46     3038461 : MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data,
      47             :                                 Handle<Name> name = Handle<Name>()) {
      48     3038461 :   if (data->IsFunctionTemplateInfo()) {
      49             :     return InstantiateFunction(isolate,
      50     5039358 :                                Handle<FunctionTemplateInfo>::cast(data), name);
      51      518782 :   } else if (data->IsObjectTemplateInfo()) {
      52             :     return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
      53      755700 :                              Handle<JSReceiver>(), false, false);
      54             :   } else {
      55             :     return data;
      56             :   }
      57             : }
      58             : 
      59         148 : MaybeHandle<Object> DefineAccessorProperty(
      60             :     Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
      61             :     Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes,
      62             :     bool force_instantiate) {
      63             :   DCHECK(!getter->IsFunctionTemplateInfo() ||
      64             :          !FunctionTemplateInfo::cast(*getter)->do_not_cache());
      65             :   DCHECK(!setter->IsFunctionTemplateInfo() ||
      66             :          !FunctionTemplateInfo::cast(*setter)->do_not_cache());
      67         148 :   if (force_instantiate) {
      68           0 :     if (getter->IsFunctionTemplateInfo()) {
      69           0 :       ASSIGN_RETURN_ON_EXCEPTION(
      70             :           isolate, getter,
      71             :           InstantiateFunction(isolate,
      72             :                               Handle<FunctionTemplateInfo>::cast(getter)),
      73             :           Object);
      74             :     }
      75           0 :     if (setter->IsFunctionTemplateInfo()) {
      76           0 :       ASSIGN_RETURN_ON_EXCEPTION(
      77             :           isolate, setter,
      78             :           InstantiateFunction(isolate,
      79             :                               Handle<FunctionTemplateInfo>::cast(setter)),
      80             :           Object);
      81             :     }
      82             :   }
      83         296 :   RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
      84             :                                                         setter, attributes),
      85             :                       Object);
      86             :   return object;
      87             : }
      88             : 
      89             : 
      90     3038461 : MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
      91             :                                        Handle<JSObject> object,
      92             :                                        Handle<Name> name,
      93             :                                        Handle<Object> prop_data,
      94             :                                        PropertyAttributes attributes) {
      95             :   Handle<Object> value;
      96     6076922 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
      97             :                              Instantiate(isolate, prop_data, name), Object);
      98             : 
      99             :   LookupIterator it = LookupIterator::PropertyOrElement(
     100     3038461 :       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
     101             : 
     102             : #ifdef DEBUG
     103             :   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     104             :   DCHECK(maybe.IsJust());
     105             :   if (it.IsFound()) {
     106             :     THROW_NEW_ERROR(
     107             :         isolate,
     108             :         NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
     109             :         Object);
     110             :   }
     111             : #endif
     112             : 
     113     3038461 :   MAYBE_RETURN_NULL(
     114             :       Object::AddDataProperty(&it, value, attributes, Object::THROW_ON_ERROR,
     115             :                               Object::CERTAINLY_NOT_STORE_FROM_KEYED));
     116             :   return value;
     117             : }
     118             : 
     119             : 
     120         293 : void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     121             :   Handle<Map> old_map(object->map());
     122             :   // Copy map so it won't interfere constructor's initial map.
     123         293 :   Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
     124             :   new_map->set_is_access_check_needed(false);
     125         293 :   JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
     126         293 : }
     127             : 
     128             : 
     129         293 : void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
     130             :   Handle<Map> old_map(object->map());
     131             :   // Copy map so it won't interfere constructor's initial map.
     132         293 :   Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
     133             :   new_map->set_is_access_check_needed(true);
     134         293 :   JSObject::MigrateToMap(object, new_map);
     135         293 : }
     136             : 
     137             : 
     138             : class AccessCheckDisableScope {
     139             :  public:
     140     4214230 :   AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
     141             :       : isolate_(isolate),
     142             :         disabled_(obj->map()->is_access_check_needed()),
     143     8428460 :         obj_(obj) {
     144     4214230 :     if (disabled_) {
     145         293 :       DisableAccessChecks(isolate_, obj_);
     146             :     }
     147     4214230 :   }
     148             :   ~AccessCheckDisableScope() {
     149     4214229 :     if (disabled_) {
     150         293 :       EnableAccessChecks(isolate_, obj_);
     151             :     }
     152             :   }
     153             : 
     154             :  private:
     155             :   Isolate* isolate_;
     156             :   const bool disabled_;
     157             :   Handle<JSObject> obj_;
     158             : };
     159             : 
     160             : 
     161          54 : Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
     162          54 :   Handle<Context> native_context = isolate->native_context();
     163             :   DCHECK(!native_context.is_null());
     164          54 :   switch (intrinsic) {
     165             : #define GET_INTRINSIC_VALUE(name, iname) \
     166             :   case v8::k##name:                      \
     167             :     return native_context->iname();
     168          54 :     V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
     169             : #undef GET_INTRINSIC_VALUE
     170             :   }
     171             :   return nullptr;
     172             : }
     173             : 
     174             : 
     175             : template <typename TemplateInfoT>
     176     4214230 : MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
     177             :                                         Handle<TemplateInfoT> data,
     178             :                                         bool is_hidden_prototype) {
     179             :   HandleScope scope(isolate);
     180             :   // Disable access checks while instantiating the object.
     181     4214230 :   AccessCheckDisableScope access_check_scope(isolate, obj);
     182             : 
     183             :   // Walk the inheritance chain and copy all accessors to current object.
     184             :   int max_number_of_properties = 0;
     185             :   TemplateInfoT* info = *data;
     186    12643172 :   while (info != nullptr) {
     187             :     Object* props = info->property_accessors();
     188     4214709 :     if (!props->IsUndefined(isolate)) {
     189       63307 :       max_number_of_properties += TemplateList::cast(props)->length();
     190             :     }
     191     4214709 :     info = info->GetParent(isolate);
     192             :   }
     193             : 
     194     4214231 :   if (max_number_of_properties > 0) {
     195             :     int valid_descriptors = 0;
     196             :     // Use a temporary FixedArray to accumulate unique accessors.
     197             :     Handle<FixedArray> array =
     198       63286 :         isolate->factory()->NewFixedArray(max_number_of_properties);
     199             : 
     200      126656 :     for (Handle<TemplateInfoT> temp(*data); *temp != nullptr;
     201       63370 :          temp = handle(temp->GetParent(isolate), isolate)) {
     202             :       // Accumulate accessors.
     203             :       Object* maybe_properties = temp->property_accessors();
     204       63370 :       if (!maybe_properties->IsUndefined(isolate)) {
     205       63307 :         valid_descriptors = AccessorInfo::AppendUnique(
     206             :             handle(maybe_properties, isolate), array, valid_descriptors);
     207             :       }
     208             :     }
     209             : 
     210             :     // Install accumulated accessors.
     211       63622 :     for (int i = 0; i < valid_descriptors; i++) {
     212             :       Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
     213       63622 :       JSObject::SetAccessor(obj, accessor).Assert();
     214             :     }
     215             :   }
     216             : 
     217             :   Object* maybe_property_list = data->property_list();
     218     4214229 :   if (maybe_property_list->IsUndefined(isolate)) return obj;
     219             :   Handle<TemplateList> properties(TemplateList::cast(maybe_property_list),
     220             :                                   isolate);
     221      381124 :   if (properties->length() == 0) return obj;
     222             : 
     223             :   int i = 0;
     224     6458342 :   for (int c = 0; c < data->number_of_properties(); c++) {
     225     6077218 :     auto name = handle(Name::cast(properties->get(i++)), isolate);
     226     3038609 :     Object* bit = properties->get(i++);
     227     3038609 :     if (bit->IsSmi()) {
     228             :       PropertyDetails details(Smi::cast(bit));
     229             :       PropertyAttributes attributes = details.attributes();
     230             :       PropertyKind kind = details.kind();
     231             : 
     232     3038555 :       if (kind == kData) {
     233     6076814 :         auto prop_data = handle(properties->get(i++), isolate);
     234     6076814 :         RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     235             :                                                         prop_data, attributes),
     236             :                             JSObject);
     237             :       } else {
     238         296 :         auto getter = handle(properties->get(i++), isolate);
     239         296 :         auto setter = handle(properties->get(i++), isolate);
     240         296 :         RETURN_ON_EXCEPTION(
     241             :             isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
     242             :                                             attributes, is_hidden_prototype),
     243             :             JSObject);
     244             :       }
     245             :     } else {
     246             :       // Intrinsic data property --- Get appropriate value from the current
     247             :       // context.
     248          54 :       PropertyDetails details(Smi::cast(properties->get(i++)));
     249             :       PropertyAttributes attributes = details.attributes();
     250             :       DCHECK_EQ(kData, details.kind());
     251             : 
     252             :       v8::Intrinsic intrinsic =
     253         108 :           static_cast<v8::Intrinsic>(Smi::cast(properties->get(i++))->value());
     254         108 :       auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
     255             : 
     256         108 :       RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
     257             :                                                       prop_data, attributes),
     258             :                           JSObject);
     259             :     }
     260             :   }
     261             :   return obj;
     262             : }
     263             : 
     264     4915110 : MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate,
     265             :                                                int serial_number) {
     266             :   DCHECK_LE(1, serial_number);
     267     4915110 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     268             :     Handle<FixedArray> fast_cache =
     269     4863076 :         isolate->fast_template_instantiations_cache();
     270     9726162 :     return fast_cache->GetValue<JSObject>(isolate, serial_number - 1);
     271             :   } else {
     272             :     Handle<UnseededNumberDictionary> slow_cache =
     273       52034 :         isolate->slow_template_instantiations_cache();
     274       52034 :     int entry = slow_cache->FindEntry(serial_number);
     275       52034 :     if (entry == UnseededNumberDictionary::kNotFound) {
     276             :       return MaybeHandle<JSObject>();
     277             :     }
     278        4194 :     return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate);
     279             :   }
     280             : }
     281             : 
     282     3979657 : void CacheTemplateInstantiation(Isolate* isolate, int serial_number,
     283             :                                 Handle<JSObject> object) {
     284             :   DCHECK_LE(1, serial_number);
     285     3979657 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     286             :     Handle<FixedArray> fast_cache =
     287     3931823 :         isolate->fast_template_instantiations_cache();
     288             :     Handle<FixedArray> new_cache =
     289     3931819 :         FixedArray::SetAndGrow(fast_cache, serial_number - 1, object);
     290     3931822 :     if (*new_cache != *fast_cache) {
     291             :       isolate->native_context()->set_fast_template_instantiations_cache(
     292           0 :           *new_cache);
     293             :     }
     294             :   } else {
     295             :     Handle<UnseededNumberDictionary> cache =
     296       47834 :         isolate->slow_template_instantiations_cache();
     297             :     auto new_cache =
     298       47834 :         UnseededNumberDictionary::AtNumberPut(cache, serial_number, object);
     299       47834 :     if (*new_cache != *cache) {
     300             :       isolate->native_context()->set_slow_template_instantiations_cache(
     301           0 :           *new_cache);
     302             :     }
     303             :   }
     304     3979656 : }
     305             : 
     306           0 : void UncacheTemplateInstantiation(Isolate* isolate, int serial_number) {
     307             :   DCHECK_LE(1, serial_number);
     308           0 :   if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
     309             :     Handle<FixedArray> fast_cache =
     310           0 :         isolate->fast_template_instantiations_cache();
     311             :     DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate));
     312           0 :     fast_cache->set_undefined(serial_number - 1);
     313             :   } else {
     314             :     Handle<UnseededNumberDictionary> cache =
     315           0 :         isolate->slow_template_instantiations_cache();
     316           0 :     int entry = cache->FindEntry(serial_number);
     317             :     DCHECK(entry != UnseededNumberDictionary::kNotFound);
     318             :     Handle<Object> result =
     319           0 :         UnseededNumberDictionary::DeleteProperty(cache, entry);
     320             :     USE(result);
     321             :     DCHECK(result->IsTrue(isolate));
     322           0 :     auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
     323             :     isolate->native_context()->set_slow_template_instantiations_cache(
     324           0 :         *new_cache);
     325             :   }
     326           0 : }
     327             : 
     328       56682 : bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo* info,
     329             :                            JSReceiver* new_target) {
     330             :   DisallowHeapAllocation no_gc;
     331             : 
     332       56682 :   if (!new_target->IsJSFunction()) return false;
     333             :   JSFunction* fun = JSFunction::cast(new_target);
     334       56682 :   if (fun->shared()->function_data() != info->constructor()) return false;
     335       56626 :   if (info->immutable_proto()) return false;
     336       56619 :   return fun->context()->native_context() == isolate->raw_native_context();
     337             : }
     338             : 
     339      694441 : MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
     340             :                                         Handle<ObjectTemplateInfo> info,
     341             :                                         Handle<JSReceiver> new_target,
     342             :                                         bool is_hidden_prototype,
     343             :                                         bool is_prototype) {
     344             :   Handle<JSFunction> constructor;
     345             :   int serial_number = Smi::cast(info->serial_number())->value();
     346      694441 :   if (!new_target.is_null()) {
     347       56682 :     if (IsSimpleInstantiation(isolate, *info, *new_target)) {
     348             :       constructor = Handle<JSFunction>::cast(new_target);
     349             :     } else {
     350             :       // Disable caching for subclass instantiation.
     351             :       serial_number = 0;
     352             :     }
     353             :   }
     354             :   // Fast path.
     355             :   Handle<JSObject> result;
     356      694441 :   if (serial_number) {
     357     1007166 :     if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) {
     358      242438 :       return isolate->factory()->CopyJSObject(result);
     359             :     }
     360             :   }
     361             : 
     362      452003 :   if (constructor.is_null()) {
     363             :     Object* maybe_constructor_info = info->constructor();
     364      448026 :     if (maybe_constructor_info->IsUndefined(isolate)) {
     365      252624 :       constructor = isolate->object_function();
     366             :     } else {
     367             :       // Enter a new scope.  Recursion could otherwise create a lot of handles.
     368             :       HandleScope scope(isolate);
     369             :       Handle<FunctionTemplateInfo> cons_templ(
     370             :           FunctionTemplateInfo::cast(maybe_constructor_info), isolate);
     371             :       Handle<JSFunction> tmp_constructor;
     372      390804 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor,
     373             :                                  InstantiateFunction(isolate, cons_templ),
     374             :                                  JSObject);
     375      195402 :       constructor = scope.CloseAndEscape(tmp_constructor);
     376             :     }
     377             : 
     378      448026 :     if (new_target.is_null()) new_target = constructor;
     379             :   }
     380             : 
     381             :   Handle<JSObject> object;
     382      904006 :   ASSIGN_RETURN_ON_EXCEPTION(isolate, object,
     383             :                              JSObject::New(constructor, new_target), JSObject);
     384             : 
     385      452003 :   if (is_prototype) JSObject::OptimizeAsPrototype(object, FAST_PROTOTYPE);
     386             : 
     387      904006 :   ASSIGN_RETURN_ON_EXCEPTION(
     388             :       isolate, result,
     389             :       ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
     390      452003 :   if (info->immutable_proto()) {
     391          28 :     JSObject::SetImmutableProto(object);
     392             :   }
     393      452003 :   if (!is_prototype) {
     394             :     // Keep prototypes in slow-mode. Let them be lazily turned fast later on.
     395             :     // TODO(dcarney): is this necessary?
     396      324379 :     JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
     397             :     // Don't cache prototypes.
     398      324379 :     if (serial_number) {
     399      260325 :       CacheTemplateInstantiation(isolate, serial_number, result);
     400      260325 :       result = isolate->factory()->CopyJSObject(result);
     401             :     }
     402             :   }
     403             : 
     404             :   return result;
     405             : }
     406             : 
     407             : namespace {
     408         280 : MaybeHandle<Object> GetInstancePrototype(Isolate* isolate,
     409             :                                          Object* function_template) {
     410             :   // Enter a new scope.  Recursion could otherwise create a lot of handles.
     411             :   HandleScope scope(isolate);
     412             :   Handle<JSFunction> parent_instance;
     413         560 :   ASSIGN_RETURN_ON_EXCEPTION(
     414             :       isolate, parent_instance,
     415             :       InstantiateFunction(
     416             :           isolate,
     417             :           handle(FunctionTemplateInfo::cast(function_template), isolate)),
     418             :       JSFunction);
     419             :   Handle<Object> instance_prototype;
     420             :   // TODO(cbruni): decide what to do here.
     421         560 :   ASSIGN_RETURN_ON_EXCEPTION(
     422             :       isolate, instance_prototype,
     423             :       JSObject::GetProperty(parent_instance,
     424             :                             isolate->factory()->prototype_string()),
     425             :       JSFunction);
     426         280 :   return scope.CloseAndEscape(instance_prototype);
     427             : }
     428             : }  // namespace
     429             : 
     430     4454425 : MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
     431             :                                             Handle<FunctionTemplateInfo> data,
     432             :                                             Handle<Name> name) {
     433             :   int serial_number = Smi::cast(data->serial_number())->value();
     434     4454425 :   if (serial_number) {
     435             :     Handle<JSObject> result;
     436     8823062 :     if (ProbeInstantiationsCache(isolate, serial_number).ToHandle(&result)) {
     437             :       return Handle<JSFunction>::cast(result);
     438             :     }
     439             :   }
     440             :   Handle<Object> prototype;
     441     3762232 :   if (!data->remove_prototype()) {
     442             :     Object* prototype_templ = data->prototype_template();
     443     3721041 :     if (prototype_templ->IsUndefined(isolate)) {
     444             :       Object* protoype_provider_templ = data->prototype_provider_template();
     445     3593417 :       if (protoype_provider_templ->IsUndefined(isolate)) {
     446     3593411 :         prototype = isolate->factory()->NewJSObject(isolate->object_function());
     447             :       } else {
     448          12 :         ASSIGN_RETURN_ON_EXCEPTION(
     449             :             isolate, prototype,
     450             :             GetInstancePrototype(isolate, protoype_provider_templ), JSFunction);
     451             :       }
     452             :     } else {
     453      382872 :       ASSIGN_RETURN_ON_EXCEPTION(
     454             :           isolate, prototype,
     455             :           InstantiateObject(
     456             :               isolate,
     457             :               handle(ObjectTemplateInfo::cast(prototype_templ), isolate),
     458             :               Handle<JSReceiver>(), data->hidden_prototype(), true),
     459             :           JSFunction);
     460             :     }
     461             :     Object* parent = data->parent_template();
     462     3721038 :     if (!parent->IsUndefined(isolate)) {
     463             :       Handle<Object> parent_prototype;
     464         548 :       ASSIGN_RETURN_ON_EXCEPTION(isolate, parent_prototype,
     465             :                                  GetInstancePrototype(isolate, parent),
     466             :                                  JSFunction);
     467             :       JSObject::ForceSetPrototype(Handle<JSObject>::cast(prototype),
     468         274 :                                   parent_prototype);
     469             :     }
     470             :   }
     471             :   Handle<JSFunction> function = ApiNatives::CreateApiFunction(
     472     3762229 :       isolate, data, prototype, ApiNatives::JavaScriptObjectType);
     473     5654802 :   if (!name.is_null() && name->IsString()) {
     474     1892568 :     function->shared()->set_name(*name);
     475             :   }
     476     3762225 :   if (serial_number) {
     477             :     // Cache the function.
     478     3719331 :     CacheTemplateInstantiation(isolate, serial_number, function);
     479             :   }
     480             :   MaybeHandle<JSObject> result =
     481     7524450 :       ConfigureInstance(isolate, function, data, data->hidden_prototype());
     482     3762225 :   if (result.is_null()) {
     483             :     // Uncache on error.
     484           0 :     if (serial_number) {
     485           0 :       UncacheTemplateInstantiation(isolate, serial_number);
     486             :     }
     487             :     return MaybeHandle<JSFunction>();
     488             :   }
     489             :   return function;
     490             : }
     491             : 
     492             : 
     493     2160921 : void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
     494             :                                int length, Handle<Object>* data) {
     495             :   Object* maybe_list = templ->property_list();
     496             :   Handle<TemplateList> list;
     497     2160921 :   if (maybe_list->IsUndefined(isolate)) {
     498      316880 :     list = TemplateList::New(isolate, length);
     499             :   } else {
     500             :     list = handle(TemplateList::cast(maybe_list), isolate);
     501             :   }
     502     2160921 :   templ->set_number_of_properties(templ->number_of_properties() + 1);
     503     8643839 :   for (int i = 0; i < length; i++) {
     504             :     Handle<Object> value =
     505     6482918 :         data[i].is_null()
     506             :             ? Handle<Object>::cast(isolate->factory()->undefined_value())
     507     6482990 :             : data[i];
     508     6482918 :     list = TemplateList::Add(isolate, list, value);
     509             :   }
     510     2160921 :   templ->set_property_list(*list);
     511     2160921 : }
     512             : 
     513             : }  // namespace
     514             : 
     515     1739066 : MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
     516             :     Handle<FunctionTemplateInfo> data) {
     517             :   Isolate* isolate = data->GetIsolate();
     518             :   InvokeScope invoke_scope(isolate);
     519     1739067 :   return ::v8::internal::InstantiateFunction(isolate, data);
     520             : }
     521             : 
     522      188967 : MaybeHandle<JSObject> ApiNatives::InstantiateObject(
     523             :     Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) {
     524             :   Isolate* isolate = data->GetIsolate();
     525             :   InvokeScope invoke_scope(isolate);
     526             :   return ::v8::internal::InstantiateObject(isolate, data, new_target, false,
     527      188967 :                                            false);
     528             : }
     529             : 
     530          34 : MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject(
     531             :     Handle<ObjectTemplateInfo> data) {
     532             :   Isolate* isolate = data->GetIsolate();
     533             :   InvokeScope invoke_scope(isolate);
     534             : 
     535             :   Handle<FunctionTemplateInfo> constructor(
     536             :       FunctionTemplateInfo::cast(data->constructor()));
     537             :   Handle<Map> object_map = isolate->factory()->NewMap(
     538             :       JS_SPECIAL_API_OBJECT_TYPE,
     539             :       JSObject::kHeaderSize + data->embedder_field_count() * kPointerSize,
     540          34 :       FAST_HOLEY_SMI_ELEMENTS);
     541             :   object_map->SetConstructor(*constructor);
     542             :   object_map->set_is_access_check_needed(true);
     543             : 
     544          34 :   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(object_map);
     545          34 :   JSObject::ForceSetPrototype(object, isolate->factory()->null_value());
     546             : 
     547          34 :   return object;
     548             : }
     549             : 
     550     2160766 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     551             :                                  Handle<Name> name, Handle<Object> value,
     552             :                                  PropertyAttributes attributes) {
     553             :   PropertyDetails details(kData, attributes, 0, PropertyCellType::kNoCell);
     554             :   auto details_handle = handle(details.AsSmi(), isolate);
     555     2160766 :   Handle<Object> data[] = {name, details_handle, value};
     556     2160766 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     557     2160766 : }
     558             : 
     559             : 
     560          48 : void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
     561             :                                  Handle<Name> name, v8::Intrinsic intrinsic,
     562             :                                  PropertyAttributes attributes) {
     563          48 :   auto value = handle(Smi::FromInt(intrinsic), isolate);
     564             :   auto intrinsic_marker = isolate->factory()->true_value();
     565             :   PropertyDetails details(kData, attributes, 0, PropertyCellType::kNoCell);
     566             :   auto details_handle = handle(details.AsSmi(), isolate);
     567             :   Handle<Object> data[] = {name, intrinsic_marker, details_handle, value};
     568          48 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     569          48 : }
     570             : 
     571             : 
     572         107 : void ApiNatives::AddAccessorProperty(Isolate* isolate,
     573             :                                      Handle<TemplateInfo> info,
     574             :                                      Handle<Name> name,
     575             :                                      Handle<FunctionTemplateInfo> getter,
     576             :                                      Handle<FunctionTemplateInfo> setter,
     577             :                                      PropertyAttributes attributes) {
     578             :   PropertyDetails details(kAccessor, attributes, 0, PropertyCellType::kNoCell);
     579             :   auto details_handle = handle(details.AsSmi(), isolate);
     580             :   Handle<Object> data[] = {name, details_handle, getter, setter};
     581         107 :   AddPropertyToPropertyList(isolate, info, arraysize(data), data);
     582         107 : }
     583             : 
     584             : 
     585       63481 : void ApiNatives::AddNativeDataProperty(Isolate* isolate,
     586             :                                        Handle<TemplateInfo> info,
     587             :                                        Handle<AccessorInfo> property) {
     588             :   Object* maybe_list = info->property_accessors();
     589             :   Handle<TemplateList> list;
     590       63481 :   if (maybe_list->IsUndefined(isolate)) {
     591       63231 :     list = TemplateList::New(isolate, 1);
     592             :   } else {
     593             :     list = handle(TemplateList::cast(maybe_list), isolate);
     594             :   }
     595       63481 :   list = TemplateList::Add(isolate, list, property);
     596       63481 :   info->set_property_accessors(*list);
     597       63481 : }
     598             : 
     599             : 
     600     3891715 : Handle<JSFunction> ApiNatives::CreateApiFunction(
     601             :     Isolate* isolate, Handle<FunctionTemplateInfo> obj,
     602             :     Handle<Object> prototype, ApiInstanceType instance_type) {
     603             :   Handle<SharedFunctionInfo> shared =
     604     3891715 :       FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
     605             :   Handle<JSFunction> result =
     606             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     607     3891719 :           shared, isolate->native_context());
     608             : 
     609     3891718 :   if (obj->remove_prototype()) {
     610       82376 :     result->set_map(*isolate->sloppy_function_without_prototype_map());
     611             :     DCHECK(prototype.is_null());
     612             :     DCHECK(result->shared()->IsApiFunction());
     613             :     DCHECK(!result->has_initial_map());
     614             :     DCHECK(!result->has_prototype());
     615             :     DCHECK(!result->IsConstructor());
     616       41188 :     return result;
     617             :   }
     618             : 
     619             :   // Down from here is only valid for API functions that can be used as a
     620             :   // constructor (don't set the "remove prototype" flag).
     621             : 
     622     3850530 :   if (obj->read_only_prototype()) {
     623     3497183 :     result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
     624             :   }
     625             : 
     626     3850525 :   if (prototype->IsTheHole(isolate)) {
     627      129490 :     prototype = isolate->factory()->NewFunctionPrototype(result);
     628     3721035 :   } else if (obj->prototype_provider_template()->IsUndefined(isolate)) {
     629             :     JSObject::AddProperty(Handle<JSObject>::cast(prototype),
     630             :                           isolate->factory()->constructor_string(), result,
     631     3721029 :                           DONT_ENUM);
     632             :   }
     633             : 
     634             :   int embedder_field_count = 0;
     635             :   bool immutable_proto = false;
     636     3850527 :   if (!obj->instance_template()->IsUndefined(isolate)) {
     637             :     Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
     638             :         ObjectTemplateInfo::cast(obj->instance_template()));
     639             :     embedder_field_count = instance_template->embedder_field_count();
     640             :     immutable_proto = instance_template->immutable_proto();
     641             :   }
     642             : 
     643             :   // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
     644             :   // JSObject::GetHeaderSize.
     645     3850527 :   int instance_size = kPointerSize * embedder_field_count;
     646             :   InstanceType type;
     647     3850527 :   switch (instance_type) {
     648             :     case JavaScriptObjectType:
     649     7441783 :       if (!obj->needs_access_check() &&
     650     7440676 :           obj->named_property_handler()->IsUndefined(isolate) &&
     651             :           obj->indexed_property_handler()->IsUndefined(isolate)) {
     652             :         type = JS_API_OBJECT_TYPE;
     653             :       } else {
     654             :         type = JS_SPECIAL_API_OBJECT_TYPE;
     655             :       }
     656     3721037 :       instance_size += JSObject::kHeaderSize;
     657     3721037 :       break;
     658             :     case GlobalObjectType:
     659             :       type = JS_GLOBAL_OBJECT_TYPE;
     660       64745 :       instance_size += JSGlobalObject::kSize;
     661       64745 :       break;
     662             :     case GlobalProxyType:
     663             :       type = JS_GLOBAL_PROXY_TYPE;
     664       64745 :       instance_size += JSGlobalProxy::kSize;
     665       64745 :       break;
     666             :     default:
     667           0 :       UNREACHABLE();
     668             :       type = JS_OBJECT_TYPE;  // Keep the compiler happy.
     669             :       break;
     670             :   }
     671             : 
     672             :   Handle<Map> map =
     673     3850527 :       isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
     674     3850529 :   JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
     675             : 
     676             :   // Mark as undetectable if needed.
     677     3850531 :   if (obj->undetectable()) {
     678             :     // We only allow callable undetectable receivers here, since this whole
     679             :     // undetectable business is only to support document.all, which is both
     680             :     // undetectable and callable. If we ever see the need to have an object
     681             :     // that is undetectable but not callable, we need to update the types.h
     682             :     // to allow encoding this.
     683         223 :     CHECK(!obj->instance_call_handler()->IsUndefined(isolate));
     684             :     map->set_is_undetectable();
     685             :   }
     686             : 
     687             :   // Mark as needs_access_check if needed.
     688     3850531 :   if (obj->needs_access_check()) {
     689             :     map->set_is_access_check_needed(true);
     690             :   }
     691             : 
     692             :   // Set interceptor information in the map.
     693     3850531 :   if (!obj->named_property_handler()->IsUndefined(isolate)) {
     694             :     map->set_has_named_interceptor();
     695             :   }
     696     3850531 :   if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
     697             :     map->set_has_indexed_interceptor();
     698             :   }
     699             : 
     700             :   // Mark instance as callable in the map.
     701     3850531 :   if (!obj->instance_call_handler()->IsUndefined(isolate)) {
     702             :     map->set_is_callable();
     703             :     map->set_is_constructor(true);
     704             :   }
     705             : 
     706     3850531 :   if (immutable_proto) map->set_immutable_proto(true);
     707             : 
     708     3850531 :   return result;
     709             : }
     710             : 
     711             : }  // namespace internal
     712             : }  // namespace v8

Generated by: LCOV version 1.10