| // Copyright 2012 the V8 project authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "src/runtime/runtime.h" | |
| #include "src/base/hashmap.h" | |
| #include "src/contexts.h" | |
| #include "src/handles-inl.h" | |
| #include "src/heap/heap.h" | |
| #include "src/isolate.h" | |
| #include "src/objects-inl.h" | |
| #include "src/reloc-info.h" | |
| #include "src/runtime/runtime-utils.h" | |
| namespace v8 { | |
| namespace internal { | |
| // Header of runtime functions. | |
| #define F(name, number_of_args, result_size) \ | |
| Object* Runtime_##name(int args_length, Object** args_object, \ | |
| Isolate* isolate); | |
| FOR_EACH_INTRINSIC_RETURN_OBJECT(F) | |
| #undef F | |
| #define P(name, number_of_args, result_size) \ | |
| ObjectPair Runtime_##name(int args_length, Object** args_object, \ | |
| Isolate* isolate); | |
| FOR_EACH_INTRINSIC_RETURN_PAIR(P) | |
| #undef P | |
| #define F(name, number_of_args, result_size) \ | |
| { \ | |
| Runtime::k##name, Runtime::RUNTIME, #name, FUNCTION_ADDR(Runtime_##name), \ | |
| number_of_args, result_size \ | |
| } \ | |
| , | |
| #define I(name, number_of_args, result_size) \ | |
| { \ | |
| Runtime::kInline##name, Runtime::INLINE, "_" #name, \ | |
| FUNCTION_ADDR(Runtime_##name), number_of_args, result_size \ | |
| } \ | |
| , | |
| static const Runtime::Function kIntrinsicFunctions[] = { | |
| FOR_EACH_INTRINSIC(F) | |
| FOR_EACH_INTRINSIC(I) | |
| }; | |
| #undef I | |
| #undef F | |
| namespace { | |
| V8_DECLARE_ONCE(initialize_function_name_map_once); | |
| static const base::CustomMatcherHashMap* kRuntimeFunctionNameMap; | |
| struct IntrinsicFunctionIdentifier { | |
| IntrinsicFunctionIdentifier(const unsigned char* data, const int length) | |
| : data_(data), length_(length) {} | |
| static bool Match(void* key1, void* key2) { | |
| const IntrinsicFunctionIdentifier* lhs = | |
| static_cast<IntrinsicFunctionIdentifier*>(key1); | |
| const IntrinsicFunctionIdentifier* rhs = | |
| static_cast<IntrinsicFunctionIdentifier*>(key2); | |
| if (lhs->length_ != rhs->length_) return false; | |
| return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs->data_), | |
| reinterpret_cast<const uint8_t*>(rhs->data_), | |
| rhs->length_) == 0; | |
| } | |
| uint32_t Hash() { | |
| return StringHasher::HashSequentialString<uint8_t>( | |
| data_, length_, v8::internal::kZeroHashSeed); | |
| } | |
| const unsigned char* data_; | |
| const int length_; | |
| }; | |
| void InitializeIntrinsicFunctionNames() { | |
| base::CustomMatcherHashMap* function_name_map = | |
| new base::CustomMatcherHashMap(IntrinsicFunctionIdentifier::Match); | |
| for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) { | |
| const Runtime::Function* function = &kIntrinsicFunctions[i]; | |
| IntrinsicFunctionIdentifier* identifier = new IntrinsicFunctionIdentifier( | |
| reinterpret_cast<const unsigned char*>(function->name), | |
| static_cast<int>(strlen(function->name))); | |
| base::HashMap::Entry* entry = | |
| function_name_map->InsertNew(identifier, identifier->Hash()); | |
| entry->value = const_cast<Runtime::Function*>(function); | |
| } | |
| kRuntimeFunctionNameMap = function_name_map; | |
| } | |
| } // namespace | |
| bool Runtime::IsNonReturning(FunctionId id) { | |
| switch (id) { | |
| case Runtime::kThrowUnsupportedSuperError: | |
| case Runtime::kThrowConstructorNonCallableError: | |
| case Runtime::kThrowStaticPrototypeError: | |
| case Runtime::kThrowSuperAlreadyCalledError: | |
| case Runtime::kThrowSuperNotCalled: | |
| case Runtime::kReThrow: | |
| case Runtime::kThrow: | |
| case Runtime::kThrowApplyNonFunction: | |
| case Runtime::kThrowCalledNonCallable: | |
| case Runtime::kThrowConstructedNonConstructable: | |
| case Runtime::kThrowConstructorReturnedNonObject: | |
| case Runtime::kThrowInvalidStringLength: | |
| case Runtime::kThrowInvalidTypedArrayAlignment: | |
| case Runtime::kThrowIteratorResultNotAnObject: | |
| case Runtime::kThrowThrowMethodMissing: | |
| case Runtime::kThrowSymbolIteratorInvalid: | |
| case Runtime::kThrowNotConstructor: | |
| case Runtime::kThrowRangeError: | |
| case Runtime::kThrowReferenceError: | |
| case Runtime::kThrowStackOverflow: | |
| case Runtime::kThrowSymbolAsyncIteratorInvalid: | |
| case Runtime::kThrowTypeError: | |
| case Runtime::kThrowConstAssignError: | |
| case Runtime::kThrowWasmError: | |
| case Runtime::kThrowWasmStackOverflow: | |
| return true; | |
| default: | |
| return false; | |
| } | |
| } | |
| const Runtime::Function* Runtime::FunctionForName(const unsigned char* name, | |
| int length) { | |
| base::CallOnce(&initialize_function_name_map_once, | |
| &InitializeIntrinsicFunctionNames); | |
| IntrinsicFunctionIdentifier identifier(name, length); | |
| base::HashMap::Entry* entry = | |
| kRuntimeFunctionNameMap->Lookup(&identifier, identifier.Hash()); | |
| if (entry) { | |
| return reinterpret_cast<Function*>(entry->value); | |
| } | |
| return nullptr; | |
| } | |
| const Runtime::Function* Runtime::FunctionForEntry(Address entry) { | |
| for (size_t i = 0; i < arraysize(kIntrinsicFunctions); ++i) { | |
| if (entry == kIntrinsicFunctions[i].entry) { | |
| return &(kIntrinsicFunctions[i]); | |
| } | |
| } | |
| return nullptr; | |
| } | |
| const Runtime::Function* Runtime::FunctionForId(Runtime::FunctionId id) { | |
| return &(kIntrinsicFunctions[static_cast<int>(id)]); | |
| } | |
| const Runtime::Function* Runtime::RuntimeFunctionTable(Isolate* isolate) { | |
| #ifdef USE_SIMULATOR | |
| // When running with the simulator we need to provide a table which has | |
| // redirected runtime entry addresses. | |
| if (!isolate->runtime_state()->redirected_intrinsic_functions()) { | |
| size_t function_count = arraysize(kIntrinsicFunctions); | |
| Function* redirected_functions = new Function[function_count]; | |
| memcpy(redirected_functions, kIntrinsicFunctions, | |
| sizeof(kIntrinsicFunctions)); | |
| for (size_t i = 0; i < function_count; i++) { | |
| ExternalReference redirected_entry = | |
| ExternalReference::Create(static_cast<Runtime::FunctionId>(i)); | |
| redirected_functions[i].entry = redirected_entry.address(); | |
| } | |
| isolate->runtime_state()->set_redirected_intrinsic_functions( | |
| redirected_functions); | |
| } | |
| return isolate->runtime_state()->redirected_intrinsic_functions(); | |
| #else | |
| return kIntrinsicFunctions; | |
| #endif | |
| } | |
| std::ostream& operator<<(std::ostream& os, Runtime::FunctionId id) { | |
| return os << Runtime::FunctionForId(id)->name; | |
| } | |
| } // namespace internal | |
| } // namespace v8 |