Home | History | Annotate | Download | only in src
      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 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
     19                                         Handle<ObjectTemplateInfo> data,
     20                                         Handle<JSReceiver> new_target,
     21                                         bool is_hidden_prototype);
     22 
     23 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
     24                                             Handle<FunctionTemplateInfo> data,
     25                                             Handle<Name> name = Handle<Name>());
     26 
     27 
     28 MaybeHandle<Object> Instantiate(Isolate* isolate, Handle<Object> data,
     29                                 Handle<Name> name = Handle<Name>()) {
     30   if (data->IsFunctionTemplateInfo()) {
     31     return InstantiateFunction(isolate,
     32                                Handle<FunctionTemplateInfo>::cast(data), name);
     33   } else if (data->IsObjectTemplateInfo()) {
     34     return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
     35                              Handle<JSReceiver>(), false);
     36   } else {
     37     return data;
     38   }
     39 }
     40 
     41 MaybeHandle<Object> DefineAccessorProperty(
     42     Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
     43     Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes,
     44     bool force_instantiate) {
     45   DCHECK(!getter->IsFunctionTemplateInfo() ||
     46          !FunctionTemplateInfo::cast(*getter)->do_not_cache());
     47   DCHECK(!setter->IsFunctionTemplateInfo() ||
     48          !FunctionTemplateInfo::cast(*setter)->do_not_cache());
     49   if (force_instantiate) {
     50     if (getter->IsFunctionTemplateInfo()) {
     51       ASSIGN_RETURN_ON_EXCEPTION(
     52           isolate, getter,
     53           InstantiateFunction(isolate,
     54                               Handle<FunctionTemplateInfo>::cast(getter)),
     55           Object);
     56     }
     57     if (setter->IsFunctionTemplateInfo()) {
     58       ASSIGN_RETURN_ON_EXCEPTION(
     59           isolate, setter,
     60           InstantiateFunction(isolate,
     61                               Handle<FunctionTemplateInfo>::cast(setter)),
     62           Object);
     63     }
     64   }
     65   RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
     66                                                         setter, attributes),
     67                       Object);
     68   return object;
     69 }
     70 
     71 
     72 MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
     73                                        Handle<JSObject> object,
     74                                        Handle<Name> name,
     75                                        Handle<Object> prop_data,
     76                                        PropertyAttributes attributes) {
     77   Handle<Object> value;
     78   ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
     79                              Instantiate(isolate, prop_data, name), Object);
     80 
     81   LookupIterator it = LookupIterator::PropertyOrElement(
     82       isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);
     83 
     84 #ifdef DEBUG
     85   Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
     86   DCHECK(maybe.IsJust());
     87   if (it.IsFound()) {
     88     THROW_NEW_ERROR(
     89         isolate,
     90         NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
     91         Object);
     92   }
     93 #endif
     94 
     95   MAYBE_RETURN_NULL(
     96       Object::AddDataProperty(&it, value, attributes, Object::THROW_ON_ERROR,
     97                               Object::CERTAINLY_NOT_STORE_FROM_KEYED));
     98   return value;
     99 }
    100 
    101 
    102 void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
    103   Handle<Map> old_map(object->map());
    104   // Copy map so it won't interfere constructor's initial map.
    105   Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
    106   new_map->set_is_access_check_needed(false);
    107   JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
    108 }
    109 
    110 
    111 void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
    112   Handle<Map> old_map(object->map());
    113   // Copy map so it won't interfere constructor's initial map.
    114   Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
    115   new_map->set_is_access_check_needed(true);
    116   JSObject::MigrateToMap(object, new_map);
    117 }
    118 
    119 
    120 class AccessCheckDisableScope {
    121  public:
    122   AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
    123       : isolate_(isolate),
    124         disabled_(obj->map()->is_access_check_needed()),
    125         obj_(obj) {
    126     if (disabled_) {
    127       DisableAccessChecks(isolate_, obj_);
    128     }
    129   }
    130   ~AccessCheckDisableScope() {
    131     if (disabled_) {
    132       EnableAccessChecks(isolate_, obj_);
    133     }
    134   }
    135 
    136  private:
    137   Isolate* isolate_;
    138   const bool disabled_;
    139   Handle<JSObject> obj_;
    140 };
    141 
    142 
    143 Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
    144   Handle<Context> native_context = isolate->native_context();
    145   DCHECK(!native_context.is_null());
    146   switch (intrinsic) {
    147 #define GET_INTRINSIC_VALUE(name, iname) \
    148   case v8::k##name:                      \
    149     return native_context->iname();
    150     V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
    151 #undef GET_INTRINSIC_VALUE
    152   }
    153   return nullptr;
    154 }
    155 
    156 // Returns parent function template or null.
    157 FunctionTemplateInfo* GetParent(FunctionTemplateInfo* data) {
    158   Object* parent = data->parent_template();
    159   return parent->IsUndefined(data->GetIsolate())
    160              ? nullptr
    161              : FunctionTemplateInfo::cast(parent);
    162 }
    163 
    164 // Starting from given object template's constructor walk up the inheritance
    165 // chain till a function template that has an instance template is found.
    166 ObjectTemplateInfo* GetParent(ObjectTemplateInfo* data) {
    167   Object* maybe_ctor = data->constructor();
    168   Isolate* isolate = data->GetIsolate();
    169   if (maybe_ctor->IsUndefined(isolate)) return nullptr;
    170   FunctionTemplateInfo* ctor = FunctionTemplateInfo::cast(maybe_ctor);
    171   while (true) {
    172     ctor = GetParent(ctor);
    173     if (ctor == nullptr) return nullptr;
    174     Object* maybe_obj = ctor->instance_template();
    175     if (!maybe_obj->IsUndefined(isolate)) {
    176       return ObjectTemplateInfo::cast(maybe_obj);
    177     }
    178   }
    179 }
    180 
    181 template <typename TemplateInfoT>
    182 MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
    183                                         Handle<TemplateInfoT> data,
    184                                         bool is_hidden_prototype) {
    185   HandleScope scope(isolate);
    186   // Disable access checks while instantiating the object.
    187   AccessCheckDisableScope access_check_scope(isolate, obj);
    188 
    189   // Walk the inheritance chain and copy all accessors to current object.
    190   int max_number_of_properties = 0;
    191   TemplateInfoT* info = *data;
    192   while (info != nullptr) {
    193     if (!info->property_accessors()->IsUndefined(isolate)) {
    194       Object* props = info->property_accessors();
    195       if (!props->IsUndefined(isolate)) {
    196         Handle<Object> props_handle(props, isolate);
    197         NeanderArray props_array(props_handle);
    198         max_number_of_properties += props_array.length();
    199       }
    200     }
    201     info = GetParent(info);
    202   }
    203 
    204   if (max_number_of_properties > 0) {
    205     int valid_descriptors = 0;
    206     // Use a temporary FixedArray to accumulate unique accessors.
    207     Handle<FixedArray> array =
    208         isolate->factory()->NewFixedArray(max_number_of_properties);
    209 
    210     info = *data;
    211     while (info != nullptr) {
    212       // Accumulate accessors.
    213       if (!info->property_accessors()->IsUndefined(isolate)) {
    214         Handle<Object> props(info->property_accessors(), isolate);
    215         valid_descriptors =
    216             AccessorInfo::AppendUnique(props, array, valid_descriptors);
    217       }
    218       info = GetParent(info);
    219     }
    220 
    221     // Install accumulated accessors.
    222     for (int i = 0; i < valid_descriptors; i++) {
    223       Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
    224       JSObject::SetAccessor(obj, accessor).Assert();
    225     }
    226   }
    227 
    228   auto property_list = handle(data->property_list(), isolate);
    229   if (property_list->IsUndefined(isolate)) return obj;
    230   // TODO(dcarney): just use a FixedArray here.
    231   NeanderArray properties(property_list);
    232   if (properties.length() == 0) return obj;
    233 
    234   int i = 0;
    235   for (int c = 0; c < data->number_of_properties(); c++) {
    236     auto name = handle(Name::cast(properties.get(i++)), isolate);
    237     auto bit = handle(properties.get(i++), isolate);
    238     if (bit->IsSmi()) {
    239       PropertyDetails details(Smi::cast(*bit));
    240       PropertyAttributes attributes = details.attributes();
    241       PropertyKind kind = details.kind();
    242 
    243       if (kind == kData) {
    244         auto prop_data = handle(properties.get(i++), isolate);
    245         RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
    246                                                         prop_data, attributes),
    247                             JSObject);
    248       } else {
    249         auto getter = handle(properties.get(i++), isolate);
    250         auto setter = handle(properties.get(i++), isolate);
    251         RETURN_ON_EXCEPTION(
    252             isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
    253                                             attributes, is_hidden_prototype),
    254             JSObject);
    255       }
    256     } else {
    257       // Intrinsic data property --- Get appropriate value from the current
    258       // context.
    259       PropertyDetails details(Smi::cast(properties.get(i++)));
    260       PropertyAttributes attributes = details.attributes();
    261       DCHECK_EQ(kData, details.kind());
    262 
    263       v8::Intrinsic intrinsic =
    264           static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value());
    265       auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
    266 
    267       RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
    268                                                       prop_data, attributes),
    269                           JSObject);
    270     }
    271   }
    272   return obj;
    273 }
    274 
    275 void CacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number,
    276                                 Handle<JSObject> object) {
    277   auto cache = isolate->template_instantiations_cache();
    278   auto new_cache =
    279       UnseededNumberDictionary::AtNumberPut(cache, serial_number, object);
    280   isolate->native_context()->set_template_instantiations_cache(*new_cache);
    281 }
    282 
    283 void UncacheTemplateInstantiation(Isolate* isolate, uint32_t serial_number) {
    284   auto cache = isolate->template_instantiations_cache();
    285   int entry = cache->FindEntry(serial_number);
    286   DCHECK(entry != UnseededNumberDictionary::kNotFound);
    287   Handle<Object> result =
    288       UnseededNumberDictionary::DeleteProperty(cache, entry);
    289   USE(result);
    290   DCHECK(result->IsTrue(isolate));
    291   auto new_cache = UnseededNumberDictionary::Shrink(cache, entry);
    292   isolate->native_context()->set_template_instantiations_cache(*new_cache);
    293 }
    294 
    295 MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
    296                                         Handle<ObjectTemplateInfo> info,
    297                                         Handle<JSReceiver> new_target,
    298                                         bool is_hidden_prototype) {
    299   Handle<JSFunction> constructor;
    300   uint32_t serial_number =
    301       static_cast<uint32_t>(Smi::cast(info->serial_number())->value());
    302   if (!new_target.is_null()) {
    303     if (new_target->IsJSFunction() &&
    304         JSFunction::cast(*new_target)->shared()->function_data() ==
    305             info->constructor() &&
    306         JSFunction::cast(*new_target)->context()->native_context() ==
    307             isolate->context()->native_context()) {
    308       constructor = Handle<JSFunction>::cast(new_target);
    309     } else {
    310       // Disable caching for subclass instantiation.
    311       serial_number = 0;
    312     }
    313   }
    314   // Fast path.
    315   Handle<JSObject> result;
    316   if (serial_number) {
    317     // Probe cache.
    318     auto cache = isolate->template_instantiations_cache();
    319     int entry = cache->FindEntry(serial_number);
    320     if (entry != UnseededNumberDictionary::kNotFound) {
    321       Object* boilerplate = cache->ValueAt(entry);
    322       result = handle(JSObject::cast(boilerplate), isolate);
    323       return isolate->factory()->CopyJSObject(result);
    324     }
    325   }
    326   // Enter a new scope.  Recursion could otherwise create a lot of handles.
    327   HandleScope scope(isolate);
    328 
    329   if (constructor.is_null()) {
    330     Handle<Object> cons(info->constructor(), isolate);
    331     if (cons->IsUndefined(isolate)) {
    332       constructor = isolate->object_function();
    333     } else {
    334       auto cons_templ = Handle<FunctionTemplateInfo>::cast(cons);
    335       ASSIGN_RETURN_ON_EXCEPTION(isolate, constructor,
    336                                  InstantiateFunction(isolate, cons_templ),
    337                                  JSObject);
    338     }
    339 
    340     if (new_target.is_null()) new_target = constructor;
    341   }
    342 
    343   Handle<JSObject> object;
    344   ASSIGN_RETURN_ON_EXCEPTION(isolate, object,
    345                              JSObject::New(constructor, new_target), JSObject);
    346   ASSIGN_RETURN_ON_EXCEPTION(
    347       isolate, result,
    348       ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
    349   // TODO(dcarney): is this necessary?
    350   JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
    351 
    352   if (serial_number) {
    353     CacheTemplateInstantiation(isolate, serial_number, result);
    354     result = isolate->factory()->CopyJSObject(result);
    355   }
    356   return scope.CloseAndEscape(result);
    357 }
    358 
    359 
    360 MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
    361                                             Handle<FunctionTemplateInfo> data,
    362                                             Handle<Name> name) {
    363   uint32_t serial_number =
    364       static_cast<uint32_t>(Smi::cast(data->serial_number())->value());
    365   if (serial_number) {
    366     // Probe cache.
    367     auto cache = isolate->template_instantiations_cache();
    368     int entry = cache->FindEntry(serial_number);
    369     if (entry != UnseededNumberDictionary::kNotFound) {
    370       Object* element = cache->ValueAt(entry);
    371       return handle(JSFunction::cast(element), isolate);
    372     }
    373   }
    374   // Enter a new scope.  Recursion could otherwise create a lot of handles.
    375   HandleScope scope(isolate);
    376   Handle<JSObject> prototype;
    377   if (!data->remove_prototype()) {
    378     auto prototype_templ = handle(data->prototype_template(), isolate);
    379     if (prototype_templ->IsUndefined(isolate)) {
    380       prototype = isolate->factory()->NewJSObject(isolate->object_function());
    381     } else {
    382       ASSIGN_RETURN_ON_EXCEPTION(
    383           isolate, prototype,
    384           InstantiateObject(isolate,
    385                             Handle<ObjectTemplateInfo>::cast(prototype_templ),
    386                             Handle<JSReceiver>(), data->hidden_prototype()),
    387           JSFunction);
    388     }
    389     auto parent = handle(data->parent_template(), isolate);
    390     if (!parent->IsUndefined(isolate)) {
    391       Handle<JSFunction> parent_instance;
    392       ASSIGN_RETURN_ON_EXCEPTION(
    393           isolate, parent_instance,
    394           InstantiateFunction(isolate,
    395                               Handle<FunctionTemplateInfo>::cast(parent)),
    396           JSFunction);
    397       // TODO(dcarney): decide what to do here.
    398       Handle<Object> parent_prototype;
    399       ASSIGN_RETURN_ON_EXCEPTION(
    400           isolate, parent_prototype,
    401           JSObject::GetProperty(parent_instance,
    402                                 isolate->factory()->prototype_string()),
    403           JSFunction);
    404       MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false,
    405                                           Object::THROW_ON_ERROR),
    406                    MaybeHandle<JSFunction>());
    407     }
    408   }
    409   auto function = ApiNatives::CreateApiFunction(
    410       isolate, data, prototype, ApiNatives::JavaScriptObjectType);
    411   if (!name.is_null() && name->IsString()) {
    412     function->shared()->set_name(*name);
    413   }
    414   if (serial_number) {
    415     // Cache the function.
    416     CacheTemplateInstantiation(isolate, serial_number, function);
    417   }
    418   auto result =
    419       ConfigureInstance(isolate, function, data, data->hidden_prototype());
    420   if (result.is_null()) {
    421     // Uncache on error.
    422     if (serial_number) {
    423       UncacheTemplateInstantiation(isolate, serial_number);
    424     }
    425     return MaybeHandle<JSFunction>();
    426   }
    427   return scope.CloseAndEscape(function);
    428 }
    429 
    430 
    431 class InvokeScope {
    432  public:
    433   explicit InvokeScope(Isolate* isolate)
    434       : isolate_(isolate), save_context_(isolate) {}
    435   ~InvokeScope() {
    436     bool has_exception = isolate_->has_pending_exception();
    437     if (has_exception) {
    438       isolate_->ReportPendingMessages();
    439     } else {
    440       isolate_->clear_pending_message();
    441     }
    442   }
    443 
    444  private:
    445   Isolate* isolate_;
    446   SaveContext save_context_;
    447 };
    448 
    449 
    450 void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
    451                                int length, Handle<Object>* data) {
    452   auto list = handle(templ->property_list(), isolate);
    453   if (list->IsUndefined(isolate)) {
    454     list = NeanderArray(isolate).value();
    455     templ->set_property_list(*list);
    456   }
    457   templ->set_number_of_properties(templ->number_of_properties() + 1);
    458   NeanderArray array(list);
    459   for (int i = 0; i < length; i++) {
    460     Handle<Object> value =
    461         data[i].is_null()
    462             ? Handle<Object>::cast(isolate->factory()->undefined_value())
    463             : data[i];
    464     array.add(isolate, value);
    465   }
    466 }
    467 
    468 }  // namespace
    469 
    470 
    471 MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
    472     Handle<FunctionTemplateInfo> data) {
    473   Isolate* isolate = data->GetIsolate();
    474   InvokeScope invoke_scope(isolate);
    475   return ::v8::internal::InstantiateFunction(isolate, data);
    476 }
    477 
    478 MaybeHandle<JSObject> ApiNatives::InstantiateObject(
    479     Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) {
    480   Isolate* isolate = data->GetIsolate();
    481   InvokeScope invoke_scope(isolate);
    482   return ::v8::internal::InstantiateObject(isolate, data, new_target, false);
    483 }
    484 
    485 
    486 void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
    487                                  Handle<Name> name, Handle<Object> value,
    488                                  PropertyAttributes attributes) {
    489   const int kSize = 3;
    490   PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
    491   auto details_handle = handle(details.AsSmi(), isolate);
    492   Handle<Object> data[kSize] = {name, details_handle, value};
    493   AddPropertyToPropertyList(isolate, info, kSize, data);
    494 }
    495 
    496 
    497 void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
    498                                  Handle<Name> name, v8::Intrinsic intrinsic,
    499                                  PropertyAttributes attributes) {
    500   const int kSize = 4;
    501   auto value = handle(Smi::FromInt(intrinsic), isolate);
    502   auto intrinsic_marker = isolate->factory()->true_value();
    503   PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
    504   auto details_handle = handle(details.AsSmi(), isolate);
    505   Handle<Object> data[kSize] = {name, intrinsic_marker, details_handle, value};
    506   AddPropertyToPropertyList(isolate, info, kSize, data);
    507 }
    508 
    509 
    510 void ApiNatives::AddAccessorProperty(Isolate* isolate,
    511                                      Handle<TemplateInfo> info,
    512                                      Handle<Name> name,
    513                                      Handle<FunctionTemplateInfo> getter,
    514                                      Handle<FunctionTemplateInfo> setter,
    515                                      PropertyAttributes attributes) {
    516   const int kSize = 4;
    517   PropertyDetails details(attributes, ACCESSOR, 0, PropertyCellType::kNoCell);
    518   auto details_handle = handle(details.AsSmi(), isolate);
    519   Handle<Object> data[kSize] = {name, details_handle, getter, setter};
    520   AddPropertyToPropertyList(isolate, info, kSize, data);
    521 }
    522 
    523 
    524 void ApiNatives::AddNativeDataProperty(Isolate* isolate,
    525                                        Handle<TemplateInfo> info,
    526                                        Handle<AccessorInfo> property) {
    527   auto list = handle(info->property_accessors(), isolate);
    528   if (list->IsUndefined(isolate)) {
    529     list = NeanderArray(isolate).value();
    530     info->set_property_accessors(*list);
    531   }
    532   NeanderArray array(list);
    533   array.add(isolate, property);
    534 }
    535 
    536 
    537 Handle<JSFunction> ApiNatives::CreateApiFunction(
    538     Isolate* isolate, Handle<FunctionTemplateInfo> obj,
    539     Handle<Object> prototype, ApiInstanceType instance_type) {
    540   Handle<SharedFunctionInfo> shared =
    541       FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
    542   Handle<JSFunction> result =
    543       isolate->factory()->NewFunctionFromSharedFunctionInfo(
    544           shared, isolate->native_context());
    545 
    546   if (obj->remove_prototype()) {
    547     result->set_map(*isolate->sloppy_function_without_prototype_map());
    548     DCHECK(prototype.is_null());
    549     DCHECK(result->shared()->IsApiFunction());
    550     DCHECK(!result->has_initial_map());
    551     DCHECK(!result->has_prototype());
    552     DCHECK(!result->IsConstructor());
    553     return result;
    554   }
    555 
    556   // Down from here is only valid for API functions that can be used as a
    557   // constructor (don't set the "remove prototype" flag).
    558 
    559   if (obj->read_only_prototype()) {
    560     result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
    561   }
    562 
    563   if (prototype->IsTheHole(isolate)) {
    564     prototype = isolate->factory()->NewFunctionPrototype(result);
    565   } else {
    566     JSObject::AddProperty(Handle<JSObject>::cast(prototype),
    567                           isolate->factory()->constructor_string(), result,
    568                           DONT_ENUM);
    569   }
    570 
    571   int internal_field_count = 0;
    572   if (!obj->instance_template()->IsUndefined(isolate)) {
    573     Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
    574         ObjectTemplateInfo::cast(obj->instance_template()));
    575     internal_field_count =
    576         Smi::cast(instance_template->internal_field_count())->value();
    577   }
    578 
    579   // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
    580   // JSObject::GetHeaderSize.
    581   int instance_size = kPointerSize * internal_field_count;
    582   InstanceType type;
    583   switch (instance_type) {
    584     case JavaScriptObjectType:
    585       if (!obj->needs_access_check() &&
    586           obj->named_property_handler()->IsUndefined(isolate) &&
    587           obj->indexed_property_handler()->IsUndefined(isolate)) {
    588         type = JS_API_OBJECT_TYPE;
    589       } else {
    590         type = JS_SPECIAL_API_OBJECT_TYPE;
    591       }
    592       instance_size += JSObject::kHeaderSize;
    593       break;
    594     case GlobalObjectType:
    595       type = JS_GLOBAL_OBJECT_TYPE;
    596       instance_size += JSGlobalObject::kSize;
    597       break;
    598     case GlobalProxyType:
    599       type = JS_GLOBAL_PROXY_TYPE;
    600       instance_size += JSGlobalProxy::kSize;
    601       break;
    602     default:
    603       UNREACHABLE();
    604       type = JS_OBJECT_TYPE;  // Keep the compiler happy.
    605       break;
    606   }
    607 
    608   Handle<Map> map =
    609       isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
    610   JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
    611 
    612   // Mark as undetectable if needed.
    613   if (obj->undetectable()) {
    614     map->set_is_undetectable();
    615   }
    616 
    617   // Mark as needs_access_check if needed.
    618   if (obj->needs_access_check()) {
    619     map->set_is_access_check_needed(true);
    620   }
    621 
    622   // Set interceptor information in the map.
    623   if (!obj->named_property_handler()->IsUndefined(isolate)) {
    624     map->set_has_named_interceptor();
    625   }
    626   if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
    627     map->set_has_indexed_interceptor();
    628   }
    629 
    630   // Mark instance as callable in the map.
    631   if (!obj->instance_call_handler()->IsUndefined(isolate)) {
    632     map->set_is_callable();
    633     map->set_is_constructor(true);
    634   }
    635 
    636   return result;
    637 }
    638 
    639 }  // namespace internal
    640 }  // namespace v8
    641