X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/81345200c95645a1b0d2635520f96ad55dfde63f..ed1e77d3adeb83d26fd1dfb16dd84cabdcefd250:/dfg/DFGInPlaceAbstractState.cpp?ds=inline diff --git a/dfg/DFGInPlaceAbstractState.cpp b/dfg/DFGInPlaceAbstractState.cpp index 1121305..b1269c1 100644 --- a/dfg/DFGInPlaceAbstractState.cpp +++ b/dfg/DFGInPlaceAbstractState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013, 2014 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 @@ -37,6 +37,8 @@ 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,20 @@ 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::iterator iter = basicBlock->ssa->valuesAtHead.begin(); HashMap::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& values, HashSet& live) @@ -106,37 +92,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 + break; + case FlushedCell: + root->valuesAtHead.argument(i).setType(m_graph, SpecCell); + break; + case FlushedJSValue: 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) { - 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 +140,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,25 +150,6 @@ void InPlaceAbstractState::initialize() block->valuesAtHead.local(i).clear(); block->valuesAtTail.local(i).clear(); } - if (m_graph.m_form == SSA) - continue; - 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) { - int operand = m_graph.m_mustHandleAbstractValues.operandForIndex(i); - Node* node = block->variablesAtHead.operand(operand); - if (!node) - continue; - AbstractValue value = m_graph.m_mustHandleAbstractValues[i]; - AbstractValue& abstractValue = block->valuesAtHead.operand(operand); - VariableAccessData* variable = node->variableAccessData(); - FlushFormat format = variable->flushFormat(); - abstractValue.merge(value); - abstractValue.fixTypeForRepresentation(resultFor(format)); - } - block->cfaShouldRevisit = true; } if (m_graph.m_form == SSA) { for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) { @@ -203,7 +179,9 @@ bool InPlaceAbstractState::endBasicBlock(MergeMode mergeMode) bool changed = false; - if (mergeMode != DontMerge || !ASSERT_DISABLED) { + if ((mergeMode != DontMerge) || !ASSERT_DISABLED) { + changed |= checkAndSet(block->cfaStructureClobberStateAtTail, m_structureClobberState); + switch (m_graph.m_form) { case ThreadedCPS: { for (size_t argument = 0; argument < block->variablesAtTail.numberOfArguments(); ++argument) { @@ -251,6 +229,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) @@ -260,40 +239,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 not 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) - 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) + RELEASE_ASSERT(!(source.m_type & ~SpecFullDouble)); + break; - default: - RELEASE_ASSERT_NOT_REACHED(); - break; - } + default: + RELEASE_ASSERT_NOT_REACHED(); + break; } if (destination == source) { @@ -311,11 +281,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) { @@ -338,8 +314,12 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) HashSet::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; } @@ -352,6 +332,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; @@ -359,7 +341,7 @@ bool InPlaceAbstractState::merge(BasicBlock* from, BasicBlock* to) inline bool InPlaceAbstractState::mergeToSuccessors(BasicBlock* basicBlock) { - Node* terminal = basicBlock->last(); + Node* terminal = basicBlock->terminal(); ASSERT(terminal->isTerminal());