• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
Instantiate(Isolate * isolate,Handle<Object> data,Handle<Name> name=Handle<Name> ())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 
DefineAccessorProperty(Isolate * isolate,Handle<JSObject> object,Handle<Name> name,Handle<Object> getter,Handle<Object> setter,PropertyAttributes attributes,bool force_instantiate)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 
DefineDataProperty(Isolate * isolate,Handle<JSObject> object,Handle<Name> name,Handle<Object> prop_data,PropertyAttributes attributes)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 
DisableAccessChecks(Isolate * isolate,Handle<JSObject> object)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 
EnableAccessChecks(Isolate * isolate,Handle<JSObject> object)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:
AccessCheckDisableScope(Isolate * isolate,Handle<JSObject> obj)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   }
~AccessCheckDisableScope()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 
GetIntrinsic(Isolate * isolate,v8::Intrinsic intrinsic)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.
GetParent(FunctionTemplateInfo * data)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.
GetParent(ObjectTemplateInfo * data)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>
ConfigureInstance(Isolate * isolate,Handle<JSObject> obj,Handle<TemplateInfoT> data,bool is_hidden_prototype)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 
CacheTemplateInstantiation(Isolate * isolate,uint32_t serial_number,Handle<JSObject> object)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 
UncacheTemplateInstantiation(Isolate * isolate,uint32_t serial_number)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 
InstantiateObject(Isolate * isolate,Handle<ObjectTemplateInfo> info,Handle<JSReceiver> new_target,bool is_hidden_prototype)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 
InstantiateFunction(Isolate * isolate,Handle<FunctionTemplateInfo> data,Handle<Name> name)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:
InvokeScope(Isolate * isolate)433   explicit InvokeScope(Isolate* isolate)
434       : isolate_(isolate), save_context_(isolate) {}
~InvokeScope()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 
AddPropertyToPropertyList(Isolate * isolate,Handle<TemplateInfo> templ,int length,Handle<Object> * data)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 
InstantiateFunction(Handle<FunctionTemplateInfo> data)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 
InstantiateObject(Handle<ObjectTemplateInfo> data,Handle<JSReceiver> new_target)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 
AddDataProperty(Isolate * isolate,Handle<TemplateInfo> info,Handle<Name> name,Handle<Object> value,PropertyAttributes attributes)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 
AddDataProperty(Isolate * isolate,Handle<TemplateInfo> info,Handle<Name> name,v8::Intrinsic intrinsic,PropertyAttributes attributes)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 
AddAccessorProperty(Isolate * isolate,Handle<TemplateInfo> info,Handle<Name> name,Handle<FunctionTemplateInfo> getter,Handle<FunctionTemplateInfo> setter,PropertyAttributes attributes)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 
AddNativeDataProperty(Isolate * isolate,Handle<TemplateInfo> info,Handle<AccessorInfo> property)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 
CreateApiFunction(Isolate * isolate,Handle<FunctionTemplateInfo> obj,Handle<Object> prototype,ApiInstanceType instance_type)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