// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/api-natives.h"

#include "src/api.h"
#include "src/isolate-inl.h"
#include "src/lookup.h"
#include "src/messages.h"

namespace v8 {
namespace internal {


namespace {

class InvokeScope {
 public:
  explicit InvokeScope(Isolate* isolate)
      : isolate_(isolate), save_context_(isolate) {}
  ~InvokeScope() {
    bool has_exception = isolate_->has_pending_exception();
    if (has_exception) {
      isolate_->ReportPendingMessages();
    } else {
      isolate_->clear_pending_message();
    }
  }

 private:
  Isolate* isolate_;
  SaveContext save_context_;
};

MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
                                        Handle<ObjectTemplateInfo> data,
                                        Handle<JSReceiver> new_target,
                                        bool is_hidden_prototype,
                                        bool is_prototype);

MaybeHandle<JSFunction> InstantiateFunction(
    Isolate* isolate, Handle<FunctionTemplateInfo> data,
    MaybeHandle<Name> maybe_name = MaybeHandle<Name>());

MaybeHandle<Object> Instantiate(
    Isolate* isolate, Handle<Object> data,
    MaybeHandle<Name> maybe_name = MaybeHandle<Name>()) {
  if (data->IsFunctionTemplateInfo()) {
    return InstantiateFunction(
        isolate, Handle<FunctionTemplateInfo>::cast(data), maybe_name);
  } else if (data->IsObjectTemplateInfo()) {
    return InstantiateObject(isolate, Handle<ObjectTemplateInfo>::cast(data),
                             Handle<JSReceiver>(), false, false);
  } else {
    return data;
  }
}

MaybeHandle<Object> DefineAccessorProperty(
    Isolate* isolate, Handle<JSObject> object, Handle<Name> name,
    Handle<Object> getter, Handle<Object> setter, PropertyAttributes attributes,
    bool force_instantiate) {
  DCHECK(!getter->IsFunctionTemplateInfo() ||
         !FunctionTemplateInfo::cast(*getter)->do_not_cache());
  DCHECK(!setter->IsFunctionTemplateInfo() ||
         !FunctionTemplateInfo::cast(*setter)->do_not_cache());
  if (force_instantiate) {
    if (getter->IsFunctionTemplateInfo()) {
      ASSIGN_RETURN_ON_EXCEPTION(
          isolate, getter,
          InstantiateFunction(isolate,
                              Handle<FunctionTemplateInfo>::cast(getter)),
          Object);
    }
    if (setter->IsFunctionTemplateInfo()) {
      ASSIGN_RETURN_ON_EXCEPTION(
          isolate, setter,
          InstantiateFunction(isolate,
                              Handle<FunctionTemplateInfo>::cast(setter)),
          Object);
    }
  }
  RETURN_ON_EXCEPTION(isolate, JSObject::DefineAccessor(object, name, getter,
                                                        setter, attributes),
                      Object);
  return object;
}


MaybeHandle<Object> DefineDataProperty(Isolate* isolate,
                                       Handle<JSObject> object,
                                       Handle<Name> name,
                                       Handle<Object> prop_data,
                                       PropertyAttributes attributes) {
  Handle<Object> value;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, value,
                             Instantiate(isolate, prop_data, name), Object);

  LookupIterator it = LookupIterator::PropertyOrElement(
      isolate, object, name, LookupIterator::OWN_SKIP_INTERCEPTOR);

#ifdef DEBUG
  Maybe<PropertyAttributes> maybe = JSReceiver::GetPropertyAttributes(&it);
  DCHECK(maybe.IsJust());
  if (it.IsFound()) {
    THROW_NEW_ERROR(
        isolate,
        NewTypeError(MessageTemplate::kDuplicateTemplateProperty, name),
        Object);
  }
#endif

