// 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/heap/factory.h"
#include "src/isolate.h"

namespace v8 {
namespace internal {

// Arguments object passed to C++ builtins.
class BuiltinArguments : public Arguments {
 public:
  BuiltinArguments(int length, Address* arguments)
      : Arguments(length, arguments) {
    // Check we have at least the receiver.
    DCHECK_LE(1, this->length());
  }

  ObjectPtr operator[](int index) {
    DCHECK_LT(index, length());
    return Arguments::operator[](index);
  }

  template <class S = Object>
  Handle<S> at(int index) {
    DCHECK_LT(index, length());
    return Arguments::at<S>(index);
  }

  static constexpr int kNewTargetOffset = 0;
  static constexpr int kTargetOffset = 1;
  static constexpr int kArgcOffset = 2;
  static constexpr int kPaddingOffset = 3;

  static constexpr int kNumExtraArgs = 4;
  static constexpr int kNumExtraArgsWithReceiver = 5;

  inline Handle<Object> atOrUndefined(Isolate* isolate, int index);
  inline Handle<Object> receiver();
  inline Handle<JSFunction> target();
  inline Handle<HeapObject> new_target();

  // 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)                                                        \
  V8_WARN_UNUSED_RESULT static Object* Builtin_Impl_##name(                  \
      BuiltinArguments args, Isolate* isolate);                              \
                                                                             \
  V8_NOINLINE static Object* Builtin_Impl_Stats_##name(                      \
      int args_length, Address* args_object, Isolate* isolate) {             \
    BuiltinArguments args(args_length, args_object);                         \
    RuntimeCallTimerScope timer(isolate,                                     \
                                RuntimeCallCounterId::kBuiltin_##name);      \
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                    \
                 "V8.Builtin_" #name);                                       \
    return Builtin_Impl_##name(args, isolate);                               \
  }                                                                          \
                                                                             \
  V8_WARN_UNUSED_RESULT Object* Builtin_##name(                              \
      int args_length, Address* args_object, Isolate* isolate) {             \
    DCHECK(isolate->context().is_null() || isolate->context()->IsContext()); \
    if (V8_UNLIKELY(FLAG_runtime_stats)) {                                   \
      return Builtin_Impl_Stats_##name(args_length, args_object, isolate);   \
    }                                                                        \
    BuiltinArguments args(args_length, args_object);                         \
    return Builtin_Impl_##name(args, isolate);                               \
  }                                                                          \
                                                                             \
  V8_WARN_UNUSED_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()->IsNullOrUndefined(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_
