summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/bytecode
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-05-25 15:09:11 +0200
committerSimon Hausmann <simon.hausmann@nokia.com>2012-05-25 15:09:11 +0200
commita89b2ebb8e192c5e8cea21079bda2ee2c0c7dddd (patch)
treeb7abd9f49ae1d4d2e426a5883bfccd42b8e2ee12 /Source/JavaScriptCore/bytecode
parent8d473cf9743f1d30a16a27114e93bd5af5648d23 (diff)
downloadqtwebkit-a89b2ebb8e192c5e8cea21079bda2ee2c0c7dddd.tar.gz
Imported WebKit commit eb5c1b8fe4d4b1b90b5137433fc58a91da0e6878 (http://svn.webkit.org/repository/webkit/trunk@118516)
Diffstat (limited to 'Source/JavaScriptCore/bytecode')
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.cpp446
-rw-r--r--Source/JavaScriptCore/bytecode/CodeBlock.h106
-rw-r--r--Source/JavaScriptCore/bytecode/CodeOrigin.h2
-rw-r--r--Source/JavaScriptCore/bytecode/DFGExitProfile.h15
-rw-r--r--Source/JavaScriptCore/bytecode/Operands.h10
-rw-r--r--Source/JavaScriptCore/bytecode/PredictedType.cpp20
-rw-r--r--Source/JavaScriptCore/bytecode/PredictedType.h44
-rw-r--r--Source/JavaScriptCore/bytecode/StructureStubInfo.h14
-rw-r--r--Source/JavaScriptCore/bytecode/ValueRecovery.h12
9 files changed, 465 insertions, 204 deletions
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index fa663504c..6677b302b 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -43,6 +43,7 @@
#include "JSStaticScopeObject.h"
#include "JSValue.h"
#include "LowLevelInterpreter.h"
+#include "MethodCallLinkStatus.h"
#include "RepatchBuffer.h"
#include "UStringConcatenate.h"
#include <stdio.h>
@@ -150,7 +151,7 @@ NEVER_INLINE static const char* debugHookName(int debugHookID)
return "";
}
-void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op)
{
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
@@ -158,7 +159,7 @@ void CodeBlock::printUnaryOp(ExecState* exec, int location, Vector<Instruction>:
dataLog("[%4d] %s\t\t %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data());
}
-void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op)
{
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
@@ -166,32 +167,240 @@ void CodeBlock::printBinaryOp(ExecState* exec, int location, Vector<Instruction>
dataLog("[%4d] %s\t\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), registerName(exec, r2).data());
}
-void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op) const
+void CodeBlock::printConditionalJump(ExecState* exec, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator& it, int location, const char* op)
{
int r0 = (++it)->u.operand;
int offset = (++it)->u.operand;
dataLog("[%4d] %s\t\t %s, %d(->%d)\n", location, op, registerName(exec, r0).data(), offset, location + offset);
}
-void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+void CodeBlock::printGetByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it)
{
+ const char* op;
+ switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
+ case op_get_by_id:
+ op = "get_by_id";
+ break;
+ case op_get_by_id_self:
+ op = "get_by_id_self";
+ break;
+ case op_get_by_id_proto:
+ op = "get_by_id_proto";
+ break;
+ case op_get_by_id_chain:
+ op = "get_by_id_chain";
+ break;
+ case op_get_by_id_getter_self:
+ op = "get_by_id_getter_self";
+ break;
+ case op_get_by_id_getter_proto:
+ op = "get_by_id_getter_proto";
+ break;
+ case op_get_by_id_getter_chain:
+ op = "get_by_id_getter_chain";
+ break;
+ case op_get_by_id_custom_self:
+ op = "get_by_id_custom_self";
+ break;
+ case op_get_by_id_custom_proto:
+ op = "get_by_id_custom_proto";
+ break;
+ case op_get_by_id_custom_chain:
+ op = "get_by_id_custom_chain";
+ break;
+ case op_get_by_id_generic:
+ op = "get_by_id_generic";
+ break;
+ case op_get_array_length:
+ op = "array_length";
+ break;
+ case op_get_string_length:
+ op = "string_length";
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ op = 0;
+ }
int r0 = (++it)->u.operand;
int r1 = (++it)->u.operand;
int id0 = (++it)->u.operand;
- dataLog("[%4d] %s\t %s, %s, %s\n", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
+ dataLog("[%4d] %s\t %s, %s, %s", location, op, registerName(exec, r0).data(), registerName(exec, r1).data(), idName(id0, m_identifiers[id0]).data());
it += 5;
}
-void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+static void dumpStructure(const char* name, ExecState* exec, Structure* structure, Identifier& ident)
+{
+ if (!structure)
+ return;
+
+ dataLog("%s = %p", name, structure);
+
+ size_t offset = structure->get(exec->globalData(), ident);
+ if (offset != notFound)
+ dataLog(" (offset = %lu)", static_cast<unsigned long>(offset));
+}
+
+static void dumpChain(ExecState* exec, StructureChain* chain, Identifier& ident)
+{
+ dataLog("chain = %p: [", chain);
+ bool first = true;
+ for (WriteBarrier<Structure>* currentStructure = chain->head();
+ *currentStructure;
+ ++currentStructure) {
+ if (first)
+ first = false;
+ else
+ dataLog(", ");
+ dumpStructure("struct", exec, currentStructure->get(), ident);
+ }
+ dataLog("]");
+}
+
+void CodeBlock::printGetByIdCacheStatus(ExecState* exec, int location)
+{
+ Instruction* instruction = instructions().begin() + location;
+
+ if (exec->interpreter()->getOpcodeID(instruction[0].u.opcode) == op_method_check)
+ instruction++;
+
+ Identifier& ident = identifier(instruction[3].u.operand);
+
+#if ENABLE(LLINT)
+ Structure* structure = instruction[4].u.structure.get();
+ dataLog(" llint(");
+ dumpStructure("struct", exec, structure, ident);
+ dataLog(")");
+#endif
+
+#if ENABLE(JIT)
+ if (numberOfStructureStubInfos()) {
+ dataLog(" jit(");
+ StructureStubInfo& stubInfo = getStubInfo(location);
+ if (!stubInfo.seen)
+ dataLog("not seen");
+ else {
+ Structure* baseStructure = 0;
+ Structure* prototypeStructure = 0;
+ StructureChain* chain = 0;
+ PolymorphicAccessStructureList* structureList = 0;
+ int listSize = 0;
+
+ switch (stubInfo.accessType) {
+ case access_get_by_id_self:
+ dataLog("self");
+ baseStructure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
+ break;
+ case access_get_by_id_proto:
+ dataLog("proto");
+ baseStructure = stubInfo.u.getByIdProto.baseObjectStructure.get();
+ prototypeStructure = stubInfo.u.getByIdProto.prototypeStructure.get();
+ break;
+ case access_get_by_id_chain:
+ dataLog("chain");
+ baseStructure = stubInfo.u.getByIdChain.baseObjectStructure.get();
+ chain = stubInfo.u.getByIdChain.chain.get();
+ break;
+ case access_get_by_id_self_list:
+ dataLog("self_list");
+ structureList = stubInfo.u.getByIdSelfList.structureList;
+ listSize = stubInfo.u.getByIdSelfList.listSize;
+ break;
+ case access_get_by_id_proto_list:
+ dataLog("proto_list");
+ structureList = stubInfo.u.getByIdProtoList.structureList;
+ listSize = stubInfo.u.getByIdProtoList.listSize;
+ break;
+ case access_unset:
+ dataLog("unset");
+ break;
+ case access_get_by_id_generic:
+ dataLog("generic");
+ break;
+ case access_get_array_length:
+ dataLog("array_length");
+ break;
+ case access_get_string_length:
+ dataLog("string_length");
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+
+ if (baseStructure) {
+ dataLog(", ");
+ dumpStructure("struct", exec, baseStructure, ident);
+ }
+
+ if (prototypeStructure) {
+ dataLog(", ");
+ dumpStructure("prototypeStruct", exec, baseStructure, ident);
+ }
+
+ if (chain) {
+ dataLog(", ");
+ dumpChain(exec, chain, ident);
+ }
+
+ if (structureList) {
+ dataLog(", list = %p: [", structureList);
+ for (int i = 0; i < listSize; ++i) {
+ if (i)
+ dataLog(", ");
+ dataLog("(");
+ dumpStructure("base", exec, structureList->list[i].base.get(), ident);
+ if (structureList->list[i].isChain) {
+ if (structureList->list[i].u.chain.get()) {
+ dataLog(", ");
+ dumpChain(exec, structureList->list[i].u.chain.get(), ident);
+ }
+ } else {
+ if (structureList->list[i].u.proto.get()) {
+ dataLog(", ");
+ dumpStructure("proto", exec, structureList->list[i].u.proto.get(), ident);
+ }
+ }
+ dataLog(")");
+ }
+ dataLog("]");
+ }
+ }
+ dataLog(")");
+ }
+#endif
+}
+
+void CodeBlock::printCallOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op, CacheDumpMode cacheDumpMode)
{
int func = (++it)->u.operand;
int argCount = (++it)->u.operand;
int registerOffset = (++it)->u.operand;
- dataLog("[%4d] %s\t %s, %d, %d\n", location, op, registerName(exec, func).data(), argCount, registerOffset);
+ dataLog("[%4d] %s\t %s, %d, %d", location, op, registerName(exec, func).data(), argCount, registerOffset);
+ if (cacheDumpMode == DumpCaches) {
+#if ENABLE(LLINT)
+ LLIntCallLinkInfo* callLinkInfo = it[1].u.callLinkInfo;
+ if (callLinkInfo->lastSeenCallee) {
+ dataLog(" llint(%p, exec %p)",
+ callLinkInfo->lastSeenCallee.get(),
+ callLinkInfo->lastSeenCallee->executable());
+ } else
+ dataLog(" llint(not set)");
+#endif
+#if ENABLE(JIT)
+ if (numberOfCallLinkInfos()) {
+ JSFunction* target = getCallLinkInfo(location).lastSeenCallee.get();
+ if (target)
+ dataLog(" jit(%p, exec %p)", target, target->executable());
+ else
+ dataLog(" jit(not set)");
+ }
+#endif
+ }
+ dataLog("\n");
it += 2;
}
-void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op) const
+void CodeBlock::printPutByIdOp(ExecState* exec, int location, Vector<Instruction>::const_iterator& it, const char* op)
{
int r0 = (++it)->u.operand;
int id0 = (++it)->u.operand;
@@ -206,26 +415,6 @@ static bool isGlobalResolve(OpcodeID opcodeID)
return opcodeID == op_resolve_global || opcodeID == op_resolve_global_dynamic;
}
-static bool isPropertyAccess(OpcodeID opcodeID)
-{
- switch (opcodeID) {
- case op_get_by_id_self:
- case op_get_by_id_proto:
- case op_get_by_id_chain:
- case op_put_by_id_transition:
- case op_put_by_id_replace:
- case op_get_by_id:
- case op_put_by_id:
- case op_get_by_id_generic:
- case op_put_by_id_generic:
- case op_get_array_length:
- case op_get_string_length:
- return true;
- default:
- return false;
- }
-}
-
static unsigned instructionOffsetForNth(ExecState* exec, const RefCountedArray<Instruction>& instructions, int nth, bool (*predicate)(OpcodeID))
{
size_t i = 0;
@@ -246,60 +435,15 @@ static void printGlobalResolveInfo(const GlobalResolveInfo& resolveInfo, unsigne
{
dataLog(" [%4d] %s: %s\n", instructionOffset, "resolve_global", pointerToSourceString(resolveInfo.structure).utf8().data());
}
-
-static void printStructureStubInfo(const StructureStubInfo& stubInfo, unsigned instructionOffset)
-{
- switch (stubInfo.accessType) {
- case access_get_by_id_self:
- dataLog(" [%4d] %s: %s\n", instructionOffset, "get_by_id_self", pointerToSourceString(stubInfo.u.getByIdSelf.baseObjectStructure).utf8().data());
- return;
- case access_get_by_id_proto:
- dataLog(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_proto", pointerToSourceString(stubInfo.u.getByIdProto.baseObjectStructure).utf8().data(), pointerToSourceString(stubInfo.u.getByIdProto.prototypeStructure).utf8().data());
- return;
- case access_get_by_id_chain:
- dataLog(" [%4d] %s: %s, %s\n", instructionOffset, "get_by_id_chain", pointerToSourceString(stubInfo.u.getByIdChain.baseObjectStructure).utf8().data(), pointerToSourceString(stubInfo.u.getByIdChain.chain).utf8().data());
- return;
- case access_get_by_id_self_list:
- dataLog(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_self_list", pointerToSourceString(stubInfo.u.getByIdSelfList.structureList).utf8().data(), stubInfo.u.getByIdSelfList.listSize);
- return;
- case access_get_by_id_proto_list:
- dataLog(" [%4d] %s: %s (%d)\n", instructionOffset, "op_get_by_id_proto_list", pointerToSourceString(stubInfo.u.getByIdProtoList.structureList).utf8().data(), stubInfo.u.getByIdProtoList.listSize);
- return;
- case access_put_by_id_transition_normal:
- case access_put_by_id_transition_direct:
- dataLog(" [%4d] %s: %s, %s, %s\n", instructionOffset, "put_by_id_transition", pointerToSourceString(stubInfo.u.putByIdTransition.previousStructure).utf8().data(), pointerToSourceString(stubInfo.u.putByIdTransition.structure).utf8().data(), pointerToSourceString(stubInfo.u.putByIdTransition.chain).utf8().data());
- return;
- case access_put_by_id_replace:
- dataLog(" [%4d] %s: %s\n", instructionOffset, "put_by_id_replace", pointerToSourceString(stubInfo.u.putByIdReplace.baseObjectStructure).utf8().data());
- return;
- case access_unset:
- dataLog(" [%4d] %s\n", instructionOffset, "unset");
- return;
- case access_get_by_id_generic:
- dataLog(" [%4d] %s\n", instructionOffset, "op_get_by_id_generic");
- return;
- case access_put_by_id_generic:
- dataLog(" [%4d] %s\n", instructionOffset, "op_put_by_id_generic");
- return;
- case access_get_array_length:
- dataLog(" [%4d] %s\n", instructionOffset, "op_get_array_length");
- return;
- case access_get_string_length:
- dataLog(" [%4d] %s\n", instructionOffset, "op_get_string_length");
- return;
- default:
- ASSERT_NOT_REACHED();
- }
-}
#endif
-void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand) const
+void CodeBlock::printStructure(const char* name, const Instruction* vPC, int operand)
{
unsigned instructionOffset = vPC - instructions().begin();
dataLog(" [%4d] %s: %s\n", instructionOffset, name, pointerToSourceString(vPC[operand].u.structure).utf8().data());
}
-void CodeBlock::printStructures(const Instruction* vPC) const
+void CodeBlock::printStructures(const Instruction* vPC)
{
Interpreter* interpreter = m_globalData->interpreter;
unsigned instructionOffset = vPC - instructions().begin();
@@ -345,17 +489,30 @@ void CodeBlock::printStructures(const Instruction* vPC) const
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));
}
-void CodeBlock::dump(ExecState* exec) const
+void CodeBlock::dump(ExecState* exec)
{
size_t instructionCount = 0;
for (size_t i = 0; i < instructions().size(); i += opcodeLengths[exec->interpreter()->getOpcodeID(instructions()[i].u.opcode)])
++instructionCount;
- dataLog("%lu m_instructions; %lu bytes at %p; %d parameter(s); %d callee register(s); %d variable(s)\n\n",
+ dataLog(
+ "%lu m_instructions; %lu bytes at %p (%s); %d parameter(s); %d callee register(s); %d variable(s)",
static_cast<unsigned long>(instructions().size()),
static_cast<unsigned long>(instructions().size() * sizeof(Instruction)),
- this, m_numParameters, m_numCalleeRegisters, m_numVars);
+ this, codeTypeToString(codeType()), m_numParameters, m_numCalleeRegisters,
+ m_numVars);
+ if (m_numCapturedVars)
+ dataLog("; %d captured var(s)", m_numCapturedVars);
+ if (usesArguments()) {
+ dataLog(
+ "; uses arguments, in r%d, r%d",
+ argumentsRegister(),
+ unmodifiedArgumentsRegister(argumentsRegister()));
+ }
+ if (needsFullScopeChain() && codeType() == FunctionCode)
+ dataLog("; activation in r%d", activationRegister());
+ dataLog("\n\n");
Vector<Instruction>::const_iterator begin = instructions().begin();
Vector<Instruction>::const_iterator end = instructions().end();
@@ -400,13 +557,6 @@ void CodeBlock::dump(ExecState* exec) const
++i;
} while (i < m_globalResolveInfos.size());
}
- if (!m_structureStubInfos.isEmpty()) {
- size_t i = 0;
- do {
- printStructureStubInfo(m_structureStubInfos[i], instructionOffsetForNth(exec, instructions(), i + 1, isPropertyAccess));
- ++i;
- } while (i < m_structureStubInfos.size());
- }
#endif
#if ENABLE(CLASSIC_INTERPRETER)
if (!m_globalResolveInstructions.isEmpty() || !m_propertyAccessInstructions.isEmpty())
@@ -489,7 +639,7 @@ void CodeBlock::dump(ExecState* exec) const
dataLog("\n");
}
-void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it) const
+void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator& it)
{
int location = it - begin;
switch (exec->interpreter()->getOpcodeID(it->u.opcode)) {
@@ -813,56 +963,22 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
it++;
break;
}
- case op_get_by_id: {
- printGetByIdOp(exec, location, it, "get_by_id");
- break;
- }
- case op_get_by_id_self: {
- printGetByIdOp(exec, location, it, "get_by_id_self");
- break;
- }
- case op_get_by_id_proto: {
- printGetByIdOp(exec, location, it, "get_by_id_proto");
- break;
- }
- case op_get_by_id_chain: {
- printGetByIdOp(exec, location, it, "get_by_id_chain");
- break;
- }
- case op_get_by_id_getter_self: {
- printGetByIdOp(exec, location, it, "get_by_id_getter_self");
- break;
- }
- case op_get_by_id_getter_proto: {
- printGetByIdOp(exec, location, it, "get_by_id_getter_proto");
- break;
- }
- case op_get_by_id_getter_chain: {
- printGetByIdOp(exec, location, it, "get_by_id_getter_chain");
- break;
- }
- case op_get_by_id_custom_self: {
- printGetByIdOp(exec, location, it, "get_by_id_custom_self");
- break;
- }
- case op_get_by_id_custom_proto: {
- printGetByIdOp(exec, location, it, "get_by_id_custom_proto");
- break;
- }
- case op_get_by_id_custom_chain: {
- printGetByIdOp(exec, location, it, "get_by_id_custom_chain");
- break;
- }
- case op_get_by_id_generic: {
- printGetByIdOp(exec, location, it, "get_by_id_generic");
- break;
- }
- case op_get_array_length: {
- printGetByIdOp(exec, location, it, "get_array_length");
- break;
- }
+ case op_get_by_id:
+ case op_get_by_id_self:
+ case op_get_by_id_proto:
+ case op_get_by_id_chain:
+ case op_get_by_id_getter_self:
+ case op_get_by_id_getter_proto:
+ case op_get_by_id_getter_chain:
+ case op_get_by_id_custom_self:
+ case op_get_by_id_custom_proto:
+ case op_get_by_id_custom_chain:
+ case op_get_by_id_generic:
+ case op_get_array_length:
case op_get_string_length: {
- printGetByIdOp(exec, location, it, "get_string_length");
+ printGetByIdOp(exec, location, it);
+ printGetByIdCacheStatus(exec, location);
+ dataLog("\n");
break;
}
case op_get_arguments_length: {
@@ -903,7 +1019,37 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_method_check: {
- dataLog("[%4d] method_check\n", location);
+ dataLog("[%4d] method_check", location);
+ if (numberOfMethodCallLinkInfos()) {
+ MethodCallLinkInfo& methodCall = getMethodCallLinkInfo(location);
+ dataLog(" jit(");
+ if (!methodCall.seen)
+ dataLog("not seen");
+ else {
+ // Use the fact that MethodCallLinkStatus already does smart things
+ // for decoding seen method calls.
+ MethodCallLinkStatus status = MethodCallLinkStatus::computeFor(this, location);
+ if (!status)
+ dataLog("not set");
+ else {
+ dataLog("function = %p (executable = ", status.function());
+ JSCell* functionAsCell = getJSFunction(status.function());
+ if (functionAsCell)
+ dataLog("%p", jsCast<JSFunction*>(functionAsCell)->executable());
+ else
+ dataLog("N/A");
+ dataLog("), struct = %p", status.structure());
+ if (status.needsPrototypeCheck())
+ dataLog(", prototype = %p, struct = %p", status.prototype(), status.prototypeStructure());
+ }
+ }
+ dataLog(")");
+ }
+ dataLog("\n");
+ ++it;
+ printGetByIdOp(exec, location, it);
+ printGetByIdCacheStatus(exec, location);
+ dataLog("\n");
break;
}
case op_del_by_id: {
@@ -1124,11 +1270,11 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_call: {
- printCallOp(exec, location, it, "call");
+ printCallOp(exec, location, it, "call", DumpCaches);
break;
}
case op_call_eval: {
- printCallOp(exec, location, it, "call_eval");
+ printCallOp(exec, location, it, "call_eval", DontDumpCaches);
break;
}
case op_call_varargs: {
@@ -1168,7 +1314,7 @@ void CodeBlock::dump(ExecState* exec, const Vector<Instruction>::const_iterator&
break;
}
case op_construct: {
- printCallOp(exec, location, it, "construct");
+ printCallOp(exec, location, it, "construct", DumpCaches);
break;
}
case op_strcat: {
@@ -1430,7 +1576,7 @@ CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other, SymbolTable* symTab)
, m_optimizationDelayCounter(0)
, m_reoptimizationRetryCounter(0)
#if ENABLE(JIT)
- , m_canCompileWithDFGState(CompileWithDFGUnset)
+ , m_canCompileWithDFGState(DFG::CapabilityLevelNotSet)
#endif
{
setNumParameters(other.numParameters());
@@ -1545,7 +1691,7 @@ void CodeBlock::addParameter()
#endif
}
-void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC) const
+void CodeBlock::visitStructures(SlotVisitor& visitor, Instruction* vPC)
{
Interpreter* interpreter = m_globalData->interpreter;
@@ -2325,17 +2471,17 @@ JSObject* FunctionCodeBlock::compileOptimized(ExecState* exec, ScopeChainNode* s
return error;
}
-bool ProgramCodeBlock::canCompileWithDFGInternal()
+DFG::CapabilityLevel ProgramCodeBlock::canCompileWithDFGInternal()
{
return DFG::canCompileProgram(this);
}
-bool EvalCodeBlock::canCompileWithDFGInternal()
+DFG::CapabilityLevel EvalCodeBlock::canCompileWithDFGInternal()
{
return DFG::canCompileEval(this);
}
-bool FunctionCodeBlock::canCompileWithDFGInternal()
+DFG::CapabilityLevel FunctionCodeBlock::canCompileWithDFGInternal()
{
if (m_isConstructor)
return DFG::canCompileFunctionForConstruct(this);
@@ -2363,25 +2509,25 @@ void FunctionCodeBlock::jettison()
static_cast<FunctionExecutable*>(ownerExecutable())->jettisonOptimizedCodeFor(*globalData(), m_isConstructor ? CodeForConstruct : CodeForCall);
}
-bool ProgramCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+bool ProgramCodeBlock::jitCompileImpl(ExecState* exec)
{
ASSERT(getJITType() == JITCode::InterpreterThunk);
ASSERT(this == replacement());
- return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(globalData);
+ return static_cast<ProgramExecutable*>(ownerExecutable())->jitCompile(exec);
}
-bool EvalCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+bool EvalCodeBlock::jitCompileImpl(ExecState* exec)
{
ASSERT(getJITType() == JITCode::InterpreterThunk);
ASSERT(this == replacement());
- return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(globalData);
+ return static_cast<EvalExecutable*>(ownerExecutable())->jitCompile(exec);
}
-bool FunctionCodeBlock::jitCompileImpl(JSGlobalData& globalData)
+bool FunctionCodeBlock::jitCompileImpl(ExecState* exec)
{
ASSERT(getJITType() == JITCode::InterpreterThunk);
ASSERT(this == replacement());
- return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(globalData, m_isConstructor ? CodeForConstruct : CodeForCall);
+ return static_cast<FunctionExecutable*>(ownerExecutable())->jitCompileFor(exec, m_isConstructor ? CodeForConstruct : CodeForCall);
}
#endif
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index fe69ec673..c1772c3bf 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -37,6 +37,7 @@
#include "CodeType.h"
#include "CompactJITCodeMap.h"
#include "DFGCodeBlocks.h"
+#include "DFGCommon.h"
#include "DFGExitProfile.h"
#include "DFGOSREntry.h"
#include "DFGOSRExit.h"
@@ -132,9 +133,9 @@ namespace JSC {
static void dumpStatistics();
- void dump(ExecState*) const;
- void printStructures(const Instruction*) const;
- void printStructure(const char* name, const Instruction*, int operand) const;
+ void dump(ExecState*);
+ void printStructures(const Instruction*);
+ void printStructure(const char* name, const Instruction*, int operand);
bool isStrictMode() const { return m_isStrictMode; }
@@ -259,7 +260,17 @@ namespace JSC {
DFG::OSREntryData* dfgOSREntryData(unsigned i) { return &m_dfgData->osrEntry[i]; }
DFG::OSREntryData* dfgOSREntryDataForBytecodeIndex(unsigned bytecodeIndex)
{
- return binarySearch<DFG::OSREntryData, unsigned, DFG::getOSREntryDataBytecodeIndex>(m_dfgData->osrEntry.begin(), m_dfgData->osrEntry.size(), bytecodeIndex);
+ if (!m_dfgData)
+ return 0;
+ if (m_dfgData->osrEntry.isEmpty())
+ return 0;
+ DFG::OSREntryData* result = binarySearch<
+ DFG::OSREntryData, unsigned, DFG::getOSREntryDataBytecodeIndex>(
+ m_dfgData->osrEntry.begin(), m_dfgData->osrEntry.size(),
+ bytecodeIndex, WTF::KeyMustNotBePresentInArray);
+ if (result->m_bytecodeIndex != bytecodeIndex)
+ return 0;
+ return result;
}
void appendOSRExit(const DFG::OSRExit& osrExit)
@@ -355,37 +366,31 @@ namespace JSC {
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*) = 0;
virtual void jettison() = 0;
enum JITCompilationResult { AlreadyCompiled, CouldNotCompile, CompiledSuccessfully };
- JITCompilationResult jitCompile(JSGlobalData& globalData)
+ JITCompilationResult jitCompile(ExecState* exec)
{
if (getJITType() != JITCode::InterpreterThunk) {
ASSERT(getJITType() == JITCode::BaselineJIT);
return AlreadyCompiled;
}
#if ENABLE(JIT)
- if (jitCompileImpl(globalData))
+ if (jitCompileImpl(exec))
return CompiledSuccessfully;
return CouldNotCompile;
#else
- UNUSED_PARAM(globalData);
+ UNUSED_PARAM(exec);
return CouldNotCompile;
#endif
}
virtual CodeBlock* replacement() = 0;
- enum CompileWithDFGState {
- CompileWithDFGFalse,
- CompileWithDFGTrue,
- CompileWithDFGUnset
- };
-
- virtual bool canCompileWithDFGInternal() = 0;
- bool canCompileWithDFG()
+ virtual DFG::CapabilityLevel canCompileWithDFGInternal() = 0;
+ DFG::CapabilityLevel canCompileWithDFG()
{
- bool result = canCompileWithDFGInternal();
- m_canCompileWithDFGState = result ? CompileWithDFGTrue : CompileWithDFGFalse;
+ DFG::CapabilityLevel result = canCompileWithDFGInternal();
+ m_canCompileWithDFGState = result;
return result;
}
- CompileWithDFGState canCompileWithDFGState() { return m_canCompileWithDFGState; }
+ DFG::CapabilityLevel canCompileWithDFGState() { return m_canCompileWithDFGState; }
bool hasOptimizedReplacement()
{
@@ -429,6 +434,12 @@ namespace JSC {
ASSERT(usesArguments());
return m_argumentsRegister;
}
+ int uncheckedArgumentsRegister()
+ {
+ if (!usesArguments())
+ return InvalidVirtualRegister;
+ return argumentsRegister();
+ }
void setActivationRegister(int activationRegister)
{
m_activationRegister = activationRegister;
@@ -439,6 +450,31 @@ namespace JSC {
return m_activationRegister;
}
bool usesArguments() const { return m_argumentsRegister != -1; }
+
+ bool needsActivation() const
+ {
+ return needsFullScopeChain() && codeType() != GlobalCode;
+ }
+
+ bool argumentIsCaptured(int) const
+ {
+ return needsActivation() || usesArguments();
+ }
+
+ bool localIsCaptured(InlineCallFrame* inlineCallFrame, int operand) const
+ {
+ if (!inlineCallFrame)
+ return operand < m_numCapturedVars;
+
+ return inlineCallFrame->capturedVars.get(operand);
+ }
+
+ bool isCaptured(InlineCallFrame* inlineCallFrame, int operand) const
+ {
+ if (operandIsArgument(operand))
+ return argumentIsCaptured(operandToArgument(operand));
+ return localIsCaptured(inlineCallFrame, operand);
+ }
CodeType codeType() const { return m_codeType; }
@@ -1065,7 +1101,7 @@ namespace JSC {
protected:
#if ENABLE(JIT)
- virtual bool jitCompileImpl(JSGlobalData&) = 0;
+ virtual bool jitCompileImpl(ExecState*) = 0;
#endif
virtual void visitWeakReferences(SlotVisitor&);
virtual void finalizeUnconditionally();
@@ -1079,16 +1115,18 @@ namespace JSC {
void tallyFrequentExitSites() { }
#endif
- void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&) const;
+ void dump(ExecState*, const Vector<Instruction>::const_iterator& begin, Vector<Instruction>::const_iterator&);
CString registerName(ExecState*, int r) const;
- void printUnaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
- void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
- void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op) const;
- void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
- void printCallOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
- void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op) const;
- void visitStructures(SlotVisitor&, Instruction* vPC) const;
+ void printUnaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op);
+ void printBinaryOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op);
+ void printConditionalJump(ExecState*, const Vector<Instruction>::const_iterator&, Vector<Instruction>::const_iterator&, int location, const char* op);
+ void printGetByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&);
+ void printGetByIdCacheStatus(ExecState*, int location);
+ enum CacheDumpMode { DumpCaches, DontDumpCaches };
+ void printCallOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op, CacheDumpMode);
+ void printPutByIdOp(ExecState*, int location, Vector<Instruction>::const_iterator&, const char* op);
+ void visitStructures(SlotVisitor&, Instruction* vPC);
#if ENABLE(DFG_JIT)
bool shouldImmediatelyAssumeLivenessDuringScan()
@@ -1272,7 +1310,7 @@ namespace JSC {
#endif
OwnPtr<RareData> m_rareData;
#if ENABLE(JIT)
- CompileWithDFGState m_canCompileWithDFGState;
+ DFG::CapabilityLevel m_canCompileWithDFGState;
#endif
};
@@ -1312,9 +1350,9 @@ namespace JSC {
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
- virtual bool jitCompileImpl(JSGlobalData&);
+ virtual bool jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
- virtual bool canCompileWithDFGInternal();
+ virtual DFG::CapabilityLevel canCompileWithDFGInternal();
#endif
};
@@ -1347,9 +1385,9 @@ namespace JSC {
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
- virtual bool jitCompileImpl(JSGlobalData&);
+ virtual bool jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
- virtual bool canCompileWithDFGInternal();
+ virtual DFG::CapabilityLevel canCompileWithDFGInternal();
#endif
private:
@@ -1385,9 +1423,9 @@ namespace JSC {
protected:
virtual JSObject* compileOptimized(ExecState*, ScopeChainNode*);
virtual void jettison();
- virtual bool jitCompileImpl(JSGlobalData&);
+ virtual bool jitCompileImpl(ExecState*);
virtual CodeBlock* replacement();
- virtual bool canCompileWithDFGInternal();
+ virtual DFG::CapabilityLevel canCompileWithDFGInternal();
#endif
};
diff --git a/Source/JavaScriptCore/bytecode/CodeOrigin.h b/Source/JavaScriptCore/bytecode/CodeOrigin.h
index eda17648b..034e48f3f 100644
--- a/Source/JavaScriptCore/bytecode/CodeOrigin.h
+++ b/Source/JavaScriptCore/bytecode/CodeOrigin.h
@@ -28,6 +28,7 @@
#include "ValueRecovery.h"
#include "WriteBarrier.h"
+#include <wtf/BitVector.h>
#include <wtf/StdLibExtras.h>
#include <wtf/Vector.h>
@@ -92,6 +93,7 @@ struct InlineCallFrame {
WriteBarrier<ExecutableBase> executable;
WriteBarrier<JSFunction> callee;
CodeOrigin caller;
+ BitVector capturedVars; // Indexed by the machine call frame's variable numbering.
unsigned stackOffset : 31;
bool isCall : 1;
};
diff --git a/Source/JavaScriptCore/bytecode/DFGExitProfile.h b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
index 31db084f5..09f9ee075 100644
--- a/Source/JavaScriptCore/bytecode/DFGExitProfile.h
+++ b/Source/JavaScriptCore/bytecode/DFGExitProfile.h
@@ -39,6 +39,7 @@ enum ExitKind {
Overflow, // We exited because of overflow.
NegativeZero, // We exited because we encountered negative zero.
InadequateCoverage, // We exited because we ended up in code that didn't have profiling coverage.
+ ArgumentsEscaped, // We exited because arguments escaped but we didn't expect them to.
Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.
};
@@ -96,6 +97,15 @@ public:
ASSERT(exitKindIsCountable(kind));
}
+ // Use this constructor if you wish for the exit site to be counted globally within its
+ // code block.
+ explicit FrequentExitSite(ExitKind kind)
+ : m_bytecodeOffset(0)
+ , m_kind(kind)
+ {
+ ASSERT(exitKindIsCountable(kind));
+ }
+
bool operator!() const
{
return m_kind == ExitKindUnset;
@@ -178,6 +188,11 @@ public:
return m_frequentExitSites.find(site) != m_frequentExitSites.end();
}
+ bool hasExitSite(ExitKind kind) const
+ {
+ return hasExitSite(FrequentExitSite(kind));
+ }
+
bool hasExitSite(unsigned bytecodeIndex, ExitKind kind) const
{
return hasExitSite(FrequentExitSite(bytecodeIndex, kind));
diff --git a/Source/JavaScriptCore/bytecode/Operands.h b/Source/JavaScriptCore/bytecode/Operands.h
index a05159f81..05a24d0fd 100644
--- a/Source/JavaScriptCore/bytecode/Operands.h
+++ b/Source/JavaScriptCore/bytecode/Operands.h
@@ -126,6 +126,16 @@ public:
setLocal(operand, value);
}
+ void setOperandFirstTime(int operand, const T& value)
+ {
+ if (operandIsArgument(operand)) {
+ setArgumentFirstTime(operandToArgument(operand), value);
+ return;
+ }
+
+ setLocalFirstTime(operand, value);
+ }
+
void clear()
{
for (size_t i = 0; i < m_arguments.size(); ++i)
diff --git a/Source/JavaScriptCore/bytecode/PredictedType.cpp b/Source/JavaScriptCore/bytecode/PredictedType.cpp
index e8a71772b..5258f4079 100644
--- a/Source/JavaScriptCore/bytecode/PredictedType.cpp
+++ b/Source/JavaScriptCore/bytecode/PredictedType.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,6 +29,7 @@
#include "config.h"
#include "PredictedType.h"
+#include "Arguments.h"
#include "JSArray.h"
#include "JSFunction.h"
#include "ValueProfile.h"
@@ -117,6 +118,16 @@ const char* predictionToString(PredictedType value)
else
isTop = false;
+ if (value & PredictMyArguments)
+ ptr.strcat("Myarguments");
+ else
+ isTop = false;
+
+ if (value & PredictForeignArguments)
+ ptr.strcat("Foreignarguments");
+ else
+ isTop = false;
+
if (value & PredictString)
ptr.strcat("String");
else
@@ -186,6 +197,10 @@ const char* predictionToAbbreviatedString(PredictedType prediction)
return "<Float32array>";
if (isFloat64ArrayPrediction(prediction))
return "<Float64array>";
+ if (isMyArgumentsPrediction(prediction))
+ return "<Myarguments>";
+ if (isArgumentsPrediction(prediction))
+ return "<Arguments>";
if (isObjectPrediction(prediction))
return "<Object>";
if (isCellPrediction(prediction))
@@ -214,6 +229,9 @@ PredictedType predictionFromClassInfo(const ClassInfo* classInfo)
if (classInfo == &JSString::s_info)
return PredictString;
+ if (classInfo == &Arguments::s_info)
+ return PredictArguments; // Cannot distinguish between MyArguments and ForeignArguments at this stage. That happens in the flow analysis.
+
if (classInfo->isSubClassOf(&JSFunction::s_info))
return PredictFunction;
diff --git a/Source/JavaScriptCore/bytecode/PredictedType.h b/Source/JavaScriptCore/bytecode/PredictedType.h
index 54b308124..9f0964a14 100644
--- a/Source/JavaScriptCore/bytecode/PredictedType.h
+++ b/Source/JavaScriptCore/bytecode/PredictedType.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2011, 2012 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -49,17 +49,20 @@ static const PredictedType PredictUint16Array = 0x00000200; // It's defini
static const PredictedType PredictUint32Array = 0x00000400; // It's definitely an Uint32Array or one of its subclasses.
static const PredictedType PredictFloat32Array = 0x00000800; // It's definitely an Uint16Array or one of its subclasses.
static const PredictedType PredictFloat64Array = 0x00001000; // It's definitely an Uint16Array or one of its subclasses.
-static const PredictedType PredictObjectOther = 0x00002000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
-static const PredictedType PredictObjectMask = 0x00003fff; // Bitmask used for testing for any kind of object prediction.
-static const PredictedType PredictString = 0x00004000; // It's definitely a JSString.
-static const PredictedType PredictCellOther = 0x00008000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
-static const PredictedType PredictCell = 0x0000ffff; // It's definitely a JSCell.
-static const PredictedType PredictInt32 = 0x00010000; // It's definitely an Int32.
-static const PredictedType PredictDoubleReal = 0x00020000; // It's definitely a non-NaN double.
-static const PredictedType PredictDoubleNaN = 0x00040000; // It's definitely a NaN.
-static const PredictedType PredictDouble = 0x00060000; // It's either a non-NaN or a NaN double.
-static const PredictedType PredictNumber = 0x00070000; // It's either an Int32 or a Double.
-static const PredictedType PredictBoolean = 0x00080000; // It's definitely a Boolean.
+static const PredictedType PredictMyArguments = 0x00002000; // It's definitely an Arguments object, and it's definitely the one for my current frame.
+static const PredictedType PredictForeignArguments = 0x00004000; // It's definitely an Arguments object, and it's definitely not mine.
+static const PredictedType PredictArguments = 0x00006000; // It's definitely an Arguments object.
+static const PredictedType PredictObjectOther = 0x00008000; // It's definitely an object but not JSFinalObject, JSArray, or JSFunction.
+static const PredictedType PredictObjectMask = 0x0000ffff; // Bitmask used for testing for any kind of object prediction.
+static const PredictedType PredictString = 0x00010000; // It's definitely a JSString.
+static const PredictedType PredictCellOther = 0x00020000; // It's definitely a JSCell but not a subclass of JSObject and definitely not a JSString.
+static const PredictedType PredictCell = 0x0003ffff; // It's definitely a JSCell.
+static const PredictedType PredictInt32 = 0x00800000; // It's definitely an Int32.
+static const PredictedType PredictDoubleReal = 0x01000000; // It's definitely a non-NaN double.
+static const PredictedType PredictDoubleNaN = 0x02000000; // It's definitely a NaN.
+static const PredictedType PredictDouble = 0x03000000; // It's either a non-NaN or a NaN double.
+static const PredictedType PredictNumber = 0x03800000; // It's either an Int32 or a Double.
+static const PredictedType PredictBoolean = 0x04000000; // It's definitely a Boolean.
static const PredictedType PredictOther = 0x08000000; // It's definitely none of the above.
static const PredictedType PredictTop = 0x0fffffff; // It can be any of the above.
static const PredictedType PredictEmpty = 0x10000000; // It's definitely an empty value marker.
@@ -68,6 +71,12 @@ static const PredictedType FixedIndexedStorageMask = PredictInt8Array | PredictI
typedef bool (*PredictionChecker)(PredictedType);
+// Dummy prediction checker, only useful if someone insists on requiring a prediction checker.
+inline bool isAnyPrediction(PredictedType)
+{
+ return true;
+}
+
inline bool isCellPrediction(PredictedType value)
{
return !!(value & PredictCell) && !(value & ~PredictCell);
@@ -153,6 +162,11 @@ inline bool isFloat64ArrayPrediction(PredictedType value)
return value == PredictFloat64Array;
}
+inline bool isArgumentsPrediction(PredictedType value)
+{
+ return !!value && (value & PredictArguments) == value;
+}
+
inline bool isActionableIntMutableArrayPrediction(PredictedType value)
{
return isInt8ArrayPrediction(value)
@@ -179,6 +193,7 @@ inline bool isActionableTypedMutableArrayPrediction(PredictedType value)
inline bool isActionableMutableArrayPrediction(PredictedType value)
{
return isArrayPrediction(value)
+ || isArgumentsPrediction(value)
|| isActionableTypedMutableArrayPrediction(value);
}
@@ -193,6 +208,11 @@ inline bool isArrayOrOtherPrediction(PredictedType value)
return !!(value & (PredictArray | PredictOther)) && !(value & ~(PredictArray | PredictOther));
}
+inline bool isMyArgumentsPrediction(PredictedType value)
+{
+ return value == PredictMyArguments;
+}
+
inline bool isInt32Prediction(PredictedType value)
{
return value == PredictInt32;
diff --git a/Source/JavaScriptCore/bytecode/StructureStubInfo.h b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
index 03c64bf39..9aa40532a 100644
--- a/Source/JavaScriptCore/bytecode/StructureStubInfo.h
+++ b/Source/JavaScriptCore/bytecode/StructureStubInfo.h
@@ -200,15 +200,15 @@ namespace JSC {
#endif
int8_t valueGPR;
int8_t scratchGPR;
- int16_t deltaCallToDone;
- int16_t deltaCallToStructCheck;
- int16_t deltaCallToSlowCase;
- int16_t deltaCheckImmToCall;
+ int32_t deltaCallToDone;
+ int32_t deltaCallToStructCheck;
+ int32_t deltaCallToSlowCase;
+ int32_t deltaCheckImmToCall;
#if USE(JSVALUE64)
- int16_t deltaCallToLoadOrStore;
+ int32_t deltaCallToLoadOrStore;
#else
- int16_t deltaCallToTagLoadOrStore;
- int16_t deltaCallToPayloadLoadOrStore;
+ int32_t deltaCallToTagLoadOrStore;
+ int32_t deltaCallToPayloadLoadOrStore;
#endif
} dfg;
struct {
diff --git a/Source/JavaScriptCore/bytecode/ValueRecovery.h b/Source/JavaScriptCore/bytecode/ValueRecovery.h
index 007c6d3b7..ebca661d0 100644
--- a/Source/JavaScriptCore/bytecode/ValueRecovery.h
+++ b/Source/JavaScriptCore/bytecode/ValueRecovery.h
@@ -61,6 +61,8 @@ enum ValueRecoveryTechnique {
DoubleDisplacedInRegisterFile,
CellDisplacedInRegisterFile,
BooleanDisplacedInRegisterFile,
+ // It's an Arguments object.
+ ArgumentsThatWereNotCreated,
// It's a constant.
Constant,
// Don't know how to recover it.
@@ -190,6 +192,13 @@ public:
return result;
}
+ static ValueRecovery argumentsThatWereNotCreated()
+ {
+ ValueRecovery result;
+ result.m_technique = ArgumentsThatWereNotCreated;
+ return result;
+ }
+
ValueRecoveryTechnique technique() const { return m_technique; }
bool isConstant() const { return m_technique == Constant; }
@@ -315,6 +324,9 @@ public:
case BooleanDisplacedInRegisterFile:
fprintf(out, "*bool(%d)", virtualRegister());
break;
+ case ArgumentsThatWereNotCreated:
+ fprintf(out, "arguments");
+ break;
case Constant:
fprintf(out, "[%s]", constant().description());
break;