summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode/CodeBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/bytecode/CodeBlock.cpp')
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp248
1 files changed, 60 insertions, 188 deletions
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();