  MAYBE_RETURN_NULL(
      Object::AddDataProperty(&it, value, attributes, kThrowOnError,
                              Object::CERTAINLY_NOT_STORE_FROM_KEYED));
  return value;
}


void DisableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
  Handle<Map> old_map(object->map());
  // Copy map so it won't interfere constructor's initial map.
  Handle<Map> new_map = Map::Copy(old_map, "DisableAccessChecks");
  new_map->set_is_access_check_needed(false);
  JSObject::MigrateToMap(Handle<JSObject>::cast(object), new_map);
}


void EnableAccessChecks(Isolate* isolate, Handle<JSObject> object) {
  Handle<Map> old_map(object->map());
  // Copy map so it won't interfere constructor's initial map.
  Handle<Map> new_map = Map::Copy(old_map, "EnableAccessChecks");
  new_map->set_is_access_check_needed(true);
  new_map->set_may_have_interesting_symbols(true);
  JSObject::MigrateToMap(object, new_map);
}


class AccessCheckDisableScope {
 public:
  AccessCheckDisableScope(Isolate* isolate, Handle<JSObject> obj)
      : isolate_(isolate),
        disabled_(obj->map()->is_access_check_needed()),
        obj_(obj) {
    if (disabled_) {
      DisableAccessChecks(isolate_, obj_);
    }
  }
  ~AccessCheckDisableScope() {
    if (disabled_) {
      EnableAccessChecks(isolate_, obj_);
    }
  }

 private:
  Isolate* isolate_;
  const bool disabled_;
  Handle<JSObject> obj_;
};


Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
  Handle<Context> native_context = isolate->native_context();
  DCHECK(!native_context.is_null());
  switch (intrinsic) {
#define GET_INTRINSIC_VALUE(name, iname) \
  case v8::k##name:                      \
    return native_context->iname();
    V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
#undef GET_INTRINSIC_VALUE
  }
  return nullptr;
}


template <typename TemplateInfoT>
MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
                                        Handle<TemplateInfoT> data,
                                        bool is_hidden_prototype) {
  HandleScope scope(isolate);
  // Disable access checks while instantiating the object.
  AccessCheckDisableScope access_check_scope(isolate, obj);

  // Walk the inheritance chain and copy all accessors to current object.
  int max_number_of_properties = 0;
  TemplateInfoT* info = *data;
  while (info != nullptr) {
    Object* props = info->property_accessors();
    if (!props->IsUndefined(isolate)) {
      max_number_of_properties += TemplateList::cast(props)->length();
    }
    info = info->GetParent(isolate);
  }

  if (max_number_of_properties > 0) {
    int valid_descriptors = 0;
    // Use a temporary FixedArray to accumulate unique accessors.
    Handle<FixedArray> array =
        isolate->factory()->NewFixedArray(max_number_of_properties);

    for (Handle<TemplateInfoT> temp(*data); *temp != nullptr;
         temp = handle(temp->GetParent(isolate), isolate)) {
      // Accumulate accessors.
      Object* maybe_properties = temp->property_accessors();
      if (!maybe_properties->IsUndefined(isolate)) {
        valid_descriptors = AccessorInfo::AppendUnique(
            handle(maybe_properties, isolate), array, valid_descriptors);
      }
    }

    // Install accumulated accessors.
    for (int i = 0; i < valid_descriptors; i++) {
      Handle<AccessorInfo> accessor(AccessorInfo::cast(array->get(i)));
      Handle<Name> name(Name::cast(accessor->name()), isolate);
      JSObject::SetAccessor(obj, name, accessor,
                            accessor->initial_property_attributes())
          .Assert();
    }
  }

  Object* maybe_property_list = data->property_list();
  if (maybe_property_list->IsUndefined(isolate)) return obj;
  Handle<TemplateList> properties(TemplateList::cast(maybe_property_list),
                                  isolate);
  if (properties->length() == 0) return obj;

  int i = 0;
  for (int c = 0; c < data->number_of_properties(); c++) {
    auto name = handle(Name::cast(properties->get(i++)), isolate);
    Object* bit = properties->get(i++);
    if (bit->IsSmi()) {
      PropertyDetails details(Smi::cast(bit));
      PropertyAttributes attributes = details.attributes();
      PropertyKind kind = details.kind();

      if (kind == kData) {
        auto prop_data = handle(properties->get(i++), isolate);
        RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
                                                        prop_data, attributes),
                            JSObject);
      } else {
        auto getter = handle(properties->get(i++), isolate);
        auto setter = handle(properties->get(i++), isolate);
        RETURN_ON_EXCEPTION(
            isolate, DefineAccessorProperty(isolate, obj, name, getter, setter,
                                            attributes, is_hidden_prototype),
            JSObject);
      }
    } else {
      // Intrinsic data property --- Get appropriate value from the current
      // context.
      PropertyDetails details(Smi::cast(properties->get(i++)));
      PropertyAttributes attributes = details.attributes();
      DCHECK_EQ(kData, details.kind());

      v8::Intrinsic intrinsic =
          static_cast<v8::Intrinsic>(Smi::ToInt(properties->get(i++)));
      auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);

      RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
                                                      prop_data, attributes),
                          JSObject);
    }
  }
  return obj;
}

