summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
committerSimon Hausmann <simon.hausmann@digia.com>2012-10-22 15:40:17 +0200
commit43a42f108af6bcbd91f2672731c3047c26213af1 (patch)
tree7fa092e5f5d873c72f2486a70e26be26f7a38bec /Source/JavaScriptCore/bytecode
parentd9cf437c840c6eb7417bdd97e6c40979255d3158 (diff)
downloadqtwebkit-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.cpp36
-rw-r--r--Source/JavaScriptCore/bytecode/ArrayProfile.h33
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp248
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h59
-rw-r--r--Source/JavaScriptCore/bytecode/DFGExitProfile.h1
-rw-r--r--Source/JavaScriptCore/bytecode/Opcode.h36
-rw-r--r--Source/JavaScriptCore/bytecode/ResolveGlobalStatus.cpp44
-rw-r--r--Source/JavaScriptCore/bytecode/ResolveGlobalStatus.h3
-rw-r--r--Source/JavaScriptCore/bytecode/StructureSet.h11
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())