Home | History | Annotate | Download | only in runtime
      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 #include "src/runtime/runtime.h"
      6 
      7 #include "src/assembler.h"
      8 #include "src/base/hashmap.h"
      9 #include "src/contexts.h"
     10 #include "src/handles-inl.h"
     11 #include "src/heap/heap.h"
     12 #include "src/isolate.h"
     13 #include "src/objects-inl.h"
     14 #include "src/runtime/runtime-utils.h"
     15 
     16 namespace v8 {
     17 namespace internal {
     18 
     19 // Header of runtime functions.
     20 #define F(name, number_of_args, result_size)                    \
     21   Object* Runtime_##name(int args_length, Object** args_object, \
     22                          Isolate* isolate);
     23 FOR_EACH_INTRINSIC_RETURN_OBJECT(F)
     24 #undef F
     25 
     26 #define P(name, number_of_args, result_size)                       \
     27   ObjectPair Runtime_##name(int args_length, Object** args_object, \
     28                             Isolate* isolate);
     29 FOR_EACH_INTRINSIC_RETURN_PAIR(P)
     30 #undef P
     31 
     32 #define T(name, number_of_args, result_size)                         \
     33   ObjectTriple Runtime_##name(int args_length, Object** args_object, \
     34                               Isolate* isolate);
     35 FOR_EACH_INTRINSIC_RETURN_TRIPLE(T)
     36 #undef T
     37 
     38 
     39 #define F(name, number_of_args, result_size)                                  \
     40   {                                                                           \
     41     Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \
     42         number_of_args, result_size                                           \
     43   }                                                                           \
     44   ,
     45 
     46 
     47 #define I(name, number_of_args, result_size)                       \
     48   {                                                                \
     49     Runtime::kInline##name, Runtime::INLINE, "_" #name,            \
     50         FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \
     51   }                                                                \
     52   ,
     53 
     54 static const Runtime::Function kIntrinsicFunctions[] = {
     55   FOR_EACH_INTRINSIC(F)
     56   FOR_EACH_INTRINSIC(I)
     57 };
     58 
     59 #undef I
     60 #undef F
     61 
     62 namespace {
     63 
     64 V8_DECLARE_ONCE(initialize_function_name_map_once);
     65 static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap;
     66 
     67 struct IntrinsicFunctionIdentifier {
     68   IntrinsicFunctionIdentifier(const unsigned char* data, const int length)
     69       : data_(data), length_(length) {}
     70 
     71   static bool Match(void* key1, void* key2) {
     72     const IntrinsicFunctionIdentifier* lhs =
     73         static_cast<IntrinsicFunctionIdentifier*>(key1);
     74     const IntrinsicFunctionIdentifier* rhs =
     75         static_cast<IntrinsicFunctionIdentifier*>(key2);
     76     if (lhs->length_ != rhs->length_) return false;
     77     return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_),
     78                                 reinterpret_cast<const uint8_t*>(rhs->data_),
     79                                 rhs->length_) == 0;
     80   }
     81 
     82   uint32_t Hash() {
     83     return StringHasher::HashSequentialString<uint8_t>(
     84         data_, length_, v8::internal::kZeroHashSeed);
     85   }
     86 
     87   const unsigned char* data_;
     88   const int length_;
     89 };
     90 
     91 void InitializeIntrinsicFunctionNames() {
     92   base::CustomMatcherHashMap* function_name_map =
     93       new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match);
     94   for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
     95     const Runtime::Function* function = &kIntrinsicFunctions[i];
     96     IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier(
     97         reinterpret_cast<const unsigned char*>(function->name),
     98         static_cast<int>(strlen(function->name)));
     99     base::HashMap::Entry* entry =
    100         function_name_map->InsertNew(identifier, identifier->Hash());
    101     entry->value = const_cast<Runtime::Function*>(function);
    102   }
    103   kRuntimeFunctionNameMap = function_name_map;
    104 }
    105 
    106 }  // namespace
    107 
    108 const Runtime::Function* Runtime::FunctionForName(const unsigned char* name,
    109                                                   int length) {
    110   base::CallOnce(&initialize_function_name_map_once,
    111                  &InitializeIntrinsicFunctionNames);
    112   IntrinsicFunctionIdentifier identifier(name, length);
    113   base::HashMap::Entry* entry =
    114       kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash());
    115   if (entry) {
    116     return reinterpret_cast<Function*>(entry->value);
    117   }
    118   return NULL;
    119 }
    120 
    121 
    122 const Runtime::Function* Runtime::FunctionForEntry(Address entry) {
    123   for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) {
    124     if (entry == kIntrinsicFunctions[i].entry) {
    125       return &(kIntrinsicFunctions[i]);
    126     }
    127   }
    128   return NULL;
    129 }
    130 
    131 
    132 const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) {
    133   return &(kIntrinsicFunctions[static_cast<int>(id)]);
    134 }
    135 
    136 
    137 const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) {
    138   if (isolate->external_reference_redirector()) {
    139     // When running with the simulator we need to provide a table which has
    140     // redirected runtime entry addresses.
    141     if (!isolate->runtime_state()->redirected_intrinsic_functions()) {
    142       size_t function_count = arraysize(kIntrinsicFunctions);
    143       Function* redirected_functions = new Function[function_count];
    144       memcpy(redirected_functions, kIntrinsicFunctions,
    145              sizeof(kIntrinsicFunctions));
    146       for (size_t i = 0; i < function_count; i++) {
    147         ExternalReference redirected_entry(static_cast<Runtime::FunctionId>(i),
    148                                            isolate);
    149         redirected_functions[i].entry = redirected_entry.address();
    150       }
    151       isolate->runtime_state()->set_redirected_intrinsic_functions(
    152           redirected_functions);
    153     }
    154 
    155     return isolate->runtime_state()->redirected_intrinsic_functions();
    156   } else {
    157     return kIntrinsicFunctions;
    158   }
    159 }
    160 
    161 
    162 std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) {
    163   return os << Runtime::FunctionForId(id)->name;
    164 }
    165 
    166 
    167 }  // namespace internal
    168 }  // namespace v8
    169