// Whether or not to cache every instance: when we materialize a getter or
// setter from an lazy AccessorPair, we rely on this cache to be able to always
// return the same getter or setter. However, objects will be cloned anyways,
// so it's not observable if we didn't cache an instance. Furthermore, a badly
// behaved embedder might create an unlimited number of objects, so we limit
// the cache for those cases.
enum class CachingMode { kLimited, kUnlimited };

MaybeHandle<JSObject> ProbeInstantiationsCache(Isolate* isolate,
                                               int serial_number,
                                               CachingMode caching_mode) {
  DCHECK_LE(1, serial_number);
  if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
    Handle<FixedArray> fast_cache =
        isolate->fast_template_instantiations_cache();
    return fast_cache->GetValue<JSObject>(isolate, serial_number - 1);
  } else if (caching_mode == CachingMode::kUnlimited ||
             (serial_number <=
              TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
    Handle<NumberDictionary> slow_cache =
        isolate->slow_template_instantiations_cache();
    int entry = slow_cache->FindEntry(serial_number);
    if (entry == NumberDictionary::kNotFound) {
      return MaybeHandle<JSObject>();
    }
    return handle(JSObject::cast(slow_cache->ValueAt(entry)), isolate);
  } else {
    return MaybeHandle<JSObject>();
  }
}

void CacheTemplateInstantiation(Isolate* isolate, int serial_number,
                                CachingMode caching_mode,
                                Handle<JSObject> object) {
  DCHECK_LE(1, serial_number);
  if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
    Handle<FixedArray> fast_cache =
        isolate->fast_template_instantiations_cache();
    Handle<FixedArray> new_cache =
        FixedArray::SetAndGrow(fast_cache, serial_number - 1, object);
    if (*new_cache != *fast_cache) {
      isolate->native_context()->set_fast_template_instantiations_cache(
          *new_cache);
    }
  } else if (caching_mode == CachingMode::kUnlimited ||
             (serial_number <=
              TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
    Handle<NumberDictionary> cache =
        isolate->slow_template_instantiations_cache();
    auto new_cache = NumberDictionary::Set(cache, serial_number, object);
    if (*new_cache != *cache) {
      isolate->native_context()->set_slow_template_instantiations_cache(
          *new_cache);
    }
  }
}

