• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
9 #include "src/builtins/builtins.h"
10 #include "src/execution/arguments.h"
11 #include "src/execution/isolate.h"
12 #include "src/heap/factory.h"
13 #include "src/logging/runtime-call-stats-scope.h"
14 
15 namespace v8 {
16 namespace internal {
17 
18 // Arguments object passed to C++ builtins.
19 class BuiltinArguments : public JavaScriptArguments {
20  public:
BuiltinArguments(int length,Address * arguments)21   BuiltinArguments(int length, Address* arguments)
22       : Arguments(length, arguments) {
23     // Check we have at least the receiver.
24     DCHECK_LE(1, this->length());
25   }
26 
27   Object operator[](int index) const {
28     DCHECK_LT(index, length());
29     return Object(*address_of_arg_at(index + kArgsOffset));
30   }
31 
32   template <class S = Object>
at(int index)33   Handle<S> at(int index) const {
34     DCHECK_LT(index, length());
35     return Handle<S>(address_of_arg_at(index + kArgsOffset));
36   }
37 
set_at(int index,Object value)38   inline void set_at(int index, Object value) {
39     DCHECK_LT(index, length());
40     *address_of_arg_at(index + kArgsOffset) = value.ptr();
41   }
42 
43   // Note: this should return the address after the receiver,
44   // even when length() == 1.
address_of_first_argument()45   inline Address* address_of_first_argument() const {
46     return address_of_arg_at(kArgsOffset + 1);  // Skips receiver.
47   }
48 
49   static constexpr int kNewTargetOffset = 0;
50   static constexpr int kTargetOffset = 1;
51   static constexpr int kArgcOffset = 2;
52   static constexpr int kPaddingOffset = 3;
53 
54   static constexpr int kNumExtraArgs = 4;
55   static constexpr int kNumExtraArgsWithReceiver = 5;
56   static constexpr int kArgsOffset = 4;
57 
58   inline Handle<Object> atOrUndefined(Isolate* isolate, int index) const;
59   inline Handle<Object> receiver() const;
60   inline Handle<JSFunction> target() const;
61   inline Handle<HeapObject> new_target() const;
62 
63   // Gets the total number of arguments including the receiver (but
64   // excluding extra arguments).
length()65   int length() const { return Arguments::length() - kNumExtraArgs; }
66 };
67 
68 // ----------------------------------------------------------------------------
69 // Support macro for defining builtins in C++.
70 // ----------------------------------------------------------------------------
71 //
72 // A builtin function is defined by writing:
73 //
74 //   BUILTIN(name) {
75 //     ...
76 //   }
77 //
78 // In the body of the builtin function the arguments can be accessed
79 // through the BuiltinArguments object args.
80 // TODO(cbruni): add global flag to check whether any tracing events have been
81 // enabled.
82 #define BUILTIN_RCS(name)                                                   \
83   V8_WARN_UNUSED_RESULT static Object Builtin_Impl_##name(                  \
84       BuiltinArguments args, Isolate* isolate);                             \
85                                                                             \
86   V8_NOINLINE static Address Builtin_Impl_Stats_##name(                     \
87       int args_length, Address* args_object, Isolate* isolate) {            \
88     BuiltinArguments args(args_length, args_object);                        \
89     RCS_SCOPE(isolate, RuntimeCallCounterId::kBuiltin_##name);              \
90     TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                   \
91                  "V8.Builtin_" #name);                                      \
92     return CONVERT_OBJECT(Builtin_Impl_##name(args, isolate));              \
93   }                                                                         \
94                                                                             \
95   V8_WARN_UNUSED_RESULT Address Builtin_##name(                             \
96       int args_length, Address* args_object, Isolate* isolate) {            \
97     DCHECK(isolate->context().is_null() || isolate->context().IsContext()); \
98     if (V8_UNLIKELY(TracingFlags::is_runtime_stats_enabled())) {            \
99       return Builtin_Impl_Stats_##name(args_length, args_object, isolate);  \
100     }                                                                       \
101     BuiltinArguments args(args_length, args_object);                        \
102     return CONVERT_OBJECT(Builtin_Impl_##name(args, isolate));              \
103   }                                                                         \
104                                                                             \
105   V8_WARN_UNUSED_RESULT static Object Builtin_Impl_##name(                  \
106       BuiltinArguments args, Isolate* isolate)
107 
108 #define BUILTIN_NO_RCS(name)                                                \
109   V8_WARN_UNUSED_RESULT static Object Builtin_Impl_##name(                  \
110       BuiltinArguments args, Isolate* isolate);                             \
111                                                                             \
112   V8_WARN_UNUSED_RESULT Address Builtin_##name(                             \
113       int args_length, Address* args_object, Isolate* isolate) {            \
114     DCHECK(isolate->context().is_null() || isolate->context().IsContext()); \
115     BuiltinArguments args(args_length, args_object);                        \
116     return CONVERT_OBJECT(Builtin_Impl_##name(args, isolate));              \
117   }                                                                         \
118                                                                             \
119   V8_WARN_UNUSED_RESULT static Object Builtin_Impl_##name(                  \
120       BuiltinArguments args, Isolate* isolate)
121 
122 #ifdef V8_RUNTIME_CALL_STATS
123 #define BUILTIN(name) BUILTIN_RCS(name)
124 #else  // V8_RUNTIME_CALL_STATS
125 #define BUILTIN(name) BUILTIN_NO_RCS(name)
126 #endif  // V8_RUNTIME_CALL_STATS
127 // ----------------------------------------------------------------------------
128 
129 #define CHECK_RECEIVER(Type, name, method)                                  \
130   if (!args.receiver()->Is##Type()) {                                       \
131     THROW_NEW_ERROR_RETURN_FAILURE(                                         \
132         isolate,                                                            \
133         NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,          \
134                      isolate->factory()->NewStringFromAsciiChecked(method), \
135                      args.receiver()));                                     \
136   }                                                                         \
137   Handle<Type> name = Handle<Type>::cast(args.receiver())
138 
139 // Throws a TypeError for {method} if the receiver is not coercible to Object,
140 // or converts the receiver to a String otherwise and assigns it to a new var
141 // with the given {name}.
142 #define TO_THIS_STRING(name, method)                                          \
143   if (args.receiver()->IsNullOrUndefined(isolate)) {                          \
144     THROW_NEW_ERROR_RETURN_FAILURE(                                           \
145         isolate,                                                              \
146         NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,               \
147                      isolate->factory()->NewStringFromAsciiChecked(method))); \
148   }                                                                           \
149   Handle<String> name;                                                        \
150   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(                                         \
151       isolate, name, Object::ToString(isolate, args.receiver()))
152 
153 }  // namespace internal
154 }  // namespace v8
155 
156 #endif  // V8_BUILTINS_BUILTINS_UTILS_H_
157