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
12 namespace v8 {
13 namespace 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
30 class Arguments BASE_EMBEDDED {
31 public:
Arguments(int length,Object ** arguments)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 inline Handle<S> at(int index);
46
47 inline int smi_at(int index);
48
49 inline double number_at(int index);
50
51 // Get the total number of arguments including the receiver.
length()52 int length() const { return static_cast<int>(length_); }
53
arguments()54 Object** arguments() { return arguments_; }
55
lowest_address()56 Object** lowest_address() { return &this->operator[](length() - 1); }
57
highest_address()58 Object** highest_address() { return &this->operator[](0); }
59
60 private:
61 intptr_t length_;
62 Object** arguments_;
63 };
64
65 template <>
at(int index)66 inline Handle<Object> Arguments::at(int index) {
67 Object** value = &((*this)[index]);
68 return Handle<Object>(value);
69 }
70
71 double ClobberDoubleRegisters(double x1, double x2, double x3, double x4);
72
73 #ifdef DEBUG
74 #define CLOBBER_DOUBLE_REGISTERS() ClobberDoubleRegisters(1, 2, 3, 4);
75 #else
76 #define CLOBBER_DOUBLE_REGISTERS()
77 #endif
78
79 // TODO(cbruni): add global flag to check whether any tracing events have been
80 // enabled.
81 #define RUNTIME_FUNCTION_RETURNS_TYPE(Type, Name) \
82 static V8_INLINE Type __RT_impl_##Name(Arguments args, Isolate* isolate); \
83 \
84 V8_NOINLINE static Type Stats_##Name(int args_length, Object** args_object, \
85 Isolate* isolate) { \
86 RuntimeCallTimerScope timer(isolate, RuntimeCallCounterId::k##Name); \
87 TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.runtime"), \
88 "V8.Runtime_" #Name); \
89 Arguments args(args_length, args_object); \
90 return __RT_impl_##Name(args, isolate); \
91 } \
92 \
93 Type Name(int args_length, Object** args_object, Isolate* isolate) { \
94 DCHECK(isolate->context() == nullptr || isolate->context()->IsContext()); \
95 CLOBBER_DOUBLE_REGISTERS(); \
96 if (V8_UNLIKELY(FLAG_runtime_stats)) { \
97 return Stats_##Name(args_length, args_object, isolate); \
98 } \
99 Arguments args(args_length, args_object); \
100 return __RT_impl_##Name(args, isolate); \
101 } \
102 \
103 static Type __RT_impl_##Name(Arguments args, Isolate* isolate)
104
105 #define RUNTIME_FUNCTION(Name) RUNTIME_FUNCTION_RETURNS_TYPE(Object*, Name)
106 #define RUNTIME_FUNCTION_RETURN_PAIR(Name) \
107 RUNTIME_FUNCTION_RETURNS_TYPE(ObjectPair, Name)
108
109 } // namespace internal
110 } // namespace v8
111
112 #endif // V8_ARGUMENTS_H_
113