void UncacheTemplateInstantiation(Isolate* isolate, int serial_number,
                                  CachingMode caching_mode) {
  DCHECK_LE(1, serial_number);
  if (serial_number <= TemplateInfo::kFastTemplateInstantiationsCacheSize) {
    Handle<FixedArray> fast_cache =
        isolate->fast_template_instantiations_cache();
    DCHECK(!fast_cache->get(serial_number - 1)->IsUndefined(isolate));
    fast_cache->set_undefined(serial_number - 1);
  } else if (caching_mode == CachingMode::kUnlimited ||
             (serial_number <=
              TemplateInfo::kSlowTemplateInstantiationsCacheSize)) {
    Handle<NumberDictionary> cache =
        isolate->slow_template_instantiations_cache();
    int entry = cache->FindEntry(serial_number);
    DCHECK_NE(NumberDictionary::kNotFound, entry);
    cache = NumberDictionary::DeleteEntry(cache, entry);
    isolate->native_context()->set_slow_template_instantiations_cache(*cache);
  }
}

bool IsSimpleInstantiation(Isolate* isolate, ObjectTemplateInfo* info,
                           JSReceiver* new_target) {
  DisallowHeapAllocation no_gc;

  if (!new_target->IsJSFunction()) return false;
  JSFunction* fun = JSFunction::cast(new_target);
  if (fun->shared()->function_data() != info->constructor()) return false;
  if (info->immutable_proto()) return false;
  return fun->context()->native_context() == isolate->raw_native_context();
}

MaybeHandle<JSObject> InstantiateObject(Isolate* isolate,
                                        Handle<ObjectTemplateInfo> info,
                                        Handle<JSReceiver> new_target,
                                        bool is_hidden_prototype,
                                        bool is_prototype) {
  Handle<JSFunction> constructor;
  int serial_number = Smi::ToInt(info->serial_number());
  if (!new_target.is_null()) {
    if (IsSimpleInstantiation(isolate, *info, *new_target)) {
      constructor = Handle<JSFunction>::cast(new_target);
    } else {
      // Disable caching for subclass instantiation.
      serial_number = 0;
    }
  }
  // Fast path.
  Handle<JSObject> result;
  if (serial_number) {
    if (ProbeInstantiationsCache(isolate, serial_number, CachingMode::kLimited)
            .ToHandle(&result)) {
      return isolate->factory()->CopyJSObject(result);
    }
  }

  if (constructor.is_null()) {
    Object* maybe_constructor_info = info->constructor();
    if (maybe_constructor_info->IsUndefined(isolate)) {
      constructor = isolate->object_function();
    } else {
      // Enter a new scope.  Recursion could otherwise create a lot of handles.
      HandleScope scope(isolate);
      Handle<FunctionTemplateInfo> cons_templ(
          FunctionTemplateInfo::cast(maybe_constructor_info), isolate);
      Handle<JSFunction> tmp_constructor;
      ASSIGN_RETURN_ON_EXCEPTION(isolate, tmp_constructor,
                                 InstantiateFunction(isolate, cons_templ),
                                 JSObject);
      constructor = scope.CloseAndEscape(tmp_constructor);
    }

    if (new_target.is_null()) new_target = constructor;
  }

  Handle<JSObject> object;
  ASSIGN_RETURN_ON_EXCEPTION(isolate, object,
                             JSObject::New(constructor, new_target), JSObject);

  if (is_prototype) JSObject::OptimizeAsPrototype(object);

  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, result,
      ConfigureInstance(isolate, object, info, is_hidden_prototype), JSObject);
  if (info->immutable_proto()) {
    JSObject::SetImmutableProto(object);
  }
  if (!is_prototype) {
    // Keep prototypes in slow-mode. Let them be lazily turned fast later on.
    // TODO(dcarney): is this necessary?
    JSObject::MigrateSlowToFast(result, 0, "ApiNatives::InstantiateObject");
    // Don't cache prototypes.
    if (serial_number) {
      CacheTemplateInstantiation(isolate, serial_number, CachingMode::kLimited,
                                 result);
      result = isolate->factory()->CopyJSObject(result);
    }
  }

  return result;
}

