Line data Source code
1 : // Copyright 2011 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 : #ifndef V8_BUILTINS_BUILTINS_H_
6 : #define V8_BUILTINS_BUILTINS_H_
7 :
8 : #include "src/base/flags.h"
9 : #include "src/builtins/builtins-definitions.h"
10 : #include "src/globals.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : class ByteArray;
16 : class Callable;
17 : template <typename T>
18 : class Handle;
19 : class Isolate;
20 :
21 : // Forward declarations.
22 : class BailoutId;
23 : class RootVisitor;
24 : enum class InterpreterPushArgsMode : unsigned;
25 : namespace compiler {
26 : class CodeAssemblerState;
27 : }
28 :
29 : template <typename T>
30 : static constexpr T FirstFromVarArgs(T x, ...) noexcept {
31 : return x;
32 : }
33 :
34 : // Convenience macro to avoid generating named accessors for all builtins.
35 : #define BUILTIN_CODE(isolate, name) \
36 : (isolate)->builtins()->builtin_handle(Builtins::k##name)
37 :
38 : class Builtins {
39 : public:
40 62422 : explicit Builtins(Isolate* isolate) : isolate_(isolate) {}
41 :
42 : void TearDown();
43 :
44 : // Disassembler support.
45 : const char* Lookup(Address pc);
46 :
47 : enum Name : int32_t {
48 : #define DEF_ENUM(Name, ...) k##Name,
49 : BUILTIN_LIST(DEF_ENUM, DEF_ENUM, DEF_ENUM, DEF_ENUM, DEF_ENUM, DEF_ENUM,
50 : DEF_ENUM, DEF_ENUM)
51 : #undef DEF_ENUM
52 : builtin_count,
53 :
54 : #define EXTRACT_NAME(Name, ...) k##Name,
55 : // Define kFirstBytecodeHandler,
56 : kFirstBytecodeHandler =
57 : FirstFromVarArgs(BUILTIN_LIST_BYTECODE_HANDLERS(EXTRACT_NAME) 0)
58 : #undef EXTRACT_NAME
59 : };
60 :
61 : static const int32_t kNoBuiltinId = -1;
62 :
63 : static constexpr bool IsBuiltinId(int maybe_id) {
64 10513868 : return 0 <= maybe_id && maybe_id < builtin_count;
65 : }
66 :
67 : // The different builtin kinds are documented in builtins-definitions.h.
68 : enum Kind { CPP, API, TFJ, TFC, TFS, TFH, BCH, ASM };
69 :
70 : static BailoutId GetContinuationBailoutId(Name name);
71 : static Name GetBuiltinFromBailoutId(BailoutId);
72 :
73 : // Convenience wrappers.
74 : Handle<Code> CallFunction(ConvertReceiverMode = ConvertReceiverMode::kAny);
75 : Handle<Code> Call(ConvertReceiverMode = ConvertReceiverMode::kAny);
76 : Handle<Code> NonPrimitiveToPrimitive(
77 : ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
78 : Handle<Code> OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint);
79 : Handle<Code> JSConstructStubGeneric();
80 :
81 : // Used by CreateOffHeapTrampolines in isolate.cc.
82 : void set_builtin(int index, Code builtin);
83 :
84 : V8_EXPORT_PRIVATE Code builtin(int index);
85 : V8_EXPORT_PRIVATE Handle<Code> builtin_handle(int index);
86 :
87 : V8_EXPORT_PRIVATE static Callable CallableFor(Isolate* isolate, Name name);
88 :
89 : static int GetStackParameterCount(Name name);
90 :
91 : static const char* name(int index);
92 :
93 : // Support for --print-builtin-size and --print-builtin-code.
94 : void PrintBuiltinCode();
95 : void PrintBuiltinSize();
96 :
97 : // Returns the C++ entry point for builtins implemented in C++, and the null
98 : // Address otherwise.
99 : static Address CppEntryOf(int index);
100 :
101 : static Kind KindOf(int index);
102 : static const char* KindNameOf(int index);
103 :
104 : static bool IsCpp(int index);
105 : static bool HasCppImplementation(int index);
106 :
107 : // True, iff the given code object is a builtin. Note that this does not
108 : // necessarily mean that its kind is Code::BUILTIN.
109 : static bool IsBuiltin(const Code code);
110 :
111 : // As above, but safe to access off the main thread since the check is done
112 : // by handle location. Similar to Heap::IsRootHandle.
113 : bool IsBuiltinHandle(Handle<HeapObject> maybe_code, int* index) const;
114 :
115 : // True, iff the given code object is a builtin with off-heap embedded code.
116 : static bool IsIsolateIndependentBuiltin(const Code code);
117 :
118 : static constexpr int kFirstWideBytecodeHandler =
119 : kFirstBytecodeHandler + kNumberOfBytecodeHandlers;
120 : static constexpr int kFirstExtraWideBytecodeHandler =
121 : kFirstWideBytecodeHandler + kNumberOfWideBytecodeHandlers;
122 : STATIC_ASSERT(kFirstExtraWideBytecodeHandler +
123 : kNumberOfWideBytecodeHandlers ==
124 : builtin_count);
125 :
126 : // True, iff the given builtin contains no isolate-specific code and can be
127 : // embedded into the binary.
128 : static constexpr bool kAllBuiltinsAreIsolateIndependent = true;
129 : static constexpr bool AllBuiltinsAreIsolateIndependent() {
130 : return kAllBuiltinsAreIsolateIndependent;
131 : }
132 : static constexpr bool IsIsolateIndependent(int index) {
133 : STATIC_ASSERT(kAllBuiltinsAreIsolateIndependent);
134 : return kAllBuiltinsAreIsolateIndependent;
135 : }
136 :
137 : // Wasm runtime stubs are treated specially by wasm. To guarantee reachability
138 : // through near jumps, their code is completely copied into a fresh off-heap
139 : // area.
140 : static bool IsWasmRuntimeStub(int index);
141 :
142 : // Updates the table of builtin entry points based on the current contents of
143 : // the builtins table.
144 : static void UpdateBuiltinEntryTable(Isolate* isolate);
145 :
146 : bool is_initialized() const { return initialized_; }
147 :
148 : // Used by SetupIsolateDelegate and Deserializer.
149 : void MarkInitialized() {
150 : DCHECK(!initialized_);
151 62422 : initialized_ = true;
152 : }
153 :
154 : V8_WARN_UNUSED_RESULT static MaybeHandle<Object> InvokeApiFunction(
155 : Isolate* isolate, bool is_construct, Handle<HeapObject> function,
156 : Handle<Object> receiver, int argc, Handle<Object> args[],
157 : Handle<HeapObject> new_target);
158 :
159 : enum ExitFrameType { EXIT, BUILTIN_EXIT };
160 :
161 : static void Generate_Adaptor(MacroAssembler* masm, Address builtin_address,
162 : ExitFrameType exit_frame_type);
163 :
164 : static void Generate_CEntry(MacroAssembler* masm, int result_size,
165 : SaveFPRegsMode save_doubles, ArgvMode argv_mode,
166 : bool builtin_exit_frame);
167 :
168 : static bool AllowDynamicFunction(Isolate* isolate, Handle<JSFunction> target,
169 : Handle<JSObject> target_global_proxy);
170 :
171 : // Creates a trampoline code object that jumps to the given off-heap entry.
172 : // The result should not be used directly, but only from the related Factory
173 : // function.
174 : static Handle<Code> GenerateOffHeapTrampolineFor(Isolate* isolate,
175 : Address off_heap_entry);
176 :
177 : // Generate the RelocInfo ByteArray that would be generated for an offheap
178 : // trampoline.
179 : static Handle<ByteArray> GenerateOffHeapTrampolineRelocInfo(Isolate* isolate);
180 :
181 : static bool IsJSEntryVariant(int builtin_index) {
182 3920 : switch (builtin_index) {
183 : case kJSEntry:
184 : case kJSConstructEntry:
185 : case kJSRunMicrotasksEntry:
186 : return true;
187 : default:
188 : return false;
189 : }
190 : UNREACHABLE();
191 : }
192 :
193 : int js_entry_handler_offset() const {
194 : DCHECK_NE(js_entry_handler_offset_, 0);
195 : return js_entry_handler_offset_;
196 : }
197 :
198 : void SetJSEntryHandlerOffset(int offset) {
199 : // Check the stored offset is either uninitialized or unchanged (we
200 : // generate multiple variants of this builtin but they should all have the
201 : // same handler offset).
202 168 : CHECK(js_entry_handler_offset_ == 0 || js_entry_handler_offset_ == offset);
203 168 : js_entry_handler_offset_ = offset;
204 : }
205 :
206 : private:
207 : static void Generate_CallFunction(MacroAssembler* masm,
208 : ConvertReceiverMode mode);
209 :
210 : static void Generate_CallBoundFunctionImpl(MacroAssembler* masm);
211 :
212 : static void Generate_Call(MacroAssembler* masm, ConvertReceiverMode mode);
213 :
214 : enum class CallOrConstructMode { kCall, kConstruct };
215 : static void Generate_CallOrConstructVarargs(MacroAssembler* masm,
216 : Handle<Code> code);
217 : static void Generate_CallOrConstructForwardVarargs(MacroAssembler* masm,
218 : CallOrConstructMode mode,
219 : Handle<Code> code);
220 :
221 : static void Generate_InterpreterPushArgsThenCallImpl(
222 : MacroAssembler* masm, ConvertReceiverMode receiver_mode,
223 : InterpreterPushArgsMode mode);
224 :
225 : static void Generate_InterpreterPushArgsThenConstructImpl(
226 : MacroAssembler* masm, InterpreterPushArgsMode mode);
227 :
228 : #define DECLARE_ASM(Name, ...) \
229 : static void Generate_##Name(MacroAssembler* masm);
230 : #define DECLARE_TF(Name, ...) \
231 : static void Generate_##Name(compiler::CodeAssemblerState* state);
232 :
233 : BUILTIN_LIST(IGNORE_BUILTIN, IGNORE_BUILTIN, DECLARE_TF, DECLARE_TF,
234 : DECLARE_TF, DECLARE_TF, IGNORE_BUILTIN, DECLARE_ASM)
235 :
236 : #undef DECLARE_ASM
237 : #undef DECLARE_TF
238 :
239 : Isolate* isolate_;
240 : bool initialized_ = false;
241 :
242 : // Stores the offset of exception handler entry point (the handler_entry
243 : // label) in JSEntry and its variants. It's used to generate the handler table
244 : // during codegen (mksnapshot-only).
245 : int js_entry_handler_offset_ = 0;
246 :
247 : friend class SetupIsolateDelegate;
248 :
249 : DISALLOW_COPY_AND_ASSIGN(Builtins);
250 : };
251 :
252 : Builtins::Name ExampleBuiltinForTorqueFunctionPointerType(
253 : size_t function_pointer_type_id);
254 :
255 : } // namespace internal
256 : } // namespace v8
257 :
258 : #endif // V8_BUILTINS_BUILTINS_H_
|