#include "config.h"
#include "GetByIdStatus.h"
#include "CodeBlock.h"
#include "LowLevelInterpreter.h"
namespace JSC {
GetByIdStatus GetByIdStatus::computeFromLLInt(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(LLINT)
Instruction* instruction = profiledBlock->instructions().begin() + bytecodeIndex;
if (instruction[0].u.opcode == llint_op_method_check)
instruction++;
Structure* structure = instruction[4].u.structure.get();
if (!structure)
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
size_t offset = structure->get(*profiledBlock->globalData(), ident);
if (offset == notFound)
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
return GetByIdStatus(SimpleDirect, StructureSet(structure), offset, false);
#else
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
#endif
}
GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, unsigned bytecodeIndex, Identifier& ident)
{
UNUSED_PARAM(profiledBlock);
UNUSED_PARAM(bytecodeIndex);
UNUSED_PARAM(ident);
#if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
if (!profiledBlock->numberOfStructureStubInfos())
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
StructureStubInfo& stubInfo = profiledBlock->getStubInfo(bytecodeIndex);
if (!stubInfo.seen)
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
PolymorphicAccessStructureList* list;
int listSize;
switch (stubInfo.accessType) {
case access_get_by_id_self_list:
list = stubInfo.u.getByIdSelfList.structureList;
listSize = stubInfo.u.getByIdSelfList.listSize;
break;
case access_get_by_id_proto_list:
list = stubInfo.u.getByIdProtoList.structureList;
listSize = stubInfo.u.getByIdProtoList.listSize;
break;
default:
list = 0;
listSize = 0;
break;
}
for (int i = 0; i < listSize; ++i) {
if (!list->list[i].isDirect)
return GetByIdStatus(MakesCalls, StructureSet(), notFound, true);
}
if (profiledBlock->likelyToTakeSlowCase(bytecodeIndex))
return GetByIdStatus(TakesSlowPath, StructureSet(), notFound, true);
GetByIdStatus result;
result.m_wasSeenInJIT = true;
switch (stubInfo.accessType) {
case access_unset:
return computeFromLLInt(profiledBlock, bytecodeIndex, ident);
case access_get_by_id_self: {
Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
result.m_offset = structure->get(*profiledBlock->globalData(), ident);
if (result.m_offset != notFound)
result.m_structureSet.add(structure);
if (result.m_offset != notFound)
ASSERT(result.m_structureSet.size());
break;
}
case access_get_by_id_self_list: {
PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
unsigned size = stubInfo.u.getByIdProtoList.listSize;
for (unsigned i = 0; i < size; ++i) {
ASSERT(list->list[i].isDirect);
Structure* structure = list->list[i].base.get();
if (result.m_structureSet.contains(structure))
continue;
size_t myOffset = structure->get(*profiledBlock->globalData(), ident);
if (myOffset == notFound) {
result.m_offset = notFound;
break;
}
if (!i)
result.m_offset = myOffset;
else if (result.m_offset != myOffset) {
result.m_offset = notFound;
break;
}
result.m_structureSet.add(structure);
}
if (result.m_offset != notFound)
ASSERT(result.m_structureSet.size());
break;
}
default:
ASSERT(result.m_offset == notFound);
break;
}
if (result.m_offset == notFound) {
result.m_state = TakesSlowPath;
result.m_structureSet.clear();
} else
result.m_state = SimpleDirect;
return result;
#else // ENABLE(JIT)
return GetByIdStatus(NoInformation, StructureSet(), notFound, false);
#endif // ENABLE(JIT)
}
}