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