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