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
18 namespace v8 {
19 namespace internal {
20
HasInstanceType()21 bool FunctionTemplateInfo::HasInstanceType() {
22 return instance_type() != kNoJSApiObjectType;
23 }
24
GetOrCreateSharedFunctionInfo(Isolate * isolate,Handle<FunctionTemplateInfo> info,MaybeHandle<Name> maybe_name)25 Handle<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
IsTemplateFor(Map map) const59 bool 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
IsLeafTemplateForApiObject(Object object) const100 bool 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
AllocateFunctionTemplateRareData(Isolate * isolate,Handle<FunctionTemplateInfo> function_template_info)121 FunctionTemplateRareData 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
TryGetCachedPropertyName(Isolate * isolate,Object getter)130 base::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
GetCFunctionsCount() const140 int FunctionTemplateInfo::GetCFunctionsCount() const {
141 i::DisallowHeapAllocation no_gc;
142 return FixedArray::cast(GetCFunctionOverloads()).length() /
143 kFunctionOverloadEntrySize;
144 }
145
GetCFunction(int index) const146 Address FunctionTemplateInfo::GetCFunction(int index) const {
147 i::DisallowHeapAllocation no_gc;
148 return v8::ToCData<Address>(FixedArray::cast(GetCFunctionOverloads())
149 .get(index * kFunctionOverloadEntrySize));
150 }
151
GetCSignature(int index) const152 const 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