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