1// Copyright 2021 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/objects/templates.h" 6 7#include "src/api/api-inl.h" 8#include "src/execution/isolate.h" 9#include "src/heap/factory.h" 10#include "src/objects/function-kind.h" 11#include "src/objects/instance-type-inl.h" 12#include "src/objects/js-function-inl.h" 13#include "src/objects/map-inl.h" 14#include "src/objects/name-inl.h" 15#include "src/objects/shared-function-info-inl.h" 16#include "src/objects/string-inl.h" 17 18namespace v8 { 19namespace internal { 20 21bool FunctionTemplateInfo::HasInstanceType() { 22 return instance_type() != kNoJSApiObjectType; 23} 24 25Handle<SharedFunctionInfo> FunctionTemplateInfo::GetOrCreateSharedFunctionInfo( 26 Isolate* isolate, Handle<FunctionTemplateInfo> info, 27 MaybeHandle<Name> maybe_name) { 28 Object current_info = info->shared_function_info(); 29 if (current_info.IsSharedFunctionInfo()) { 30 return handle(SharedFunctionInfo::cast(current_info), isolate); 31 } 32 Handle<Name> name; 33 Handle<String> name_string; 34 if (maybe_name.ToHandle(&name) && name->IsString()) { 35 name_string = Handle<String>::cast(name); 36 } else if (info->class_name().IsString()) { 37 name_string = handle(String::cast(info->class_name()), isolate); 38 } else { 39 name_string = isolate->factory()->empty_string(); 40 } 41 FunctionKind function_kind; 42 if (info->remove_prototype()) { 43 function_kind = FunctionKind::kConciseMethod; 44 } else { 45 function_kind = FunctionKind::kNormalFunction; 46 } 47 Handle<SharedFunctionInfo> result = 48 isolate->factory()->NewSharedFunctionInfoForApiFunction(name_string, info, 49 function_kind); 50 51 result->set_length(info->length()); 52 result->DontAdaptArguments(); 53 DCHECK(result->IsApiFunction()); 54 55 info->set_shared_function_info(*result); 56 return result; 57} 58 59bool FunctionTemplateInfo::IsTemplateFor(Map map) const { 60 RCS_SCOPE( 61 LocalHeap::Current() == nullptr 62 ? GetIsolate()->counters()->runtime_call_stats() 63 : LocalIsolate::FromHeap(LocalHeap::Current())->runtime_call_stats(), 64 RuntimeCallCounterId::kIsTemplateFor); 65 66 // There is a constraint on the object; check. 67 if (!map.IsJSObjectMap()) return false; 68 69 if (FLAG_embedder_instance_types) { 70 DCHECK_IMPLIES(allowed_receiver_instance_type_range_start() == 0, 71 allowed_receiver_instance_type_range_end() == 0); 72 if (base::IsInRange(map.instance_type(), 73 allowed_receiver_instance_type_range_start(), 74 allowed_receiver_instance_type_range_end())) { 75 return true; 76 } 77 } 78 79 // Fetch the constructor function of the object. 80 Object cons_obj = map.GetConstructor(); 81 Object type; 82 if (cons_obj.IsJSFunction()) { 83 JSFunction fun = JSFunction::cast(cons_obj); 84 type = fun.shared().function_data(kAcquireLoad); 85 } else if (cons_obj.IsFunctionTemplateInfo()) { 86 type = FunctionTemplateInfo::cast(cons_obj); 87 } else { 88 return false; 89 } 90 // Iterate through the chain of inheriting function templates to 91 // see if the required one occurs. 92 while (type.IsFunctionTemplateInfo()) { 93 if (type == *this) return true; 94 type = FunctionTemplateInfo::cast(type).GetParentTemplate(); 95 } 96 // Didn't find the required type in the inheritance chain. 97 return false; 98} 99 100bool FunctionTemplateInfo::IsLeafTemplateForApiObject(Object object) const { 101 i::DisallowGarbageCollection no_gc; 102 103 if (!object.IsJSApiObject()) { 104 return false; 105 } 106 107 bool result = false; 108 Map map = HeapObject::cast(object).map(); 109 Object constructor_obj = map.GetConstructor(); 110 if (constructor_obj.IsJSFunction()) { 111 JSFunction fun = JSFunction::cast(constructor_obj); 112 result = (*this == fun.shared().function_data(kAcquireLoad)); 113 } else if (constructor_obj.IsFunctionTemplateInfo()) { 114 result = (*this == constructor_obj); 115 } 116 DCHECK_IMPLIES(result, IsTemplateFor(map)); 117 return result; 118} 119 120// static 121FunctionTemplateRareData FunctionTemplateInfo::AllocateFunctionTemplateRareData( 122 Isolate* isolate, Handle<FunctionTemplateInfo> function_template_info) { 123 DCHECK(function_template_info->rare_data(kAcquireLoad).IsUndefined(isolate)); 124 Handle<FunctionTemplateRareData> rare_data = 125 isolate->factory()->NewFunctionTemplateRareData(); 126 function_template_info->set_rare_data(*rare_data, kReleaseStore); 127 return *rare_data; 128} 129 130base::Optional<Name> FunctionTemplateInfo::TryGetCachedPropertyName( 131 Isolate* isolate, Object getter) { 132 DisallowGarbageCollection no_gc; 133 if (!getter.IsFunctionTemplateInfo()) return {}; 134 // Check if the accessor uses a cached property. 135 Object maybe_name = FunctionTemplateInfo::cast(getter).cached_property_name(); 136 if (maybe_name.IsTheHole(isolate)) return {}; 137 return Name::cast(maybe_name); 138} 139 140int FunctionTemplateInfo::GetCFunctionsCount() const { 141 i::DisallowHeapAllocation no_gc; 142 return FixedArray::cast(GetCFunctionOverloads()).length() / 143 kFunctionOverloadEntrySize; 144} 145 146Address FunctionTemplateInfo::GetCFunction(int index) const { 147 i::DisallowHeapAllocation no_gc; 148 return v8::ToCData<Address>(FixedArray::cast(GetCFunctionOverloads()) 149 .get(index * kFunctionOverloadEntrySize)); 150} 151 152const CFunctionInfo* FunctionTemplateInfo::GetCSignature(int index) const { 153 i::DisallowHeapAllocation no_gc; 154 return v8::ToCData<CFunctionInfo*>( 155 FixedArray::cast(GetCFunctionOverloads()) 156 .get(index * kFunctionOverloadEntrySize + 1)); 157} 158 159} // namespace internal 160} // namespace v8 161