summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-02-03 09:55:33 +0100
commitcd44dc59cdfc39534aef4d417e9f3c412e3be139 (patch)
tree8d89889ba95ed6ec9322e733846cc9cce9d7dff1 /Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
parentd11f84f5b5cdc0d92a08af01b13472fdd5f9acb9 (diff)
downloadqtwebkit-cd44dc59cdfc39534aef4d417e9f3c412e3be139.tar.gz
Imported WebKit commit fce473cb4d55aa9fe9d0b0322a2fffecb731b961 (http://svn.webkit.org/repository/webkit/trunk@106560)
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp329
1 files changed, 155 insertions, 174 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
index 964618c43..87c3a23b9 100644
--- a/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
+++ b/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
@@ -28,9 +28,13 @@
#if ENABLE(DFG_JIT)
+#include "CallLinkStatus.h"
+#include "CodeBlock.h"
#include "DFGByteCodeCache.h"
#include "DFGCapabilities.h"
-#include "CodeBlock.h"
+#include "GetByIdStatus.h"
+#include "MethodCallLinkStatus.h"
+#include "PutByIdStatus.h"
#include <wtf/HashMap.h>
#include <wtf/MathExtras.h>
@@ -48,6 +52,7 @@ public:
, m_graph(graph)
, m_currentBlock(0)
, m_currentIndex(0)
+ , m_currentProfilingIndex(0)
, m_constantUndefined(UINT_MAX)
, m_constantNull(UINT_MAX)
, m_constantNaN(UINT_MAX)
@@ -329,7 +334,8 @@ private:
JSValue v = valueOfJSConstant(index);
if (v.isInt32())
return getJSConstant(node.constantNumber());
- // FIXME: We could convert the double ToInteger at this point.
+ if (v.isNumber())
+ return getJSConstantForValue(JSValue(JSC::toInt32(v.asNumber())));
}
return addToGraph(ValueToInt32, index);
@@ -351,6 +357,17 @@ private:
return addToGraph(ValueToNumber, OpInfo(NodeUseBottom), index);
}
+
+ NodeIndex getJSConstantForValue(JSValue constantValue)
+ {
+ unsigned constantIndex = m_codeBlock->addOrFindConstant(constantValue);
+ if (constantIndex >= m_constants.size())
+ m_constants.append(ConstantRecord());
+
+ ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
+
+ return getJSConstant(constantIndex);
+ }
NodeIndex getJSConstant(unsigned constant)
{
@@ -382,16 +399,6 @@ private:
{
return isJSConstant(nodeIndex) && valueOfJSConstant(nodeIndex).isInt32();
}
- bool isSmallInt32Constant(NodeIndex nodeIndex)
- {
- if (!isJSConstant(nodeIndex))
- return false;
- JSValue value = valueOfJSConstant(nodeIndex);
- if (!value.isInt32())
- return false;
- int32_t intValue = value.asInt32();
- return intValue >= -5 && intValue <= 5;
- }
// Convenience methods for getting constant values.
JSValue valueOfJSConstant(NodeIndex index)
{
@@ -403,7 +410,7 @@ private:
ASSERT(isInt32Constant(nodeIndex));
return valueOfJSConstant(nodeIndex).asInt32();
}
-
+
// This method returns a JSConstant with the value 'undefined'.
NodeIndex constantUndefined()
{
@@ -519,7 +526,7 @@ private:
CodeOrigin currentCodeOrigin()
{
- return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame);
+ return CodeOrigin(m_currentIndex, m_inlineStackTop->m_inlineCallFrame, m_currentProfilingIndex - m_currentIndex);
}
// These methods create a node and add it to the graph. If nodes of this type are
@@ -574,8 +581,10 @@ private:
Instruction* putInstruction = currentInstruction + OPCODE_LENGTH(op_call);
PredictedType prediction = PredictNone;
- if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result)
- prediction = getPrediction(m_graph.size(), m_currentIndex + OPCODE_LENGTH(op_call));
+ if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
+ m_currentProfilingIndex = m_currentIndex + OPCODE_LENGTH(op_call);
+ prediction = getPrediction();
+ }
addVarArgChild(get(currentInstruction[1].u.operand));
int argCount = currentInstruction[2].u.operand;
@@ -622,12 +631,12 @@ private:
PredictedType getPredictionWithoutOSRExit()
{
- return getPredictionWithoutOSRExit(m_graph.size(), m_currentIndex);
+ return getPredictionWithoutOSRExit(m_graph.size(), m_currentProfilingIndex);
}
PredictedType getPrediction()
{
- return getPrediction(m_graph.size(), m_currentIndex);
+ return getPrediction(m_graph.size(), m_currentProfilingIndex);
}
NodeIndex makeSafe(NodeIndex nodeIndex)
@@ -700,6 +709,29 @@ private:
return nodeIndex;
}
+ bool willNeedFlush(StructureStubInfo& stubInfo)
+ {
+ PolymorphicAccessStructureList* list;
+ int listSize;
+ switch (stubInfo.accessType) {
+ case access_get_by_id_self_list:
+ list = stubInfo.u.getByIdSelfList.structureList;
+ listSize = stubInfo.u.getByIdSelfList.listSize;
+ break;
+ case access_get_by_id_proto_list:
+ list = stubInfo.u.getByIdProtoList.structureList;
+ listSize = stubInfo.u.getByIdProtoList.listSize;
+ break;
+ default:
+ return false;
+ }
+ for (int i = 0; i < listSize; ++i) {
+ if (!list->list[i].isDirect)
+ return true;
+ }
+ return false;
+ }
+
bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)
{
if (direct)
@@ -727,6 +759,8 @@ private:
BasicBlock* m_currentBlock;
// The bytecode index of the current instruction being generated.
unsigned m_currentIndex;
+ // The bytecode index of the value profile of the current instruction being generated.
+ unsigned m_currentProfilingIndex;
// We use these values during code generation, and to avoid the need for
// special handling we make sure they are available as constants in the
@@ -890,6 +924,7 @@ private:
m_currentIndex += OPCODE_LENGTH(name); \
return shouldContinueParsing
+
void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentInstruction, NodeType op, CodeSpecializationKind kind)
{
ASSERT(OPCODE_LENGTH(op_call) == OPCODE_LENGTH(op_construct));
@@ -898,13 +933,15 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
enum { ConstantFunction, LinkedFunction, UnknownFunction } callType;
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Slow case count for call at @%lu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+ printf("Slow case count for call at @%zu bc#%u: %u/%u; exit profile: %d.\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_profiledBlock->executionEntryCount(), m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
-
+
+ CallLinkStatus callLinkStatus = CallLinkStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex);
+
if (m_graph.isFunctionConstant(m_codeBlock, callTarget))
callType = ConstantFunction;
- else if (!!m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee
- && !m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
+ else if (callLinkStatus.isSet() && !callLinkStatus.couldTakeSlowPath()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache))
callType = LinkedFunction;
else
@@ -922,7 +959,8 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
if (interpreter->getOpcodeID(putInstruction->u.opcode) == op_call_put_result) {
resultOperand = putInstruction[1].u.operand;
usesResult = true;
- prediction = getPrediction(m_graph.size(), nextOffset);
+ m_currentProfilingIndex = nextOffset;
+ prediction = getPrediction();
nextOffset += OPCODE_LENGTH(op_call_put_result);
}
JSFunction* expectedFunction;
@@ -934,7 +972,7 @@ void ByteCodeParser::handleCall(Interpreter* interpreter, Instruction* currentIn
certainAboutExpectedFunction = true;
} else {
ASSERT(callType == LinkedFunction);
- expectedFunction = m_inlineStackTop->m_profiledBlock->getCallLinkInfo(m_currentIndex).lastSeenCallee.get();
+ expectedFunction = callLinkStatus.callTarget();
intrinsic = expectedFunction->executable()->intrinsicFor(kind);
certainAboutExpectedFunction = false;
}
@@ -1029,7 +1067,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
int inlineCallFrameStart = m_inlineStackTop->remapOperand(registerOffset) - RegisterFile::CallFrameHeaderSize;
// Make sure that the area used by the call frame is reserved.
- for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart + 1;)
+ for (int arg = inlineCallFrameStart + RegisterFile::CallFrameHeaderSize + codeBlock->m_numVars; arg-- > inlineCallFrameStart;)
m_preservedVars.set(m_inlineStackTop->remapOperand(arg));
// Make sure that we have enough locals.
@@ -1044,13 +1082,16 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// This is where the actual inlining really happens.
unsigned oldIndex = m_currentIndex;
+ unsigned oldProfilingIndex = m_currentProfilingIndex;
m_currentIndex = 0;
+ m_currentProfilingIndex = 0;
addToGraph(InlineStart);
parseCodeBlock();
m_currentIndex = oldIndex;
+ m_currentProfilingIndex = oldProfilingIndex;
// If the inlined code created some new basic blocks, then we have linking to do.
if (inlineStackEntry.m_callsiteBlockHead != m_graph.m_blocks.size() - 1) {
@@ -1129,7 +1170,7 @@ bool ByteCodeParser::handleInlining(bool usesResult, int callTarget, NodeIndex c
// Need to create a new basic block for the continuation at the caller.
OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(nextOffset, m_graph.size(), m_numArguments, m_numLocals));
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Creating inline epilogue basic block %p, #%lu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+ printf("Creating inline epilogue basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
#endif
m_currentBlock = block.get();
ASSERT(m_inlineStackTop->m_caller->m_blockLinkingTargets.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_caller->m_blockLinkingTargets.last()]->bytecodeBegin < nextOffset);
@@ -1308,6 +1349,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
while (true) {
+ m_currentProfilingIndex = m_currentIndex;
+
// Don't extend over jump destinations.
if (m_currentIndex == limit) {
// Ordinarily we want to plant a jump. But refuse to do this if the block is
@@ -1680,6 +1723,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
}
case op_method_check: {
+ m_currentProfilingIndex += OPCODE_LENGTH(op_method_check);
Instruction* getInstruction = currentInstruction + OPCODE_LENGTH(op_method_check);
PredictedType prediction = getPrediction();
@@ -1691,23 +1735,26 @@ bool ByteCodeParser::parseBlock(unsigned limit)
// Check if the method_check was monomorphic. If so, emit a CheckXYZMethod
// node, which is a lot more efficient.
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
- MethodCallLinkInfo& methodCall = m_inlineStackTop->m_profiledBlock->getMethodCallLinkInfo(m_currentIndex);
+ GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock,
+ m_currentIndex,
+ m_codeBlock->identifier(identifier));
+ MethodCallLinkStatus methodCallStatus = MethodCallLinkStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex);
- if (methodCall.seen
- && !!methodCall.cachedStructure
- && !stubInfo.seen
+ if (methodCallStatus.isSet()
+ && !getByIdStatus.isSet()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
// It's monomorphic as far as we can tell, since the method_check was linked
// but the slow path (i.e. the normal get_by_id) never fired.
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedStructure.get())), base);
- if (methodCall.cachedPrototype.get() != m_inlineStackTop->m_profiledBlock->globalObject()->methodCallDummy())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCall.cachedPrototypeStructure.get())), cellConstant(methodCall.cachedPrototype.get()));
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.structure())), base);
+ if (methodCallStatus.needsPrototypeCheck())
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(methodCallStatus.prototypeStructure())), cellConstant(methodCallStatus.prototype()));
- set(getInstruction[1].u.operand, cellConstant(methodCall.cachedFunction.get()));
+ set(getInstruction[1].u.operand, cellConstant(methodCallStatus.function()));
} else
- set(getInstruction[1].u.operand, addToGraph(GetById, OpInfo(identifier), OpInfo(prediction), base));
+ set(getInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifier), OpInfo(prediction), base));
m_currentIndex += OPCODE_LENGTH(op_method_check) + OPCODE_LENGTH(op_get_by_id);
continue;
@@ -1737,178 +1784,109 @@ bool ByteCodeParser::parseBlock(unsigned limit)
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[3].u.operand];
Identifier identifier = m_codeBlock->identifier(identifierNumber);
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
+ GetByIdStatus getByIdStatus = GetByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock, m_currentIndex, identifier);
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Slow case count for GetById @%lu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+ printf("Slow case count for GetById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
- size_t offset = notFound;
- StructureSet structureSet;
- if (stubInfo.seen
- && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
+ if (getByIdStatus.isSimpleDirect()
&& !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- switch (stubInfo.accessType) {
- case access_get_by_id_self: {
- Structure* structure = stubInfo.u.getByIdSelf.baseObjectStructure.get();
- offset = structure->get(*m_globalData, identifier);
-
- if (offset != notFound)
- structureSet.add(structure);
-
- if (offset != notFound)
- ASSERT(structureSet.size());
- break;
- }
-
- case access_get_by_id_self_list: {
- PolymorphicAccessStructureList* list = stubInfo.u.getByIdProtoList.structureList;
- unsigned size = stubInfo.u.getByIdProtoList.listSize;
- for (unsigned i = 0; i < size; ++i) {
- if (!list->list[i].isDirect) {
- offset = notFound;
- break;
- }
-
- Structure* structure = list->list[i].base.get();
- if (structureSet.contains(structure))
- continue;
-
- size_t myOffset = structure->get(*m_globalData, identifier);
-
- if (myOffset == notFound) {
- offset = notFound;
- break;
- }
-
- if (!i)
- offset = myOffset;
- else if (offset != myOffset) {
- offset = notFound;
- break;
- }
-
- structureSet.add(structure);
- }
-
- if (offset != notFound)
- ASSERT(structureSet.size());
- break;
- }
-
- default:
- ASSERT(offset == notFound);
- break;
- }
- }
-
- if (offset != notFound) {
- ASSERT(structureSet.size());
+ ASSERT(getByIdStatus.structureSet().size());
// The implementation of GetByOffset does not know to terminate speculative
// execution if it doesn't have a prediction, so we do it manually.
if (prediction == PredictNone)
addToGraph(ForceOSRExit);
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structureSet)), base);
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(getByIdStatus.structureSet())), base);
set(currentInstruction[1].u.operand, addToGraph(GetByOffset, OpInfo(m_graph.m_storageAccessData.size()), OpInfo(prediction), addToGraph(GetPropertyStorage, base)));
StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
+ storageAccessData.offset = getByIdStatus.offset();
storageAccessData.identifierNumber = identifierNumber;
m_graph.m_storageAccessData.append(storageAccessData);
} else
- set(currentInstruction[1].u.operand, addToGraph(GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
+ set(currentInstruction[1].u.operand, addToGraph(getByIdStatus.makesCalls() ? GetByIdFlush : GetById, OpInfo(identifierNumber), OpInfo(prediction), base));
NEXT_OPCODE(op_get_by_id);
}
-
case op_put_by_id: {
NodeIndex value = get(currentInstruction[3].u.operand);
NodeIndex base = get(currentInstruction[1].u.operand);
unsigned identifierNumber = m_inlineStackTop->m_identifierRemap[currentInstruction[2].u.operand];
bool direct = currentInstruction[8].u.operand;
- StructureStubInfo& stubInfo = m_inlineStackTop->m_profiledBlock->getStubInfo(m_currentIndex);
- if (!stubInfo.seen)
+ PutByIdStatus putByIdStatus = PutByIdStatus::computeFor(
+ m_inlineStackTop->m_profiledBlock,
+ m_currentIndex,
+ m_codeBlock->identifier(identifierNumber));
+ if (!putByIdStatus.isSet())
addToGraph(ForceOSRExit);
- bool alreadyGenerated = false;
+ bool hasExitSite = m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache);
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Slow case count for PutById @%lu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
+ printf("Slow case count for PutById @%zu bc#%u: %u; exit profile: %d\n", m_graph.size(), m_currentIndex, m_inlineStackTop->m_profiledBlock->rareCaseProfileForBytecodeOffset(m_currentIndex)->m_counter, m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
#endif
- if (stubInfo.seen
- && !m_inlineStackTop->m_profiledBlock->likelyToTakeSlowCase(m_currentIndex)
- && !m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)) {
- switch (stubInfo.accessType) {
- case access_put_by_id_replace: {
- Structure* structure = stubInfo.u.putByIdReplace.baseObjectStructure.get();
- Identifier identifier = m_codeBlock->identifier(identifierNumber);
- size_t offset = structure->get(*m_globalData, identifier);
-
- if (offset != notFound) {
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), base);
- addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
-
- alreadyGenerated = true;
- }
- break;
- }
-
- case access_put_by_id_transition_normal:
- case access_put_by_id_transition_direct: {
- Structure* previousStructure = stubInfo.u.putByIdTransition.previousStructure.get();
- Structure* newStructure = stubInfo.u.putByIdTransition.structure.get();
-
- if (previousStructure->propertyStorageCapacity() != newStructure->propertyStorageCapacity())
- break;
-
- StructureChain* structureChain = stubInfo.u.putByIdTransition.chain.get();
-
- Identifier identifier = m_codeBlock->identifier(identifierNumber);
- size_t offset = newStructure->get(*m_globalData, identifier);
+ if (!hasExitSite && putByIdStatus.isSimpleReplace()) {
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+ addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = putByIdStatus.offset();
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+ } else if (!hasExitSite
+ && putByIdStatus.isSimpleTransition()
+ && putByIdStatus.oldStructure()->propertyStorageCapacity() == putByIdStatus.newStructure()->propertyStorageCapacity()
+ && structureChainIsStillValid(
+ direct,
+ putByIdStatus.oldStructure(),
+ putByIdStatus.structureChain())) {
+
+ addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure())), base);
+ if (!direct) {
+ if (!putByIdStatus.oldStructure()->storedPrototype().isNull())
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(putByIdStatus.oldStructure()->storedPrototype().asCell()->structure())),
+ cellConstant(putByIdStatus.oldStructure()->storedPrototype().asCell()));
- if (offset != notFound && structureChainIsStillValid(direct, previousStructure, structureChain)) {
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure)), base);
- if (!direct) {
- if (!previousStructure->storedPrototype().isNull())
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(previousStructure->storedPrototype().asCell()->structure())), cellConstant(previousStructure->storedPrototype().asCell()));
-
- for (WriteBarrier<Structure>* it = structureChain->head(); *it; ++it) {
- JSValue prototype = (*it)->storedPrototype();
- if (prototype.isNull())
- continue;
- ASSERT(prototype.isCell());
- addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())), cellConstant(prototype.asCell()));
- }
- }
- addToGraph(PutStructure, OpInfo(m_graph.addStructureTransitionData(StructureTransitionData(previousStructure, newStructure))), base);
-
- addToGraph(PutByOffset, OpInfo(m_graph.m_storageAccessData.size()), base, addToGraph(GetPropertyStorage, base), value);
-
- StorageAccessData storageAccessData;
- storageAccessData.offset = offset;
- storageAccessData.identifierNumber = identifierNumber;
- m_graph.m_storageAccessData.append(storageAccessData);
-
- alreadyGenerated = true;
+ for (WriteBarrier<Structure>* it = putByIdStatus.structureChain()->head(); *it; ++it) {
+ JSValue prototype = (*it)->storedPrototype();
+ if (prototype.isNull())
+ continue;
+ ASSERT(prototype.isCell());
+ addToGraph(
+ CheckStructure,
+ OpInfo(m_graph.addStructureSet(prototype.asCell()->structure())),
+ cellConstant(prototype.asCell()));
}
- break;
- }
-
- default:
- break;
}
- }
-
- if (!alreadyGenerated) {
+ addToGraph(
+ PutStructure,
+ OpInfo(
+ m_graph.addStructureTransitionData(
+ StructureTransitionData(
+ putByIdStatus.oldStructure(),
+ putByIdStatus.newStructure()))),
+ base);
+
+ addToGraph(
+ PutByOffset,
+ OpInfo(m_graph.m_storageAccessData.size()),
+ base,
+ addToGraph(GetPropertyStorage, base),
+ value);
+
+ StorageAccessData storageAccessData;
+ storageAccessData.offset = putByIdStatus.offset();
+ storageAccessData.identifierNumber = identifierNumber;
+ m_graph.m_storageAccessData.append(storageAccessData);
+ } else {
if (direct)
addToGraph(PutByIdDirect, OpInfo(identifierNumber), base, value);
else
@@ -2570,7 +2548,7 @@ void ByteCodeParser::parseCodeBlock()
} else {
OwnPtr<BasicBlock> block = adoptPtr(new BasicBlock(m_currentIndex, m_graph.size(), m_numArguments, m_numLocals));
#if DFG_ENABLE(DEBUG_VERBOSE)
- printf("Creating basic block %p, #%lu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
+ printf("Creating basic block %p, #%zu for %p bc#%u at inline depth %u.\n", block.get(), m_graph.m_blocks.size(), m_inlineStackTop->executable(), m_currentIndex, CodeOrigin::inlineDepthForCallFrame(m_inlineStackTop->m_inlineCallFrame));
#endif
m_currentBlock = block.get();
ASSERT(m_inlineStackTop->m_unlinkedBlocks.isEmpty() || m_graph.m_blocks[m_inlineStackTop->m_unlinkedBlocks.last().m_blockIndex]->bytecodeBegin < m_currentIndex);
@@ -2620,6 +2598,9 @@ bool ByteCodeParser::parse()
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
printf("Processing local variable phis.\n");
#endif
+
+ m_currentProfilingIndex = m_currentIndex;
+
processPhiStack<LocalPhiStack>();
#if DFG_ENABLE(DEBUG_PROPAGATION_VERBOSE)
printf("Processing argument phis.\n");