//------------------------------------------------------------------------------------------------------- // Copyright (C) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. //------------------------------------------------------------------------------------------------------- #pragma once namespace Js { #if ENABLE_NATIVE_CODEGEN template class BranchDictionaryWrapper { public: class DictAllocator :public NativeCodeData::Allocator { public: char * Alloc(size_t requestedBytes) { char* dataBlock = __super::Alloc(requestedBytes); #if DBG if (JITManager::GetJITManager()->IsJITServer()) { NativeCodeData::DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock); chunk->dataType = "BranchDictionary::Bucket"; if (PHASE_TRACE1(Js::NativeCodeDataPhase)) { Output::Print(_u("NativeCodeData BranchDictionary::Bucket: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"), chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType); } } #endif return dataBlock; } char * AllocZero(size_t requestedBytes) { char* dataBlock = __super::AllocZero(requestedBytes); #if DBG if (JITManager::GetJITManager()->IsJITServer()) { NativeCodeData::DataChunk* chunk = NativeCodeData::GetDataChunk(dataBlock); chunk->dataType = "BranchDictionary::Entries"; if (PHASE_TRACE1(Js::NativeCodeDataPhase)) { Output::Print(_u("NativeCodeData BranchDictionary::Entries: chunk: %p, data: %p, index: %d, len: %x, totalOffset: %x, type: %S\n"), chunk, (void*)dataBlock, chunk->allocIndex, chunk->len, chunk->offset, chunk->dataType); } } #endif return dataBlock; } }; template class SimpleDictionaryEntryWithFixUp : public JsUtil::SimpleDictionaryEntry { public: void FixupWithRemoteKey(void* remoteKey) { this->key = (TKey)remoteKey; } }; typedef JsUtil::BaseDictionary BranchBaseDictionary; class BranchDictionary :public BranchBaseDictionary { public: BranchDictionary(DictAllocator* allocator, uint dictionarySize) : BranchBaseDictionary(allocator, dictionarySize) { } void Fixup(NativeCodeData::DataChunk* chunkList, void** remoteKeys) { for (int i = 0; i < this->Count(); i++) { this->entries[i].FixupWithRemoteKey(remoteKeys[i]); } FixupNativeDataPointer(buckets, chunkList); FixupNativeDataPointer(entries, chunkList); } }; BranchDictionaryWrapper(NativeCodeData::Allocator * allocator, uint dictionarySize, ArenaAllocator* remoteKeyAlloc) : defaultTarget(nullptr), dictionary((DictAllocator*)allocator, dictionarySize) { if (remoteKeyAlloc) { remoteKeys = AnewArrayZ(remoteKeyAlloc, void*, dictionarySize); } else { Assert(!JITManager::GetJITManager()->IsJITServer()); remoteKeys = nullptr; } } BranchDictionary dictionary; void* defaultTarget; void** remoteKeys; static BranchDictionaryWrapper* New(NativeCodeData::Allocator * allocator, uint dictionarySize, ArenaAllocator* remoteKeyAlloc) { return NativeCodeDataNew(allocator, BranchDictionaryWrapper, allocator, dictionarySize, remoteKeyAlloc); } void AddEntry(uint32 offset, T key, void* remoteVar) { int index = dictionary.AddNew(key, (void**)offset); if (JITManager::GetJITManager()->IsJITServer()) { Assert(remoteKeys); remoteKeys[index] = remoteVar; } } void Fixup(NativeCodeData::DataChunk* chunkList) { if (JITManager::GetJITManager()->IsJITServer()) { dictionary.Fixup(chunkList, remoteKeys); } } }; class JavascriptNativeOperators { public: static void * Op_SwitchStringLookUp(JavascriptString* str, Js::BranchDictionaryWrapper* stringDictionary, uintptr_t funcStart, uintptr_t funcEnd); #if ENABLE_DEBUG_CONFIG_OPTIONS static void TracePropertyEquivalenceCheck(const JitEquivalentTypeGuard* guard, const Type* type, const Type* refType, bool isEquivalent, uint failedPropertyIndex); #endif static bool CheckIfTypeIsEquivalent(Type* type, JitEquivalentTypeGuard* guard); static bool CheckIfTypeIsEquivalentForFixedField(Type* type, JitEquivalentTypeGuard* guard); static bool CheckIfPolyTypeIsEquivalent(Type* type, JitPolyEquivalentTypeGuard* guard, uint8 index); static bool CheckIfPolyTypeIsEquivalentForFixedField(Type* type, JitPolyEquivalentTypeGuard* guard, uint8 index); static bool EquivalenceCheckHelper(Type* type, JitEquivalentTypeGuard* guard, intptr_t value); static Var OP_GetElementI_JIT_ExpectingNativeFloatArray(Var instance, Var index, ScriptContext *scriptContext); static Var OP_GetElementI_JIT_ExpectingVarArray(Var instance, Var index, ScriptContext *scriptContext); static Var OP_GetElementI_UInt32_ExpectingNativeFloatArray(Var instance, uint32 aElementIndex, ScriptContext* scriptContext); static Var OP_GetElementI_UInt32_ExpectingVarArray(Var instance, uint32 aElementIndex, ScriptContext* scriptContext); static Var OP_GetElementI_Int32_ExpectingNativeFloatArray(Var instance, int32 aElementIndex, ScriptContext* scriptContext); static Var OP_GetElementI_Int32_ExpectingVarArray(Var instance, int32 aElementIndex, ScriptContext* scriptContext); #if DBG static void IntRangeCheckFailure(); #endif private: static bool IsStaticTypeObjTypeSpecEquivalent(const TypeEquivalenceRecord& equivalenceRecord, uint& failedIndex); static bool IsStaticTypeObjTypeSpecEquivalent(const EquivalentPropertyEntry *entry); }; #endif };