1958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Copyright 2012 the V8 project authors. All rights reserved. 2958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Use of this source code is governed by a BSD-style license that can be 3958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// found in the LICENSE file. 4958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 5958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime.h" 6014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 7014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/assembler.h" 8f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch#include "src/base/hashmap.h" 9014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/contexts.h" 10014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/handles-inl.h" 11014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/heap/heap.h" 12014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#include "src/isolate.h" 1362ed631aa0ff23db68a47fd423efa9c019ff2c9eBen Murdoch#include "src/objects-inl.h" 14958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#include "src/runtime/runtime-utils.h" 15958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 16958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace v8 { 17958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniernamespace internal { 18958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 19958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier// Header of runtime functions. 20958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define F(name, number_of_args, result_size) \ 21958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Object* Runtime_##name(int args_length, Object** args_object, \ 22958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate); 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFOR_EACH_INTRINSIC_RETURN_OBJECT(F) 24014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#undef F 25958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 26958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define P(name, number_of_args, result_size) \ 27958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier ObjectPair Runtime_##name(int args_length, Object** args_object, \ 28958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Isolate* isolate); 29014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben MurdochFOR_EACH_INTRINSIC_RETURN_PAIR(P) 30958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef P 31958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 32109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#define T(name, number_of_args, result_size) \ 33109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch ObjectTriple Runtime_##name(int args_length, Object** args_object, \ 34109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch Isolate* isolate); 35109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben MurdochFOR_EACH_INTRINSIC_RETURN_TRIPLE(T) 36109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch#undef T 37109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 38958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 39958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#define F(name, number_of_args, result_size) \ 40958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier { \ 41958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \ 42958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier number_of_args, result_size \ 43958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } \ 44958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier , 45958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 46958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 47014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch#define I(name, number_of_args, result_size) \ 48014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch { \ 49014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Runtime::kInline##name, Runtime::INLINE, "_" #name, \ 50014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \ 51014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } \ 52958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier , 53958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 54958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic const Runtime::Function kIntrinsicFunctions[] = { 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FOR_EACH_INTRINSIC(F) 56014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FOR_EACH_INTRINSIC(I) 57014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch}; 58958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 59958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef I 60958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier#undef F 61958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 62f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochnamespace { 63958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 64f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben MurdochV8_DECLARE_ONCE(initialize_function_name_map_once); 65f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstatic const base::CustomMatcherHashMap* kRuntimeFunctionNameMap; 66f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 67f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochstruct IntrinsicFunctionIdentifier { 68f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntrinsicFunctionIdentifier(const unsigned char* data, const int length) 69f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch : data_(data), length_(length) {} 70f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 71f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static bool Match(void* key1, void* key2) { 72f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const IntrinsicFunctionIdentifier* lhs = 73f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static_cast<IntrinsicFunctionIdentifier*>(key1); 74f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const IntrinsicFunctionIdentifier* rhs = 75f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static_cast<IntrinsicFunctionIdentifier*>(key2); 76f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (lhs->length_ != rhs->length_) return false; 77f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_), 78f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch reinterpret_cast<const uint8_t*>(rhs->data_), 79f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch rhs->length_) == 0; 80f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 81f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 82f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch uint32_t Hash() { 83f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return StringHasher::HashSequentialString<uint8_t>( 84f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch data_, length_, v8::internal::kZeroHashSeed); 85958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 86958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 87f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const unsigned char* data_; 88f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const int length_; 89f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch}; 90f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 91f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochvoid InitializeIntrinsicFunctionNames() { 92f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::CustomMatcherHashMap* function_name_map = 93f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match); 94f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) { 95f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch const Runtime::Function* function = &kIntrinsicFunctions[i]; 96f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier( 97f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch reinterpret_cast<const unsigned char*>(function->name), 98f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch static_cast<int>(strlen(function->name))); 99f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::HashMap::Entry* entry = 100f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch function_name_map->InsertNew(identifier, identifier->Hash()); 101f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch entry->value = const_cast<Runtime::Function*>(function); 102f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch } 103f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kRuntimeFunctionNameMap = function_name_map; 104f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} 105958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 106f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch} // namespace 107f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch 108f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdochconst Runtime::Function* Runtime::FunctionForName(const unsigned char* name, 109f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch int length) { 110f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::CallOnce(&initialize_function_name_map_once, 111f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch &InitializeIntrinsicFunctionNames); 112f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch IntrinsicFunctionIdentifier identifier(name, length); 113f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch base::HashMap::Entry* entry = 114f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash()); 115f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch if (entry) { 116f3b273f5e6ffd2f6ba1c18a27a17db41dfb113c3Ben Murdoch return reinterpret_cast<Function*>(entry->value); 117958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 118958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return NULL; 119958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 120958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 121958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 122958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst Runtime::Function* Runtime::FunctionForEntry(Address entry) { 123958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) { 124958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier if (entry == kIntrinsicFunctions[i].entry) { 125958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return &(kIntrinsicFunctions[i]); 126958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 127958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier } 128958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return NULL; 129958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 130958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 131958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 132958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierconst Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { 133958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return &(kIntrinsicFunctions[static_cast<int>(id)]); 134958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 135958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 136958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 137014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochconst Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) { 138014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (isolate->external_reference_redirector()) { 139014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // When running with the simulator we need to provide a table which has 140014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // redirected runtime entry addresses. 141014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (!isolate->runtime_state()->redirected_intrinsic_functions()) { 142014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch size_t function_count = arraysize(kIntrinsicFunctions); 143014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Function* redirected_functions = new Function[function_count]; 144014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch memcpy(redirected_functions, kIntrinsicFunctions, 145014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch sizeof(kIntrinsicFunctions)); 146014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch for (size_t i = 0; i < function_count; i++) { 147014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch ExternalReference redirected_entry(static_cast<Runtime::FunctionId>(i), 148014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate); 149014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch redirected_functions[i].entry = redirected_entry.address(); 150014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 151014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch isolate->runtime_state()->set_redirected_intrinsic_functions( 152014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch redirected_functions); 153014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 154014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 155014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return isolate->runtime_state()->redirected_intrinsic_functions(); 156014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 157014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch return kIntrinsicFunctions; 158014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 159014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 162958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstd::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) { 163958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier return os << Runtime::FunctionForId(id)->name; 164958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 165958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 166109988c7ccb6f3fd1a58574fa3dfb88beaef6632Ben Murdoch 167958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} // namespace internal 168958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} // namespace v8 169