+2008-12-11 Sam Weinig <sam@webkit.org>
+
+ Reviewed by Geoffrey Garen.
+
+ Remove dependancy on having the Instruction buffer in order to
+ deref Structures used for property access and global resolves.
+ Instead, we put references to the necessary Structures in axillary
+ data structures on the CodeBlock. This is not an ideal solution,
+ as we still pay for having the Structures in two places and we
+ would like to eventually just hold on to offsets into the machine
+ code buffer.
+
+ - Also removes CodeBlock bloat in non-JIT by #ifdefing the JIT
+ only data structures.
+
+ * GNUmakefile.am:
+ * JavaScriptCore.pri:
+ * JavaScriptCore.scons:
+ * JavaScriptCore.vcproj/JavaScriptCore/JavaScriptCore.vcproj:
+ * JavaScriptCore.xcodeproj/project.pbxproj:
+ * JavaScriptCoreSources.bkl:
+ * bytecode/CodeBlock.cpp:
+ (JSC::isGlobalResolve):
+ (JSC::isPropertyAccess):
+ (JSC::instructionOffsetForNth):
+ (JSC::printGlobalResolveInfo):
+ (JSC::printStructureStubInfo):
+ (JSC::CodeBlock::printStructures):
+ (JSC::CodeBlock::dump):
+ (JSC::CodeBlock::~CodeBlock):
+ (JSC::CodeBlock::shrinkToFit):
+ * bytecode/CodeBlock.h:
+ (JSC::GlobalResolveInfo::GlobalResolveInfo):
+ (JSC::getNativePC):
+ (JSC::CodeBlock::instructions):
+ (JSC::CodeBlock::getStubInfo):
+ (JSC::CodeBlock::getBytecodeIndex):
+ (JSC::CodeBlock::addPropertyAccessInstruction):
+ (JSC::CodeBlock::addGlobalResolveInstruction):
+ (JSC::CodeBlock::numberOfStructureStubInfos):
+ (JSC::CodeBlock::addStructureStubInfo):
+ (JSC::CodeBlock::structureStubInfo):
+ (JSC::CodeBlock::addGlobalResolveInfo):
+ (JSC::CodeBlock::globalResolveInfo):
+ (JSC::CodeBlock::numberOfCallLinkInfos):
+ (JSC::CodeBlock::addCallLinkInfo):
+ (JSC::CodeBlock::callLinkInfo):
+ * bytecode/Instruction.h:
+ (JSC::PolymorphicAccessStructureList::PolymorphicStubInfo::set):
+ (JSC::PolymorphicAccessStructureList::PolymorphicAccessStructureList):
+ * bytecode/Opcode.h:
+ (JSC::):
+ * bytecode/StructureStubInfo.cpp: Copied from bytecode/CodeBlock.cpp.
+ (JSC::StructureStubInfo::deref):
+ * bytecode/StructureStubInfo.h: Copied from bytecode/CodeBlock.h.
+ (JSC::StructureStubInfo::StructureStubInfo):
+ (JSC::StructureStubInfo::initGetByIdSelf):
+ (JSC::StructureStubInfo::initGetByIdProto):
+ (JSC::StructureStubInfo::initGetByIdChain):
+ (JSC::StructureStubInfo::initGetByIdSelfList):
+ (JSC::StructureStubInfo::initGetByIdProtoList):
+ (JSC::StructureStubInfo::initPutByIdTransition):
+ (JSC::StructureStubInfo::initPutByIdReplace):
+ (JSC::StructureStubInfo::):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitResolve):
+ (JSC::BytecodeGenerator::emitGetById):
+ (JSC::BytecodeGenerator::emitPutById):
+ (JSC::BytecodeGenerator::emitCall):
+ (JSC::BytecodeGenerator::emitConstruct):
+ (JSC::BytecodeGenerator::emitCatch):
+ * interpreter/Interpreter.cpp:
+ (JSC::Interpreter::tryCTICachePutByID):
+ (JSC::Interpreter::tryCTICacheGetByID):
+ (JSC::Interpreter::cti_op_get_by_id_self_fail):
+ (JSC::getPolymorphicAccessStructureListSlot):
+ (JSC::Interpreter::cti_op_get_by_id_proto_list):
+ (JSC::Interpreter::cti_op_resolve_global):
+ * jit/JIT.cpp:
+ (JSC::JIT::JIT):
+ (JSC::JIT::privateCompileMainPass):
+ (JSC::JIT::privateCompileSlowCases):
+ (JSC::JIT::privateCompile):
+ * jit/JITPropertyAccess.cpp:
+ (JSC::JIT::compileGetByIdHotPath):
+ (JSC::JIT::compilePutByIdHotPath):
+ (JSC::JIT::compileGetByIdSlowCase):
+ (JSC::JIT::compilePutByIdSlowCase):
+ (JSC::JIT::privateCompileGetByIdSelfList):
+ (JSC::JIT::privateCompileGetByIdProtoList):
+ (JSC::JIT::privateCompileGetByIdChainList):
+
2008-12-11 Gavin Barraclough <barraclough@apple.com>
Reviewed by Oliver Hunt.
JavaScriptCore/jit/ExecutableAllocatorPosix.cpp \
JavaScriptCore/jit/JIT.h \
JavaScriptCore/jit/JITInlineMethods.h \
+ JavaScriptCore/bytecode/StructureStubInfo.cpp \
+ JavaScriptCore/bytecode/StructureStubInfo.h \
JavaScriptCore/bytecode/CodeBlock.cpp \
JavaScriptCore/bytecode/CodeBlock.h \
JavaScriptCore/bytecode/JumpTable.cpp \
runtime/JSActivation.cpp \
runtime/JSNotAnObject.cpp \
bytecode/CodeBlock.cpp \
+ bytecode/StructureStubInfo.cpp \
bytecode/JumpTable.cpp \
jit/JIT.cpp \
jit/JITCall.cpp \
]
sources['bytecode'] = [
'bytecode/CodeBlock.cpp',
+ 'bytecode/StructureStubInfo.cpp',
'bytecode/JumpTable.cpp',
'bytecode/Opcode.cpp',
'bytecode/SamplingTool.cpp',
Name="bytecode"\r
>\r
<File\r
+ RelativePath="..\..\bytecode\StructureStubInfo.cpp"\r
+ >\r
+ </File>\r
+ <File\r
+ RelativePath="..\..\bytecode\StructureStubInfo.h"\r
+ >\r
+ </File>\r
+ <File\r
RelativePath="..\..\bytecode\CodeBlock.cpp"\r
>\r
</File>\r
BC7F8FB90E19D1C3008632C0 /* JSNumberCell.h in Headers */ = {isa = PBXBuildFile; fileRef = BC7F8FB80E19D1C3008632C0 /* JSNumberCell.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC9041480EB9250900FE26FA /* StructureTransitionTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC9041470EB9250900FE26FA /* StructureTransitionTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC95437D0EBA70FD0072B6D3 /* PropertyMapHashTable.h in Headers */ = {isa = PBXBuildFile; fileRef = BC95437C0EBA70FD0072B6D3 /* PropertyMapHashTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */; };
+ BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */; };
BCD202C20E1706A7002C7E82 /* RegExpConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */; };
BCD202C40E1706A7002C7E82 /* RegExpPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202C00E1706A7002C7E82 /* RegExpPrototype.h */; };
BCD202D60E170708002C7E82 /* RegExpConstructor.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BCD202D50E170708002C7E82 /* RegExpConstructor.lut.h */; };
BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InternalFunction.cpp; sourceTree = "<group>"; };
BCA62DFE0E2826230004F30D /* CallData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CallData.cpp; sourceTree = "<group>"; };
BCA62DFF0E2826310004F30D /* ConstructData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstructData.cpp; sourceTree = "<group>"; };
+ BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StructureStubInfo.h; sourceTree = "<group>"; };
+ BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureStubInfo.cpp; sourceTree = "<group>"; };
BCD202BD0E1706A7002C7E82 /* RegExpConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpConstructor.cpp; sourceTree = "<group>"; };
BCD202BE0E1706A7002C7E82 /* RegExpConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RegExpConstructor.h; sourceTree = "<group>"; };
BCD202BF0E1706A7002C7E82 /* RegExpPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RegExpPrototype.cpp; sourceTree = "<group>"; };
969A07950ED1D3AE00F1F681 /* Opcode.h */,
1429D8830ED21C3D00B89619 /* SamplingTool.cpp */,
1429D8840ED21C3D00B89619 /* SamplingTool.h */,
+ BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */,
+ BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */,
);
path = bytecode;
sourceTree = "<group>";
BC18C44D0E16F5CD00B34460 /* pcre.h in Headers */,
BC18C44E0E16F5CD00B34460 /* pcre_internal.h in Headers */,
BC18C4720E16F5CD00B34460 /* ucpinternal.h in Headers */,
+ BCCF0D080EF0AAB900413C8F /* StructureStubInfo.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
930754D008B0F74600AB3056 /* pcre_tables.cpp in Sources */,
937013480CA97E0E00FA14D3 /* pcre_ucp_searchfuncs.cpp in Sources */,
93E26BD408B1514100F85226 /* pcre_xclass.cpp in Sources */,
+ BCCF0D0C0EF0B8A500413C8F /* StructureStubInfo.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
</set>
<set append="1" var="JSCORE_VM_SOURCES">
bytecode/CodeBlock.cpp
+ bytecode/StructureStubInfo.cpp
bytecode/JumpTable.cpp
runtime/ExceptionHelpers.cpp
interpreter/Interpreter.cpp
it += 4;
}
+#if ENABLE(JIT)
+static bool isGlobalResolve(OpcodeID opcodeID)
+{
+ return opcodeID == op_resolve_global;
+}
+
+static bool isPropertyAccess(OpcodeID opcodeID)
+{
+ switch (opcodeID) {
+ case op_get_by_id_self:
+ case op_get_by_id_proto:
+ case op_get_by_id_chain:
+ case op_get_by_id_self_list:
+ case op_get_by_id_proto_list:
+ case op_put_by_id_transition:
+ case op_put_by_id_replace:
+ case op_get_by_id:
+ case op_put_by_id:
+ case op_get_by_id_generic:
+ case op_put_by_id_generic:
+ case op_get_array_length:
+ case op_get_string_length:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static unsigned instructionOffsetForNth(ExecState* exec, const Vector<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
+{
+ size_t i = 0;
+ while (i < instructions.size()) {
+ OpcodeID currentOpcode = exec->interpreter()->getOpcodeID(instructions[i].u.opcode);
+ if (predicate(exec->interpreter()->getOpcodeID(instructions[i].u.opcode))) {
+ if (!--nth)
+ return i;
+ }
+ i += opcodeLengths[currentOpcode];
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset)
+{
+ printf(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).UTF8String().c_str());
+}
+
+static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
+{
+ switch (stubInfo.opcodeID) {
+ case op_get_by_id_self:
+ printf(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).UTF8String().c_str());
+ return;
+ case op_get_by_id_proto:
+ printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).UTF8String().c_str());
+ return;
+ case op_get_by_id_chain:
+ printf(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.getByIdChain.chain).UTF8String().c_str());
+ return;
+ case op_get_by_id_self_list:
+ printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).UTF8String().c_str(), stubInfo.u.getByIdSelfList.listSize);
+ return;
+ case op_get_by_id_proto_list:
+ printf(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).UTF8String().c_str(), stubInfo.u.getByIdProtoList.listSize);
+ return;
+ case op_put_by_id_transition:
+ printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).UTF8String().c_str(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).UTF8String().c_str());
+ return;
+ case op_put_by_id_replace:
+ printf(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).UTF8String().c_str());
+ return;
+ case op_get_by_id:
+ printf(" [%4d] %s\n", instructionOffset, "get_by_id");
+ return;
+ case op_put_by_id:
+ printf(" [%4d] %s\n", instructionOffset, "put_by_id");
+ return;
+ case op_get_by_id_generic:
+ printf(" [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
+ return;
+ case op_put_by_id_generic:
+ printf(" [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
+ return;
+ case op_get_array_length:
+ printf(" [%4d] %s\n", instructionOffset, "op_get_array_length");
+ return;
+ case op_get_string_length:
+ printf(" [%4d] %s\n", instructionOffset, "op_get_string_length");
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+#endif
+
void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
{
unsigned instructionOffset = vPC - m_instructions.begin();
return;
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_transition)) {
- printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_new", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());
+ printf(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(vPC[4].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[5].u.structure).UTF8String().c_str(), pointerToSourceString(vPC[6].u.structureChain).UTF8String().c_str());
return;
}
if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
void CodeBlock::dump(ExecState* exec) const
{
- Vector<Instruction>::const_iterator begin = m_instructions.begin();
- Vector<Instruction>::const_iterator end = m_instructions.end();
-
size_t instructionCount = 0;
- for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
- if (exec->interpreter()->isOpcode(it->u.opcode))
- ++instructionCount;
+
+ for (size_t i = 0; i < m_instructions.size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(m_instructions[i].u.opcode)])
+ ++instructionCount;
printf("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s)\n\n",
static_cast<unsigned long>(instructionCount),
static_cast<unsigned long>(m_instructions.size() * sizeof(Instruction)),
this, m_numParameters, m_numCalleeRegisters);
-
+
+ Vector<Instruction>::const_iterator begin = m_instructions.begin();
+ Vector<Instruction>::const_iterator end = m_instructions.end();
for (Vector<Instruction>::const_iterator it = begin; it != end; ++it)
dump(exec, begin, it);
} while (i < m_rareData->m_regexps.size());
}
+#if ENABLE(JIT)
+ if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
+ printf("\nStructures:\n");
+
+ if (!m_globalResolveInfos.isEmpty()) {
+ size_t i = 0;
+ do {
+ printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isGlobalResolve));
+ ++i;
+ } while (i < m_globalResolveInfos.size());
+ }
+ if (!m_structureStubInfos.isEmpty()) {
+ size_t i = 0;
+ do {
+ printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, m_instructions, i + 1, isPropertyAccess));
+ ++i;
+ } while (i < m_structureStubInfos.size());
+ }
+#else
if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
printf("\nStructures:\n");
if (!m_propertyAccessInstructions.isEmpty()) {
size_t i = 0;
do {
- printStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);
+ printStructures(&m_instructions[m_propertyAccessInstructions[i]]);
++i;
} while (i < m_propertyAccessInstructions.size());
}
-
+#endif
+
if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) {
printf("\nException Handlers:\n");
unsigned i = 0;
#define FOR_EACH_MEMBER_VECTOR(macro) \
macro(instructions) \
- macro(globalResolveInstructions) \
- macro(propertyAccessInstructions) \
+ macro(globalResolveInfos) \
+ macro(structureStubInfos) \
macro(callLinkInfos) \
macro(linkedCallerList) \
macro(identifiers) \
CodeBlock::~CodeBlock()
{
+#if !ENABLE(JIT)
for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i)
derefStructures(&m_instructions[m_globalResolveInstructions[i]]);
- for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i) {
- derefStructures(&m_instructions[m_propertyAccessInstructions[i].bytecodeIndex]);
+ for (size_t size = m_propertyAccessInstructions.size(), i = 0; i < size; ++i)
+ derefStructures(&m_instructions[m_propertyAccessInstructions[i]]);
+#else
+ for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) {
+ if (m_globalResolveInfos[i].structure)
+ m_globalResolveInfos[i].structure->deref();
}
+ for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i)
+ m_structureStubInfos[i].deref();
+
for (size_t size = m_callLinkInfos.size(), i = 0; i < size; ++i) {
CallLinkInfo* callLinkInfo = &m_callLinkInfos[i];
if (callLinkInfo->isLinked())
callLinkInfo->callee->removeCaller(callLinkInfo);
}
-#if ENABLE(JIT)
unlinkCallers();
#endif
{
m_instructions.shrinkToFit();
- m_globalResolveInstructions.shrinkToFit();
+#if !ENABLE(JIT)
m_propertyAccessInstructions.shrinkToFit();
+ m_globalResolveInstructions.shrinkToFit();
+#else
+ m_structureStubInfos.shrinkToFit();
+ m_globalResolveInfos.shrinkToFit();
m_callLinkInfos.shrinkToFit();
m_linkedCallerList.shrinkToFit();
+#endif
+
m_expressionInfo.shrinkToFit();
m_lineInfo.shrinkToFit();
+
m_identifiers.shrinkToFit();
m_functionExpressions.shrinkToFit();
m_constantRegisters.shrinkToFit();
#include <wtf/RefPtr.h>
#include <wtf/Vector.h>
+#if ENABLE(JIT)
+#include "StructureStubInfo.h"
+#endif
+
namespace JSC {
class ExecState;
uint32_t end;
uint32_t target;
uint32_t scopeDepth;
+#if ENABLE(JIT)
void* nativeCode;
+#endif
};
struct ExpressionRangeInfo {
int32_t lineNumber;
};
- struct StructureStubInfo {
- StructureStubInfo(unsigned bytecodeIndex)
- : bytecodeIndex(bytecodeIndex)
- , stubRoutine(0)
- , callReturnLocation(0)
- , hotPathBegin(0)
- {
- }
-
- unsigned bytecodeIndex;
- void* stubRoutine;
- void* callReturnLocation;
- void* hotPathBegin;
- };
-
+#if ENABLE(JIT)
struct CallLinkInfo {
CallLinkInfo()
: callReturnLocation(0)
bool isLinked() { return callee; }
};
-#if ENABLE(JIT)
+ struct GlobalResolveInfo {
+ GlobalResolveInfo()
+ : structure(0)
+ , offset(0)
+ {
+ }
+
+ Structure* structure;
+ unsigned offset;
+ };
+
struct PC {
PC(void* nativePC, unsigned bytecodeIndex)
: nativePC(nativePC)
void* nativePC;
unsigned bytecodeIndex;
};
-#endif
// valueAtPosition helpers for the binaryChop algorithm below.
return callLinkInfo->callReturnLocation;
}
-#if ENABLE(JIT)
inline void* getNativePC(PC* pc)
{
return pc->nativePC;
}
-#endif
// Binary chop algorithm, calls valueAtPosition on pre-sorted elements in array,
// compares result with key (KeyTypes should be comparable with '--', '<', '>').
ASSERT(key == valueAtPosition(&array[0]));
return &array[0];
}
+#endif
class CodeBlock {
friend class JIT;
CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset);
~CodeBlock();
- static void dumpStatistics();
-
-#if ENABLE(JIT)
+ void mark();
+ void refStructures(Instruction* vPC) const;
+ void derefStructures(Instruction* vPC) const;
+#if ENABLE(JIT)
void unlinkCallers();
#endif
- void addCaller(CallLinkInfo* caller)
- {
- caller->callee = this;
- caller->position = m_linkedCallerList.size();
- m_linkedCallerList.append(caller);
- }
-
- void removeCaller(CallLinkInfo* caller)
- {
- unsigned pos = caller->position;
- unsigned lastPos = m_linkedCallerList.size() - 1;
+ static void dumpStatistics();
- if (pos != lastPos) {
- m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
- m_linkedCallerList[pos]->position = pos;
- }
- m_linkedCallerList.shrink(lastPos);
- }
+#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
+ void dump(ExecState*) const;
+ void printStructures(const Instruction*) const;
+ void printStructure(const char* name, const Instruction*, int operand) const;
+#endif
inline bool isKnownNotImmediate(int index)
{
return index >= m_numVars + m_numConstants;
}
-#if !defined(NDEBUG) || ENABLE_OPCODE_SAMPLING
- void dump(ExecState*) const;
- void printStructures(const Instruction*) const;
- void printStructure(const char* name, const Instruction*, int operand) const;
-#endif
int expressionRangeForVPC(const Instruction*, int& divot, int& startOffset, int& endOffset);
int lineNumberForVPC(const Instruction* vPC);
HandlerInfo* handlerForVPC(const Instruction* vPC);
- void mark();
- void refStructures(Instruction* vPC) const;
- void derefStructures(Instruction* vPC) const;
+#if ENABLE(JIT)
+ void addCaller(CallLinkInfo* caller)
+ {
+ caller->callee = this;
+ caller->position = m_linkedCallerList.size();
+ m_linkedCallerList.append(caller);
+ }
+
+ void removeCaller(CallLinkInfo* caller)
+ {
+ unsigned pos = caller->position;
+ unsigned lastPos = m_linkedCallerList.size() - 1;
+
+ if (pos != lastPos) {
+ m_linkedCallerList[pos] = m_linkedCallerList[lastPos];
+ m_linkedCallerList[pos]->position = pos;
+ }
+ m_linkedCallerList.shrink(lastPos);
+ }
StructureStubInfo& getStubInfo(void* returnAddress)
{
- return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_propertyAccessInstructions.begin(), m_propertyAccessInstructions.size(), returnAddress));
+ return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress));
}
CallLinkInfo& getCallLinkInfo(void* returnAddress)
return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress));
}
-#if ENABLE(JIT)
unsigned getBytecodeIndex(void* nativePC)
{
return binaryChop<PC, void*, getNativePC>(m_pcVector.begin(), m_pcVector.size(), nativePC)->bytecodeIndex;
#endif
Vector<Instruction>& instructions() { return m_instructions; }
+
#if ENABLE(JIT)
void setJITCode(void* jitCode) { m_jitCode = jitCode; }
void* jitCode() { return m_jitCode; }
SourceProvider* source() const { return m_source.get(); }
unsigned sourceOffset() const { return m_sourceOffset; }
- void addGlobalResolveInstruction(unsigned globalResolveInstructions) { m_globalResolveInstructions.append(globalResolveInstructions); }
-
- size_t numberOfPropertyAccessInstructions() const { return m_propertyAccessInstructions.size(); }
- void addPropertyAccessInstruction(unsigned propertyAccessInstructions) { m_propertyAccessInstructions.append(StructureStubInfo(propertyAccessInstructions)); }
- StructureStubInfo& propertyAccessInstruction(int index) { return m_propertyAccessInstructions[index]; }
-
- size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
- void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
- CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
-
size_t numberOfJumpTargets() const { return m_jumpTargets.size(); }
void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); }
unsigned jumpTarget(int index) const { return m_jumpTargets[index]; }
void addLineInfo(const LineInfo& lineInfo) { return m_lineInfo.append(lineInfo); }
LineInfo& lastLineInfo() { return m_lineInfo.last(); }
-#if ENABLE(JIT)
+#if !ENABLE(JIT)
+ void addPropertyAccessInstruction(unsigned propertyAccessInstruction) { m_propertyAccessInstructions.append(propertyAccessInstruction); }
+ void addGlobalResolveInstruction(unsigned globalResolveInstructions) { m_globalResolveInstructions.append(globalResolveInstructions); }
+#else
+ size_t numberOfStructureStubInfos() const { return m_structureStubInfos.size(); }
+ void addStructureStubInfo(const StructureStubInfo& stubInfo) { m_structureStubInfos.append(stubInfo); }
+ StructureStubInfo& structureStubInfo(int index) { return m_structureStubInfos[index]; }
+
+ void addGlobalResolveInfo() { m_globalResolveInfos.append(GlobalResolveInfo()); }
+ GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; }
+
+ size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); }
+ void addCallLinkInfo() { m_callLinkInfos.append(CallLinkInfo()); }
+ CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; }
+
Vector<PC>& pcVector() { return m_pcVector; }
#endif
RefPtr<SourceProvider> m_source;
unsigned m_sourceOffset;
+#if !ENABLE(JIT)
+ Vector<unsigned> m_propertyAccessInstructions;
Vector<unsigned> m_globalResolveInstructions;
- Vector<StructureStubInfo> m_propertyAccessInstructions;
+#else
+ Vector<StructureStubInfo> m_structureStubInfos;
+ Vector<GlobalResolveInfo> m_globalResolveInfos;
Vector<CallLinkInfo> m_callLinkInfos;
Vector<CallLinkInfo*> m_linkedCallerList;
+#endif
Vector<unsigned> m_jumpTargets;
#define Instruction_h
#include "Opcode.h"
+#include "Structure.h"
#include <wtf/VectorTraits.h>
#define POLYMORPHIC_LIST_CACHE_SIZE 4
class Structure;
class StructureChain;
- // Structure used by op_get_by_id_proto_list instruction to hold data off the main opcode stream.
+ // Structure used by op_get_by_id_self_list and op_get_by_id_proto_list instruction to hold data off the main opcode stream.
struct PolymorphicAccessStructureList {
struct PolymorphicStubInfo {
- unsigned cachedOffset : 31;
- unsigned isChain : 1;
+ bool isChain;
void* stubRoutine;
Structure* base;
union {
StructureChain* chain;
} u;
- void set(int _cachedOffset, void* _stubRoutine, Structure* _base)
+ void set(void* _stubRoutine, Structure* _base)
{
- cachedOffset = _cachedOffset;
stubRoutine = _stubRoutine;
base = _base;
u.proto = 0;
isChain = false;
}
- void set(int _cachedOffset, void* _stubRoutine, Structure* _base, Structure* _proto)
+ void set(void* _stubRoutine, Structure* _base, Structure* _proto)
{
- cachedOffset = _cachedOffset;
stubRoutine = _stubRoutine;
base = _base;
u.proto = _proto;
isChain = false;
}
- void set(int _cachedOffset, void* _stubRoutine, Structure* _base, StructureChain* _chain)
+ void set(void* _stubRoutine, Structure* _base, StructureChain* _chain)
{
- cachedOffset = _cachedOffset;
stubRoutine = _stubRoutine;
base = _base;
u.chain = _chain;
}
} list[POLYMORPHIC_LIST_CACHE_SIZE];
- PolymorphicAccessStructureList(int cachedOffset, void* stubRoutine, Structure* firstBase)
+ PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase)
{
- list[0].set(cachedOffset, stubRoutine, firstBase);
+ list[0].set(stubRoutine, firstBase);
}
- PolymorphicAccessStructureList(int cachedOffset, void* stubRoutine, Structure* firstBase, Structure* firstProto)
+ PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, Structure* firstProto)
{
- list[0].set(cachedOffset, stubRoutine, firstBase, firstProto);
+ list[0].set(stubRoutine, firstBase, firstProto);
}
- PolymorphicAccessStructureList(int cachedOffset, void* stubRoutine, Structure* firstBase, StructureChain* firstChain)
+ PolymorphicAccessStructureList(void* stubRoutine, Structure* firstBase, StructureChain* firstChain)
{
- list[0].set(cachedOffset, stubRoutine, firstBase, firstChain);
+ list[0].set(stubRoutine, firstBase, firstChain);
}
void derefStructures(int count)
#define OPCODE_LENGTH(opcode) opcode##_length
+ #define OPCODE_ID_LENGTH_MAP(opcode, length) length,
+ const int opcodeLengths[numOpcodeIDs] = { FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTH_MAP) };
+ #undef OPCODE_ID_LENGTH_MAP
+
#define VERIFY_OPCODE_ID(id, size) COMPILE_ASSERT(id <= op_end, ASSERT_THAT_JS_OPCODE_IDS_ARE_VALID);
FOR_EACH_OPCODE_ID(VERIFY_OPCODE_ID);
#undef VERIFY_OPCODE_ID
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StructureStubInfo.h"
+
+namespace JSC {
+
+#if ENABLE(JIT)
+void StructureStubInfo::deref()
+{
+ switch (opcodeID) {
+ case op_get_by_id_self:
+ u.getByIdSelf.baseObjectStructure->deref();
+ return;
+ case op_get_by_id_proto:
+ u.getByIdProto.baseObjectStructure->deref();
+ u.getByIdProto.prototypeStructure->deref();
+ return;
+ case op_get_by_id_chain:
+ u.getByIdChain.baseObjectStructure->deref();
+ u.getByIdChain.chain->deref();
+ return;
+ case op_get_by_id_self_list: {
+ PolymorphicAccessStructureList* polymorphicStructures = u.getByIdSelfList.structureList;
+ polymorphicStructures->derefStructures(u.getByIdSelfList.listSize);
+ delete polymorphicStructures;
+ return;
+ }
+ case op_get_by_id_proto_list: {
+ PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList;
+ polymorphicStructures->derefStructures(u.getByIdProtoList.listSize);
+ delete polymorphicStructures;
+ return;
+ }
+ case op_put_by_id_transition:
+ u.putByIdTransition.previousStructure->deref();
+ u.putByIdTransition.structure->deref();
+ u.putByIdTransition.chain->deref();
+ return;
+ case op_put_by_id_replace:
+ u.putByIdReplace.baseObjectStructure->deref();
+ return;
+ case op_get_by_id:
+ case op_put_by_id:
+ case op_get_by_id_generic:
+ case op_put_by_id_generic:
+ case op_get_array_length:
+ case op_get_string_length:
+ // These instructions don't ref their Structures.
+ return;
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+#endif
+
+} // namespace JSC
--- /dev/null
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StructureStubInfo_h
+#define StructureStubInfo_h
+
+#include "Instruction.h"
+#include "Opcode.h"
+#include "Structure.h"
+
+namespace JSC {
+
+#if ENABLE(JIT)
+ struct StructureStubInfo {
+ StructureStubInfo(OpcodeID opcodeID)
+ : opcodeID(opcodeID)
+ , stubRoutine(0)
+ , callReturnLocation(0)
+ , hotPathBegin(0)
+ {
+ }
+
+ void initGetByIdSelf(Structure* baseObjectStructure)
+ {
+ opcodeID = op_get_by_id_self;
+
+ u.getByIdSelf.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+ }
+
+ void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure)
+ {
+ opcodeID = op_get_by_id_proto;
+
+ u.getByIdProto.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+
+ u.getByIdProto.prototypeStructure = prototypeStructure;
+ prototypeStructure->ref();
+ }
+
+ void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain)
+ {
+ opcodeID = op_get_by_id_chain;
+
+ u.getByIdChain.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+
+ u.getByIdChain.chain = chain;
+ chain->ref();
+ }
+
+ void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize)
+ {
+ opcodeID = op_get_by_id_self_list;
+
+ u.getByIdProtoList.structureList = structureList;
+ u.getByIdProtoList.listSize = listSize;
+ }
+
+ void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize)
+ {
+ opcodeID = op_get_by_id_proto_list;
+
+ u.getByIdProtoList.structureList = structureList;
+ u.getByIdProtoList.listSize = listSize;
+ }
+
+ // PutById*
+
+ void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain)
+ {
+ opcodeID = op_put_by_id_transition;
+
+ u.putByIdTransition.previousStructure = previousStructure;
+ previousStructure->ref();
+
+ u.putByIdTransition.structure = structure;
+ structure->ref();
+
+ u.putByIdTransition.chain = chain;
+ chain->ref();
+ }
+
+ void initPutByIdReplace(Structure* baseObjectStructure)
+ {
+ opcodeID = op_put_by_id_replace;
+
+ u.putByIdReplace.baseObjectStructure = baseObjectStructure;
+ baseObjectStructure->ref();
+ }
+
+ void deref();
+
+ OpcodeID opcodeID;
+ union {
+ struct {
+ Structure* baseObjectStructure;
+ } getByIdSelf;
+ struct {
+ Structure* baseObjectStructure;
+ Structure* prototypeStructure;
+ } getByIdProto;
+ struct {
+ Structure* baseObjectStructure;
+ StructureChain* chain;
+ } getByIdChain;
+ struct {
+ PolymorphicAccessStructureList* structureList;
+ int listSize;
+ } getByIdSelfList;
+ struct {
+ PolymorphicAccessStructureList* structureList;
+ int listSize;
+ } getByIdProtoList;
+ struct {
+ Structure* previousStructure;
+ Structure* structure;
+ StructureChain* chain;
+ } putByIdTransition;
+ struct {
+ Structure* baseObjectStructure;
+ } putByIdReplace;
+ } u;
+
+ void* stubRoutine;
+ void* callReturnLocation;
+ void* hotPathBegin;
+ };
+#endif
+
+} // namespace JSC
+
+#endif // StructureStubInfo_h
}
if (globalObject) {
+#if ENABLE(JIT)
+ m_codeBlock->addGlobalResolveInfo();
+#else
m_codeBlock->addGlobalResolveInstruction(instructions().size());
+#endif
emitOpcode(op_resolve_global);
instructions().append(dst->index());
instructions().append(globalObject);
RegisterID* BytecodeGenerator::emitGetById(RegisterID* dst, RegisterID* base, const Identifier& property)
{
+#if ENABLE(JIT)
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(op_get_by_id));
+#else
m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
emitOpcode(op_get_by_id);
instructions().append(dst->index());
RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& property, RegisterID* value)
{
+#if ENABLE(JIT)
+ m_codeBlock->addStructureStubInfo(StructureStubInfo(op_put_by_id));
+#else
m_codeBlock->addPropertyAccessInstruction(instructions().size());
+#endif
emitOpcode(op_put_by_id);
instructions().append(base->index());
}
emitExpressionInfo(divot, startOffset, endOffset);
+
+#if ENABLE(JIT)
m_codeBlock->addCallLinkInfo();
+#endif
// Emit call.
emitOpcode(opcodeID);
callFrame.append(newTemporary());
emitExpressionInfo(divot, startOffset, endOffset);
+
+#if ENABLE(JIT)
m_codeBlock->addCallLinkInfo();
+#endif
emitOpcode(op_construct);
instructions().append(dst->index()); // dst
RegisterID* BytecodeGenerator::emitCatch(RegisterID* targetRegister, Label* start, Label* end)
{
+#if ENABLE(JIT)
HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth, 0 };
+#else
+ HandlerInfo info = { start->offsetFrom(0), end->offsetFrom(0), instructions().size(), m_dynamicScopeDepth };
+#endif
+
m_codeBlock->addExceptionHandler(info);
emitOpcode(op_catch);
instructions().append(targetRegister->index());
}
StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
- Instruction* vPC = codeBlock->instructions().begin() + stubInfo->bytecodeIndex;
// Cache hit: Specialize instruction and ref Structures.
// Structure transition, cache transition info
if (slot.type() == PutPropertySlot::NewProperty) {
- vPC[0] = getOpcode(op_put_by_id_transition);
- vPC[4] = structure->previousID();
- vPC[5] = structure;
StructureChain* chain = structure->cachedPrototypeChain();
if (!chain) {
chain = cachePrototypeChain(callFrame, structure);
if (!chain) {
- // This happens if someone has manually inserted null into the prototype chain
- vPC[0] = getOpcode(op_put_by_id_generic);
+ // This happens if someone has manually inserted null into the prototype chain
+ stubInfo->opcodeID = op_put_by_id_generic;
return;
}
}
- vPC[6] = chain;
- vPC[7] = slot.cachedOffset();
- codeBlock->refStructures(vPC);
+ stubInfo->initPutByIdTransition(structure->previousID(), structure, chain);
JIT::compilePutByIdTransition(callFrame->scopeChain()->globalData, codeBlock, stubInfo, structure->previousID(), structure, slot.cachedOffset(), chain, returnAddress);
return;
}
- vPC[0] = getOpcode(op_put_by_id_replace);
- vPC[4] = structure;
- vPC[5] = slot.cachedOffset();
- codeBlock->refStructures(vPC);
+ stubInfo->initPutByIdReplace(structure);
#if USE(CTI_REPATCH_PIC)
UNUSED_PARAM(callFrame);
// *_second method to achieve a similar (but not quite the same) effect.
StructureStubInfo* stubInfo = &codeBlock->getStubInfo(returnAddress);
- Instruction* vPC = codeBlock->instructions().begin() + stubInfo->bytecodeIndex;
// Cache hit: Specialize instruction and ref Structures.
if (slot.slotBase() == baseValue) {
// set this up, so derefStructures can do it's job.
- vPC[0] = getOpcode(op_get_by_id_self);
- vPC[4] = structure;
- vPC[5] = slot.cachedOffset();
- codeBlock->refStructures(vPC);
+ stubInfo->initGetByIdSelf(structure);
#if USE(CTI_REPATCH_PIC)
JIT::patchGetByIdSelf(stubInfo, structure, slot.cachedOffset(), returnAddress);
slotBaseObject->setStructure(transition.release());
asObject(baseValue)->structure()->setCachedPrototypeChain(0);
}
-
- vPC[0] = getOpcode(op_get_by_id_proto);
- vPC[4] = structure;
- vPC[5] = slotBaseObject->structure();
- vPC[6] = slot.cachedOffset();
- codeBlock->refStructures(vPC);
+
+ stubInfo->initGetByIdProto(structure, slotBaseObject->structure());
JIT::compileGetByIdProto(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, slotBaseObject->structure(), slot.cachedOffset(), returnAddress);
return;
size_t count = countPrototypeChainEntriesAndCheckForProxies(callFrame, baseValue, slot);
if (!count) {
- vPC[0] = getOpcode(op_get_by_id_generic);
+ stubInfo->opcodeID = op_get_by_id_generic;
return;
}
chain = cachePrototypeChain(callFrame, structure);
ASSERT(chain);
- vPC[0] = getOpcode(op_get_by_id_chain);
- vPC[4] = structure;
- vPC[5] = chain;
- vPC[6] = count;
- vPC[7] = slot.cachedOffset();
- codeBlock->refStructures(vPC);
+ stubInfo->initGetByIdChain(structure, chain);
JIT::compileGetByIdChain(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, structure, chain, count, slot.cachedOffset(), returnAddress);
}
CodeBlock* codeBlock = callFrame->codeBlock();
StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS);
- Instruction* vPC = codeBlock->instructions().begin() + stubInfo->bytecodeIndex;
ASSERT(slot.slotBase()->isObject());
PolymorphicAccessStructureList* polymorphicStructureList;
int listIndex = 1;
- if (vPC[0].u.opcode == ARG_globalData->interpreter->getOpcode(op_get_by_id_self)) {
+ if (stubInfo->opcodeID == op_get_by_id_self) {
ASSERT(!stubInfo->stubRoutine);
- polymorphicStructureList = new PolymorphicAccessStructureList(vPC[5].u.operand, 0, vPC[4].u.structure);
-
- vPC[0] = ARG_globalData->interpreter->getOpcode(op_get_by_id_self_list);
- vPC[4] = polymorphicStructureList;
- vPC[5] = 2;
+ polymorphicStructureList = new PolymorphicAccessStructureList(0, stubInfo->u.getByIdSelf.baseObjectStructure);
+ stubInfo->initGetByIdSelfList(polymorphicStructureList, 2);
} else {
- polymorphicStructureList = vPC[4].u.polymorphicStructures;
- listIndex = vPC[5].u.operand;
-
- vPC[5] = listIndex + 1;
+ polymorphicStructureList = stubInfo->u.getByIdSelfList.structureList;
+ listIndex = stubInfo->u.getByIdSelfList.listSize;
+ stubInfo->u.getByIdSelfList.listSize++;
}
JIT::compileGetByIdSelfList(callFrame->scopeChain()->globalData, codeBlock, stubInfo, polymorphicStructureList, listIndex, asCell(baseValue)->structure(), slot.cachedOffset());
return result;
}
-static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(Interpreter* interpreter, StructureStubInfo* stubInfo, Instruction* vPC, int& listIndex)
+static PolymorphicAccessStructureList* getPolymorphicAccessStructureListSlot(StructureStubInfo* stubInfo, int& listIndex)
{
- PolymorphicAccessStructureList* prototypeStructureList;
+ PolymorphicAccessStructureList* prototypeStructureList = 0;
listIndex = 1;
- if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto)) {
- prototypeStructureList = new PolymorphicAccessStructureList(vPC[6].u.operand, stubInfo->stubRoutine, vPC[4].u.structure, vPC[5].u.structure);
+ switch (stubInfo->opcodeID) {
+ case op_get_by_id_proto:
+ prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdProto.baseObjectStructure, stubInfo->u.getByIdProto.prototypeStructure);
stubInfo->stubRoutine = 0;
-
- vPC[0] = interpreter->getOpcode(op_get_by_id_proto_list);
- vPC[4] = prototypeStructureList;
- vPC[5] = 2;
- } else if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain)) {
- prototypeStructureList = new PolymorphicAccessStructureList(vPC[6].u.operand, stubInfo->stubRoutine, vPC[4].u.structure, vPC[5].u.structureChain);
+ stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
+ break;
+ case op_get_by_id_chain:
+ prototypeStructureList = new PolymorphicAccessStructureList(stubInfo->stubRoutine, stubInfo->u.getByIdChain.baseObjectStructure, stubInfo->u.getByIdChain.chain);
stubInfo->stubRoutine = 0;
-
- vPC[0] = interpreter->getOpcode(op_get_by_id_proto_list);
- vPC[4] = prototypeStructureList;
- vPC[5] = 2;
- } else {
- ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list));
- prototypeStructureList = vPC[4].u.polymorphicStructures;
- listIndex = vPC[5].u.operand;
- vPC[5] = listIndex + 1;
-
- ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE);
+ stubInfo->initGetByIdProtoList(prototypeStructureList, 2);
+ break;
+ case op_get_by_id_proto_list:
+ prototypeStructureList = stubInfo->u.getByIdProtoList.structureList;
+ listIndex = stubInfo->u.getByIdProtoList.listSize;
+ stubInfo->u.getByIdProtoList.listSize++;
+ break;
+ default:
+ ASSERT_NOT_REACHED();
}
+ ASSERT(listIndex < POLYMORPHIC_LIST_CACHE_SIZE);
return prototypeStructureList;
}
Structure* structure = asCell(baseValue)->structure();
CodeBlock* codeBlock = callFrame->codeBlock();
StructureStubInfo* stubInfo = &codeBlock->getStubInfo(CTI_RETURN_ADDRESS);
- Instruction* vPC = codeBlock->instructions().begin() + stubInfo->bytecodeIndex;
ASSERT(slot.slotBase()->isObject());
JSObject* slotBaseObject = asObject(slot.slotBase());
}
int listIndex;
- PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(ARG_globalData->interpreter, stubInfo, vPC, listIndex);
+ PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
JIT::compileGetByIdProtoList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, slotBaseObject->structure(), slot.cachedOffset());
ASSERT(chain);
int listIndex;
- PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(ARG_globalData->interpreter, stubInfo, vPC, listIndex);
+ PolymorphicAccessStructureList* prototypeStructureList = getPolymorphicAccessStructureListSlot(stubInfo, listIndex);
JIT::compileGetByIdChainList(callFrame->scopeChain()->globalData, callFrame, codeBlock, stubInfo, prototypeStructureList, listIndex, structure, chain, count, slot.cachedOffset());
CallFrame* callFrame = ARG_callFrame;
JSGlobalObject* globalObject = asGlobalObject(ARG_src1);
Identifier& ident = *ARG_id2;
- Instruction* vPC = ARG_instr3;
+ unsigned globalResolveInfoIndex = ARG_int3;
+ Instruction* vPC = ARG_instr4;
ASSERT(globalObject->isGlobalObject());
PropertySlot slot(globalObject);
if (globalObject->getPropertySlot(callFrame, ident, slot)) {
JSValue* result = slot.getValue(callFrame, ident);
if (slot.isCacheable()) {
- if (vPC[4].u.structure)
- vPC[4].u.structure->deref();
+ GlobalResolveInfo& globalResolveInfo = callFrame->codeBlock()->globalResolveInfo(globalResolveInfoIndex);
+ if (globalResolveInfo.structure)
+ globalResolveInfo.structure->deref();
globalObject->structure()->ref();
- vPC[4] = globalObject->structure();
- vPC[5] = slot.cachedOffset();
+ globalResolveInfo.structure = globalObject->structure();
+ globalResolveInfo.offset = slot.cachedOffset();
return result;
}
, m_globalData(globalData)
, m_codeBlock(codeBlock)
, m_labels(codeBlock ? codeBlock->instructions().size() : 0)
- , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfPropertyAccessInstructions() : 0)
+ , m_propertyAccessCompilationInfo(codeBlock ? codeBlock->numberOfStructureStubInfos() : 0)
, m_callStructureStubCompilationInfo(codeBlock ? codeBlock->numberOfCallLinkInfos() : 0)
, m_lastResultBytecodeRegister(std::numeric_limits<int>::max())
, m_jumpTargetsPosition(0)
unsigned instructionCount = m_codeBlock->instructions().size();
unsigned propertyAccessInstructionIndex = 0;
+ unsigned globalResolveInfoIndex = 0;
unsigned callLinkInfoIndex = 0;
for (unsigned i = 0; i < instructionCount; ) {
// Fast case
void* globalObject = instruction[i + 2].u.jsCell;
Identifier* ident = &(m_codeBlock->identifier(instruction[i + 3].u.operand));
- void* structureAddress = reinterpret_cast<void*>(instruction + i + 4);
- void* offsetAddr = reinterpret_cast<void*>(instruction + i + 5);
+
+ unsigned currentIndex = globalResolveInfoIndex++;
+ void* structureAddress = &(m_codeBlock->globalResolveInfo(currentIndex).structure);
+ void* offsetAddr = &(m_codeBlock->globalResolveInfo(currentIndex).offset);
// Check Structure of global object
move(ImmPtr(globalObject), X86::eax);
noMatch.link(this);
emitPutCTIArgConstant(globalObject, 0);
emitPutCTIArgConstant(reinterpret_cast<unsigned>(ident), 4);
- emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction + i), 8);
+ emitPutCTIArgConstant(currentIndex, 8);
+ emitPutCTIArgConstant(reinterpret_cast<unsigned>(instruction + i), 12);
emitCTICall(i, Interpreter::cti_op_resolve_global);
emitPutVirtualRegister(instruction[i + 1].u.operand);
end.link(this);
}
}
- ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfPropertyAccessInstructions());
+ ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
}
__ link(__ jmp(), m_labels[i]);
}
- ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfPropertyAccessInstructions());
+ ASSERT(propertyAccessInstructionIndex == m_codeBlock->numberOfStructureStubInfos());
ASSERT(callLinkInfoIndex == m_codeBlock->numberOfCallLinkInfos());
}
for (Vector<JSRInfo>::iterator iter = m_jsrSites.begin(); iter != m_jsrSites.end(); ++iter)
X86Assembler::linkAbsoluteAddress(code, iter->addrPosition, iter->target);
- for (unsigned i = 0; i < m_codeBlock->numberOfPropertyAccessInstructions(); ++i) {
- StructureStubInfo& info = m_codeBlock->propertyAccessInstruction(i);
+ for (unsigned i = 0; i < m_codeBlock->numberOfStructureStubInfos(); ++i) {
+ StructureStubInfo& info = m_codeBlock->structureStubInfo(i);
info.callReturnLocation = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].callReturnLocation);
info.hotPathBegin = X86Assembler::getRelocatedAddress(code, m_propertyAccessCompilationInfo[i].hotPathBegin);
}
#ifdef NDEBUG
UNUSED_PARAM(propertyAccessInstructionIndex);
#endif
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
#ifndef NDEBUG
JmpDst coldPathBegin = __ label();
emitPutVirtualRegister(resultVReg);
// Track the location of the call; this will be used to recover repatch information.
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
}
JmpSrc call = emitCTICall(i, Interpreter::cti_op_put_by_id_generic);
// Track the location of the call; this will be used to recover repatch information.
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
}
emitGetVirtualRegister(baseVReg, X86::eax, i);
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
-
emitJumpSlowCaseIfNotJSCell(X86::eax, i, baseVReg);
JmpDst hotPathBegin = __ label();
emitPutVirtualRegister(resultVReg);
// Track the location of the call; this will be used to recover repatch information.
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
}
emitGetVirtualRegisters(baseVReg, X86::eax, valueVReg, X86::edx, i);
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
-
// Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
emitJumpSlowCaseIfNotJSCell(X86::eax, i, baseVReg);
JmpSrc call = emitCTICall(i, Interpreter::cti_op_put_by_id);
// Track the location of the call; this will be used to recover repatch information.
- ASSERT(m_codeBlock->propertyAccessInstruction(propertyAccessInstructionIndex).bytecodeIndex == i);
m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].callReturnLocation = call;
}
X86Assembler::link(code, success, reinterpret_cast<void*>(successDest));
structure->ref();
- polymorphicStructures->list[currentIndex].set(cachedOffset, code, structure);
+ polymorphicStructures->list[currentIndex].set(code, structure);
// Finally repatch the jump to slow case back in the hot path to jump here instead.
intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
structure->ref();
prototypeStructure->ref();
- prototypeStructures->list[currentIndex].set(cachedOffset, code, structure, prototypeStructure);
+ prototypeStructures->list[currentIndex].set(code, structure, prototypeStructure);
// Finally repatch the jump to slow case back in the hot path to jump here instead.
intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;
// Track the stub we have created so that it will be deleted later.
structure->ref();
chain->ref();
- prototypeStructures->list[currentIndex].set(cachedOffset, code, structure, chain);
+ prototypeStructures->list[currentIndex].set(code, structure, chain);
// Finally repatch the jump to slow case back in the hot path to jump here instead.
intptr_t jmpLocation = reinterpret_cast<intptr_t>(stubInfo->hotPathBegin) + repatchOffsetGetByIdBranchToSlowCase;