// Copyright 2013 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.

#include "src/v8.h"

#include "src/arguments.h"
#include "src/vm-state-inl.h"

namespace v8 {
namespace internal {


template<typename T>
template<typename V>
v8::Handle<V> CustomArguments<T>::GetReturnValue(Isolate* isolate) {
  // Check the ReturnValue.
  Object** handle = &this->begin()[kReturnValueOffset];
  // Nothing was set, return empty handle as per previous behaviour.
  if ((*handle)->IsTheHole()) return v8::Handle<V>();
  return Utils::Convert<Object, V>(Handle<Object>(handle));
}


v8::Handle<v8::Value> FunctionCallbackArguments::Call(FunctionCallback f) {
  Isolate* isolate = this->isolate();
  VMState<EXTERNAL> state(isolate);
  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));
  FunctionCallbackInfo<v8::Value> info(begin(),
                                       argv_,
                                       argc_,
                                       is_construct_call_);
  f(info);
  return GetReturnValue<v8::Value>(isolate);
}


#define WRITE_CALL_0(Function, ReturnValue)                                    \
v8::Handle<ReturnValue> PropertyCallbackArguments::Call(Function f) {          \
  Isolate* isolate = this->isolate();                                          \
  VMState<EXTERNAL> state(isolate);                                            \
  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));                 \
  PropertyCallbackInfo<ReturnValue> info(begin());                             \
  f(info);                                                                     \
  return GetReturnValue<ReturnValue>(isolate);                                 \
}


#define WRITE_CALL_1(Function, ReturnValue, Arg1)                              \
v8::Handle<ReturnValue> PropertyCallbackArguments::Call(Function f,            \
                                                        Arg1 arg1) {           \
  Isolate* isolate = this->isolate();                                          \
  VMState<EXTERNAL> state(isolate);                                            \
  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));                 \
  PropertyCallbackInfo<ReturnValue> info(begin());                             \
  f(arg1, info);                                                               \
  return GetReturnValue<ReturnValue>(isolate);                                 \
}


#define WRITE_CALL_2(Function, ReturnValue, Arg1, Arg2)                        \
v8::Handle<ReturnValue> PropertyCallbackArguments::Call(Function f,            \
                                                        Arg1 arg1,             \
                                                        Arg2 arg2) {           \
  Isolate* isolate = this->isolate();                                          \
  VMState<EXTERNAL> state(isolate);                                            \
  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));                 \
  PropertyCallbackInfo<ReturnValue> info(begin());                             \
  f(arg1, arg2, info);                                                         \
  return GetReturnValue<ReturnValue>(isolate);                                 \
}


#define WRITE_CALL_2_VOID(Function, ReturnValue, Arg1, Arg2)                   \
void PropertyCallbackArguments::Call(Function f,                               \
                                     Arg1 arg1,                                \
                                     Arg2 arg2) {                              \
  Isolate* isolate = this->isolate();                                          \
  VMState<EXTERNAL> state(isolate);                                            \
  ExternalCallbackScope call_scope(isolate, FUNCTION_ADDR(f));                 \
  PropertyCallbackInfo<ReturnValue> info(begin());                             \
  f(arg1, arg2, info);                                                         \
}


FOR_EACH_CALLBACK_TABLE_MAPPING_0(WRITE_CALL_0)
FOR_EACH_CALLBACK_TABLE_MAPPING_1(WRITE_CALL_1)
FOR_EACH_CALLBACK_TABLE_MAPPING_2(WRITE_CALL_2)
FOR_EACH_CALLBACK_TABLE_MAPPING_2_VOID_RETURN(WRITE_CALL_2_VOID)

#undef WRITE_CALL_0
#undef WRITE_CALL_1
#undef WRITE_CALL_2
#undef WRITE_CALL_2_VOID


double ClobberDoubleRegisters(double x1, double x2, double x3, double x4) {
  // TODO(ulan): This clobbers only subset of registers depending on compiler,
  // Rewrite this in assembly to really clobber all registers.
  // GCC for ia32 uses the FPU and does not touch XMM registers.
  return x1 * 1.01 + x2 * 2.02 + x3 * 3.03 + x4 * 4.04;
}


} }  // namespace v8::internal
