diff options
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp')
-rw-r--r-- | Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp | 175 |
1 files changed, 95 insertions, 80 deletions
diff --git a/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp b/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp index b1269c1b7..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,20 +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) { HashMap<Node*, AbstractValue>::iterator iter = basicBlock->ssa->valuesAtHead.begin(); HashMap<Node*, AbstractValue>::iterator end = basicBlock->ssa->valuesAtHead.end(); - for (; iter != end; ++iter) + 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) @@ -92,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: + else if (isCellSpeculation(prediction)) + root->valuesAtHead.argument(i).setType(SpecCell); + else root->valuesAtHead.argument(i).makeHeapTop(); - break; - default: - DFG_CRASH(m_graph, nullptr, "Bad flush format for argument"); - break; - } } 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) { @@ -140,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(); @@ -150,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) { @@ -179,9 +194,7 @@ bool InPlaceAbstractState::endBasicBlock(MergeMode mergeMode) bool changed = false; - if ((mergeMode != DontMerge) || !ASSERT_DISABLED) { - 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) { @@ -229,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) @@ -239,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) { @@ -281,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) { @@ -314,12 +335,8 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) HashSet<Node*>::iterator end = to->ssa->liveAtHead.end(); for (; iter != end; ++iter) { Node* node = *iter; - if (verbose) - dataLog(" Merging for ", node, ": from ", from->ssa->valuesAtTail.find(node)->value, " to ", to->ssa->valuesAtHead.find(node)->value, "\n"); changed |= to->ssa->valuesAtHead.find(node)->value.merge( from->ssa->valuesAtTail.find(node)->value); - if (verbose) - dataLog(" Result: ", to->ssa->valuesAtHead.find(node)->value, "\n"); } break; } @@ -332,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; @@ -341,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; } @@ -366,9 +381,9 @@ 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; } |