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