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