namespace {
MaybeHandle<Object> GetInstancePrototype(Isolate* isolate,
                                         Object* function_template) {
  // Enter a new scope.  Recursion could otherwise create a lot of handles.
  HandleScope scope(isolate);
  Handle<JSFunction> parent_instance;
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, parent_instance,
      InstantiateFunction(
          isolate,
          handle(FunctionTemplateInfo::cast(function_template), isolate)),
      JSFunction);
  Handle<Object> instance_prototype;
  // TODO(cbruni): decide what to do here.
  ASSIGN_RETURN_ON_EXCEPTION(
      isolate, instance_prototype,
      JSObject::GetProperty(parent_instance,
                            isolate->factory()->prototype_string()),
      JSFunction);
  return scope.CloseAndEscape(instance_prototype);
}
}  // namespace

MaybeHandle<JSFunction> InstantiateFunction(Isolate* isolate,
                                            Handle<FunctionTemplateInfo> data,
                                            MaybeHandle<Name> maybe_name) {
  int serial_number = Smi::ToInt(data->serial_number());
  if (serial_number) {
    Handle<JSObject> result;
    if (ProbeInstantiationsCache(isolate, serial_number,
                                 CachingMode::kUnlimited)
            .ToHandle(&result)) {
      return Handle<JSFunction>::cast(result);
    }
  }
  Handle<Object> prototype;
  if (!data->remove_prototype()) {
    Object* prototype_templ = data->prototype_template();
    if (prototype_templ->IsUndefined(isolate)) {
      Object* protoype_provider_templ = data->prototype_provider_template();
      if (protoype_provider_templ->IsUndefined(isolate)) {
        prototype = isolate->factory()->NewJSObject(isolate->object_function());
      } else {
        ASSIGN_RETURN_ON_EXCEPTION(
            isolate, prototype,
            GetInstancePrototype(isolate, protoype_provider_templ), JSFunction);
      }
    } else {
      ASSIGN_RETURN_ON_EXCEPTION(
          isolate, prototype,
          InstantiateObject(
              isolate,
              handle(ObjectTemplateInfo::cast(prototype_templ), isolate),
              Handle<JSReceiver>(), data->hidden_prototype(), true),
          JSFunction);
    }
    Object* parent = data->parent_template();
    if (!parent->IsUndefined(isolate)) {
      Handle<Object> parent_prototype;
      ASSIGN_RETURN_ON_EXCEPTION(isolate, parent_prototype,
                                 GetInstancePrototype(isolate, parent),
                                 JSFunction);
      JSObject::ForceSetPrototype(Handle<JSObject>::cast(prototype),
                                  parent_prototype);
    }
  }
  Handle<JSFunction> function = ApiNatives::CreateApiFunction(
      isolate, data, prototype, ApiNatives::JavaScriptObjectType, maybe_name);
  if (serial_number) {
    // Cache the function.
    CacheTemplateInstantiation(isolate, serial_number, CachingMode::kUnlimited,
                               function);
  }
  MaybeHandle<JSObject> result =
      ConfigureInstance(isolate, function, data, data->hidden_prototype());
  if (result.is_null()) {
    // Uncache on error.
    if (serial_number) {
      UncacheTemplateInstantiation(isolate, serial_number,
                                   CachingMode::kUnlimited);
    }
    return MaybeHandle<JSFunction>();
  }
  return function;
}


void AddPropertyToPropertyList(Isolate* isolate, Handle<TemplateInfo> templ,
                               int length, Handle<Object>* data) {
  Object* maybe_list = templ->property_list();
  Handle<TemplateList> list;
  if (maybe_list->IsUndefined(isolate)) {
    list = TemplateList::New(isolate, length);
  } else {
    list = handle(TemplateList::cast(maybe_list), isolate);
  }
  templ->set_number_of_properties(templ->number_of_properties() + 1);
  for (int i = 0; i < length; i++) {
    Handle<Object> value =
        data[i].is_null()
            ? Handle<Object>::cast(isolate->factory()->undefined_value())
            : data[i];
    list = TemplateList::Add(isolate, list, value);
  }
  templ->set_property_list(*list);
}

}  // namespace

