summaryrefslogtreecommitdiffstats
path: root/JavaScriptCore/bytecode/CodeBlock.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'JavaScriptCore/bytecode/CodeBlock.cpp')
-rw-r--r--JavaScriptCore/bytecode/CodeBlock.cpp134
1 files changed, 103 insertions, 31 deletions
diff --git a/JavaScriptCore/bytecode/CodeBlock.cpp b/JavaScriptCore/bytecode/CodeBlock.cpp
index 8e77e12..df3ca7b 100644
--- a/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -89,6 +89,25 @@ CString CodeBlock::registerName(ExecState* exec, int r) const
return makeString("r", UString::from(r)).UTF8String();
}
+static UString regexpToSourceString(RegExp* regExp)
+{
+ char postfix[5] = { '/', 0, 0, 0, 0 };
+ int index = 1;
+ if (regExp->global())
+ postfix[index++] = 'g';
+ if (regExp->ignoreCase())
+ postfix[index++] = 'i';
+ if (regExp->multiline())
+ postfix[index] = 'm';
+
+ return makeString("/", regExp->pattern(), postfix);
+}
+
+static CString regexpName(int re, RegExp* regexp)
+{
+ return makeString(regexpToSourceString(regexp), "(@re", UString::from(re), ")").UTF8String();
+}
+
static UString pointerToSourceString(void* p)
{
char buffer[2 + 2 * sizeof(void*) + 1]; // 0x [two characters per byte] \0
@@ -161,7 +180,7 @@ void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction
#if ENABLE(JIT)
static bool isGlobalResolve(OpcodeID opcodeID)
{
- return opcodeID == op_resolve_global;
+ return opcodeID == op_resolve_global || opcodeID == op_resolve_global_dynamic;
}
static bool isPropertyAccess(OpcodeID opcodeID)
@@ -298,6 +317,10 @@ void CodeBlock::printStructures(const Instruction* vPC) const
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));
@@ -345,6 +368,15 @@ void CodeBlock::dump(ExecState* exec) const
} while (i < m_constantRegisters.size());
}
+ if (m_rareData && !m_rareData->m_regexps.isEmpty()) {
+ printf("\nm_regexps:\n");
+ size_t i = 0;
+ do {
+ printf(" re%u = %s\n", static_cast<unsigned>(i), regexpToSourceString(m_rareData->m_regexps[i].get()).ascii());
+ ++i;
+ } while (i < m_rareData->m_regexps.size());
+ }
+
#if ENABLE(JIT)
if (!m_globalResolveInfos.isEmpty() || !m_structureStubInfos.isEmpty())
printf("\nStructures:\n");
@@ -458,11 +490,24 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_create_arguments: {
- printf("[%4d] create_arguments\n", location);
+ int r0 = (++it)->u.operand;
+ printf("[%4d] create_arguments\t %s\n", location, registerName(exec, r0).data());
break;
}
case op_init_arguments: {
- printf("[%4d] init_arguments\n", location);
+ int r0 = (++it)->u.operand;
+ printf("[%4d] init_arguments\t %s\n", location, registerName(exec, r0).data());
+ break;
+ }
+ case op_get_callee: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] op_get_callee %s\n", location, registerName(exec, r0).data());
+ break;
+ }
+ case op_create_this: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ printf("[%4d] create_this %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
break;
}
case op_convert_this: {
@@ -482,6 +527,12 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
printf("[%4d] new_array\t %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, argv).data(), argc);
break;
}
+ case op_new_regexp: {
+ int r0 = (++it)->u.operand;
+ int re0 = (++it)->u.operand;
+ printf("[%4d] new_regexp\t %s, %s\n", location, registerName(exec, r0).data(), regexpName(re0, regexp(re0)).data());
+ break;
+ }
case op_mov: {
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
@@ -666,6 +717,15 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
it += 2;
break;
}
+ case op_resolve_global_dynamic: {
+ int r0 = (++it)->u.operand;
+ JSValue scope = JSValue((++it)->u.jsCell);
+ int id0 = (++it)->u.operand;
+ int depth = it[2].u.operand;
+ printf("[%4d] resolve_global_dynamic\t %s, %s, %s, %d\n", location, registerName(exec, r0).data(), valueToSourceString(exec, scope).ascii(), idName(id0, m_identifiers[id0]).data(), depth);
+ it += 3;
+ break;
+ }
case op_get_scoped_var: {
int r0 = (++it)->u.operand;
int index = (++it)->u.operand;
@@ -931,6 +991,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
printf("[%4d] jless\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
break;
}
+ case op_jlesseq: {
+ int r0 = (++it)->u.operand;
+ int r1 = (++it)->u.operand;
+ int offset = (++it)->u.operand;
+ printf("[%4d] jlesseq\t\t %s, %s, %d(->%d)\n", location, registerName(exec, r0).data(), registerName(exec, r1).data(), offset, location + offset);
+ break;
+ }
case op_loop_if_lesseq: {
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
@@ -972,27 +1039,24 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_call: {
- int dst = (++it)->u.operand;
int func = (++it)->u.operand;
int argCount = (++it)->u.operand;
int registerOffset = (++it)->u.operand;
- printf("[%4d] call\t\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset);
+ printf("[%4d] call\t\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
break;
}
case op_call_eval: {
- int dst = (++it)->u.operand;
int func = (++it)->u.operand;
int argCount = (++it)->u.operand;
int registerOffset = (++it)->u.operand;
- printf("[%4d] call_eval\t %s, %s, %d, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset);
+ printf("[%4d] call_eval\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
break;
}
case op_call_varargs: {
- int dst = (++it)->u.operand;
int func = (++it)->u.operand;
int argCount = (++it)->u.operand;
int registerOffset = (++it)->u.operand;
- printf("[%4d] call_varargs\t %s, %s, %s, %d\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset);
+ printf("[%4d] call_varargs\t %s, %s, %d\n", location, registerName(exec, func).data(), registerName(exec, argCount).data(), registerOffset);
break;
}
case op_load_varargs: {
@@ -1001,11 +1065,13 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
}
case op_tear_off_activation: {
int r0 = (++it)->u.operand;
- printf("[%4d] tear_off_activation\t %s\n", location, registerName(exec, r0).data());
+ int r1 = (++it)->u.operand;
+ printf("[%4d] tear_off_activation\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
break;
}
case op_tear_off_arguments: {
- printf("[%4d] tear_off_arguments\n", location);
+ int r0 = (++it)->u.operand;
+ printf("[%4d] tear_off_arguments\t %s\n", location, registerName(exec, r0).data());
break;
}
case op_ret: {
@@ -1013,20 +1079,22 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
printf("[%4d] ret\t\t %s\n", location, registerName(exec, r0).data());
break;
}
- case op_construct: {
- int dst = (++it)->u.operand;
- int func = (++it)->u.operand;
- int argCount = (++it)->u.operand;
- int registerOffset = (++it)->u.operand;
- int proto = (++it)->u.operand;
- int thisRegister = (++it)->u.operand;
- printf("[%4d] construct\t %s, %s, %d, %d, %s, %s\n", location, registerName(exec, dst).data(), registerName(exec, func).data(), argCount, registerOffset, registerName(exec, proto).data(), registerName(exec, thisRegister).data());
+ case op_call_put_result: {
+ int r0 = (++it)->u.operand;
+ printf("[%4d] op_call_put_result\t\t %s\n", location, registerName(exec, r0).data());
break;
}
- case op_construct_verify: {
+ case op_ret_object_or_this: {
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
- printf("[%4d] construct_verify\t %s, %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+ printf("[%4d] constructor_ret\t\t %s %s\n", location, registerName(exec, r0).data(), registerName(exec, r1).data());
+ break;
+ }
+ case op_construct: {
+ int func = (++it)->u.operand;
+ int argCount = (++it)->u.operand;
+ int registerOffset = (++it)->u.operand;
+ printf("[%4d] construct\t %s, %d, %d\n", location, registerName(exec, func).data(), argCount, registerOffset);
break;
}
case op_strcat: {
@@ -1276,18 +1344,19 @@ void CodeBlock::dumpStatistics()
#endif
}
-CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab)
+CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, CodeType codeType, PassRefPtr<SourceProvider> sourceProvider, unsigned sourceOffset, SymbolTable* symTab, bool isConstructor)
: m_numCalleeRegisters(0)
, m_numVars(0)
, m_numParameters(0)
+ , m_isConstructor(isConstructor)
, m_ownerExecutable(ownerExecutable)
, m_globalData(0)
#ifndef NDEBUG
, m_instructionCount(0)
#endif
+ , m_argumentsRegister(-1)
, m_needsFullScopeChain(ownerExecutable->needsActivation())
, m_usesEval(ownerExecutable->usesEval())
- , m_usesArguments(false)
, m_isNumericCompareFunction(false)
, m_codeType(codeType)
, m_source(sourceProvider)
@@ -1351,7 +1420,7 @@ void CodeBlock::unlinkCallers()
size_t size = m_linkedCallerList.size();
for (size_t i = 0; i < size; ++i) {
CallLinkInfo* currentCaller = m_linkedCallerList[i];
- JIT::unlinkCall(currentCaller);
+ JIT::unlinkCallOrConstruct(currentCaller);
currentCaller->setUnlinked();
}
m_linkedCallerList.clear();
@@ -1366,12 +1435,12 @@ void CodeBlock::derefStructures(Instruction* vPC) const
vPC[4].u.structure->deref();
return;
}
- if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto)) {
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
vPC[4].u.structure->deref();
vPC[5].u.structure->deref();
return;
}
- if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain)) {
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
vPC[4].u.structure->deref();
vPC[5].u.structureChain->deref();
return;
@@ -1386,7 +1455,7 @@ void CodeBlock::derefStructures(Instruction* vPC) const
vPC[4].u.structure->deref();
return;
}
- if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global)) {
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global) || vPC[0].u.opcode == interpreter->getOpcode(op_resolve_global_dynamic)) {
if(vPC[4].u.structure)
vPC[4].u.structure->deref();
return;
@@ -1394,7 +1463,9 @@ void CodeBlock::derefStructures(Instruction* vPC) const
if ((vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto_list))
|| (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_self_list))
|| (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto_list))
- || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list))) {
+ || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_self_list))
+ || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto_list))
+ || (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_self_list))) {
PolymorphicAccessStructureList* polymorphicStructures = vPC[4].u.polymorphicStructures;
polymorphicStructures->derefStructures(vPC[5].u.operand);
delete polymorphicStructures;
@@ -1413,12 +1484,12 @@ void CodeBlock::refStructures(Instruction* vPC) const
vPC[4].u.structure->ref();
return;
}
- if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto)) {
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_proto) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_proto)) {
vPC[4].u.structure->ref();
vPC[5].u.structure->ref();
return;
}
- if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain)) {
+ if (vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_getter_chain) || vPC[0].u.opcode == interpreter->getOpcode(op_get_by_id_custom_chain)) {
vPC[4].u.structure->ref();
vPC[5].u.structureChain->ref();
return;
@@ -1574,7 +1645,7 @@ bool CodeBlock::getByIdExceptionInfoForBytecodeOffset(CallFrame* callFrame, unsi
if (!low || m_exceptionInfo->m_getByIdExceptionInfo[low - 1].bytecodeOffset != bytecodeOffset)
return false;
- opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpConstruct ? op_construct : op_instanceof;
+ opcodeID = m_exceptionInfo->m_getByIdExceptionInfo[low - 1].isOpCreateThis ? op_create_this : op_instanceof;
return true;
}
@@ -1673,6 +1744,7 @@ void CodeBlock::shrinkToFit()
if (m_rareData) {
m_rareData->m_exceptionHandlers.shrinkToFit();
+ m_rareData->m_regexps.shrinkToFit();
m_rareData->m_immediateSwitchJumpTables.shrinkToFit();
m_rareData->m_characterSwitchJumpTables.shrinkToFit();
m_rareData->m_stringSwitchJumpTables.shrinkToFit();