summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp')
-rw-r--r--Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp175
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;
}