MaybeHandle<JSFunction> ApiNatives::InstantiateFunction(
    Handle<FunctionTemplateInfo> data, MaybeHandle<Name> maybe_name) {
  Isolate* isolate = data->GetIsolate();
  InvokeScope invoke_scope(isolate);
  return ::v8::internal::InstantiateFunction(isolate, data, maybe_name);
}

MaybeHandle<JSObject> ApiNatives::InstantiateObject(
    Handle<ObjectTemplateInfo> data, Handle<JSReceiver> new_target) {
  Isolate* isolate = data->GetIsolate();
  InvokeScope invoke_scope(isolate);
  return ::v8::internal::InstantiateObject(isolate, data, new_target, false,
                                           false);
}

MaybeHandle<JSObject> ApiNatives::InstantiateRemoteObject(
    Handle<ObjectTemplateInfo> data) {
  Isolate* isolate = data->GetIsolate();
  InvokeScope invoke_scope(isolate);

  Handle<FunctionTemplateInfo> constructor(
      FunctionTemplateInfo::cast(data->constructor()));
  Handle<Map> object_map = isolate->factory()->NewMap(
      JS_SPECIAL_API_OBJECT_TYPE,
      JSObject::kHeaderSize + data->embedder_field_count() * kPointerSize,
      TERMINAL_FAST_ELEMENTS_KIND);
  object_map->SetConstructor(*constructor);
  object_map->set_is_access_check_needed(true);
  object_map->set_may_have_interesting_symbols(true);

  Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(object_map);
  JSObject::ForceSetPrototype(object, isolate->factory()->null_value());

  return object;
}

void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
                                 Handle<Name> name, Handle<Object> value,
                                 PropertyAttributes attributes) {
  PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
  auto details_handle = handle(details.AsSmi(), isolate);
  Handle<Object> data[] = {name, details_handle, value};
  AddPropertyToPropertyList(isolate, info, arraysize(data), data);
}


void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
                                 Handle<Name> name, v8::Intrinsic intrinsic,
                                 PropertyAttributes attributes) {
  auto value = handle(Smi::FromInt(intrinsic), isolate);
  auto intrinsic_marker = isolate->factory()->true_value();
  PropertyDetails details(kData, attributes, PropertyCellType::kNoCell);
  auto details_handle = handle(details.AsSmi(), isolate);
  Handle<Object> data[] = {name, intrinsic_marker, details_handle, value};
  AddPropertyToPropertyList(isolate, info, arraysize(data), data);
}


void ApiNatives::AddAccessorProperty(Isolate* isolate,
                                     Handle<TemplateInfo> info,
                                     Handle<Name> name,
                                     Handle<FunctionTemplateInfo> getter,
                                     Handle<FunctionTemplateInfo> setter,
                                     PropertyAttributes attributes) {
  PropertyDetails details(kAccessor, attributes, PropertyCellType::kNoCell);
  auto details_handle = handle(details.AsSmi(), isolate);
  Handle<Object> data[] = {name, details_handle, getter, setter};
  AddPropertyToPropertyList(isolate, info, arraysize(data), data);
}


void ApiNatives::AddNativeDataProperty(Isolate* isolate,
                                       Handle<TemplateInfo> info,
                                       Handle<AccessorInfo> property) {
  Object* maybe_list = info->property_accessors();
  Handle<TemplateList> list;
  if (maybe_list->IsUndefined(isolate)) {
    list = TemplateList::New(isolate, 1);
  } else {
    list = handle(TemplateList::cast(maybe_list), isolate);
  }
  list = TemplateList::Add(isolate, list, property);
  info->set_property_accessors(*list);
}

