Line data Source code
1 : // Copyright 2012 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/builtins/builtins.h"
6 : #include "src/api.h"
7 : #include "src/assembler-inl.h"
8 : #include "src/builtins/builtins-descriptors.h"
9 : #include "src/callable.h"
10 : #include "src/isolate.h"
11 : #include "src/macro-assembler.h"
12 : #include "src/objects-inl.h"
13 : #include "src/visitors.h"
14 :
15 : namespace v8 {
16 : namespace internal {
17 :
18 : // Forward declarations for C++ builtins.
19 : #define FORWARD_DECLARE(Name) \
20 : Object* Builtin_##Name(int argc, Object** args, Isolate* isolate);
21 : BUILTIN_LIST_C(FORWARD_DECLARE)
22 :
23 60743 : Builtins::Builtins() : initialized_(false) {
24 60743 : memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
25 60743 : }
26 :
27 59259 : Builtins::~Builtins() {}
28 :
29 59259 : void Builtins::TearDown() { initialized_ = false; }
30 :
31 172238 : void Builtins::IterateBuiltins(RootVisitor* v) {
32 : v->VisitRootPointers(Root::kBuiltins, &builtins_[0],
33 172238 : &builtins_[0] + builtin_count);
34 172238 : }
35 :
36 0 : const char* Builtins::Lookup(byte* pc) {
37 : // may be called during initialization (disassembler!)
38 0 : if (initialized_) {
39 0 : for (int i = 0; i < builtin_count; i++) {
40 0 : Code* entry = Code::cast(builtins_[i]);
41 0 : if (entry->contains(pc)) return name(i);
42 : }
43 : }
44 : return NULL;
45 : }
46 :
47 45292 : Handle<Code> Builtins::NewFunctionContext(ScopeType scope_type) {
48 45292 : switch (scope_type) {
49 : case ScopeType::EVAL_SCOPE:
50 : return FastNewFunctionContextEval();
51 : case ScopeType::FUNCTION_SCOPE:
52 : return FastNewFunctionContextFunction();
53 : default:
54 0 : UNREACHABLE();
55 : }
56 : return Handle<Code>::null();
57 : }
58 :
59 92194 : Handle<Code> Builtins::NewCloneShallowArray(
60 : AllocationSiteMode allocation_mode) {
61 92194 : switch (allocation_mode) {
62 : case TRACK_ALLOCATION_SITE:
63 : return FastCloneShallowArrayTrack();
64 : case DONT_TRACK_ALLOCATION_SITE:
65 : return FastCloneShallowArrayDontTrack();
66 : default:
67 0 : UNREACHABLE();
68 : }
69 : return Handle<Code>::null();
70 : }
71 :
72 47931 : Handle<Code> Builtins::NewCloneShallowObject(int length) {
73 47931 : switch (length) {
74 : case 0:
75 : return FastCloneShallowObject0();
76 : case 1:
77 : return FastCloneShallowObject1();
78 : case 2:
79 : return FastCloneShallowObject2();
80 : case 3:
81 : return FastCloneShallowObject3();
82 : case 4:
83 : return FastCloneShallowObject4();
84 : case 5:
85 : return FastCloneShallowObject5();
86 : case 6:
87 : return FastCloneShallowObject6();
88 : default:
89 0 : UNREACHABLE();
90 : }
91 : return Handle<Code>::null();
92 : }
93 :
94 2200 : Handle<Code> Builtins::NonPrimitiveToPrimitive(ToPrimitiveHint hint) {
95 2200 : switch (hint) {
96 : case ToPrimitiveHint::kDefault:
97 : return NonPrimitiveToPrimitive_Default();
98 : case ToPrimitiveHint::kNumber:
99 : return NonPrimitiveToPrimitive_Number();
100 : case ToPrimitiveHint::kString:
101 : return NonPrimitiveToPrimitive_String();
102 : }
103 0 : UNREACHABLE();
104 : return Handle<Code>::null();
105 : }
106 :
107 215 : Handle<Code> Builtins::OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint) {
108 215 : switch (hint) {
109 : case OrdinaryToPrimitiveHint::kNumber:
110 : return OrdinaryToPrimitive_Number();
111 : case OrdinaryToPrimitiveHint::kString:
112 : return OrdinaryToPrimitive_String();
113 : }
114 0 : UNREACHABLE();
115 : return Handle<Code>::null();
116 : }
117 :
118 : // static
119 5756 : Callable Builtins::CallableFor(Isolate* isolate, Name name) {
120 5756 : switch (name) {
121 : #define CASE(Name, ...) \
122 : case k##Name: { \
123 : Handle<Code> code = isolate->builtins()->Name(); \
124 : auto descriptor = Builtin_##Name##_InterfaceDescriptor(isolate); \
125 : return Callable(code, descriptor); \
126 : }
127 5713 : BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, CASE, CASE,
128 : CASE, IGNORE_BUILTIN, IGNORE_BUILTIN)
129 : #undef CASE
130 : #define CASE(Name, ...) \
131 : case k##Name: { \
132 : Handle<Code> code = isolate->builtins()->Name(); \
133 : return Callable(code, BuiltinDescriptor(isolate)); \
134 : }
135 86 : BUILTIN_LIST(CASE, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN,
136 : IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
137 : #undef CASE
138 : default:
139 0 : UNREACHABLE();
140 : return Callable(Handle<Code>::null(), VoidDescriptor(isolate));
141 : }
142 : }
143 :
144 : // static
145 283006 : const char* Builtins::name(int index) {
146 283006 : switch (index) {
147 : #define CASE(Name, ...) \
148 : case k##Name: \
149 : return #Name;
150 426 : BUILTIN_LIST_ALL(CASE)
151 : #undef CASE
152 : default:
153 0 : UNREACHABLE();
154 : break;
155 : }
156 : return "";
157 : }
158 :
159 : // static
160 11708 : Address Builtins::CppEntryOf(int index) {
161 : DCHECK(0 <= index && index < builtin_count);
162 11708 : switch (index) {
163 : #define CASE(Name, ...) \
164 : case k##Name: \
165 : return FUNCTION_ADDR(Builtin_##Name);
166 : BUILTIN_LIST_C(CASE)
167 : #undef CASE
168 : default:
169 : return nullptr;
170 : }
171 : UNREACHABLE();
172 : }
173 :
174 : // static
175 11708 : bool Builtins::IsCpp(int index) {
176 : DCHECK(0 <= index && index < builtin_count);
177 11708 : switch (index) {
178 : #define CASE(Name, ...) \
179 : case k##Name: \
180 : return true;
181 : #define BUILTIN_LIST_CPP(V) \
182 : BUILTIN_LIST(V, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, \
183 : IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
184 : BUILTIN_LIST_CPP(CASE)
185 : #undef BUILTIN_LIST_CPP
186 : #undef CASE
187 : default:
188 91 : return false;
189 : }
190 : UNREACHABLE();
191 : }
192 :
193 : // static
194 0 : bool Builtins::IsApi(int index) {
195 : DCHECK(0 <= index && index < builtin_count);
196 0 : switch (index) {
197 : #define CASE(Name, ...) \
198 : case k##Name: \
199 : return true;
200 : #define BUILTIN_LIST_API(V) \
201 : BUILTIN_LIST(IGNORE_BUILTIN, V, IGNORE_BUILTIN, IGNORE_BUILTIN, \
202 : IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN, IGNORE_BUILTIN)
203 : BUILTIN_LIST_API(CASE);
204 : #undef BUILTIN_LIST_API
205 : #undef CASE
206 : default:
207 0 : return false;
208 : }
209 : UNREACHABLE();
210 : }
211 :
212 : // static
213 135171 : bool Builtins::HasCppImplementation(int index) {
214 : DCHECK(0 <= index && index < builtin_count);
215 135171 : switch (index) {
216 : #define CASE(Name, ...) \
217 : case k##Name: \
218 : return true;
219 : BUILTIN_LIST_C(CASE)
220 : #undef CASE
221 : default:
222 123450 : return false;
223 : }
224 : UNREACHABLE();
225 : }
226 :
227 : #define DEFINE_BUILTIN_ACCESSOR(Name, ...) \
228 : Handle<Code> Builtins::Name() { \
229 : Code** code_address = reinterpret_cast<Code**>(builtin_address(k##Name)); \
230 : return Handle<Code>(code_address); \
231 : }
232 101908667 : BUILTIN_LIST_ALL(DEFINE_BUILTIN_ACCESSOR)
233 : #undef DEFINE_BUILTIN_ACCESSOR
234 :
235 : // static
236 3600036 : bool Builtins::AllowDynamicFunction(Isolate* isolate, Handle<JSFunction> target,
237 : Handle<JSObject> target_global_proxy) {
238 1800214 : if (FLAG_allow_unsafe_function_constructor) return true;
239 : HandleScopeImplementer* impl = isolate->handle_scope_implementer();
240 : Handle<Context> responsible_context =
241 : impl->MicrotaskContextIsLastEnteredContext() ? impl->MicrotaskContext()
242 1799822 : : impl->LastEnteredContext();
243 : // TODO(jochen): Remove this.
244 1799822 : if (responsible_context.is_null()) {
245 : return true;
246 : }
247 1799822 : if (*responsible_context == target->context()) return true;
248 406 : return isolate->MayAccess(responsible_context, target_global_proxy);
249 : }
250 :
251 : } // namespace internal
252 : } // namespace v8
|