1// Copyright 2012 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_ARGUMENTS_H_
6#define V8_ARGUMENTS_H_
7
8#include "src/allocation.h"
9#include "src/objects.h"
10#include "src/tracing/trace-event.h"
11
12namespace v8 {
13namespace internal {
14
15// Arguments provides access to runtime call parameters.
16//
17// It uses the fact that the instance fields of Arguments
18// (length_, arguments_) are "overlayed" with the parameters
19// (no. of parameters, and the parameter pointer) passed so
20// that inside the C++ function, the parameters passed can
21// be accessed conveniently:
22//
23//   Object* Runtime_function(Arguments args) {
24//     ... use args[i] here ...
25//   }
26//
27// Note that length_ (whose value is in the integer range) is defined
28// as intptr_t to provide endian-neutrality on 64-bit archs.
29
30class Arguments BASE_EMBEDDED {
31 public:
32  Arguments(int length, Object** arguments)
33      : length_(length), arguments_(arguments) {
34    DCHECK_GE(length_, 0);
35  }
36
37  Object*& operator[] (int index) {
38    DCHECK_GE(index, 0);
39    DCHECK_LT(static_cast<uint32_t>(index), static_cast<uint32_t>(length_));
40    return *(reinterpret_cast<Object**>(reinterpret_cast<intptr_t>(arguments_) -
41                                        index * kPointerSize));
42  }
43
44  template <class S = Object>
45  Handle<S> at(int index) {
46    Object** value = &((*this)[index]);
47    // This cast checks that the object we're accessing does indeed have the
48    // expected type.
49    S::cast(*value);
50    return Handle<S>(reinterpret_cast<S**>(value));
51  }
52
53  int smi_at(int index) {
54    return Smi::cast((*this)[index])->value();
55  }
56
57  double number_at(int index) {
58    return (*this)[index]->Number();
59  }
60
61  // Get the total number of arguments including the receiver.
62  int length() const { return static_cast<int>(length_); }
63
64  Object** arguments() { return arguments_; }
65
66  Object** lowest_address() { return &this->operator[](length() - 1); }
67
68  Object** highest_address() { return &this->operator[](0); }
69
70 private:
71  intptr_t length_;
72  Object** arguments_;
73};
74
75double ClobberDoubleRegisters(double x1, double x2, double x3, double x4);
76
77#ifdef DEBUG
78#define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4);
79#else
80#define CLOBBER_DOUBLE_REGISTERS()
81#endif
82
83// TODO(cbruni): add global flag to check whether any tracing events have been
84// enabled.
85#define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name)                             \
86  static INLINE(Type __RT_impl_##Name(Arguments args, Isolate* isolate));     \
87                                                                              \
88  V8_NOINLINE static Type Stats_##Name(int args_length, Object** args_object, \
89                                       Isolate* isolate) {                    \
90    RuntimeCallTimerScope timer(isolate, &RuntimeCallStats::Name);            \
91    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"),                     \
92                 "V8.Runtime_" #Name);                                        \
93    Arguments args(args_length, args_object);                                 \
94    return __RT_impl_##Name(args, isolate);                                   \
95  }                                                                           \
96                                                                              \
97  Type Name(int args_length, Object** args_object, Isolate* isolate) {        \
98    DCHECK(isolate->context() == nullptr || isolate->context()->IsContext()); \
99    CLOBBER_DOUBLE_REGISTERS();                                               \
100    if (V8_UNLIKELY(FLAG_runtime_stats)) {                                    \
101      return Stats_##Name(args_length, args_object, isolate);                 \
102    }                                                                         \
103    Arguments args(args_length, args_object);                                 \
104    return __RT_impl_##Name(args, isolate);                                   \
105  }                                                                           \
106                                                                              \
107  static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
108
109#define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name)
110#define RUNTIME_FUNCTION_RETURN_PAIR(Name) \
111    RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name)
112#define RUNTIME_FUNCTION_RETURN_TRIPLE(Name) \
113    RUNTIME_FUNCTION_RETURNS_TYPE(ObjectTriple, Name)
114
115}  // namespace internal
116}  // namespace v8
117
118#endif  // V8_ARGUMENTS_H_
119