Handle<JSFunction> ApiNatives::CreateApiFunction(
    Isolate* isolate, Handle<FunctionTemplateInfo> obj,
    Handle<Object> prototype, ApiInstanceType instance_type,
    MaybeHandle<Name> maybe_name) {
  Handle<SharedFunctionInfo> shared =
      FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj,
                                                          maybe_name);
  // To simplify things, API functions always have shared name.
  DCHECK(shared->has_shared_name());

  Handle<JSFunction> result =
      isolate->factory()->NewFunctionFromSharedFunctionInfo(
          shared, isolate->native_context());

  if (obj->remove_prototype()) {
    DCHECK(prototype.is_null());
    DCHECK(result->shared()->IsApiFunction());
    DCHECK(!result->IsConstructor());
    DCHECK(!result->has_prototype_slot());
    return result;
  }

  // Down from here is only valid for API functions that can be used as a
  // constructor (don't set the "remove prototype" flag).
  DCHECK(result->has_prototype_slot());

  if (obj->read_only_prototype()) {
    result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
  }

  if (prototype->IsTheHole(isolate)) {
    prototype = isolate->factory()->NewFunctionPrototype(result);
  } else if (obj->prototype_provider_template()->IsUndefined(isolate)) {
    JSObject::AddProperty(Handle<JSObject>::cast(prototype),
                          isolate->factory()->constructor_string(), result,
                          DONT_ENUM);
  }

  int embedder_field_count = 0;
  bool immutable_proto = false;
  if (!obj->instance_template()->IsUndefined(isolate)) {
    Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
        ObjectTemplateInfo::cast(obj->instance_template()));
    embedder_field_count = instance_template->embedder_field_count();
    immutable_proto = instance_template->immutable_proto();
  }

  // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
  // JSObject::GetHeaderSize.
  int instance_size = kPointerSize * embedder_field_count;
  InstanceType type;
  switch (instance_type) {
    case JavaScriptObjectType:
      if (!obj->needs_access_check() &&
          obj->named_property_handler()->IsUndefined(isolate) &&
          obj->indexed_property_handler()->IsUndefined(isolate)) {
        type = JS_API_OBJECT_TYPE;
      } else {
        type = JS_SPECIAL_API_OBJECT_TYPE;
      }
      instance_size += JSObject::kHeaderSize;
      break;
    case GlobalObjectType:
      type = JS_GLOBAL_OBJECT_TYPE;
      instance_size += JSGlobalObject::kSize;
      break;
    case GlobalProxyType:
      type = JS_GLOBAL_PROXY_TYPE;
      instance_size += JSGlobalProxy::kSize;
      break;
    default:
      UNREACHABLE();
      break;
  }

  Handle<Map> map = isolate->factory()->NewMap(type, instance_size,
                                               TERMINAL_FAST_ELEMENTS_KIND);
  JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));

  // Mark as undetectable if needed.
  if (obj->undetectable()) {
    // We only allow callable undetectable receivers here, since this whole
    // undetectable business is only to support document.all, which is both
    // undetectable and callable. If we ever see the need to have an object
    // that is undetectable but not callable, we need to update the types.h
    // to allow encoding this.
    CHECK(!obj->instance_call_handler()->IsUndefined(isolate));
    map->set_is_undetectable(true);
  }

  // Mark as needs_access_check if needed.
  if (obj->needs_access_check()) {
    map->set_is_access_check_needed(true);
    map->set_may_have_interesting_symbols(true);
  }

  // Set interceptor information in the map.
  if (!obj->named_property_handler()->IsUndefined(isolate)) {
    map->set_has_named_interceptor(true);
    map->set_may_have_interesting_symbols(true);
  }
  if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
    map->set_has_indexed_interceptor(true);
  }

  // Mark instance as callable in the map.
  if (!obj->instance_call_handler()->IsUndefined(isolate)) {
    map->set_is_callable(true);
    map->set_is_constructor(true);
  }

  if (immutable_proto) map->set_is_immutable_proto(true);

  return result;
}

}  // namespace internal
}  // namespace v8
