diff options
author | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-22 15:40:17 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@digia.com> | 2012-10-22 15:40:17 +0200 |
commit | 43a42f108af6bcbd91f2672731c3047c26213af1 (patch) | |
tree | 7fa092e5f5d873c72f2486a70e26be26f7a38bec /Source/JavaScriptCore/bytecode | |
parent | d9cf437c840c6eb7417bdd97e6c40979255d3158 (diff) | |
download | qtwebkit-43a42f108af6bcbd91f2672731c3047c26213af1.tar.gz |
Imported WebKit commit 302e7806bff028bd1167a1ec7c86a1ee00ecfb49 (http://svn.webkit.org/repository/webkit/trunk@132067)
New snapshot that fixes build without QtWidgets
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
-rw-r--r-- | Source/JavaScriptCore/bytecode/ArrayProfile.cpp | 36 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/ArrayProfile.h | 33 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.cpp | 248 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/CodeBlock.h | 59 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/DFGExitProfile.h | 1 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/Opcode.h | 36 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp | 44 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h | 3 | ||||
-rw-r--r-- | Source/JavaScriptCore/bytecode/StructureSet.h | 11 |
9 files changed, 201 insertions, 270 deletions
diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp index 3ba974d74..de7f67887 100644 --- a/Source/JavaScriptCore/bytecode/ArrayProfile.cpp +++ b/Source/JavaScriptCore/bytecode/ArrayProfile.cpp @@ -26,8 +26,44 @@ #include "config.h" #include "ArrayProfile.h" +#include <wtf/StringExtras.h> + namespace JSC { +const char* arrayModesToString(ArrayModes arrayModes) +{ + if (!arrayModes) + return "0:<empty>"; + + if (arrayModes == ALL_ARRAY_MODES) + return "TOP"; + + bool isNonArray = !!(arrayModes & NonArray); + bool isNonArrayWithContiguous = !!(arrayModes & NonArrayWithContiguous); + bool isNonArrayWithArrayStorage = !!(arrayModes & NonArrayWithArrayStorage); + bool isNonArrayWithSlowPutArrayStorage = !!(arrayModes & NonArrayWithSlowPutArrayStorage); + bool isArray = !!(arrayModes & ArrayClass); + bool isArrayWithContiguous = !!(arrayModes & ArrayWithContiguous); + bool isArrayWithArrayStorage = !!(arrayModes & ArrayWithArrayStorage); + bool isArrayWithSlowPutArrayStorage = !!(arrayModes & ArrayWithSlowPutArrayStorage); + + static char result[256]; + snprintf( + result, sizeof(result), + "%u:%s%s%s%s%s%s%s%s", + arrayModes, + isNonArray ? "NonArray" : "", + isNonArrayWithContiguous ? "NonArrayWithContiguous" : "", + isNonArrayWithArrayStorage ? " NonArrayWithArrayStorage" : "", + isNonArrayWithSlowPutArrayStorage ? "NonArrayWithSlowPutArrayStorage" : "", + isArray ? "ArrayClass" : "", + isArrayWithContiguous ? "ArrayWithContiguous" : "", + isArrayWithArrayStorage ? " ArrayWithArrayStorage" : "", + isArrayWithSlowPutArrayStorage ? "ArrayWithSlowPutArrayStorage" : ""); + + return result; +} + void ArrayProfile::computeUpdatedPrediction(OperationInProgress operation) { if (m_lastSeenStructure) { diff --git a/Source/JavaScriptCore/bytecode/ArrayProfile.h b/Source/JavaScriptCore/bytecode/ArrayProfile.h index 3b462eaba..ffc136258 100644 --- a/Source/JavaScriptCore/bytecode/ArrayProfile.h +++ b/Source/JavaScriptCore/bytecode/ArrayProfile.h @@ -40,13 +40,44 @@ class LLIntOffsetsExtractor; typedef unsigned ArrayModes; #define asArrayModes(type) \ - (1 << static_cast<unsigned>(type)) + (static_cast<unsigned>(1) << static_cast<unsigned>(type)) + +#define ALL_NON_ARRAY_ARRAY_MODES \ + (asArrayModes(NonArray) \ + | asArrayModes(NonArrayWithContiguous) \ + | asArrayModes(NonArrayWithArrayStorage) \ + | asArrayModes(NonArrayWithSlowPutArrayStorage)) + +#define ALL_ARRAY_ARRAY_MODES \ + (asArrayModes(ArrayClass) \ + | asArrayModes(ArrayWithContiguous) \ + | asArrayModes(ArrayWithArrayStorage) \ + | asArrayModes(ArrayWithSlowPutArrayStorage)) + +#define ALL_ARRAY_MODES (ALL_NON_ARRAY_ARRAY_MODES | ALL_ARRAY_ARRAY_MODES) inline ArrayModes arrayModeFromStructure(Structure* structure) { return asArrayModes(structure->indexingType()); } +const char* arrayModesToString(ArrayModes); + +inline bool mergeArrayModes(ArrayModes& left, ArrayModes right) +{ + ArrayModes newModes = left | right; + if (newModes == left) + return false; + left = newModes; + return true; +} + +// Checks if proven is a subset of expected. +inline bool arrayModesAlreadyChecked(ArrayModes proven, ArrayModes expected) +{ + return (expected | proven) == expected; +} + class ArrayProfile { public: ArrayProfile() diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp index d1151482e..7f86186a0 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp +++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp @@ -439,34 +439,6 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction it += 5; } -#if ENABLE(JIT) -static bool isGlobalResolve(OpcodeID opcodeID) -{ - return opcodeID == op_resolve_global || opcodeID == op_resolve_global_dynamic; -} - -static unsigned instructionOffsetForNth(ExecState* exec, const RefCountedArray<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(currentOpcode)) { - if (!--nth) - return i; - } - i += opcodeLengths[currentOpcode]; - } - - ASSERT_NOT_REACHED(); - return 0; -} - -static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigned instructionOffset) -{ - dataLog(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).utf8().data()); -} -#endif - void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) { unsigned instructionOffset = vPC - instructions().begin(); @@ -506,14 +478,6 @@ void CodeBlock::printStructures(const Instruction* vPC) printStructure("put_by_id_replace", vPC, 4); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) { - printStructure("resolve_global", vPC, 4); - return; - } - if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) { - printStructure("resolve_global_dynamic", vPC, 4); - return; - } // These m_instructions doesn't ref Structures. ASSERT(vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_put_by_id_generic) || vPC[0].u.opcode == interpreter->getOpcode(op_call) || vPC[0].u.opcode == interpreter->getOpcode(op_call_eval) || vPC[0].u.opcode == interpreter->getOpcode(op_construct)); @@ -577,16 +541,8 @@ void CodeBlock::dump(ExecState* exec) } #if ENABLE(JIT) - if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty()) + if (!m_structureStubInfos.isEmpty()) dataLog("\nStructures:\n"); - - if (!m_globalResolveInfos.isEmpty()) { - size_t i = 0; - do { - printGlobalResolveInfo(m_globalResolveInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isGlobalResolve)); - ++i; - } while (i < m_globalResolveInfos.size()); - } #endif if (m_rareData && !m_rareData->m_exceptionHandlers.isEmpty()) { @@ -909,92 +865,30 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& printBinaryOp(exec, location, it, "in"); break; } - case op_resolve: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - dataLog("[%4d] resolve\t\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); - dumpBytecodeCommentAndNewLine(location); - it++; - break; - } - case op_resolve_skip: { - int r0 = (++it)->u.operand; - int id0 = (++it)->u.operand; - int skipLevels = (++it)->u.operand; - dataLog("[%4d] resolve_skip\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), skipLevels); - dumpBytecodeCommentAndNewLine(location); - it++; - break; - } - case op_resolve_global: { - int r0 = (++it)->u.operand; + case op_put_to_base_variable: + case op_put_to_base: { + int base = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve_global\t %s, %s", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + int value = (++it)->u.operand; + int resolveInfo = (++it)->u.operand; + dataLog("[%4d] put_to_base\t %s, %s, %s, %d", location, registerName(exec, base).data(), idName(id0, m_identifiers[id0]).data(), registerName(exec, value).data(), resolveInfo); dumpBytecodeCommentAndNewLine(location); - it += 3; break; } - case op_resolve_global_dynamic: { + case op_resolve: + case op_resolve_global_property: + case op_resolve_global_var: + case op_resolve_scoped_var: + case op_resolve_scoped_var_on_top_scope: + case op_resolve_scoped_var_with_top_scope_check: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; - JSValue scope = JSValue((++it)->u.jsCell.get()); - ++it; - int depth = (++it)->u.operand; - dataLog("[%4d] resolve_global_dynamic\t %s, %s, %s, %d", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).utf8().data(), idName(id0, m_identifiers[id0]).data(), depth); - dumpBytecodeCommentAndNewLine(location); - ++it; - break; - } - case op_get_scoped_var: { - int r0 = (++it)->u.operand; - int index = (++it)->u.operand; - int skipLevels = (++it)->u.operand; - dataLog("[%4d] get_scoped_var\t %s, %d, %d", location, registerName(exec, r0).data(), index, skipLevels); - dumpBytecodeCommentAndNewLine(location); - it++; - break; - } - case op_put_scoped_var: { - int index = (++it)->u.operand; - int skipLevels = (++it)->u.operand; - int r0 = (++it)->u.operand; - dataLog("[%4d] put_scoped_var\t %d, %d, %s", location, index, skipLevels, registerName(exec, r0).data()); - dumpBytecodeCommentAndNewLine(location); - break; - } - case op_get_global_var: { - int r0 = (++it)->u.operand; - WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; - dataLog("[%4d] get_global_var\t %s, g%d(%p)", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); + int resolveInfo = (++it)->u.operand; + dataLog("[%4d] resolve\t\t %s, %s, %d", location, registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); dumpBytecodeCommentAndNewLine(location); it++; break; } - case op_get_global_var_watchable: { - int r0 = (++it)->u.operand; - WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; - dataLog("[%4d] get_global_var_watchable\t %s, g%d(%p)", location, registerName(exec, r0).data(), m_globalObject->findRegisterIndex(registerPointer), registerPointer); - dumpBytecodeCommentAndNewLine(location); - it++; - it++; - break; - } - case op_put_global_var: { - WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; - int r0 = (++it)->u.operand; - dataLog("[%4d] put_global_var\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); - dumpBytecodeCommentAndNewLine(location); - break; - } - case op_put_global_var_check: { - WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; - int r0 = (++it)->u.operand; - dataLog("[%4d] put_global_var_check\t g%d(%p), %s", location, m_globalObject->findRegisterIndex(registerPointer), registerPointer, registerName(exec, r0).data()); - dumpBytecodeCommentAndNewLine(location); - it++; - it++; - break; - } case op_init_global_const: { WriteBarrier<Unknown>* registerPointer = (++it)->u.registerPointer; int r0 = (++it)->u.operand; @@ -1011,11 +905,17 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& it++; break; } + case op_resolve_base_to_global: + case op_resolve_base_to_global_dynamic: + case op_resolve_base_to_scope: + case op_resolve_base_to_scope_with_top_scope_check: case op_resolve_base: { int r0 = (++it)->u.operand; int id0 = (++it)->u.operand; int isStrict = (++it)->u.operand; - dataLog("[%4d] resolve_base%s\t %s, %s", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data()); + int resolveInfo = (++it)->u.operand; + int putToBaseInfo = (++it)->u.operand; + dataLog("[%4d] resolve_base%s\t %s, %s, %d, %d", location, isStrict ? "_strict" : "", registerName(exec, r0).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -1031,7 +931,9 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve_with_base %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + int resolveInfo = (++it)->u.operand; + int putToBaseInfo = (++it)->u.operand; + dataLog("[%4d] resolve_with_base %s, %s, %s, %d, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo, putToBaseInfo); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -1040,7 +942,8 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& int r0 = (++it)->u.operand; int r1 = (++it)->u.operand; int id0 = (++it)->u.operand; - dataLog("[%4d] resolve_with_this %s, %s, %s", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data()); + int resolveInfo = (++it)->u.operand; + dataLog("[%4d] resolve_with_this %s, %s, %s, %d", location, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data(), resolveInfo); dumpBytecodeCommentAndNewLine(location); it++; break; @@ -1704,6 +1607,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other) , m_thisRegister(other.m_thisRegister) , m_argumentsRegister(other.m_argumentsRegister) , m_activationRegister(other.m_activationRegister) + , m_globalObjectConstant(other.m_globalObjectConstant) , m_needsFullScopeChain(other.m_needsFullScopeChain) , m_usesEval(other.m_usesEval) , m_isNumericCompareFunction(other.m_isNumericCompareFunction) @@ -1711,9 +1615,6 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other) , m_codeType(other.m_codeType) , m_source(other.m_source) , m_sourceOffset(other.m_sourceOffset) -#if ENABLE(JIT) - , m_globalResolveInfos(other.m_globalResolveInfos.size()) -#endif #if ENABLE(VALUE_PROFILER) , m_executionEntryCount(0) #endif @@ -1728,6 +1629,8 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other) , m_optimizationDelayCounter(0) , m_reoptimizationRetryCounter(0) , m_lineInfo(other.m_lineInfo) + , m_resolveOperations(other.m_resolveOperations) + , m_putToBaseOperations(other.m_putToBaseOperations) #if ENABLE(BYTECODE_COMMENTS) , m_bytecodeCommentIterator(0) #endif @@ -1739,11 +1642,6 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other) optimizeAfterWarmUp(); jitAfterWarmUp(); -#if ENABLE(JIT) - for (unsigned i = m_globalResolveInfos.size(); i--;) - m_globalResolveInfos[i] = GlobalResolveInfo(other.m_globalResolveInfos[i].bytecodeOffset); -#endif - if (other.m_rareData) { createRareDataIfNecessary(); @@ -1787,13 +1685,16 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, JSGlo #endif { ASSERT(m_source); - + optimizeAfterWarmUp(); jitAfterWarmUp(); #if DUMP_CODE_BLOCK_STATISTICS liveCodeBlockSet.add(this); #endif + // We have a stub putToBase operation to allow resolve_base to + // remain branchless + m_putToBaseOperations.append(PutToBaseOperation(isStrictMode())); } CodeBlock::~CodeBlock() @@ -1892,11 +1793,6 @@ void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) visitor.append(&vPC[4].u.structure); return; } - if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global) || vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) { - if (vPC[3].u.structure) - visitor.append(&vPC[3].u.structure); - return; - } // These instructions don't ref their Structures. 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) || vPC[0].u.opcode == interpreter->getOpcode(op_get_array_length) || vPC[0].u.opcode == interpreter->getOpcode(op_get_string_length)); @@ -2048,7 +1944,7 @@ static const bool verboseUnlinking = true; #else static const bool verboseUnlinking = false; #endif - + void CodeBlock::finalizeUnconditionally() { #if ENABLE(LLINT) @@ -2093,17 +1989,7 @@ void CodeBlock::finalizeUnconditionally() ASSERT_NOT_REACHED(); } } - for (size_t size = m_globalResolveInstructions.size(), i = 0; i < size; ++i) { - Instruction* curInstruction = &instructions()[m_globalResolveInstructions[i]]; - ASSERT(interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global - || interpreter->getOpcodeID(curInstruction[0].u.opcode) == op_resolve_global_dynamic); - if (!curInstruction[3].u.structure || Heap::isMarked(curInstruction[3].u.structure.get())) - continue; - if (verboseUnlinking) - dataLog("Clearing LLInt global resolve cache with structure %p.\n", curInstruction[3].u.structure.get()); - curInstruction[3].u.structure.clear(); - curInstruction[4].u.operand = 0; - } + for (unsigned i = 0; i < m_llintCallLinkInfos.size(); ++i) { if (m_llintCallLinkInfos[i].isLinked() && !Heap::isMarked(m_llintCallLinkInfos[i].callee.get())) { if (verboseUnlinking) @@ -2130,7 +2016,29 @@ void CodeBlock::finalizeUnconditionally() return; } #endif // ENABLE(DFG_JIT) - + + for (size_t size = m_putToBaseOperations.size(), i = 0; i < size; ++i) { + if (m_putToBaseOperations[i].m_structure && !Heap::isMarked(m_putToBaseOperations[i].m_structure.get())) { + if (verboseUnlinking) + dataLog("Clearing putToBase info in %p.\n", this); + m_putToBaseOperations[i].m_structure.clear(); + } + } + for (size_t size = m_resolveOperations.size(), i = 0; i < size; ++i) { + if (m_resolveOperations[i].isEmpty()) + continue; +#ifndef NDEBUG + for (size_t insnSize = m_resolveOperations[i].size() - 1, k = 0; k < insnSize; ++k) + ASSERT(!m_resolveOperations[i][k].m_structure); +#endif + m_resolveOperations[i].last().m_structure.clear(); + if (m_resolveOperations[i].last().m_structure && !Heap::isMarked(m_resolveOperations[i].last().m_structure.get())) { + if (verboseUnlinking) + dataLog("Clearing resolve info in %p.\n", this); + m_resolveOperations[i].last().m_structure.clear(); + } + } + #if ENABLE(JIT) // Handle inline caches. if (!!getJITCode()) { @@ -2145,14 +2053,6 @@ void CodeBlock::finalizeUnconditionally() && !Heap::isMarked(callLinkInfo(i).lastSeenCallee.get())) callLinkInfo(i).lastSeenCallee.clear(); } - for (size_t size = m_globalResolveInfos.size(), i = 0; i < size; ++i) { - if (m_globalResolveInfos[i].structure && !Heap::isMarked(m_globalResolveInfos[i].structure.get())) { - if (verboseUnlinking) - dataLog("Clearing resolve info in %p.\n", this); - m_globalResolveInfos[i].structure.clear(); - } - } - for (size_t size = m_structureStubInfos.size(), i = 0; i < size; ++i) { StructureStubInfo& stubInfo = m_structureStubInfos[i]; @@ -2422,43 +2322,14 @@ void CodeBlock::expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& d return; } -#if ENABLE(JIT) -bool CodeBlock::hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset) -{ - if (m_globalResolveInfos.isEmpty()) - return false; - - int low = 0; - int high = m_globalResolveInfos.size(); - while (low < high) { - int mid = low + (high - low) / 2; - if (m_globalResolveInfos[mid].bytecodeOffset <= bytecodeOffset) - low = mid + 1; - else - high = mid; - } - - if (!low || m_globalResolveInfos[low - 1].bytecodeOffset != bytecodeOffset) - return false; - return true; -} -GlobalResolveInfo& CodeBlock::globalResolveInfoForBytecodeOffset(unsigned bytecodeOffset) -{ - return *(binarySearch<GlobalResolveInfo, unsigned, getGlobalResolveInfoBytecodeOffset>(m_globalResolveInfos.begin(), m_globalResolveInfos.size(), bytecodeOffset)); -} -#endif - void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) { m_propertyAccessInstructions.shrinkToFit(); - m_globalResolveInstructions.shrinkToFit(); #if ENABLE(LLINT) m_llintCallLinkInfos.shrinkToFit(); #endif #if ENABLE(JIT) m_structureStubInfos.shrinkToFit(); - if (shrinkMode == EarlyShrink) - m_globalResolveInfos.shrinkToFit(); m_callLinkInfos.shrinkToFit(); m_methodCallLinkInfos.shrinkToFit(); #endif @@ -2477,6 +2348,7 @@ void CodeBlock::shrinkToFit(ShrinkMode shrinkMode) m_constantRegisters.shrinkToFit(); } // else don't shrink these, because we would have already pointed pointers into these tables. + m_resolveOperations.shrinkToFit(); m_lineInfo.shrinkToFit(); if (m_rareData) { m_rareData->m_exceptionHandlers.shrinkToFit(); diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h index 01a8ef4a1..fe588c787 100644 --- a/Source/JavaScriptCore/bytecode/CodeBlock.h +++ b/Source/JavaScriptCore/bytecode/CodeBlock.h @@ -49,7 +49,6 @@ #include "EvalCodeCache.h" #include "ExecutionCounter.h" #include "ExpressionRangeInfo.h" -#include "GlobalResolveInfo.h" #include "HandlerInfo.h" #include "MethodCallLinkInfo.h" #include "Options.h" @@ -64,6 +63,7 @@ #include "LineInfo.h" #include "Nodes.h" #include "RegExpObject.h" +#include "ResolveOperation.h" #include "StructureStubInfo.h" #include "UnconditionalFinalizer.h" #include "ValueProfile.h" @@ -197,6 +197,30 @@ namespace JSC { int lineNumberForBytecodeOffset(unsigned bytecodeOffset); void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot, int& startOffset, int& endOffset); + uint32_t addResolve() + { + m_resolveOperations.grow(m_resolveOperations.size() + 1); + return m_resolveOperations.size() - 1; + } + uint32_t addPutToBase() + { + m_putToBaseOperations.append(PutToBaseOperation(isStrictMode())); + return m_putToBaseOperations.size() - 1; + } + + ResolveOperations* resolveOperations(uint32_t i) + { + return &m_resolveOperations[i]; + } + + PutToBaseOperation* putToBaseOperation(uint32_t i) + { + return &m_putToBaseOperations[i]; + } + + size_t numberOfResolveOperations() const { return m_resolveOperations.size(); } + size_t numberOfPutToBaseOperations() const { return m_putToBaseOperations.size(); } + #if ENABLE(JIT) StructureStubInfo& getStubInfo(ReturnAddressPtr returnAddress) @@ -600,11 +624,6 @@ namespace JSC { { m_propertyAccessInstructions.append(propertyAccessInstruction); } - void addGlobalResolveInstruction(unsigned globalResolveInstruction) - { - m_globalResolveInstructions.append(globalResolveInstruction); - } - bool hasGlobalResolveInstructionAtBytecodeOffset(unsigned bytecodeOffset); #if ENABLE(LLINT) LLIntCallLinkInfo* addLLIntCallLinkInfo() { @@ -621,15 +640,6 @@ namespace JSC { size_t numberOfByValInfos() const { return m_byValInfos.size(); } ByValInfo& byValInfo(size_t index) { return m_byValInfos[index]; } - void addGlobalResolveInfo(unsigned globalResolveInstruction) - { - m_globalResolveInfos.append(GlobalResolveInfo(globalResolveInstruction)); - } - GlobalResolveInfo& globalResolveInfo(int index) { return m_globalResolveInfos[index]; } - bool hasGlobalResolveInfoAtBytecodeOffset(unsigned bytecodeOffset); - GlobalResolveInfo& globalResolveInfoForBytecodeOffset(unsigned bytecodeOffset); - unsigned numberOfGlobalResolveInfos() { return m_globalResolveInfos.size(); } - void setNumberOfCallLinkInfos(size_t size) { m_callLinkInfos.grow(size); } size_t numberOfCallLinkInfos() const { return m_callLinkInfos.size(); } CallLinkInfo& callLinkInfo(int index) { return m_callLinkInfos[index]; } @@ -781,15 +791,6 @@ namespace JSC { ArrayProfile* getArrayProfile(unsigned bytecodeOffset); ArrayProfile* getOrAddArrayProfile(unsigned bytecodeOffset); #endif - - unsigned globalResolveInfoCount() const - { -#if ENABLE(JIT) - if (m_globalData->canUseJIT()) - return m_globalResolveInfos.size(); -#endif - return 0; - } // Exception handling support @@ -1215,13 +1216,16 @@ namespace JSC { int m_numVars; bool m_isConstructor; + int globalObjectConstant() const { return m_globalObjectConstant; } + void setGlobalObjectConstant(int globalRegister) { m_globalObjectConstant = globalRegister; } + protected: #if ENABLE(JIT) virtual bool jitCompileImpl(ExecState*) = 0; #endif virtual void visitWeakReferences(SlotVisitor&); virtual void finalizeUnconditionally(); - + private: friend class DFGCodeBlocks; @@ -1294,6 +1298,7 @@ namespace JSC { int m_thisRegister; int m_argumentsRegister; int m_activationRegister; + int m_globalObjectConstant; bool m_needsFullScopeChain; bool m_usesEval; @@ -1306,7 +1311,6 @@ namespace JSC { unsigned m_sourceOffset; Vector<unsigned> m_propertyAccessInstructions; - Vector<unsigned> m_globalResolveInstructions; #if ENABLE(LLINT) SegmentedVector<LLIntCallLinkInfo, 8> m_llintCallLinkInfos; SentinelLinkedList<LLIntCallLinkInfo, BasicRawSentinelNode<LLIntCallLinkInfo> > m_incomingLLIntCalls; @@ -1314,7 +1318,6 @@ namespace JSC { #if ENABLE(JIT) Vector<StructureStubInfo> m_structureStubInfos; Vector<ByValInfo> m_byValInfos; - Vector<GlobalResolveInfo> m_globalResolveInfos; Vector<CallLinkInfo> m_callLinkInfos; Vector<MethodCallLinkInfo> m_methodCallLinkInfos; JITCode m_jitCode; @@ -1406,6 +1409,8 @@ namespace JSC { Vector<Comment> m_bytecodeComments; size_t m_bytecodeCommentIterator; #endif + Vector<ResolveOperations> m_resolveOperations; + Vector<PutToBaseOperation> m_putToBaseOperations; struct RareData { WTF_MAKE_FAST_ALLOCATED; diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h index 45947c8af..57fb06bda 100644 --- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h +++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h @@ -36,6 +36,7 @@ enum ExitKind { ExitKindUnset, BadType, // We exited because a type prediction was wrong. BadCache, // We exited because an inline cache was wrong. + BadIndexingType, // We exited because an indexing type was wrong. Overflow, // We exited because of overflow. NegativeZero, // We exited because we encountered negative zero. OutOfBounds, // We had an out-of-bounds access to an array. diff --git a/Source/JavaScriptCore/bytecode/Opcode.h b/Source/JavaScriptCore/bytecode/Opcode.h index dd62df700..3ce56c80e 100644 --- a/Source/JavaScriptCore/bytecode/Opcode.h +++ b/Source/JavaScriptCore/bytecode/Opcode.h @@ -96,22 +96,30 @@ namespace JSC { macro(op_is_function, 3) \ macro(op_in, 4) \ \ - macro(op_resolve, 4) /* has value profiling */ \ - macro(op_resolve_skip, 5) /* has value profiling */ \ - macro(op_resolve_global, 6) /* has value profiling */ \ - macro(op_resolve_global_dynamic, 7) /* has value profiling */ \ - macro(op_get_scoped_var, 5) /* has value profiling */ \ - macro(op_put_scoped_var, 4) \ - macro(op_get_global_var, 4) /* has value profiling */ \ - macro(op_get_global_var_watchable, 5) /* has value profiling */ \ - macro(op_put_global_var, 3) \ - macro(op_put_global_var_check, 5) \ + macro(op_resolve, 5) /* has value profiling */ \ + macro(op_resolve_global_property, 5) /* has value profiling */ \ + macro(op_resolve_global_var, 5) /* has value profiling */ \ + macro(op_resolve_scoped_var, 5) /* has value profiling */ \ + macro(op_resolve_scoped_var_on_top_scope, 5) /* has value profiling */ \ + macro(op_resolve_scoped_var_with_top_scope_check, 5) /* has value profiling */ \ + \ + macro(op_resolve_base_to_global, 7) /* has value profiling */ \ + macro(op_resolve_base_to_global_dynamic, 7) /* has value profiling */ \ + macro(op_resolve_base_to_scope, 7) /* has value profiling */ \ + macro(op_resolve_base_to_scope_with_top_scope_check, 7) /* has value profiling */ \ + macro(op_resolve_base, 7) /* has value profiling */ \ + \ + macro(op_ensure_property_exists, 3) \ + \ + macro(op_resolve_with_base, 7) /* has value profiling */ \ + \ + macro(op_resolve_with_this, 6) /* has value profiling */ \ + \ + macro(op_put_to_base, 5) \ + macro(op_put_to_base_variable, 5) \ + \ macro(op_init_global_const, 3) \ macro(op_init_global_const_check, 5) \ - macro(op_resolve_base, 5) /* has value profiling */ \ - macro(op_ensure_property_exists, 3) \ - macro(op_resolve_with_base, 5) /* has value profiling */ \ - macro(op_resolve_with_this, 5) /* has value profiling */ \ macro(op_get_by_id, 9) /* has value profiling */ \ macro(op_get_by_id_out_of_line, 9) /* has value profiling */ \ macro(op_get_by_id_self, 9) /* has value profiling */ \ diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp index c9fd7dca2..7814f8c99 100644 --- a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp @@ -32,13 +32,11 @@ namespace JSC { -#if ENABLE(LLINT) || (ENABLE(JIT) && ENABLE(VALUE_PROFILER)) static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure* structure, Identifier& identifier) { unsigned attributesIgnored; JSCell* specificValue; - PropertyOffset offset = structure->get( - *codeBlock->globalData(), identifier, attributesIgnored, specificValue); + PropertyOffset offset = structure->get(*codeBlock->globalData(), identifier, attributesIgnored, specificValue); if (structure->isDictionary()) specificValue = 0; if (!isValidOffset(offset)) @@ -46,46 +44,14 @@ static ResolveGlobalStatus computeForStructure(CodeBlock* codeBlock, Structure* return ResolveGlobalStatus(ResolveGlobalStatus::Simple, structure, offset, specificValue); } -#endif // ENABLE(LLINT) || ENABLE(JIT) -static ResolveGlobalStatus computeForLLInt(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier) +ResolveGlobalStatus ResolveGlobalStatus::computeFor(CodeBlock* codeBlock, int, ResolveOperation* operation, Identifier& identifier) { -#if ENABLE(LLINT) - Instruction* instruction = codeBlock->instructions().begin() + bytecodeIndex; - - ASSERT(instruction[0].u.opcode == LLInt::getOpcode(op_resolve_global)); - - Structure* structure = instruction[3].u.structure.get(); - if (!structure) + ASSERT(operation->m_operation == ResolveOperation::GetAndReturnGlobalProperty); + if (!operation->m_structure) return ResolveGlobalStatus(); - return computeForStructure(codeBlock, structure, identifier); -#else - UNUSED_PARAM(codeBlock); - UNUSED_PARAM(bytecodeIndex); - UNUSED_PARAM(identifier); - return ResolveGlobalStatus(); -#endif -} - -ResolveGlobalStatus ResolveGlobalStatus::computeFor(CodeBlock* codeBlock, unsigned bytecodeIndex, Identifier& identifier) -{ -#if ENABLE(JIT) && ENABLE(VALUE_PROFILER) - if (!codeBlock->numberOfGlobalResolveInfos()) - return computeForLLInt(codeBlock, bytecodeIndex, identifier); - - if (codeBlock->likelyToTakeSlowCase(bytecodeIndex)) - return ResolveGlobalStatus(TakesSlowPath); - - GlobalResolveInfo& globalResolveInfo = codeBlock->globalResolveInfoForBytecodeOffset(bytecodeIndex); - - if (!globalResolveInfo.structure) - return computeForLLInt(codeBlock, bytecodeIndex, identifier); - - return computeForStructure(codeBlock, globalResolveInfo.structure.get(), identifier); -#else - return computeForLLInt(codeBlock, bytecodeIndex, identifier); -#endif + return computeForStructure(codeBlock, operation->m_structure.get(), identifier); } } // namespace JSC diff --git a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h index cbe4d3b5f..46a9254e7 100644 --- a/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h +++ b/Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h @@ -34,6 +34,7 @@ namespace JSC { class CodeBlock; class Identifier; +struct ResolveOperation; class Structure; class ResolveGlobalStatus { @@ -61,7 +62,7 @@ public: { } - static ResolveGlobalStatus computeFor(CodeBlock*, unsigned bytecodeIndex, Identifier&); + static ResolveGlobalStatus computeFor(CodeBlock*, int bytecodeIndex, ResolveOperation*, Identifier&); State state() const { return m_state; } diff --git a/Source/JavaScriptCore/bytecode/StructureSet.h b/Source/JavaScriptCore/bytecode/StructureSet.h index ebde9779f..c95d3047b 100644 --- a/Source/JavaScriptCore/bytecode/StructureSet.h +++ b/Source/JavaScriptCore/bytecode/StructureSet.h @@ -26,6 +26,7 @@ #ifndef StructureSet_h #define StructureSet_h +#include "ArrayProfile.h" #include "SpeculatedType.h" #include "Structure.h" #include <stdio.h> @@ -137,6 +138,16 @@ public: return result; } + ArrayModes arrayModesFromStructures() const + { + ArrayModes result = 0; + + for (size_t i = 0; i < m_structures.size(); ++i) + mergeArrayModes(result, asArrayModes(m_structures[i]->indexingType())); + + return result; + } + bool operator==(const StructureSet& other) const { if (m_structures.size() != other.m_structures.size()) |