blob: 96f6ca92018c9b6c7cc0c02bdd3e261c245a27b3 [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// 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 <typename T>
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 TKey, class TValue>
class SimpleDictionaryEntryWithFixUp : public JsUtil::SimpleDictionaryEntry<TKey, TValue>
{
public:
void FixupWithRemoteKey(void* remoteKey)
{
this->key = (TKey)remoteKey;
}
};
typedef JsUtil::BaseDictionary<T, void*, DictAllocator, PowerOf2SizePolicy, DefaultComparer, SimpleDictionaryEntryWithFixUp> 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<Js::JavascriptString*>* 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
};