Qt 4.8
qevaluationcache.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtXmlPatterns module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
48 template<bool IsForGlobal>
50  const VariableDeclaration *varDecl,
51  const VariableSlotID aSlot) : SingleContainer(op)
52  , m_declarationUsedByMany(varDecl->usedByMany())
53  , m_varSlot(aSlot)
54 {
55  Q_ASSERT(m_varSlot > -1);
56 }
57 
58 template<bool IsForGlobal>
60 {
61  DynamicContext::Ptr result(context);
62 
63  while(true)
64  {
65  DynamicContext::Ptr candidate(result->previousContext());
66 
67  /* We want the top focus, not GenericDynamicContext. */
68  if(candidate && candidate->focusIterator())
69  result = candidate;
70  else
71  return result;
72  }
73 }
74 
75 template<bool IsForGlobal>
77 {
78  ItemCacheCell &cell = IsForGlobal ? context->globalItemCacheCell(m_varSlot) : context->itemCacheCell(m_varSlot);
79 
81  return cell.cachedItem;
82  else
83  {
85  cell.cachedItem = m_operand->evaluateSingleton(IsForGlobal ? topFocusContext(context) : context);
87  return cell.cachedItem;
88  }
89 }
90 
91 #if defined(Q_OS_IRIX) && defined(Q_CC_MIPS)
92 
101 static inline Item::Iterator::Ptr workaroundIrixMIPSPro(const ItemSequenceCacheCell &cell)
102 {
104 }
105 #endif
106 
107 template<bool IsForGlobal>
109 {
110  ItemSequenceCacheCell::Vector &cells = IsForGlobal ? context->globalItemSequenceCacheCells(m_varSlot) : context->itemSequenceCacheCells(m_varSlot);
111  ItemSequenceCacheCell &cell = cells[m_varSlot];
112 
113 
114  if(cell.inUse)
115  {
116  context->error(QtXmlPatterns::tr("Circularity detected"),
118  }
119 
120  switch(cell.cacheState)
121  {
123  {
128  }
130  {
131  cell.inUse = true;
132  cell.sourceIterator = m_operand->evaluateSequence(IsForGlobal ? topFocusContext(context) : context);
134  /* Fallthrough. */
135  }
137  {
138  cell.inUse = false;
139  Q_ASSERT_X(cells.at(m_varSlot).sourceIterator, Q_FUNC_INFO,
140  "This trigger for a cache bug which hasn't yet been analyzed.");
141  return Item::Iterator::Ptr(new CachingIterator(cells, m_varSlot, IsForGlobal ? topFocusContext(context) : context));
142  }
143  default:
144  {
145  Q_ASSERT_X(false, Q_FUNC_INFO, "This path is not supposed to be run.");
146  return Item::Iterator::Ptr();
147  }
148  }
149 }
150 
151 template<bool IsForGlobal>
153  const SequenceType::Ptr &reqType)
154 {
155  /* It's important that we do the typeCheck() before checking for the use of local variables,
156  * because ExpressionVariableReference can reference an expression that is a local variable,
157  * so it must rewrite itself to it operand before, and it does that in EvaluationCache::typeCheck(). */
158  const Expression::Ptr me(SingleContainer::typeCheck(context, reqType));
159 
161  Expression::Ptr next(it.next());
162 
163  /* If our operand or any sub operand gets its value from a for-loop, we cannot
164  * cache it since then our cache would be filled -- but not invalidated -- on the
165  * first for-iteration. Consider this query:
166  *
167  * <tt>for $i in expr
168  * let $v := $i/p
169  * return ($v, $v)</tt>
170  *
171  * An evaluation cache is inserted for the two operands in the return clause. However,
172  * $i changes for each iteration so the cache can only be active on a per-iteration basis,
173  * it it's possible(which it isn't).
174  *
175  * This means that for some queries we don't cache what we really should, and hence evaluate
176  * in a sub-optimal way, since this DependsOnLocalVariable don't communicate whether it references
177  * a loop that affects us. The correct fix for this would be to let ForExpression reset the
178  * relevant caches only, but we don't know which ones that are. */
179  while(next)
180  {
181  if(next->has(DependsOnLocalVariable))
182  return m_operand->typeCheck(context, reqType);
183 
184  next = it.next();
185  }
186 
187  return me;
188 }
189 
190 template<bool IsForGlobal>
192 {
193  const Expression::Ptr me(SingleContainer::compress(context));
194 
195  if(me != this)
196  return me;
197 
199  return m_operand;
200 
202  {
203  /* If it's only an atomic value an EvaluationCache is overkill. However,
204  * it's still needed for functions like fn:current-time() that must adhere to
205  * query stability. */
206  const Properties props(m_operand->properties());
207 
208  if(props.testFlag(EvaluationCacheRedundant) ||
209  ((props.testFlag(IsEvaluated)) &&
210  !props.testFlag(DisableElimination) &&
211  CommonSequenceTypes::ExactlyOneAtomicType->matches(m_operand->staticType())))
212  {
213  return m_operand;
214  }
215  else
216  return me;
217  }
218  else
219  {
220  /* If we're only used once, there's no need for an EvaluationCache. */
221  return m_operand;
222  }
223 }
224 
225 template<bool IsForGlobal>
227 {
228  return m_operand->staticType();
229 }
230 
231 template<bool IsForGlobal>
233 {
234  /* Remember that EvaluationCache::typeCheck() will be called from multiple locations,
235  * which potentially have different type requirements. For instance, one wants a node,
236  * and another requires atomization and casting.
237  *
238  * Returning ZeroOrMoreItems is safe here because staticType() returns the operand's type
239  * and therefore the convertors like Atomizer will be parents to us, and hence only affect
240  * the relevant path.
241  *
242  * ZeroOrMoreItems also make sense logically since we're actually only used where the
243  * variable references reference us. */
244  SequenceType::List result;
246 
247  return result;
248 }
249 
250 template<bool IsForGlobal>
252 {
253  /* We cannot return the operand's properties unconditionally, because some
254  * doesn't hold for this Expression.
255  *
256  * However, some of the properties must propagate through, which are the ones being OR'd here.
257  */
258  return m_operand->properties() & (DisableElimination | IsEvaluated | DisableTypingDeduction);
259 }
260 
261 template<bool IsForGlobal>
264 {
265  return visitor->visit(this);
266 }
267 
268 template<bool IsForGlobal>
270 {
271  return m_operand->actualReflection();
272 }
273 
qint32 VariableSlotID
An QAbstractXmlForwardIterator that gets its item from a cache unless its empty, in which case it con...
Represents a declared variable. Only used at the compilation stage.
static const SequenceType::Ptr ZeroOrMoreItems
virtual Item::Iterator::Ptr evaluateSequence(const DynamicContext::Ptr &context) const
#define it(className, varName)
const VariableSlotID m_varSlot
static DynamicContext::Ptr topFocusContext(const DynamicContext::Ptr &context)
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
Definition: qexpression.cpp:70
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
static const SequenceType::Ptr ExactlyOneAtomicType
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
virtual Expression::Ptr compress(const StaticContext::Ptr &context)
Expression::Ptr next()
Returns the current Expression and advances the iterator.
QExplicitlySharedDataPointer< QAbstractXmlForwardIterator< Item > > Ptr
A smart pointer wrapping an instance of a QAbstractXmlForwardIterator subclass.
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
Represents a cache entry for a sequence of items.
virtual SequenceType::List expectedOperandTypes() const
virtual ExpressionVisitorResult::Ptr accept(const ExpressionVisitor::Ptr &visitor) const
virtual SequenceType::Ptr staticType() const
Represents a cache entry for a single Item, as opposed to for a sequence of items.
Definition: qcachecells_p.h:81
const T & at(int i) const
Returns the item at index position i in the vector.
Definition: qvector.h:350
#define Q_ASSERT_X(cond, where, what)
Definition: qglobal.h:1837
Represents an item in the XPath 2.0 Data Model.
Definition: qitem_p.h:182
Evaluates to the same result as its operand, but ensures the operand is evaluated once even if this E...
virtual Expression::Ptr typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType)
virtual const SourceLocationReflection * actualReflection() const
Returns this.
virtual Properties properties() const
virtual Item evaluateSingleton(const DynamicContext::Ptr &context) const
The QFlags class provides a type-safe way of storing OR-combinations of enum values.
Definition: qglobal.h:2313
Item::Iterator::Ptr sourceIterator
Bridges values in Qt&#39;s QList container class into an QAbstractXmlForwardIterator. ...
The QList class is a template class that provides lists.
Definition: qdatastream.h:62
Base class for all instances that represents something at a certain location.
Base class for expressions that has exactly one operand.
A helper class that iterates a tree of Expression instances. It is not a sub-class of QAbstractXmlFor...
#define Q_FUNC_INFO
Definition: qglobal.h:1871