v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
builtins-utils.h
Go to the documentation of this file.
1// Copyright 2016 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_UTILS_H_
6#define V8_BUILTINS_BUILTINS_UTILS_H_
7
8#include "src/base/logging.h"
13#include "src/heap/factory.h"
15
16namespace v8 {
17namespace internal {
18
19// Arguments object passed to C++ builtins.
21 public:
22 BuiltinArguments(int length, Address* arguments)
23 : Arguments(length, arguments) {
24 // Check we have at least the receiver.
25 DCHECK_LE(1, this->length());
26 DCHECK(Tagged<Object>((*at(0)).ptr()).IsObject());
27 }
28
29 // Zero index states for receiver.
30 Tagged<Object> operator[](int index) const {
31 DCHECK_LT(index, length());
33 }
34
35 // Zero index states for receiver.
36 template <class S = Object>
37 Handle<S> at(int index) const {
38 DCHECK_LT(index, length());
39 return Handle<S>(address_of_arg_at(index + kArgsIndex));
40 }
41
42 // Zero index states for receiver.
43 inline void set_at(int index, Tagged<Object> value) {
44 DCHECK_LT(index, length());
45 *address_of_arg_at(index + kArgsIndex) = value.ptr();
46 }
47
48 // Note: this should return the address after the receiver,
49 // even when length() == 1.
53
54 static constexpr int kNewTargetIndex = 0;
55 static constexpr int kTargetIndex = 1;
56 static constexpr int kArgcIndex = 2;
57 // TODO(ishell): this padding is required only on arm64.
58 static constexpr int kPaddingIndex = 3;
59
60 static constexpr int kNumExtraArgs = 4;
61 static constexpr int kNumExtraArgsWithReceiver = 5;
62
63 static constexpr int kArgsIndex = kNumExtraArgs;
64 static constexpr int kReceiverIndex = kArgsIndex;
65 static constexpr int kFirstArgsIndex = kArgsIndex + 1; // Skip receiver.
66 // Index of the receiver argument in JS arguments array returned by
67 // |address_of_first_argument()|.
69
70 // Zero index states for receiver.
71 inline Handle<Object> atOrUndefined(Isolate* isolate, int index) const;
72 inline Handle<JSAny> receiver() const;
73 inline Handle<JSFunction> target() const;
74 inline Handle<HeapObject> new_target() const;
75
76 // Gets the total number of arguments including the receiver (but
77 // excluding extra arguments).
78 int length() const { return Arguments::length() - kNumExtraArgs; }
79};
80
83static_assert(BuiltinArguments::kTargetIndex ==
85static_assert(BuiltinArguments::kArgcIndex ==
89
94
95// ----------------------------------------------------------------------------
96// Support macro for defining builtins in C++.
97// ----------------------------------------------------------------------------
98//
99// A builtin function is defined by writing:
100//
101// BUILTIN(name) {
102// ...
103// }
104//
105// In the body of the builtin function the arguments can be accessed
106// through the BuiltinArguments object args.
107// TODO(cbruni): add global flag to check whether any tracing events have been
108// enabled.
109#define BUILTIN_RCS(name) \
110 V8_WARN_UNUSED_RESULT static Tagged<Object> Builtin_Impl_##name( \
111 BuiltinArguments args, Isolate* isolate); \
112 \
113 V8_NOINLINE static Address Builtin_Impl_Stats_##name( \
114 int args_length, Address* args_object, Isolate* isolate) { \
115 BuiltinArguments args(args_length, args_object); \
116 RCS_SCOPE(isolate, RuntimeCallCounterId::kBuiltin_##name); \
117 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
118 "V8.Builtin_" #name); \
119 return BUILTIN_CONVERT_RESULT(Builtin_Impl_##name(args, isolate)); \
120 } \
121 \
122 V8_WARN_UNUSED_RESULT Address Builtin_##name( \
123 int args_length, Address* args_object, Isolate* isolate) { \
124 DCHECK(isolate->context().is_null() || IsContext(isolate->context())); \
125 if (V8_UNLIKELY(TracingFlags::is_runtime_stats_enabled())) { \
126 return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
127 } \
128 BuiltinArguments args(args_length, args_object); \
129 return BUILTIN_CONVERT_RESULT(Builtin_Impl_##name(args, isolate)); \
130 } \
131 \
132 V8_WARN_UNUSED_RESULT static Tagged<Object> Builtin_Impl_##name( \
133 BuiltinArguments args, Isolate* isolate)
134
135#define BUILTIN_NO_RCS(name) \
136 V8_WARN_UNUSED_RESULT static Tagged<Object> Builtin_Impl_##name( \
137 BuiltinArguments args, Isolate* isolate); \
138 \
139 V8_WARN_UNUSED_RESULT Address Builtin_##name( \
140 int args_length, Address* args_object, Isolate* isolate) { \
141 DCHECK(isolate->context().is_null() || IsContext(isolate->context())); \
142 BuiltinArguments args(args_length, args_object); \
143 return BUILTIN_CONVERT_RESULT(Builtin_Impl_##name(args, isolate)); \
144 } \
145 \
146 V8_WARN_UNUSED_RESULT static Tagged<Object> Builtin_Impl_##name( \
147 BuiltinArguments args, Isolate* isolate)
148
149#ifdef V8_RUNTIME_CALL_STATS
150#define BUILTIN(name) BUILTIN_RCS(name)
151#else // V8_RUNTIME_CALL_STATS
152#define BUILTIN(name) BUILTIN_NO_RCS(name)
153#endif // V8_RUNTIME_CALL_STATS
154// ----------------------------------------------------------------------------
155
156#define CHECK_RECEIVER(Type, name, method) \
157 if (!Is##Type(*args.receiver())) { \
158 THROW_NEW_ERROR_RETURN_FAILURE( \
159 isolate, \
160 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
161 isolate->factory()->NewStringFromAsciiChecked(method), \
162 args.receiver())); \
163 } \
164 auto name = Cast<Type>(args.receiver())
165
166// Throws a TypeError for {method} if the receiver is not coercible to Object,
167// or converts the receiver to a String otherwise and assigns it to a new var
168// with the given {name}.
169#define TO_THIS_STRING(name, method) \
170 if (IsNullOrUndefined(*args.receiver(), isolate)) { \
171 THROW_NEW_ERROR_RETURN_FAILURE( \
172 isolate, \
173 NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, \
174 isolate->factory()->NewStringFromAsciiChecked(method))); \
175 } \
176 DirectHandle<String> name; \
177 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
178 isolate, name, Object::ToString(isolate, args.receiver()))
179
180} // namespace internal
181} // namespace v8
182
183#endif // V8_BUILTINS_BUILTINS_UTILS_H_
V8_INLINE int length() const
Definition arguments.h:89
V8_INLINE Address * address_of_arg_at(int index) const
Definition arguments.h:73
static constexpr int kNumExtraArgsWithReceiver
static constexpr int kNewTargetIndex
Handle< JSFunction > target() const
Handle< S > at(int index) const
static constexpr int kPaddingIndex
static constexpr int kReceiverArgsIndex
Tagged< Object > operator[](int index) const
Handle< Object > atOrUndefined(Isolate *isolate, int index) const
static constexpr int kArgcIndex
Handle< JSAny > receiver() const
Handle< HeapObject > new_target() const
void set_at(int index, Tagged< Object > value)
static constexpr int kFirstArgsIndex
Address * address_of_first_argument() const
static constexpr int kNumExtraArgs
static constexpr int kTargetIndex
BuiltinArguments(int length, Address *arguments)
static constexpr int kReceiverIndex
static constexpr int kArgsIndex
V8_INLINE constexpr bool IsObject(TaggedImpl< kRefType, StorageType > obj)
Definition objects.h:661
Local< T > Handle
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489