diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-05-24 08:28:08 +0000 |
commit | a4e969f4965059196ca948db781e52f7cfebf19e (patch) | |
tree | 6ca352808c8fdc52006a0f33f6ae3c593b23867d /Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp | |
parent | 41386e9cb918eed93b3f13648cbef387e371e451 (diff) | |
download | WebKitGtk-tarball-a4e969f4965059196ca948db781e52f7cfebf19e.tar.gz |
webkitgtk-2.12.3webkitgtk-2.12.3
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp | 256 |
1 files changed, 116 insertions, 140 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp index 468c68f84..e5d88d2d5 100644 --- a/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013 Apple Inc. All rights reserved. + * Copyright (C) 2013-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -31,12 +31,14 @@ #include "CodeBlock.h" #include "DFGBasicBlock.h" #include "GetByIdStatus.h" -#include "Operations.h" +#include "JSCInlines.h" #include "PutByIdStatus.h" #include "StringObject.h" namespace JSC { namespace DFG { +static const bool verbose = false; + InPlaceAbstractState::InPlaceAbstractState(Graph& graph) : m_graph(graph) , m_variables(m_graph.m_codeBlock->numParameters(), graph.m_localVars) @@ -58,36 +60,18 @@ void InPlaceAbstractState::beginBasicBlock(BasicBlock* basicBlock) forNode(basicBlock->at(i)).clear(); m_variables = basicBlock->valuesAtHead; - m_haveStructures = false; - for (size_t i = 0; i < m_variables.numberOfArguments(); ++i) { - if (m_variables.argument(i).hasClobberableState()) { - m_haveStructures = true; - break; - } - } - for (size_t i = 0; i < m_variables.numberOfLocals(); ++i) { - if (m_variables.local(i).hasClobberableState()) { - m_haveStructures = true; - break; - } - } if (m_graph.m_form == SSA) { - HashMap<Node*, AbstractValue>::iterator iter = basicBlock->ssa->valuesAtHead.begin(); - HashMap<Node*, AbstractValue>::iterator end = basicBlock->ssa->valuesAtHead.end(); - for (; iter != end; ++iter) { - forNode(iter->key) = iter->value; - if (iter->value.hasClobberableState()) - m_haveStructures = true; - } + for (auto& entry : basicBlock->ssa->valuesAtHead) + forNode(entry.key) = entry.value; } - basicBlock->cfaShouldRevisit = false; basicBlock->cfaHasVisited = true; m_block = basicBlock; m_isValid = true; m_foundConstants = false; m_branchDirection = InvalidBranchDirection; + m_structureClobberState = basicBlock->cfaStructureClobberStateAtHead; } static void setLiveValues(HashMap<Node*, AbstractValue>& values, HashSet<Node*>& live) @@ -106,37 +90,44 @@ void InPlaceAbstractState::initialize() root->cfaShouldRevisit = true; root->cfaHasVisited = false; root->cfaFoundConstants = false; + root->cfaStructureClobberStateAtHead = StructuresAreWatched; + root->cfaStructureClobberStateAtTail = StructuresAreWatched; for (size_t i = 0; i < root->valuesAtHead.numberOfArguments(); ++i) { root->valuesAtTail.argument(i).clear(); - if (m_graph.m_form == SSA) { - root->valuesAtHead.argument(i).makeHeapTop(); - continue; - } - - Node* node = root->variablesAtHead.argument(i); - ASSERT(node->op() == SetArgument); - if (!node->variableAccessData()->shouldUnboxIfPossible()) { - root->valuesAtHead.argument(i).makeHeapTop(); - continue; + + FlushFormat format; + if (m_graph.m_form == SSA) + format = m_graph.m_argumentFormats[i]; + else { + Node* node = m_graph.m_arguments[i]; + if (!node) + format = FlushedJSValue; + else { + ASSERT(node->op() == SetArgument); + format = node->variableAccessData()->flushFormat(); + } } - SpeculatedType prediction = - node->variableAccessData()->argumentAwarePrediction(); - if (isInt32Speculation(prediction)) + switch (format) { + case FlushedInt32: root->valuesAtHead.argument(i).setType(SpecInt32); - else if (isBooleanSpeculation(prediction)) + break; + case FlushedBoolean: root->valuesAtHead.argument(i).setType(SpecBoolean); - else if (isCellSpeculation(prediction)) - root->valuesAtHead.argument(i).setType(SpecCell); - else - root->valuesAtHead.argument(i).makeHeapTop(); + break; + case FlushedCell: + root->valuesAtHead.argument(i).setType(m_graph, SpecCell); + break; + case FlushedJSValue: + root->valuesAtHead.argument(i).makeBytecodeTop(); + break; + default: + DFG_CRASH(m_graph, nullptr, "Bad flush format for argument"); + break; + } } for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) { - Node* node = root->variablesAtHead.local(i); - if (node && node->variableAccessData()->isCaptured()) - root->valuesAtHead.local(i).makeHeapTop(); - else - root->valuesAtHead.local(i).clear(); + root->valuesAtHead.local(i).clear(); root->valuesAtTail.local(i).clear(); } for (BlockIndex blockIndex = 1 ; blockIndex < m_graph.numBlocks(); ++blockIndex) { @@ -147,6 +138,8 @@ void InPlaceAbstractState::initialize() block->cfaShouldRevisit = false; block->cfaHasVisited = false; block->cfaFoundConstants = false; + block->cfaStructureClobberStateAtHead = StructuresAreWatched; + block->cfaStructureClobberStateAtTail = StructuresAreWatched; for (size_t i = 0; i < block->valuesAtHead.numberOfArguments(); ++i) { block->valuesAtHead.argument(i).clear(); block->valuesAtTail.argument(i).clear(); @@ -155,16 +148,6 @@ void InPlaceAbstractState::initialize() block->valuesAtHead.local(i).clear(); block->valuesAtTail.local(i).clear(); } - if (!block->isOSRTarget) - continue; - if (block->bytecodeBegin != m_graph.m_plan.osrEntryBytecodeIndex) - continue; - for (size_t i = 0; i < m_graph.m_mustHandleAbstractValues.size(); ++i) { - AbstractValue value = m_graph.m_mustHandleAbstractValues[i]; - int operand = m_graph.m_mustHandleAbstractValues.operandForIndex(i); - block->valuesAtHead.operand(operand).merge(value); - } - block->cfaShouldRevisit = true; } if (m_graph.m_form == SSA) { for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { @@ -177,7 +160,7 @@ void InPlaceAbstractState::initialize() } } -bool InPlaceAbstractState::endBasicBlock(MergeMode mergeMode) +bool InPlaceAbstractState::endBasicBlock() { ASSERT(m_block); @@ -192,48 +175,41 @@ bool InPlaceAbstractState::endBasicBlock(MergeMode mergeMode) return false; } - bool changed = false; + bool changed = checkAndSet(block->cfaStructureClobberStateAtTail, m_structureClobberState); - if (mergeMode != DontMerge || !ASSERT_DISABLED) { - switch (m_graph.m_form) { - case ThreadedCPS: { - for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) { - AbstractValue& destination = block->valuesAtTail.argument(argument); - changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument)); - } - - for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) { - AbstractValue& destination = block->valuesAtTail.local(local); - changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local)); - } - break; + switch (m_graph.m_form) { + case ThreadedCPS: { + for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) { + AbstractValue& destination = block->valuesAtTail.argument(argument); + changed |= mergeStateAtTail(destination, m_variables.argument(argument), block->variablesAtTail.argument(argument)); } - - case SSA: { - for (size_t i = 0; i < block->valuesAtTail.size(); ++i) - changed |= block->valuesAtTail[i].merge(m_variables[i]); - - HashSet<Node*>::iterator iter = block->ssa->liveAtTail.begin(); - HashSet<Node*>::iterator end = block->ssa->liveAtTail.end(); - for (; iter != end; ++iter) { - Node* node = *iter; - changed |= block->ssa->valuesAtTail.find(node)->value.merge(forNode(node)); - } - break; + + for (size_t local = 0; local < block->variablesAtTail.numberOfLocals(); ++local) { + AbstractValue& destination = block->valuesAtTail.local(local); + changed |= mergeStateAtTail(destination, m_variables.local(local), block->variablesAtTail.local(local)); } - - default: - RELEASE_ASSERT_NOT_REACHED(); + break; + } + + case SSA: { + for (size_t i = 0; i < block->valuesAtTail.size(); ++i) + changed |= block->valuesAtTail[i].merge(m_variables[i]); + + HashSet<Node*>::iterator iter = block->ssa->liveAtTail.begin(); + HashSet<Node*>::iterator end = block->ssa->liveAtTail.end(); + for (; iter != end; ++iter) { + Node* node = *iter; + changed |= block->ssa->valuesAtTail.find(node)->value.merge(forNode(node)); } + break; } - - ASSERT(mergeMode != DontMerge || !changed); - + + default: + RELEASE_ASSERT_NOT_REACHED(); + } + reset(); - if (mergeMode != MergeToSuccessors) - return changed; - return mergeToSuccessors(block); } @@ -242,6 +218,7 @@ void InPlaceAbstractState::reset() m_block = 0; m_isValid = false; m_branchDirection = InvalidBranchDirection; + m_structureClobberState = StructuresAreWatched; } bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node) @@ -251,46 +228,31 @@ bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, Abstract AbstractValue source; - if (node->variableAccessData()->isCaptured()) { - // If it's captured then we know that whatever value was stored into the variable last is the - // one we care about. This is true even if the variable at tail is dead, which might happen if - // the last thing we did to the variable was a GetLocal and then ended up now using the - // GetLocal's result. - + switch (node->op()) { + case Phi: + case SetArgument: + case PhantomLocal: + case Flush: + // The block transfers the value from head to tail. source = inVariable; - } else { - switch (node->op()) { - case Phi: - case SetArgument: - case PhantomLocal: - case Flush: - // The block transfers the value from head to tail. - source = inVariable; - break; + break; - case GetLocal: - // The block refines the value with additional speculations. - source = forNode(node); - break; + case GetLocal: + // The block refines the value with additional speculations. + source = forNode(node); + break; - case SetLocal: - // The block sets the variable, and potentially refines it, both - // before and after setting it. - source = forNode(node->child1()); - if (node->variableAccessData()->flushFormat() == FlushedDouble) { - ASSERT(!(source.m_type & ~SpecFullNumber)); - ASSERT(!!(source.m_type & ~SpecDouble) == !!(source.m_type & SpecMachineInt)); - if (!(source.m_type & ~SpecDouble)) { - source.merge(SpecInt52AsDouble); - source.filter(SpecDouble); - } - } - break; + case SetLocal: + // The block sets the variable, and potentially refines it, both + // before and after setting it. + source = forNode(node->child1()); + if (node->variableAccessData()->flushFormat() == FlushedDouble) + RELEASE_ASSERT(!(source.m_type & ~SpecFullDouble)); + break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; - } + default: + RELEASE_ASSERT_NOT_REACHED(); + break; } if (destination == source) { @@ -308,11 +270,17 @@ bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, Abstract bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) { + if (verbose) + dataLog(" Merging from ", pointerDump(from), " to ", pointerDump(to), "\n"); ASSERT(from->variablesAtTail.numberOfArguments() == to->variablesAtHead.numberOfArguments()); ASSERT(from->variablesAtTail.numberOfLocals() == to->variablesAtHead.numberOfLocals()); bool changed = false; + changed |= checkAndSet( + to->cfaStructureClobberStateAtHead, + DFG::merge(from->cfaStructureClobberStateAtTail, to->cfaStructureClobberStateAtHead)); + switch (m_graph.m_form) { case ThreadedCPS: { for (size_t argument = 0; argument < from->variablesAtTail.numberOfArguments(); ++argument) { @@ -330,13 +298,16 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) case SSA: { for (size_t i = from->valuesAtTail.size(); i--;) changed |= to->valuesAtHead[i].merge(from->valuesAtTail[i]); - - HashSet<Node*>::iterator iter = to->ssa->liveAtHead.begin(); - HashSet<Node*>::iterator end = to->ssa->liveAtHead.end(); - for (; iter != end; ++iter) { - Node* node = *iter; - changed |= to->ssa->valuesAtHead.find(node)->value.merge( + + for (auto& entry : to->ssa->valuesAtHead) { + Node* node = entry.key; + if (verbose) + dataLog(" Merging for ", node, ": from ", from->ssa->valuesAtTail.find(node)->value, " to ", entry.value, "\n"); + changed |= entry.value.merge( from->ssa->valuesAtTail.find(node)->value); + + if (verbose) + dataLog(" Result: ", entry.value, "\n"); } break; } @@ -349,6 +320,8 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) if (!to->cfaHasVisited) changed = true; + if (verbose) + dataLog(" Will revisit: ", changed, "\n"); to->cfaShouldRevisit |= changed; return changed; @@ -356,23 +329,23 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) inline bool InPlaceAbstractState::mergeToSuccessors(BasicBlock* basicBlock) { - Node* terminal = basicBlock->last(); + Node* terminal = basicBlock->terminal(); ASSERT(terminal->isTerminal()); switch (terminal->op()) { case Jump: { ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); - return merge(basicBlock, terminal->takenBlock()); + return merge(basicBlock, terminal->targetBlock()); } case Branch: { ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection); bool changed = false; if (basicBlock->cfaBranchDirection != TakeFalse) - changed |= merge(basicBlock, terminal->takenBlock()); + changed |= merge(basicBlock, terminal->branchData()->taken.block); if (basicBlock->cfaBranchDirection != TakeTrue) - changed |= merge(basicBlock, terminal->notTakenBlock()); + changed |= merge(basicBlock, terminal->branchData()->notTaken.block); return changed; } @@ -381,13 +354,16 @@ inline bool InPlaceAbstractState::mergeToSuccessors(BasicBlock* basicBlock) // we're not. However I somehow doubt that this will ever be a big deal. ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); SwitchData* data = terminal->switchData(); - bool changed = merge(basicBlock, data->fallThrough); + bool changed = merge(basicBlock, data->fallThrough.block); for (unsigned i = data->cases.size(); i--;) - changed |= merge(basicBlock, data->cases[i].target); + changed |= merge(basicBlock, data->cases[i].target.block); return changed; } case Return: + case TailCall: + case TailCallVarargs: + case TailCallForwardVarargs: case Unreachable: ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); return false; |