diff options
author | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
---|---|---|
committer | Lorry Tar Creator <lorry-tar-importer@lorry> | 2016-04-10 09:28:39 +0000 |
commit | 32761a6cee1d0dee366b885b7b9c777e67885688 (patch) | |
tree | d6bec92bebfb216f4126356e55518842c2f476a1 /Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp | |
parent | a4e969f4965059196ca948db781e52f7cfebf19e (diff) | |
download | WebKitGtk-tarball-32761a6cee1d0dee366b885b7b9c777e67885688.tar.gz |
webkitgtk-2.4.11webkitgtk-2.4.11
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp | 256 |
1 files changed, 140 insertions, 116 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp index e5d88d2d5..468c68f84 100644 --- a/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp +++ b/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2015 Apple Inc. All rights reserved. + * Copyright (C) 2013 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,14 +31,12 @@ #include "CodeBlock.h" #include "DFGBasicBlock.h" #include "GetByIdStatus.h" -#include "JSCInlines.h" +#include "Operations.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) @@ -60,18 +58,36 @@ 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) { - for (auto& entry : basicBlock->ssa->valuesAtHead) - forNode(entry.key) = entry.value; + 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; + } } + 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) @@ -90,44 +106,37 @@ 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(); - - 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(); - } + 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; } - switch (format) { - case FlushedInt32: + SpeculatedType prediction = + node->variableAccessData()->argumentAwarePrediction(); + if (isInt32Speculation(prediction)) root->valuesAtHead.argument(i).setType(SpecInt32); - break; - case FlushedBoolean: + else if (isBooleanSpeculation(prediction)) root->valuesAtHead.argument(i).setType(SpecBoolean); - 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; - } + else if (isCellSpeculation(prediction)) + root->valuesAtHead.argument(i).setType(SpecCell); + else + root->valuesAtHead.argument(i).makeHeapTop(); } for (size_t i = 0; i < root->valuesAtHead.numberOfLocals(); ++i) { - root->valuesAtHead.local(i).clear(); + Node* node = root->variablesAtHead.local(i); + if (node && node->variableAccessData()->isCaptured()) + root->valuesAtHead.local(i).makeHeapTop(); + else + root->valuesAtHead.local(i).clear(); root->valuesAtTail.local(i).clear(); } for (BlockIndex blockIndex = 1 ; blockIndex < m_graph.numBlocks(); ++blockIndex) { @@ -138,8 +147,6 @@ 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(); @@ -148,6 +155,16 @@ 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) { @@ -160,7 +177,7 @@ void InPlaceAbstractState::initialize() } } -bool InPlaceAbstractState::endBasicBlock() +bool InPlaceAbstractState::endBasicBlock(MergeMode mergeMode) { ASSERT(m_block); @@ -175,41 +192,48 @@ bool InPlaceAbstractState::endBasicBlock() return false; } - bool changed = checkAndSet(block->cfaStructureClobberStateAtTail, m_structureClobberState); + bool changed = false; - 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)); + 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; } - - 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)); + + 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; } - 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)); + + default: + RELEASE_ASSERT_NOT_REACHED(); } - break; } - - default: - RELEASE_ASSERT_NOT_REACHED(); - } - + + ASSERT(mergeMode != DontMerge || !changed); + reset(); + if (mergeMode != MergeToSuccessors) + return changed; + return mergeToSuccessors(block); } @@ -218,7 +242,6 @@ void InPlaceAbstractState::reset() m_block = 0; m_isValid = false; m_branchDirection = InvalidBranchDirection; - m_structureClobberState = StructuresAreWatched; } bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, AbstractValue& inVariable, Node* node) @@ -228,31 +251,46 @@ bool InPlaceAbstractState::mergeStateAtTail(AbstractValue& destination, Abstract AbstractValue source; - switch (node->op()) { - case Phi: - case SetArgument: - case PhantomLocal: - case Flush: - // The block transfers the value from head to tail. + 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. + source = inVariable; - break; + } else { + switch (node->op()) { + case Phi: + case SetArgument: + case PhantomLocal: + case Flush: + // The block transfers the value from head to tail. + source = inVariable; + 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) - RELEASE_ASSERT(!(source.m_type & ~SpecFullDouble)); - 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; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; + default: + RELEASE_ASSERT_NOT_REACHED(); + break; + } } if (destination == source) { @@ -270,17 +308,11 @@ 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) { @@ -298,16 +330,13 @@ 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]); - - 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( + + 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( from->ssa->valuesAtTail.find(node)->value); - - if (verbose) - dataLog(" Result: ", entry.value, "\n"); } break; } @@ -320,8 +349,6 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) if (!to->cfaHasVisited) changed = true; - if (verbose) - dataLog(" Will revisit: ", changed, "\n"); to->cfaShouldRevisit |= changed; return changed; @@ -329,23 +356,23 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) inline bool InPlaceAbstractState::mergeToSuccessors(BasicBlock* basicBlock) { - Node* terminal = basicBlock->terminal(); + Node* terminal = basicBlock->last(); ASSERT(terminal->isTerminal()); switch (terminal->op()) { case Jump: { ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); - return merge(basicBlock, terminal->targetBlock()); + return merge(basicBlock, terminal->takenBlock()); } case Branch: { ASSERT(basicBlock->cfaBranchDirection != InvalidBranchDirection); bool changed = false; if (basicBlock->cfaBranchDirection != TakeFalse) - changed |= merge(basicBlock, terminal->branchData()->taken.block); + changed |= merge(basicBlock, terminal->takenBlock()); if (basicBlock->cfaBranchDirection != TakeTrue) - changed |= merge(basicBlock, terminal->branchData()->notTaken.block); + changed |= merge(basicBlock, terminal->notTakenBlock()); return changed; } @@ -354,16 +381,13 @@ 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.block); + bool changed = merge(basicBlock, data->fallThrough); for (unsigned i = data->cases.size(); i--;) - changed |= merge(basicBlock, data->cases[i].target.block); + changed |= merge(basicBlock, data->cases[i].target); return changed; } case Return: - case TailCall: - case TailCallVarargs: - case TailCallForwardVarargs: case Unreachable: ASSERT(basicBlock->cfaBranchDirection == InvalidBranchDirection); return false; |