| Index: src/builtins/builtins-utils.h
|
| diff --git a/src/builtins/builtins-utils.h b/src/builtins/builtins-utils.h
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c2caa136e1725a73f00251889377fcf4b0718637
|
| --- /dev/null
|
| +++ b/src/builtins/builtins-utils.h
|
| @@ -0,0 +1,135 @@
|
| +// Copyright 2016 the V8 project authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#ifndef V8_BUILTINS_BUILTINS_UTILS_H_
|
| +#define V8_BUILTINS_BUILTINS_UTILS_H_
|
| +
|
| +#include "src/arguments.h"
|
| +#include "src/base/logging.h"
|
| +#include "src/builtins/builtins.h"
|
| +#include "src/code-stub-assembler.h"
|
| +
|
| +namespace v8 {
|
| +namespace internal {
|
| +
|
| +// Arguments object passed to C++ builtins.
|
| +class BuiltinArguments : public Arguments {
|
| + public:
|
| + BuiltinArguments(int length, Object** arguments)
|
| + : Arguments(length, arguments) {
|
| + // Check we have at least the receiver.
|
| + DCHECK_LE(1, this->length());
|
| + }
|
| +
|
| + Object*& operator[](int index) {
|
| + DCHECK_LT(index, length());
|
| + return Arguments::operator[](index);
|
| + }
|
| +
|
| + template <class S>
|
| + Handle<S> at(int index) {
|
| + DCHECK_LT(index, length());
|
| + return Arguments::at<S>(index);
|
| + }
|
| +
|
| + Handle<Object> atOrUndefined(Isolate* isolate, int index) {
|
| + if (index >= length()) {
|
| + return isolate->factory()->undefined_value();
|
| + }
|
| + return at<Object>(index);
|
| + }
|
| +
|
| + Handle<Object> receiver() { return Arguments::at<Object>(0); }
|
| +
|
| + static const int kNewTargetOffset = 0;
|
| + static const int kTargetOffset = 1;
|
| + static const int kArgcOffset = 2;
|
| + static const int kNumExtraArgs = 3;
|
| + static const int kNumExtraArgsWithReceiver = 4;
|
| +
|
| + template <class S>
|
| + Handle<S> target() {
|
| + return Arguments::at<S>(Arguments::length() - 1 - kTargetOffset);
|
| + }
|
| + Handle<HeapObject> new_target() {
|
| + return Arguments::at<HeapObject>(Arguments::length() - 1 -
|
| + kNewTargetOffset);
|
| + }
|
| +
|
| + // Gets the total number of arguments including the receiver (but
|
| + // excluding extra arguments).
|
| + int length() const { return Arguments::length() - kNumExtraArgs; }
|
| +};
|
| +
|
| +// ----------------------------------------------------------------------------
|
| +// Support macro for defining builtins in C++.
|
| +// ----------------------------------------------------------------------------
|
| +//
|
| +// A builtin function is defined by writing:
|
| +//
|
| +// BUILTIN(name) {
|
| +// ...
|
| +// }
|
| +//
|
| +// In the body of the builtin function the arguments can be accessed
|
| +// through the BuiltinArguments object args.
|
| +// TODO(cbruni): add global flag to check whether any tracing events have been
|
| +// enabled.
|
| +#define BUILTIN(name) \
|
| + MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args, \
|
| + Isolate* isolate); \
|
| + \
|
| + V8_NOINLINE static Object* Builtin_Impl_Stats_##name( \
|
| + int args_length, Object** args_object, Isolate* isolate) { \
|
| + BuiltinArguments args(args_length, args_object); \
|
| + RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Builtin_##name); \
|
| + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
|
| + "V8.Builtin_" #name); \
|
| + return Builtin_Impl_##name(args, isolate); \
|
| + } \
|
| + \
|
| + MUST_USE_RESULT Object* Builtin_##name( \
|
| + int args_length, Object** args_object, Isolate* isolate) { \
|
| + DCHECK(isolate->context() == nullptr || isolate->context()->IsContext()); \
|
| + if (FLAG_runtime_call_stats) { \
|
| + return Builtin_Impl_Stats_##name(args_length, args_object, isolate); \
|
| + } \
|
| + BuiltinArguments args(args_length, args_object); \
|
| + return Builtin_Impl_##name(args, isolate); \
|
| + } \
|
| + \
|
| + MUST_USE_RESULT static Object* Builtin_Impl_##name(BuiltinArguments args, \
|
| + Isolate* isolate)
|
| +
|
| +// ----------------------------------------------------------------------------
|
| +
|
| +#define CHECK_RECEIVER(Type, name, method) \
|
| + if (!args.receiver()->Is##Type()) { \
|
| + THROW_NEW_ERROR_RETURN_FAILURE( \
|
| + isolate, \
|
| + NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, \
|
| + isolate->factory()->NewStringFromAsciiChecked(method), \
|
| + args.receiver())); \
|
| + } \
|
| + Handle<Type> name = Handle<Type>::cast(args.receiver())
|
| +
|
| +// Throws a TypeError for {method} if the receiver is not coercible to Object,
|
| +// or converts the receiver to a String otherwise and assigns it to a new var
|
| +// with the given {name}.
|
| +#define TO_THIS_STRING(name, method) \
|
| + if (args.receiver()->IsNull(isolate) || \
|
| + args.receiver()->IsUndefined(isolate)) { \
|
| + THROW_NEW_ERROR_RETURN_FAILURE( \
|
| + isolate, \
|
| + NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, \
|
| + isolate->factory()->NewStringFromAsciiChecked(method))); \
|
| + } \
|
| + Handle<String> name; \
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION( \
|
| + isolate, name, Object::ToString(isolate, args.receiver()))
|
| +
|
| +} // namespace internal
|
| +} // namespace v8
|
| +
|
| +#endif // V8_BUILTINS_BUILTINS_UTILS_H_
|
|
|