diff options
Diffstat (limited to 'JavaScriptCore/bytecode')
-rw-r--r-- | JavaScriptCore/bytecode/CodeBlock.cpp | 119 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/CodeBlock.h | 123 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/EvalCodeCache.h | 4 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/Instruction.h | 6 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/JumpTable.h | 12 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/Opcode.h | 6 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/SamplingTool.h | 6 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/StructureStubInfo.cpp | 28 | ||||
-rw-r--r-- | JavaScriptCore/bytecode/StructureStubInfo.h | 55 |
9 files changed, 214 insertions, 145 deletions
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp index d2b122a..e22f25a 100644 --- a/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/JavaScriptCore/bytecode/CodeBlock.cpp @@ -57,6 +57,9 @@ static UString escapeQuotes(const UString& str) static UString valueToSourceString(ExecState* exec, JSValue val) { + if (!val) + return "0"; + if (val.isString()) { UString result("\""); result += escapeQuotes(val.toString(exec)) + "\""; @@ -227,44 +230,44 @@ static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigne static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset) { - switch (stubInfo.opcodeID) { - case op_get_by_id_self: + switch (stubInfo.accessType) { + case access_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: + case access_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: + case access_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: + case access_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: + case access_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: + case access_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: + case access_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: + case access_get_by_id: printf(" [%4d] %s\n", instructionOffset, "get_by_id"); return; - case op_put_by_id: + case access_put_by_id: printf(" [%4d] %s\n", instructionOffset, "put_by_id"); return; - case op_get_by_id_generic: + case access_get_by_id_generic: printf(" [%4d] %s\n", instructionOffset, "op_get_by_id_generic"); return; - case op_put_by_id_generic: + case access_put_by_id_generic: printf(" [%4d] %s\n", instructionOffset, "op_put_by_id_generic"); return; - case op_get_array_length: + case access_get_array_length: printf(" [%4d] %s\n", instructionOffset, "op_get_array_length"); return; - case op_get_string_length: + case access_get_string_length: printf(" [%4d] %s\n", instructionOffset, "op_get_string_length"); return; default: @@ -363,15 +366,6 @@ void CodeBlock::dump(ExecState* exec) const } while (i < m_constantRegisters.size()); } - if (m_rareData && !m_rareData->m_unexpectedConstants.isEmpty()) { - printf("\nUnexpected Constants:\n"); - size_t i = 0; - do { - printf(" k%u = %s\n", static_cast<unsigned>(i), valueToSourceString(exec, m_rareData->m_unexpectedConstants[i]).ascii()); - ++i; - } while (i < m_rareData->m_unexpectedConstants.size()); - } - if (m_rareData && !m_rareData->m_regexps.isEmpty()) { printf("\nm_regexps:\n"); size_t i = 0; @@ -506,12 +500,6 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printf("[%4d] convert_this %s\n", location, registerName(r0).c_str()); break; } - case op_unexpected_load: { - int r0 = (++it)->u.operand; - int k0 = (++it)->u.operand; - printf("[%4d] unexpected_load\t %s, %s\n", location, registerName(r0).c_str(), constantName(exec, k0, unexpectedConstant(k0)).c_str()); - break; - } case op_new_object: { int r0 = (++it)->u.operand; printf("[%4d] new_object\t %s\n", location, registerName(r0).c_str()); @@ -610,6 +598,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& } case op_div: { printBinaryOp(location, it, "div"); + ++it; break; } case op_mod: { @@ -754,13 +743,6 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printf("[%4d] resolve_with_base %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); break; } - case op_resolve_func: { - int r0 = (++it)->u.operand; - int r1 = (++it)->u.operand; - int id0 = (++it)->u.operand; - printf("[%4d] resolve_func\t %s, %s, %s\n", location, registerName(r0).c_str(), registerName(r1).c_str(), idName(id0, m_identifiers[id0]).c_str()); - break; - } case op_get_by_id: { printGetByIdOp(location, it, m_identifiers, "get_by_id"); break; @@ -1084,7 +1066,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int errorType = (++it)->u.operand; int k0 = (++it)->u.operand; - printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, unexpectedConstant(k0)).c_str()); + printf("[%4d] new_error\t %s, %d, %s\n", location, registerName(r0).c_str(), errorType, constantName(exec, k0, getConstant(k0)).c_str()); break; } case op_jsr: { @@ -1142,7 +1124,6 @@ static HashSet<CodeBlock*> liveCodeBlockSet; #define FOR_EACH_MEMBER_VECTOR_RARE_DATA(macro) \ macro(regexps) \ macro(functions) \ - macro(unexpectedConstants) \ macro(exceptionHandlers) \ macro(immediateSwitchJumpTables) \ macro(characterSwitchJumpTables) \ @@ -1265,10 +1246,30 @@ void CodeBlock::dumpStatistics() #endif } +CodeBlock::CodeBlock(ScopeNode* ownerNode) + : m_numCalleeRegisters(0) + , m_numVars(0) + , m_numParameters(0) + , m_ownerNode(ownerNode) + , m_globalData(0) +#ifndef NDEBUG + , m_instructionCount(0) +#endif + , m_needsFullScopeChain(false) + , m_usesEval(false) + , m_isNumericCompareFunction(false) + , m_codeType(NativeCode) + , m_source(0) + , m_sourceOffset(0) + , m_exceptionInfo(0) +{ +#if DUMP_CODE_BLOCK_STATISTICS + liveCodeBlockSet.add(this); +#endif +} CodeBlock::CodeBlock(ScopeNode* ownerNode, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset) : m_numCalleeRegisters(0) - , m_numConstants(0) , m_numVars(0) , m_numParameters(0) , m_ownerNode(ownerNode) @@ -1315,19 +1316,26 @@ CodeBlock::~CodeBlock() } for (size_t size = m_methodCallLinkInfos.size(), i = 0; i < size; ++i) { - if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) + if (Structure* structure = m_methodCallLinkInfos[i].cachedStructure) { structure->deref(); + // Both members must be filled at the same time + ASSERT(!!m_methodCallLinkInfos[i].cachedPrototypeStructure); + m_methodCallLinkInfos[i].cachedPrototypeStructure->deref(); + } } +#if ENABLE(JIT_OPTIMIZE_CALL) unlinkCallers(); #endif +#endif // !ENABLE(JIT) + #if DUMP_CODE_BLOCK_STATISTICS liveCodeBlockSet.remove(this); #endif } -#if ENABLE(JIT) +#if ENABLE(JIT_OPTIMIZE_CALL) void CodeBlock::unlinkCallers() { size_t size = m_linkedCallerList.size(); @@ -1342,6 +1350,7 @@ void CodeBlock::unlinkCallers() void CodeBlock::derefStructures(Instruction* vPC) const { + ASSERT(m_codeType != NativeCode); Interpreter* interpreter = m_globalData->interpreter; if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { @@ -1387,6 +1396,7 @@ void CodeBlock::derefStructures(Instruction* vPC) const void CodeBlock::refStructures(Instruction* vPC) const { + ASSERT(m_codeType != NativeCode); Interpreter* interpreter = m_globalData->interpreter; if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self)) { @@ -1418,29 +1428,27 @@ void CodeBlock::refStructures(Instruction* vPC) const ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic)); } -void CodeBlock::mark() +void CodeBlock::markAggregate(MarkStack& markStack) { - for (size_t i = 0; i < m_constantRegisters.size(); ++i) + for (size_t i = 0; i < m_constantRegisters.size(); ++i) { if (!m_constantRegisters[i].marked()) - m_constantRegisters[i].mark(); + markStack.append(m_constantRegisters[i].jsValue()); + } for (size_t i = 0; i < m_functionExpressions.size(); ++i) - m_functionExpressions[i]->body()->mark(); + m_functionExpressions[i]->body()->markAggregate(markStack); if (m_rareData) { for (size_t i = 0; i < m_rareData->m_functions.size(); ++i) - m_rareData->m_functions[i]->body()->mark(); + m_rareData->m_functions[i]->body()->markAggregate(markStack); - for (size_t i = 0; i < m_rareData->m_unexpectedConstants.size(); ++i) { - if (!m_rareData->m_unexpectedConstants[i].marked()) - m_rareData->m_unexpectedConstants[i].mark(); - } - m_rareData->m_evalCodeCache.mark(); + m_rareData->m_evalCodeCache.markAggregate(markStack); } } void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) { + ASSERT(m_codeType != NativeCode); if (m_exceptionInfo) return; @@ -1511,6 +1519,7 @@ void CodeBlock::reparseForExceptionInfoIfNecessary(CallFrame* callFrame) HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) { + ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); if (!m_rareData) @@ -1529,6 +1538,7 @@ HandlerInfo* CodeBlock::handlerForBytecodeOffset(unsigned bytecodeOffset) int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset) { + ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); reparseForExceptionInfoIfNecessary(callFrame); @@ -1554,6 +1564,7 @@ int CodeBlock::lineNumberForBytecodeOffset(CallFrame* callFrame, unsigned byteco int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset) { + ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); reparseForExceptionInfoIfNecessary(callFrame); @@ -1593,6 +1604,7 @@ int CodeBlock::expressionRangeForBytecodeOffset(CallFrame* callFrame, unsigned b bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsigned bytecodeOffset, OpcodeID& opcodeID) { + ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); reparseForExceptionInfoIfNecessary(callFrame); @@ -1621,6 +1633,7 @@ bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsi #if ENABLE(JIT) bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex) { + ASSERT(m_codeType != NativeCode); ASSERT(bytecodeOffset < m_instructionCount); if (!m_rareData || !m_rareData->m_functionRegisterInfos.size()) @@ -1647,6 +1660,7 @@ bool CodeBlock::functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& #if !ENABLE(JIT) bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset) { + ASSERT(m_codeType != NativeCode); if (m_globalResolveInstructions.isEmpty()) return false; @@ -1667,6 +1681,7 @@ bool CodeBlock::hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOff #else bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) { + ASSERT(m_codeType != NativeCode); if (m_globalResolveInfos.isEmpty()) return false; @@ -1689,6 +1704,7 @@ bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) #if ENABLE(JIT) void CodeBlock::setJITCode(JITCode jitCode) { + ASSERT(m_codeType != NativeCode); ownerNode()->setJITCode(jitCode); #if !ENABLE(OPCODE_SAMPLING) if (!BytecodeGenerator::dumpsGeneratedCode()) @@ -1724,7 +1740,6 @@ void CodeBlock::shrinkToFit() if (m_rareData) { m_rareData->m_exceptionHandlers.shrinkToFit(); m_rareData->m_functions.shrinkToFit(); - m_rareData->m_unexpectedConstants.shrinkToFit(); m_rareData->m_regexps.shrinkToFit(); m_rareData->m_immediateSwitchJumpTables.shrinkToFit(); m_rareData->m_characterSwitchJumpTables.shrinkToFit(); diff --git a/JavaScriptCore/bytecode/CodeBlock.h b/JavaScriptCore/bytecode/CodeBlock.h index ac29c6c..39b1db3 100644 --- a/JavaScriptCore/bytecode/CodeBlock.h +++ b/JavaScriptCore/bytecode/CodeBlock.h @@ -36,8 +36,10 @@ #include "JSGlobalObject.h" #include "JumpTable.h" #include "Nodes.h" +#include "PtrAndFlags.h" #include "RegExp.h" #include "UString.h" +#include <wtf/FastAllocBase.h> #include <wtf/RefPtr.h> #include <wtf/Vector.h> @@ -45,11 +47,21 @@ #include "StructureStubInfo.h" #endif +// Register numbers used in bytecode operations have different meaning accoring to their ranges: +// 0x80000000-0xFFFFFFFF Negative indicies from the CallFrame pointer are entries in the call frame, see RegisterFile.h. +// 0x00000000-0x3FFFFFFF Forwards indices from the CallFrame pointer are local vars and temporaries with the function's callframe. +// 0x40000000-0x7FFFFFFF Positive indices from 0x40000000 specify entries in the constant pool on the CodeBlock. +static const int FirstConstantRegisterIndex = 0x40000000; + namespace JSC { + enum HasSeenShouldRepatch { + hasSeenShouldRepatch + }; + class ExecState; - enum CodeType { GlobalCode, EvalCode, FunctionCode }; + enum CodeType { GlobalCode, EvalCode, FunctionCode, NativeCode }; static ALWAYS_INLINE int missingThisObjectMarker() { return std::numeric_limits<int>::max(); } @@ -59,7 +71,7 @@ namespace JSC { uint32_t target; uint32_t scopeDepth; #if ENABLE(JIT) - MacroAssembler::CodeLocationLabel nativeCode; + CodeLocationLabel nativeCode; #endif }; @@ -95,15 +107,25 @@ namespace JSC { } unsigned bytecodeIndex; - MacroAssembler::CodeLocationNearCall callReturnLocation; - MacroAssembler::CodeLocationDataLabelPtr hotPathBegin; - MacroAssembler::CodeLocationNearCall hotPathOther; - MacroAssembler::CodeLocationLabel coldPathOther; + CodeLocationNearCall callReturnLocation; + CodeLocationDataLabelPtr hotPathBegin; + CodeLocationNearCall hotPathOther; + PtrAndFlags<CodeBlock, HasSeenShouldRepatch> ownerCodeBlock; CodeBlock* callee; unsigned position; void setUnlinked() { callee = 0; } bool isLinked() { return callee; } + + bool seenOnce() + { + return ownerCodeBlock.isFlagSet(hasSeenShouldRepatch); + } + + void setSeen() + { + ownerCodeBlock.setFlag(hasSeenShouldRepatch); + } }; struct MethodCallLinkInfo { @@ -112,9 +134,20 @@ namespace JSC { { } - MacroAssembler::CodeLocationCall callReturnLocation; - MacroAssembler::CodeLocationDataLabelPtr structureLabel; + bool seenOnce() + { + return cachedPrototypeStructure.isFlagSet(hasSeenShouldRepatch); + } + + void setSeen() + { + cachedPrototypeStructure.setFlag(hasSeenShouldRepatch); + } + + CodeLocationCall callReturnLocation; + CodeLocationDataLabelPtr structureLabel; Structure* cachedStructure; + PtrAndFlags<Structure, HasSeenShouldRepatch> cachedPrototypeStructure; }; struct FunctionRegisterInfo { @@ -160,17 +193,17 @@ namespace JSC { inline void* getStructureStubInfoReturnLocation(StructureStubInfo* structureStubInfo) { - return structureStubInfo->callReturnLocation.calleeReturnAddressValue(); + return structureStubInfo->callReturnLocation.executableAddress(); } inline void* getCallLinkInfoReturnLocation(CallLinkInfo* callLinkInfo) { - return callLinkInfo->callReturnLocation.calleeReturnAddressValue(); + return callLinkInfo->callReturnLocation.executableAddress(); } inline void* getMethodCallLinkInfoReturnLocation(MethodCallLinkInfo* methodCallLinkInfo) { - return methodCallLinkInfo->callReturnLocation.calleeReturnAddressValue(); + return methodCallLinkInfo->callReturnLocation.executableAddress(); } inline unsigned getCallReturnOffset(CallReturnOffsetToBytecodeIndex* pc) @@ -215,16 +248,17 @@ namespace JSC { } #endif - class CodeBlock { + class CodeBlock : public FastAllocBase { friend class JIT; public: + CodeBlock(ScopeNode* ownerNode); CodeBlock(ScopeNode* ownerNode, CodeType, PassRefPtr<SourceProvider>, unsigned sourceOffset); ~CodeBlock(); - void mark(); + void markAggregate(MarkStack&); void refStructures(Instruction* vPC) const; void derefStructures(Instruction* vPC) const; -#if ENABLE(JIT) +#if ENABLE(JIT_OPTIMIZE_CALL) void unlinkCallers(); #endif @@ -247,19 +281,9 @@ namespace JSC { return false; } - ALWAYS_INLINE bool isConstantRegisterIndex(int index) - { - return index >= m_numVars && index < m_numVars + m_numConstants; - } - - ALWAYS_INLINE JSValue getConstant(int index) - { - return m_constantRegisters[index - m_numVars].jsValue(); - } - ALWAYS_INLINE bool isTemporaryRegisterIndex(int index) { - return index >= m_numVars + m_numConstants; + return index >= m_numVars; } HandlerInfo* handlerForBytecodeOffset(unsigned bytecodeOffset); @@ -287,25 +311,25 @@ namespace JSC { m_linkedCallerList.shrink(lastPos); } - StructureStubInfo& getStubInfo(void* returnAddress) + StructureStubInfo& getStubInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress)); + return *(binaryChop<StructureStubInfo, void*, getStructureStubInfoReturnLocation>(m_structureStubInfos.begin(), m_structureStubInfos.size(), returnAddress.value())); } - CallLinkInfo& getCallLinkInfo(void* returnAddress) + CallLinkInfo& getCallLinkInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress)); + return *(binaryChop<CallLinkInfo, void*, getCallLinkInfoReturnLocation>(m_callLinkInfos.begin(), m_callLinkInfos.size(), returnAddress.value())); } - MethodCallLinkInfo& getMethodCallLinkInfo(void* returnAddress) + MethodCallLinkInfo& getMethodCallLinkInfo(ReturnAddressPtr returnAddress) { - return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress)); + return *(binaryChop<MethodCallLinkInfo, void*, getMethodCallLinkInfoReturnLocation>(m_methodCallLinkInfos.begin(), m_methodCallLinkInfos.size(), returnAddress.value())); } - unsigned getBytecodeIndex(CallFrame* callFrame, void* nativePC) + unsigned getBytecodeIndex(CallFrame* callFrame, ReturnAddressPtr returnAddress) { reparseForExceptionInfoIfNecessary(callFrame); - return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(m_exceptionInfo->m_callReturnIndexVector.begin(), m_exceptionInfo->m_callReturnIndexVector.size(), ownerNode()->generatedJITCode().offsetOf(nativePC))->bytecodeIndex; + return binaryChop<CallReturnOffsetToBytecodeIndex, unsigned, getCallReturnOffset>(callReturnIndexVector().begin(), callReturnIndexVector().size(), ownerNode()->generatedJITCode().offsetOf(returnAddress.value()))->bytecodeIndex; } bool functionRegisterForBytecodeOffset(unsigned bytecodeOffset, int& functionRegisterIndex); @@ -320,6 +344,7 @@ namespace JSC { #endif #if ENABLE(JIT) + JITCode& getJITCode() { return ownerNode()->generatedJITCode(); } void setJITCode(JITCode); ExecutablePool* executablePool() { return ownerNode()->getExecutablePool(); } #endif @@ -340,8 +365,8 @@ namespace JSC { CodeType codeType() const { return m_codeType; } - SourceProvider* source() const { return m_source.get(); } - unsigned sourceOffset() const { return m_sourceOffset; } + SourceProvider* source() const { ASSERT(m_codeType != NativeCode); return m_source.get(); } + unsigned sourceOffset() const { ASSERT(m_codeType != NativeCode); return m_sourceOffset; } size_t numberOfJumpTargets() const { return m_jumpTargets.size(); } void addJumpTarget(unsigned jumpTarget) { m_jumpTargets.append(jumpTarget); } @@ -399,7 +424,9 @@ namespace JSC { size_t numberOfConstantRegisters() const { return m_constantRegisters.size(); } void addConstantRegister(const Register& r) { return m_constantRegisters.append(r); } - Register& constantRegister(int index) { return m_constantRegisters[index]; } + Register& constantRegister(int index) { return m_constantRegisters[index - FirstConstantRegisterIndex]; } + ALWAYS_INLINE bool isConstantRegisterIndex(int index) { return index >= FirstConstantRegisterIndex; } + ALWAYS_INLINE JSValue getConstant(int index) const { return m_constantRegisters[index - FirstConstantRegisterIndex].jsValue(); } unsigned addFunctionExpression(FuncExprNode* n) { unsigned size = m_functionExpressions.size(); m_functionExpressions.append(n); return size; } FuncExprNode* functionExpression(int index) const { return m_functionExpressions[index].get(); } @@ -409,9 +436,6 @@ namespace JSC { bool hasFunctions() const { return m_functionExpressions.size() || (m_rareData && m_rareData->m_functions.size()); } - unsigned addUnexpectedConstant(JSValue v) { createRareDataIfNecessary(); unsigned size = m_rareData->m_unexpectedConstants.size(); m_rareData->m_unexpectedConstants.append(v); return size; } - JSValue unexpectedConstant(int index) const { ASSERT(m_rareData); return m_rareData->m_unexpectedConstants[index]; } - unsigned addRegExp(RegExp* r) { createRareDataIfNecessary(); unsigned size = m_rareData->m_regexps.size(); m_rareData->m_regexps.append(r); return size; } RegExp* regexp(int index) const { ASSERT(m_rareData); return m_rareData->m_regexps[index].get(); } @@ -433,18 +457,13 @@ namespace JSC { SymbolTable& symbolTable() { return m_symbolTable; } - EvalCodeCache& evalCodeCache() { createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; } + EvalCodeCache& evalCodeCache() { ASSERT(m_codeType != NativeCode); createRareDataIfNecessary(); return m_rareData->m_evalCodeCache; } void shrinkToFit(); // FIXME: Make these remaining members private. int m_numCalleeRegisters; - // NOTE: numConstants holds the number of constant registers allocated - // by the code generator, not the number of constant registers used. - // (Duplicate constants are uniqued during code generation, and spare - // constant registers may be allocated.) - int m_numConstants; int m_numVars; int m_numParameters; @@ -457,6 +476,7 @@ namespace JSC { void createRareDataIfNecessary() { + ASSERT(m_codeType != NativeCode); if (!m_rareData) m_rareData.set(new RareData); } @@ -501,7 +521,7 @@ namespace JSC { SymbolTable m_symbolTable; - struct ExceptionInfo { + struct ExceptionInfo : FastAllocBase { Vector<ExpressionRangeInfo> m_expressionInfo; Vector<LineInfo> m_lineInfo; Vector<GetByIdExceptionInfo> m_getByIdExceptionInfo; @@ -512,12 +532,11 @@ namespace JSC { }; OwnPtr<ExceptionInfo> m_exceptionInfo; - struct RareData { + struct RareData : FastAllocBase { Vector<HandlerInfo> m_exceptionHandlers; // Rare Constants Vector<RefPtr<FuncDeclNode> > m_functions; - Vector<JSValue> m_unexpectedConstants; Vector<RefPtr<RegExp> > m_regexps; // Jump Tables @@ -572,6 +591,14 @@ namespace JSC { int m_baseScopeDepth; }; + inline Register& ExecState::r(int index) + { + CodeBlock* codeBlock = this->codeBlock(); + if (codeBlock->isConstantRegisterIndex(index)) + return codeBlock->constantRegister(index); + return this[index]; + } + } // namespace JSC #endif // CodeBlock_h diff --git a/JavaScriptCore/bytecode/EvalCodeCache.h b/JavaScriptCore/bytecode/EvalCodeCache.h index f0ce73e..986525c 100644 --- a/JavaScriptCore/bytecode/EvalCodeCache.h +++ b/JavaScriptCore/bytecode/EvalCodeCache.h @@ -68,11 +68,11 @@ namespace JSC { bool isEmpty() const { return m_cacheMap.isEmpty(); } - void mark() + void markAggregate(MarkStack& markStack) { EvalCacheMap::iterator end = m_cacheMap.end(); for (EvalCacheMap::iterator ptr = m_cacheMap.begin(); ptr != end; ++ptr) - ptr->second->mark(); + ptr->second->markAggregate(markStack); } private: static const int maxCacheableSourceLength = 256; diff --git a/JavaScriptCore/bytecode/Instruction.h b/JavaScriptCore/bytecode/Instruction.h index 24ba490..bcef7fb 100644 --- a/JavaScriptCore/bytecode/Instruction.h +++ b/JavaScriptCore/bytecode/Instruction.h @@ -38,12 +38,12 @@ namespace JSC { - // *Sigh*, If the JIT is enabled we need to track the stubRountine (of type MacroAssembler::CodeLocationLabel), + // *Sigh*, If the JIT is enabled we need to track the stubRountine (of type CodeLocationLabel), // If the JIT is not in use we don't actually need the variable (that said, if the JIT is not in use we don't // curently actually use PolymorphicAccessStructureLists, which we should). Anyway, this seems like the best // solution for now - will need to something smarter if/when we actually want mixed-mode operation. #if ENABLE(JIT) - typedef MacroAssembler::CodeLocationLabel PolymorphicAccessStructureListStubRoutineType; + typedef CodeLocationLabel PolymorphicAccessStructureListStubRoutineType; #else typedef void* PolymorphicAccessStructureListStubRoutineType; #endif @@ -53,7 +53,7 @@ namespace JSC { class StructureChain; // 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 PolymorphicAccessStructureList : FastAllocBase { struct PolymorphicStubInfo { bool isChain; PolymorphicAccessStructureListStubRoutineType stubRoutine; diff --git a/JavaScriptCore/bytecode/JumpTable.h b/JavaScriptCore/bytecode/JumpTable.h index eee773c..b4f8e44 100644 --- a/JavaScriptCore/bytecode/JumpTable.h +++ b/JavaScriptCore/bytecode/JumpTable.h @@ -40,7 +40,7 @@ namespace JSC { struct OffsetLocation { int32_t branchOffset; #if ENABLE(JIT) - MacroAssembler::CodeLocationLabel ctiOffset; + CodeLocationLabel ctiOffset; #endif }; @@ -48,7 +48,7 @@ namespace JSC { typedef HashMap<RefPtr<UString::Rep>, OffsetLocation> StringOffsetTable; StringOffsetTable offsetTable; #if ENABLE(JIT) - MacroAssembler::CodeLocationLabel ctiDefault; // FIXME: it should not be necessary to store this. + CodeLocationLabel ctiDefault; // FIXME: it should not be necessary to store this. #endif inline int32_t offsetForValue(UString::Rep* value, int32_t defaultOffset) @@ -61,7 +61,7 @@ namespace JSC { } #if ENABLE(JIT) - inline MacroAssembler::CodeLocationLabel ctiForValue(UString::Rep* value) + inline CodeLocationLabel ctiForValue(UString::Rep* value) { StringOffsetTable::const_iterator end = offsetTable.end(); StringOffsetTable::const_iterator loc = offsetTable.find(value); @@ -77,8 +77,8 @@ namespace JSC { Vector<int32_t> branchOffsets; int32_t min; #if ENABLE(JIT) - Vector<MacroAssembler::CodeLocationLabel> ctiOffsets; - MacroAssembler::CodeLocationLabel ctiDefault; + Vector<CodeLocationLabel> ctiOffsets; + CodeLocationLabel ctiDefault; #endif int32_t offsetForValue(int32_t value, int32_t defaultOffset); @@ -89,7 +89,7 @@ namespace JSC { } #if ENABLE(JIT) - inline MacroAssembler::CodeLocationLabel ctiForValue(int32_t value) + inline CodeLocationLabel ctiForValue(int32_t value) { if (value >= min && static_cast<uint32_t>(value - min) < ctiOffsets.size()) return ctiOffsets[value - min]; diff --git a/JavaScriptCore/bytecode/Opcode.h b/JavaScriptCore/bytecode/Opcode.h index f4421df..c9196ce 100644 --- a/JavaScriptCore/bytecode/Opcode.h +++ b/JavaScriptCore/bytecode/Opcode.h @@ -44,7 +44,6 @@ namespace JSC { macro(op_create_arguments, 1) \ macro(op_convert_this, 2) \ \ - macro(op_unexpected_load, 3) \ macro(op_new_object, 2) \ macro(op_new_array, 4) \ macro(op_new_regexp, 3) \ @@ -68,7 +67,7 @@ namespace JSC { macro(op_negate, 3) \ macro(op_add, 5) \ macro(op_mul, 5) \ - macro(op_div, 4) \ + macro(op_div, 5) \ macro(op_mod, 4) \ macro(op_sub, 5) \ \ @@ -99,7 +98,6 @@ namespace JSC { macro(op_put_global_var, 4) \ macro(op_resolve_base, 3) \ macro(op_resolve_with_base, 4) \ - macro(op_resolve_func, 4) \ macro(op_get_by_id, 8) \ macro(op_get_by_id_self, 8) \ macro(op_get_by_id_self_list, 8) \ @@ -182,7 +180,7 @@ namespace JSC { #define OPCODE_ID_LENGTHS(id, length) const int id##_length = length; FOR_EACH_OPCODE_ID(OPCODE_ID_LENGTHS); - #undef OPCODE_ID_SIZES + #undef OPCODE_ID_LENGTHS #define OPCODE_LENGTH(opcode) opcode##_length diff --git a/JavaScriptCore/bytecode/SamplingTool.h b/JavaScriptCore/bytecode/SamplingTool.h index 7d7dc9c..1a3f7cf 100644 --- a/JavaScriptCore/bytecode/SamplingTool.h +++ b/JavaScriptCore/bytecode/SamplingTool.h @@ -136,11 +136,11 @@ namespace JSC { class SamplingTool { public: - friend class CallRecord; + friend struct CallRecord; friend class HostCallRecord; #if ENABLE(OPCODE_SAMPLING) - class CallRecord : Noncopyable { + class CallRecord : public Noncopyable { public: CallRecord(SamplingTool* samplingTool) : m_samplingTool(samplingTool) @@ -170,7 +170,7 @@ namespace JSC { } }; #else - class CallRecord : Noncopyable { + class CallRecord : public Noncopyable { public: CallRecord(SamplingTool*) { diff --git a/JavaScriptCore/bytecode/StructureStubInfo.cpp b/JavaScriptCore/bytecode/StructureStubInfo.cpp index bf3fdc4..018d832 100644 --- a/JavaScriptCore/bytecode/StructureStubInfo.cpp +++ b/JavaScriptCore/bytecode/StructureStubInfo.cpp @@ -31,44 +31,44 @@ namespace JSC { #if ENABLE(JIT) void StructureStubInfo::deref() { - switch (opcodeID) { - case op_get_by_id_self: + switch (accessType) { + case access_get_by_id_self: u.getByIdSelf.baseObjectStructure->deref(); return; - case op_get_by_id_proto: + case access_get_by_id_proto: u.getByIdProto.baseObjectStructure->deref(); u.getByIdProto.prototypeStructure->deref(); return; - case op_get_by_id_chain: + case access_get_by_id_chain: u.getByIdChain.baseObjectStructure->deref(); u.getByIdChain.chain->deref(); return; - case op_get_by_id_self_list: { + case access_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: { + case access_get_by_id_proto_list: { PolymorphicAccessStructureList* polymorphicStructures = u.getByIdProtoList.structureList; polymorphicStructures->derefStructures(u.getByIdProtoList.listSize); delete polymorphicStructures; return; } - case op_put_by_id_transition: + case access_put_by_id_transition: u.putByIdTransition.previousStructure->deref(); u.putByIdTransition.structure->deref(); u.putByIdTransition.chain->deref(); return; - case op_put_by_id_replace: + case access_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: + case access_get_by_id: + case access_put_by_id: + case access_get_by_id_generic: + case access_put_by_id_generic: + case access_get_array_length: + case access_get_string_length: // These instructions don't ref their Structures. return; default: diff --git a/JavaScriptCore/bytecode/StructureStubInfo.h b/JavaScriptCore/bytecode/StructureStubInfo.h index 24fcb7d..8e2c489 100644 --- a/JavaScriptCore/bytecode/StructureStubInfo.h +++ b/JavaScriptCore/bytecode/StructureStubInfo.h @@ -35,15 +35,32 @@ namespace JSC { + enum AccessType { + access_get_by_id_self, + access_get_by_id_proto, + access_get_by_id_chain, + access_get_by_id_self_list, + access_get_by_id_proto_list, + access_put_by_id_transition, + access_put_by_id_replace, + access_get_by_id, + access_put_by_id, + access_get_by_id_generic, + access_put_by_id_generic, + access_get_array_length, + access_get_string_length, + }; + struct StructureStubInfo { - StructureStubInfo(OpcodeID opcodeID) - : opcodeID(opcodeID) + StructureStubInfo(AccessType accessType) + : accessType(accessType) + , seen(false) { } void initGetByIdSelf(Structure* baseObjectStructure) { - opcodeID = op_get_by_id_self; + accessType = access_get_by_id_self; u.getByIdSelf.baseObjectStructure = baseObjectStructure; baseObjectStructure->ref(); @@ -51,7 +68,7 @@ namespace JSC { void initGetByIdProto(Structure* baseObjectStructure, Structure* prototypeStructure) { - opcodeID = op_get_by_id_proto; + accessType = access_get_by_id_proto; u.getByIdProto.baseObjectStructure = baseObjectStructure; baseObjectStructure->ref(); @@ -62,7 +79,7 @@ namespace JSC { void initGetByIdChain(Structure* baseObjectStructure, StructureChain* chain) { - opcodeID = op_get_by_id_chain; + accessType = access_get_by_id_chain; u.getByIdChain.baseObjectStructure = baseObjectStructure; baseObjectStructure->ref(); @@ -73,7 +90,7 @@ namespace JSC { void initGetByIdSelfList(PolymorphicAccessStructureList* structureList, int listSize) { - opcodeID = op_get_by_id_self_list; + accessType = access_get_by_id_self_list; u.getByIdProtoList.structureList = structureList; u.getByIdProtoList.listSize = listSize; @@ -81,7 +98,7 @@ namespace JSC { void initGetByIdProtoList(PolymorphicAccessStructureList* structureList, int listSize) { - opcodeID = op_get_by_id_proto_list; + accessType = access_get_by_id_proto_list; u.getByIdProtoList.structureList = structureList; u.getByIdProtoList.listSize = listSize; @@ -91,7 +108,7 @@ namespace JSC { void initPutByIdTransition(Structure* previousStructure, Structure* structure, StructureChain* chain) { - opcodeID = op_put_by_id_transition; + accessType = access_put_by_id_transition; u.putByIdTransition.previousStructure = previousStructure; previousStructure->ref(); @@ -105,7 +122,7 @@ namespace JSC { void initPutByIdReplace(Structure* baseObjectStructure) { - opcodeID = op_put_by_id_replace; + accessType = access_put_by_id_replace; u.putByIdReplace.baseObjectStructure = baseObjectStructure; baseObjectStructure->ref(); @@ -113,7 +130,19 @@ namespace JSC { void deref(); - OpcodeID opcodeID; + bool seenOnce() + { + return seen; + } + + void setSeen() + { + seen = true; + } + + int accessType : 31; + int seen : 1; + union { struct { Structure* baseObjectStructure; @@ -144,9 +173,9 @@ namespace JSC { } putByIdReplace; } u; - MacroAssembler::CodeLocationLabel stubRoutine; - MacroAssembler::CodeLocationCall callReturnLocation; - MacroAssembler::CodeLocationLabel hotPathBegin; + CodeLocationLabel stubRoutine; + CodeLocationCall callReturnLocation; + CodeLocationLabel hotPathBegin; }; } // namespace JSC |