Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Side by Side Diff: src/api-natives.cc

Issue 2095953002: Refactor CreateApiFunction (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Create the template instantiation cache early enough Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/api-natives.h ('k') | src/bootstrapper.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/api-natives.h" 5 #include "src/api-natives.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/isolate-inl.h" 8 #include "src/isolate-inl.h"
9 #include "src/lookup.h" 9 #include "src/lookup.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 353 matching lines...) Expand 10 before | Expand all | Expand 10 after
364 static_cast<uint32_t>(Smi::cast(data->serial_number())->value()); 364 static_cast<uint32_t>(Smi::cast(data->serial_number())->value());
365 if (serial_number) { 365 if (serial_number) {
366 // Probe cache. 366 // Probe cache.
367 auto cache = isolate->template_instantiations_cache(); 367 auto cache = isolate->template_instantiations_cache();
368 int entry = cache->FindEntry(serial_number); 368 int entry = cache->FindEntry(serial_number);
369 if (entry != UnseededNumberDictionary::kNotFound) { 369 if (entry != UnseededNumberDictionary::kNotFound) {
370 Object* element = cache->ValueAt(entry); 370 Object* element = cache->ValueAt(entry);
371 return handle(JSFunction::cast(element), isolate); 371 return handle(JSFunction::cast(element), isolate);
372 } 372 }
373 } 373 }
374
374 // Enter a new scope. Recursion could otherwise create a lot of handles. 375 // Enter a new scope. Recursion could otherwise create a lot of handles.
375 HandleScope scope(isolate); 376 HandleScope scope(isolate);
376 Handle<JSObject> prototype; 377
377 if (!data->remove_prototype()) { 378 auto function =
378 auto prototype_templ = handle(data->prototype_template(), isolate); 379 ApiNatives::CreateApiFunction(isolate, data, JS_API_OBJECT_TYPE);
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()) { 380 if (!name.is_null() && name->IsString()) {
412 function->shared()->set_name(*name); 381 function->shared()->set_name(*name);
413 } 382 }
414 if (serial_number) { 383 if (serial_number) {
415 // Cache the function. 384 // Cache the function.
416 CacheTemplateInstantiation(isolate, serial_number, function); 385 CacheTemplateInstantiation(isolate, serial_number, function);
417 } 386 }
418 auto result = 387 auto result =
419 ConfigureInstance(isolate, function, data, data->hidden_prototype()); 388 ConfigureInstance(isolate, function, data, data->hidden_prototype());
420 if (result.is_null()) { 389 if (result.is_null()) {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
526 Handle<AccessorInfo> property) { 495 Handle<AccessorInfo> property) {
527 auto list = handle(info->property_accessors(), isolate); 496 auto list = handle(info->property_accessors(), isolate);
528 if (list->IsUndefined(isolate)) { 497 if (list->IsUndefined(isolate)) {
529 list = NeanderArray(isolate).value(); 498 list = NeanderArray(isolate).value();
530 info->set_property_accessors(*list); 499 info->set_property_accessors(*list);
531 } 500 }
532 NeanderArray array(list); 501 NeanderArray array(list);
533 array.add(isolate, property); 502 array.add(isolate, property);
534 } 503 }
535 504
536
537 Handle<JSFunction> ApiNatives::CreateApiFunction( 505 Handle<JSFunction> ApiNatives::CreateApiFunction(
538 Isolate* isolate, Handle<FunctionTemplateInfo> obj, 506 Isolate* isolate, Handle<FunctionTemplateInfo> obj, InstanceType type) {
539 Handle<Object> prototype, ApiInstanceType instance_type) {
540 Handle<SharedFunctionInfo> shared = 507 Handle<SharedFunctionInfo> shared =
541 FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj); 508 FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
509 DCHECK(shared->IsApiFunction());
542 Handle<JSFunction> result = 510 Handle<JSFunction> result =
543 isolate->factory()->NewFunctionFromSharedFunctionInfo( 511 isolate->factory()->NewFunctionFromSharedFunctionInfo(
544 shared, isolate->native_context()); 512 shared, isolate->native_context());
545 513
546 if (obj->remove_prototype()) { 514 if (obj->remove_prototype()) {
547 result->set_map(*isolate->sloppy_function_without_prototype_map()); 515 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()); 516 DCHECK(!result->has_initial_map());
551 DCHECK(!result->has_prototype()); 517 DCHECK(!result->has_prototype());
552 DCHECK(!result->IsConstructor()); 518 DCHECK(!result->IsConstructor());
553 return result; 519 return result;
554 } 520 }
555 521
556 // Down from here is only valid for API functions that can be used as a 522 // Down from here is only valid for API functions that can be used as a
557 // constructor (don't set the "remove prototype" flag). 523 // constructor (don't set the "remove prototype" flag).
558 524
525 // Set up function.prototype.
526 Handle<JSObject> prototype;
527 auto prototype_templ = handle(obj->prototype_template(), isolate);
528 if (type != JS_API_OBJECT_TYPE || prototype_templ->IsUndefined(isolate)) {
529 prototype = isolate->factory()->NewFunctionPrototype(result);
530 } else {
531 prototype = internal::InstantiateObject(
532 isolate, Handle<ObjectTemplateInfo>::cast(prototype_templ),
533 Handle<JSReceiver>(), obj->hidden_prototype())
534 .ToHandleChecked();
535
536 JSObject::AddProperty(Handle<JSObject>::cast(prototype),
537 isolate->factory()->constructor_string(), result,
538 DONT_ENUM);
539 }
540 // Set up function.prototype.__proto__.
541 auto parent = handle(obj->parent_template(), isolate);
542 if (!parent->IsUndefined(isolate)) {
543 Handle<JSFunction> parent_instance =
544 internal::InstantiateFunction(
545 isolate, Handle<FunctionTemplateInfo>::cast(parent))
546 .ToHandleChecked();
547 Handle<Object> parent_prototype =
548 JSFunction::GetPrototype(isolate, parent_instance);
549 CHECK(JSObject::SetPrototype(prototype, parent_prototype, false,
550 Object::THROW_ON_ERROR)
551 .IsJust());
552 }
553
559 if (obj->read_only_prototype()) { 554 if (obj->read_only_prototype()) {
560 result->set_map(*isolate->sloppy_function_with_readonly_prototype_map()); 555 result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
561 } 556 }
562 557
563 if (prototype->IsTheHole(isolate)) { 558 // Set up the function's initial map.
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; 559 int internal_field_count = 0;
572 if (!obj->instance_template()->IsUndefined(isolate)) { 560 if (!obj->instance_template()->IsUndefined(isolate)) {
573 Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>( 561 Handle<ObjectTemplateInfo> instance_template(
574 ObjectTemplateInfo::cast(obj->instance_template())); 562 ObjectTemplateInfo::cast(obj->instance_template()));
575 internal_field_count = 563 internal_field_count =
576 Smi::cast(instance_template->internal_field_count())->value(); 564 Smi::cast(instance_template->internal_field_count())->value();
577 } 565 }
578 566
579 // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
580 // JSObject::GetHeaderSize.
581 int instance_size = kPointerSize * internal_field_count; 567 int instance_size = kPointerSize * internal_field_count;
582 InstanceType type; 568 switch (type) {
583 switch (instance_type) { 569 case JS_API_OBJECT_TYPE:
584 case JavaScriptObjectType: 570 if (obj->needs_access_check() ||
585 if (!obj->needs_access_check() && 571 !obj->named_property_handler()->IsUndefined(isolate) ||
586 obj->named_property_handler()->IsUndefined(isolate) && 572 !obj->indexed_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; 573 type = JS_SPECIAL_API_OBJECT_TYPE;
591 } 574 }
592 instance_size += JSObject::kHeaderSize; 575 instance_size += JSObject::kHeaderSize;
593 break; 576 break;
594 case GlobalObjectType: 577 case JS_GLOBAL_OBJECT_TYPE:
595 type = JS_GLOBAL_OBJECT_TYPE;
596 instance_size += JSGlobalObject::kSize; 578 instance_size += JSGlobalObject::kSize;
597 break; 579 break;
598 case GlobalProxyType: 580 case JS_GLOBAL_PROXY_TYPE:
599 type = JS_GLOBAL_PROXY_TYPE;
600 instance_size += JSGlobalProxy::kSize; 581 instance_size += JSGlobalProxy::kSize;
601 break; 582 break;
602 default: 583 default:
603 UNREACHABLE(); 584 UNREACHABLE();
604 type = JS_OBJECT_TYPE; // Keep the compiler happy.
605 break; 585 break;
606 } 586 }
607 587
608 Handle<Map> map = 588 Handle<Map> map =
609 isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS); 589 isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
610 JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype)); 590 JSFunction::SetInitialMap(result, map, prototype);
611 591
612 // Mark as undetectable if needed. 592 if (obj->undetectable()) map->set_is_undetectable();
613 if (obj->undetectable()) { 593 if (obj->needs_access_check()) map->set_is_access_check_needed(true);
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)) { 594 if (!obj->named_property_handler()->IsUndefined(isolate)) {
624 map->set_has_named_interceptor(); 595 map->set_has_named_interceptor();
625 } 596 }
626 if (!obj->indexed_property_handler()->IsUndefined(isolate)) { 597 if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
627 map->set_has_indexed_interceptor(); 598 map->set_has_indexed_interceptor();
628 } 599 }
629
630 // Mark instance as callable in the map.
631 if (!obj->instance_call_handler()->IsUndefined(isolate)) { 600 if (!obj->instance_call_handler()->IsUndefined(isolate)) {
632 map->set_is_callable(); 601 map->set_is_callable();
633 map->set_is_constructor(true); 602 map->set_is_constructor(true);
634 } 603 }
635 604
636 return result; 605 return result;
637 } 606 }
638 607
639 } // namespace internal 608 } // namespace internal
640 } // namespace v8 609 } // namespace v8
OLDNEW
« no previous file with comments | « src/api-natives.h ('k') | src/bootstrapper.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698