• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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