TupleTableSlot abstraction

Started by Andres Freundalmost 8 years ago50 messages
#1Andres Freund
andres@anarazel.de
1 attachment(s)

Hi,

I've recently been discussing with Robert how to abstract
TupleTableSlots in the light of upcoming developments around abstracting
storage away. Besides that aspect I think we also need to make them
more abstract to later deal with vectorized excution, but I'm more fuzzy
on the details there.

I'd previously, in a response to an early version of the pluggable
storage patch, commented [1]http://archives.postgresql.org/message-id/20170815065348.afkj45dgmg22ecfh%40alap3.anarazel.de how I think the abstraction should roughly
look like. I'd privately started to prototype that. After my discussion
with Robert I got that prototype in a state that can run many queries,
but doesn't pass the regression tests.

The pluggable storage patch has also been updated [2]http://archives.postgresql.org/message-id/CAJrrPGdY_hgvu06R_vCibUktKRLp%3Db8nBfeZkh%3DKRc95tq4euA%40mail.gmail.com to abstract slots
more (see patch 0005).

My position is that there's a number of weaknesses with the current
TupleTableSlot API in light of multiple independent, possibly out of
core, storage implementations:

- TupleTableSlots have to contain all the necessary information for each
type of slot. Some implementations might require a buffer pin to be
hold (our heap), others pointers to multiple underlying points of data
(columns store), some need additional metadata (our MinimalTuple).

Unifying the information into one struct makes it much harder to
provide differing implementations without modifying core postgres
and/or increasing overhead for every user of slots.

I think the consequence of that is that we need to allow each type of
slot to have their own TupleTableSlot embedding struct.

Haribabu's patch solved this by adding a tts_storage parameter that
contains additional data, but imo that's unconvincing due to the added
indirection in very performance critical codepaths.

- The way slots currently are implemented each new variant data is
stored in slots adds new branches to hot code paths like
ExecClearTuple(), and they're not extensible.

Therefore I think we need to move to callback based implementation. In
my tests, by moving the callback invocations into very thin inline
functions, the branch prediction accuracy actually goes sligthly
*up*.

- Currently we frequently convert from one way of representing a row
into another, in the same slot. We do so fairly implicilty in
ExecMaterializeSlot(), ExecFetchSlotMinimalTuple(), ExecCopySlot()...

The more we abstract specific storage representation away, the worse I
think that is. I think we should make such conversions explicit by
requiring transfers between two slots if a specific type is required.

- We have a few codepaths that set fields on tuples that can't be
represented in virtual slots. E.g. postgres_fdw sets ctid, oid,
ExecProcessReturning() will set tableoid.

In my POC I turned TupleTableSlot into basically an abstract base class:
struct TupleTableSlot
{
NodeTag type;

uint16 flags;
uint16 nvalid; /* # of valid values in tts_values */

const TupleTableSlotOps *const cb;

TupleDesc tupleDescriptor; /* slot's tuple descriptor */

Datum *values; /* current per-attribute values */
bool *nulls; /* current per-attribute null flags */

/* can we optimize away? */
MemoryContext mcxt; /* slot itself is in this context */
};

which then is inherited from for specific implementations of tuple
slots:

typedef struct HeapTupleTableSlot
{
TupleTableSlot base;
HeapTuple tuple; /* physical tuple */
uint32 off; /* saved state for slot_deform_tuple */
} HeapTupleTableSlot;

...
typedef struct MinimalTupleTableSlot
{
TupleTableSlot base;
HeapTuple tuple; /* tuple wrapper */
MinimalTuple mintuple; /* minimal tuple, or NULL if none */
HeapTupleData minhdr; /* workspace for minimal-tuple-only case */
uint32 off; /* saved state for slot_deform_tuple */
} MinimalTupleTableSlot;

typedef struct TupleTableSlotOps
{
void (*init)(TupleTableSlot *slot);
void (*release)(TupleTableSlot *slot);

void (*clear)(TupleTableSlot *slot);

void (*getsomeattrs)(TupleTableSlot *slot, int natts);

void (*materialize)(TupleTableSlot *slot);

HeapTuple (*get_heap_tuple)(TupleTableSlot *slot);
MinimalTuple (*get_minimal_tuple)(TupleTableSlot *slot);

HeapTuple (*copy_heap_tuple)(TupleTableSlot *slot);
MinimalTuple (*copy_minimal_tuple)(TupleTableSlot *slot);

} TupleTableSlotOps;

when creating a slot one has to specify the type of slot one wants to
use:

typedef enum TupleTableSlotType
{
TTS_TYPE_VIRTUAL,
TTS_TYPE_HEAPTUPLE,
TTS_TYPE_MINIMALTUPLE,
TTS_TYPE_BUFFER
} TupleTableSlotType;

extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc, TupleTableSlotType st);

You might notice that I've renamed a few fields (tts_values -> values,
tts_isnull -> nulls, tts_nvalid -> nvalid) that haven't actually changed
in the above structs / the attached patch. I now think that's probably
not a good idea, unnecessarily breaking more code than necessary.

I generally like this scheme because it allows the TupleTableStruct to
be relatively lean, without knowing much about specific implementations
of slots.

After this change functions like slot_getattr are thin inline wrappers:
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+   Assert(attnum > 0);
+
+   if (attnum > slot->nvalid)
+       slot->cb->getsomeattrs(slot, attnum);
+
+   Assert(attnum <= slot->nvalid);
+
+   *isnull = slot->nulls[attnum - 1];
+   return slot->values[attnum - 1];
+}

Note that I've moved system attribute handling out of the slot_getattr
path - there were a few paths accessing them via slot_getattr, and it's
a lot of unnecessary branching.

The fact that slots of different types have different storage means that
we can't just change the type of a slot when needed. In nearly all
places that's not a problem. E.g. ExecHashTableInsert() converts the
"incoming" slot to one containing a minimal tuple with
ExecFetchSlotMinimalTuple(), but that's essentially transient as it's
just used to copy the tuple into the hashtable. We could even gain
quite some efficiency by directly copying into the allocated space
(saving one serialization/copy step for the common case where input is
either a virtual or a heap tuple).

The slightly bigger issue is that several parts of the code currently
require heaptuples they can scribble upon. E.g. nodeModifyTable.c
materializes the tuple - those can be solved by using a local slot to
store the tuple, rather than using the incoming one. In nearly all cases
we'd still be left with the same number of tuple copy steps, as
materializing the tuple with copy into the local storage anyway. A few
other cases, e.g. intorel_receive(), just can use ExecCopySlotTuple() or
such instead of materialize.

The biggest issue I don't have a good answer for, and where I don't like
Haribabu's solution, is how to deal with system columns like oid, ctid,
tableoid. Haribabu's patch adds storage of those to the slot, but that
seems like quite the cludge to me. It appears to me that the best thing
would be to require projections for all accesses to system columns, at
the original level of access. Then we don't need any sort of special
codepaths dealing with them. But that's not exactly a trivial change and
has some added complications too (junkfilter type things).

I made a reference to vectorized execution above. That's because that I
found, while prototyping vectorized execution, that it's a very common
need to interact with parts of the system that aren't vectorized, and
doing so has to be extremely cheap. With the above we can have a
TupleTableSlot type that's essentially just a cheap cursor into a batch
of tuples. Besides making it efficiently possible to hand of slots to
part of the system that can't deal with tuple batches, it allows to do
fun things like having the first slot_deform_tuple() call for one tuple
in a batch to deform a full page's worth of tuples, yielding *much*
better cache access patterns.

I haven't done that, but I think we should split ExecStoreTuple() into
multiple versions, that only work on specific types of tuple
slots. E.g. seqscan et al would call ExecStoreBufferHeapTuple(), other
code dealing with tuples would call ExecStoreHeapTuple(). The relevant
callers already need to know what kind of tuple they're dealing with,
therefore that's not a huge burden.

Please please note that the attached patch is *NOT* meant to be a full
proposal or even a to be reviewed patch, it's just an illustration of
the concepts I'm talking about.

Comments? Better ideas?

[1]: http://archives.postgresql.org/message-id/20170815065348.afkj45dgmg22ecfh%40alap3.anarazel.de
[2]: http://archives.postgresql.org/message-id/CAJrrPGdY_hgvu06R_vCibUktKRLp%3Db8nBfeZkh%3DKRc95tq4euA%40mail.gmail.com

Greetings,

Andres Freund

Attachments:

0001-tupleslot-rewrite.patchtext/x-diff; charset=us-asciiDownload
From 42e39640f24ee15b5596e7cbb6831785883ca627 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 20 Feb 2018 14:40:23 -0800
Subject: [PATCH] tupleslot-rewrite

---
 src/backend/access/common/heaptuple.c          |  268 +-----
 src/backend/access/common/printsimple.c        |    6 +-
 src/backend/access/common/printtup.c           |   24 +-
 src/backend/catalog/index.c                    |   18 +-
 src/backend/catalog/indexing.c                 |    3 +-
 src/backend/catalog/partition.c                |    2 +-
 src/backend/commands/analyze.c                 |    3 +-
 src/backend/commands/constraint.c              |    3 +-
 src/backend/commands/copy.c                    |    8 +-
 src/backend/commands/createas.c                |    2 +-
 src/backend/commands/subscriptioncmds.c        |    2 +-
 src/backend/commands/tablecmds.c               |    6 +-
 src/backend/commands/trigger.c                 |   22 +-
 src/backend/executor/execCurrent.c             |   19 +-
 src/backend/executor/execExpr.c                |    7 +-
 src/backend/executor/execExprInterp.c          |  102 +--
 src/backend/executor/execGrouping.c            |    3 +-
 src/backend/executor/execIndexing.c            |    3 +-
 src/backend/executor/execJunk.c                |   12 +-
 src/backend/executor/execMain.c                |    6 +-
 src/backend/executor/execPartition.c           |    7 +-
 src/backend/executor/execReplication.c         |   30 +-
 src/backend/executor/execSRF.c                 |    4 +-
 src/backend/executor/execScan.c                |    4 +-
 src/backend/executor/execTuples.c              | 1048 ++++++++++++++++--------
 src/backend/executor/execUtils.c               |    6 +-
 src/backend/executor/functions.c               |    5 +-
 src/backend/executor/nodeAgg.c                 |   39 +-
 src/backend/executor/nodeAppend.c              |    2 +-
 src/backend/executor/nodeBitmapHeapscan.c      |    6 +-
 src/backend/executor/nodeCtescan.c             |    5 +-
 src/backend/executor/nodeCustom.c              |    6 +-
 src/backend/executor/nodeForeignscan.c         |    9 +-
 src/backend/executor/nodeFunctionscan.c        |   21 +-
 src/backend/executor/nodeGather.c              |    5 +-
 src/backend/executor/nodeGatherMerge.c         |    5 +-
 src/backend/executor/nodeGroup.c               |    5 +-
 src/backend/executor/nodeHash.c                |    2 +-
 src/backend/executor/nodeHashjoin.c            |   13 +-
 src/backend/executor/nodeIndexonlyscan.c       |   12 +-
 src/backend/executor/nodeIndexscan.c           |    5 +-
 src/backend/executor/nodeLimit.c               |    3 +-
 src/backend/executor/nodeLockRows.c            |    2 +-
 src/backend/executor/nodeMaterial.c            |    4 +-
 src/backend/executor/nodeMergeAppend.c         |    3 +-
 src/backend/executor/nodeMergejoin.c           |   13 +-
 src/backend/executor/nodeModifyTable.c         |   27 +-
 src/backend/executor/nodeNamedtuplestorescan.c |    5 +-
 src/backend/executor/nodeNestloop.c            |    5 +-
 src/backend/executor/nodeProjectSet.c          |    6 +-
 src/backend/executor/nodeRecursiveunion.c      |    2 +-
 src/backend/executor/nodeResult.c              |    2 +-
 src/backend/executor/nodeSamplescan.c          |    6 +-
 src/backend/executor/nodeSeqscan.c             |    5 +-
 src/backend/executor/nodeSetOp.c               |    2 +-
 src/backend/executor/nodeSort.c                |    4 +-
 src/backend/executor/nodeSubplan.c             |   12 +-
 src/backend/executor/nodeSubqueryscan.c        |    6 +-
 src/backend/executor/nodeTableFuncscan.c       |   16 +-
 src/backend/executor/nodeTidscan.c             |    5 +-
 src/backend/executor/nodeUnique.c              |    2 +-
 src/backend/executor/nodeValuesscan.c          |   12 +-
 src/backend/executor/nodeWindowAgg.c           |   24 +-
 src/backend/executor/nodeWorktablescan.c       |    4 +-
 src/backend/executor/tstoreReceiver.c          |    8 +-
 src/backend/nodes/print.c                      |    2 +-
 src/backend/replication/logical/tablesync.c    |    4 +-
 src/backend/replication/logical/worker.c       |   60 +-
 src/backend/tcop/pquery.c                      |    2 +-
 src/backend/utils/adt/orderedsetaggs.c         |   34 +-
 src/backend/utils/adt/selfuncs.c               |    3 +-
 src/backend/utils/sort/tuplesort.c             |    2 +-
 src/include/access/htup_details.h              |    5 +
 src/include/executor/executor.h                |   16 +-
 src/include/executor/tuptable.h                |  204 ++++-
 src/include/nodes/execnodes.h                  |    3 +
 76 files changed, 1306 insertions(+), 965 deletions(-)

diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 0a13251067f..5ef9ea5c483 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -1032,18 +1032,17 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
  *		re-computing information about previously extracted attributes.
  *		slot->tts_nvalid is the number of attributes already extracted.
  */
-static void
-slot_deform_tuple(TupleTableSlot *slot, int natts)
+void
+slot_deform_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts)
 {
-	HeapTuple	tuple = slot->tts_tuple;
-	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
-	Datum	   *values = slot->tts_values;
-	bool	   *isnull = slot->tts_isnull;
+	TupleDesc	tupleDesc = slot->tupleDescriptor;
+	Datum	   *values = slot->values;
+	bool	   *isnull = slot->nulls;
 	HeapTupleHeader tup = tuple->t_data;
 	bool		hasnulls = HeapTupleHasNulls(tuple);
 	int			attnum;
 	char	   *tp;				/* ptr to tuple data */
-	long		off;			/* offset in tuple data */
+	uint32		off;			/* offset in tuple data */
 	bits8	   *bp = tup->t_bits;	/* ptr to null bitmap in tuple */
 	bool		slow;			/* can we use/set attcacheoff? */
 
@@ -1051,7 +1050,7 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
 	 * Check whether the first call for this tuple, and initialize or restore
 	 * loop state.
 	 */
-	attnum = slot->tts_nvalid;
+	attnum = slot->nvalid;
 	if (attnum == 0)
 	{
 		/* Start from the first attribute */
@@ -1061,8 +1060,8 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
 	else
 	{
 		/* Restore state from previous execution */
-		off = slot->tts_off;
-		slow = slot->tts_slow;
+		off = *offp;
+		slow = (slot->flags & TTS_SLOW) != 0;
 	}
 
 	tp = (char *) tup + tup->t_hoff;
@@ -1121,249 +1120,12 @@ slot_deform_tuple(TupleTableSlot *slot, int natts)
 	/*
 	 * Save state for next execution
 	 */
-	slot->tts_nvalid = attnum;
-	slot->tts_off = off;
-	slot->tts_slow = slow;
-}
-
-/*
- * slot_getattr
- *		This function fetches an attribute of the slot's current tuple.
- *		It is functionally equivalent to heap_getattr, but fetches of
- *		multiple attributes of the same tuple will be optimized better,
- *		because we avoid O(N^2) behavior from multiple calls of
- *		nocachegetattr(), even when attcacheoff isn't usable.
- *
- *		A difference from raw heap_getattr is that attnums beyond the
- *		slot's tupdesc's last attribute will be considered NULL even
- *		when the physical tuple is longer than the tupdesc.
- */
-Datum
-slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
-{
-	HeapTuple	tuple = slot->tts_tuple;
-	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
-	HeapTupleHeader tup;
-
-	/*
-	 * system attributes are handled by heap_getsysattr
-	 */
-	if (attnum <= 0)
-	{
-		if (tuple == NULL)		/* internal error */
-			elog(ERROR, "cannot extract system attribute from virtual tuple");
-		if (tuple == &(slot->tts_minhdr))	/* internal error */
-			elog(ERROR, "cannot extract system attribute from minimal tuple");
-		return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
-	}
-
-	/*
-	 * fast path if desired attribute already cached
-	 */
-	if (attnum <= slot->tts_nvalid)
-	{
-		*isnull = slot->tts_isnull[attnum - 1];
-		return slot->tts_values[attnum - 1];
-	}
-
-	/*
-	 * return NULL if attnum is out of range according to the tupdesc
-	 */
-	if (attnum > tupleDesc->natts)
-	{
-		*isnull = true;
-		return (Datum) 0;
-	}
-
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
-
-	/*
-	 * return NULL if attnum is out of range according to the tuple
-	 *
-	 * (We have to check this separately because of various inheritance and
-	 * table-alteration scenarios: the tuple could be either longer or shorter
-	 * than the tupdesc.)
-	 */
-	tup = tuple->t_data;
-	if (attnum > HeapTupleHeaderGetNatts(tup))
-	{
-		*isnull = true;
-		return (Datum) 0;
-	}
-
-	/*
-	 * check if target attribute is null: no point in groveling through tuple
-	 */
-	if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
-	{
-		*isnull = true;
-		return (Datum) 0;
-	}
-
-	/*
-	 * If the attribute's column has been dropped, we force a NULL result.
-	 * This case should not happen in normal use, but it could happen if we
-	 * are executing a plan cached before the column was dropped.
-	 */
-	if (TupleDescAttr(tupleDesc, attnum - 1)->attisdropped)
-	{
-		*isnull = true;
-		return (Datum) 0;
-	}
-
-	/*
-	 * Extract the attribute, along with any preceding attributes.
-	 */
-	slot_deform_tuple(slot, attnum);
-
-	/*
-	 * The result is acquired from tts_values array.
-	 */
-	*isnull = slot->tts_isnull[attnum - 1];
-	return slot->tts_values[attnum - 1];
-}
-
-/*
- * slot_getallattrs
- *		This function forces all the entries of the slot's Datum/isnull
- *		arrays to be valid.  The caller may then extract data directly
- *		from those arrays instead of using slot_getattr.
- */
-void
-slot_getallattrs(TupleTableSlot *slot)
-{
-	int			tdesc_natts = slot->tts_tupleDescriptor->natts;
-	int			attnum;
-	HeapTuple	tuple;
-
-	/* Quick out if we have 'em all already */
-	if (slot->tts_nvalid == tdesc_natts)
-		return;
-
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	tuple = slot->tts_tuple;
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
-
-	/*
-	 * load up any slots available from physical tuple
-	 */
-	attnum = HeapTupleHeaderGetNatts(tuple->t_data);
-	attnum = Min(attnum, tdesc_natts);
-
-	slot_deform_tuple(slot, attnum);
-
-	/*
-	 * If tuple doesn't have all the atts indicated by tupleDesc, read the
-	 * rest as null
-	 */
-	for (; attnum < tdesc_natts; attnum++)
-	{
-		slot->tts_values[attnum] = (Datum) 0;
-		slot->tts_isnull[attnum] = true;
-	}
-	slot->tts_nvalid = tdesc_natts;
-}
-
-/*
- * slot_getsomeattrs
- *		This function forces the entries of the slot's Datum/isnull
- *		arrays to be valid at least up through the attnum'th entry.
- */
-void
-slot_getsomeattrs(TupleTableSlot *slot, int attnum)
-{
-	HeapTuple	tuple;
-	int			attno;
-
-	/* Quick out if we have 'em all already */
-	if (slot->tts_nvalid >= attnum)
-		return;
-
-	/* Check for caller error */
-	if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
-		elog(ERROR, "invalid attribute number %d", attnum);
-
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	tuple = slot->tts_tuple;
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
-
-	/*
-	 * load up any slots available from physical tuple
-	 */
-	attno = HeapTupleHeaderGetNatts(tuple->t_data);
-	attno = Min(attno, attnum);
-
-	slot_deform_tuple(slot, attno);
-
-	/*
-	 * If tuple doesn't have all the atts indicated by tupleDesc, read the
-	 * rest as null
-	 */
-	for (; attno < attnum; attno++)
-	{
-		slot->tts_values[attno] = (Datum) 0;
-		slot->tts_isnull[attno] = true;
-	}
-	slot->tts_nvalid = attnum;
-}
-
-/*
- * slot_attisnull
- *		Detect whether an attribute of the slot is null, without
- *		actually fetching it.
- */
-bool
-slot_attisnull(TupleTableSlot *slot, int attnum)
-{
-	HeapTuple	tuple = slot->tts_tuple;
-	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
-
-	/*
-	 * system attributes are handled by heap_attisnull
-	 */
-	if (attnum <= 0)
-	{
-		if (tuple == NULL)		/* internal error */
-			elog(ERROR, "cannot extract system attribute from virtual tuple");
-		if (tuple == &(slot->tts_minhdr))	/* internal error */
-			elog(ERROR, "cannot extract system attribute from minimal tuple");
-		return heap_attisnull(tuple, attnum);
-	}
-
-	/*
-	 * fast path if desired attribute already cached
-	 */
-	if (attnum <= slot->tts_nvalid)
-		return slot->tts_isnull[attnum - 1];
-
-	/*
-	 * return NULL if attnum is out of range according to the tupdesc
-	 */
-	if (attnum > tupleDesc->natts)
-		return true;
-
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
-
-	/* and let the tuple tell it */
-	return heap_attisnull(tuple, attnum);
+	slot->nvalid = attnum;
+	*offp = off;
+	if (slow)
+		slot->flags |= TTS_SLOW;
+	else
+		slot->flags &= ~TTS_SLOW;
 }
 
 /*
diff --git a/src/backend/access/common/printsimple.c b/src/backend/access/common/printsimple.c
index 3c4d2277125..b3eb4f96757 100644
--- a/src/backend/access/common/printsimple.c
+++ b/src/backend/access/common/printsimple.c
@@ -58,7 +58,7 @@ printsimple_startup(DestReceiver *self, int operation, TupleDesc tupdesc)
 bool
 printsimple(TupleTableSlot *slot, DestReceiver *self)
 {
-	TupleDesc	tupdesc = slot->tts_tupleDescriptor;
+	TupleDesc	tupdesc = slot->tupleDescriptor;
 	StringInfoData buf;
 	int			i;
 
@@ -74,13 +74,13 @@ printsimple(TupleTableSlot *slot, DestReceiver *self)
 		Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
 		Datum		value;
 
-		if (slot->tts_isnull[i])
+		if (slot->nulls[i])
 		{
 			pq_sendint32(&buf, -1);
 			continue;
 		}
 
-		value = slot->tts_values[i];
+		value = slot->values[i];
 
 		/*
 		 * We can't call the regular type output functions here because we
diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index a1d44157044..795b3f19a07 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -373,7 +373,7 @@ printtup_prepare_info(DR_printtup *myState, TupleDesc typeinfo, int numAttrs)
 static bool
 printtup(TupleTableSlot *slot, DestReceiver *self)
 {
-	TupleDesc	typeinfo = slot->tts_tupleDescriptor;
+	TupleDesc	typeinfo = slot->tupleDescriptor;
 	DR_printtup *myState = (DR_printtup *) self;
 	MemoryContext oldcontext;
 	StringInfo	buf = &myState->buf;
@@ -403,9 +403,9 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
 	for (i = 0; i < natts; ++i)
 	{
 		PrinttupAttrInfo *thisState = myState->myinfo + i;
-		Datum		attr = slot->tts_values[i];
+		Datum		attr = slot->values[i];
 
-		if (slot->tts_isnull[i])
+		if (slot->nulls[i])
 		{
 			pq_sendint32(buf, -1);
 			continue;
@@ -458,7 +458,7 @@ printtup(TupleTableSlot *slot, DestReceiver *self)
 static bool
 printtup_20(TupleTableSlot *slot, DestReceiver *self)
 {
-	TupleDesc	typeinfo = slot->tts_tupleDescriptor;
+	TupleDesc	typeinfo = slot->tupleDescriptor;
 	DR_printtup *myState = (DR_printtup *) self;
 	MemoryContext oldcontext;
 	StringInfo	buf = &myState->buf;
@@ -489,7 +489,7 @@ printtup_20(TupleTableSlot *slot, DestReceiver *self)
 	k = 1 << 7;
 	for (i = 0; i < natts; ++i)
 	{
-		if (!slot->tts_isnull[i])
+		if (!slot->nulls[i])
 			j |= k;				/* set bit if not null */
 		k >>= 1;
 		if (k == 0)				/* end of byte? */
@@ -508,10 +508,10 @@ printtup_20(TupleTableSlot *slot, DestReceiver *self)
 	for (i = 0; i < natts; ++i)
 	{
 		PrinttupAttrInfo *thisState = myState->myinfo + i;
-		Datum		attr = slot->tts_values[i];
+		Datum		attr = slot->values[i];
 		char	   *outputstr;
 
-		if (slot->tts_isnull[i])
+		if (slot->nulls[i])
 			continue;
 
 		Assert(thisState->format == 0);
@@ -605,7 +605,7 @@ debugStartup(DestReceiver *self, int operation, TupleDesc typeinfo)
 bool
 debugtup(TupleTableSlot *slot, DestReceiver *self)
 {
-	TupleDesc	typeinfo = slot->tts_tupleDescriptor;
+	TupleDesc	typeinfo = slot->tupleDescriptor;
 	int			natts = typeinfo->natts;
 	int			i;
 	Datum		attr;
@@ -643,7 +643,7 @@ debugtup(TupleTableSlot *slot, DestReceiver *self)
 static bool
 printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
 {
-	TupleDesc	typeinfo = slot->tts_tupleDescriptor;
+	TupleDesc	typeinfo = slot->tupleDescriptor;
 	DR_printtup *myState = (DR_printtup *) self;
 	MemoryContext oldcontext;
 	StringInfo	buf = &myState->buf;
@@ -674,7 +674,7 @@ printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
 	k = 1 << 7;
 	for (i = 0; i < natts; ++i)
 	{
-		if (!slot->tts_isnull[i])
+		if (!slot->nulls[i])
 			j |= k;				/* set bit if not null */
 		k >>= 1;
 		if (k == 0)				/* end of byte? */
@@ -693,10 +693,10 @@ printtup_internal_20(TupleTableSlot *slot, DestReceiver *self)
 	for (i = 0; i < natts; ++i)
 	{
 		PrinttupAttrInfo *thisState = myState->myinfo + i;
-		Datum		attr = slot->tts_values[i];
+		Datum		attr = slot->values[i];
 		bytea	   *outputbytes;
 
-		if (slot->tts_isnull[i])
+		if (slot->nulls[i])
 			continue;
 
 		Assert(thisState->format == 1);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index f2cb6d7fb81..8fa19526214 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -1964,7 +1964,14 @@ FormIndexDatum(IndexInfo *indexInfo,
 		Datum		iDatum;
 		bool		isNull;
 
-		if (keycol != 0)
+		if (keycol < 0)
+		{
+			iDatum = heap_getsysattr(((HeapTupleTableSlot *) slot)->tuple,
+									 keycol,
+									 slot->tupleDescriptor,
+									 &isNull);
+		}
+		else if (keycol != 0)
 		{
 			/*
 			 * Plain index column; get the value we need directly from the
@@ -2445,7 +2452,8 @@ IndexBuildHeapRangeScan(Relation heapRelation,
 	 */
 	estate = CreateExecutorState();
 	econtext = GetPerTupleExprContext(estate);
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									TTS_TYPE_HEAPTUPLE);
 
 	/* Arrange for econtext's scan tuple to be the tuple under test */
 	econtext->ecxt_scantuple = slot;
@@ -2900,7 +2908,8 @@ IndexCheckExclusion(Relation heapRelation,
 	 */
 	estate = CreateExecutorState();
 	econtext = GetPerTupleExprContext(estate);
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									TTS_TYPE_HEAPTUPLE);
 
 	/* Arrange for econtext's scan tuple to be the tuple under test */
 	econtext->ecxt_scantuple = slot;
@@ -3218,7 +3227,8 @@ validate_index_heapscan(Relation heapRelation,
 	 */
 	estate = CreateExecutorState();
 	econtext = GetPerTupleExprContext(estate);
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									TTS_TYPE_HEAPTUPLE);
 
 	/* Arrange for econtext's scan tuple to be the tuple under test */
 	econtext->ecxt_scantuple = slot;
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index a84b7da114a..748f0a98cdf 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -95,7 +95,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 	heapRelation = indstate->ri_RelationDesc;
 
 	/* Need a slot to hold the tuple being examined */
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									TTS_TYPE_HEAPTUPLE);
 	ExecStoreTuple(heapTuple, slot, InvalidBuffer, false);
 
 	/*
diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c
index 31c80c7f1ad..be31dcc57db 100644
--- a/src/backend/catalog/partition.c
+++ b/src/backend/catalog/partition.c
@@ -1338,7 +1338,7 @@ check_default_allows_bound(Relation parent, Relation default_rel,
 		econtext = GetPerTupleExprContext(estate);
 		snapshot = RegisterSnapshot(GetLatestSnapshot());
 		scan = heap_beginscan(part_rel, snapshot, 0, NULL);
-		tupslot = MakeSingleTupleTableSlot(tupdesc);
+		tupslot = MakeSingleTupleTableSlot(tupdesc, TTS_TYPE_HEAPTUPLE);
 
 		/*
 		 * Switch to per-tuple memory context and reset it for each tuple
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 5f21fcb5f40..d49068f0966 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -783,7 +783,8 @@ compute_index_stats(Relation onerel, double totalrows,
 		estate = CreateExecutorState();
 		econtext = GetPerTupleExprContext(estate);
 		/* Need a slot to hold the current heap tuple, too */
-		slot = MakeSingleTupleTableSlot(RelationGetDescr(onerel));
+		slot = MakeSingleTupleTableSlot(RelationGetDescr(onerel),
+										TTS_TYPE_HEAPTUPLE);
 
 		/* Arrange for econtext's scan tuple to be the tuple under test */
 		econtext->ecxt_scantuple = slot;
diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c
index 90f19ad3dd9..2d77f475319 100644
--- a/src/backend/commands/constraint.c
+++ b/src/backend/commands/constraint.c
@@ -122,7 +122,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
 	/*
 	 * The heap tuple must be put into a slot for FormIndexDatum.
 	 */
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(trigdata->tg_relation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(trigdata->tg_relation),
+									TTS_TYPE_HEAPTUPLE);
 
 	ExecStoreTuple(new_row, slot, InvalidBuffer, false);
 
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index d5883c98d15..27aae408ac6 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2444,9 +2444,11 @@ CopyFrom(CopyState cstate)
 	estate->es_range_table = cstate->range_table;
 
 	/* Set up a tuple slot too */
-	myslot = ExecInitExtraTupleSlot(estate, tupDesc);
+	myslot = ExecInitExtraTupleSlot(estate, tupDesc,
+									TTS_TYPE_HEAPTUPLE);
 	/* Triggers might need a slot as well */
-	estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
+	estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
+														TTS_TYPE_HEAPTUPLE);
 
 	/* Prepare to catch AFTER triggers. */
 	AfterTriggerBeginQuery();
@@ -4747,7 +4749,7 @@ copy_dest_receive(TupleTableSlot *slot, DestReceiver *self)
 	slot_getallattrs(slot);
 
 	/* And send the data */
-	CopyOneRowTo(cstate, InvalidOid, slot->tts_values, slot->tts_isnull);
+	CopyOneRowTo(cstate, InvalidOid, slot->values, slot->nulls);
 	myState->processed++;
 
 	return true;
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 3d82edbf581..fbb84382280 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -588,7 +588,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 	 * get the heap tuple out of the tuple table slot, making sure we have a
 	 * writable copy
 	 */
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecCopySlotTuple(slot);
 
 	/*
 	 * force assignment of new OID (see comments in ExecInsert)
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index 9de59693022..2c2cc4f33d5 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1148,7 +1148,7 @@ fetch_table_list(WalReceiverConn *wrconn, List *publications)
 						res->err)));
 
 	/* Process tables. */
-	slot = MakeSingleTupleTableSlot(res->tupledesc);
+	slot = MakeSingleTupleTableSlot(res->tupledesc, TTS_TYPE_MINIMALTUPLE);
 	while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
 	{
 		char	   *nspname;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 89454d8e80f..6cca6a4b65e 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4588,8 +4588,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 		 * tuples are the same, the tupDescs might not be (consider ADD COLUMN
 		 * without a default).
 		 */
-		oldslot = MakeSingleTupleTableSlot(oldTupDesc);
-		newslot = MakeSingleTupleTableSlot(newTupDesc);
+		oldslot = MakeSingleTupleTableSlot(oldTupDesc, TTS_TYPE_HEAPTUPLE);
+		newslot = MakeSingleTupleTableSlot(newTupDesc, TTS_TYPE_HEAPTUPLE);
 
 		/* Preallocate values/isnull arrays */
 		i = Max(newTupDesc->natts, oldTupDesc->natts);
@@ -8280,7 +8280,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
 
 	econtext = GetPerTupleExprContext(estate);
 	tupdesc = RelationGetDescr(rel);
-	slot = MakeSingleTupleTableSlot(tupdesc);
+	slot = MakeSingleTupleTableSlot(tupdesc, TTS_TYPE_HEAPTUPLE);
 	econtext->ecxt_scantuple = slot;
 
 	snapshot = RegisterSnapshot(GetLatestSnapshot());
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index fffc0095a79..aeeae171115 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2342,7 +2342,7 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		TupleTableSlot *newslot = estate->es_trig_tuple_slot;
 		TupleDesc	tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
 
-		if (newslot->tts_tupleDescriptor != tupdesc)
+		if (newslot->tupleDescriptor != tupdesc)
 			ExecSetSlotDescriptor(newslot, tupdesc);
 		ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
 		slot = newslot;
@@ -2423,7 +2423,7 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		TupleTableSlot *newslot = estate->es_trig_tuple_slot;
 		TupleDesc	tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
 
-		if (newslot->tts_tupleDescriptor != tupdesc)
+		if (newslot->tupleDescriptor != tupdesc)
 			ExecSetSlotDescriptor(newslot, tupdesc);
 		ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
 		slot = newslot;
@@ -2829,7 +2829,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 		TupleTableSlot *newslot = estate->es_trig_tuple_slot;
 		TupleDesc	tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
 
-		if (newslot->tts_tupleDescriptor != tupdesc)
+		if (newslot->tupleDescriptor != tupdesc)
 			ExecSetSlotDescriptor(newslot, tupdesc);
 		ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
 		slot = newslot;
@@ -2937,7 +2937,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 		TupleTableSlot *newslot = estate->es_trig_tuple_slot;
 		TupleDesc	tupdesc = RelationGetDescr(relinfo->ri_RelationDesc);
 
-		if (newslot->tts_tupleDescriptor != tupdesc)
+		if (newslot->tupleDescriptor != tupdesc)
 			ExecSetSlotDescriptor(newslot, tupdesc);
 		ExecStoreTuple(newtuple, newslot, InvalidBuffer, false);
 		slot = newslot;
@@ -3252,11 +3252,11 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
 			{
 				oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
 				estate->es_trig_oldtup_slot =
-					ExecInitExtraTupleSlot(estate, NULL);
+					ExecInitExtraTupleSlot(estate, NULL, TTS_TYPE_HEAPTUPLE);
 				MemoryContextSwitchTo(oldContext);
 			}
 			oldslot = estate->es_trig_oldtup_slot;
-			if (oldslot->tts_tupleDescriptor != tupdesc)
+			if (oldslot->tupleDescriptor != tupdesc)
 				ExecSetSlotDescriptor(oldslot, tupdesc);
 			ExecStoreTuple(oldtup, oldslot, InvalidBuffer, false);
 		}
@@ -3266,11 +3266,11 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
 			{
 				oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
 				estate->es_trig_newtup_slot =
-					ExecInitExtraTupleSlot(estate, NULL);
+					ExecInitExtraTupleSlot(estate, NULL, TTS_TYPE_HEAPTUPLE);
 				MemoryContextSwitchTo(oldContext);
 			}
 			newslot = estate->es_trig_newtup_slot;
-			if (newslot->tts_tupleDescriptor != tupdesc)
+			if (newslot->tupleDescriptor != tupdesc)
 				ExecSetSlotDescriptor(newslot, tupdesc);
 			ExecStoreTuple(newtup, newslot, InvalidBuffer, false);
 		}
@@ -4273,8 +4273,10 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
 							ExecDropSingleTupleTableSlot(slot1);
 							ExecDropSingleTupleTableSlot(slot2);
 						}
-						slot1 = MakeSingleTupleTableSlot(rel->rd_att);
-						slot2 = MakeSingleTupleTableSlot(rel->rd_att);
+						slot1 = MakeSingleTupleTableSlot(rel->rd_att,
+														 TTS_TYPE_HEAPTUPLE);
+						slot2 = MakeSingleTupleTableSlot(rel->rd_att,
+														 TTS_TYPE_HEAPTUPLE);
 					}
 					if (trigdesc == NULL)	/* should not happen */
 						elog(ERROR, "relation %u has no triggers",
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index ce7d4ac592a..2574639ecef 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -13,6 +13,7 @@
 #include "postgres.h"
 
 #include "access/sysattr.h"
+#include "access/htup_details.h"
 #include "catalog/pg_type.h"
 #include "executor/executor.h"
 #include "utils/builtins.h"
@@ -183,16 +184,22 @@ execCurrentOf(CurrentOfExpr *cexpr,
 		if (TupIsNull(scanstate->ss_ScanTupleSlot))
 			return false;
 
+#if 0
 		/* Use slot_getattr to catch any possible mistakes */
 		tuple_tableoid =
-			DatumGetObjectId(slot_getattr(scanstate->ss_ScanTupleSlot,
-										  TableOidAttributeNumber,
-										  &lisnull));
+			DatumGetObjectId(heap_getsysattr(scanstate->ss_ScanTupleSlot->tts_tuple,
+											 TableOidAttributeNumber,
+											 scanstate->ss_ScanTupleSlot->tts_tupleDescriptor,
+											 &lisnull));
 		Assert(!lisnull);
 		tuple_tid = (ItemPointer)
-			DatumGetPointer(slot_getattr(scanstate->ss_ScanTupleSlot,
-										 SelfItemPointerAttributeNumber,
-										 &lisnull));
+			DatumGetPointer(heap_getsysattr(scanstate->ss_ScanTupleSlot->tts_tuple,
+											 SelfItemPointerAttributeNumber,
+											 scanstate->ss_ScanTupleSlot->tts_tupleDescriptor,
+											 &lisnull));
+#else
+		elog(ERROR, "not yet");
+#endif
 		Assert(!lisnull);
 
 		Assert(tuple_tableoid == table_oid);
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index db5fcafbfe4..c6e478c3650 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2415,7 +2415,8 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
 				scratch->d.wholerow.junkFilter =
 					ExecInitJunkFilter(subplan->plan->targetlist,
 									   ExecGetResultType(subplan)->tdhasoid,
-									   ExecInitExtraTupleSlot(parent->state, NULL));
+									   ExecInitExtraTupleSlot(parent->state, NULL,
+															  TTS_TYPE_VIRTUAL));
 			}
 		}
 	}
@@ -2994,8 +2995,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 			/*
 			 * DISTINCT and/or ORDER BY case, with multiple columns sorted on.
 			 */
-			Datum	   *values = pertrans->sortslot->tts_values;
-			bool	   *nulls = pertrans->sortslot->tts_isnull;
+			Datum	   *values = pertrans->sortslot->values;
+			bool	   *nulls = pertrans->sortslot->nulls;
 
 			strictnulls = nulls;
 
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 771b7e3945c..e7c2b9fb43c 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -455,9 +455,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			 * directly out of the slot's decomposed-data arrays.  But let's
 			 * have an Assert to check that that did happen.
 			 */
-			Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
-			*op->resvalue = innerslot->tts_values[attnum];
-			*op->resnull = innerslot->tts_isnull[attnum];
+			Assert(attnum >= 0 && attnum < innerslot->nvalid);
+			*op->resvalue = innerslot->values[attnum];
+			*op->resnull = innerslot->nulls[attnum];
 
 			EEO_NEXT();
 		}
@@ -468,9 +468,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 			/* See EEOP_INNER_VAR comments */
 
-			Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
-			*op->resvalue = outerslot->tts_values[attnum];
-			*op->resnull = outerslot->tts_isnull[attnum];
+			Assert(attnum >= 0 && attnum < outerslot->nvalid);
+			*op->resvalue = outerslot->values[attnum];
+			*op->resnull = outerslot->nulls[attnum];
 
 			EEO_NEXT();
 		}
@@ -481,9 +481,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 			/* See EEOP_INNER_VAR comments */
 
-			Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
-			*op->resvalue = scanslot->tts_values[attnum];
-			*op->resnull = scanslot->tts_isnull[attnum];
+			Assert(attnum >= 0 && attnum < scanslot->nvalid);
+			*op->resvalue = scanslot->values[attnum];
+			*op->resnull = scanslot->nulls[attnum];
 
 			EEO_NEXT();
 		}
@@ -494,12 +494,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			Datum		d;
 
 			/* these asserts must match defenses in slot_getattr */
-			Assert(innerslot->tts_tuple != NULL);
-			Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
+			//Assert(innerslot->tts_tuple != NULL);
+			//Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
 
 			/* heap_getsysattr has sufficient defenses against bad attnums */
-			d = heap_getsysattr(innerslot->tts_tuple, attnum,
-								innerslot->tts_tupleDescriptor,
+			d = heap_getsysattr(((HeapTupleTableSlot *)innerslot)->tuple, attnum,
+								innerslot->tupleDescriptor,
 								op->resnull);
 			*op->resvalue = d;
 
@@ -512,12 +512,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			Datum		d;
 
 			/* these asserts must match defenses in slot_getattr */
-			Assert(outerslot->tts_tuple != NULL);
-			Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
+			//Assert(outerslot->tts_tuple != NULL);
+			//Assert(outerslot->tts_tuple != &(outerslot->tts_minhdr));
 
 			/* heap_getsysattr has sufficient defenses against bad attnums */
-			d = heap_getsysattr(outerslot->tts_tuple, attnum,
-								outerslot->tts_tupleDescriptor,
+			d = heap_getsysattr(((HeapTupleTableSlot *)outerslot)->tuple, attnum,
+								outerslot->tupleDescriptor,
 								op->resnull);
 			*op->resvalue = d;
 
@@ -530,12 +530,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			Datum		d;
 
 			/* these asserts must match defenses in slot_getattr */
-			Assert(scanslot->tts_tuple != NULL);
-			Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
+			//Assert(scanslot->tts_tuple != NULL);
+			//Assert(scanslot->tts_tuple != &(scanslot->tts_minhdr));
 
 			/* heap_getsysattr has sufficient defenses against bad attnums */
-			d = heap_getsysattr(scanslot->tts_tuple, attnum,
-								scanslot->tts_tupleDescriptor,
+			d = heap_getsysattr(((HeapTupleTableSlot *)scanslot)->tuple, attnum,
+								scanslot->tupleDescriptor,
 								op->resnull);
 			*op->resvalue = d;
 
@@ -559,9 +559,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			 * We do not need CheckVarSlotCompatibility here; that was taken
 			 * care of at compilation time.  But see EEOP_INNER_VAR comments.
 			 */
-			Assert(attnum >= 0 && attnum < innerslot->tts_nvalid);
-			resultslot->tts_values[resultnum] = innerslot->tts_values[attnum];
-			resultslot->tts_isnull[resultnum] = innerslot->tts_isnull[attnum];
+			Assert(attnum >= 0 && attnum < innerslot->nvalid);
+			resultslot->values[resultnum] = innerslot->values[attnum];
+			resultslot->nulls[resultnum] = innerslot->nulls[attnum];
 
 			EEO_NEXT();
 		}
@@ -575,9 +575,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			 * We do not need CheckVarSlotCompatibility here; that was taken
 			 * care of at compilation time.  But see EEOP_INNER_VAR comments.
 			 */
-			Assert(attnum >= 0 && attnum < outerslot->tts_nvalid);
-			resultslot->tts_values[resultnum] = outerslot->tts_values[attnum];
-			resultslot->tts_isnull[resultnum] = outerslot->tts_isnull[attnum];
+			Assert(attnum >= 0 && attnum < outerslot->nvalid);
+			resultslot->values[resultnum] = outerslot->values[attnum];
+			resultslot->nulls[resultnum] = outerslot->nulls[attnum];
 
 			EEO_NEXT();
 		}
@@ -591,9 +591,9 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			 * We do not need CheckVarSlotCompatibility here; that was taken
 			 * care of at compilation time.  But see EEOP_INNER_VAR comments.
 			 */
-			Assert(attnum >= 0 && attnum < scanslot->tts_nvalid);
-			resultslot->tts_values[resultnum] = scanslot->tts_values[attnum];
-			resultslot->tts_isnull[resultnum] = scanslot->tts_isnull[attnum];
+			Assert(attnum >= 0 && attnum < scanslot->nvalid);
+			resultslot->values[resultnum] = scanslot->values[attnum];
+			resultslot->nulls[resultnum] = scanslot->nulls[attnum];
 
 			EEO_NEXT();
 		}
@@ -602,8 +602,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		{
 			int			resultnum = op->d.assign_tmp.resultnum;
 
-			resultslot->tts_values[resultnum] = state->resvalue;
-			resultslot->tts_isnull[resultnum] = state->resnull;
+			resultslot->values[resultnum] = state->resvalue;
+			resultslot->nulls[resultnum] = state->resnull;
 
 			EEO_NEXT();
 		}
@@ -612,12 +612,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		{
 			int			resultnum = op->d.assign_tmp.resultnum;
 
-			resultslot->tts_isnull[resultnum] = state->resnull;
-			if (!resultslot->tts_isnull[resultnum])
-				resultslot->tts_values[resultnum] =
+			resultslot->nulls[resultnum] = state->resnull;
+			if (!resultslot->nulls[resultnum])
+				resultslot->values[resultnum] =
 					MakeExpandedObjectReadOnlyInternal(state->resvalue);
 			else
-				resultslot->tts_values[resultnum] = state->resvalue;
+				resultslot->values[resultnum] = state->resvalue;
 
 			EEO_NEXT();
 		}
@@ -1897,7 +1897,7 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
 	 */
 	if (attnum > 0)
 	{
-		TupleDesc	slot_tupdesc = slot->tts_tupleDescriptor;
+		TupleDesc	slot_tupdesc = slot->tupleDescriptor;
 		Form_pg_attribute attr;
 
 		if (attnum > slot_tupdesc->natts)	/* should never happen */
@@ -2050,8 +2050,8 @@ ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	 * step explicitly, and we also needn't Assert that the attnum is in range
 	 * --- slot_getattr() will take care of any problems.
 	 */
-	outslot->tts_values[resultnum] =
-		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
+	outslot->values[resultnum] =
+		slot_getattr(inslot, attnum, &outslot->nulls[resultnum]);
 	return 0;
 }
 
@@ -2066,8 +2066,8 @@ ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	TupleTableSlot *outslot = state->resultslot;
 
 	/* See comments in ExecJustAssignInnerVar */
-	outslot->tts_values[resultnum] =
-		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
+	outslot->values[resultnum] =
+		slot_getattr(inslot, attnum, &outslot->nulls[resultnum]);
 	return 0;
 }
 
@@ -2082,8 +2082,8 @@ ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	TupleTableSlot *outslot = state->resultslot;
 
 	/* See comments in ExecJustAssignInnerVar */
-	outslot->tts_values[resultnum] =
-		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
+	outslot->values[resultnum] =
+		slot_getattr(inslot, attnum, &outslot->nulls[resultnum]);
 	return 0;
 }
 
@@ -3858,7 +3858,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 			var_tupdesc = lookup_rowtype_tupdesc_domain(variable->vartype,
 														-1, false);
 
-			slot_tupdesc = slot->tts_tupleDescriptor;
+			slot_tupdesc = slot->tupleDescriptor;
 
 			if (var_tupdesc->natts != slot_tupdesc->natts)
 				ereport(ERROR,
@@ -3911,7 +3911,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 			 * column names below.
 			 */
 			oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_query_memory);
-			output_tupdesc = CreateTupleDescCopy(slot->tts_tupleDescriptor);
+			output_tupdesc = CreateTupleDescCopy(slot->tupleDescriptor);
 			MemoryContextSwitchTo(oldcontext);
 		}
 
@@ -3963,7 +3963,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 	if (op->d.wholerow.slow)
 	{
 		/* Check to see if any dropped attributes are non-null */
-		TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
+		TupleDesc	tupleDesc = slot->tupleDescriptor;
 		TupleDesc	var_tupdesc = op->d.wholerow.tupdesc;
 		int			i;
 
@@ -3976,7 +3976,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 
 			if (!vattr->attisdropped)
 				continue;		/* already checked non-dropped cols */
-			if (slot->tts_isnull[i])
+			if (slot->nulls[i])
 				continue;		/* null is always okay */
 			if (vattr->attlen != sattr->attlen ||
 				vattr->attalign != sattr->attalign)
@@ -3993,9 +3993,9 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 	 *
 	 * (Note: it is critical that we not change the slot's state here.)
 	 */
-	tuple = toast_build_flattened_tuple(slot->tts_tupleDescriptor,
-										slot->tts_values,
-										slot->tts_isnull);
+	tuple = toast_build_flattened_tuple(slot->tupleDescriptor,
+										slot->values,
+										slot->nulls);
 	dtuple = tuple->t_data;
 
 	/*
@@ -4099,7 +4099,7 @@ ExecEvalAggOrderedTransTuple(ExprState *state, ExprEvalStep *op,
 	int			setno = op->d.agg_trans.setno;
 
 	ExecClearTuple(pertrans->sortslot);
-	pertrans->sortslot->tts_nvalid = pertrans->numInputs;
+	pertrans->sortslot->nvalid = pertrans->numInputs;
 	ExecStoreVirtualTuple(pertrans->sortslot);
 	tuplesort_puttupleslot(pertrans->sortstates[setno], pertrans->sortslot);
 }
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index c4d0e040587..9be9da4b161 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -202,7 +202,8 @@ BuildTupleHashTable(PlanState *parent,
 	 * We copy the input tuple descriptor just for safety --- we assume all
 	 * input tuples will have equivalent descriptors.
 	 */
-	hashtable->tableslot = MakeSingleTupleTableSlot(CreateTupleDescCopy(inputDesc));
+	hashtable->tableslot = MakeSingleTupleTableSlot(CreateTupleDescCopy(inputDesc),
+													TTS_TYPE_MINIMALTUPLE);
 
 	/* build comparator for all columns */
 	hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index 62e51f1ef3b..4403fd7fa3e 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -706,7 +706,8 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index,
 	 * to this slot.  Be sure to save and restore caller's value for
 	 * scantuple.
 	 */
-	existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap));
+	existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap),
+											 TTS_TYPE_HEAPTUPLE);
 
 	econtext = GetPerTupleExprContext(estate);
 	save_scantuple = econtext->ecxt_scantuple;
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 57d74e57c1a..1abc2630b94 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -78,7 +78,7 @@ ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
 	if (slot)
 		ExecSetSlotDescriptor(slot, cleanTupType);
 	else
-		slot = MakeSingleTupleTableSlot(cleanTupType);
+		slot = MakeSingleTupleTableSlot(cleanTupType, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * Now calculate the mapping between the original tuple's attributes and
@@ -149,7 +149,7 @@ ExecInitJunkFilterConversion(List *targetList,
 	if (slot)
 		ExecSetSlotDescriptor(slot, cleanTupType);
 	else
-		slot = MakeSingleTupleTableSlot(cleanTupType);
+		slot = MakeSingleTupleTableSlot(cleanTupType, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * Calculate the mapping between the original tuple's attributes and the
@@ -275,8 +275,8 @@ ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 	 * Extract all the values of the old tuple.
 	 */
 	slot_getallattrs(slot);
-	old_values = slot->tts_values;
-	old_isnull = slot->tts_isnull;
+	old_values = slot->values;
+	old_isnull = slot->nulls;
 
 	/*
 	 * get info from the junk filter
@@ -290,8 +290,8 @@ ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)
 	 * Prepare to build a virtual result tuple.
 	 */
 	ExecClearTuple(resultSlot);
-	values = resultSlot->tts_values;
-	isnull = resultSlot->tts_isnull;
+	values = resultSlot->values;
+	isnull = resultSlot->nulls;
 
 	/*
 	 * Transpose data into proper fields of the new tuple.
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 91ba939bdca..a93cfe963cb 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1073,7 +1073,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 
 			j = ExecInitJunkFilter(planstate->plan->targetlist,
 								   tupType->tdhasoid,
-								   ExecInitExtraTupleSlot(estate, NULL));
+								   ExecInitExtraTupleSlot(estate, NULL, TTS_TYPE_VIRTUAL));
 			estate->es_junkFilter = j;
 
 			/* Want to return the cleaned tuple type */
@@ -2319,7 +2319,7 @@ ExecBuildSlotValueDescription(Oid reloid,
 
 		if (table_perm || column_perm)
 		{
-			if (slot->tts_isnull[i])
+			if (slot->nulls[i])
 				val = "null";
 			else
 			{
@@ -2328,7 +2328,7 @@ ExecBuildSlotValueDescription(Oid reloid,
 
 				getTypeOutputInfo(att->atttypid,
 								  &foutoid, &typisvarlena);
-				val = OidOutputFunctionCall(foutoid, slot->tts_values[i]);
+				val = OidOutputFunctionCall(foutoid, slot->values[i]);
 			}
 
 			if (write_comma)
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 00523ce250d..04979eb7e75 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -93,7 +93,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
 		 * We need an additional tuple slot for storing transient tuples that
 		 * are converted to the root table descriptor.
 		 */
-		proute->root_tuple_slot = MakeTupleTableSlot(NULL);
+		proute->root_tuple_slot = MakeTupleTableSlot(NULL, TTS_TYPE_HEAPTUPLE);
 	}
 	else
 	{
@@ -112,7 +112,8 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
 	 * (such as ModifyTableState) and released when the node finishes
 	 * processing.
 	 */
-	proute->partition_tuple_slot = MakeTupleTableSlot(NULL);
+	proute->partition_tuple_slot = MakeTupleTableSlot(NULL,
+													  TTS_TYPE_HEAPTUPLE);
 
 	i = 0;
 	foreach(cell, leaf_parts)
@@ -590,7 +591,7 @@ get_partition_dispatch_recurse(Relation rel, Relation parent,
 		 * using the correct tuple descriptor when computing its partition key
 		 * for tuple routing.
 		 */
-		pd->tupslot = MakeSingleTupleTableSlot(tupdesc);
+		pd->tupslot = MakeSingleTupleTableSlot(tupdesc, TTS_TYPE_HEAPTUPLE);
 		pd->tupmap = convert_tuples_by_name(RelationGetDescr(parent),
 											tupdesc,
 											gettext_noop("could not convert row type"));
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index 32891abbdf5..daf20589f4f 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -92,10 +92,10 @@ build_replindex_scan_key(ScanKey skey, Relation rel, Relation idxrel,
 					pkattno,
 					BTEqualStrategyNumber,
 					regop,
-					searchslot->tts_values[mainattno - 1]);
+					searchslot->values[mainattno - 1]);
 
 		/* Check for null value. */
-		if (searchslot->tts_isnull[mainattno - 1])
+		if (searchslot->nulls[mainattno - 1])
 		{
 			hasnulls = true;
 			skey[attoff].sk_flags |= SK_ISNULL;
@@ -171,7 +171,7 @@ retry:
 		HTSU_Result res;
 		HeapTupleData locktup;
 
-		ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+		ItemPointerCopy(&((HeapTupleTableSlot *)outslot)->tuple->t_self, &locktup.t_self);
 
 		PushActiveSnapshot(GetLatestSnapshot());
 
@@ -238,7 +238,7 @@ tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot)
 		 * If one value is NULL and other is not, then they are certainly not
 		 * equal
 		 */
-		if (isnull[attrnum] != slot->tts_isnull[attrnum])
+		if (isnull[attrnum] != slot->nulls[attrnum])
 			return false;
 
 		/*
@@ -258,7 +258,7 @@ tuple_equals_slot(TupleDesc desc, HeapTuple tup, TupleTableSlot *slot)
 
 		if (!DatumGetBool(FunctionCall2(&typentry->eq_opr_finfo,
 										values[attrnum],
-										slot->tts_values[attrnum])))
+										slot->values[attrnum])))
 			return false;
 	}
 
@@ -286,7 +286,7 @@ RelationFindReplTupleSeq(Relation rel, LockTupleMode lockmode,
 	bool		found;
 	TupleDesc	desc = RelationGetDescr(rel);
 
-	Assert(equalTupleDescs(desc, outslot->tts_tupleDescriptor));
+	Assert(equalTupleDescs(desc, outslot->tupleDescriptor));
 
 	/* Start a heap scan. */
 	InitDirtySnapshot(snap);
@@ -329,7 +329,7 @@ retry:
 		HTSU_Result res;
 		HeapTupleData locktup;
 
-		ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+		ItemPointerCopy(&((HeapTupleTableSlot *)outslot)->tuple->t_self, &locktup.t_self);
 
 		PushActiveSnapshot(GetLatestSnapshot());
 
@@ -453,7 +453,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 		resultRelInfo->ri_TrigDesc->trig_update_before_row)
 	{
 		slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
-									&searchslot->tts_tuple->t_self,
+									&((HeapTupleTableSlot *) searchslot)->tuple->t_self,
 									NULL, slot);
 
 		if (slot == NULL)		/* "do nothing" */
@@ -472,18 +472,18 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 		tuple = ExecMaterializeSlot(slot);
 
 		/* OK, update the tuple and index entries for it */
-		simple_heap_update(rel, &searchslot->tts_tuple->t_self,
-						   slot->tts_tuple);
+		simple_heap_update(rel, &((HeapTupleTableSlot *) searchslot)->tuple->t_self,
+						   ((HeapTupleTableSlot *)slot)->tuple);
 
 		if (resultRelInfo->ri_NumIndices > 0 &&
-			!HeapTupleIsHeapOnly(slot->tts_tuple))
+			!HeapTupleIsHeapOnly(((HeapTupleTableSlot *)slot)->tuple))
 			recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
 												   estate, false, NULL,
 												   NIL);
 
 		/* AFTER ROW UPDATE Triggers */
 		ExecARUpdateTriggers(estate, resultRelInfo,
-							 &searchslot->tts_tuple->t_self,
+							 &((HeapTupleTableSlot *)searchslot)->tuple->t_self,
 							 NULL, tuple, recheckIndexes, NULL);
 
 		list_free(recheckIndexes);
@@ -514,7 +514,7 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
 		resultRelInfo->ri_TrigDesc->trig_delete_before_row)
 	{
 		skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
-										   &searchslot->tts_tuple->t_self,
+										   &((HeapTupleTableSlot *)searchslot)->tuple->t_self,
 										   NULL);
 	}
 
@@ -523,11 +523,11 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
 		List	   *recheckIndexes = NIL;
 
 		/* OK, delete the tuple */
-		simple_heap_delete(rel, &searchslot->tts_tuple->t_self);
+		simple_heap_delete(rel, &((HeapTupleTableSlot *)searchslot)->tuple->t_self);
 
 		/* AFTER ROW DELETE Triggers */
 		ExecARDeleteTriggers(estate, resultRelInfo,
-							 &searchslot->tts_tuple->t_self, NULL, NULL);
+							 &((HeapTupleTableSlot *)searchslot)->tuple->t_self, NULL, NULL);
 
 		list_free(recheckIndexes);
 	}
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index b97b8d797ec..163d8bb1183 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -509,7 +509,7 @@ restart:
 		 * clearing the slot could end up trying to free something already
 		 * freed.
 		 */
-		oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+		oldContext = MemoryContextSwitchTo(slot->mcxt);
 		foundTup = tuplestore_gettupleslot(fcache->funcResultStore, true, false,
 										   fcache->funcResultSlot);
 		MemoryContextSwitchTo(oldContext);
@@ -873,7 +873,7 @@ ExecPrepareTuplestoreResult(SetExprState *sexpr,
 			slotDesc = NULL;	/* keep compiler quiet */
 		}
 
-		sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
+		sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc, TTS_TYPE_MINIMALTUPLE);
 		MemoryContextSwitchTo(oldcontext);
 	}
 
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index caf91730ce1..0cc264f2c41 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -235,7 +235,7 @@ void
 ExecAssignScanProjectionInfo(ScanState *node)
 {
 	Scan	   *scan = (Scan *) node->ps.plan;
-	TupleDesc	tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
+	TupleDesc	tupdesc = node->ss_ScanTupleSlot->tupleDescriptor;
 
 	ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, scan->scanrelid);
 }
@@ -247,7 +247,7 @@ ExecAssignScanProjectionInfo(ScanState *node)
 void
 ExecAssignScanProjectionInfoWithVarno(ScanState *node, Index varno)
 {
-	TupleDesc	tupdesc = node->ss_ScanTupleSlot->tts_tupleDescriptor;
+	TupleDesc	tupdesc = node->ss_ScanTupleSlot->tupleDescriptor;
 
 	ExecConditionalAssignProjectionInfo(&node->ps, tupdesc, varno);
 }
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index c46d65cf938..32bee3acd7e 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -101,6 +101,560 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
  * ----------------------------------------------------------------
  */
 
+static void
+tts_virtual_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_virtual_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_virtual_clear(TupleTableSlot *slot)
+{
+	slot->nvalid = 0;
+	slot->flags |= TTS_ISEMPTY;
+}
+
+static void
+tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	elog(ERROR, "should not be called");
+}
+
+static void
+tts_virtual_materialize(TupleTableSlot *slot)
+{
+	elog(ERROR, "materializing a virtual tuple");
+}
+
+static HeapTuple
+tts_virtual_get_heap_tuple(TupleTableSlot *slot)
+{
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	return heap_form_tuple(slot->tupleDescriptor,
+						   slot->values,
+						   slot->nulls);
+
+}
+
+static MinimalTuple
+tts_virtual_get_minimal_tuple(TupleTableSlot *slot)
+{
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	return heap_form_minimal_tuple(slot->tupleDescriptor,
+								   slot->values,
+								   slot->nulls);
+}
+
+static HeapTuple
+tts_virtual_copy_heap_tuple(TupleTableSlot *slot)
+{
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	return heap_form_tuple(slot->tupleDescriptor,
+						   slot->values,
+						   slot->nulls);
+
+}
+
+static MinimalTuple
+tts_virtual_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	return heap_form_minimal_tuple(slot->tupleDescriptor,
+								   slot->values,
+								   slot->nulls);
+}
+
+
+static void
+tts_heap_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_heap_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_heap_clear(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	if (slot->flags & TTS_SHOULDFREE)
+	{
+		heap_freetuple(hslot->tuple);
+		slot->flags &= ~TTS_SHOULDFREE;
+	}
+
+	slot->nvalid = 0;
+	slot->flags |= TTS_ISEMPTY;
+	hslot->off = 0;
+	hslot->tuple = NULL;
+}
+
+static void
+tts_heap_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	slot_deform_tuple(slot, hslot->tuple, &hslot->off, natts);
+}
+
+static void
+tts_heap_materialize(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+	MemoryContext oldContext;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	if (slot->flags & TTS_SHOULDFREE)
+		return;
+
+	slot->flags |= TTS_SHOULDFREE;
+	oldContext = MemoryContextSwitchTo(slot->mcxt);
+
+	if (!hslot->tuple)
+		hslot->tuple = heap_form_tuple(slot->tupleDescriptor,
+									   slot->values,
+									   slot->nulls);
+	else
+		hslot->tuple = heap_copytuple(hslot->tuple);
+
+	slot->nvalid = 0;
+	hslot->off = 0;
+
+	MemoryContextSwitchTo(oldContext);
+}
+
+static HeapTuple
+tts_heap_get_heap_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return hslot->tuple;
+}
+
+static MinimalTuple
+tts_heap_get_minimal_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return minimal_tuple_from_heap_tuple(hslot->tuple);
+}
+
+static HeapTuple
+tts_heap_copy_heap_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return heap_copytuple(hslot->tuple);
+}
+
+static MinimalTuple
+tts_heap_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return minimal_tuple_from_heap_tuple(hslot->tuple);
+}
+
+static void
+tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	tts_heap_clear(slot);
+
+	slot->nvalid = 0;
+	hslot->tuple = tuple;
+	hslot->off = 0;
+	slot->flags &= ~TTS_ISEMPTY;
+
+	if (shouldFree)
+		slot->flags |= TTS_SHOULDFREE;
+}
+
+
+static void
+tts_minimal_init(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	mslot->tuple = &mslot->minhdr;
+}
+
+static void
+tts_minimal_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_minimal_clear(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	/* FIXME */
+	if (slot->flags & TTS_SHOULDFREE)
+	{
+		heap_free_minimal_tuple(mslot->mintuple);
+		slot->flags &= ~TTS_SHOULDFREE;
+	}
+
+	slot->nvalid = 0;
+	slot->flags |= TTS_ISEMPTY;
+	mslot->off = 0;
+	mslot->mintuple = NULL;
+}
+
+static void
+tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	slot_deform_tuple(slot, mslot->tuple, &mslot->off, natts);
+}
+
+static void
+tts_minimal_materialize(TupleTableSlot *slot)
+{
+	elog(ERROR, "materializing a minimal tuple");
+}
+
+static void
+tts_minimal_localize(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+	MemoryContext oldContext;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	if (slot->flags & TTS_SHOULDFREE)
+		return;
+
+	slot->flags |= TTS_SHOULDFREE;
+	oldContext = MemoryContextSwitchTo(slot->mcxt);
+
+	if (!mslot->mintuple)
+		mslot->mintuple = heap_form_minimal_tuple(slot->tupleDescriptor,
+												  slot->values,
+												  slot->nulls);
+	else
+		mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple);
+	mslot->tuple = &mslot->minhdr;
+	mslot->minhdr.t_len = mslot->mintuple->t_len + MINIMAL_TUPLE_OFFSET;
+	mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mslot->mintuple - MINIMAL_TUPLE_OFFSET);
+
+	MemoryContextSwitchTo(oldContext);
+
+	slot->nvalid = 0;
+	mslot->off = 0;
+}
+
+static HeapTuple
+tts_minimal_get_heap_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!mslot->mintuple)
+		tts_minimal_localize(slot);
+
+	return mslot->tuple;
+}
+
+static MinimalTuple
+tts_minimal_get_minimal_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!mslot->mintuple)
+		tts_minimal_localize(slot);
+
+	return mslot->mintuple;
+}
+
+static HeapTuple
+tts_minimal_copy_heap_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	if (!mslot->mintuple)
+		tts_minimal_localize(slot);
+
+	return heap_tuple_from_minimal_tuple(mslot->mintuple);
+}
+
+static MinimalTuple
+tts_minimal_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	if (!mslot->mintuple)
+		tts_minimal_localize(slot);
+
+	return heap_copy_minimal_tuple(mslot->mintuple);
+}
+
+static void
+tts_minimal_store_tuple(TupleTableSlot *slot, MinimalTuple mtup, bool shouldFree)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	tts_minimal_clear(slot);
+
+	slot->flags &= ~TTS_ISEMPTY;
+	slot->nvalid = 0;
+	mslot->off = 0;
+
+	mslot->mintuple = mtup;
+	mslot->tuple = &mslot->minhdr;
+	mslot->minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
+	mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
+	/* no need to set t_self or t_tableOid since we won't allow access */
+
+	if (shouldFree)
+		slot->flags |= TTS_SHOULDFREE;
+	else
+		Assert(!(slot->flags & TTS_SHOULDFREE));
+}
+
+
+static void
+tts_buffer_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_buffer_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_buffer_clear(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	if (slot->flags & TTS_SHOULDFREE)
+	{
+		heap_freetuple(bslot->base.tuple);
+		slot->flags &= ~TTS_SHOULDFREE;
+	}
+
+	if (BufferIsValid(bslot->buffer))
+		ReleaseBuffer(bslot->buffer);
+
+	slot->nvalid = 0;
+	slot->flags |= TTS_ISEMPTY;
+	bslot->base.tuple = NULL;
+	bslot->buffer = InvalidBuffer;
+
+}
+
+static void
+tts_buffer_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	slot_deform_tuple(slot, bslot->base.tuple, &bslot->base.off, natts);
+}
+
+static void
+tts_buffer_materialize(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+	MemoryContext oldContext;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+
+	if (slot->flags & TTS_SHOULDFREE)
+		return;
+
+	slot->flags |= TTS_SHOULDFREE;
+	oldContext = MemoryContextSwitchTo(slot->mcxt);
+
+	if (!bslot->base.tuple)
+		bslot->base.tuple = heap_form_tuple(slot->tupleDescriptor,
+											slot->values,
+											slot->nulls);
+	else
+		bslot->base.tuple = heap_copytuple(bslot->base.tuple);
+	MemoryContextSwitchTo(oldContext);
+
+
+	if (BufferIsValid(bslot->buffer))
+	{
+		ReleaseBuffer(bslot->buffer);
+		bslot->buffer = InvalidBuffer;
+	}
+
+	bslot->base.off = 0;
+	slot->nvalid = 0;
+
+}
+
+static HeapTuple
+tts_buffer_get_heap_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!bslot->base.tuple)
+		tts_buffer_materialize(slot);
+
+	return bslot->base.tuple;
+}
+
+static MinimalTuple
+tts_buffer_get_minimal_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!bslot->base.tuple)
+		tts_buffer_materialize(slot);
+
+	return minimal_tuple_from_heap_tuple(bslot->base.tuple);
+}
+
+static HeapTuple
+tts_buffer_copy_heap_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	if (!bslot->base.tuple)
+		tts_buffer_materialize(slot);
+
+	return heap_copytuple(bslot->base.tuple);
+}
+
+static MinimalTuple
+tts_buffer_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	if (!bslot->base.tuple)
+		tts_buffer_materialize(slot);
+
+	return minimal_tuple_from_heap_tuple(bslot->base.tuple);
+}
+
+static void
+tts_buffer_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	if (slot->flags & TTS_SHOULDFREE)
+	{
+		heap_freetuple(bslot->base.tuple);
+		slot->flags &= ~TTS_SHOULDFREE;
+	}
+
+	slot->flags &= ~TTS_ISEMPTY;
+	slot->nvalid = 0;
+	bslot->base.tuple = tuple;
+	bslot->base.off = 0;
+
+	/*
+	 * If tuple is on a disk page, keep the page pinned as long as we hold a
+	 * pointer into it.  We assume the caller already has such a pin.
+	 *
+	 * This is coded to optimize the case where the slot previously held a
+	 * tuple on the same disk page: in that case releasing and re-acquiring
+	 * the pin is a waste of cycles.  This is a common situation during
+	 * seqscans, so it's worth troubling over.
+	 */
+	if (bslot->buffer != buffer)
+	{
+		if (BufferIsValid(bslot->buffer))
+			ReleaseBuffer(bslot->buffer);
+		bslot->buffer = buffer;
+		IncrBufferRefCount(buffer);
+	}
+
+}
+
+
+static const TupleTableSlotOps TTSOpsVirtual = {
+	tts_virtual_init,
+	tts_virtual_release,
+	tts_virtual_clear,
+	tts_virtual_getsomeattrs,
+	tts_virtual_materialize,
+	tts_virtual_get_heap_tuple,
+	tts_virtual_get_minimal_tuple,
+	tts_virtual_copy_heap_tuple,
+	tts_virtual_copy_minimal_tuple,
+};
+
+static const TupleTableSlotOps TTSOpsHeapTuple = {
+	tts_heap_init,
+	tts_heap_release,
+	tts_heap_clear,
+	tts_heap_getsomeattrs,
+	tts_heap_materialize,
+	tts_heap_get_heap_tuple,
+	tts_heap_get_minimal_tuple,
+	tts_heap_copy_heap_tuple,
+	tts_heap_copy_minimal_tuple,
+};
+
+static const TupleTableSlotOps TTSOpsMinimalTuple = {
+	tts_minimal_init,
+	tts_minimal_release,
+	tts_minimal_clear,
+	tts_minimal_getsomeattrs,
+	tts_minimal_materialize,
+	tts_minimal_get_heap_tuple,
+	tts_minimal_get_minimal_tuple,
+	tts_minimal_copy_heap_tuple,
+	tts_minimal_copy_minimal_tuple,
+};
+
+static const TupleTableSlotOps TTSOpsBufferTuple = {
+	tts_buffer_init,
+	tts_buffer_release,
+	tts_buffer_clear,
+	tts_buffer_getsomeattrs,
+	tts_buffer_materialize,
+	tts_buffer_get_heap_tuple,
+	tts_buffer_get_minimal_tuple,
+	tts_buffer_copy_heap_tuple,
+	tts_buffer_copy_minimal_tuple,
+};
+
+
 /* --------------------------------
  *		MakeTupleTableSlot
  *
@@ -110,50 +664,75 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
  * --------------------------------
  */
 TupleTableSlot *
-MakeTupleTableSlot(TupleDesc tupleDesc)
+MakeTupleTableSlot(TupleDesc tupleDesc, TupleTableSlotType st)
 {
-	Size		sz;
+	Size		basesz, allocsz;
 	TupleTableSlot *slot;
+	const TupleTableSlotOps *ops;
+
+	switch (st)
+	{
+		case TTS_TYPE_VIRTUAL:
+			ops = &TTSOpsVirtual;
+			basesz = sizeof(TupleTableSlot);
+			break;
+		case TTS_TYPE_HEAPTUPLE:
+			ops = &TTSOpsHeapTuple;
+			basesz = sizeof(HeapTupleTableSlot);
+			break;
+		case TTS_TYPE_MINIMALTUPLE:
+			ops = &TTSOpsMinimalTuple;
+			basesz = sizeof(MinimalTupleTableSlot);
+			break;
+		case TTS_TYPE_BUFFER:
+			ops = &TTSOpsBufferTuple;
+			basesz = sizeof(BufferHeapTupleTableSlot);
+			break;
+	}
+
+	/*
+	 * XXX: Main body of this should be in separate initialization
+	 * function so external types of slots can reuse.
+	 */
 
 	/*
 	 * When a fixed descriptor is specified, we can reduce overhead by
 	 * allocating the entire slot in one go.
 	 */
 	if (tupleDesc)
-		sz = MAXALIGN(sizeof(TupleTableSlot)) +
+		allocsz = MAXALIGN(basesz) +
 			MAXALIGN(tupleDesc->natts * sizeof(Datum)) +
 			MAXALIGN(tupleDesc->natts * sizeof(bool));
 	else
-		sz = sizeof(TupleTableSlot);
+		allocsz = basesz;
 
-	slot = palloc0(sz);
+	slot = palloc0(allocsz);
+	*((const TupleTableSlotOps **) &slot->cb) = ops;
 	slot->type = T_TupleTableSlot;
-	slot->tts_isempty = true;
-	slot->tts_shouldFree = false;
-	slot->tts_shouldFreeMin = false;
-	slot->tts_tuple = NULL;
-	slot->tts_fixedTupleDescriptor = tupleDesc != NULL;
-	slot->tts_tupleDescriptor = tupleDesc;
-	slot->tts_mcxt = CurrentMemoryContext;
-	slot->tts_buffer = InvalidBuffer;
-	slot->tts_nvalid = 0;
-	slot->tts_values = NULL;
-	slot->tts_isnull = NULL;
-	slot->tts_mintuple = NULL;
+	slot->flags = TTS_ISEMPTY;
+	slot->flags |= tupleDesc != NULL ? TTS_FIXED : 0;
+	slot->tupleDescriptor = tupleDesc;
+	slot->mcxt = CurrentMemoryContext;
+	slot->nvalid = 0;
 
 	if (tupleDesc != NULL)
 	{
-		slot->tts_values = (Datum *)
+		slot->values = (Datum *)
 			(((char *) slot)
-			 + MAXALIGN(sizeof(TupleTableSlot)));
-		slot->tts_isnull = (bool *)
+			 + MAXALIGN(basesz));
+		slot->nulls = (bool *)
 			(((char *) slot)
-			 + MAXALIGN(sizeof(TupleTableSlot))
+			 + MAXALIGN(basesz)
 			 + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
 
 		PinTupleDesc(tupleDesc);
 	}
 
+	/*
+	 * And allow slot type specific initialization.
+	 */
+	slot->cb->init(slot);
+
 	return slot;
 }
 
@@ -164,9 +743,9 @@ MakeTupleTableSlot(TupleDesc tupleDesc)
  * --------------------------------
  */
 TupleTableSlot *
-ExecAllocTableSlot(List **tupleTable, TupleDesc desc)
+ExecAllocTableSlot(List **tupleTable, TupleDesc desc, TupleTableSlotType st)
 {
-	TupleTableSlot *slot = MakeTupleTableSlot(desc);
+	TupleTableSlot *slot = MakeTupleTableSlot(desc, st);
 
 	*tupleTable = lappend(*tupleTable, slot);
 
@@ -194,21 +773,21 @@ ExecResetTupleTable(List *tupleTable,	/* tuple table */
 
 		/* Always release resources and reset the slot to empty */
 		ExecClearTuple(slot);
-		if (slot->tts_tupleDescriptor)
+		if (slot->tupleDescriptor)
 		{
-			ReleaseTupleDesc(slot->tts_tupleDescriptor);
-			slot->tts_tupleDescriptor = NULL;
+			ReleaseTupleDesc(slot->tupleDescriptor);
+			slot->tupleDescriptor = NULL;
 		}
 
 		/* If shouldFree, release memory occupied by the slot itself */
 		if (shouldFree)
 		{
-			if (!slot->tts_fixedTupleDescriptor)
+			if (!(slot->flags & TTS_FIXED))
 			{
-				if (slot->tts_values)
-					pfree(slot->tts_values);
-				if (slot->tts_isnull)
-					pfree(slot->tts_isnull);
+				if (slot->values)
+					pfree(slot->values);
+				if (slot->nulls)
+					pfree(slot->nulls);
 			}
 			pfree(slot);
 		}
@@ -229,9 +808,9 @@ ExecResetTupleTable(List *tupleTable,	/* tuple table */
  * --------------------------------
  */
 TupleTableSlot *
-MakeSingleTupleTableSlot(TupleDesc tupdesc)
+MakeSingleTupleTableSlot(TupleDesc tupdesc, TupleTableSlotType st)
 {
-	TupleTableSlot *slot = MakeTupleTableSlot(tupdesc);
+	TupleTableSlot *slot = MakeTupleTableSlot(tupdesc, st);
 
 	return slot;
 }
@@ -246,17 +825,18 @@ MakeSingleTupleTableSlot(TupleDesc tupdesc)
 void
 ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
 {
+	slot->cb->release(slot);
 	/* This should match ExecResetTupleTable's processing of one slot */
 	Assert(IsA(slot, TupleTableSlot));
 	ExecClearTuple(slot);
-	if (slot->tts_tupleDescriptor)
-		ReleaseTupleDesc(slot->tts_tupleDescriptor);
-	if (!slot->tts_fixedTupleDescriptor)
+	if (slot->tupleDescriptor)
+		ReleaseTupleDesc(slot->tupleDescriptor);
+	if (!(slot->flags & TTS_FIXED))
 	{
-		if (slot->tts_values)
-			pfree(slot->tts_values);
-		if (slot->tts_isnull)
-			pfree(slot->tts_isnull);
+		if (slot->values)
+			pfree(slot->values);
+		if (slot->nulls)
+			pfree(slot->nulls);
 	}
 	pfree(slot);
 }
@@ -281,7 +861,7 @@ void
 ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
 					  TupleDesc tupdesc)	/* new tuple descriptor */
 {
-	Assert(!slot->tts_fixedTupleDescriptor);
+	Assert(!(slot->flags & TTS_FIXED));
 
 	/* For safety, make sure slot is empty before changing it */
 	ExecClearTuple(slot);
@@ -290,28 +870,28 @@ ExecSetSlotDescriptor(TupleTableSlot *slot, /* slot to change */
 	 * Release any old descriptor.  Also release old Datum/isnull arrays if
 	 * present (we don't bother to check if they could be re-used).
 	 */
-	if (slot->tts_tupleDescriptor)
-		ReleaseTupleDesc(slot->tts_tupleDescriptor);
+	if (slot->tupleDescriptor)
+		ReleaseTupleDesc(slot->tupleDescriptor);
 
-	if (slot->tts_values)
-		pfree(slot->tts_values);
-	if (slot->tts_isnull)
-		pfree(slot->tts_isnull);
+	if (slot->values)
+		pfree(slot->values);
+	if (slot->nulls)
+		pfree(slot->nulls);
 
 	/*
 	 * Install the new descriptor; if it's refcounted, bump its refcount.
 	 */
-	slot->tts_tupleDescriptor = tupdesc;
+	slot->tupleDescriptor = tupdesc;
 	PinTupleDesc(tupdesc);
 
 	/*
 	 * Allocate Datum/isnull arrays of the appropriate size.  These must have
 	 * the same lifetime as the slot, so allocate in the slot's own context.
 	 */
-	slot->tts_values = (Datum *)
-		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(Datum));
-	slot->tts_isnull = (bool *)
-		MemoryContextAlloc(slot->tts_mcxt, tupdesc->natts * sizeof(bool));
+	slot->values = (Datum *)
+		MemoryContextAlloc(slot->mcxt, tupdesc->natts * sizeof(Datum));
+	slot->nulls = (bool *)
+		MemoryContextAlloc(slot->mcxt, tupdesc->natts * sizeof(bool));
 }
 
 /* --------------------------------
@@ -363,51 +943,28 @@ ExecStoreTuple(HeapTuple tuple,
 	 */
 	Assert(tuple != NULL);
 	Assert(slot != NULL);
-	Assert(slot->tts_tupleDescriptor != NULL);
+	Assert(slot->tupleDescriptor != NULL);
 	/* passing shouldFree=true for a tuple on a disk page is not sane */
 	Assert(BufferIsValid(buffer) ? (!shouldFree) : true);
 
-	/*
-	 * Free any old physical tuple belonging to the slot.
-	 */
-	if (slot->tts_shouldFree)
-		heap_freetuple(slot->tts_tuple);
-	if (slot->tts_shouldFreeMin)
-		heap_free_minimal_tuple(slot->tts_mintuple);
-
-	/*
-	 * Store the new tuple into the specified slot.
-	 */
-	slot->tts_isempty = false;
-	slot->tts_shouldFree = shouldFree;
-	slot->tts_shouldFreeMin = false;
-	slot->tts_tuple = tuple;
-	slot->tts_mintuple = NULL;
-
-	/* Mark extracted state invalid */
-	slot->tts_nvalid = 0;
-
-	/*
-	 * If tuple is on a disk page, keep the page pinned as long as we hold a
-	 * pointer into it.  We assume the caller already has such a pin.
-	 *
-	 * This is coded to optimize the case where the slot previously held a
-	 * tuple on the same disk page: in that case releasing and re-acquiring
-	 * the pin is a waste of cycles.  This is a common situation during
-	 * seqscans, so it's worth troubling over.
-	 */
-	if (slot->tts_buffer != buffer)
+	if (BufferIsValid(buffer))
 	{
-		if (BufferIsValid(slot->tts_buffer))
-			ReleaseBuffer(slot->tts_buffer);
-		slot->tts_buffer = buffer;
-		if (BufferIsValid(buffer))
-			IncrBufferRefCount(buffer);
+		if (slot->cb != &TTSOpsBufferTuple)
+			elog(ERROR, "trying to store buffer tuple into wrong type of slot");
+		tts_buffer_store_tuple(slot, tuple, buffer);
+	}
+	else
+	{
+		if (slot->cb != &TTSOpsHeapTuple)
+			elog(ERROR, "trying to store heap tuple into wrong type of slot");
+		tts_heap_store_tuple(slot, tuple, shouldFree);
+
 	}
 
 	return slot;
 }
 
+
 /* --------------------------------
  *		ExecStoreMinimalTuple
  *
@@ -426,88 +983,15 @@ ExecStoreMinimalTuple(MinimalTuple mtup,
 	 */
 	Assert(mtup != NULL);
 	Assert(slot != NULL);
-	Assert(slot->tts_tupleDescriptor != NULL);
+	Assert(slot->tupleDescriptor != NULL);
 
-	/*
-	 * Free any old physical tuple belonging to the slot.
-	 */
-	if (slot->tts_shouldFree)
-		heap_freetuple(slot->tts_tuple);
-	if (slot->tts_shouldFreeMin)
-		heap_free_minimal_tuple(slot->tts_mintuple);
-
-	/*
-	 * Drop the pin on the referenced buffer, if there is one.
-	 */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-
-	slot->tts_buffer = InvalidBuffer;
-
-	/*
-	 * Store the new tuple into the specified slot.
-	 */
-	slot->tts_isempty = false;
-	slot->tts_shouldFree = false;
-	slot->tts_shouldFreeMin = shouldFree;
-	slot->tts_tuple = &slot->tts_minhdr;
-	slot->tts_mintuple = mtup;
-
-	slot->tts_minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
-	slot->tts_minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
-	/* no need to set t_self or t_tableOid since we won't allow access */
-
-	/* Mark extracted state invalid */
-	slot->tts_nvalid = 0;
+	if (slot->cb != &TTSOpsMinimalTuple)
+		elog(ERROR, "trying to store minimal tuple into wrong type of slot");
+	tts_minimal_store_tuple(slot, mtup, shouldFree);
 
 	return slot;
 }
 
-/* --------------------------------
- *		ExecClearTuple
- *
- *		This function is used to clear out a slot in the tuple table.
- *
- *		NB: only the tuple is cleared, not the tuple descriptor (if any).
- * --------------------------------
- */
-TupleTableSlot *				/* return: slot passed */
-ExecClearTuple(TupleTableSlot *slot)	/* slot in which to store tuple */
-{
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-
-	/*
-	 * Free the old physical tuple if necessary.
-	 */
-	if (slot->tts_shouldFree)
-		heap_freetuple(slot->tts_tuple);
-	if (slot->tts_shouldFreeMin)
-		heap_free_minimal_tuple(slot->tts_mintuple);
-
-	slot->tts_tuple = NULL;
-	slot->tts_mintuple = NULL;
-	slot->tts_shouldFree = false;
-	slot->tts_shouldFreeMin = false;
-
-	/*
-	 * Drop the pin on the referenced buffer, if there is one.
-	 */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-
-	slot->tts_buffer = InvalidBuffer;
-
-	/*
-	 * Mark it empty.
-	 */
-	slot->tts_isempty = true;
-	slot->tts_nvalid = 0;
-
-	return slot;
-}
 
 /* --------------------------------
  *		ExecStoreVirtualTuple
@@ -527,11 +1011,11 @@ ExecStoreVirtualTuple(TupleTableSlot *slot)
 	 * sanity checks
 	 */
 	Assert(slot != NULL);
-	Assert(slot->tts_tupleDescriptor != NULL);
-	Assert(slot->tts_isempty);
+	Assert(slot->tupleDescriptor != NULL);
+	Assert(slot->flags & TTS_ISEMPTY);
 
-	slot->tts_isempty = false;
-	slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
+	slot->flags &= ~TTS_ISEMPTY;
+	slot->nvalid = slot->tupleDescriptor->natts;
 
 	return slot;
 }
@@ -551,7 +1035,7 @@ ExecStoreAllNullTuple(TupleTableSlot *slot)
 	 * sanity checks
 	 */
 	Assert(slot != NULL);
-	Assert(slot->tts_tupleDescriptor != NULL);
+	Assert(slot->tupleDescriptor != NULL);
 
 	/* Clear any old contents */
 	ExecClearTuple(slot);
@@ -559,82 +1043,14 @@ ExecStoreAllNullTuple(TupleTableSlot *slot)
 	/*
 	 * Fill all the columns of the virtual tuple with nulls
 	 */
-	MemSet(slot->tts_values, 0,
-		   slot->tts_tupleDescriptor->natts * sizeof(Datum));
-	memset(slot->tts_isnull, true,
-		   slot->tts_tupleDescriptor->natts * sizeof(bool));
+	MemSet(slot->values, 0,
+		   slot->tupleDescriptor->natts * sizeof(Datum));
+	memset(slot->nulls, true,
+		   slot->tupleDescriptor->natts * sizeof(bool));
 
 	return ExecStoreVirtualTuple(slot);
 }
 
-/* --------------------------------
- *		ExecCopySlotTuple
- *			Obtain a copy of a slot's regular physical tuple.  The copy is
- *			palloc'd in the current memory context.
- *			The slot itself is undisturbed.
- *
- *		This works even if the slot contains a virtual or minimal tuple;
- *		however the "system columns" of the result will not be meaningful.
- * --------------------------------
- */
-HeapTuple
-ExecCopySlotTuple(TupleTableSlot *slot)
-{
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-	Assert(!slot->tts_isempty);
-
-	/*
-	 * If we have a physical tuple (either format) then just copy it.
-	 */
-	if (TTS_HAS_PHYSICAL_TUPLE(slot))
-		return heap_copytuple(slot->tts_tuple);
-	if (slot->tts_mintuple)
-		return heap_tuple_from_minimal_tuple(slot->tts_mintuple);
-
-	/*
-	 * Otherwise we need to build a tuple from the Datum array.
-	 */
-	return heap_form_tuple(slot->tts_tupleDescriptor,
-						   slot->tts_values,
-						   slot->tts_isnull);
-}
-
-/* --------------------------------
- *		ExecCopySlotMinimalTuple
- *			Obtain a copy of a slot's minimal physical tuple.  The copy is
- *			palloc'd in the current memory context.
- *			The slot itself is undisturbed.
- * --------------------------------
- */
-MinimalTuple
-ExecCopySlotMinimalTuple(TupleTableSlot *slot)
-{
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-	Assert(!slot->tts_isempty);
-
-	/*
-	 * If we have a physical tuple then just copy it.  Prefer to copy
-	 * tts_mintuple since that's a tad cheaper.
-	 */
-	if (slot->tts_mintuple)
-		return heap_copy_minimal_tuple(slot->tts_mintuple);
-	if (slot->tts_tuple)
-		return minimal_tuple_from_heap_tuple(slot->tts_tuple);
-
-	/*
-	 * Otherwise we need to build a tuple from the Datum array.
-	 */
-	return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
-								   slot->tts_values,
-								   slot->tts_isnull);
-}
-
 /* --------------------------------
  *		ExecFetchSlotTuple
  *			Fetch the slot's regular physical tuple.
@@ -657,18 +1073,9 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
 	 * sanity checks
 	 */
 	Assert(slot != NULL);
-	Assert(!slot->tts_isempty);
+	Assert(!(slot->flags & TTS_ISEMPTY));
 
-	/*
-	 * If we have a regular physical tuple then just return it.
-	 */
-	if (TTS_HAS_PHYSICAL_TUPLE(slot))
-		return slot->tts_tuple;
-
-	/*
-	 * Otherwise materialize the slot...
-	 */
-	return ExecMaterializeSlot(slot);
+	return slot->cb->get_heap_tuple(slot);
 }
 
 /* --------------------------------
@@ -687,14 +1094,23 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
 MinimalTuple
 ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
 {
+#ifdef NOT_ANYMORE
 	MemoryContext oldContext;
+#endif
 
 	/*
 	 * sanity checks
 	 */
 	Assert(slot != NULL);
-	Assert(!slot->tts_isempty);
+	Assert(!(slot->flags & TTS_ISEMPTY));
 
+	if (slot->cb == &TTSOpsMinimalTuple)
+		return tts_minimal_get_minimal_tuple(slot);
+	else
+		/* XXX: this'll copy! */
+		return slot->cb->get_minimal_tuple(slot);
+
+#ifdef NOT_ANYMORE
 	/*
 	 * If we have a minimal physical tuple (local or not) then just return it.
 	 */
@@ -721,6 +1137,7 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
 	 */
 
 	return slot->tts_mintuple;
+#endif
 }
 
 /* --------------------------------
@@ -738,85 +1155,12 @@ ExecFetchSlotTupleDatum(TupleTableSlot *slot)
 
 	/* Fetch slot's contents in regular-physical-tuple form */
 	tup = ExecFetchSlotTuple(slot);
-	tupdesc = slot->tts_tupleDescriptor;
+	tupdesc = slot->tupleDescriptor;
 
 	/* Convert to Datum form */
 	return heap_copy_tuple_as_datum(tup, tupdesc);
 }
 
-/* --------------------------------
- *		ExecMaterializeSlot
- *			Force a slot into the "materialized" state.
- *
- *		This causes the slot's tuple to be a local copy not dependent on
- *		any external storage.  A pointer to the contained tuple is returned.
- *
- *		A typical use for this operation is to prepare a computed tuple
- *		for being stored on disk.  The original data may or may not be
- *		virtual, but in any case we need a private copy for heap_insert
- *		to scribble on.
- * --------------------------------
- */
-HeapTuple
-ExecMaterializeSlot(TupleTableSlot *slot)
-{
-	MemoryContext oldContext;
-
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-	Assert(!slot->tts_isempty);
-
-	/*
-	 * If we have a regular physical tuple, and it's locally palloc'd, we have
-	 * nothing to do.
-	 */
-	if (slot->tts_tuple && slot->tts_shouldFree)
-		return slot->tts_tuple;
-
-	/*
-	 * Otherwise, copy or build a physical tuple, and store it into the slot.
-	 *
-	 * We may be called in a context that is shorter-lived than the tuple
-	 * slot, but we have to ensure that the materialized tuple will survive
-	 * anyway.
-	 */
-	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
-	slot->tts_tuple = ExecCopySlotTuple(slot);
-	slot->tts_shouldFree = true;
-	MemoryContextSwitchTo(oldContext);
-
-	/*
-	 * Drop the pin on the referenced buffer, if there is one.
-	 */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-
-	slot->tts_buffer = InvalidBuffer;
-
-	/*
-	 * Mark extracted state invalid.  This is important because the slot is
-	 * not supposed to depend any more on the previous external data; we
-	 * mustn't leave any dangling pass-by-reference datums in tts_values.
-	 * However, we have not actually invalidated any such datums, if there
-	 * happen to be any previously fetched from the slot.  (Note in particular
-	 * that we have not pfree'd tts_mintuple, if there is one.)
-	 */
-	slot->tts_nvalid = 0;
-
-	/*
-	 * On the same principle of not depending on previous remote storage,
-	 * forget the mintuple if it's not local storage.  (If it is local
-	 * storage, we must not pfree it now, since callers might have already
-	 * fetched datum pointers referencing it.)
-	 */
-	if (!slot->tts_shouldFreeMin)
-		slot->tts_mintuple = NULL;
-
-	return slot->tts_tuple;
-}
-
 /* --------------------------------
  *		ExecCopySlot
  *			Copy the source slot's contents into the destination slot.
@@ -830,19 +1174,16 @@ ExecMaterializeSlot(TupleTableSlot *slot)
 TupleTableSlot *
 ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
 {
-	HeapTuple	newTuple;
-	MemoryContext oldContext;
+	int natts = srcslot->tupleDescriptor->natts;
 
-	/*
-	 * There might be ways to optimize this when the source is virtual, but
-	 * for now just always build a physical copy.  Make sure it is in the
-	 * right context.
-	 */
-	oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
-	newTuple = ExecCopySlotTuple(srcslot);
-	MemoryContextSwitchTo(oldContext);
+	ExecClearTuple(dstslot);
+	/* XXX: optimize when tuple based? */
+	slot_getallattrs(srcslot);
+	memcpy(dstslot->values, srcslot->values, sizeof(Datum) * natts);
+	memcpy(dstslot->nulls, srcslot->nulls, sizeof(bool) * natts);
+	ExecStoreVirtualTuple(dstslot);
 
-	return ExecStoreTuple(newTuple, dstslot, InvalidBuffer, true);
+	return dstslot;
 }
 
 
@@ -867,7 +1208,7 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
  * ----------------
  */
 void
-ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
+ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate, TupleTableSlotType st)
 {
 	bool		hasoid;
 	TupleDesc	tupDesc;
@@ -884,7 +1225,8 @@ ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
 
 	tupDesc = ExecTypeFromTL(planstate->plan->targetlist, hasoid);
 
-	planstate->ps_ResultTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable, tupDesc);
+	planstate->ps_ResultTupleSlot =
+		ExecAllocTableSlot(&estate->es_tupleTable, tupDesc, st);
 }
 
 /* ----------------
@@ -892,10 +1234,10 @@ ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
  * ----------------
  */
 void
-ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
+ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc, TupleTableSlotType st)
 {
-	scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
-													 tupledesc);
+	scanstate->ss_ScanTupleSlot =
+		ExecAllocTableSlot(&estate->es_tupleTable, tupledesc, st);
 }
 
 /* ----------------
@@ -907,9 +1249,9 @@ ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
  * ----------------
  */
 TupleTableSlot *
-ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
+ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc, TupleTableSlotType st)
 {
-	return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc);
+	return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc, st);
 }
 
 /* ----------------
@@ -921,9 +1263,9 @@ ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
  * ----------------
  */
 TupleTableSlot *
-ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
+ExecInitNullTupleSlot(EState *estate, TupleDesc tupType, TupleTableSlotType st)
 {
-	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType);
+	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, st);
 
 	return ExecStoreAllNullTuple(slot);
 }
@@ -1094,6 +1436,7 @@ BlessTupleDesc(TupleDesc tupdesc)
 	return tupdesc;				/* just for notational convenience */
 }
 
+#ifdef NOT_ANYMORE
 /*
  * TupleDescGetSlot - Initialize a slot based on the supplied tupledesc
  *
@@ -1115,6 +1458,7 @@ TupleDescGetSlot(TupleDesc tupdesc)
 	/* Return the slot */
 	return slot;
 }
+#endif
 
 /*
  * TupleDescGetAttInMetadata - Build an AttInMetadata structure based on the
@@ -1294,7 +1638,7 @@ begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
 
 	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
 
-	tstate->slot = MakeSingleTupleTableSlot(tupdesc);
+	tstate->slot = MakeSingleTupleTableSlot(tupdesc, TTS_TYPE_VIRTUAL);
 	tstate->dest = dest;
 
 	tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
@@ -1309,14 +1653,14 @@ void
 do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull)
 {
 	TupleTableSlot *slot = tstate->slot;
-	int			natts = slot->tts_tupleDescriptor->natts;
+	int			natts = slot->tupleDescriptor->natts;
 
 	/* make sure the slot is clear */
 	ExecClearTuple(slot);
 
 	/* insert data */
-	memcpy(slot->tts_values, values, natts * sizeof(Datum));
-	memcpy(slot->tts_isnull, isnull, natts * sizeof(bool));
+	memcpy(slot->values, values, natts * sizeof(Datum));
+	memcpy(slot->nulls, isnull, natts * sizeof(bool));
 
 	/* mark slot as containing a virtual tuple */
 	ExecStoreVirtualTuple(slot);
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index a8ae37ebc80..94e9fbf6766 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -436,7 +436,7 @@ ExecGetResultType(PlanState *planstate)
 {
 	TupleTableSlot *slot = planstate->ps_ResultTupleSlot;
 
-	return slot->tts_tupleDescriptor;
+	return slot->tupleDescriptor;
 }
 
 
@@ -590,7 +590,7 @@ ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
  * ----------------
  */
 void
-ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
+ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate, TupleTableSlotType tp)
 {
 	PlanState  *outerPlan;
 	TupleDesc	tupDesc;
@@ -598,7 +598,7 @@ ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
 	outerPlan = outerPlanState(scanstate);
 	tupDesc = ExecGetResultType(outerPlan);
 
-	ExecInitScanTupleSlot(estate, scanstate, tupDesc);
+	ExecInitScanTupleSlot(estate, scanstate, tupDesc, tp);
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 7e249f575f3..7f2763d9b21 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -751,7 +751,7 @@ init_sql_fcache(FmgrInfo *finfo, Oid collation, bool lazyEvalOK)
 	if (fcache->returnsTuple)
 	{
 		/* Make sure output rowtype is properly blessed */
-		BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tts_tupleDescriptor);
+		BlessTupleDesc(fcache->junkFilter->jf_resultSlot->tupleDescriptor);
 	}
 	else if (fcache->returnsSet && type_is_rowtype(fcache->rettype))
 	{
@@ -1667,7 +1667,8 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 
 		/* Set up junk filter if needed */
 		if (junkFilter)
-			*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+			*junkFilter = ExecInitJunkFilter(tlist, false,
+											 MakeSingleTupleTableSlot(NULL, TTS_TYPE_MINIMALTUPLE));
 	}
 	else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
 	{
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 1b1334006fa..05958fb9ffa 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -843,8 +843,8 @@ process_ordered_aggregate_multi(AggState *aggstate,
 			/* Start from 1, since the 0th arg will be the transition value */
 			for (i = 0; i < numTransInputs; i++)
 			{
-				fcinfo->arg[i + 1] = slot1->tts_values[i];
-				fcinfo->argnull[i + 1] = slot1->tts_isnull[i];
+				fcinfo->arg[i + 1] = slot1->values[i];
+				fcinfo->argnull[i + 1] = slot1->nulls[i];
 			}
 
 			advance_transition_function(aggstate, pertrans, pergroupstate);
@@ -1080,7 +1080,7 @@ prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet
 
 		aggstate->grouped_cols = grouped_cols;
 
-		if (slot->tts_isempty)
+		if (slot->flags & TTS_ISEMPTY)
 		{
 			/*
 			 * Force all values to be NULL if working on an empty input tuple
@@ -1101,7 +1101,7 @@ prepare_projection_slot(AggState *aggstate, TupleTableSlot *slot, int currentSet
 				int			attnum = lfirst_int(lc);
 
 				if (!bms_is_member(attnum, grouped_cols))
-					slot->tts_isnull[attnum - 1] = true;
+					slot->nulls[attnum - 1] = true;
 			}
 		}
 	}
@@ -1278,7 +1278,7 @@ build_hash_table(AggState *aggstate)
 		Assert(perhash->aggnode->numGroups > 0);
 
 		perhash->hashtable = BuildTupleHashTable(&aggstate->ss.ps,
-												 perhash->hashslot->tts_tupleDescriptor,
+												 perhash->hashslot->tupleDescriptor,
 												 perhash->numCols,
 												 perhash->hashGrpColIdxHash,
 												 perhash->eqfuncoids,
@@ -1403,7 +1403,8 @@ find_hash_columns(AggState *aggstate)
 							  &perhash->eqfuncoids,
 							  &perhash->hashfunctions);
 		perhash->hashslot =
-			ExecAllocTableSlot(&estate->es_tupleTable, hashDesc);
+			ExecAllocTableSlot(&estate->es_tupleTable, hashDesc,
+							   TTS_TYPE_MINIMALTUPLE);
 
 		list_free(hashTlist);
 		bms_free(colnos);
@@ -1459,8 +1460,8 @@ lookup_hash_entry(AggState *aggstate)
 	{
 		int			varNumber = perhash->hashGrpColIdxInput[i] - 1;
 
-		hashslot->tts_values[i] = inputslot->tts_values[varNumber];
-		hashslot->tts_isnull[i] = inputslot->tts_isnull[varNumber];
+		hashslot->values[i] = inputslot->values[varNumber];
+		hashslot->nulls[i] = inputslot->nulls[varNumber];
 	}
 	ExecStoreVirtualTuple(hashslot);
 
@@ -2030,15 +2031,15 @@ agg_retrieve_hash_table(AggState *aggstate)
 		slot_getallattrs(hashslot);
 
 		ExecClearTuple(firstSlot);
-		memset(firstSlot->tts_isnull, true,
-			   firstSlot->tts_tupleDescriptor->natts * sizeof(bool));
+		memset(firstSlot->nulls, true,
+			   firstSlot->tupleDescriptor->natts * sizeof(bool));
 
 		for (i = 0; i < perhash->numhashGrpCols; i++)
 		{
 			int			varNumber = perhash->hashGrpColIdxInput[i] - 1;
 
-			firstSlot->tts_values[varNumber] = hashslot->tts_values[i];
-			firstSlot->tts_isnull[varNumber] = hashslot->tts_isnull[i];
+			firstSlot->values[varNumber] = hashslot->values[i];
+			firstSlot->nulls[varNumber] = hashslot->nulls[i];
 		}
 		ExecStoreVirtualTuple(firstSlot);
 
@@ -2212,15 +2213,15 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	/*
 	 * initialize source tuple type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss);
-	scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+	ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss, TTS_TYPE_HEAPTUPLE);
+	scanDesc = aggstate->ss.ss_ScanTupleSlot->tupleDescriptor;
 	if (node->chain)
-		aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+		aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc, TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * Initialize result type, slot and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &aggstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &aggstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
 
 	/*
@@ -3063,7 +3064,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 	{
 		pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
 		pertrans->sortslot =
-			ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
+			ExecInitExtraTupleSlot(estate, pertrans->sortdesc,
+								   TTS_TYPE_MINIMALTUPLE);
 	}
 
 	if (numSortCols > 0)
@@ -3085,7 +3087,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		{
 			/* we will need an extra slot to store prior values */
 			pertrans->uniqslot =
-				ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
+				ExecInitExtraTupleSlot(estate, pertrans->sortdesc,
+									   TTS_TYPE_MINIMALTUPLE);
 		}
 
 		/* Extract the sort information for use later */
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 7a3dd2ee2d0..8e10edbb63c 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -131,7 +131,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 	/*
 	 * Initialize result tuple type and slot.
 	 */
-	ExecInitResultTupleSlotTL(estate, &appendstate->ps);
+	ExecInitResultTupleSlotTL(estate, &appendstate->ps, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * call ExecInitNode on each of the plans to be executed and save the
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index 3e1c9e07145..399d67126cb 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -924,13 +924,15 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	 * get the scan type from the relation descriptor.
 	 */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  RelationGetDescr(currentRelation));
+						  RelationGetDescr(currentRelation),
+						  TTS_TYPE_BUFFER);
 
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps,
+							  TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index 218619c760d..35b98a93b1b 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -247,12 +247,13 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
 	 * table) is the same as the result rowtype of the CTE query.
 	 */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  ExecGetResultType(scanstate->cteplanstate));
+						  ExecGetResultType(scanstate->cteplanstate),
+						  TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index b816e0b31db..569a050d8f8 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -73,13 +73,13 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 		TupleDesc	scan_tupdesc;
 
 		scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false);
-		ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc);
+		ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc, TTS_TYPE_VIRTUAL); /* FIXME */
 		/* Node's targetlist will contain Vars with varno = INDEX_VAR */
 		tlistvarno = INDEX_VAR;
 	}
 	else
 	{
-		ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel));
+		ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel), TTS_TYPE_VIRTUAL);
 		/* Node's targetlist will contain Vars with varno = scanrelid */
 		tlistvarno = scanrelid;
 	}
@@ -87,7 +87,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &css->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &css->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
 
 	/* initialize child expressions */
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 0084234b350..7cd8657bfa8 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -180,13 +180,16 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 		TupleDesc	scan_tupdesc;
 
 		scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false);
-		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
+		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
+							  TTS_TYPE_HEAPTUPLE);
 		/* Node's targetlist will contain Vars with varno = INDEX_VAR */
 		tlistvarno = INDEX_VAR;
 	}
 	else
 	{
-		ExecInitScanTupleSlot(estate, &scanstate->ss, RelationGetDescr(currentRelation));
+		ExecInitScanTupleSlot(estate, &scanstate->ss,
+							  RelationGetDescr(currentRelation),
+							  TTS_TYPE_HEAPTUPLE);
 		/* Node's targetlist will contain Vars with varno = scanrelid */
 		tlistvarno = scanrelid;
 	}
@@ -194,7 +197,7 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfoWithVarno(&scanstate->ss, tlistvarno);
 
 	/*
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index fb7c9f67875..be3ed221ac9 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -197,8 +197,8 @@ FunctionNext(FunctionScanState *node)
 			 */
 			for (i = 0; i < fs->colcount; i++)
 			{
-				scanslot->tts_values[att] = (Datum) 0;
-				scanslot->tts_isnull[att] = true;
+				scanslot->values[att] = (Datum) 0;
+				scanslot->nulls[att] = true;
 				att++;
 			}
 		}
@@ -211,8 +211,8 @@ FunctionNext(FunctionScanState *node)
 
 			for (i = 0; i < fs->colcount; i++)
 			{
-				scanslot->tts_values[att] = fs->func_slot->tts_values[i];
-				scanslot->tts_isnull[att] = fs->func_slot->tts_isnull[i];
+				scanslot->values[att] = fs->func_slot->values[i];
+				scanslot->nulls[att] = fs->func_slot->nulls[i];
 				att++;
 			}
 
@@ -229,8 +229,8 @@ FunctionNext(FunctionScanState *node)
 	 */
 	if (node->ordinality)
 	{
-		scanslot->tts_values[att] = Int64GetDatumFast(node->ordinal);
-		scanslot->tts_isnull[att] = false;
+		scanslot->values[att] = Int64GetDatumFast(node->ordinal);
+		scanslot->nulls[att] = false;
 	}
 
 	/*
@@ -424,7 +424,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 		 */
 		if (!scanstate->simple)
 		{
-			fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc);
+			fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc,
+												   TTS_TYPE_VIRTUAL);
 		}
 		else
 			fs->func_slot = NULL;
@@ -482,12 +483,14 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	/*
 	 * Initialize scan slot and type.
 	 */
-	ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
+						  TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps,
+							  TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index eaf7d2d5632..4a19c589a2d 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -94,13 +94,14 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &gatherstate->ps);
+	ExecInitResultTupleSlotTL(estate, &gatherstate->ps, TTS_TYPE_VIRTUAL);
 	ExecConditionalAssignProjectionInfo(&gatherstate->ps, tupDesc, OUTER_VAR);
 
 	/*
 	 * Initialize funnel slot to same tuple descriptor as outer plan.
 	 */
-	gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc);
+	gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc,
+													  TTS_TYPE_HEAPTUPLE);
 
 	/*
 	 * Gather doesn't support checking a qual (it's always more efficient to
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 83221cdbaee..5d71b00cfd9 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -119,7 +119,7 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &gm_state->ps);
+	ExecInitResultTupleSlotTL(estate, &gm_state->ps, TTS_TYPE_VIRTUAL);
 	ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR);
 
 	/*
@@ -403,7 +403,8 @@ gather_merge_setup(GatherMergeState *gm_state)
 
 		/* Initialize tuple slot for worker */
 		gm_state->gm_slots[i + 1] =
-			ExecInitExtraTupleSlot(gm_state->ps.state, gm_state->tupDesc);
+			ExecInitExtraTupleSlot(gm_state->ps.state, gm_state->tupDesc,
+				TTS_TYPE_HEAPTUPLE);
 	}
 
 	/* Allocate the resources for the merge */
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index c6efd64d00d..34b2483a3a2 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -189,12 +189,13 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
 	/*
 	 * Initialize scan slot and type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss,
+									TTS_TYPE_VIRTUAL);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &grpstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &grpstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
 
 	/*
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 06bb44b1631..fa3490be726 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -382,7 +382,7 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
 	 * initialize our result slot and type. No need to build projection
 	 * because this node doesn't do projections.
 	 */
-	ExecInitResultTupleSlotTL(estate, &hashstate->ps);
+	ExecInitResultTupleSlotTL(estate, &hashstate->ps, TTS_TYPE_MINIMALTUPLE);
 	hashstate->ps.ps_ProjInfo = NULL;
 
 	/*
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index ab91eb25273..97f76fc0d29 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -642,13 +642,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &hjstate->js.ps);
+	ExecInitResultTupleSlotTL(estate, &hjstate->js.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
 
 	/*
 	 * tuple table initialization
 	 */
-	hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc);
+	hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc,
+														TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * detect whether we need only consider the first matching inner tuple
@@ -665,17 +666,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 		case JOIN_LEFT:
 		case JOIN_ANTI:
 			hjstate->hj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, TTS_TYPE_VIRTUAL);
 			break;
 		case JOIN_RIGHT:
 			hjstate->hj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, TTS_TYPE_VIRTUAL);
 			break;
 		case JOIN_FULL:
 			hjstate->hj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, TTS_TYPE_VIRTUAL);
 			hjstate->hj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, TTS_TYPE_VIRTUAL);
 			break;
 		default:
 			elog(ERROR, "unrecognized join type: %d",
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index ddc0ae90615..523ff79989f 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -197,7 +197,7 @@ IndexOnlyNext(IndexOnlyScanState *node)
 			 * exactly the slot's format, but it seems worth doing a quick
 			 * check on the number of fields.
 			 */
-			Assert(slot->tts_tupleDescriptor->natts ==
+			Assert(slot->tupleDescriptor->natts ==
 				   scandesc->xs_hitupdesc->natts);
 			ExecStoreTuple(scandesc->xs_hitup, slot, InvalidBuffer, false);
 		}
@@ -268,8 +268,8 @@ static void
 StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, TupleDesc itupdesc)
 {
 	int			nindexatts = itupdesc->natts;
-	Datum	   *values = slot->tts_values;
-	bool	   *isnull = slot->tts_isnull;
+	Datum	   *values = slot->values;
+	bool	   *isnull = slot->nulls;
 	int			i;
 
 	/*
@@ -279,7 +279,7 @@ StoreIndexTuple(TupleTableSlot *slot, IndexTuple itup, TupleDesc itupdesc)
 	 * number of columns though, as well as being datatype-compatible which is
 	 * something we can't so easily check.
 	 */
-	Assert(slot->tts_tupleDescriptor->natts == nindexatts);
+	Assert(slot->tupleDescriptor->natts == nindexatts);
 
 	ExecClearTuple(slot);
 	for (i = 0; i < nindexatts; i++)
@@ -534,14 +534,14 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	 * suitable data anyway.)
 	 */
 	tupDesc = ExecTypeFromTL(node->indextlist, false);
-	ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc);
+	ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc, TTS_TYPE_HEAPTUPLE);
 
 	/*
 	 * Initialize result slot, type and projection info.  The node's
 	 * targetlist will contain Vars with varno = INDEX_VAR, referencing the
 	 * scan tuple.
 	 */
-	ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfoWithVarno(&indexstate->ss, INDEX_VAR);
 
 	/*
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 01c9de88f4d..6ddec9be18a 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -952,12 +952,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	 * get the scan type from the relation descriptor.
 	 */
 	ExecInitScanTupleSlot(estate, &indexstate->ss,
-						  RelationGetDescr(currentRelation));
+						  RelationGetDescr(currentRelation),
+						  TTS_TYPE_BUFFER); /* FIXME: wrong for reorder case */
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &indexstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&indexstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index 56d98b4490b..356ccc64746 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -371,7 +371,8 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
 	 * Initialize result slot and type. (XXX not actually used, but upper
 	 * nodes access it to get this node's result tupledesc...)
 	 */
-	ExecInitResultTupleSlotTL(estate, &limitstate->ps);
+	ExecInitResultTupleSlotTL(estate, &limitstate->ps,
+							  TTS_TYPE_VIRTUAL);
 
 	/*
 	 * limit nodes do no projections, so initialize projection info for this
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index b39ccf7dc13..30d8422e45e 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -378,7 +378,7 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
 	 * Tuple table initialization (XXX not actually used, but upper nodes
 	 * access it to get this node's result tupledesc...)
 	 */
-	ExecInitResultTupleSlotTL(estate, &lrstate->ps);
+	ExecInitResultTupleSlotTL(estate, &lrstate->ps, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * then initialize outer plan
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 8c2e57dbd07..3a106916097 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -223,13 +223,13 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
 	 *
 	 * material nodes only return tuples from their materialized relation.
 	 */
-	ExecInitResultTupleSlotTL(estate, &matstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &matstate->ss.ps, TTS_TYPE_MINIMALTUPLE);
 	matstate->ss.ps.ps_ProjInfo = NULL;
 
 	/*
 	 * initialize tuple type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss, TTS_TYPE_MINIMALTUPLE);
 
 	return matstate;
 }
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index 118f4ef07df..7a708901bba 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -109,7 +109,8 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
 	 * MergeAppend nodes do have Result slots, which hold pointers to tuples,
 	 * so we have to initialize them.
 	 */
-	ExecInitResultTupleSlotTL(estate, &mergestate->ps);
+	/* FIXME: unused? */
+	ExecInitResultTupleSlotTL(estate, &mergestate->ps, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * call ExecInitNode on each of the plans to be executed and save the
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index f3cbe2f889b..fd236e6402b 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -1511,13 +1511,14 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &mergestate->js.ps);
+	ExecInitResultTupleSlotTL(estate, &mergestate->js.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
 
 	/*
 	 * tuple table initialization
 	 */
-	mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc);
+	mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc,
+															TTS_TYPE_VIRTUAL);
 
 	/*
 	 * initialize child expressions
@@ -1547,13 +1548,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 			mergestate->mj_FillOuter = true;
 			mergestate->mj_FillInner = false;
 			mergestate->mj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, TTS_TYPE_VIRTUAL);
 			break;
 		case JOIN_RIGHT:
 			mergestate->mj_FillOuter = false;
 			mergestate->mj_FillInner = true;
 			mergestate->mj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, TTS_TYPE_VIRTUAL);
 
 			/*
 			 * Can't handle right or full join with non-constant extra
@@ -1569,9 +1570,9 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 			mergestate->mj_FillOuter = true;
 			mergestate->mj_FillInner = true;
 			mergestate->mj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, TTS_TYPE_VIRTUAL);
 			mergestate->mj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, TTS_TYPE_VIRTUAL);
 
 			/*
 			 * Can't handle right or full join with non-constant extra
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 93c03cfb071..c1316e80a49 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -766,7 +766,7 @@ ExecDelete(ModifyTableState *mtstate,
 		 * the slot's tupdesc so the FDW doesn't need to do that for itself.
 		 */
 		slot = estate->es_trig_tuple_slot;
-		if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc))
+		if (slot->tupleDescriptor != RelationGetDescr(resultRelationDesc))
 			ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc));
 
 		slot = resultRelInfo->ri_FdwRoutine->ExecForeignDelete(estate,
@@ -781,7 +781,7 @@ ExecDelete(ModifyTableState *mtstate,
 		 * RETURNING expressions might reference the tableoid column, so
 		 * initialize t_tableOid before evaluating them.
 		 */
-		if (slot->tts_isempty)
+		if (slot->flags & TTS_ISEMPTY)
 			ExecStoreAllNullTuple(slot);
 		tuple = ExecMaterializeSlot(slot);
 		tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
@@ -951,7 +951,7 @@ ldelete:;
 					elog(ERROR, "failed to fetch deleted tuple for DELETE RETURNING");
 			}
 
-			if (slot->tts_tupleDescriptor != RelationGetDescr(resultRelationDesc))
+			if (slot->tupleDescriptor != RelationGetDescr(resultRelationDesc))
 				ExecSetSlotDescriptor(slot, RelationGetDescr(resultRelationDesc));
 			ExecStoreTuple(&deltuple, slot, InvalidBuffer, false);
 		}
@@ -1944,6 +1944,13 @@ ExecModifyTable(PlanState *pstate)
 				break;
 		}
 
+		if (node->mt_scan->tupleDescriptor != planSlot->tupleDescriptor)
+			ExecSetSlotDescriptor(node->mt_scan, planSlot->tupleDescriptor);
+
+		ExecStoreTuple(ExecCopySlotTuple(planSlot), node->mt_scan,
+					   InvalidBuffer, true);
+		planSlot = node->mt_scan;
+
 		/*
 		 * If resultRelInfo->ri_usesFdwDirectModify is true, all we need to do
 		 * here is compute the RETURNING expressions.
@@ -2139,6 +2146,8 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 	EvalPlanQualInit(&mtstate->mt_epqstate, estate, NULL, NIL, node->epqParam);
 	mtstate->fireBSTriggers = true;
 
+	mtstate->mt_scan = ExecInitExtraTupleSlot(mtstate->ps.state, NULL, TTS_TYPE_HEAPTUPLE);
+
 	/*
 	 * call ExecInitNode on each of the plans to be executed and save the
 	 * results into the array "mt_plans".  This is also a convenient place to
@@ -2367,7 +2376,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
 
 		/* Set up a slot for the output of the RETURNING projection(s) */
-		ExecInitResultTupleSlotTL(estate, &mtstate->ps);
+		ExecInitResultTupleSlotTL(estate, &mtstate->ps, TTS_TYPE_VIRTUAL);
 		slot = mtstate->ps.ps_ResultTupleSlot;
 
 		/* Need an econtext too */
@@ -2434,7 +2443,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		 * expects one (maybe should change that?).
 		 */
 		mtstate->ps.plan->targetlist = NIL;
-		ExecInitResultTupleSlotTL(estate, &mtstate->ps);
+		ExecInitResultTupleSlotTL(estate, &mtstate->ps, TTS_TYPE_VIRTUAL);
 
 		mtstate->ps.ps_ExprContext = NULL;
 	}
@@ -2462,7 +2471,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 
 		/* initialize slot for the existing tuple */
 		mtstate->mt_existing =
-			ExecInitExtraTupleSlot(mtstate->ps.state, relationDesc);
+			ExecInitExtraTupleSlot(mtstate->ps.state, relationDesc, TTS_TYPE_BUFFER);
 
 		/* carried forward solely for the benefit of explain */
 		mtstate->mt_excludedtlist = node->exclRelTlist;
@@ -2471,7 +2480,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		tupDesc = ExecTypeFromTL((List *) node->onConflictSet,
 								 relationDesc->tdhasoid);
 		mtstate->mt_conflproj =
-			ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc);
+			ExecInitExtraTupleSlot(mtstate->ps.state, tupDesc, TTS_TYPE_VIRTUAL);
 
 		/* build UPDATE SET projection state */
 		resultRelInfo->ri_onConflictSetProj =
@@ -2582,7 +2591,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 
 				j = ExecInitJunkFilter(subplan->targetlist,
 									   resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
-									   ExecInitExtraTupleSlot(estate, NULL));
+									   ExecInitExtraTupleSlot(estate, NULL, TTS_TYPE_HEAPTUPLE));
 
 				if (operation == CMD_UPDATE || operation == CMD_DELETE)
 				{
@@ -2632,7 +2641,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 	 * we keep it in the estate.
 	 */
 	if (estate->es_trig_tuple_slot == NULL)
-		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
+		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL, TTS_TYPE_BUFFER);
 
 	/*
 	 * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
index 4d898b1f83e..9ba4da2f078 100644
--- a/src/backend/executor/nodeNamedtuplestorescan.c
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -136,8 +136,9 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
 	 * Tuple table and result type initialization. The scan tuple type is
 	 * specified for the tuplestore.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
-	ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps, TTS_TYPE_VIRTUAL);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
+						  TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * initialize child expressions
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 9ae9863226c..9864473693b 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -304,7 +304,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &nlstate->js.ps);
+	ExecInitResultTupleSlotTL(estate, &nlstate->js.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
 
 	/*
@@ -332,7 +332,8 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
 		case JOIN_ANTI:
 			nlstate->nl_NullInnerTupleSlot =
 				ExecInitNullTupleSlot(estate,
-									  ExecGetResultType(innerPlanState(nlstate)));
+									  ExecGetResultType(innerPlanState(nlstate)),
+									  TTS_TYPE_VIRTUAL);
 			break;
 		default:
 			elog(ERROR, "unrecognized join type: %d",
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index 6d6ed38ceeb..2afe5abedc9 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -154,8 +154,8 @@ ExecProjectSRF(ProjectSetState *node, bool continuing)
 	{
 		Node	   *elem = node->elems[argno];
 		ExprDoneCond *isdone = &node->elemdone[argno];
-		Datum	   *result = &resultSlot->tts_values[argno];
-		bool	   *isnull = &resultSlot->tts_isnull[argno];
+		Datum	   *result = &resultSlot->values[argno];
+		bool	   *isnull = &resultSlot->nulls[argno];
 
 		if (continuing && *isdone == ExprEndResult)
 		{
@@ -256,7 +256,7 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
 	/*
 	 * tuple table and result type initialization
 	 */
-	ExecInitResultTupleSlotTL(estate, &state->ps);
+	ExecInitResultTupleSlotTL(estate, &state->ps, TTS_TYPE_VIRTUAL);
 
 	/* Create workspace for per-tlist-entry expr state & SRF-is-done state */
 	state->nelems = list_length(node->plan.targetlist);
diff --git a/src/backend/executor/nodeRecursiveunion.c b/src/backend/executor/nodeRecursiveunion.c
index 6b3ea5afb31..3e4273eab5c 100644
--- a/src/backend/executor/nodeRecursiveunion.c
+++ b/src/backend/executor/nodeRecursiveunion.c
@@ -229,7 +229,7 @@ ExecInitRecursiveUnion(RecursiveUnion *node, EState *estate, int eflags)
 	 * RecursiveUnion nodes still have Result slots, which hold pointers to
 	 * tuples, so we have to initialize them.
 	 */
-	ExecInitResultTupleSlotTL(estate, &rustate->ps);
+	ExecInitResultTupleSlotTL(estate, &rustate->ps, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * Initialize result tuple type.  (Note: we have to set up the result type
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index e4418a29bba..b936b4876b8 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -217,7 +217,7 @@ ExecInitResult(Result *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &resstate->ps);
+	ExecInitResultTupleSlotTL(estate, &resstate->ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&resstate->ps, NULL);
 
 	/*
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index 872d6e5735e..de7e976d5af 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -150,13 +150,15 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  RelationGetDescr(scanstate->ss.ss_currentRelation));
+						  RelationGetDescr(scanstate->ss.ss_currentRelation),
+						  TTS_TYPE_BUFFER);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 * tuple table and result tuple initialization
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps,
+							  TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index 9db368922a3..34d356d4463 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -176,12 +176,13 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
 
 	/* and create slot with the appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  RelationGetDescr(scanstate->ss.ss_currentRelation));
+						  RelationGetDescr(scanstate->ss.ss_currentRelation),
+						  TTS_TYPE_BUFFER);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 3fa4a5fcc65..20129f0fa5b 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -533,7 +533,7 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
 	 * Initialize result slot and type. Setop nodes do no projections, so
 	 * initialize projection info for this node appropriately.
 	 */
-	ExecInitResultTupleSlotTL(estate, &setopstate->ps);
+	ExecInitResultTupleSlotTL(estate, &setopstate->ps, TTS_TYPE_VIRTUAL);
 	setopstate->ps.ps_ProjInfo = NULL;
 
 	/*
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index 73f16c9abaa..8b1950d4987 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -211,13 +211,13 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
 	/*
 	 * Initialize scan slot and type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * Initialize return slot and type. No need to initialize projection info because
 	 * this node doesn't do projections.
 	 */
-	ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &sortstate->ss.ps, TTS_TYPE_MINIMALTUPLE);
 	sortstate->ss.ps.ps_ProjInfo = NULL;
 
 	SO1_printf("ExecInitSort: %s\n",
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index d5411500a2b..fef59dbe1a7 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -314,7 +314,7 @@ ExecScanSubPlan(SubPlanState *node,
 		 !TupIsNull(slot);
 		 slot = ExecProcNode(planstate))
 	{
-		TupleDesc	tdesc = slot->tts_tupleDescriptor;
+		TupleDesc	tdesc = slot->tupleDescriptor;
 		Datum		rowresult;
 		bool		rownull;
 		int			col;
@@ -721,7 +721,7 @@ findPartialMatch(TupleHashTable hashtable, TupleTableSlot *slot,
 static bool
 slotAllNulls(TupleTableSlot *slot)
 {
-	int			ncols = slot->tts_tupleDescriptor->natts;
+	int			ncols = slot->tupleDescriptor->natts;
 	int			i;
 
 	for (i = 1; i <= ncols; i++)
@@ -741,7 +741,7 @@ slotAllNulls(TupleTableSlot *slot)
 static bool
 slotNoNulls(TupleTableSlot *slot)
 {
-	int			ncols = slot->tts_tupleDescriptor->natts;
+	int			ncols = slot->tupleDescriptor->natts;
 	int			i;
 
 	for (i = 1; i <= ncols; i++)
@@ -957,7 +957,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 		 * own innerecontext.
 		 */
 		tupDescLeft = ExecTypeFromTL(lefttlist, false);
-		slot = ExecInitExtraTupleSlot(estate, tupDescLeft);
+		slot = ExecInitExtraTupleSlot(estate, tupDescLeft, TTS_TYPE_VIRTUAL);
 		sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
 												   NULL,
 												   slot,
@@ -965,7 +965,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 												   NULL);
 
 		sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false);
-		slot = ExecInitExtraTupleSlot(estate, tupDescRight);
+		slot = ExecInitExtraTupleSlot(estate, tupDescRight, TTS_TYPE_VIRTUAL);
 		sstate->projRight = ExecBuildProjectionInfo(righttlist,
 													sstate->innerecontext,
 													slot,
@@ -1057,7 +1057,7 @@ ExecSetParamPlan(SubPlanState *node, ExprContext *econtext)
 		 !TupIsNull(slot);
 		 slot = ExecProcNode(planstate))
 	{
-		TupleDesc	tdesc = slot->tts_tupleDescriptor;
+		TupleDesc	tdesc = slot->tupleDescriptor;
 		int			i = 1;
 
 		if (subLinkType == EXISTS_SUBLINK)
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index fa618847851..a8e5a8c347c 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -129,12 +129,14 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
 	 * Initialize scan slot and type (needed by ExecInitResultTupleSlotTL)
 	 */
 	ExecInitScanTupleSlot(estate, &subquerystate->ss,
-						  ExecGetResultType(subquerystate->subplan));
+						  ExecGetResultType(subquerystate->subplan),
+						  TTS_TYPE_HEAPTUPLE); /* FIXME */
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &subquerystate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &subquerystate->ss.ps,
+							  TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&subquerystate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index fed6f2b3a53..9f11732b271 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -147,12 +147,14 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
 								 tf->coltypmods,
 								 tf->colcollations);
 	/* and the corresponding scan slot */
-	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc,
+						  TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps,
+							  TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
@@ -285,7 +287,7 @@ tfuncFetchRows(TableFuncScanState *tstate, ExprContext *econtext)
 	PG_TRY();
 	{
 		routine->InitOpaque(tstate,
-							tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor->natts);
+							tstate->ss.ss_ScanTupleSlot->tupleDescriptor->natts);
 
 		/*
 		 * If evaluating the document expression returns NULL, the table
@@ -380,7 +382,7 @@ tfuncInitialize(TableFuncScanState *tstate, ExprContext *econtext, Datum doc)
 	 * is the column filter.
 	 */
 	colno = 0;
-	tupdesc = tstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+	tupdesc = tstate->ss.ss_ScanTupleSlot->tupleDescriptor;
 	foreach(lc1, tstate->colexprs)
 	{
 		char	   *colfilter;
@@ -419,9 +421,9 @@ tfuncLoadRows(TableFuncScanState *tstate, ExprContext *econtext)
 {
 	const TableFuncRoutine *routine = tstate->routine;
 	TupleTableSlot *slot = tstate->ss.ss_ScanTupleSlot;
-	TupleDesc	tupdesc = slot->tts_tupleDescriptor;
-	Datum	   *values = slot->tts_values;
-	bool	   *nulls = slot->tts_isnull;
+	TupleDesc	tupdesc = slot->tupleDescriptor;
+	Datum	   *values = slot->values;
+	bool	   *nulls = slot->nulls;
 	int			natts = tupdesc->natts;
 	MemoryContext oldcxt;
 	int			ordinalitycol;
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index e207b1ffb51..d125611571d 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -549,12 +549,13 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	 * get the scan type from the relation descriptor.
 	 */
 	ExecInitScanTupleSlot(estate, &tidstate->ss,
-						  RelationGetDescr(currentRelation));
+						  RelationGetDescr(currentRelation),
+						  TTS_TYPE_BUFFER);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &tidstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &tidstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&tidstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index 05d65330a0e..6cff86f9091 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -141,7 +141,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
 	 * Initialize result slot and type. Unique nodes do no projections, so
 	 * initialize projection info for this node appropriately.
 	 */
-	ExecInitResultTupleSlotTL(estate, &uniquestate->ps);
+	ExecInitResultTupleSlotTL(estate, &uniquestate->ps, TTS_TYPE_VIRTUAL);
 	uniquestate->ps.ps_ProjInfo = NULL;
 
 	/*
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index 63b7e7ef5b8..cb0d9643a79 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -133,20 +133,20 @@ ValuesNext(ValuesScanState *node)
 		node->ss.ps.subPlan = oldsubplans;
 
 		/* parser should have checked all sublists are the same length */
-		Assert(list_length(exprstatelist) == slot->tts_tupleDescriptor->natts);
+		Assert(list_length(exprstatelist) == slot->tupleDescriptor->natts);
 
 		/*
 		 * Compute the expressions and build a virtual result tuple. We
 		 * already did ExecClearTuple(slot).
 		 */
-		values = slot->tts_values;
-		isnull = slot->tts_isnull;
+		values = slot->values;
+		isnull = slot->nulls;
 
 		resind = 0;
 		foreach(lc, exprstatelist)
 		{
 			ExprState  *estate = (ExprState *) lfirst(lc);
-			Form_pg_attribute attr = TupleDescAttr(slot->tts_tupleDescriptor,
+			Form_pg_attribute attr = TupleDescAttr(slot->tupleDescriptor,
 												   resind);
 
 			values[resind] = ExecEvalExpr(estate,
@@ -251,12 +251,12 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 	 * Get info about values list, initialize scan slot with it.
 	 */
 	tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
-	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, TTS_TYPE_VIRTUAL);
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignScanProjectionInfo(&scanstate->ss);
 
 	/*
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index a56c3e89fd5..8768d8c6955 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2304,16 +2304,20 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	 * initialize source tuple type (which is also the tuple type that we'll
 	 * store in the tuplestore and use in all our working slots).
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &winstate->ss);
-	scanDesc = winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
+	ExecCreateScanSlotFromOuterPlan(estate, &winstate->ss, TTS_TYPE_MINIMALTUPLE);
+	scanDesc = winstate->ss.ss_ScanTupleSlot->tupleDescriptor;
 
 	/*
 	 * tuple table initialization
 	 */
-	winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc);
-	winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc);
-	winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc);
-	winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc);
+	winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+													   TTS_TYPE_VIRTUAL);
+	winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+													TTS_TYPE_VIRTUAL);
+	winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc,
+												   TTS_TYPE_VIRTUAL);
+	winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc,
+												   TTS_TYPE_VIRTUAL);
 
 	/*
 	 * create frame head and tail slots only if needed (must match logic in
@@ -2324,15 +2328,17 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	if (frameOptions & (FRAMEOPTION_RANGE | FRAMEOPTION_GROUPS))
 	{
 		if (!(frameOptions & FRAMEOPTION_START_UNBOUNDED_PRECEDING))
-			winstate->framehead_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+			winstate->framehead_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+															  TTS_TYPE_VIRTUAL);
 		if (!(frameOptions & FRAMEOPTION_END_UNBOUNDED_FOLLOWING))
-			winstate->frametail_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+			winstate->frametail_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+															  TTS_TYPE_VIRTUAL);
 	}
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(estate, &winstate->ss.ps);
+	ExecInitResultTupleSlotTL(estate, &winstate->ss.ps, TTS_TYPE_VIRTUAL);
 	ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
 
 	/* Set up data for comparing tuples */
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index 2ff9a215b12..76a1aad4aa7 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -159,8 +159,8 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
 	/*
 	 * tuple table initialization
 	 */
-	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps);
-	ExecInitScanTupleSlot(estate, &scanstate->ss, NULL);
+	ExecInitResultTupleSlotTL(estate, &scanstate->ss.ps, TTS_TYPE_VIRTUAL);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, NULL, TTS_TYPE_MINIMALTUPLE);
 
 	/*
 	 * initialize child expressions
diff --git a/src/backend/executor/tstoreReceiver.c b/src/backend/executor/tstoreReceiver.c
index d02ca3afd12..a0ec3dcb404 100644
--- a/src/backend/executor/tstoreReceiver.c
+++ b/src/backend/executor/tstoreReceiver.c
@@ -109,7 +109,7 @@ static bool
 tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
 {
 	TStoreState *myState = (TStoreState *) self;
-	TupleDesc	typeinfo = slot->tts_tupleDescriptor;
+	TupleDesc	typeinfo = slot->tupleDescriptor;
 	int			natts = typeinfo->natts;
 	int			nfree;
 	int			i;
@@ -126,10 +126,10 @@ tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
 	nfree = 0;
 	for (i = 0; i < natts; i++)
 	{
-		Datum		val = slot->tts_values[i];
+		Datum		val = slot->values[i];
 		Form_pg_attribute attr = TupleDescAttr(typeinfo, i);
 
-		if (!attr->attisdropped && attr->attlen == -1 && !slot->tts_isnull[i])
+		if (!attr->attisdropped && attr->attlen == -1 && !slot->nulls[i])
 		{
 			if (VARATT_IS_EXTERNAL(DatumGetPointer(val)))
 			{
@@ -147,7 +147,7 @@ tstoreReceiveSlot_detoast(TupleTableSlot *slot, DestReceiver *self)
 	 */
 	oldcxt = MemoryContextSwitchTo(myState->cxt);
 	tuplestore_putvalues(myState->tstore, typeinfo,
-						 myState->outvalues, slot->tts_isnull);
+						 myState->outvalues, slot->nulls);
 	MemoryContextSwitchTo(oldcxt);
 
 	/* And release any temporary detoasted values */
diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c
index b9bad5eacca..6b69ea8b5f3 100644
--- a/src/backend/nodes/print.c
+++ b/src/backend/nodes/print.c
@@ -492,7 +492,7 @@ print_slot(TupleTableSlot *slot)
 		printf("tuple is null.\n");
 		return;
 	}
-	if (!slot->tts_tupleDescriptor)
+	if (!slot->tupleDescriptor)
 	{
 		printf("no tuple descriptor.\n");
 		return;
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index e50b9f79056..495d91d555d 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -685,7 +685,7 @@ fetch_remote_table_info(char *nspname, char *relname,
 				(errmsg("could not fetch table info for table \"%s.%s\" from publisher: %s",
 						nspname, relname, res->err)));
 
-	slot = MakeSingleTupleTableSlot(res->tupledesc);
+	slot = MakeSingleTupleTableSlot(res->tupledesc, TTS_TYPE_MINIMALTUPLE);
 	if (!tuplestore_gettupleslot(res->tuplestore, true, false, slot))
 		ereport(ERROR,
 				(errmsg("table \"%s.%s\" not found on publisher",
@@ -727,7 +727,7 @@ fetch_remote_table_info(char *nspname, char *relname,
 	lrel->attkeys = NULL;
 
 	natt = 0;
-	slot = MakeSingleTupleTableSlot(res->tupledesc);
+	slot = MakeSingleTupleTableSlot(res->tupledesc, TTS_TYPE_MINIMALTUPLE);
 	while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
 	{
 		lrel->attnames[natt] =
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 04985c9f91d..ee9adf74c31 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -208,7 +208,8 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
 
 	/* Triggers might need a slot */
 	if (resultRelInfo->ri_TrigDesc)
-		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
+		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
+															TTS_TYPE_VIRTUAL);
 
 	/* Prepare to catch AFTER triggers. */
 	AfterTriggerBeginQuery();
@@ -271,8 +272,8 @@ slot_fill_defaults(LogicalRepRelMapEntry *rel, EState *estate,
 	}
 
 	for (i = 0; i < num_defaults; i++)
-		slot->tts_values[defmap[i]] =
-			ExecEvalExpr(defexprs[i], econtext, &slot->tts_isnull[defmap[i]]);
+		slot->values[defmap[i]] =
+			ExecEvalExpr(defexprs[i], econtext, &slot->nulls[defmap[i]]);
 }
 
 /*
@@ -307,7 +308,7 @@ static void
 slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 					char **values)
 {
-	int			natts = slot->tts_tupleDescriptor->natts;
+	int			natts = slot->tupleDescriptor->natts;
 	int			i;
 	SlotErrCallbackArg errarg;
 	ErrorContextCallback errcallback;
@@ -325,7 +326,7 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 	/* Call the "in" function for each non-dropped attribute */
 	for (i = 0; i < natts; i++)
 	{
-		Form_pg_attribute att = TupleDescAttr(slot->tts_tupleDescriptor, i);
+		Form_pg_attribute att = TupleDescAttr(slot->tupleDescriptor, i);
 		int			remoteattnum = rel->attrmap[i];
 
 		if (!att->attisdropped && remoteattnum >= 0 &&
@@ -337,11 +338,11 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 			errarg.attnum = remoteattnum;
 
 			getTypeInputInfo(att->atttypid, &typinput, &typioparam);
-			slot->tts_values[i] = OidInputFunctionCall(typinput,
-													   values[remoteattnum],
-													   typioparam,
-													   att->atttypmod);
-			slot->tts_isnull[i] = false;
+			slot->values[i] = OidInputFunctionCall(typinput,
+												   values[remoteattnum],
+												   typioparam,
+												   att->atttypmod);
+			slot->nulls[i] = false;
 		}
 		else
 		{
@@ -350,8 +351,8 @@ slot_store_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 			 * values (missing values should be later filled using
 			 * slot_fill_defaults).
 			 */
-			slot->tts_values[i] = (Datum) 0;
-			slot->tts_isnull[i] = true;
+			slot->values[i] = (Datum) 0;
+			slot->nulls[i] = true;
 		}
 	}
 
@@ -371,7 +372,7 @@ static void
 slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 					 char **values, bool *replaces)
 {
-	int			natts = slot->tts_tupleDescriptor->natts;
+	int			natts = slot->tupleDescriptor->natts;
 	int			i;
 	SlotErrCallbackArg errarg;
 	ErrorContextCallback errcallback;
@@ -390,7 +391,7 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 	/* Call the "in" function for each replaced attribute */
 	for (i = 0; i < natts; i++)
 	{
-		Form_pg_attribute att = TupleDescAttr(slot->tts_tupleDescriptor, i);
+		Form_pg_attribute att = TupleDescAttr(slot->tupleDescriptor, i);
 		int			remoteattnum = rel->attrmap[i];
 
 		if (remoteattnum < 0)
@@ -407,16 +408,16 @@ slot_modify_cstrings(TupleTableSlot *slot, LogicalRepRelMapEntry *rel,
 			errarg.attnum = remoteattnum;
 
 			getTypeInputInfo(att->atttypid, &typinput, &typioparam);
-			slot->tts_values[i] = OidInputFunctionCall(typinput,
-													   values[remoteattnum],
-													   typioparam,
-													   att->atttypmod);
-			slot->tts_isnull[i] = false;
+			slot->values[i] = OidInputFunctionCall(typinput,
+												   values[remoteattnum],
+												   typioparam,
+												   att->atttypmod);
+			slot->nulls[i] = false;
 		}
 		else
 		{
-			slot->tts_values[i] = (Datum) 0;
-			slot->tts_isnull[i] = true;
+			slot->values[i] = (Datum) 0;
+			slot->nulls[i] = true;
 		}
 	}
 
@@ -586,7 +587,8 @@ apply_handle_insert(StringInfo s)
 	/* Initialize the executor state. */
 	estate = create_estate_for_relation(rel);
 	remoteslot = ExecInitExtraTupleSlot(estate,
-										RelationGetDescr(rel->localrel));
+										RelationGetDescr(rel->localrel),
+										TTS_TYPE_VIRTUAL);
 
 	/* Process and store remote tuple in the slot */
 	oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
@@ -690,9 +692,11 @@ apply_handle_update(StringInfo s)
 	/* Initialize the executor state. */
 	estate = create_estate_for_relation(rel);
 	remoteslot = ExecInitExtraTupleSlot(estate,
-										RelationGetDescr(rel->localrel));
+										RelationGetDescr(rel->localrel),
+										TTS_TYPE_VIRTUAL);
 	localslot = ExecInitExtraTupleSlot(estate,
-									   RelationGetDescr(rel->localrel));
+									   RelationGetDescr(rel->localrel),
+									   TTS_TYPE_HEAPTUPLE);
 	EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
 
 	PushActiveSnapshot(GetTransactionSnapshot());
@@ -731,7 +735,7 @@ apply_handle_update(StringInfo s)
 	{
 		/* Process and store remote tuple in the slot */
 		oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
-		ExecStoreTuple(localslot->tts_tuple, remoteslot, InvalidBuffer, false);
+		ExecCopySlot(localslot, remoteslot);
 		slot_modify_cstrings(remoteslot, rel, newtup.values, newtup.changed);
 		MemoryContextSwitchTo(oldctx);
 
@@ -808,9 +812,11 @@ apply_handle_delete(StringInfo s)
 	/* Initialize the executor state. */
 	estate = create_estate_for_relation(rel);
 	remoteslot = ExecInitExtraTupleSlot(estate,
-										RelationGetDescr(rel->localrel));
+										RelationGetDescr(rel->localrel),
+										TTS_TYPE_VIRTUAL);
 	localslot = ExecInitExtraTupleSlot(estate,
-									   RelationGetDescr(rel->localrel));
+									   RelationGetDescr(rel->localrel),
+									   TTS_TYPE_HEAPTUPLE);
 	EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
 
 	PushActiveSnapshot(GetTransactionSnapshot());
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 66cc5c35c68..8b803c77d5b 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -1071,7 +1071,7 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count,
 	uint64		current_tuple_count = 0;
 	TupleTableSlot *slot;
 
-	slot = MakeSingleTupleTableSlot(portal->tupDesc);
+	slot = MakeSingleTupleTableSlot(portal->tupDesc, TTS_TYPE_MINIMALTUPLE);
 
 	dest->rStartup(dest, CMD_SELECT, portal->tupDesc);
 
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index 50b34fcbc68..e833ed1f852 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -240,7 +240,8 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 			}
 
 			/* Create slot we'll use to store/retrieve rows */
-			qstate->tupslot = MakeSingleTupleTableSlot(qstate->tupdesc);
+			qstate->tupslot = MakeSingleTupleTableSlot(qstate->tupdesc,
+													   TTS_TYPE_VIRTUAL);
 		}
 		else
 		{
@@ -398,17 +399,17 @@ ordered_set_transition_multi(PG_FUNCTION_ARGS)
 	nargs = PG_NARGS() - 1;
 	for (i = 0; i < nargs; i++)
 	{
-		slot->tts_values[i] = PG_GETARG_DATUM(i + 1);
-		slot->tts_isnull[i] = PG_ARGISNULL(i + 1);
+		slot->values[i] = PG_GETARG_DATUM(i + 1);
+		slot->nulls[i] = PG_ARGISNULL(i + 1);
 	}
 	if (osastate->qstate->aggref->aggkind == AGGKIND_HYPOTHETICAL)
 	{
 		/* Add a zero flag value to mark this row as a normal input row */
-		slot->tts_values[i] = Int32GetDatum(0);
-		slot->tts_isnull[i] = false;
+		slot->values[i] = Int32GetDatum(0);
+		slot->nulls[i] = false;
 		i++;
 	}
-	Assert(i == slot->tts_tupleDescriptor->natts);
+	Assert(i == slot->tupleDescriptor->natts);
 	ExecStoreVirtualTuple(slot);
 
 	/* Load the row into the tuplesort object */
@@ -1200,11 +1201,11 @@ hypothetical_rank_common(FunctionCallInfo fcinfo, int flag,
 	ExecClearTuple(slot);
 	for (i = 0; i < nargs; i++)
 	{
-		slot->tts_values[i] = PG_GETARG_DATUM(i + 1);
-		slot->tts_isnull[i] = PG_ARGISNULL(i + 1);
+		slot->values[i] = PG_GETARG_DATUM(i + 1);
+		slot->nulls[i] = PG_ARGISNULL(i + 1);
 	}
-	slot->tts_values[i] = Int32GetDatum(flag);
-	slot->tts_isnull[i] = false;
+	slot->values[i] = Int32GetDatum(flag);
+	slot->nulls[i] = false;
 	ExecStoreVirtualTuple(slot);
 
 	tuplesort_puttupleslot(osastate->sortstate, slot);
@@ -1353,11 +1354,11 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
 	ExecClearTuple(slot);
 	for (i = 0; i < nargs; i++)
 	{
-		slot->tts_values[i] = PG_GETARG_DATUM(i + 1);
-		slot->tts_isnull[i] = PG_ARGISNULL(i + 1);
+		slot->values[i] = PG_GETARG_DATUM(i + 1);
+		slot->nulls[i] = PG_ARGISNULL(i + 1);
 	}
-	slot->tts_values[i] = Int32GetDatum(-1);
-	slot->tts_isnull[i] = false;
+	slot->values[i] = Int32GetDatum(-1);
+	slot->nulls[i] = false;
 	ExecStoreVirtualTuple(slot);
 
 	tuplesort_puttupleslot(osastate->sortstate, slot);
@@ -1371,9 +1372,10 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
 	 * previous row available for comparisons.  This is accomplished by
 	 * swapping the slot pointer variables after each row.
 	 */
-	extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc);
+	extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc,
+										 TTS_TYPE_MINIMALTUPLE);
 	slot2 = extraslot;
-
+	/* FIXME: will store minimal into virtual slot! */
 	/* iterate till we find the hypothetical row */
 	while (tuplesort_gettupleslot(osastate->sortstate, true, true, slot,
 								  &abbrevVal))
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index fcc8323f626..69d5622ed07 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5504,7 +5504,8 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
 			indexInfo = BuildIndexInfo(indexRel);
 
 			/* some other stuff */
-			slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel));
+			slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel),
+											TTS_TYPE_HEAPTUPLE);
 			econtext->ecxt_scantuple = slot;
 			get_typlenbyval(vardata->atttype, &typLen, &typByVal);
 			InitNonVacuumableSnapshot(SnapshotNonVacuumable, RecentGlobalXmin);
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 041bdc2fa7e..ef2669c603b 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -933,7 +933,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
 		 * scantuple has to point to that slot, too.
 		 */
 		state->estate = CreateExecutorState();
-		slot = MakeSingleTupleTableSlot(tupDesc);
+		slot = MakeSingleTupleTableSlot(tupDesc, TTS_TYPE_VIRTUAL);
 		econtext = GetPerTupleExprContext(state->estate);
 		econtext->ecxt_scantuple = slot;
 	}
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index 2ab1815390c..5bcdca99601 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -826,4 +826,9 @@ extern MinimalTuple heap_copy_minimal_tuple(MinimalTuple mtup);
 extern HeapTuple heap_tuple_from_minimal_tuple(MinimalTuple mtup);
 extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
 
+struct TupleTableSlot;
+extern void
+slot_deform_tuple(struct TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts);
+
+
 #endif							/* HTUP_DETAILS_H */
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 45a077a949c..430e3ec6b27 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -342,8 +342,9 @@ ExecProject(ProjectionInfo *projInfo)
 	 * Successfully formed a result row.  Mark the result slot as containing a
 	 * valid virtual tuple (inlined version of ExecStoreVirtualTuple()).
 	 */
-	slot->tts_isempty = false;
-	slot->tts_nvalid = slot->tts_tupleDescriptor->natts;
+	//FIXME: slot->isempty = false;
+	slot->flags &= ~TTS_ISEMPTY;
+	slot->nvalid = slot->tupleDescriptor->natts;
 
 	return slot;
 }
@@ -431,12 +432,12 @@ extern void ExecScanReScan(ScanState *node);
 /*
  * prototypes from functions in execTuples.c
  */
-extern void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate);
-extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc);
+extern void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate, TupleTableSlotType st);
+extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc, TupleTableSlotType st);
 extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
-					  TupleDesc tupleDesc);
+					  TupleDesc tupleDesc, TupleTableSlotType st);
 extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
-					  TupleDesc tupType);
+					  TupleDesc tupType, TupleTableSlotType st);
 extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
 extern TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid);
 extern TupleDesc ExecTypeFromExprList(List *exprList);
@@ -510,7 +511,8 @@ extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
 									TupleDesc inputDesc, Index varno);
 extern void ExecFreeExprContext(PlanState *planstate);
 extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
-extern void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate);
+extern void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate,
+											TupleTableSlotType tp);
 
 extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
 
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 8be0d5edc29..beeb630a4c1 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -110,42 +110,111 @@
  * be touched by any other code.
  *----------
  */
-typedef struct TupleTableSlot
+
+/* true = slot is empty */
+#define			TTS_ISEMPTY			(1 << 1)
+/* should pfree tts_tuple? */
+#define			TTS_SHOULDFREE		(1 << 2)
+/* should pfree tts_mintuple? */
+#define			TTS_SHOULDFREEMIN	(1 << 3)
+/* saved state for slot_deform_tuple */
+#define			TTS_SLOW			(1 << 4)
+/* fixed tuple descriptor */
+#define			TTS_FIXED			(1 << 5)
+
+
+typedef enum TupleTableSlotType
+{
+	TTS_TYPE_VIRTUAL,
+	TTS_TYPE_HEAPTUPLE,
+	TTS_TYPE_MINIMALTUPLE,
+	TTS_TYPE_BUFFER
+} TupleTableSlotType;
+
+struct TupleTableSlot;
+typedef struct TupleTableSlot TupleTableSlot;
+
+typedef struct TupleTableSlotOps
+{
+	void (*init)(TupleTableSlot *slot);
+	void (*release)(TupleTableSlot *slot);
+
+	void (*clear)(TupleTableSlot *slot);
+
+	void (*getsomeattrs)(TupleTableSlot *slot, int natts);
+
+	void (*materialize)(TupleTableSlot *slot);
+
+	HeapTuple (*get_heap_tuple)(TupleTableSlot *slot);
+	MinimalTuple (*get_minimal_tuple)(TupleTableSlot *slot);
+
+	HeapTuple (*copy_heap_tuple)(TupleTableSlot *slot);
+	MinimalTuple (*copy_minimal_tuple)(TupleTableSlot *slot);
+
+} TupleTableSlotOps;
+
+extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);
+
+extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
+			 TupleTableSlot *srcslot);
+
+/* virtual or base type */
+struct TupleTableSlot
 {
 	NodeTag		type;
-	bool		tts_isempty;	/* true = slot is empty */
-	bool		tts_shouldFree; /* should pfree tts_tuple? */
-	bool		tts_shouldFreeMin;	/* should pfree tts_mintuple? */
-	bool		tts_slow;		/* saved state for slot_deform_tuple */
-	HeapTuple	tts_tuple;		/* physical tuple, or NULL if virtual */
-	TupleDesc	tts_tupleDescriptor;	/* slot's tuple descriptor */
-	MemoryContext tts_mcxt;		/* slot itself is in this context */
-	Buffer		tts_buffer;		/* tuple's buffer, or InvalidBuffer */
-	int			tts_nvalid;		/* # of valid values in tts_values */
-	Datum	   *tts_values;		/* current per-attribute values */
-	bool	   *tts_isnull;		/* current per-attribute isnull flags */
-	MinimalTuple tts_mintuple;	/* minimal tuple, or NULL if none */
-	HeapTupleData tts_minhdr;	/* workspace for minimal-tuple-only case */
-	long		tts_off;		/* saved state for slot_deform_tuple */
-	bool		tts_fixedTupleDescriptor; /* descriptor can't be changed */
-} TupleTableSlot;
 
-#define TTS_HAS_PHYSICAL_TUPLE(slot)  \
-	((slot)->tts_tuple != NULL && (slot)->tts_tuple != &((slot)->tts_minhdr))
+	uint16		flags;
+	uint16		nvalid;		/* # of valid values in tts_values */
+
+	const TupleTableSlotOps *const cb;
+
+	TupleDesc	tupleDescriptor;	/* slot's tuple descriptor */
+
+	Datum	   *values;		/* current per-attribute values */
+	bool	   *nulls;		/* current per-attribute null flags */
+
+	/* can we optimize away? */
+	MemoryContext mcxt;		/* slot itself is in this context */
+};
+
+
+typedef struct HeapTupleTableSlot
+{
+	TupleTableSlot base;
+	HeapTuple	tuple;		/* physical tuple */
+	uint32		off;		/* saved state for slot_deform_tuple */
+} HeapTupleTableSlot;
+
+/* heap tuple residing in a buffer */
+typedef struct BufferHeapTupleTableSlot
+{
+	HeapTupleTableSlot base;
+	Buffer		buffer;		/* tuple's buffer, or InvalidBuffer */
+} BufferHeapTupleTableSlot;
+
+typedef struct MinimalTupleTableSlot
+{
+	TupleTableSlot base;
+	HeapTuple	tuple;		/* tuple wrapper */
+	MinimalTuple mintuple;	/* minimal tuple, or NULL if none */
+	HeapTupleData minhdr;	/* workspace for minimal-tuple-only case */
+	uint32		off;		/* saved state for slot_deform_tuple */
+} MinimalTupleTableSlot;
 
 /*
  * TupIsNull -- is a TupleTableSlot empty?
  */
 #define TupIsNull(slot) \
-	((slot) == NULL || (slot)->tts_isempty)
+	((slot) == NULL || (slot)->flags & TTS_ISEMPTY)
 
 /* in executor/execTuples.c */
-extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc);
-extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc);
+extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc, TupleTableSlotType st);
+extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc, TupleTableSlotType st);
 extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
-extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
+extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc, TupleTableSlotType st);
 extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
 extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
+
 extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
 			   TupleTableSlot *slot,
 			   Buffer buffer,
@@ -153,22 +222,95 @@ extern TupleTableSlot *ExecStoreTuple(HeapTuple tuple,
 extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
 					  TupleTableSlot *slot,
 					  bool shouldFree);
-extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
+
 extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
 extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
-extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot);
-extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot);
+
 extern HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot);
 extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot);
 extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);
-extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot);
+
 extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
 			 TupleTableSlot *srcslot);
 
+
+static inline TupleTableSlot *
+ExecClearTuple(TupleTableSlot *slot)
+{
+	slot->cb->clear(slot);
+	return slot;
+}
+
+static inline HeapTuple
+ExecMaterializeSlot(TupleTableSlot *slot)
+{
+	slot->cb->materialize(slot);
+	return slot->cb->get_heap_tuple(slot);
+}
+
+static inline HeapTuple
+ExecCopySlotTuple(TupleTableSlot *slot)
+{
+	/*
+	 * sanity checks
+	 */
+	Assert(slot != NULL);
+	Assert(!(slot->flags & TTS_ISEMPTY));
+	return slot->cb->copy_heap_tuple(slot);
+}
+
+static inline MinimalTuple
+ExecCopySlotMinimalTuple(TupleTableSlot *slot)
+{
+	return slot->cb->copy_minimal_tuple(slot);
+}
+
 /* in access/common/heaptuple.c */
-extern Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull);
-extern void slot_getallattrs(TupleTableSlot *slot);
-extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
-extern bool slot_attisnull(TupleTableSlot *slot, int attnum);
+
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+	Assert(attnum > 0);
+
+	if (attnum > slot->nvalid)
+		slot->cb->getsomeattrs(slot, attnum);
+
+	Assert(attnum <= slot->nvalid);
+
+	*isnull = slot->nulls[attnum - 1];
+	return slot->values[attnum - 1];
+}
+
+static inline void
+slot_getallattrs(TupleTableSlot *slot)
+{
+	int			tdesc_natts = slot->tupleDescriptor->natts;
+
+	/* Quick out if we have 'em all already */
+	if (slot->nvalid == tdesc_natts)
+		return;
+	slot->cb->getsomeattrs(slot, tdesc_natts);
+}
+
+
+static inline void
+slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+{
+	/* FIXME: we're sometimes called with attnum == 0 which is wrong */
+	Assert(attnum >= 0);
+
+	if (attnum > slot->nvalid)
+		slot->cb->getsomeattrs(slot, attnum);
+}
+
+static inline bool
+slot_attisnull(TupleTableSlot *slot, int attnum)
+{
+	bool isnull;
+
+	slot_getattr(slot, attnum, &isnull);
+
+	return isnull;
+}
 
 #endif							/* TUPTABLE_H */
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index a953820f43a..d7c54057ae5 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -992,6 +992,9 @@ typedef struct ModifyTableState
 	OnConflictAction mt_onconflict; /* ON CONFLICT type */
 	List	   *mt_arbiterindexes;	/* unique index OIDs to arbitrate taking
 									 * alt path */
+
+	TupleTableSlot *mt_scan;	/* input */
+
 	TupleTableSlot *mt_existing;	/* slot to store existing target tuple in */
 	List	   *mt_excludedtlist;	/* the excluded pseudo relation's tlist  */
 	TupleTableSlot *mt_conflproj;	/* CONFLICT ... SET ... projection target */
-- 
2.15.1.354.g95ec6b1b33.dirty

#2Alexander Korotkov
a.korotkov@postgrespro.ru
In reply to: Andres Freund (#1)
Re: TupleTableSlot abstraction

Hi!

Thank you for working on this subject. See some my comments below.

On Wed, Feb 21, 2018 at 1:43 AM, Andres Freund <andres@anarazel.de> wrote:

- TupleTableSlots have to contain all the necessary information for each
type of slot. Some implementations might require a buffer pin to be
hold (our heap), others pointers to multiple underlying points of data
(columns store), some need additional metadata (our MinimalTuple).

Unifying the information into one struct makes it much harder to
provide differing implementations without modifying core postgres
and/or increasing overhead for every user of slots.

I think the consequence of that is that we need to allow each type of
slot to have their own TupleTableSlot embedding struct.

+1, I think that it's reasonable to keep minimal common slot information in
TupleTableSlot struct and to let particular slot implementations to extend
it.

Haribabu's patch solved this by adding a tts_storage parameter that

contains additional data, but imo that's unconvincing due to the added
indirection in very performance critical codepaths.

+1

- The way slots currently are implemented each new variant data is

stored in slots adds new branches to hot code paths like
ExecClearTuple(), and they're not extensible.

Therefore I think we need to move to callback based implementation. In
my tests, by moving the callback invocations into very thin inline
functions, the branch prediction accuracy actually goes sligthly
*up*.

Sounds interesting. Besides branch prediction accuracy, what can you
say about overall performance?

- Currently we frequently convert from one way of representing a row

into another, in the same slot. We do so fairly implicilty in
ExecMaterializeSlot(), ExecFetchSlotMinimalTuple(), ExecCopySlot()...

The more we abstract specific storage representation away, the worse I
think that is. I think we should make such conversions explicit by
requiring transfers between two slots if a specific type is required.

- We have a few codepaths that set fields on tuples that can't be
represented in virtual slots. E.g. postgres_fdw sets ctid, oid,
ExecProcessReturning() will set tableoid.

In my POC I turned TupleTableSlot into basically an abstract base class:
struct TupleTableSlot
{
NodeTag type;

uint16 flags;
uint16 nvalid; /* # of valid values in tts_values
*/

const TupleTableSlotOps *const cb;

TupleDesc tupleDescriptor; /* slot's tuple descriptor
*/

Datum *values; /* current per-attribute values */
bool *nulls; /* current per-attribute null
flags */

/* can we optimize away? */
MemoryContext mcxt; /* slot itself is in this context
*/
};

which then is inherited from for specific implementations of tuple
slots:

typedef struct HeapTupleTableSlot
{
TupleTableSlot base;
HeapTuple tuple; /* physical tuple */
uint32 off; /* saved state for
slot_deform_tuple */
} HeapTupleTableSlot;

...
typedef struct MinimalTupleTableSlot
{
TupleTableSlot base;
HeapTuple tuple; /* tuple wrapper */
MinimalTuple mintuple; /* minimal tuple, or NULL if none */
HeapTupleData minhdr; /* workspace for minimal-tuple-only case */
uint32 off; /* saved state for
slot_deform_tuple */
} MinimalTupleTableSlot;

typedef struct TupleTableSlotOps
{
void (*init)(TupleTableSlot *slot);
void (*release)(TupleTableSlot *slot);

void (*clear)(TupleTableSlot *slot);

void (*getsomeattrs)(TupleTableSlot *slot, int natts);

void (*materialize)(TupleTableSlot *slot);

HeapTuple (*get_heap_tuple)(TupleTableSlot *slot);
MinimalTuple (*get_minimal_tuple)(TupleTableSlot *slot);

HeapTuple (*copy_heap_tuple)(TupleTableSlot *slot);
MinimalTuple (*copy_minimal_tuple)(TupleTableSlot *slot);

} TupleTableSlotOps;

when creating a slot one has to specify the type of slot one wants to
use:

typedef enum TupleTableSlotType
{
TTS_TYPE_VIRTUAL,
TTS_TYPE_HEAPTUPLE,
TTS_TYPE_MINIMALTUPLE,
TTS_TYPE_BUFFER
} TupleTableSlotType;

extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc,
TupleTableSlotType st);

Can user define his own slot type? If so, I assume that hard-coded
enum is a limitation of current prototype, and eventually we would have
an extendable array of slot types. Is it correct?

You might notice that I've renamed a few fields (tts_values -> values,

tts_isnull -> nulls, tts_nvalid -> nvalid) that haven't actually changed
in the above structs / the attached patch. I now think that's probably
not a good idea, unnecessarily breaking more code than necessary.

For me "tss_" prefix looks a bit weird, but I agree that we probably should
refrain from renaming this in order to break as small number of things as
possible.

I generally like this scheme because it allows the TupleTableStruct to
be relatively lean, without knowing much about specific implementations
of slots.

After this change functions like slot_getattr are thin inline wrappers:
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+   Assert(attnum > 0);
+
+   if (attnum > slot->nvalid)
+       slot->cb->getsomeattrs(slot, attnum);
+
+   Assert(attnum <= slot->nvalid);
+
+   *isnull = slot->nulls[attnum - 1];
+   return slot->values[attnum - 1];
+}

Note that I've moved system attribute handling out of the slot_getattr
path - there were a few paths accessing them via slot_getattr, and it's
a lot of unnecessary branching.

The fact that slots of different types have different storage means that
we can't just change the type of a slot when needed. In nearly all
places that's not a problem. E.g. ExecHashTableInsert() converts the
"incoming" slot to one containing a minimal tuple with
ExecFetchSlotMinimalTuple(), but that's essentially transient as it's
just used to copy the tuple into the hashtable. We could even gain
quite some efficiency by directly copying into the allocated space
(saving one serialization/copy step for the common case where input is
either a virtual or a heap tuple).

The slightly bigger issue is that several parts of the code currently
require heaptuples they can scribble upon. E.g. nodeModifyTable.c
materializes the tuple - those can be solved by using a local slot to
store the tuple, rather than using the incoming one. In nearly all cases
we'd still be left with the same number of tuple copy steps, as
materializing the tuple with copy into the local storage anyway. A few
other cases, e.g. intorel_receive(), just can use ExecCopySlotTuple() or
such instead of materialize.

The biggest issue I don't have a good answer for, and where I don't like
Haribabu's solution, is how to deal with system columns like oid, ctid,
tableoid. Haribabu's patch adds storage of those to the slot, but that
seems like quite the cludge to me. It appears to me that the best thing
would be to require projections for all accesses to system columns, at
the original level of access. Then we don't need any sort of special
codepaths dealing with them. But that's not exactly a trivial change and
has some added complications too (junkfilter type things).

I also think that projections for accessing system columns is probably
the best solution for them.

I made a reference to vectorized execution above. That's because that I
found, while prototyping vectorized execution, that it's a very common
need to interact with parts of the system that aren't vectorized, and
doing so has to be extremely cheap. With the above we can have a
TupleTableSlot type that's essentially just a cheap cursor into a batch
of tuples. Besides making it efficiently possible to hand of slots to
part of the system that can't deal with tuple batches, it allows to do
fun things like having the first slot_deform_tuple() call for one tuple
in a batch to deform a full page's worth of tuples, yielding *much*
better cache access patterns.

Are you planning to use custom slots only for interaction between
vectorized and non-vectorized parts of executor, or also for interaction
inside vectorized part of executor. It seems that proposed interface
isn't suitable for interaction between two vectorized nodes. Are you
planning to introduce special kind of vectorized slots or whatever?

I haven't done that, but I think we should split ExecStoreTuple() into

multiple versions, that only work on specific types of tuple
slots. E.g. seqscan et al would call ExecStoreBufferHeapTuple(), other
code dealing with tuples would call ExecStoreHeapTuple(). The relevant
callers already need to know what kind of tuple they're dealing with,
therefore that's not a huge burden.

Please please note that the attached patch is *NOT* meant to be a full
proposal or even a to be reviewed patch, it's just an illustration of
the concepts I'm talking about.

Comments? Better ideas?

As I get, your primary interest in this topic is vectorized execution. When
passing data from vectorized to non-vectorized parts of executor tuples are
materialized by moving them from vectorized slot to regular slot.
But what do you thing about alternative tuple formats in custom row-oriented
table access methods? It's likely we should try to minimize tuple format
conversion. Thus, some executor nodes can switch their tuple format to
match table access method tuple format. For instance, we're running
aggregate over table with custom table access method. Then hash
aggregate node may accumulate tuples in the same format as they are
received from table access method. Does it make sense?

------
Alexander Korotkov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

#3Alvaro Herrera
alvherre@alvh.no-ip.org
In reply to: Andres Freund (#1)
Re: TupleTableSlot abstraction

Andres Freund wrote:

Hi,

I've recently been discussing with Robert how to abstract
TupleTableSlots in the light of upcoming developments around abstracting
storage away. Besides that aspect I think we also need to make them
more abstract to later deal with vectorized excution, but I'm more fuzzy
on the details there.

Hi, is this patch proposed for pg11?

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#4Andres Freund
andres@anarazel.de
In reply to: Alvaro Herrera (#3)
Re: TupleTableSlot abstraction

On 2018-03-13 15:18:34 -0300, Alvaro Herrera wrote:

Andres Freund wrote:

Hi,

I've recently been discussing with Robert how to abstract
TupleTableSlots in the light of upcoming developments around abstracting
storage away. Besides that aspect I think we also need to make them
more abstract to later deal with vectorized excution, but I'm more fuzzy
on the details there.

Hi, is this patch proposed for pg11?

I wish, but I don't see it happening unless I get a time compression
device from somewhere :(

Greetings,

Andres Freund

#5Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Andres Freund (#1)
1 attachment(s)
Re: TupleTableSlot abstraction

On Wed, Feb 21, 2018 at 4:13 AM, Andres Freund <andres@anarazel.de> wrote:

In my POC I turned TupleTableSlot into basically an abstract base class:

Here's set of patches which move this POC forward towards completion,
not yet complete though.

Here's what has changed.
1. Fixed all the regression failures while running make check from
regress and postgres_fdw.
2. Added/modified a bunch of comments about the new TupleTableSlot
structure. Modified comments in existing functions working with
TupleTableSlots as per the new implementation. Added comments
explaining each callback in TupleTableSlotOps, and their
implementations.
3. Improved error messages in some TupleTableTypeSlot specific implementations.
4. Fixed some coding errors in the POC patch (which didn't show up as
a failure in regression)

You might notice that I've renamed a few fields (tts_values -> values,
tts_isnull -> nulls, tts_nvalid -> nvalid) that haven't actually changed
in the above structs / the attached patch. I now think that's probably
not a good idea, unnecessarily breaking more code than necessary.

Done that. All members of TupleTableSlot have their names starting with tts_

After this change functions like slot_getattr are thin inline wrappers:
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+   Assert(attnum > 0);
+
+   if (attnum > slot->nvalid)
+       slot->cb->getsomeattrs(slot, attnum);
+
+   Assert(attnum <= slot->nvalid);
+
+   *isnull = slot->nulls[attnum - 1];
+   return slot->values[attnum - 1];
+}

Note that I've moved system attribute handling out of the slot_getattr
path - there were a few paths accessing them via slot_getattr, and it's
a lot of unnecessary branching.

The system attributes are accessed via heap_getsysattr() by passing
that function a tuple from HeapTupleTableSlot or
BufferHeapTupleTableSlot. Those places Assert that the slot being used
is either HeapTupleTableSlot or BufferHeapTupleTableSlot.
slot_getsysattr() which accessed system attributes through a lot is
now removed and replaced with heap_getsysattr as described.

The slightly bigger issue is that several parts of the code currently
require heaptuples they can scribble upon. E.g. nodeModifyTable.c
materializes the tuple - those can be solved by using a local slot to
store the tuple, rather than using the incoming one. In nearly all cases
we'd still be left with the same number of tuple copy steps, as
materializing the tuple with copy into the local storage anyway. A few
other cases, e.g. intorel_receive(), just can use ExecCopySlotTuple() or
such instead of materialize.

There is a patch changing callers of ExecMaterializeSlot() to use
ExecGetHeapTupleFromSlot() or ExecSaveSlot(), new functions added by
me. But I think that needs more work. I don't think the new functions
are necessary. We could use ExecCopySlotTuple(), ExecFetchSlotTuple()
in place of ExecGetHeapTupleFromSlot() appropriately. The callers who
just want the tuple and not necessarily a writable one, can use
ExecFetchSlotTuple(). Those who want a writable copy can use
ExecCopySlotTuple(). When the slot is *not* heap or buffer heap tuple
table slot, we materialize a heap tuple every time we want to get the
heap tuple out of the slot. If we are doing this multiple times
without changing the contents of the slot, we will leak memory. I have
TODOs to check whether that's a problem in practice. May be we should
use ExecCopySlotTuple() explicitly while fetching tuples from those
kinds of slot. Same is case while fetching a minimal heap tuple from
non minimal heap tuple slots.

The biggest issue I don't have a good answer for, and where I don't like
Haribabu's solution, is how to deal with system columns like oid, ctid,
tableoid. Haribabu's patch adds storage of those to the slot, but that
seems like quite the cludge to me. It appears to me that the best thing
would be to require projections for all accesses to system columns, at
the original level of access. Then we don't need any sort of special
codepaths dealing with them. But that's not exactly a trivial change and
has some added complications too (junkfilter type things).

I studied the code extensively to check whether there are any cases
where we fetch system columns using (Var nodes with varattno < 0) from
(headers of ) tuples produced by non-scan nodes (e.g. join,
aggregation). That's not the case. We do have instances of INNER,
OUTER Var with varattno < 0, but those are the cases when trigger
accesses OLD and NEW tuples. I have a patch to add tests for the same.

I haven't done that, but I think we should split ExecStoreTuple() into
multiple versions, that only work on specific types of tuple
slots. E.g. seqscan et al would call ExecStoreBufferHeapTuple(), other
code dealing with tuples would call ExecStoreHeapTuple(). The relevant
callers already need to know what kind of tuple they're dealing with,
therefore that's not a huge burden.

I thought so too, but haven't done that change right now. Will work on
that. That's in my TODO list.

Here's description of patches.
0001, 0002 are the same patches as submitted in [1]/messages/by-id/CAFjFpRerUFX=T0nSnCoroXAJMoo-xah9J+pi7+xDUx86PtQmew@mail.gmail.com.

0003 changes tts_nvalid from int to AttrNumber. int would take at
least 4 bytes whereas the maximum value that tts_nvalid can take is
restricted by AttrNumber which 2 byte long.

0004 removed TupleDescGetSlot() function, which is obsolete, but
retained for extensions. With TupleTableSlot abstraction, I think the
extensions need to change anyway, so removing that function
altogether.

0005 packs various boolean members from TupleTableSlot structure into
a uint16 tts_flags, with each bit for each one bool member. I think we
can remove SHOULDFREEMIN since SHOULDFREE on MinimalHeapTupleTableSlot
can be used in place of SHOULDFREEMIN. I will do that in the next
version. This reduces the size of TupleTableSlot structure and can be
committed as an independent patch. There's also possibility that only
the BufferHeapTupleTableSlot will have ~SHOULDFREE but all other slots
have SHOULDFREE set, so we can get rid of that flag altogether. But I
need to verify that.

0006 This is improved version of your POC patch. I have changed the
tuple table slot type in many places which showed up as regression
failures. Added/modified a bunch of comments, improved error messages,
corrected code at some places, addressed FIXME's at some places. Also
added macros to check the TupleTableSlot's type based on
TupleTableSlotOps set.

0007 adds tts_type member indicating TupleTableSlot type readily
avaialble for debugging. We may or may not commit this patch.

0008 changes the place where we reset expression context used for
processing RETURNING and ON CONFLICT clause. If a query has both the
clauses, we reset the same expression twice while processing same
input/output tuple. This means that some memory allocated while
processing ON CONFLICT and required by RETURNING will get freed before
the later gets at it. This looks like a bug in the existing code, but
I have not been able to create a reproduction for the same. It showed
up as a regression failure with TupleTableAbstraction changes.

0009 Replaces ExecMaterializeSlot as described above. I will work on
this again and examine all the instances of ExecMaterializeSlot as
described above.

0010 Index scan uses reorder queue in some cases. Tuples are stored
reorder queue as heap tuples without any associated buffer. While
returning a tuple from reorder queue, IndexNextWithReorder() should
use TupleTableSlot of type HeapTupleTableSlot. A tuple returned
directly from an index scan has a buffer associated with it, so should
use
TupleTableSlot of type BufferHeapTupleTableSlot. So, use different
kinds of slots for an index scan.

Next steps
1. Address TODO in the code. I have listed some of those above.

2. Right now we are using TupleTableSlotType, an enum, to create slots
of required type. But extensions which want to add their own slot
types won't be able to add a type in that enum. So, they will need to
write their own MakeTupleTableSlot. That function uses the
TupleTableSlotType to set TupleTableSlotOps and calculate the minimum
size of slot. We could change the function to accept TupleTableSlotOps
and the minimum size and it just works for all the extensions. Or it
could just accept TupleTableSlotOps and there's a callback to
calculate minimum memory required for the slot (say based on the tuple
descriptor available).

3. compile with LLVM and fix any compilation and regression errors.

4. We need to do something with the name ExecStoreVirtualSlot(), which
is being (and will be) used for all kinds of TupleTableSlot type.
Right now I don't have any bright ideas.

5. ExecFetch* functions are now one liners, so we could make those
inline and keep those in header file like, say slot_getattr.

6. ExecCopySlot can be a thin wrapper if we add a callback copyslot()
and invoked on the destination slot type.

7. slot_attisnull() deforms a heap/minimal tuple if that status for
given attribute is not available tts_isnull. Should we instead add a
callback attisnull() which can use something like heap_isnull()?

There are TODOs in the patches for 4, 5, 6, 7.

I will continue to work on these steps.

[1]: /messages/by-id/CAFjFpRerUFX=T0nSnCoroXAJMoo-xah9J+pi7+xDUx86PtQmew@mail.gmail.com

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches.tar.zipapplication/zip; name=pg_abstract_tts_patches.tar.zipDownload
#6Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Ashutosh Bapat (#5)
2 attachment(s)
Re: TupleTableSlot abstraction

On Mon, Jun 11, 2018 at 6:13 PM, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

The slightly bigger issue is that several parts of the code currently
require heaptuples they can scribble upon. E.g. nodeModifyTable.c
materializes the tuple - those can be solved by using a local slot to
store the tuple, rather than using the incoming one. In nearly all cases
we'd still be left with the same number of tuple copy steps, as
materializing the tuple with copy into the local storage anyway. A few
other cases, e.g. intorel_receive(), just can use ExecCopySlotTuple() or
such instead of materialize.

There is a patch changing callers of ExecMaterializeSlot() to use
ExecGetHeapTupleFromSlot() or ExecSaveSlot(), new functions added by
me. But I think that needs more work. I don't think the new functions
are necessary. We could use ExecCopySlotTuple(), ExecFetchSlotTuple()
in place of ExecGetHeapTupleFromSlot() appropriately. The callers who
just want the tuple and not necessarily a writable one, can use
ExecFetchSlotTuple(). Those who want a writable copy can use
ExecCopySlotTuple(). When the slot is *not* heap or buffer heap tuple
table slot, we materialize a heap tuple every time we want to get the
heap tuple out of the slot. If we are doing this multiple times
without changing the contents of the slot, we will leak memory. I have
TODOs to check whether that's a problem in practice. May be we should
use ExecCopySlotTuple() explicitly while fetching tuples from those
kinds of slot. Same is case while fetching a minimal heap tuple from
non minimal heap tuple slots.

In the attached set of patches, the ExecMaterializeSlot(),
ExecFetchSlotTuple() and ExecFetchSlotMinimalTuple() have been
changed.

Here's excerpt of the commit messages included in 0006 in the attached
patch-set.
---
Before this work, the contents of the slot could be in virtual form
(in tts_datums and tts_isnull) and/or be stored as a heap tuple and/or
a minimal tuple. When the contents were in heap or minimal tuple
form, those tuples need not be "owned" by the slot. When a tuple is
owned by a slot, it's slot's responsibility to free the memory
consumed by the tuple when the tuple is not needed. That typically
happened when the slot got a new tuple to store in it or when the slot
itself was discarded, mostly along-with the other slots in tuple
table.

Then ExecMaterializeSlot() served two purposes: 1. If the contents of
the slot were not "owned" by the slot, or if there was no heap tuple
in the slot, it created a heap tuple which it "owned" from those
contents. 2. It returned the heap tuple, which the slot "owned". This
was typically used when the caller wanted, from the slot, a heap tuple
which it can upon (esp. system attributes like tableOid) and expected
it to be visible from within the slot.

Since a single slot contained a tuple in various forms, it could "own"
multiple forms at a time and return whichever was requested when
ExecFetchSlotTuple() or ExecFetchSlotMinimalTuple() was called. Those
functions, however, differed from ExecMaterializeSlot() in the sense
that they returned a tuple even when the slot didn't own it.

With this work, every slot contains a tuple in "virtual" form, but
only one of the other two forms. Thus ExecMaterializeSlot() can not
create a heap tuple, and let the slot "own" it, in a slot that can not
contain a heap tuple. Neither ExecFetchSlotTuple() can return a tuple
from a slot which can not contain a heap tuple without consuming
memory (slots with minimal tuple can do some pointer swizzling and
save memory but that lump of memory is not exactly same as a heap
tuple memory lump.). Since such a heap tuple can not be "owned" by the
slot, the memory consumed by the tuple needs to be freed by the
caller. Similarly for ExecFetchSlotMinimalTuple().

Hence, in the new scheme the meaning of ExecMaterializeSlot(),
ExecFetchSlotTuple() and ExecFetchSlotMinimalTuple() needs to change.

ExecMaterializeSlot()
---------------------

ExecMaterializeSlot() should save the contents of the slot into its
native tuple format, whichever it is, so that it "owns" the tuple.

ExecFetchSlotTuple()
--------------------

ExecFetchSlotTuple() should just return the heap tuple when the
underlying slot can "own" a heap tuple and error out when slot can not
contain the requested format e.g. when ExecFetchSlotTuple() is called
on a "virtual" or "minimal" tuple slot. This is in-line with what we
are doing with ExecStore* functions. The earlier callers of
ExecMaterializeSlot(), which expected a heap tuple to be returned,
require to call ExecMaterializeSlot() (no return value) followed by
ExecFetchSlotTuple(). Instead of that ExecFetchSlotTuple() is changed
to accept a second argument "materialize". When it's true, the
returned heap tuple is materialized and "owned" by the slot. When it's
false, the returned heap tuple may not be "owned" by the slot. All the
callers of ExecFetchSlotTuple() can be managed to pass a
HeapTupleTableSlot or a BufferHeapTupleTableSlot. Instead of relying
on the TupleTableSlotType (which may be expanded later for user
defined TupleTableSlots) we rely on the presence get_heap_tuple()
callback in the given slot. That callback is expected to return a heap
tuple as is from the slot.

In a few cases, ExecFetchSlotTuple() is called with a slot which is
filled by tuplestore_gettupleslot(). We use a separate tuple store to
store foreign table tuples for processing AFTER triggers and for
storing tuples returned by a function. They are stored in the tuple
store as minimal tuples. In both the cases, the minimal tuples are
converted to heap tuple (using earlier version of
ExecFetchSlotTuple()) before they are processed further after
obtaining those from a tuple store using tuplestore_gettupleslot().
With the tuple table store abstraction a minimal tuple can be stored
in a MinimalTupleTableSlot. Thus we have two options

1. Pass a MinimalTupleTableSlot to tuplestore_gettupleslot() and get a
minimal tuple in this slot. Convert the minimal tuple to a heap tuple
by allocating memory for the converted tuple. We have to explicitly
release the memory allocated for the heap tuple after it's been
processed. When do we do that exactly in AfterTriggerExecute() is not
clear. ExecFetchSlotTupleDatum() could do that right away.

2. Pass a HeapTupleTableSlot to tuplestore_gettupleslot() and let it
store the heap tuple crafted from minimal tuple, which can be freed
within the same function, if necessary. The heap tuple gets freed when
the slot is used to store the next tuple to be processed.

The second option looks better since it continues to use slot's
mechanism to "own" and free tuples that it "owns". Hence implemented
the same.

ExecFetchSlotMinimalTuple()
---------------------------

Before this work, a TupleTableSlot could "own" a minimal tuple as
well. Thus ExecFetchSlotMinimalTuple() returned a minimal tuple after
constructing and "owning" it if it was not readily available. When the
slot "owned" the minimal tuple, the memory consumed by the tuple was
freed when a new tuple was stored in it or the slot was cleared.

With this work, not all TupleTableSlot types can "own" a minimal
tuple. When fetching a minimal tuple from a slot that can not "own" a
tuple, memory is allocated to construct the minimal tuple, which needs
to be freed explicitly. Hence ExecFetchSlotMinimalTuple() is modified
to flag the caller whether it should free the memory consumed by the
returned minimal tuple.

Right now only a MinimalTupleTableSlot can own a minimal tuple. But we
may change that in future or a user defined TupleTableSlot type (added
through an extension) may be able to "own" a minimal tuple in it.
Hence instead of relying upon TTS_IS_MINIMAL() macro to tell us
whether the TupleTableSlot can "own" a minimal tuple or not, we rely
on the set of callbacks. A TupleTableSlot which can hold a minimal
tuple implements get_minimal_tuple callback. Other TupleTableSlot
types leave the callback NULL.

The minimal tuple returned by this function is usually copied into a
hash table or a file. But, unlike ExecFetchSlotTuple() it's never
written to. Hence the difference between signatures of the two
functions.

---

I haven't done that, but I think we should split ExecStoreTuple() into
multiple versions, that only work on specific types of tuple
slots. E.g. seqscan et al would call ExecStoreBufferHeapTuple(), other
code dealing with tuples would call ExecStoreHeapTuple(). The relevant
callers already need to know what kind of tuple they're dealing with,
therefore that's not a huge burden.

I thought so too, but haven't done that change right now. Will work on
that. That's in my TODO list.

This is still a TODO.

0001-0005 are same as the previous patch set.

0006 This is improved version of your POC patch. I have changed the
tuple table slot type in many places which showed up as regression
failures. Added/modified a bunch of comments, improved error messages,
corrected code at some places, addressed FIXME's at some places. Also
added macros to check the TupleTableSlot's type based on
TupleTableSlotOps set.

The changes to ExecMaterializeSlot(), ExecFetchSlotTuple() and
ExecFetchSlotMinimalTuple() discussed above are included in this
patch.

0007, 0008 are same as previous patch set.

0009 Replaces ExecMaterializeSlot as described above. I will work on
this again and examine all the instances of ExecMaterializeSlot as
described above.

This is merged with 0006.

0010 Index scan uses reorder queue in some cases. Tuples are stored
reorder queue as heap tuples without any associated buffer. While
returning a tuple from reorder queue, IndexNextWithReorder() should
use TupleTableSlot of type HeapTupleTableSlot. A tuple returned
directly from an index scan has a buffer associated with it, so should
use
TupleTableSlot of type BufferHeapTupleTableSlot. So, use different
kinds of slots for an index scan.

This is 0009

Next steps
1. Address TODO in the code. I have listed some of those above.

There are still a handful of TODOs in the patches. I will work on those next.

2. Right now we are using TupleTableSlotType, an enum, to create slots
of required type. But extensions which want to add their own slot
types won't be able to add a type in that enum. So, they will need to
write their own MakeTupleTableSlot. That function uses the
TupleTableSlotType to set TupleTableSlotOps and calculate the minimum
size of slot. We could change the function to accept TupleTableSlotOps
and the minimum size and it just works for all the extensions. Or it
could just accept TupleTableSlotOps and there's a callback to
calculate minimum memory required for the slot (say based on the tuple
descriptor available).

This is still a TODO.

3. compile with LLVM and fix any compilation and regression errors.

When I compiled server with just 0003 applied with LLVM, the
compilation went well, but there was a server crash. That patch
changes type of tts_nvalid from int32 to AttrNumber. I tried debugging
the crash with a debug LLVM build, but couldn't complete the work.
Attached patch attrnumber_llvm_type.patch is my incomplete attempt to
fix that crash. I think, we should make it easy to change the data
types of the members in structures shared by JIT and non-JIT code, may
be automatically create both copies of the code somehow. I will get
back to this after addressing other TODOs.

4. We need to do something with the name ExecStoreVirtualSlot(), which
is being (and will be) used for all kinds of TupleTableSlot type.
Right now I don't have any bright ideas.

Still a TODO.

5. ExecFetch* functions are now one liners, so we could make those
inline and keep those in header file like, say slot_getattr.

This is still a TODO.

6. ExecCopySlot can be a thin wrapper if we add a callback copyslot()
and invoked on the destination slot type.

This is still a TODO.

7. slot_attisnull() deforms a heap/minimal tuple if that status for
given attribute is not available tts_isnull. Should we instead add a
callback attisnull() which can use something like heap_isnull()?

This is still a TODO.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v2.tar.zipapplication/zip; name=pg_abstract_tts_patches_v2.tar.zipDownload
�H�=[�\{s�F���������| ��;�ci�;��J�z���Xx%D$�@���>��c�"�vl�f/���AOOwOO�oz]Om'Ic�M�i�L#;uodr��3~t��F�6F���}�i���9��tc���b�9�h�,����x`'7�4Ln���w����:�t�&������Tv�e4�m�M�a�M�n,�e���;��E�G*}���C�I�#�����:�3��`�@�_C���
:�g:�7������g�;�������������`2�a .e$����C�O�A��9�JF��
V ��d�s��3�2�b?���s��S��!R���!��P3�����C�m}`�����I�����7�W?�(��������u
2AA�)�:E
�N���N
���'c��K��=M;<�A$��e�*���$\H��p�'���CiK/k�qs;7������&\��Vp+	]8�����d��n|`����kak<d��GG��������{�}�����k������D���������c%-�8���;_i�5��/�r����Q����v@@;�����c�2������n���D=�����h�jho���Z&�&J�8��p�e���n���$v����w ?H��A�I�/w��L�]�t��O��;_z�J��������hk�/f>�{c�����1$2F�V{�#���s������"���&s���N�4��nX���z��2=��e�B��������g�DJD�_Cj��.^�C�)N��Hh_��CJ [W<x���O�)�|���tCp)��A��"�oz�!���GZw�<B���C��fm��?���'����/���_�����<$kci�-�3��!������}�~���O�r��V1NE��8����_���^u(�
y,�v/
�E�`��j@���E���'iS�G�f�����;	<���,����n��f�|�T��S'j����c�Wv�� qu�1x 
�g\���-zB����/de�*jU8��a.m�K�
F	��i��j_O����IA��l���,����Ih��U ��j(��`�)]�v�����
O3�'Loz-S���{G����{4�h=�������J�tsd�h��Lq�����a��wR@g�0�"��-�$��x����+=\J�5.�=`�0�0)�M��G�Q������	j$%*�0�GhOvH�,�����g���5`���$r6���}5D��������xD2��d��	|���s5�����[�2��5�����@m��.�W�xs2}�����b��$N��~~r(��B\���c!����8�6Y6�
�����3��r�������o�?���H��>�:���!���!�����^�P��^-��}��s��$����C�,���U#I`����� ���p~1H4�j����%6��n�J�0�0.�����a�
�Q��4h�R]PSw�F�
�����BQ���Oc/y4�z$�c2��y���l�e�,��m����7Wo��<!��[fb!Ss|�l�������]������8�d3Hj�PDG�m��M��A}�����I�x�x����R�H��P�K�{�����f���1�i�Rt���������`�qC8��CG��Dw�BZ�7�Y�����������z�
.�vc	�#I��La@~����$,��� ����?�1tkh��?�p�'��5>��8�p�w��7l���'��2\C:�Lz��t�e���s����/�������?l����N�����p�@���S(�D0��G�g���FbfsC?�A�(�X�2�Bd ��tBw�	
�����X�X�L�3��x�W�h�Y�O�l���q�W��BB���~�V�e������&Y[�����+���`�'��_��*,0�h���w���9Y�@b��]L9�%��L�����}��B��3�xL q��r;�d��s�/I�kd!%�E
B5t<�O.�<Z��x|�LB���,�tLNRJK ��6:���4��8�[������u�����P��P"�L�V�����4Vb���?E=�s�	W+4VB43?
A���t�$rz/���R�����Q��FB�;�m�S��j�n-9[�I$J�*t��6&�]�n���LU3��ZN����7���I����@�L������U�k���m2��f�I�'ug<6G;�h*[@�J;�*-�����s�VV�R�~b(��zA�|���ZI��
��<�y�������!�rTi�p	a����s��[+7�Cb�AS���u���$?{>����f��������o��E�}cLu��C��R�K��9���gd��b���H*!Q�3t��YCfo`��w�t����������������x��+rl!�@�LW�������2l�?���������{u�Py��X2����3R����*���q�������T/N.O���+�����G���f��>��<M�����:?���B�%��CS:��xb��1kN]�hl&�u��0>Qh/8	�[�!ia�*�T��+,Z�)+,=2	�Mi���"i{�|�F-p�C��=pA�l�+�2��"E�x��`��7),����D ��+H���k����gI�c@��o��B�lZ���yD��D"�ZV���]��V=�-����D�H�wG��5���S�G�D�c#PQ����Pq_���?�G�D��hT�����&=4�-C�����_�f�A�s�wggC��<n��q�G�W*}���"R ,R���'|�+�xD0��pS�5�a6I�-����G�$X������\FSa��=�Z�L�:`��K� �$��h�%��l�X��#4?���9�,
���pW��'j*7�
#��h��^}����w"�X;��i"�3��4��;����ic���Mk�!+"����~ 7	m}��a������N�����=�/��Y��u��-�_����4��>���F�|�����3���X
������9�����Z�}�����:���#}6L��7rf�91<����
�3������������l���A^���P���03NA�z�85�M�>�e	0[}�����(��������t%�a�� ��F�{W
�a(3A�-�# �?���Y��rx��3��(��;O�|,�"X��x����R��	��.�� ��8�q�bi�(�N0��q�����vPs����uF�K����{lB��"��Tj���dTJ���� N���u��� 51\G�&��/}�"�f
9��Si`_�#9�{=�;#{�O5S�����Ro�#�~P����4����A+��na�}z��K�V�B2�A���������#o�� �rV������
�p��e���%!�/_�+�XN#�	����R��h��@gzC�y��1��
�����A*�D�U�G��X��H�l��>7�F�mS��-��� ���/�:��5�z��������Q�>(� xI�D����
����*Do%?��%�
�`�XU9��a���R�).G�����4�?�e*o�����eu������''�����*4��%+:=����mfTi��7&Y��� �\��pt�H
���_�"gp
<�h�H��RyW_�]��dZh����E�q��}Yb��f%��9���2��R|��Y�U���Z����R�o�K���
�,��+���2s#�'���z(�A��w��	k`�z���\�k'^
�[_�'��J��]�8�qoi������H��\'���.�1�j�d�>�=N�/e�)�hXM��N
D��pq^��!��OD�[��:hE�	F0�����F,Y �����I,�]��	���M�:^���)��O���M��S�cP��������%��n���nV	b�J��]X�����y�iU��)��k������q��R2���c��vR�?JT�z�a�N�D��en��"��3tIUq�-r[W1R�;.u
�;����E��'��Z��0������j�����e��_�2������Z����j�H����������}���<%���v;�g6��o������Jn����Q������G����W��[`�������b��;���2?Pi5�L0������_yZ4E�[=�g�C~�o-��C��� ��bIG���d��!��O���
88����kd�v|�Q	M���������\F�o;�� _/70��Fv*����F��sG����T����X��*�.�V����3}�'Wn�I�"��`<*�*K�O��>p��H�6�G�u�s���i�T�����>{����O���OU
��%$�.�	�'h�C�B{hL6]Y#�Hc��o�GP��x�CR�pXR8���h<����7�^�x���A�o*o���N����g�l�&��s>)+�.S'9�V��w����s�����rWay!v?�;��B�8��������#
�Z=���������G�t���Ne����B2������X�B�2_)��[��=����nT���MA!+��#Q��,��i�-t,�L��*�������0����9���rw0������:6	��O�s��$�/�_`y;aq��]G�����F0W���ci{+&4C'�����'�>�c'yt��Uo�bJ�4L�u$�)��,�F[������E� ���I���{��=������-$�ya7R�~�{�o��x�AN��������u����V�}���TE��L��}�L��u.#�M��������9�y.:![�pe���^U@_��O�i�U���q$��N���-d<v��P?���5;*��?�E���J�#<�0�zF��c��Q�UR�(�����	Gi�����V����"eEk���������^�E�`&I���j��9#�"��P�r��j��A�)5{�{-QWvV'������F���n��9:_���+��u��
w�s~���S�����S��e������&����Y�q��^o���=�m4���Z�o�k�/e*o�+�����,���1z�K��K�[�-1 ��	i���d��3�����m��������'��9���S�k���$`UB8k����w��xN�E���db:����X}�K�=h'���=��|�0��;�D �'=�*UjAx��=���j��HR�:��!6���6Q��k��%�]k]hp���`%-��\�C��������&��`O~B��D����t�W]2����\����=���wqa�����`�Lj}#�N���:0�I����U�e��(0r$���n)�#�����\�[��Wv�;D�^dQ���2�$�����t����o���)BvD,/��W�[��NA�,�{�M�$^�����H��jD�h��F�=�^���
-�*;�QB��=�P
��CL�!�t�������k:�7��s���i��g>�u&����|��{5�Y�_�N�9����'N��O�����|����"�����<8���v�N
����m�t5���H�Q4��c<�f=�Y�hS<]6��{��E<,Wp��8����������&�����0��W(Z3,�ykJ����R&���!�O����f���Z������f��DFm
��� �;�^��b�N��5x@���a�`�1����A�uv~�rJ����>=���Js�,,�a�WAt�.Q�%�)�*t\��X��k>�������H��&+�;����������
�Rp�)�/PF�������=�V2a�4�IeY�;����n������V6�a�\.���4Z��W$��"x���*"kd������2�w�	c?o!6#�����#Q�Sz�&5�������X����'��$HJ��Z����52(�@&���6�#EQ����.d�Hj�4onM�T�t�9�]@0����m"*v�w�4�*���6dU��uu7�1A�}>�Nv���e���{��4�sa��+>E��{l��#��s5�<���I�InN.��n���fh�FI|?�}����I�$�J�HtUu-O=��}�7������]���}���7�w���/[��[b�����M/��v�_55�X�����d�L7�M+W��)��<��$(zo�����4�q��������hq6���^��9��n��5�/oNO���3�:���	�����
t��h�"�`��O��PN�7o��t� ��9U��>+��7�D��Lp�����vu�#yy���V���J�Qt��'�G����/�^��=���?,.��c>����F�Ko��*��0!W������;���"
{h1[��g�m<��FYJtM�2�,��6#x������)I�~�!���szI`�ln���<(=8H@�t�3qA��6���p.�?�b���j�}�Ps-�1cN2���A%J��; p8�����fM�b�v�A#�v�f"����u7o�J�	p�]����bTsG�������w�<=R2��)�%p�4��~v��m|u�����(�DR�D4���A�E����/�_H������_�I<
u~F�L�>e������I��1�c���w�!��U;���[�� ��f�Gy��P�fM~{rr�~xzvvrQ;�pur�{��v��J����/�������}�3����`G�
�~w�5F����w'M�5�����n�U�UFx�e���	oQ8@'`�NG��U?
:KN�/<�������	�z(]j]�XD�S��m�k���a�����m�b�_�]�.|������5&I���y*�]�~I�d2�!��2��:�_�7F���=.{)cl���Vd����?�Z��xc�\�O��~kol��c������I�r�R}��
1N�Om�����_�<(�J��C�W�'�L��9���>�K���?#����)0��	o���q
��<;>�3��4�����b
(��6L�z���p�
6`�������~���n�
�T��5��4G�I^���KZ�>�+��v�	n�z���nA?��a{�3�s���U5�z����}4X�}�"������|\������I�b$���4��_:N��g�0a����_��@����Z������qII��Y����W��B���
	F��������k���2"*�i`�l��Y��R���	��Xv���@��_�����~���=o�iL���m���{0����1i�n�`�xn������@M��-�i�J�N��E*��@gIc�:�r��Yl�$E���c2^����*
QFq�J�X������*���GS�F�B�N�7�~�{w�p��15J�LGR4��*��F@2��%�U��K�Y���9.Q�5$�(�.��?���f�_Z��]��#��y����3bk�������dt�~��=��bgwOg���D?>4���M�[�;�qA���*�����a�/��t2�I�wo=[y��w�x��L�S��4�����Pv�{K��C���H�E�p�s�k"���!�6W%z�r�/���.����D������Oi�_�#������S��l#[��(�"���+
�������tq
@O�����(}���eP��2��������.���V�r�Z�������'�F9=�'nw����m[.lj����jG����5��_��~���Y���_����
�_�[&���m��Q-6b��~��-�_��h��_���������~��4&����u�
���t='~k�mk�M&����9��v��O������A���&���u���91p���S��P��L�����::;k�]@�����Jvnwmy��Q\9��C�Vg�gh:fwve����3&�(%�|�	���@2��8%~��}�s�{d����\y-�����V���Ur��w���x/�������A�/���$9�(�Ki�(����f�I}�(�������r���\Q*�V�,��n!�����un����wsW�����9��.�KP���?�)�@�j����X��j�~�F�qm�m��u��]��k�Z����F�����!����Q��=i4;�^s��G�`�����h29�u~�g��x`���^vr�b:�`�)9n:��qH�np�o#��\:x������"�c��Q�3���5��\�zQ$�-Nc<u�������L�5����,#��J�U�*x#�=�-.�� @��%|t>?��?����
����)�m��R����tt~������LI����\�8�[��U��I����s��PU]R���I����H8�~�b�p���Q(�MjA�������N��&r5�
h�Dm;7�S	T����0_M9��X;�v.��RpMR:R��{%�x�SrXR�?	~��M�],g��[B���a�^�d�M�w��t�p>�V���U����p�z���8���]#����������?������Zr@|�jg�o�KLV��V�vc�>@�'�%��7�E��?^>��?v;�I��hz�I'����������M`���gD��W�B�s����=f����o=@����z��^Q���=��:�L�m��"�qcN���9��<����Z��CNTvS�����G�D.��cqQ�����k^O�5VPV@�J�J����5��8v��{�+���Op�U�7#�s�:a�����S������b�u��A7T0����F������.��/a����J#	[�Q<���:z����I�,���A|b�0�j�� ��M~�'����q�q	,N�����Z���n�)�PeXF�����������T����&w�F�Ymi_7��x?u�r|:��J*B�aY�}�Wi-��rQJ��������tL��0���	<R�3���vv��d���G�������K�U���N��a�a�� 9E�)X�����R���J���(�cm�2*�-W|����������������q��<�-0L��Fom��u���E5x�9����~����xp�xE�Y"��4�b�\-�*��W�o��v�p<h:E��R���*O�B� ��,�H����\�to��=��da Y9Z��Q��#?v�W=+��$����g���'����[�R��&��H��j�(�H�0�����X��������_�����m����7r;����x��@	�F�u�����V��i�k�^b��l�����t�
k1t�W�dZv�P-��F���G ��+����*��N��s�4YYJ{Em��A�h�HU�9��)����~Az��6�����A2�������,�4�t����~��M�T�Wq�����DR��y�L5V�����y��}?U����
��2��J��*�����q�]|���!�����z]���|5�� �>~4{�!��S9 �c����TEp�G��9�\��9S}X�j�<a�:��� g��:`�h��P�r�q����*�T�|�1��o*A��"���q#�.S�����n��ZF��������������������\��c�(3~Q�T������^��n��?�/������������Z����qr0��;�I���&�I��K��m�l4_��y�_O�p&q?b3N���\S����c�U�l���0��_���
����,��FxV��)���MTwNH_����4@D�}I��"���(���[-��>��cf:0�O�9,>XQ0D��l�`�!V4�X�� Y�U1e���LHX��,��a�2��(�R-e������W9����B�}����N��(~��$�+�]rB��K����-OC��+��Ho�C��t��=�],�!�.�T
���]�
����\x�*����WJ|���]���~�{sD��wx��1T��q?�K8�������3�g��`����+x�$�D�]uA����#��Je��%���������F�	-q�^�:�NT�vb����T7��q@�F�?�����p�	&)R�4cH�K�W�( �:GQ9.���#x�����2H�G ����9���i�������r��3�m�P�t��3�5��_lU��\�6�R���1������+&P��iW*�t@�	�����9����p�j!h��������E�g3�OQ��1��AU3�u��Q����	;1�j�0���er�/����S���k��,�yD�3u��E��@��XAA)�QF C�������)�<�6���3S�
w������->f&�T������RP1{��R�I�����r��t`�hz���>�J��}�RY�w�����&��99u�q��S���8l��T�Q=�[**6��qB����8<a*�Hn��t���B�J���_R�*�tH�+� 7�b}e�!oQ2��PC���N<�N��mW8%���Lw�J���L��\��2e?U��$p3��%�FDt���]z����$�I��"eM#hf��%��*�&k��gC+�����
��z��}�^:MGi�Q)��Q_e9?��q�������q��`�	�'�
�H�ptyQ3�;-��*�Y��W;�I�PuB�%��>/����K�e��q�u�r��9���(z���2�W]E�d��JRN�n���
	��T�Pz%��w.�����T���J+���Z������6���=xR�s�amF���5�1')�<�0�n�"�R�lR)���o�o41��x������o�m�RQ�l�U��D���~w1 ����(h�@/����;f/���GcN6>����D����m����)K]D�O��B��W�P���E��Z���1�W6?�yW
n�����)[��n�I)��c��r������W]���xw�_@p����7��������P���x��O���q�����rh6�H�eV�a��z��m���?�cD����	S�2�c�:�X|��5��Z�Z`���������&�m�syKF&�f���
d�M!~fYUpN�2\���R.�H�4��}=�6�O�fg�=3c�l>%��b��0s���[E���
>�
���U����e�:DO�S�I'��9���j�f��S�Ji=�|8O
��J���I����K8t�$�[77/-{*<��w��u��d�6P8��e��o{"W��r�`��2��	�t;�[���:{9������Xn��Z@S��;�a��(Rgo�rEa�]-� OP��k6P���:�9+�Y��b���}���;Xk�n�����-����k��T���,���>���u
J��������ggq��*	rcx�#*I?�/>�J|H�$`����kq���q��B���Ck��>���T�Pt�6�� [����DJ�cE��QE���r�?Ev#���$��`]R��B���-�{t��S5�bH]�1]4����&Oh�[MQc��(G���o�Ea�%�S�.��^<V�/��:�����Q"���\P9,�/(�se]bA*��v�S��a�s�:4�����fhD�q��C:�I��M�#���7��� ��v3r#K�R��2)�24D�7��K���������"�����*B���Jic�.�9�p7��D��y/���NsCZ�.{��hVRU�D3\R.�@b{O�6�+����8�5�����8���I�L�A�}9a$�M�bj,��?���x���8n�dTQ#���j,���^����E�� T`7oI�D�_����C�x����S�]%��z�z�u��7���.�a����u�'���d�����������K-q�"#%�+���DK� �<���T�}��6��;&��[H�������OoN��Y��
@BFb��r�F�������`.�����dU)�ing�<�
���KT�i��?�%W�e��R)�
I;u���t�O��L����lb�V�E�F,���}����'����������}]+�J�b$}��=���Q��Tn��c����X����[I)���_������f�t���FUd����u�\k��j���:/c�Cu�e��v��	Q%S
�1��M��<"����R� S#u���=����)�����-�.���T��!�C�,I)v�O����������QD��f��s�L�?p5�����*��"���b��L��
X�#�=�~�R����T�/CB�pa�%��iV5�b�������*V=�a���I����4�������Yy8T�\w�i���%�&p�����[tsdl������6����#�Zu,���7��k)Ug=']g6��y��|�v��
^�fP� ���O �>2����l��p>��0�J����+��	�9���T:k��4����e+�A�,1^�
xO�������l`�J-)^8��TzC�+�T���^��D��0�1�	��Q�x(�V�f#���n@l6w5��'�z�iA��aJ�P)���Q,�3
H=q�#,�vp���i���N{�~��?�������TS/��_r���j +�`�p1�^pC/Xb�
fs�K�����b F�A���)�V.#&!���������_1.$��B����I5�Q�-Z/?��K���������b���v"��]���i���F��9Z�D[�*��2C��v�xM�@"3���d�I�$�TJ�d�o�f��MW�y����,��H�3��Y-Q����O�_G���T��/��T��"�6���J��h�g��8�R����Hd=�r(����;av�*Z25.,I
�!y�(\��A��a�?f�#u���RZ������gm�D	5��*�#f�{�����2y�Dx���$"�`����t��kG��I���fm����! ��p�q�C���,�
mM��%��U��/���OA&T[�MI�P�����\���<�M|xO�N#�&}���ZV�����%+��x8�aO���#�f��X�~@V<B8(u��/�_�1i�b�����*n4��%��eX����#aw @ ��V���?�"��:�K��R 4g��HI��z����@����o������J�����e���K�q���~������i���c���T#�~I�����5�=�<y{rt�,��G����\8���c���/���]�5��g�V�����U�y5�	���x����w��k�������U�Dx��y�PR^���~�����p	���Nc���0�b�T!�7������[!���J�j	���U��[���������j���i62'K�����L�[@J�G�X���0a�Z�T�u�LC�$�EC���8	�ro��{">��N����HD��S�fmP�����bT>AV����=���
���&��-��-�u*�S���+T�+��8~�i3iZCE��|J���J�swzZ��8
�#��]����n���C��
*?V��I���|���5�u�:����*���r�_~���9140p��*��q��MW��%�S�r� ��K6�4,���gKQ�ut��+/I�#��TB�dvt��t�;�xBe��tn`�!��8��=��F/��7q�x��v����J(7Z�C\���M�=95����<���}���p�����.���e������;�G?���J��������D���'�F�r�b�c���d3N������8�R�Z<�^f��s���A}�� @��W)#=��7n0��f�����>��C�;\�)� ���{�EJ��6�5G�j[z�`�J��)�9
1j0�� 1�z�l��5A�&
n���|��e��XJ�eoB�M	@7�%��������3�}xXR���uyK�q��������%�Uo'�&��R�K%� -Li����>���)�����3�4l��FB+s�LB
X~��G)Y���k6�e9���u�����*��H�B?����S���"���TsIB"����8������a�y#9�4�&�0����%�����9�x|����(jc������������������zF���2~)	��Y�Z��_��W�������T�4��}��;v�C&�ZP�!�{W%��-TH���6v,@-���}�����MdZSy_��7����&��������uVB�rEC��|o�T v��\@�g�G$)���	��FI�9R.����fVp��Y��{�`����^Q�!q%�m���!�Z��q L*g�v>��`�w%<px��J!�9�
q�W��y��N���t���q���[����Q��-�M���Gs��Y�����zU�r���t��8���}��,VFZ�d����:b�0G9�+�:>��%����7Ij?��g����Gkz�
)��9(���4<�S�*4���G��fJ��oN�����M��U����t3�����7������`�z2���YI17�|.��#�O��n�����
�'�f��V�������s/��l�YA��U�N��>}V)mK�X��U�}��u*F�^��
^)V�K}���NZ�l��,8�>ZV������a`��$�!fA��E�
���Db������[�'��
����h<��f�)��+��i���@~���q$A��L�"e(��P�s�8����IB/Nk'��1��i]R�(WJoR��U
4����P��������p
��k��4�ai�Na1+@�k��u���l�1M�S�|�|U~.z��,�����Kia��{�9�-���N�)c7J\�M!�XE%��A�T|
|��]���8���ywxurqz����>9v�?=���}���3�fy/%FF4���+d����+�/R��oSI���=C��V$�t��r����<�M;uNb^q���#jT3�r�U���]K�����=Q�d����I�p��3����i�Z�������=���M����rx���'��N�Su��A?��������*���c�Ze������Mq�r��a�4�K	zdvo��%��x7�'U�_(j�U���I ���C$��1|P0���H�c4�Y��-!C:L��/�����9�s��v�UE��g���MG����7��7��Q����Put��/�v�+����s��:z��H\)~����An���W2�Z�����1_���g���_�g������F4F��0
���H�BP��8G��.��0�kq�����_ 3������n6������?��~�zo;�^`��ix��rJ�:�������uMw�{',�����j�����D���{.���I����n��{�;3vH�T"�x�E�p��S���J����GZ�f�w�l	����z�6��,{���;��rGl�K�&�K�PF!��JCB��)��I�����V�~�������H�?��s�����\����-�|�=�����;�{�9
X4�b����^^�)���=��F3]�V�����A+�lXC�Y�����'Z���pi3}����3����N{~�f��
�5�F���V�# �F��gE=����U�w�����{s���S���u4c�o]������ur�w�^N�vkO�1�����wnt�}�[[��;����S{��^C_pks���3EE��6�)`+.�����Ex�E����L���e��KZd���q"�C�m=��F�&fm������^��!T�X���R���zJ��K�:�"�r�/������XO����6/]��$!��:/���6ak�s�������R�''������d��@�[�,��4:��3�������>��=�����e�~ W�$�������#1�;!\Vef�@�N�dp�8@�Y����
��e��QS��t����?g�Y=QfP`��4IZ���bA0�-���v����[��/�W��u�D��
=1��lQ��=���#���8[�'��4�5��J������������m77���%�-E�6�JO�l����'z�+�A����h��������7Q�j�;�T���NgT��*a0jL:�z�5���D��"�p��"-1gw{�iT� ��/-L���s���=��f���7����{��
Tf}2���d��K�a�<r~�(Y��UI�,��3�z�K_Sgl�s���Gc�&���J�H������I5���U��;������M���]R��pa����i���R���+I;�����z&L�q�*%
QU[�v�*��V�5W���W���k!G��	��;�����^������#�+���]�V��%������Y=3K����r�Tpy�@p��D���&]�jw��S�?�w�U�..���JN���+�b[S��Jc�(&	1��b�{�.}���<����W���\AD�Q(%���T�^�FQ�4�	g���E�vft=Y���g������J��@�y���>=��pd�!����K�u��a5�$�E*-�s`�UQ��V�Cn�P{-��_�����������8Zw�Dw���rh�4*���b���#��qe���?b�D���7�Q��X����S3UK6'e�QA�J���*���N/���������7�F�[D7��mB[n����h����8{�
�y9>w���g���k<��Z����4���n�5n�7x�:p���;���#�v&F�*o���A>��}FH��t���)o�z�c�Sw������1���d�w�M�����r`���B{)���B�6�UTm5��Fu���^j�mi��|���j��x���)���
�*��T�z8�V�a��w�=LUp���=��b�:�������jH���c`)kQ�(j�������E{�6	�V�[��p2YX;u1=�3J!#,q��yO��&����|.7�l/����Xj%��l�_����U�o��=v�a��<3�J��*#��.�=��z�>kv�714�=�..���8��"9�o���� )����]k�^��
��������3�g�9� 2a��g-	�	��hE�OG��[���:�\Z^�����x�;�>�*�Y���(��7�����\'���Ki��������AN�k[�B�-\���G���M	�)f@�)��:S����1���T�j>����S
���� ���j�x���������\ )�Ni���()���<�0%�%���Y]�z�gH ;�no��L(A�Y�����!AP��uw!�����a�!�3B�q@�f6p�<���_��E���`g������-��#L�1'�	[�8I@<
��W�vG����������S�d:2�'�r=�u�H�����T\��NCs��x����b���\�x�.�;v��.��Xjf������W>5�:��Q�<���L����%��T��	���p��q�+:��A� -X���&�t����Hb\}4�������4�f�(�&����Nt������7w�(
�3�%��wX�SY�yoZ�����bPB7'-���H��r?���n\�E%���e�j�t���X4�^`�5�j �i����W"$7Ad��b��H��s���b����<��^������=�u�-�S2��#%x\vW�dd��5�e{2���!zid2��$Y�`f��	���M�%1u|+R��h�$K�J�[_~�������*���\����'���������1�!��b5��s�'�&%!W|*
���T\8b��8O���r���E&��2
�z=�~I��^r>��q9���-�����6R�|�PV�q�s)�B�|��bwq#�(Sat����	�UTt�HH��+�,�����=��I�x�uk[5�=���Qy����k*�$���'r����rQ	IO;�C�a��U5H5�4���O9�WqTR�)�Y�I2b�PY��8I)FQ��o��R�*��F�t%t��(�|�.��i� �
��M�2o�D~����@4�%�g����q�G�3����/�fk��2�F�
Y��Bl6d��QkGMb%a,l%xLu���� !$Alx����C_��<p��@��~�w7�kQ�i�b�+��`f�8�����K��
4*�l�[�.��yY���a��
��X���W)
��$~!Y�,R���T��I�RJ1/�J)�/S�Kdcg��LBb�f�\]�~$TF�,��vm@SCQ�I���+�����J�M����1M\Wl���-��%|,������I��{D�/W2!bT����a�J�Js���.����'9�B{����B�������B�����2Q8���0����4K��0�q� ����iZS�UEA��%e��	��4�J,���<�U*6O�vV
��K��~�=Q�ci�J�������������8O��*��2G�h�+h���D ����/O:��ib��T� ��[v�L�L)�7m����t��Sh��]U�� <I�|�)D#�N�&
Y1�r�R�� 1���S�M5����`~v<��k���Z(9�Ul��6Z@����9h�Qy���F���F��pF�\)v�8���*cJ�(
/ �����Ff���NI9{��[���A�F
)WL{�|��������]�����(��V{�u����������f� �>fv34�v:�Z������@�+����x��/��_���sN1���f��������
���)�&�(�����Nz�+����|B���3�A���xen��by�Y����w�0�{���M�<`Es1�;�������j�v��1q��x����x�U����I�5�hg�=">��/�c�F��N��O�<|w���O�r���/���j���������V�7��~�u:�|�N�Ot��r��j#,�g���
H$_\���z>	�WtV��'�t����G/Ta�>�wc��_��o}�;���tpi���4��V�!��lz���F*t)��$guDF�E��T��@��(���o>�ysra<�����3��� P���\<7 X��S�M�	���!Jm����:���`��T����-��0�}&�\jT���:�A�@��h3�#P�fL=<�Ds��S��7A�Q�^5�Q�N�gg�`��1���0(���s�duBj�X;3n	I
�����
�E�wNz�^���VC�ir/����tN�A�8'�G��$�9����zF�;���MaH��tA��d��.���T�ns��
������^�w��o�[�qA��Cl!���k�E��	�����m�o�W�#pL����������;���^/����S��O��T:��08����;��������8��.�-�J�G+�n�%�8*��ioF[D���A�����v�5�Q�!2 *�!�@L!~L)�v�U	Q����x���5��`���$n�W� ,�F�5��0�sbNd�w�^��{[I.�{���M)V�6����9p�z�����N�XZ�l�L�yM��-�N.�1v�!"�S~��������������������1�^cV[���t������T��=0fCB����:!�=QX�X��h�����39o�eE��2i�� >U��n�7u�u�`�mx�B�B�7��`�������f�(��=J9�	��h�
nL4���d�Z�������{�����fv'g�2��{m9��/���:x�>(�R�O���sm��l~*Ec�y��N�������T�l�%�C����O7
U2{T��9���: �w��O���o���ov8�d#��i����{��3��P�\��@4>R8��2���
�Z�N���>���VZg��F����.(��\��Q��D��"�r��M98(�)�s�����J����U_�+�'�~��z��?$o��WDh�6*��r�a)�B�B���{�z}2t�Epa<�&|�����!�w�Y"�3�g�X��.T�����Bb�����br4�cFAG���*�8������:�������l��#������a�W*�N�����1\f��R��`��i�7���et�9��R��:���������-p��q6�@�%�j�>��V�'AB�$�����:���;C;)��[~�y�]��`l�	^0-P�������:<��TPRK���G) ���q�@�*FY�1F�������a���do�4
�y`>\zh��i1�k����g��x�+�$���E8�st�I6#'^��E�AI
�i�������>a�KU��o}~jd�����w�`�
]2D�J��\?'k�O�p�!�\��u��8��n��Vv�H�.t�x�����gy����=N��s�t��~����z}0����F�K��~���&y�!����0�Y��s�<Y_8�Oy��	�G�T���V�wl�A\����1����������(��,x��2�-8
%�:q�C6�_��#,Y����=�
4;u�}���6����Sl�v��H�v����f���5�����5}��g���3Zs��q7�	_����!���?�Su\G�|�<�]���� w�/�#�a,�����@�Y.+�X	�^����e�b����S��n]�q�w�g����R����}4A�_�@��yb�,�W**�8�%y������E���:���&�Qc�O^��q��z�A6@����xo0���O�����G\��]>�8>��?��
CT����������������3
�g��2��3d7L�^U��t-zs���
�v���������H�r�#��*u~�9��6��&WZ�]�l�M��no�f��avzs�0J)��&��u$q*�I�[��~2����3��
������������Hk-?�^��I������ ���7����iN�(�P�m�foW�����nB�D���//��2��-��\�o*���8M|��V
�E��m&~�>�FMo�Az�M�C7"���d��?E*H$-����X�=N�q��_�Y�Y�e�q�dH�N^���n��Mn�7#R�����YO�c5
J�c�`�6��#KB9�m86����&q��=NV������A���!���8Q^+��'����Y��s?�G����4����o����{n0�5`~��_�nYqg�����ub�����/���Q�(��;nj�^��M�f�IN/��o����r���]�,����)��w���'|���Q}[o�-g�B|��fp�Q�F��x���UX6L@�ty8��^����C<a�������`�\n~��Q�}�c�x�*������ot���=v>%6��w���t��.{�K��Y���>�)sk���k�b��`'�.)�Z��^���90��O���j_5�����]J;����e���������[Lg�O����:?>�.1����K�h����}�4m�s�����F%h��5#w�*��7���<&����p���.g�	��]�8	e���$�Q�(�����#.����e;��h����z�i��Y+M��r6��u��qR6�=��n�X����^1m�X.��V�
@��I`�!]��suq���'���O������^���|-��?�?>�:�8�/�m���R���.�7�%�R����
�2P�(�����R��la&U��n��~�	3Did�
C��Hq$���e�����n��Vfqd��p
��������^����wW
�s�B�������R4�f���tb&���0*���?kJ5��F�������^7*�H���
������q��
�>9���9
9�*�>����K������FP-��'%�����$����y��n�'�f���s���� M��#��X��T[d�1�{>)��P�<���WW���`������_���������.
Wh���D6��&�?q>\�//O.��G������[���w3��]q���5bp�����V�U��
i:� f���,�+��W�x)�f�|~��9-�?i������P�
�������l�_.�����G��'�������>\\�_/��6���;���O�,�
��������\��}�������ch���������8�9������W���-ak��7*pph>��!g�0b�����@h�T���#�W���U6�|�%�N�2/�B	�h�B*{��7 �`�.�"��tb\�{��Z�v����B���F(,(��n��_t4��kd���(h�/0m�U���T��@.�����h�����zk����
a<Ycl!���}�[��A�Za��7���o�w�e�p<���_8�a]���<�������c+�5�n������������k�����?�G����^�����^D������*�zV���n���K�JE �_�"f&w��!l�*�WL��gRe(]<x�a�v*t�����[�wZ��7j�\z� �����>mt~��X3KM�q9	=O�l�L:
�L����p�u������1S�T4���-W��;T��9zB��e|�fu����H
"C���4��V��*��i�������\W^��~��3t;NV�z�P�'/8��W�#���	z��%�acgX�~�<Ilxm �ct�����vQ���\O�����2hV�v�l%4��^6K�Zk|�5�I�tC��oR����J���v��l����l��{�B�?�Y��
�z�mP7�<���n��y-�&��.�����Z��oV���Y��Y�~���,b��d�!�tN���������Cs����b%|�J6��J��q�k��N�>���^�7�^�h)��$},��������{`��b2_��,�W�����1�a��[+E��n�;�Ww.��.�zF)Ny$��$�#5*�cFq/@�
tx�.���nt�~������j�����C���J:�2�F=
�GC�z����))��)��*$+:?u�'�!+�N��-��y)3rZ�p�v����H�;�z��tS�������A�~}�a�t�*y�0\%�|��zCN��OZ��8���J#S��q��9:��\�9���j�[�Y$���,JChg�na�h��n��������|'���bqO,��<���H��A�[h�R���1�`��9����[@NZqz
��a8E��63���E�'y�N:2��
���0pL��i<�I_����.IW IF�c��f�jZ�b�i���x��)R�3w��3���R�,\��\yR��13"�=U9��6�����+���	{y��}�Dp���;@����P��7t:�z��s�����Nc�=�V
��&��-X!;R��I�O���WN+�O��uT>��F����>S���� ����2U���K?O�Y�Kl;j�Q�Z_��_���U�!��h}4��z�VY������r ��$t3�-��-����?�gx��G������V&
�oq��$��o����O������s�-vC��1�;����|%���F���)���D[wjooO�0��=U>y�]����q{w����7�����u���m�6��m�����sG�'�^�]vS6s����V������e�u��
�!X���=�X������s;����4hf��$V0O�R��p����{�����^����]F���?R�?��U,n`*�s�v������rz�&u
�0`��]���_�4O)��D���1[weK����3dI���)�Dg��������`���������������LE���^�<I���]�U�'1����M%pY����w����!�EH���,G�g+�DG(���$�/VG����6���H�s��*�]�P�;YB��1��}��bL���/!�����%j��CC;r�	�6�/��[���g�2��)���Y�q���F��
f�Jv��|�u�`�t��y��|�����x�G��FBK�j/j����~]��&'_����n3��t�7����v`��!�4�4R����j� �����������hA:�����L2�H�4�0c�P@�f��]��}H�}"s���	��tjA=p8�K%IQD�S��A��i]���b��'��*���OD)��b�+�Wzd�����i�+A)����H����i�e$��w����������+#�y�>�&2�������ptGRi��R��d�S1����^3���pQ~2�^��&��[���l������P�'6-��rv��7i���H��^lj��>�c�}��� +.�^�$���q��z�i�n��q�����!_z��_�.�]aS���������\�5�k�4�O��a���m����<�7���+)����{�ck�����x�X��wF��M�����y��n�+L��98_b4��i��n��W_N��N�?�N������}�N��Bx�<)V��������r�D3��I������d %�8����0�Ku"�!;�^�:b��|d+uNL���U�M.q+d�8�L
f���H��_�<t���l��-�QQ�E=J+�k���S�KUP�KU6u�6�Lv�$?�Y��[�#���;��~��g���m����0���8������Q��q��E_����Rfn�A!���-��K��@�!�c�d����a��z�N�N�X�H1�����(�����A����<=;��!��V���S��A#��{i(Qa��j-����?�B��Y:+{A*7�z�~���(���O����FK
m�pc�`#a���3�S7�cf������Y���V�l����C����<	����k6.�������$0�	.o�M�c~k�N����1�|���_;
���|�1�i��"�RNN���2�Z�g�-��O%��2b!��hU��i�ZPB��R�$��X[�ltv��8�8�2�
���������A
(z�{r�E��7#��G��x��K���x�Rn���J�R�&<�$�����x�������-ZXH�>�[�qf����������MX�}@P�Ts3O$�SP]��c�s��xx|����Ds�/@���vI�	j��t���$�&�}���_~����8u'dc�ab�E6T��y���^��n��83.�����.m��m��4��&E(]��Y}�7*�3f���S�'
|{�
.����x�Y!G
D7�G^�^��=��(�x�ClQ�q#�Z���]�����*�(%��~��_�.�:���NU1��\�.w(�x2�3�|��%4�(R�X�}0��8��)��]b:{�E�,������P{�����|8�,G�3}N���t�������W�W}A
�K?��|��,���Y���[t��-�,�6`�/s$t������m��2��t
fp��U�U�l�n��6������e�
Sm��X{<��Z�z��O�]��%��l�g��R��-9R���P����@��N�N.������D�����6	���L�jQzT�cWb��|{~�]�������������{i���^M)���:��������1wnf{��8R����-�Cu@r�A����u�w��5fx��H@�W�J�qN��^0��m��#�A�]���_�zLV��2�<�}b��Y�����?��85�"�V�@qI���*I�#��F�������x��E��6#�������
�N�Q�f��'�����	RR)R�8/��r��kzL��
R�Y��j
�^@Q���B�;��it�]���S�5���0cG���H"0��[
����7�}��Y���rv���HV^@ �po���?���72M����I���d�`�Qb�i���7��p�a_�WsLFB��X���x����;D��Q.����'�����JQ&���1xuh���i�Oc�q�����Rw@���p�e��6L�����|�OG�{:�h4Y�
G9���Ci�W�������e��+�}����&��>=��pdE��9����*5�J?��U{�(��&��[;�^����|���`�k�Z�h)'9�;*���K�'yG:C	7b_�5��&��X��oo\C��9N9�?�f6�`�H�?�p��(�^ 9�/h���e<>�%'��xog �Q	��m����UT���a-QgtG�7���������|��g�V����Qk>�����
����������������b	�|]���l�
��K=�������������-1��ZN����E�"z����R����h�A�/�6
g�|]�3	���X���o QA���6�T8�����h�P����I4�Rf�a�9���r�pcc����:~���I�c�*��*�B��.���}�4P�#���N����J1�tt��3��:��xO�)A��}���6����' �"q%�X�X� y#�x,�!!�4��Y���\U��Z�hx���.�ds��%�,������J'@��S]iW�'��NCX!Vv�3?��	�/�6����������x��[u�k���(��R=�s:�0���� ��df��tP&a�^��D�����IID<���|<t�A����Y<'�Kgy(�$^l�Z�����	��4�����mR��U}YH�|KA��s��O
��KiV����$j"����X�3-1��lp����������OYeBl4�X]�XD���T��;�T�����e`��r�<����}yr5D�����W�:s�:�WL�}��]e��ta0&dl����4���G�\�Y|���1C��8E���3�g@&�'q*�2�+�f�a�K��H�r=���"yO�����uI��|
<�M���4\��Gu��||�%eu�](Y�o�I|������i�a�f�i4��b�h��Vh���H�1o����,�\�VB�"U~�4GXv��\#5F#�kI�(]!t�9ve��l��*N��W�����HKd�w�(n$y�JA��0h���;j�]�v�e�}//���p	<�;���Xm��J�wz�D��%������os~?������L'���������O���K��������]�.��@1m+��h
,�;���z�z��������L�D,�.���	��IH��4T�	 \~w�����������DM��W4�8Q59���;��=y	p����6Gk@6l�=h���a���y"v���������j^�])Y�=�8d�]���������\@������i?����a�Rv�-eE����	�e�����J
6W������za�a�����@y��N��N���;Fw������V����*,����W����_���*���(����2�9��8������`1H�H�K\'��1"@��!I�y��D5�m�h)������.����s�(|�����RWG��q���+�H5��Z>��dq�zp���)I�����-�_��6��d�/uK
n���}.g��}��m��w���6��Xs��.o�������n�J��l�P�?P����d�c)����Xu������q���;0����1����������*�x?��t
����&\m:�K��4�f��J��C�p-X�*Wio}NM7��aQ�t���������w��'��.�D�x6��R���8��@`�b�(�BO�q������������|������,R�rf��������y���"5��/1E�Z�Xiz���+YH-Vu���������8as|Oi4z������3?>B��"�#�E��-B����39�M@����b���}eQ��8�+D�����N�#2��Y�D�s�����xW��U�?Y�mZC��M��oh�5����*���N�I��9����G��c����
5�4�9��e5(,0'hC|�?��<K!������j���t"H����U� m�7���K&$��)?�!�tY/��/�����7�J_��E�\����G���'�yJ
o�+l.�S���<��!�q�c!�p9l�;'l�.d(�b���p��������"��f��
R01�����*�X�C	m{b,�����V�L�?���X�f��$�5�u��������{�{����F�aNH�Q�������RE���9�:��2���Z*�$�<d~���@��T4
C�n�#e�I��R�z!�S��b��4������JKIr�/N���	X��I)�hPD-����d��-mg���DJ*'�O%��nz����C�X���=���j8�y}�$�Cg|���W������o�4f
C����>(�\�`��J�N-s�Jq���)�!�(��%t.G�v"i*���l�>Zq��/��I�C�[�����(.�db����5O�d�����-�+O���5D�rp�N������j9�o6k���V\�8�f�Lg2�G:�x������6jh�����GA%m�=�M���(�]�nlRn$g��P�A���+j���+��83h��|��Mkj������t��\�������	`�
���(g9TOr�+�f�!9����o�$'����� %q�QG���$AL1��qk��;9����~�-���JE��U���*��H]��&6�b�]������]]5!��&�<o
c|Y	9�	��W:��0O����Q���Hu�&R�S�>W���
��:�������cGg~%�x�~��i+x"e�W�������#��<����p�Q�.�;�,q��H1�q�D��|LM�������OyD~y�*T����G���CSRu����f\�d���goA�s:����|�oK����i%
���nC��s7�(7+��9n��V��&�-^!��T�n���5;�vO��X�P(0{��Qy���<=[]l`�xlF�`�S����<��asyO
��?��u"������b�*�����M�Y�$�&
�i�(|?X�������S�X|g���oe(���H�\6��j(3a@`: �!9�����6��F��Y��m% B��UQ�J����S����_�"R�X��#UZ�QP��+0�W��P]d�������S�}2��W"��R�����f�waU���o�|�
���r7�B�`4n.����[Y��L\`���/Gn��������I>&�8f^��<3�++�L-3�Lmc
���2�M)dj�R��Z�]RO��.U?�A�H(���Lx�j�e)'y�<���T���[����Ya��
+���[9��r�x��������p��OG�)�QMC��o�M��&%���D[w�s�e���A��1�`��`���0���fz���`��j����U�}��?���������?���zu/������<��SWs��_�H7����������r���T��u�5+(�u<J��H���E~���p�GS�Z>)��B�6���1�a�/�7��Wi&}�t>^r�r������������Z��K�a��X;O�~z��LW7~�>L���
�P�����`�<�8+"AlK���n���
�V�Slf��j�;Q'�&����T�%���j	���1�����'����-�'������!P�sR���3[���L�����Il��:�j~����S��&k?�1����;4wn��&���}������n���.�������#/���zv�=��s�6����w���,n�/��<���j�����g�;��4G\KL����!�6k���z��L5%������	1}��R�������������> ����",cTGF��lo���",��^��y���1=���q}#YU�v��Z�SE��9�X��;��Y��-�L�};��cLK��e��4N������[��OP�"0aK��<X��J��5L|�u�"X�S6����a gW��I�>g��v�����>�A0���G_H�k�"��;����?8hU=L�{���
���RF�>�x��T��)�d�	��f�i�A�cDL?�O�,2����?	� �rL|t��:X�q�Zc2	���;��g~=��%��
lr�I��!�q�	H|��� �Jg�y�m�t��lX����1�xT��d�M������*(�oL���f��{��n~�r(q!Y;��������K�
��v����u�jr&>&�S	yh����'����c�a�z
d����:9���~�������/���F� ��8��M��� ��e@��|)Em"����\&� �|�����l�i	A�D�x�\
kc~4h��A$7��q���D�D��������<�����T�� jl���2};�E����<�;]��(�*��j�^ct��1H��&��xDX-��^��Q��<�w�`D���:>p��sTF�<��<\Db�'��S���MZ��������o95:tC�.K�#�X&�i�8�����4���*���=�-Z�~OZm��]f.�����q�3�����K�d��������M���%���~���bm�����h�Yc��JW��q`#��Q�����LT�T7XG��5�����vW��M�5q��5�5`[��� ��� b�\�P�Y�[d��������2����|�����r6dV�^��d�����X�@�_!�HS���wP�~6��o�B�4yv\�G4�z�(������V�����r.jx^q��
���c�p���++\
��� S_[����~
�T5H�U�Zu|s�������c*��5C�������$��>J��js�n2��h���A���~W����Qh�R�!z���_H��T���i;u]��+���\����1�������	�2[�
�3�Z]���7��4�����]Q5d��&��Q�:5���a��tq��h7�	�w����r�m�Q�I��}�J-�^k�
P�C!�(�� 6(]
C���+��j�3E����E��~�Kbtm���`q[9|c��~�	��^���BC\����6{�>�
�E��\���oR�v<
�:L!�`'�;�M,��V�9�����@��U����]��)r�wEl^�N�'6���p"�&�|�*
�+��&(?�l"�u�S�/	%^��!*S����!��kt��e�;���d/����T�bj�N�t,o�o2�Y(��E�b���w�v��$�MNbR.P4��e�u���.��Nt��AZ�����!m��h��qfk��G}�B��<OI��_^����a�~~��cA0��Y�
L��vB�8��Y�4:?�$AF:������Y����j�g���/�^�O5�b~,�)����^5���I�u��1��
d�gT�����`�P�D�/���f��J��x ����/����0S��6��I������P���)P�E	(���>DC>��,,�k���kqw\Y���'���pb���i�S���k�N4�������n���D@��(��;�l���P0�3��h����Z����%4��q�?����21����b~&����J9=�9�cl;m��w�����=����;�9�>y���
����nH�Ro�SKDT�z���D���gK��V����+8�+�?�*����AS?=m:+��	���7V�-q��h�����&�1#4VQSa���N��8\�N����G���		p�W�,/����ph�
�5�}`>
�2u��C�S�fL��"�)�	?M�[�$6b���
��T7�;��&�[��5HCT�$�C+�5@�d=���� 1�d�W��Q���>&��`��}��[SF�9�>aVPf��"�����)�ufn���4Dk��"%���LE"{��DQ�SdG��V���*(�����R�JF�����_��1����+�W3�#�����K�zc�cl�@g�f=^`Bw	�C�K����	�ab>!�Z�����5��k.�!�Pj���z���-E�8���/!~5f�_�0d��u����g%'(���dW��$�e��r�%<]Q�����#���!O� �Q(���3���|~�G�?Iw^�$�F��T�j�������I1'��j�V��G-K]����#���cw;��Xi:��v^:8~E�8�T�/V�@�d���E�c�������e[Ky�&���d�B+6�Qr �j��b�r�W��kyl=����O[�3����<U-l����YZ�>6�,y� �-?��W���.X]J��Q���8��G���1x�����=��o�Q<|k�x��7.�+��|3�{�c/*�kY����%��S�^�-&��W�����^��S��S���`� $��^;������YK�N��%B���������L#o��c��9em�->����J�l��@�������q�Ya�i&_�Y�N�Y=h#!�4�j����u������n��������9��A�Pm��O���Uf_�*F�Z�+r��_�B����"o��[��>����(?������hN�SK>�5�Of�g��=R��G�?,�T���AK5��bM)~gXp����]�G���jW�8����0g�����V�=��Z"�6�'�Gs���*�N,�������Oy{^
wC�
j�Pg�����V)	#��9�@�4�)��Acm�H_�l]K"]��H������q\���������	+���g�'Ue��}��2��^j+��:/����U�������<�X��$�b���6��z��I��"���5�$-��D�j�z����*Y�G�E&��z��$�e'	�s���Q���'h�#xs�x7�%��p�j�VbpReW�t�����N��'�X���
��>��X5^��%{�NB"O��
�!l�$)�I+��2��N!�R0�^�T����v���Y)���F�����������a�g�>���tj7[�V�b���3�
 ��!�?&�����;�A$N��*G�������I�����
{�|�L����I,���[_)x
V���DpG����?��KB��H�b��Tq�������(7�-%���O$"�i=�GOx,�h=]��PTO������;�8�H-m9�>����9%:!uy�U���k�+����0|�	�
_������w�<=R�A��s���
����Jz�U��3O��1GA"A����~��^�����`�3���>�@�%�o��������-������}J��yO��Jr-
H�e�L��6]��.�u���%#�M�EI�G�J��T���:C��d�|�`������!.��.���i������o��*.1:�3��y��6YX����B
W�����L�N�^���J&}i�������f2-�M���a^�������D�F�t'���X/�e	���b� |%�f#&^���"��\��7�������0�*�c���T��D)Q.��lU!�7�LDl���j]��W�p�Wk"r$�gu�+��zv�� R/������5p�0?v��,iE	�I�k.�y^5�'��qVZ��Z�j�wI���jo��X��CR����L7r��D�-����(y#_U�N{J� ����XX �M��k_��L]b,
85
��/��?Z��;�LI�����*N"�/����j}H�
��r����2�/���A�Yh�����{�|If��3��q��X������m����n[Jbc{��5��9��z�A����]�S�jo�B��jF��M�<�$[<���r.��<��;�\�xzI\PtO��r���7����p�|�����*�!j���1n�
���I���9�Zb��NO������Ey"'���dlWv\u*������G�m��U���?|hb:�UeP�77��C�����u�,�B��%�3r:�L]�������������^t��$
km�\Y�b����wf�T�(C^�I�����h
Ue�hj�]x4{�G����+����E�;T��E��������������������I���A��He�B�
�h���1)��Ty�F�%�����#�^W�{���|Q�W�Fo�k�6���p6�E�b}����+��a"�2����~����eG%�9T���"����:�x�';�78j�1��������������:
�.\/�r���`%lgZ+`dr��2�K�=g����Rs�.i*���{gz[�]�fa�,�3���7]�9NV=J���yc�#����.��T%�����+��O�v6��Y��B��+8�r�X�k���h3�M��2�
�
�����M7���Ost��.�:'��5����y�����A������7�A����B.k�����f<	k*����
^�D/
��*����)����'�Gr�w���>�q��<W���[q�0��a��+���2�AI�3��T7VO�l����Zaza�����Z����09���;�����`��TK�.�|z�2b�TdVj�`V�XIH������K0'K��E^,�����v�I�~��c���D�_3A%o�\7���t���ED�?l��Z�-�A�(��5�hc�4��)�w�+�_)q
���Y1���yo��5���9�)h��\��+�G�[�RB%����E���0�L
���I�z�G1;��j5#��A����VT�����
�	�J�Ho��� ������+��4��7{��p�q��1���{�e0*a�ng !2E,��)�I�"$�yy>fJ@Y8�Q��B:�s�}�e"jW��h��=]�g���e�	�.$��5L�����[517%v�3V}�N�1�I�s�J"@����.�����b�R���{+pKE@��.�����N������;�!Z�������Q)�e��vC��u��
)%1�������H	�V<���e�.�_� �=����_3��;���V�R�-�r-�1�?��4�r�X�rG]%�a��/�?e����<�]R,�e�������i1O�������($����Z��3�i�r��[�4�!��+�_�;\�~�i��&"?��*fB�������Z����X�r����O�~����i!�t#�J+��h��\��t)���r�YC���*M��y�,�{+�������p$���g�1�a����z��X;�)�1r�9�|j��@�P��|e�����VG�� �7u�M�=V����{'�����{'�c�Cqs��W�rW�3��M��=������j���x �m.T	|54W�T�l����.��S�B����������8K7��W(�'r�S�y��p+����XM�L@T��_��;�(z��+44��U����V[�P�8^��O�%�j����#IX<_�g�pc����_~������J5]��+4����Y������K�W��E��]�6����������f���9�o�G�5~2�}SX���P���jD�o�����Q�#a��%v��r�T�i��#�x�h�1���'�R�@��xO����j�>*$�Ao+�E�;vN�����d;����A��<Z|�y�����hk���3K�1t��]�i'�
��{�g����3��?�<�e-�^*���"�ez�\T�9p�b������d���W"n?a4��A�������%9.,���v�����	1}�2��D����;���c��f2�NY�����MbAm����:s���FN��$�c)p�m�X� ]��������@��M��c�\��g�,��������h���`����8�����y�F�p����Y�`�������l7�{��6�����+����
����"z�{���X{�xmY��N�`������hG�������-�`7�%���3����4����������i
)(e��c������I`5�HF�v�M���`w���Nr�}P��%%v�kt:Vd��qhO��O.��z��Uu�O��|��_�[1\��F:2i:{�0��q��WI==g���4x�Z�x��:�����t����u��k���
�L������+j����������O}��a�D�2��-�*�md�M4O����U�
����9���.
��cw��O
�O�+����jxa����|�l���7%�u����Q4�^�$�A8�xa����13>[s����]I75q���������<�Il8�l��o?A1����|���S�4��u3����]�N���7���>�x�������[k���=���9g;�K��6�g.6B:Wsv��r�z�M�����f������p�Z�WC�������~�A����Ol�!6V�|M���i����\���s���Rhl�Tg��^��w�SM��a;����C�|�2��j��0]�me���S���;^��=9��:�1�`���_�

��{����/��u}���6)�YrF�^{�����?5���l4z�N	.N�����������]���{~E����5�`�b����"�G��Hc��!k��/��"	r�:L��_-���,��<T�n`${
�g�����/������3�wjX���J1���������f�c5c�L�q�NU��<����i��c�M3��Mk������^o
:��7.p��A6�4�!�~�OH?I� S�0�q:�����A�+c2&�9����|�y2�<��kyw��}�G��X^`m���^8X��S��8!G�#������e�<�� I�_�E:�i�������0��8%�,SVQ�ebul�Wb�������������T������������cN��'�g2��7���c	��3;���y����'U�C�u�:���>�XS��Gx�$��:;��&�D���J7���:
��?���
Z�{|@�n�����S�)�b��c���t�9f���S�2�(�Yl���M&�<��|�r������b|��%:�A��45mU������N����kcig��,�]bqU�c�1�t�$4�A�X��)������}|h��~]�h�&=�0������'q'���qo��X6���:�.�B��n��oO�u�?q&�T9bM�(v�m�O��x����n�����1s��5_�����_bs��Dh��Y���������Y���0w���f���3&�!y�������������"��lFr�[�&`�������_������s<�����A�r�����*FJ\����^��j����T'��4��s����3������/�)��nO����
�DE�����i�LF4D��c��s;��Mp�qz5:8.������ ���<��"�����r4��^��t>	���:91-�
4z�W���x��aC������a��?�������g�jTU�(�|b^�i���v������@2N<�R������MFhA�zv	���i��v���.�������7i��x�����=��s ��.�A�t�
��w����GcO�������j����s.o�9�U��e�K��{q��:�~�B��������LF�z�9����-J��(���j��&���a .Y����t���k�W�.��f��+���-��<����Q1[��+o�����(^T�F�J!�'��7�j�.�k)�f(I�hi����o���������%5��I�'#H�Sm��}����7Gb^��,OJ�-_���}���T�I�-E����{jY���2��>��*K�>�}%
46-�v�w���WF�$���'`-t �����p��I��.��]�#��[��n����~��y�zw����A�K��6�
���5P��O�m�1�\����O���xL<,���n�oUg�����!���w �7Z�W~�``^����n�N��o�f���a
��l�u�6�Xv��������mtEo�e�eP�(�M�?��@��2�_��c��m�0*ase����*�����Cnkh�8����2�"e�W�.o������9�����Q�[������q	tu�w��S���<�@����?�?��1�S��i%P���"E�hY@�+��F�89��^���������!��
+|����?7�
��=���~�����e�������
z��?a�_D1��%�7 ^�4����<���F�z}�4��NA�g�������"#w�!H����\��
36�P���z�y�D��d�{��
��4B?O w�J�'x/7�Zf����@�C��wP������xyD�j�$�������"5v���bl�C�O{����"����taC�L^�V�����5�!�|�3��sQt�4����"#S�
���t�A<)���Z-aq+�hJ�q���H�y�����<�[f��_��`.��������E)�2m'yVK�y�Q<���'���:^Q�g��������a����6���;���a�����`������N�!Kx1[
6�.�H�{�*����~)��~���~��-��G����H�5mhJ[
�'���~E���.�oF&�����7���z��t��~A4�G��@t;��g�q'�����
ZsMs���������.�4���J{���:�@�-�f�����x�*E������hE���^�D�����GI�s&c��^�������8U�����L���Iy��$��l�t������o�P���Q�����}�;hVX�C�y�11}������~��l������������+h����!g�)�<�7`8��FX���]�T��X\26�o,��Gcq76FC�xn�4��8�N�o��%�e������!����8��������J.��L�$��T��EuH�.��b�m�&�p��
�x�q������A��@i�:�����R�S�2����u������{z��=M��c���Q�1��D��=�R�mO�b ���l�`n!��L\��v�#�����~�����?��&e�������e7>�]�,L�!�G�3Q2��D����NpC~����S~���g5�"� �hi��%�����S������zJI;i��s��\XW��+Y������>���R_��X��$��Yy��%�@���rZ�>�SV�aI~7Zx����
&C�/x�z��"��� ��yL�!���nZ{'����&���y�M���$
4�������0YK�\���H���]b��t�5m��8�"w�rG7�C�tp\L�M��o0l,���������T6���a�8~�O���M$��������Ng�A�&� o��o=��������l��m�
�-��^3���D1/Jt��;���>N{�g]�L����ky\6Q
�5�����*0�[_Q��l@�q`���L:--�(�z����%�L?@�����0�
��!Mu	\��H���=�@J�q�
�<���P�H�`,T��W�
�-�1�>o�����Ff���L���I~-�I���y:/1�)�7�����������s+a�=o�O&�z�����.l��S�5���0�g?[-���`Og���0���j�,
Hn�`.�n�x�����r���}��! ,�o�2��{z��������O~~����'W��sy�����2����o��!=�����;���{�/�x���1#����0Z-��('�'�x�c5�������/1O��
K���Y)q���$��q?�8V���8X��k��[�z�u@lc��o������&���g��a�8�Z+��f������%���O�=7*f�'��
����.����;��axvrr��0$��$������������a��^g�0$���8�������~�Ea��Y��nk#�87���r���l\�������\Z��(#�0K����`c0w#GU���js\�2�S�m��B<R��Wm������ ���=����������7W/����NYH1�}�Nqb����Vv����s�0�7�s��w���=���o����s��������w�����)�����'. 0�@���z������
c �Dh���?���
7o`�C�7���`�w�=��F�D�����,�qq��R
��+�'��e~2X��Ez�"���+f����1�o�h����I��Z�Bd��U4\�WLl7i*��(O�n��������z��lf����N��8|s~1A�������b�	���#&��E�h���F��������~AQ!9�y!��R����g_>
rB���5y�X��G��	;�p�4��*/++�7)?�->>��t�+�/+�k^:���l�+E���a)l��^�U+C<fl�M��E\�N����X�T���6&OA/wW+�l�i�F��h��p�Nw�,��/9P��h�v���>��[���B(k��~�XV����]��h�_���h.W�������&yWv� o�Y��|9������%������^����r)T3�e�I���/�)����A��������g���:B=&][/�����E�f�G�xV��0��Ri�8���z]S�B��U�T����d����i�
�(��B,�kX��Xa�0�'H��3Y������vCH������"g���M:e��
����D���A��1P������w����x|6<��x�{�N�y��:�Xa9](�������6CO�J��`���}��l�E]��q�@����k�RP>
�Q
�������
<�e%�Q"|IH{���A*J�Y��C��69�$�nrEIz����~�e�{w�/3{nXYI'W��T����H���{�y0���z������&{�m�n5&J��y�jF���{a�i����]�D�����&D�,U8�*���%��,�j���?��b��lT���9���s�����D1���^��2g�����*�����Q-�
��|�n7x��w[�A�u������L�fSvQk�����tRH
q��o�c��N��T���1#��$c4���=���[�h����[.���a��0������+~�����|�Y�H��8;sV���~>�6�a�gnA�>�6�&%�hX���G.:�����TT
�	��v	R���y�b�� *�>�7��K�iW~�!�7������H`Q������|���r���'[�0n��-�v�E���P�����cT�x}(c�2D��B%�.3����$/<_���*!1��DFX�#4$Ec�9���
G�k�$(�T?����?�(}�J�Q�����l(�]S�T�Q�:��R���l)���^/��j" -������R�C�g&9��}*���V��h����3c!O�|~�'�`�:d=R8������6�Z�L�6���K��*��d[�S��rI�-���P�K1Ma
L8��|���S���;~p:�\�Z^�y\��US�7���@Js�X4H����E����@�?	o��T�R,{X��#Eg���Z]@�U�����i:5�~��+���D�����S[dl�GCo6s)m5���o$���A/��3	�����	t���%.������q
X7��PiO��iB�*�c���+��I�wfp7��4,#@��������83*AZw������|a���`�K�\����������>T�U�Ls��TA�YQ��-���/^�Z+C0qq���Cq��Q�Dk}b����"]������f��.�|����s�kE|s A���pU��O��l���p��Mf�v�Y�}X�Q���
'?R�V7���wt=W�?��W����
�^$�8�P��9����2�UtvN����n����6���1�."+�P���1�_������l!�����8@��������9�\���(:W<+��D�n�����7^4�|���"-����f��v�c ��GY���~�2��}��m�L�a���8��pqvz�������<X�E��_�7�9������#F�@6�sN����K����.�U��g��Y�6S�p����z�j[����u_,:�Q�\~x|xu�x�%�Q�0/��I���j�IZ����y*�k�)?�.C���E�
���}�����_��_���"��C�O5w�A�~�X1����2y���<���a?��������q���P}s������`v�����4��6��8�+�,~���Y�2\��\5f�)kQ�S�B������r�J��s�u���7_u\�3
o�� Z���+zr���9���������dO�K,X0�_� �*��4M�o��>^�<@?Ql���X�0�\�z�U�_�s��Sl��-�p��s)U+S�J�QU.��v�o��^��fp��)[�3�a��|���of���O>�2���J��x���l�%M+������(/��J*!��
T���kf�`�w��1,�����%7��}�����������Pi�w�����-�E�o�I.�5J����;���YO&xe��S}�2Z�J��pf�|S��8X+�[N�T����*�N�e$`�|l5g��0G��I��|c����'�m�36~/f<��@������`��3��;���{��\^�����ch��R3��R}'��\j$�-�h�7�'��\�,vl�[�������2s�x��K.�r��9O`�4�
��CDa9u�o��R9��������m�#Q}�A�T�fqf#��k��Uz+�TlcruqY|�^�5�p�g����\��2���U�qjI8<?��u>X�&�������V�BBJZ,@�W>�w
���B�#4x/L��:�Y��53b���g
(�|
���k��C^�T���G��_�%��+���z�f�h���%���g�<��F��U-2\�KV�|��s��xx|����������y�c���h��X������b�����jKB�N7�\���KWGq�<s���8�P
�����_F@���{Cv<�\?�����9�m�>����:�>����1���4?����Z+_Q�nu7\��]Q
,��X�=���K�4==�[T�AIF�@!P]x��]=	���N���?�'�1�)��C{1��=�S�"�����<�5�a}��m5~�s!#="�_�`VV>���y>@i>-v0����t~��y�h�Qr�G�/O��(��7Pp�h�9����;���g��/G�Q��Q�[����7tW�p{7n����q�9]���y*�d�n�5�$���������N*���������|-o����U%{����F����CG�}a>�U�����9��A	v1���h
��(C1���'62�:����{L������YGPs
8Le4	E�G��0"�)e���I+du#��M�
��CG��*l���f����@i�I!-����������������$0�6rs����D1�I/��#6�s��(m�(5�u{|���d�����m���F��]U�+��3'Yo����S�u�^WR�{���M1��3w��N��3;�r��^��Z�z�����qA_��!��\fw"m\������eL=�t
G��n+-�"Q�V��UaG0^��H	���%g�����E=���}*�����z4�u��6�tv�o�1,�����M�pK*�������z�z��t�E~�q����j�5�H�b3�WV��6b��S3z�(���v�Jv�C���������v13���|���O�F�|����vir��*�����dr�w�Z�~�<V���*P��7�l��{=�ku��q��-x'����J�-T=�k{�����_w����h'*b�hv��!�S
L2_�Ir��Y#y���W�� rq��sy��D5���"�����?�g������?�^���
0��$��`]���(������6W���Q�w�.X��/��*5� K�g�
+PZ	��n���?�1'�1W��-�p0�����������0kt���&�1Ww��Y�f�%b�J���+Y
��6��6u~��<p��
��Q�h,=�Vh�veMV�6�I(�F���`1���.�>;�v����t�>�v�l�����~����^��E��i Xm9��!!��D�:7%+���������M��� $`�v�|I�e�|�2LFY��������	��Y�r��Cx/��	~`��K���H5R2�7j�@�;^��+Z8f��
�g��U������v|u�������_��o����pV�[��D�*���;������M���z	���������@�2��x��`8��7d�K���R�q�4�JM�v�%���r���L��rF����;�b_�\��~wx��������43�����;7e�*��ro�-^��z��7n:n�($���[1W��|g�iB"4*�?�n9�f`"��}Y]wv�i9q��j��7�������N����-�6�/��C�����������D�;/���d�������t&�n�.���v�����l��!g�%��?�������\��U�t�u)JM|���9'Q�O���x.��'��f������<����k�1��R�[�o��B�y�.	B/�pp��@��r�G�PC�x��^�<�2��rAN���D��8J�������q �����s�:c���Q,XM5�*|�\������r�'n�yp��������&��~����1`9������b�q�-M'�������\g��&���eH3iKH�5_*K�)�)Kv1�,���J����]�hF�m���	7�!wp����z>�~�M�������t�w�Q�Q���\�ds.�����������rY���G���^��)�,��j�	���l�x�EH�}�/�h�,�Y�;������W<��<D!pxn�j���F���(�lu{��)��a�����9�\���o��E$V0�"������/��*w�D�{���1v��(�f8Wm�������v��O&���@���u;F��"�����Fe�x<����[P��i*;k��r�)���J���XW�e��g��
�^o,��E������V��	w��X���g�ka�V��8�����Y���d��d|��Q�,/]'�u0b����oN)��N��=vw��q�8���x{x}�����
�w�u=@�M�0>�1�@[.�����=*8M�����m��������z96+>8�8q�422	�SJ{s�?�N�E���c{�L��V�|4�:���"n=q*�P5�����i6{nT��0�W���f?�ZfF����=~U������j��s�q��k���AV�lA#��0Fk�1�cS��
N� ���}K�'�����9��f��v8����
g�a�tg`�Q�+7�pl)�LT6��l�*0;��:�����E��n$�/��a|
M�|A���)��8|wr�����lxqx����/�������/+�cGr~���pyuxq5�p�����������������o+�e�5����5�����?N���O�����9������#P<���1�n���0R�)�G%�����o9�8<**���Oq9w�x\^Av�>Q��RJ���]��d����z��6]���Sr�m�W�9;(X��(��m9M�+�_�w�TW�]���X���L"j����Z��I���+�����I�����n!�_���t�(��<:|�����?��O�k�F�F�<��V�j	���	��������G��4YO+�Et���.�]�h�8���p��Pgq�<^.��A��U����p@�N�2s������1*��T`/�x�$/AK���l�hy����������]���F*(L����A�����g�
f"���$�+���3��Sn�����|O�q��K_$�_K�c�gXS9v��|���~j����cc
��?7�Bb���cs������~��<�����L����~=�/����{7|��������w'�dT� ��\L�c���p=��ESs��x��`�^��,s�#�1D~[��yZ�|1��JL���C�����;�fQ�
}GuZ�SNI=�ii�����?#_��nqc�����X��:��.��2t
����"�8
��z���2�w8G
Zu�"q�I�����K���o#���F������q*����@$Fw��;j�����|�������!�l�t/Hr�/����S������;�:�`�:}�����6^2���D���_L1��������)Ydy|���G�9��U���?�\���Yt]~2�P�e�F�������������D���Mg��hD7����h��~�z�Z�5��R��l� �:��j����&�	Z�mx���/{zX�����$1�A
=C9�5�����mE�	1��=a��~�����9��k�����Yv�9|	_4^��;��/���{O��Z\~�W\����w��)�����j�%���n�>i6��7V���������;�Og�������N[~��/���w���Bldt���ii$eu�������9pR��������j�!K��H8��	����A2�'tQ*W8[Y�A	�z�X��XL��\�n�9���+����(�����5"�px������p�x��F"�(�MF�����]�i��#[Y�5�v~��Sj}NKJ��{F	��p��W?!�!&@�#�����<Y
�$���k2��*�����i����h����st2�W6�r{s;�D^XJ:�������@��ut���@�7�+LT������	����W~�E ���������Tji}��5���YM��V�e������>Ru���8�����+H������:[�������^7o!	\����[�qr�/��������<�j.^,�9�Z�T���x������F{�����i��~NJ�F�}����X���N7��dw�,���������A�Vu��|�����S����'�C�6��,!8�Z5;��6�
���E��D���i�/�-/W.�t-��UJ�yy�������g���zL���z.=����_���iU~C���� �7�u���6{���JC����1������h���lz�#$�S�6�0Y��gS�a�����J��n\��Bn&����@��'
%�$E����"�]5d4�UJ`�/B��J�;H'��L�M8A�L��
8��n�X�Dx�! ���I0w�����|8;"���������X���p��8�'7��*���E�h$�����0����f*�U��@� �E��U`���JU���^��Y��!��������~V�#:�0�(@[��&`�Y�n	�0�lK��V*���A�J����bE8O����{�\������7�&*vs�8S��I�?��E0�1�&\a4#�W�m�'�	��!�E��CN��\Te�/�y�����
��h�~}�A[F��Z
�;U_����J
�D�|7�m�
�M�9�[��@��E������7r���dQq��+3��Gh�����o��;`d��Q��B����[�Ec���Bw�<��{w�^�h��aQ�XO��0���4��?���&��A����#9��l�\2'�v{4���Q��l<�&^S
)��sB�j��&s�p<]�%����F���%��s�R]��\���%ah�k����L�NDD 7������{�l����\d����X?�-��v+�p+��n��p�~�>���NwC���q
��f��������2t�0�*��F�/$5����%k���?����f�^�����.@�� %
�O&������FIQ]Xe��a���[/0Iy0���d]
��O}��G�0-��p<<f�;�k����9�e�q�����H���Ji���%T�a�d{.�b��Z��*�R5�[h8��D.�UcK��U�����S
3�I�s�	���IU���TP�q�%���,%�,���<����%���C��~�m��
��Z!�j����(�^RtG&c{[�;���<�Dqr����(�D�us�>n�9D#��PLX��y���[�@�! ���i���������Q��A����\�Fu���n�"���#��}����8��*�&�!&�hT��1���q����0����������{&x��"{�ub���c+�eb:d���RO]�2�w����������j�,���6o�z?R�����u��m����RkM(���\V����N)R�-. ��r������.���v���o��ll��-��n�Q�wF-�=��K�y���mn���^�����@�}L��=J���;�+
�y��=�Ft���?-��'�?���+�b������CQ(�!���#8����1����P��a����&������ p�z�v�yN&vE�q����7p�D��S���FnO�o��ez��s�����e���N<j��~���2��Mc�a(�BPGxttcsI+�
�I�9�Yc��	�tH��B$R�(�Q�r�#ZL��Z�%��I^3k�T�W�����zM�d�D������M������G���{,��o�(^�8b��]�~����33��z�U�*����dg�����J��O�Y��P�D�#�S��o)���.>�;����~�(��Y��?�l�e�nS��I�;��,gdF.dv��(�����%�R�yhL_��
�kSv����~q�*%�)p�U�\j���\�����1*�4H��B�����R�4�"R�����/\�S���������Y�B�<i
:C�����^F
�Mcl�gF+�������8��� ��s_�i~s���c�4/�'�)<�����nU�{_����k��5(��0�(N&cR�W���z��xJ���'�@U�;-X��������K��3�FlO��q!�����31)W5;\���6~��xLc�P�h�t���R�������W�:��������!ckA?U]���c������*+%FR�l�#IYfU��M#����
D������]�Q-B�Lh9�F�S�[u���Lc���J��R�S��bt������.�A;
��I�����<�21n\�A���g���s���j<�4��y��8_��h^��/��i������.�L�����'��y<�g�_�+:��0�y)�;��A&�Z�kq��fy'�5���;���x�����TI��Q���^�m��<������i�?]�mJ�C�,
F�4X���~Ih����3��Gv<����BZ�G|�U�1n\E�xl�/Hb�����I��+�MTk+��Y���0�|	<W��������f���+��Y"Jz�c���q�bv;[���1��x��&��'!�E����'x<�H�aX�
>K������n�K#"a��R�M#�n^��J6�\-�^?\>�Ph�><I���	oQX��I����U��A�`V#,�� B�������b�`��z�<����?�N��y�������r�(�����^�>)�:�����M��A:�m�`�ER���2�������� ���?c��_�"�}�;��5��=��w6�|�ttIF�IaO���~�3����EEgt�a
c��\f4� F^oI*taa��"C��:�{������}{������I+�
||,�W��=��;p���Y��?k�U������!N��5a��Sk����p��!�6�I[�6�c�Hz�T�����������+��������;�����^�b��}r�J�����4��O��k2��oU>&[�,9�F)o���V$q��~�9=y{|v>���:�������������^:�R��T�=����W���&Q�����t�eH�m��!��{���.n�"r'�H�I0�k.���������W�N^�R{YI�������NQ�'<	M��O+�t�="(K��x��9����[Gb���Yf�"�=��������I��N�v������=���o�����p���X����'�N��uz�����A����D���x��"E�1n��`�^�N���^��K(��z����!R4+�hL�I0��a�o��kl������q����;e8��Q�)J
Q`��o�8Mu��-�p2�����������^�$���n���/����������������7[��G���f�9 ��S������1��.V�eu�����05����	'�fi/Q �xq�+���E}<Wu���^�	)�aILQ@����h��Mru������^�S!�], ��Y���������.��B���4��ry���>���)d��1<9�����j����:��bu�{)���6�~�`����Q�����Lm����S�x������h�!���Wk[9�����:����������,N����/[���tK����F����I[�}s���4�[Q����w������l[,��a��M���QkmD�},6��<^���A��{��_a��;�Qfg�t��p�J����;8@_��v�Um�z��x�����\�l�C(;s�B���e}g�+_��:q�F7�u�b��!o��xo����t����m��N�O���u�{��r��sDb�@b$��Y��z��{�C����N���n�8�5�V���H;�:��wI�nP3��^�T�a�1�+Z�BO�����\�Sb�+�������J�R{�oS��g�7�??������}b"o������k��(�}t�_�F�����T{c�;�L*��~lhI���g����i:�/�.��#�"X��h���mq�G5��/���VI���	�A��v���cc���P�u^��SK��"mSA��%6������Q��q`
z���vJI�"�	?�(�A������W�m�
�O�i�^�x��[J�3��7�z{�Q/������a�������3���5����$
]�+��lp:�DU�������I:�����jm�V'���u��@���'u��8������&��sR���%Ks{mt�j(_��8�j�0�a�SQ��)�q�{��x@3�X7�XQ��|������
�.����%2�@���9h������5�b��s8���y�Vo��d(CB��\�F�}��?�{�3_;)�����v�f	�%S��d����P�7�nj���G���Q��I�B+.�>�Vv��]/���_��V��Y/����O�����s��`+zm`V!UT�g�b���[�o�9����c��I=B�
������ez��$��"5w���c6���*}kN�o���a=��s����w�����	��c�%&}a{����X�l�l�FO+�>��FY����0��`����UP�y!61:���\��
��Pd�����Z���55�~�Z����g��gxp[��w1�&��c��	|�X�[A���s�����~�I�-@w�����n���Q�`������0P1����m�s�e0��k�W��d+K������T>GK<�����.C���+��/������k�A���B�v{�S�ji&�
���<�i�K���:\@-^b��1	%xA������r�i��� am�$y!O]�]�|���%LNX�J�=U�	��(��f�	��[����J6�P����L	�[������yNU���M)���~6�9"�{�`���Vg�*�b
w���`�dD����d��MG�	I%O��bR�%��s��nk\�O&�;nfd��!w�nC!5MJ2���G]d$�R9M��0JIM�(��I0z2������s�����PWlq�e��b-0}���.0�N@��d���M���������w�D�=�O��<�u����{2��}���&��Z�@�"c��S�=�	�QbJ�`����'��2��,�����������ex;s��uh}�������"�}���L����h�=�������q�.9
�������Cp��	��o.U�^���V�DD�j���k���q�3���h2@���N�v^ik^�j~�UB�x��Q��f�\�zdKe�c�
��F�\��������������N����@�L�(�ut~������S��1�>�"�2=�kN�U��;��}��%~�Cw/>DFc������htj�,����A��;k�[�i+��l�S��w�X�^����~�a~�O����W��n���F����F��o���i��F��8��F7�U�.b����t�����Z�`��N<�9���X�����������^��y�\���w�����Y�a^:��G�7.��;�g����H� ��Q}�^����/����N���z�5�f�e���u��7��F�r=BL����������F�E��7���Q��2I�,WJ��w��9��JiM'�F9���Q8/�J��������������
P���GD����B�.?VK�6��%D�5E2�j�RZ�*]����1�[�9�@[^�9�#�Z�h)���B(�;��uA@�������~@�������u:)O�JK������3��I�!�����EM���-I^(�������#$��V����(_2Z��,�e�^��E�U�R/�x*��k�q����Y��rS���j���Sr��Lu�Y�RNd���5����������>HY��?�O����`�t
���F�P��jG�]�I�����V��F3<AJ�g�G�)���X�ff�:pyJ	�)��X�����h����J}�`�W'�qZk�	L�}���hdq���*�����6����&����b)q$}�����2��hm����|��!�����wCa*�(	�����-�>���\��x�q�W��s���F�@}��B��d0��1���l�o�3�����A�=������5Nn����kX�	(4�=l=�y�����
��
!�����T���-DF�[�����Wd�S�������/?_~��|����������/?_~��|����������/?_~��|����������/?_~��|����������/?_~��|�������~�?/Uv�
attrnumber_llvm_type.patchtext/x-patch; charset=US-ASCII; name=attrnumber_llvm_type.patchDownload
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index daae964..46b4c5d 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -49,6 +49,7 @@ LLVMTypeRef TypeSizeT;
 LLVMTypeRef TypeParamBool;
 LLVMTypeRef TypeStorageBool;
 LLVMTypeRef TypePGFunction;
+LLVMTypeRef TypeAttrNumber;
 LLVMTypeRef StructHeapTupleFieldsField3;
 LLVMTypeRef StructHeapTupleFields;
 LLVMTypeRef StructHeapTupleHeaderData;
@@ -798,6 +799,7 @@ llvm_create_types(void)
 	TypeParamBool = load_return_type(mod, "FunctionReturningBool");
 	TypeStorageBool = load_type(mod, "TypeStorageBool");
 	TypePGFunction = load_type(mod, "TypePGFunction");
+	TypeAttrNumber = load_type(mod, "TypeAttrNumber");
 	StructExprContext = load_type(mod, "StructExprContext");
 	StructExprEvalStep = load_type(mod, "StructExprEvalStep");
 	StructExprState = load_type(mod, "StructExprState");
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 795f671..804bb94 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -691,7 +691,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 	{
 		LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
 
-		LLVMBuildStore(b, l_int32_const(natts), v_nvalidp);
+		LLVMBuildStore(b, l_attrnumber_const(natts), v_nvalidp);
 		v_off = LLVMBuildTrunc(b, v_off, LLVMInt32Type(), "");
 		LLVMBuildStore(b, v_off, v_slotoffp);
 		LLVMBuildStore(b, l_int8_const(1), v_slowp);
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 36c5f7d..aaa5bac 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -324,7 +324,7 @@ llvm_compile_expr(ExprState *state)
 										  "");
 					LLVMBuildCondBr(b,
 									LLVMBuildICmp(b, LLVMIntUGE, v_nvalid,
-												  l_int32_const(op->d.fetch.last_var),
+												  l_attrnumber_const(op->d.fetch.last_var),
 												  ""),
 									opblocks[i + 1], b_fetch);
 
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index 42304d0..19e7aaa 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -48,6 +48,7 @@
 PGFunction	TypePGFunction;
 size_t		TypeSizeT;
 bool		TypeStorageBool;
+AttrNumber	TypeAttrNumber;
 
 AggState	StructAggState;
 AggStatePerGroupData StructAggStatePerGroupData;
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index b0093db..b65b6df 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -61,6 +61,7 @@ extern LLVMTypeRef TypeParamBool;
 extern LLVMTypeRef TypePGFunction;
 extern LLVMTypeRef TypeSizeT;
 extern LLVMTypeRef TypeStorageBool;
+extern LLVMTypeRef TypeAttrNumber;
 
 extern LLVMTypeRef StructtupleDesc;
 extern LLVMTypeRef StructHeapTupleData;
diff --git a/src/include/jit/llvmjit_emit.h b/src/include/jit/llvmjit_emit.h
index 0d1b246..a80380d 100644
--- a/src/include/jit/llvmjit_emit.h
+++ b/src/include/jit/llvmjit_emit.h
@@ -97,6 +97,15 @@ l_pbool_const(bool i)
 }
 
 /*
+ * Emit constant AttrNumber.
+ */
+static inline LLVMValueRef
+l_attrnumber_const(AttrNumber i)
+{
+	return LLVMConstInt(TypeAttrNumber, (int) i, false);
+}
+
+/*
  * Load a pointer member idx from a struct.
  */
 static inline LLVMValueRef
#7Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Ashutosh Bapat (#6)
1 attachment(s)
Re: TupleTableSlot abstraction

On Thu, Jul 5, 2018 at 4:07 PM, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

I haven't done that, but I think we should split ExecStoreTuple() into
multiple versions, that only work on specific types of tuple
slots. E.g. seqscan et al would call ExecStoreBufferHeapTuple(), other
code dealing with tuples would call ExecStoreHeapTuple(). The relevant
callers already need to know what kind of tuple they're dealing with,
therefore that's not a huge burden.

I thought so too, but haven't done that change right now. Will work on
that. That's in my TODO list.

Done. Added that as a separate patch 0001 since that change adds value
by itself.

0001 in the earlier patch set got committed, 0002 in that patch set is
not required anymore.

0002 - 0004 in this patch set are same as 0003-0005 in the previous patch set.

0005 in this patch set is 0006 in the previous one with a bunch of
TODO's addressed. An important change is virtual tuple slot contents
are never required to be freed when slot is cleared.

0006-0009 are same as 0007 - 0010 in the previous patch set.

Next steps
1. Address TODO in the code. I have listed some of those above.

There are still a handful of TODOs in the patches. I will work on those next.

The number of TODOs has reduced, but there are still some that I am working on.

2. Right now we are using TupleTableSlotType, an enum, to create slots
of required type. But extensions which want to add their own slot
types won't be able to add a type in that enum. So, they will need to
write their own MakeTupleTableSlot. That function uses the
TupleTableSlotType to set TupleTableSlotOps and calculate the minimum
size of slot. We could change the function to accept TupleTableSlotOps
and the minimum size and it just works for all the extensions. Or it
could just accept TupleTableSlotOps and there's a callback to
calculate minimum memory required for the slot (say based on the tuple
descriptor available).

This is still TODO.

3. compile with LLVM and fix any compilation and regression errors.

When I compiled server with just 0003 applied with LLVM, the
compilation went well, but there was a server crash. That patch
changes type of tts_nvalid from int32 to AttrNumber. I tried debugging
the crash with a debug LLVM build, but couldn't complete the work.
Attached patch attrnumber_llvm_type.patch is my incomplete attempt to
fix that crash. I think, we should make it easy to change the data
types of the members in structures shared by JIT and non-JIT code, may
be automatically create both copies of the code somehow. I will get
back to this after addressing other TODOs.

This is still a TODO

4. We need to do something with the name ExecStoreVirtualSlot(), which
is being (and will be) used for all kinds of TupleTableSlot type.
Right now I don't have any bright ideas.

Done and added as a separate patch 0010. Separate patch so that we can
discard this change, if we don't agree on it.

5. ExecFetch* functions are now one liners, so we could make those
inline and keep those in header file like, say slot_getattr.

Done.

6. ExecCopySlot can be a thin wrapper if we add a callback copyslot()
and invoked on the destination slot type.

This is still a TODO

7. slot_attisnull() deforms a heap/minimal tuple if that status for
given attribute is not available tts_isnull. Should we instead add a
callback attisnull() which can use something like heap_isnull()?

This is still a TODO.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v3.tar.zipapplication/zip; name=pg_abstract_tts_patches_v3.tar.zipDownload
�JyH[�[ks���g�
�������e�*���m�F[~�$����b�3 9�p���b*?~Ow� ���Jm�����@?OwC���L]Y�������L-�;��/�9���g�����I�w�����������|>9}zv��+}�Wnb�O�JSh��q����b���{��g�G��������**���W����ij���<*�#��������(/�8*f�:k���>}�/����O�=��������W����������:z6}]<}�4��'O��4��7�R0�������ob{���s�&���]��g������g��"2����H?7��]��xJ���f�-VE�l<G����)�%Q�g������7������������������?�����������������uK9uW9u�kVN-��Y95�3S�kV<\������2)��c����Z���n���"Oc�����*7+|Z�(�%����������[l�7�aOD��S�Rc����kvY����lf��7�M�%K�n?^/�h����g�����)��,���l�M��
�sWZ�|�W�}H����]Nm�y
��H��)�L>/A��01�``���^�������o �"1i���2�W�&�����-MY#UKSz���._��#|N\VA"�I=�m
�c�4�,M2�gU�I���i��"�B���VE�����JcD��R��mnua�&�&KJhl����|�G����d�������������������yoq��y����y��d����^�J���(EvUn����Y��,-�2�/���II�� >\��
�C/a�~/�C=A�(�)��tl]��P���9.����!2����uR.j#�6�|^�Y�ds�JM�I�j�`�
��6z��,����V��U�2��az�)���wV��p�o2
�Mx�����i�h�`8�CB�����-���f�"���,/�b\����x����3&��2�'h��2W�^�Y@���J��WQt�p�--���x�6wjc��I���V�]W�b������F/�^th���CR��I�V�2��8M�(�Y;=�
\�R5�9��� �8�.;$u��q6s��)�����%[)m�!�wZr��1|�W))���vf�
��FaQ�Cc�^�<+
�V�n*X�R�Q%��{<+����g�s%��7v^�c	�p�'�zNc9��u^@�rt����	[�C����E����a��)������!���z,>��)���
����Yw?k��Pf�hg����r���
v!�3X� _C�uy��k����14D<��t��#~��r�4I�rC:5+�ej�y�Q������t�� a�������a�(	��F-�,m������a�k"X\��������Hg���8q�)��H/sW�8\�g���A��iN�*q�$��h	���
�*�E�s�����.�)�h��F�>����#�#��D[������%�`t��7�������X+T��X�a�%J��[�PY�iOj��^��jy	�y���0X��k�=�7���=�
�����wl���&�c,�wI���#<7�`��!�!�b���$���w��,"�K�*�M:�(�@�S0�$kr�f�|���Z%4�_c�45Y
�v
����1�B���z����d$�q�%I�Xp����F�s�9!���l`
(�a��i!0�-����
�����|j�i9�h3���z����?��<�������������$�5�#%F�Q�K#�eW���Q���k2��p��MxO�b��^�&�`b���/��`=�+~	�I�T��7b�D@��`a�1$Z'��J�L�
���,�L������{lMD�����~(�b��
g��!p'�(1�&<���@��y+��R�kq&��2Ik7����c��(�9��0�e�R&#.�����<I�>g���b���q���z�0���?�V;��2y%�1!�fG/�P���2���)�Mo��w��C���\�,��08Ue��<I�0�Cb���H�����Hxv=�m��L�g�����c����$�Tx!���'�v�M���C���9�_v�	9[���F�]@��cZ����M�N���	�h7��=`XHu]����=R>�g-���_�^4�s�,*B���J�I
X�p���d���$A���k�0�Z�l�t��'#���,�
U���aA�5Qj@��,T3�:���(�L.��%�FH�C���ef.�:�D�������K;|.,�i&m���1��c`y�X���FP��,+b�7[9(��5�_`dO~���	'z>�V!u�<x#����M-�&.��a��`B��5�������V��N�$�%��D��%���u��EC�JIy�usQ�J>PF��3�!�"���<�����W���P�d>'� }�&@���Z�8�
n�����{>#LZ���X�	��k;��g,�U�:��,�E8}/����x�S!��|$�!;��� [��"��)ya>8'���++�N@�A&�|���I�Q���:�V�z�JB��B3_�SV
�{6������g��,��1�i���KdW`�hgE�*T�D<�<n"�� V���p���/M�h.4����@S��vX�����E�R��;T��5W�����^��{�R!dkb����>�1��T(!��p!����6���Z$=~�w�A�?)�%m��
:���:��{@���HFF<�<=��&Sl$��V���`Y����$a���R�NXo 
 FEcu���HR%CF���IFed� ?'E$����c�������.&k��:Y�%Em�����(��q}�6���h2�K7N�m��r�}p���n�`oEI7�|��������+�B�&N�^�`��L���mFv���,���h�&6Hy�� Q5�l��c;�m�������~���,�K�/[�k����9�S��Mz�x����}���$J���������	#�q2K��R3�T��#��������� ���*u���s\��6�CT,�)�>�8a ���b�`�=]��t?�ci���c6�"���D��B�0C�0��J����}~JQ���nrs7ys�����������0��T���P�O���F��_A��:�n��iWj}�M�q����R��o9����$�!<��x�]�J�����n�~x��;��9���0Dq��H�|��-S�W����^E+F������)>g���u����cy������W��%� k�[��@>M����������&�*,�t�.N��+�o�-)��mOX�]�}��
Nf�a*F�����G�l�j���@�]�S'%�3_�i+���Wn����Zp"�R]��F��s'�-�2�B��ldWx0���Hq�~�WY\'2��"�D����)x�OIf�	�'B���a�OJ�o�kp�2��o���lu��ZHD��V�`�������6���|5�n	n';� ��O�QA��� �TA|�gK
Wzc����C�D���j�����r�I������e"�Q��U�U��u{,�?��S�Pk�L"�-�C������J�B����.X�d�Hig���	�X����\ ���B�lE����,��w���<��}����B�!Le��2 �a����;�"N
�����e�:"1R��N����D�-*u��9�s=�r���v��`w+W�Nf�)����R���("�p$�o��&��nZ-���T#�&���6(��v�g�v������b�3����,�����QI�i�����,h�^ }h�=�#g�!���a���yZ�?87ru������t3���guw�����.L�	N�����z���%~=�I��wG��V�><=;=�xz8�H�z��sAz�W����_*Oh�I9M����p����A�%�T�t�s�����\wA�7A2���l� ���gS���+��2)�Ot�T��w�@��T����:��������+$�B��[��
%�^$wL_�Uq���\@���k�s^�:��q�V�A5��'�S�jm1�p��+i�1�9����G4�|��P�>e���H58���3������p���o����RO��M���/�������G]e&���`������Dljwz'��|U��.j).qh}C����� �76t/
~�2x���cel#�].")�=��&�Pjn��Z9+$
�
�J )��KZ� ,���t�f���S5)�q��M]�Bm����������TQj��5~;���r5XZ��U���HM���C!��G���d�r�+c�2�y^��k�[�F�a�j8�x��p����I,M�p?��$��m�m�xU�o��(��T7;��}Y��w��X,t����GFM�O/��S���?�O�����*������{�����X�^�WII^��(���:�����N��2��Q��T�5�a��t1[Ue��^�Z4Duop��C�jo����.��TQ�	�-���a�)��s�E4w�\��P��,��Y�~�|�QLuGw^�Y�V���_����SD�Z5��������2��w_GU�eZ������e�����({�����u��B��L�;�w�������IOu:LU������~���t�Gj�&>oUY���B ����"���p�8g�87��s|�y�Xv�"QQ�@_��Rl���������b��?�L����sY�k����7%��
���&��/e��}aR]�����%P#7���+@7L6#�������g�v_Pr�3�����-������A��B�j��rB�Fs�����Wg��/Y���}}{���R{t*�(�wI��\D �G���[Ln�������U�#�����|@��5�������R��l���M��D�1V����m���ZHl�J�|��^~w&������F�	$��^�O�v���M�}4��'��I�.���Y�����n�S��=X#
i�h"	�+J�RS�%��Y�k.q�N<��r;�(8V�H�z���n�u4>�4��C:3�o�$��o������h�L�r������]�
�gs���aX�N�p&�~0���7����n;���M'`�����w������d��AWE�V�E��]�q������X�["��]D�0�V��{k�p�|
Rk>�Z���u��'aA�����Y�
��n�Q8�a�������]`D��+����#[_��F�u�	0��d�K[�ix�6>
qz���J�F~�i����3'�?��4U���H^!�������;���CjB�)z��n���%�`�?��+~�� T�]b����4���h'0�	���P�w�������::�����n,���(��'w��%Qc�5TP�9�)��[� u@�?�Dd��?�L��l��S=0Q)]�C��Od���D�;�VN�P�6������%�3��k�D��:��&���u�)�`�^�T��vT�Z�g����������?�S���aH4�o�y�c~���p������W�7?�2��h8�+�r���c8�a�BP��
��$��*�H���6	�>��8���1�%�%o��A�������������������7�y�R�xs�Q/h��\�h��=�(��@�<�-	pMf��X
�����������!�F�`��d�V^G�����mw�h�{A��a'���(		������u..������%Y�6R7�2�� �%5A�B�`7d)XI��u��j��t�@�c%%���j����z�������__�����on�?\�I����H�W�VT�o�����1����3)���	����F.��������Ru�z��g9?���V�~j���4$��R��g	B�|�a6�/���������m[��.���<4�_<t��C�/�PKC��!R���������\_�;�����twHq�2�2���a����,�u9�u}�	UG�h�/���=��o���#��������2��O��T�AE����s��������"���c�]��15������`��3���39/��M����.�=�Y ����$��;���gg��IU������!
�������m�H�8��J���=�PI�~�'�ul9��my$%�=���4�M��$�a�V�3����n@}�����lH54P(
��O�hF�?�5c�(Y����6�D������(]���A!US\�0Nu��-�(��
j*E ��i�5��T�������c��������u����g�k/}y��}�������'?�3^�C�T�S�I�Q����U�+�.�4�V����V���v��9���|����VJ���i��;��5��	����K���[������o������4iw;P3�O['���fG��uP@���+�f��&�����������kb|��)Kfk~l������Z�Y�V�W��U*�����������
��$��#���jf��e��5�r�+1��%�����0��miM�1��WR�k7��^���~-���t�������Z�-[+�f�����m�R�C�,�����yx����e���Y2N���"���w�Z#E�vY��.�~gw��������n"2AU�����TR���p@D�����*�r�7Q������ZM<S�El^�h�Irn�q^���Qli�r�B	�]���Z�Vs7E�������{��["��eQ^��IY���#m�!'��p��t����
}GNr�M?��f�7IY�K��4��D�$�
��:+�A>xQ����5��p�DX>]D�����mVM��;0Q(�%�5o0���3�P���p�|�&n�>Z��s�Z�S��>
��/����U���������^u3��x���j7��pm�&��>e����4j������b+�v��
�6��8�U_g���]����K���m?����wkF�������xGm��t����Q�"Et�}�i�}��Bm�v|�Z��������!��8����=�b��V)uH��=�����lv���7c�������R�����N�;�����s�_:<��"�p���yM��������[��M��9�(
��R���hm?z~�@��O����pu���f�b�\E�Kb����i�l�U�4q[�������3#�e%?`����T��������6|
�
�NMh�xq�FT�U�����	���F�D:_d�
X4<.���,�+�	B����C��]����_n������jF�i�r����h:t�f����o�{������E�o�;�g� ����5���
�g�s��tC�vy�!0��cE�eN�gI�=�@�T�E9�?�3��5�D���x��������B��R:LE�"�s��F��N��38E_�e��2|)D��������Oa�6p%�p,�iO�����Sf��~��7�����������	6�-��W�s�*�C�q�[�3|:g����;�Z��������di��V���T}l�%��Zbj����)��\��
q2���{�%��EaX�D�1i��&\���`k���sf�#�R 
�y����:(����xA{�L�p������>f�F��Wa6��j�#��$�	�l��dLd�Z<�8qo�s���`�V���c���A�������&�|�t�\�y�&g�����`��-5�#��G�4���`pU��>�[�$8�tp��u������9���#�LP�T�{��Sm������vw���Q��K-|W�w(��l�����
�/s7CA�������^��*���HLMv�U��@������N���Z����5ps
f�!��A�������jW��"���v�'�|��v������(%�`�=�t>�t.�ZX��:��'���������R���R����GwP"{�G�	��@I�E�0�H��
��Uw�>�5zd^�@>�w�7)4����B����t��x{�	9T_p+����4�^|����� 0_�>���������R�L����kH���F��t��v��=�8�����o���!���`���]hj.j{��.-OO�v��jQ�n<����>Qw��Sr2W��+���|v@Qp���N!�M����P��0P/F��X�p�>a�,���[���R�`rq�;g����B/�I!@Gv��Q�"�i��U8s�K�K���a;�	��s���.bD[Q�^�����{c
�*�5x�g/7!��b|�-��5z��-X��~r:`}}�&�G�^I�����-J�#I��&��[<�I<J���WA6��F�����q�8�F��pJ�'`f	�m��T�@�e|���&��e����w����r
�mxU�����h���6�T��=,��G��Y�|l�u�R���!;`��J$
0	O.����XOpd�E[4�=�W�UF��`c*z��e���ER�������&�N����RZa���y�D�+�������YT��pC	�{W�T�h^�Dk������N�����=$p���������D���f�Zr:�.�-��^���
	]�h�#k@�%���E�`E����W�)���� �v����qcr�>p������|��\C��c:4��U$�������������LBef�
+D��*�}/h�"�1>�:��g95����4l��C�O�Y�y����+����������#W��?^��1��t�n�OO0�A�gx�ft�9���� .���-�a���Y��y���_�2	&$�4��u��%1�z���m��e`?����5Z�oHm$@t�P6�5�!��A����8%
�(#!Vx��`J��"�������[��L�R*��r�����&a�s�Y���RKv�1!�/(����%Od�[��s��]���a��R5���i��u�r�/c�4R�(*[��!rh��_Q}K�������vK
�L�9(�yr0� ����MT~���Fh���<A+k�6��F�-y���D�[n#�i�Hs�;�@�za��P�-Sk���}[�f�t
�vT$6����������.!�[@�|�����C/��y�:��!$��
��m������ F|C�Y�Q�)�P���`��w6�-u�w����Pc��g��DlpL0����@n��c��������Y�n$��R^��2_�����������L��9�<z$LF�)�3����(��#���G+LU���'`����&NUv@�>��%|(������I���"����X.K2q�� 8���I����V��j-�����G9���Z��<
q&��H���\�)a�d�/Q@Y�Ei�a!H0c5�����YZS�UYY��M�l�j�,��XRWQ�"�T(���
�J
��K��~�E�CY��5����Uh���8���3��g����/`�R=��/����[��K�h�N�����*S)SF��K�4��_�|������`+HN���X�4r��(�xE!#��1NMR�'�=��9�AS5�ax������]�����_����/-�����'���:z����v9������a�
��a�l�>L,�z*O%y�`���4�4L�L���fI9{��%VB�B�
)WDia=����n�����������(G��l��:�f�o�~����n$���.����������9�K[���p���������c�2�b����0���4�:o�h�w��xD�����^��j�q�Y>!�M���iP+����Xo^18*���9��Q��
i-&�&Q�u?��.�.P3:N|w�|��::��0G����6�H���qS��}��_��u���_'>�����u�����2������*\=w���7l6{���v
�:Y?������V���L�mb�7p"!���3���y(��_�X�+�Or�`�d�G/TQ�>��3�����yl=��<�'M\J��k��Z��G�#��iz������pNngMFXE���l�L��xJ�_������s��#�R}�8��R��k�g��5K=fj�O�����Rdu�Yu3�	�� ������9e^�}�7��%�m�1�<�Fo�!����,����'�����%A�Q�^5��h/���x0{��~M��-a��y�amBj���D�$�Y�U&?�1��V��?�a;�����._��pL�4��y"{��%����s���#[�����AiJ��F���_r����Q��R��{�ao���{�������{s%8B�������X���l�����8�Z��C�V�p71'	(��7^l��z���'��O	��zd<����.	$U����y/�w�d�i2����Wq�S>��y�%��f#�;��M��g�Y���`�t!d���4A� FR~�,�p��X:�+�����;������}�� ����x�����g������u���1$W�=�X��\�D|����:����n��l����jU`K�������t�tQ� ���!���U����&o�y���������WG��0bf3�������4��NoT����.�m(�W���r+��J�g�[�7�
"N'XV!���i�_�=��i0��o���QwX�=�~!cP	>���1����n���@Q	�������V�`�D�[�/�lm�S��a�&�.4���xY��D��E4�i�e���b�=��N�=
z�p]�qe�JQ�b;4H�LP�!�����H�HS��I���6�g7
�>��������9�S�2��8j�f������h�B~9�N�E��C�_ST��S|$�aO����&4�/��%�P(�%�\�<�$L���L?�\"$���
>�p��,���e4`��F�����B��C�C��O0RL�Q:����c�q'�7`N=~~�]r�l|�A�+2U�y:�0OJ��8��:�7m6�����U��qE�0.����I<�������5��MA���
<�s��R�"c���E�&�����0���sS��Sc��M���T��x��B�t#��I�3�9%
>;}
������]��o� >j2g2t��a����f�k
\�St�K7Q0�q!Z�^��A��	���L�}p7���'k�R�b�D���9��*�?a�\l1�j�b#������a+>�Ch4�HfU��S�*X���p��\>�0���#=�nW����t�6,#j
p�HE���8�Gu��o_����9;��rry��K�y^8A
[u���p��m���E��������T�4g��R�P��S��i6�]o�����D;�(Il������S��_���RM}QL��.���n0�b����
����<Hi�����2�2]��'�j[����O��P����N�I^4�pk�Lq�Gr-Q�����Y��s�Hp�eA�-a/���d��2�N�����j{�	p���B�{��;A�)���I�U9���9\��m:�uA����a�`�D�����u�����(m�x���],1hQm���
�Y�a�Sl���b�1~�����w>b�������b��
'4����P$�?m�ouD�K^2��
_�����m��n@a��\����v��������A��l��^�w+�yF[�Q�qlz���'<"G >�N�+����P��*\��'7��aP�����*��H��������(��?($�kV3yPC4?ZH�W�K�w��O��|k9�2O?���*�e7D?�!@ll�8:R���S�*Z���_E�x�9�fQ������l;�ik���(f#b�%>�a>�Ox����GY�����E��?����;g2����[����?�;{}[��#l�|�S!��a�"��J8���m
�5��"����_;���~�����sx8�e����0\��+�(r�-(P�NY(ri]�{K={�>���9�(�����I��#	�PZ�E/��hW\3�N�c������[����l�;�W��j�(�WAl~ew������l%��S��Q��$P�l����8�h��������@r�B%�j�����s��T��b���%�
������7�5�3w������n�Ht�B����|\�OQ���ak'rfT�;>_���,�`d���v��Lp�s M����c3wHt��e�6�t��F*�Q�U�
cq=v��\��ZF	v���Y�
g�������~�'��N�{�x<���}j>N$:K����_���������E�4�������������#0�Z�D������3���
�bB��I���	�@R+�	T���D�������d�O��K�S��
H25����2
Dx��B��'<R��(�����c��J+8�(���}����2�w^d��~`,����}wX.������Z������@<F)�#�7��F�(�3���_)���~����`��:�Qa��<�ed���}BK=��m��OBWa��������7�����|sq�Ln�(���l�P�g�`8r6�8��k2���j�_E������&Z���F�
�>������� �����Y�QP�.%s����������T"��g�<c��!��:�]���z]�VB5���V(]=b8/���B%q=�����pP������|W,����
������Y8��^8,��D��8�3�Z���*3�����Qm�ML��=�^"h��v#l�n��"�T�V�����h��5����W�����&L�[�M�d�E����o�vR^��T��t�`�r9��������be�Ej���F�.P��	����QB���������^^����B�%~������'G�+��s�<�cU��@Q~t��Pe����"���Y����"�~C�C���O�>JK��S*&���&\gS�T.����;��b�TSCeY�W�:�k��������O���R����
�4���2J�3���vY�
�d���-T9��
���a������x�o��|KUN3ikUNA��,q��5����y$!�@J�s�(�G	���S?��O����~
��v�'~���b��IY�;8�+j���@a������9c�g�����U����^�l��t��D�-�3>2.�y[�l,�0��n��3�{��ep������r����W>}��O�[���HrQ]�h��`Ze��U�K�wF	'8��=���E���Ge|d��Y�=���c�������N#� /�����
*��l��'[��Z�5������_��>����������W��_��O..qo��1�|]�a�4P����E����LPQ����_��5*DxqMq�G��?�v&+����C�~�0��X��9��\���ybK�#sy�����G�0��ZG��O�g�Oi�}�o�������� �<������ ��9;��k�\����t��R\��������\X�Q�)-#���:Z��22zu�(n���
����E�(l�\B]AwF�9�;��x���7K%��b�{���O���������|�njX�t����v�}]������g�8��������h,�/��
��	o��)X���O��Z��/��X���\D��
s��*tS5�����t��U������c�R�L�[5����a4�I?�m�:C���%�����o�w������>��[��b�,;3u��N�>cS;���$�0?��-��0:b���<kd8`��$3��2e*w
V+P���u�!�~D�� P"m��]�����|rQV[

Ce��4���]y^����/
���]��<D��U`�v�,x����O�r����:��L*�\���aPF�;��
�
�����yp�\�1r���S;�\x{V�5��/�����Z^e5jnY� 2��7w�'�HA�xl]��[���p������OV��Cs�n��k��G��u��<����/���ZYY�����j��+�3�����ote����[�j���s
>N��g��Q���3��;3W�(����u0FN)���Z~��l����s{�I��]�()XWu�B2"������m�(�*\��r�^A�w���+�`��TH+	#1��;������nIp���Q[��G�lZq�Q~w��G^�����/��.��cxA�^MN��`��\���g7;��i�#�	L����0�*PC%�%�������o����O��	�����;���\|���SJ��������|0���O��^�JLG��7��a:��w�+��I��8�,��������4aq�}�N����|�s�<�\�����`���<1��&�wm���u�}���qW&V3�=��93�+{/7g���M��h\U���������]�
{~�go��0a��(a9)��0
cx����fd~�E�'y�k:������)�u�W�K�l����3qhel�D�
x.f�zf��ah�>��u0�-p��}a��Q!
��/Y��Mp��/��{��,���r�Gd��O��"�[����|u_:��I�u�.+�;�������v��l�F��T������J��O>	�/��:R�Hnv��^}ed�p��#�S�a�o��b�.0���v���i��7_�y&�jU2xC�Q�/���:�0���\�>�1�O�M�����<�P$�|�J��n�n����"�s-��h������~"�[��y�������9~�L���
�#�b�n��qT�X���3�X������j�XmnT����RJh���:P�����>5,�R����������s�<��l�?��d	��r����5��{��������������~l�i��Q�lT�����Ar;�?>�i����@���u���p�3���;�����N�/��~�����;�_��U-��(�j�n<m/����VCrp�d@�wMK�~�<%Pd�bF
�Y��$��WK�
dC��^�H{b3�L�x	���y�_��[���&��X1��N2�M������f-�W����P�bb�Ht	D�������<�!e���p��,T�r�b��j���yg7���}�4&
�@�P�1W�h�10z��;�&D�6�K�-+f�z�`X�P�F3C�6���{W���Q�#v��_�?���>����w9Y�H����
H����B���*�����X3TZ$�)_�b��X��w���6��`u���S��um�cR(�|�/�M�:�����z�d/��]�u��&�d���	����������5#�d��w���VAb��9x\��g:��8����Debz��K����bbQu�x1���� ��n���s�WlpE6����+o�>mq%.e�Z��9���/-Q\������G������I��N~����,��c�8�Lo�A*m�b*��,*��~�x[�
�u��L{���7t>zT�n���Z��oZVA��:��;��p�����WZ�T��e&y:D��c�`�P8+nn�!�p�p��7X�6>#^��M����Lx����\Ua�
�"h��>��ssm\�^cdY,?�8�_!y��cy��w��^|x������w�����������6/���K���.�~9����	���p&��a���}&r&�����������T�+�'���cE�=��2��SKl��j�]5��7G�-��bG��/����g���n
RF�s��?�����N����g.*j��%�]T�^��N���D����8R�E�	teA�g�U��]*�sP�3�������`�0��r�/v:����*��x�e��)t��^H����F�en��q�Wk,{�v�M;(�&(����)�K��'��\���B8������	QJ�a.TEG���@s:����������|�H��C�s����^�x������y���<�������G��Po��r��U�q<Yr�(�GC���
\[-�B�������f.�,���j�Y�s��xX��b�m%23OB$����-��.���<�8�dar��l��OM�I���;��`.�N���?�i�w�W�Sj��q�VfQ���qK�SA�T�X(G�5��I?�YJ���V��
���B�O��c�s�p�k;�2O�����{ �Y�61�j�X���*9M�����6kv)�K����,��������_Y.p��%�$C�oJ]����_m�<./G��Hbx�����d�\zr�>E(�`{�"������'oO.O����[z�g�1��5�[�G�en�&�}�;;��.;;����;	Z���,
�.�D�x�h������R=��;�d���)Y
���y��1�r�*{`z����/S�3�f�~��p���*�{�\�dwq���TG�D7�#tf��������M������[x��
m���G�&��x����v�oMgy���*�M�
f���105���Gi����4W)2Y N�*n}4��&��2�=|�)�+�"Z�/���9_M�h��2r�P���B=�O��V}M����|e(���VF������z���BDy3[B���j:���;�r|3M�a�w�_]O�Qz�M�����U-nq5OK�
Sed���?�ta�������d�R��t9������|�Hr��� ��|ub�����'���3���>{�����oS$����N��#V��U���������������O..����l��A�:�����Y�v��z{K���pF�������7d>��!�������S�4~l��&����G��%P������,@� \�M��"i���������aai(��ZoBD �+���^.��-y
�o?��1h�:��W��$�J��@L�%�z���6t�8�;�9w$�f�����q���j'��b����Nw��U�ui������6���%f�
������<�9Z��XE��i�.�R\��]d��+���i�?P�B�D���dI 4���M��CN���<�9�`��v�'�|�fGO��aK���S^�o0xY*��xA�@����(�oqa�����Z��'��������4<����j4:�H���-43�YL��_��"3���C�
���D��<���c:!
��!����o�CD$����n����`|�cry��x'tz��a�j���9��:4�*�Zf,U��v2vM�Vh��a�/�L����)W@@���2��hy��"�c���O���}�n�|A��Tx[c$���M�3 p{-���0a�G�~8g��L�@��/h��\e�>��'O��6�\���d��F�|�Uj�k�yk��-}0m��k������a��1~���Z�_�����Ij�-.�wx��p�q�]r������>�kb
{����|?b�w���"�KSt�4Y6��Q��
��m�"(�m����jJ-S`G^�Gzj��(\���s�V��v�V�!DE�M���S�TC��D�ChC}g��]0�H��/���s���<X�2����a��_��8�d5�m���TeQ�;�&nM1�Nm2���"q�I�].\ ��!��0q������}��5��MIv#OXB��*
Gt��1f�>��q[�+B@�O�f�4�"�=GTL
[�2����l�&��!�1=Y�H5F:�]����|��"�bB������@/"Aj���/1�����=�9�LK����`E&��^r����
U�
��$��<�+m6�������^��dp��UA�|r&�I8irS��D��m1kM#��&�g��<�<RX�I-��	�e	��5�C���y��<�\�����jSR4�H��L5�)�X��hh����my����)�����Z���fd/���(�Y=���H�� -�O�
���U�n��
:����-R�)��X���7o_�9?���s���+��������p�?���d��o�>qp��3zA[����XA!M�Z�d68a�FK.�[�l
]V��KY�� �U[%��I:�!��
�m�Q���T�t=��\x�$k&
�	%��w/�x�������\�����j|��9�.<N��S��KZ��S����)k�a�-qd4�WK#(����1�/��u��N�Q�h�YS�A����3����3!���Lb���[����Q���4���>����{�&T��g�I�tg��a�����c����	�O1D����6w���Y��o��,����u���j�u��������S��:��C2t���7�!A� c��|�k"y��:<&�K&�!�����{�m�Yt�]�@^��*h�h3D���]�kJ�U�	�;b#�<�G_wT�:kyX)�y����*@e�FA�@����F��!�sE:���<�;
�7I��MR�>[��}��ZE�A�x��^�za�aR���B��xM���6nYk������o?�B9O*'�H�_�Q�2�M�_�J�F��qn��������5|+*#71(�Mi�j0/&7�J!
��[I$[�"p�����D���.n�9�X��DW����X��<��7E���TX�j
�D�7�3e���47�;�����SD����6�B��
	K�����O(asVN��R���v�z���2���H��<��"��4�S[+-�.���Ru���K����If;���%�LM�������;��7�v��\�7�v��.Y�kug�#|�����I���UV��5I�������WE�r�C)X�f��=�j21|�
X�*W�Kn|u�����n�}���.a�<�����P��p>��)�0���%�/P�~�IL��*�L����S�~+��*�L��@�4��+�����J�P�Z1J,�r~�O4b��Wek�k��#t�2��7� ��
�5��s����m�[���X�f(��C���]O��~�����10!�bj��G�e��o.;�n��`�$����d���������Z����cRi���������GE�$��8�0�c���a��1Q�����%K�����w:DJKt�t�S���}O�9��P�D��&�;Or�6��5��t�'�6^����8�N�Str��
����f��Tj������f����(�����Q�3p����9�������.��l�����UB�PL�K�32����������wr�H�\�8_���v��9}�+���y�-9�9F#u��D�p:�"����$������Q�K�p�4���W���/�sF���q�TnL*L�a3���6��5���������x�=���^�ue�D����/xVWC/?��Cq�P2�����>���w����e�dpH��Q��������p��/����4,����-j;!w�3�����*D���TGz����|�T�*�4{�8s������T�n7�R���^j@���d�VI~�,�M�u�}�o�_�M��Y�~sS�n������b�|�#��{�:�yR�A-FKl�q.�O���-��yevF*1���Vk�5����J�^��=M_P%p�>c��F����My1rCl(q�
_4���� �H
1�q�D�bE=G�:l�X�;�,���}s��1�}�:)������_������i�ah���y�)�<��,9�%����4���$��0sIjeu�Vd��Q���PxbL�[-p�%s�m�����!���eI�N�2�Y+���mg��J3���X�G��;�=U�wz��n
�:�6�=��y�?��rIt��I��Bo�~��#��%���B��!%�e��X��^,s��k.������m"AT�� g��m�\��^E��������xQ��:����D(��\I4l��� g�I�S�y�zW���OR���u1�����A��1��s���%�V�z#3t�Q��(]o��7�B�S?Z���_���b�w~^����{}�Z}5���V��'�q�Z��9h����[9m���l?�LN��8�����{x0���������Joh���!bo�i���6���0#�����^}t� �������:b��o��:� _������A���H�th�����!q��b�k�j���`��17��%f����p�
��`O�Rn�L��z�
�]��f��G<�p������"s��[�*O:g����HK�D�	��=�������t�]���@7�v�Ro���S^]��#��	7���M��.H���,sJ����g_����L%�U�)"u��������j������U�[mkF�$,@�b��&�@�������M��7x��f	G��s�`GL(�yV����������?���S.+�`�z������H�|h�������8oV��5%m�i���A���,�����"���$�)o1muY�|��j��i=��g�}7Y��0��Q@_K�m�t�s3O�v�Y�s1�L�z�Y����[�a!3�Y���)��U�J��t^���
��������h��������o+������Ed���0�m�V����HW3�W�������������(�YA��I���;��DO��*Xc:�x`
]�����0"|�(	=��v*_��gnk�q����$�]sC���<O[)��q[��!]�����&�f�� ����B��$��K���(�
�+����5�>��+e�
F�d[?�~� ���{��^�q�P�h�� �*��H�����1�l��%y��[�����`�����`�����_�
Z���� �6��?��'P�<23B�Z�?�D =m�}�AAa�A��������,)p+;k�V�`����A�����=�����\7c�'G����*��?@n�`��[��"�t��
�0�,�d���1�� �������E���7cur�&_j����Z�����bwu�K�
20@u,�++�X�i��^%s�#�����q���[��0�}x��"��������Ml�w�^	���f��7W;�2J��XY�zrE�&7w
�z��O,�������4�����<_�^��`������a�"C>I��N0)'bAY�
�H�Y�n�8���D�D��������*�T�:t���wM���F)#�Y'5h:�.��YI�==L�:ld$#���^�pp�V0����#�tF���
�������1 ��:{���A����9o�#����6����)������a��uD�3�t
!���~�����<�
��}\�~O��T�.R8�u�����L����2�~��M*�my�������_�9�V�����V0c}~�:�
H3�[-���$ ��1"��#�)��T3}�w����m�����V����H[4�\����r##�������I`��*��������^���������9��!�,&�<O��p���~� ���0�WP�����,����;N:!��5���A����x*U��'�Z�hxr�<�m����A��Q&L������@���Qh7��V��r�'�J��*�9�����Q�1��V��a�UW��r����C�*� �m����n�)9-G�]yw�N�m��B�m�`A3JE:E�����d�v�p��Z�.��~x��n�%�L$�YRV�Y��h����yo�F����H%9Vz7$�B�7�3����/�EZ8"�f	������xA.����QwcrM��$hF���R�������4(��lu��q��X)�K�b)K�q2sF����U���2�F'��������u}UJ33�����(Nrq��J�F��&�za��i{��NW���bl"L��%/��b&��	�R�Zj��D��o�63�2C#���Y���8���C:n�>[e���@�v�5�/�!�^V�������Z�> S�:��4\���S''�����.PMIL���-,�81��Tn��@+�&�^�>VZ�`�T�(����U11e�u�N<��Ca����qc��%���������G,A���j�J�m�L�{�2�]r����o�i�v{,��y�V��M��h�c��'��4N'KL���?��;����@c��7S�M�N�������P�� ���n������8k9���[|ZU�t�hJ{n?��G���w���T�q	����7��&��589W��G#�#�����Mh]�n%7h��
l#��y���G��yb��=�o��u���G'�t�<s�ut�:hl��_����a�n>*ps��O�|B��e���+;�o(~�����X��+�o6�1b^���w&�.�o3r1_��Z�zJ{j@�Z;	�G�
*])9n�������R�-.�VnR��H��)���@��Qqc�}���n�!���FE��v7�����*v�2WS��bxR5P7���JV�e�p�JzN����F�T5�]�cJ�t2�r���M�>�8�w����Y��AC�������8�8���>��H��z	m�,o�9��w���Gm[�6����0�x��d��V�$���We��/�Jv�_j*���d��{%��ck�</g�b��F��}�
2�����@��1[���#>�"�J,�'8|f�r�+v����%{r��R��������_>�$�1.s�m�}=�_�k���n���JC%������L�|�,|�h���y���j�|W���36�Oc�F�*��:�w8�1[B7�BI�!t�'�8�������p�r_���C���l%�{�w"�p�5/��g3�����,�������������i��by���6P�z��{��v�U��'�J������`��9�����X���L������}p��G��p^?�%�� 11h�o�����NA�
�T/;��K6n��g!Wg���)��`
�e-0��#�N9�C����y�B ��JDmQ����C*��VEa����}�}����FH�7�F�������9UQ.�{�1C#�
Z��x��6��;mK�~�X�f(`9��+����K�i����t6����*����[�k�t\�����<`_��u����S��\�R�k�%=% �� ��8�P0{�G�>	��uL�x�����\�7���U�[:��n��)��PRr�[�O��EC�|��k��c�)�����7��SS���1�	!��y���d��iy�+|��//&�����WJ#5��� ���?cO6BO���JOZ1����Ud��M`3i)��7��)�	N�~��w������|��Vk��X�UW�=����J�Sz�8�������L��g����z�gw�oP�].���%�~�2�%N�:Uj��N�J��
Io�\"\��a������W���X9y�G6>��W-=K*�������z�E����D�����u� p�
=4�r������x��&9��`c����j�AJ�L��6�`����Mt�������B`��>K���Q�T�OCL�1P�E9�y�������V��+��:�3wI|s1F �����b
^s>VTk���#�1R9�t/��9=���@Ga�q
H6Qa�HAb�h����v��Cg|��e�!hC	��.t��@�wuSy�t��8m9�xU�@�K�i�F+I�Uvq[�_�^w������K� ��Po�KU��`M	���&�N���H�`�����%���+�)|����v1+\�[��&~�����H�.3\��`)ZA?��`A*p������� L�$KT�f
�}<M+���y���9��^���&��Ob����*�t�r,��bIA:1���_����0�d7l
������z_��U�V�5J�L�n�-�
���G�������v�J:�$Nst�o�r1��:L�?�~��0*�}�X=D�2��yY�pZ��L�e-�I�]\��L�Z���WU'r�U��re���Y��g�@��-�� ����������R����7W �]��hk���Va�56�(C�KHM��j�T���T�=N:�?��M5iU,yM���������)jC7^Y3�#�s3%��3��>�����*fV��b�2b�������$������ENX��S
wNA3�E�lk�(����V �H*��Nb�A���[%���u���(^�V��[A���{��Ol5h���V�u��q��H���f��~��d:�|�o��'��2L��7BOnU)����`U�C*����zu��T4sr���������^��6���JG_�eF�f�`�X`c���V���f0��J��I8o��MsQ�.����5zx�k��d���4�{����r�	�	^B��{��i�U�8����V���������Q�����������f�PN�	��W�ex�QJ��_�_s��ua����$$��k��b���rj�����B\*Py
��Y���aAn�?�~
b��Y���k��1N�l�:�-�P��|���%wu{c�����\���`�Ep�N
�������2+���I�k";Q�<��doDL��Q9I�Y�E�ir�,[8�,��������S~�jZB���c_s�")|S��
�
���(���P�9J��O��B�8z~m��$���o��@�����)�3W�M[15���h�n}~�9�ki��Mg�1F����n�g��I��=�_�sn�Gs����{�=/X)����!BT_i=�����=��u����);�;����Uj�P�!�F�A}8FJ
1<hJ��8S���Z�����|�����I����h����$�|T�<�?�+\q+�l5\���q^��}sL�J�0���H�`8��B��G�����.9����z�U�j�� �+:c�G9y���*�����H��vo����Q'�iE����}
����[���R�L�������S�E��]x�(]p{W����w{��3V�	�D��+�������#G�anz��)r����TSq�������5
4�;�5�u���`#�$X�	�]m���:��5�'U��e���2��E������s� nM,��#���hX������mC�V2�����P����� �.c��Pt�����AA?�Z<O���>���������j�	���SCE�{�6������{��S����6���#�*���EP��E��f��!��]�3N�S�v��K	�}���v ��,�)����V@u�(B�$���z�XNu���V���ZH%(Kz#��9�Mz�pDp�<��T:1��~�y$�#�rE��w�J��W��f@��S7(�[P����������6)x�n���4���i�EKP�jy��E}���LZ��=��Y�7���� �V�����4����9�8�aG��G���2i
�LMI�4;�!);R[)�������V�\-���
�%����k	)��W��%D��1'���Gq��T0�*����^��'h���`E�;.���Y�����4��mV|vu��[�����qp���~$�dv�1����$�$�P��;��f����q�����Y��Z���I#�6������G�Q�r)�\#�\���#�)8�����!�|[;� ]��O:Q���pW�h
_���u��@����7�A��F�4p���I3���z}�^�S�>�s�&��m68qM�k������O�@|bI(#lb��&��H�	���T�e�<'�
�QI�jm����[�3�0����Rz�1"J�E���z1sW��T���<��n~������u��m����Ps��F�EM�W��	��(�$�s��R?��5;�������tQ�m<#�[�7���:s���4���-���S��b,$c#������G�j�d��q����P�N��#����5�j��w��!�z��T�U��`V��Q�I�^����"�zm�I{��=;�\�:h���p�\��`lA��P8�S(���9����/O��E
��9/�]���n��me.S�*X!NB�a"���l	3?�`�'�W%�L���������+�	�d��4C<'�C�����j{�+g����
j�	@�5���S���\���	���
��x��n�ap]3��(�G��w�''oO^]���g��
��
C+��B�}+���Ta���o0G`s�LK�����L��������?�����n���!��
�9<>>��.�z�6�"�^FQp���(X��G�c����W�Em����,�oP���;���o3�p����/�I��-��-�j<�u ��@��nDtV��`-.�<���
�OW�������2��}+���{�?�����t���f�����{������{��7����F
V�Y���a{H/����^M����j;�k���5'�h���J�P���������%����^�[g�v0!�3�f5�������
��
���XO����'��&5q�����kZ�v����=���G
�96���2�m��5����w�.N/O��K??yuv����5�f��[<#CP:5%8�����d��}f�MTy��j:�4bP����J�G�;�9Aj�?��{u4��\����HEE��<}���N�c7	wPv���VRn{��f���=M��}����O��e�T��(�����j>�>�<�2�����S�v��%�����5��DK�e����p�Z�a�2e�eLW$4��ax8�Ih�-���)�c��y<i?jz��xe�o9g�Z~�����8�3
��.������U���������+��;��~�3��+�M��q!b��m�I;�^?�v����D���(f�����M��
o���GnEp�z���_�0����0N��
��U�;���f��<�O���I8L5�{��8�����Va$���i���w��K�@�G��"a�'8u'�
�y����*:2��c�pu{��I�/����m�����XM'Z��}k�,}6�Fn�o&��y�{$��<��k7X�.b��vR���z�<r�&�I�R�0j�N�y�r�^MI�7�?|NfMc��<s���:�T�VO��:R��|��{w����t}�_IC&`����r>{,W��x���`�l���/��%���Bu�@B=��2oY���ws�����	!S0���"f�z�I����w���*\D��%`��Q�i:���LT��n����!W���e���z�G���z�q�
�7hzg�����d5��v���[1��9��=���#���S6���]����������l����s�U�v�J�������Gn�07 N��mC�LoC�Y�.8{2���i�,��j������%"��2nc�������)���k�8�d�D�~l������sI��������w���h�w[nEnI�V�5���g���������f�Y���������G�n���p��O��Yl�{l]��S��&��`�5�tR���CC���S��4���p����Z2w�����$��:p�6�$OjVs�&Pm���Y�6t!e��
[-�k6�S��wGE�L�j��&?h�y��>��2x��rM>+3>��	6�8���B�	o�'>}uy�����k m7J��~�ka.����V�^���le���a���d9H�E���5��0��~��jP��-U�b�xG�s%P!^���d��([��W��r�6�z� �s�e
K#u���Y�Q�|��]jf���9���������p-�����Y9��F`�{�
1>�����N�}y.mP����-���j��a�V|�5���YOw�6
m^=��Lr'Ux������?���!��w�\�u�E��������i��]�[��""D�o����
/����UPD��q;������Y�WQ��M��=�0�r�U�������\���56�pth&zf��ytA8�p�����`O#t�Q!�f-�'�{��<��3�h���$��7�4	_�����l�T�����5"|X�UL
US���+p����w[{�_(���k����|w`�����ps&}�(�p�����"S�L����p��/<	���{o`p[ehJ�q�-P�#���t������j��������o��������x���|��J��7�g��}��n��U�����6=�4%����?lI!E�w�?*�w�:�3����}Q�T�	�vW����{��=����v�_��D�yk�F]#u�P4c9�eM_4�o
�!@&���~A��W.F@UF����;�����;v�q���J���8������s��:��+�����j;��p�p��"�b5���$=���������f�/��;4)������������HL���PEQi:������z��d@!�Q�@��������wU�p|�d&�>f��l����;4�*�M
�E�v�mo��^�=r{-:�T���
�����O��G%k��_�B\N�_�F�{-A�����I��{J;O�
�,���������W��%���bi��}4����h(�
�A��o�s���^��`�)�����~M���9���lG������rd�)
A-��������u�j�"���wG-6��x������P)[�R�m"#����2�S���'��*�q]m�w�3k�b��T��>���%�����o�CU����������p�`>w�aN�nw
G��\,m�0��"���q�:���Ej������V�9�1;��D�����U�0=_��^h���r>�w��*�
8VA��	�r�>J�/F9��gm$49��4�Oa��g����Xov[���V��`b��C.]
.����=(aB��==�����j�o�TV���&�v����B��m���`�����A?X��^�hj�X���h�E���K|��`��M��w��b��C|�����k���X�K1�����n0�b��������^�Net�	�+q�t�����yc�o7��������M�����&c�D�f��]����J'Z"����'�t�CS�K�����r��������{�::OR����8A9l���{}����v�s�5���h�������IyE5�B�����Nw��k}�Q�����J���U���r��G�9�cN��.@�Q;R�g����w�=���h�PI��4��p���kw�X�
�;�$�����&*�
�5�p���>��U7OW�
�g��|�b0n����:��M�J��T��7����f��i{no�X���KIV���s����9�8������^��H)�"$�
I*�q{����6������ �����2����B��=}������'>�n��7��|r9y&/Q!�YK�e��2&j�8i�-�ZW�2������E�_��v�y�2���Z�����O�h��/�P|�z�YS��h0������I����T��6
����]J����	����x%!`��TU�h�3Z��qA�1�]�*��f������%c����undV�g�y�kIp��6.%�����O��''��?�M��&��zVTB�?�`z�z8���	�Z��:������?��G���6G$���v>�5E��>����������9�����O�����RJ�T�3y�����9*�w�%��qZ�`m�{v��R���n0����}^Sf�;��������������g����/O��b��N�c���+�*~��������4��||nw�����/�����*}��z����������������	ha��V^��u%������U�y� 1�|h�E�#\K���^b���>�%�����4�����8W��P}�?2�;�����e�����#e��{��Xu���a�����m4Y����Y*��xS6�>/,9SQf-���>�T���G���'��<ysv>��20�7./jb��v@8E}%y�+U��������f��w�N�]���l����,Nxc]��9�Oc;��gP����*���]�;�F�|��6��D���l��U2��*�f�U�����FQ��:fEn����Z[������N��8���C{�{������oL�����X��W�������1zG��V�
�_��*+��l��}vS�0^���x����:~��s�	����~��T�9�������]4����y,�m���"
*`����5���`6�UuR��,
U�lYC2�����Kej���� {�����_��W;���r���z�o�|]ef~IZf^ar��yd!��j6�nW��8��o�Ze������2./�����u����-LgS��l���yxSi����<��,n
���UY.n�����lDeX�0O������w�k�(g<�n��e��]Men�����XN���"��P�b��K	��f�?�@`���`\U�6�)��$�l�QP>
�Qk�KU�a�|l�X�j��a��=�����N���-�eSKT+rDI-rEIz����nNf�{�s23k��P���
t�T�����
��UP����{������h\���n�����d@i�Sokl��F������4���R����8f�����!�g�c��Kl|"
�\�&+]�������*�[���#6Vm�X��
QD>���=L��0z��`� �y��F@Z����|��_x��~��;�q���<w<�,n�����q����;�d���RHq���qc��^�1��{��d�p�+���?&������L����Z�����L���Yo$l��}�a�����b����s
��=�
�Q�Wh����)�@��L����qwr�����b��E��k���K��5���r��|�p���s��J ����5��m;�/���r��Z��E��<�r���U����R��gcP*��i:���l7U��[�9Z����[��v�7�sA��'�O��Jbd��?��;�M�m����*_���R�����������% ����l��2��(�USY6)yc��^��b���bLTaii��G�Ku�K���I��K?��X�����������U��/���%���L�[��'L���u�4k���*�S����kK��/)+��&�M�l�~
���d`���~�j�I����y��m����5�Z7����QHV�c���	�����9Ggp�����U�mF�d����y�H�b�+��6�/�������4�1-f������~n��~�$4�Go��+I���'L7:�q�A/�vK���M���Nu6Q�7���h��~R7���(iw�\jBt-�i����Q���t�w��6(�6#@������8K���t^.��}-��~�x�+P'�����x��.?��X2rs���C�YV��*����T%�-������x�z���f�(I���^$���2�^�3����E~����8��e���]������	r�/WU{��I�F~�[$��<��lG����t|�����?�F��5�NrkU�����0%2�@���2��Ry&:t�L����4N�Hu6ew���5M��Z����ph���'{ga��aJ6��8��������<y��9{���}�+:��+�h�Aw�~����/_�7����rv�3=���@�a�A���w��Y��~�}nqN�d��=?��������,8?��r{`������1�JS�����~	E�6(sN�}�����H�����'��=U�5A���}E��Q������=��.��(�]~�������mp��������~&��Q}Kk@�;O�ai��N�?MT�	�����g�k�����������~
����>���;���S?��X����M�:�=�On��A����|
��f���,�Y�������	m�"�Me�C�����\���0@�6��n3a��d�p������c�9T��~M�Z�v�AP�����~����~�9��ws�V�������Lx�a&��@im�����
"�b��f�3	5���U��>u��b���9����}��T���^:+��
a�T#��r����H�n;g�z�O����^��^s�������:��B&T~U�(���D�}����a7��y�\/�um��f�4Rz�ry|�������.�P@o��7��u�������������3���[�����V��5:��P��Rc����%9����#M�K��������`5_/iG4}�X5SE�'�����x���Tmh�2&���Oz5�N�dl@Mg�R��
��k�
i���Bi	JK��%(g��g
�������3N��i|�v�y��] �e�.�������
�h�Z�6'�}�V��`@��]�T�9���-��m(:4���}��2��mZ���a���@�^p�#�������uA���G���%<���WXIba+o��HQ��^?�c�^��4&�8�6��S�\�G�B��d����;��7���n�q������b����O-:���N����/n���-�`|����i�:�)�"�p����b�~b
����=5�F��LX����p�C�����)�����c7yRBCc���M�t%�����R�hZ����K��I�4���JdV�+'f��7l(��������'oO@���Y(�8�g9��X�M����*����-Cu|�����3n����]]:�:�kK���#*�D�1��G���������=�/��"A��o^	Y���(e���h������N������\iGP�%A��
�UT��=6�7�6������o�^,�%���+��3�!�r����~.���cS���c�V4-&8�h1[�<�S�"-<���Y��A����~��S�9 ���e&fk��f�������b����pF^��:i��O%#[����������OU�A�����&�?��O��V�v��\���K,�����[T��k7
�D�q�2�R��5g�b�L�M�}�)#�����_y��FM��������2����,�n����N��b���-|p��*Rp��|����=-���w?!F�h�v����3�!�l����)���)���2�V�� �d+�P$>V�O����7�b�,���d�����	9��X%�#��o+����"�}*�v�Q�dl�b���wo�5E�/����q	�lAq�2=8�"Xw��j$=d����s�5�����QW%W	�����]�n�sP3������:�]�r C���z�`�nn�1��K��(E-��G>D��F��K��i���PI�YA%����:�f�����YE?��&K�I�+���;��)~X�T�R��x��g�2�0���m��a#v8���A�H�g*9��)�*�}S��%�������s��Ww��cwg�,>�!�tn�%��q)Y	c���f���
�F4���\���Z��JD4c1����/������O��dv��������(�+c�+�=3�t/V��8�,�K�i�),A��k�����[�b���SuU[�2����H���`�
|�;����f�~�$TVK%��*K:<�(wlO�`��_�[����^��e���BAh���d�Q�i��A������V��Y������7� j���>�:j����x�>Y�������)�T|��>Tc�s����O�n������e�M���w��z�a���`��J�,U�/U(B�?F�����5���q��j��G[t9��mp-��<P�6�|��g�*���-0V���S{nA�c��x%�������X����������#������ioT����Rn�r�em�g��a!	��u�����F�����]2�\�����f�S����M}`���=lU�7��J�*���c�N�#sQ:`�_��
a��i�I:lSh��N�0>��7�U���CE��}��H>^�lVZ����0f9Z��!�C��R!�3E���}�e�
��gn��j6����U�U�f��.(�A��
?-�(�K�?��n������+���,��Y��B�(0�~�?m�a+�����V"��..���t���iKx@�������98����LFyXx��XR���x	{��9��e�����t���-Z�/N.�>L�~y���k��!�hf:5�4�w�wU��pS��r	����qg�A���Z��[5q��Q��\���6�����P����e�fF�S�hfU���C���Ud�K�_)�?]�Dk8���D�"��d�\��8kO@����#�c�9�����I��o�K�*$k������i���������6t3e�C�C:����>vSb7�t��m~�1�q]����f��)����6����\��x�x�
7��n���������|3��8�����r�����H�)G�����?�1��*�5�e9'�l�G��LLA��s>��;L��2#f�����M�����B4A����;S!}�]R�����h�k6���wGU�Vm��z�4t����I���0V�?�����I�&!��['W��i�N2jd���MH�4/*�S�R���P�4����f���>�hF�2(���M��}8���f���/�DQ����?��V:�{���j&�dc%K+Y�-hC^[�i�-]���WU�7�����b.�i���������M�WV�t^�x�Z�V�&?��`��{^�����\3�1\^���
��`����l:�Y�V]#������aa]��u �r�"�������nW1��d92~�7G��'����e��/��
`g)�sUFY�����6����i��Zt+%\�������^"�������_��������mKT+:�'���r�-�$����YN���x<����h0��zX-���U�]��$@���..J24�Z������b�%j�>Y�<�@�Hu�
�Kg��������&
���g�����~e*���h|�����*^2F1u����A�9����~�DfC%�,�9��J�M_:-s���5���z1�D�����N-F&ZDT�J�>7�����	�x��.��ZhfEh�����������st{�M`���f�f����,�
��Y�23d~o���w��*��������q����~�l���Z�����^m?Q��
N������K�����D���*�NQ�UV����o�%�Zs���
80[2s��U[�����0"��c� �h{� r�bmj5�����K�����������g�'�/�/'��9??y99?��H��6��{�[�
�p�D�~.o�������#��2Y�!��_���P:�`�+������& 6YD>d�!���|?�,���qUW����3L��\
Ut��������CJ���jm����DQe4���n�
����vALU�����r���FcL!`���e�%<Y����A��=��H��:�{>J�B�t�X[8��s���-z�M��������?�V`>�B��2d�PVy��������>1��~�%K�h[)��g�b��u��m��-"�M��G�Eq�A���T���d��D���N/g��PV�!��<<&�!��&zw��
��8T��R��X��HC�p\.���x��X�P�����������B�j�W;��X�
jt[��8�H����}M��]����E�8������E�v	m�:F�B%�R2�&�c�i���:����e���E|����SL4��'�~��c��W���#m9s��w��D%����M��e�������O^��(�FB�\I��6�s��i�[y�\���T���`0�M�������F����"�,C�����k"�r��Z;5e�w�y���	Ui�/�{��n`�~�`BGD�8G��utM���D�L����B�h��I%7���B�>���{��F�NK�H�)Z�;���Y��@��v�=������7�n$iFk���E2���	AY����h>"�c0��x�����)+ ��Y�KJO����7�����A�����4g��@���?��Q0��.����7Y�]������
������|�\�7�etU{4#d)�.�����n���}�_Q����}�r��tD��}���j�B�*���x��� ��qU����_�"s`�F�������f����)���g�>L��r�l��IjYQ� ����#�v��(ax��\���w����F���
����_��7�I��W���I�G�����C����~rM����PEUW�w��a�	[�h�-�>)l���������������	�X�r������k�����
�E��1()��uu��H��oY'�,���_���c�h�N�Dz9�T���K�F���O�#�@0v�@�Xv������N��v���<]c�q��n��T8hZ^���aL-�!��(%*���!8Hy1�bZ��-���=PV��|�)���]�=#iQ!\x��(vH	������f(OV�>�4
��r<l�����'��}���EE�����S����6~E^�K?�3��N����1�!��
E���]2�Y�4�P�@�����
��U�������	N������;1W���d�]�,��N(	��d	���&7V�
���>�OI�
e�iA����,.�Q7s){����R�})g/�J��
.P��uB����t[��`�l��v�WQ4�)���}4�#��S�_ma^�F[Y�^�V�?�����k���=y-�����c"�o[�8����c���9���?[�kg�:Eh4�p�[���3'��96@�*.^�,k����b�|�����-kP-��0�t��t[w���t-����s�������M�
UIP�@���E���v���K���'��W�e���+�=����)�i����4oF����1�B����b�dQ��4���L�%WI�	gu�����&��x���&+b�Y�~�������~S�G���?�����Z�YAq�vZL��s^�!���'<:����t���p�u��>��[q2��ougG����H.���@�'��
?�m�I�%C
W�7qo������#Q��Z
���$^vk���8y{�����{��O�n,����}n`W�����WWi�z~A��{���lv~k�.�x+h*��������rz�B(5��DAC�]p����`u�r�@':����Q��c�2�hE�<��C�'�?�WAp��ZC������/���m���=��-���E*�����������o�!��[���f�Z�V�q2V�������o��"/���_]��#��OA���.���
d�4�"��6���9�21�Oo@-7����	Z ;���e��������G��za�
��&�~MXSQ�	����~f7%lj�-��;@q�'4��(L[�e`�C�~� we���)�TL��)L��.��U��Zb�[����(�1���VC[]w�-@�l�HV�8���r�'�	 �t{8(L;!g_qB���!A�d���[)�."����	���S"�Fb(��T=��O�|�SR%B0���qF�PV$G���Hx/w���\��9g�������������l�P�������-(y5!����
��n�o��|y��U	�4\}��v�%�Z����W������"����.�U�Z�������]��.���2��;~��ng<��-���N��":2��'$�����y�y�+��������m���vA%��F�%��@�X^8A�S��+g���at�����R�
R�\,45k��T���R^������-'�cZ�E������%K7��z�Y(�B�6{�{�~�9���Q��6;���E�*H�.����������-v����Xt��kq�%��K��H������
C�D_.����x"�@�!�Y�E.
��l��y��� V��J���=����K��K	������E�Jw<�
 L����0RR���N�>9�8�����O�:.HZ$�!�tE#%W7a%���MT��&�U@������?�3J�7��u.��{�)�00���&��=��(���g�]Jn�	�38�"`��N/�?0
�/KP�|l{��w�^�����1�e�3��D)/�J:���a�
�*w[�(o�@�Q�H������@�e�`>�.yO�9%d�L� �=,O�
d��s;��2Mf�S����0<j����v}��k���b��8�bzl�����D��IglW���H5���[��Y�b9�c�5��#�1gv}#��D]�J��y���K4�A@�!#f�)�������i$`��q����,�=Zu�S���~����,����1Q��h����+��I�[T��l#o6lm"3������������_�&{�^��Rj����V�������J5u��l�X�/wW��s
��n��]��:���"C��S���=��n{�=^�W4�@���T�������-XQ����W�S�������y-�Lauj
��N
�i�uG������Zq9���{x�)��}����;ZJ��������i"�����X�+O�0��X/���.����IQr�>�G0k��c�1� y!�	
����q��dVS^�q�o���8O��|���1�:�	jE0�S��F���oa�e���y���K��2J(�����M;�fk������6�<�U
9�'@_=
�e��|��~.��3�.�a38I�wKF�p���G���0����yM���F�%�1,���n!�(�ng�f��$[2F�#[����:k��X������|�#or����d����'�N���'���^j������}����u�z%6n�'�[��P�@"CYp*���A:'��m�����o+)`
n��?�R�������d��lA~:��<#+���1��l���_�'�����%N�������[���+O�%��|��RKvVY������XD�~D+`��
{��$�T^���n��6���[cqe���)�o�����������!���(F��IMiyM�-�U��;ER��e�rt�^�=B���AH����������m3aQ������������F]��W�����/��� #���!q	uI3�f>^������
j��F�b�b�Q�d�����v�D�����<�\|}����o�OT�_�?��"u�}��E��v�O�i�����j���T
�5G)BPti�#�)��<{}����)X
���=����r������?8]cdp�K+��*|TD���R����S����je?sJ�����ui�T*s"K��9T
6���0����
����=<��t�[7�������KX?p�����o��G���p ����Y

'!�9����2�?[GL�!V��R�.	����>���>�����+R�A��n����@cT�������\Q����X?�]hD�3�Ap*��g����**�.y�H�W����r�r��SW���%Z�X��J��f	F�����Mf�U�N�S���`t,���z\�Jo��`�v������|&,Au#L��� �������-I1����taaG��ox�&��v�����<k9���������n���|���3������XN�>�i��_9����5��:5{g����*�)�]�8JQc�tW��s6dYA��`����l���O�d�^PX>c�F���������F�SwK��&7�����l���G*�z\��7���XL/��)���I�+����i�J�%Z����+�Y:lP�L��Z���j��M���C�8������m��wDL�3
�Z���3!�E���M�n�g$c2,�!��eJ�oJ�b��`���P#��-�d�{����b*!�96�.�qM��s�j�2�b��H����= ��;��_����"����K=�>�*PJ��B0�-�G���.��#�St��� ��4����	��Z0>8��U�4�~�M�&��,�����`�E�@��bT3o3`���w�>�6������������9i���3w�IK����W��%]�&E=�����|/]�vTthA�R64�4���b��S��Q��E��Hb[XmA�p���&�{���z�����g��b�Iw
Ty��6��+��;T�k�.����K�/w��������%��r��:a�������Q��$NO~��F�����I7�B*h����F����4����s~�	[GH&��-;�kK���f7��O<,�)"*�l����CCK�S�����-�8�^oNO��~6!R]������������/��p��
��h��:m?���/�����q%Mr*�4i`Y��Rnt}}����50@RM��s��>�xu~�������+��� nVE����<���m����[�tB��~D���3�1����������|��sW�q�*�}��������Nz���`�w�)��s����D�H���>>!Vx;����gH�u�z�?��C�����9�%��KO�����6��@x�����T��1�^B0j�|F.z���� �Lc���u��P�
V_�+	���|���k�)�����	T�c����Z�1��y���R�v�}��\�N��9�(uO�Hn�Be���_^L>|�?��^���r��_x�%�����s2|l�a���&8���m����{���Q��{���I'�fi-1 �re�sS>�}�W5���^����:1E%�!����7���$�c���z�
<@�;������0Qn6�z-�8Hz���x���.��I��/��4��t��������/���?���[�qg4���{dK�P��,"�����.N�}������Qn#�e�Z��"�{$�����������,M�%����|y�d�K�W����WW����fP�0���rg}�y��xqi��`4Mw�|�}�>vE����n��5��(_o�u~�i�=��o�@�����FZ���p�L����������������	��bBp��-m����% 4���NMB�ku�Q.1|�?W�v\�����6N��5�F�6
[R���Y���^�O ���]�J�S��}�b���"���1����=�>G�lr'Qz��������h����tH�K��S�Z�nQ����e�QuQL7��#��BO�P��mhA�}�c��UV3�f�Uc/�m�hFnr��G�p�A{=�7!&�q�{B��=2x�{$N���L�$T�$�����"PH]������K����u�����p�R��t.�5_Mq`��$�/h��5B��%9�0�A��p���icg��\�5_&��%��������A��
�S/Ya�r�<���+�I%,�H��_F�H\&�TbZy�Y����i��c*��)�OR���R���>��{1}�Ia�����$@����S��O,��lt�o�FS���x��e��r?�Ma*��&*�+�J���F�@a�w�n���Q5����$�"K��&ymq�C���<M��Pf\�a.1��,�v�����K-���mEMX���o\[F']�q9�:h�e5dt�]�6���`#���k��A@�88�W��{�9&�4�r�����C�_�����0��v��9�8�,�@j���]��B%p�wSgg KW�4������`ZGi��1b6����0q/��*9���{����#�A��o'���0�	��T�u,b���$�+���w�m��j�[=r��W����5������$��T��?2}�Y��M�6���37�]�����|E��-a��"=C�'Y���C��~dB�#��6_P��T_iN�dFz]��Y��1��C��*��\E�N5�-Kd���O<�O�w������)����h/���`
���y������~�,d���q�s��2����<���RV6+�L��R<���iX�<Q���5(#W�ju/~����1 [�T��k�`����{l������o��7>�K�=�|��8�-G�������K��;r��2,5�Zy�����`���)�<ok&�
��4<�iQ����:,@�����k:����C!��a�_���h�[��r����'�E�QbWE:j�iO�P�>;������`D��8����V���������U��Ih��[B�\�vm�S�yljSJt��?FK�\��2�%0����{|>X�Z��9%�z���,	q���d��o�����W���y�3k6�s���g�q%��Q%�20�&��g�O�H|[
�Q��(��+�Z�����9�>#T��gaBU��5��/��;�����wo�p��p����x��\L����@gk��R&F Y��g�z��~1�&p�,)�6%���j�6'P��h�l����9A�#J4B�)v#)�0DKo�9i�%�G,��=?p�'O��B7����|���]|��b$G��~8o�����\�~��/���W��z�|��K.�&�4�>�s�\mr���	�9�M���l��(�.�:E�?gL��y��uf����[Rs�6{���2�G��J��(�JG��p�i�#O��J#���-��Zb�s~��#���*G���
:�K����|�8Z�����o����t��&����%��c|�9�4�����<������F�hNp]�t*}�j�:�x�m��=�F5b��&��y��z���[�'���[��hw��Nk��
�������8��`��n	��nt���Q�J�����Ng:�����x�����t�g����G������x{bg�\�k�=tZ�g�?��y��<s^
��/]���f�)���>
��&�|o����� %�g�j��9������i������#�����/vS\���}xy��k��y�n��1A���9/
WW��@3`�]��XA�9��-B� �RP5H��q�-u�G�DH�!f��W ��& ���ZY�?K�i��[w���'������cO����vQ�D?^:
�@]y-���_�lh(�A%��M�g�bZ4������D;�������r��`�7Dp��C�,��_N�9�rm�NT��9������r�l�4Q��v[�f�uS7#��CE��9����,`{��������S��r|�P����$���gY�G��l����X�qDo���������8�1��kd�4��~x����~&3mZ(��{�� ��Qhu��A������G��h�m�~g<������=���mO������;c���O;?��y���`!
��Y�n��n� ��dr'R:��--������6��)R��'���M����8���ED� Z��'��G*N%�mb�[j���8�,B�+�@VZ���.����Q����>�7@���"�y�~���g�;�@���g��������@>����f���z�^�yCQ��2�],������Hp�L"�
~\`
�l��#F������e���P&�����]��������r^��:RV0]%�/�6��2t�)�:��w��4g���_�����UkF�+�4�P��V�)Q�R�������B�J������_�*D�(��/�����xr�������WW�,���R)-�
��K:�U1��N�*�t�o+Q�0�n�U)L��K��\%�"�S�P����b�?T����G�?��|D*���u�(��-�i����wf�������`8���������������S[�W
>��o@�NS��nB
J:'�����7d�RR�Ml3����;��E;��V��y 7�,=��&.�N	���W� ��p���Si�+F���i��F���y�y��v2��}{E��!���7�������(�?Y�R�S��_��(��w|\_�n1�Kr=�~=s��}�7�tS)���C��1�|��y����~�K�#gx�����o�0�(,�[��+X���d0�-T{�n�����mC�4����^m�����
F-u�^O]��e�G�!��eG�����~�k=���l��p����l0����<��p"gi��4��ih6]Ne�y�-��v�i�RJ���qo6n6����v�����[������6g<���4�|�+h�i>\��n8��9�zK
�����z��_���A�S3r��R����D�0a�s������H���Qt�=I�>9��4�d�M�4�g�"��mb/>��+��aa`0���nz���d,s���+��j���{����v1S��ke}�o)�� �,�~�;#���!��Rt�3��(�)O�W��,��	��
�yR�T�B�s���iK_�p�u���
mBO��'bO����
3J�s���X0�
�dU�p2�;�����X���x�=����NespN��)�	���X`z@�4����H�����TA���Pq	�I������h<$x�j��a�e�qV?�F}Cr��?������ET2�Kyp��X+��HkP�1��>�./A�Q(��R[JT�F�*2�*���w�2����y]�o����`����0�.���S����U��Q�^��t�m8OrtD����\m����SX+�����2��'8���g��'f�L��:cJ��

@Rq9����+������n�a�L��v���0�r�':E`|6H�s��[�|jv#^cy�S���������M:1ndH���9E�5{e���O��6���}M�"�1	��O�1F���u����k�-��X;�{����!-��U�H*:,��%����\@n5��8
�S��8��L�����A;0��������N����
�"g(2�8-qV+2F����]�?��*���D���?\����kw�8	-Y�'nd��R�pv�n�;�w�����iV�>9�22,�B�r
�v?���m��r�W�Yc��$�����#!E�N�X�KP�R�a���R�:���p���'���y������M^S�t{������e4�����GM���s�yc6"�w����LR���!Q��n�[^��Z�kFjI��g��A5��4o^d�6��o
6Q�Q�	> *#��*S��,�0I`+.�?��NQ��#_$o�B�V�r)BI����K*u.B;�K��$�����Quu���>�fs0�}?������4.��}��Ox��������zB�5u�w��U
%DP�s%:������W���6l���(����`rEf��YK7^,��3�~�Y�
��G���D�[,��RY�P���_��f:T����1V����z�^�z��m���o��?OW� �����]�����"^�
JP]�����$��{%TI�����V�s�e�p��7_C'DD=������o$�I��a�a��
�����j!of�O^����o���swI�8��::�"��
n���7�_�r���������D���:S��bj�Zw��A��)v����k�yV�?�����������gs�E{l��
}�
�f2��gG��J�h53�J���am���a�w�N�k6;�v���*���J��Di��]������*��_5�G��2!.�Q�]x������(kt��,9�a��aw��wdxwT^fm���N��v�Q����h������������X�_��{K����sK��T�u���H��N$I{
����
�|���t��G�1�7���s�A{�xN\��Y#�V���I���M�iZQ�uu���
xYN(��(���~��n6�C��3�"Vj�dm$��M�-pwm��#*Q����dj9���`�7���y+;�*1����"a�7%{�s'������t`�6���b�Q�����!�pF�q�s���/G���f�.��YNX��{�~��l�~k�W��VK%�e�e�;b�k�T��7���!�����`��p��`'e�kA���R�����X��=����_�\/\BoD_E�y�z��x��?\xq�z+��&���2�%2�CC����Zcl����'
c���SQW���|w����%EqE6���
�,g)��~�����n?#�[yK%ln��l���#ar��6>�����U����N�(�k�����sDt����P(>��)���O�w��9��Q�d�_����p$n������sD,�)���*�v���'"�tl�r.�:wN+6����Q����=uF�lZ�X�S��ek�=c:�CGB�l?����U^��[n��_���w���f5���<�l^������]�|FB��_��?U�t���V/A�;T#U��
�`��[L�;�)�1�cA����!i��D�^���U�asRa���M
��/�3�~#��N�>�/�~=������!I��f�\�X��>�XPi��L��f6������������0s�8N�f%�&P����L�)�k��������������_]h���pC�1n�����3�=a��O0���%nX[��u,r�Z��|B�r�y�#�
�o�`����#D��<,a��A��b�o
�F��hN�]u&��Wv0|����[
��;rF�����������O��\chQ���1_P�'<��]#lq�O�R'���M#(	�d>C��X6�^���#����=���Ge���@N�����K�����������Z������1}��l�e��8�D_�[�B��4��+2�?���e�TV�~q<��IDI;�%��|��{������T�y���Us�O������V������� �]�aP�|U����T`�N!������f�����!6U��E/O11���'���(W��9��c�q�k2-ar]4��t�L�,s���i��M������mU����SLXy�=������\���O��Xf��2��s�"���i���yEf����<��	��	������Fx'��������D~CyoK.�p�k�����?E
<�6��i
�����������G�/��������m��^��G#���|4��m��u�n������w������u�zy�/���w�������8G9��������~�����!�K���.�#�w��C>J:�p(���������\���(�(^az��@�{��|w,T�m�e
s���>�����s��v�B��	h7r�F`�}L�A/�����![�V|��T����h��T���(���\P�N���G��?��9���V����hy`u���=��0TX@1�o�\�v`K�$�2��$^��.�RW��7���q�����f���:~��=FLg������2��f�i`K�E��Q4���%�1�����@5�������"F�B��"_77�v2~�(|�� �^?���
������_��
��/��:p��qJ[��D��IY���$�����m�^���I>�=9r��3`�[�?��kqAC�N����1M�:p�qg��x����/`���D��0�_X,G|>c����xf�y�M���P����)��f�F�9%���Oi)��`.��'�c�b���Y�c�������L��{�@���j�S�v[��4���J���x��h?��}%v��2|���+O��I���
8�B#�*9������
<"�h�^���Y�#����%37��X}"�0��M��OF��2�b;�p�\��r�9������>����oT3��k��c��2�E1��s.@�hy�3eM�/��#�gD.8�^��������ysr~D��oN�����di�=Xi$q���6t^0&����K����Q���}>����}>�XyZ�tB ��/o�~��[5��b�5���j��RJ�����C��c�Ar���D2���ag�\E��3E����#1������4(X�W�&��6l���VY�����/��L��}�P�|�gp�\�~����Fi�[_���@x��#N�5�}2H�f����;�)2�y�C��]uq��wJ������^�����S
�wc{�Q���@#�p0�������y�~�:�c�C�s�������
J���=X�C����
�"DG�{��o�t:����������#��x��{�t�y������h6���`>v��)<��v�'����u<s�������Y/7�P��5�N��D������N2l9�_����g�R��G�'�1/-������I�������3rF��� �p�����$>?��Mp(UuX!��������8Wm���YB�=[����YcL	�"��iln��3E����o�������t��Pg"�.1��������~�bm���t'EQ�a��1Wb�t����>N<X2�az�P�����V�o���A�9����|!0�K0�78�<��H� z!�V�X���|����f%�����:��*gIe!;��������|W7~`3�P�3�����_<e��DMv��_]'�w����(b<P�b�N��|���s^����8��������Dc�w�Ur���g��]��<�;�C�
�XdE��S������	1H�������R`��
�����?
���t<���dvS%�2�0)�h<��R8���I�%~NG(����������0��p���ZR��bL�����rO;[�l��:�����1�iXD�!/"Ts�j����[K]�l*4[����#��@a���3��������t���@w}G	J�S.!������zXnP5��Bo�`�8<f�Md���tP�V��ml��x����f��
R�;���Gi��D���j�Za:w�	$�(7�Xi=s�k��:�:�Y*������ �����"�����qE��<s�m�[�e +��� 
d��l���z�D+w
��/�C:�[��=�|m�V�W�h�S���i2}�8�\��4�b���������������h�o��'pKI�)W6wj������bR���.�6��$Q��s�%/����j3���E�z��#��`	Kx����2�������I��|�n61"X��d6BP��M���M����������9Bj��SC�Vq�����:�D�)�1�)W��;�>����x��A����#��%
e�Z�4�>KU�k,�0gS<���l�[�{��j�q0f`�$��Fhx���GG�[~���n���P �,!
�����_��Y��������v���p��~��9��������;���c���g�y����a{���������������7����uZ�:�����	�]1g���d����8b}��[��M�uu���8��M���%p}�7��M���z��:�D2	;�ZP��9�|���yRJYE%;7n�|�g"aJ��(�SqI�r#��O��B��n�vK< o��aO���Q�f����{��������m`��������]2K�M�������s!�>�y��Vg��d(�o���p7p?���
��w�Kv�]��~��l7�
V�uu�}4�]�zj~�y�Q������z���.)r�/��'�N��m��E�=�Z/�����v{�o6��?��`�X�����w��p�c�D%D�aM���u��Py�
�u�
��{O]d@	��v��"Pv2lRc��Q�l�J��x�*����`�R!NJt��c��<Ko�����&wl�do4�G��1B�Zoii���Z�$$<�,�h�A}�����nA"	�O7�t�J��jVW��������.����$�kM��O5v����d"��O�9��������u���!)8�����!��(��f�l3Q�L����J ���+Gbv�=��z;�"�m������!��n��@����/>�{�F���z�p�P'�^L6��9����a+��u�x�w������?^�=u�^��u���4A��;~�����
����?������A��g��,[��i�_���0'^Ah��/1s~��w�:�cj��������=���&�7>�w�aB�|g�Vu����g�>��]�0��18
oQpD�p�+��%��K��MJC!f���%��S��}��A�N�5o�P��������Z���JO�t��]�j�(��
T_,�����T6�an��<x��)�^XI�~U%/z���i`�����f�7��A����RZ��/�v���qc�&���@CK6=�����^�h�$�G|.�+�'
�b���@N3�
�Fw_TJn���sq��_$v����wIx�-a�BCgY��s���v&����������������D\&s�-�Xa�����H^����y*��19���q��E��sw<��I��t;^��r�v�#Ig\oS2���D���PR-���i�r�Cw������_8@@�1{r`���
0��85lg���(]�� '�������y�����I���N���]B<�\����'����*`����&�A��|O�_�-�pR�h/��]p9�k�W|Yc��%��i
r�����1��0��#+y<���p�s�N��n�%��zJ�����#P��.�r��f�u�J��_���#��]����Y1e��OES����k����hp$��k�J�*��*G�t�~
'���av ��E�$z�M������i6�82bE�P��zN2�UL��j$���nN[~����9�	B�K�k"�$1r�e)@�[�7*F>^@X��q��2�a�Ydyn�9�;�1V#��<-A
���O^3���=��@���1��?�O3s�1���|�f���Q���e}}�	�d�/B���6!��
9�'�\��$J�H`F���(��2S�c���-������F��\���g��op����k�Q,�����
w2TT����x���?:y{����������gb�	���lW��5"V���IVM�D����V��G5���_�#��
���W6��0�����
�L�_�b��|\"�5�s�r	�?�������?Z��=�|Z��J�U��@iV@�l�����Q��A����,�����nn���E�i�PB=����l5��)l���]v�.�L#7��pC.\Z�l��e�*2����2���H��!�R�ipj�I-�K�?�����bJ�
i*3�9��	���25�RH&�Xf���L2������A�A�Pc������UF��U1Q�Np��,�R�Y�����R��N�9���[p��@�4�D�����=��4��X��=g�|Fcr�a���
�{��Qo������^X\���O�oS>J��W7���W�CI�G���[��'�0������1�� �@^����| ��:�!)���6w���+�b��H�����x��<�t)�a��	��_���<��"��]�rs��WW��1`�k91ya�R�����5?J��(^�:;�Q�����Q�0�V���`�,������zgfp��a�.�P�4�K��H6a��V�M]������]l|�����(D������,J;e�i��b��rv���w(�,8���d������l�lz�i�?��~�L���b�	�$3�$)���mF~�z6N0]�J�����0U���/��d��� ��k\I.��!�
�$�p�?�(+#����$��p�QB���X��0��%�����v���
�����	��	2�?�]zl�E��!Hf�/GE>���}G��0P�2O�0�`8��Y��p���K3����";�},L��q�R�
����	�_���L��kv-G7|wr0��J2�:�~{�l�����.n�Q�.n��;'>�wU�X#��u��d����n���

i��	����60��Y��1>��q�5�P���%�wL8�9�U�#��g��h�uS��lN����d�,|��A�<J�������0U&N���� ���X�z7����hIP5T���xSK���-����	��;
�,���HD3���\�B�l�
�e��OA����\B<��4��zq�`(iO.�1��#P��%@�dn*y���@�Z1�O�AvK��H1���f{v��%?���������Q���"����7!��W# �T�a��[�����0
5��CKI^@nji����LP���T�+�;�eDz4&�qv��i)��i���������k Jlg�+�����=e�F�y����^�y���m	S�#�%8�S�3�'�1b���jM/}�I�%�e��ux�����=�&�*@�u���E��X�������=�pB��S@}^V=��$��/������7��LO"�0�g<�x���J}�������7�z�K��U��H�Y������"��zHM�^*������/��n�WP���h/��0�7��C�s�S��a���^����A���S��>�(f������o'I79{��_���>h���TA��M$�%�c�*H�%g� ��g��	���bD�V��K�*�S��&0�Xz!�,���9+a�)�������t�L6dZ���B�PY�����JN�zi7J�c6��%E�S��D�������d�|������7�_����?8�#]�Ik�5�+�c�h�����9���EN�L].���_8���@H�V�/�1��PT����r��%E\2�U��d��iXD��l��5ZL X�B�n���
T����*l,E+���[�j��he2$�v ���eM���
�d������]7�y��\��O>��N��1�S�t?=h��2�T(c�%�e������E#W
&qN�:��;���:8��h��\��q��A�P6�-N����.X���WxC���������x�|�����K��z�+0T�|�+���7p�}?���ro�����i��~�x�z��7_Jd�'2�����7��x[����	�R����_�\�:?�pyv��u����Nj7����!�����2ki&nuy!3�������#��z&���F�Ko��*��0q��B����|{����E
��l����ah�A|h�.�'�����&cQ���
=��|s��*���B�(��/���P�0�s0�������b�v��;Rrth/���\oE��lp,��eL�?Sv�Y(��Xa�=���kO7|����Gk�%�I�&25(��2����i�JIC���+� ��2F��!�A�[@�2V��]}N��DZU~L�dbT}�=����_����+u��}��_	�����l�k����r
N���"��G>9�}�hW������V�R�8���cn��9?�d�q���a�f�ar�I��)��_3~�������a�x�y����CPb�@�O8<7��pg�����k��������~������qw�
gc���������`:��[��x��f���'��n[����8b@����N��s'��'D���e�!�A5v3�����;%^�����30��
/��j��
2�����Af�E���Q	�E
�/#�����)���^�5�.^���?e����R��1�����@�4���S���!��Oj5������%���v0�a�:�n�d�B�����_;9��?��p�y��n6��a��d��;=����vY�n��r���-����K��f3S�%�H6	�+��G\D����z�P��<�������m0ED$b�Y)m����c�S^C��<p� lZ%`���6WZ)�6��w��+�etQH�Cb5a��dS�����b�!����
�FkD!q�:69���]��A�sG�a�If����L�����.�`���{�[��5��_���n\����=Ih��?����������_��tz	�����;����������j{�����#o6���v`���7��������r�j��g���~'O�k��G�������i�$������C���2���-������������������� $��BeF����rR�TW��J�K����}���v��#� ���zz�@2-^��"'��C������
H�&9XhTZ�E��-t�,>��5��b~`�X�7���ooB�AY�P����|B:�H��]t�}�z'�#�<�py���W�t���8N
r�?��'�U��,��#vg���"7d��������D3��i]�c%��6	�#������$��SC���w�@C�&�>]�Br��a��n�?4�f(n�������.
�6���R mp�r��S�Qj�u�uP��%����y&"z�������{��E�?��s�u���������Xl��"��E�!5���O7]��W�RI`�����i��������Yo�:��:\8�RB�Y\'M8����|���*���$�eT�dHu��n��]���b4�/���]���	����W.����`�:�����t\�$:�7E�oeL�LI��s���0�|������	��U�v����*90Q	���UY�����|Q�
k�@`1�S�����	���S�x{��?��uv�`2��>�kIO)1��6�����){��7k@F�
X�B�S��2^��$jf�;,�����M���G0w��f�=����k�<���f�*%���������b�U�SP�@Yy�Dp��D���D�t�h�i���c/��V8�$��'�o�o��M���.��a�����JzY�cr��)��U�7X����S1���PdF�-���Mtf�	�T�>\��nX�)�K#���G.��)#����
W�����w�3�*OU���!D����<O��������;����Ir�
�5�(��|�j�
�L5z�2�����}4b�]�[�\��^�w�?O*oP��	��G����;��A���~4���U4]���A��zq&>�UDT;�q��7���l��2��
�����Q��B��c�~�@$��i��JdnMEe�c2}�;�99\xD��	��gth��ds*����M��]f��k��p���H�#5"�J�h���o�^���a�)�t���?��kL���<�M�~�M;��t�l��n��$I�Osn�`8��|�#6%v@B�#��F���^�A�����%k�$�k���AVU:2��o1�,����������w���ZMh9d0A����I/�����.�=�������T�Z
���Aw#�U`��j�I���"�+���`�X��$N��@
��G�xTM���B����}��'���ZN~���J�{�|���w��j��
��
���������
����V�w�D���Bt�M�1�x��x���P�|��� a|���I|��v��dX������������UwI��z�(}��M.z5�U�h��3���5�����k�-�_(fm��-Z0�4�>I��%�O�~�7��������G�>I7��'�B�=�"E�?�f��i1���2$\�����	w|�,�	oD�)R�~Sb�x�x%b���F��R�������!,�q�\�eTb���=v=P�z������j��3�r���=X��n|��'�[8�=jp�y���W��g�'/����3N������C8���:^�NZ�^;�����?Q5k�_��U�^���@W*�=[r��`�I�U%�+����_�4p��S�u����h�H�/�p*AZ���7��=~�;�9��1SY�E��@	���#�B���B��|���S�D�v�C��llI�d�;�c�]�y�o�
nP�Z)K)mg�Hj�x56�)��0S��UMQ�6������.IV�4�������m�9[����M��t��Z�A1�i�#%�Tg��Q;V!�n�=.S�������s�����������,�+k2��0�/��yBJH,���������#d���LS�>�*�x�6�����-g%�������n{;��O�^�a&�����(I,����|
����@�]l�����I��;���Df"P��^�H��`�6\�:,�3?��o�
��`',|���y�e=���zb����`��q���.c�dS1�4g�����a���J���:����y�?�����?^�L�]l��ET���?j��f�w}�;�������Y��{CN�"�������9D%������8D�D�A8;}���A����g������	B~\�F]�Z?p��8K��lEx�u0��Ep��n�$�	@�2�����$���@�Y�m.P�T��0��)��h<��N����D��.�A�&��,n���L�H&d�SL�����>�
AbM0���aMn*FjG[���r�M#Y�$me����A�U�E+�	�x����mA!��+M��m��Fl���W�S����&q�o�
����#D��E[��`�h^GG��?&%������x\��G�3s0�:�lk'��g�E����H��Q�t�u�q������7�U�n��"��q�(B�=�O��<g����F���u�0�xml"WD��������S�A���q��;��k*� oU�&/ ��J!�w�wk�7�JO'�>D���#��G&'~����K��QO������7	����?5��w.���o���A���d���W�|@Qi���h�>P�����Du�	-��:��Z��(�w\E�+����~Tl���F�b�2?
$�����1���ef3��/N{/���������������k�jq��y�29��i���o6����-���k�$������	
�]\n��U�	��H>	��#��0� �^�J��B��DuUgr753��1y���:������k"~`8LT��1.�.�,7��`��R��� "+r��Q�R��c�k=�y_�s3_�/���f�0%�?���[�@�pBA�q�S������T�r���+�I�JX��(��:-���O��EJ�Iq����C��hrw��G��m�$[��wg�(��C�}�sg��E��!���H�O!�w�������~�{u�gX��G�O�n��K13��M���=�iO�RE��&B����fS��no0����Ao�n�N��
�HT�(�{�t:��x���������"�5u��=9*$s�u��o���K��5�`�U]����`s��"���AwS�[=pj�����F��;w�<�a��x��,o'��C����F=������@���n�WF�i1[W��*4,NlZ�G$*B���V�TT��VA�p�C����f�?u��*)G�M��
�0G���S���B������FL���������N�8^��w�:�0d���RNA�q���������S��h���?,����G1;pr�vJY?@�i��I����W[&W��\B�~����a����N��U�{i����K9�[����G��VK��F/R !�M����n��b������>��$3#����_O���u���9
��"dbO�=5�*o�����r�"�I\\����xo�h,��u��t+/��g�-����Ox������^sT� eM&�z?�����#�.��������V�A�R��.'$T8��:/_�:��8;��g���A�p��<LP�5Or���Sx�q7��d��Q���U(��A��J"8�i�"���q�vL�Jc49�3���'���
�.-�B����L5Pk�9qh�&���o8%K�B�0%K�����;
�?.9��jG�K#�����\���������#���5x������xF
�H@��C=tT�^������b�k"�4n?v�Y�{��(�������
�'F�lB:�#�N$Y�Y�x�$�#����q��������r( 7
� ��~�7B}`P
���Rli��m
���:�GF*�6�ldS:o���E�c����%�����7��b�����DY�\��{������p�a4t�g����q3{�=sH2��
��!�]�qM}���]V^��J�1,x0O��w�(
7�(d�C���`{�h(*�����;�y~�4a�`�~�
<��!�8u����}c�z�%ua���QL��q��1�x��)�qo��]�Y4��0+�������}����1�h�4�k������2f�;����y���������B�fD�U��"\]I�S�Y�7����?��\K>H��)�4��QC#���t�s�l��`MF'�	�+�b>���#rpN����3d�w$��U�'YFqO�"��K�B&f�^[�����E�
�E������-��CD�~�'����x�>�UD���u�C����3���*YDZ�����	�vK� ��[�~��PC|NwH)J����r�D��|����"�0������8c��>t��
s�l�����L���"����������&�9����Iol���.e�A�eKik��@��v^H;Y��J��>7�������q�'���ybLr(��
��X�Q{Nb4q�	
����q���B��:�eX+�qQ�[�m��K�<��g�1�t�-�n]��(�A���|�_����o�6�Y�U�VR5p
���mB��nY����"s2 )Li�pl�i�!�\��c$8G*����`If�k��Mr�Vs\��?�V��W��
�?�w�E��A�o��R����v��Q�#W�������n�r����wc�����nLMU���wc�R�9N����V�Bc��P��B��I7�%�!0x+.��Z����F������;����������qw.���5�uf4-4o�1���P��K��4y>����!B8��-8'N!5����5�
f���m�'Y�����(���x�nT.D�����`�Ax�29�,%�p�u|!��������_:{Kt\����S[R��8��K�JHS��������i�2:qF�&�Ux��A0�*E��l�TQ9�FJEL�����F�v(?J����r��2���9JiFu�����{�MYE=�*)9=4��Z���h�N���(��>
l�R=aZ��1���9���&���ax� �dZ�[!��G���1���F��^"��
6�&��l�=�J�}_3:7G�m�]��q�c'_1v�c"�hT���R�A���F�l=Yf�q 	\�b&����/yW��@n"��98��	�a!�����4�`���j��s�-C��@
�������1/6�u����%n��o��s$<Z�Z��'�?\o�e���Jjc�z�
�]D�1��r�����3GiZ�^�����`���%I�KI�n�hKp�xk���mk��F�V �]�J�(�Q����P��<��#����Ct�!��{t>���
;�$�}�����"��/YIB��91�M���������<�*�� OW�
�|��_aF��n���gG\�S~�=v���Fn��s�]Wl�����m�%�����H��R"�-�Vto�kI��~�fh
�0yQ��,r��Y;>+����zEwj#��6�;��G��� K�9��������v9,7mw���sU
q��`�.�05��1��<'nO{x�^\��9>{�+��S���s7�4(<k4�N�%�Mr��@��O\
�����F��*4��o�����}��\�+| ���-�
�1�r���.�<
�~k�� �x��Uqc��(p3�����s�y��Y�+�Ga8��GNX5(/�,���� ����I��������Eu�L����j������zB���9%c�k8z�2���>H��d�Q���<�{��+)'$X��	��$)]�qP
y�`��ec����o5�Sw>w�����JX,U���Z�����"w���L�VG#<����I��COi����+��G5����RSJf�V=�5^l������2���Y��L���!<���
-X�nz`�)�n��:n�;Ra�:�E�<Z|�������EE�������('=o6�����;���yU��[)�>]N����b���uW��v=���m��	E���UQxV������]I4���8��J�e�xl��+�B	P�Q�(�a�-��t���Y-�0##_&�O���P�����~O�����{���~�s���N��t��R.����nk��v{��m����{1�j�w���������2x|��&x�6X�j*~_N$.�'D��l��y�b;Z�"PV�@oiZ�J�f�����\���^P���vI~�����/YG%� sQ���u��,<Zq�����k,�;���(���+m�!�A
��^)�!+?G�'�j��V���M�?��n��#�X�K���1�S�
�3(C���+Gwa�Tf�n�X����B`�D�@������u���.)����r�x��v���t
LV�
���S�1����
g<�X�=��"gY\�
Z�������t\���P�2�I�a�T��R�%s������J��3�u�
E9����M@iD>B4���dD$���T.�tY�
G���������R����l(7�}�Vab�:>h�c��du=VA
�nKv����}B [�Q�{n�����\���������_F'2���������|��Ma.������u���}� �N�H�����	r)�
�/Q]�c����0je���T��n�`��C�����OxDI^�����������"����6.;�X�6bTA���������
��Jy��M�l_va�S�������`3��������=��#��1>;*����]��L5�1��H��hG��iT��a�t�s�����60���M��%0��|���l�*\��l��T5cvD�/��������������������QwZ|�����x�� R�S���	N�gD&&	.�Y*���v�Uo�D�N�*4���xGQ>�q���?�`����v>������,TVq��_0V��R�R��(��,�v�=zS	�wF�*1���J��U�l]=��q�'-��f(���g�E5�h��hj.
%�?�������n�vL�K��	l����*{A���l�������������C�1��i\��u��"vR���7�Fp��gn�������2��h���#���Sq���`[�a�m�Q��7����S��qcj��zD�B-���Hc����c+�n��s���%�/T�*n*�8��+x��_m������J�^#v;����m9|K(��������o����]�c�]�����+�&�I��������W(fRC���x�����6?������b��(������y���w��vU��j�T�p1F���@��"�S�TE���/�%r��My��\���������;o�����m��%+Q�q��R�N�#���������T�u�����-C����Grh�ya�^tj%�w���M�[c�j�'L.�]H������6���igP�m%��~��3k��j�g��A�6I���f/����+}���k������B�����H�%v�BC�=�sU�|��1���s��a������]�&D�i���u�jiZ�=� K[|�y
�:iZ���>�v#�:Q�!��8�w*�s�q��]��	����iP�v�m����p0����K9���j�/K�C�&�x��E��i��s��$N��J��<�
&�����a$���Dd�r��.��d��i��i�2R ��P�JO��9�i����*'?�3�1�V�w1o|.�6�f����ex`��q������������t�Ep1�����8�
LHr�&G+�,$F �0�g�0_[�+�W������U@�SG�H�$�����2�����8��%��&���������A��
_X��'�P�k+��X����=u��S�I�[���+�����=����LG������]f#i~�,�|����I>%Y�;������M6H�������f�H�o�*)�1���CY������a&�$dQ�����Z{�@SZ/���*e��Ri9Vg��y�IUQ�e�V3�{-&|�����;�-����(�l�������d!�k����t�l����+���i&o��
J�`�\��I����k=���p@���s�X�{������(����fjW
-H�?��K���v@3k��w�l"l^�ib�'�Z1���W1���`��7�av?�7�n�#L-8,v�f���q-|[PB�3��=�����V�BU�F�B�J��\�oM������0�0���C	����L
!:O��A=�
D�F�j5����R]�p����)*�v2�)����sY�i����s��P���c����$�>��2#k����^���U�����6{����3�[_M�iD��wBT����Vk������&��
"-�,
��I��-~�����
	�'Z4���Vk0��g{�o���~��G���tZ�^�����p�N�� ����q����APE�y��~���{CpO��������[��h����;u;��l������8���s�����i�����L�!6��y)4r�t��?(�5�����j����M���8�m����u��w��[Ak����>���u�q��m^������������vZ������NG��n����u�;�N����0��"���)p�+���q�@>C�dHd�|~4F�M�J�)P8M��C�G������E*�q,��C^a ��������H�SLSy_�z�����6 �,19z��4[�<UY}�������z)!h9Kt
�6����M
���@�V�k�=��QT������d��v�k%����]������j����@uM��"<	6�?�NN�&O6xd|@c�P`�a����C��)��#��q��0����w��\��*$Y��G9��|^�����N�U�rlq]���{���\%����b�I9e[�G�)
-�u"����}d�~���*@��("��Z47�4+�]5)��#�_���\�Hgu�������(;��Au����z�!s|t��a�������w^���n��R��}0���N� ~Pt1j�E:,K��_����L�e;~�O`���~}�n4���.h!��y������fn��|�h�V>:N�Gm�|�Vu=��/�+���<�nn��>
�lp�n�� {p$��chL�
��.�5}���*=�8�J*����D�N�� Q���B6E9mT���Y���:��\��1uz�}L\�\������������������>Y��,z�g�Ob?��}o�7���|�oeD�?��'	&?�R���V��A�(������%�����G*�lj"��A���]Z��(�9����Y��c�Q�%��x�������b�x������H�P�k]�3p�x��f@s�]�K��B$U���0�/!R�W������4`'�k��}�`'[f�����S�	�8��a�\��J4b��FL-j��N4yQ����,d//��aK�JsJh�� C>W�W�b���h?z���V����� �*H�M��Ww%T-0�*�U��Z�\k{�=88����x��\S�q#�����A�[�*��f=����)�����.�{���)����t� �G�K�t�
���^�[�%4e�#��P�S�����	(����FD�4jh2�T��Ok7�M/��Pm���f��������������~��o���P
 `
#8Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Ashutosh Bapat (#7)
1 attachment(s)
Re: TupleTableSlot abstraction

On Fri, Jul 13, 2018 at 3:45 PM, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

Next steps
1. Address TODO in the code. I have listed some of those above.

There are still a handful of TODOs in the patches. I will work on those next.

The number of TODOs has reduced, but there are still some that I am working on.

The attached patch set has all the TODOs fixed.

2. Right now we are using TupleTableSlotType, an enum, to create slots
of required type. But extensions which want to add their own slot
types won't be able to add a type in that enum. So, they will need to
write their own MakeTupleTableSlot. That function uses the
TupleTableSlotType to set TupleTableSlotOps and calculate the minimum
size of slot. We could change the function to accept TupleTableSlotOps
and the minimum size and it just works for all the extensions. Or it
could just accept TupleTableSlotOps and there's a callback to
calculate minimum memory required for the slot (say based on the tuple
descriptor available).

This is still TODO.

Done.

3. compile with LLVM and fix any compilation and regression errors.

When I compiled server with just 0003 applied with LLVM, the
compilation went well, but there was a server crash. That patch
changes type of tts_nvalid from int32 to AttrNumber. I tried debugging
the crash with a debug LLVM build, but couldn't complete the work.
Attached patch attrnumber_llvm_type.patch is my incomplete attempt to
fix that crash. I think, we should make it easy to change the data
types of the members in structures shared by JIT and non-JIT code, may
be automatically create both copies of the code somehow. I will get
back to this after addressing other TODOs.

This is still a TODO

Still a TODO.

6. ExecCopySlot can be a thin wrapper if we add a callback copyslot()
and invoked on the destination slot type.

This is still a TODO

Still a TODO.

7. slot_attisnull() deforms a heap/minimal tuple if that status for
given attribute is not available tts_isnull. Should we instead add a
callback attisnull() which can use something like heap_isnull()?

This is still a TODO.

Done. I also noticed that slot_getattr() optimizes the cases when the
requested attributes is NULL or is missing from a tuple. Given that a
custom TupleTableSlot type can have its own optimizations for the
same, added a new call back getattr() to obtain value of a given
attribute from slot. The callback is called from slot_getattr().

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v4.tar.zipapplication/zip; name=pg_abstract_tts_patches_v4.tar.zipDownload
#9Andres Freund
andres@anarazel.de
In reply to: Ashutosh Bapat (#8)
Re: TupleTableSlot abstraction

Hi,

Working on rebasing the pluggable storage patch on the current version
of this.

On 2018-07-26 17:09:08 +0530, Ashutosh Bapat wrote:

Done. I also noticed that slot_getattr() optimizes the cases when the
requested attributes is NULL or is missing from a tuple. Given that a
custom TupleTableSlot type can have its own optimizations for the
same, added a new call back getattr() to obtain value of a given
attribute from slot. The callback is called from slot_getattr().

I'm quite against this. This is just proliferation of callbacks without
much use. Why do you think this is helpful? I think it's much better
to go back to a single callback to deform here.

Greetings,

Andres Freund

#10Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Andres Freund (#9)
Re: TupleTableSlot abstraction

On Sun, Aug 5, 2018 at 3:49 PM, Andres Freund <andres@anarazel.de> wrote:

Hi,

Working on rebasing the pluggable storage patch on the current version
of this.

Thanks. Please let me know if you see any issues.

On 2018-07-26 17:09:08 +0530, Ashutosh Bapat wrote:

Done. I also noticed that slot_getattr() optimizes the cases when the
requested attributes is NULL or is missing from a tuple. Given that a
custom TupleTableSlot type can have its own optimizations for the
same, added a new call back getattr() to obtain value of a given
attribute from slot. The callback is called from slot_getattr().

I'm quite against this. This is just proliferation of callbacks without
much use. Why do you think this is helpful? I think it's much better
to go back to a single callback to deform here.

I think, I explained why getattr() needs to be a separate callback.
There's a reason why slot_getattr() more code than just calling
slot_getsomeattrs() and return the required one - the cases when the
requested attribute is NULL or is missing from a tuple. Depending
upon the tuple layout access to a simple attribute can be optimized
without spending cycles to extract attributes prior to that one.
Columnar store (I haven't seen Haribabu's patch), for example, stores
columns from multiple rows together and thus doesn't have a compact
version of tuple. In such cases extracting an individual attribute
directly is far cheaper than extracting all the previous attributes.
Why should we force the storage API to extract all the attributes in
such a case?

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

#11Andres Freund
andres@anarazel.de
In reply to: Ashutosh Bapat (#10)
Re: TupleTableSlot abstraction

Hi,

On 2018-08-06 10:08:24 +0530, Ashutosh Bapat wrote:

I think, I explained why getattr() needs to be a separate callback.
There's a reason why slot_getattr() more code than just calling
slot_getsomeattrs() and return the required one - the cases when the
requested attribute is NULL or is missing from a tuple. Depending
upon the tuple layout access to a simple attribute can be optimized
without spending cycles to extract attributes prior to that one.
Columnar store (I haven't seen Haribabu's patch), for example, stores
columns from multiple rows together and thus doesn't have a compact
version of tuple. In such cases extracting an individual attribute
directly is far cheaper than extracting all the previous attributes.

OTOH, it means we continually access the null bitmap instead of just
tts_isnull[i].

Your logic about not deforming columns in this case would hold for *any*
deforming of previous columns as well. That's an optimization that we
probably want to implement at some point (e.g. by building a bitmap of
needed columns in the planner), but I don't think we should do it
together with this already large patchset.

Why should we force the storage API to extract all the attributes in
such a case?

Because there's no need yet, and it complicates the API without
corresponding benefit.

Greetings,

Andres Freund

#12Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Andres Freund (#11)
Re: TupleTableSlot abstraction

On Mon, Aug 6, 2018 at 10:15 AM, Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2018-08-06 10:08:24 +0530, Ashutosh Bapat wrote:

I think, I explained why getattr() needs to be a separate callback.
There's a reason why slot_getattr() more code than just calling
slot_getsomeattrs() and return the required one - the cases when the
requested attribute is NULL or is missing from a tuple. Depending
upon the tuple layout access to a simple attribute can be optimized
without spending cycles to extract attributes prior to that one.
Columnar store (I haven't seen Haribabu's patch), for example, stores
columns from multiple rows together and thus doesn't have a compact
version of tuple. In such cases extracting an individual attribute
directly is far cheaper than extracting all the previous attributes.

OTOH, it means we continually access the null bitmap instead of just
tts_isnull[i].

Nope. The slot_getattr implementation in these patches as well as in
the current master return from tts_isnull if the array has the
information.

Your logic about not deforming columns in this case would hold for *any*
deforming of previous columns as well. That's an optimization that we
probably want to implement at some point (e.g. by building a bitmap of
needed columns in the planner), but I don't think we should do it
together with this already large patchset.

Agree about optimizing using a separate bitmap indicating validity of
a particular value.

Why should we force the storage API to extract all the attributes in
such a case?

Because there's no need yet, and it complicates the API without
corresponding benefit.

The earlier version of slot_getattr() was optimized to access a given
attribute. That must have been done for some reason. Leaving that
optimization aside for this work will cause regression in the cases
where that optimization matters.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

#13Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Ashutosh Bapat (#8)
1 attachment(s)
Re: TupleTableSlot abstraction

On Thu, Jul 26, 2018 at 5:09 PM, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

3. compile with LLVM and fix any compilation and regression errors.

When I compiled server with just 0003 applied with LLVM, the
compilation went well, but there was a server crash. That patch
changes type of tts_nvalid from int32 to AttrNumber. I tried debugging
the crash with a debug LLVM build, but couldn't complete the work.
Attached patch attrnumber_llvm_type.patch is my incomplete attempt to
fix that crash. I think, we should make it easy to change the data
types of the members in structures shared by JIT and non-JIT code, may
be automatically create both copies of the code somehow. I will get
back to this after addressing other TODOs.

Still a TODO.

6. ExecCopySlot can be a thin wrapper if we add a callback copyslot()
and invoked on the destination slot type.

Done.

With this set of patches, make check-world passes clean.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v5.tar.zipapplication/zip; name=pg_abstract_tts_patches_v5.tar.zipDownload
�Z�j[�<ks�F��J����p�D">�����,�e)���J���B\�������g�"�_R�,[ �����~O6�%��$�v�L�x���}-��G��g6��U�MF�k�y���iL&�����aL��C����1�����$����=��~65�K������3|�Q��I���(�r�j�����������_�a��R�����f����i����g��#6��7_��(\3g4�����,�sS7&�3q�\8�����.��\�/�E�K�a���F�����]Ds��)��9p�6��f���D��hy�p,��O�/x"N���v�t�����>g��t295M�M�Q�rk�*���������?0]?��_��NV����]V��?s+�n�Mx��k��`���`dc�P��[�7���q�
�`��Vr��nu�^��^��x���^`����<`�`[�;���k��;B�Ed,	�r��~�!��������"~k��#�;"�y�N�w�����l;��K���0�,���.��LAcW!����G�`�'�a������;������}��%,�D����WM�����������m"��gj/����������E��v�k����M�m`�,�����k�!����!s���]�[#x���&Z�[���p8�"i����b�:���f��'�����K�6a��`j���#m��[uY�'�oD���4�%�//?n�s5��M���Mq�m�e���'6��hNu�|A��g�U�Je�6;K�D�:�9�1�;��M�wQ�Z�R$���m$/�#�m���"
�8��|�On��FDrl5d�&��p'9	#GD��E�W+�$�P�����-A�[G��mG�N�.���������;f�5V���"��V��?�����u����l8\��:i��i���c���\h�b:sg�9u�1�c��f�]������
g�dd�����A�@���r�V�%�j�����c\��.����1�a�`�D�}�F��;F�@Mrib���^�ZAe�7@���|�cR������[��D��s���$��
@5���8z����w+��������2<����"���o�
=�9�J�f���oU�z���:��{��0H4�d�7<F�������	{�����5Xo��-��E`�&���v
��E/
m(��1����g0Oa4�cDC"y�9�����B����$Wv!��X���b��"q�����c�:n�
h@����=��+b����M��p��!������pG�H�-�#�e=�����6���;�>P:r�Hp�!x{"�@��@e�!QX�n.m��K��}����p?�VfM��j�*71]����Y�)��V+�&<e%��k.}0c}u�[|�����H�Q����[�9�/@p��"�)�u�r�Z�]�.3y����B�v�'��k�Q]d��(��	��y�XJ��}��D�c<���������%�_&�>�W������(t,�)�8r��j\g�VG�j��0���������df�T[���9�V;8�����#K�tC�.������v���c]����+�B��o�����"�r9��Zc����_��a�����;Q[����<a�f����K[�-}D�$����
H��k�'0)���8������u�oK�`zdvr�`�>6��]��
�����Q��%�'��]h$w�O"�/V����,�b�6����N&sc�i���uGzK�U80��BV5�TJ�������������RE
����5�-R�IO�^�_D[��>eM����3�r�jl��
���.����m�5��(�Q,�X����4���p�-Y6�r�i38\���P��i�B4� �:�V�[�H0e��5e(���Q>�\��&����G��{AE�a���J��#8�'B�S��1{�ABY`P��8�rP��Mh
����'�u9�����OE��D�\S��������
lJ|Y��r�(�����]9"~��D�fQ@Fv�[������o e ���<� ~���}�-��g1���g{���Ro�������>�\^]]._^���9�Sx�������g���N����'d4�
m(�D�K6$���0k)%%�\!<����V�g��8L�
=�\
`�M�A�3&��!v�o�����K�aC)�c��3���$�X{��;������������qAa�[0	g���*��z� {�A�$O�Ha(R,>�k���@
4�$�R��a� ����o�=+��#�J6�����}��
���X�:�n}1�/p�	q��p����yK����(��";N�	8!v,�����#�J��RJR[���2RE�So@�rs ����|��m7���VE���!h��'U�U*f�_�������I�;|@T$F�o�rXz�e!&If��mm�t[D���"�u�;�a���AD�"=4dG��;"��)DL(��G�[�]�vE�������)� �XX������hp�r �g&c�3�
��0�q�����at�K�Sv�[�-�V3��\�%Ti�OG8��#�q�R���r%�8\�}J���Q`Ht�8��O}��������?w>=��o�Z.@1�FF���d�6�"T�"{��a����7E��)�D��t�t����O�A6���<z�]["���~s)\����r��k�g�x��C=Xs��c*��Zt���D	������p;7�f��0O�k� ��@����-G�s�����LR��X(�2��WL��V�r�<�/�������*hx�����6O����������K6.�J%��J����_�p������s��|��Q���$5�zjvv��cgX�Yx\�~����g�@��O�W����K�G���+h6�w���{����b�8nZr�0��;{�
�����B����D�L>�F���u��u�L�@��\���+MApo������JS#w
d�
nb�X���@@�w{����h�3J*.��M����$��	#��x����E�]�[����Z��~~�: R2�����`����qjk����`p��o���m�7$����.���K\-UsJ��<��,��r�~Y�$M�V�(�=�.������B���U����p@4�Tp�p[��.���.���@a���p��D��������,��4�����c�G��
rS5��	� ���r�^{�e�)G�9J��k��:�i��Yy���A6%i��?������B���V��iX�"\�b�%�05m1��=��d���U���w�r#y> z���ZA��^y���"�R��<���f���2�*���!�J��u�cBH|���M��B`m��QT[���C�������;Uiqy��e�
{B�
�c�DR.�k�<F]�8��0W�e�P�GwH�z_���������:����+�)6�	C�f���YmC��l^��%������d���j�GY$�P;�Ey';O�CW��z1��2���c$K`����Be�$�����:�����Ma�>@���&���B�9'�������6[Rj�P+C��Y�Zm�^�Z��������H�\w4�n��T#�}Nm��DCV}���BBb��C�����Z�{/6���7���HP]B�������Y���"��H��Xs��_
Q,9�BS/���-��)�>���Pr���Rr!���j(���-X_*]s&�4{`"�(������b�������	�&����/�y`���l����1�H^�Dj����
��VK��C9�pmM	�2�
AP�}��,9^*c���%K�(M�\�#����Z��������7�g�_]fI��0Z3�2�T'�����^��c{�L
���"��f,������K]������(~�] ����
�^,!�NBy<��?�~�:@��nz�
&��+�� �
Z�
�����t
K.FMUV�8YU���U.��/�������
�A���J����a��FP%��NrmTMY$���j��F����4h_��q�J5�oW�zy��|�������)���Ad��/%qY�(���4^���{O�������C1�gpK��isRAG{H��F��T�|d�}/3���7�Z��P�Ss���n:e�Pvz2r
wbi�bn����t��@7A�e6��)Xf���4�Q���:�R<GL�M�F����{�j��_[��gY�ng��S[�����~���>Uzt������.�+���*��%�����J��V��{�����������z��,n���������X������^�^����Z�
��Z�_�H0u0�"?�qI�,UP7�[���D��B�#��J�����*+����/������EB���C].�4��.�#�����!gGL+�!�vjhj�c/�LY��f�����~3���4��c4���7C<+��S�+�C/�!� �P0&�t�0����}4���xj���_�C�������g��kLmg�M��\X���Xg6u��u6����qy�O���@���<ON�i��?F���N����p��j�I�������@�X��e$$��������I�+�k���wfN�a$��!��K1�0��B��K���n������`Y��h5r�����G���x����b�&NaU"L��y�dq�]�FP���1yp!89t�?-7������li�� �X�-q�2W')����7��M���=�
�y6 5��9!B���lD�1��s~X�}Ki"�<�n@%E8���*Z�m�1��M�U��`2<������������%�K��w��$Wa�����@���u>\��e�7RT|#��^�����L�t����"��!��*5�E��.���H���������8��Y�q�/gq�>�D�Z�L�i��M������OL��o�h�B�O�0��D]���0�^A�go���C����a�sG����?�<�h:����tb��������%'�O;(��������m����"����2`�O��n�U�{����8 �T5�9Q�4G�E�t��[�Q��r'����+�p�{�������$�#��hF�~�x�M�D4�F(���&P<8����0��U�bI�
T�L>'��AC��_����DS}�D-��f
15���I�O�p7��J����>�]��8�����J�8o~�I�!�/�-������Q�/c"+����
���W/^�>�x�����:v\������E�zZ�!�����Qf4kCP<j���@�Zhg��1�Q�3@�*zo1}�G��	��y�l�+%\��LY�gJ��{���w*�y�Ce�=TBu�Ke��T�����B��D����)]��oBn�:�=U>7��3���>���������T(��tK.�J��^����������~�jb�t*�P�<k���I8U��6U����T0n[��t��Z����E��Vz��-��e�A�KY%�
6�iBS�W=������>gt�����rK����
�O����w�-���
��U��C�����wQ�Ixq�T�������+��-79~+Y]�>�������v�/�?�����a��`��L�������<Y�����Q�/���g�G#�'��5>���\s2Y,�1�]��\1�����/���[��d�G����{�/����hrj�k�#������Em�3'&nD��Q�/xt.)�8tl�9����K���-Z^P�e�Y�XzZ�SE/��av����`�)e�����Go
���n��G��0[�/~��8��M�����'��Fr��FRj�N}��@���L����{�.:����
�b����d���l8��OS����^J��<[����V���P����h�i���Z�"O�0������m���8������{m��H���;Gc�3Jl�����d��j��R�$��&-+��?�����wJ�KrFk���(
�B�����a��1��gjX��K�:����)3zV��	M7����-z����woN�&�?�;�<����������wG�N�8�J�TY�z�3`�XO��A5�5��*F�K��>�.~<��y?u��-'���n�����?9����1����w��
T��a� �*j�������5lw{���A�7��������=kw����L���mw���3���A��������S����;m��{�
@�yg������� �S_s$.*�%{����"��o�#N�;_lz�I�b����A�^�>��.`�d�
��>��5�8�Q����4n:�_x�gPQ��l����*�8��E���]�&��D�c[;*:��(�����1����GB�.n+dkZQ�'Q������(��*jB��F�ot�B�,������|�|o������.�*8�,e%;X���G����2�~�a���O��#T�����v7����^��E!�v`o�tA��xB��A��7T&���n�\>�c)���a*�:��$q��� �&PR^S�8QU ��k�ob�wK5����xA��|���i^3Q��G�Y�h��V(Z��V� ���cU������V�'Zi����X�uk��a%�\�.u�������VF����E\�!x�+�����&�^]p�ag�e����/���z	�!t�?�X��;�p'��i	7Q��'i�t���'�G��ib��yI&�^�)��������8Vl'^88+���.?��(2�gX�9t���Emi�R������:�����B.Q_�]�:O�(�$$��1��O��9h���[����h���BVz������%?|l��`�-���Y^��'��h����Z?�'�`��^��E?����s:�h�h��Q����UY�1�P��GE�9��
��`����G>��q1`���K���{{������2�a���'	��rZ�Q��[��^�>�X�k��=k����W���h��!(z`R����/S���� �������-����EL0�@���LU��U�$c��#���h�(��BB�%�a�3�t�]��U����l����n��Z�[P�{����E{�<�� |�.������)��Fif/�>!�i��:�4�{n9��Y{�l��~:X_vI#Q�y�:�q C�bF"{�4�����]}�������AJ�w>��_v�*��rT<�y�_�d�?�:�"��?�6���O��g�8�o����w�����0�- �%��'�S���iub��B�n�v���������G��x:���p�i�[31c����<��Z�����*�#X8����J�������0����#����t$sV*��R� ��������c
�$e�q�����<���������4,�J���R��IV�D|��vb'�M���f��	u\����umPB_�+�o�E]���!,�@�Q�F�V��RI\(�U����h��,�!��g�{E�=CTwI���ma���� ��*Hx�+�M���HS�o���5;�`�`��:7�9z�o!q��U^=p�1�Rp�������F��pg�$ms*�}���,%f	e���s��pW��2��".N��t�:��Q��{���������|�I������Z��[Z,�)����e�����C[�[����@�pb�Q���$/3�\fz*�D�eT����.dzD���[��'��������t,�K����F���F:�9N�T�5�Qo4�������������F��8�"�I���6%�0��??	V�O�?��Vp�Gyz�s7��^���0��`��s�#xQ�96�1�J1�'��8lS�V�b�Y�_q]�Y�����-S�%��Ku��"5u�49QJU�U�����J�p}�c����x<�(�i�O�����-BE/3t����&���������Ltfr�WSX@��~�����3��%8oSOA�@F6AL�x��1<�@�D�������WAiw��|S��=h!��1�Q����v���X�z��_�+�B�d�O���\��.!���N����R��h���
�{���]����]|�f�j�h[g�a�5N���D]�W�4����zv�4�=��7_�������T����M}�
�t4�S�bPu1&�z��r�)ZK����Ok���;=��lr��Ok�`\���v���l�d|�0�UC�a�:F���Yn�O���;�qp�i���V�Xs������ $j�?dQ
�0����%EI��mD3G�&N����2�l2������{�/P7�M��OgFY����8�����g��k����Zk�0@:~�6��T����X�M�\xE��x��3�o��\���s���a]���F���VM���8\^LN.&�}@��j�T�h��K�b�M�{�0��>���C��]prF�;��������NQ\�]m�lm6��Q����PH$��H��J
D�T�p��~A�I[�`
C�!q&��� �b
w�@8v�)�}9��p��j�� ��X[E�71c�Z]R��7���x�`�/=h��P����UV���H.}J}o��A/~T4�MLB���������Kw}�a�,N��g!e����_��Xq+�7k�x�-]�p�F��)|�����07��z!�.;��Z�Y�o������D3��-H�P+	�����QQ[���c$���,�H2�U�<��AV(Z�"�CB�I)elMHp�oV��~2~r����9�f74�{C��C���;�����9� ����?��V��������?h��t���������z��p<�
���8bx��m�F�~�7����/#�����;~���r��u@��c�2�NGq'����A����R�������l1r?�-�v-�}��N�Up��8'�����E���"�=n�Y�+\U%�
��L@���T�\�]����:[���?�!E�K��:��8�_~<?=9��tvZy}v�����K�RT�Fb_��D��&�i?�!CD<4��B�%l}��������i��^�5!6x���l+�ux�G�s����_��.��	�KV��)��T����y�g�B"oV��:�a'U@s��qM)�,�����/����w&�lp�a��,�9�M��Ra�Q�n����h�����j�[w�}g�>�Y�S��UU�r�
����f�E�j�^�������`��/���)��5��M����'�[�w�������j�Fx��t���h4��)�%�*����J	N��R���c'��9�����|��?�
�A�OQv�R
({2�i���x!�G`H���m��8����u�D�$�u;�Mp`��DC~��i��1�{Ts����#�����3v�? ���J$S#_��XK�_����]���09B�|����-����V�4�r�Y��q���8e����]H?)�n�2����-��
�Be��6�W��b$��gY�V�J����?�Gu�,P�Sz�.v3���
����W;��X7��:��.%��7����XQ�s<��Nl���~�D+w-6�����9�����i�}ZON��Q��B^����lQ�a}`�Ikx��!�A����j�2.V���j(�����N�7Q8w��W�Z��L
�,t���(L�����Z�x!����H������Q����N���s�����2��7D�P��~c���
e����C���
��~`��w��N������C�_�����Yk8�gBo�g�Yw�����`���f�y{�vz?���	���i=�d��|��t$s:�9�8sV���|�)������f� PE������qG�M�fP�+��'NT�1�b�H�W@���v��a��G�	9�)�b1u��k_F�KG���"��J���-���
��=��O����Dx:�^ ����{KQy�&\�S�8�|���&�����nb.���X����=����f�����{�|3
���d7��%k�`�q������k;��t���|����t���<�$\��@�'������s7��;\�n����������Oza��w��p�<�|-������U��4|?��N���d����$U�n�^�NMBC��i�e����%��6�D��<��T��b�u@]��#�-��	���i�$��L�����bKj�%�	|/4��9���k�H���4	8�����m�
"	�����]��H6�*����s���Z_E�����u�h�\_u�V,$���P����m�'����E����c����D^�Q�5�,��f�2\2M����w)���������=��y;�"��5�n"��d���[����z��1������/U��4�.S	�����V\��������,?����^{0���>d��vB���=��w{BCo�~Z���a�����,��VO�?(�4|��9��;sV*$#<��.e1=
����f�Q/i��w��zg'i���;c
��1�f'a���\D����8�nApD	�� ��4�z�a��P��U`�u�<����=I��C��^��?=j��^'��L3����l���	#��i�(��b��X�9��&�8�����c$��Z�<��*y��3-W����?�����F��;�V��[J*|�e�������)z�~y��i�	��RC��6.�����EjE���^L��P��DT�(%7���;W�7�9���������5��BoB�}���L��}e��1�-�u�A�Tr1�hs�-mi-��
����7hZ����@�_����Q����G>�4�n���;e}��v$����y?{���k*�.�T���U��a�zC��KG�j�������KqF����SH�fJ�����=J9<�HneL��g��y{~|�����S] f����'>~��FV�D����9����2��HJ{����^�y������P_���Z�|
�������ki�X�>870�����C�����l��]9����F�1@��S=:��S���X�E�1e|@X+��������.
��2��1��z#NF���4Yc��$����S�+$�>���4��,�b�Ts�J�|Z��V#����O��&!,���X���=��U��I��.���"�I����r
���;��g	V����C�D��L_#�[
}���[�w���Z��V���\������
�����0�+�d�C�&*�{9cO���I�b����$
o���T���d�A	q�%6����x._h^�^H��At���?� �lr�mt�;(*����]v6G�������y��kcL���3������+�>BV���qV-���7��50�>�Y&���<8�Ro����0����P�
�L�_�b��|\ ��3�r�?�����d�?Z��=X��~����e2Ih����������Q��������/>P\���,�N{�����]d�1�pN!cl��v�����3��[��x�N�u}J������d��1gF��dl��d��JXq8,	?���wb4@z�og����damaBp'_ff��;goK�������N�`�(�`,�z>Q�Np)��*�Rb#F��P\�U���Q��,�����=���@�0�A[{�����cu�(#�.���� x8l^")��f��j�p7��g�s=����)%��������K��8���+��[����0������2�%��z�k�|�?b���/q�el�����\��G2T�L|��k(��N��G������5�������1R�eq�7O���L�	&���f)�4����'��S����eOOE��gp�O�C0o��`�\~�3���o4����g�	����&��*���������9b3����� D W�(�X�Hi�d8m�,V�*ca�-�YG�\����K�b�� 'V
HH��x����M�=��G~��,j� &�
1�4�b�)�7��O4<5\�n��u�WWw�}�+C��-%�:�WW�p����,Dj�O������\2�"EjU�|�p�?�hRHP�<9V���H�
P(pF����7h���f���g���|7c&a��wU��Q}�8*TG�������;
��x�/v���p&�������7���T)����v�X@8L�n���@|�xC���4�������
��r-��f��ddZ�%�du����� x!�&����nF)�s��=}�0M�
���K����M���7��(���F� �h��8�(�R�77��@�gJ�����3U<[x����sz�V��������~���������I�F{��~�>z�����?��
`�`�(�Tb12x.x�������as�%"����%�(k��M�����;
��\D(��L>�+��U�,/�����;M%��
���]/n����Kf���Pbn@p25�Pv#�FN0xH>��-M�C�h�SC�k(v����^Dh������Q���@��?�M���KP�T@���[L)����
6��CI�CnN�^�����c�5=�����<"5��0;������4�EW~jkX��{�r�����Z��
��~0��a{�������{	��'b]�=#|9J�s3F'�1@��rM/}�I�%�0��x���
@t��{�� O4^�xlGk�p��@bW?l�C
@T7M�0�fM�z���-�)Z.	q�=
oG<2=�����������,�$25�������5��^�e��MQqi-I��������d����������
�����6���p������B���v��W^�B��A���S��>�Hf'���G�(�����[��Rb���0)U��p�b���
�d	��T�'�3 ����Y1"��H��g��S"��^@,���n����n
���#��G�JF2.b�2��J��d%V2����Q�1�8�a���H��h�%����6-�R�� �������i�T	'��T��}�p����v�&��T�������\Z�_:����IHV�/�>�Z
H*t�TH8�d�B�L�F�f�$��d_���j*�:r��H�w&Q7�D����D�\B�6����Z�-j9�Q�D�"�F;!����M����J�I#QnUI�n��|.�:}*S�0ccF�J5�~r���e���P��*����S���F.H�k�u:0[���{upe���y����f	e���������Z���+�7
������_�����:(z���e�{�����-N�;�v���z�5G�a"��_���)����>o��D�R�����_�>?�pyv��u����0�*t'�!�����e����8���gr����a
������g�Io���6�V�_��Uet�����7���.\p7f���t����F]�o8K���L����_%z$���X�[��K\r(���7�Y��z$�����;�h�w�����.��U��{$V��"�7T�!�G,c������B����%Sja���t��
�}�vg$=�9�j��A��,��8p8�^!i�X[�
$H�C�i{H3C������GY��
;����M�����|{t1���_.N^�3�S��r�������)��K�"�4D�"��{��V}����7��/SL;���cn��9?�d�qA��?50�#d��I:?�����
�f���~������o��=�h�h�!�1��7������B�],@�E
q�����?[�~���������� �����[������y�=�x�p>����t������������
��zWw�c���ku���Y}�0����;�8w20�z���E��!�S+�!�]���;O�M������0+��0��T	"���q��e�9Y�'`:�l��qoMH9P��e
��'no�����y�*������7��'��i��'P�k������7�bA`�:+�[Y3�����!@����4��l��9�~�V
�D1���M��D�I@7t��
�������
����F����?r�����!8~(X��s��N %OI��!y�<<8�� �
��G��T��<��bx$xF��F0��tb�C�}
�to����p��s�`#������kVX:����v�L�.i!��0B7��ex�!,e���z��ux�sYO�@4�6�Y1���v�������T��R����K��&b��z�B�EK����
O�f�p7^���q����
�������p\�NP��GJ�����
�r\�t@��=�7:�7bX����u�
}zC� K��}T�	���wk�H����	��"�
M���G���o����@����fEGUE"�r���E=K����N�Rm����\nO�/i}�����}�����0L �03�M	������;��'�u��i�����G�C�(��K����(UL�QN��r��nm�>�y$O����6���i6�^w<�SR�>�s`e�w|v�v3��i�B��E�Um��Y�x��p�=L����:�������:a�����W���U��F�h@�D���BdI��.����^���S 7<X�e@�9�����2>��px'��M�`f����aI�&��([�D@x��p���B����@?~@���[���w����� ���R��6�a}OHo��6��u_�O������_��o�����?�i�u��y���[���w��io4���t.&gh�?�g�y����i���_
�7&=���S�q"7����V�!}�,�,�z`A��V!
�h\��;b���gF�p����1d��wl%�
Dx9XQ�j:��������J/F���L�c�(Vb��'1(y���1!{�g������LUm:�/h���R>[t[�����+)Q�d�W��R����YOj[�������J�����]YY���V���Qq���,��Mp��I+��V�$@���6	3EoCWW<_T��x��
M����	K�Ar�'dYp��k	W���\=^��t��0��O$;Q���1���I�2�Sb*���zzrp�������H�3g����9��
M����1(f�y
�c=%s7dA���:~�iS=d�^�[�J��F�l�ZhQ����F0%����K6������m��O�72����pC�����^�3���w�r�1�SnTp��z��VQ-U�o���&x����t4BGR,���&0���D�w�P/�l5��jK^��5&����
,���k�R��&(�A0�cWR����
����y����&u�r�9�n
$%�7Nc�l�P���N���=��a�����J�.��_V4w�("]L���@������:~��Ud���-�m�J�m}���c��� u�E��g��@'}K�����@�O�1i�z�����w����S�|������������+H��@g�v�T���3Q��;�RI��3��A)*P�M6$�����?7�Q����?�-�����="E	E�J�D�$�����7���}8~�)\�[P�`�����R��R���_�	@�dT�%f��]�{�r����+XX�������@�|�=�@�yA4s7\-�h1]p�P��I2��$����R�J�V�0����Y�6kA����n���f��-�QQ��M:),�28�b�$�GY����~��r(e��tD/�*jl�JMSu��j���@��|�n�h���"`�:��m��hTG!Zk'��
�j�`3��E���n�W��=�<d�T�J�Z[�\`P���W����r�*#A5F�~"3�|����R(G����`�Sn�%i����"�B����D��
81�9�
��M�Z�I��B��/������.�e%Q`S��|���$!D���
�6H�KI�h�(��i�-�F&]��|���S[A�6�hX.DXOH^���G\�(�,��@����9���w���p��������)##�N��9w�F�^����8�-��S��#�	;)�FWI����hO(�g�Q#��&��?0C1�`��v�2��b�\��9�`���P�a�$�(�l
�VP�c�� ��b*������o�HK.��q}&��e�p9O�JA}L��.���b1.�.�b�5�&����	���>�T���������R����TJ(��6��	��$(�x�
A�	�����w�����t|��}N/*{l�(��B)P*������y��h\5�k_X$X[7-�K9K�w��U����V��J�!�����{d�q����F\��������aD�X��?��:�����A�2LDnu6ih�H�]��A^e>Kg��*�S�g�� �p����> ���fR��o*`����Ha�h�����O�0U�kEmE�`E�FE�ke���`EF�_k"�-��~�^|�f"=I�[��[�WtZ�#�����D�u0����qmT885��Q%��aL!��Z�D�l��	�*2�P�Z�(�[��Hh�y+�w<����bZ���U����'wk���nC�/�����	��9�Rs!��W$��V+�.k�*�<������J!�7!�d�+��+W7�s��N�����<�A*��������`�����l������*)����(n)��N��!w���m?B��4��
�4�4bQ}����t��������S��e���mP-B�L%�JL:|�dR���=9�{���iax-�M"����T�R���JJw*P1�5
�JE��>��M��a�Y�����O�PD���3��0��0OE�*���zp�rbI?�^�'���f\n����[�en�hWC9<��E�3T�n���	�������%��c�����3�
4S�3^���DuA6�A�%��V*5%)r�p>@�����v�
���H�p��KM�b$AG���n�@��n����@�m���a�QK����u=t���(q���O���#��������@����b�^���
-7$3l��������t\K,o�K��%"n��vb��Q\��3a�:nfcM���C^��y	�'~�Z���a|p��^$=��(W1
#�u]��#^R1�0L��_�
d��$���B�����������P"K���J�3
A		 �&�y�5����
�Z/��A]�y�h��!�b��D�,�7��#�[@*(bN��kw,AL>��l��Y���m��T�QR�m Del@!0�$��[@w��Z���;��FE8']���t�����$�C]��l�5��
f,��,9���'�?b�p&Uhz�	Q��(�Y��M��i��7Vx�M��TuhF�@_�:It'-���>��ZnE��Z`����s�}����2�K��vn�,��q�:���E�m�}�iH+�nt�
As�ug�B[g�
��
���hz���w�d��?U��Pd]�@`�A~XIJ����v���Ab�'J=An����9$F��f5��N*	���<T�6W�@��hwE7)^�b�j�Ry��W�R:���]_�Adv���0�H������~�l�� I4@5�6w�����&\d*[�����=Q[��W �����w�'����"^�W���u������-F
�rM�b�.,����B����R������M nBn��A��7*b��m�1�g�46��#�N
*q��f=��/I"s�C>�E�������v��`�R6j�,��y�]����v�j4�2�T�T�j�X�eWBF��i�L9��#-n�%�T���]�r�I�K��J�W���z'�t��������t���%!���
��oU��x����R5���v&�
�����E�������v��V*&�E|�C)��u��n��
7�JV0K2\-���o��V7�!kx���v$W�UI��3Ny�F�ME�ZP�]�Da����w{X{By�#t%V�,Km1��u�6}�7G�NAI{�C��������Bn���Z�n ��;��g�pq{%���rq������qW���8��������_��Y;�k���
�I������'5G�R�A�"�W����������&���v�x�������Uw������9!����FH~w����$%����|5��ge�\j�
Dr�ulE<����S������cY����n�vE!,+q@�.���(��"�c�s q���Kh� ��Ew�6��p��7�C�j���kY��.J���,�V�� �<��;qV�&�uiC����F���#U�]��������j5�s�K��T�M����CR8$%{���?���������^�$����U������]`�����C�%�Z
8l��)~��V2�K	��+��"}�MA`�!�)B����ps��*fZW��I[-�
d!��	�0����7-U-4��0���[{���������+��"O��&��o�������N�wD�jwif����'}�������Z������uyaYQ����)��}�Fb�8sey��g�YEy*/����IbT|/U������e�z'w���O�;�[H��<6>����1��!|fY
��R:�I�������:�i���7� ��+v�i�0�]1>��mf.�
b]I1NcS�,"/�����8����>�w� 	��"�\��(������L�~������%7y�u�p2��{-`(�D��
��#�-#)tg;j�����|fc�>�����b|����Uj���n���_x�P>')�iY���*r�k��@�����?py����)Ev+�_���|?6�x�R��������>��b,?���T,�~�1���<-@��q��V�A��O`&��#��6���������t����#������Q�y|�P��X���P�@a�W��d%^/��~9a����4����\�����A%���W�%��Pj4��Q@i��������E�+���;���)�]~�`� �"P�� 2Fd���F
��20D�u����m:��[p�4
�Mm>�@�f�-��n�1s��x��6�#�l�w�3o��q`�|
��N{�B��D�C\�08�wC:��o�/��� C���N�����t!]������dS��o�A
F#I�v>^@��V`���f0�NU/����8!���i
���=�]q�%�8����?��F��
9�*?�s���O=f�l(��Pq���F_�=w�_���	:F�3?�o�
�b3���!M�l+6[A<}���0�SEA�u�%$��B������;���b��I�����q�+4�������0O��7C��E���r1AR�g��4R���A�J���nd��g��;�rC��
6��7�$���
�������P�$+�$x����\P����O�.���u6�;O��i�R�;�������\B�*N��6g�(�����+���S[5`'xM~���/�����jt'I-�0�6�3pl|8�F��9zA(��x�1L5d\sTA��eK�W���G0�N��Ow|?�\�����m����tk�E{���}�7y;Zbal�it+���W5kR���1:�+%	��,J`�;�����Z�m����J��n��S�]1�!��S4��p!6���y�|��`���
�����/�{~�s��u�4p`���S�c`
�����I�j5��6��EX����M��[��b4��b)�K�F*��R�9��rv~�����[�����������{������{g�jL�K1�T�X� &��L��[P�&s��������-��]B_=�H7�h��k�s8]f���7{�
4�s��C�������{�����Vk���t�do2���y}I]�L���	Y�H��7������ �Z�=kP4���\�M�(p	|����o��>F�q_���������;N��
y$����&}M���@>���d�ab������_�L�T%{�`��Y�����y"�,�qk?u#g���\2,���0.�*������s8A�������O�'��N���/��/�?A�Y�).���g����.�����i6��;����HQ��'5���!/{bu���vR�4�)IL�\=a���?)j�����j�h�*��8~#�W���%�f���/����F^4kv�P��i����.����v�J����!U�������+l�r�;� ��=s����5���\\s}�=�v+�&J7J��w�PH�dW�;�S�fK/J����R1�xg�U�h7Uv<��E�DA����9���z^zo{�Y�@�_��_�6��(����u�K3h��y��)�5�t��5����R�i�<I]jej�a���1�^~�����k%�	V����f0��s�_S�G	Y������[�����,�/�%]g&�I��k�ZX�H��V{���Vv����+�f'g:{s�\��kB���*Ksfj~l�����#[('�|-�^�����Y��;��&��"���o).$���o��3cU-�f���^���-'�|��Xok��I�������u�z����liOJ�nmQ���E��U�j&���8�� �<�R��>��7i�q�I�lJ��q"$i�w�k�����S�5���[��]��v�	*3-�|�SJi�jr�����2$:�o����[;N��p�����p���2�������9�
�wn�k�\���Q�z[\�IRn� B�y�'E5�����Ncw����4��	�����~�q��n>�����%�h��	�Ir\K
P�����E%��Fk���!`J�t��fT?��i5��f��J�Y�"��9E%yh+������G��q�@K|�z�g!9F������B~�S0r���nfTn#�]�f���-��g$��b!w�FM���5T	i-M�������I�S�2rO�_������+5���V�5�����+�����M�o����*����z1�y/��N^��2�i�RJ������m6;�`����^�i�����p����Btr���3.>\��n�` i'���<���N��(����J�p��#��cb��xbL@�E��9��u4�����Y9���i��.��1�Z#�,2MB�L�^��_����|��m����M���]`���"��o!���b#Q#���N
�j��t�:bD�`��m@��������v�~�$/������^���,I^��zO�f��/6����m+���\�Rz�X
�����b��$��0����mp'L����{����KZZ���m���P�n���n|#S�*�0)�-��+���P�\j"���l/�R�=��)4-;��Dgu��*�K"3��	�N&h��a4YX�����_������+CP-6�o�he��)
�P3�C}�7�2|p����"�	7wh�U���V����4�B5�RB��*���0!J���{A{�@�j�G��/�1�6
^3>��	.
�<�*�bQ��VF�6��y����yA�5����Z�o���qj�U���x��p�q�]R�������j�``����D>3�
����m}Lj3�Sz�7���P$x���!����]�4!����Q�MJ�������[�17|������`�.��WHs�%�&`(7S���0��[GI�����&���X���p��Z����58i�!��Ae�(N�sh��(Q3A$���<
�������d.��MV�eE�������+�,���������R�����{�`�Q��������7�C��4M�s�����=���Z���A�n#J������!v�g�rm�3wv-d�3�;B���'�i�@�[C�@�3�	���&�9��� sT��SuG%
!�;�5z����I�a���y��F&%������[%n��t����jS�;�
l�0I�;�%f�+��|=��`A�L�x��I�����p��N�	�)�.|	��f<��:����/�$����z�����y��\q���7<0����Z�
�����2etH\^���w:}�����05C�`�����"
��*I���G�b�a9���
�MA����O�B�3
`8�|S8�&l������GA���gg��Z�S�F��+V��Y�������d�s\A�)$_����E��bU�������O�m���Y�>882��=��8mK�LA����3��}�	�m���BbL�=���H�~R*`#�P��9%��_����>`�Y�K2�F�����Fe�K2�o'�K�C�����s1|��|x/������f�;��w��������m���
��Rz�j�+��;��q(y����J�st�����(���^pZ�1U7�����2�".q��d�!��
��7sD	�=V��<W���y�x��H:
rg�p��"����T�h^i��da������4���V���Lv�_*�9���{L5�����}����U�eD
K ���R$��-��l�`�������
�sCgTy
��%3`	\�������J�JZ��&_��-G�9g���L�W�^������n�|s�lP�FB� |��>�����jV$���d�a���<~������\7
���/�W���,��.�0:�&\����S�D���C�$J	W9�
�J����5p��X��_}����,fhj	�3�JT�H~@����W�zh�~U{����$�5!k�W����������-r�)�c���� p���{����K���pW��RC��	i����gS�~E�-���"�2���S�fg�&��f�.��6�&�G��Te�N�>T��W/�[�������a�#hlA1�B��|����l���$��hc��x�2X�����;�;�whd�cS�'JB#uw������)�v���E;��d���.:�3WC�u�1���g�0K��#i��V���lr���X*�U2�J!�[)���R�-���'=o�}�4����2�\��8�X�3'��y����
e�X���w������� �
��?S�*e��cMrz�Q�#!�����G9��+f�~B��Y������#��N�- '��q��)����L����7
�����Q�1��*�U��0�ghv3
�z�+�*���4�-�z"[��C3�4
@��N��gI^r�������aj�EC�
�*H���M���;��xX��A�[���J���������h3��+GG��������{<9:�Ku
W���P����9��3T@3eL�x��
�!2S& 9��4�������,�����)�1�����`��#|l���-=r���O��]_i���Ku��7��Q���o�l�l��OH�E*6c�F���r��
�IXe6�
Hl�L8���.����&J��ac���b]��P5����r�,��A|f��y_d�;�i�=zV9���C�h���\��t�����}�q�OQ&��!il;�+�P�N+������[�|[��C�������Vwx@7�b�;<�'��a�����Gk<��0�Ad���N�����gn��+kn:,gn:�9S����Vv���fcw�i6���g�.�v#���v1��z�qn��s���`�I�q�~��s��G��+?\@l��d���B;�� ����n�td�b����\U6�������u	P�JA��R�/��k�
�����_:���;e�R�5uN��5�e���L�j����;�^����������l)"����."���������'�o��<y�����r�7]��*H����8��4�[�������a�9���V�����Iv��N��:]�d�l#+�����+W��!s#�
.��\~�3�&@�
��|����������g��G(S��f��5�B5��|IR��3p�2�9SyB� �v 7=NL�i���������=>7������S��k��$�i�&s�(�f��DM�u����F����9�{���������Z^`~1����1~()��d�d������ouI�!+|�L�9���j9D���?R� �K��-�^���_���t�s�6d`��$@���Pg�4�� `/��j��g_��i�M���3�q����1Kx�p���r��_p��r��v��,����8�����~�Y*�c�I���x��
����6���7��9�hJ[7�������V��o�����(JM�@Qj��y��.�eN���,�x�	&�9L���S�!/HtT=�����.X����9O����UE�:����L�e3QhjZP��h6�������F�vg��D�&R�(Y�h8B
>��d\	'��HK�p�]��x���pAb���>�����KZ�M|\@%'���A�"��sm���!�F��G����ep�YF�Hz�N��o6��ig6��`J��������(| kRR���|�T���o&o?���<9;��sQ3B.�T����v
yg3/X��zQb`z�������Jo����"�V��dX�q�U�Q�.s��[����C�����x8*�X?�-��I��Xh���n��'�~���D�R��"�&��v��\Dlj���� 	��w}Z�,oye�4�!�q}�]E]��;��N��$�(���teHI�;,�6� @<�Eaw����F�F�lm��\��?4�Q(sG�u��7�W�ahe�/>S�11��M�a�Gq7��r��������#J�p�y}I���S���
�������q~��fA��7����`w�9���������0��c���=�1QF"�hT�(�sB��nT��J������8�����M0�����s�������2��U`*�n,!�4�f��R%�)�u|o*���t�����A�F�,��`6�8��}9����`���OB�lU|#���9��I���i�����`d���A�� �$�U��j;-�f!��DOLV�Cs�i1#l8���g'o�b�)�)"r+G��� :��fL�*��>�z��t�l�f����;�%���t]W����@������T?���e��5�`.p�]��3
KU�?"]l!9 h�l���+�
�aK��C�������U�1�R�+�W!������NW���rt�6,�������dD#�������������������������/Q�y�4k�z��[��ku���fC�}99���b8��m��GA����N�9�=w^F�����_���d�N�>������X'U�/����K����IYF|o�n�e0��PZ����zz����+��W�mj��;$$��!�YH\���Z#5����%DY��W�N�g%K�Q�8���[Dw����_��� �����Z
�d�/?���v�hC�>�Z
�(��9�i`��P���?����x��������=]/VG=�W������?wS�K$���.Ig?�uRt��A��>�A1�����UxCn;�6%�TH?��=�B}{|�W!�7���`o7������y�������p,�1/�����K����vw��b���y��6���O)MXL=T��S<Bg&:�N���������:\���7���9�+���T"FJu��f�o6����?H4�2l�3t`C8?JD�W�.e���e%��G��G���f�KR���A��ZM�<�F���h�r�~Qh��g��QD�C����~�����?��`���0����b>�O�����ID��A���tO/��;g+p�����
F0���?�?{s,���'�9��NzR��D1�K�
��1P���Dt���q^������[R9i�Wk�7����8F�TvQE��*���aj��-��}�p���6"M�����d�����_��s��/F��`_wto��=]+�zd��O�Z�~_+[���d^���u�.G�]:��>I����"7QJ�p�tR�ax��]G�!�Q]	�))~T}�i��I9-J'��Z���
o�y�������tP�FG7�'4T!T��m:"�'+��$��c>'JS���|���/%���N��D�67��JO�jM��M��!��{C��)�?eW�7��z�^��BZ�����U<$�{��?���O����4�g�������x�'��T|K�����?�'�$�4}�(i��qq%tMi��5�>�G`����!a�b���������`�&i�.�W��[!�4u�$j&-%lW��E�^@��n������?��Z( �PO���L�9���HN^����J�y��`������/��q��&���!�$n���|�7eo�J���u�Oz���������s� ������Hwb���#D����NT�d	�8���G��}�<�m����W_����o��o�|?9?�xq��o�0,j1p?M(�������*M�d�*�D���}5Q�L��7n��.O�f�����2�[gFQ0�x::��E��������-�H�\�y2�Y����@G��w��l%�Q�Y��������$^i��@�z>��e�����A+����GW�R���W�7���3f��s��0gBdy����l%sb���j$sb�gD��51�fD�z	pZ�]=�Y7a���Dq�}���Q�n���B���+q{?lZ��-m��0�,�r[K��x;	�CU�k~�Q���zT�W��ZZQ �Z������+(PN�Y�y�H!v�����������?���\-���o�.�k��K��Ss�3�����O�+>�^�s�2���'����m{���0g���z��GQ%�?Y}i�I��F�f�S�(�cJ���?JGl$���j�P���Z����W��3�{���T���>1�_���3QZMz��(���?;r[�R�F����������������{�fs<���O��*����*� A##7�����o�`�<��KALu�(�K��/_��z����~-V����}�������Mw����i����"���^��=�W�o`Qu��|�A����
��H��D,�G�0mI�-=������s��;B�]\�_N^{���'����$/����$g�5�&�����\� ��}g�$�B�Nh�,���e?�h���g�#�g��a��Q{����nZ�_����T��4��H�O�d��f3=�>{s<99����������g���K��TqYFW�G��O(S�����}����$8Q�\B�u>^H#�������#-������l��~�������������8�4Mla�c&������("�P�@�_�*�).�o����4�xUhL�0@����+����������K��+����������\���������"������-,#�W5Gr?����Uom.��;g�����3��)|���99���(���y�S�~*�/��|.����;wS�
�B����k����+������00��m�ld:s��+�ymn���6������A}U�(�g��K� �a�Ep��bn�F�a�fMT���"V����J�uh���
>���U�}�������!�G�H�g'�
�`�e9��
�N�m6�y����g�n��������C�_�li6�"P����bEG��k�W?��M�fSBI�cf�����O���2� ��_E>������L�$X���nK u%��L���o$4XL����W-���8��$&uK�R����q�W.��9SW�Er�^�@O��������S�8�5S���0����O��3����o������?��B�9�����������T?��
�����=9�3"�����8���0\F���/��n�����R�rwfKi���VNA�f��i8�d�A�k��^����:��_R90�)P
��J��D�}"����ntM^��&'�\P�"�L��o���T��	OH+�����[�q�ka�D\lj������
n$��mF:bX��5��xE��m+)�|���j�i����Mf@d��r�W�\B@��L�]-d�_�_���?L�R�W-����c����;���<|����QJ*�������h��O���<|����UQZ����N�_"�L�����g)��������!0�oL���8_�� G.�g��zG�$b�'���&����Z�u�D���V*���=���2��v//U�����)ZV��94���3]�
{~�����Q''4����R�A���}h��":+���N�)8��HD����>f�����>^���#�Jq�*��0k�S"�*:6�4��50�-`��a��A
���)��Mp��u�X-&����))��8����>����������R����i1�)%d�������B��F�^BbZk���m�h�?h-��R��[���A�J��|�^E5VL�n�%��Rl���i96����l��e�*W%���nM��������RZM�A`�t
n�T��q����W�w�
`� D���+��W�g��2
����K�6�CZ���^����MK7�'F���EQ�Z��w��S�_�����{�,�������R��$�d�����O
�p����f���v-o�)��>�D6�����2��?Sl��5��{�����������x�d�~l�q��a�cT������v>�RH���FeFr0g������Xq����||'�O@�O��>a�������U������s7�2���fq+V��K�d�������Jt�1k)(�	j��9�Z���@6�����FgG%y4$��C�X�����z�b�|e�(���7m���f��wf�����P�Zb��a��K�b�UAd��S2V�JO�������3L0$����Rg��XhK}C�}.-'�W�
A���(e^����jY�S������b
��6�h�1�V{{�]-���G�}H�%@���}B�+t��]��i�Z�O��0QN%�^��8�� ��#jcM��`�Pg{I���cy*��j���	�a�- 2$ug������8�xe��U|��j�~+��"z�f��ro�h�F��k�.Y�����m��BW3��7�}w��l(�q�aGE��OX~�	/(N��f�u�[��j�8XL�lzL@��m"?+���&V`�]DI6`5o:<icE%$QJ�9�����-�K9��������!E���G�g��Xn��c8�Lo��%i�"�L7�'m?x@Z����h�\B�M�7x2z��l���Z�?�oWVA��:��;���������n�
�n�`���,�!|��8%nn��`:(���,v#��ws������Z�����UH����q Ho�Jg���'-�K��?���{��)�����{�������V��YI	��Yy	����D�M_����������f���_"�����d�;��;���C���>��6��{#��<})�Z<~���!�Ff�q��
��?�j�;>��p���-H������LA������]��u��{s�Sg�S��"J$q�
�v�@"7�{�?1��p����Cq!utyA%g�U�c]L�e��1�A�����@�'�@2�.6Z�a��
���KY�n%��B&�!d+��t�i��v����ZA��l��Z����7F���=F����k)�
��W�owVD�q*�d���PeX}�0�������?������#���|8bx���%�b��$���u�9�&�t�O������4�>�|�z��$i/��z���Q�������Z�E�UGa�R���i��)�����������i?�$���cb��@���
[S]��%y�q�9���-��<�1����\1�;��)�4B\��+%�N�0ZJ<�"�����O�6#��0����9���	���q�P������md'�:=ygL��r�O��Lk:t�%2D@��=���j�1Th�X,PK�JF�8x��C\��]�-R��:$�~W��r����K�
9��'��U��]b�<,.����-w�����`{[z|�>��`{K"���7�7���/��~�"��~��`��k��t�K��M^��vvz�]vv�ww6�,c+�*\��
r���8z���R=��;�du�������i��1�R�2{`r���f/U����~��pO��2�{�\�`wq�6�P��@7�#p^l{�^^Z��&
sT%�-8u�����a��]��z8��VP������
fK��2���!{�&��� M���F#v�B����������Hh��Vp��0����J�PD8��+p^m�W�%#u��9�i��/u��:
�z}��5�����q~��4�Hf+�W��E�u[��Ui$@s��`�w���>a���Kk��}�;��Zr:M(������l�0M@�z�exI��?�t��}���e��U+�J�#`-0��Gq��N�
1K[^;O����Q�J�tqA���!�Vcn��5�hb�<�������SV;
��Yt����6�"���}����.;���UY
p���q����m�}Kw�IeRb#fcw>SA�
�o5�����4��G��u�=���A;����M�I����|��z���������R]�������f��G�!5D?
��[�`vF$���i� T#\%��"@AM���>;���������srzryr�����V-����'����}�:0��j���n#q�`���V�}���Q����)�����>r�+O|D]�3S�"�G��vgJ)�L"H��=&$r����h)s^[����F���;tc:����=�b+����
B�%�����rh<�
�=8,�*9I
��UN����m}t���Bwf�r#����tQ?�h5fF�+�"�I���C�$�j��8�F��. W���n����=�0���>�b@"����Q����!)��;�U\��T�v>�X���}�-�t�������[��{��
C�SPQL��E���[������vC9�_��N.�2��uB
���h���ff>�$
!xx/v�g�b*
�A�9(C*ka{��g�v�m�C`-�����{��x<���h�=�-��BL,�]������L����,G��������+
,B��Q��B�A��+Y�'_�

��!��/��S���/��[4x�����l��t	����H��C�H-:sv�jZ���
� �Il_���^�2<������������!�	�4�6���1��L�`�|�)UR�w�yJ�2I����rJ%�8�����;I'[���ww%�=<D���'������[$�����
���@T���UVk!?�����Hc;�9���:a�s�z)!�9/�c)�Ar�BGl��,1�
��t�<�JM�����j�4���*�3y�!��� �`H4�>��I��K%��A���Wk|O��j.9���UC����mY-����l����v�}�
7A|b��\ZPI~��u�A���<����X��b��j5�d��P�j��X�����n�aA�mi�[q`��S!���*���s���Lk����v�i�
�	��$�l���V���_�%.(�UJM-4�p���_(UJPP�F�Jf��	J�C��L�e�����	-3EN<@�1��)��y�p����q����4����.itO�.
._!������)d��;(&��E���1:��9��xv�k�3$v�Ft�{�������a�.�g��� ����#&N����6L��
o��7�%!
�w�U
�"5��Y0����&=����Wr��r�K]k�J�(\��7e�e�k�����-���;�J��A�'�G�����pwu-Nt��X���m�r�zX(�X��M�O�`�	W��<��dY��$���z�[����Y���^�E�-�����(����%l�`%�'��
�������Ub��+{P�������"O�-���/nQ�^6	���7�
����7�(��'���_��������C��U0��U6c'��xb�~gN^����#��RI�9/�r��J�����(C����5��LSYb���$�����t�.Z$�����p��h���������?^_���(�Y=4o�i��!��+>SX��P���X�-Zs��<���}���g��y{~���2�[���X������(��v�>f�x����
8L�w�
��I(I�5t�Kg�"L;D�|C/��t'�M��p�op���J�G�,URKa�O<����/�/M5z�z������������=��Xv����j?d'YM�����z���'<D��S��"�������q~�8�K�nq"��Z�|N;�����r[�����:���8����`��~�#7;{�`3fq2���J�|�fG�I���s�����L���
}�% ��e����X=����8��P���|[XH)hI������	�mfY$�:������:;';H��B�t�6C��^��8���7���)W����K�wZ��g�a�����~�!�M5����G�B})�T���p]	k�UQ���Z��n��{S�dh^�2��y�<'k>$L��g�Vg)G��K#s�����o#����c�K��\4_���9D��s�i(\Wx@��c)�����%�^wdJ�-���
t�Q��A���Tf2%E��$�����C/��	�c���	3�*��K�pV��{1|w��'k����6kMI���Lz��V�de��36J��(�O��Hc�1!�N)�tB/,'�,3O��*�^O�8���K=KL����D�����Z�gx '���o��2gg�V��Sri��*���Ux+��7l���;6������^K�Vz �MU��$Jj�|�O�.�E{V����}������Z���4nV|itJ=�]Om��N&`e�g�d��0�WL���<F���R�$�D�t!��4F�,�����dj�9�|�D5L�e|�JC��#@������q2�}�F>X�7UB�L	U���_m�z+��rY��%^���	�Hq���F��#�,�;�@p�.�` o�9�����qd<���MAM��l]�:E��%����5v2�{k�S�O��e��-SN����'�e/�y�Os���4�`�m�|�Vp��IU�8��z��/�S�l;���$��K�Z�\�=�7p���m���X�Q��K�kug
����A�b��<��*}\��$�k�.N��&_�M������;uKO9���%h����_�*W�	���>�8�bbZ�>�M��%�TX[hN��~��3Eu'��H�<�����!&1fF0&�@�{�����j}t������A�����BG�D��s�%��H��v���J?X�e��P����,���T����t�G1�@�=-�Ix�S*�L����]�M�~������(&�45~ZC�2���7��d��`Nz���dr_]1_����v�n�u��}�K�d����p��73�L���L	5��������$�K��K��LNJ���TxqR���^�XM�L��b��rY�����*�2FqKh�r�5*��U*��)'����G��mu"�O0X����Bt��k����C�������w�?���}+X�EJ3Wlj��rtV��k�HY���i�6^+oK���{����f���jzK
�,m}Sj�=
py��VP�d�{������y/����|Yy�\lR����n���p����l��q��a�f(�KzQy�����f�kY�F����e?��sI�Q���VS����b��~
�p����V*�`�)�f��?s����=�9�@��F{5iO{dhJ��Q=R�J���v�k�f�Q�4����3�=�1�!(^Nk���*S�#�&Ac���L�r��VA{g%���0�I��1}Y����U����b�4K1U~mT4���r����P$r�U&�ax&��S
|�G)�NI�!���i%���2��{���������-����P����Y�r�N�*�.�fN���������� ��t�75���|
�� vD��w���to��i�T�����]`v
�>��j�b���[	��c����R}�.�N=?��)����WD���;��)-FjH�h�\e!��=��0��7bC�sT.V ���!�V��y���Z��g�����`5~0����8A����|V��������`�O7%�-fKM���2,����]����o].3��}9?��gvgdz��1?e��|2O�)���_�I9)�&�#s�Q7�(�-�����r+,^�(
gxE��k����#��������
�����v�Q�h3���=�F��n��d��AY�%g���C���{9����_����������d;nM���4��J���E=��o�>s�I��KZtu4��x�R��b�L�j-Rn�T�B� FT�:CE����Yp�.��KNPY|����|�;		�	�1��!5���Kz�l1$!�oA[ R�Z�;C�Jm�l�N��������o�oi�(G4�',��c�C������u��bs�A,f����(���q��OI������F���q���Hh�\��0J��u�F�F��^dx��B����$�y��nf�����|��0��Oy�k!��e�$�fJW�g��tw�&c�����i�y�,����J��N>4��3b��GC��e�`{[��Tw�
e����;"��$�����PF�?�&
5d��I��K!�)SS�����ME_��&"�b�k����`E
zEC��cF������R{��vj��7�� �E���{D#c\>�R�{N���R{d��K!���TO��[�F��
�������0e�������������N��?p�7��{7B_�v��p7]�V�Y����_����a1��MO3���T�cNV�
U<�����j[5j�Xta2���o
7���/ft�dCS��94P���R�e�' �}7#*1��]�V�[4P)��o9����h�|��)KdJ%�l�����S�����,�������fA��E~��k�~mm����(~��NoL��%���A��`=���������m<�7�+Nc�L����M4R��-/g�,��iORV,X���L�u�m�L�m��3$�,6E�}v�a�D%|�S*������xw����R������
6�`��d.��J5�|����8v,���5��g��&o���.d,�P�����{S
I�j�1�����e����-�U��-����v%
$�S�8M7�0IV�`����>S[��;W��8Y�J!����K�vR[�4��%�]�s\��,�l���+�v�����5g����V�y{�����{�*�jK����	�T��!"Y=yI�n$I�6u���x��}(_�N�@��l��8��B����#��o����s�nu��A���
J���	��l~��0����C�z���m������cv5��
��u�a�ak�QP���`�~/��/�Bt^Q:nH������,B����.���(�@O�� �>��k ��*@uS�R|�N����Q:���FY����J��^i$�_c7�q��J��|I�8NA��ZE�����?bj��� �;����)��p���7�TN�[����v"Yf����|�]�5����u�6o'�E8�]C*��-5�/�C�����&����E�qfD����z����G�N�9���j/x�fy/|�H�c�
4N$�(_A&zp�5N�8��/�nR�()[���m�*:-�%�S��_=�V3�i�y��,�u��CG�8��t.'v}(�j�i��}��}r*��,�5�,+�=���]	���&�@�0%I��<9�o��4*���� x�o_S��>�~W�U��a�j$�f��6�0R�J��:y�T	�c�$�v�R���v6%[:d�'���F<l��E�s�6�*�
���Yo�F���k��?+%�
�#sg&qt �Y\��p�} ��]�%ps�5^���2�;&(�x���D�=�Q�sr2��^s�

s��d�/!���V��*�G��]������c�O2FOf�����xR���uL^8^��O4cb�b������z.[�.�k�6�`*����S�7Mv~16�v�
��%H�Y �Vb,'���8������� #�El.FGri�z�{:����h4��g�rw:���N}��������tT+���{%4���R��3\�B�'#;:���]o���0�i���U��
�I�_	���I@�cdM�9���
������A�D���!1�zZMc]��ct�����1:�����1�D�E#e��:5�5�{k��)k-��iM�\a����P�f?(�e�����k��&Q7�����Z\�o6�:{��[{��x�`���-]H	�"��������\�M�f2��>O�#���P(K��l�~����tF}�u���6�]��Z��!U���t��(,�Ch(
P�p�K;������D�O����{��H��z�jxjJ��[��l0B�����8���tNReG���q�,Tj�����:�8��{�t��%�Y�����"�|�Y�`d�%\�����3���%&����5f8\[>���-����l����7�7�,��V�������~o��e��^kT��@�vz�v�Z;����+�p�d8�*������K��q�����t
Q�f6��Z��4B���u�V���pi<���X��}�F�����4b������i�~��7�D�&�:�(�MwI#�t i�;�40����_|���|?�}���)�r�8V�L�N�+ ��=�#�*��Q}������!w$^��JT^�����x}o|1�p��x��V6ap���Wf�/�Rf�_j*���dd�{��ck�3c�"��F��}aR��I��@H�1[���#<+#�R,�<3<*A�sD:�u�UwQ���l�����Szy�?�6�L!����
����6Uj(�D�33�����y���O�^SO�P_�����C}���i���]�[g�C#��%t#.t13WR�����������/q+s_��?C���d;�=�:��8�����8�����D����E�7���q���k�����-���"g��:VJ�R�L�@���p�1�\�c���v!����:�����r@W�OT��h������0lq���$����`Kd������3�����<��V��S�������kG�d�e�&D%��S�t�t7�-���:(�����>�w���QH�B;�������r.U��p������d�4�1m^��������8y-�C��G�eI��o������^��Wz�t,b�4�t��)<�������I^���B������X����%�u�Ud(��������q>��,C���b��3����M��>��l+G�rI��L_(i���$vT������D�G�tA���ec����P.��Y�+/}}��?��,hx��U�""����?�)�D��'L�/N������]k��t���{�������m�
M������ie{�P�e6$�H��7+]k�u��!�X/�<����r@��]�A��s0|�����l������$T�l�y]�3wqd��%
;d����7���4����R�=d��Y�����>��@�a
t"��j
$1���h��W;w����
>��U�W��\����F6�M�i	O(N[��F�7��pN��ho6�3�&E���������@�&�\����z[Z�*jR;T����i�S(�v���">�t�������!82�G���i����3#�kz\t��.5Y��`)\AQ��@��P��mJ�����TN2�(����S��y��g(�����r���l�9f����m��,8��%�� �rJ �e[�����5��:p������<���V�m;]7q�t�tim�(�>Z��u�w�s���%:�����;��'��+���OHL�����	L��L����}�Q[���4���r��#�B�v���N��� W:d��F�OO��wE�.j�h(��>�{�mVy3��[����Z�	/�h'U��IM�Ch&T�����=L:�?��M5IU,~w���e������ilC5^Z3�c�23)��3��>�����*fV��bv$�1
?��
���[����r�"$ kz����BD,��
W
UN"nS)1e��72g���~?���Kj['[vV���M���RA�`+h��}�����M�G��"�J�W9���B�!�7�E��Q������rcO�{>1���0=U2�Cc�)�uj)��������s���R(��!h5{i��cL����S�lY�L��ah,U�Tjsz�
[^�P-j(�&�9.�tej��5���M�>6
<E{��v~�	�_�C�{��I�U�8/��V���&.;zg�62�WZwW4KM���*��^���9C)�7~%��0���7����j�A��U�����^1r)�5�T>����,���bbX]���M��T�h
���Tn!���B�w���ej�]�����������	���\�[D
����p�?�����Fr��#�6�c�K�FDT�n]��(���"�4�V�-"O}IP��fI�Ig89-!@]����9S�	�;S��
�R[1lE�ff��!��Pt~B�t�P�k;B�Y?�|cm
R��/ig���L57i�T��f�;�]���f����Z4����z�����8�����pT�2O���(;�GA��@*8��f63���|&
����WS��F�[�NS���;�Y�?���Z�&#�����: K�M0N~u�������bg(�.z�,��7���{���F>2O@�=#4��(�A)�|��{�pE��2"��Y�q�����P�5}:/�iD	x��B�J�50������p��me���-:����A��OZ�&�
����2n��[���6X��4Z�4"'`_j�7�g��B��d qB��b��{�St���w���s[�����wy��2R	X�K�by7Z���1�>C{!nz����f����Si���N�}���9�����w���L��?X���]m�m�:��5A'Sv�$�L�0$�E�&h����� jL*�O*F����=�Qa4�86��
EZ�GuM��Y�o�!H-\��7����#$��xF^Pkz��!�x�����]1���L���S��%��m0Y���*����������RS��g7+������j�R��.I��z*6����R�c2��q�+�o�s���}](�LV?y����D�|j�PVh�u��PV������82�{���9�&<�
0"q��YK*����M=���L�|wV�T*����,���m
���"t0X���������8	AKMHO;���_����38}J�S�#�)PuD/��*dt/g��	P��7J+��R^V�SB�dH�v"�H�#��i��_�(h*gj��-����a���hl	L�Q���
�E;c��(��
7M�7I�O��^h���.����9�q%�;�r����6�D8���qgT��~�_�c�=8.�p��B��G�>:��l���z|���S7���a����Z��O�`x��d`e`��7\������1������>����t��8:���3���WU���W�����>�����f�h�7��y�s�E=��po��^�,y��M��,�[��j:�v�A�]�o/f�J5�h��G�IO���o���Efb'��zI�V�5^E����^|az+B��_������i�#��	��G7����1A�����?����B�
o?��C���9 ����������M1�������{�/��G]��q����C�;��
H)~�ec2���'�^�7�������)�B:Nz(�vA@�n�
���������0�Iw*�Q����$9
^�kw,����P�G1�qz�������S4�����c���������g����W�
Xw�V��b���2���y
���D�z����$�	5k [�1��a��jl�3P�����V���
g�5 ���c��.�H��s �E���r���U�q���c�y���������K��~�B\��3��>��=��\���m���3gZX��m��3�3�o6�=�w�]��j
z���1%�S9<<,�.X? ��	
@�(����|bmVKlr���	m�5:�`�b�@��o@*���L���/�i=t�)�0���<
�;st�A������9P��~��U]�EB����Y�[U�Wf��#�bL����[�����O�����W�Q�Wb����G�fs>�
��V��h6���b��
�C<��'���f����W�'~vU������;��x�����������3�:�P^�[g�v��[}r���s��%��&������)���~`��P�|8d/0�7:�����g�vD�w'���$�,������d�.�������������g'�����%I���>;sv��}i>�-����0:5!0��������}���
��O�d�a8����S7��:����������}sJx2I(��j�p4��wv��w�p$�����|�!Jlv+@�or5�c�\�}*y&�&R�E��dM����l�}"ieny�Zq�)�+k=��};C<���#��e%���o�:�Y�.Et%o�HlLaZZJ:iJ���"i���X�|���GE�s32�5���K�s
��c_m��5��;2�+]]e�����^{*vc�{]o4�%vc�D�^�!#�He�O������k7��0�AU�f����R:���������W���B�������J |g�;f5��=�#PS�gw���d�!��yX�^�P���QL�=[���N���S������F���<���;q=X���p����{����=���39|�S�s�w<��	�K���]3u��I�5q�t3n(�rCC�i��]��
w�%�b'��.�'��j�(��"��D�K���bL��	�������tS|�4��u6)_MM��T��t,���v����dm���F��� ��g��	^QN�B�]E�>�l���+��%|��Bu	Y/�ly�79�X�����Lw�X��p����K
��W=�_�%�D�������:\D�+��0��Q�(:���DR��n�q���V�������k�	���	>X��#���������iQ����|��~��V]�O�T'����8K�����`3�2���g~O���Qo��f����l�hK��H���5~�������6�A�6rD��}D�B�[�av�4&zA���$��1�-��v�e����)��5j�,�@�����]�v�F>���J��;��~��l����7,�+��
x&Q���x���}�{tq�������	���< P	�G��m�c����<�oy{l]��I��&��@�U%��k��P�����8��X/w����\3w�����������o�"4�+VcZ	(�F^�%Y�8T!i��
[-�k6���p0-sS`7S�tAT�-���g�\�IA��gi���7FWa�J72��7�����/�<��{$��F����n�j(_+�,�R�e���^;�q-������=�[�f����A��A�R�d9���;-�>z�*�B��������R��Z���Ai�C�g�>}/��3;�_��W�t���c*��u�bn�����p�|B�7v�d9�U�)�Z�����������X��F��Blp_�=�AJW�Y��0Q��G�+�P��@4D��|�c� LF���_���M�}8�4���=�����g��A8�F �Lr�v���v:�|p�
#_!���1�e����<�c�nm����8�W�(��L��	M �����{|(���U�lfxI���;�Q����Z}zlI�Y���|	���L�9x �#�i���G�9����'��*���7��|wt��6�����BB��1���$�������y8j@����K������n���q�>6=����v=&������N����w@���FMR������5x��_�!�Dp��o��/�Q�(Zy�t;ng46�����uJn�vS��]7K4~
8���V�w��Z�Y��<�����������|�d�	�W���\&�Pj���a��G9���
����h�a����,����^W��/������I�r*�}���������5��w���)�2�����dB����f���a��g��o�|�1��9��4�X�&���ci#������]�9��N���^{�1,�V�����<�c�{�.������^'�E�7;�$�v��p6���q{4��ew;�����.�Y�:x7�����9�%%�����I�`In��q.�t�(w����{�b��w*�|��'����ao�5�>=S�"��-d�
���������~�B�w��e��<���������^�S���j�@t�r�G��S�*}�:��+���wT�j�;��pEp��"��=��r+>�xy|*[��Bf�/��.��^c��r#��v���ic��*)"Mo�{����HU���3�`9(�pH�ud��_U`{�J��y0�g�����B++����\pm������z�i����T�U'����V����%�����E�����:�X~V+yk���+���#��,�������e��W���AF�J�
`�%/QR�
~E������[���9�&SK?3������z��Q���QM�t	�^mcb\'�`Y{�7�p�.X�TD^(�����M����~Pv
r#E�����c��~Z��X����d�\)��������fMS`�r*���=4�X�=���m��r<��]��0�`���;����V�,s���	mD^}���o@�*�S��0
��nN�f^�4����|@�h�(D2�|��{�Q8��k�y�����)�X�wL�{�o���H�}6���:W��s������>Cg�-�	�'S�#��n'����:��'!��^��3�A�2��F��gwh�PV&��M���N0�vO\�> z
��@�k00B;��(�� ��*�x��7_����������v(AT
l����[��c�`8�s���@��b�1�q��x�;�X��5 K�����t�7������nn�3
�����������&A{E/f��]���
'�����'�p����^
�c��V�6�;�����$ua�$��J�L��ON)��uM���?����)j�����#��d������3j���.^�v�YF
��O��>(�f�PhL���B�����8M=�:���:=q��{G�����v��{�LM�
���vg�@N����
n���������.�y������5�A��0Yye���6�
1���s��7������3�v�����P��$)�c�:��N��l����za:��Ys�4kP$e�>P�D�v��y��W�`_�}"0����B��:9�����������|����/'�g���d��Z61H����D��mv�EY����L���?k��0���+�d�d�@��H
$FSW��HD*f$�
e�!�Rh�A��_���s�+��l����]J����	������wD��D��Z-��0�y
����&�Y|e�6�oIY������l�z��wa����u��l�b������������	��4X��L����<�=�O����I%S����������"�Z{�"��mK�����]G��]u����V��9����~���L��RB���<+����1J\{��!�&Q��`m`|vM���B�}��68v
��y�;@��?���N���|n?::�<��I8p;������l�4���1���{aL�^�������o��L�q|����f������[�"~��U����]!��xV���j�������~�����?���h�$�
��x�0k�`��(��PK�WS��@:K�F!�H�3�ug�c�Sn���[R��V#�Zo���c�=s�;4�)m��z��
6�:�\E����xa�9���1kM�M�J��^0��=~�������8���������r����A��J���������;j6��Y{�����7VpF�G�.������`�3Q|��J[��]@�9�|�<��x��L	�M�
���+��o�������I�MK�@oN��B�J<R���l��18����Fh�}�0Q�>���P����
���j�����t<n6{�Yo�-�f6Tf���}����nb���ki�M�/���oO�����s�	�����7�;S��g?���/�j��e��.X����E$X��K��l���N{\�I6R�*d14^
���/������A�����?���v����O����P;��H���Q���i��e/Da���M���b�l��^�V����"���!A�qE]�����xl�R	���Z8�t�������-��B���_:��h���tI���
~�l�������w�i�(f;�j��e��}I�~��I��X����$����|����wF���z��`0����N(F;�c�$`5����=�`U�R�{��2�/U4��x_6v6:�����������e���
�y��]s�:x7O2���y��53�UQ���8^,�dqp),��ddFo�Gs����L�wk��et��"^�
���E>�����Q�j�^Z`�u���Y����
)�1��unX2[dcC�B3q��H��r�E��[H��
�$@�**Bl���]1H^!H(BP��A�4��p�����_`�����;�q0����Wv76*�f�f���Pn	���`44r��~7+���u������JJ��]��
-�>�������m�}���W��w-��O��3��F�bpu�};��m�&|�><��u���R�:�{��K����f �J����
AVV���>��Bf3&2���h�.�z�
W
��,��m��7lq�+����_5��K��X���r���U�������gc�/��i��m������6r�0���	k�@��j�%�y�6�s�����O����4���c���[6���'�id&�K\�s���+�e��[��@��aG0�������DWZY5�	W/B8�h�x�	&�34C)����%�
%�����CL����DH5c>Y�,���r�z���`�="Q������	ce�.�0M�pa�
���T|M��T���a��JVe���n6|�9g	���i�0�:����	��E&���xk�<��Y��pe�y'�F�bG�i�?
oV�#0��}|&�����T&����/��������1-f���
�&����L�j�[I"�p�)?�x��$Xq&��?!�����"��h�T�oH4�+�l��!n�5��l��N����K��t�	�=�����@���k���a��F�-���,1�o�9Z�w������^��� �sRh��E�M�J\w0S2g��]Nk���20��<���l���Q"�R[H	��W���k����[��y�I�#HE���\L�=>�@N��=@��7_|������w�����p���Q�r�����g�+�=~�$z����t������i��5z�o���+�h=���Q9��J���&G���{>Rj�*y0�gB~��t����WY��}�C�"��it)��*/�6���bF��������l��8���mON/.���8go�����O���%�
��p�]2������������OVBK	�3����P�a�A������I��}��faN�d��{~|������x��)�����!PJQ�����~E�!l@���p��S�b"+��O��{�t)j�����|���zW?"�j],�8���v������c��m`��������j?�~�(��5D�;O��`i��NF_Md�	�����fE�����S�������Q�d
���}�O�w�A��~R[Z�������z��3t�2��!���4�_�fyH
���o���q�e�n*S~�]P�Eqe�M�{B&��&���@�%��`��c(�3���L�4��8�q�F����ZgnMr�[��\lZ��7���Z<����������NB{����
d����9\L.r��Z��YL<	)(S�@���;��������^:���
��)G����������v�p�(���Q������lK���Ay"�I�T2�$�2�m���n��}�_����s��0
�Q�����x�0����������
�MGw1g�������-�&0E��47>���3��[��D��V�1:���Sc5����E�o%�hQ��qI����_Z����������*��j��D�T�;�w�]��@�Q�v.���J���I�&�FB��	6BM'�b�
��;�M3����P(}(�6v��*$���#���xl����i�^������&���]@c��K��%(��j���������(^K�I�u��__(��nB���h]�3���i�>#�z9tv���0�	�s7��y$:�-<��1�pL�3�K�p�@�(�n�#Z��t��AhB���OiLRQ�#��S���5g��~��T&d����f�iW����D\k���U;�T�ke�tb.�t��x�����Mf��B��H'������8�#/pM`�����[8����V��:o��_����x<)�Y1�,�q�gR������4\����|��~�fB]r~o���y�k+_E�X���y*s��5� h(5�N��p3��}Y_���Svu��NU�&Rz����Z��J���]�w���p~���Xl�������%H����w��������DT/������:b��
�e�/�#6��	.m50)�sex4�K�K�SC�����3�X�7�FH�p�/n�x��+�||��_�e�����=�/�	��B!�������l��o�TS�� �~���Zh��_��%5(���x����R�����Dj$.�/������LfyD���`�y�Y ���P\���S�h7��;���-xwj�w�Fa��X1�S�����������U)w,�����_���x"ME��~1-H��KBj}JgH��a����f!�%�@�tN����4�A��X_y@�C�zR����p�vB�d�d�5>��
�"����i,S�`K�Z+��C'�E�k�)�=;�qF��6��{�����b9�������l���N(���B�	�	���wo��c�������G%�
�r&
�������`,��##&L��`�l~����/������������w����`�wn�]�����c���	l,���S��!{�^�������/����2��#�S+��b�p�N������|V��3����Jh
�����G3��T50�=�Y���$B+�,� !|�l �K�*�����.N�`R����o���d��?�)�k��?�.9p����	'7����][�a|�.��`������lZ���+�i�S���$:���C��b3W���:�V3H�,����M�W����������h��[�z�Z�����`��P�NE�!�8]����m��u��O�Un-���]/5��d>o�{]�6�M}�/8h�T�"�������a����`U�������x��=,��>2K9�$�����;��x�k����e@,����sq��D
��PGR�@��/�,�'u��f�,&j�gG��rlu.~�D�g�9��Z�����]�����?�����${%Z+`�Dy���0�N���
��U������j��G[p�)m�,�z<PH4$J��c�*����O+nM����[!���Dt���=r9��A�Q�{TF���z��+�Y���u��<����Ckc�o��x
q���C��no�0���V�U����������.���2���h�7��V����,`�T�VY��S�rf����J�Z�,(�
�t�^��5(�k���O7�
rG�0� �f�ZR�u�b��.�3@X�
`��P~�����y��Pb�B������k��Mw������H5S��TAv���g�i���r�v���o�[<����?�Z��X-��D:�]{G$�������F
W#�W<h�� �D�*��p�z�9qb���K�����(������q�d�3�U����SD�l��[�[__�}�|{t����w!�T���������J�a�)�k�sa�����~����,4�Q��T�4�6a������P��e�NF����-����1=�c��H9��F*?]�Ak0���X�l8�x�L��8kO��_m��G&�<w�'��Ui3��s,
Y��E�7����fS�*�Y�lZd�L��P)��{�a���Y�?��|g_wLwX#���(�Yl�tp2]��?��?�wi��B<Mo�~�9�nF�VxK�j����'������V��u�
'���|J1dH�����=��x��K����st�V�"���d ��=g���t`���0{�6!�l��V,>M��)�����P�vI���������?(��k�x���)�bL��N�l����b�qE-�?:U��:��]C�_��R�0�{�xiZR���t��������.�c�g�L����\t��7��!]��V���+*W��
��m�[`%m�\I��
�R�8�������ZK�4.&����j4!�y��,\�Y�^TO~#���4^�
�y�������}���^5��������^�s����D���q����m6���������f�V�*�pdk?�C�(G��>�[��2���2������@���X�;��������@l+��.�H�B����fs:{���8��6W�H�S f/��N����p.n��`��aW�6q��e��c�o��2yE�b�,'5��`<{�@���_�@n�T�UVY�o���O���(�P�ki���lw
����,r�����x���0���L�8W����7MCwg����:�����Y��^�~xstu��\�b���3�u��f�;���a��b6T�X�����=����K�e�U��~+�V���633'�S��?��@#�o:���X��/b
�����E�;*�'-�x�O��~6�;��ok���&�5s���F�2+���� Sc��������}U�#_v��n�����5���kla�~�6:{�q�D��*8YG��{�.������������������ti?��K���P��,h�S��`.����]�5��!���]w��|@�l�D�a�L���;[�:�<v���?>�pyrv:��<:����x~~|z99?���Nty������E-@����={������!V&kC= ��+��AJF�d�t	��yh�A�y��z����}������Y�UyE,VmO��Dm�oP��a�Z8���K�6�$��J�kBm�����+*�C���������������xcE�[�8e�cW?��e	�;�_w��PW�}1*�a������.�j+N�yF���n�yS8o6}�3���x��r�M�As������}y����3��`�D���l��6����_]�	j��Q�#��m��� *�-!_�B}��,�(Y����d������NhC��
��8������K�&��2�����O"��B���c���@��Z�
5�V��5��T!��1�w�������x��D`K�Ki����W��E�L��������E����g�W���� }�O�~��m�p^�+�/�(����46{���*=~C�k������n7s���6~3��f������������o�����~CL�LI�2���p����X3���1��`��6����;����n))!��8:d��x0bM8�����k�*��yc��m�#+m�ab�D�X���o`���f�����Q�:���H0�?����D�h����a���OE�<���z��F�NK�F�t���{��!��m�X5�o{��Lf���.n��A�`�� B-v$����G8b`\*���\�����"��.���q��%x��4s�;�
z��U��?���-j/��E5�;#�N�� ��.��Op���X�]�b�YE������)8�������,����bA����$y[����������#�u[��� ��7��H�G��W��5^�7�j�V�7XgV��~U�
W�%��o�+K����u&DQ���(}1M�6J��1R�i�D���f���k�R�����r!~o�r��O�md]���C���������!}���Ny�vUc��G���y����)%dQ����vw�lz����wD�m���W��������N��	��Lvk��?��b#z���1�FE�(�I�U^!E���P8��dF�EX�03�Q����
���a���4UkW6 �A����z���P��	U/�pz�kJ>�����
E<��iPb�93H�#H�RD2N
����h�
(*l�=�����{�������H�p���_@����Z��a�P��Rm�i�!��p����/>O�'��<�l�����Iqy��eqqx"=Z%	����h3~�E��P��
����]4�Y:42P����a�:����J�7�?�7R����puG��>Ef#D���IY�jO�8��)�RO0���d!����<�����&��?��J'Qgfn�����n?m�{�t����7M��-|{��R!o���*��=�d���j��fs4�������v�uF�$���hA������b	^�F[Y���.v���?_�����������4!��v$Lhu;�8�����4���
�*���<{�������r���;��	h�X]a��L�kK������y�nw���xR�w�V����*��s5����s�������N���YG�@���E���v��e�d��'��W�e���+�T���	�g����3�nF�	0��c�}�Y,�G� /J���I��[s1��p�e$��8��A����	����by�k;�����Z�w�h0��g�>����y�1v������$>C���O��|�_$�=����]8k��;p�E�"��*�;;�E��w+�����z"���k�~8�$`@�r�(�
(��5����]����5
������/�����;��;��������m����^�o�����=�������N��h���a{�4�������BW]>as��(5��D@���]Pb���duH(�g:������5>y��kz��p��O���?#|������P���(���=(���pz ���fu�}�������o���n�`��JPJ�B�&�`�.�����x��J����`H!<?�.�8�g7X����U� ����1��h��?v���y�(1�����q;.�^��/��=;|PJ�hF.S/m���5�^��
�!S��$�(��-`'N(���7����E�oYK�������*�]L�_:���cw:����oje$�fB|[���E���Z~Kl��;�
s�R��F1�+��W��2B�g"�y��N$3__Q����A!�t�i�;.n#o��������H2
�`\��|P���}�*��
��!f���;AY�E��8�}��>=���-3ROS�����}��B����EQ���OW�[��U�Lh{G,��]���i�����D(��N��w�l�[b��9K�b}�3�m������`���c,�h��j�����.�;���j6��?�z�"�4��M�Z:4�'���o>���
���U����.t�6�v���?D�E/���\^8��M�+!�U)������Q�����<Z,-���4�~UTX������-'���P����C�5,���
$c����Ao�����������h&k�$
���'n��,��-g�8>�wH������v1[*��U��ahB��K'�6R�����U�"��A;��,��nQ�b����#���W���Y�sK�?h�]_p�;�[�=���)�.\�O���?)�8�Z����(<"pf#�A�����o�H��3����b����e�_c3>�(��v����\�Q[���Gb�wkHO�!q�	�R�����y���p&��C{2'��Cg��P�|h{��w�>��f�rY�u�v��l�����}I
�LT��[_`s���	a 2�� �R�o�����tN��G�������-�1x��z	x��y�I�%wC1<l�����t���kB+G�46��8�B�h������3�qgl���C`4���Z���#:�c�5��#�1'Wv��)QgeR�~��'U�	"�0r%mL��e-dZO#�l�;�N?cA�����X�v�EG�dA�����BoE�M�������w�7(iA���
����	������A��t�L��^��bj����V��D�����5U�tGY�/uWg#���n�����:��� �����d����5������;J��rzT�><��+L<������f�a�J���m&��</�Cw�hBw6��lk���M-��Y�=��p����}��!�;H�7wu��6��5�<S�Y�+�'QG���DcK����-�H��h�r�i�m[�	���D!�x{>�!���j�-_��L����4����a����[���RB���	���5�m�e��s�ni�B	�4�V���Vd��o��s.!�'��E���'��H�����B�/	�N)!]�c6�@�_����6�|�V
����b��7�y����C|� � ������nC�-#�;��+DC�5=mJB;�}�Iz�M<j���[p��Z�#m�-#Q�7Yk���:k8_���fdq�p����Y������N|xt�-��������F�������e�uA�v�������B�7$_l���}&�N]LvM�{O�c#1HB��+��%��l���lt�V�"�������C;QO��AJ������0H���c�	]���o���v���ICFY�a��~�l����
�4��j����F��S�O�
�9�������M���6��O�B~y
��P�o3:x\0��::"�F���B���������&}P�Va����&�N����7$�iD�,���uTG��&��hS+.yR_���\E&�@����8�.Q*��#�i��n�	�� +FNdkD��������	���t6�JhDF9�Q
���Q�
a��	�����K
��'p�;~���/ Y�O����f�_/9f��t����-<~��v��3i9q��)�E�A���Q�}��|�V����e�`���\|{�������������9����k���c��%�W��`j;���:����J'�8Eiz6�����I���RI�b��$
m%���X�Vvki���\�b� ��N�~�=�!��`s�;��@�U/������ej���w��/XR��������o
)��R�����l��H�4���>Z�VK�En?�=L���9��������r�O�MGS�PC�|�FO������b��nD!?x�"�O,��&U�����	j��5UT5�`���N|������2��%�H�9��k�a��PR�T=�l�3h�'������,u��D4���k�I���Jj	����Hi��9pV|��m<���������QQ�L'�q)*�����A,*2�8��1��\��g1�����
bm���Z�%.��]c����W1��./X������z�4dU����r
���`�����h�&��L:���!��P?$�y�.���n���(�"�:5��K��O'� �V�&���Q����5���s(,�Q��E�S3��z�F��.P�z�o���?�����|�M�j�4n�2��������aRE� }�����������oh� �H�}�}"�4�"��}�+�u�.�W��7|i��Z���$����L������\�XL��s��]��s����Q������5��	w��qi|������%-��dM��{��~���|[KtA�������k���"w�knA���Tu5�Uh�3xE���+@==.���)FG��iF������+�>	t��)o0uc��`1��\{~S#����`uSGU�{�.Cm�0�>e�9��s%�T���\�
k�
<�1�y�����92��QA9�;���
�\���}���M��0�b~N�HL�����J]���f��H�����)��
f��	�Tw�=*X��7O�O,
�GB�"N OESn7�DR+=b6�/�Y��R�F2�J9V�o�:�D��`,���1�l�%�at�U�P�����?��K�{=S*Yl��<�bR�Fz��<����"�b�[��4Zm��5��en"hQP������'�J��9�] ��o��L��1��;���?6M`2�-������Ni>�k������4B�;@�Y)��S�R����c��+�N���O���:
��K9�O����O�3��_�����"����I�z*���@[����:�-�G�G�~�#�S���Dr�R��	�b�[�L��KN�����7��t;��\��Lr��(g�f�r�OM��q���f&���K^&���I�z���{OZl�&����������)���a��	�K����\{!���S1��b��Ac�p@�.�"N��1�tX{�q(�A�����7�����pv~�y�d9���CU��R�����7r��4H{V}wr~���]��m6���_n��8�av:�"�H��-�+�(�T91�%3�����Ib=P�n6�?{�|&2�*&<G��N�JV@�8�ZWP��6&�=9~���l�c�<����������wG�\8�JC<�QOK_����Bi�!S�#����$��tD�����F����d��!���8�1�}������'.����x�����4��e �P��' �M� 0�ja�eK���_�A���>�q��S]|�x+=�����j���wG�N�8!R�s�J�v���m����7.�r���>@�x�x���g��i��$}AK���52�����,�H���g3���2�H�1`�;�t��>d�}1�����Q8���m��*\1"�Z(0�M\{D!@)�����m�9ql �=ZLK����[�-�z�C�����e����#�M���������8y}�nb
N���-�I�~Epz�E���c��}va��`���z,�
��qo�Z��V���(�c1Iwr���	q��/Lm� S�Q_�|�7B7JvHn��&
01!!L�����$Q����8���W��d�3������O�f�������G�>��0�x��p���DA�v���D���4dt��_������!��v[��Jw��4���[x������nACB���_���p��;X��K�6��Th���qBr��
�}JKn��*��Ukl{��:5���R�*�v7�54b;�U*��W�6��	���?���j5��!�����a�'7��Ru.@*�t��8�6F��B��m4j��c�`Nk�����p��b������Fr�A\*A����VIl��Op��j�(q0���>m����^z�L
�Y�O�`����X��VT1r,�1�Xa����s)m���-��E�0~!�&���������cf��cc*"�)�����vJDQ�r�����<�f���G5��Ml��Z��%�o�����W�3"���n�)EY���%y�_P
��M?xRU
�7Lt�6FU������wu7�>�#����u�$���WG��@PbF�h1��M��	�}(��U.<�g�I&x���$��4�0�%`���A:�
���W���<�14�p)���o�d�6I� dmh����a�i�\��0��c����]1���fZ���"�N�&j��\�������e���"8)B� :�������4�]ze�5v2m�"w
��:*/U�����w������4*�Y `���8�@��������0����������*i�KK��tE��}����o��yo�����2��x�\��|K!�y3�
M`���5r� ��M��~M�(��/��P@����6����X�k<"��*�:���c�.j0v�L6[���"��F���p2b������IS�u�����6"��
��jD�D������Zt�OA�zdy���ez�
�{�������e�=z�J���=�>���.u"+��"c�r�`(P,^NA��������]+�U�+�"p�!��lE����Spm�7��d�M�/X�n�L&���k���&5��=U��������p(|���K������2��9X,��J�yzp����7�K�y�������
�3>l`#�dM&�m
:8��x��R�8&�$���-���a�K�mHk	YlC�IcrQ��s�8f��A@��;�]��2�O +)F��De����`�^�_G�dU���V�:�N���4]����j)@����["�.�=��y�p�������sg�����t�2,�F�'���9�7�+s��O�
#M��kN�r���]�e�������U���x-]o�
�!x���;'\0h���x�Ky��\L���G%���br^������|���M���r�O0�v��"!�@Z4�Xd��Z8bd�F`N��3�5�Zv#�.�ZWo�:i�11���z.���O�b��7Kw��^7��n
Q�q��r���;08����?aS�������.��Aef�w�DR�ws.$��2U�8%{���RYnU!��K��%���;e����(}��p�nNR�F�%��+���.v�W���d#8&)7�k����%JxAO�u��<����\0�CA'}i����n�8El�����w'�/�f�	Qs�i�-r����p*�����T�������j�N#��& ����JH�V��n\�����>8-
��i$�
w���&�`�C��z���[�����tz���v��~�����m���rZ?v�:9����nF�Y����7��}g6���������5�f���U�1
�l��������+��_;���j=���U��<w��F�����w�f�)��|���M���)�"�*B����F(������B��9���n�y�����V�b7�����������:���v�or�cs'�&���+N��R�[������8K���-��=���+�a|��B�5���I�)P/�
_����l�}��5p(V�X�c1@,��)o�'��V�!e�(�d9�V��n�����O,��G�j0����-({>�
��\�������_��`������$�,������E(�0���lA�Z�"������h�[�)2FI�*�+�q���tJ����g�"�9�+�z�+�������J
�4��~�7x����$$�Q�+�$��;�v)����	�o�v6���:��W�I���q���9�7�J&�D������A�q����	�m^=C��,����@��Y�N'Y'\.�DD�\�������-RW��Q����6u<)4�u$�������{�����M7U���
��d]���)��9��{@S��/rF�u>����b:��:F��U���$�VPG]8�:�NW���OC�d������f��|l���HD#�:��:�`h��s�A�y�]X�t��$P	���oEL��D�l7��aN5�TVj����Y��J����!�X%C�*m���UY����K}Q�
�y��Wen���:��6
VK�{j�<X$[4������m�S.
�o0r(�-l����x�:�B�4j��Tf���)%���q��i6�������M�L;dY*S�`z�:Ak�,uB\�
}�1����&r%�e(�
;' z��e_���i��H'��W�7�%������\-&O�3�_����)�U�7*@C���h��|��;��#� ��������n�)���'�b�����wC2�I9_&��(���������dFXt�-�sL}bZ�����8@�	���F����PLt"���&�)�����vM.J������3S�P���p����'g��RM.�k�����I���V���6��f=��AR��}hb��-���*�X���Ku��O��tv����o6�����u��6��Z�Zq*��V��C�J�E<CJ-}\��UY}����9&�����X��E����D�3b��D��)���l�u��<���1�%�J��8N���o�{�D���5����g��{�)�����i�����ig8��������a6���'97^��F}��	)d�[���:���Pq-��"�MdlF������
_kP�nM�JjBJa��
�����u/���p�.����sA�}�����&��	�����.�`���mn<�WsYx�����Dw#
�%��ja
T��d~
6�c���@#q��bDH�<
�Q5���)$�)a_��l���|����J�{�|�3�����$<rD���;G�f�7���[R�Q"�
a6*��1s�k*�)1�|D��h�k�T�[M�;�\2��.�
|��O�Uw�X*�]R����w��}�F�x���w2�`F 2k������'I�����L���{�y������|���/��>I��-T��C<����#���!��
�X;�#B�B�b�^���[�
���9�+u�0:M	���]?��>%��g��YFf�h��c�������`�����������!�V�;������AF��;-{0:Sb�-���w�@���
��������~�]���
�
x��y�w[��.W���]�b�u2�y�[)
��`6�CZ�i0��5b�s'|-��w���'��K�s���(�3eWj�����#�����?���G	��2y!q����-I�l{g}l���a��6(R����3��3d�����������j��D��W�27���i�6����!A���M�u�	:��D�r��e���I&;8�m&����$�x�K���w��i�:A�1z���*�����<K��������=�%�9)y��6����d�BrL�]3MA��*!9	l��2��h��-c%�������n{,vp�����LV;9k7V�R�S�^����j�C~����>��-
m;�xc�aw.������m��mn'h�?<�^����b�����zl���c���N�����LoJ�^Ns��/-��8P����i|/EH,/��R�L�]l��E��:���������2;��H����7�w0
}�GG��>f�������A��Eu8�������;��^�����cB���F]����$��(����������3P^S�p�5E�&<�����x �R���\D�B�������8��f����\�p��

S��,n�+��2�	���VyO��p@k���6
�O�
��j�����#�r�M#^�$me����A�U�+�eG��>�iXP�b�Z��e�Gc��������Veodj�&<���$[���G�V�8���������k��Huf#��^9����S�#Y2G������f��wF�<��>��<��
����qk�O��>'�BzF'2�P
;��� }��%��RC`b����L�Tl�U1�Y7w%�T�=@���MT/ ���nB��@�2O~#�>D���#��G&'~�<	�D���	G�?K���l��������q�E�~��
,������`�F��gm9-PIY��x9BgPZ�]��n���x9�i:���mT���;h��G&�&bw�j�>�Gl��b�Q]��{q�^l�uM}G�/Q�&6_�e* Y^��2��iU���l�����w��NR�*	|1���-�C<���|Ux�!��I'!���&D�:�*nH���/>�����njf�c�2
�ul�	p7��������0Q�#��8gn�����:��/�����"�$'p\��\������L97���2�o6b&���g��
�N�@�B�>����x�X�k>L�/�k�������*�sT4[�o��L}&��Iq ��A������ex�90�3�}�;�G�g��C�;�f/���H��E*2a�������������?���|����)���i?n�����O{2��(�\9j�\�H7���Ot{�A�lz�vk�s��l�@��E	���G��oEgT�����ro�cM��k��
Hh,��#���x#[�f\�h���i�u�sn������s�����j��2���7�l�����T���dy;�'�z2��|d`:�*&k����p�U+#�����(Z�'6��	���w�Ua���UP*�����y���O�q�/�2��
��]��pu���v�y�jZT�	d#��W�}�p~I�S����w�:�0d���$>��F�/7n�{�qW�K��=y��V���e�j�����"�CBY�~���8�����[&���T��~����a����N����{n����I������w�q������Y
�d�I:tb�p��m��Y�����D����/���8�����_U�x���K�@zb��i�y�D5��H8C���..K�SbjH�h0��x�>nQ_U����Ws�Hg|M-�A��L�u��4�3Wk�O��\����Y�uiz+����P��L�"����@���������|���40������ �l��m���x�#�0��������2�� �n%��4��Y�8V;&��1� gT��<� e�s�^l4�Z��C���dnf
���q�8���!u�~��l��a �1s��nU��7��Mg���8������#���5��A�9�hFr��Ad��=td*1Z�*{�B�7�|�N�'&�A,��N�
�m1���r��c��7������
'��b���?UN����m}@RR�A�t�P������{#���@m/%�Z
�#�NG��#��9q�Ig#��Y�]���_G �.�\u�[Rb�K�+j��)E-"��f�r�sQ������p�`4T������q3y�=wP218	$��D���\�Wp�-�>{���(���*��-�$��\�g�h���!�d3���VN
�?��=�����6BTy�d�	
d�4`���#�<���k�%ua��s�hR�b���44F�W!f���w�]o��`w7K�����	P�	�wcC��_���5��;�i�<�����=�Pp+�W�{�)o9�7� r��,����C��X����BG$T����`�UF�1j(�{�. �@F�Mt�Q���*��~�^�Y�q�KJ���x����Hq+�Q��1�� �L��]\<1;�Z`tL������u��Z�)
�q�|��.��8/�+���'br���2^�GfFg(���	��]7�K����� *�gBC_)��s3������@�� G����u��'-��a .�)�B,��@O����8��YC��)iCb��y��,l��.8z��\LJ[+(�e{�:k|� ���dt{�U_��v)i>Tj2��1&>�!F��������n5�0A8J�za}iH����fcIoGV��d~%G����d
�x�*SU@�C|����JdP��<J��l�_����m�6�Y�U�V\5pr���mB��nI�����5�!���.�d�� z����N
*LHp�"�qW��l7��w�����n������|�����������M����H� ���cl)uK�s;���������T��\~7��
v���1�J��\r7��J����1u�����z�h9-T+W��h�*��N��-9�A+Xr1���ZLv� lW�Ow�����������s��w�����)�y���x
f��\�����-g��M����0�E����B��Y���FL���f��$�z��%A,?���d� �=��-�����he�������_�EhnAF@!0�/��9:.�}�Y�r@�	���tYi����!�����X���9#��w�
L���|l6p�����Pc`�I��������sj����Y�p�R���A+��[��5�d-�m����{���G�����:
����@�l7"�{E��x Q/Wnl���Z����Dy��$q~�T�2��y�o���"H��`n^������W�5�s3���_��S�;�����#�F�z�u�N����d���b�b���O��f�"xJ�M�7p#�>���X.5%e7ND�=������.���(�[�RwP:�8����l��5�.�9�K��{�.�px4�A��
��M�(UR���s�"�g�DR��Kc���ia{Zu#U�A*x9RK�H��z�F�z�oXfn��4b��2�����D�����&�ej��x;	��<D�IB~�G�u�����y)��8�B����.���-���8T�G�U���N��'_����W��y��m��s�:�dU�}����.�	?����z�����9��K[��I�M���(��u���QB��#����~-���9
�z��q�Rl����$L���<,�����������$������Y����;�����;MY�H�05��!��<�nO{x�^\��>{���G���b���`*G����S��3�:kp�D6���9����
�
;p��V�)�r����x#�z��K�h����U@z�����(���5+�����q3��(Y�2��':��W��Bp��U���E|+a:��!��pj%7~}��U�SF��e'��6�	BO\���	�����K� �Oc��Fy�� �R�<��8`l U�&�9�����v�$��j����o5�Sw>w�����
X,Q���Z����K����3��QO�}�4d"9��D��vbb2��F��cVjr�T���0���M4�m!_h����[��_��V����H_l��u�����0������JY�a�b2,4D���(J(���]��J������t��f�Y��l���;���n���S�8<�(���\w��*�S*��F��PD��x[�Ga���O
aY��Dc>��Ti� <Z�Tqm��+�B	��Q�(�A�,��T���i-�0C#]&�����P�����zO�����{���~�s��NN��d��B.����nk��v{���n����bl�T)���Q������e��
M��m�:�����p\(�O(:�
W!8���-}H+����8�1���b�4lw`��<�j/����v�~��_��+XG� uQ���u��<Zre����+,�;���(���+m�!�A
��^*�!-?G���*��V���M�?��n��#�X�����1�S�
�3Q��W��B���$�)J��S�jx�6^}�&����t.�%Y�n���������>f�A���5����/���cu�����eq�7h�;�6��G�q jfCe8��&V��S����4>BK
�����'u�>�g�.RH��<p�%k:�r#����F{�=�R��dN��8J��m�'7�`e�2g�fC�1���
�uj}�"F.S����VAr�n�w����}L [�Q�{n����](��:;��="E_��������m���:%���k[��M�E�T���z�q��]�N�_���"�4��8�F#�����7�NdL[�f����<Vb�pk�v�U����������)j�AuvA#��{g&�%o*J:D������)(��������O5���,�8$8��I~_a��W�.�0�B��9l�j��,#
F�����Bl:f�r�M� J��z��&3z���������'7��o�}����iV���5|w�����=HL���Z<�o������mT��p�3:�Y�h�J'���@�o���_������'���L5j���
�������?�nQf����gy�#��hK���X��Mm��6'u�!~-��02���y���F�ny�N�m�96@P+j�'������'L[<��b�>���O���n�=�6�>>�%�<#����<Kf�U�HP2_gCr�-I=�������R�br���h������>�~W�����5{��	����y�+�1�K%|1���X��NBQy-�p�/Y�6��*6�M��v�"���d��L��z��N��I2I��"��k��Z%y��N�j�������V��pV�^��[�����B��jgr��*B�P���#af^��=�^+���ba�[���D2���fp�a�!�x��WI���x�;�<�����!�A��r���i���
_(+�SBf���
Eu<�J3y�G����������W�%Y�fp���������
cY���XV�6��'�x�t�w@����4�N&q'�l��F
��r��Pjy������<O��9^��r�Cs�|Rn���uN���w����:���m���B����:�sO#�qS�����E
>Q����aw&��X�����^jE�w�~���\?LSu�d��(&��r>]e3�I�l��T[q���W�H��1V����Aw.���u���f��+u��^�|'��s��I����H�&�����������Wj�~���l�0�����2�|���?;b�l��+�mX�( �K�$z/�u���B��7�hsb� )����J38���9���y6�O����t�L&��r�]d����d�f7/�a���+Y-=O����bZ���A�D���/��$�A�R�')4�!��\��_|-���m`~�%e�&��BG�U���9�2��`V�W���=���)��w��W��B^v��	��o��i���������BN��3�#�a�B��t�����%0Z5�B���;?�
��:C9,���d*6�=u��t�SB;��O�:��_\}��.�M^c/�#��y��D��G�pB�������3�El����8�AM��!�'�.���,_���������n��b�['�Y�����r��4������m*������Q3�������P��F\�U����+���ffW��"��z��{��P
�)etEx�Ne�H){��Yw��7�*R��j����:~1}���
=�����Z�����;��m3I[c��qv?����}���s�q�Z����R&�p���]�
���bD�:2�n�qd}��qa����o�vU��8��Wu.��^��mr~��)�
6��ib���m4����s\�@���Hv��oa���ha�jae��*b#������{.�'�[��g\��$�2�����'C��%tj��sBqKH?�
��`�b�v*������bl%d�Na!�2��q���U�p����.�}u;��C�P�����u4�����`�{�'�cp�g��w�Pg����=����p�m��v��{5��&�W��	(P�@�
(P�@�
(P�@�
(P�@�
h �M0���
#14Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Ashutosh Bapat (#13)
1 attachment(s)
Re: TupleTableSlot abstraction

On Wed, Aug 8, 2018 at 5:07 PM, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

Amit Khandekar offlist told me that the previous patch-set doesn't
apply cleanly on the latest head.

PFA patches rebased on 31380bc7c204e7cfa9c9e1c62947909e2b38577c

3. compile with LLVM and fix any compilation and regression errors.

When I compiled server with just 0003 applied with LLVM, the
compilation went well, but there was a server crash. That patch
changes type of tts_nvalid from int32 to AttrNumber. I tried debugging
the crash with a debug LLVM build, but couldn't complete the work.
Attached patch attrnumber_llvm_type.patch is my incomplete attempt to
fix that crash. I think, we should make it easy to change the data
types of the members in structures shared by JIT and non-JIT code, may
be automatically create both copies of the code somehow. I will get
back to this after addressing other TODOs.

still a TODO

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v6.tar.zipapplication/zip; name=pg_abstract_tts_patches_v6.tar.zipDownload
�Z�j[�<ks�F��J����p�D">�����,�e)���J���B\�������g�"�_R�,[ �����~O6�%��$�v�L�x���}-��G��g6��U�MF�k�y���iL&�����aL��C����1�����$����=��~65�K������3|�Q��I���(�r�j�����������_�a��R�����f����i����g��#6��7_��(\3g4�����,�sS7&�3q�\8�����.��\�/�E�K�a���F�����]Ds��)��9p�6��f���D��hy�p,��O�/x"N���v�t�����>g��t295M�M�Q�rk�*���������?0]?��_��NV����]V��?s+�n�Mx��k��`���`dc�P��[�7���q�
�`��Vr��nu�^��^��x���^`����<`�`[�;���k��;B�Ed,	�r��~�!��������"~k��#�;"�y�N�w�����l;��K���0�,���.��LAcW!����G�`�'�a������;������}��%,�D����WM�����������m"��gj/����������E��v�k����M�m`�,�����k�!����!s���]�[#x���&Z�[���p8�"i����b�:���f��'�����K�6a��`j���#m��[uY�'�oD���4�%�//?n�s5��M���Mq�m�e���'6��hNu�|A��g�U�Je�6;K�D�:�9�1�;��M�wQ�Z�R$���m$/�#�m���"
�8��|�On��FDrl5d�&��p'9	#GD��E�W+�$�P�����-A�[G��mG�N�.���������;f�5V���"��V��?�����u����l8\��:i��i���c���\h�b:sg�9u�1�c��f�]������
g�dd�����A�@���r�V�%�j�����c\��.����1�a�`�D�}�F��;F�@Mrib���^�ZAe�7@���|�cR������[��D��s���$��
@5���8z����w+��������2<����"���o�
=�9�J�f���oU�z���:��{��0H4�d�7<F�������	{�����5Xo��-��E`�&���v
��E/
m(��1����g0Oa4�cDC"y�9�����B����$Wv!��X���b��"q�����c�:n�
h@����=��+b����M��p��!������pG�H�-�#�e=�����6���;�>P:r�Hp�!x{"�@��@e�!QX�n.m��K��}����p?�VfM��j�*71]����Y�)��V+�&<e%��k.}0c}u�[|�����H�Q����[�9�/@p��"�)�u�r�Z�]�.3y����B�v�'��k�Q]d��(��	��y�XJ��}��D�c<���������%�_&�>�W������(t,�)�8r��j\g�VG�j��0���������df�T[���9�V;8�����#K�tC�.������v���c]����+�B��o�����"�r9��Zc����_��a�����;Q[����<a�f����K[�-}D�$����
H��k�'0)���8������u�oK�`zdvr�`�>6��]��
�����Q��%�'��]h$w�O"�/V����,�b�6����N&sc�i���uGzK�U80��BV5�TJ�������������RE
����5�-R�IO�^�_D[��>eM����3�r�jl��
���.����m�5��(�Q,�X����4���p�-Y6�r�i38\���P��i�B4� �:�V�[�H0e��5e(���Q>�\��&����G��{AE�a���J��#8�'B�S��1{�ABY`P��8�rP��Mh
����'�u9�����OE��D�\S��������
lJ|Y��r�(�����]9"~��D�fQ@Fv�[������o e ���<� ~���}�-��g1���g{���Ro�������>�\^]]._^���9�Sx�������g���N����'d4�
m(�D�K6$���0k)%%�\!<����V�g��8L�
=�\
`�M�A�3&��!v�o�����K�aC)�c��3���$�X{��;������������qAa�[0	g���*��z� {�A�$O�Ha(R,>�k���@
4�$�R��a� ����o�=+��#�J6�����}��
���X�:�n}1�/p�	q��p����yK����(��";N�	8!v,�����#�J��RJR[���2RE�So@�rs ����|��m7���VE���!h��'U�U*f�_�������I�;|@T$F�o�rXz�e!&If��mm�t[D���"�u�;�a���AD�"=4dG��;"��)DL(��G�[�]�vE�������)� �XX������hp�r �g&c�3�
��0�q�����at�K�Sv�[�-�V3��\�%Ti�OG8��#�q�R���r%�8\�}J���Q`Ht�8��O}��������?w>=��o�Z.@1�FF���d�6�"T�"{��a����7E��)�D��t�t����O�A6���<z�]["���~s)\����r��k�g�x��C=Xs��c*��Zt���D	������p;7�f��0O�k� ��@����-G�s�����LR��X(�2��WL��V�r�<�/�������*hx�����6O����������K6.�J%��J����_�p������s��|��Q���$5�zjvv��cgX�Yx\�~����g�@��O�W����K�G���+h6�w���{����b�8nZr�0��;{�
�����B����D�L>�F���u��u�L�@��\���+MApo������JS#w
d�
nb�X���@@�w{����h�3J*.��M����$��	#��x����E�]�[����Z��~~�: R2�����`����qjk����`p��o���m�7$����.���K\-UsJ��<��,��r�~Y�$M�V�(�=�.������B���U����p@4�Tp�p[��.���.���@a���p��D��������,��4�����c�G��
rS5��	� ���r�^{�e�)G�9J��k��:�i��Yy���A6%i��?������B���V��iX�"\�b�%�05m1��=��d���U���w�r#y> z���ZA��^y���"�R��<���f���2�*���!�J��u�cBH|���M��B`m��QT[���C�������;Uiqy��e�
{B�
�c�DR.�k�<F]�8��0W�e�P�GwH�z_���������:����+�)6�	C�f���YmC��l^��%������d���j�GY$�P;�Ey';O�CW��z1��2���c$K`����Be�$�����:�����Ma�>@���&���B�9'�������6[Rj�P+C��Y�Zm�^�Z��������H�\w4�n��T#�}Nm��DCV}���BBb��C�����Z�{/6���7���HP]B�������Y���"��H��Xs��_
Q,9�BS/���-��)�>���Pr���Rr!���j(���-X_*]s&�4{`"�(������b�������	�&����/�y`���l����1�H^�Dj����
��VK��C9�pmM	�2�
AP�}��,9^*c���%K�(M�\�#����Z��������7�g�_]fI��0Z3�2�T'�����^��c{�L
���"��f,������K]������(~�] ����
�^,!�NBy<��?�~�:@��nz�
&��+�� �
Z�
�����t
K.FMUV�8YU���U.��/�������
�A���J����a��FP%��NrmTMY$���j��F����4h_��q�J5�oW�zy��|�������)���Ad��/%qY�(���4^���{O�������C1�gpK��isRAG{H��F��T�|d�}/3���7�Z��P�Ss���n:e�Pvz2r
wbi�bn����t��@7A�e6��)Xf���4�Q���:�R<GL�M�F����{�j��_[��gY�ng��S[�����~���>Uzt������.�+���*��%�����J��V��{�����������z��,n���������X������^�^����Z�
��Z�_�H0u0�"?�qI�,UP7�[���D��B�#��J�����*+����/������EB���C].�4��.�#�����!gGL+�!�vjhj�c/�LY��f�����~3���4��c4���7C<+��S�+�C/�!� �P0&�t�0����}4���xj���_�C�������g��kLmg�M��\X���Xg6u��u6����qy�O���@���<ON�i��?F���N����p��j�I�������@�X��e$$��������I�+�k���wfN�a$��!��K1�0��B��K���n������`Y��h5r�����G���x����b�&NaU"L��y�dq�]�FP���1yp!89t�?-7������li�� �X�-q�2W')����7��M���=�
�y6 5��9!B���lD�1��s~X�}Ki"�<�n@%E8���*Z�m�1��M�U��`2<������������%�K��w��$Wa�����@���u>\��e�7RT|#��^�����L�t����"��!��*5�E��.���H���������8��Y�q�/gq�>�D�Z�L�i��M������OL��o�h�B�O�0��D]���0�^A�go���C����a�sG����?�<�h:����tb��������%'�O;(��������m����"����2`�O��n�U�{����8 �T5�9Q�4G�E�t��[�Q��r'����+�p�{�������$�#��hF�~�x�M�D4�F(���&P<8����0��U�bI�
T�L>'��AC��_����DS}�D-��f
15���I�O�p7��J����>�]��8�����J�8o~�I�!�/�-������Q�/c"+����
���W/^�>�x�����:v\������E�zZ�!�����Qf4kCP<j���@�Zhg��1�Q�3@�*zo1}�G��	��y�l�+%\��LY�gJ��{���w*�y�Ce�=TBu�Ke��T�����B��D����)]��oBn�:�=U>7��3���>���������T(��tK.�J��^����������~�jb�t*�P�<k���I8U��6U����T0n[��t��Z����E��Vz��-��e�A�KY%�
6�iBS�W=������>gt�����rK����
�O����w�-���
��U��C�����wQ�Ixq�T�������+��-79~+Y]�>�������v�/�?�����a��`��L�������<Y�����Q�/���g�G#�'��5>���\s2Y,�1�]��\1�����/���[��d�G����{�/����hrj�k�#������Em�3'&nD��Q�/xt.)�8tl�9����K���-Z^P�e�Y�XzZ�SE/��av����`�)e�����Go
���n��G��0[�/~��8��M�����'��Fr��FRj�N}��@���L����{�.:����
�b����d���l8��OS����^J��<[����V���P����h�i���Z�"O�0������m���8������{m��H���;Gc�3Jl�����d��j��R�$��&-+��?�����wJ�KrFk���(
�B�����a��1��gjX��K�:����)3zV��	M7����-z����woN�&�?�;�<����������wG�N�8�J�TY�z�3`�XO��A5�5��*F�K��>�.~<��y?u��-'���n�����?9����1����w��
T��a� �*j�������5lw{���A�7��������=kw����L���mw���3���A��������S����;m��{�
@�yg������� �S_s$.*�%{����"��o�#N�;_lz�I�b����A�^�>��.`�d�
��>��5�8�Q����4n:�_x�gPQ��l����*�8��E���]�&��D�c[;*:��(�����1����GB�.n+dkZQ�'Q������(��*jB��F�ot�B�,������|�|o������.�*8�,e%;X���G����2�~�a���O��#T�����v7����^��E!�v`o�tA��xB��A��7T&���n�\>�c)���a*�:��$q��� �&PR^S�8QU ��k�ob�wK5����xA��|���i^3Q��G�Y�h��V(Z��V� ���cU������V�'Zi����X�uk��a%�\�.u�������VF����E\�!x�+�����&�^]p�ag�e����/���z	�!t�?�X��;�p'��i	7Q��'i�t���'�G��ib��yI&�^�)��������8Vl'^88+���.?��(2�gX�9t���Emi�R������:�����B.Q_�]�:O�(�$$��1��O��9h���[����h���BVz������%?|l��`�-���Y^��'��h����Z?�'�`��^��E?����s:�h�h��Q����UY�1�P��GE�9��
��`����G>��q1`���K���{{������2�a���'	��rZ�Q��[��^�>�X�k��=k����W���h��!(z`R����/S���� �������-����EL0�@���LU��U�$c��#���h�(��BB�%�a�3�t�]��U����l����n��Z�[P�{����E{�<�� |�.������)��Fif/�>!�i��:�4�{n9��Y{�l��~:X_vI#Q�y�:�q C�bF"{�4�����]}�������AJ�w>��_v�*��rT<�y�_�d�?�:�"��?�6���O��g�8�o����w�����0�- �%��'�S���iub��B�n�v���������G��x:���p�i�[31c����<��Z�����*�#X8����J�������0����#����t$sV*��R� ��������c
�$e�q�����<���������4,�J���R��IV�D|��vb'�M���f��	u\����umPB_�+�o�E]���!,�@�Q�F�V��RI\(�U����h��,�!��g�{E�=CTwI���ma���� ��*Hx�+�M���HS�o���5;�`�`��:7�9z�o!q��U^=p�1�Rp�������F��pg�$ms*�}���,%f	e���s��pW��2��".N��t�:��Q��{���������|�I������Z��[Z,�)����e�����C[�[����@�pb�Q���$/3�\fz*�D�eT����.dzD���[��'��������t,�K����F���F:�9N�T�5�Qo4�������������F��8�"�I���6%�0��??	V�O�?��Vp�Gyz�s7��^���0��`��s�#xQ�96�1�J1�'��8lS�V�b�Y�_q]�Y�����-S�%��Ku��"5u�49QJU�U�����J�p}�c����x<�(�i�O�����-BE/3t����&���������Ltfr�WSX@��~�����3��%8oSOA�@F6AL�x��1<�@�D�������WAiw��|S��=h!��1�Q����v���X�z��_�+�B�d�O���\��.!���N����R��h���
�{���]����]|�f�j�h[g�a�5N���D]�W�4����zv�4�=��7_�������T����M}�
�t4�S�bPu1&�z��r�)ZK����Ok���;=��lr��Ok�`\���v���l�d|�0�UC�a�:F���Yn�O���;�qp�i���V�Xs������ $j�?dQ
�0����%EI��mD3G�&N����2�l2������{�/P7�M��OgFY����8�����g��k����Zk�0@:~�6��T����X�M�\xE��x��3�o��\���s���a]���F���VM���8\^LN.&�}@��j�T�h��K�b�M�{�0��>���C��]prF�;��������NQ\�]m�lm6��Q����PH$��H��J
D�T�p��~A�I[�`
C�!q&��� �b
w�@8v�)�}9��p��j�� ��X[E�71c�Z]R��7���x�`�/=h��P����UV���H.}J}o��A/~T4�MLB���������Kw}�a�,N��g!e����_��Xq+�7k�x�-]�p�F��)|�����07��z!�.;��Z�Y�o������D3��-H�P+	�����QQ[���c$���,�H2�U�<��AV(Z�"�CB�I)elMHp�oV��~2~r����9�f74�{C��C���;�����9� ����?��V��������?h��t���������z��p<�
���8bx��m�F�~�7����/#�����;~���r��u@��c�2�NGq'����A����R�������l1r?�-�v-�}��N�Up��8'�����E���"�=n�Y�+\U%�
��L@���T�\�]����:[���?�!E�K��:��8�_~<?=9��tvZy}v�����K�RT�Fb_��D��&�i?�!CD<4��B�%l}��������i��^�5!6x���l+�ux�G�s����_��.��	�KV��)��T����y�g�B"oV��:�a'U@s��qM)�,�����/����w&�lp�a��,�9�M��Ra�Q�n����h�����j�[w�}g�>�Y�S��UU�r�
����f�E�j�^�������`��/���)��5��M����'�[�w�������j�Fx��t���h4��)�%�*����J	N��R���c'��9�����|��?�
�A�OQv�R
({2�i���x!�G`H���m��8����u�D�$�u;�Mp`��DC~��i��1�{Ts����#�����3v�? ���J$S#_��XK�_����]���09B�|����-����V�4�r�Y��q���8e����]H?)�n�2����-��
�Be��6�W��b$��gY�V�J����?�Gu�,P�Sz�.v3���
����W;��X7��:��.%��7����XQ�s<��Nl���~�D+w-6�����9�����i�}ZON��Q��B^����lQ�a}`�Ikx��!�A����j�2.V���j(�����N�7Q8w��W�Z��L
�,t���(L�����Z�x!����H������Q����N���s�����2��7D�P��~c���
e����C���
��~`��w��N������C�_�����Yk8�gBo�g�Yw�����`���f�y{�vz?���	���i=�d��|��t$s:�9�8sV���|�)������f� PE������qG�M�fP�+��'NT�1�b�H�W@���v��a��G�	9�)�b1u��k_F�KG���"��J���-���
��=��O����Dx:�^ ����{KQy�&\�S�8�|���&�����nb.���X����=����f�����{�|3
���d7��%k�`�q������k;��t���|����t���<�$\��@�'������s7��;\�n����������Oza��w��p�<�|-������U��4|?��N���d����$U�n�^�NMBC��i�e����%��6�D��<��T��b�u@]��#�-��	���i�$��L�����bKj�%�	|/4��9���k�H���4	8�����m�
"	�����]��H6�*����s���Z_E�����u�h�\_u�V,$���P����m�'����E����c����D^�Q�5�,��f�2\2M����w)���������=��y;�"��5�n"��d���[����z��1������/U��4�.S	�����V\��������,?����^{0���>d��vB���=��w{BCo�~Z���a�����,��VO�?(�4|��9��;sV*$#<��.e1=
����f�Q/i��w��zg'i���;c
��1�f'a���\D����8�nApD	�� ��4�z�a��P��U`�u�<����=I��C��^��?=j��^'��L3����l���	#��i�(��b��X�9��&�8�����c$��Z�<��*y��3-W����?�����F��;�V��[J*|�e�������)z�~y��i�	��RC��6.�����EjE���^L��P��DT�(%7���;W�7�9���������5��BoB�}���L��}e��1�-�u�A�Tr1�hs�-mi-��
����7hZ����@�_����Q����G>�4�n���;e}��v$����y?{���k*�.�T���U��a�zC��KG�j�������KqF����SH�fJ�����=J9<�HneL��g��y{~|�����S] f����'>~��FV�D����9����2��HJ{����^�y������P_���Z�|
�������ki�X�>870�����C�����l��]9����F�1@��S=:��S���X�E�1e|@X+��������.
��2��1��z#NF���4Yc��$����S�+$�>���4��,�b�Ts�J�|Z��V#����O��&!,���X���=��U��I��.���"�I����r
���;��g	V����C�D��L_#�[
}���[�w���Z��V���\������
�����0�+�d�C�&*�{9cO���I�b����$
o���T���d�A	q�%6����x._h^�^H��At���?� �lr�mt�;(*����]v6G�������y��kcL���3������+�>BV���qV-���7��50�>�Y&���<8�Ro����0����P�
�L�_�b��|\ ��3�r�?�����d�?Z��=X��~����e2Ih����������Q��������/>P\���,�N{�����]d�1�pN!cl��v�����3��[��x�N�u}J������d��1gF��dl��d��JXq8,	?���wb4@z�og����damaBp'_ff��;goK�������N�`�(�`,�z>Q�Np)��*�Rb#F��P\�U���Q��,�����=���@�0�A[{�����cu�(#�.���� x8l^")��f��j�p7��g�s=����)%��������K��8���+��[����0������2�%��z�k�|�?b���/q�el�����\��G2T�L|��k(��N��G������5�������1R�eq�7O���L�	&���f)�4����'��S����eOOE��gp�O�C0o��`�\~�3���o4����g�	����&��*���������9b3����� D W�(�X�Hi�d8m�,V�*ca�-�YG�\����K�b�� 'V
HH��x����M�=��G~��,j� &�
1�4�b�)�7��O4<5\�n��u�WWw�}�+C��-%�:�WW�p����,Dj�O������\2�"EjU�|�p�?�hRHP�<9V���H�
P(pF����7h���f���g���|7c&a��wU��Q}�8*TG�������;
��x�/v���p&�������7���T)����v�X@8L�n���@|�xC���4�������
��r-��f��ddZ�%�du����� x!�&����nF)�s��=}�0M�
���K����M���7��(���F� �h��8�(�R�77��@�gJ�����3U<[x����sz�V��������~���������I�F{��~�>z�����?��
`�`�(�Tb12x.x�������as�%"����%�(k��M�����;
��\D(��L>�+��U�,/�����;M%��
���]/n����Kf���Pbn@p25�Pv#�FN0xH>��-M�C�h�SC�k(v����^Dh������Q���@��?�M���KP�T@���[L)����
6��CI�CnN�^�����c�5=�����<"5��0;������4�EW~jkX��{�r�����Z��
��~0��a{�������{	��'b]�=#|9J�s3F'�1@��rM/}�I�%�0��x���
@t��{�� O4^�xlGk�p��@bW?l�C
@T7M�0�fM�z���-�)Z.	q�=
oG<2=�����������,�$25�������5��^�e��MQqi-I��������d����������
�����6���p������B���v��W^�B��A���S��>�Hf'���G�(�����[��Rb���0)U��p�b���
�d	��T�'�3 ����Y1"��H��g��S"��^@,���n����n
���#��G�JF2.b�2��J��d%V2����Q�1�8�a���H��h�%����6-�R�� �������i�T	'��T��}�p����v�&��T�������\Z�_:����IHV�/�>�Z
H*t�TH8�d�B�L�F�f�$��d_���j*�:r��H�w&Q7�D����D�\B�6����Z�-j9�Q�D�"�F;!����M����J�I#QnUI�n��|.�:}*S�0ccF�J5�~r���e���P��*����S���F.H�k�u:0[���{upe���y����f	e���������Z���+�7
������_�����:(z���e�{�����-N�;�v���z�5G�a"��_���)����>o��D�R�����_�>?�pyv��u����0�*t'�!�����e����8���gr����a
������g�Io���6�V�_��Uet�����7���.\p7f���t����F]�o8K���L����_%z$���X�[��K\r(���7�Y��z$�����;�h�w�����.��U��{$V��"�7T�!�G,c������B����%Sja���t��
�}�vg$=�9�j��A��,��8p8�^!i�X[�
$H�C�i{H3C������GY��
;����M�����|{t1���_.N^�3�S��r�������)��K�"�4D�"��{��V}����7��/SL;���cn��9?�d�qA��?50�#d��I:?�����
�f���~������o��=�h�h�!�1��7������B�],@�E
q�����?[�~���������� �����[������y�=�x�p>����t������������
��zWw�c���ku���Y}�0����;�8w20�z���E��!�S+�!�]���;O�M������0+��0��T	"���q��e�9Y�'`:�l��qoMH9P��e
��'no�����y�*������7��'��i��'P�k������7�bA`�:+�[Y3�����!@����4��l��9�~�V
�D1���M��D�I@7t��
�������
����F����?r�����!8~(X��s��N %OI��!y�<<8�� �
��G��T��<��bx$xF��F0��tb�C�}
�to����p��s�`#������kVX:����v�L�.i!��0B7��ex�!,e���z��ux�sYO�@4�6�Y1���v�������T��R����K��&b��z�B�EK����
O�f�p7^���q����
�������p\�NP��GJ�����
�r\�t@��=�7:�7bX����u�
}zC� K��}T�	���wk�H����	��"�
M���G���o����@����fEGUE"�r���E=K����N�Rm����\nO�/i}�����}�����0L �03�M	������;��'�u��i�����G�C�(��K����(UL�QN��r��nm�>�y$O����6���i6�^w<�SR�>�s`e�w|v�v3��i�B��E�Um��Y�x��p�=L����:�������:a�����W���U��F�h@�D���BdI��.����^���S 7<X�e@�9�����2>��px'��M�`f����aI�&��([�D@x��p���B����@?~@���[���w����� ���R��6�a}OHo��6��u_�O������_��o�����?�i�u��y���[���w��io4���t.&gh�?�g�y����i���_
�7&=���S�q"7����V�!}�,�,�z`A��V!
�h\��;b���gF�p����1d��wl%�
Dx9XQ�j:��������J/F���L�c�(Vb��'1(y���1!{�g������LUm:�/h���R>[t[�����+)Q�d�W��R����YOj[�������J�����]YY���V���Qq���,��Mp��I+��V�$@���6	3EoCWW<_T��x��
M����	K�Ar�'dYp��k	W���\=^��t��0��O$;Q���1���I�2�Sb*���zzrp�������H�3g����9��
M����1(f�y
�c=%s7dA���:~�iS=d�^�[�J��F�l�ZhQ����F0%����K6������m��O�72����pC�����^�3���w�r�1�SnTp��z��VQ-U�o���&x����t4BGR,���&0���D�w�P/�l5��jK^��5&����
,���k�R��&(�A0�cWR����
����y����&u�r�9�n
$%�7Nc�l�P���N���=��a�����J�.��_V4w�("]L���@������:~��Ud���-�m�J�m}���c��� u�E��g��@'}K�����@�O�1i�z�����w����S�|������������+H��@g�v�T���3Q��;�RI��3��A)*P�M6$�����?7�Q����?�-�����="E	E�J�D�$�����7���}8~�)\�[P�`�����R��R���_�	@�dT�%f��]�{�r����+XX�������@�|�=�@�yA4s7\-�h1]p�P��I2��$����R�J�V�0����Y�6kA����n���f��-�QQ��M:),�28�b�$�GY����~��r(e��tD/�*jl�JMSu��j���@��|�n�h���"`�:��m��hTG!Zk'��
�j�`3��E���n�W��=�<d�T�J�Z[�\`P���W����r�*#A5F�~"3�|����R(G����`�Sn�%i����"�B����D��
81�9�
��M�Z�I��B��/������.�e%Q`S��|���$!D���
�6H�KI�h�(��i�-�F&]��|���S[A�6�hX.DXOH^���G\�(�,��@����9���w���p��������)##�N��9w�F�^����8�-��S��#�	;)�FWI����hO(�g�Q#��&��?0C1�`��v�2��b�\��9�`���P�a�$�(�l
�VP�c�� ��b*������o�HK.��q}&��e�p9O�JA}L��.���b1.�.�b�5�&����	���>�T���������R����TJ(��6��	��$(�x�
A�	�����w�����t|��}N/*{l�(��B)P*������y��h\5�k_X$X[7-�K9K�w��U����V��J�!�����{d�q����F\��������aD�X��?��:�����A�2LDnu6ih�H�]��A^e>Kg��*�S�g�� �p����> ���fR��o*`����Ha�h�����O�0U�kEmE�`E�FE�ke���`EF�_k"�-��~�^|�f"=I�[��[�WtZ�#�����D�u0����qmT885��Q%��aL!��Z�D�l��	�*2�P�Z�(�[��Hh�y+�w<����bZ���U����'wk���nC�/�����	��9�Rs!��W$��V+�.k�*�<������J!�7!�d�+��+W7�s��N�����<�A*��������`�����l������*)����(n)��N��!w���m?B��4��
�4�4bQ}����t��������S��e���mP-B�L%�JL:|�dR���=9�{���iax-�M"����T�R���JJw*P1�5
�JE��>��M��a�Y�����O�PD���3��0��0OE�*���zp�rbI?�^�'���f\n����[�en�hWC9<��E�3T�n���	�������%��c�����3�
4S�3^���DuA6�A�%��V*5%)r�p>@�����v�
���H�p��KM�b$AG���n�@��n����@�m���a�QK����u=t���(q���O���#��������@����b�^���
-7$3l��������t\K,o�K��%"n��vb��Q\��3a�:nfcM���C^��y	�'~�Z���a|p��^$=��(W1
#�u]��#^R1�0L��_�
d��$���B�����������P"K���J�3
A		 �&�y�5����
�Z/��A]�y�h��!�b��D�,�7��#�[@*(bN��kw,AL>��l��Y���m��T�QR�m Del@!0�$��[@w��Z���;��FE8']���t�����$�C]��l�5��
f,��,9���'�?b�p&Uhz�	Q��(�Y��M��i��7Vx�M��TuhF�@_�:It'-���>��ZnE��Z`����s�}����2�K��vn�,��q�:���E�m�}�iH+�nt�
As�ug�B[g�
��
���hz���w�d��?U��Pd]�@`�A~XIJ����v���Ab�'J=An����9$F��f5��N*	���<T�6W�@��hwE7)^�b�j�Ry��W�R:���]_�Adv���0�H������~�l�� I4@5�6w�����&\d*[�����=Q[��W �����w�'����"^�W���u������-F
�rM�b�.,����B����R������M nBn��A��7*b��m�1�g�46��#�N
*q��f=��/I"s�C>�E�������v��`�R6j�,��y�]����v�j4�2�T�T�j�X�eWBF��i�L9��#-n�%�T���]�r�I�K��J�W���z'�t��������t���%!���
��oU��x����R5���v&�
�����E�������v��V*&�E|�C)��u��n��
7�JV0K2\-���o��V7�!kx���v$W�UI��3Ny�F�ME�ZP�]�Da����w{X{By�#t%V�,Km1��u�6}�7G�NAI{�C��������Bn���Z�n ��;��g�pq{%���rq������qW���8��������_��Y;�k���
�I������'5G�R�A�"�W����������&���v�x�������Uw������9!����FH~w����$%����|5��ge�\j�
Dr�ulE<����S������cY����n�vE!,+q@�.���(��"�c�s q���Kh� ��Ew�6��p��7�C�j���kY��.J���,�V�� �<��;qV�&�uiC����F���#U�]��������j5�s�K��T�M����CR8$%{���?���������^�$����U������]`�����C�%�Z
8l��)~��V2�K	��+��"}�MA`�!�)B����ps��*fZW��I[-�
d!��	�0����7-U-4��0���[{���������+��"O��&��o�������N�wD�jwif����'}�������Z������uyaYQ����)��}�Fb�8sey��g�YEy*/����IbT|/U������e�z'w���O�;�[H��<6>����1��!|fY
��R:�I�������:�i���7� ��+v�i�0�]1>��mf.�
b]I1NcS�,"/�����8����>�w� 	��"�\��(������L�~������%7y�u�p2��{-`(�D��
��#�-#)tg;j�����|fc�>�����b|����Uj���n���_x�P>')�iY���*r�k��@�����?py����)Ev+�_���|?6�x�R��������>��b,?���T,�~�1���<-@��q��V�A��O`&��#��6���������t����#������Q�y|�P��X���P�@a�W��d%^/��~9a����4����\�����A%���W�%��Pj4��Q@i��������E�+���;���)�]~�`� �"P�� 2Fd���F
��20D�u����m:��[p�4
�Mm>�@�f�-��n�1s��x��6�#�l�w�3o��q`�|
��N{�B��D�C\�08�wC:��o�/��� C���N�����t!]������dS��o�A
F#I�v>^@��V`���f0�NU/����8!���i
���=�]q�%�8����?��F��
9�*?�s���O=f�l(��Pq���F_�=w�_���	:F�3?�o�
�b3���!M�l+6[A<}���0�SEA�u�%$��B������;���b��I�����q�+4�������0O��7C��E���r1AR�g��4R���A�J���nd��g��;�rC��
6��7�$���
�������P�$+�$x����\P����O�.���u6�;O��i�R�;�������\B�*N��6g�(�����+���S[5`'xM~���/�����jt'I-�0�6�3pl|8�F��9zA(��x�1L5d\sTA��eK�W���G0�N��Ow|?�\�����m����tk�E{���}�7y;Zbal�it+���W5kR���1:�+%	��,J`�;�����Z�m����J��n��S�]1�!��S4��p!6���y�|��`���
�����/�{~�s��u�4p`���S�c`
�����I�j5��6��EX����M��[��b4��b)�K�F*��R�9��rv~�����[�����������{������{g�jL�K1�T�X� &��L��[P�&s��������-��]B_=�H7�h��k�s8]f���7{�
4�s��C�������{�����Vk���t�do2���y}I]�L���	Y�H��7������ �Z�=kP4���\�M�(p	|����o��>F�q_���������;N��
y$����&}M���@>���d�ab������_�L�T%{�`��Y�����y"�,�qk?u#g���\2,���0.�*������s8A�������O�'��N���/��/�?A�Y�).���g����.�����i6��;����HQ��'5���!/{bu���vR�4�)IL�\=a���?)j�����j�h�*��8~#�W���%�f���/����F^4kv�P��i����.����v�J����!U�������+l�r�;� ��=s����5���\\s}�=�v+�&J7J��w�PH�dW�;�S�fK/J����R1�xg�U�h7Uv<��E�DA����9���z^zo{�Y�@�_��_�6��(����u�K3h��y��)�5�t��5����R�i�<I]jej�a���1�^~�����k%�	V����f0��s�_S�G	Y������[�����,�/�%]g&�I��k�ZX�H��V{���Vv����+�f'g:{s�\��kB���*Ksfj~l�����#[('�|-�^�����Y��;��&��"���o).$���o��3cU-�f���^���-'�|��Xok��I�������u�z����liOJ�nmQ���E��U�j&���8�� �<�R��>��7i�q�I�lJ��q"$i�w�k�����S�5���[��]��v�	*3-�|�SJi�jr�����2$:�o����[;N��p�����p���2�������9�
�wn�k�\���Q�z[\�IRn� B�y�'E5�����Ncw����4��	�����~�q��n>�����%�h��	�Ir\K
P�����E%��Fk���!`J�t��fT?��i5��f��J�Y�"��9E%yh+������G��q�@K|�z�g!9F������B~�S0r���nfTn#�]�f���-��g$��b!w�FM���5T	i-M�������I�S�2rO�_������+5���V�5�����+�����M�o����*����z1�y/��N^��2�i�RJ������m6;�`����^�i�����p����Btr���3.>\��n�` i'���<���N��(����J�p��#��cb��xbL@�E��9��u4�����Y9���i��.��1�Z#�,2MB�L�^��_����|��m����M���]`���"��o!���b#Q#���N
�j��t�:bD�`��m@��������v�~�$/������^���,I^��zO�f��/6����m+���\�Rz�X
�����b��$��0����mp'L����{����KZZ���m���P�n���n|#S�*�0)�-��+���P�\j"���l/�R�=��)4-;��Dgu��*�K"3��	�N&h��a4YX�����_������+CP-6�o�he��)
�P3�C}�7�2|p����"�	7wh�U���V����4�B5�RB��*���0!J���{A{�@�j�G��/�1�6
^3>��	.
�<�*�bQ��VF�6��y����yA�5����Z�o���qj�U���x��p�q�]R�������j�``����D>3�
����m}Lj3�Sz�7���P$x���!����]�4!����Q�MJ�������[�17|������`�.��WHs�%�&`(7S���0��[GI�����&���X���p��Z����58i�!��Ae�(N�sh��(Q3A$���<
�������d.��MV�eE�������+�,���������R�����{�`�Q��������7�C��4M�s�����=���Z���A�n#J������!v�g�rm�3wv-d�3�;B���'�i�@�[C�@�3�	���&�9��� sT��SuG%
!�;�5z����I�a���y��F&%������[%n��t����jS�;�
l�0I�;�%f�+��|=��`A�L�x��I�����p��N�	�)�.|	��f<��:����/�$����z�����y��\q���7<0����Z�
�����2etH\^���w:}�����05C�`�����"
��*I���G�b�a9���
�MA����O�B�3
`8�|S8�&l������GA���gg��Z�S�F��+V��Y�������d�s\A�)$_����E��bU�������O�m���Y�>882��=��8mK�LA����3��}�	�m���BbL�=���H�~R*`#�P��9%��_����>`�Y�K2�F�����Fe�K2�o'�K�C�����s1|��|x/������f�;��w��������m���
��Rz�j�+��;��q(y����J�st�����(���^pZ�1U7�����2�".q��d�!��
��7sD	�=V��<W���y�x��H:
rg�p��"����T�h^i��da������4���V���Lv�_*�9���{L5�����}����U�eD
K ���R$��-��l�`�������
�sCgTy
��%3`	\�������J�JZ��&_��-G�9g���L�W�^������n�|s�lP�FB� |��>�����jV$���d�a���<~������\7
���/�W���,��.�0:�&\����S�D���C�$J	W9�
�J����5p��X��_}����,fhj	�3�JT�H~@����W�zh�~U{����$�5!k�W����������-r�)�c���� p���{����K���pW��RC��	i����gS�~E�-���"�2���S�fg�&��f�.��6�&�G��Te�N�>T��W/�[�������a�#hlA1�B��|����l���$��hc��x�2X�����;�;�whd�cS�'JB#uw������)�v���E;��d���.:�3WC�u�1���g�0K��#i��V���lr���X*�U2�J!�[)���R�-���'=o�}�4����2�\��8�X�3'��y����
e�X���w������� �
��?S�*e��cMrz�Q�#!�����G9��+f�~B��Y������#��N�- '��q��)����L����7
�����Q�1��*�U��0�ghv3
�z�+�*���4�-�z"[��C3�4
@��N��gI^r�������aj�EC�
�*H���M���;��xX��A�[���J���������h3��+GG��������{<9:�Ku
W���P����9��3T@3eL�x��
�!2S& 9��4�������,�����)�1�����`��#|l���-=r���O��]_i���Ku��7��Q���o�l�l��OH�E*6c�F���r��
�IXe6�
Hl�L8���.����&J��ac���b]��P5����r�,��A|f��y_d�;�i�=zV9���C�h���\��t�����}�q�OQ&��!il;�+�P�N+������[�|[��C�������Vwx@7�b�;<�'��a�����Gk<��0�Ad���N�����gn��+kn:,gn:�9S����Vv���fcw�i6���g�.�v#���v1��z�qn��s���`�I�q�~��s��G��+?\@l��d���B;�� ����n�td�b����\U6�������u	P�JA��R�/��k�
�����_:���;e�R�5uN��5�e���L�j����;�^����������l)"����."���������'�o��<y�����r�7]��*H����8��4�[�������a�9���V�����Iv��N��:]�d�l#+�����+W��!s#�
.��\~�3�&@�
��|����������g��G(S��f��5�B5��|IR��3p�2�9SyB� �v 7=NL�i���������=>7������S��k��$�i�&s�(�f��DM�u����F����9�{���������Z^`~1����1~()��d�d������ouI�!+|�L�9���j9D���?R� �K��-�^���_���t�s�6d`��$@���Pg�4�� `/��j��g_��i�M���3�q����1Kx�p���r��_p��r��v��,����8�����~�Y*�c�I���x��
����6���7��9�hJ[7�������V��o�����(JM�@Qj��y��.�eN���,�x�	&�9L���S�!/HtT=�����.X����9O����UE�:����L�e3QhjZP��h6�������F�vg��D�&R�(Y�h8B
>��d\	'��HK�p�]��x���pAb���>�����KZ�M|\@%'���A�"��sm���!�F��G����ep�YF�Hz�N��o6��ig6��`J��������(| kRR���|�T���o&o?���<9;��sQ3B.�T����v
yg3/X��zQb`z�������Jo����"�V��dX�q�U�Q�.s��[����C�����x8*�X?�-��I��Xh���n��'�~���D�R��"�&��v��\Dlj���� 	��w}Z�,oye�4�!�q}�]E]��;��N��$�(���teHI�;,�6� @<�Eaw����F�F�lm��\��?4�Q(sG�u��7�W�ahe�/>S�11��M�a�Gq7��r��������#J�p�y}I���S���
�������q~��fA��7����`w�9���������0��c���=�1QF"�hT�(�sB��nT��J������8�����M0�����s�������2��U`*�n,!�4�f��R%�)�u|o*���t�����A�F�,��`6�8��}9����`���OB�lU|#���9��I���i�����`d���A�� �$�U��j;-�f!��DOLV�Cs�i1#l8���g'o�b�)�)"r+G��� :��fL�*��>�z��t�l�f����;�%���t]W����@������T?���e��5�`.p�]��3
KU�?"]l!9 h�l���+�
�aK��C�������U�1�R�+�W!������NW���rt�6,�������dD#�������������������������/Q�y�4k�z��[��ku���fC�}99���b8��m��GA����N�9�=w^F�����_���d�N�>������X'U�/����K����IYF|o�n�e0��PZ����zz����+��W�mj��;$$��!�YH\���Z#5����%DY��W�N�g%K�Q�8���[Dw����_��� �����Z
�d�/?���v�hC�>�Z
�(��9�i`��P���?����x��������=]/VG=�W������?wS�K$���.Ig?�uRt��A��>�A1�����UxCn;�6%�TH?��=�B}{|�W!�7���`o7������y�������p,�1/�����K����vw��b���y��6���O)MXL=T��S<Bg&:�N���������:\���7���9�+���T"FJu��f�o6����?H4�2l�3t`C8?JD�W�.e���e%��G��G���f�KR���A��ZM�<�F���h�r�~Qh��g��QD�C����~�����?��`���0����b>�O�����ID��A���tO/��;g+p�����
F0���?�?{s,���'�9��NzR��D1�K�
��1P���Dt���q^������[R9i�Wk�7����8F�TvQE��*���aj��-��}�p���6"M�����d�����_��s��/F��`_wto��=]+�zd��O�Z�~_+[���d^���u�.G�]:��>I����"7QJ�p�tR�ax��]G�!�Q]	�))~T}�i��I9-J'��Z���
o�y�������tP�FG7�'4T!T��m:"�'+��$��c>'JS���|���/%���N��D�67��JO�jM��M��!��{C��)�?eW�7��z�^��BZ�����U<$�{��?���O����4�g�������x�'��T|K�����?�'�$�4}�(i��qq%tMi��5�>�G`����!a�b���������`�&i�.�W��[!�4u�$j&-%lW��E�^@��n������?��Z( �PO���L�9���HN^����J�y��`������/��q��&���!�$n���|�7eo�J���u�Oz���������s� ������Hwb���#D����NT�d	�8���G��}�<�m����W_����o��o�|?9?�xq��o�0,j1p?M(�������*M�d�*�D���}5Q�L��7n��.O�f�����2�[gFQ0�x::��E��������-�H�\�y2�Y����@G��w��l%�Q�Y��������$^i��@�z>��e�����A+����GW�R���W�7���3f��s��0gBdy����l%sb���j$sb�gD��51�fD�z	pZ�]=�Y7a���Dq�}���Q�n���B���+q{?lZ��-m��0�,�r[K��x;	�CU�k~�Q���zT�W��ZZQ �Z������+(PN�Y�y�H!v�����������?���\-���o�.�k��K��Ss�3�����O�+>�^�s�2���'����m{���0g���z��GQ%�?Y}i�I��F�f�S�(�cJ���?JGl$���j�P���Z����W��3�{���T���>1�_���3QZMz��(���?;r[�R�F����������������{�fs<���O��*����*� A##7�����o�`�<��KALu�(�K��/_��z����~-V����}�������Mw����i����"���^��=�W�o`Qu��|�A����
��H��D,�G�0mI�-=������s��;B�]\�_N^{���'����$/����$g�5�&�����\� ��}g�$�B�Nh�,���e?�h���g�#�g��a��Q{����nZ�_����T��4��H�O�d��f3=�>{s<99����������g���K��TqYFW�G��O(S�����}����$8Q�\B�u>^H#�������#-������l��~�������������8�4Mla�c&������("�P�@�_�*�).�o����4�xUhL�0@����+����������K��+����������\���������"������-,#�W5Gr?����Uom.��;g�����3��)|���99���(���y�S�~*�/��|.����;wS�
�B����k����+������00��m�ld:s��+�ymn���6������A}U�(�g��K� �a�Ep��bn�F�a�fMT���"V����J�uh���
>���U�}�������!�G�H�g'�
�`�e9��
�N�m6�y����g�n��������C�_�li6�"P����bEG��k�W?��M�fSBI�cf�����O���2� ��_E>������L�$X���nK u%��L���o$4XL����W-���8��$&uK�R����q�W.��9SW�Er�^�@O��������S�8�5S���0����O��3����o������?��B�9�����������T?��
�����=9�3"�����8���0\F���/��n�����R�rwfKi���VNA�f��i8�d�A�k��^����:��_R90�)P
��J��D�}"����ntM^��&'�\P�"�L��o���T��	OH+�����[�q�ka�D\lj������
n$��mF:bX��5��xE��m+)�|���j�i����Mf@d��r�W�\B@��L�]-d�_�_���?L�R�W-����c����;���<|����QJ*�������h��O���<|����UQZ����N�_"�L�����g)��������!0�oL���8_�� G.�g��zG�$b�'���&����Z�u�D���V*���=���2��v//U�����)ZV��94���3]�
{~�����Q''4����R�A���}h��":+���N�)8��HD����>f�����>^���#�Jq�*��0k�S"�*:6�4��50�-`��a��A
���)��Mp��u�X-&����))��8����>����������R����i1�)%d�������B��F�^BbZk���m�h�?h-��R��[���A�J��|�^E5VL�n�%��Rl���i96����l��e�*W%���nM��������RZM�A`�t
n�T��q����W�w�
`� D���+��W�g��2
����K�6�CZ���^����MK7�'F���EQ�Z��w��S�_�����{�,�������R��$�d�����O
�p����f���v-o�)��>�D6�����2��?Sl��5��{�����������x�d�~l�q��a�cT������v>�RH���FeFr0g������Xq����||'�O@�O��>a�������U������s7�2���fq+V��K�d�������Jt�1k)(�	j��9�Z���@6�����FgG%y4$��C�X�����z�b�|e�(���7m���f��wf�����P�Zb��a��K�b�UAd��S2V�JO�������3L0$����Rg��XhK}C�}.-'�W�
A���(e^����jY�S������b
��6�h�1�V{{�]-���G�}H�%@���}B�+t��]��i�Z�O��0QN%�^��8�� ��#jcM��`�Pg{I���cy*��j���	�a�- 2$ug������8�xe��U|��j�~+��"z�f��ro�h�F��k�.Y�����m��BW3��7�}w��l(�q�aGE��OX~�	/(N��f�u�[��j�8XL�lzL@��m"?+���&V`�]DI6`5o:<icE%$QJ�9�����-�K9��������!E���G�g��Xn��c8�Lo��%i�"�L7�'m?x@Z����h�\B�M�7x2z��l���Z�?�oWVA��:��;���������n�
�n�`���,�!|��8%nn��`:(���,v#��ws������Z�����UH����q Ho�Jg���'-�K��?���{��)�����{�������V��YI	��Yy	����D�M_����������f���_"�����d�;��;���C���>��6��{#��<})�Z<~���!�Ff�q��
��?�j�;>��p���-H������LA������]��u��{s�Sg�S��"J$q�
�v�@"7�{�?1��p����Cq!utyA%g�U�c]L�e��1�A�����@�'�@2�.6Z�a��
���KY�n%��B&�!d+��t�i��v����ZA��l��Z����7F���=F����k)�
��W�owVD�q*�d���PeX}�0�������?������#���|8bx���%�b��$���u�9�&�t�O������4�>�|�z��$i/��z���Q�������Z�E�UGa�R���i��)�����������i?�$���cb��@���
[S]��%y�q�9���-��<�1����\1�;��)�4B\��+%�N�0ZJ<�"�����O�6#��0����9���	���q�P������md'�:=ygL��r�O��Lk:t�%2D@��=���j�1Th�X,PK�JF�8x��C\��]�-R��:$�~W��r����K�
9��'��U��]b�<,.����-w�����`{[z|�>��`{K"���7�7���/��~�"��~��`��k��t�K��M^��vvz�]vv�ww6�,c+�*\��
r���8z���R=��;�du�������i��1�R�2{`r���f/U����~��pO��2�{�\�`wq�6�P��@7�#p^l{�^^Z��&
sT%�-8u�����a��]��z8��VP������
fK��2���!{�&��� M���F#v�B����������Hh��Vp��0����J�PD8��+p^m�W�%#u��9�i��/u��:
�z}��5�����q~��4�Hf+�W��E�u[��Ui$@s��`�w���>a���Kk��}�;��Zr:M(������l�0M@�z�exI��?�t��}���e��U+�J�#`-0��Gq��N�
1K[^;O����Q�J�tqA���!�Vcn��5�hb�<�������SV;
��Yt����6�"���}����.;���UY
p���q����m�}Kw�IeRb#fcw>SA�
�o5�����4��G��u�=���A;����M�I����|��z���������R]�������f��G�!5D?
��[�`vF$���i� T#\%��"@AM���>;���������srzryr�����V-����'����}�:0��j���n#q�`���V�}���Q����)�����>r�+O|D]�3S�"�G��vgJ)�L"H��=&$r����h)s^[����F���;tc:����=�b+����
B�%�����rh<�
�=8,�*9I
��UN����m}t���Bwf�r#����tQ?�h5fF�+�"�I���C�$�j��8�F��. W���n����=�0���>�b@"����Q����!)��;�U\��T�v>�X���}�-�t�������[��{��
C�SPQL��E���[������vC9�_��N.�2��uB
���h���ff>�$
!xx/v�g�b*
�A�9(C*ka{��g�v�m�C`-�����{��x<���h�=�-��BL,�]������L����,G��������+
,B��Q��B�A��+Y�'_�

��!��/��S���/��[4x�����l��t	����H��C�H-:sv�jZ���
� �Il_���^�2<������������!�	�4�6���1��L�`�|�)UR�w�yJ�2I����rJ%�8�����;I'[���ww%�=<D���'������[$�����
���@T���UVk!?�����Hc;�9���:a�s�z)!�9/�c)�Ar�BGl��,1�
��t�<�JM�����j�4���*�3y�!��� �`H4�>��I��K%��A���Wk|O��j.9���UC����mY-����l����v�}�
7A|b��\ZPI~��u�A���<����X��b��j5�d��P�j��X�����n�aA�mi�[q`��S!���*���s���Lk����v�i�
�	��$�l���V���_�%.(�UJM-4�p���_(UJPP�F�Jf��	J�C��L�e�����	-3EN<@�1��)��y�p����q����4����.itO�.
._!������)d��;(&��E���1:��9��xv�k�3$v�Ft�{�������a�.�g��� ����#&N����6L��
o��7�%!
�w�U
�"5��Y0����&=����Wr��r�K]k�J�(\��7e�e�k�����-���;�J��A�'�G�����pwu-Nt��X���m�r�zX(�X��M�O�`�	W��<��dY��$���z�[����Y���^�E�-�����(����%l�`%�'��
�������Ub��+{P�������"O�-���/nQ�^6	���7�
����7�(��'���_��������C��U0��U6c'��xb�~gN^����#��RI�9/�r��J�����(C����5��LSYb���$�����t�.Z$�����p��h���������?^_���(�Y=4o�i��!��+>SX��P���X�-Zs��<���}���g��y{~���2�[���X������(��v�>f�x����
8L�w�
��I(I�5t�Kg�"L;D�|C/��t'�M��p�op���J�G�,URKa�O<����/�/M5z�z������������=��Xv����j?d'YM�����z���'<D��S��"�������q~�8�K�nq"��Z�|N;�����r[�����:���8����`��~�#7;{�`3fq2���J�|�fG�I���s�����L���
}�% ��e����X=����8��P���|[XH)hI������	�mfY$�:������:;';H��B�t�6C��^��8���7���)W����K�wZ��g�a�����~�!�M5����G�B})�T���p]	k�UQ���Z��n��{S�dh^�2��y�<'k>$L��g�Vg)G��K#s�����o#����c�K��\4_���9D��s�i(\Wx@��c)�����%�^wdJ�-���
t�Q��A���Tf2%E��$�����C/��	�c���	3�*��K�pV��{1|w��'k����6kMI���Lz��V�de��36J��(�O��Hc�1!�N)�tB/,'�,3O��*�^O�8���K=KL����D�����Z�gx '���o��2gg�V��Sri��*���Ux+��7l���;6������^K�Vz �MU��$Jj�|�O�.�E{V����}������Z���4nV|itJ=�]Om��N&`e�g�d��0�WL���<F���R�$�D�t!��4F�,�����dj�9�|�D5L�e|�JC��#@������q2�}�F>X�7UB�L	U���_m�z+��rY��%^���	�Hq���F��#�,�;�@p�.�` o�9�����qd<���MAM��l]�:E��%����5v2�{k�S�O��e��-SN����'�e/�y�Os���4�`�m�|�Vp��IU�8��z��/�S�l;���$��K�Z�\�=�7p���m���X�Q��K�kug
����A�b��<��*}\��$�k�.N��&_�M������;uKO9���%h����_�*W�	���>�8�bbZ�>�M��%�TX[hN��~��3Eu'��H�<�����!&1fF0&�@�{�����j}t������A�����BG�D��s�%��H��v���J?X�e��P����,���T����t�G1�@�=-�Ix�S*�L����]�M�~������(&�45~ZC�2���7��d��`Nz���dr_]1_����v�n�u��}�K�d����p��73�L���L	5��������$�K��K��LNJ���TxqR���^�XM�L��b��rY�����*�2FqKh�r�5*��U*��)'����G��mu"�O0X����Bt��k����C�������w�?���}+X�EJ3Wlj��rtV��k�HY���i�6^+oK���{����f���jzK
�,m}Sj�=
py��VP�d�{������y/����|Yy�\lR����n���p����l��q��a�f(�KzQy�����f�kY�F����e?��sI�Q���VS����b��~
�p����V*�`�)�f��?s����=�9�@��F{5iO{dhJ��Q=R�J���v�k�f�Q�4����3�=�1�!(^Nk���*S�#�&Ac���L�r��VA{g%���0�I��1}Y����U����b�4K1U~mT4���r����P$r�U&�ax&��S
|�G)�NI�!���i%���2��{���������-����P����Y�r�N�*�.�fN���������� ��t�75���|
�� vD��w���to��i�T�����]`v
�>��j�b���[	��c����R}�.�N=?��)����WD���;��)-FjH�h�\e!��=��0��7bC�sT.V ���!�V��y���Z��g�����`5~0����8A����|V��������`�O7%�-fKM���2,����]����o].3��}9?��gvgdz��1?e��|2O�)���_�I9)�&�#s�Q7�(�-�����r+,^�(
gxE��k����#��������
�����v�Q�h3���=�F��n��d��AY�%g���C���{9����_����������d;nM���4��J���E=��o�>s�I��KZtu4��x�R��b�L�j-Rn�T�B� FT�:CE����Yp�.��KNPY|����|�;		�	�1��!5���Kz�l1$!�oA[ R�Z�;C�Jm�l�N��������o�oi�(G4�',��c�C������u��bs�A,f����(���q��OI������F���q���Hh�\��0J��u�F�F��^dx��B����$�y��nf�����|��0��Oy�k!��e�$�fJW�g��tw�&c�����i�y�,����J��N>4��3b��GC��e�`{[��Tw�
e����;"��$�����PF�?�&
5d��I��K!�)SS�����ME_��&"�b�k����`E
zEC��cF������R{��vj��7�� �E���{D#c\>�R�{N���R{d��K!���TO��[�F��
�������0e�������������N��?p�7��{7B_�v��p7]�V�Y����_����a1��MO3���T�cNV�
U<�����j[5j�Xta2���o
7���/ft�dCS��94P���R�e�' �}7#*1��]�V�[4P)��o9����h�|��)KdJ%�l�����S�����,�������fA��E~��k�~mm����(~��NoL��%���A��`=���������m<�7�+Nc�L����M4R��-/g�,��iORV,X���L�u�m�L�m��3$�,6E�}v�a�D%|�S*������xw����R������
6�`��d.��J5�|����8v,���5��g��&o���.d,�P�����{S
I�j�1�����e����-�U��-����v%
$�S�8M7�0IV�`����>S[��;W��8Y�J!����K�vR[�4��%�]�s\��,�l���+�v�����5g����V�y{�����{�*�jK����	�T��!"Y=yI�n$I�6u���x��}(_�N�@��l��8��B����#��o����s�nu��A���
J���	��l~��0����C�z���m������cv5��
��u�a�ak�QP���`�~/��/�Bt^Q:nH������,B����.���(�@O�� �>��k ��*@uS�R|�N����Q:���FY����J��^i$�_c7�q��J��|I�8NA��ZE�����?bj��� �;����)��p���7�TN�[����v"Yf����|�]�5����u�6o'�E8�]C*��-5�/�C�����&����E�qfD����z����G�N�9���j/x�fy/|�H�c�
4N$�(_A&zp�5N�8��/�nR�()[���m�*:-�%�S��_=�V3�i�y��,�u��CG�8��t.'v}(�j�i��}��}r*��,�5�,+�=���]	���&�@�0%I��<9�o��4*���� x�o_S��>�~W�U��a�j$�f��6�0R�J��:y�T	�c�$�v�R���v6%[:d�'���F<l��E�s�6�*�
���Yo�F���k��?+%�
�#sg&qt �Y\��p�} ��]�%ps�5^���2�;&(�x���D�=�Q�sr2��^s�

s��d�/!���V��*�G��]������c�O2FOf�����xR���uL^8^��O4cb�b������z.[�.�k�6�`*����S�7Mv~16�v�
��%H�Y �Vb,'���8������� #�El.FGri�z�{:����h4��g�rw:���N}��������tT+���{%4���R��3\�B�'#;:���]o���0�i���U��
�I�_	���I@�cdM�9���
������A�D���!1�zZMc]��ct�����1:�����1�D�E#e��:5�5�{k��)k-��iM�\a����P�f?(�e�����k��&Q7�����Z\�o6�:{��[{��x�`���-]H	�"��������\�M�f2��>O�#���P(K��l�~����tF}�u���6�]��Z��!U���t��(,�Ch(
P�p�K;������D�O����{��H��z�jxjJ��[��l0B�����8���tNReG���q�,Tj�����:�8��{�t��%�Y�����"�|�Y�`d�%\�����3���%&����5f8\[>���-����l����7�7�,��V�������~o��e��^kT��@�vz�v�Z;����+�p�d8�*������K��q�����t
Q�f6��Z��4B���u�V���pi<���X��}�F�����4b������i�~��7�D�&�:�(�MwI#�t i�;�40����_|���|?�}���)�r�8V�L�N�+ ��=�#�*��Q}������!w$^��JT^�����x}o|1�p��x��V6ap���Wf�/�Rf�_j*���dd�{��ck�3c�"��F��}aR��I��@H�1[���#<+#�R,�<3<*A�sD:�u�UwQ���l�����Szy�?�6�L!����
����6Uj(�D�33�����y���O�^SO�P_�����C}���i���]�[g�C#��%t#.t13WR�����������/q+s_��?C���d;�=�:��8�����8�����D����E�7���q���k�����-���"g��:VJ�R�L�@���p�1�\�c���v!����:�����r@W�OT��h������0lq���$����`Kd������3�����<��V��S�������kG�d�e�&D%��S�t�t7�-���:(�����>�w���QH�B;�������r.U��p������d�4�1m^��������8y-�C��G�eI��o������^��Wz�t,b�4�t��)<�������I^���B������X����%�u�Ud(��������q>��,C���b��3����M��>��l+G�rI��L_(i���$vT������D�G�tA���ec����P.��Y�+/}}��?��,hx��U�""����?�)�D��'L�/N������]k��t���{�������m�
M������ie{�P�e6$�H��7+]k�u��!�X/�<����r@��]�A��s0|�����l������$T�l�y]�3wqd��%
;d����7���4����R�=d��Y�����>��@�a
t"��j
$1���h��W;w����
>��U�W��\����F6�M�i	O(N[��F�7��pN��ho6�3�&E���������@�&�\����z[Z�*jR;T����i�S(�v���">�t�������!82�G���i����3#�kz\t��.5Y��`)\AQ��@��P��mJ�����TN2�(����S��y��g(�����r���l�9f����m��,8��%�� �rJ �e[�����5��:p������<���V�m;]7q�t�tim�(�>Z��u�w�s���%:�����;��'��+���OHL�����	L��L����}�Q[���4���r��#�B�v���N��� W:d��F�OO��wE�.j�h(��>�{�mVy3��[����Z�	/�h'U��IM�Ch&T�����=L:�?��M5IU,~w���e������ilC5^Z3�c�23)��3��>�����*fV��bv$�1
?��
���[����r�"$ kz����BD,��
W
UN"nS)1e��72g���~?���Kj['[vV���M���RA�`+h��}�����M�G��"�J�W9���B�!�7�E��Q������rcO�{>1���0=U2�Cc�)�uj)��������s���R(��!h5{i��cL����S�lY�L��ah,U�Tjsz�
[^�P-j(�&�9.�tej��5���M�>6
<E{��v~�	�_�C�{��I�U�8/��V���&.;zg�62�WZwW4KM���*��^���9C)�7~%��0���7����j�A��U�����^1r)�5�T>����,���bbX]���M��T�h
���Tn!���B�w���ej�]�����������	���\�[D
����p�?�����Fr��#�6�c�K�FDT�n]��(���"�4�V�-"O}IP��fI�Ig89-!@]����9S�	�;S��
�R[1lE�ff��!��Pt~B�t�P�k;B�Y?�|cm
R��/ig���L57i�T��f�;�]���f����Z4����z�����8�����pT�2O���(;�GA��@*8��f63���|&
����WS��F�[�NS���;�Y�?���Z�&#�����: K�M0N~u�������bg(�.z�,��7���{���F>2O@�=#4��(�A)�|��{�pE��2"��Y�q�����P�5}:/�iD	x��B�J�50������p��me���-:����A��OZ�&�
����2n��[���6X��4Z�4"'`_j�7�g��B��d qB��b��{�St���w���s[�����wy��2R	X�K�by7Z���1�>C{!nz����f����Si���N�}���9�����w���L��?X���]m�m�:��5A'Sv�$�L�0$�E�&h����� jL*�O*F����=�Qa4�86��
EZ�GuM��Y�o�!H-\��7����#$��xF^Pkz��!�x�����]1���L���S��%��m0Y���*����������RS��g7+������j�R��.I��z*6����R�c2��q�+�o�s���}](�LV?y����D�|j�PVh�u��PV������82�{���9�&<�
0"q��YK*����M=���L�|wV�T*����,���m
���"t0X���������8	AKMHO;���_����38}J�S�#�)PuD/��*dt/g��	P��7J+��R^V�SB�dH�v"�H�#��i��_�(h*gj��-����a���hl	L�Q���
�E;c��(��
7M�7I�O��^h���.����9�q%�;�r����6�D8���qgT��~�_�c�=8.�p��B��G�>:��l���z|���S7���a����Z��O�`x��d`e`��7\������1������>����t��8:���3���WU���W�����>�����f�h�7��y�s�E=��po��^�,y��M��,�[��j:�v�A�]�o/f�J5�h��G�IO���o���Efb'��zI�V�5^E����^|az+B��_������i�#��	��G7����1A�����?����B�
o?��C���9 ����������M1�������{�/��G]��q����C�;��
H)~�ec2���'�^�7�������)�B:Nz(�vA@�n�
���������0�Iw*�Q����$9
^�kw,����P�G1�qz�������S4�����c���������g����W�
Xw�V��b���2���y
���D�z����$�	5k [�1��a��jl�3P�����V���
g�5 ���c��.�H��s �E���r���U�q���c�y���������K��~�B\��3��>��=��\���m���3gZX��m��3�3�o6�=�w�]��j
z���1%�S9<<,�.X? ��	
@�(����|bmVKlr���	m�5:�`�b�@��o@*���L���/�i=t�)�0���<
�;st�A������9P��~��U]�EB����Y�[U�Wf��#�bL����[�����O�����W�Q�Wb����G�fs>�
��V��h6���b��
�C<��'���f����W�'~vU������;��x�����������3�:�P^�[g�v��[}r���s��%��&������)���~`��P�|8d/0�7:�����g�vD�w'���$�,������d�.�������������g'�����%I���>;sv��}i>�-����0:5!0��������}���
��O�d�a8����S7��:����������}sJx2I(��j�p4��wv��w�p$�����|�!Jlv+@�or5�c�\�}*y&�&R�E��dM����l�}"ieny�Zq�)�+k=��};C<���#��e%���o�:�Y�.Et%o�HlLaZZJ:iJ���"i���X�|���GE�s32�5���K�s
��c_m��5��;2�+]]e�����^{*vc�{]o4�%vc�D�^�!#�He�O������k7��0�AU�f����R:���������W���B�������J |g�;f5��=�#PS�gw���d�!��yX�^�P���QL�=[���N���S������F���<���;q=X���p����{����=���39|�S�s�w<��	�K���]3u��I�5q�t3n(�rCC�i��]��
w�%�b'��.�'��j�(��"��D�K���bL��	�������tS|�4��u6)_MM��T��t,���v����dm���F��� ��g��	^QN�B�]E�>�l���+��%|��Bu	Y/�ly�79�X�����Lw�X��p����K
��W=�_�%�D�������:\D�+��0��Q�(:���DR��n�q���V�������k�	���	>X��#���������iQ����|��~��V]�O�T'����8K�����`3�2���g~O���Qo��f����l�hK��H���5~�������6�A�6rD��}D�B�[�av�4&zA���$��1�-��v�e����)��5j�,�@�����]�v�F>���J��;��~��l����7,�+��
x&Q���x���}�{tq�������	���< P	�G��m�c����<�oy{l]��I��&��@�U%��k��P�����8��X/w����\3w�����������o�"4�+VcZ	(�F^�%Y�8T!i��
[-�k6���p0-sS`7S�tAT�-���g�\�IA��gi���7FWa�J72��7�����/�<��{$��F����n�j(_+�,�R�e���^;�q-������=�[�f����A��A�R�d9���;-�>z�*�B��������R��Z���Ai�C�g�>}/��3;�_��W�t���c*��u�bn�����p�|B�7v�d9�U�)�Z�����������X��F��Blp_�=�AJW�Y��0Q��G�+�P��@4D��|�c� LF���_���M�}8�4���=�����g��A8�F �Lr�v���v:�|p�
#_!���1�e����<�c�nm����8�W�(��L��	M �����{|(���U�lfxI���;�Q����Z}zlI�Y���|	���L�9x �#�i���G�9����'��*���7��|wt��6�����BB��1���$�������y8j@����K������n���q�>6=����v=&������N����w@���FMR������5x��_�!�Dp��o��/�Q�(Zy�t;ng46�����uJn�vS��]7K4~
8���V�w��Z�Y��<�����������|�d�	�W���\&�Pj���a��G9���
����h�a����,����^W��/������I�r*�}���������5��w���)�2�����dB����f���a��g��o�|�1��9��4�X�&���ci#������]�9��N���^{�1,�V�����<�c�{�.������^'�E�7;�$�v��p6���q{4��ew;�����.�Y�:x7�����9�%%�����I�`In��q.�t�(w����{�b��w*�|��'����ao�5�>=S�"��-d�
���������~�B�w��e��<���������^�S���j�@t�r�G��S�*}�:��+���wT�j�;��pEp��"��=��r+>�xy|*[��Bf�/��.��^c��r#��v���ic��*)"Mo�{����HU���3�`9(�pH�ud��_U`{�J��y0�g�����B++����\pm������z�i����T�U'����V����%�����E�����:�X~V+yk���+���#��,�������e��W���AF�J�
`�%/QR�
~E������[���9�&SK?3������z��Q���QM�t	�^mcb\'�`Y{�7�p�.X�TD^(�����M����~Pv
r#E�����c��~Z��X����d�\)��������fMS`�r*���=4�X�=���m��r<��]��0�`���;����V�,s���	mD^}���o@�*�S��0
��nN�f^�4����|@�h�(D2�|��{�Q8��k�y�����)�X�wL�{�o���H�}6���:W��s������>Cg�-�	�'S�#��n'����:��'!��^��3�A�2��F��gwh�PV&��M���N0�vO\�> z
��@�k00B;��(�� ��*�x��7_����������v(AT
l����[��c�`8�s���@��b�1�q��x�;�X��5 K�����t�7������nn�3
�����������&A{E/f��]���
'�����'�p����^
�c��V�6�;�����$ua�$��J�L��ON)��uM���?����)j�����#��d������3j���.^�v�YF
��O��>(�f�PhL���B�����8M=�:���:=q��{G�����v��{�LM�
���vg�@N����
n���������.�y������5�A��0Yye���6�
1���s��7������3�v�����P��$)�c�:��N��l����za:��Ys�4kP$e�>P�D�v��y��W�`_�}"0����B��:9�����������|����/'�g���d��Z61H����D��mv�EY����L���?k��0���+�d�d�@��H
$FSW��HD*f$�
e�!�Rh�A��_���s�+��l����]J����	������wD��D��Z-��0�y
����&�Y|e�6�oIY������l�z��wa����u��l�b������������	��4X��L����<�=�O����I%S����������"�Z{�"��mK�����]G��]u����V��9����~���L��RB���<+����1J\{��!�&Q��`m`|vM���B�}��68v
��y�;@��?���N���|n?::�<��I8p;������l�4���1���{aL�^�������o��L�q|����f������[�"~��U����]!��xV���j�������~�����?���h�$�
��x�0k�`��(��PK�WS��@:K�F!�H�3�ug�c�Sn���[R��V#�Zo���c�=s�;4�)m��z��
6�:�\E����xa�9���1kM�M�J��^0��=~�������8���������r����A��J���������;j6��Y{�����7VpF�G�.������`�3Q|��J[��]@�9�|�<��x��L	�M�
���+��o�������I�MK�@oN��B�J<R���l��18����Fh�}�0Q�>���P����
���j�����t<n6{�Yo�-�f6Tf���}����nb���ki�M�/���oO�����s�	�����7�;S��g?���/�j��e��.X����E$X��K��l���N{\�I6R�*d14^
���/������A�����?���v����O����P;��H���Q���i��e/Da���M���b�l��^�V����"���!A�qE]�����xl�R	���Z8�t�������-��B���_:��h���tI���
~�l�������w�i�(f;�j��e��}I�~��I��X����$����|����wF���z��`0����N(F;�c�$`5����=�`U�R�{��2�/U4��x_6v6:�����������e���
�y��]s�:x7O2���y��53�UQ���8^,�dqp),��ddFo�Gs����L�wk��et��"^�
���E>�����Q�j�^Z`�u���Y����
)�1��unX2[dcC�B3q��H��r�E��[H��
�$@�**Bl���]1H^!H(BP��A�4��p�����_`�����;�q0����Wv76*�f�f���Pn	���`44r��~7+���u������JJ��]��
-�>�������m�}���W��w-��O��3��F�bpu�};��m�&|�><��u���R�:�{��K����f �J����
AVV���>��Bf3&2���h�.�z�
W
��,��m��7lq�+����_5��K��X���r���U�������gc�/��i��m������6r�0���	k�@��j�%�y�6�s�����O����4���c���[6���'�id&�K\�s���+�e��[��@��aG0�������DWZY5�	W/B8�h�x�	&�34C)����%�
%�����CL����DH5c>Y�,���r�z���`�="Q������	ce�.�0M�pa�
���T|M��T���a��JVe���n6|�9g	���i�0�:����	��E&���xk�<��Y��pe�y'�F�bG�i�?
oV�#0��}|&�����T&����/��������1-f���
�&����L�j�[I"�p�)?�x��$Xq&��?!�����"��h�T�oH4�+�l��!n�5��l��N����K��t�	�=�����@���k���a��F�-���,1�o�9Z�w������^��� �sRh��E�M�J\w0S2g��]Nk���20��<���l���Q"�R[H	��W���k����[��y�I�#HE���\L�=>�@N��=@��7_|������w�����p���Q�r�����g�+�=~�$z����t������i��5z�o���+�h=���Q9��J���&G���{>Rj�*y0�gB~��t����WY��}�C�"��it)��*/�6���bF��������l��8���mON/.���8go�����O���%�
��p�]2������������OVBK	�3����P�a�A������I��}��faN�d��{~|������x��)�����!PJQ�����~E�!l@���p��S�b"+��O��{�t)j�����|���zW?"�j],�8���v������c��m`��������j?�~�(��5D�;O��`i��NF_Md�	�����fE�����S�������Q�d
���}�O�w�A��~R[Z�������z��3t�2��!���4�_�fyH
���o���q�e�n*S~�]P�Eqe�M�{B&��&���@�%��`��c(�3���L�4��8�q�F����ZgnMr�[��\lZ��7���Z<����������NB{����
d����9\L.r��Z��YL<	)(S�@���;��������^:���
��)G����������v�p�(���Q������lK���Ay"�I�T2�$�2�m���n��}�_����s��0
�Q�����x�0����������
�MGw1g�������-�&0E��47>���3��[��D��V�1:���Sc5����E�o%�hQ��qI����_Z����������*��j��D�T�;�w�]��@�Q�v.���J���I�&�FB��	6BM'�b�
��;�M3����P(}(�6v��*$���#���xl����i�^������&���]@c��K��%(��j���������(^K�I�u��__(��nB���h]�3���i�>#�z9tv���0�	�s7��y$:�-<��1�pL�3�K�p�@�(�n�#Z��t��AhB���OiLRQ�#��S���5g��~��T&d����f�iW����D\k���U;�T�ke�tb.�t��x�����Mf��B��H'������8�#/pM`�����[8����V��:o��_����x<)�Y1�,�q�gR������4\����|��~�fB]r~o���y�k+_E�X���y*s��5� h(5�N��p3��}Y_���Svu��NU�&Rz����Z��J���]�w���p~���Xl�������%H����w��������DT/������:b��
�e�/�#6��	.m50)�sex4�K�K�SC�����3�X�7�FH�p�/n�x��+�||��_�e�����=�/�	��B!�������l��o�TS�� �~���Zh��_��%5(���x����R�����Dj$.�/������LfyD���`�y�Y ���P\���S�h7��;���-xwj�w�Fa��X1�S�����������U)w,�����_���x"ME��~1-H��KBj}JgH��a����f!�%�@�tN����4�A��X_y@�C�zR����p�vB�d�d�5>��
�"����i,S�`K�Z+��C'�E�k�)�=;�qF��6��{�����b9�������l���N(���B�	�	���wo��c�������G%�
�r&
�������`,��##&L��`�l~����/������������w����`�wn�]�����c���	l,���S��!{�^�������/����2��#�S+��b�p�N������|V��3����Jh
�����G3��T50�=�Y���$B+�,� !|�l �K�*�����.N�`R����o���d��?�)�k��?�.9p����	'7����][�a|�.��`������lZ���+�i�S���$:���C��b3W���:�V3H�,����M�W����������h��[�z�Z�����`��P�NE�!�8]����m��u��O�Un-���]/5��d>o�{]�6�M}�/8h�T�"�������a����`U�������x��=,��>2K9�$�����;��x�k����e@,����sq��D
��PGR�@��/�,�'u��f�,&j�gG��rlu.~�D�g�9��Z�����]�����?�����${%Z+`�Dy���0�N���
��U������j��G[p�)m�,�z<PH4$J��c�*����O+nM����[!���Dt���=r9��A�Q�{TF���z��+�Y���u��<����Ckc�o��x
q���C��no�0���V�U����������.���2���h�7��V����,`�T�VY��S�rf����J�Z�,(�
�t�^��5(�k���O7�
rG�0� �f�ZR�u�b��.�3@X�
`��P~�����y��Pb�B������k��Mw������H5S��TAv���g�i���r�v���o�[<����?�Z��X-��D:�]{G$�������F
W#�W<h�� �D�*��p�z�9qb���K�����(������q�d�3�U����SD�l��[�[__�}�|{t����w!�T���������J�a�)�k�sa�����~����,4�Q��T�4�6a������P��e�NF����-����1=�c��H9��F*?]�Ak0���X�l8�x�L��8kO��_m��G&�<w�'��Ui3��s,
Y��E�7����fS�*�Y�lZd�L��P)��{�a���Y�?��|g_wLwX#���(�Yl�tp2]��?��?�wi��B<Mo�~�9�nF�VxK�j����'������V��u�
'���|J1dH�����=��x��K����st�V�"���d ��=g���t`���0{�6!�l��V,>M��)�����P�vI���������?(��k�x���)�bL��N�l����b�qE-�?:U��:��]C�_��R�0�{�xiZR���t��������.�c�g�L����\t��7��!]��V���+*W��
��m�[`%m�\I��
�R�8�������ZK�4.&����j4!�y��,\�Y�^TO~#���4^�
�y�������}���^5��������^�s����D���q����m6���������f�V�*�pdk?�C�(G��>�[��2���2������@���X�;��������@l+��.�H�B����fs:{���8��6W�H�S f/��N����p.n��`��aW�6q��e��c�o��2yE�b�,'5��`<{�@���_�@n�T�UVY�o���O���(�P�ki���lw
����,r�����x���0���L�8W����7MCwg����:�����Y��^�~xstu��\�b���3�u��f�;���a��b6T�X�����=����K�e�U��~+�V���633'�S��?��@#�o:���X��/b
�����E�;*�'-�x�O��~6�;��ok���&�5s���F�2+���� Sc��������}U�#_v��n�����5���kla�~�6:{�q�D��*8YG��{�.������������������ti?��K���P��,h�S��`.����]�5��!���]w��|@�l�D�a�L���;[�:�<v���?>�pyrv:��<:����x~~|z99?���Nty������E-@����={������!V&kC= ��+��AJF�d�t	��yh�A�y��z����}������Y�UyE,VmO��Dm�oP��a�Z8���K�6�$��J�kBm�����+*�C���������������xcE�[�8e�cW?��e	�;�_w��PW�}1*�a������.�j+N�yF���n�yS8o6}�3���x��r�M�As������}y����3��`�D���l��6����_]�	j��Q�#��m��� *�-!_�B}��,�(Y����d������NhC��
��8������K�&��2�����O"��B���c���@��Z�
5�V��5��T!��1�w�������x��D`K�Ki����W��E�L��������E����g�W���� }�O�~��m�p^�+�/�(����46{���*=~C�k������n7s���6~3��f������������o�����~CL�LI�2���p����X3���1��`��6����;����n))!��8:d��x0bM8�����k�*��yc��m�#+m�ab�D�X���o`���f�����Q�:���H0�?����D�h����a���OE�<���z��F�NK�F�t���{��!��m�X5�o{��Lf���.n��A�`�� B-v$����G8b`\*���\�����"��.���q��%x��4s�;�
z��U��?���-j/��E5�;#�N�� ��.��Op���X�]�b�YE������)8�������,����bA����$y[����������#�u[��� ��7��H�G��W��5^�7�j�V�7XgV��~U�
W�%��o�+K����u&DQ���(}1M�6J��1R�i�D���f���k�R�����r!~o�r��O�md]���C���������!}���Ny�vUc��G���y����)%dQ����vw�lz����wD�m���W��������N��	��Lvk��?��b#z���1�FE�(�I�U^!E���P8��dF�EX�03�Q����
���a���4UkW6 �A����z���P��	U/�pz�kJ>�����
E<��iPb�93H�#H�RD2N
����h�
(*l�=�����{�������H�p���_@����Z��a�P��Rm�i�!��p����/>O�'��<�l�����Iqy��eqqx"=Z%	����h3~�E��P��
����]4�Y:42P����a�:����J�7�?�7R����puG��>Ef#D���IY�jO�8��)�RO0���d!����<�����&��?��J'Qgfn�����n?m�{�t����7M��-|{��R!o���*��=�d���j��fs4�������v�uF�$���hA������b	^�F[Y���.v���?_�����������4!��v$Lhu;�8�����4���
�*���<{�������r���;��	h�X]a��L�kK������y�nw���xR�w�V����*��s5����s�������N���YG�@���E���v��e�d��'��W�e���+�T���	�g����3�nF�	0��c�}�Y,�G� /J���I��[s1��p�e$��8��A����	����by�k;�����Z�w�h0��g�>����y�1v������$>C���O��|�_$�=����]8k��;p�E�"��*�;;�E��w+�����z"���k�~8�$`@�r�(�
(��5����]����5
������/�����;��;��������m����^�o�����=�������N��h���a{�4�������BW]>as��(5��D@���]Pb���duH(�g:������5>y��kz��p��O���?#|������P���(���=(���pz ���fu�}�������o���n�`��JPJ�B�&�`�.�����x��J����`H!<?�.�8�g7X����U� ����1��h��?v���y�(1�����q;.�^��/��=;|PJ�hF.S/m���5�^��
�!S��$�(��-`'N(���7����E�oYK�������*�]L�_:���cw:����oje$�fB|[���E���Z~Kl��;�
s�R��F1�+��W��2B�g"�y��N$3__Q����A!�t�i�;.n#o��������H2
�`\��|P���}�*��
��!f���;AY�E��8�}��>=���-3ROS�����}��B����EQ���OW�[��U�Lh{G,��]���i�����D(��N��w�l�[b��9K�b}�3�m������`���c,�h��j�����.�;���j6��?�z�"�4��M�Z:4�'���o>���
���U����.t�6�v���?D�E/���\^8��M�+!�U)������Q�����<Z,-���4�~UTX������-'���P����C�5,���
$c����Ao�����������h&k�$
���'n��,��-g�8>�wH������v1[*��U��ahB��K'�6R�����U�"��A;��,��nQ�b����#���W���Y�sK�?h�]_p�;�[�=���)�.\�O���?)�8�Z����(<"pf#�A�����o�H��3����b����e�_c3>�(��v����\�Q[���Gb�wkHO�!q�	�R�����y���p&��C{2'��Cg��P�|h{��w�>��f�rY�u�v��l�����}I
�LT��[_`s���	a 2�� �R�o�����tN��G�������-�1x��z	x��y�I�%wC1<l�����t���kB+G�46��8�B�h������3�qgl���C`4���Z���#:�c�5��#�1'Wv��)QgeR�~��'U�	"�0r%mL��e-dZO#�l�;�N?cA�����X�v�EG�dA�����BoE�M�������w�7(iA���
����	������A��t�L��^��bj����V��D�����5U�tGY�/uWg#���n�����:��� �����d����5������;J��rzT�><��+L<������f�a�J���m&��</�Cw�hBw6��lk���M-��Y�=��p����}��!�;H�7wu��6��5�<S�Y�+�'QG���DcK����-�H��h�r�i�m[�	���D!�x{>�!���j�-_��L����4����a����[���RB���	���5�m�e��s�ni�B	�4�V���Vd��o��s.!�'��E���'��H�����B�/	�N)!]�c6�@�_����6�|�V
����b��7�y����C|� � ������nC�-#�;��+DC�5=mJB;�}�Iz�M<j���[p��Z�#m�-#Q�7Yk���:k8_���fdq�p����Y������N|xt�-��������F�������e�uA�v�������B�7$_l���}&�N]LvM�{O�c#1HB��+��%��l���lt�V�"�������C;QO��AJ������0H���c�	]���o���v���ICFY�a��~�l����
�4��j����F��S�O�
�9�������M���6��O�B~y
��P�o3:x\0��::"�F���B���������&}P�Va����&�N����7$�iD�,���uTG��&��hS+.yR_���\E&�@����8�.Q*��#�i��n�	�� +FNdkD��������	���t6�JhDF9�Q
���Q�
a��	�����K
��'p�;~���/ Y�O����f�_/9f��t����-<~��v��3i9q��)�E�A���Q�}��|�V����e�`���\|{�������������9����k���c��%�W��`j;���:����J'�8Eiz6�����I���RI�b��$
m%���X�Vvki���\�b� ��N�~�=�!��`s�;��@�U/������ej���w��/XR��������o
)��R�����l��H�4���>Z�VK�En?�=L���9��������r�O�MGS�PC�|�FO������b��nD!?x�"�O,��&U�����	j��5UT5�`���N|������2��%�H�9��k�a��PR�T=�l�3h�'������,u��D4���k�I���Jj	����Hi��9pV|��m<���������QQ�L'�q)*�����A,*2�8��1��\��g1�����
bm���Z�%.��]c����W1��./X������z�4dU����r
���`�����h�&��L:���!��P?$�y�.���n���(�"�:5��K��O'� �V�&���Q����5���s(,�Q��E�S3��z�F��.P�z�o���?�����|�M�j�4n�2��������aRE� }�����������oh� �H�}�}"�4�"��}�+�u�.�W��7|i��Z���$����L������\�XL��s��]��s����Q������5��	w��qi|������%-��dM��{��~���|[KtA�������k���"w�knA���Tu5�Uh�3xE���+@==.���)FG��iF������+�>	t��)o0uc��`1��\{~S#����`uSGU�{�.Cm�0�>e�9��s%�T���\�
k�
<�1�y�����92��QA9�;���
�\���}���M��0�b~N�HL�����J]���f��H�����)��
f��	�Tw�=*X��7O�O,
�GB�"N OESn7�DR+=b6�/�Y��R�F2�J9V�o�:�D��`,���1�l�%�at�U�P�����?��K�{=S*Yl��<�bR�Fz��<����"�b�[��4Zm��5��en"hQP������'�J��9�] ��o��L��1��;���?6M`2�-������Ni>�k������4B�;@�Y)��S�R����c��+�N���O���:
��K9�O����O�3��_�����"����I�z*���@[����:�-�G�G�~�#�S���Dr�R��	�b�[�L��KN�����7��t;��\��Lr��(g�f�r�OM��q���f&���K^&���I�z���{OZl�&����������)���a��	�K����\{!���S1��b��Ac�p@�.�"N��1�tX{�q(�A�����7�����pv~�y�d9���CU��R�����7r��4H{V}wr~���]��m6���_n��8�av:�"�H��-�+�(�T91�%3�����Ib=P�n6�?{�|&2�*&<G��N�JV@�8�ZWP��6&�=9~���l�c�<����������wG�\8�JC<�QOK_����Bi�!S�#����$��tD�����F����d��!���8�1�}������'.����x�����4��e �P��' �M� 0�ja�eK���_�A���>�q��S]|�x+=�����j���wG�N�8!R�s�J�v���m����7.�r���>@�x�x���g��i��$}AK���52�����,�H���g3���2�H�1`�;�t��>d�}1�����Q8���m��*\1"�Z(0�M\{D!@)�����m�9ql �=ZLK����[�-�z�C�����e����#�M���������8y}�nb
N���-�I�~Epz�E���c��}va��`���z,�
��qo�Z��V���(�c1Iwr���	q��/Lm� S�Q_�|�7B7JvHn��&
01!!L�����$Q����8���W��d�3������O�f�������G�>��0�x��p���DA�v���D���4dt��_������!��v[��Jw��4���[x������nACB���_���p��;X��K�6��Th���qBr��
�}JKn��*��Ukl{��:5���R�*�v7�54b;�U*��W�6��	���?���j5��!�����a�'7��Ru.@*�t��8�6F��B��m4j��c�`Nk�����p��b������Fr�A\*A����VIl��Op��j�(q0���>m����^z�L
�Y�O�`����X��VT1r,�1�Xa����s)m���-��E�0~!�&���������cf��cc*"�)�����vJDQ�r�����<�f���G5��Ml��Z��%�o�����W�3"���n�)EY���%y�_P
��M?xRU
�7Lt�6FU������wu7�>�#����u�$���WG��@PbF�h1��M��	�}(��U.<�g�I&x���$��4�0�%`���A:�
���W���<�14�p)���o�d�6I� dmh����a�i�\��0��c����]1���fZ���"�N�&j��\�������e���"8)B� :�������4�]ze�5v2m�"w
��:*/U�����w������4*�Y `���8�@��������0����������*i�KK��tE��}����o��yo�����2��x�\��|K!�y3�
M`���5r� ��M��~M�(��/��P@����6����X�k<"��*�:���c�.j0v�L6[���"��F���p2b������IS�u�����6"��
��jD�D������Zt�OA�zdy���ez�
�{�������e�=z�J���=�>���.u"+��"c�r�`(P,^NA��������]+�U�+�"p�!��lE����Spm�7��d�M�/X�n�L&���k���&5��=U��������p(|���K������2��9X,��J�yzp����7�K�y�������
�3>l`#�dM&�m
:8��x��R�8&�$���-���a�K�mHk	YlC�IcrQ��s�8f��A@��;�]��2�O +)F��De����`�^�_G�dU���V�:�N���4]����j)@����["�.�=��y�p�������sg�����t�2,�F�'���9�7�+s��O�
#M��kN�r���]�e�������U���x-]o�
�!x���;'\0h���x�Ky��\L���G%���br^������|���M���r�O0�v��"!�@Z4�Xd��Z8bd�F`N��3�5�Zv#�.�ZWo�:i�11���z.���O�b��7Kw��^7��n
Q�q��r���;08����?aS�������.��Aef�w�DR�ws.$��2U�8%{���RYnU!��K��%���;e����(}��p�nNR�F�%��+���.v�W���d#8&)7�k����%JxAO�u��<����\0�CA'}i����n�8El�����w'�/�f�	Qs�i�-r����p*�����T�������j�N#��& ����JH�V��n\�����>8-
��i$�
w���&�`�C��z���[�����tz���v��~�����m���rZ?v�:9����nF�Y����7��}g6���������5�f���U�1
�l��������+��_;���j=���U��<w��F�����w�f�)��|���M���)�"�*B����F(������B��9���n�y�����V�b7�����������:���v�or�cs'�&���+N��R�[������8K���-��=���+�a|��B�5���I�)P/�
_����l�}��5p(V�X�c1@,��)o�'��V�!e�(�d9�V��n�����O,��G�j0����-({>�
��\�������_��`������$�,������E(�0���lA�Z�"������h�[�)2FI�*�+�q���tJ����g�"�9�+�z�+�������J
�4��~�7x����$$�Q�+�$��;�v)����	�o�v6���:��W�I���q���9�7�J&�D������A�q����	�m^=C��,����@��Y�N'Y'\.�DD�\�������-RW��Q����6u<)4�u$�������{�����M7U���
��d]���)��9��{@S��/rF�u>����b:��:F��U���$�VPG]8�:�NW���OC�d������f��|l���HD#�:��:�`h��s�A�y�]X�t��$P	���oEL��D�l7��aN5�TVj����Y��J����!�X%C�*m���UY����K}Q�
�y��Wen���:��6
VK�{j�<X$[4������m�S.
�o0r(�-l����x�:�B�4j��Tf���)%���q��i6�������M�L;dY*S�`z�:Ak�,uB\�
}�1����&r%�e(�
;' z��e_���i��H'��W�7�%������\-&O�3�_����)�U�7*@C���h��|��;��#� ��������n�)���'�b�����wC2�I9_&��(���������dFXt�-�sL}bZ�����8@�	���F����PLt"���&�)�����vM.J������3S�P���p����'g��RM.�k�����I���V���6��f=��AR��}hb��-���*�X���Ku��O��tv����o6�����u��6��Z�Zq*��V��C�J�E<CJ-}\��UY}����9&�����X��E����D�3b��D��)���l�u��<���1�%�J��8N���o�{�D���5����g��{�)�����i�����ig8��������a6���'97^��F}��	)d�[���:���Pq-��"�MdlF������
_kP�nM�JjBJa��
�����u/���p�.����sA�}�����&��	�����.�`���mn<�WsYx�����Dw#
�%��ja
T��d~
6�c���@#q��bDH�<
�Q5���)$�)a_��l���|����J�{�|�3�����$<rD���;G�f�7���[R�Q"�
a6*��1s�k*�)1�|D��h�k�T�[M�;�\2��.�
|��O�Uw�X*�]R����w��}�F�x���w2�`F 2k������'I�����L���{�y������|���/��>I��-T��C<����#���!��
�X;�#B�B�b�^���[�
���9�+u�0:M	���]?��>%��g��YFf�h��c�������`�����������!�V�;������AF��;-{0:Sb�-���w�@���
��������~�]���
�
x��y�w[��.W���]�b�u2�y�[)
��`6�CZ�i0��5b�s'|-��w���'��K�s���(�3eWj�����#�����?���G	��2y!q����-I�l{g}l���a��6(R����3��3d�����������j��D��W�27���i�6����!A���M�u�	:��D�r��e���I&;8�m&����$�x�K���w��i�:A�1z���*�����<K��������=�%�9)y��6����d�BrL�]3MA��*!9	l��2��h��-c%�������n{,vp�����LV;9k7V�R�S�^����j�C~����>��-
m;�xc�aw.������m��mn'h�?<�^����b�����zl���c���N�����LoJ�^Ns��/-��8P����i|/EH,/��R�L�]l��E��:���������2;��H����7�w0
}�GG��>f�������A��Eu8�������;��^�����cB���F]����$��(����������3P^S�p�5E�&<�����x �R���\D�B�������8��f����\�p��

S��,n�+��2�	���VyO��p@k���6
�O�
��j�����#�r�M#^�$me����A�U�+�eG��>�iXP�b�Z��e�Gc��������Veodj�&<���$[���G�V�8���������k��Huf#��^9����S�#Y2G������f��wF�<��>��<��
����qk�O��>'�BzF'2�P
;��� }��%��RC`b����L�Tl�U1�Y7w%�T�=@���MT/ ���nB��@�2O~#�>D���#��G&'~�<	�D���	G�?K���l��������q�E�~��
,������`�F��gm9-PIY��x9BgPZ�]��n���x9�i:���mT���;h��G&�&bw�j�>�Gl��b�Q]��{q�^l�uM}G�/Q�&6_�e* Y^��2��iU���l�����w��NR�*	|1���-�C<���|Ux�!��I'!���&D�:�*nH���/>�����njf�c�2
�ul�	p7��������0Q�#��8gn�����:��/�����"�$'p\��\������L97���2�o6b&���g��
�N�@�B�>����x�X�k>L�/�k�������*�sT4[�o��L}&��Iq ��A������ex�90�3�}�;�G�g��C�;�f/���H��E*2a�������������?���|����)���i?n�����O{2��(�\9j�\�H7���Ot{�A�lz�vk�s��l�@��E	���G��oEgT�����ro�cM��k��
Hh,��#���x#[�f\�h���i�u�sn������s�����j��2���7�l�����T���dy;�'�z2��|d`:�*&k����p�U+#�����(Z�'6��	���w�Ua���UP*�����y���O�q�/�2��
��]��pu���v�y�jZT�	d#��W�}�p~I�S����w�:�0d���$>��F�/7n�{�qW�K��=y��V���e�j�����"�CBY�~���8�����[&���T��~����a����N����{n����I������w�q������Y
�d�I:tb�p��m��Y�����D����/���8�����_U�x���K�@zb��i�y�D5��H8C���..K�SbjH�h0��x�>nQ_U����Ws�Hg|M-�A��L�u��4�3Wk�O��\����Y�uiz+����P��L�"����@���������|���40������ �l��m���x�#�0��������2�� �n%��4��Y�8V;&��1� gT��<� e�s�^l4�Z��C���dnf
���q�8���!u�~��l��a �1s��nU��7��Mg���8������#���5��A�9�hFr��Ad��=td*1Z�*{�B�7�|�N�'&�A,��N�
�m1���r��c��7������
'��b���?UN����m}@RR�A�t�P������{#���@m/%�Z
�#�NG��#��9q�Ig#��Y�]���_G �.�\u�[Rb�K�+j��)E-"��f�r�sQ������p�`4T������q3y�=wP218	$��D���\�Wp�-�>{���(���*��-�$��\�g�h���!�d3���VN
�?��=�����6BTy�d�	
d�4`���#�<���k�%ua��s�hR�b���44F�W!f���w�]o��`w7K�����	P�	�wcC��_���5��;�i�<�����=�Pp+�W�{�)o9�7� r��,����C��X����BG$T����`�UF�1j(�{�. �@F�Mt�Q���*��~�^�Y�q�KJ���x����Hq+�Q��1�� �L��]\<1;�Z`tL������u��Z�)
�q�|��.��8/�+���'br���2^�GfFg(���	��]7�K����� *�gBC_)��s3������@�� G����u��'-��a .�)�B,��@O����8��YC��)iCb��y��,l��.8z��\LJ[+(�e{�:k|� ���dt{�U_��v)i>Tj2��1&>�!F��������n5�0A8J�za}iH����fcIoGV��d~%G����d
�x�*SU@�C|����JdP��<J��l�_����m�6�Y�U�V\5pr���mB��nI�����5�!���.�d�� z����N
*LHp�"�qW��l7��w�����n������|�����������M����H� ���cl)uK�s;���������T��\~7��
v���1�J��\r7��J����1u�����z�h9-T+W��h�*��N��-9�A+Xr1���ZLv� lW�Ow�����������s��w�����)�y���x
f��\�����-g��M����0�E����B��Y���FL���f��$�z��%A,?���d� �=��-�����he�������_�EhnAF@!0�/��9:.�}�Y�r@�	���tYi����!�����X���9#��w�
L���|l6p�����Pc`�I��������sj����Y�p�R���A+��[��5�d-�m����{���G�����:
����@�l7"�{E��x Q/Wnl���Z����Dy��$q~�T�2��y�o���"H��`n^������W�5�s3���_��S�;�����#�F�z�u�N����d���b�b���O��f�"xJ�M�7p#�>���X.5%e7ND�=������.���(�[�RwP:�8����l��5�.�9�K��{�.�px4�A��
��M�(UR���s�"�g�DR��Kc���ia{Zu#U�A*x9RK�H��z�F�z�oXfn��4b��2�����D�����&�ej��x;	��<D�IB~�G�u�����y)��8�B����.���-���8T�G�U���N��'_����W��y��m��s�:�dU�}����.�	?����z�����9��K[��I�M���(��u���QB��#����~-���9
�z��q�Rl����$L���<,�����������$������Y����;�����;MY�H�05��!��<�nO{x�^\��>{���G���b���`*G����S��3�:kp�D6���9����
�
;p��V�)�r����x#�z��K�h����U@z�����(���5+�����q3��(Y�2��':��W��Bp��U���E|+a:��!��pj%7~}��U�SF��e'��6�	BO\���	�����K� �Oc��Fy�� �R�<��8`l U�&�9�����v�$��j����o5�Sw>w�����
X,Q���Z����K����3��QO�}�4d"9��D��vbb2��F��cVjr�T���0���M4�m!_h����[��_��V����H_l��u�����0������JY�a�b2,4D���(J(���]��J������t��f�Y��l���;���n���S�8<�(���\w��*�S*��F��PD��x[�Ga���O
aY��Dc>��Ti� <Z�Tqm��+�B	��Q�(�A�,��T���i-�0C#]&�����P�����zO�����{���~�s��NN��d��B.����nk��v{���n����bl�T)���Q������e��
M��m�:�����p\(�O(:�
W!8���-}H+����8�1���b�4lw`��<�j/����v�~��_��+XG� uQ���u��<Zre����+,�;���(���+m�!�A
��^*�!-?G���*��V���M�?��n��#�X�����1�S�
�3Q��W��B���$�)J��S�jx�6^}�&����t.�%Y�n���������>f�A���5����/���cu�����eq�7h�;�6��G�q jfCe8��&V��S����4>BK
�����'u�>�g�.RH��<p�%k:�r#����F{�=�R��dN��8J��m�'7�`e�2g�fC�1���
�uj}�"F.S����VAr�n�w����}L [�Q�{n����](��:;��="E_��������m���:%���k[��M�E�T���z�q��]�N�_���"�4��8�F#�����7�NdL[�f����<Vb�pk�v�U����������)j�AuvA#��{g&�%o*J:D������)(��������O5���,�8$8��I~_a��W�.�0�B��9l�j��,#
F�����Bl:f�r�M� J��z��&3z���������'7��o�}����iV���5|w�����=HL���Z<�o������mT��p�3:�Y�h�J'���@�o���_������'���L5j���
�������?�nQf����gy�#��hK���X��Mm��6'u�!~-��02���y���F�ny�N�m�96@P+j�'������'L[<��b�>���O���n�=�6�>>�%�<#����<Kf�U�HP2_gCr�-I=�������R�br���h������>�~W�����5{��	����y�+�1�K%|1���X��NBQy-�p�/Y�6��*6�M��v�"���d��L��z��N��I2I��"��k��Z%y��N�j�������V��pV�^��[�����B��jgr��*B�P���#af^��=�^+���ba�[���D2���fp�a�!�x��WI���x�;�<�����!�A��r���i���
_(+�SBf���
Eu<�J3y�G����������W�%Y�fp���������
cY���XV�6��'�x�t�w@����4�N&q'�l��F
��r��Pjy������<O��9^��r�Cs�|Rn���uN���w����:���m���B����:�sO#�qS�����E
>Q����aw&��X�����^jE�w�~���\?LSu�d��(&��r>]e3�I�l��T[q���W�H��1V����Aw.���u���f��+u��^�|'��s��I����H�&�����������Wj�~���l�0�����2�|���?;b�l��+�mX�( �K�$z/�u���B��7�hsb� )����J38���9���y6�O����t�L&��r�]d����d�f7/�a���+Y-=O����bZ���A�D���/��$�A�R�')4�!��\��_|-���m`~�%e�&��BG�U���9�2��`V�W���=���)��w��W��B^v��	��o��i���������BN��3�#�a�B��t�����%0Z5�B���;?�
��:C9,���d*6�=u��t�SB;��O�:��_\}��.�M^c/�#��y��D��G�pB�������3�El����8�AM��!�'�.���,_���������n��b�['�Y�����r��4������m*������Q3�������P��F\�U����+���ffW��"��z��{��P
�)etEx�Ne�H){��Yw��7�*R��j����:~1}���
=�����Z�����;��m3I[c��qv?����}���s�q�Z����R&�p���]�
���bD�:2�n�qd}��qa����o�vU��8��Wu.��^��mr~��)�
6��ib���m4����s\�@���Hv��oa���ha�jae��*b#������{.�'�[��g\��$�2�����'C��%tj��sBqKH?�
��`�b�v*������bl%d�Na!�2��q���U�p����.�}u;��C�P�����u4�����`�{�'�cp�g��w�Pg����=����p�m��v��{5��&�W��	(P�@�
(P�@�
(P�@�
(P�@�
h �M0���
#15Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Ashutosh Bapat (#14)
1 attachment(s)
Re: TupleTableSlot abstraction

PFA patches rebased on ee80124811908ef1d4679296c46e36bd8a32b9de.

On Thu, Aug 9, 2018 at 5:12 PM, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

3. compile with LLVM and fix any compilation and regression errors.

When I compiled server with just 0003 applied with LLVM, the
compilation went well, but there was a server crash. That patch
changes type of tts_nvalid from int32 to AttrNumber.

Done. Fixed the crash in the attached patch set. Thanks Andres for offlist help.

I also tried compiling the whole patch-set with LLVM. I have fixed
compilation errors in llvm_compile_expr().

The compilation errors in slot_compile_deform() requite more work.
That function accesses tuple, slow and offset properties from a
TupleTableSlot. The tuple and offset properties are now moved to
HeapTupleTableSlot so they can't be accessed from a TupleTableSlot
unless it's HeapTupleTableSlot or BufferHeapTupleTableSlot and even
then TupleTableSlot needs to be casted into a HeapTupleTableSlot for
accessing those properties. I do not know yet as to how casting works
in LLVM code. slow property of a TupleTableSlot is now available
through tts_flags. We need to add LLVM code to fetch tts_flags and
perform bit operation on it to get or set slow property. I haven't
found any precedence for LLVM bit operations in postgresql's JIT code.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v7.tar.zipapplication/zip; name=pg_abstract_tts_patches_v7.tar.zipDownload
�{fv[�<ks�F��*����p�D��{��]Y��R�u�J��P�@���uI���c�"�_R�,[ ==3==���Y/�������4Mk+u�dr��~t�L�c|��^~f����p8M��1�
����Wb���h�l������J�6i�\5�z������|�������G�\�Q,��tc��u VB/^���\��� J5�Pi'x25��H
���
d�	�����8Z	o47F��9S�q��7�D�C����7�N�l�
W�G���kaL��?����� �G������.�d4�l���S�c?���9��i����G��/��x�Y6c&��9}4���>������t�G����.��O
�g��S�r�����a��`#�N�mt+�+���W��7\Y�T;�l��@@$,���Cg�(�[�~��]?+?	����R$~�@Y*+�����+a�w����D� �\�K�����O�M+���D�K���1��q��cD����`�i�~�u���W0	�gz%;��s�	��&.#a[��-��6����K�
�g������=���u�����������AB�h���:���6����
^�����jDi�D�&����X����h���6>	E	W:�"�
Y�?,U�:�*�w�AI�B�N=?�����h��|~b&z���Rm%��FU�?��Pm$�VG$�sj[���S	��������u|FK�k���������6u��IQ�71�qH4��O�0r����B�*�������?�u�s��cw�R�:�����L���0/g=k��u�KFqDK���F����o
d��~��Znz�������Z.yJ~�I��+��Q�qe�I�v$���2���Y�\ ����\Y�R�}15a�$2������b2�E��
����{��(�N�-{����s'L�������d�MAr`c�F�
�c������b05�} ;?�_���9�
���/`V��� �@~���wDG���q".A�d�GxQ��@kK��!�I�U���+��*��(�B�R@r�e�iEQ0LQ{G$jB�y(��(�:d�n�D#���������[���v��=z����X���Er���]`��T��(�o��XLT��uz��<� �a�h����S��^[	*�u�XD~L����7o@{;�2�\�]�b�lV�?<��P����>�=���)��
@Q��G��nM�X�!�P��	rc��	�g�)p��BE�?��iT�
By�&�>i�G�;����Lp��=���>@��h?xZ�6�R	�H�5�!�]j��{T���~5�@Y�iE�������q��EQ���i_�H�k(��p`v���&y\/���o�
�n��p���4�;����><U!�9v87�>X��	E�z�-b�n�V�8���~���}�I�# ���[w��^�z�c4����7~��"�f7A�����tq�%+p�H��ODQ^�9b)�G� ����1�19�� ��.�AE�W����5����*1J
�8%�\�;��\p�����b=�}+�� �����Z"�V��v���Nq�D�S�5�0������v������T��k��WO(B��k�[U��&<X_��tX���p�I��9���^�TW��.�/OD�<u5��T�e��=�$ qaTI�8�;&�1x�DqzX������b^!��NnVg�z�B��8wO��9��W��X�������Fr'?�~��zT��da��a#��,��x<3g�6�=O7Z���q�a��9��P��b�W$�����8�������KT�Hk�[��>9]X�i
&��5=�.���a��Oj+�V���F��e��
��F�bY�u-{jj���f����es,�6���1��YJ�2�f��~dXe�*�+�si���}�n���F�WG�V|��V`��ed�a��a���o#4��zp��Z��=�FO�st��
;SuJ��

@!B�^X�fU����&vC�;-� ������1�i{mB�_�&���
yQ����=r��
0�6�kd{�u����r�+�2X���&V����\I�:�"\���;��/��$s *�,7h�^P�p
���],.///��_�{��xy��r�V����-���RR���8��\���U���f���V�!���������e�,�����WG�c]p��i��;�7y#�;eRjX��$���l\h����]�g��oG������qa�|��[R	�0�a�GfA����,�<�"��H1�$R��
L�)��,�xC^����������(8>fSr�KZ����j)��,���o��6���n��_D��=$�;����TY�$�IM��&
�����VR��U���L�6�V�(�z
�a��y��!���kPw��-�U�)���myR�[Y0S���Y���$�O����"1�n����g#	&	����u����C�?�!;�i��8��H�F�L�.*��|�]���"&������-��b����2�k�����N�9���W�b��U���H����(���te%W��]7sN�	n��,Z-�g��vP�
?)]�����ESM�o��L�h�)���O�!��0�<
�x	�}��G�������2����%(A��Xt}����-���_��^�z(~Ut��N�lO���������z��������nV��~�[�Wmu��Z�����C���E=�s��c(���t��o���$Y�}'���V�8b�'�
Q�z�= xID��#�����/�)o�/���&������r�!����g�04�L�WA�<���yRt���D�����;�q�T*]�VB��v��Z��f�&�K�9��-��J��9�����?5����ag��������?������9�_C�zn���;.��YC��R��5��*����iiQ���.����#���J;���3�5mh�l}8j��pP[���+�TY���t���SYh�n-��>'�� z��-@J��0��W�s��fL1��2�B�<�,�4�:Q��m������?FS�VA���j���_@�#XR�S�� p�~B��q�k0����p��o�$�N�b�7���������#�f���6��eS]��_V&�>K�D��y���ep�.�bn���14��p>E�i���v���������x��7t����J����E |�bq�%7��9��������'ODH�_�������ZM��P:��6���#��.��=a��!�6g~��+p+_��-����g��p��<��R5m>6,g2n�bL����w�b#E< ���[�����s����
�',"���g������]�i{b����I%~��0 $?bV^�*��a!��6��:�|�N�Yq.WQ|�2-.n}��QW*��S�|L����bE���h��c|&
���}�F9�E����G�(-���okhT��0\N���_N��6�����`:��X��q�L19�&��_��EU������,Liq�'��s�%��0[b����=��v�y@����Jyc|��)��$�(n��IZr<g���hI?���R�~�\�HQ�*72���E�5�bS�2�l�k���
��i3��E���{�i#��R�=��\Bb�����.�����}��28������XR^B����*��Y���"��H���s��_QN9�LU�R����{���D�\�2������,
��� h6`�;�2��L$�e�>����Y�!MN
�pN��4�e�|���p���O�P���D�xH����Q.�I��[f����h�.={8��e�T�q0s�����Z�$Q�d�C����x�����g��.�}x}��_E�JX*bHy��g�r��u��r�"�fL�J,���zj���.Q���@0��������YB����Hg��'�F��#@��n����r����zC�p����J�%":������ULN������d7�9oP������)��P���j�yhE��$�A���E*��Z����(t]�V����!nQ�������//�/�]�p�%�:#��S~�z~.����{q�C��Lik���4��-
�?~G�,��E1�5�q%����0b���7�����f�^�&Uk�j������F�� ������mM����i�+��(�>(���I�##}���)������k�����d��N��.�7�������X-�4���>?5��&5�G�����d�KwR�z���~�{��ES't*����m���oO�`�v��zG��R����O�Woo��)[��i�z�j��l�:��l�^�L�#!����� ��TB���tG�1����#��L����W����[��&W�&p_�R�����'v�CH����Wh���������B�};54���4��cjSm������e>{����P|=����8y������
��A
@������x����T���_�C��M�5�co<;��1L��mw��WwM�6���3���r��N�w
�����W�sgq�5*�:��<�<"��~�!���Rl&W�W`����2��G1�����R'
aUm�_�*���f:Y���"aY�co52�x���a\IO�:��B��_'�
�ix��H�,�C�J��W2!.#���g�u}����A��!k$�3����:�D~o.�M�:k�=��y�!��D��#��Y�e�	��c~��}Ka"�,�NH)E����JZ+t�	v��M�U��@e�4&0+�����wo���e�������c��(���>B�}B(��v����|^D0#Y���0���)��D�e2�Ki���h�������F9�]�k�f�ra
�G&q,>-N)@�N��,�& �(Z+�Cp�}��{���'�O'���|�D�)~�Y4in_A1�����o�����!�Sy�5�MS����T�d��=����u-���[���6m���o�O
����rh���&�AT�����=}S��U��������bSuh��"����WNW|��<��a�0	Y�2����>���O�;��@��O��'��6��J�7��������hljW�����W�
~O����u.���M�Dc�D-����'mi�u|�8�������32}���iqFM4�������������e����4���_��3��aLK����/��9;���%[[&��u"`���r���}H>V��?rD����vY�d��z�x
�0D����F�g[�
��}�U*��R�u_�T�[����u*Y�<���8l��V�he�����n'4'
5�UN��,x�P�<:B�S�sSE�9�����������Q��zLG�x�U���*h��h8)���&��QA�������T�N������:����
���:J����b��^L
�Z���[����/c�la���VZ0����U���;�)����C��&�Gkh��������SS1Ef*�������<\�$
����7yC��r �r�����u��S�
�
�iZ�W�r�����n
�c~U��d�V�������?}<6�����+}���'��%>����5�;#iOG�ny}n���p���#OJ���sk��I��I���U��l#��)�#72wG��(�L:���#
B6��
�#a��xl�U/H����N��VfU��}/r�T6��FR��#,+���S���~��G�n0\�7?a}�Iv�/���%��H������T�g�Ac,,��O�V���QA��p��f�'w1�c�a2F�s�	����/~z7+�?.�`�(�Sw��<�L��KM�k}ki�s-�h;$4�w)i������S4��������;u���z�fL���fX��:eY�#K������S���y��������m$G�(�|%~E�����}�,��)��c��I����8T�,@�Q���q���f,�����O��
���[y�?���W��p"_3
�D� 5A������@���F�A�2�8�����	�kg1	�gd�r�$���A��y�����_&F��e�:�������
>G#�q�) o@n����h�#����BA~��3�^uZ�������?VM�*ml��[�'��5!2��BaZ7����j�[�����~�3���H�^�=��L�����F<�v�����R2dq���B�d��y��w��^w��r"c�������
h{vd��DQ�K���u<��K\X��}�h4������5`�W��7'z���C
�6]Q�9�C��ZWhp�Z�RdET}�����[��=�k�;�	B�����������7��n���W�9�O�����$S�~�j��u���DS_�O��N���uJ4@=�������������������O���~r���jr�������X���"z�p�!]�&c�e
�	H�%��_4F1�O'�b5f}(x��%�an����>�_��G��.��A|	��c5�<�j�Q��A��������h�z����_�����=������Z���my�n������=���^�=p�?��wu������F/{���n����:�:)4(mm�h�.	������G����I���:�}��,�K�pXC+-�-�������mF��ry���4������+�\�B7�t�K��P�@�*u�oT��{�;�V\a��jl���/5��n6������2y���z���gG�tS��4��n�(x�+
$�3#��O��.O���������������]*g
�z�pBnk�O������n��U4��2X��
]��tK
�-�`��B���N`H�DB	f��b?ADB���n�yS(������b(�G�S�Kvji��j(���FC���'�T��Od�y�x���|1��]���ieB���QoUz*����_��R�LY��OW��*���oe��P~�URo�k�.���~�E��w~�5�#�E�(��(e�(S����l	V�5S�.����P"�:��u~n�KG3Q@
��P��1�{��m'�I��-
��� ��8�QDB�YwHyLHo�e��M9tv�Fe��4fY\���a� �M}!:+��������1����P���e�G@�.�:�_�	�{�nO�����m1.-������V-0ou����s��:cV����[��,�����4$�o��x��&�@)7�h��mA$��we�QM�8����_N�V����)����{]�Y������hD�9\�B���o��w"����'�T��C�F�_EhMo�7Z��$����hUa�=����3t�N�a/c������_RH���|��:�����V������{�s��g�"�!�84���4k�L4�O`��D������
HIj&��v:[�5G
�W������V_���bA�2���jM�g�3L��g���/M���x%�7��09���q��]�D�C7��b��B����A%��\�U��Xv�Y����������.�]N���|{ry|q����"�I�����J�Gm��KB�\L�����[�D=l�C{����kr�f]j���Z?��c^�A�1���KO�G�;(.[]�^���@����j�N��P�pu��	�U�S�����[8e�f�r��Hl��L@$��;���>�E�'����	K�_&�&�N^N�����Q������$��?e\��2Bc8m���fs�j�#/��M�����~�Bp�!|��dP
te1H��r���~7��pW%������KtD���=�~M�+�^Q^���L��*��:1����S!Qc����u'����;2-��B�	.Z#�,�����������K4�~{0�v?����W��-���8	��;;��+B���S�z�i�vG( d�<��Z<������]�B���?����%|}9x����^��{CI?��[������Q�S�7d )��#wh�Mf6��E
X������a���������x�;�����u�vk>�y~k<�N��7sg�Ng4���������w����:u��6��*�r;d$���s~��`x�`�v�@����ox�����Q����w1z���+�����#�!����p`d��4��o�����[� 0Xk�T�/`^��jM�����<{�I������GM���E�}K/�*k������'�1���8���a�a�q��\�u4�����iS�,���Q�!`
��S�Q���,�i���L^�����)B�M�m����R������{�l��ZT��J�w�-t������9v�L@e�(�%Z#(���(����d�k�?�5�*lQ4��2L]j�A5�����`�:�f#�����S��~�fNY�qJ=T�:=N����8����k7���()���U�<��a���r�'k*��4���zF���
(��y�1_�wYo��l0\��+$�d�9��'�d ���@���Z�~XQ������4�9&�Qv8�;�
�%D�|��E�q���A��p�7����e��%-Q�)��>`&�Y��*�;^�9+t�����T�@�	���^���[��VMU� )z�C��[w�����@�%+�+v���D�t1dKGb\��?����e��B�}�c51:d�n~R�(��W��p��`���oI����e��B�c����>����
�`�PT��_��8�����|T�tU
	�zwU�x�8�i.#�Ht�����������]��i"(��
�x�;��������a)��^��@�J���KUY���a�p�xM�:�����d���!��h��10z`b��f��d����U���+�5��W�������e�P�s�7�Wo����2-���Px��E�p�y6q�����I�b&�1�U~�a2[�c��&T�kyoA�����G��}����|6��#m8vJ�����K��F�����2�4����u����Rg���:9qII�Z�
ei�)�H��`�����������w�������)-��+|~)�
n���G���gX���5C��)6�W�~7��k�����g�-�z"H��8���z4C���x�����N����?B���n��E���g>���������7�������f�q<�O��N��z����g��A���@P�#��R���B�V.d~�\�SV�C��!�����P����ez���H�,�N���R��Iv�D���v�(�K��`9�3��pw���*����h����qu���q
u�/��*��X��tNZ\�H�13�m}�s,�"��0|E�>����m;q.lwd�������qZ �TH��4���&�]�pf�
&��s+�#N�������J�q���[���P���6����"7�b�w��G���*!S#�;K���3,�� 8����)�87�'����T��������l�
�5	����ZHX\^��)�����L�����L��������N�?��r�d��}�V>�p�I�J������Y:0�lB�QJr�2f:��nVJ?n���+���B-X�������i6������95`D�p+J��R�4��F��I���%HI����uV���^�����|��,v���p@��hQ(��X�Z���(^��]���%?��<Z���*�.�?����&�e��e�BFI�#�IM�:PNR�����k=;�{N�I"\����=e#��5�� ��BA�N 2�ey%8�aCu�ZH L����`��dM���@5���M.�X���M��
�7�H�������������$��
��d(p"���J�j@����`_��|S��#h!������G!�&m)`�������lU�T�2����l���
{i����Y��5����:���h��{���� u�_��R<D�d5f����0�*�@?a���M�
���12i�>�	3n�<,�E�W�{���2g���l}hD��z4T�"Pu3&����� 9S4��+?1��-�p{4s�^�����?k�����������[�^������ 
��Af�+E9��3�v>'oL�vx��
C"��v�U2��*p o��	��M)#��&Nl�)J��l+�9����(�S������qa
�����@��7��>�,\fE��"I��J��W�ib�k���y�I�0�����3��:������[�=f9�����; G�L|��-d^g��ScT��VM��$8\]NN/'��}D��j�R����[�l�m�{1�����&�CvM/��3>�l�6.F�p�����6�fs����qNR��C�cL�
i�P)�<���&N��������rl!�3;�L�}m���	o?����?�K�������U��A	W�����&V�#�\S��� ���NA�3�z0+��}!F�g���w���B�[����3�Q��p���,
�	\��zm_���>�0��.V�����{L}����W��9���(g��7��[z��
/G�S�[��am��6������7B��c�T���F%�H[������1,j<#�r�w��T��{����c�{<�
�K��tpH�<)�!��-		���l����9��a����m��@I�����?v�����fk�qp���%�����������bwu�������7��|>[�������x������;���Vg��������H���N�
��A�tu�� ��]@��B9r�j
��I����L)�ksFw:����G�8���a8y�.X��*B���@�s�p��_������89����B���C+���W������y�Bd���i(����Og�g�����*��g���_�������S�lo���S��x���6�P�����f��8��i���4Yt����!g��B?Z=�V������KB�K�� rMF'���u�q�
+(P�_�A@�2���x|ut;�A����T��5�x�8�%����.�3�b����dP���n��*�6��M�]>Gk�X�@FsT;�����K8s��Y�"��g_H�b�;\h0>��4���B��|��%�k�1���������f�����F����������������j5dMg:���v�9n�C�uK����
<d��(Q����|��-��)^H�X�������5`w*@���O��&���B���<p*��zh���T�A���sf�$���K����%�����L���(*"�	�]���f�������F�b�*@�,���`l(�������8��|���-�	`@�al��-�R6z��~�b�����jYW�7��������	�m�
��[��fUe��6b�+�ZByU@��Hv���^:��{R���?�W�r7���%Y����+�	ir��+Z���w�F`6~+�	���<������c'Z�kqm����4vp�:�i�\E%.Q��B���lP�i}d�Ikz��!�A�o1���e�����(.����N��(\�CY�w�Z��L	�t���hL��0��Z`�x����HZ�����Q�����^����u�����
� g����Vx�4�����w+����~��Gg8lw~��~���M{��p�����������P�����$���=��w{�����e������H�t��Y�c�7�;����&�-2N� 
3�
�7��k��N�i�n�V�@���H�T�Vk��*V$�^��R��E�Rg��	F���@������(T�e��(55*�CQ�4���4�m�6m��!}���c���u�(,���k�&	E�{�F�7���E�nb����D����=��8�f�������|3M����0����e��'�n�.u��)�JI`������*#���`"RG.O{��*OV&������_�=.�}��n��B����@���������;pc_P��Z<���i�����h��/F�N�q��e���w���zHC	�@�,��e5=dN�
�[	�!RRl���z����2�6�5&�#��'�}D1�w�I��$7��B����+��6
�
��Hs��DIB@�
H\�X��MQ�����:����"���L���QTle��O��W]�UJ�������m������:H
�q�#���@In�P�"���LS6(<�C2d�2?�b��##��C."���uiJ�l��E�����T��{�6�yC��
Jip��L!0_��[q�������"�P�k�����u{��7u�81h	!���y��`8�����[��z*���N��[+����Y�|��X�g�]�2�)���*�BMH��^�$������N�p*�w���A�� ��\EU�s���<��r��q$v�8���L� ��MBBASV���E����e�z&"�N3t��r�d���R\�����A���%0U?`�r^u8�����O59�~�I��9��3H$xh%��e������k'�u�����f�7����`���_v[2hv���?e�4*����d���h(�O>���M�g1��J�v�c
D����~x�����s�^�?�^Wk'���	a��7��s�p&7���#���l��=i���*/SU�i�<G{n4Y�";���mM��7'z���t�zR��T�D�M���������t���?�D�jLH����%����1�`�lU���K����@��8��C/��BG������9�������?� �(��P�����W��j,������}wqr������n�.5_�(Q
�2�8�����'��;Z^��I����n����c��[~�vCNq�������)�v�5��5h��+_GC���*�J���4q,p�;ze����C����l��e9��Q�7�>F0O��l>f���
����K�l%3CW�2K�n
�OY��id��Q�v��"k��"���������
�Sk�yA9��8�����5I�V>�F���J{�'��OY,(��X���=j�����M�K�q�DJ`���)h��?�������g	V��r��N�q
g&���mb�s�$i����z�����"2�u�<���M�n\��]��s�7w&�&�L�EH��8`���3�B����D
1��@)�D����A��3��7(&n���ko@��������� �Dk��-��H;�rO2T�%�;}��<�����y�<�`L;��3v�����+�A0BR���qR�%���`���h�I��&
F�K�7l�}���p"?�g)��N���h�U����h�-�����M�Y!>�)��SkIn�M&��%���c�Kx��t8?aL�HBu��_���Ez	�(��@������(���w�Y�^.�zd�{�j,#�)d�/`������3��WF[n�grK�� $���3���� R
�c������
��T�S�0a]���0$���g����#����)�����
���3S3p�F�1���E����r������R��9��4�e`q�icx}�g'�(��P�Vp�<��g����ip)��*SF�F���<Bq�V����t3��/>����=��PJ�.�$'m���JsO��q>"�@\�F�`0*�p�2<VY�7=���[����3������
������-�a����P����u���
-���a�w!�a;e�K�&-��c�}��~�8Ug?��q�fn;�syGl���2��h�]Cpu��?������?�:�s{PBj�BrY����3�.;0AD7�1ya�PH	r����y��q2����d@���a�-�8�A�i�[�ds����:�����slH�y\���n�	�$�
o��, � )v������90(����8�=R�)N�5������q�v�
�kYp2i�\���KaY��7�f��=��Ge����,j�Y���O��z�u�&:?5V>L��}�+C��-E%�>�7Xx��&�SP�rri{�K�%�*R�V�H����gn#c
)U�L��,���HX��Cf���y�������3�:�L��`<F	?�]xl�_A0�
��2r�*��|G����[� y�0�O��y��zC��KU��Dq�T����abwkV��D|�xC���6�y_@����6����h������Sp�ZH�0�L��A�9���4�p�`�v�Vx�D�=}�8M�
���K��g��w���,���Vh���l�dp#�r�������\
V��"���	�zz�V������?KYDo�L�V�9{3?-U���E����>����q@� X4�(��9y.xb�Jq��7����D�z��1BRem��	���(~����X7d�Op%��U��U�$/��!�c;�Z��F�	%�Y�5������C�@������	T�B��zEyPI>�>-M�C�h�������%�J/�l������QGH��@����!i�F�����wX��Q���4Ly��<�i���0nKz�j���<#5��:oZ��t���+���5,|0�`������Z�9��~0��!<��A�J�Y����D�A�]��M!�&�%�#�}���rO/}�I�%�iXfH����rt��{�m $��_R���A8Z���F����H���
CS(L�YS��w���m���gO�[AOLO"�1x��>F�z�NC�z�LhICX�����b��<����x���$B4B�F)�O���rz��n�W`��h._
�������B�����W^�BZ������1�:����u���=�i���{'�_���<h�a���u�6b���
�x	��A�VO�g@�	�:�f���Q#�K_H�S�}��p4�dY��us�VLtP�>��
+��������L���5�G���!`��aA�9���r��N$�r���Qbr�bVJ<�_����?8��.�������>V8������"�9)���:��,���k���A �d�P��Sp����B'����N&*t�l��(I��}i��T:v��G�����n���y	,��������
-��� !�����N���z)HS>�9�m�P��Ub����<�����G�����<gt�T��''mx]f��L��3�;�;��;o�@"�f\�K)#���W����S������hq��Xz���j����FA�u<�z�+ T}�K���7P�}������G�\:m����X��Z+����)UF�^��P:S\�m	����+1Kiw�V��s|{ry|q���������[�����Aj%�����e����8���Wr�����2�����I�$���H}�m����$��Uet��������/�p7f���l��Zi�!��Rlk"�1d�W���|:��*��!���
L��_F#���!��+Lwb����%�]�]8n9�U����v�E�h��C��H�t�3yR������/� �����
�7��h���{08��@S���Y��p8�^!j�Y[�
8H�C�i{p3�������GU��*wg���41������������<=�:�S�s�����^��D�(���h`&��	��?ri5���x{C�������:��i��SZ��1�3��O
����o���sc�d���p����=�_N��~���	Z@;Gt�������
�BB	iw��5���?���y9���V������?��0���i���G��|8�v�qg6��3o8������m
;���}��`P'�ob�t��������s�T*���9��1����x�i��4���`j��RXURJ����y��e�9]�_�r\	�����-�De�.k�T=q{Vd��(Y����X~=� �����	6
������_���<f��[��d��(�[Y3����!d�#	�))������3�h���(N��O�-�a'���O�����8_C�9���|��$n���>�����Jb�@pN��NP�%�I��%��o(������p�����M��VT��k�*��z�����u�h���)�m�x�x�Fp����[V�:��o�H�\�����0@7q�e8�aV.* ���>���R���L�0�k���tZ���X
0����%bU4Kq.����clX��.��(c/�o��Wx�2k���6��?E�`��#�	�������K����YC'+��q���[�J���lHmo�r%C����6���$A�$��}R����wk����2ES�j*��b.j���|�o�U�V��.����!�r���E#K(YU����)Xq�gw:�����~��?y��kqE�u,��W\
J0LI�ae.TM)1��:�3�#�	J���;�^3g�������(�].q�S��T6U�E9�,�Qi�vk����3y&�~��y|c�%���z���O�n�8�1�*�c����Y��U
5����.��l��YC��ux�&��a��N9F�J
���%��Ap4A<�A��;�.*�JA�{�;4���Z�2�-X��h�=t��
�oJq	��D���Ad8���p�t0�3�\�(��aI��&��0[$D@t�Op��B�\�R�~����������_�/��3��_2�j,/mc6��������aC������~w����j�{��~����/��?�n{��f#�M���l��Z���������b���_*�o�}��-P���Dn>�:W-C�&0Z�]����Y��Bb\��;��c��rH��5�(��J�	Dx9XQ�j:g�������J,_�~���L��Q����-j'�T��K%d�`�QI��J~���*���S���[�[�g�n���x�z%%������[gj�?9�Iq�������p��|,+��B����34*��;��n�mh������>	�UO�if���m���
F��W[-��;�.��ii=�����,.sz#��U�}3w��n*���2����N����e�8���I�*�Se*����zzqpZ�ctm�r��7��B��@��O���~��	Hf���4�����Pt�u�N�(PN]��P�{�o�,�1��>� �����	pz����������S�������T�oe5	Z��pC�����^�3���w�r�1�Sn�p��z�@�(�*���Z<���\�;�#)��z��A����^�?��-�DM����Wn�d����xOu�x����X��� X�q(�CHK&mU��4seqz;j;���iW�����1���T�T���
���b�0j��za�r�o�/+�:��.�@{(A������:�J�*�j�����u'��>(q��c����t�E��W��@'}M�����@���1i�zZZ]3=�j?��_��5{b�be�z�g�� ��]���ReG.Eiob�(%���y�
LQ�Jl��0��^W���5+���C�4	����#�����tJ���"�\��
zS;�����j����*���}ZE��NvJp�����!���+�s�&7�
%��8�����Z*���dX�+���������fhF[���g
��I�$��,2^!#
��tj�3����n�x�^:�&Z]m2����m�r����Et�AB�T�����"��X��/�f%�4���V�C�m^)i�A3�&2�
L���
�l~�u!��c���k�F
��v������&36��]�9��<�pGq]!�C�CF ���������%����P[Z�(W�P2DcL�Oh��8xRY
�(XS�lv �m�$��#"qbQ�K���I�T'�=��!:�����T�-D�q�����<��IV"��,�x�	A"B@\�v�xp�@�]*"E�GqN�sl!62��������X�
z��J�r#�~B����>��E�M`��,��M�O�������W`h���3����l�����<P���0������N����&���5�J�Y�-<!`�e��D�����(F�z�3�������3�t���"L�D6��M!b��vbN��GL�6�>���i���0�O���.���)(��Q�%���/6�R�R.�^sXaR�H��@My�SM@UK��.�d4��.f�PB���Q4�/����n0",�y
��t���U�A���:���r�f��P(Je�����4�#
���F|��{�����@{�gi����nR���j_��a�'��'����F�o�j��w'���+`��B������k[)�RA�	b�t�!�G���.�o�+����g�DU]�riP��	d�a
�\��j��N�5��~Sc)�n�������>Q�Ta�u����d��g`EF��h$����%��H/R�0p+���uP�7M/D�.K1����qoT885��Q%��iL���Z�D�l���Ud���Z�(�;U�HH�y+��	*z�XWLk�������n-����m��E�@qq�X2�`;��j.5:�d��j����NX!��|&=P3e��B�oB�?Pd�*I�����s��ap��*�H��0��:�D\_S�M�:}���"<��$@.pGa�����<7���m;��5F�iV3lQ0}^���t��������S��e��mP,B�L%���&�|�db����8U{��"�qa�-�M"����R��,JJ*1�52�JEhlq��w�����������O�PD���+�\0��0�" ��
c�	��e��$�~/���[�n��u	AW����c�j�����Q�:3C��-Z���K�Q��:^�.8A��x8��@3e;�m>�N$�
&Zr�Ll��QK��G�$�`�;)n���lYG���h�]J�S�Yn���v�-hw�i��/p�
�N�R��[�X�@�Z|��:�0�I�=J6�~�8�92�T��,c�B�
�[&l:(C;��b�3������lm��C�N�t7�����f���2��
���c}	�'�?A)y����,���H�6�Q�bF�����#^R12a��-x�>���-H`
������a� ����"K���J�3M�R�u�^k��\�g��K�q0�.�<
S��P���Z��h�$�VdDH���9'L����'�@&�)1�e|�� j�e+��TpH	�2�
�K�](�-�����6�@���QP�I�p5���y�5���E_'GzM
�$��[* Ko���IF9�1�t&U=�����v��H�&E�4���+��&IT���hF�@_�:��N�M��}��5��P����+�M��l���6�K*�R��Wf��<L�.���~�6RJ}�eH+7nt���
�*��n���t����Yhz���w�d��?U��d]�@`�A~\IJ������_!���O�x���c��uH��f%��N%T�5��y�,m�@���tE7)^�b��]��C��T�L�q�7��,�.`�cv������\����
���(f��.A��~�e��"S�
QD�D����{�	$�3:��"@��
A�(t��|0o^����[�b�P+��` k!���Z�������^�U*J������&�7)h���x�"N��V
S� ~��L�`my3B�eA%����'���x!�R�y�(���DF��h��/e�6�b�7��+�BT��\�F������Gm���J�����1
�)��Pi1r.A�0f��j�� )�(X�P*�*d��;y�+�<t�M���k�K����+v�UA#��ux;�L���b�3�l�N$���,:N�w�t"���R�4i.b]�(n[�������
7��V�J2\-�����f��`���Z�����*I��3p�1O���"kPJ���h���]�i{O�!|������m�-���n����{svJJ��t�����
yl�r�cH����{�D?,^�����`p�{��������qW��8������_�_��Y;h���
�Y������g5G�P�O����s�]�p~����5�N��BX7�!���n����5'�w5������z�I��akD��G]��Z�����P�/8Bqn;�{rq"8p����"+�m%DrII�_/;�?7�$�����l_�]tj�(�=x9)�+�e�2�(y8�Y&�4�I z"!N��nM�����������T�v���������^��|��X{fG����&`�c�!�����z�������%��\�$����U������]`��u�!��F:lriS��� ��/9��x�J��l
yOQ�=z��	77tV�����=L���$��P�_RB�(c	\���D���c��^��n���:F����]�-\`y�/7!b|}G��t��nuR�#
����!��#__�b�1[����#�ke3V������eE�C�����A;����[X+��5�:L*��SyQ�]\��N��{Y��6m��O�,��;�G?���|���/��.�sc�VO8�
�g����_:�K�)������S�2�UtBy�|)��+v�i�0�]q~~I�L\"]�1OcS�,"/�����8���}&b�bCRFw�rGh�H�~��v03y�>�o3/�I;�!��2d�7�0 �ZHZ�HM��d��|��������2��Z�� ��/�v�=a���Y����L��t.C*��$�:-�VTW�NxM����t1�\���V���n%�K������&�\J7�i��4�����!T����J�B��W�3��*���K�7���
b3��,V���w{J*�-�7�Y*�����Q�y��+�$7������@`�Wt���\�����r�!�&,����O���N���-Q���P���E�Z��:��_V�W��h��tJ�(v�]�����@H���d���?
`1L_��y�m#R�����n<l�Em���|
�
��;4���c�0t�|mDG8����g2��4z�;Ba�z
_�N{�B��D�C\�0(�OC��Y��tA��mf��x���|���.]HW4%���E�%�� YZ�7� ���8� ;/ ��*���M3Xj�*����(N����y^��s7BOxW(�Dgp�tK�'2��5�%GS���hNQR��sV���]�*��3:��������=��(�����:0+6�����b
�����:U�D]WXLRy.�}���~G�"�Q��9�Z��{3�p����P���w?W��nx3�(,�����	��8>����Q���
�V��q#�_P=+��!�2�U���,�I"v5���
�
�ID1{!�IRBH�}&bLs�1"t��}���|]+J7�;���6�?���jG�u���Y
.!d������CJ���|��
�v�����	^�WC�WRT�zt5����b���N����x��AJ4#�*w��IQC�u�F��L��D|�)@=��wjO�~B���������n;Uw��[l�Moe����������h($��W5kQ�s�X���JH�7���N�uq��Z��KXxT	����;������;E�?�p{�<���3��H��PLf+X����g��
��i�1����5#�����4|gCR�%
���8��V�a�/�B��[��b6��`)�KF*��P�%��rvq�����[�����������������������l�bj��1��&��B��[�&s����E�o[.I���=�H7�p��k
����|k��=.���	��"��%T3t�r\���j�]��N�H�!C�	������$oj�P�8�x���3LN������
����$���W�x2����#��6�����N/�>���(��G����:(`��HA�~��)�L6&F��,�������JU�'
�y�%��A���'!�����S7�q��} ��08�q�W!�
�Xp:�T�{�n��)v��}V���|�Y��^���3L5'�<<>��W(l}�P���vN���!��M�����4�:���������i�.EL�]?c���?+�C��iA4�\�@�'p}5�iYk���	��;��S/�=����������?��~�|m7�Z!�������JtR=;���`�Mv�z�����.X����GO-"�;�\�e�������������)�=�������l�E)d��S��L������g��h��'�C�=9=Y�Km/�*VN�c����F���<�q����&z�b���u:������a���z��n�2=�k���1�^~����{%I	V��BMP0���9��)�Q��k�EJH������]����n3�����u�Z�������>m��Vv����+�g'g�xs�Z��{B����KsVz~l�����#!�z����b�3g���N���#��&��;
��7���=��X]��z~���b*n�I=?��:6����c������nt���;��-����[�[�k��k!�h���	**3���2H��{����m�y\@}�*���`�H�MZ����#��v�<���F�vg��v=s����Fx��,�_������\����V��.��M|�w+��)�T����K�Aq�-3�K��{�M����P@~��&�W���M�%m��=��$��0"$Y��IvR�3����O�3vJ���TJ(����3?�3�5�g�����^�l�i����1����Y�t��J����_%���v��f�?c�i=��f��B�����9�%ih+��k��t�2s�;�_���EH>���u���8����9@�e3�	��/�w��g��z�;�b�I��;O�'I�"�Li-M�������I�S(z�'��x7~e+�JM���fO4��;���o����*����z1��u/��N^��2��i�V��|����^����g~f'%/���i	����~���LO�q_����w��H:A�/����j��@�l0=��d�;��v���2��P�"��i��:Z���r������w[w���A��3�,�AZI�)���^U#���/�9��9�*u���q�xs�F���8\D5�
a,62i��:�����a^�����X��X�oP��{����v�
k?����l�����=�E���;��`���%^��F����V�+�������6���2)�IF�a���#x���0��sh���k��^A��:XHg\��bV8w��ts�(��v���W�����B������ry�D�T�*j~`<=p��
%����*�$*��u�����1��oxZ�%_��7��k��������=E!9cA�����>��B>����_
b�����k��1T��j�9
�Q
��������5,��|;�^���P����$��i������S������D��I�����pd^����G���k<��AZ����H8��8�����]�E.��s�]R�W1�����@P�-���g�V��0��w[��L�T�-��]BN$�M%+����w)��p�<�|�
lR
�����vw������K�d�����U�F��2�0^�n���f
��2����1RF>U����g86�8���V��4��0��5�l��s�:%z&�D�]���|��;���E�V�����0���^Y�y�����Y������k�2}t���1�y���u�6��� v�~P�	~�R��-:��H�h�V�v$oP���j~�(���k����\�����^4����yD���}Pt���(�L2"B 8��%Gd�1�U��T�QECHf��9FG23`9)e�rzg�!�QEI�������6p�W�;���V�j��ku�a��Ib��/S&���]e�'m64�d�p�v��1���;�>�.���+�B=w*�AP����4�A��x������2&{Q#W�v���vt�8kJ�	Og$�t��q�=�<�J�"��o���N&(x���L�(�9�: {�Bp�*�f������ �S��P�k
���|������F��7�s���;M������>��Y�����)����b�������Y��@������j�Y��bU�V
~����%f�����L���������Xre	(���W\�M�c�poC�����r�p2hP"Q�IT�F�:�x3�S����[�p���Qf�>�(%�����x*��.��LJ��b�����GO����i)9=��aV���z���yX�lOH��^������G����B}y��$/�YPIq�.�v����)@n@��lL�M�a������s\�4�b���w�i���QBf�����pws�7��HG�?�ln�V;Z��J���4Y,,9����fM�i%G��T��J����l��0�v8�j���n�����.(#�,��p��!<�����5���f�
:D/
�Q�)�����!��M�� ��V�V���4�*Nn92h��9�Me�`����7V��������\���K0zP"	J��'W\Y�S��$4=7�5,?���O<o����uSQ�=lq8��H>d��q)��m�����>�H�)�L�Tp��`�m<�^����h����\����&`�&Hp��T�9e0�O#�&�U���_��{�8;�r��Z�
�r����	oy�u*���b����0���z/���{I�
��^��2`B�a�LYdD3�)I����R�D�vS��%o�+sS��V�._�6�&�G��Ta�.�>V��7��[���Y_��a�F�8�b�D)��c�����#,XIK������d���5���w�w	������&���F����+w��S��F[
�v2�G���	Y2t�`����cF)���a$8�*�G�,���2Me���_��T��d<�J`l%5���[����o��X��]���+�g����:�<�S�_A7�#cQ�W?U~�����WS��V������*U(���sh������(Q�iQ���}���|��O06kR*70����r�S�:H�zd\5DJ �qY�a�R��^����g��(�|u����
��3$;��l#�er}�|��I=Q�o�!��I�&	9L]'G'�U����w�i-G�6Lm6kH\C�
���j��4�Na4��3e���{x?������DHfU��?_���#_�������{29:�ku
WP��P����9��3T<30eL���9�*d
��B�������!$T&.d%���|�R�k
�.�\��?[6yiK������y��W���RCf����(Tp�7������	u�HdC0�kTt9�:__`$CiR�2;�
p��L8���.�j�3�����N}�|��
�ng�_,��h���:�n��"'���8��C��8���zM���^w�p���/0�W�I�hH�%�J����n�N�������1lu�x�M���d�;<���G�����0��tx��5��X��$��By8�S����������������*t����S��&�@�����n6g�Q�?�
(m ���v38�z�q���sgD�`�i�i�^��������>\@d������m$���A�%�H<���������A���w�'���})+������J�\o��$�s_����
�hR%�5����X2���%�D�T������F���X'�{zuuy���k�E�U�H�_�`t F������L>�e����^�]��6�m2�;��`���iz�������l��-�����x�$9�[%wZ�1P2~����	���E����W�������DW���
C�	���o5������8��B������'���<3H��i��������|�PF:w.S��%���#����t4��6X~���w�N.�g5�R�}��|�\��2M�$���l���I��?�P�H��9 ''r�:n��V�M�+,.�D;��1�Ud���������4��119$��w�����&w)�\��	����F*fD{�����9*�7a.PA9�hC�����A�sP�B������e�"�q����v=M���;�QWi,�%�Jx�p�#���}�~��v[]X�n�=�B�2���D�!�}�z�T����'9G*6�s�7����l������J������F@Zc����HV���l<���(FM@�5C��QX�2�H`H�o���;,�Z�3��!-���z1�����������7My:zO�\UH�s�U4��0�l"J���4`"����|4n6G�Q���QD
%
G����HFes���4g
W������(��/���a1���C��vuI;��R��to��ym����|dp��ai�i���2(�l�D9�
;�~��������S�(-(9ti�C#p��n��I�*�L���HA��~�f����������������pe�Q�@,(��Si�q���������{�*� �7!�_�l���Y��J�)�k��N6�H=���
���\4x�����Ag�l��^o>��a���%lA:��v�B���vO=��s�#�Q"��$��s��U�57���UhP�@��>�Z�w���r�����>���/_�����tc���9����.�vX�]���x������)���@�F�li��\��he�P����wo��F5+����_|��c"��l��OQ7��r�\��������p�E}����s�e�
���d�Pi�q}��fA����JZ�;���������!�v���_���X_���g<h�B
����1��(0������mE(aS8���c�z�����wW'�����M��e�@ep�X�!��Y,K�`���F��q>��z�Q��a�1G�
��?B�
}���3Sw��F	��������s����(���F�I*��4}���@A�Y��X�����l$+����1�o��Z-��
�X������>�?������9�s<��O�X��W�=pG-��l���?n�Yo� r]7�-=�PI�@)�����U?������5�dnp�]���)���XL t��R� �����o`V+d�-���P"^U�L��`�gB��+\W����/���
�!i��0,+���b��G����9������������GW����\!��	�������lu��0�R�];94���biu3V�n��5�:c ��H�C�����XK$�n�����s���PRU~�$%(�]�
^@��2�klw.���w�be�����K����@P�zt�m��G��PVJ��o�����Fr����DY��W�I�g'K�Q�PE�-�w����_�������z{�����Cti���@4*V�V-���ke�A��9�&T&@��O�������lX��i9���M�����!~H�G��{������.I8����:	:d!��{��>���1b�����UxK^<�E%�T(F���=��]} )
��B�����s���2�+t���N�v
c�J;`y�a�x1U��� �dKi�hwG���l�|���Zrs`�|JkJ��CQ�?�O��D������\��j�<���s\�p]q���2�`�d�
V�fS����LN��
��,�G�����%O4k}!o�������.V�/>$��Md���d��h�b�W��/�
���kf4Qd2���� ������a�&��0����>��?�OGW>p"Bu��:}���{���C����g�-0�H��������8>g���H��t�����.Y#X��@5���1�9z��9>���CRj�!Wk������(F4�R��E0��.���a{��-��s�p��������aR�2�`��v7�,t��
��o_w�h�>�3��m�����g���ce\����{ ��n�i��D��e �II9���pd�X	�MGu�u���ut�_����B����b���R�V�RN���#�6�l 
����������2W<D�P�Px��IE�O��%��'�'J��Tb=��l����@�M"�!�Ab��s4cm0�L�6t�h���R�Sv�|���G�v�*����|�8cO	���g������?��8�������x��.��I��~q�|���e�����o��<L��a^�	}UZm$b�|���"�����-�R.3.�aN]�S5Q��=����d��������Y���n�C�j� �`��r-�����f
�x�/��O��,����PNn���c%�|�������Zg7Wa���B��d�#%>;8H\����N�o8�^��l�!�����3�v?��<�3��������E���+�]�9s ��:�Qj'�/���TK�~��y���E|c���\]�~���|����������|S�Q���}�8�4�Ps6.�wtWi<�&a����S���bg:|��qS��,C-�T9Ef�Y�9�0��)����7�*�k:XBB�
2�����f����:`o��n$��fM�0�y�5]K����0���|0kKF�?L�+��`?^^�m�J�����|n�����Kf�9"A���S�"J���Y$sa�WD��Z�r+�F���ZTk=�Y7��eN�-�I�aU�n��\Br��+q�<lZ��-m��<2���r���[N�i�����Ow�U�/$��V��|����V���mt�
�Cf�h�$�<u$;����jr������j�k�{�����������h�������Pv�GP��/�9X�n|�3s�~g��=�l�����E�����>Jr�����%���&\��Q$��n�����$���b��H���:�{���g��M)���>1	���
��d�5�b�L!/X���a^�U(�j���m���O:-�H��-���7��Y�-�e[�2�$�T
)S2����>���m�'�)���n��<��+xx�xh����K�����wk?�4������
MwB[
V�B���6���q��Wq�t��U�
,����/>h�rd��S�uZ��	��'������>�����s��;B�]^�\\M��=9����7�7�mla'����E��R�r]�h`���s��B�vg�w�l���e����5+��J�4���cN��e��i�����o��Q9x�-[�7�Y�����������wG�O�N�?]\�_L.��\R�!O�2��>��B���'����m!����Z ����B����z��?�����LVte�7�����)�'�
vT&�hZ��X�L1�#��Q"fr�r	b����_q�}�o��P�����$@�`��:\��`\���G�E.�������)�*l�G����B5�\*,M(��!�%�la��9���IL�n����u�s�Kj!}p:���6������s2��(8����S ~*�/��|.����;wS�'B����k����+�����B2b �������2���7^�`n���6K�@�k�K=�FT�����K�B�?����]����
�d������E�t��e������|��AI���vMQ�����!�'�H�''U�`�e;Y������lZ�v�5��������R��������@�j�v��),��rTp�����'\�	�l������)4�������Xp�Hd07��_E>����5�N�$X���ns u%��L���'2SXL����W��E�a���%��`�cz�������+� Er�^
CO��J��#O�k�vq4�����������'���#}\%���T+����Bq8�����O�O�Aq
�/Gqi��?��A{ �uFDq�3�rW��h�4���&�r��2��[
���Z9��M�[�%6�h%�{^�o����t�i������@40Zr�"NRD�'���5���n������d�
Y�8+���;��+�bf+��������;�q�{a��4����IN����aF:�X��
��xC��m<%�|���j�i���� 3rf��r�W�\���#P�
*�
\��h��8�����Z\=��'��K����%i�4+9GF+)��;Ct�����N{%i�4/MGVKL��B<��4��9�e���P�9�}���y�.��O���sk4�k�"��������g�}q�'�E�ARS�:\�]O�h+5���a�t��T���*`�r��-�@A�'<j!S�a��7��A�?��Dm��( 8nE9=(����d+�tWD�2|gq���,�#!��f����>��'h����z���+��#��D6�G=%���cC��[����	8����%���"]�	����������dEG*�8�B���/Bv��[	d��c���XD��r{�CZ�mJ�c.��w������w��%i0
��v�n
16�?1�Z�1���������J)������j,�����`lN0J�	3���8������mP~���\�e�j�5��;����KU6e,����p��*8�L���>��m���[��B��j����S�P�mg=BI�"���������tsC=90�}@N�mQ�����w�<�{�
y��������?�BL�[���:�����>=,��b���gl������������
s���FL2���Pl��6�{������
���=��q�d�~lop��c�cT����O�o;��RH����e��`�V��=)����{�����^�/^�~�R�����?��U���^���s7�2���fq'6V�kM�b�vM��~%�y�Il9u.`�7�
��s�Z��8@6�����#�tG�|��H���n��h���r�"�|a�h&s5�����6����=�s�be*K��<���z�]BL�j��sb��j"�����ma�
���9o0�����*i�����"����e�����_%��08Q�2!����emO1�F�0��=,���@������{�n��?I��u]�P������hp��v�p<�w��V���<G��^�����U���XSl7�!�n/1��c,���u�[�2�a@�k�5B��Mu�Cy61��^q�v����&�wb�)����j�6��h�~���R�%�j�/1p��Mg�o>�T�(Ya
(�:�#"�T����D^;k�o���a�0D�i1e�	v,u�WL�bJ0�(b���X���K[X��v������T�I+�(e��z�FdGgH�Q�}7�c�}��kH��5�������P��
��a�G��:�$mX�����p ���!�$Z����d�<B�M��=�
B��-s?��VVC>�:��;���������n���Upb����!��!|PfG�$n�^�`9(���,v�nvs�����O�� ���]H�����@����JW���'-�K4�?����
T���)����2� ��1��5�V��YE
��Yu
�czeb���U�pQ����n�f���_!�����d�;��;���c��/���6��{#��}��8�x\��2!?�����N�����
H��9B������[.���y�f��GolP��S���C
d4���U8d�l8����+����	��-?2��N�.o��*��*���4U�fy��H�T>�	�x�!��bg�?���B��8)�&�Pr�/d�Jl����e
��x=�U�qY������3��(h��dt���<Hy0�7��uA�.r��z!�(#��J�(�Z��_�\�/N������D|AjmI��!F'�ZY�`/2<H���\�,g��}��������/-�@"=�|�z�3$i'��z�����4B��n,6�����4t��rZ������O���a��~�E����D<1����6'����K����k:��[�<�15i'�c�v��>J>�l���W����2RJ�
#���6��O�6g�?�|~��
��� dE��UkB1-p%������ �������:�3x����g`@GY� ��]��������%��l� �. q�p��i�v+6H�+�2���R}J�����/�(���B\&�_VXp�Vw����r�������T(���c��6�;b9��N���?�:Q�}���{���TS|�{.�H7i�+:����9��}�?�������dT��c��ekqj*�~w[����<���uC�Z0R�p�e0��HM����������T�N���3����=}��0�=�s9�����|C6�UA���|����7*��B 
s��J�@���}����Ig=��tT/�����b�������N�+x��=B
��I��e�W�{G�Q�J�)1��W����G��ZP�l���;ef"�y4���js��,9a���aO3�}�����6��5>��M����8?�_�
~"��1*�Y`��oaQ���L8X��9LX�_����=���G-��f&���I)7��E����I�Q^c^��;���m{9�{���*���j��>����y��x������,J��]�rO�wD��bk5�Vm\3M
e'�y�lP^}�������������o�"!�,R��'g:��=g�)�$i��q���~m�}Kw�YUVb#�fw�PCN��jfs������1V���@v6'�h�3A�E�i���QR#5$��{�k���G�r�E�G���)�]q�#�#�
��[�`v�DR�	�
A�F�J�,
+L=��s|~���������szvzuz����E�Z���N�N.q�
�iu8��:
����F�=��z�[Uk���GHm8��g�R^CW��I�<���pg�pE���GpgJ�(��D�l{z�H�b]	�$T��>�eSA@5��xc<���?�b+���B�%D�|������!�C�|$�VO�:'&��Q��>z��Q�73�����$tQ>��jtB�um���0OLJ��x&�d��'�HW�mCW���0�uP���<`�q}��xD����/�	�C������r�^���X���>�L2s���s��DQ	���E�3�SLQL��M���W*�B��F�vC>��^��N��0��}�����n����������g�b%����s��D� Bx��g�v�m�C -������{�Qw��u�h�=�-���XX��V9�_�O�@��#^gH�rja�
�����^������_������/B�b�����N<B��@;Xs_Cwh���+���I�P�ok����Hj��-���q���jT��&q|�sJ�����p���{������O�����\���=d�s�3�����[�[��5:n�%��S:(	e@�U�XV=H�l���J<=<D����o����[$�?7�%5~�@X�A�*�Z�Oq�#��cl'3����'�|.@/��{�k{���y���0���D�XyM~:�Ej�RR�z�t-���Nd��*D(�e����	1@-�@����r!���h����|�@G�zH,���l�]5DL9�c����0q�iV���f�lG���p�s&���J�;�
�R�	���|u�������&K��zR����?��]����6�8����S��X
ADvy�_�bgeDX�����N���M8�&�gc�~������!q�@eX�R�B�7���R�%m6od�Y�$9���Cf�������6S�D�B�q'M!������/D�[_������$@����;�tQP�
��:;���B�h���f��\�'H��H�'=��xu�k�3$�V�G���������]D�V
R�n��{?�XH],���0��*�m:���7�b��E��Y0���Lzn	2�Mo����.��������p������a�I>��6SFl���`iuF'�O��+oo6���F��3���]�p�FX�����C���`�w�%x|��BI�${�ZC����Y���^:E �[�I�7-�QR6GT[�f��J�O���bs��{"�W�I��A�[��;����t��m�X�~q�����I���IU1���#s`��q�b���VO��U2n��q�,������s�R5�I�cln2�JB�ym�3wT��w5<E��$y���DfZ��?���a�4������_h���3;s�����
0����#��g�x{����v�ry�Iyy�X���2&�l�J���jd����	\�^~{����w'��+C�E�yr��N>|�����1	AeN�Z��71��_�`���FG�pZMBF���.���0M�^��X����x6���b��&�
��
I�$+���QC3���_&�4��)����n&e<Q����(k�t@c�������d)=����q�����eN%8��8��|	<�����l�F�B!��Z�}.:�"���*[���������8�4��d� }I����I�N&�lN���=`t��o���>)7r�x\��X�<R�^b��tW��fA�$����A+,.�v2�p���/1�HM^�%
O�o3�B�5`v},����� �Q ���������q*�+�)�)�)O����K�3-���3��R��WY?�m��S��l�t���P^����P+G�CV�����s�����=W��
���[W�1/��d��r��Bw�bu�p$��X��/�hpq"%�8�\b��u�/	�s��|�6�� �B����p_��B7%�V�����KN�����R�so�A�4��~�=)�dr��I.������^|$H����LV)y]:���L�����u�O�A���k�MI���L:�+G�2[����e���t�-����bg�2��cj��'�s�(��I�������&���l	��\�:X��3T����������X���5��\���HiPj�
2�-�}����ip��5���l��T5�gQR2=`E?� e�Y��R���SvzuBk�I�,����x,�����M�,�� ���U�a�3�����y��rzG����h�B�i������dJ�5�|HC�b��/����NT~I�6��v��dXU-�j���T539T	/V~�����*�c�*G�xy�c&�"���5o��H�B��K�(�08{��:w=8~��t�� ����l��Rr�]K��3��kL3�gkI��g��2�u��)����~�����<���5U�B�;B0GX+�\}m���=���.Z��w*�m�U���bviT�}����6������Bt]C�;k0��wu�+�<I�]�Piu�A���U��8,�t��(�*t�N��#=E{��K����_�*W�	���3|���bYZ�=�C��%ZT�[hN�?~���Du'v�H�<���R��3#U ��3I�}I�Z���.o����	���)x�DT`y90���b)��������xU�b����B��k��2S��v�g�U1+���{Z������B�������d�B��# |/�Q��il����e��co.�%�a����(��Q����"�2F%9���J�0�t��=��X����������of�Y����bR)K����$�K����MNJ���Txq��=�^�HM�L��b
��rI���`�
{���m�����g���~��v�dR�-N��	&���v��|��`C�5<8t>���~8z?����w�i�J�a���*�xP��Z��@=�Z�N#x��--��O���]��E>���-5����M��4���[1��ph�3vZV���r ���f������#�g��K�I�������Ph�0�����_B��<��$�3��;�~d������I���-I�b��~
�p�x��*�`��f7�?s����=��] U�E����'=2$����)Y�
O�\�l��5L��S�4����3�=���/'���s����H��q��j&A9�b��}���Yv�GX����X�,�^y�*�`Sz��h�%��.?�4*���_+��!'�#r�T&�ax.��S
t�G)�NI�!���i%�JP�������SHz�]���}�k����v��Y9��r�d7I3����~r�E�H
�N���@��*�^��5����&�\�w�e���h@�p�K�M!�'�*�3���J)x9F��[���7%��W:T��>���E,��W����;��)mF�rh�\e#A�=��0��7" �9jk��:f�����U��/~?%���L�1��=���F���'�Qw�����"���6"?���M�)S��RigK��r�����S��.�Yd���d��32�K����`i>����M���eRNr��	��\k��=�d�D�y<����E�,@/��	��V?b��m����a�����c2GC��b��T���-�����>�%����!����������/a��?�1��l��ItH#N��h�qP�y����1g�����EWG�>�f,!l/�Q���"��H�(�bH5��3D; ,k���"�^����7� n���l'�QScJ]Bj\Q����bJ�����
yH�������	�N�������2����
�Q�hfOX4�j�c���IM��I����X�p U�a4�����%����_N���6"6�a�:%&B3����Q2��;��6�6�D�"����jl��)��4�0��u/5������}���X)��/k&�0i�tU��9[~��+���c���I��Gf�AxV�������WW-������m�O��1�!�V��>D���@Ir�^z��@�����D!�,B�<�0�R��	�t�e��� �����L�����o:!�W�"��3��cF������R0��-�vj��7�� �E��[��f�i��H��%m2wK�����B(	5�����t�����+���n�K��]�L-Nlwd��vJ����#�F������������/�0,���g|�ZoO��Y�nZ��$����cNW�
u�����n��=*��5�a�SH��2���:�����+s
-���d|Y�	(�>'73,qnQ�q���hfB��o|�������7�LY"S:A���SJ��U�zL�.�g���x�&=�5	��,�3'�F�c�-~B���v�`�V/���
�������/i�f���������/�+e��F�u��,�%76�E��K>���X������V��1#A�����������P	���N�r�x=$����l����j:G�2������_&�p^������������$K;��)�g��W�6�H����O!3���'+��|6%R��!	�C�z94J�x.��Kw�wt|4�]���)�<M��0I)��b����c&X��;W�V-��J%��7�r�$X�h<�J��\��4�I�n��?%w��).KV{������q�m|������Kv1w[RM��6� SmK�d��q8e��$�i��9bD�����r	��������b*{4~��D|�_����v�����VP4O(fd��������g����p���h�����]���R[p�AD08����
	[g}����E0��j!X�5U�a@��>f�`Zw������F�FR�DD����^�v�V������t�'H��f�dO�d��B������H.�N���)��r
���q��:e��`���K�~���z��w�����Sl	<p���7��4�-���&�t,Y������Lk6�����m�N�����@%������B�FF��u���/�0��B�n��p�������U��������������Y���'�B�� �<8�'G�>�W�0itT���Pk|���AKc��+w�G���L�y^s�j;� ��0P~��k�jb�����F��'����3� ��`����g����_N���P�47Y
�)I�����?�.0��$+���9 �S��>�~W�U��a�j$�f��6�0R%B}�<t�z��Wm;��|sU;��-�d�k�V#�Z�&�5K�P�|�����"P����]�����b����
�I��:��7��{�`}�
AI��~�7���L���_��'�!���(���6�S��y����T�����x�|���
�����>��=���1.'C�'Z����;)��:��/�jMH�'Z1�R�b�N_E���V�K��(���G�������/��&�NV���;$���A���_�b��z�<|10�/bs1:�Kc���H��wuEln�)*m���F<����!j/1=����Ms�JH���R��3\���OFvt6qY��
��ab���u��
�I�_	���5@	�1����nQ���D8j���xf���!1�zZLcY��st�����9:��#`���b�H����N����`)?�b��=-��k��t�������l6?�p����FbuxU����&\gO?qk��/*���lrK*��0��q�3�W��r�i�l�����it�^�q�eq������;}����/�nY��N}�����yH����{��j4�!$��
	�T�p��;����(�D�O�*��{��H��F�bx*%��P2s6!x
cf�{�MhF�$��#�s��{"�
tr��d)3�K�A�N�^��B=M[l��gY�f�E�ey�^����&0,���}��1����	�n��&de�_O�~���q����l�
���A����F<Y6?��F�0�n�Wo��������
wJ���r}�}+��������?I��Ja���U�N#�}��@!P��4�x,����C�F����w1wS��b��4@>J��w�msI4z�����G:�4�H~`r��?�{wr��>��0�O9��A��b�������#�
����>�K�wb���w$^��HT������xo|����y��u��0��[�+�c�7L)���u�zj12�������L�3���\���}��vp&��#ex���bL����2l�!�����7�����1G�E7]u�=��f���}������#�7``
�O���*����j��T��:3^���/����O�)��7�����a���1��5�i�����3��������g�X�+�t!����������/q+�P�����#�d;�#���K�����TgSr��	Qi�qH���7�t���i�C!���z�mI@G���n����$���4�3K5���SPc�@-W�Xl���B0>{k��s%�����3�!��sER�+��[<<�0	"��)D#�Y��9�&0����H�X0Qk_�������������D��)�p�)�����w��8�Jk$�c�����i~���Nu�h7�l�\KRc�B������b���1i^��������<=�b��@�����q
[��_�����:�������.X���
��7�����b#�xQ�3�a�>bLJ���}-�������"{B��-��)��#�2���.�\@23;�	�t=����rdn�������via�Jb��7���$�}@��l'��)�*�C�X�����]y��K���}����YU."2�+��3�������������2�����- ��.�h�^f����4��fCfPX��y���L1OB@����7�M��Gw|r��r[�3�-^,'�����D0�9�'�Q�P/d��
��B}I�b�����f�.bd��(K*;d���[*mA�AJ����({8�t/��p/����}��C�e4��bVk��9;�vq�s7�����!�J{������0��n
OK�xBp��'7���~�e8�_�������Fl�Pi��s�����tr���p���������'���fn	X�����`�Cofd�	���B_b�Jw���	?��CL�� H�K�����y�2�]J�d9?��pE�^c�b�lS��>��`�r�9�D�E>����[N4C������]`�N1{xd��n��e�(�����QN	��lK��
[����]�U��fWjX���t����M���!�P����-#8������/������Afz�=�~���	�q���Q6��j����b��s�Vly���u(������P�]NDUV&�O��@Wz�*�*�M>�$#�Q�w��'C���A�s�d�f�7�!��
!��H5�w[�0�����I��b\���	�-�0e���I'�G
���&)�����$�������F
xi���E��$J�$�}3��
fhC0;���_���N��-�e���c>a!2kz����AD,�Z���*'����0B��+eJ����I�%���-;+Dz�&JH� !��t�{"���)�(�W$�D�p�3��a^:]h3�F��E2����[����K��
�S1\0t8�h� e�:~y��9zNXRT
��<Pq����A:��Hy���a	�-��Is�"�RK%6�W�����"@�9�l$�+@�%q���L0��P�@�]e��'��-/��ka���n�W����^�h�z���K	��dv]3/;zg'pmdJ�2���2h��~B9UR��^���9C(�7~%�f��L�e��qXu�`��U����}�����5�R>D���,6���lbX]���M�N����7�Vne��
�B(���� ���[��t�8��2�����+p�(#��un��2��*��������M���}V�[W�7�5��M��f��S�_R*]w�$`�N.K�.h���\��L�;K��
@����p33����x*
�����$����q���o��@�T2�k:1x/S�MZ1Ub]���
}6��5�-/E�>����P��Bow��p�25�+�J�	�Q(E#����Y��e��$��� ����n���Ls[�ii��� �8K�S>�R5������Y��h�	�A����Vf�����P|]�I�5ohMF�D�u%�"|dj@,=cj�	���P����V����6,�;(����5�3L�Rj0�t^�= ��
�����Bk`��k�
f�r��J���-����<b��3kZ�&�`���<n��;��&�������/�����Y!rd1����q�X1����r�W�sn��d�_�./�^F"%���X���egf'���^���>u���2�*�D��	�.�h��wF�$so1�_�7+�?�����q�����X:�����C%1d�� /26A�f`v�0��?���r���D�������5j9�?�k�����|KAj�R�������!m�;0����u"@��;�;3�bg��0��a�
�-K��`���`W�#Z��������RS��W7+������j�V��)I���Rl�o���d�s��Wv>���}](�LV?y���A��:��3��}"��.���\n��aL�i�$���#k��J�"�}@SU V�������B�*��Y0�w���!#��)B�����(N��]�H0Z!=�h�9�����)�N��h�@���R4�����mg�{<@qC�(���+yYQN!����D�"�������)��m��-Z<8]z����[��D0m$���p68��U��L++�P8I?$U=��g�q��T�oJ���TN�+�$�7g�4���t{;���������#�6>����l(��x��S1��9@8�����K<t��x����w�?��W��
��`+�f�9{�����������+	����]�����!��-��v���j�x_Ic����sh�|h��&��0�X���>w���sz
��`��C6S-d�?���`{��������t{9sW
|8<��0��~U4Cr��%�����4������5�D���^taz+���_���xd��9�u�����������1&��������!���~�C���) ��Z����O��M1�����X��/��G]Z�q��}=��ZO�R����b��S/����d H�V3'N9��p�Cy�C&�v�`�>l�{�z���t�"u�wvB��$���p�N�E�r#'(�(3N����||tz�� ��|�q�SZ���v���
US�:X�NB|0a!�*�K,3?�����m����>���_"$�H��lq�h}�;��[���gd4�K/��<!*MRj:���bi�>�Y ��D_�0'Bo6�P�n���?���Pk��������'�W�%������/���\���Bf��/���"j��ia�J ����������������r������S�=����2���.H���EQp���O��j�C.;)bB�9Fg�)�$OA ���R�+��=�hy!O�!��������<������6b�����@�[P���
������/�!K����#��t�G�X~Sl��S�{�%v�J����&�;�~�?��8�
��2;����fx�
�CT���=���D?,&��D��_�Er@�I���C�����9���7wW��$������:�������3�9g�U�8�$����;|L�E���Y�_��*+����F�{��D�l��Y�����"5�E��ajU�2�J������G�����������W'�?�)Q�/N��/�����������PH��Z��O�Qn]�W�!kC^Y�O�b�c�����S7�;,���������}{��dQ�����h@�7�<���3�6��H>���BC���V�=���h��ky����L[H�E���JF��q���u����k��_�^Y�Q���3Dm�q��_�J����{��R�W�6����]���������*�&(���������u�cEfy�>z�qM�{��M���D���G�����j��������o6��7�
����s�FH�=��O��x����n&���*Z�P�^_+�L�����@����U!�F����_%	P~g��,������{��G���tV�����^���
��YL��.0�
#��������~(�t E�a�(�:�a5�N\Z����uT3|ou�byODd���L�����O�b��R��{�L��d�dI�l��J����Arof7n�����$v����E����A �q��M,r�N��1� ��/���������K�n�O]��:�t�����q)H������jl��yXM�V��p����5�����G��('b���"i�8���Gs���.S��h�����x�n�#��1�9�\rV;�R�������l��'��ny)����y��8
tk�#����(�N�[v�"'�y�����������,���V�F����4���~B>I|��j+J]�O�T'����<K��X���0�6|��[#o>�
��w�����y.���=-���a;Ts�>�;|R�:|�Y�J�aa8
uoU�����X��R��X��������q�["���b�����F��Kw
�!��4o��2u�s��4���t<��%i%��f��������7�G7�#�j�Y��������z����_pn_���������e��:��a��@�rR"�{M�	%�O�'��r�;��=s��������)��
���0`�B@�=r,�d��P��}�7l�<Op�Ak8�vK�

�`;���C-���g���$ W��4���gWa�J72��7��L �_�8��?x$��F����n�n(�+�-��c����;!q-������=�[B�pG��pP�|PP�6�l�w:�z���G����6���<�.�
o}!u-��:�J�8�>C��\�v�_ '=�.�����Tk�bm�����r�|B�7v�d>i�h/R����_����������wF��Bp_�=��*W�U��4Q�����W6���if�����mS�a2�xe��D�lb���i�������3��|�~�$�v�E��P�Lr�v-��v:�|p�
#_e47c�e����<5c�6bG�j�H+���k&����rN����(��s��������w�OI�1��Z{lq�Y���|1���L�9x �#�i�F��#����
����fB������L�;�`�
;%�WH��=f������6����/
�!a���%�m[mzV�s�z��=�;�c���{���{U�����3-���P����+�d�7�F��h5�#�����t�lv��~w�)yD��
�I�1��wX���g���*7<B�����<�.1��q������"�F�&Nx�Zy���e�Jm�0���G�T;@e�mn��:l�%�n\[���=��e�a�vX11TN�~�@��{��������)��?E+�m�?��@7��b�>����=,� �L�����##Ii�|��$�	�LE�����J{dl����h����������^���m�[}�8c+�r�=���h�ag�����p6���q{4��eO;V�qg���L����KpS�������R���q�$7f��q.�t�(w�����������Uq>�J�El�����7�U�)[�:u��B~;|n�oaG���������Fd).{��l8j6;��p��J2��u�v�G��S�*}�6��k��wT�n�'�q��t��"��=H���:��-{W&���^�d�1�H�yT;�|h�X/&@%Y��-�`(	��T!��>$,!��s�~�W��=�J��y0 ��6�k�}��TVf�qC���n�����k�{�iY��Uj���(���(��Gb�a����7�	���w�����������0��)O:���09�����[F�|�V�4VbpT�,y)��zl�M4��8�N���^.����-���y�wn�N����������"���:��������u�N�&�B�wG-_zno4����{���>nF��Jv�i]&b�*��g��J9�]o��t4{������!�������m{����o��&���S�`>w�a_P�����e)�a0�B'�y��bE��
�)}	n���n7�]�s�J�h: (:wf2�|u�{��8��j�y�����)�X�uL�z�n�h$�>��S���f�\>��{���
�����[J'@�Li����N,K��}��O�6F�gO�P�����3|�����=`�eUB<����qnW���+`�����W|
}��'�@�T��U��(�����.X��q��O�C�D���|�]!t+��y.C��2���t7��{NyT��C^�Nd���2K�����t�6������n�^2��)���p�H�r�R{E�g��]���
������p����^M�c�|+�
����A[���:�a�$�N�E��?��Q5��!�������j�����3��$������3j�C��.^�v�.#��g�v'3����n9��9�#JS?]
�F�H������n�>��@ �a���J��{�,M�
��4q�� eHx5�0��O6�	~��o������r��+pY�|�8_��������)���������|�l���Y�S�O��SB0��$�!��>;s�aaO����H�f��0��
p@��9�@5�m����)� �����D0, ��i3��)uz��������?�|?�����N�&g����e���mb)��w�t���e��C���w)�Y�_��v�X�'�${BB~��@d4u�K����9��*�P�R�� ������q�����A��s��n%W�M������I@0:BUY$�A��dz�^'~Me�,�2]�����q�����j�z���a����u�����B}�_������?�O���I�������������Ao�?��P<��a���+~���a����l["�]�v�:J'w��
sSP�9����~���L��)�W��K��h���x0���XCVM�2W�&�B���
�J2������5����i���������������OGgW������S��<;��N����2��|�t/����>��|q���W�#�/w���S��#~'v�ov���U���+�!��r�[m�Yx���� !�|�����.�
� �$d��2{�#�:V�k���(�{�8�K�F!���
f
<)���j�S���[��V��Z�7�e���yD��'�����d����g�@������yj��@�2b�^���&U$�/��oO��4yw~1�� �O�.�l~)������U*�����t����f��i
����3q`:B�9���~=��i#��\�F�����h�q�5_��v0�f�B&Eq�p�-p��N��[�LiY]��I�OJ�@o.��B�J<R���l��18����Dh�}�0��!���P����
���n�v���t�v������;�k'�����>y��g7����-�4��W�i����N�����s�	�����7 ;S��������k��e��>X����Md���3�����t�n��eR1�@
v�l���!zu��&�'���K����7�u���_��9�g�
?��kCp�u�h3���kK���^��4rP��j6�QW��0��/{�^�����n<+/���u
�����K�+Kj���Ex����n��my��7��������7���nI6SJj�&�q���R���2
�dGkCp~^����t��Gj�t����_!�:K�������ig4�����l��?/��b�)��%%V# �#V����C��x���(���z�����c~�M@��q���sk��uw�a���<�����If���WE%����b�$��Ka��MVC&��;�x]W�����;+K��"Z����	tmVi���K3L��:��
��>��$1�{�	�
KVK��blh E(47��t�/��0�������OB*[�E���v�+&��W�%��<
�D�-�s"����_a�dV|�����j����q��yl*Ch�-f���Pu	��K�����������{]�$:�y����~�,&��?&PE��������-y�[|�bl�D�?�Xo�$�w�G!�����l�W�3�Y]W/Oi��3��^���?{j&2��[��P��
'$?v���F�H�����4p���w�p��xq�3��-���-�}e�������F�osK<I�<�C����
q��tEr����i6����;o�=�-PE����M��m��c#0�k/df�*������O���i:���c���[6���'=jd-�+����z��7���-&��J��&Q>F�&�]��R���R+���q���r�X�i����	��)����%��$��S��X~>���k�z2�Y���r�:W�E0���(\�����	cm�)�0��pe���}M��D�����XLV��'P��q�������G�~��Ny��g�C�"�&���xk����w/�b�����l#1%F���������	��\�?>\FpC��*��g��/�������9-�����6���g����wE�(?�x��$Xq-��?!��RF �H�(�-U�7D���*��9���u?������sL��j�%U���9K�7�2��F@y��BH-���6���x�g�_��|�+]�Dw.������.U�yk%s�p
�����*C�\����k�7
*-�-��PJ��~�8��?r�o%��1&�|�i*�P ��r����Gr�������|������Y
n�����/�������A	|+�Wv{��I������IM����k*:������#	���[��QU��N�\M_N��kr�=��:�TL���I�C":yVS�W�������h�g�]�9���
l���Q��'f���>�FNi$�P����������;���{�S��sE���J8�.�����I��W��)���+4������}
f�e���~�+L��_A�G��s�T-���'W�.�N���R��0�+>��aiB�F���`���#�
������3�1���l�3P��"]��z�Y��>��Q����O�R�/�_��Q�����������6p�L�p���Oj��|�(�5D�{3O��`I��IF�&����2��U���o�U��w��?Cx1��S��d����K��?9-�!�>@�$`�ZF�<�=��d�[�,I�������	���Ma����� _�8��b����xO��2���T�$���:FB�R'�oIP��NS��wh������u��$��n/���|�@k�����7Z��.eJh9��b5)f�KS)9N@�},���"�)k�V����V���`/�U����)g�"��U��3�|�N+}�j����(����^s�%���pP	{b!
�L�O:����L����)��s��1
�Q������Me5�.��/��k6�7���!�[��j����M`�4�Q�.n}�92����n�W
��1P�5s�`��\2v������O/�K6.���y�Kk��2��^�%������)"�/R����!O���F��
�*�&�'���L	��6�1�����6b)28Q��2$!P��
�m�8MZ*�l�c\����m��v��i|/w�y��]�y�.X��R�i	k�^�7U>;}/q)�@�����d��@�������Ppc0��S}���R��6��g#.�����#@h�#��������s���#�'"��$�A\��+L5�LNR��VG��a����*�=h����DU0a^;U*)]s|���M�B�����0�L�:?!�_p��f��X��O5���Q�O'��M�>F����Ma��j����H�j�C�������'���tE�?�t0
���\�������z�������$&�#��Br��x����kCv�����o'4$��f���q^��� a�U4�
J��g��(_�
��R����]J83�e�{(�����eW���Tj"���?���w��l��K�{.]��C�'� 8f�*�^��:�!��w���Y����^+�o)V-e>��n\�`�GlH�T�0z`Y����h:�d���9)"�	�
f�_o������_�)�2�W�<@�"�jf�� :f���{�^��
����@o�����]{mi�9����6[+�l��t�����o���_��K/$��dC����W�^�:��Fv ���������_J��F�i���!�6o��7q� �z7n��-�q��<�S�\��}R�*�����ta����Y��IDKa���n���%���d���No��lbY���s
&~��!	���@������h��y!?B�NH�l����G��������3ch3�e�S���
�%��
���Q�Zc�l���g��ht�F`]vO�W^�R$��P(���������n)�����<{��=;�H��@u�=jAW T5Q�����\�`�nY19a���d��
�Z�����^[{U���oi������vqWS���$��A
l,���S��!{�^�������/����2��c�S;�]qr���������l4P:���Nh
��@i���{\����[!��$�+A	�q��a6O��r�Jp"!��=�����Z��>uk��mJ���U��O{0{���
�(�7��aX�@_�R1q�x4�6����=��p�H_�D��y(�b�4�DsU�����Z�ABe	���ghR���D^^����V�{�05s��j�3�r_n�%�BK�9�(�t�_X���;��~?O�r{��T�z���l'+x������l��~��AR�����������k0���U�u�}�-}��uzXF�}:d��r�I�!�.�pBnl�~��W[!�[f���sy��D
��P*�s �����`���������IK5i�Q��Y]���(���V��rI+�V�����}��G^w^���
H,���70U	}d���U������n$�G[p�)m�,��x��h(��'�]
���G����S=��{3�H���=r;��A�QD{��i����#W��N�����i����Ckcp��hq��oC��no�0��)V�]�S�������J��NJ��~g4���n���^Y� �����U�)X9�h���J���5����Q��Ew-�@����&�E�(�%�V$r���ZKJ����a�����;EX�`�~����y��Pb�F2�������f�?l��n�t{L�R
�M�J����/������n�u�}��v����{a{^`��&2���cP����/[,[)�������7���m����K�'�	�='�\�T��j�*�{jq�%�H����^fr=�z Zf�_�������������oO����2��`W������$����Z0���;� ������M
�0���Z�D��li�iR�hT�����'#1s���/���������c��#�����5�}�o�_vB�x�L��<oO��_m��'&��t�3��Ui3�%�sl
�H�����������Z�Y�lad
�hk�����}�{c7ER�O�9������8v4
oW��D:8�.E�������4#�B��H�m�i�����������/��'�����V;���
'�����b�������?�R�� �7*��|E�����2\
}���~��a�<mA�)��QP,:M4��)��������������=����?����*�
�x���)�bL�I'��sc�P�?�#�%�G�����;'�����E���Y�
������-ei.�;%�GH���q��>GfJ��l�E
L��J�4���f�)��w�;��[��I�N�3�%wRX�V�7';���|Z{I���d�U6�-�v�x3�d����O��H�F�KSA��������O����^W��y5�A��!
�U���%������vn�)�.�;.{/�����~�~ZJ�hG��>�[1�2������/B��D���X�{��L�R��U ��|B�m�Y��
���8�coV�GA) s��8?���"�Q�>����~�eoW�[��k�p��wP�+*f�f;)����
yGH�~Y���T@UV[�o#��O���)�P��4�}��l����X�,rH���v�a�	�����,�8W����7MCwg����:����_X��^�~x{t}��]�f�[����;4����
��P�f1�R����O��N��-�mU}+�W���63�*�S�������b��[��b�n��k�]���/�Q!{�b�����J��gS��9�6�V}k��3��*�pf*���Y25&}����X���Jz���"��p��k�#�0 [�F��#�����1�Up�T���.������������������ti?��K���P��,h�S��`.�iU��hk^�C�=s����u 3g{�(��e�U���I��������������������������������gp:�I�7��ny."Hp���\�����w�'W5�2I�������(����%xr���� ����(���}���/"�Y�UyA,�mO��Do�oP��a�ZP� ��K	mPH��������i��k*�C���������������d�Xs�J1��~�#���E��X����Q]��UbT��(�jBV��L��{��F>���3o�����vF����)9����9r�e��GI�^�3?�B8C<i"��N��V����]]�z��"��I{Zs�/�
uKD��P��YN�?LTY����r���i==]���{UF.�pN�ECGYRjB)���q���Y���P@-f�1����F�0�z.���zk�k���*���{���2s'
�D>�L$AbKJ������N�EI�u��K�oV�����Oy&���V���#�i���:���e����w���1�YU��'�\'�<��g�����s}�������a�����?O��\{��D�b�fr�!CP�1
w+/Y�5�s��p0�����`4��bm�!%9Dv[���!~��&�f���{�*��yc��m�#;m�����5b�~d�����7�;��ut�"��D��.�����^4����w�\a��S�k?TQ=�Q8h�i���2]�t����_
�,|�!VM���3���lq������F0Xwe-v$�����t�@����fS!�Pf�/����xA���j�������y6��#8�f3��9[/I�E=�:#�N�?��-��]�[���c�������*Z���^w�OA�'�W��f]W��0$@hJN����?������?�[��n��qO�}�z�|�Z��xS������;��*r��K��
sIk������_6|X�����8y2�@_,��R�k�q\!R��@n��'��5�����ak��o����Y�#+�����������!}>���y����
������z?VS����3�����c�"�4�Q�r�����9�0S�6��ahB��DlS������_�kq}p�'w��HT�I#?���B�2w�+��I'sv\L������(b	�h�������3�4Uk��l@)�-�S��zq7��{J<T�����������LT�

E<��iRb�9+H�#p�RH2$�p+-BA+�JP���{����9���VtA�,�;&�T���!�DTlb�%w��62��+���"<K�A���Aq�a���Q"����26�w�N��K�(���'��T��ws3�6�L�� �>����
�A?�K����%)C.����� ��p���?����.�$_�UCC�H��2p�R;��5�����I�>f���i�
��k���MZ1%�	����"DZT5G�����l�s������t��p�a�F`v8����G)n���������oo�R��-����F���8u�����:�V+�)9N��h���FcQ�C�p�������w��_V���������/W��owu���5KK��E{�A2hu-�8������4�9a��*���]w����mf.v���~�D87'��`n�mK<�o-�8����
y�nw���x��w[���\X�r�n����\��p������g�h�c�:e��{����i!�t��`�"���	���w,����?H�zJ����3��[��D�n�	��M��]�{��`�C��&Q�/M�xN�6�����B���w14���	���v�_�1,#���g2��`6���s���u�.b��Ie?�%��,}��.v+pCB���1�l�������YT(���[��!5���[a��}p��i	����$�����h4h�x[�&��w�"kd-�5�$�<yr|Uw��w�{�
����7�<�������I�{vC����:���������3T�&r�[�������&��$b�cM��]PM��,du�%�?:Z����3��d��
^y�t������*���3g0O88�A������3?@i�,�+�:O\+�;��4,>�v��n
�v�!!
���4�y2V�������Og��Rrt��%�?
��%w`�q�������B�Fy���6N�c��[!����2]��E@@������l��]�����wa�2����a ���v�0�}L���"s��6YPZ@�m����\�/2�P*6�m'��Ta��VJ�%m�H����X���yS+�9�"B�rx�n"��h��[��w�io���!H�0�QHQ��D!�3�8O'������d��� �x�	A���[���[��y.��}*�g��R|*���_	KxlCZ�^F���,s�"RK�EpUw���{��yF�>�o o���TYH�X��(V�w����NwUF���������^�|}���
Z�Y�����vK�����)�������"����,�U�8C������]�/�X%N����l��x4�I���E�F�=tX��?A}�	o��t��kr��
��C'���E��!����H����p'A�+!4���_�=�Z0���c�G���e��g0�j��8pV��D��bj�������������$�F�r{�{�>x��i�h�$�dm�DC�|A��\���G��-v��@�Yo ej������Be(XPihW9�����D�7���`x�f?t&�Z�.����l����-��B�Q��r8�O{�
��/$j����Zn���P�b[�=���� n�dj��'���(�P�r
eF�*5�-�������/<�D����������.B�������dX�n�3j��
jp�5�0��*�s���^DB��*�>�����VxP8�-��=��E������B���K|�#~�j�*�P�\�j��9����HU��$�������a)Ft%�����K]�=�.~O�9�<>���s���f��u�C/��x
O��\�4�C0T�=�`��(CR1�0��I��i��44�sNJ	����^�M�����[�&o:1���[�� �9y�+�L��:�b�+��0T�&�`b@���9E�����i?�8?ek��w�j��`?:�����2

��g���[�����X-y:��	�i�������������C�z�wh��Uy3�)d��bOU;�G�K���o\9l2v�?V��>h�.�}��y�s���0������qDi�S���*�'��`�5�^�_^���L<\��7|����>����� +�;�S��|(�P�oG���zn-�-t���#�;H���������������\�+�Q?���+��%J�7��2R��V#�l��c�1AB�B��ho��3�_��Mz��10��	��q�����@�+�{�=x��e8bJp6�`3�S�������,�b�K�-�^�!��j�X���8�!D�`�-�z�����g}�^0���IK*�A~I�vJ�	��l������)�p�$]����qj1��d�4�L@��>|���AD�
8��1��pZF�r�������CIH�x.6�/I�����,
@4;�&���
�����7X���L6!e�y�?�f����w:����[<I�M����%8�����v��,�lHs�<�/6m��>q�!&����'�H,�#%���*�1121���	�x�2z(�D:���l(�����'���%�	�hV~�FD[��)�]���'��L;N����EY�a��>���Z�~K�W5>piP��������?	��i�x�q.�i�������IP�!/a�|i�mNgL����T����tV��xj�c%G���I��U;z�	��4�d�
�~:&�,q���uN��2�9���S.y\_�+A�
MH�0yuq]!W�'fF����b%$"�V����tyw�u�sj9���l����9��
U�����g�A_���_��y�'���|�x�W����'�ob0����.��j���IIO_;��
��x!-'��"8���1~3���'������a��]�\	6�x�������}wqrrpPm;���1�-�]�Q���e-��2`��p4K
�1i�JG���4>Y�pz�(��T�$�D��X�
X���K��������%0FA�w"���q�7�I��i�����IW���q%��8�_��m�������w�9y[�1l�JX�%�$�J#)��6[����l�����0Y�v�Pq{�"�.���),M	B�=
���2o����E�L�'�~j�hhR'<���!5A-5X�����Lt��/^Y����A�U�_��i:����z7�BPB
���\�z�|J�#K;a�J�vp@��@M-0��|QI�0q#4���mT�=��������+K;���h=��x����;pl��LCE�
=>�K8��tG�OE�6�]�w-������A[���el�,b�rr���F�4dU����r
���`�����h�&��L:
3�a�!~H���]��Y��Y�Q�E:���i����LU+�����(x�"����Sb
��>*��(})c�2cU/���J@T����;��'s\��������mAqp�A@6X5����/����&��>��$xCc6�R�9��D��]���w9������j
�����N��ru���rsc3
�w�@���3e�G�&`�Wkx#��x8����Ah����}`�����@p�y�D:��%����o���l����s���5��t^}���G*����n���^���f��Q>�3��oC�d
�h 5	��)o050Eo�S �>���Lx�&&#C��Q����`f<�lF8��*�TI�
I3�*�&���	3�&-�����p�����o`��O��6�,&h� ���s�FbR�%V|��<�oW��	~���`��p���fJE�?�=*X���g8&�<"!W%�'��)���HJbD,����E[Bkbb�Y���g���R�J1�-^�����AL�E����#&��mb�$6������X~��'rw��u���fJ$�m2�g������>� ����\����h���@�M����s�M�M-
jU�}�D_	��/�������-|�e�,7��r��`h��+a��`���,�uwJ�a]���$�� ��A��A��J����( ��9�������5j�<%���(�&���?�"L�tb�@�J0��DbTS��$�\ �����h��3u�[8O8�����'���HM!���P�4�t�|��#�����7	��t9�����Lr��(W�&�r�O�r������������s��\�V�����I'����)i�`s
�}}��d�R�����k/���p*�1��73Hl��]��9���U��JO��&����}���������K'�1��=��=p���Z���QN�A��������OG���o�)$����&��f��!	 I�8V�QT"ib$������If{���l����BhQLx��6�n��8�#��g]@�W����������	������'����&��}s��+
�lD?i,}�N3_���"`8�L�zH����FNy�A@�7w�d��!&���P����������������+^����+���2X�Wq
�b�$t�0�qK���_d�A�r�a�B��S_|�x+��>%��(3�������u��&�
�*	5��W��E��`\d�b��V K�]�����3��4�^������-�CJ&xz<����sR����sz�7/����������l�O �18�:
'��
R_q&c�`����C��,Z�3��ap�������bZb����9m���"�p>g�.s?�����m2�o�.'����������8��o��'A��2��q���V����
	�t+N��6X��{������������.b���tc���_���A&������o-�l��<:,�&
�&!!L����8Q����yJ��/��zg�S���_B���]�yq��}6�al��g�>�R��n!��)��F���4dt�!�_��w��a�ww[��Jw��$���[x������oABB�������p��;X)�K�6��Th���qBr��
&�����KU�_����,�u@j�J�%�U�a�KhDv�U
��7�6)�����?JKJ�j5�w!�����a��e�R}T^�TD��r.%n�C��m5��1k�up��kC�Up1����u�@B#��`f*A�����Xi	��C�Y��8��O_6�iOK�]z�L�U�/���<�"K��m��b�X.a*��ieQ����uD�
��xK)e�(���H^|�"���_���1�SM^�����S"����=�����7�8���Pjb�n��������v_m��,x��
�ebw�{�9�AA8�f6����`�h0��i�x6��U������no|�Gt��E�vI�+���P��R]��3E�����m:�0N��C���r���q���a���QM��Ng�����dT�P���Sf;O�t@0]�@�+3�i40L((�6��}|�b,��G�K����h�aW����6B��$����@���5����X�����[����$�g���V��B��!�1��Lo�]����Kez�i��>P*��q4���A�0FPM�l ��������0����������ji�KK��E��}������yo���*�2��x�\��|G!�y+����BV	\�r� ���M��~M�(��/���@����6����X�k<"�t�q�I{�1U���I��,�V�d�8������&��f����\0�@��T�RY@�L4nK������������,�;������10�1=X4�x��t@	y�X��<��"��4��/01&,�
���EQ������t�ZA<(�]��e����er�,�h�=�&�a�F�w�4������d�v_+�55����)��u��E��C�{f�\b���o�!L��b� +
����N�C��/���4����6n�L^���@���L(��t���x��R�8���t��;���a�K�m�h	lC���������3p��#@�@��;�CGp��$+)F��Be(��������^��"@������E�ui�� �iJv��O��� �D�G���D]��������V�?zc�3���KBHF�%�`�h3?��8��{�q��T���L���0�
�`��*/'+h���^V*KP��g�
-n�k�z���.�����	��4��������[.&��(��j�}t�./����K.�?���y,p^N�,%����H�$�Ml0P
��
�	�tF1 �C�B��z����.�,
A3����9����86����|���Mg��B.E��~�o?��L��~����@����z�0d=���By'K$����s�A���U�^����V�K�@Ld�U��v/e!���M�)�`v��q���
���$�
a6?��{������|�P��.7��a�2�c�P�������#���E��	:�[C���|���������WN����9�4�-�����p*�����T����������Fx�M����J����V���\/�mCi<�
��i$�������&B��!`��|�����)��;�N�����n�7������������qZ�v 09��q���6�n��=���s�����`��:�q�3m�����Z#o4����L��^ ������N{��Z/�NG�a��t�G�����g�)�������� ��iSh o*���/j�iw������9�����e����V�r7����������o�V�E��w��������	^�'��Q��P�5���]i��}�}0!��������`l�9��p�b
O�km�x���e$�n���+v,&��#�] �
����*2�����*��8��������=�y�P����i�s"�B`�����9��6��D��"��d5	����]T����7[�{�H����M��_AD��L��������4N)��:��U�5te��tG�O}� �\I!�&�%��|��E��N&"i���� 	�>W�#q��fM�y+���	�/�a����i��Z����q���Pt2���|qbr�w�zP'G��>3!�-��(���U�A~��=���$����X���+D������C���`t+���K�O
dIb�%��.��d�:d�M�!�/�H~��u��XN�O����P��/rF�}>�j��c:��>F��U�d�I�����f�}����
�
�/��G�)����:�.�5p��f}��}�������������8�H�	�c����D����j9���n�.Vj����aX��J����!�H%��:m���]Y����K}Q����wenI��>�%6
vKF>��>y��l��"lw;�:@s\jQ�}��C5l�p��@:X:i�*����A7-��-I�Q�;����qk&FK?_������/�n�_�F![�R��wB���^U�����1T��]0����=_��I��H���7�7�%������H-O�.�_����=S���oTi�;��u.
'B�'�=�ocAs�9����IZ��O��t���;��x�r�L$p;8���/�L��_�'3�@g:�BN��OD+$�[�
�I#����"�_��KLx"k��Hlc�-jY�S������fr:S�:M���v��1!�F5����Cw�?O"FV��&h=��w=�=
�5����l1V��X��FL^��T�xZ�D�)���N������S�(H�VAj3�N�o������/�G�^H��O+�����������fm�Bx�q�"����D�)b�.��!�WS���j�}��<���9���*��(N���o�{����5�_���/F��S&!���i�S&���z��8���;l
��7�?I��xc5`IN�����+a�.�d� TT����r���$��2%k���[�5R������D������eR��}/�&�p���o��SAZ��xo���CN�SVA��]8����B��x��V��������F�K,���f�)�|6����DGq���D^y��j�{]�i�?�X��	BE�(�������8�����Qv9NG�V�
du!�;J@��{S?�pv
��G���KP��zL�����?��% p�Z�~���cgXAF]��U���n��a�]b�U��>���������}�Fj<x�
U;�Z���{�}
�������YqZ������{��8g#�;�s�$	"�N���PG������v��=D���+_tb��;�c	Aa�z���/�6 ���P��m��v�4�]C�v���)A��8c��6��Ek��P��7�t��daA����:=�l����*�a�O>�wv.���{�mFg*���Z�'��\;�@q����k���K�>����T4�B���R��]�+�J��J��:Y�<�T.�t6��f�k
�NN�x��_�*�����?��������xB�(��>. �V��\w`���>@�1����D!�;2�$e�����m�,�aJ8�H���R<� ����rn����{�4�$�n#�Oot�~
�
	��xf�cZ�SO�cx�Q���6<��Hr�8f����VP��k	I��^�z:�N��-O��X�-�{�c_����9�i8�I��� �,|@0����$p� &`m�����|��I���-��b�f-c���xkF��x:o6�Ag��Jl���-kI���C*(����4��P<�r����@5�����=G�l��n�e0�K�ru�-&�u��	��O�����U����v�2x�����Sw���w��Ai��g��|� ����c�-��s�)bE?T��bb2�\3��h�d$����t�����n����CCf34�
��=��������r��u�����?���Qw��O�����������O���@������b��l�X%r���83){�����w���TN�@����,d�k+7�����@��g�h^��r��dgy�j��d�P���$.�f�\N���Z� ������l��[d!�_|���08�.�l���)�#G��>�F�����r{�Y��pvT�  ���$���a(A���B�e�65`�����y��V�hd��V3��CB	�
&�����b�V
�z�/ �������{��H�����b��\��)�,�#H+o�;�w����7���n
DoS��h����|4~}A��t{N����t�hoAm��K$2���)��n9������|�2�.�J��Ls���CTo ���.<I����>���#q$v[����SQ�',���D��/~a7��k�
H�
L*,@��Th!���2}y)c��G�@�4��>K�iQH�(���!:�J��0�u�[F����M��~�d���F�l^Y��������a���MA�����U�E�Y�����md�mY���l:-�JYPS���x��^J\_��<���b�G_�?�'��K�<��Nmh$MH�������R)@2<�i](�~�.�L�'f&���O�c;F�W�|.+{���r���9kC-�f�Q�o	������n�Q5
Fp+���C�O>��3��/���f#�a�-���������E�ff����t��L�o�{��NR^)!�
���N����u��{!d/��-�a��O�?2�����#��v�A��q�j~R�DL{�E��'#��`{�[�|M~����Ilt���O�i�BK����������'AI�B��c�fdEw3�13m��q�;k6n{�w�%��	����M)�X��D�NF����j�6�0��y������L�,���������k���v��Ys�W9�&.��kFmT��/�p�
m��������s1
@���dy7����C9����Hu�d��,��7�n��I��1]p����^�& �y���
����v���r��j(%Qw�������������26��Mc7��T����G�������@��n:`�����9�_RU��C.�{��i�w�c2+����o���j��"�
�{R��V����2X��?�=�<��	)r�q����M��.�0�2�R�v�cqt7�������J�=�( xn����>����x���������������C'&�������,�YD�/����j�����*�Y8�R^���{��e� �
���/JT�����(%�������;/��g�+����[���jN������GYk��N������VS:����}����\��C)�.�yJ���#���`��J?8G��'�����[�x��znnVI�Se�@nC���K1��*�*��M.#���Pb��N#�������������9�Rp��D�`�U<�M{���Q��4<�G�Hd��xYG�k=�aD��_�4�j���0�����b����I#�����\�?���JI����F����vA���hEr`�2d��:�~�gU2V��7r��0�����:�7�f���m ~��v��"�OC�T('��0�<0r�S��t=�����Ij<�h��*�;�������A}4P�K���F�#�fG����s�d�NF6����^/;i������]%etIxEP,�R��0��;\�R-
����,�ECu~y qIc��9���K9�&���4�������{
�����Y~�R^���6�)����4+gC�?�����	V=�ri���
����m�V����a'p���	K�)wo|��.d�����G�P?���9�^�X�@�(a�����Y��,�d�;���Ef��L_�|��B��s.��<C�����~�l/3��"���f"D�U�"\]s*r(}q�o���P���7	���C9n��*'�1z�L��4]Hte7�M�F��K����C���������zh�w��i~�d�r��y+d��2������A�c`j��\����Rk?E!��SU��������W��]�{&vP!��N�,�]	83:�@���E������^����R9e&�J%��0K�L�D~�������q�D��,��
��3�Z(��-����v�4�sz�R!���Z!1���{���ll��.8��]�K[;(YZ{�:k~H��Jm2��#��/DBDJmU�L�3��:�(�5O��<sb��P��2�5p��{W��6n�����=$vb)�,YRn��M����5���{�t4�H�j$SGJq�����| ;N��m\�b�X���G��!�^��������������%{��S	�A`Uz�
-�>��/���6A�����:�����-�6�Y�UD��$A���@�������pt�u� �R8Ed��D���P�S�6�&$8��7��J����$�BJ���~��YX�y�pZ
6�'!��%>�Xw�E��M��#%��|����G`E�_��ThE�_��T�����W���IE�������"#�^�&��j�*����P����
l�a����y��d�3!9��O2��7o���B����7��������?<'FSB���x
�3i.�V����X� ����e�Qh�����9�tJ��m��9�����$\�hpIK�O��neu���v��
����D�OY!�;��������B`-�_�{sp\����|�m&�ux�.��@SI��u/s��b*��[��
��+n�s �aN���I��H����X��u��^H;����si�yU��U�A)��g�J��k����W��G[%E#������q��y���&
lr��p�iE��j�^��D����)�[j�=c�w�X�C��/����O������j��P�6	�@������k�6(���+��H��'��qR�q�f���"]��qC������N�����D}��=��SBn�AZ%�-�*��BH�����!6�3r��8��V����UG!�q��I�w�J����Z��R��D���mpGGs�S����d�DF�����/�O��X�9�$5]�b�3z�"������z=R9���(]�PJ����|��w���2]+%�K�����R�c�W�������x;���y���"������f�B��R�qV	��Uk��C5[����w�K^��J�k�z�|���R/��o7��n�����I�*����v-v����?�"n�����K[����~C	P�y������N��j��(��=ySh3�^�� ��J�]�N����~X6T������3�\�b2�Y~W���?�S
�u�Nv�x����S*���L���#����c�;x�]��|��W�9�����VKB�d����r��w��b�� ����F���1��p���(`�Umj�:+��ND�N�
��p��*HO�u>Xa��x>�b�X4�����D���f�^��%��(�����P��>;������
A�6P�q����f\Q��_�%�Z6���C�_ $�{c�����O$j�����H��5�X���y���W�`*06��w[H���Z"9��|�z]
��������i>��+�Z�9�	Xn�npE�`]�
��^��D<������I��M��oo
��@FI��Q�R�kz]�C�z��j�:@�������(��7��U�Mx�=��JP������&D��uXX)u����/�
�h�A��������n#�RA��A������`����i6�\Mc�����}��m��9\��>�]�yJ������D��;��<
��D)�eeh���?��MI��Z��kK���-�����RU�
��dd����<a���H�� t�@��V@�B~!��e��n��]5�C�L'���P'�&����9��c\��:,/..�����p������To����N���x��J�q��OJn�-8Z�'T�-�7x��i+�
HG����k:t��	>`w`����3�d{�2�CW��_������9��R7E���?�<9}�NS����zo,���L�c��tC�
h�%��y�*����b�N�//��E�<H�e���S����,��[QU�_��B��� �YI��^�J���^}����{���
�}�~Q��t�1�x�6�x����5��L�Z�����v��]��eq�p0���~����Yk$�Q&7�*�W�O��||�vH8wK�O� }���c�`��.���;�s@�c"j�Q��F��	��R:�d �[l�r[�������k�_�fC�1����5j��"F�Q�5]� �������8��	dk1��y�M�P����Qc�z��W��+��0��l�����G3�iCXIU�8��|�/�p���Z8O�����D��-ENG�����'������]�Q��F�N���C��������	3���"��$�&a�$���q��H,��Xy��f�l�{��z�M����M�e��+�=x���t?l����Gc�<xw�U�4���ehrG���I�E�C"�E;rw�fJ�����d���Z�8���+2|��@g�|e������Bz�:\�i='8��V8(h\�TM�} �2��<y|��:�D��t|��	��TF�lS�#
q7c���K�8�g'�P����^xm�4A��3������|�	@�������������I�)�lS����l��S����Qf=��N��i����h��	�v(��c�.�(��%'r��������������~U-�~���������}�m�+��c	�{1z��X��M�Qy-�X���,��*�'j���7c2R�f��*�d��d%z=���Y.�Qbo>����5�6�Uq	�'b	s�0��q5���cY�9d�	�������G�<j��z�����w��L]p�\��HA�`���]C
���8D�
���:9��ns#^��o��zn�	�=%���MG�*��VBg�\�>de���f������wm���!W�&Y�jp��������������Q�U�
�����
��"O4��8�������d9���i9T��ky�x�'IU~(��q9>��k�#s��>'w����:%�o�[�o�����e�����j�x7���)=�=/���6��T�yzB�vn6�)�������<z�����;|(�����T�-9�?�sk>L�C@�I/���@��2-��+�+�����QC7.���t���f��+u���j����ex�G���R|��T�����9V:��}Ls�m���0���2�lB��?��\�:�F�4
���r��%���,�u��C�y�D�:MH�`wa}�b�����I���|WOA�'�`������q����;���"��pBN����E��S!V���+���=��6�$�!HI@� ��!�o����Z�OG&s���I�HX���:'iA#�s�/������8]���xt1���K���B��L\4a.J��������|q$�������R��u�������,��D�^>C�6�#�_��o9��V6O�y��Q$�=q�!m���vr5t��Mn�U��T��u1�AQ�%�0��yO�P�c���;�-S�<��!S��f�
/_�h(��k��,g�A>`iz�����|6���_9S{�������-J�S����K��,` ��������g0��t}B6w��l��,���������3���W�(k��r�X��j��~��"�����'Lh�~���u#o�|�|������F���[�$u����b9�����<�5�i��NE�K���s��`��/ ��� �"�Ar%�#e�iz�8�-Y�pVgC��y]� J��������~Y��]�/�fzn��D_{����H��������#�=,���~���e����Cg�������z3+�A�����
�q6gb�\��a:��^��3$T��&tj��L��9��w9����R�Az���A�p��c�Aa"�1��i�q�^� �NK`��t=��C v���^C��_���mmxp0��w~���f�����$;�j
�_+�����?��=�SW����t�+]�JW����t�+]�JW����t�+]�JW����t�+]�JW����t�+��D�`�
#16Andres Freund
andres@anarazel.de
In reply to: Ashutosh Bapat (#15)
Re: TupleTableSlot abstraction

Hi,

On 2018-08-17 12:10:20 +0530, Ashutosh Bapat wrote:

We need to add LLVM code to fetch tts_flags and
perform bit operation on it to get or set slow property. I haven't
found any precedence for LLVM bit operations in postgresql's JIT code.

There are several, look for the infomask accesses in
slot_compiler_deform.

I'll try to do the adaption later today.

Greetings,

Andres Freund

#17Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#16)
4 attachment(s)
Re: TupleTableSlot abstraction

On 2018-08-17 01:07:06 -0700, Andres Freund wrote:

Hi,

On 2018-08-17 12:10:20 +0530, Ashutosh Bapat wrote:

We need to add LLVM code to fetch tts_flags and
perform bit operation on it to get or set slow property. I haven't
found any precedence for LLVM bit operations in postgresql's JIT code.

There are several, look for the infomask accesses in
slot_compiler_deform.

I'll try to do the adaption later today.

Attached is a series of patches doing so. The previous implementation
of sysvar accesses wasn't actually working - the slot argument was
uninitialized.

I also noticed an independent issue in your changes to
ExecInitScanTupleSlot(): You can't assume that the plan belonging to the
ScanState have a Scan node in their plan. Look e.g. at Material, Sort
etc. So currently your scanrelid access is often just uninitialized
data.

Greetings,

Andres Freund

Attachments:

0001-Fix-slot-type-used-in-subqueryscan.patchtext/x-diff; charset=us-asciiDownload
From 68ab969d94964a8e6cdfac974d73ef559546ffa0 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 18 Aug 2018 08:12:52 -0700
Subject: [PATCH 1/4] Fix slot type used in subqueryscan.

This later becomes relevant because it prevents upper layers from
making assumptions about the format of the slots.
---
 src/backend/executor/nodeSubqueryscan.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index 1e83e673939..6da918894fd 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -130,7 +130,7 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
 	 */
 	ExecInitScanTupleSlot(estate, &subquerystate->ss,
 						  ExecGetResultType(subquerystate->subplan),
-						  &TTSOpsHeapTuple);
+						  &TTSOpsVirtual);
 
 	/*
 	 * Initialize result slot, type and projection.
-- 
2.18.0.rc2.dirty

0002-XXX-Copy-slot-in-nodeMaterial.c.patchtext/x-diff; charset=us-asciiDownload
From 50ca33b96bf6017f04863486763e2e3250c5cc0a Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 18 Aug 2018 08:13:49 -0700
Subject: [PATCH 2/4] XXX: Copy slot in nodeMaterial.c

This is needed because otherwise upper layers can't make correct
assumptions about the type of slot handed up.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/executor/nodeMaterial.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 66c4ef6ca90..fc36aedfa26 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -146,10 +146,8 @@ ExecMaterial(PlanState *pstate)
 		if (tuplestorestate)
 			tuplestore_puttupleslot(tuplestorestate, outerslot);
 
-		/*
-		 * We can just return the subplan's returned tuple, without copying.
-		 */
-		return outerslot;
+		ExecCopySlot(slot, outerslot);
+		return slot;
 	}
 
 	/*
-- 
2.18.0.rc2.dirty

0003-Fix-JIT-calls-to-ExecEvalSysVar.patchtext/x-diff; charset=us-asciiDownload
From 5d6168601419ff044f197dfe5c1a2479f97496d1 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 18 Aug 2018 08:15:52 -0700
Subject: [PATCH 3/4] Fix JIT calls to ExecEvalSysVar().

The previous attempt at this called the function without initializing
the slot argument. Which unsurprisingly leads to crashes.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/jit/llvm/llvmjit_expr.c | 58 ++++++++++++++++++++++++++---
 1 file changed, 52 insertions(+), 6 deletions(-)

diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 432f81e0dfb..5c878e45285 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -64,6 +64,9 @@ static void build_EvalXFunc(LLVMBuilderRef b, LLVMModuleRef mod,
 				const char *funcname,
 				LLVMValueRef v_state, LLVMValueRef v_econtext,
 				ExprEvalStep *op);
+static void build_ExecEvalSysVar(LLVMBuilderRef b, LLVMModuleRef mod,
+				LLVMValueRef v_state, LLVMValueRef v_econtext,
+				ExprEvalStep *op, LLVMValueRef v_slot);
 static LLVMValueRef create_LifetimeEnd(LLVMModuleRef mod);
 
 
@@ -403,14 +406,22 @@ llvm_compile_expr(ExprState *state)
 				}
 
 			case EEOP_INNER_SYSVAR:
+				build_ExecEvalSysVar(b, mod, v_state,
+									 v_econtext, op, v_innerslot);
+				LLVMBuildBr(b, opblocks[i + 1]);
+				break;
+
 			case EEOP_OUTER_SYSVAR:
+				build_ExecEvalSysVar(b, mod, v_state,
+									 v_econtext, op, v_outerslot);
+				LLVMBuildBr(b, opblocks[i + 1]);
+				break;
+
 			case EEOP_SCAN_SYSVAR:
-				{
-					build_EvalXFunc(b, mod, "ExecEvalSysVar",
-									v_state, v_econtext, op);
-					LLVMBuildBr(b, opblocks[i + 1]);
-					break;
-				}
+				build_ExecEvalSysVar(b, mod, v_state,
+										 v_econtext, op, v_scanslot);
+				LLVMBuildBr(b, opblocks[i + 1]);
+				break;
 
 			case EEOP_WHOLEROW:
 				build_EvalXFunc(b, mod, "ExecEvalWholeRowVar",
@@ -2634,6 +2645,41 @@ build_EvalXFunc(LLVMBuilderRef b, LLVMModuleRef mod, const char *funcname,
 				  params, lengthof(params), "");
 }
 
+static void
+build_ExecEvalSysVar(LLVMBuilderRef b, LLVMModuleRef mod,
+					 LLVMValueRef v_state, LLVMValueRef v_econtext,
+					 ExprEvalStep *op, LLVMValueRef v_slot)
+{
+	LLVMTypeRef sig;
+	LLVMValueRef v_fn;
+	LLVMTypeRef param_types[4];
+	LLVMValueRef params[4];
+	const char *funcname = "ExecEvalSysVar";
+
+	v_fn = LLVMGetNamedFunction(mod, funcname);
+	if (!v_fn)
+	{
+		param_types[0] = l_ptr(StructExprState);
+		param_types[1] = l_ptr(StructExprEvalStep);
+		param_types[2] = l_ptr(StructExprContext);
+		param_types[3] = l_ptr(StructTupleTableSlot);
+
+		sig = LLVMFunctionType(LLVMVoidType(),
+							   param_types, lengthof(param_types),
+							   false);
+		v_fn = LLVMAddFunction(mod, funcname, sig);
+	}
+
+	params[0] = v_state;
+	params[1] = l_ptr_const(op, l_ptr(StructExprEvalStep));
+	params[2] = v_econtext;
+	params[3] = v_slot;
+
+	LLVMBuildCall(b,
+				  v_fn,
+				  params, lengthof(params), "");
+}
+
 static LLVMValueRef
 create_LifetimeEnd(LLVMModuleRef mod)
 {
-- 
2.18.0.rc2.dirty

0004-First-attempt-at-support-JITing-of-tuple-deforming-w.patchtext/x-diff; charset=us-asciiDownload
From 6ce4e9632ebb5d55693588e25b0f45c2005c7b43 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Sat, 18 Aug 2018 08:17:13 -0700
Subject: [PATCH 4/4] First attempt at support JITing of tuple deforming with
 abstract slots.

This now assumes that slots for which we JIT compile deforming allways
have the same slot type, not just tupledesc. Previous commits attempt
to make that the case.

With that knowledge this commit JIT compiles differently for different
slot types. Besides just making things work, this has the advantage
that we no longer JIT compile in cases virtual slots are
used. Previously we did so entirely unnecessarily.

Author:
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/jit/llvm/llvmjit.c        |  4 ++
 src/backend/jit/llvm/llvmjit_deform.c | 61 +++++++++++++++++++++++----
 src/backend/jit/llvm/llvmjit_expr.c   | 25 +++++++++--
 src/backend/jit/llvm/llvmjit_types.c  |  2 +
 src/include/executor/tuptable.h       |  5 +++
 src/include/jit/llvmjit.h             |  5 ++-
 6 files changed, 88 insertions(+), 14 deletions(-)

diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 640c27fc408..55ee46d292b 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -65,6 +65,8 @@ LLVMTypeRef StructFormPgAttribute;
 LLVMTypeRef StructTupleConstr;
 LLVMTypeRef StructtupleDesc;
 LLVMTypeRef StructTupleTableSlot;
+LLVMTypeRef StructHeapTupleTableSlot;
+LLVMTypeRef StructMinimalTupleTableSlot;
 LLVMTypeRef StructMemoryContextData;
 LLVMTypeRef StructPGFinfoRecord;
 LLVMTypeRef StructFmgrInfo;
@@ -811,6 +813,8 @@ llvm_create_types(void)
 	StructFunctionCallInfoData = load_type(mod, "StructFunctionCallInfoData");
 	StructMemoryContextData = load_type(mod, "StructMemoryContextData");
 	StructTupleTableSlot = load_type(mod, "StructTupleTableSlot");
+	StructHeapTupleTableSlot = load_type(mod, "StructHeapTupleTableSlot");
+	StructMinimalTupleTableSlot = load_type(mod, "StructMinimalTupleTableSlot");
 	StructHeapTupleData = load_type(mod, "StructHeapTupleData");
 	StructtupleDesc = load_type(mod, "StructtupleDesc");
 	StructAggState = load_type(mod, "StructAggState");
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 6d7ce21865c..f213480f32d 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -31,7 +31,7 @@
  * Create a function that deforms a tuple of type desc up to natts columns.
  */
 LLVMValueRef
-slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
+slot_compile_deform(LLVMJitContext *context, TupleDesc desc, const TupleTableSlotOps *ops, int natts)
 {
 	char	   *funcname;
 
@@ -60,7 +60,7 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 	LLVMValueRef v_tts_values;
 	LLVMValueRef v_tts_nulls;
 	LLVMValueRef v_slotoffp;
-	LLVMValueRef v_slowp;
+	LLVMValueRef v_flagsp;
 	LLVMValueRef v_nvalidp;
 	LLVMValueRef v_nvalid;
 	LLVMValueRef v_maxatt;
@@ -88,6 +88,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 
 	int			attnum;
 
+	if (ops != &TTSOpsHeapTuple && ops != &TTSOpsBufferTuple &&
+		ops != &TTSOpsMinimalTuple)
+	{
+		/*
+		 * Decline to JIT for slot types we don't know to handle, or don't
+		 * want to handle (say virtual slots).
+		 */
+		return NULL;
+	}
+
 	mod = llvm_mutable_module(context);
 
 	funcname = llvm_expand_funcname(context, "deform");
@@ -166,14 +176,44 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 	v_tts_nulls =
 		l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
 						  "tts_ISNULL");
-
-	v_slotoffp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_OFF, "");
-	v_slowp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_SLOW, "");
+	v_flagsp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
 	v_nvalidp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
 
-	v_tupleheaderp =
-		l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_TUPLE,
-						  "tupleheader");
+	if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferTuple)
+	{
+		LLVMValueRef v_heapslot;
+
+		v_heapslot =
+			LLVMBuildBitCast(b,
+							 v_slot,
+							 l_ptr(StructHeapTupleTableSlot),
+							 "heapslot");
+		v_slotoffp = LLVMBuildStructGEP(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
+		v_tupleheaderp =
+			l_load_struct_gep(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
+							  "tupleheader");
+
+	}
+	else if (ops == &TTSOpsMinimalTuple)
+	{
+		LLVMValueRef v_minimalslot;
+
+		v_minimalslot =
+			LLVMBuildBitCast(b,
+							 v_slot,
+							 l_ptr(StructMinimalTupleTableSlot),
+							 "minimalslotslot");
+		v_slotoffp = LLVMBuildStructGEP(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
+		v_tupleheaderp =
+			l_load_struct_gep(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
+							  "tupleheader");
+	}
+	else
+	{
+		/* should've returned at the start of the function */
+		pg_unreachable();
+	}
+
 	v_tuplep =
 		l_load_struct_gep(b, v_tupleheaderp, FIELDNO_HEAPTUPLEDATA_DATA,
 						  "tuple");
@@ -690,11 +730,14 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 
 	{
 		LLVMValueRef v_off = LLVMBuildLoad(b, v_offp, "");
+		LLVMValueRef v_flags;
 
 		LLVMBuildStore(b, l_int16_const(natts), v_nvalidp);
 		v_off = LLVMBuildTrunc(b, v_off, LLVMInt32Type(), "");
 		LLVMBuildStore(b, v_off, v_slotoffp);
-		LLVMBuildStore(b, l_int8_const(1), v_slowp);
+		v_flags = LLVMBuildLoad(b, v_flagsp, "tts_flags");
+		v_flags = LLVMBuildOr(b, v_flags, l_int16_const(TTS_SLOW), "");
+		LLVMBuildStore(b, v_flags, v_flagsp);
 		LLVMBuildRetVoid(b);
 	}
 
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 5c878e45285..546c0bc0785 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -276,9 +276,11 @@ llvm_compile_expr(ExprState *state)
 			case EEOP_SCAN_FETCHSOME:
 				{
 					TupleDesc	desc = NULL;
+					TupleTableSlot *slot;
 					LLVMValueRef v_slot;
 					LLVMBasicBlockRef b_fetch;
 					LLVMValueRef v_nvalid;
+					LLVMValueRef l_jit_deform = NULL;
 
 					b_fetch = l_bb_before_v(opblocks[i + 1],
 											"op.%d.fetch", i);
@@ -296,7 +298,10 @@ llvm_compile_expr(ExprState *state)
 							is &&
 							is->ps_ResultTupleSlot &&
 							IS_TTS_FIXED(is->ps_ResultTupleSlot))
+						{
+							slot = is->ps_ResultTupleSlot;
 							desc = is->ps_ResultTupleSlot->tts_tupleDescriptor;
+						}
 					}
 					else if (opcode == EEOP_OUTER_FETCHSOME)
 					{
@@ -308,13 +313,20 @@ llvm_compile_expr(ExprState *state)
 							os &&
 							os->ps_ResultTupleSlot &&
 							IS_TTS_FIXED(os->ps_ResultTupleSlot))
+						{
+							slot = os->ps_ResultTupleSlot;
 							desc = os->ps_ResultTupleSlot->tts_tupleDescriptor;
+						}
 					}
 					else
 					{
 						v_slot = v_scanslot;
+
 						if (!desc && parent)
+						{
+							slot = ((ScanState*) parent)->ss_ScanTupleSlot;
 							desc = parent->scandesc;
+						}
 					}
 
 					/*
@@ -339,14 +351,19 @@ llvm_compile_expr(ExprState *state)
 					 * function specific to tupledesc and the exact number of
 					 * to-be-extracted attributes.
 					 */
-					if (desc && (context->base.flags & PGJIT_DEFORM))
+					if (slot && desc && (context->base.flags & PGJIT_DEFORM))
 					{
-						LLVMValueRef params[1];
-						LLVMValueRef l_jit_deform;
-
 						l_jit_deform =
 							slot_compile_deform(context, desc,
+												slot->tts_cb,
 												op->d.fetch.last_var);
+					}
+
+
+					if (l_jit_deform)
+					{
+						LLVMValueRef params[1];
+
 						params[0] = v_slot;
 
 						LLVMBuildCall(b, l_jit_deform,
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index 58316a760d4..ea24866938f 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -59,6 +59,8 @@ FunctionCallInfoData StructFunctionCallInfoData;
 HeapTupleData StructHeapTupleData;
 MemoryContextData StructMemoryContextData;
 TupleTableSlot StructTupleTableSlot;
+HeapTupleTableSlot StructHeapTupleTableSlot;
+MinimalTupleTableSlot StructMinimalTupleTableSlot;
 struct tupleDesc StructtupleDesc;
 
 
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index e16bb26f6fc..fa5997cc3dc 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -273,6 +273,7 @@ extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);
 struct TupleTableSlot
 {
 	NodeTag		type;
+#define FIELDNO_TUPLETABLESLOT_FLAGS 1
 	uint16		tts_flags;
 #define FIELDNO_TUPLETABLESLOT_NVALID 2
 	AttrNumber	tts_nvalid;		/* # of valid values in tts_values */
@@ -300,7 +301,9 @@ struct TupleTableSlot
 typedef struct HeapTupleTableSlot
 {
 	TupleTableSlot base;
+#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
 	HeapTuple	tuple;		/* physical tuple */
+#define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
 	uint32		off;		/* saved state for slot_deform_tuple */
 } HeapTupleTableSlot;
 
@@ -314,9 +317,11 @@ typedef struct BufferHeapTupleTableSlot
 typedef struct MinimalTupleTableSlot
 {
 	TupleTableSlot base;
+#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
 	HeapTuple	tuple;		/* tuple wrapper */
 	MinimalTuple mintuple;	/* minimal tuple, or NULL if none */
 	HeapTupleData minhdr;	/* workspace for minimal-tuple-only case */
+#define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
 	uint32		off;		/* saved state for slot_deform_tuple */
 } MinimalTupleTableSlot;
 
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index b0093db49d7..da2f088cd31 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -65,6 +65,8 @@ extern LLVMTypeRef TypeStorageBool;
 extern LLVMTypeRef StructtupleDesc;
 extern LLVMTypeRef StructHeapTupleData;
 extern LLVMTypeRef StructTupleTableSlot;
+extern LLVMTypeRef StructHeapTupleTableSlot;
+extern LLVMTypeRef StructMinimalTupleTableSlot;
 extern LLVMTypeRef StructMemoryContextData;
 extern LLVMTypeRef StructFunctionCallInfoData;
 extern LLVMTypeRef StructExprContext;
@@ -111,7 +113,8 @@ extern void llvm_inline(LLVMModuleRef mod);
  ****************************************************************************
  */
 extern bool llvm_compile_expr(struct ExprState *state);
-extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc, int natts);
+struct TupleTableSlotOps;
+extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc, const struct TupleTableSlotOps *ops, int natts);
 
 /*
  ****************************************************************************
-- 
2.18.0.rc2.dirty

#18Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Andres Freund (#17)
1 attachment(s)
Re: TupleTableSlot abstraction

On Sat, Aug 18, 2018 at 8:53 PM, Andres Freund <andres@anarazel.de> wrote:

On 2018-08-17 01:07:06 -0700, Andres Freund wrote:

Hi,

On 2018-08-17 12:10:20 +0530, Ashutosh Bapat wrote:

We need to add LLVM code to fetch tts_flags and
perform bit operation on it to get or set slow property. I haven't
found any precedence for LLVM bit operations in postgresql's JIT code.

There are several, look for the infomask accesses in
slot_compiler_deform.

I'll try to do the adaption later today.

Attached is a series of patches doing so. The previous implementation
of sysvar accesses wasn't actually working - the slot argument was
uninitialized.

Sorry for that. I couldn't test it since the code wasn't compiling.
The changes to slot_compile_deform changes you provided in the patch
fix the compilation errors. Thanks for those changes.

I also noticed an independent issue in your changes to
ExecInitScanTupleSlot(): You can't assume that the plan belonging to the
ScanState have a Scan node in their plan. Look e.g. at Material, Sort
etc. So currently your scanrelid access is often just uninitialized
data.

I have incorporated changes in your patches into the relevant patches
in the updated patch-set. With this patch-set make check-world passes
for me.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v8.tar.zipapplication/zip; name=pg_abstract_tts_patches_v8.tar.zipDownload
#19Andres Freund
andres@anarazel.de
In reply to: Ashutosh Bapat (#18)
Re: TupleTableSlot abstraction

On 2018-08-20 17:51:38 +0530, Ashutosh Bapat wrote:

I also noticed an independent issue in your changes to
ExecInitScanTupleSlot(): You can't assume that the plan belonging to the
ScanState have a Scan node in their plan. Look e.g. at Material, Sort
etc. So currently your scanrelid access is often just uninitialized
data.

I have incorporated changes in your patches into the relevant patches
in the updated patch-set. With this patch-set make check-world passes
for me.

Have you addressed the issue I commented on above?

Greetings,

Andres Freund

#20Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Andres Freund (#19)
1 attachment(s)
Re: TupleTableSlot abstraction

On Mon, Aug 20, 2018 at 5:58 PM, Andres Freund <andres@anarazel.de> wrote:

On 2018-08-20 17:51:38 +0530, Ashutosh Bapat wrote:

I also noticed an independent issue in your changes to
ExecInitScanTupleSlot(): You can't assume that the plan belonging to the
ScanState have a Scan node in their plan. Look e.g. at Material, Sort
etc. So currently your scanrelid access is often just uninitialized
data.

I have incorporated changes in your patches into the relevant patches
in the updated patch-set. With this patch-set make check-world passes
for me.

Have you addressed the issue I commented on above?

Sorry, forgot about that. Here's the patch set with that addressed.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v9.tar.zipapplication/zip; name=pg_abstract_tts_patches_v9.tar.zipDownload
#21Andres Freund
andres@anarazel.de
In reply to: Ashutosh Bapat (#20)
Re: TupleTableSlot abstraction

Hi,

On 2018-08-20 19:51:33 +0530, Ashutosh Bapat wrote:

Sorry, forgot about that. Here's the patch set with that addressed.

Btw, you attach files as tar.zip, but they're actually gzip
compressed...

From 838a463646a048b3dccff95079a514fdc86effb3 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 13 Aug 2018 11:27:57 +0530
Subject: [PATCH 01/11] Split ExecStoreTuple into ExecStoreHeapTuple and
ExecStoreBufferHeapTuple

ExecStoreTuple() accepts a heap tuple from a buffer or constructed
on-the-fly. In the first case the caller passed a valid buffer and in
the later case it passes InvalidBuffer. In the first case,
ExecStoreTuple() pins the given buffer and in the later case it
records shouldFree flag. The function has some extra checks to
differentiate between the two cases. The usecases never overlap thus
spending extra cycles in checks is useless. Hence separate these
usecases into separate functions ExecStoreHeapTuple() to store
on-the-fly tuple and ExecStoreBufferHeapTuple() to store an on-disk
tuple from a buffer. This allows to shave some extra cycles while
storing a tuple in the slot.

It doesn't *yet* allow shaving extra cycles, no?

*	 SLOT ACCESSORS
*		ExecSetSlotDescriptor	- set a slot's tuple descriptor
- *		ExecStoreTuple			- store a physical tuple in the slot
+ *		ExecStoreHeapTuple		- store an on-the-fly heap tuple in the slot
+ *		ExecStoreBufferHeapTuple - store an on-disk heap tuple in the slot
*		ExecStoreMinimalTuple	- store a minimal physical tuple in the slot
*		ExecClearTuple			- clear contents of a slot
*		ExecStoreVirtualTuple	- mark slot as containing a virtual
*		tuple

I'd advocate for a separate patch ripping these out, they're almost
always out of date.

/* --------------------------------
- *		ExecStoreTuple
+ *		ExecStoreHeapTuple
*
- *		This function is used to store a physical tuple into a specified
+ *		This function is used to store an on-the-fly physical tuple into a specified
*		slot in the tuple table.
*
*		tuple:	tuple to store
*		slot:	slot to store it in
- *		buffer: disk buffer if tuple is in a disk page, else InvalidBuffer
*		shouldFree: true if ExecClearTuple should pfree() the tuple
*					when done with it
*
- * If 'buffer' is not InvalidBuffer, the tuple table code acquires a pin
- * on the buffer which is held until the slot is cleared, so that the tuple
- * won't go away on us.
+ * shouldFree is normally set 'true' for tuples constructed on-the-fly.  But it
+ * can be 'false' when the referenced tuple is held in a tuple table slot
+ * belonging to a lower-level executor Proc node.  In this case the lower-level
+ * slot retains ownership and responsibility for eventually releasing the
+ * tuple.  When this method is used, we must be certain that the upper-level
+ * Proc node will lose interest in the tuple sooner than the lower-level one
+ * does!  If you're not certain, copy the lower-level tuple with heap_copytuple
+ * and let the upper-level table slot assume ownership of the copy!
+ *
+ * Return value is just the passed-in slot pointer.
+ * --------------------------------
+ */
+TupleTableSlot *
+ExecStoreHeapTuple(HeapTuple tuple,
+				   TupleTableSlot *slot,
+				   bool shouldFree)
+{
+	/*
+	 * sanity checks
+	 */
+	Assert(tuple != NULL);
+	Assert(slot != NULL);
+	Assert(slot->tts_tupleDescriptor != NULL);
+
+	/*
+	 * Free any old physical tuple belonging to the slot.
+	 */
+	if (slot->tts_shouldFree)
+		heap_freetuple(slot->tts_tuple);
+	if (slot->tts_shouldFreeMin)
+		heap_free_minimal_tuple(slot->tts_mintuple);
+
+	/*
+	 * Store the new tuple into the specified slot.
+	 */
+	slot->tts_isempty = false;
+	slot->tts_shouldFree = shouldFree;
+	slot->tts_shouldFreeMin = false;
+	slot->tts_tuple = tuple;
+	slot->tts_mintuple = NULL;
+
+	/* Mark extracted state invalid */
+	slot->tts_nvalid = 0;
+
+	return slot;
+}

Uh, there could very well be a buffer previously stored in the slot, no?
This can't currently be applied independently afaict.

From c4c55bc0d501400ffca2e7393039b2d38660cd2d Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 13 Aug 2018 11:27:57 +0530
Subject: [PATCH 02/11] tts_nvalid in TupleTableSlot is AttrNumber

@@ -125,7 +125,7 @@ typedef struct TupleTableSlot
MemoryContext tts_mcxt;		/* slot itself is in this context */
Buffer		tts_buffer;		/* tuple's buffer, or InvalidBuffer */
#define FIELDNO_TUPLETABLESLOT_NVALID 9
-	int			tts_nvalid;		/* # of valid values in tts_values */
+	AttrNumber	tts_nvalid;		/* # of valid values in tts_values */
#define FIELDNO_TUPLETABLESLOT_VALUES 10
Datum	   *tts_values;		/* current per-attribute values */
#define FIELDNO_TUPLETABLESLOT_ISNULL 11

Shouldn't this be adapting at least a *few* more things, like
slot_getattr's argument?

/*
- * Fill in missing values for a TupleTableSlot.
- *
- * This is only exposed because it's needed for JIT compiled tuple
- * deforming. That exception aside, there should be no callers outside of this
- * file.
- */
-void
-slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
-{
- AttrMissing *attrmiss = NULL;
- int missattnum;
-
- if (slot->tts_tupleDescriptor->constr)
- attrmiss = slot->tts_tupleDescriptor->constr->missing;
-
- if (!attrmiss)
- {
- /* no missing values array at all, so just fill everything in as NULL */
- memset(slot->tts_values + startAttNum, 0,
- (lastAttNum - startAttNum) * sizeof(Datum));
- memset(slot->tts_isnull + startAttNum, 1,
- (lastAttNum - startAttNum) * sizeof(bool));
- }
- else
- {
- /* if there is a missing values array we must process them one by one */
- for (missattnum = startAttNum;
- missattnum < lastAttNum;
- missattnum++)
- {
- slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
- slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
- }
- }
-}

I would split out these moves into a separate commit, they are trivially
committable separately. The commit's pretty big already, and that'd make
it easier to see the actual differences.

-
-/*
* heap_compute_data_size
*		Determine size of the data area of a tuple to be constructed
*/
@@ -1407,10 +1370,9 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
*		re-computing information about previously extracted attributes.
*		slot->tts_nvalid is the number of attributes already extracted.
*/
-static void
-slot_deform_tuple(TupleTableSlot *slot, int natts)
+void
+slot_deform_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts)
{

This should be renamed to include "heap" in the name, as it's not going
to be usable for, say, zheap.

-/*
- * slot_getsysattr
- * This function fetches a system attribute of the slot's current tuple.
- * Unlike slot_getattr, if the slot does not contain system attributes,
- * this will return false (with a NULL attribute value) instead of
- * throwing an error.
- */
-bool
-slot_getsysattr(TupleTableSlot *slot, int attnum,
- Datum *value, bool *isnull)
-{
- HeapTuple tuple = slot->tts_tuple;
-
- Assert(attnum < 0); /* else caller error */
- if (tuple == NULL ||
- tuple == &(slot->tts_minhdr))
- {
- /* No physical tuple, or minimal tuple, so fail */
- *value = (Datum) 0;
- *isnull = true;
- return false;
- }
- *value = heap_getsysattr(tuple, attnum, slot->tts_tupleDescriptor, isnull);
- return true;
-}

I think I was wrong at saying that we should remove this. I think you
were right that it should become a callback...

+/*
+ * This is a function used by all getattr() callbacks which deal with a heap
+ * tuple or some tuple format which can be represented as a heap tuple e.g. a
+ * minimal tuple.
+ *
+ * heap_getattr considers any attnum beyond the attributes available in the
+ * tuple as NULL. This function however returns the values of missing
+ * attributes from the tuple descriptor in that case. Also this function does
+ * not support extracting system attributes.
+ *
+ * If the attribute needs to be fetched from the tuple, the function fills in
+ * tts_values and tts_isnull arrays upto the required attnum.
+ */
+Datum
+tts_heap_getattr_common(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+						int attnum, bool *isnull)
+{
+	HeapTupleHeader tup = tuple->t_data;
+	Assert(slot->tts_nvalid < attnum);
+
+	Assert(attnum > 0);
+
+	if (attnum > HeapTupleHeaderGetNatts(tup))
+		return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
+
+	/*
+	 * check if target attribute is null: no point in groveling through tuple
+	 */
+	if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
+	{
+		*isnull = true;
+		return (Datum) 0;
+	}

I still think this is an optimization with a negative benefit,
especially as it requires an extra callback. We should just rely on
slot_deform_tuple and then access that. That'll also just access the
null bitmap for the relevant column, and it'll make successive accesses
cheaper.

@@ -2883,7 +2885,7 @@ CopyFrom(CopyState cstate)
if (slot == NULL)	/* "do nothing" */
skip_tuple = true;
else				/* trigger might have changed tuple */
-				tuple = ExecMaterializeSlot(slot);
+				tuple = ExecFetchSlotTuple(slot, true);
}

Could we do the Materialize vs Fetch vs Copy change separately?

diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index e1eb7c3..9957c70 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -484,7 +484,7 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
* get the heap tuple out of the tuple table slot, making sure we have a
* writable copy
*/
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecCopySlotTuple(slot);

heap_insert(myState->transientrel,
tuple,
@@ -494,6 +494,9 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)

/* We know this is a newly created relation, so there are no indexes */

+	/* Free the copied tuple. */
+	heap_freetuple(tuple);
+
return true;
}

This'll potentially increase a fair amount of extra allocation overhead,
no?

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 9d6e25a..1b4e726 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -490,54 +490,21 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_INNER_SYSVAR)
{
-			int			attnum = op->d.var.attnum;
-			Datum		d;
-
-			/* these asserts must match defenses in slot_getattr */
-			Assert(innerslot->tts_tuple != NULL);
-			Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
-
-			/* heap_getsysattr has sufficient defenses against bad attnums */
-			d = heap_getsysattr(innerslot->tts_tuple, attnum,
-								innerslot->tts_tupleDescriptor,
-								op->resnull);
-			*op->resvalue = d;
+			ExecEvalSysVar(state, op, econtext, innerslot);

Please split this out into a separate patch.

+/*
+ * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
+ */
+
+static void
+tts_buffer_init(TupleTableSlot *slot)
+{
+}

Should rename these to buffer_heap or such.

+/*
+ * Store the given tuple into the given BufferHeapTupleTableSlot and pin the
+ * given buffer. If the tuple already contained in the slot can be freed free
+ * it.
+ */
+static void
+tts_buffer_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	if (IS_TTS_SHOULDFREE(slot))
+	{
+		/*
+		 * A heap tuple stored in a BufferHeapTupleTableSlot should have a
+		 * buffer associated with it, unless it's materialized.
+		 */
+		Assert(!BufferIsValid(bslot->buffer));
+
+		heap_freetuple(bslot->base.tuple);
+		RESET_TTS_SHOULDFREE(slot);
+	}
+
+	RESET_TTS_EMPTY(slot);
+	slot->tts_nvalid = 0;
+	bslot->base.tuple = tuple;
+	bslot->base.off = 0;
+
+	/*
+	 * If tuple is on a disk page, keep the page pinned as long as we hold a
+	 * pointer into it.  We assume the caller already has such a pin.
+	 *
+	 * This is coded to optimize the case where the slot previously held a
+	 * tuple on the same disk page: in that case releasing and re-acquiring
+	 * the pin is a waste of cycles.  This is a common situation during
+	 * seqscans, so it's worth troubling over.
+	 */
+	if (bslot->buffer != buffer)
+	{
+		if (BufferIsValid(bslot->buffer))
+			ReleaseBuffer(bslot->buffer);
+		bslot->buffer = buffer;
+		IncrBufferRefCount(buffer);
+	}
+}

This needs to also support storing a non-buffer tuple, I think.

+/*
+ * TupleTableSlotOps for each of TupleTableSlotTypes. These are used to
+ * identify the type of slot.
+ */
+const TupleTableSlotOps TTSOpsVirtual = {
+	sizeof(TupleTableSlot),
+	tts_virtual_init,
+	tts_virtual_release,
+	tts_virtual_clear,
+	tts_virtual_getsomeattrs,
+	tts_virtual_attisnull,
+	tts_virtual_getattr,
+	tts_virtual_materialize,
+	tts_virtual_copyslot,
+
+	/*
+	 * A virtual tuple table slot can not "own" a heap tuple or a minimal
+	 * tuple.
+	 */
+	NULL,
+	NULL,
+	tts_virtual_copy_heap_tuple,
+	tts_virtual_copy_minimal_tuple,
+};

As we're now going to require C99, could you convert these into
designated initializer style (i.e. .init = tts_heap_init etc)?

@@ -353,25 +1285,9 @@ ExecStoreHeapTuple(HeapTuple tuple,
Assert(slot != NULL);
Assert(slot->tts_tupleDescriptor != NULL);

-	/*
-	 * Free any old physical tuple belonging to the slot.
-	 */
-	if (IS_TTS_SHOULDFREE(slot))
-		heap_freetuple(slot->tts_tuple);
-	if (IS_TTS_SHOULDFREEMIN(slot))
-		heap_free_minimal_tuple(slot->tts_mintuple);
-
-	/*
-	 * Store the new tuple into the specified slot.
-	 */
-	RESET_TTS_EMPTY(slot);
-	shouldFree ? SET_TTS_SHOULDFREE(slot) : RESET_TTS_SHOULDFREE(slot);
-	RESET_TTS_SHOULDFREEMIN(slot);
-	slot->tts_tuple = tuple;
-	slot->tts_mintuple = NULL;
-
-	/* Mark extracted state invalid */
-	slot->tts_nvalid = 0;
+	if (!TTS_IS_HEAPTUPLE(slot))
+		elog(ERROR, "trying to store a heap tuple into wrong type of slot");
+	tts_heap_store_tuple(slot, tuple, shouldFree);

return slot;
}

This should allow for buffer tuples too.

@@ -983,9 +1595,10 @@ ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
* ----------------
*/
TupleTableSlot *
-ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
+ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
+					  const TupleTableSlotOps *tts_cb)
{
-	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType);
+	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_cb);

return ExecStoreAllNullTuple(slot);
}

It's a bit weird that the type name is *Ops but the param is tts_cb, no?

@@ -1590,7 +1590,8 @@ ExecHashTableInsert(HashJoinTable hashtable,
TupleTableSlot *slot,
uint32 hashvalue)
{
-	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+	bool		shouldFree;
+	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
int			bucketno;
int			batchno;
@@ -1664,6 +1665,9 @@ ExecHashTableInsert(HashJoinTable hashtable,
hashvalue,
&hashtable->innerBatchFile[batchno]);
}
+
+	if (shouldFree)
+		heap_free_minimal_tuple(tuple);
}

Hm, how about splitting these out?

@@ -277,10 +277,32 @@ ExecInsert(ModifyTableState *mtstate,
OnConflictAction onconflict = node->onConflictAction;

/*
-	 * get the heap tuple out of the tuple table slot, making sure we have a
-	 * writable copy
+	 * Get the heap tuple out of the tuple table slot, making sure we have a
+	 * writable copy.
+	 *
+	 * If the slot can contain a heap tuple, materialize the tuple within the
+	 * slot itself so that the slot "owns" it and any changes to the tuple
+	 * reflect in the slot as well.
+	 *
+	 * Otherwise, store the copy of the heap tuple in es_dml_input_tuple_slot, which
+	 * is assumed to be able to hold a heap tuple, so that repeated requests
+	 * for heap tuple in the following code will not create multiple copies and
+	 * leak memory. Also keeping the tuple in the slot makes sure that it will
+	 * be freed when it's no more needed either because a trigger modified it
+	 * or when we are done processing it.
*/
-	tuple = ExecMaterializeSlot(slot);
+	if (!(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot)))
+	{
+		TupleTableSlot *es_slot = estate->es_dml_input_tuple_slot;
+
+		Assert(es_slot && TTS_IS_HEAPTUPLE(es_slot));
+		if (es_slot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
+			ExecSetSlotDescriptor(es_slot, slot->tts_tupleDescriptor);
+		ExecCopySlot(es_slot, slot);
+		slot = es_slot;
+	}
+
+	tuple = ExecFetchSlotTuple(slot, true);

I strongly dislike this. Could you look at my pluggable storage tree
and see whether you could do something similar here?

@@ -2402,8 +2454,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
*/
mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);

-		/* Set up a slot for the output of the RETURNING projection(s) */
-		ExecInitResultTupleSlotTL(estate, &mtstate->ps);
+		/*
+		 * Set up a slot for the output of the RETURNING projection(s).
+		 * ExecDelete() requies the contents of the slot to be
+		 * saved/materialized, so use heap tuple table slot for a DELETE.
+		 * Otherwise a virtual tuple table slot suffices.
+		 */
+		ExecInitResultTupleSlotTL(estate, &mtstate->ps,
+								  operation == CMD_DELETE ?
+								  &TTSOpsHeapTuple : &TTSOpsVirtual);
slot = mtstate->ps.ps_ResultTupleSlot;

I'm not clear on why this this the case?

/* Need a
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index ecdbe7f..ea2858b 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -56,11 +56,28 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
HeapTuple	tuple;
shm_mq_result result;
+	bool		tuple_copied = false;
+
+	/* Get the tuple out of slot, if necessary converting the slot's contents
+	 * into a heap tuple by copying. In the later case we need to free the copy.
+	 */
+	if (TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot))
+	{
+		tuple = ExecFetchSlotTuple(slot, true);
+		tuple_copied = false;
+	}
+	else
+	{
+		tuple = ExecCopySlotTuple(slot);
+		tuple_copied = true;
+	}

To me needing this if() here is a bad sign, I think we want a
ExecFetchSlotTuple* like api with a bool *shouldFree arg, like you did
for minimal tuples instead.

diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 66cc5c3..b44438b 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -1071,7 +1071,7 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count,
uint64		current_tuple_count = 0;
TupleTableSlot *slot;
-	slot = MakeSingleTupleTableSlot(portal->tupDesc);
+	slot = MakeSingleTupleTableSlot(portal->tupDesc, &TTSOpsMinimalTuple);

dest->rStartup(dest, CMD_SELECT, portal->tupDesc);

These fairly rote changes make it really hard to see the actual meat of
the changes in the patch. I think one way to address that would be to
introduce stub &TTSOps* variables, add them to MakeSingleTupleTableSlot
etc, but still have them return the "old style" slots. Then that can be
reviewed separately.

@@ -1375,9 +1376,9 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
* previous row available for comparisons.  This is accomplished by
* swapping the slot pointer variables after each row.
*/
-	extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc);
+	extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc,
+										 &TTSOpsMinimalTuple);
slot2 = extraslot;
-
/* iterate till we find the hypothetical row */
while (tuplesort_gettupleslot(osastate->sortstate, true, true, slot,
&abbrevVal))

superflous change.

diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index 5560a3e..ba98908 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -1073,6 +1073,13 @@ tuplestore_gettuple(Tuplestorestate *state, bool forward,
* pointer to a tuple held within the tuplestore.  The latter is more
* efficient but the slot contents may be corrupted if additional writes to
* the tuplestore occur.  (If using tuplestore_trim, see comments therein.)
+ *
+ * If the given slot can not contain a minimal tuple, the given minimal tuple
+ * is converted into the form that the given slot can contain. Irrespective of
+ * the value of copy, that conversion might need to create a copy. If
+ * should_free is set to true by tuplestore_gettuple(), the minimal tuple is
+ * freed after the conversion, if necessary. Right now, the function only
+ * supports slots of type HeapTupleTableSlot, other than MinimalTupleTableSlot.
*/
bool
tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
@@ -1085,12 +1092,25 @@ tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
if (tuple)
{
-		if (copy && !should_free)
+		if (TTS_IS_MINIMALTUPLE(slot))
{
-			tuple = heap_copy_minimal_tuple(tuple);
+			if (copy && !should_free)
+			{
+				tuple = heap_copy_minimal_tuple(tuple);
+				should_free = true;
+			}
+			ExecStoreMinimalTuple(tuple, slot, should_free);
+		}
+		else if (TTS_IS_HEAPTUPLE(slot))
+		{
+			HeapTuple htup = heap_tuple_from_minimal_tuple(tuple);
+
+			if (should_free)
+				heap_free_minimal_tuple(tuple);
should_free = true;
+
+			ExecStoreHeapTuple(htup, slot, should_free);
}
-		ExecStoreMinimalTuple(tuple, slot, should_free);
return true;
}
else

Why is this a good idea? Shouldn't the caller always have a minimal slot
here? This is problematic, because it means this'd need adapting for
every new slot type, which'd be kinda against the idea of the whole
thing...

+#define TTS_IS_VIRTUAL(slot) ((slot)->tts_cb == &TTSOpsVirtual)
+#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_cb == &TTSOpsHeapTuple)
+#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_cb == &TTSOpsMinimalTuple)
+#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_cb == &TTSOpsBufferTuple)
+
+extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);

this is a weird place for the function protoype?

+/* TupleTableSlotType specific routines */
+typedef struct TupleTableSlotOps
+{
+	/* Minimum size of the slot */
+	size_t			base_slot_size;
+
+	/* Initialization. */
+	void (*init)(TupleTableSlot *slot);
+
+	/* Destruction. */
+	void (*release)(TupleTableSlot *slot);
+
+	/*
+	 * Clear the contents of the slot. Only the contents are expected to be
+	 * cleared and not the tuple descriptor. Typically an implementation of
+	 * this callback should free the memory allocated for the tuple contained
+	 * in the slot.
+	 */
+	void (*clear)(TupleTableSlot *slot);
+
+	/*
+	 * Fill up first natts entries of tts_values and tts_isnull arrays with
+	 * values from the tuple contained in the slot. The function may be called
+	 * with natts more than the number of attributes available in the tuple, in
+	 * which case it should fill up as many entries as the number of available
+	 * attributes. The callback should update tts_nvalid with number of entries
+	 * filled up.
+	 */
+	void (*getsomeattrs)(TupleTableSlot *slot, int natts);
+
+	/*
+	 * Returns true if the attribute given by attnum is NULL, return false
+	 * otherwise. Some slot types may have more efficient methods to return
+	 * NULL-ness of a given attribute compared to checking NULL-ness after
+	 * calling getsomeattrs(). So this is a separate callback. We expect this
+	 * callback to be invoked by slot_attisnull() only. That function returns
+	 * if the information is available readily e.g. in tts_isnull array.  The
+	 * callback need not repeat the same.
+	 */
+	bool (*attisnull)(TupleTableSlot *slot, int attnum);
+
+	/*
+	 * Returns value of the given attribute as a datum and sets isnull to
+	 * false, if it's not NULL. If the attribute is NULL, it sets isnull to
+	 * true. Some slot types may have more efficient methods to return value of
+	 * a given attribute rather than returning the attribute value from
+	 * tts_values and tts_isnull after calling getsomeattrs(). So this is a
+	 * separate callback. We expect this callback to be invoked by
+	 * slot_getattr() only. That function returns if the information is
+	 * available readily e.g. in tts_values and tts_isnull array or can be
+	 * inferred from tuple descriptor.  The callback need not repeat the same.
+	 */
+	Datum (*getattr)(TupleTableSlot *slot, int attnum, bool *isnull);

These two really show go.

+/* virtual or base type */
+struct TupleTableSlot
{
NodeTag		type;
#define FIELDNO_TUPLETABLESLOT_FLAGS 1
-	uint16		tts_flags;		/* Boolean states */
-#define FIELDNO_TUPLETABLESLOT_TUPLE 2
-	HeapTuple	tts_tuple;		/* physical tuple, or NULL if virtual */
-#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 3
-	TupleDesc	tts_tupleDescriptor;	/* slot's tuple descriptor */
-	MemoryContext tts_mcxt;		/* slot itself is in this context */
-	Buffer		tts_buffer;		/* tuple's buffer, or InvalidBuffer */
-#define FIELDNO_TUPLETABLESLOT_NVALID 6
+	uint16		tts_flags;
+#define FIELDNO_TUPLETABLESLOT_NVALID 2
AttrNumber	tts_nvalid;		/* # of valid values in tts_values */
-#define FIELDNO_TUPLETABLESLOT_VALUES 7
+
+	const TupleTableSlotOps *const tts_cb;
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
+	TupleDesc	tts_tupleDescriptor;	/* slot's tuple descriptor */
+#define FIELDNO_TUPLETABLESLOT_VALUES 5
Datum	   *tts_values;		/* current per-attribute values */
-#define FIELDNO_TUPLETABLESLOT_ISNULL 8
+#define FIELDNO_TUPLETABLESLOT_ISNULL 6
bool	   *tts_isnull;		/* current per-attribute isnull flags */
-	MinimalTuple tts_mintuple;	/* minimal tuple, or NULL if none */
-	HeapTupleData tts_minhdr;	/* workspace for minimal-tuple-only case */
-#define FIELDNO_TUPLETABLESLOT_OFF 11
-	uint32		tts_off;		/* saved state for slot_deform_tuple */
-} TupleTableSlot;
-#define TTS_HAS_PHYSICAL_TUPLE(slot)  \
-	((slot)->tts_tuple != NULL && (slot)->tts_tuple != &((slot)->tts_minhdr))
+	/* can we optimize away? */
+	MemoryContext tts_mcxt;		/* slot itself is in this context */
+};

the "can we" comment above is pretty clearly wrong, I think (Yes, I made
it...).

From 84046126d5b8c9d780cb7134048cc717bda462a8 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 13 Aug 2018 11:27:57 +0530
Subject: [PATCH 07/11] Reset expression context just after resetting per tuple
context in ExecModifyTable().

Expression context saved in ps_ExprContext for ModifyTable node is
used to process returning clause and on conflict clause. For every
processed tuple it's reset in ExecProcessReturning() and
ExecOnConflictUpdate(). When a query has both RETURNING and ON
CONFLICT clauses, the reset happens twice and the first one of those
might reset memory used by the other. For some reason this doesn't
show up on HEAD, but is apparent when virtual tuple table slots, which
do not copy the datums in its own memory, are used for tuples returned
by RETURNING clause.

This is fix for a query failing in sql/insert_conflict.sql

insert into insertconflicttest as i values (23, 'Avocado') on conflict (key) do update set fruit = excluded.*::text
returning *;

Ashutosh Bapat, per suggestion by Andres Freund

Doesn't this have to be earlier in the series?

Phew, sorry if some things are daft, I'm kinda jetlagged...

- Andres

#22Ashutosh Bapat
ashutosh.bapat@enterprisedb.com
In reply to: Andres Freund (#21)
1 attachment(s)
Re: TupleTableSlot abstraction

On Fri, Aug 24, 2018 at 6:46 AM, Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2018-08-20 19:51:33 +0530, Ashutosh Bapat wrote:

Sorry, forgot about that. Here's the patch set with that addressed.

Btw, you attach files as tar.zip, but they're actually gzip
compressed...

I am using "tar -zcvf" to create the files where -z indicates gzip.
But if I use .gz as extension for some reason it's not able to
recognize the format. So, I just keep .zip. Do you see any problem
with that extension? The attached file has extension .tar.gz.

From 838a463646a048b3dccff95079a514fdc86effb3 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 13 Aug 2018 11:27:57 +0530
Subject: [PATCH 01/11] Split ExecStoreTuple into ExecStoreHeapTuple and
ExecStoreBufferHeapTuple

ExecStoreTuple() accepts a heap tuple from a buffer or constructed
on-the-fly. In the first case the caller passed a valid buffer and in
the later case it passes InvalidBuffer. In the first case,
ExecStoreTuple() pins the given buffer and in the later case it
records shouldFree flag. The function has some extra checks to
differentiate between the two cases. The usecases never overlap thus
spending extra cycles in checks is useless. Hence separate these
usecases into separate functions ExecStoreHeapTuple() to store
on-the-fly tuple and ExecStoreBufferHeapTuple() to store an on-disk
tuple from a buffer. This allows to shave some extra cycles while
storing a tuple in the slot.

It doesn't *yet* allow shaving extra cycles, no?

By segregating those two functions we are already saving some cycles
by not checking for a valid buffer for an on the fly tuple. That's not
huge but some. More saving will come with the complete abstraction.

*      SLOT ACCESSORS
*           ExecSetSlotDescriptor   - set a slot's tuple descriptor
- *           ExecStoreTuple                  - store a physical tuple in the slot
+ *           ExecStoreHeapTuple              - store an on-the-fly heap tuple in the slot
+ *           ExecStoreBufferHeapTuple - store an on-disk heap tuple in the slot
*           ExecStoreMinimalTuple   - store a minimal physical tuple in the slot
*           ExecClearTuple                  - clear contents of a slot
*           ExecStoreVirtualTuple   - mark slot as containing a virtual
*           tuple

I'd advocate for a separate patch ripping these out, they're almost
always out of date.

Done. Added as 0001 patch.

+ * Return value is just the passed-in slot pointer.
+ * --------------------------------
+ */
+TupleTableSlot *
+ExecStoreHeapTuple(HeapTuple tuple,
+                                TupleTableSlot *slot,
+                                bool shouldFree)
+{
+
+     return slot;
+}

Uh, there could very well be a buffer previously stored in the slot, no?
This can't currently be applied independently afaict.

Sorry, I missed that when splitting the function. Added code to unpin
any buffer that was pinned for an earlier tuple.

From c4c55bc0d501400ffca2e7393039b2d38660cd2d Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 13 Aug 2018 11:27:57 +0530
Subject: [PATCH 02/11] tts_nvalid in TupleTableSlot is AttrNumber

@@ -125,7 +125,7 @@ typedef struct TupleTableSlot
MemoryContext tts_mcxt;         /* slot itself is in this context */
Buffer          tts_buffer;             /* tuple's buffer, or InvalidBuffer */
#define FIELDNO_TUPLETABLESLOT_NVALID 9
-     int                     tts_nvalid;             /* # of valid values in tts_values */
+     AttrNumber      tts_nvalid;             /* # of valid values in tts_values */
#define FIELDNO_TUPLETABLESLOT_VALUES 1
Datum      *tts_values;         /* current per-attribute values */
#define FIELDNO_TUPLETABLESLOT_ISNULL 11

Shouldn't this be adapting at least a *few* more things, like
slot_getattr's argument?

That's not something I had in mind for this patch. There are many
other places where we declare attribute number variables as "int"
instead of "AttrNumber". I don't think that's what we should do in
this patch set. The idea of this patch is to reduce the size of
TupleTableSlot by 2 bytes. Changing signatures of the functions,
though has some readability improvement, doesn't achieve any such
benefit.

Even then I went ahead and change signatures of those functions, but
server built with LLVM crashed. So, I have reverted back all those
changes. I think we should change the JIT code automatically when
function signatures/structure definitions change OR at least
compilation should fail indicating the difference between JIT code and
normal code. Investigating a crash takes a hell lot of time and is not
easy without a custom LLVM build. I doubt if every PostgreSQL
developer would want to do that.

/*
- * Fill in missing values for a TupleTableSlot.
- *
- * This is only exposed because it's needed for JIT compiled tuple
- * deforming. That exception aside, there should be no callers outside of this
- * file.
- */
-void
-slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
-{
- AttrMissing *attrmiss = NULL;
- int missattnum;
-
- if (slot->tts_tupleDescriptor->constr)
- attrmiss = slot->tts_tupleDescriptor->constr->missing;
-
- if (!attrmiss)
- {
- /* no missing values array at all, so just fill everything in as NULL */
- memset(slot->tts_values + startAttNum, 0,
- (lastAttNum - startAttNum) * sizeof(Datum));
- memset(slot->tts_isnull + startAttNum, 1,
- (lastAttNum - startAttNum) * sizeof(bool));
- }
- else
- {
- /* if there is a missing values array we must process them one by one */
- for (missattnum = startAttNum;
- missattnum < lastAttNum;
- missattnum++)
- {
- slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
- slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
- }
- }
-}

I would split out these moves into a separate commit, they are trivially
committable separately. The commit's pretty big already, and that'd make
it easier to see the actual differences.

I have included some of those movements in the same patch which
changes the type of tts_nvalid. Functions like slot_attisnull() are
changed to be inline static functions in tuptable.h. Those functions
are now inline since they are just wrapper around slot specific
callbacks. Thus without the TupleTableSlot abstraction patch it's not
possible to mark them "inline and thus move them to a header file e.g.
tuptable.h. For now I have left these kinds of movements in
TupleTableSlot abstraction patch.

-
-/*
* heap_compute_data_size
*           Determine size of the data area of a tuple to be constructed
*/
@@ -1407,10 +1370,9 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
*           re-computing information about previously extracted attributes.
*           slot->tts_nvalid is the number of attributes already extracted.
*/
-static void
-slot_deform_tuple(TupleTableSlot *slot, int natts)
+void
+slot_deform_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp, int natts)
{

This should be renamed to include "heap" in the name, as it's not going
to be usable for, say, zheap.

LGTM. Done.

-/*
- * slot_getsysattr
- * This function fetches a system attribute of the slot's current tuple.
- * Unlike slot_getattr, if the slot does not contain system attributes,
- * this will return false (with a NULL attribute value) instead of
- * throwing an error.
- */
-bool
-slot_getsysattr(TupleTableSlot *slot, int attnum,
- Datum *value, bool *isnull)
-{
- HeapTuple tuple = slot->tts_tuple;
-
- Assert(attnum < 0); /* else caller error */
- if (tuple == NULL ||
- tuple == &(slot->tts_minhdr))
- {
- /* No physical tuple, or minimal tuple, so fail */
- *value = (Datum) 0;
- *isnull = true;
- return false;
- }
- *value = heap_getsysattr(tuple, attnum, slot->tts_tupleDescriptor, isnull);
- return true;
-}

I think I was wrong at saying that we should remove this. I think you
were right that it should become a callback...

We have replaced all slot_getsysattrs() with heap_getsysattr(). Do you
want to reinstantiate those as well? If so, slot_getsysattr() becomes
a wrapper around getsysattr() callback.

+/*
+ * This is a function used by all getattr() callbacks which deal with a heap
+ * tuple or some tuple format which can be represented as a heap tuple e.g. a
+ * minimal tuple.
+ *
+ * heap_getattr considers any attnum beyond the attributes available in the
+ * tuple as NULL. This function however returns the values of missing
+ * attributes from the tuple descriptor in that case. Also this function does
+ * not support extracting system attributes.
+ *
+ * If the attribute needs to be fetched from the tuple, the function fills in
+ * tts_values and tts_isnull arrays upto the required attnum.
+ */
+Datum
+tts_heap_getattr_common(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+                                             int attnum, bool *isnull)
+{
+     HeapTupleHeader tup = tuple->t_data;
+     Assert(slot->tts_nvalid < attnum);
+
+     Assert(attnum > 0);
+
+     if (attnum > HeapTupleHeaderGetNatts(tup))
+             return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
+
+     /*
+      * check if target attribute is null: no point in groveling through tuple
+      */
+     if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
+     {
+             *isnull = true;
+             return (Datum) 0;
+     }

I still think this is an optimization with a negative benefit,
especially as it requires an extra callback. We should just rely on
slot_deform_tuple and then access that. That'll also just access the
null bitmap for the relevant column, and it'll make successive accesses
cheaper.

I don't understand why we have differing implementations for
slot_attisnull(), slot_getsomeattrs(), slot_getattr() in HEAD. If what
you are saying is true, we should have implemented all the first and
last as a call to slot_getsomeattrs() followed by returing values from
tts_values and tts_isnull. Since this is refactoring work, I am trying
not to change the existing functionality of those functions.

@@ -2883,7 +2885,7 @@ CopyFrom(CopyState cstate)
if (slot == NULL)       /* "do nothing" */
skip_tuple = true;
else                            /* trigger might have changed tuple */
-                             tuple = ExecMaterializeSlot(slot);
+                             tuple = ExecFetchSlotTuple(slot, true);
}

Could we do the Materialize vs Fetch vs Copy change separately?

Ok. I will do that.

diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index e1eb7c3..9957c70 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -484,7 +484,7 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
* get the heap tuple out of the tuple table slot, making sure we have a
* writable copy
*/
-     tuple = ExecMaterializeSlot(slot);
+     tuple = ExecCopySlotTuple(slot);

heap_insert(myState->transientrel,
tuple,
@@ -494,6 +494,9 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)

/* We know this is a newly created relation, so there are no indexes */

+     /* Free the copied tuple. */
+     heap_freetuple(tuple);
+
return true;
}

This'll potentially increase a fair amount of extra allocation overhead,
no?

Yes. There are two ways to avoid that 1. Using a slot type specific
for the transient rel which is receiving the tuple OR 2. Allocate
memory for the converted tuple into per tuple memory context. The
first case too will have the same problem since we will free one tuple
at at time in ExecClearSlot(). I am inclined to use second option.
Comments?

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 9d6e25a..1b4e726 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -490,54 +490,21 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_INNER_SYSVAR)
{
-                     int                     attnum = op->d.var.attnum;
-                     Datum           d;
-
-                     /* these asserts must match defenses in slot_getattr */
-                     Assert(innerslot->tts_tuple != NULL);
-                     Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
-
-                     /* heap_getsysattr has sufficient defenses against bad attnums */
-                     d = heap_getsysattr(innerslot->tts_tuple, attnum,
-                                                             innerslot->tts_tupleDescriptor,
-                                                             op->resnull);
-                     *op->resvalue = d;
+                     ExecEvalSysVar(state, op, econtext, innerslot);

Please split this out into a separate patch.

Ok. Will do (not in the attached patch-set)

+/*
+ * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
+ */
+
+static void
+tts_buffer_init(TupleTableSlot *slot)
+{
+}

Should rename these to buffer_heap or such.

Ok. Done.

+/*
+ * Store the given tuple into the given BufferHeapTupleTableSlot and pin the
+ * given buffer. If the tuple already contained in the slot can be freed free
+ * it.
+ */
+static void
+tts_buffer_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
+{
+     BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+     if (IS_TTS_SHOULDFREE(slot))
+     {
+             /*
+              * A heap tuple stored in a BufferHeapTupleTableSlot should have a
+              * buffer associated with it, unless it's materialized.
+              */
+             Assert(!BufferIsValid(bslot->buffer));
+
+             heap_freetuple(bslot->base.tuple);
+             RESET_TTS_SHOULDFREE(slot);
+     }
+
+     RESET_TTS_EMPTY(slot);
+     slot->tts_nvalid = 0;
+     bslot->base.tuple = tuple;
+     bslot->base.off = 0;
+
+     /*
+      * If tuple is on a disk page, keep the page pinned as long as we hold a
+      * pointer into it.  We assume the caller already has such a pin.
+      *
+      * This is coded to optimize the case where the slot previously held a
+      * tuple on the same disk page: in that case releasing and re-acquiring
+      * the pin is a waste of cycles.  This is a common situation during
+      * seqscans, so it's worth troubling over.
+      */
+     if (bslot->buffer != buffer)
+     {
+             if (BufferIsValid(bslot->buffer))
+                     ReleaseBuffer(bslot->buffer);
+             bslot->buffer = buffer;
+             IncrBufferRefCount(buffer);
+     }
+}

This needs to also support storing a non-buffer tuple, I think.

I don't see a reason why that's needed. A non-buffer tuple should be
stored in a HeapTupleTableSlot. It might happen that
ExecMaterializeSlot() creates a copy of the buffer tuple in the memory
context of the slot. But there should be a buffer associated with the
heap tuple being stored in BufferHeapTupleTableSlot. Otherwise, why
are we separating those two types.

In fact, as discussed earlier offline, I am of the opinion that buffer
should be an attribute of every tuple table slot which may carry tuple
from a buffer, instead of creating two slot types with and without
buffer.

OTOH, I observe that tts_buffer_store_tuple() is called only from
ExecStoreBufferHeapTuple(). We may want to merge the first into the
later.

+/*
+ * TupleTableSlotOps for each of TupleTableSlotTypes. These are used to
+ * identify the type of slot.
+ */
+const TupleTableSlotOps TTSOpsVirtual = {
+     sizeof(TupleTableSlot),
+     tts_virtual_init,
+     tts_virtual_release,
+     tts_virtual_clear,
+     tts_virtual_getsomeattrs,
+     tts_virtual_attisnull,
+     tts_virtual_getattr,
+     tts_virtual_materialize,
+     tts_virtual_copyslot,
+
+     /*
+      * A virtual tuple table slot can not "own" a heap tuple or a minimal
+      * tuple.
+      */
+     NULL,
+     NULL,
+     tts_virtual_copy_heap_tuple,
+     tts_virtual_copy_minimal_tuple,
+};

As we're now going to require C99, could you convert these into
designated initializer style (i.e. .init = tts_heap_init etc)?

That's a good idea. Done.

@@ -353,25 +1285,9 @@ ExecStoreHeapTuple(HeapTuple tuple,
Assert(slot != NULL);
Assert(slot->tts_tupleDescriptor != NULL);

-     /*
-      * Free any old physical tuple belonging to the slot.
-      */
-     if (IS_TTS_SHOULDFREE(slot))
-             heap_freetuple(slot->tts_tuple);
-     if (IS_TTS_SHOULDFREEMIN(slot))
-             heap_free_minimal_tuple(slot->tts_mintuple);
-
-     /*
-      * Store the new tuple into the specified slot.
-      */
-     RESET_TTS_EMPTY(slot);
-     shouldFree ? SET_TTS_SHOULDFREE(slot) : RESET_TTS_SHOULDFREE(slot);
-     RESET_TTS_SHOULDFREEMIN(slot);
-     slot->tts_tuple = tuple;
-     slot->tts_mintuple = NULL;
-
-     /* Mark extracted state invalid */
-     slot->tts_nvalid = 0;
+     if (!TTS_IS_HEAPTUPLE(slot))
+             elog(ERROR, "trying to store a heap tuple into wrong type of slot");
+     tts_heap_store_tuple(slot, tuple, shouldFree);

return slot;
}

This should allow for buffer tuples too.

Same answer as the answer to your comment on tts_buffer_store_tuple().

@@ -983,9 +1595,10 @@ ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
* ----------------
*/
TupleTableSlot *
-ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
+ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
+                                       const TupleTableSlotOps *tts_cb)
{
-     TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType);
+     TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_cb);

return ExecStoreAllNullTuple(slot);
}

It's a bit weird that the type name is *Ops but the param is tts_cb, no?

Your original patch used the same names and I haven't changed that. I
am fine with tts_ops as well. Is that good enough?

@@ -1590,7 +1590,8 @@ ExecHashTableInsert(HashJoinTable hashtable,
TupleTableSlot *slot,
uint32 hashvalue)
{
-     MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+     bool            shouldFree;
+     MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
int                     bucketno;
int                     batchno;
@@ -1664,6 +1665,9 @@ ExecHashTableInsert(HashJoinTable hashtable,
hashvalue,
&hashtable->innerBatchFile[batchno]);
}
+
+     if (shouldFree)
+             heap_free_minimal_tuple(tuple);
}

Hm, how about splitting these out?

Split into a separate patch? It doesn't make sense to add this patch
before 0006 since the slots in those patches can "own" a minimal
tuple. Let's add a patch after 0006 i.e. tuple table abstraction
patch. Will do.

@@ -277,10 +277,32 @@ ExecInsert(ModifyTableState *mtstate,
OnConflictAction onconflict = node->onConflictAction;

/*
-      * get the heap tuple out of the tuple table slot, making sure we have a
-      * writable copy
+      * Get the heap tuple out of the tuple table slot, making sure we have a
+      * writable copy.
+      *
+      * If the slot can contain a heap tuple, materialize the tuple within the
+      * slot itself so that the slot "owns" it and any changes to the tuple
+      * reflect in the slot as well.
+      *
+      * Otherwise, store the copy of the heap tuple in es_dml_input_tuple_slot, which
+      * is assumed to be able to hold a heap tuple, so that repeated requests
+      * for heap tuple in the following code will not create multiple copies and
+      * leak memory. Also keeping the tuple in the slot makes sure that it will
+      * be freed when it's no more needed either because a trigger modified it
+      * or when we are done processing it.
*/
-     tuple = ExecMaterializeSlot(slot);
+     if (!(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot)))
+     {
+             TupleTableSlot *es_slot = estate->es_dml_input_tuple_slot;
+
+             Assert(es_slot && TTS_IS_HEAPTUPLE(es_slot));
+             if (es_slot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
+                     ExecSetSlotDescriptor(es_slot, slot->tts_tupleDescriptor);
+             ExecCopySlot(es_slot, slot);
+             slot = es_slot;
+     }
+
+     tuple = ExecFetchSlotTuple(slot, true);

I strongly dislike this. Could you look at my pluggable storage tree
and see whether you could do something similar here?

Can you please provide the URL to your tree?

@@ -2402,8 +2454,15 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
*/
mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);

-             /* Set up a slot for the output of the RETURNING projection(s) */
-             ExecInitResultTupleSlotTL(estate, &mtstate->ps);
+             /*
+              * Set up a slot for the output of the RETURNING projection(s).
+              * ExecDelete() requies the contents of the slot to be
+              * saved/materialized, so use heap tuple table slot for a DELETE.
+              * Otherwise a virtual tuple table slot suffices.
+              */
+             ExecInitResultTupleSlotTL(estate, &mtstate->ps,
+                                                               operation == CMD_DELETE ?
+                                                               &TTSOpsHeapTuple : &TTSOpsVirtual);
slot = mtstate->ps.ps_ResultTupleSlot;

I'm not clear on why this this the case?

Do you mean why does ExecDelete() materializes the tuple? I don't
know. But my guess is materialization ensures valid tuple being
returned in case the deleted tuple's contents are destroyed.

/* Need a
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index ecdbe7f..ea2858b 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -56,11 +56,28 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
HeapTuple       tuple;
shm_mq_result result;
+     bool            tuple_copied = false;
+
+     /* Get the tuple out of slot, if necessary converting the slot's contents
+      * into a heap tuple by copying. In the later case we need to free the copy.
+      */
+     if (TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot))
+     {
+             tuple = ExecFetchSlotTuple(slot, true);
+             tuple_copied = false;
+     }
+     else
+     {
+             tuple = ExecCopySlotTuple(slot);
+             tuple_copied = true;
+     }

To me needing this if() here is a bad sign, I think we want a
ExecFetchSlotTuple* like api with a bool *shouldFree arg, like you did
for minimal tuples instead.

If we change the existing API, we will need to handle shouldFree flag
everywhere ExecFetchSlotTuple() is being called. Most of the callers
of ExecFetchSlotTuple pass tuple table slots which can "own" a heap
tuple. Your suggestion to use a separate ExecFetchSlotTuple() like API
looks good.. But I am not sure how useful it will be if there's going
to be a single caller of that API.

diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 66cc5c3..b44438b 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -1071,7 +1071,7 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count,
uint64          current_tuple_count = 0;
TupleTableSlot *slot;
-     slot = MakeSingleTupleTableSlot(portal->tupDesc);
+     slot = MakeSingleTupleTableSlot(portal->tupDesc, &TTSOpsMinimalTuple);

dest->rStartup(dest, CMD_SELECT, portal->tupDesc);

These fairly rote changes make it really hard to see the actual meat of
the changes in the patch. I think one way to address that would be to
introduce stub &TTSOps* variables, add them to MakeSingleTupleTableSlot
etc, but still have them return the "old style" slots. Then that can be
reviewed separately.

This means that we have to define TTSOps variables before the actual
abstraction patch and then redefine those in the abstraction patch
(0006). Instead we could separate changes to the slot initialization
functions in a separate patch which comes after the abstraction proper
patch. The abstraction proper patch always creates a virtual tuple
table slot. We will need to compile, test and commit both the patches
together but reviewing becomes easier. Also the tuple table
abstraction patch doesn't pass regession on its own, it requires some
patches that follow it. So it should be fine. Comments?

@@ -1375,9 +1376,9 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
* previous row available for comparisons.  This is accomplished by
* swapping the slot pointer variables after each row.
*/
-     extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc);
+     extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc,
+                                                                              &TTSOpsMinimalTuple);
slot2 = extraslot;
-
/* iterate till we find the hypothetical row */
while (tuplesort_gettupleslot(osastate->sortstate, true, true, slot,
&abbrevVal))

superflous change.

Done.

diff --git a/src/backend/utils/sort/tuplestore.c b/src/backend/utils/sort/tuplestore.c
index 5560a3e..ba98908 100644
--- a/src/backend/utils/sort/tuplestore.c
+++ b/src/backend/utils/sort/tuplestore.c
@@ -1073,6 +1073,13 @@ tuplestore_gettuple(Tuplestorestate *state, bool forward,
* pointer to a tuple held within the tuplestore.  The latter is more
* efficient but the slot contents may be corrupted if additional writes to
* the tuplestore occur.  (If using tuplestore_trim, see comments therein.)
+ *
+ * If the given slot can not contain a minimal tuple, the given minimal tuple
+ * is converted into the form that the given slot can contain. Irrespective of
+ * the value of copy, that conversion might need to create a copy. If
+ * should_free is set to true by tuplestore_gettuple(), the minimal tuple is
+ * freed after the conversion, if necessary. Right now, the function only
+ * supports slots of type HeapTupleTableSlot, other than MinimalTupleTableSlot.
*/
bool
tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
@@ -1085,12 +1092,25 @@ tuplestore_gettupleslot(Tuplestorestate *state, bool forward,
if (tuple)
{
-             if (copy && !should_free)
+             if (TTS_IS_MINIMALTUPLE(slot))
{
-                     tuple = heap_copy_minimal_tuple(tuple);
+                     if (copy && !should_free)
+                     {
+                             tuple = heap_copy_minimal_tuple(tuple);
+                             should_free = true;
+                     }
+                     ExecStoreMinimalTuple(tuple, slot, should_free);
+             }
+             else if (TTS_IS_HEAPTUPLE(slot))
+             {
+                     HeapTuple htup = heap_tuple_from_minimal_tuple(tuple);
+
+                     if (should_free)
+                             heap_free_minimal_tuple(tuple);
should_free = true;
+
+                     ExecStoreHeapTuple(htup, slot, should_free);
}
-             ExecStoreMinimalTuple(tuple, slot, should_free);
return true;
}
else

Why is this a good idea? Shouldn't the caller always have a minimal slot
here?

As I have explained in the commit message, not every caller has a
minimal slot right now. For example, AfterTriggerExecute fetches
foreign tuples from a tuple store as minimal tuples and requires those
to be in the form of heap tuple for trigger processing. We can use two
slots, first a minimal for fetching tuple from tuple store and second
a heap for trigger processing and convert from minimal tuple to heap
tuple using ExecCopySlotTuple(). That increases the number of slots.

This is problematic, because it means this'd need adapting for
every new slot type, which'd be kinda against the idea of the whole
thing...

I don't think we will need to support more slot types in than what's
there right now. But in case we have to we have two more options as
below.

Amit Khandekar suggested offlist to invoke a (new) slot type specific
callback which will convert given minimal tuple into the tuple type of
the slot.

Third option is to write tuplestore_gettupleslot* functions one for
each kind of TupleTableSlot type.

I don't have much preference for one over the other.

+#define TTS_IS_VIRTUAL(slot) ((slot)->tts_cb == &TTSOpsVirtual)
+#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_cb == &TTSOpsHeapTuple)
+#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_cb == &TTSOpsMinimalTuple)
+#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_cb == &TTSOpsBufferTuple)
+
+extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);

this is a weird place for the function protoype?

Fixed.

+/* TupleTableSlotType specific routines */
+typedef struct TupleTableSlotOps
+{
+     /* Minimum size of the slot */
+     size_t                  base_slot_size;
+
+     /* Initialization. */
+     void (*init)(TupleTableSlot *slot);
+
+     /* Destruction. */
+     void (*release)(TupleTableSlot *slot);
+
+     /*
+      * Clear the contents of the slot. Only the contents are expected to be
+      * cleared and not the tuple descriptor. Typically an implementation of
+      * this callback should free the memory allocated for the tuple contained
+      * in the slot.
+      */
+     void (*clear)(TupleTableSlot *slot);
+
+     /*
+      * Fill up first natts entries of tts_values and tts_isnull arrays with
+      * values from the tuple contained in the slot. The function may be called
+      * with natts more than the number of attributes available in the tuple, in
+      * which case it should fill up as many entries as the number of available
+      * attributes. The callback should update tts_nvalid with number of entries
+      * filled up.
+      */
+     void (*getsomeattrs)(TupleTableSlot *slot, int natts);
+
+     /*
+      * Returns true if the attribute given by attnum is NULL, return false
+      * otherwise. Some slot types may have more efficient methods to return
+      * NULL-ness of a given attribute compared to checking NULL-ness after
+      * calling getsomeattrs(). So this is a separate callback. We expect this
+      * callback to be invoked by slot_attisnull() only. That function returns
+      * if the information is available readily e.g. in tts_isnull array.  The
+      * callback need not repeat the same.
+      */
+     bool (*attisnull)(TupleTableSlot *slot, int attnum);
+
+     /*
+      * Returns value of the given attribute as a datum and sets isnull to
+      * false, if it's not NULL. If the attribute is NULL, it sets isnull to
+      * true. Some slot types may have more efficient methods to return value of
+      * a given attribute rather than returning the attribute value from
+      * tts_values and tts_isnull after calling getsomeattrs(). So this is a
+      * separate callback. We expect this callback to be invoked by
+      * slot_getattr() only. That function returns if the information is
+      * available readily e.g. in tts_values and tts_isnull array or can be
+      * inferred from tuple descriptor.  The callback need not repeat the same.
+      */
+     Datum (*getattr)(TupleTableSlot *slot, int attnum, bool *isnull);

These two really show go.

I have explained my position for this while replying to an earlier comment.

+/* virtual or base type */
+struct TupleTableSlot
{
NodeTag         type;
#define FIELDNO_TUPLETABLESLOT_FLAGS 1
-     uint16          tts_flags;              /* Boolean states */
-#define FIELDNO_TUPLETABLESLOT_TUPLE 2
-     HeapTuple       tts_tuple;              /* physical tuple, or NULL if virtual */
-#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 3
-     TupleDesc       tts_tupleDescriptor;    /* slot's tuple descriptor */
-     MemoryContext tts_mcxt;         /* slot itself is in this context */
-     Buffer          tts_buffer;             /* tuple's buffer, or InvalidBuffer */
-#define FIELDNO_TUPLETABLESLOT_NVALID 6
+     uint16          tts_flags;
+#define FIELDNO_TUPLETABLESLOT_NVALID 2
AttrNumber      tts_nvalid;             /* # of valid values in tts_values */
-#define FIELDNO_TUPLETABLESLOT_VALUES 7
+
+     const TupleTableSlotOps *const tts_cb;
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
+     TupleDesc       tts_tupleDescriptor;    /* slot's tuple descriptor */
+#define FIELDNO_TUPLETABLESLOT_VALUES 5
Datum      *tts_values;         /* current per-attribute values */
-#define FIELDNO_TUPLETABLESLOT_ISNULL 8
+#define FIELDNO_TUPLETABLESLOT_ISNULL 6
bool       *tts_isnull;         /* current per-attribute isnull flags */
-     MinimalTuple tts_mintuple;      /* minimal tuple, or NULL if none */
-     HeapTupleData tts_minhdr;       /* workspace for minimal-tuple-only case */
-#define FIELDNO_TUPLETABLESLOT_OFF 11
-     uint32          tts_off;                /* saved state for slot_deform_tuple */
-} TupleTableSlot;
-#define TTS_HAS_PHYSICAL_TUPLE(slot)  \
-     ((slot)->tts_tuple != NULL && (slot)->tts_tuple != &((slot)->tts_minhdr))
+     /* can we optimize away? */
+     MemoryContext tts_mcxt;         /* slot itself is in this context */
+};

the "can we" comment above is pretty clearly wrong, I think (Yes, I made
it...).

Removed.

From 84046126d5b8c9d780cb7134048cc717bda462a8 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Mon, 13 Aug 2018 11:27:57 +0530
Subject: [PATCH 07/11] Reset expression context just after resetting per tuple
context in ExecModifyTable().

Expression context saved in ps_ExprContext for ModifyTable node is
used to process returning clause and on conflict clause. For every
processed tuple it's reset in ExecProcessReturning() and
ExecOnConflictUpdate(). When a query has both RETURNING and ON
CONFLICT clauses, the reset happens twice and the first one of those
might reset memory used by the other. For some reason this doesn't
show up on HEAD, but is apparent when virtual tuple table slots, which
do not copy the datums in its own memory, are used for tuples returned
by RETURNING clause.

This is fix for a query failing in sql/insert_conflict.sql

insert into insertconflicttest as i values (23, 'Avocado') on conflict (key) do update set fruit = excluded.*::text
returning *;

Ashutosh Bapat, per suggestion by Andres Freund

Doesn't this have to be earlier in the series?

I have placed it later since the tuple table slot abstraction work
exposes the bug, which otherwise is not visible. But yes, we can
commit that patch before the tuple table slot abstraction proper work.

--
Best Wishes,
Ashutosh Bapat
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v10.tar.gzapplication/gzip; name=pg_abstract_tts_patches_v10.tar.gzDownload
�
��[�<ko�H��*���=`G�$��[�$'�3>��;�8M�c���T�$�����H����������Y]�]]�.�r>3�8�L;�%I<[��}#��'����3�j��z��~������p�D7F�~��>� �>�81#!����*	��*�}��E?����%2��e`.��=�$��$����(Y���j�����S/��z|���F
}��F�����~���}c<<�� �����F�B=������0{�d����5r�V4�DSq�J.�1�����@6�Sq�h$^�����f����A"�e����4;\�h�6��v����9`3&�0���O�c���}�y��~�v�T�ry|��gx|d�
����;�7E	{���W2n6��w"��A�Iqc~��#7	�NL���	S�riF0X���/e�Y������t�`.b/��^"l3�+�����a�����D
?4�"���������3���X?K���1��r��D��g��i�^�C���G�0fz$�8s�
�&�Ca���=��>�����.��tE3J�G���r���������h�|?��|4����l���<P{A�}OF��@-�$�C_/C ?6qW���ZG������N����wn�,����h�f����n���I`XG������e_4[>����v��-4[�q2��Q����94l�qdY�}+�H��a,}9����H��U�6��
n�C���(�[}�Ds��T�BG��*IT��4]1l�o���,p��0��U�:m.����L���0/�#�l���"
�8��9|�����VF<�
2����L'9
#GF��eb���$�A��j�stm���$h;Ru�M����,�.P�����o�`.���@Db�J��1���r���f��\Wt�sTZG������������SSj�t4v��9
�1�����0�==������a������@�@���r����j+����C\���h���!���TM�}�F�47����4���q�(��(����Z)�!���X���[o�DM�3��?$����j�q����w'��5�mm��exJ-�CGE&C�zKz���+��*��Hh�MT��er��<���Ab4��h�!�J/�
�2z,"?%��x�����m�-��E`�&���j��E/
m(�No�A�S��`��hL�
�x�������
��#�1��`&��WlT$��3X�Js� D�
W�H�*\����re�������v�>D����o���aY�bK��sE�:;��6��z6�F����$��E���"Dt.P�jH���3��}3�oa�p7������g��l����@)��
[mM�����B���STr� �c��^�����-s���g�LVQ4�m]�O��� 8vr	��:^������e&��Zy�CB����Y���j/K�DC�����~����Xm��d&�`�������eF���/a��KhQ��Eb�:fuJ!��������Yu�Fy���/@�i.3�D������O���z��qo�i�t8:\_�}=X\������+�B���7������b^l��X):���W`p�a��5��t)#j+�����"\v_8xi3�����=�4 8qAXI�qm�&��}�Q�_������m��Gfg
�g�r����8w���9�bT��xg��x�	���!������da�`#�H=��p8�M4m4���n�d[�c�*(d��d�J�/�QOI!P��Oq�|g���h�����H�]zz����hkp������xt9/�U�.�� j)�l^�]�0|�0�e��`0�5�t����5Y6���i38\���v0��/�t�h�@�EJ���:w�`��k��Q���++|D~��0��4��=#�J�0
��]q��4^1�s�����)wz(^a�P���hi��B�� ��6���Mi[]l�"�z"E���A��aj��Z6%��UB9��E�xl���.���(�(�,
����5��Z����d���<���i��te�8�����/���p����kJ.��2������������8r����������3lXb'+{�i&d4�
m(9C����Y)������C7���:b#
bs��o��Xl�Q�Js,�D9c�bG�&?��^��6T�?��2z���bmuT���!��b;2�rC�c�I��o�$�bz�T)��������<�"�D�b�U�X��69R��Y$�����{��|��mYa��+�����M�������,���c��6�#�7��?W	�{H�w�M9����I!��4���L�WAV��`)I�m&N���@���4�xs ����|;y
�.��E��6E�C��.O�|++f�_�������I�|@T$F�n�rXz�d!�$3�����tkD���2��:I�gl�}�S���� [xG�0=��	e����Y
�k�]Q�e��r����$��VZ��Z���n��H���#=�W����-�����@F��48��U���l�����QB�6��t���:rH-5Q���2����$�[�DW�����7�9��M�|�g���g�b�����sP����hyd�'~\�*~�cx�n�f�]�i�g:��>���������
#��]x�������~}�������zTl��Rz��W.A��5�;�B���EG ��&J�U���9v���T�E�a��s� ��g@pBD��#�����#���w0
o���|���|�)����W�0T�LyTA������y��k��$���1�wf��T:���0���5�(K���0�h�7`�u��@gj����llt����������?o������N�������G���sh��w+��{���b�q<��4)�P�l�A�P�EHe��:��4����xP�:l��c&6�I����7R��i�?�������R�.V�-@�s[�T��`��n<��XbFIe��Y�	>�$�:a��n���w��?@W�N�~����w����
)�����;?'�|��,��,��G�t���qz�
Ib����0�����Sb���x��/j�����$��i�����R����*+�����J4F�
�SM����0dM��D�G66�9�jt�t�[D%��:b
 <�bq�57��>��m_������E@�_����-zMk����(�6���#����mat�)�5g~P�+�/_��5�P��c��p��\��R�5m:4L{4��bL{����w��w���@�O[k��VPq.�W^��������d��k����.����J�`�F��R�x]�����*/F���X�.;�jK�Y>�;�����0�W�WwX���%@���?%3@�r1[x�1���H��
����B�� a�}�F�J������h
�v0\N��t�n�j���5�d��=l^��%��O��c2|����QV��U�Nq���S�%�!�+-���B�����cI�~�z�'T��9����7	o�/C7�9�}�"�M(�'��sB,�����c�-)5�G��!���r%���^�j��{SfONF��
�I�����;�ms�Np�H�����.p�BBb��C���
������{�_�K
~�a$��	!O���*":��XS�	}�5GJ�����o4���/W�F�����n(B�"U	������j(���-X��n�D?2�p��r��j�g��tA�(h�5A���T��m3��b;?�m@�yxc@=����I��f�J���<��	�t�d26L�h�L��U����5�`�x�9^+4(.I�4�l����|3;�����������o����i-��2�T'���qU/�=�X���I�F�Y�u���bSe�����Z�{~CH?�.��-��u ��(
�r#�<���������t���1��A����qB-^�sz	�P��Zm�d�W"���x1*�����Ueq��r�
c�|�[7�K�����^,� K��J<C�����0�H������>��s����|>��-*���}\����a�����E����l=����z��F\V>�� ������[O�*�����c1�Wp�H��isXBG{0�\L#Vk�>��}�~���`R��������-����(kDZ
jY�pv�1�q�(�$���6����2z�Xf��4�����:�B<GL�N�F����[�j��_Y�~`Y�fg��SY�����v���6Uz4������]�U*��T�K��]	M��)�~�K����oG�������
.n)��k?�����Z�UU����j�v�aE�^LI�^�t%0�������W��Ruix51���	X6W�~u-�pUZ	�~J���&\��i$%�=��za'���di���gX�1�L����SCS�����tW4{�X4���'3|����?��5������X8����zA���
�u���$��.������0��>�<�c0���������?,{����no�;�-��t2���95&�4]k02�Q����������Bq'��������s��k��h����zq�H:*K���8]���/����0�F|�#�C1�0�ZA�l^�[w�L���^,��b�F�o{q?�+n���6u�#�q
�a���.��O�I�*��2&.'�^�O�
��D���|?C�) ��V`3N�suL��Ml<��7- fh.Q�x68����c��"q�f���&��������D6yp��J�p�YKU�����8H7y�V����������?�:�>��I�!�
�_�_���!�?�_�+T<&$�"	�a���p^���	n$T<�v/�u4��L�t��5w����7����"g��u+����a��$��o�S����x8����$��*��f� ��h|�����>�T�O��s �g��W�D}�6����7��0�#(�O�x������]���U�U���?�����,�����$si;�X|��~�,����_���@a�������k8��Vj6�,X��|�s�FgZx����ue�y����H����~8o����}G�5��Im��-H�w/�-�
wJ+�zg�W~_fcQ�<�K�P���D>���ea>'�q����m��F���LB��.���o�:��7�}��p�>5�SU1g����9�������[�nIMS��?*��>4^�I.�|���������k�<6��w�X����=���#]�����]�.���]�_�<?��-�2�mwg����s����������0���ii|�/��������@a&�,��9>�����"�ovw4!�:�Wl�����n�(w{	W}�W�s}y���_���%T{\`Q�&L;���Ah��jy�����6t����@�S�y�>���d�1TP��A9\|��0��?�<	�}*#���Z%2��\&g�g'�������]�<?�:w
�G�$��"��uz��>TFw��y\RY���!�5���
������>�h)S�"X�pMH4���GV������tx����2���d�S@�%��]Qj/.T�~Y��@^o�?f�wO�������l[�THX�/�FG�������?}���.�$I�Bl�H��<`ZJ�E��*�R�������������h����w�P�o"'},��;���]�����L
�S���Om���$��)�����;��NTO)w�?sg�y��J��[z�%��6!�I�����N4�E�Y��V	���>7�����o��	��qH���+Y�`oT���7t��'!sL
�;6s�u�E��2Sd��'�AA��
����i���#.9B��>��:�R�y��g1�K�2��K�<����#<�F��#Q������c�O�$��1(�2� ��A�a��^�g�����������EeFVEwfFvDTU���r=w�:=����gT|����d�db�����L�63�_4H��fH,�	�H,����6U]�M�e���w�s�=��s�2�~�����`����2�~J��D
4���fEMU�����
DY�-LM�kY���\�Z/�������C�a�r��_��Hx�I�o6�u]�-%�]�e�a�Vc��Z��-��A��=���2�� ��� �fq4��EC�&�/;s�-��w4\�#��y���^���4��_���W���[�{��|����C;�j_�������n4ic�SB@�]
�V����'KSD�����UZ{�{;�4"�hE@w���F�W���Z��������������*������\�$�Z9�c[i���3�4�.���Vy�:�i��U��7p
�"{;��r~~�����N���9zk
d�r-,zu����yh�H��%8�;�I�M0��O���@R��S9k|�R�� k{d���2�o:A�%����!��V�A��vX74L�S�O����P7$���h�^��Q��6,�q����7��C���
	���c���K��8���bx��@����]h��_�e��r9_����i��K����Iy�Q������08��s�#"�Y�~��$Z���2��+�_c�=#��E�i�$ut�#ND��)�F���q����@X�7&��&�Xv^i`yj9x�?	V�+4�t$��P��B��M�ebYG��V?�����$+I�
E�������a2��WnP��S��moCF�X�0��A����S�S�c����&�n'�2�j���jl�������"�"�$K.8�������q�m0h����u�yO�[�i��J.&v�P���'�'���ZU\�~D��n��e���;xg������Z����H`�����eCq���P�&�7��
Y>�(o@���\������V���7)�e���8�E������H���;!���7�����(���O�����r)����VkQNauo8S��e�4�u�UP�\���lRe4k��d��5r��"����M=`eC�� �4,U����#�kwndw��d�Q��l7��x�43����8(��:�Av�VH!L�������N>P�$�@}����$q�VB2Ba��].�1�\���i�P�]KN�9#������iPwD���<�>/x�Z�~/?�Y/����_f�^P\�u��={�V�dj����-�^����d�����fs��p�{�n����� ��^l�e���o��:h3�����#6~�d�j�4sp�^�[�7��^�����g�O��j����L�������*sc�5O$��<�)�|��K[����c�����.�5�\6��.�7
s�l.��Y;������������Dz�n�FNn6���9��;X���)�2���&HD�St}Mq��8��:��I���k��D�\����K�A��I����z���>l�{E#�n�����l��G�`��x�'���9=i_��%�i��P����s�x�����_%������kK�������#�t���D����A_!J.=C�
��)���������)�L�'�q;������Qp���6,�[���>si�{�A�*,+}����'�g_��=z��[S�������*T?������J���8�7����J����)�s���c��8���Bk=�g�I0��}�+�3KdM����s�B�u��X9�x��:R�Q
�D6e�������BD1:��&n���\�����o~����HLh�������Z��$�x�v�KJh��G4�Lxh&_]-���='s�EJ[,g�Iyq�c�b�F�p\�N���%���lZ~_NqL��S��S�����]yXU�L��_��x���!0�iShe#m��(8���W�>;��p��87m�����^���E����KhVf��i��u�����c�FOzJ�g�k������X��>�<@����l��<���o�s������H�]�V��z�w�R�t(526e��'��V�.�I������T�M@_�g�:^Zu��P�`�.t�3������O���p������8�K�
T�K	�o5'�a�_�6������1��t_J��F����5PD�,��F��1��� ��g;a�~���'t���!�J����d��?��Fz3�z�;4�g^^w1=�S���|������b<���qvx2xux�����7����Y#-�X���mX�Kl
��f�`���X8�Z�������z�a���V��~0�p�ym�8�Z����8�f��KXxXG
���/�K���5$O��a�
�U�������]�����B��g�k���hev]�� c���|�q���[�b�;�d�N����dRk�j����w�/�i3SA��l+��~��q�3XU�����a)���" �S`1T�	�F-i/9WY��01W�A\t��7�n$#����_�.�S��7��`jLaD-�
0�K�	�|�Ao/�����6�=��������L���z~�N���k��G��'��H�4�!�[��4e����;B����!�c[��(����?�s��W��S!{�����S
�{jL�/A�n�d.����cwUg*l��������������sD\O�>��Lqx���b.�+4����+���]2jh�RGj���F�e��h,c8dv�A�!����~���u�toL�_h�F����.��B���0Km��;�w�����,���:��Q���kx�I���}z�����E���)������>�-�x�$���?���o�f��a��rw�nbN�'K%d�n&��|�$�%�*�XD�l�6������F�1�(���A��7T{WvXF�h-,�����7�������6��S���GOgV�v*M�T[�V:
�l%��\����%��H)�l���*x]s�����N�!��}�q��3��x�~-��F��<V�<�o�����Dj���b��L�n����;�G���Ky��+U9&�6�h��1�!w�s��$��c>���1V��V�{��9�l�o����y�]]�K�8w��<����U;��R���YF�T^.�������@@��@�\�q
PPh$���x��)��"�HR�������T:t���wQ3D����p.�rK��m-�,���A�&�;�
zw�R���s`����VU�q��y#������I8O�j���t=�vr��K���P��7T�y�k�����\5P��B��`�%+�%.<��!�vy�D��'c����3�+��o�CGZ��}_9lI�}������
����:H�kR��`X�L��T��x"��n��iw�s�N��mN`��"Wi1���������wg�'^����M����AZ:+e�
�e���u��3w��~\�z�^���<&W_�x��p����`���;Fh�!��R�k�;xa�L��M#�~�8|�m����n�i�p$�S��q8R�W�u�'@�����mN�Cgk�0+��7�KL
`9`h
-�SiNBk����������6����aTHA�
Fet����Y�0MIM��v���=$�]BWp,���A*F;X����w������������H""p�����l8�P<Y/�"�C���9�CL�Dg��Yr0cQ���?���Q�w�����g��}DJ�Tk	��Q���H8������lQ8�TV��*�l��@��2�w����$�2�F�$���.|U�����������q��F�]k4����N��1����3�}y��D�/�����������_/>��p
�qs_����%�=���8�|��v0����������������^�Q'���?�������z@>�|�����������?>�|��V�'��^����������>���J�������T��C���_y�w��%���#���������y ������oy���1���%��������Oy�����N���C�O�����}�o��?���X���%����G���=6���F���M��=���{�����������7�����7�������|�b��uy�������������������_���N���I�+����=��M�����O�)���Q�#������Cl}��;��������.��'�W��?Tr��oc�����U��G�����u��o��T��Gc����>���F���"�����>���*�?�R���2�~�oq��/b����������[������������I����?{�?���~�����������/��"��5���Q�����������{�1������������������_�������������{E_K��������b��G��7���{������������X��d��?#��������a?����$�_���n��?-�.�w�v���@����c����W���{�O���������r}��|����>�|�����������?�/?���=d�����3F��o����������~����_�������������=���~�*������;���������/�����(��~�4��E���~�}
��6�[~�
��C�������������~?��?�d���^��c���@��/��~�A��~w������?����O��o�����?
��1��C��w���o��o����&���8��W����C�����_����m:�w�Gh�$������+=�*�g�c&�I���d{U�Q��T84?���\EE�T�/��S%G�{Vb�
��RNjn�?j!�u���Qp�8Ka$����vO"8����������������%L�j�-��t=��:y��r��=v��'����8�F�r����G+���(��:�:{��#���'���&y���d�H�ARC��St��
E�K�CCS�ho)��-=C�@��������ad<���-�b:�D���,��B�"yG���:R^3)+Uu����7W=qY��OkP�%5�����R�0���F����1f�
����B?.p�Sq�B�[4
�d�`E<v1���12����x���?��#(��;	0���t����Y���b�U9�����(�"��-O�1!,g����e���Z���:B�U�g���"L�zO��F�g��v<"�����,"���od�i�uO� ��N��nvo�J+�X������SDT���/U�-N��wOi~��"� n��z�2�����5�����<�:U�@B%u�!��i�
R,^�����A�
@)��W�aR_���w��������g�S?����g�	�	R�a���~A<H�E��9
��p ��{�������p\��|���iBi���97�G!����������i.���,�����Lq�	�$T��1�.�
5vf4
qS`�"<H�q�]3	/��.���>���C���A3*)i��`N���9�������?���!�F�|7�g\
��A���{�<,��bJGU6����i{���7F_������9�����'4��?9�<������&|t��&r2UBLI���+��@m>
��C���`r��������/�?�����<4�~6�<>��-a
��	9�8 ���2�"��4!��y6�.�B�Z9������{W����M<���#�D���������g��t�=+��3����c}IID}yI�bRE��B0��D�`N�%��9a��b1_�(��D�fK�
gO���"j��v�G��>1��a������<_c�Gv�����Q'L�V�_������"R$�
D����|�D��	�M���o������VDVu@��rF-P7�>|'�XI�Jyu�S?�K�$c����%����7���z�I1;�Tc���r�N_b�V�9��Sm��SS�J.�{Y'6?�/�+�
����=m�]����_#/�]"#���E�����/2�"��GD)������2������g�u/�j�C��-���x0F��+�����{����Y�dI�\���L��Z}��t��F�>����3�5���o��5+q3���E��G��u���������
~_�����2���i������k ��e�}�/�����y����q�������Ed�~	�5����������)��
~�N���A��G�����}�#���a�3��5����y���{����?>�|�����g�rD�����o~���#��&S�H^�/���z}����V���>Ml|o�/�o�=��0!2yz_b�T���)<�p�����"
�c�����1\����Q��(���F%�^��h���wo/���s�
z��8XN��|��qA����^����2<I=�x0��@�a���� �~��9|�3�`��Y|M���=�l}?�?Q�3���g;q`�G�/�W���}Dm��|�.�k?�����(&���s��V����Y-�w�����^��r�B�����}@��}�Q)�#��/��b��t�����SdO�n��X�fkJ�S�"+=�Z]h|������q��BQh�T��
Kf%=��/����RBKz����^p� �@]�A-�`�����1Z��Q��rv0�a3u�y��81
BD���W��^2�g���X�O�F�]����~��J4�{��G
m������M	��'��N�p��ca�x���S���(�>�/";�9 ]V������A����H�Rb++���X~z�)��.Q�:e��S�0�u���J��AZO	,���5|�Jd|��q��b�D����N�!U�+����{���2y������j�Zc�t1
W�:*1��G5�y����gc|��rO�:���F�����Z�����5��n�c������H�������Q}�h4{����������9n�;�~��]���F*�L�U*�!+%�r
R�vz.v�:���-e�E/��V�j�.�b��t�������3n�`\��������5���I Qe�W�d�����5J�6+a9�W[J�����R)=T�sX�3�18?3�#/�Q	���ryv���wJcN9����� �����!��0X]��j�K�w|�4������"�/�Q)��S���h�q���0�����"���s�*
J�q���h����R�����@!o����
����})Y�N�W���� y�WpV��I�a�e����n�j�b�������hu�vo2�r�TG����0�T�sQ���1�;��_�\�ky�:#8���������u�N~��[
�4�u�����c���?�����|��m���N�O
T�b��qd;��jr*d�M�av=�:����:�C<}pN�77�'������*DH����s��@�G��U�^z'�����e��m�
�;�����14���u>
W���H�3�:��:��x�C��u0u��������$X������6!��Y������9��l~�����������;
��T����J 5�w�����qjGq(,���H_���L��t�/�y�m)�#Ez��*�����$���IB��D���1�h�_���:y	@\�Tch7���1'q�����>:X��\��EN���4�'��%7�H��nX��d ��j�Q�V��k�z��r3�i�u EJJ�fB�jE�:Z�(x�Dx>C�V���m�J|�9Z�?�Q�S2��cb\�$���������.����~U�tE�xd����3v�cJ�Ai�R���=��8]����D>�[N���Sx������
�,����)�;5�b�#��\�t����e8O�� �\T.a�SIFZeY���-4���6a����a�^El��Y�kp���R�2����l�e�2=�
����H���$=V�0J�Y?c�����4�-�5+5-�"6m�u���H�[���d��K���������$h4��v'�v����q��$S���em���0qO��QR+�Q��LhnY�L��!c��~�~�p������;' p���r0���SVS�}��t�Z���zIs�0�e;��4�i�b����'������)��J�^0�Vs�D���6�{��������j���z�qJz���I����$��6o��G4m����:A���Pc-"��B�w������@[�`)73l�(�	��+o���B'�A��I������t�}�t3� A��}�I~m��{�7���`TQ0���,I�s���`���Z��i��q��Z�����)N�#�� �#��R� lfU���
fH��X���Z\����[@�� �����8���]����#�Q�wm��!�Zmu��a��w�����C����_p!>�I*�����$%�9�5�9�1������\A��2��n#�7�%9!Q�z*��<N��4Y�J�N���6���9c��k��CF>Y������z*�,'�;O�j����'�x8�'��h�n
s�$�D
�$qz;d����U�Z�������,���|=$F@���J��<V���l�s(��WB6*|;`
�p�3����pD�����3��.����&��?�V'�n��n@���p�������x=�^����@,y� ��������������NwE+p�m�JgAbC���/I����d������3�^m���
t�bp5�x�5en_Hm:��
�]d.�U�>u���Z�:�N�5���N%�K��h���x�w�e�+�b��U�����#�������/|���#�P��(��feK�'[��[��b�K����Y+�)��`-���x����kqb�:P�������h��aEl��h����598F��)�6>��F�u)J5�h����l��������_���so�S�����_����blKRs�eNw�3-���E/����� �8�j�wm���NUV`�I����nJ^�M7k�-%[������I���t}�V`k��������U�Mh�S��F�	���y;�M�.���"� V�~�_�/�Q�D2�(?K��2X�S��������[��<M�(��"C�w��:o%(�	��M��i�B=�}Q�H�cH4��{E)`P��f���3��d_�f��UD�����N�Z����q'O��H��H���bz�=��Gg'��2\��\>��h��N]MT<�����o�+�{}���o�_z��������	�n9G��Xl���b���=��@�IU�9f��C��=+��F�Mr����*�+f�!������$��M�vb�2
�|`<S���� O���X�����!���xA����[����_	#�yn
����y�����UZ-e4�v~p`.794��m��@V�+�Z���W�G��l��h"d��R��b������%`����C2���e51o��8���j����cT)���S��kD�$�~xdV>!/^��q��E3�@.t�.�����w�"Y4GP����t�
�_'��x2*B�ty�M����%S\�����f/��C9�|q���[�!k��8�J�&K
X��hg`����h���1���/��2��Y�JQ�������dQ��`Q��0@<��m���u{��O��_ �dQy�����k���'����
������ ���u�)>��4�m �r���V�I�b����f�Hg]���r�}�x�o���G�������b��n���y;`����v����
��B����2}��.���,��26)�5�@�;A���7������d���G�J���M�0�������R���}����r�;;}�����4dd���M���3���h�Z�L{�x�0�
�{1�0,��b!��9k�%F�^3�S�7��~3G����,�R�G���S�2m��w����p��}� ��
����@�sto���D}�c��_�0������2Iq��	*�sb4k�;�O�������Q��
 [���`�2;r��X�����?o�m��
pn��@��Vd`�]���S�!�h+/�����?������RN�\2��6m�N���-JaA�	�=+r��UL�i���[�Q�������,HL��6PT�(�A�D,�$x���������#r)�-��Y*��Pj��\r[�����7.�7g�U]m���T�����I������j(P�����5*`����44�����?4z�Y�z���2�Ma	������Jo�L=c:�b�	�.}-8U,�o*H������T���NA����q0�T�����7��[�mj��q�w	��a����e[��F �k7=T��gx_���&�n@�Z�n���5`��o�������~s����gK�4��������~s�v��>�-��	.~u�������z�] nr9h�%��O�ptW�����n�
������I^�J��e8��K�s;@��Y:�e�1�;�
$�y���`kd#�%L�;���`�5=�%�A-������C�Xbo���A����-qTb�r`�l��K.����b��w�q����U�'ee��f5��f�f7�>�YKt�5����x��O�a���~��/�[��
���Q�����?����=�����k��>��'�Yy��������w|���$�_��8_����������7yf;4BO���5�x������L,)\�*M[��'��dN�7��H���%S3���E�	<��$$dsX/��/3Wf2\91��g�
0~�]>�I�����Z������U��5�I�=4+no<+����D*1x�)����45	>�^0@�]��c+�����������U$]�x�Z��*���	���Ns�.�fi����ud]�����d���x�lM�����x��d�����r���M)�C��J7��|B'=6�*����g�l��!/��|&q���Z�@}��{�R|��6���I<w#sPKr�/3�P��w`��[��g�8V0��a�������������Q���A�]^��d�����d�K
EvH�i�}���D<�1��{H��C��dP���LPs	M�N������!�M�W�r|��"�d�B'w���'T����E`��1�	�@YF��L,�
��f��'o�G���g<'J����F4(�����X>mY��b�L���E������!����h���C:>E�������Q�z�~(�yd6lq����2�aZ)ZD���[�%!�-��U����'�5$���/FHQ^����7��p^�9��Qt#	�C����������0�|0Q��]�%�;K�,����!��?D+�8�Qh�G��Y#T�1a�y�y�
[���E� 4��Qig�(1j��������� \iV��8��A�&�%foK����I�tr[��O��:sb�1���?�F�Z�BO���{f�iV!�Kz;J����J��Ss�(f�G8|���XO�9��g^MW�b�@b	K-�|��4S
��|�h�P7�uwi�N��I��dwV��3�@��9�{���"�����#o	�(�������g���3.^&���O�Y��y����Y�����9��K���:�����U&:��0�
(�[W�8�a�:�2K�H���dp�1?���cy�I�����<
�3��@��e���
�kl�B-��/[�.�.9�Kq�����^�s.����8��8����\��B�K>��C*�������x(��2w���'8�5G���XF�sF���o���@��#��9��k�W�Kz%M8�h�����6�2�,�
u>`z�a@�S�����T�Y�_�bq�=��
1�	��	��DW��������{���������@D?�?��*�����e&�A[o�i�(O�tEA��/8�)o	J��A�����#�C�Y�TV��zJ��2.bFXG���rm>�<�$��X��$/�����K>��i�?�:T38`h%���N��%�7������EF��k�-���{Y����-{�p�����!ZPzF����r��m+�;LO���O���x?���XK�=17�y�b�7��	��Qm�kE�-�m{�fp��7��M#�f.�����<.�u+�:B�_i���*�)�U��a����1��},��cHf������'�����sS��B�+<�u>Y�b�)P��5�\]A%��!���K���_T1����9$n����s�=I:��3�>_�����U3������*H\�IoW�nO����Xj��>�+�3���w��G�c�Ltj�H�U��������W��>^�V"�"���j����Kt���{H�qW�gF����7�EF��p�~9������/���~`�*f�1)t(��~ZW�< �f�%�>	&/� I�-7��'��	�V�n�[�zA�[D�q���nT��fz_vv~����l�� ��.I��G�]K�w};7:o�AUc'=0����F�T���������yK�����:�?$+�,|�M*�\7�LVCx��<� ��.��h���	|&&8[��YE���d���[q�U�kM���������o�����2�q$�	/G
��O�	����R^�a�`�����k�.X����x�]{�=��.�M����g]@���Q���@������i"���"s!�
�����)�s����c2*Cy����*L!�#T-K��I���hq�[���.7x��A�??_.���SR0����.W8���<��,��[vy;Y(�r�r/���Y�������� %"?�,r���U3���A�Z���4
�U��
(�(���jdS�����"��55n��#Y��J�J�d����z;_�t��V����R2���Nh��2������]�f���=q!<��������=��H� ��	|�Y������R�&��R�U/���kZ+ul�|Pe[~�Vv�U\���E��ne��r�7\�(��IXwNo��#l�wv(�t��rc�t��W��E<���i�
Y���M�[�%J��J�E�&��l�������������L��6|u�Nd���159������m�7�&�����M���cRP���
��&�;����x�Z��
��*L�n�ON�5�/��%n��������+"������p6G3�]�EK�J��Q�UZ��G7F1uBZdqD�+*vb�.���1{I���/y�����6���-5�g��xe����'c�dM^G2����cBM=�����mROv��,���C��y�����������Z�����������=/�~~}v��[p���.�[���i�Bz�9����I�,a"�ub��7��"\���L�=IV���_v;q'j��&��]k���aL|��S����U����z��pT���0�9Q�2*�Q66	+,�
�.���Q0�������a0����3�l~����>�?iD�sT��K{R!��?_C*�F����=A*�nk�8y��3�����4[����v�Q1�i�L;o����U,>xNb�1��F���;D%���m������������9�B4C���`���#��"l�E�^�`��/��_���1�n�+xC`�X�"��k��<��G�|_��k��k���-��@s�����'�Q��+5���&��	�oB�Y��r3Y�#NA����#����������6_na���6�?����|O�ZRs��{"D�v����l77�	o�B���I`�y$fw���v��T�4�D��)����
t2;e�7s	]f:�S������>�8^R9�S��@�\G��C�2�(�����=X�{u��"���S�������&���K������s�rbvyiT���9�+�P�f�
9�������r�������_�>���p�st�6��/���s9;�.���v��1vM���N��a;eIw�^n�$����?S�Aj���<��Q4�R�4�S��?�{��=��a��KL K��t,��zD�����E�de��}�bE���MN�#aL�
����c��0�T!��������(��[����if���t�*�6A-�V�\$��0���.�^��jB��c�|�Ka��x���o������4F6������A��h���Z,�\q����X�O$��{�p\���W���bK	c3��cl�l��;B)@�e��|�l?5�9�B�o��%�]1��2�oT�'��?@2����,�9�0�z��|g�����*�n4'~�oO��f����8���l$9\���������(X���r�"��J�+s1�/|O���F�-y�8hzM�xktdT����4���wF���>��pJ������*|��q��Y��@h�����h]��MZ)�����r�^`�b�j�����.�2�4j�a����a���!*��
�j
��{�I9��Ma+�1���u�����?��5{���w����$�d�����:qk�*2nI��R�-�d�%�	�ep�����N�<
�����H(K���@0���t�W��p����X��v�pC�
16w*�i�%�en�����b�t��z�����z����%��n)����R��z��%
-i��`�Y��
?��{�;x`&���1�a�$��D��r��&��x��������"�#�HQ�����9�I��������v����j4[�I���X�r�s�Z���`��XL�@���`�J���Sl�Hl?6�?H0!������(�<
-=Z}���R
9?V�f����M
�M$!n�+��`)����Xx��%���������d�c!WU�[�*�7��L�VW>[��=�����*i=%�WZ��I��	� ����r�9�6����bC�S��'��T���NJ�6X"L��g,%�����@&�%�zu(�et��:wf�e�����7�c�6�H���[�}�FR�m'��cyQ��t,�4�*
��h�xJ,����?B����������6��2vl���5&�fs��V�N�?�d��h&k�&
�\�A&e�I���k1���  �)��w
���{�W����0���"�vbQ����T��c���V�-����Dvt�
=V���}*�W��n������az����.�3Ll��q`�Y���l\���P������w��	��F3E��k����Rt-'�����7@��y8&)����9�������J��"��j�3��d�L]�ZQ�#A)*�v��)���1��F��1����6��1�y��}~'��(��/X��x�H�N�V�MN6X�Q�V[����?
�,��0"�n���Z���Z��o���S�wqj?��V������R����U�tZ�Y��k�'����n�^��l���Z���W��z��W�>�����{~tGE�5���O0�����A�_�4:����m[�V�����`�F����M�����;
^���jO�����*a3O��������H��:���Z��bF�xXv�y	��	�Z��M�`}��{^����}����n�J��!��}���������Z�q��+�
�&Hfy;K%���^���]�"��x5�6�`���\y-ox�B����Q��hP��&������%r�O�#��|L������kxM�\�����K	���' �A��9���T��1���PQE�9�H��na$N����
T����B���j��._�[����������w0���� v[$����9�c	& *����z��f�����������m�����t�����/�w�����z��o(�I:iX���+~S��2�yM#�~=S�-��*{�8��{�~�����5O�:��>�Q�����o��#=��-eK��+4,VN-k����kA����g�[J���e�^�T"=V�`�;�m�������=:3�����+$3����rh>����K�(�#������E��\���b�
�
/gp�/E@x$"S"������ y�gG�:��@����o�s��B���&����.1��y����3�bc:l�'Gg�,�[��x�`�4hO�
�C��G!�g����/%jLD��������S��pGa���Y Q������{�-BL�j����>�b �{#pz��a�:T�>���u���h���Y��?���d�b5����s����U�[�Z�-��\��x,0)���� `��k�(�@i�7k�.�K�a��Hs{.�jZ�*�y�v�]����|R�-!*�D�
/�A}�p�p���/Y��X�=L*"�Bn9��%�^����l�������=���,�J���#\���aC���������������Z`p�Z�$�	L�5�-��[�4��3�r�p�\�.	0����AY����C��\�U�m
=��S<����������d�!�W�b��N�pP�`���������?jb�2�v
KV5����^!���rq*��n/v*����i��S��S�����4�_N"`+�j�J���D@m>)n��}p(��3N�00	H�s�L�X	�eU�,��#��U+`1�z����.��Q�=�z�O����t"4��P#��r��T<1<cV+RQ^9�0N����o���.��a������E���#�$�,K��U�����9pT�0�#���5x�oq�X�g�_9g��w�!y�����t���0R�7�)��j����$E�2��8NnA���gq��ovHV�E��������[��
���{Go�������v����4��OQ�/��V@����D�w,{� ��X/�1���3��bm��=�;1>�P�$�����+�����''�'�>�oh.%D$12F��o�x���>Mt����~1^������]2����J�n�e7t����ic-�qD�<����M�5��m5�X�8��K#(����R�'�3J��r������lHL,�%�t%	9��t��J��s4�����NH&���Q(�#���W!�_B�	����u�	sPpj����y�QZ�+EF�H���["%�02��`�[��"l�Xh����/�T��������r����n����\����X�1�?\�z6���V��S�)�(�a���e?R�QRlr��0/X�%��N.�6�OT(T�ib����-F/?Voq�%�������I���7[�Z���B��f�ct](��6]L;_�?Sp����fU����[h!���	���/��L�	2a{�n����r>l��aO�F�`�r#������}t�:���-C�j��|�q%���`�'n	�3VQ�PNf��S��X�4Lts�V����@Sv&������KI��A���1>�%�]t�^~�V�x5�$���9��g&���#LY��dE�E�#����/�����i4RyoD!M�k^��|!��1���)D"�1u��k��&[�!�{������.z|Y�tf��SH
�����:��������C�H������?3�*��ms�C�%<�u�8;����4}��e7q��.�������3P�wsJ�0���|:���������K
���S���gy��9�U5����\�8K�GJ�RF�����#�&��,P&�U�N����R�@B�ODw�p%���vQ���������R����Rfq��������3���V����IlK��@�"����6�-3E�?)t������Jr�j�������]f��+4��;�?������tD�����1/R/����%���%����9F_�����/��S@H8|�/�x��oq�n����*�~[�)@�+d�h�dst(�F*����;�wMd1m�r0��V�3!j�����t_��V��d�����D@j�����r�R�����+0�������~F��������������>��~�����������%2�e�����~Fub�����x��~fo�������u�y?�E�~f8�=��1��������3{��3{�����-�g���~fo�@��N����i�|JB����{������v~�6����k�uj��i��n�����v�i�#�J;O���v~o{��^�v�����v��]�h��������v>�eq��������F;O��Z�����k�����U�����K�|�l�������k/M����{��~{B����[�Y�q����D��;�����v^���k��2�j��������v�^�;����vk��m��]h���L;�wK��
��h�o��h������y��������GJ�%��6��4�{+���m��i"�6��4f�H����t�E��q�;���3�yi;[;��������������)��x���m��j*�j��r��{H�\�dk��G����{��q^����m��W�����*�\p��R'D]-��������l��a�r������N�^�v��Q��	,��RR-�]���k-�G�e@)�S)Y~���7?	W���=�2�f{���eU���������SE�~���wT>��:����;'�����?�j6��,��P�����(9X�`<~���aQX���LHG!}N����|���}Lqe��.�?�xV"61��<��!��y
4�<��������^��,�B�{������j�i�`����-�'�#���#��*�x�iJ�����U�F����w���"/�F�������t��f��oV����6��D3�j�����=�=�=���0,W��*���PE�P�����8�tY�qN����������79�u�� �������c���)�L�Tu<���~6_���=`WA�P�A���������N�����~w�h�R�^�����^�����
F�mJ�*qyw����dC��Z���y�m�(+��_���I���.d�N��5������L/�������=v�����4�^)�V�'�N�?��N�������w���gG�O��������,�Lj����w��A����M7��KQ<A-	���oV�K��V���Y5RgFH�(;;&u�S�
L�&�C'������::|������5����O_�
�~y�������U�K�����c��h�ibQ��M�o#���SXM���x��������E��72J�^�NI�S�K�[�J�=���RrEsL����J��7p�,9�,Y?l�M�
7eXf��D�:}rr���^���=������-_�:WM#�B��}�H��tVF��[<>����YZ��*����[w<�����#�Q�fx�q*�����YZ0����N������Nr�������}u��
�}�H!e�j��?~�#���	&?�K�[o��������/�������Q��MF�^���;�~k�o�F���������J����on;��'(�G� �$efI���\v�R���qR�uD�@��x�)�j�*�l�@�s��x����3R6��Z�"K�r�+���T	�<���`{����J�q�c�/(0���h���w ���O8����D]�3��IP�K5?+�z��Xa�s���f
�t^�7�FgUz��
���r���H54�M�j23�b�'��R���V��
�KGn��-������)��n���v��v��v�nN�E�S�"Ij���(���m�JLT%�Mt��PRU!�����f��+ �S1}�Oy�/�iL�&�D��)����j�$�D�&���b�iRB����i�f����p���Y�:��\�\���K���5�v=�c�����w�.B�������JZ�V�{��QI*����>���L��!x?S)H	\
b��t�n�<S���}<\������-��d���z�
i)��`&�9u�JV)_�g�:����Li��S$��I��\����O��T�+[x�bp�aV�v��^F�U���*��	��<��f�H���O��p��������}�V��J{N�E�������-�
�Q�� �6R���
��(4��g��xqo
����?�vu�,��������9�oiE��L�)��|W+�=������"�3�:�}������9|�]-��a�����Iv������J�# ,^s��x����q����Z�U�{{��A�r����xp�����L��R�����S)���:J��{���I�%��J2��������a���|F�7�����M�Fg��M�i�
�I�<�\��!v�V��5����ijy�����X���2Y��x���*-���G"K�*��U'y�a�{��9�
`��z��H�&��BRK�,C�����}�i���f�G�Us���^�O#�=��x���)�,+�{�tk�oK���R|���%L>�g~�~r�?�����z�}�����~�OF��c��7����i6�����&������>~H�����I���t@05�~��z�8�F����j��j7�?�O��?������S�Y*��K}�����6�:S�dn�"����M�Ti��������,A����\�w�%+��S�:bh�u.���0��CsW2V�d4JU���K���?����7��&_CI�;��RR��J���a��
m��! ��T|E���	2��sa9�V�`��	 EQ�Fv��_G��e;�x��V��2��L5!��Xr�#�B�*
e� 2�/����)&����b��!���l�}8�5���Yu(u�������|���������`@��*L�v���z��S�<�k8����h���J}Aea2z8��+�:rW���~I�G����N���I9��}	][�-�+�p&!����r4c�P�i��5[�0<s~M������ktrE��?
W��wPd�I��2��XQr���A4�L��kz���=�g�>�T�v�������N�b���X�- ��70�C���P����*��6W�I��Z;8�@�Z^o	I���
�A����j�dn��$aW��0���j�*�4t�����N#�ol��HPN.�R�������V�~���%MkcC�)EJ�v����g����1��D\=Y|�4�J�8����{���g��p`��_8$�x
V���?2yD^[�(�i���.Z�Fz���(�+�����l������Ev��!���T�d;��y��c���
�|�YE��t��1C9,�b�t����p}I�����k#������66���E9�����*d�z��?�|><R<�a����#�]y���U�����XbV�|��L@��e������U���KgI-&��TR�<q�<'���{%=l1�p�{kfJ(�����n������o4�I����2�����"��WjN|I7��}IE��KK��g��_��,/�4;�� ~s�W��������i����.p$[{%�tDW��L�I����%:9S������L���R(ku�+�������������f���W�s�B�����������*�y�7��2�w����~��c����F� D|\����P�jPfZ�J.���T�)	a�@b���P���bf3���G��)���c&������f�'e�	/�����������,;�pT��`R�Z!4>��������m�A�pvFfou��������=���)���
A�?N�/�����3^r�3+�[._|�1���U.9�a2�V�������x�����l#Q��3d��o��3Ma��s����p��,�vW��l���^*�������
��u!���u;�f�:�{]���-�if����l�AL'~8�
�h5��;]F�KxB"��Y%G�@3�)�i���lAov#]�
'o=��,?H��n���vm<*����M�����Za���}g������{D:����i�>�K��V|�����UZ��D��EE�,��M��%�b����r`���k���f��>�|Ew����5to��k�RJIZK������Z�7�����^3�NIu�_����6z�
��qQ3�X[��-�������mVEyY�/whF��jZ}���:������7����jO7j�fHr'�wZ�?������Z���b~$M����1zR���XP	��F�P�qd��D�N*����'}�js6!����1����:. �������j����F�S����v��s��k�����vL�]aEQ��~���4�b��O0K��>��y<o��I���$Q%�]d�g��M���d��p�j�����E�i��lQ����S���8�,���E�1������������YL��:�jM`1��tG�^��-�KNKP�)�ys�1����0���W�w�)���6�Ft�1�`E(�(�0�F:o�T!Ev��V��6�4'�fQT��l�]�]�Y�vcH|�����6�R�� oq�����r
^eMj��8']w^[���--f�b��
)�b}�,Q)�~��^Q�� �����|�7&�Y�XQA�a�����j����u�H����6�H�8�'}�O�.����%��bh"�)���������=���P���B�
41(X����
�if:��$�I=�."�cF���������w����W�:��d�[
�6�F����f'%&���6��S6�~��?��}����~F�r�G��������DT�D�7P���	���<+���Z��r%��^d�F����Stdym�D��J�N��$�h����� 6�"g!�:J�MM-����/�	��#X��Vt�_��ap�g���X_T
�c/m�[$���J1������:�v����uO<���^�Q�)���w����"
?��������������A ����1�)�CT�_������<�L,����Ct���c�H�fP��+�#.X|��_��\��%��������B���;�f�y>����Y��z���43��|��1�j5b��tG6$8^
��#v�������C����`A�G�6��PDH	AG�3TJ����q�9�
�J`�6`�9"��|jxLz�FS�EJ�f�G��a�Y��cP��]��@��R�n�{;
�;Ia>e�A�4E�#,��qJ1&L)�Z��Q}t2��r�?��p��}�����}�p��O}��9��-�c`��z��_�V-���������a��F��l����8h�:�����w���	�F������F�L��.�vZ:x���/vz;)DSc].�ho���\M*���_�E�b%�~7�Vu>P��D���rh�|�����tn2
���*aaG��TU)>9(MG���8Qm�w��_�^H�_,�c�����/J�3_]x'�g_��=z�
��m����W��^������Tr��[]�#��b�-.y����t�_���%�;��|�'K�����%��������������<�C �N���M�L�K�9�`���z�Q*)�m�����L�W��34HreUe�\��H�b�J��c~#	^��Fr~F_O�[�@-v��J�����o��|J`}B��hV���#<�� N�}��rM��o��r�[�7������<At-y">z�1�L�	��!����E�a�|�X�:9��~����Mb��C��<8�t��4'�j�_�c�/��p����p��A�R��Q:���f!����d��r���;-�s���S�����B��0���_-^v��"�(�:��g�Gg��nL��9�BPB_r�~��&��[�h�<��c�`J���mt=�T�*O:uk��'�}����+�k�_8q��5���D�����5AO��6�'�=F����s7�a������/
�h=W�f[�"������@��p>�����C��G���:z�����
y���9f�N�k�b��SjR��1����l*w��f���`	����C�a����p������F+�i"��8������;�\���(l��8��@�4�w�<v��555
��}}|Y�}�a��M�F�� �6-�Z5ib����H�$�-�|dsP�b�X���l@����S�Y��������Nb��i�WU�^?����#��A����1���������'��4�0
��:��O���;�^�k���x��Z��Q��>~H���M�=i�:�z��;�Z�O����n��kL��4�K��������z�I��%��E�C��;=���`����� �����xw�*LN� v�~=qJ7"�b9���[��J�K+�z���It�
AU���oA2�rix��	7p��
�awB����$(7�F���z���F��!�Z�S8��AL���]"��#�3c2S`�dg��������\��A��r~�l���������;�4
_e�c������48 �U4�D���I�j#X�Uj�"��0�4�E> ^c��8vVJ�r��:����Y��s�?�h���n�*A��}���21u�U�Tvr2�&2f��T,A`>��B��������Pv�Px�02P�&��C�&��������o���8�����>��gG�o���/�����>��+P�����,0�&_�lP��n#�=��� B���"HLU�5���C��������=�z��d��p�r
��D�-��i��K\�_k�?��������w&A��h��������V����NwX:�qs8���?�a��F���ZO��'�z��Q���qC����J�K�����d�@ ����������b�1%3ZE�D8���aI67�"��pD��=�g��wH�c��������%�U��Y��QJ��J)+�F�IAh=���&�8Jl<��g����#��*1�7��h`����5T<�����3������xY�EV��R����*Nj�JI��P����U�%�"V]���Z4M\�p6��s���4�<2qI����a�591 b^�R	z����y_��&�%P����K�l����2F*�?dG��hd�������.H��KW�-��	�B>��t��'*��d!A�
�u� ��>�?Z/s`�~rtF�'��Y�l����+u�H�O�E���%5��,���s�l��4��i��^��G	U�+%��
]��`I*U�wZaE���,�$Ch!���l,���{)4s(I1T����LV��5�B7��Q����K��#s������
�!W����s�UP��=J�������c�fW�j������qH	`l�2�G��,@%"p��ku������^�H�2��*�vr��_,a���>���x
tU��*�b���iR���YK9i`IK�Mp�G;#�IE�1X�e����<S�������#2��+�qd�Y�9���7������y����p��SD:KV�NEg����{�b�XO��5��5
t���RXa� ��Ej_����A��d4�]�}2�d!��$��w��;v����xy����p�� ��)�p_.����" ^��PR���K	'�&B����3��������zN��F������Y'<K�J����!�:�^��-�s��
\���C��d�)/�@X2�H_��@�]��"XH��;�~����wQvM����2u5����\*�t =|���u�����2��/l.��77�)�>E�	�*+x���x�:4�
�n�����w���Zu�9�Q��@)��xH�]�3�+J�3����Q��T$���DBg����+X���t������{���"����ZEtL��p�~T�3�<���>���R��s8$��E���lG������)H?U-�9n,"�b!�b���G|�U�$������h�/��U�LZ��}M�Y��CUo�85�L�tl�(�:����[���{����6������AK��OYJ,���?�G8Y�R�v.�7��w���p���k��<jDU��\�q�����
=hi�y�L�K�Dka-0N:�[�T�1�-���y���-�B��cw����pL;JB�c�<tD�_����;�!���I5����Q�a��wS�`���0�_��($M#�F.�����$
�]B\Q����l_	�J��d�7j�1:kq%��S)�
;�(�TN�t�U@�C�����`�fRpw ��x���U��J��L9%m�����}!��=�S��%�w7�fj#�~"����>6{_�x8�U���+��S�K����u3<d���� �1�.��5�
6
h+$���$�Y%�(�M<I�����H����������yt����	�x�K;C���M���:������.��,}0���Y�wP��99sPL1%qf���R�<"��x�h���	�|N)0�$�?��(<'-l�KuJ�3e���������?���%�������������������**���A7���F|�j��J� �Ct���:>��1�U#&���+q�&&(%;�++^f�E���,�s�M�uq{��a���<}/��W�N�hCES�
A��<Ao�e����K����l�TM�;�Dt�)=����[�GF#�*%�1vw��3QG��.�nWJ"�����T��v�!�s���U�s��j��;�k&4����*[�}����&�������r_�O�0WKTs�9������������,6X��W��9�������Q�E�>����?Kq�����D��?�������X����(3n�4��l�Q���C(��l��:bob2�.��&��\|Et����=�K��Kr�%��W�Rc�q,s�m�m��w��5��2D@�[E�h����NBz�KH�n<V��> G�A����Y�X�K���.�
�R1[��Wg�'������JP&�A<�� *pm�-�H�	��c�����Rc���[�-��6/���eR�h�Rw>�J:��O��zIlidJ�B�u�(|
dCwm%(H[�M�2*1,D��NrCZ�.{�z�"�$�=+����/�(�J ���M�^��9pZz����������lo�X0����"D��D�	��y��ZX�O�R�����������T�
i��x���c��jD���(z����)��X��3�����Cv��J�3�US��KT� �$vA5�$O��GuC/I
��S2���K-q�"#9K�aO�h�$�GV��B���V������������g��S.EfxV�hQ���;9Fc��|�>R	�"��C�/���MC��2P)���\x,$W��a����U�xh/�p`xj���E����4]���3�vb��Q�*�N-�0����XD����gE^������%O�V��(�J��"e+X�J���I��btR2(�(��s6�z�h�P�{��#.���������r�l�R?��&R6�rAg������+���xi(��
�i��mGBT��
ES(����#��~�,(�
q4R�XL�Sb���*F����J'D�����Y�B�%	�.f/�y7���
�_��1���y��)��1mMI�1�X3<�wc��^��T����	���r�Z�����7����h9'"��YR�M��ig�7fd����bu���r��x�;�7j�4Yp�P�����Yy9P�7\��i�n�|����4�w������y<��������U���u�t�G���J��/aE�[�H���SJ�KW��?�U;�,�JzD�6�d�����E����a�����k��}#�v0s�T������<0�	as�y���}��Y"b�b Ke�*�������|?�/����o�Lt�V��W$���*���KqA���v���<b�6�w����n����|���H?��g&ah	=�"�Wt���
UF�ja�!�BY���`w*��}]���^su�`�f�6i���
�@�`�v�r�{1he�n/C@��8\�`8�|�{�Q��s�R�5�TR2$���yy�B-�����?cZH���|�'�q5�H�������:�x� 2�*)n'"������r|�F��yZ�D d]�uT	�����tD���D1cy��I��35	0�R0���G�%��Sw�J�c�(�N��Kv*%
���p�`wt;�@H���
-c}"b�������D��a�tj�\$�Q9�V���0�1Yo25-,Q�d��A����H7���V�)���[))Vge&m�D�4�
�AT��2��K?���)�����v�9nK�1���>:F��g�����@9��J�7$=��G����X�����qCR��|����98��?=|}���[���@$��<<���'/���_x�G�����{Xo4+�v���"T�". ^��W'�o����x�}
V�����0��qW^����A}�����<_u@:5Aw�%��:$U0�%�"�l���de9\0X �H�j��� ~_������P�~��k��%R��
D��RJ�$��H��+���1��@�EQx����s{b� ��X��bYCT4\��,�V��$<Q0EWm��������,�7��_Y�Y��V��!�M�m��z���>E����������)�����g���f��:
5�|=}I�����������]���@q�c���`'_���f�B��Jw���0���H%���&Gc�5����q�=������0����XN_��k�M���e�*<��*��v��?J���e)��;_%�k���H�kvI)�E=�����X�DY�|�u���������,iv�P���9x4��|����8N�c�_Am���(�..dVG�Y���������A����
���F��'�O����M86X=Er��,K���XO�/��6e^������:�j�d���4|�d�����#�������)��*���Q���~bE���!���M;�~�1	0��
��W�cc)��r�����c�QmwAw^���<���|�R�@�}j�j����Q �����DT���"m� ��C�����'��83�v��%1���z�s	��$E;���tU
N�&{	`7^��|�����������}�* ����r]^*3�9�F�jE7���'�\#V3B�VJP_q��l&��,�/e�$�B0������D�
�t��k�I�nIG�A��~�uL���+	��97�p���nql��f�=Ls�l��}��	�I�����Y�bR12[_9��O�~�YPP�U����l����G!`�x���*JL~/Q���E�$Q	v9 2dc���P�A���rIT3����n�y����R�K��W������ad2���#�e�+��x�i�R�@`��N��.�/qf��(9
Y�n������q�t���m�>>_H�&���F�	��&�7x�\����tL!����^�p���.�W��d.�M\��G�Tt�Gd	���������X��
�&Wlh�����(J���s.�g?��L��{��ol�>8Fq���7��Yr��2�P*p�����]����M��p���\��bYV���-����S��I�7�8�����o]U���e��"���9��T��Yq���vN�G$��0�q,����m���V���	��Q�VK?v5M���
�)D�=0w
�2#���+i�C��4<��x�|;&z�p��)_��U<z��+��|�\�O�F��w�N8R\����:2pl~4��}�2���gv��XaA��a�q}T�P���hK$W���}�c�>V�`���ST7�z�+s� �T�E����4^��cK�1�0�6��:���{�R4X�L��9� ?L"w���������&AF�@�����1�1 �\�c<��|
��3��4z���4X��0���up��
b�i�1
�[�|�lU~$z�����%s
�M)V��`�\��,���N�)4m���M��c`,���a���a�����W'���{o�O(L��K�������Xc���0�i����L��x�2\����1+�����[WKR�<�W7�1�n��%����Y�m�}���UH���j�v�s����c��v��	]�8<���W��nj9���{���g���>�>��0.I�x�/��~��p������/��>�����/�N��8x]�kb��"Q�^(�b��[��b�Lug�71f�F!��7��fr�J�E�| ^� �����e��[��)o���>Pn	��0<�i���=�:J�I8<{/��W��\>�.:,^tT���x��r��3|����/`�TWu�Ym�U�U�"�{UdS����a=t"\��z*
�i��T�
><(�/}�<����v�����yN+��7����.�f�t0�D^1W!^�-0�����
��)O�������|-A1�V[���6^/��,�n:4�.����mo/��������z>{��!��#�f��5��b���t{T�6���O���)�Y�������j�8Y9�O�!@0z��Z����4<Z�������y�k95��Q�6��!USL)n0O%��.�Q
��T�IF�I��5��P��~7��ur��f'������m%W�	���/c�	o{�51�j�z&a��yD!|b�k'����L�/��S�(u������}�<[�5��".��$&85���g2�����	�0�~�.aBo���'��0~�<��:5AM��f�Dn��o�i����E���i���j6r�����YT���'�D�q*-�Ye����Pm"y�
�k�Xv���U��k`�G�&�����/%�o�wk��q�n�f�����G*l7��k�AEyl�k"�I��
5?������������?I��`Kt
���n���f����ux&�����j�G�O�Wi���S�i��&�#Hl�B}�k��������j�]��yU��������Y��r�T�cvjJF���Y�" :���Q�!X���XM��oB6�������@�B����a������R�&G�O���v�o��BO��EM�x[�~AFk7�')�V������~�����/����e�l��D�$y�:\=�N?\��N!������*�i'���$8|�`j��p�\i��P|.p���,�Thi��� Jc0��0�:��X���������zn�+��F��j��)+�/hO����\#/������2
V��y?��}����t�#�k������(u����h5����$����U�$l-FJ�VU
�������E�h{
�Rs�4������)��X
=X/8�SZ�&��'a������D=k��D��,��5;8�^�\�"+@���'��w�y����EJI��~mT��Z�j�]���%�H;�'�HI��o�+u��G3�d\�;5�zI.*��I����N���q�Fje���[������G��]��T��t}9���i�.A�����lS���p����[c�;V:cJN��d9�W�j��B�o�E�B3�l��_��)�z1�R���v�)��R��=q��{y5c$�b���<?�y �Jew���`���w��adk��������I�o6��q���IvV�����1��"�w1-����������'����������|�����V�������s�_������p�p�N!���G^�������:��KJ_���v��(]���{$�)kSj�m8a��)�o�Tv�F3���X
{���'��[�_�� O�����Xz*	���hB��$KXJ��O qT*!���:P%�7� ���I�'O��h:�K��Q�B�=~�����`����yjb�0�?#���}�� 2Pvo�F����
8��z��r/��5����v(��9���<���Q#3D���E����}�&��,Z�0h�M�s�����r�*����G�v��y���p������`��+�Ifl��e��� ��a�K��%*��e���c�0u3*&�����
��|2YT(��Q��C�n�36�<3mz��#dv4��M.�B�@	������#,���J	������Vl�������������j��.8#t5��O��Y����F2$e�I�N�
���M@c����1����]�snB�a�[JSx��#�'dl��?���9�h�0�7�� /���g��-����8����|9��J���l�l�|�N���}� 3�!jN������B�%��������j-�k7Z�D8�8��?	Ttd_���t����e���;�������	�h���h�r���+����frO���N�����b���V�hx�G����y&��S��3%x#�������(���Y���2�^����u%3�M��8�tV���2X�	�B8�,vCF��*��kk�(�#S��j�&����0�r��_���oO���|��p���f��H�,I��K�C�~����x���	i�g������A�>gp�?�7u,���)�b��X8�G�X��f���cw�.��������TY�&���*P�o�E@�w	q���!9����aM�z���m�k�,~H�R��{�_�� �)�������������-L]������|���F32��s!�C�*R����ie�Ih��k@n�#4��CCPG2��U��3�8�f�M����x(�R\����W�0"M��^�G*�)���p�L��'e��'1�"x�#N�E����H/�J�����N���mw� 4n�}�1����B_ze	�H�hF&a?���jd�N*FW*��Z��7Q�
f
�#��H��3;���^�U�����!�"<Y�@F�����9E������6�$��S�4A��I�SMz��e3|�lT�qi������,1t�<�*����c�Aa5J��<��h�NI,�)t��
�3��:�q��e�x�2��-H��T'_��������_��x|\��������7�2HF�"x/���I�������ID�5^=����b-��~��}�����R�-PP`������G�X���B[�p�!>�1�sqo�O}�OV����a�R���C���ei@�'��Jj��F�q�n���G�k�:E!E���IT.Bv)�J������!#����qlh��#�R�K��k��B�E�P�iD %��+��5`��mD��l���o�LL$��X�4��B����{���^��=G�F���?G
�����c��Z��g���87=,;�Q�/��@��	����-��C�v�J��*)��S13�)}�H������,��10U[T�I"�������{;�:�9��A�
�{{��2��9�/��P��/���E���!��0DH
G���a����o:������^�K�c����5w��SU�N���;A�3�W��Q����7���F2��n1<�Z�>����ZrMg���(�b&f��R���>E���,������0Z�z����1��>�T����3,WV���}H�NT�}��VJ��2�f�|!��*��3�pVE�H����j����(#�v�83h�����4���gg���HyWk�vH���&V��X��Go_�|���������W�.��=�(���qG�a�[�i�?���c��N��j�8��D�x	��F����=��*��B����g��`#�IW��>I���	���5������`��za�y�#yDd�j*\.��^��K�q�0���
�&���u�IlQ�T��+���7�~������nWu��O��/�
2Q������C��04�R�[��d�X��_��u��;�=�h��O)D���P0'7=���Z/��P��oj�k-&r�
�b�s\�$r�s��9��R�����h+��5q�G���vM��F_H��,Y��X5?�a����	�m5L4��d�\������Y
��-��
E����~�a������7W�w�BMX"\�f��W���w�6'qr��}��[�b'6{
��T@��V��~�:��;�`T���&6�\Q��E{�?��.$6�l�#6G���b</4�Z��T����p���b�zP�{��b��3�9fc��Iq|HK���<c���5�*7�4g�b+�����
������V�~=�;�$J6��D�Bd���c?�0��Z'\��P��,^����kh���9�#�L���P|��]J�m����b��=x^�[7���nH�mhZ�p��e)'�n��nW����16
 ��J^:�H�h��xCX�k;�#� �S~����o_���|v�k�����]�4_��al����G)��T�.j���?�1�nH���*pl���Yp5Xb8�8�*�(����h�V�c\�t:
�X����s���s��J�L�k��}��t���=y���I�f�`�D�xG��gR5�ThG|�0����i���eT�/���B�H'�y{���x:�U�!�%2�����r!d �r�p����F�J�lnO�W�X�s���\���W/�*G�d1D��Q0��I�Yz=`{=1����e��2w������R�0���}(�WK����"t0*Z�C�Z�v���j%��9���n��
s�X/��E�-bF�+�b���b�^(���:����&j�	���L�BD�q��'���� �_�M�$������Y*O	��exY� �0Y$K�P�����@'�a��F�Fq4�py�=�5��9g�J�����HaKxL'bI��E�)*$����E��^zd:���)L�������T|Q��1����E�s����'�����%�����P�-	y��R�-J����d���W�k�jk<	��<�m���E7�hKw:������C~�3t3+�����G��R�tu��W8bnUX�O;]a�d�EID��qV3"�5#�B��������y8C�3�R�'��1,����W��0�t�6-�'����*�E��\�������������7g�����	��j��)�:&�-���0����V[=nF�Xl���vK	ju&�FQ��C+BPb���W�$!Y��zF�4��{/��1���P(��_�
]`|@LdOw��j~�\�����=�^\��5y���!(��|�-���M$184����p���[c�����[���%]�I�e%������7�"���`�:sJ^�������*�|���O�:����e�A"��E�A�('tA����&���vw�-B�L9�g
�Mk�����F���{���{\�/�9a��;qc�X������1��*��c�A�g*��[r�]s�M�>������9_@�� n	�T�C��E��;9�2L�3���1'#;��X��+��%������z�Z@���������)�I�Qo+'����XV�A@�+����|6�]-��5@���z���#��/��
���]s�K�JFz������h}4���JE�D;b7�6N����]�4C/+��]R������@���!f�b�_EH��-c��"��u[���Z
:m���@���������p��'<:8;	�1������_�C�8#�6������O��<��s�G���� ���[E���J�l^V����������_�y+-�8��D����v���7a9���DgS(rf�^����vN�m�oj#J�����+K�{Q9SW�X���}�3�Uv�|��k�H��O���.�_h��c�d���uE6H��&z;��FJ�8����4Q��H�tPo��������.�lWu�I1����c��fV�I1.�a�����R�N��d\T��v:E��n"�h�B����,"��0���E�C����e*XO�"K����i�����&�����7�	�L�2|�h�c#����*��1S���4V��n	��gT�������b���w��)0�g���[���m������8�?��w?SO_�`���I�>�K*��J�NH,��0jX`|�OD���2����O���e����
S�P+����@���r�m��u��8v�������<Z�@�o�h��'<R�(�x+���$��B�7o(��|?�utq6/[�^���a������X�������Z�������P�}K�~8g
��>����������F������h�*_O��2^J������?�����������������'�_�>��2r�%A��`�Fv��/��Y
�Ump��Hb=�493>�����U2)�L���SH-����y�C��c)TnV�O�j�QXE��*@�������qFy���by�-���je��fYX��2�]�LKT�y��������8���1,W�����������V�(]��+v�����9��$��<gATy��m\�J��Y�H��l^�F��[=�Is����l�N
���L�xL�E+���%dS}�w����`B��6h�"�.�-��4|���0���X����k�$�TW��Z�Q`�Z.V�&�EB��������o������t�{&�b��x����p��qa�5v�'D��`���0>�^�s�2\�{���F�t{�Y�Q�A��C����H}������=��K����|��FQS�p��VrP#�z�)��c�,���(^ko������v4���F�I�4�nYI���������(�B���sk���7+*���J�f*#���@!u������Z���u���Pe4��Re�(An�%��J�H�R��xc (�������}�/�/���Nue_�8�����)�^���v�i5�Q��Z�[]���]�Y�=���_�Q��0�2o[�����g���MUl2|d]��4X�����tt���dL<`���'g����)&���QfcS7��\��(���f�+jG#���)<&�����uv�<-��x��:�|N���lG>s��/{�������4���r�G=.����l9X.1a,>~q��pp�����G//�89=>������c�����|��3�G��\�G����s��kN����m"��\����;��`�W6�V��5��)�'�wT&�`���}!3q�v��G���(����OR��V�,X1������@�B�7�<���
'l>r�-rL'����N�O�����p�n�P3#���������&����Q�z
���B�\3�d�����K(�F�5w������s"����`�Rlv������Po���|������e�p���*Xx���-��}�6�|`��S6>\����2������+ls9������'�U9�������]D�
k�:*4S5w������*)����7����a%���"h��mE����.�N:����V�T��q'h��j�>l�F��dvKL�e��Z��B��Z�Q7h�E�p9�;�M��0����������2��(�[�Oq����x�a����W���/w�&2�f�����/�����\DZcC�&�,
��X�I�~�0�l��K�����"%���xb�(c��y*E�������>f���
x���S�v��*n��m��M�uA��20q�vv�#�L�\�"8��A������Ez���o~Vv�%\�8������ �zd�|���G��R�#��w����������v�S92
>����P#e@)��R��G�i6^��Uk6���V�#���,l<�%�-�+a��'b�#k^0	�H�{3q/6����0/���xn#��Y(����R��e�����n�}{���6K�/&�X���c�Me�8#�kR�q����d0�����:N���>���9��l�^Q{�^���n���q6�j�+�]Z���8�I����9<�)%|��5��V����ZP�o����5Z%%����b���.a2M6�}L�r�"��c�P||��� �NLv4�_#5FF�$X]c��=���y�-Y�%.y	`�HXFR�fd��.H>F�e���yJh��p�0���5��:�m�����lF�
�1���A���NU�1mu8��}�PZ=��������?��QV���RJ��7�>���a�=����jg�a\�5���������@Eo���|0J1�� kn��� �����U��4`'x���I,H���������5XC�����&�J
��hz�6\�������!�X
g��;�,	�s��K����q����F���5r�����pR����J�=������5"�Q�o��EA�e�����!���2G���i@:9T�g�A[bj�kTR�@-����+����	���/�
a��+<���|��3e)����<���-IJ��1`��:00[����|q[(�MI�=�&�;��������juT��~N���66��7�#�^����|RP�p�lH����x�k�'��&S�<m�������D}�h�s�����x�RU���� K�Y�J3DqiY��:]��O�%���?[�����H�#G��,@`8�	��)���J#��/a����0K����z���WdJ��<����%&� ����}*�)�p��M6���.o|��`>f���E�?j�1(����m�P^;J=�5����n'\`FF�����Z[b��[7�R^���fV8CS��5,o
���p3�9��|
@�
W�q��L���?�����Rl����e	�a��n��Gb��7@�������y�m�Uj+Bl?�O?C���{���{�|�/�Z����5l�}TI�O=4�q�k��~�<���U!L�=v7xv��uX8@�d*J��>�eO�Z0rp���3Zx_�����X�T��
0�k}4�����i�
m`K���W.n�f�����.H�sB9P���\�.U���T�%!�1��xL�iKg�1I�c�L
*4������4���#B`��Ui8�����>�v)^`�V��0e���xZ��u���o�q��&/l�+��4Z�GkN���+R=E�c<��0��7	gatD�����Q�e{��cq(��j\��)=�kd���]�G���yN�e$���u>Z�_�^�@�?�=]�e-���b\Q���a�cu���h~&(z{s��R������!Y����XM������+;��xZ�&��`�Jf�b`S5�1D��(�y��oF��8��8%n�%F�O�X	E9�,'\�`0p��DZl������}?&��MR���0��N����9[�)���
��d���a1�vm��A�>��{j6�/��G�XXzX\�`t?�?�9N��
�Z9U>����7�j��n�{��y�6���rsF0�9��������.;`����z�o��z2��������xd���*�VaQ�~�w���	(�]�c�K�����Q�lBY�IzVa�h���!Z�.�mm����B��Ja�^s��A�Vxy�%Q��:�8�����	�C��\{�f�Ro|\��\��}-[uR%��/�)����I��<��B����]�h�%��(���K����3�w�*#��}�f������Za2+��h:K�`|��c�J�Pt�'`� `t����a�� t���������T����v�&���_�P�����A���M,���}A�m�_�E�[��?U��8�Y��y���6�{QR���*7���egg���e&2%v�������&�f��%�"%���x����?�)ja�*����O�����F]Wx����Z��E�B��$���/<�9z0b6�c?���HD�P�����"���>0�F���,�l��i�%�N���n'�N?�}�c%��k����go�b�1#O� gQ�}�s]��q�������-��<�������1o��� !sz����M��H�A.%��S<�R�:���-��$����B:B���H��A��PL
BX)l��~�&�z{��ZT��}M�o�38��,b�A����lfz��������V7�n�T�h�&�W1������1iB����$]xL��t��*��_��s�8 �6�#jb�!���zw��
���|}�����5��o^^�><;��}�"=��[���X��HSs�G��k�������dG�Q�t'bC�2������9VAm^��fih7��U�����lY�R6A�����#/�u8&�@.R�LtN�l��w��t���7$��K^�xoA��)�NO^�+���(���������nk��5q�&6(����E�?���2@�&��(��QP>
V�E�vs��e�S���$w��c�M��Y��e7W��XG�R�����R���V���G��	1`4�e3�2�T�<����ju2\J�*�+�{��!��BG��ci�R������i���^��R|�j+kT������EXim��A{���y?Nh���Eq�=��T<�nr9� [#+�Vn4p�y���*�L�G�^��-���Z���
�J�c��a_��#`x�E���r�T!����zV��7����>=�N������.��F|��I�vQy���#���V0�v<o��D��V�q���@L�:\�jioC��&������ n�w��2o��
p���c�\r�H�O�!���C�4�L�v�����pe����������
�������0\U�I�&��{��$<���i(����
��59���i���02�Y0}A6
���+�=~�L!���}G�'�y�z��5H:#C��jJ��RHO>p�����?`'t���,��7������h;�GI�<���GA$^��_��c$1��F�$���@Il6��Y�RS��
��W�����D	�(N??����W'�n�s�2q4+����9=<�j�o���B+h���U�m���d���}�%�pJ�tF��V�j�I��H������B!�����LSP_�^)AH�����'��t~E�Ws���(�^e�������h����y���Nv}vc��CK�P�3� d���0������;R����3L��K��}��$o�<�Eo��~���%�����p*���r���16�����lj.
�����l�	�!c}�}?^#����l&�]�F�W��?'w;|$�.U�s
�(���������Y�qXU����:���������qb%
�H��'�NV�0�������I�1��R^��V�p�G�q#��ml$�q�bO�o9��3`���z�gI�Euj!o9c�E���k~N���4��S�l�9���w:4��;9[I�����.��6�y���������KI%����*��7����M%���K��b�snvu*��*��e�N`�k���M*���#x�c����]�@��C�)����������N���*hw�T�@�s�e������8�-eQ#�R����S9q2X!jjk>�VS�)������h2�E�����L�]L/>��`�g�,��^:�sB]����m��y�"P�iM�m:�i6��C0��|��E�	fWN�b`tK���(]]����lO���x^���"s�y��@|���5���?qh%�R��m�Fl<\�NW���NR9
�gZK�74QR|il41�
�)����2����I�D��4���E�z��[9������0J��;"��B����+�dJAq�NO����il�p�<;�#O���	�(��r������e�)��TL����'a(	-Y1���������bZ���uV:���6�/F�����lfb�"�fBf��F��I�n+_X	i�.?�J���������y)PeD���/p)*]9l����A��n�<��d�T�psr�1
�Wa��1����e'�^+��3��kL<SgkA��;d�2�u�����b��z����8p�;�yMu_cXX)jk�U��>�������k>�N����Nh��]�D���������K��,����#-i�[���?��ely�b�Y��2���V��q�P��*oQN��8���Gz����a��|�V��b�*��T���2���
Rr,����"�z���	{���N8*���#R��d~��%X��Qg�>������])\p���N�L��G�D�/;�^�J\* e�w�!|Ct�������J10W��V�!
2`n*�\�Y:!Q�1��P��"<���2S��uS����Q�t�J��x��6�2����7)���o�S��N�d�`Ec`�������;�s�����mTL���\�tw���5�,��uM	^�����bD
�5N���G������;N�����0���I=T�@MT.Jn�HI3����4R���<��r��j*�)b@������.Og*
�g��`
�|���FK_|���9z{�����L���^j>Mi�lXmv�c��ryt�y1v�}x����W���������|��d��oq��N�y�[j����m��)���.��i�:���VZ9�!�Yq�\lQ&b����s4q����l��q���Cd�������������<��8�]�[;K������
���M1��nK���
'�E�>>�SAZC�
?����������N��
\%,���=-�A��
�t�53e����4W9[`a-����f���t�w$����q-y��\f*u&J/h�v�3����f��{�A�,���nR�c-_���8k��5�)=��5�bL��w��B�9,(�0��x~���<D��P��K��h[JFTJ}�g[�J�T�D}k���G��!U������M��vu�Y��
���.��2N3�s
�����>#.�nk������5�,�*���tM�!.�k:mU�!a��Jd���"���]��V2Q�r�q�������/���a��#N�c�B;}��=�,,��<���
��M1�AU�����'��#5����b�%������8�{�\�p���;���)�p�x�gE��6$�V1���)��iZP
��c�s��]�?_]d������zA]����4�G�T��-%��T�I�P��N<��}�2Aj�[��"t����($E0�
]��)2f��w5�gk�4B�@��s��_,����x�H�2z�^I3�~X6@���+Md2��xpI�5� Pm� �yk<����tS��&-������~G����z@�,w����_�?z+�q���PFsY�[7q=�x��lC���u����e�3`�:)��qLy>���{�FH��	��
�V����7N����&�R�<�����X�A�U�!lQ����Vx���������5���I����3C��KW60�����Q%��lo�!��	�������1��1@u����Gn��\��(
����^�[j��So'��H��ml�W~������q�R4�9�����jb�����X�|����P�66J[EY=@k\\�F�|�����c���:���S��Yy�X���������w.�X��F���M@����V�b��&&�� �s��>P�/�F���:8��/c"d/@" xc~��=@�#J����jR�W��rs
}B���sC*W�h>fq�X��JAy��H�;e�>��u��E`F�3��������i���c�8]2�����E���G�{W�~S������m���e�(\�Y�?^�V��k��N7��{W�W_x��|=��Ai�=t��O����{���u���{�J���9���\�$����g��U��M H�1��}���"�X�#�9
:C��(���e��s2B�LJU��h!=��c>�QF��[���C� N�N�Nb��)�`Q�}O���z�-d���&��[P?W-R��Dc��J�"�[�z�c�*>|y\���ECF�����������+v�B_M��s��1�7e
�[S#�^~��u"���gV�>������7}���l��]���\�%n4Rq���� ������8��Z�8_I]�D��.���|�]��lKTJ����(�;/�D�i��G��	T��zR�)���@(�R!���.R�*����Y1���J1�I���Yd�t��X!�U���t&	����,������({u0MP%!R^�zM������6:�W�?ZRXX
;��6	�1a4�#��cyN�������[�F�����?�M�p>�`Q�/$t�
�uE���L�:��=fnk��'Z����c���0�IPv�����r%Y��%��9�!��/�8d[�������,)A!�6%)T"�j$A)V!Y�"�j=�b��>�P������=H�i:��C*[gj�U�X�GV�~09��K��L,x��-kB�2P8U�c	�cb���H�'[�v�����N���i@�g��Hj�
��H2MJ��t\.V�1"P�R;
5���h��I�\Q `Z�/�XN�o����9
'H�p�`2e$���L/�L�Qd�ZtV>�X���p�#��E���y�I '��M!��Yz�'�mm���=An k�E�=.%.�J�)	i
��y��^��tx��!��n��T��@�`i�����o���?�����v��V�\T��h�
%#O�Y��B_p��?��z�N��x������pC�k��:�U�����m�#��h������go�����G�;��]����1��~���N�S�iq�dC��E��D)li�F�>���0yt�DFN����a�JWh=����Q���0�v�F���W*oP��;���@��r?W������[U �����gU����_�
P���:�-M�}�ZSL��)����`
��
�}�^b�]�l��+�������u��D
�~���������N��.�%����So���6_*a��	��������h��&Tf������+5j?���wU��p���EtTZK�a�-�i;����
��y���bo���d����<u��d��V���]���������<����yFYp���N�;z��e+G5���&��=���1/5%�N��];e,�5t�3%[�q����N�`�6fG��:&��	�+���4M(G�L2|���i�c�N�e�������7%�E���\41%�E�f�hb=y�FrWB^VvR��L��(��fU��t]�R����L�Z�v���IO�cXu��g�kH���"�9_KN4�7Ld��o���Sd`b����|����2b�W����fV���1�8��Fm,~4����Ry�J����a�����=3�4�~����qc�����J��g���e���<~j�!���
�_���j�k��F�	T�r�`�p�=���]�Z�����h�\���O�x�����u���jt�F@�[,���DL��F�I9d4O.������3X(�� l�V���T���*��L2n�a�E�P��S�y:�j�����r��x�����]+c�^���1q����|���	s����	OmB3�n+�P,�}kf�~
�xF&w��"�s�0��Z{
z?��D��w+9'M*��
,=O6��=���'K5�E�!1H���e\�t6#\)E�=$
������q	���58H�)&�EXz
rb�����Z0VL�]k[x~�D����M��m�m5�{_nc,��lj��5*-$w���[���������q����J�����������Se�����a�R��LO�=7����[�����k�������nc�eL���|{.{7%��e�����[a[���QYe���o��OD6v�=����eb�e���d=�4z���b�/5n�|D�;�J�	t�Qo�6'�P2��G��81G�@Z�&_��(|�e�+�$�=�C�����&�����9�������n8�8�DQp3�/�-��m�������G�C��tv�����Y�Wd�����A�{q�w�
30���/����UL3o?}[h�����
��Cm�yc���1���z��*4Q\�G}���D�}`/�hL�NU
`}5K	��36�k�F�,\]{�=�1�B���.��K]�e��~��6��\��3��A���+Vo�e)
R���N	��R�M����I��b.��]l; ����u��F��������4g�2;V�3T�����w��(�X��2Y��)>wk#�#������C�i5���DlX.}�$�pE�GH&0a ���K���/�n��kE@S&�@D�u|��\������#��|���E����$��jH��h���7YO�����t?�'}%oNM����v4!I���mY�(c�x
���u�2���]��������qz�B�	Mw���)d5�=M�v���5�D�����4~
q���)y�����O�s2�����bn���Dx�����]������Pf0��~J��{G�
!!��/`�Y,7�1��_d�:2�K��r�FI�Wq&1Q��`��8�uPA��(?��%f \.�V|��g����w�d_��E�~s[N�J�~�$$ki�HI>1�=9���W�jta6#���qh_`.����iQ4Q$��+�IV�q#)�I�@��w\��et.���B�t�2xV����v������>j?����!���p�+�H^���|R�a��#i�u��A$a���6�����u�&{W�C�-i�8�s����@�!��q�Pc���]����I��v9_�K�0P����^�lt�s�S��R���K�x�8���������Ga8aA��Z�U�6��4�e�%���+U>�T{��
�[�V��"�&�����0�,$�lM��D�Hk���m��r-��:b�s
�����0�f^,��f�%]��B)�A���1=@�`��U�����b�Y|�4R8�3��,�a�c�G������J��-�FbL�K��w,)�-�h�	��v9����Z����Y�W�%��F�v:o�e�&����Q� F�p�7����U�G�NL�}���fp��}1��V��H��7[n�B�"=Tq/��/��r��>I���t_�P�]	(W�'���Wz�9�*��4�9����=@�o-�36u��1_X�L�D�*h��:�B=:�0ah���K��bT���	�-�0�v���N��DaUM�����qd��92R������\���L��4�L5�
c��w��������<��[sCGv�&�2��/
�p�ar�!��^��3�5����TyI�F�@�����^)�{��=�+�R���J,"��!r;n.��;=��m���
|���V��|fb\�b^Y^5�Fw$,�S�E�J{d���{#����,;�Q'V��2��9�	gN��q�a�!��ihc���(������i%�f�C�����RK�6�g
aO���%��RC��@�W�����E^��pC��v�*��"��D[��I�j�I��..�bG���Tr^�1�XA����0��rv ��L�U������B�O(��Bl���Q<g0������epE�z��81
��
�:K~p{_id!,�hj*u�,�U��\�O�����o]��r*^5���0ziI�N$l%�MA(_/?@���?���UO7a�3n-�����
fE8Pk���W��<b6�R�d��������{1TV+����s[��&�J���kl\rHly��)�8�,s�^�����JEv��,�y :lJ�x��#�V�pN��������^_�"��Y��s��g6a~�'#yf��I-��m'�t�EB��l��Z�-�E��oT��
��n��L��������(�'���T�a�Ypa�����#�+���9X���]vSL�g�[��KC�X��Y����U��Z��K^�����%����af�k��%�E��}����&t�5�;W���G�$�3E�Q��h<2E�]��j>�Vp����Z��yv��U���1��Qt���[hc���H8G���O����b�R�j}7��`94'����{�����<����D���������&��}�8P�d�e���8*��$$@����3�U�m����s�m]���������%���\@���hEU���$�c��^�5S�V�K�6��<���JZg�p27fc~�m�2�3-s��%N�R�G�W{�%S1�d���"��E9(����)`7�*�'��~`s�1pT��6����}
ZI�A���3e�z��A�����s��sz�f�J���/�5�N��J������v����m�7ga�+#c����`����5�
{D�r�3�$��jT1����rl9y�A0��������f)���+}�#�pn�Z�#G���#6�^��Y��.�BH��������e����M������O�cd4iZ#��S��39r��R����
h�d|�2I��Mx�)���3d�N&��x$�5���?�s�3�)��s���r���a��c��v��Owt�+���b�.y�BF�2pv��n����
s�4���eE1&�%CFF�a��
�/�Y�6s��I�������W
�:�{`�H
��Y�X�1V��2-����I�!���>�������)�C�vR1qo#&I8<;��)Fa���~�QA��f�S�)����8E!9�F��N����!x�.����(�������3y��?��(o�����H$o��;;~��9����'8��-����c��%��n0��.�����x�S�'��X�:�.
b���c�tR!R/hd4$�oh��}�v4�,��_�8E�F�R��	�����������[yD���T���V��(H���\)������Q4p�^���8&3��j�%^�+mdU��(ztq+RU�������Zl��larP!����Qt��>�+��N]m��Xd�|*�;��E������Enw$�m�|���)��A�l-��5��*2O�T�j�9Qz����'����P��Z��Gd#��H>X
�_�kgS�d�Vx�0_����w!l�e���as�����v��4�8���j��YFm=f���V�+`.{�S�A����[}a�t�xo��Wrj��T�$"�-Y�� �K% E�n-�J$,IV��k���l���M3��$�z�#k�
&p�7q��k-�jt�PI�����`�jE��U��?���6��>�jBB�S#��I�jm�=�G�q 3r���SD�(�$���h7m����(w����6a"L�B:#L�	����?W�M'��i>�&.�!#���L@u��K
"�-�6d�
�1Q�6@J��w\~�w7v�H�!���/=�����#�U��w+�aGr+<����
����[G����+���Y�W����9/(H���|6f������
�I�X����j��18�8�-d���9�
��h�4�R�tJ�����od�O
�O�,��9K$��W�L��r�Y(!�]N�&���N���i�Cq^JjjeF�����f��L��6_RY)��(p�wg�m���s�1J�����2�����V�l����g=�d	����T�����l|[���Q���3��P������"	���%ldR��,��cG����#�M�x�g�]���I��x��{�p�1d�}�����JE�f�T.Md]�;?c �U�X��u#�O��,|�e8�(T=^�VtVI2%�c���4�xL����v�A�E@D��JsP����K�$�G��rlE�*'V\�6�=7��	�!d�a�H�4s�l�+nn{�]��h��0�l��2�n844^4�(e�no�#Wu�.����&.vpt]nY��=[{=����
�X��	�e]���27�t��*��@��^��5h����{���2\�x��������JD�`��'���H�������������Q��i�aE*��r�xG�,���\o�,m�7��4�X+��C��~��e,��f\t9DY������L9	�Y�hf~�\��������p�j��^��d���,{:�OM���������k=!7�F���z��!2�l��b3Do��%��U�J�GA�	�.G!��q��\�MT0'������r��������>�0���N�����t���z�,G��4�
)�9il��6�r����( `1����`��!�&.��sJ�#����$�c���V����{su�d`6��z�|J�\"�����<��Q������z�b������������v��T"� �J:%V�8���+����(����?��v���?i>�$��^z�h|�������� <�jl�1X�$�6��t������\Y�{?[�@��l�l"w��J3�	���3��������&�X�{
�c���9s����4���ei��*|�9~��!��n|���������~WL�t��%�� �?���vj���
�L%����O�Z5��3Z�y�������Qm���){<�����e0[`�����I�an����R��!-�����s�>�t�qt�G����L=�bdBFq7*6�P�9IW�`z��Nt�2|��`�Y.5*��w��V�&�"��>7��������b����ZKg,n/[�4���\�blo�h)��9�T�yf5R��}�������~��ov*�6R��na[���T.�Yv��,�a8
W�U��	d
�Xu��w���������_y���������z%7A��ap�p�
��b BGh��X�#x=B������n���wH4�]N�|p&���!���7�����a+���^y���M�Tg�H�����MlY��sVuDP?�������S�YX/����W��a�{���������3�cU�����+�q�=F�1���%���pUG�pc�����=l~0�V'�~���z��i�J���)�����#�a��=����a��3�a>�\�2=;=T���9
S��\h�,�N��5���n���K���`+��X�x����[�N�N�7M������}F���`��{��+j(V3������t�
5k�W�y����Xl}l��:/l�N���Nl4��v�;q���Ev��H�N���I��w��?IB��A��t0�
@D����1���f��WtS�y��^���eH�Y�>
Hz��z����S
�?!��+���+z�q�����O����������m]�1������{�Lx�+��|�S+�.�}��w��w��p���������C�t������������8����C�[��w� 8�o�������m���v������2<�;��G'�#{tDK������g��F���b�r�(@}����x�+}%�r�����ER��_���J,�3L#\�j<�����R�J�-�^�M����GV�q���u�e��Gz*r���h��
6�7{�
�wK�|���
�Jp�W�j�����0T�����l�qk�&5=�����}��u���v���y��$�2�=Q�2���|"c�������X��x\�iT����7��Nc�D�Yl
"��)�O:�'�����.]���)���5O�`�`,�����k�U�~�J�{�_st��8��p1�0����=�QMs$���z�DM�(_��g��g1���9@l6�d�7�
���40[�e�	 E�z�p5*^�F�f0����}�l�6*����Z����V}<P��V�����f��g�g������Av��(���������Z�;(f��F��q�&*q���,j����	�`�M�Re���:q�c{	�M�S������x5�x_��yWeod�����l2/'k�<4a��X���
|�(�B
`�hg��@;�`����`y��<U��n��^�q��7���_�GvX�X�q�Y�d�i����/��EN"����)T}1�F�s4/b��Z�^�Ve���w%fyL`��~�����K�=��Ha�����k�7��`�T�|�ox���"_.�(��}�q�OrJc��0�2r�Oj��d4�:���v��y�Z�t��rt��h��}�p�m����I!d����lT�	�Qh���$���F�`\J�A�I{���2����9,�Joo��-�E�~�.��xn��H������L��Q�����d�-�+��6�L�<�M6���>�6���x������	I��c��=��lL%���tZ��|�����J�p"m���Z+`�|��	
[N��vl_k��{����������u��?^�f|s�y�p3L@�=������)�d�[���@A;�ng�,�+L3��)H4�SCm�}6�}����|�|�x�(��!�Gv����J%*��/�=��o�	��p��hwQ{7���[��?�]�}��5p\����Q�C��	j�K��V��)z>�V6mU��t:�F�������o���h��(�T����g�u"��S�	#j��r|@?�&�����������]X[�l���z�>��C?R!��cz��b���������L����N�����-��H�3<3Mb���p���f'+�z��E7���"�������h��9xw��&0�E��z������%���h������N��+�-���G�6�G�Dn�6���<A1c��bT)J���
��f�_�����5�[�C����.�����zvd?�QRb���H��;�(�(�X�aw���&5Si]�vD�*��$����������hQN�LGo_�|����mT)���B"�n1����hw��g�sw��&��p�
������G����+6����N=������I���K�^�,��>�lM��#����(j���B���2�alf��rD�
��v��f{�n��H��
��[�K��;"v����7���mY8`�=��'���|�^�����	,�y.��V�_�]�r�iRK�&��=DG�Bg~fo��:��e�n\Z2�����e�pb�XP�!T���������nH�]N{�S �~�T�����s�o(y���������N�F���W����4o��"�����������>2��iW�E��?�����W��X_Xs�[m�?���u
�V6�,,z��{����SR)���Q��V�����j=���6wniD�V��&���R�1��R��[V
��0/��Y���B�.����qo�@�2p�]��b��]r��f�x�Z����<S�"	u�2y�|rx��O��w�]��Gg�|2��(vy\����j��mtG~� ��l ����V��P�?~g�9�e�;�X����|�i��i��{�!mV|����	�l����,��{]��������������*H"mk�[����He����(�%I���u�C7;�LA�E�E����$��g�m�&���^��j���z}<�
W��������T�]�
��%�������e���&�l��:��~N+y{��o6���t���K�� 
������Tua�#���
P;�V
P��
�BG�_���W�U���=��@�<�7������*�(|��H���`d�I�
LF8XT_��r�^l��\D](~�����z���)���M�O����G�}:��T�L�g�\!��������vM�`��X8{D[pp�j[Z�%j��q�p�s?��Ga.!��L|�����Z�(KXJ�Z���z1�",R��
_�[�a���������%ER7x����1ql|��s�p���
���S)�S��q�v{o�h$��(��S��f�\>�4?����=#c��-fK�4C~�n
��lP��S��Q��S�����H�&C>�A[(C���dL�(�k@N�G����=`xu:-
>����k���B�R�1`�E�����.?��_����2�_Y�-������B��}x,)�Ja��w�s��i�;��Y�w��o�[�)~�`���+�������M��n����V��'oes%;{{�bS;A�W��)D��w�����m�ZZ�	�6/��u�=Zz=Y�O���F�pq��`��
}�%�c^`f�7\�'g_�{}8xs���(�Q�j����Z^�mR�x
6���
��WT�"���l4�
|��eEPO�W��8������Rh��C�cL��N��Q'R�v�l�'��|�O��0(��C���j���L����W�+Z"��d������,�I���y4C��(������i���83�k��f��K)��q�5�L��~�1j6���Z�`��$3�}t����F�^l\�����6$_�HA�B��A*�m�������{�@v�`_�z��S�Ls��:z���������~5���?=<�=�N�Gt���g��R��R j�8��.��W{2������r��G��|&�=+'�*����j*�b�!��(�	��q�3�a��I8
L=�:WN�j9X��m�����
=O[ �P�1;	qG��*
D����L�r�7	�RX�7K]�s��K����}��y�+����@����(�,E����?�=<|	�}5 ��$'�����L����N��:�~��@�C�������"��z]�[kKUD�����t�Z1��2��%l��n���������ZZ�x'-%��f��8XX0>�*.��V��^L�e��D��F��":b����{�nS���v(T�O���^�:{�>:x{v��
84;��Y�s���-�������[a��/x�����g����8��EF�"O��[��������>&>-�7r=[����r\ D��	�T�(�F�Z��0�{��TERDk����(��X�x;;	��y�u{�O
����@}�#��`����l�b�a��s�{��g�pB�D��*,�+>`���U|[�?�7�Q���]�a�������e����?�:>�p��������_�	G��#�l*+*�Ak����j���u����3��6������&�����u�PiLDB>�����h�qN��%��10^e�\dA�`�0��`�C�l������������F����:�;��Q)�)T�h���!F�u���#t��S��x���
��n{gE�Zp7:;q4�A�V��v��n�����ss�-������f��\�c�;�i�����~����w����x;��K������|r��p��7��;�ux��w�Q��Fo4�V��n�^o	�h7�aW�b����EP��mBxR�2�_x���u�[���NjL�p�8���b�XKn�����/T���e/zaZ1((�IUu��i�������o�i��&��)�����x�����_bFEQm>z2��	����k��A��W����������s�$�L9�
}�h'������w�����v�6��w�v���N��Hm��%{��+�]gA�Q�c��cJ	��F������f����X�l��$��I�mevWe��vu6�nd����Z�B�/,B��7a�`��p�* ��_�?��cBn`=D���C�n�nyL��1�/PZ�v[��tg��Hg��������f�Iq�q�Xa�h�c<������fc|�T����V-��%lP���I9�����h�&��Z��N�`��N��I��73���������9���e���=\A���E�]9�.��nc��������QQ��4��48�����*���b�,[>_�:�(�4'���e���s�Zc�rpTz��:���9�1�v�G������p�PzR�=D[;8R&)qj8������D\n�E0�m�m���UL%��a$�v���[E���"�f]����'��?Z	T�[���*�^��n����J��;)���_�����x��$W-~g�%��7_NY�>$AP���������N|��B�������[(�Q��J���*Ro�r��=5�P�!\�8�gI����9��6����&�F��)����s6���{=&��`���)ow-���1�������w���9��&k�
��]PYn��Fg��V����9�=���6�Nav��sp+�`�8Q���|8�S�-��t�L�I��u���������Y�^����?F��(F�J��������B�dV%DJ5��;���&$�T������e8PE�%���m,5<d&OI�%	��%�?�
C�j�z
��d1W�x�b>�L����Uj��H@/|�5���������NaP$9���j�U@�"?�h�4��sSWK��C����}v'��%Z��u%;��b)��\w�V�[>��FZ�&u�	WQ0���R�A�����,���3dQ1a��hG���V��L�4G��XO���S{��*�fE�R�q��Z��4D���t�$u�40�H(�&1�n�/u�<�I"�5�e�@q_���J�DT�� [�9��Rd>�8�6��Dz��F��u
9L�6���.����w0����B1t� p.@uBd���������������<�����ca�I��.�1��%n�J�+n=O�1C�m���#KYa����VQT�2S��������J��c�?y���^�X�(7Y����`�#f�����	b� WU{��K�F��UY��f,@k�������4X���+�h%�vR�T��z�j����C�E�4���`�$���>g�S��:\�PuV�7�m���f
�u�F��6��?!:��dl� m8
p
�x&�==;<x���N���������P���|����O;�WGx�q�c;8T�������L����~d����������{rx�������9�
y�����H�F���e"/�i�
6@�
k�i���wg�0���L�Qw0�j^_��;��-Y�6��m����JS��_P�
pIK?����g��x��Cf8��0���������Sl�\�_��x*c�kvO2~5PU��S��^���}�i��G��������m�O5v�Ao�~r[���)Q�-��'7f��E����������q�{�P}z�����^��63���I��e����[v� �5�x�V���+���Gjxj
+~E������er�)�Y�<�f��|�&�m^��N��
g����V�o����	`Z��&��w%��t�)<F����*��B�},e����)k`�{V�`���Vw��eg+�~��pf�hAoGg�mt9�B�QK�����#��8���d\�X��3��PH��*��	~���;�~;X�iJ
��9���Q����<�A������C0��UG7Qgz<\���b����##��*����()�J�0Ib�v���k���Z���e�������{��py�����_i�����+�F���l��D��[�b}�SgG���v)#������$w��P����t/%NZ�G�(_NX��\Z�2�R��d-Q�R�dU��uZ�f-��^O��bw���)"����+?�TfZ$
\K����o�^+XB���d�4Uw���T�}�fV����i�pi���N�����Z��^���P=�����0pj�>������2���pF�9��a|N�Qk���5Z�V,Q���O)ilPqb�o��W����Tn�d�����>2��*)�o�9���".Q4�j|���pE�tb6�,�S���w_�&,5�.I�(:�D<[�n���R�`��6%�?�t����|������C����Y�������Tz�(Zq�9I[��`�z�g��o^xH���B���=I5
F���h�a9����rM
�+���j69>O?�����T�y�|�_u^+fzI���n��N��������e?�@~��6�n���r��v�~��u�������"����`�v��/-��%3t���V
���D+m����T���{���Hn,�_��P�'��/l����1������$9>mw:c�w����o����R�
$�����n�$�J�R��H'��QM���Y�f��Q������>�����$C������*z�� <����K+����Ss�4�}��!�d~���DV�����vGi	*6kh�&d�~�s�HX�Dr�M�H�>�1��BF��������b�����!��^�j���d+��|���#'B���s��w��:B�Yy���9'�dHU������"���Oy���S�^�d�n����$���e���woZ�R-$e	>P5������%HV�#�k�cdR��=E3�pv�	�k�2�R2�5���xO<��1�5y��X��yAm-�/=N�yW^k����i��0)c%p�����X%�#�{.�\�d[�����'o)����e1|���\�(�E�~�].�W �dH;���^���?sVBe�L��#E4��r�
0�V@/���D���=+�e�65[e���0�=�Q�c���	l����������8��)\]���f������L�C�p�.���K3��vt����7P6���J�
����,�f�q�kP ��g��s;����`�6���c��D�[�V��,��`J�����6OI�#F�~��p�)I���l�:�����������$�@\J��y��~�����C�j�vN��%�x��J�����0._M��������NBU	����kR�����V^l���Z�'�03����b��3@r_��%�bI;w;�h�tM6��l�W�[��9Q���E9����F��J���=�{���c���:Z�JV�U��v2���V�~��n�.���F������B�k����� !������"Y��<~~%��N~� �}$[j�x3o�jq�>�y���N�d)�U|v�>T#�+�{���z�|����ey���s�.���C�;�H^)h%$�*�����2�����5�gew�D5����*;E4�aP^�)3�nH�F�w���nM!j����1��T2��Z��ik����4��z�C�I���u��4'����,G4�����e��NS���wS�QgC�����T@�&;-?t����9<���f�����[�,H%d`���,CvVN�e��t�������']Z/����%��y��*x ��T�>H�T�O-������.�����j9"�)<C��R.?3!����
�HR�	��no�n6�^���0S��tAi�����r��r�v����n�_��O���Z�.K���

�
���Hn�;��[\)]\����A�����+������E���^�/�*����	��55{����'����Zf,B>���L��>������������oO>�����z�N�i�W�"���KH*l�g2�c��i�3�@�(#B.�m��������P
��e�t��s�o/����1G������F��y���l����%K����e{+Mk;&�|-~�eQY�u���%�B�5�e���N�j��L������Ov��e����HM~�=yg_�9�Cp��(xXp�e�d�I��so������3x��Tn�i���-������/�a����{4�Hl�q�
#���#��}����4�����Uv	jx�rE���VD�LL�y�l�'L�+���Yb�F��b�i�MO�%��������.)����{�f�u��W��n�*_�fiv�����:���|B1~<EPK���&���"���9��/jdG���G�4/)��R�R��RU��B����7�03���.;�$nz�!����bR��E�:r��i��u4�t;��N�u�V����YK6�����J��i)Y���V�	���w�`$3���~��9����y�r����
}���F57����?�?k�<����V�*$�G���;}���3��V�����]���-Z�m������rD��*��f:�	���������2!lJ��-|�V�	]�QJ�����>0����8J	��r��9�`/�W��j��r�-	��A����l��JT�?�'
>_5�=&>���YNI���p8t��^�V�S��,H%Te�e;�6�O�m�%�Y��>�P6 .��.����,����pp�s�M�C�������qK�y�=�T����/$���^)��<��/��\-��p���������P�b1�rf�v��u����Zt�����Z1�C�^M�������F,"~K�s���f���"
IC������;i6�
YO���V6�OP&?���o�K6k�P��KeV�;=kAfz�o>n�����UE{|�Q�61����<H���a�~��`��R��
"�H��l�%�*o�I�M4Si@O���
Y	7��~�r��������x�s��Bi���y���G�z���C���������p;r����{�K'�W������������������������O7���ve��-ry�~Z���Y��-Z��^��<=�>��%+����j����"���<�3]�'�>�4�d���^yO�	�~��Hb�fU]KT��d0U��T�y���f���p6$$��*�k 6�FZ~�IU���t�t�pnn�z^���I`e�[�8�����A"]%���Ex��~=���E
�6=�h��9lz���y�T����6���m��co0m6=�sxp8�@xB��2���S�z�����+o����3��$�yp�H�Z�3o6E������1D"��vW`]d���^�@}7��>�Ad�'�s��*�t�t6����q1��P\�u�%0�&:���W��K�6�1^�������J��N�3D�o�9s"�"����qAuU��	�;U�N�D�h��H���/�������!���@����Y�����z�3�J��1}�O�}�6Fp�y�n����86{L��8�#�z������w��m7S���+���I�e�^�.�0�prst�������Do.'����������2�$�(��^k�A^pp�y�~A��if�Q�A����������@5��7�0���4X�?�E���)�b�Q�1f�Ye������������hFQ\�d�F��6/(���)�������if�������U#.�o���el"�G|n�����E�������E�����W�9����.v�S����!�BJ�4�$x��q�����.j����Ae�6�+��U���i8��.aV�S'�ey�T��"�����x^�Kt9��=i��������|H��%.K���7�o������ �K�f!�
ud�������Y N�V=[����x5�J�����n��>l��%~�G*&��2t�84��G������Y�(�����L���j4#0H���Y��d��3&ng�P���F~���p���p����<�=�{x�NE|��+a�2�l�������������}�&3A���?����N��$Q�r����(t<�r�cL`z!�<`�6�Z�B�Q�S�8J����|�-X��2�O��t(��5�	��4�&F�C4:R�k�;<-���8����~{���z/:�[�#�)/��Y�����������[��uq/C������t9"����������
��M�;��� 0����%�JF���>�|�����)��������O�uz~�����]����G�g<-���y�%g3|
f��aE�c��mN-�o2��2_�Fj=�����n8����0T@i��Zs�����T��l��V������ vT;<�j��������,�!������L%�r�b����&���L���9����x����{��1Z�t���1"/�>�]���Lm�F�|���p������W~uTZOE�J��������p`k�s���!�,����3h�������/��LD]T����js����3�OZ��0Uyp*��$�/{t����*����c�da4�?������[��<�����J��.��Pj�E&�*����/�4a������f$4������M��c�������'ti?�K��J�"�i��'�s�E��;Y��T�X���G���	����U�(8�5���.S���4_''��G��G�F�'7��^_^�p�~@1[�VF�`�eB����g�|��	���Y0�B0��Z,�.	�Q��lY,s*�H�(���c�w�6�16�����W�eb'X6�6��mR�9����Zn�g����#�_h���l����N��x���]|wW��h�*���+��j"����:�&d��m��F�W"���nN�b�R�����EN�p��J�MpX�6�ev�\fWH�2�����x����]�=��W��|K	�\N@$�U�Hj5��Ad����x�b�����%� �rI����KG$�cS��-o���/��U{��/8�i�?����~t&p�Z���u�����kPV�	��W�O���Bo�d�TT����1��&�s�W��G8��>`��M(X/dB��W,O3[b^�������|m�:<����Y������>���{�P�d�p"��w�#6g �������|[Z��(tib��&i���W����9�j���ZT�����������:]s�2�):�7��O���]�������iJ�w������j���m�m�mb�M��i��t?*|)/�����'���y��9���p��^�5����
L$�*�6�y/J(��xO�D)���2���T�Z��K����h���$:I��W(q�SI������>C�j�\�!�?+I��rh���N�
f|T%P	AH�,#�R2SjaOS��`	�)?C�Q1�9�����Uk�� ~Gqm*�G:���y)�1��aHn'�k�
ol�y��Q��:�P�����������U���W����%����ngD��?����h�j�/���^��m���^��X��������=�_SS ��E��(o=����r���G���F����Z^LA
�iM=J���g�,@"�3F�����~)�1����*���Y����������Y���F�5<���8:{K���������)1�P]�Q]��.�n������k�R4t�=:�>E� 
�B��R���S�3CK���L5�V��_EQ�%��
��Q�2/�C���|d�.�&������6��L��da�������bc��w�`����y�������*Z�jv�x���S�Y��UVa0]��U�X�%Jw���Y�����!�w=a��~�Z\aNC�(��]\���6V����Aq�A+9��B4"�m�8������r1�k���"b�M����%�Y[�>
�����}R�f����)��z��6���\+�I}��a��wd��;��h����UE��o��S�f���[���
)2�&�L�%��&��1
�0+)�
��)�bP��i�%�_.9�DH���~����M�Cn9I�A�?�����a�;(
��)M�e�$��������F2����II��7�������P�V���R���4��,�0
*-teX����K_y�~b��|T���P0���]YiB)!��o���F~@����EK�sBcy��p�x����gjG�
�g���3_?��W��	N�BNN/�dpS�������QR�|*�L�p��x3n�L��m��-��V�D&�~ox�,j2��������]!u�< 5L�<@�:2�@3���p�;�
0����Z������N��[��� ^�������&l�&���WX��3?��V�lGk�t��)���;hiwW���
U��D"����{(���xR���������?K�C]Hd\�0M�s$P��!��@�8����C���s9����<��{�k������,��|�Iz&�I�������ai3���^�����\��N�w06�c���l�U[��8���T�m��D�l�_�`����s��-a#�p�'�^	F����4���cZ|�y�����d<K���I�)���\�����J%�����vY����}��W���e�E�-)/:���q�&w#�/�B?,�G!}�L�5�jaONl!�A��&g���CTB��3JE���4�Vr��Ba��y�`��5N]A�9�����F��g$a@�|0����:�;�B��s����g�>�P�hZ�?h��{k�@��N�d�Tt�>���F�,/n'��F�N�^�X����:`�� k����?X��W'B� L:�.���3w����yda�&�'��:#��D����(���5.��"��������V�A��<5���E��Fb�8�����f���#�:��(0�'��vP6z{��:����vYK��L��w���������_Iv|@��Xl4J������;n6�����*�>��XX4K����D��g���`	^?��7�>W
�7'��D��F�N��r�^Ji�u����>��t���i���81�H��$�c4mX'?�{����"��	����_-.[�)��=���T������|W1�n�?}��k4����\K>8��bo2w�`�����Ny5�t�>-d�-�~�-����OtT^�7��;��'@����gY���gD�2�VY���Zt��������|�F�4�>I�C��N���<|Bk�	4���oS^�2�h,�,)�n�mY���m29�`��^��-���k�Y����|�1�]�o�/�?����%}��}�Wr�\�W]��a��d�����ddMy�����yf�T"��M|��I�)
��kb-�����~}r~r|S��t�����o7z�`?���������=�����
{���l��W�l]*M�9~�0�J�[A�Q(Q����	j��C"`�4�"Y���(i�(�EW��}H}�����)AR�e��bA�����1g~��A��4U������t���>#��q�|KvA 
/S 
}M��3�}�8:���1�:��x-������u�X����H�i��	1�p_�����s�qbw�>�(n�PY!�=@ ��pP��:}h+��Cf�e�BGb/k�����|00N�nK3w���G�2w���5'��[�'^9R��,���Z������>�:��� �N&���l��������
�@��
o�f	�>�����U���e	�U�{�=�C�-h�hd�W�?Sj����������c<���rY��B���wiW�����E�y�������Y);����=�������D���v�3?.�1B����{���Q�����d��S��QH�a����	��g����q�/��
&��N����7l��*0s�s�M��&������>
y�i!�@�O�&�������w���b��r��i��7-v�����������(7!�)P��C�Z$�$�K��P���o����L����g���O�����Qb���Z���YX�<0��UVV��B��������v�?$����`R)Q�&��08�z����l�F	"��D��+/�c�u��t��;?9���2�� 0�A�!9m,��H����v��CEq�������mX��+p��7��S���K)s��~��zx[9<�
2���@.��<��-*}sr��+_&zn#R�����Y���(A���IB�f.�O�L&9��a�F�������O|���|>C��J�9!�z�>N�T8�Kf> �=�@���dtoj&p��T�gS8R�i�p���E�!����By�����}���g�s}S�VG�������tR���^8?TA�p ��CP�7-���d;MqFa<������������5����Kd�]Um(�������.�%vm��hrYd����FU	�q��������������-������au�c�%�CnW�I[���0	�_�L�9�	y;kLd�P��y=�<��a��9�YP@�n���n�`7#�,t���1Q�of��3#��|Byc)�F�gME3�#ykn��A���	�-����|�'@_r��V���w!�T�jj���h��_�n����n�6

��:���BC�/����=��b{�=^R#4���8��M1{Y������
���
�f�R��y'���2*�����Zp^���^��a�S%�������a�����2�l���^��E�@H<K1Ap��F�%+�_���f%�I�E] �0;fJ���Tt�84�[���la?���t�QN"f�j�Z�����*vwT�t5 �~�Z^��P�Y:��X�f��

��U�x��O�]����p�Oe	8�|��b\�������(���e�
S��QB������h��s�fD )�����R|�E�-��� c�z��r4�g]���I��z��F���@,����� �W�
��kb?�	�vT�~���t��d�G���a��
����w��jnnZ=�C�G��s�X��>���?���-�+���7l�"9����%k�����lz��"9K%�,K�_��QJ�Y�HW \j����M4='wg���cC5���I���xC�]#�Hv��d�q3-�L���l4;^w�1�;���3��u�0��������}�����^ILI�E���c������N5����@�[K9p6��i�t��m��d"���t���7�=1S��q.��Y��N9�hO�s��L2��<g�l(��d��?����#;����@.�����L.I�Hh�?'�����F��*"���8d�5�c��x�V�+Z��
���%;�4��	�)���8�h����}|�.��6��QZz�X�.������>hw8�Z�1c�[��d���f�q(��>�9������fsdI>�pl2��9{CZ�������F�`T��~Ua�Y,~��^���T\�B��h"
������������O���f�,*HD�Vr�����*��p�
.
��ik\E"2`HDF)������R���
G�WX����bv�\|���L�P�o���J?}#3/P�����IE_}#��
b���N�%'�P��M�%S��0�<,<w�4�R[K�U�p�A;��^~w�����dk�����������Bv��4������#�R�$&-P�������<]�}�(���RiA��X�����
��peC�BWq�Rc�(�����\6����-uJq�_������AW��WPfW&���m���������1��0F�2	�������H�4��WVK�En?�=,�GG�FBw�����s��H8CB4��qk�s��>ap0�������sfe{jr%��j{��h73������v0U��,��M�uP���|e�).1�����AP�(_����&����xsg���G5������^���#o����Bx����N�#���u0q��6Z5&/�<w[&���r�H<Q�+a�M��KA-e�����]@�2[1�2��,��V�cH��I������Kw���H�����(�1�/�Z���F�D�z���D
��FIc)0�
�r�^Q.���0�������4��t�#��c���hx�!�����RjA�B#+l.��������+�5��g���������`@���a&b@t)���^S\����������	�o��^t�d�����X��T�!��<�;N�	���q������/M��v���(�[�z;�5;M��Z�T,�EsG��y|!�J��6S{m��4q����R�O%�b4���j���7I�x���5o�D����7��~��/�����T0qg���B�ymOw��Tt��,Z����v<="���)y�y��;������c�3�4�_S]���4��b���T�z�#��55 }��U�m\�a 3�}�g�S��VN���4��R@��W:���M�-��Y��17
�5���{+\���S���$�	����(�_)=�t$&u_#��	l�����E"(J��Tb�j�^�g��Y���C�G��"|�[����G W1%�)�������
�GR�M��
#Fkj`�I���g�i3������Qx@h�,B����1f	�u�9�a2��mh^b�`�;ju����^���H�Xd�����������~�l]�A���������``C��Z&h�D=+��*�q1\����6<�N�do��L�b�	��'���n>6Np2�H�dX&<�]�fSB�7�,
�~�!�:h��D�YD%�c��+6�\�	�����9v�Jr9����2j"��g��7w����C���sI�B��
�E{����L�H�Q�Jm����!����*~����\�z���/�I��^��s�����Z$k��.F5�6V�|U@�����D���W��D`������z��=i�5��b+������N!���+�U@n����h���[,��4�����:��va�"���<(��4Er�4F���������������K'������5����\<���t��A)��i��gW7��g��&c#Q�2,OHfB�����M4�$rv%@��/@����O%BD�L���r?~
\xt������:���w��� /�v�)m�[2�zR7�y������0|��H#���`�����������N2j�U����.4����&���W�����c�8)|70�1�N'�'q\?���>O"#qLs]j
Z�g4�3�q�*�����<1=W1���`�.8p}"E�V���~��(�g���}T��Mh���k1��3��_�"(�|r�{�Y3]���`�N��M5�#Km�q3�S��)��)K{#��7��^u���E��Gz��`
7�S���P����u��1��UM�����8��{����%���H��`�l�\�����K��z0���X�6�������y+|�g��7,iG�bI�%��3h=/�$p�}�����Lz�N~	�_#t3d�(��6*��.
��t3��-�3�{y����,��Y�����&E�0��o��G�������������_�"�=�G�k�JI��^~e�����	�d��lBK�.���{��r�K����m�&b?�!��*I��������[��Y�f~���K��Dx�e���|A=�a���nk��l�7K`�4�Z�d����bPB$����67LH�Zf�y���7�H����^gE�t�&��R��k�R��+2������[G��}��g3&i�S	��w��:�)��������
�����D�`OT�:	�������+���ut��LD��G�\+�CZ�o5��	m�%���kS�U!���:��%�#(���!���-1t�c~
���3f,Q������3�d`��|�P���&��]Qd%R��55r�,$L��$E�=)�������tKje���E�%y>Q�|���� f��c*C�������v�K`�r�����"�����G6�KMR���n�|
'o�W�^�!k>�;���4�G�p#�(���
�P���Oj�}�#�.�&�J{��Y����ExW�p��=�c��Z�k���^� �u$8V
l����}��l��������mm��1M3�
9&�%�{�8>7'RY��-r�f��J/v&�����X7������G�;����������0+xun^��IS������x�Y���V���������"�*q-6�I���BjE��<%�����h5q�n�cs���[m&����:�a��;o��7��d"�N�SQ�l0R�������{��r=��N{�.i��+��tE�O�!z�o������]���k(��1���uy�>�E3�[�BV\W�d'��U��o&��1�_�EX ^79|/k�E�Y	����/�U��z���z���p���8<���B�D��	 �[��qYVo�S��%�-���o(S
��v��F����W�������~"�������`_���� ��i���g�*v�a$���N�vO9|�F��t"+��2�|�
����n�h��h��Vo�"=��O2@�Z|�y��q
o�2v+�h������J�o�s�-9��Qx�'4�p���lhC��mF�[���������L��5,����-r4x�/0���az�f3��vC�mm�E�%NQ��;�0��cu��<rij���p
�B<�9t���9�k�a�g�C����,�}��=������$����#f�	�@��������s���Nj�r��4����,��N��T�*�l[�L�=��*�m:d��w�I�[.D�������NghO���f�3��A��k�}���������� f�[��2/�cVeJ���-����[0���/Y�t��<�BF����9YBs���20~������8-�Q�JFz����^�#������>�g;Z�8=�++��#��S�FC��r��#|����l��</1�^�}>l�5��d�d&�����r�p����Jq��{���=u:��=8U�r�4�4�I�!��6����a������
����3��EF���c2W����C4�>'*�/�sXK�A�|'���X_��?\��`���}��N:�����lDu��vtr��Q�������.�����!j"(�5����3xB	!���T����	�{6`�I�ik 8'h&�P�M� ��9�go�9i���G,�{���>�r<���n�;��#pT���W���88���� P[P_�����a��R5�	�D���A��������*��[���FaW�*�d�4����1�s���ms�3kL�3{$����8B�
q4?��qCQ�z%8�I�4��#Q*��s#DA��U�T,Co��U4G>�k:,(�����b:������������h6���L�FDf�=<L4�v�9h�������?���3I8�������[�V�q2�����Ak��BConY���jym�V�������e~��{p0�U��������n�����J��X��]�_9��:
��A����`��i���`�s'��`8:������^gx�O�q�w�����[��@�Z_�P���F0_�#�#����S8k�����p�X���s�M��m�&�}�P���G�[��>������ ��������������n�����v����S(����I���no���'_�e�.��dr<��!o�m';t���u�z'Dp���:���tF.�`�jEag������������,l�W��������{����~��r)���.�v�>HA���+�^��_n|`G��������]K������%�	^:t����7�|�����?�m8�O��U	*��j��"�EU7�S�m(I�����d��^�C����!Z=��;���cdk"C�7��{�>��37g����t�Dav[����o�~��Y�m�F�x��[���]��Z(47�{vc��2*����u��f��5�����L�P�����q�n���xB�G���6�t�q���<�4�^j����kS^f�% �F'��z���(�aU������rS$�x�^{�5������y6KtZ 0��pS�O��[�?%s������>���XI��47�� %%���f����?�@Bg'jx���<�Qt\C�������������MV�E��������������_�l`�>����M�?c��Q�(����9�Glp:4��_�mXLBae�"
��������S���)�L�.��LJ�a��r�5q�k��=Y�)�l�J����������y��~^?���������y��~^?���������y��~^?��������x
#23Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Ashutosh Bapat (#22)
Re: TupleTableSlot abstraction

Man, how I dislike patches in tarballs.

0002 says:

+ * shouldFree is set 'true' since a tuple stored on a disk page should not be
+ * pfree'd.

Surely you mean 'false' :-)

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#24Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Ashutosh Bapat (#22)
Re: TupleTableSlot abstraction

On 28 August 2018 at 22:43, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

On Fri, Aug 24, 2018 at 6:46 AM, Andres Freund <andres@anarazel.de> wrote:

-/*
- * slot_getsysattr
- * This function fetches a system attribute of the slot's current tuple.
- * Unlike slot_getattr, if the slot does not contain system attributes,
- * this will return false (with a NULL attribute value) instead of
- * throwing an error.
- */
-bool
-slot_getsysattr(TupleTableSlot *slot, int attnum,
- Datum *value, bool *isnull)
-{
- HeapTuple tuple = slot->tts_tuple;
-
- Assert(attnum < 0); /* else caller error */
- if (tuple == NULL ||
- tuple == &(slot->tts_minhdr))
- {
- /* No physical tuple, or minimal tuple, so fail */
- *value = (Datum) 0;
- *isnull = true;
- return false;
- }
- *value = heap_getsysattr(tuple, attnum, slot->tts_tupleDescriptor, isnull);
- return true;
-}

I think I was wrong at saying that we should remove this. I think you
were right that it should become a callback...

We have replaced all slot_getsysattrs() with heap_getsysattr(). Do you
want to reinstantiate those as well? If so, slot_getsysattr() becomes
a wrapper around getsysattr() callback.

One option is that the getsysattr() callback function returns false if
system attributes are not supported for that slot type. Other option
is that in the not-supported case, the function errors out, meaning
that the caller should be aware that the slot type is the one that
supports system attributes.

I had prepared changes for the first option, but Ashutosh Bapat
offlist made me realize that it's worth considering the 2nd option(
i.e. erroring out).

The only use case where slot_getsysattr() is called right now is
execCurrentOf(), and it currently checks the bool return value of
slot_getsysattr() and prints a user-friendly message if false is
returned. Looking at the code (commit 8f5ac440430ab), it seems that we
want to continue to have a user-friendly message for some unhandled
cases like custom scans. So perhaps for now it's ok to go with the
first option where getsysattr callback returns false for slot types
that don't have system attributes.

+/*
+ * This is a function used by all getattr() callbacks which deal with a heap
+ * tuple or some tuple format which can be represented as a heap tuple e.g. a
+ * minimal tuple.
+ *
+ * heap_getattr considers any attnum beyond the attributes available in the
+ * tuple as NULL. This function however returns the values of missing
+ * attributes from the tuple descriptor in that case. Also this function does
+ * not support extracting system attributes.
+ *
+ * If the attribute needs to be fetched from the tuple, the function fills in
+ * tts_values and tts_isnull arrays upto the required attnum.
+ */
+Datum
+tts_heap_getattr_common(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+                                             int attnum, bool *isnull)
+{
+     HeapTupleHeader tup = tuple->t_data;
+     Assert(slot->tts_nvalid < attnum);
+
+     Assert(attnum > 0);
+
+     if (attnum > HeapTupleHeaderGetNatts(tup))
+             return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
+
+     /*
+      * check if target attribute is null: no point in groveling through tuple
+      */
+     if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
+     {
+             *isnull = true;
+             return (Datum) 0;
+     }

I still think this is an optimization with a negative benefit,
especially as it requires an extra callback. We should just rely on
slot_deform_tuple and then access that. That'll also just access the
null bitmap for the relevant column, and it'll make successive accesses
cheaper.

I don't understand why we have differing implementations for
slot_attisnull(), slot_getsomeattrs(), slot_getattr() in HEAD. If what
you are saying is true, we should have implemented all the first and
last as a call to slot_getsomeattrs() followed by returing values from
tts_values and tts_isnull. Since this is refactoring work, I am trying
not to change the existing functionality of those functions.

I agree that we should not change the way in which slot_getattr()
finds the attr; i.e. first call att_isnull(), and only then try to
deform the tuple. I mean there must be some good reason that is done
on HEAD. Maybe we can change this separately after investigation, but
not as part of the tuple abstraction patch.

----------

BTW, on HEAD, for dropped attribute slot_getattr() returns null datum,
which hasn't been done in the patch series. That needs to be done.

#25Andres Freund
andres@anarazel.de
In reply to: Amit Khandekar (#24)
Re: TupleTableSlot abstraction

Hi,

On 2018-08-31 10:05:05 +0530, Amit Khandekar wrote:

On 28 August 2018 at 22:43, Ashutosh Bapat

I think I was wrong at saying that we should remove this. I think you
were right that it should become a callback...

We have replaced all slot_getsysattrs() with heap_getsysattr(). Do you
want to reinstantiate those as well? If so, slot_getsysattr() becomes
a wrapper around getsysattr() callback.

Right.

One option is that the getsysattr() callback function returns false if
system attributes are not supported for that slot type. Other option
is that in the not-supported case, the function errors out, meaning
that the caller should be aware that the slot type is the one that
supports system attributes.

I had prepared changes for the first option, but Ashutosh Bapat
offlist made me realize that it's worth considering the 2nd option(
i.e. erroring out).

I think we should error out.

I still think this is an optimization with a negative benefit,
especially as it requires an extra callback. We should just rely on
slot_deform_tuple and then access that. That'll also just access the
null bitmap for the relevant column, and it'll make successive accesses
cheaper.

I don't understand why we have differing implementations for
slot_attisnull(), slot_getsomeattrs(), slot_getattr() in HEAD. If what
you are saying is true, we should have implemented all the first and
last as a call to slot_getsomeattrs() followed by returing values from
tts_values and tts_isnull. Since this is refactoring work, I am trying
not to change the existing functionality of those functions.

I agree that we should not change the way in which slot_getattr()
finds the attr; i.e. first call att_isnull(), and only then try to
deform the tuple. I mean there must be some good reason that is done
on HEAD. Maybe we can change this separately after investigation, but
not as part of the tuple abstraction patch.

There's really no good reason for the behaviour as it exists on HEAD. It
already can cause worse performance there. The price to pay for
continuing to have an optimization which isn't actually optimizing
anything is way too high if it requires us to have multiple functionally
unnecessary callbacks.

Greetings,

Andres Freund

#26Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Ashutosh Bapat (#22)
1 attachment(s)
Re: TupleTableSlot abstraction

On 28 August 2018 at 22:43, Ashutosh Bapat
<ashutosh.bapat@enterprisedb.com> wrote:

On Fri, Aug 24, 2018 at 6:46 AM, Andres Freund <andres@anarazel.de> wrote:

@@ -2883,7 +2885,7 @@ CopyFrom(CopyState cstate)
if (slot == NULL)       /* "do nothing" */
skip_tuple = true;
else                            /* trigger might have changed tuple */
-                             tuple = ExecMaterializeSlot(slot);
+                             tuple = ExecFetchSlotTuple(slot, true);
}

Could we do the Materialize vs Fetch vs Copy change separately?

Ok. I will do that.

Ashutosh offlist has shared with me
0006-Rethink-ExecMaterializeSlot-ExecFetchSlotTuple-in-th.patch which
contains the separated changes. The attached tar includes this
additional patch.

@@ -1590,7 +1590,8 @@ ExecHashTableInsert(HashJoinTable hashtable,
TupleTableSlot *slot,
uint32 hashvalue)
{
-     MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+     bool            shouldFree;
+     MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
int                     bucketno;
int                     batchno;
@@ -1664,6 +1665,9 @@ ExecHashTableInsert(HashJoinTable hashtable,
hashvalue,
&hashtable->innerBatchFile[batchno]);
}
+
+     if (shouldFree)
+             heap_free_minimal_tuple(tuple);
}

Hm, how about splitting these out?

Split into a separate patch? It doesn't make sense to add this patch
before 0006 since the slots in those patches can "own" a minimal
tuple. Let's add a patch after 0006 i.e. tuple table abstraction
patch. Will do.

Ashutosh offlist has shared with me
0009-Rethink-ExecFetchSlotMinimalTuple.patch which contains the above
separated changes. The attached tar includes this additional patch.

On 31 August 2018 at 20:50, Andres Freund <andres@anarazel.de> wrote:

On 31 August 2018 at 10:05, Amit Khandekar <amitdkhan.pg@gmail.com> wrote:

Hi,

On 2018-08-31 10:05:05 +0530, Amit Khandekar wrote:

On 28 August 2018 at 22:43, Ashutosh Bapat

I think I was wrong at saying that we should remove this. I think you
were right that it should become a callback...

We have replaced all slot_getsysattrs() with heap_getsysattr(). Do you
want to reinstantiate those as well? If so, slot_getsysattr() becomes
a wrapper around getsysattr() callback.

Right.

One option is that the getsysattr() callback function returns false if
system attributes are not supported for that slot type. Other option
is that in the not-supported case, the function errors out, meaning
that the caller should be aware that the slot type is the one that
supports system attributes.

I had prepared changes for the first option, but Ashutosh Bapat
offlist made me realize that it's worth considering the 2nd option(
i.e. erroring out).

I think we should error out.

I did these changes in the existing 0007-Restructure-TupleTableSlot...
patch. This patch now contains changes for the new getsysattr()
callback. I used the 2nd option : erroring out.

On 31 August 2018 at 10:05, Amit Khandekar <amitdkhan.pg@gmail.com> wrote:

The only use case where slot_getsysattr() is called right now is
execCurrentOf(), and it currently checks the bool return value of
slot_getsysattr() and prints a user-friendly message if false is
returned. Looking at the code (commit 8f5ac440430ab), it seems that we
want to continue to have a user-friendly message for some unhandled
cases like custom scans. So perhaps for now it's ok to go with the
first option where getsysattr callback returns false for slot types
that don't have system attributes.

I noticed that the issue for which commit 8f5ac440430ab was done was
that the tid was attempted to be fetched from a tuple that doesn't
support system attribute (virtual tuple), although the report
complained about a non-user-friendly message being given. So similarly
for custom scan, since it is not handled similarly, for now we can
continue to give an "unfriendly" message. The getsysattr() callbacks
will return something like "virtual tuple table slot does not have
system atttributes" if the slot does not support system attributes.

The attached v11 tar has the above set of changes.

Thanks
-Amit Khandekar

Attachments:

pg_abstract_tts_patches_v11.tar.gzapplication/x-gzip; name=pg_abstract_tts_patches_v11.tar.gzDownload
�
|�[�\�w����W��@�4r,���r7�8�������N{����P$$��H� �����}�>���v��-��"�?3�|bMUYv<�c5	��^H5�d�'_�NW�a�����������v{���7�j�����J��
��[�{�9��I��W������b�n�2�$[woo�[g��ww7�w-%��
��,
��0
�`��V0k����7�KVvp�����]�����1�}g8��?���(V���:��g���8�AR��`���OF����dG\����0���>��E���lN��Z$q��� ������_J?�Q�J:S����_[�<E�M���d���0;�f��3��~�]�K������������ �����E�d
�L�I���)P2E*�"���fzRv�~����]%|�IF���z�m�r���R��H,OD���/��>Y�gM=x�;u��Fb�����������04E�U2�K����w"`�&�	�i�Zu�"�dj����`]�GtR����0M����0�������K����I,G5ZG����f@2wca��/a�?O���Y��r:������LN��nz=l�!%����*��K���M��c�
���u!��jW�y��sOR�{��;/�EK,���l��A�K��Ez;n�!eGnE1�(�u�[�A�8
�9"u�*2Hi��N���uV`�E�����1V�PN
O\�Z
������rm�H�yE)���I�\�]Zs����|�sOZQ^��(��`��Q)�G7�!�����MX��-��?�O��kP(54]pKL�s��N��Z����z��������@7E���� �J"�k��`k���<�Tn��E`a�`O]O�(�o������>������go/������Z�����������w�[��#����5���J���������Ufrg[~��V�{
���A��)V^�Y	?���.�ch�����y���i�����aVk�5R��� O�AZ!��z������iw:e������E��ewm���M��������i�}g<�:=g�K����i�����g�v����6��C�I�(K�@���I�Z��*��d�����\G�-CPv�X@��<1%j�dc'�c������y����t�F*��$=�4�]h)@'@��N�
*�G�Rx8�04��+`I���Jh��!t}E��.����ZA�H�A�(�A�9`�{����6�X�4���s�X�����
Y�2�>v����x%%�*D�x%`v�������<�x���
�D�@��Ca}uA`�9��hnS2�",�R��1'I�^��W�����V�E���6�)B>��[��>�7�UV4���KHn�j�|Y���f���{hQD��$T<�b2sV������@7����r��+u��N�eF�D�'�4��V���KP���v�@#�dH�Y�	�K�ub�����(�`v���4����l� �IE�^:���rb�3J�q�h"|�h
���G^V�\���V*	iF�i�YQ�")�f�J4��9�FFu
Z�ku�C�y�9����hX��~�F~h��7pw{���/���� �p7�����9����2�t�CH���$��]�}B���Bo�4�A���*�9��\���i��%v`^������$*[4`�(�	��rOA�����*
a:@`0��4H�Ll<��	�O�9OVA���b3
8}�L'>�)����YG�iT�'4���R�
4�o{�#s��4�����6���P�JVCf7^5������
b2�M���F���m��m��Q��:������,���6�1����s��7`O�s�[���.FC�9
�Q]�N���\��8��>���`���w'�V%���)�lZ�q���=#����i!\�y9��JFh�<�<%����6W��x\+�=��4)��bH����}s���`���� �p^a��#�w�7��u��r���4�s~]������A�2���c�M
:@[g+����e��~��d>��A��	�S�_��]S�*�Hp2�M�)uVQ�
���~r�>S�R���
�ml83`s�r�@�!w��I���c��Xq�2|5�ln�,@���Lr�;�L�j�K@fk�|�]<��Ek��h:���a�r8p��a��L����a���f�i�rN@��(��&�K���:�q+=�FD�4E�'�C��)�#�<����c�vW|�9��1��9nH�l����Sz�L[��H�������e�`��gA&q�J��ey�C
��@}������#�gI��i� W�������v��v�g�����]|����[��B��Iy�;$Q�_a���E���0�Z����%�A��E�D2���wt�$�O4�%���	jp0�DRL;E�������q�J�.{��^��_
6�uq��Ig�KW@�n�<A6����9<a������b���j��3�|�5R�|Oa>����g0���A�1L����p�*���u� �;$Q]����N���� �T������Q�2�>L�q�c�*�Z�������
�����w�b���L(!c�c=�9���
5�Il~����9���@�~��X&#3��/��R������t}��.j�����������W�EQ=�y��r�X�I=ki��TZ�y�������������zXq�'���L[��tg������a�
r��	�d8F��o���$S#(*�!�/����$�=%@��`���]���)�!.g�s���j����J�l��:�<������3��W�<Z,���9������n��X�����R>�#tz(|���w?&r�A>�/Gx4��y���wL�n��;�Q�'{:�c:������	H�S��t���1��=����ZR�eU5�4/|�����
z3�!��D���v�M�}j��4�=:�hM���)Y�������/q��A�Lh��i~8���w�e���Q��w�2���}�W��X�-!����d����x�-&^�XF8A�i�FJi:���O����<��a�}c&)P}/����+���aS\���v������8l�a���U1�]��h��Z�TS�:�a'������I���t�B�u ����[��l�b���KSw�cU�FE�����]K��`���H��Yg
b����b�'�N��&�a�{�
�?++k[L9�����Og�1�
:c�}�����1D+9i�v�����.(8.�Ae��K����x��oS��"k���>
��D����`��M
|[��d��F2�Gul�
������x�v-� K��@����&�i�X��>����Eo����/p�%���4
��f�}�)�����`���Y�����~-d�b����3��i{�`Wd�2T�Fa�������tv+W����8�bp�@"�X4J����k�B��������n^_/�?,��-����c�B%a��0�L����d��
����K��22�A���?nh\�<�M~G�A$l+n�C �^��c"�����Vq����	�EJ�����O4��,qeb�P<��Fm�����[n�^+m�Z���
>%^�	�|�=�t(W���
q
��)�F���du���~c��Q��Ed��(���y@)d]��#OC��yF4im�`��W�X��xD++r0����x���Q��"��c����5m&[���#3��%�+��qq{{s�+���Ad��I3������_g��3��n�]�-�DSch���w=5��e�����F����� <�@\��� j��#V���c��	��]��L����^�8������*=�����J��
�;�
�;9����������t�$�=Z*r+���+M	?�+H���#^O�{&�{�K
K �MSo\��Pw��)���M(VjkY��o�+���*��~�[������}��v��n��~K�&�~�~D��x�����>�M�/[�����
����G�����'}k�e��j�a�^n[{��+���RH��;C��Y���U�m9)����0|����p�W/>��1�@#{B�w
��m���*w��C)�Q�m^�$�S�����5������JS���
��zsD�P�q�D���;��shI����l�Qju��q��L5�=R�sQ}�#�w=�e{�y�|��Q�pM-��n��q���h�~�,�P;S���c�@��p��*�s24�;�w
K����P�R4��0y:,�C��g�Z����4|Rx��c�y26����,�A��C���]��/h(����������@����v�,���8iz�8}�<=R�R�"�S��/+vh�B6�LMk<�um�X�Pv�*�"�=�����C.�����d�v���{�*��T<y�M*^�H�6��o���Q�G����u��K�wG�������E5����In=�h��j��@�)&N��5`�������p�|���Gf��)�V�&e@�����6	�w�� ��a�5���p�?'������DR��Mi��a���Q��-eL-Qk�Hgf���w��C��j��)g�����[�E�oC��	���M�a����"��M�qV�]I�st������v�BC�K���W��R|Y���!�N��)�
��K�?������\���0W����]��3�b�9R����a�6sj�����r�y�x��<�Qs�����|#qI������ ;+;��Q��61���1x2��gC�����gJ`'?��JA����GJ�i0
���0�/d����4�)!5+�"��B�E�w�,���>���ZK/\���?}.������[���#� ������J}I�~��A�� ���������C������� >��uB�V_h���o��V���\Z�N~�F%{D�����9}�K���V������|M���P��C��������/B�fJ�L#;���3�G�N��)1�����$K[�����*]y�EI���<��[��-�����0�ZsD^�$���B}h���d_��M��^�7���963��f�P��������F���K�4�($��b�Y��H3�����Ed�.��N����#��,!�Bi�37�}\������}	xB�T���|�]C�����NV��Ok)�\�qn3�&:�����*@[���9��9���>,+^]Lf@��L�L����1E���Pf��0��+>�l������/����+��N���T��26���}��d����uKW75+��P��/�f0���t�[��J#3�9�.[Yx�t��BP<���-i�$D��yF;~��*i"�G��W�����@3���G��{G�t���LH�B�V�D����9�c�5/X����O��j��*4s��=A,�CU
�X�����+������Ch�;u��>�F�I�x��3���dA�SGm�������6FM�P�L��0lp�,�c�0,U,k/��F�*�I��9��&�.o���Y�(�A�FJ��C����2sf����T@�\�z����T��P��k��F&�H�L�bD�W��r��7-W[^a@�g��B�Q�W�s�x��oa;��(0�6���-��+x�����(#���Qf�J���~5#�;�����]J���f.�Nc7�����.�������h�����W����3S�P-��6�+pAJ,&�p�I��g�
m�v:}��*�8��t���&��*��G^�U�m�eA��(���L���|R_[���V	���m�
�;��p���_��YO�6�������CT���������q\i����m�3(�E���%�f"�
I�����i�dGF�9��o�g����� �%k&�������Sgy�
��uD������}7�
s�CZ�s�k]�.c�J^��>��w���G����c:I�-�%>�3����VRpqre��l���Xf9z8��N��8�YB�����A����h�N*(xHtH�nF5�P�[p�q�����9��o��Bp"F<���C�)'��'y���-���<f\M@F�e��\�n��Z�_�]x]
����5U$���\���Ky��i�Xz))�PS���b���TJzIl?c��6P$ �%����O,�0�9�O<}1�_2�%8�<y��;����b.���6Z5^^�8o��^�#�H�6�2M���L�Y�S��<�[{��T��^]�b�TmeGD�f��1$"2\E����	3o5Q�I���1���#x5F�B���9������7������,p:��s�����A�H����H�0�n�}�*�f�9���x��
�#a���\�O5�4)y4���E�E��<�SA�T���O��	Z)���������#�������
����,��'-;9�����\G�	���x�^��y����m+�w����;m�J����S��X�yl	,���`��4O�'�j��,;��J�fth��]���7�����|)�)���hPk�p�F�v��Te��j���h� L�t�|%�hJDv7rp-�N[��w�)��i!�
��:��Xw��e��-0T���2��Q�2�e]=F}�>�v�s��%�	�E��"po����&X�������l���g�LR�L���T�]#}�(Q���e���,r���tM��rA��0�}&��I�=�h��F�FB��m�J�(�Q|p��k����{|;���<D�Y&z�G��~�"������~9������
����?��*n��[�D����W��y������?{�M�j\p;���r��6�����J2�2�a���y
b��;%��o�Xv~v�G�ly�b��.I��{�_KJv��:o�Q�0m�UV�W��������B�J�W8��>�_����Qv�%��g-��+�?�\�M+��0�\QCx,X���L�/CtRm����d�GQ�r�3Y�V���*�5����vl0�MoENQ��G/�����j�A���I6��������3�H6���G�P��S��%���������_��c����u+:���v�@F����E�D��;.D�B�
3r���)�+��`8��GN@U(/��T�D�?E����
�t��Z�|`K]=�rG���D���z5&L�K������5�u\�B_���d�Q���;�{��+�v�:0�nB%1�WEI
J!?,r���U�oMG~�������*GW��v�X�<#�5��?	�6.E�
��L�PG#�}�W���KOi�����Y)�auN�Z�!%3}{������x
oI����uAh�|������'���y���M?�o��H������D�yE�$� ��
���q������$Ujl�zPe�
�����
�k�����M����t9��!�6~�]�S��������	��!�Q�a����~��_q4�Z��d��/]<�T�m��
��QN1���R�������n��)AX+�<�����l&�?dM��1g���G�L/��v�f����o�~'�IA!k�9�t:w�r[-o�Y��J��*L��`DN�M��Xh�7n�������X��ybA��HS����0��eo��pr�V1!���(�N�BG�90P�S{hA����zG�N�m�.��2��2��U��B�%�O����F2����cB
=�����RO~��<���C�y�������v��������a6�c�%�s�����F��!�E��\�9�RH�_-]��y)�Y"D`�D����:�p����=IW�[�_~;� j�I�����5x��p&�S��?I���U��,�j5���d�hL�6�(_�
��(��D�OEO1-e��Q0��
���%z�O�m�q���/z}��sP��F��#DeMl�'"�����Y{���E���,�R����l�6�v�`b�:�f1c�+bu=A
�nKv����}�![�QPzfBT����\���������_�1��FT�����|��ak.������U�"�}� �H�H�x��B`B,���g�5�5��������bt�]���a��E���&?�=)����y����	���7!��,wp���
���
�z�����Y���e��vS;�/�0���dM��a�J��/�[s��=�x�g�����7w�f2�����"�C:JUO���
U��&��49�D�2��Af��f)a�B'���l�:\���t�xIUcu��/6����H������b�j�����(�_�����}-~
�#�S�x�I�%�3���.�Y(@��f�Uo��wN��J4���xOE�q���=�P�����<�8}�i?���et��?a���[�J0W���rJ
��o��5��pR&b8���}l�%�G��%�?')���
���k�U5�hl������O�}��Wf7��5&���e:��	FoB�����E�d���s�be���M����
��s-I�:�a9�B*�w0��<�Qp7������fv��.HGP������lU*DR�d��R�u2�Q�&t
<v�/����1��=$}{��w���1�a]����d�l�B�=�	�������JjMv�`	/X����W����bO��g�n'�U��-�m�R�*��u�Z�f�����C:v��=K~�K����S�����
�Lj����1CX��6��c<�8��
Pe���]�7k4:�No�*n6���p1O�b_,I��	W)s9U�C%b��8�����������g_���-��Y����$+M�a���(x���xi�(���7U���p��e�a��W�D�l�.���.��?.�p��+�_�R�t�����?��`�BX�3i�2D�4��^��dqv(�#}��2�����<#��3����f��S�������d�����BJ/�k*2����r�}������S:��xc3Zw�E�= jZ����%Qh���{,�
�
��$iA��I<��Fbq�tC�
q�m*�k�q�������'��i��V�m������%��o)�����M��N��BK�����\`�c]wL�K3�<�b���*!&>�����CD�.>��kI�.�M@��*)1'�u)��\�)L�>)]T��7{]w��n����
����$TX�Qk��zBE�j5�_����-+�.6��M�z�v�~g���	q.���fe��D	���t�f�t����|�YT�
�z�0��XB�W:���2�kws	x���Tn�iD�U���d���
�V�J�
n(������m��=s��3L��]N��+�������� ����7�3I�[f1�P�7��$��*��b��X���k��*��,���9�8��J	R�`���P��N��s��L�N�����n8f���|/y����������|�e�K'�N�����@S��gPb���&����[3�c�F�z���F�W��MR��l��LF������iAf��f�vm� G����R�����.j�VcL��*A8P����n�I�6�"u:��L,�����'Ou�>�<he����M�c�K7M(�D]k $�\��*R��D����?��&~��#\�G��*p�o=?���;d�Z�����6?�]��h�`w�;w��6�RT��r�
H�m�@�>����G�J�K��9�0?��t�����aR������&Y�TFU�:��E��N�>e4P�.�7��!�|Q��v�����J��'���'��x����Y w�[8���iz���*�����T����������$"�n�W'�Z����V�Y������x��6]���~���?l��R��w@;�n�K��~�>�m�OZ�A�?Z�N��t�-x���Z��4�	I�];��r^�����������!;����G������Ag��u;���m�^����Y�?�
������WNk�4�����v���`3����������Zp~������7j	��u������
*�sl���:���
Zk
�V�y{����f���\l'��������_;���V�o���Xf91eV*d��]Q��Y��s^
��Ft���Ln7(�^�UE��f0�e0�n4���{�>�Nax�G�ohbF-uMn����C��.
nk���
Z\�T{�p�F<*g+PQ�"��9H���BO���S����6��=K���s��T���9+��^]A�Q�8�u�������]B
�g7�$�J�����e���J�tZ��s�;<~7�4���F ���g���`�l>���������L�s`���;�c�N��o��J���_��C �y�����g���*r���wf������ZG���<*G��wF�=�/��J�M6�&��i��I����Q���������W����/B*�!+Dm�D��m0�o+���x���p�xX�9��&B�P�d��g�:^���C�����E��l���b�
�
�3��� <�+�)�����u;p�����uv7.@�r���7��Fb��w �PB0$�=�����������?�^����3��x�`�4h��b�!cp���yN�d8A#���D�	���	�Z�=�3*�;^V`�Q1kOH�sY����{��6�0���+u�b �{/�����5TPq"a��G^4�
-�|��b�E�^1��Y��J���U#�G�%��]��[<�`2	|�p�fH��q3
�(-b�f���_���4wdO\S_����9u��!!A�����%D��z���K����p�p�?���#%�c��gN�Bd^���/vprK<7H��x�q������c<��AZ��GGD����l�5.�7x�Zp������/-�t&Z�"�	L�5�#O��Hi�%3q�N8F)b�.	�v�O����H�pA�!F��'*�6A�2���(��:QY�;�m�J���d�;����sw���6{��&&hT��d�n�B�
8�%S�S�V����@L���K��Z>��H?�����rR�-��j�k�^������+��CqWqV���O7?��T��u��_V���9%Y[�B������g<e��F{H�)�q��|�l��^�B��r�Rxbx�l6�:"^9�'�t_g��o���-��d����t��p�B���U�Z����z�D��6b����k:vP�b�X~�������*�!yo����N�R�DJ�!�1B�����RF���-h(�d�|3!Y�-��e9�nHme�7t��������z���/�v��pi�?��
�/��6�����F��[��P��_���VL������Ru^�M� ���3��2q����zr~~v^s��
�����z���9X�%�W�����+��������!;`AvI��:1U�wC-{��c��6�r��v�
y�'6PZ�6��f������H�n�4Br��Q)�1{�9����(gw^*����
H�E�DFW���=�S�T�h^��������	���"j!
e��k}0��v#��������>��P[���#�B����O=����$YD�	Rd�QnW��1g=�}��W~�PI���W���U a?#������\����"��?��
���e��uw��rJ4��X!zn8�O����\83��f
uu����e�_*�4�r/�����_����z�X�������oyc��*�����P�9�j�u(�j~��p�&l�xU��#p��B$1����
_�721&��I��~�KBF�0P�aw�=������F
����t���X��#��5�8��
>�d�}�"���-�q��"B
�dv�?.8c�S71�Uz���U�����3+�'���
�����L�~#�"�%Zr��@>���>mUS�W�N��,�p��x���1���}|��b���GJ�E]�L�;
>i42eo$!�������B��g�'n��������\��l-�y���ml�6[����S���b}
����8���593�}�	L��4��.l�^�oU�����x�xb�JHv�?��h����0u��.1k�+�y�rH��9��_���0����:>7ct�{*�P����4��@�BU����*�ki�XI(eTIJ|�:"h����������p�Z*�$��DrW��a����R�M��%C�w�n���#�}�\�=MU5Kgq�"���;&�-y:u�������������I�G�O�eT��6���qg��2���U��;��$�Sl;�������P	?�4=��J��gJ7���Q����x��� �+$�W�VWc�"�S�h0�a���Zk�S8}��
�|�N$�H!X��Kh�0F�>+���nE�f�L��]�BL�B��C�������$[���"�W&�\�<�\X��^��3�������i���U�i���z������Q*#]�}������>st��}8���>���;�g�^�k����>s���g��y���N��Q�}�(m�9:�>��>s������u
=��Lk�3����?��v��!��G����];�S��O;to���]���{��^�y��%��G�k�����f�����f�RK;/���v��a���W�����)���}���k���O;��i��,MYU�QI�|�����g�&K;�����t^�>�������P�����/�y�q�|�5������?zH����Ij��2dj�����=�v�\�����vo��}��Ch��L;tO��9�w���g&���7rj�����W�(��;Q���X;�%{���?��v>����v>K��o����t�e���[wZ;k���|�|J��S;�<�Jj��S�@����}��j(�j��
��G;XI(e����#��������,ij��������h��c�I.�SW����cv.�Q��\U|~���\9Q�F�Y�j4��`���%�[J����R|������(Eq*%���}���Fb����!cj�=�M^���O*��j�P��w\J}G������}��s���:V�����N{Lz�jL;j������u�=�5p���qD�$5U���$B�:���O�|���>&\������<��H�7/������T����
X�#U���e����o����V<�9��fU�^�:v��@��FN����P1�=�z���L�_pXy�gC�X�P�����h�*��.\J',����N������~�Q^;%6�����������E4�a�*�J(F#i�B�Ps}`�"�����:1qN���������7_��+���m�
���5H5�@�b��)��:��r�8v��[��=8G ���cL-�.d�Mv�Q�����4���kw�y��[IC/d��(�N��������w;����0F1dL��M"��7���F1��&����J���f!�v*7l�,
� �_�F)
f����qhE�Vc��2d��Z��:%��f0�����o>���\����	�����T��f�v>��{�	�?��t�\9�S�LPK����
��b��
�bq�0�����C�4Fq88�SW��S�ipo�?�_��B�0������7����`%�|wr���r����w�o����2d^z���%F�>c��4���:�.�w������&�]����4n�_��S+]��(��rzA*�VK�20*}
>B����8Y�#�7`���Y3�,y?���|LH��2,s�h�e�>9���f���*i��_������M���)��{�/^p���s���-�O��~�>K�byP���a���$?�D<�Un����$�2��G;���bg4\����s�!�<���/��9���:
�����u��_1�T.����f��$�_���o�/?�?�i7'��h0�z��t0��\o6l�;��
���`���'�����K�/L����X_����a�����0���tC�f�T����-qL�y��%��m���:�l|����Q����(�R����A��Z%����:A�iwX���<������r#K�.\.���\m9�G�5���w?�}��sB)O@�3���
�"����<u+������s�@�///���x2����#	kh��iN�)gs��F���7�P������_"�?�\W��
��T���6B
1-l��bLfHc���`������������:8
=_ VR@887���t��m�i�C���.�r_wh��n4���?y?�;4��~�=D�����������C;L=I�N������M��>��V�@��r���p����N�BrsDp��x�!%%:o�fL[���f������i��(�?�[��-�M$*')�URm�RDN��ce��
/�m���p���I�5���\����(.=4���u�N,w��;��5q+V^O+�>���� 
8E]��3����/�[�I(,O*b��6�kBsE�b�R��2��_;�N������%.��vN��Bd�W-����z�o"�0gs�*��h��^=��Ge���G�B�)��������7�����Y���7���a�y�i�3���M�mG����k�����j�Z���� 0��LG(�Y�2�V)�Y�|t%�+���.�'Y���8�uZ}gl��4*���q��C�B�I4������ft�+��%�Au������#b�A�`fNT�yh�vQ~X�$��`a����hs�+��Y�{i�'7�����j����)�������M�X~�,
��5�)x?kF���g�h7���3���&��Z�a�o��������h�f]�S�}����Z�f���6��=zO4$����[��#/�3��/\��'d��3��	����/������nH����Qo�Xx�N�U����C��#� yM����-3|r:�;
��Q�^b>������`o���M~.'�����������Z���.=r�i4�S��]&���/=�!%[�O�d��pB�2�1��������%A���L`�X�����+Ff0N�|�cJ���=�����^���/�/���_�}����������O?���M�N7bP���?��)"#��I���N�;�Of����_2��tR�h/��]����5��,c�]P��������G���~�'|g#U��1�zFp��RB#L��R��	���*`��8r�m��m�>va�����������%c�,c���%P�xp���S��v�8c���'k�<	*�z:�iqx)uO2������
w�����?��d�V�\
x�2W�_�Ob#�!K"*s�N4`�"(H��Q���Z����sJp����������w�onk��^���#q'|�>���i�����Z���=�"��o"�WO,���KzO|��7��X+�hYZ�,�h�\Z�6z@ajr�9r���������c��:����1�&�j�$��i0C�dOG�AWx������<���%q�����;�������c�>M�s/�qE��m2�v�)R����7��u�>�Y.���4�o����`�#�w'����	��u0�i��<��&6����xG����w��ckI��u.��D�t�-J�}�k�%MwB��Bc����@�����Q������?��>*P\ ���y��B��L�.��XF���2e��w�<��}EM(JPAd�!��^g�{����h���\�T�i�&�T85y&,S
�7B.��3��r�r,]���~Kn
4R�Wxa��}�����e��]DH������\^�9M�}����Y�sf�~kh�����A�@-�NM�A��I���eL�93�ir����|��?���d;��D^)4�.�����A[g�����cu���#��I�/��Xp����=��������������hK>L��W��G�W�II��,�%�-�O���^����tH�R�����8U�?$�q��n;�sEGl���r���O��<l
j��s4l��Sf��C��{{���K��D.�[�<a����]�����B^������QR\F�"�1�������P����3�I���<�fQn	�-��;+>8��]f��9���il=D �0Jr���&����|)UL<A<pC���a����a���N���"�/r6vR��w(�,8����n{���t��
��a���&��0#:���sa\��<M�b'���j�pF�x���%�"\�:��^]�x���^����7���_]�������p�@��W	�����\A=��Zlr(x��H
?e�	�b���>�H@G��|�\m�����n nT��gM�����v�k�\`��mf)m�R�������_5
�J/6q*vLmxr�����_�[��l������������0���JA�<�S��@���V�F��
����D����=80�n��%J�7���K���r�W���*	��%x�'��
��&�����O�oz�<C����~��YY��G�h��f��
�A&'w�UF[����$����F$f����k������q"8������P�����G`N��z���@G�d���z�H[Gj�����w�_]hP�8wm�c�5��H;�����Ya�M�����C��}�(U��V@W~��"��)��"G�d���������<��u�6�$�C�������U/N���|G^u�=�~R|�Ei4��f�dx|���n��>
	�H�pUS�����j����=C%��������,o��fc,�!��^���*�����P���+��z	�������7�'���'����8{r��
u�i
#���i�.���f7��������@ �3t<G\B]���I��o4F��?�dH�Em�����$'���#_���u�t9��x����R}�%���v���
�r�4��lbHK�
��
���������k���N5X����3����8��>Kfr#�O�	#P0��?��AFp��`��{,T�fj����������z����|�e�z���( ��^/F-I�n��S��q���Qf�ntG~D+���\�sZ]�B2��'I�N`���Q�;e�!^�o��5w���^�B����.]n*����
�
iNV�S����Iw�i�pjxT��SCSFd����Pf���k��R_Rnt���:�,-�&�BuD����s��sjL�/;��`�9IJ�)�9��`b�m��	T<�eDz4�\��P{����=�H��@�&M���`��I�
�5��4D���r,�������W�#5�Ky�:k�0������Mp��2�
���������G'� Z���Y7��}�`.�Z��|�yz`�8V��w�\�W��vI��n�c�~�O:h)��#KQA*��;J�`o�)�.�� �7@�L�l�1��=����SK=�L��F��Vc�i��a���)��C�KjB��C�`�z��q\c�
xC%�wc����eG��aA��������{��`���A����<�
���_��Pm;�������~8}����x����B�"
�m(�WAs��-�v�S�y�@#�`�}l����f�(>jT��3�������7�]��H���~K!�	���a�o�7�����9q�\�������JNb���n����F��L\��D���������x�]?����U[��~��u	'��<����4�����Q;Cs2���eN�LY.���/���n�&@���@�\�}��\@�B;=)�����Kf�F�fdJ2����*�����Q{�x�`��u��(vA,1KP�p�
K���Z�[Z��y�v������wW7c�tP`�\��(c�
�����fE#�W����<3�%1f���A���6�X�GM�2�����;Y;3~�h����.�LT�~f|�^`YT;b�:CU�u��AS6�.�N1���>X���wx}�$i]�����e���70^R/^�"���������=So�0�Od�c����nF�mZ�F�>'0Je�UZ��c|sr���������/�5�F:��aq'
��ro��l���_�u�ip�]�"���t/(�]=��\wuIJ*��|����uWw���C{V��!%�z#�e��1���&� j����������z��BF06�����2���8_H�T
$����p8�����b-������1�nf0�,%5���yS�nL4����)Hk'��3��������rq�Z����r�GHu��K�:3v�)e�r�uNJ��"��{�9�}Q�������R%g��5��i�Gd����P ��H��\�Bp�Urj�S�~����z��F=�q\���uj�Sw����O�f����3�#��^�=�y���m7�v�5{�I{0�u��Ao�������D�O����>ov���>��/��D���D��,w�CT�f��C�&��X����lT��u�R�R�~"��4p0���D,N=A�X��+U9��)3��T2~���>��JV���@%��0�Jq��sC�F�c���&������H�vl4QZ��e����Z>*C�G\Qp��AQ�2f"�s��7�����vWp�Z��U��%e��\�pR�������I�
�����1R���dX�+"4R*� ��kixF4'a�j�F����
��@F����J����`6B�j���j�����s��P	
2��Zm\B~�r�����n�>aPJ%XE1���4,r�� ~����w�����^���Sj�m(�Z�ii�A��
vL��0��������Zlv�>�������6}g��T��)���'ag�G���X��Q���D��q��9��� 7k����zc�5��-@��%W)������8�*:
6��!���	��U0
M����G��J&��r�5���X
�L�#�*����	S
�_F��_o����V�,�z���C�����_�1��Z����j��dEQ��gw~���[2kWr�v�fd}BD�h��8�Uk�,�M�Y1$a�KF������'�)zs1�trl�}�.�zlF��P/Me����:R�U"��Q"Y1a$����d �.>�"y����jp���Yg=��Gr>B��H�GFC�D"'zR0:+�J���8xa��j���1�7�
���y��upp���9�f
��0{P;�V�n�+�MT�e������0Yh�.sU���8�D<���7�
�0L�s�����HNk:�����7�1Xh���]���`E9\��d��po��cN�X�){����p������q+�B���e"���Z���ioT��h�D�L����������	�?�Y�[5�=W���@t(�[

�I������������a^�e���bJ�h*c���v��c���vN�l�6T����i������
#��ML���(�gVj� L��w�K��v#{��hB�U��uGw��;HY=�����0�������@�\�:�g���E�����4�(�*�]�n
T
9ZP��17�ke����0���c��R�r�������U��BzM?����a������]�>��M�<�*�������i�k�Ld!�mq
��y�Gp�Y��@[�X���^S�W
3V��j'�a�)\�n��O��R^|�i�?�6�^k����_�v���LIr��Z����C��������1Ll�������8��^q��:�*����:/�&�G=��I��*��Q�lkI-I�
���\]�y��9?�FL�����:���J��������TJ��(����,sSu�FT�u8���a6Z+����.k��j&�y\�F���n�Z�M�0�����1����H��I�S�m������Fc8�v���d��������)���#�B�J��D�S�]E����aV�!-��4>c�)X�`^���c�d~�o�+����?(�w�,�X��Z��B�(b��C	~��8��7*5)��G����fI�>���}�pVTY��|���a��C�;����:�o/O������K^��@�24yT�K�w�a����d2�v
���(���!�)L�?�A�=�A��"}��9�X�o�|&�� ''��xC13��%�P��"P�f��j��$��(��RD`��0�$�y�],������
�n�'�����o��t���m����������'�i���z���Yb��&
=.DXvC���Z���2��;�7��q,�U�����9�,��"�uk}�1�=���Q��ex��"������]KD���PW��R�!j�d�0�g&;~+���M �1s'\V"'Ra�^��$��tun��Co6m4m��z%�:n����BtP!�T�)AF_��vU��z"R�/~��*x���`��C%��y8d_+i���O�/�%M�_��1�a���!ra#��9�J����R�tv�p��_���W�]85�
�uo4�9�w����C��h�c�k�3����C�����R�����+����h&-�:x �8��5�������23��&VgQ��v��P�
����S��������H+�*�I���sRs��G�O��:�i&�z����;�@�Vk�
���,c�@"F�7��jJ�?�rT���:��Z�}Fy�{�������2�<?��+��~���������r�!�	�s�!ek��x���|W�L�j�_����j�����dI0nM��#c>�4T3�S�C&��QhF���uF�M�|����jA�������Q����~eBB+�j]�V�A��)�U�z��re��>��6u=Lk���?u�������^�$���"��"��WiX9c7����Lm+��93sATE���\�J���Y�H���^�F���[��G9.<5�@3���SR��6���H3�\����j
�?4�{����
��XIC #-Q}��Eo�vj�@�3����'�Y:���S+f�|>T���Mt
w����Dc"��&v����������DwN��x���7��'���KO[����HU)����^�f��'�A�3�7Y���J3��������hZ2����#����LI��Jj��6�F���E�9AO�jJD0��,�����z��y�`�	����;���y������~��8��D1P����:���p)p��{<]����l��?5T22��M�s����M%��@���{���aM�A�Lp�3��
�/��f������u��=u.����zl�i��,=�2�{��]�r*�M�-F��O����p��{�b��w���l���������5��95W�PO�>D���d|w:����^�^O�)=����8w������OO!s���]��r�^��B?�:J>���P4��R0����� ��`+�;��E������"��F�<�G{>+�1v�$���������B�	fSP�nk�wP���#�@�����S�,���s���K�[��.W��]�MQ���t��L��D]�pEV�)c�b	�<�B0V��ZYe7���v{�3O
��������w�g�.��_�l'��U�

-�{w��������2����vP�]�n��+��k���@d_�V���B���^���`�0��"�a����{��M�,���!7�r���j���k*c��*�c[L1����OwW�^��`r��i�AK���!l��]����+�{�w]�-MCb
JN>�����0���h7�v��O��XR7����M� �[��������}�i�&����tg|GMj������Q��5�NM���j�)o�i`H(����&
W����.��D���
V��� =$O]E�s,/i������*w`�R`�~-G�0��Bc�=*�n{<��[�6�m'�F��m�z��o����n&�g������6U���
��-�tBp��,vy�LiA5K���e����6��GQE�(K|�*#��?���7�V��u�.�=��[C�f�#F�D��s���z~W�|�Py]b
�E[�O�����z�����Uw��yM��>�J���p\��u���
&A��;{&&�6���M������A$����� ���I�?\\��q����|=9������4h���������+��{�Gd�-��%\1�R���%����o�����\M��K�����wJ��P�=�o�@�h����.��!�"����������#�@G��/9�X=}4��n���K��0Hf��o�����o�Z-Nu&�8�������EcK�El%�����I�����*��p[��-���.j�#�����j�R>3��Gy��^M��z;�����1?���A�4(�|������S��E
���*�������>V��ctIB��]�?���}U�m����y���r>Y��h[��g�_f
�Up�:�9%B�M����R�y�o4����~*���h��!�I��������v4���
�RU-����K�A3�_Fw�x��������R5n��,{����T�=���������M�G��_��P��u��f}WT'���������n�m����w���������9����m��i�;�xM�6;��7�O��,�����2���Z���5�|�I������\��K��R��5x�>o������	3��^���=��[����\��@@.�	���z�"�7����A�D+��)C}��*j8'�������`E�T�����Q�K]�V����Y���Y ��0��O�J�?.!\m����
��D�KA�b�g�+Z�<U����+Q��25R#_2h���,��Z�bc���� VS������C?���o��'b9�R���������0z���L%~���V�h��$*���Q�`��"j�uL��4A��)FOE�p����(�<=NIT�& ��V�'K7t�
�,?��`�{���`oL�"Bcz��u�A-��D�*L�����K�n"r�0���Q���1��X�o��K��GUq�u$]����o���������w(''AP�>AJ������Q�,/P���{"������`4s�+�
�b�/�=u9��������K?
p>5�����1j ��py�]�����W�[Y�]$\����qk�4� O������o7(g#�	ZR���.�>���u0�E0������4h�$��s�bD5���h�>����������S��p�p�����YH���FB�������vN�n1�@��E�wb�����$\)~�@c�M���'H�rX���X��V&u��Q�']c��@@QH���pV>���vZ���d�w%��o����@����K��3gG39o*��}$��.c���N�_���'�������R��/*1u"����PC���.d�N0E����`Kh�(v9�|����o�t`��=�XTHA������	@U����������c�b���@�Z�����Y�I�������
�<M�:��w#<
��+T
T^S3���P})���J�����i�Z��k����d6��1�����L����8�1''�&������"��Y3+��^�sBy"s����r������������:
+8�&�)j]�k�7��l���S�Y������5:�8�n@��p�H7�����=���S�cR������������ZQBx�-���1=��]F�%l?R1�zb���F��h������,K���
��� q������%��=���D�
3HS����e�v�T�1D��V������F**���T����q��L�2��3���*?�V�U0E* ^�������(D"�'��)��1>���
���g��&��R�0i.�#��k�oy^�
���'�	*E�Q���A"�r#�y�U��[�v#TF	r�0�9R�����wUR��3����
�,=�/�`�_��\��r�=���/�;�V���G>�������P����� �0K��J��?%���sCV�����?[���+`p�w������Kg�.?�8����������/������_���i�����Z��r�,k�O��������w�����5�L�/�:��n����v|��[�N���p
��R6�m;
4>�77>p��a�k�D�� '`Q9\@>C|4i�F��/�C�L}j9�}}r~�
8�sZ���+�m7uyI���&g\^d��u��������*����.�;�Y�G���P���G0��L�4��x�[)"�L��A��s8y��:�
��xQ8��UEp��������#��:��?�@J���G�D<v6��+/��W9^���(��m���/����l�tu�45x�}R"������	9�����k0=��8����L������[��9g^������y�9a���}nZ�Zh"w���}p���tL3��Z��)d6���3��\����Y*0�^���]��`*'�Y�+@�/���]��������+Z�9}���9h���������I��Ra"����pleTI4���E�0Q$T���
c�l�$6C�z��1�����t ��������D�id
�-;�<w�A5G�* !�+)4�%6�K��c�mm��X=��t�r��h��2�`�Us�4v0��fm��u�4�1�|��wm��&W���?RL��B��������e����!j��2d�7R��:�P$i*�r��E�1�AD�B\�H_PA�`!c�>'|�-���br�,m�mn����n���_t����,>���]UOg����.e�A,�@���exS����B�}��.���+J�F�\S�9|>BMX~�[�X���c���'I] ����1n����B\�[f0�����?I4��ni�3j�]�~�wLV����Z�I����KyD7��%6:^��a����������������������"I�����c��am�0
,m?j;Z~Y�_T�pN�����;"���V������	($Q	V�����8=�6�0��J�a����R��^��������4fY`����hT��t����lR={��2lN��U�I�7�^j\�a���Vf�v���&������r&`u����6����	YW�$J���w���S".:i���N
����R�Q�9�C�@o+����).�S��Q���'n���C*:s#���p�e������b�Z������YNy90���N�����:�]��M�3q�;|n������y��w~V�Xf�&6��VYYU]��S�'�����I�7�Ij ��	��y��5�U�(��9���T#q2s�[�`��:.����~2Lp��S.��8��'����i����g����sf�D����xBb���:�|r�P���V�U�����@*	�8��>���5�
�I=w���r���4�cB��$E
��c�����'�p����j��?}r��T����E��

D�_���(]���N�j�Sz
�]�/��FN��d�p"%e�����uN���U�s��a,D���t�C6�5
D�u��-_
��G8���#����
"������j9Uw�L)�B��9���!:U]�w����f�CkQ�s�X�6��c�eXk&��M�.>�R�v���)M�B�L��vEs�X�P������p��K���h>����`��`6%���B�5���8`*8@�\n�OE��q����������9[o��q����������,��	R��������'_;��/O�O����?'o�oOO�s���x���e��%[��g����\�}[jIZ�'��	�F��aBwT�����z����TK:�K��_�*��Nd�Z5M�V\1���{��/�������O��v1)��F2��7�_�aj����u�9���\�M0)4r���'��O�?rvg�yG?�������w56[��	j��B�n���`��w��G�L��y���i	�	�Z�J�@Q;��s:�"g��H"uR$��)����>���>�9L���n�b�t��@��^�Ko5�|�>)]tR���|Q�|Q�	���Iq�_�}����������F��y���I�����aL�b�-{��^HC[%Gm G��'WOD��o�'���J*�E����V,g4f:LE����@�Q�[x�Ql���4wo�C�3 �O���It�D#��U[�N�k��]58��
�Y���p���3��X��Rf�V���<������y���
A���:���"�F{G&��V�Sr��~9����{�n�����[;��9�#�O�3h%�����Ej����`�Y����0��(�r�b�R5�l���������nrZ��	H�UzuS50�I�E���
�B��W�d�����5�Yl��'�O�����p
�a�U�$z�P�"����J�d��\�N��(�35x\
]�xQ/5�����/��"���n&S>�z�^2���9,��T��L��S�E�Y�E+�5��aF$�������e)���i��C���;N�������������������?����n(��sP�?��<��9�8VO07��|��Dp��~F~���QV��u�]H`�SI�LI(���V����q�r����l���K<��������r���"�Ng��Y�z2J
Ly�uf���A�I�K�����J�b�Y'�����:
�,G�s��������7��3_�Kz,���Q��8�"��W�*r��5G�4�Td��D��}q��T&X��g�}�vo���J7�hT��4	�zEzLnd���ds��{U%�1�43���c�_�sU�z�����{e��;�p&�;O/v���3l�P���N"�X�l\z�BTB�U�i���0'�k4�@���S15�-4�i;O��l����F��?,lw�m��v^$��d���y���OEX6��OX�	��1K�O/di�=d��9��������T���	��lw�\Z�
Y�'���]i'�/��"a��`(NJ�M:�g����L�����{#}�wl�
��O�J����E��3<z�Iz�;��}�������W��>��38��p>�x9���$��$FH�4P���4
�0��vM��k�V�-�S9d;ToDY�Z�����iu$B��+�hW�yt��-x_��x�p�v�;�<���	(|��>�����wSS'ihu�Kw��{��������h�B����dJ���r�`|�5$x"����J�wC8'���X0�am0�����u|�H�!�Oo��:�h�3�b;�xD����R\[��h���O�j�&���Y�a�K���dw���]*����}���k�.�l��3��,A��%��:�{�4'����w��J���#���B�,����*Ypk�#`9h�Pgz�c��,]�#��^���C���7�t@|����*�$�^����h~D��k�����k�~�:��W{9K����F����_�Z�i��&��"��m���p�$��
��eu�U<��+��q�8����XqC��P��Am(�3%�:X������=��������@��ZN�m.�QM�\0pM���*��h���*��N}�&�d��@TDS&��]�K]Z�^e{t��n0<�TW_��qS�,��E���@�������,�)FS���+��e���T%1Qb�3�
=�jd����i�2������r
E"L^�J�g(&�tj��q��|��`X������fr�C���6��������AB�<H4����&q�X����7.��p��v2�*A��gR��w�z�5(���������0�K�S������k]��?��$�1��b�<]	R����������d|��/��!e=<����Jz�/qz�(�2�{1iQ������,C�qG*�
.y���
3�l�47�(!|��R�8~��������
��~V+@��h�<t7��o����hb�������2Y�.C'������ux�c��$����iyX	A�������s`��4���vOA�B��c��\��R�K����"��1��H�z���l��0(�t�i�u�bM��]��(����=�nI�����z�Y�v�+�A�R��f�3��aS|��/d(��J���S�)^����26��:�n����4GIh�
x�����{+'_g�<����o�"�?���?�Q�}�@*=���>�C�G����`����W#��f^�i�8�)n����G?Z�9��"`�-{{�>$�Y�/��Q��W��HE���.\�a�LKh�7��������Hl��(-�r��b��I{����BBM�-�k4���`0t��&�g$�M��5mIQ���/N������?I9�����>I����������������.`G�o������mopBZ�?��!>d*`�w����b������������G�|����'���C�R}�L���ly�f��)�,��g���~��hXEkZ�'i�a?|�8i�'�����%�>b�F�@.n�o��.$=4�^w�h����?)����� �� '-i�����>���2g����z��)(��p
4�1��S��+�3�R�7 �] �����'���AHu��ER���eA���1�-��@bz8�L=V�����f��s����3�s1� ���x�.�`dwt���_��9�~��������o�/������NGQ]U��*���W�?���g�u��]������3������nr;c��q!���P�y\��K���Wr'��Os};1�"�W�� ����W�b6?�H�z�"�������������
�@��p_b�{!��CG������EQF�|��f�.:��~��6�I��+�E��v0R�,��5k��s���V���E�p�#(�*���Z@��*����r@���__�T���@�N��r7_9��|m������	Az�p{n��}-�x��`d����t�Z�����o��Hi^�$�������Sg�(S�q��R��L���m5^���J�6q��-R��2$��.�l��m��)���8� gkE��'�_�x+#u`z����[60�D�{L	��
?�����/���~�"��o.M�AYJ�G^���'?ydu)�<��������y\�>����:��GN���?idt(�22J����^�Otb5;h�=�6�pdu����w"��
�!���.l���_�y�!u=5�c�3Yr�H�{���������$�#��N"?2H�(i�[���v��R�}�/�e�^��Dj�}i���(��Pu�\�.cXq.r-�y����5��c�����2\���1u�72#H9�2i��
�z��"�e)��[���9FJ��Fc������RAS{'�l
�5������)s��+�!�}��xY�qC`��__^|3�dL��{���O���O@v���j$8fX�DW8C�����cy�������������"HX*�V��VC�i���y�(��_�����*�.���������/��*�7U���Cx�����P���DCLS4������C������^���~G��B���B4u�8Ei�`%w��������f&!�`�(G���W(�"���SH�����
�&���1^�b��G�g`Q���uk���������Jh�UK� ��m��%)r"I�.����������1;���O������1|_��}P�l��)�����>�l�4�����C!�C6�L}�5���C�U��T8�z�~�M���{�+Ul\e�;���`�V����8*w��i{�8#���H���>b]�V>N&<�a�P�e��wv�����[�{�^��t��^��f����\�41~���-@d�WN�y�����f*���gO���������%7����G�1r�FMD�����k*g��+��t*L�p��X�8VF�3I�~���rvW��=�}"�	{2j�~�[������JN�4x�e!O��]�0N��k�0���QBqz�I�y�-'���WW��s�aO�g���r�Cb`����z��I�	^/<�5�z���e��������w'�'ZjCz������r�^T���� ������/�������D�Q��$fC�2������9QAm^�+�-O��P�~�[���k?��=xl��gR��}8J�z|8��@.R�LtV����d�L���=����������9�S�p8y��
��e2L����tF~o�.�v�&v�[��t��x��������GA�����H�����"��(T������Ff��nX��R��H���~~O�OJ��=Qm�*�QF���H��,[\	����.n�0/�*���
�"��x1�a��U�'�xUUY�N{���~�����v��V+;�V�c�Sk5Q`���u�rd����P����!?I�7z��������b��I���82~�y�e�v9�q����\�^c��K�F�{i��=2;��8��^��y�y����O����pn�<��D��I6��x��Z�}\���(��^�����{�����{��`�"���x�!�������r������rA,��w�sR���(�����:����(<1��a�YW�	�>��MO��N�)���5����[�M���FC��\z������dc!����pt�n����D�)&9+���]�Ilm��(�Y>"�[�����8����zlMPDmpP����*����7���=?��"S�/�gXQI����U��8�]��x�*���/vo��H��M�E(��5A��8W�N�EY�G
��7a��m'IY���R�u�����I�|���9@@R/��4�Gz���xd�t���t?u�����`�g����������'�o����]���:�-�����%w[��P9s�R����&w��9�&+���H��L�����D����UA�$p��T��F&��s�Q�������R���E��p�{����_��Z��<���QB�S��s�D�$"/�o��D|�1S*cej��h������4o
�u�MgfMup���%q�g��jf�����'�R1�~�~f�
��3��3�'Av?���w�x����q_�.+���S�J���TG5�*�Q�����6F�22�]�� �����`��I�i���E����q*�e�&�P��Dc$��c����%���4~Q:FT��(��;�[�Z���
��
m�C���70g���D�}I��^C�����3��@b2#M�&+=���b^w.X�_���l6�?�{�����Al���
����o72��b#�g�(��.1��SR���������V�sx&1��2�-z�r})Pj��|`{>J�^X�����xv��|��^vQ��h�/���u�/;��(�D
�f�s��&*H8������&�\S��:j%�'���*�gnX�.b�L#N�aCz�dz9��Z/n�I���D�9�(�����q��MR�^��D���u�]CD~�@�.��%8��J*MI����o(�<�>U1=�f�	��6Nhge}:R	U�g�Dqw��N���sFA�D�:�#aC��Wv�b�u�KU�!�CMMU��"��w�������[�(�r���1A���<z��-d���U��x^%R���v}D���Bq��T��'gg�L% �1�Ar]wRu������i��<2�2R�Q/{1\���<����]�$7��bI~[bV����z���{gN���^�62qb��6���E�D�Y�6��M��=iIk��G�m-�O,OZW�PiE���^�`uq��h�U��\�l|zg�z���M��S�)^�*����=���cFg�]t��R)�iQqo�����!��~��l�#;
�#b
c�v�/�L�g_Z�+-l����5��"a��?c��9d'�~�P��������y�8
W
�"T�q�J��t��*`�t���*f��k���^����cs�6j���iS�w*�`��R�%8^<?�
m�"���wi�T���H{�)��:�$����2�45��5j0�l��=�����������Y�`+X�;)�Lr~03�-#��������R�1������	)������!�ri�����}p�)��i�Y�@�Y!I���I3�z��tg�i��Xyfwn_%Z��g\X���M
�����#d`��������N�mt\�G��������)r`|��-����f�%������V���wcr�������
$����UZ���j
�����PK���9e[����Skh�4Sqh��^�C�!���Z���Hr��a2kel���I:��14�H;�(�S^��sH���Z����u�k���lmbZ��Cp��)��2s���$~
���V*�������L�����.-��|���RR�+�I��
I��+���h;O�B5r��54��[R������V>�V�!f���R��,�2G�4��i��i0��w+1��
J��1`u�:*c�����E�L���>�i�`�a����F��Y���O�})��l�{�|�DW!�����Rt�?��J]u	*����b"����������l��V���Z��A:O'j���Rng�8������X��$p��)r2���T��:_n7�B���K����5C��%Vw;[�9���i1�E�/�,f��B��o�+��d�~%^��~����#	��/xvOQ,������J�v�B��bO�4�����K(�I�p�T�c����<f�����Jo�����~0����;5/5���[E�9{+�l�U��K9&���
t���������_�*/����<������Kq������2DQ�[����K:���_RO�0�����Y�^��A������/�?6����N�y�����In������'�=�]�Qh%��m����R�^���a������T��"����~��H3�Q�X�����wtm��,%��I
t�R��6cy��y�?�6�'U���������{���L�!��-����A���Kr��d�*�u�D�K>�)R%&�p=�������u
�dvx$Ee|�{A�)���L����v��(
�v��n#�pu)��u������`BW�)=V�R���k�6Z�]���b)�������f�1�*RZ���CFa�3�������$es�a�t�
����5e���q�M�B%��?�����*�:��(
&sDm.��
o��wP$|����6v�rz�����m�2�������qj�K���O,~�s�NZ(���;K`d�m���QSN��d�~��A5Um�_9UK��w�n�IO�\�i�+�!��2J���$Y"�:�rDUCp?�����B����d�����:��I�r��'f���74���E�p�F�v�{I2k+���2f��,�W$�)����m$#��M�P��H��/;��p��?�6���q�xd�2����=�2;l.���(,�9�*�L���i8��
����}z;%dU#55���(�l��m�V"�{��B�v�������:�N(�m�Yi�?��#_���'��RJ������g��;����+�����v��5�eBn����0a�S�X���Oy����1�#d��D�BI�d��_�"l��	�R7���������G8Kp�C��5���{(��F����x,�R	�����7zj�[���GT6�����U����j����5�7�*g^-����������k	�@Y�6���������F����QD
�����	99c���F��bl��f�i4>��J�&��[�.��4�(M�g�"c�f9��B��h�*2�T�gSaB��C�Ia/��,�@-�6r�R��G�ZB|���=�-��VLl9�~9J�|@,b�t�H����Ar����Y.!y����I{����KD�dS`:Z"�3����0��������|�����E	��
qd���-���*br�Z��`�����'R��8�n�P�����1V���'�l��H7�����$�*���3�n���B����V�9�)�������k�fV�w7�������{�>s[��;�����0�����'X�r�����r^Z����T��Z�Ar�-��H��_9>�b`����8I��'��d���8J�M'����:dr�Lw���aB��0���.�����4YJ���/_�k�"����`������_B�,		��?F���yR(��&I
4<.%F���z���F���=��[��.1<���'���1x��p;�:���I:�'2R����6�0Z�@]
"n#Z��`�qJ0�{�;/���9�z<f>\��`���x<pC��_oNoE��b�����\���HP���2{R�q�����{����Q:���FY�����J�RV�������a��\A�HqgG�������/�����/����xi����qv��9H�ZyrpQa�	k������A=�'�Bk6����i �-H������[nD���{"�hke�]�-�*lP�g�`��B�d��}���w�_}�f�#R.����<^|���g���+�|C��[&��=*�s%�a7a�����������Frj��i�
�V�L�W�J��V�����y�A�t��cG�	��^:�c�>�������O��~Pk�3^�<��oO�|�&�@���`�@=��W;|:�y���We ��<}�]��H-��]y.N����+�/���#-a��P����)�d�v�r�j�x�V/L���;���UR6�Y����x�����5���U^�`����tT�'�F
3#��HG�4��������~�W����o���1[����y����f�H�s�M<Jr�?�('�!t#��N��8`=���z�������ip���8�9IV�[������c#1P�������8
�k��P�fU��lw]��v���4��4�e�&��:\]�Y3�<xS�^�������
W
��g�<H �u(�q�z����e,xj��Jv��n���P�����N�]�4aVZL �����yISf�/�b"/����Q����Td"���ku}��V"L|����g�P?��e���z�v���M�C�n%I���#����� �@�MHK���r����u���{'�Xu�;�:s�NH1y/<l��������v���r�al=m4�����Q+Drb�eT3��J��m�K���v�u.U��1-��Y������6�[�X�7�]����5�yM���jm��b�{_��F�I�c���6��.��vkXku���L$U��w���Pm��m�����u70���s�v	P^8�Jg���:?pc�}��n�!����@>L��}�b�n�����M)�g�?�PkP���a�Y\V9B��!��nor�tv��<8������}Y<Y�4�;%���'� !U!��o�����~B`�K�q��Im��9^�W�l��+�62OV���:\����=�hRJ8������^��t����Z&��9����|�/�@f�{C���Ng�1�������bK�%���|R63��
��������7�F������s���1��
T�y,~bh�����=��J
�(y�GM:LO�s9�A��yF��L��W��1u�p����4r�������������d��{-�t�'�m����<5l��zO�����6��{��4���8%�k�;m�O�$����R������b;B��j�ZK:��?l���m��X)a,�zfJ
���l�w#�U�������&	��D
�����3OtX���)�I.}�n$������AS4A�z�#���I"C#X��RR~��D�u|��\�7��U���4�o����������z��K.^�f��^9�����d����iqp���Ngt�(���J^_��pA�!\��o#�y2!����>���/����`0����<n��V����Y�i;������r�d�86Hl�$�����qY/H���LC-�E���������%�u�]d(�������q>�����E�b�,3�w
���a��U��#w�d�eo�,���0I\��7�������]��w��"b��r�<���������9�/�D���P.�/�+�������c%�����D+k����u, �K�h:*����i�1-�&�
X�����T����L	O��`9��f����`���d7T����g�^���d/d��!�~"���������.���l�pV�a�n#i�u����e���6���Wc�a���{��!�G��3��=����:.�����Y=DN,�(��c/����v�3��L1�L��]��:�6�@N�5SxZ ��iCN��G%v/��X��i�7k�kY��	������n\=����'����8����������W7�pY�VD��3,���G,>Et�������`���)`����%�Ra�,����xbtp�j|I���x����8�dt_]`�j���]�E>��+���i���p �D���6�����x�4���/V��a1��[N�3��Sq�[��-,8y�B6�4��c������;:JJ���8���6���d�>��G��$�����R�H�
��
��m�������]��9>���H�Pm&�C*+�C���+8I���2��E����;����}P��,l�As9i����3�L�nm���T���)Z%�+�)*�t�v���N���Di�	�����j��t[�Z?���9���I��,��������5��x������*�����
1]�V[�����2x������������OQ$�+��.8��<�/1Qn�i@�n�E�96������1�t��8b��-A�F=&�������W.i���b���V�L	�'K3cE��9�>�����{K���P����F��)�C������r;���:�����;�N�*C��dB���������F��bh^w~��r�X#��#������?�Ten�FM��35=~�Yre���.e��Y`�r`l��B�
~��,�f �%*w�8�s
k[��)P�5�N�TsAQ�S�N��h�6�ynR	�s�����@M(��ye����e����t�E��2g����#�j���A[],�#:���`>1Z2C&��@��yQN@1kFf�(���K�la���%�s�W�v�v������VP$I9��<����t���kL�u�o�Y��w����7�=��Y��nL3<�M�-�i�S��4B���`��F4n�+�������TqiJ9���o����p���`9
p+�3��d�x)�@�}q�'87��\�����o^����*uY!M�;�-����2����Q�(��k	�4���4�Q��P��#�������yl;k�q�R�g�wW��P����f����<e�H�cv�C���g�Sf���q��r�����}o�@Z>������:��	�������V��D�������o.����rI���F1��vqD����L��)��m�t�7k��K���R��0^��	��$�l����<��Y9��zN�I����Yh\��D��t�/�I��A;)I��I���t�#�T8m��>�&���z�F�1,�?�=_e�+���o6�~���|����~��9O�9l�p��J�m�������}�=R�����
��z�B����N�N�6����=q�BFK
�H����U�<]
���� ,� }���>8�	w[5~NJ���f<���c5'�N����^�]k���
�k���A����?7�~�h��-���kB@G�F�����9{i����r�����T�6US��rn��-1�	R����z-�
�E�
Ir������NC@�t3Qo
g��b;��D���N"�qC��>j�7 q��%Q��7������}��<�I ��b�����#��JiqXc�:M�z���� o#v�sbE�a~����k�����y9oCNw)�Z��g5^w�hc,�=r���QQ�����-��/�6�q����-
F��'(���".�IBEY�������]�v
e�D�W�^�F�����A��q���%jfhG/�>�,����0�em;�*#�����
�j�4@��`A�9��%pbD�cK�V��XV[�l_�@��MCMB�>u��4rCM�-m�������+���_��!;`YL�9�Q��FE�����������r12����x71%f��AZ��C��9�
�[�@���<9��Z��G�`�����
�/2E�[���)��[B5Y���G��p���Q��nR��xB
����A�2��K$q�`�^��������<?6�p�"O�.����j�^���!9�#����.��ZH&6up���Z�6����A�����U��.C�X�.��r��m��r���o�j	���I3{�_�:`?�2�Z��o��=��K�=7lISe��B9�`\�������~Q�~�V�"Iny�N�e)xm����&��\!�8�	8�X`��C��A���[���9��1D]�*������FLz�����E�T#�;-bZ8!�������
hm?�BHn?'k��i5��n���~G~�2���D�j/@�z����l�~T���>�r���|5w��.%O�X����oB#^�bX�|>���D�_���W3�����>K�����a%8&Mmu���S.:��O, $)����a�)�l�]�7
��K�p��gI99��L��S����o���H����f�0��Q~Cx��J��T�$��.���,�������]�*�o3�\"�!d��4``�u+$T�Z~��i����z��D��G����lW1?a��>R��oc)��p��Sc{���w[�S&��K���k�T�E�%����Lb+���p "Qi9u�~�2~k�]�ya�W����[��&/�k0I����?��w;�8	1C�w��b��y�������T�U�������X]t��i^�"#���$!r�z�aB���rc�A���L|����!S����n0w������!�M�L���KF������5R���G%-��B�q�[�f���<����>X���4$}���~�He}HJ���������#'�G�.���<�Z{i����/_�:�N>�;�����]]������&\�c�R�~dI�<�x���3�ZI��P���i}P�v�K+d;}S��v1��Z�&v��&o�pK���{�����u(q�,mt��M��J�8����g��|����J��(��KwW��e����+����m��vB�&�]�J��\G�Tk���/�W�iPsJ�%jb���� �H�
����	Kjl;����P�
�\!X��h=}������� \?CL7���:�2�*�_������^�1mw�Ig����~�[��{[�����I���k-,����)Te��ZsA� OW�r���hE��(�� �q��n��n�k(%�f�kWL�k������2Q�v�W�'Q��F��$�c��yf����3�2*3���9:HD��7���B�[�[;��,(��k�{]w�h4��^����[M�"�0!�
D�	r��)y
V��B	�
�"����u��������w������m�Wa��-�(�3�
���:	�'��D��v���nPGDx��F��W��Q�u3��g�Z9h\+UA��XY�Tp��o�q�b�4�|���F�[���inh����TcD�A�0P���w��0��J�LL4�Gco�y5`w��0�Y`�I�G�����&���rn��!���^�ow�M)����"�������Q�
{&?�p$n
n��$d������1L�gY����#<rb7�8�3&kS���&�P���9��Q�3]��+�=.pCQZ���iXs+7�V�C�����'q�)�@'��j6�^�r�t���x�NS��a^�C	/,s��������< [��������Ai����`��G��ZA���`U��z�j�b7$�c9���dy�����g�UE�=T��?�� ���#:��h0D������{��Gg^[������D!�������������W��}���N!������j�t������aV���vj�S��f�`�o���r�����;>��|����\>�����R(�'�=���'P����������:W�X����������;��/y��X��f]X������s�+���[:m����o������5}0��{�����'qDs����a�#
g���u��.Kg5_���^�Ck�_V�tXs�P�up�������^��_�����P�����`
���7�F��
�������H4b1�'���8��q�q����Q�����-����r������
�m{�I���n���� ��\�r�������������`�����Rk�
=���?am�����YO��4��9��b��~����0a8u��N	T�Q��NF��Kp=�K�$�Q�t�E w24�Z���[�0qN�����`B�����%u��$PAi��;I�E~�Mf{��b����8>;H��d�FiIU���������*�O�}�bW���4�y���'���MzLL-.�^�xM�!(���`�C#����p�����?���\�����apT���	�l�������b������������n���M��AF!B����K����o�#���?s.`����pu�xu���0��2D5��W>��>#�ky|��E��3�e&;�|����<�2J}��-�m�u�k/��������?8��V's���l�L�Y��	#��a�Gj�1�r��7���fG*_�n�����y�3���R%�f�?�
�k��*��tQ�����TVis`�e�sc�2�k���K�����X����
`��LDl�;y�.',�kM�������[���@[���n���/-�������k�����.k\+���x�%�$N:�����  ��Yw��h~�mY���E��n��%�lT��S	��=�%^n��8�WC���Ud��������������$V��k���ay��Q��v���)>=�{xUx�L`G���).Cp���������P��?�K��?�^�����gF�'�$|"t�����H+7�D��c�������5\��a��2�5:�qg"�^lIa4��� 'Lu���ZUX�d��U=��xYp7����G$����_�vt
>��Z����K�H�cb1������Nj�g�A�==y����]������%����Q�7��Q�U�9s�l�~���/1���W'K����[�������{��������0Zcs���������7�=-��k���f�.z����t�#��G�����e���;����pz?����������A��^���@kn��A�����Z7(?������wP%�����������e�
5�X�@���j]VH�#�D���I�V&�K����X�b�v���{��1���U��4��`��x���J�q����|6����#N��\�"|Z����%�)p4�:�0>2dp�B�k�?��_��?��:������-r)��f���V��O���"��SB��t�������b$�5R8������nS�TH�w�G��=��J�<],]q�u���������:`��	��q��U	
;��?�S*u}������]:��R��R�H?��r�|'i�O�^5�7�k����s��^P_[ED���bwDm(�I�urr�q|����������/���<�i����b<�>)L?L%|��C6Q��/���-��� s�������q|e�����[E�o<�(E�g8&�����s�����1�{���5��#�Dl�:xj���;��<�� ��|��ZE�sRP�^�yG�N<�]\r��J)�*���
/t�����r"e�?J#��8[�@�+���7�'�1M����)��Z����N���\��\���ev���������b����'i��2~&��D�)Y(=�h!�����Z���U���*]Ec�=h\
B)������_�8�X����N�Uk��[_t�Rg��~B�;��z������$#���7a}��cx/���=�gPM��rz��s�������;~����P�{=����Z`�YX��B�_9�*���u�C�l��/�����t!���+c�#���+��
DMv��{ �����Q���1o���������� �C}j�E5�]5�[�����t��[�{�����`<�����_.�=>NK?c���T��^oSo�l�&f��T9��4}>�[�39!���y�o9���h�������8
�I<Ttm�5��)�����L�o��{��(3R�k��H����R�5�b�BA�����.��G��A�%Sp���YI��6�P�NcnU��U��JB���� dg�b��)���s�	\v�
��pu��"�	&�7q�s�N��Jo(�%�������z�#�����k�jz��\�>?�xyv���V�������������t��ZQ�\��h�n�[�����i������X���}
Y��y�����2�D�f������7;�}��M��������u8����E��g�,@"��^�x��z�c��K�w�%;+q1�E_~L�:7�4���)~w���G�w_��;9?�Nn�I-���#����C���7��G|B��pcE��~�]����.��@��8)�T$)�br�2���{�	RW�2�������Lv\��������D97����?���I���xdO�#������P�������y�j!���*Z�jv�x����x�e[Ye������� ����d��fV��0�2t5d�n��o������u�eH%�jWn1����|��L1��^i%�QR���|���ZHu�3zh���H���c��GBe�Qs�C���/;v��l3td�rJ24�����2�V�J1�6�����<���~}�j��BV%��2O�/��d���{��0��E���L�%��&��q
�p+)�
��)�b0F��p^���%��&�G��p�yFU�C?E
9�1��M��7w45bY��I�B^I�(���>[��eP�c��K�[d\z%���w��y������q��idt��7�]B����6���#�P�����^oW��A�-�����8j�~�N���oo#+-)a��x�O��z!�����g����'u �2��[V3�[�9r5&�TJ) �!���%�w�{����J��jF�ay�g��Z�;�=��Y<*�S>�f��5f����������YdrXS��fN^JI%��l#	]�����
������]�Kq�t�?�4��P��=���2w�r!BB�d�)���;���������F�Z�����hU���*AR	J#��<~�|a,���(H��(]��E������;^��s�4x`�W�X�n4:|�J*�IBB�^PUA�O��5����Z\o��8em�7��#5
��U]'o�����	�Y�x���D���
�L�M���`9�o=��;���{W{�<��q-�La9�F��m�������n�����Zq9r��k]�?8��fX�?;wiLL���`�$���!o"�1��m���Z&�;v��{e����`f�*x��2:1�T��tPp��Vvw�K9G*j�M�d��/�6Q����/ ����B����'f��I�gO��a�����;����s�Y���xWIQsF	���`��
@^�4[�����(j#M�Y�(yY���ch�1-��N�	s���C�R��ZZ?��8�U�y�.�Yo31{�&�GY��I���
F���B�%�#;��:]����vU���O��+y������\���Y���X��>>��?�)�m#o��}6�����[�|X��9.!��l��=X�����Fe��h����R��x�QK�2l``^��2JI��*�5����|)QRT�0�~R���/���n����������#X�1�.��|�[}7���K@�v���j����������f�w�����+���`f;�$������T�d�A4A��	AU��s�K��H'"*3KP�h+=���Rse��5]��K�7H[��Y'S�����E\���;Pt���+x�s�����Z�k���E��Q��d��]3F�2	kG}5C��J�uj��d�|!��Z�8mr�W+��N�C����U�zv���"&p�����Q��c4���)=����e=�r���Y�����0;a������T�5���Q�BA��1�������H�9����A��,��������SF(V[z�%g
�F��,�1j`�dV9��_�Z[���e���O<'���%eiE�|��TT������,�E�	8�g�:���5@�������E��$�4�_��VIs�u#VZJn�0��7�
�v��da�j\SSK��x�!#�j�e�
�U����/R�sc�;��^�e���B�����E����J�54a^��2q�1V���� y��EV�i�P��Q�csC���\@g�8'\5����u�sz���qK����8��J�>Q6��h�0�U�qR��n@N�����2T��0�ysS��-Z;F�	���O�JL��	��x���&&\�
��i6���4�5��E���J^i�%�''�EJN�9�Z�3��B���S��"R��Y3hE+]c���!'��0R�Yg���P(��fe���k(������
7cFKH���7=����ah�*WQh
qn���)��Ga7UrK;I3�*+�I�E($�l��i)$���q���W�#4��c���h3���WN��p�/xmi�N!����@�O���$LI�7�&�5d+@�7s������B�pg�Cl�	�����Dt����d����T�����T���O�P��1J�0�1m
��i��v�)T��Hd�d�w&�"0m%��
=���< �{a��I0�����&DA�O t3i)~G#���G����g�����t��7D�\
f������\����1�p��'�� 5c6��WC�����U��
�p)��k`��]�x�?�2��'aK��JHk��+a�	.��+�������2��$
�� `���R��4-
e�L�9>h�u��]��x�*@� ������1�����_�����"����I=�	}jU`i�wQ��m��#������Y���H-P;A����i����1��7���t9����d��fT+o`����
����s3�c�-"������"�^�{/Zb����EK�cZ$�%�X���Y�e@���B�mc9�1UL63
>�S���m��$��f<(�������(��_�y��������\�p���4^����w�l��]�X	�J)>���_~s�.K9���2��TI��&�4�I�f���H4���+h��� ���LBDu$�L��� k>��tup��_���"��U������zJ��)1���<+�#�VPu���tS:S5j��!��4S�������S��f�g��\%�ns�b�A:*�<w:�?�����\��'�3�p]z�����
�k�.�8}�����I��v��)�?������C��ONV��=�'������|sr�����[��	vw>������Vz�e=�-��T<�-F����'�+�f��|����H�>���6Ug�.\��n�!�)�<NM; MYB�7��R����������M����)���9�eVGu��KL����NK��N�i=��d/�1����?z��o��H�V����pdkSB.A�A�y8���RH��3���1{`��	�o2A��t�����E%�$o���n�9c��7sN�2{����^ay��H/�����b����\��>~76�o��"�3�G��SP�x���V��;5)�����R>O>9q/o��v�!t��!��.��������!�������Ra�^g�Kb!(=���V? H�N�P��c��\�f�%Be��^F%sD�1q 0�i���2���Qz���?v��_������u�E�u��V�
��*�,��s��U9���}5c��?��g�6us�3WQ��9�j��[L��62K���P�����"���V6k�����\��1Z��S�������i��Mj�U��8��a�����A��\b�>��+��L�B��$�':��W~��q\d�s��2g@�Zr�,��<�,E����J!���Y�P��]0H����%j��^i]���R�|�V����� f��c�5�&�����������C^���7*�~����R�(���-&���}�R�f��B�O��o(�-�o�^�Qe���>�s(����_����#�.O�JG�����x�o�j{s��E�]f'/%� ����S���YN�2�K���!
�9��P"�r��HMrL
GP\�p�J$��@����9�=U4]���Q��%
�`���&�
�WM���8���FV�g��:��MY���/�.E�iI���H8a����8� %�T&��Q"��(��K�Km�
>"OL��d:��`L/:`�2I6��O��[U+
H`x�'��_8�����`O�nt�$��5k��
k��"��
J�K��X��^���l��P.�NN�zJv�@o9(�^��]RA?����r���,J������s[R.��Z����g����D��l�Gc�&tJ7X�W�o%�b
�~���x���������rw��Y�%��(K��?���x����T���wD_��S���P.�55�����q�����%�#�����e�P�%.��XM;��=����I���;<gOI���[k��q:�MH�)�D�\�;&(7�z��sZ�J=#�<^y#��E����s|���=	�g�W�@a�������r��L��x��k~�m�?t�i���`	"�����{�������#p��S�2���wr�N��t�C�3n�������)X�����Ip�t���f�F�=tg��ld���aa��t�!!mw�!�]@�`�[���JB��L��w7Y�t�0�BXJn�����F����-J��R��LNN�nL��P� �>�?�&�NCp��3���^���N�T��C��9�q����������r�,�!'��`z��nM�W����k.�i�Z�Fc2�'��(���[Hs�t�<j��?F�"!�f�`�~4�D���&��Tx�Ee�$=Ybq�����_�7e����R6]x-��V[&������+M��H����KK��>"R�O�;�.�s��G��R�gh�����y��bz�@�f�-�
��,�T7�k���(�!��0�Jw��D�f��%sx����H�����]����:�N0�(co8o��s']?��'j������L���]v��C�1��O�Bg=�o�	NT9	���R�����	` ��J4q�q�B����t�����Y�oIz@�����A�8�t���[A"�G�(}95,y<2���1o�SF-1�6���"��:�8�����5����j���z}�������N����S����$	����_w*�F���T��A�����$"	��*�\�=�~n��5��a�5��"��(�X����su$Z��@g�J5��h���v�s���g����v~��V���t�v�w��v�?������������7b�O�����[������N{���7l�[^����H��<����#���e����,���N�����i7��
6��9����0�v�t������1����#�[����&
�^U�O�������tZ���
Zk!���^�y��5{�f�b;����������_;���V�oSfJ;�(����q�#eV���C�J��M��������gbPr"?����~d%�UHB�b�5~��9C�\d�q=�S����'x��w�jVn�V���1jVI	�l3�g15x�5���0`�N��T���K'����+35�U�<7��N����Ar����93N|j�AAj����A�;6��4�/��5�\�jI	|�FmI�a��T(GUP�'�����b"I��?��%�M�<��W�HlKUQ�Fe�WZU1�r�v�+a<0�3������G2��#YuW��m�A*I�P���������RTL^dW.�R
[DRu�^;�c�e%F(K�[M^�D�4�Q�r�(�z���"���N3�nw�?l��2��uR�cU|�����a��yC�Ve�7�X�������m�J��"����_A{� �hY��5�g�lw�9m�m��*���d4���+�r������6w�� �U�]����7�Y%~c����"la�m�H���izRp�L��:�b�vU�RV�<�oU��b�3fw�X��{���;+"��"�]��m�����=L�}X��S���M�{�5�;�������|,�����kP=��������lj�z�FH����%^��R+RvA���� �94E��$2�+/V�%��a�JM�����|�[�{����u|	�8������������$�������x'L�Y&[����b�N��2�{���tWKT�~��oS�v��BT��:�Lv�����7�:�?��<���]���&����"C�)�-����%X�J	g I��	:AF;w��_��)����*X��n�S������x%4Qk�1yP~7���J�'���
������oA9�e�y��<��.���
�[�\;��qM�K#��;���"��������fOo
?���!f������M'�*Ep��k��?B�+_]����i�����I������x���_����<�����"*CA���V�1�{����� ��tz��b���;j�A�>�"�G�:��7K����h����f8������
1��b���_:����
��UU����"�+��/�t���R�*���
��G��5�T}m��L�Qv<h�t:4:NN�q��;���K�}<H�:��v��-�
t��`a$�������y�����?����oq],#���2����QM��
M{��`�M�[?�<�~���%(_U������I�L�E�mp����QI3��=�������"��)�����0	)���Py�f�a�����D���u�����c��72o:��?���i\��D�pz�Q��3���*�F��	��0Y�o+��P���
u:��9da'�n����~�U*��Y[�7��0�n�����g3���3�����������5o��\�e
���O�o-f��I$��p�%�d�R��j���:�.�J������a,��G����  ����S^fR��JP�r��4Q�4�Q@��3��z�I����I��- �tD�.D)�"� 2B[�V3'\�(�L��G����[
�
�����w3�}8�sPD]
����������<x\L[w�mI�9�aX�}xZ��1�R�2*�Hw���z�Id��N�%��j��.�r�L�n�sg[D�-�j������/U?~5~������g���_]�nt���@1��
���g7vLz��%I�o��{V�VF�����\����Y�m�863�� �k�N�d^e������O��d:�f�Fc�w����qP�B��$�v����]�lQ]WA�*��������]~4�-7f_��R��W}�]��W�s�z��,ne�>�}����z;�����	�������'��F��?g�(s��3�����}�F�7�|i���^���$�_���9�2o�|W��,��r���>A������!��t��V�6�f���f��Ut�N7Q@�q!����|�;��B�f����d&���CX��2��k��!����l�+<�%�����Fx�������F;�
&�F���*X������.�UD��a�
�q{����mXY��8w/$� ����qL'�����������������/)�����T�_�{
��|b3p
�_!��[Uf��]�09�m��������`�$V�@5���J�$"�;)Q~
����cRRU��H���V��)�����`Z�����>�k�iX����"�`��N�?@�����n<����_:�0��g:Nk����Ir�����,m�+X�����j>
�(���2e"�46����9I�(�����_|�$���%
A�q�j-��v�b�sUq�K*1����V����/���U@��9��;�����)��h���~�����a�<�Y�[��A_��D�G�����m�����1���Q������[����=jb��J-���](������7Ck���)dz���L�0d����_F+L�^�hL���53��Cq:�z}����=��o� ���0��ae����G�	?_���3���Ji}���z
M����s�N�|�op+�������7'��	������g��M(��\��(���gT��
�Zv�������7�?HK�����'�a����n��(�\j������
�4D���R��hG{�7�u����Uz#��I����6�W�`�*p5'��B�`�����U�4���������T����k�)Q�9-l�6<���J�X������J^�tW�u�6�+��p��OU��;���_��7�km�fV�m�~�����
&�~���(b�i�{MR��'�d�UOD�V��;a%��
b�c��� ���>�P�������j\�H�O9;)VO^��=�%G�����,�C,�/�����������A,�[<���8�Fd��|�c\0��n���#?��
�Q�"�}N�r�A�������'���d�4�7�p�����-5�2��q�e�������y���C�>
U�v�ZG��+���9#��M�v�#���-���d��8m)J$���&������R�C������u����E��]%����aw�
��l��z.7Ym�y|V)V	���>�]�f2�s���g^�9����0bU*,�'S��_y�l����o���(r�P9�������[���XP���;L�A�S8|%L
���&b�z�ba����U28'iFF��bB��j�X���Y�~,INFXL�B��T�}�k��n���L���_���vv��Q�������"�����5�<00Pi�h�f����*�o���m����=���a�`�����>n����7Al&�Es�F5^�f[/�p�9��_rw��l��Q�E�z�^M�
"��m2�'+y5����^F�8y8o)yu������Q&�jZ=��'��w�������<���RB��Q{�"kN:��������>��M�)�[x�b�a��4�c��M3nK�tm�_iB�Ir�D�p�/��L������k�V����u������T�"���h+���dz�6l�����uS���dy���WV�_p	�;�]�\�~�7l�����ApR����wQ�e��,h�Q��Y�L�CQ������o�D��)������x����N��%����a�����n��$s�����1s���q�P,�<�3������t����)���:��&�_&_�w)W�=�>�B�QB)�'��p4���������6v��������k�|��g�A1�J�BB_b��:�6�OyNX�up�w�tklN�9��Y ��)��L�4_�����rUR�!��q36�r����D��;w�1r�������*Gf�s�������d�kMg��_�"���B1��IE,*1��-�]��4����qUM��.6ZOkP���;ABl����d}��e��YyQ�f�e7��FB���8���%Z��|ANFnaC��B�t����cB�q����Z�6�G���]���J��"�0
�7��5:w$�����X�7��1R���$]���b�J�Z�R3�������&e�\s*�8�@A�;��N}�R�q��1��	��G�b���G^P	:�m�����o����|Fq����t'on4��+I`g���ou>���R?�eD�+�x=���c!��N�RZ����x���E���m�i������](��#.��b������R��`.n��>*�/d`E�=*�������������A�M�`�\�LO|
��������W�n>���0�K�S����^�0�>��Ja��������G�y���Wx���/v��z�x?HzE�j���I��)�y�e�f���}�I�;��\���P��X��h�/@1��2B4���3j��F4�L��D�[�A7�{���?XQ_��Q������ �&oR�:������c�j��A���r(���9���Y�~ULjJ2��NG�=��������Y���U���5����o`��W�L�C��\�g��6E����5%h"���j���0�!7I�i�k�����y������*.�Tp�x�2Mp��&�^@��7�Z<R�9i2.}�Y��r����iN��<d	��ct��IC{���7f�1���w0~[j�N<tn,o�������,������omS���Vb�[9��Eu��9����I2WCf�������L��M���s��{���Z��x<_�Z���(/�7	���{����u�wFl
w
��CEJ����Y2':#
'N�������{jG�8���l���r�&&��N���NW��=�e)���L5N��"�N�9������������r�$i�����hlub/�0����x�/�Y���dktd5��x���B���>
��n��X�[�Z�3�r���@qe����?-w���o+z��{��~�W�����������-~������f���v�Nik��Z�#tD��MK�D�uF5�hk����=\���j�w^M^I�&�0Sw�N�y��m8�9�u~������B"���g�9���5��?��Y�J=7����p�r�C���OZ��IR�5�����@�j����"��jBw8K<?	b���=tp{��NU����9~P��"tI��?��j��:���_��;y}Ys�~���(��E�Qv�I�w�i�1k�M� �-��JU�O�I�\�)�xE����>��*q����cy�����*<q�fb��H���6F,�9OC��9���r��Nl	��$8��@��o*X���H������(;3[�Q]1������T����_��hB�����Ovz��p;q�Lzev��H�N4��I6h
������P��|<[��L����Y�5����_0Z�NPV����r���x � ���Z���T.3���t4��rIjYv3L�r?�x(�[{����O.o�l����RT���
S�B���/���|��?�>{���������������g�o�N�p4�����1�[A��G(>���%{e��6�������b�a8��z'B��1;"R2�|8�G���Sp���p����y�F��]<5Cm�&��������#J>�Pb�]n����>f����RV2k!�Z���r-�G�[H^G+���+���X�bQ�M����V����Gj~������e���d)�u��g���)M�P;���=^��l���p�a�>�F�}c��mSR��[�0!3h-��9��9#u9���Nc���:�p�wK��qgq\H4��X�S�^?F'���=W��e�Yk�-��>^�k,^���
���c>��jI@��gBj��{hG�fly�K��Hv���i�,�{��n�b�K����,"�fl���v�a���m4�Z�R�V�)�F�I���;�vL�M<Nn�S�?8B�o�K�V�x���Z���f�J�"���IUif
{����S5�v�%�FK�cK���0}����gQQ8��i�f�=�k�e���^�le|�4V�u7)_-�� ��}���j���Y�E����%>�i��*����7o<�chg��4_A�v|��B����x��Lc7V���"w*Y9�\
V;�R���U���|�"'��v�`���y��r��2��.��pp��HW8���#�M�UR��D���:�*�t�1����;O����hR���DrP�����0>�������.��k��):d����n��t�k��{e�#�Vv��\"��r��BU�����`d��!F����^h�UifW�q��R�@�X�f]��]R��%r:��5j�s$��{T�j��B+w6s�v���MF3oP�VR����Ty�kw��@�=�z����m-GM@H�K�"�Q"�h�El�bK�B��c��oN6C�=m����
!�/���f1���$�x�����������g
����yR����r{$��U@����Ov�������2��v3;�C\�����M9����^��\����O��Ct4S�?�n��O�!�d���w^_�8�k��� �7JN7~��a������b/��W�+~��������Q�������<������ne�FP�����a���Z��
�F�:O)�RY��
��E�n�D����s:,fl��q|&T,�]Mew).9>&*�"n���"������u�R�!�a������~����~�o���(SZ"�~�vlcZ(���m�$���W�!��8i��D�|����w��T������9�x�d�b��^�����e]�35w�[b��K������GoX�e��;�A(-���L�� l���JDB����]�2"�w�V���k(@y���K���;�[��0��D]
c$�c]�hj���7��������.N;�"�~��b�y���<��1c|L�ts��t$��]GL@���2��rN�o����F�RM��#N	Ij��~;7�$�=yY���lp�
�z��k�C�����������k�}�}s�-�^5^�xJc$
CS9�FP
�����Q4��vB����*�dt[��t�htz�^�T�V����]���C������$2�.':����
u�����������~��#D�S�?�����Z�b�w��o�����w�N��3������-�x�91D���%V8�V���o������h�z������=�m�5�O�l�/���L�E��*�0����h�Z����+����v�u�4!�I�6���L9�������a�q�`w��f��4X���P������k���@���WR�1���U����8?<�|flE��hk[�Tzv����B_��i�r�^Y�i��z��tba{�L�2�hV+;X�.G��.+��	"�BU��u�1W���m1�j�'��p��[�-�������7�'�(���
`2K�/Q��z	N���s����zn�sC%Y��|�VJc����x���mW��DNd��A�A�`�/��,����f��r����{��2{M
�
�r[-o�9�N��y4Uj���I�f���Q�j��+�����;��s��g�R����f�1�1��?^�L�#�#2�V�T�"��hhC� ���E6���A����s���V��a�!��fn��5!;���9V�	��C�[c� &�`Y������\D�|w����s����+@��ld���b���dG����JU��?�,W�y�j�����Y3#��/ ��=�C�KT��,U��+G�n\L�\B'�����a����`icK)r����0�8�E�����^C
��\��x�al�!������?u�bD��N|/4
G{Q
���{�X��sY��:�H=�uA]�&���E�v)�;������`��&{���S�d�$�H��3C��$��
V��Q����H��o���d��6�pt�$1G�����@��������E�����I��������y��,��
���\�$���e���::�J�n��	n�-v�>�D��&\�=h�`����������������?\��O��a��)v��<�#�����4��|�l�����O/���~��ev���]��6��/�G������v�W����'�JL�]��ix��9���u>w��+���
�������NU��I��uZ�F��tFe�u���8����G�:t���#���&M�����mA�u7.�F�7�m�P{xl����&Is��G���R%�Q:4;�jnV�;��Y�p(/��lY)����K�:���r*^L�������{{�{�����1"%W@v���k��h�������f��wzMw��N�c���=6u�g'����k��N,�/�D�	oO�����s���QM���5
FtZ�X~!��5����y,�M���"��t�Ng�Fc2h�Z�2�f#;v�*FW����lS*���K����7.��?�����Nq����m��^��$_AJ���������n�F�n�FCu��i����m�*��;���������f�7���K��AT��������i�.%�iz����7k�����vv�\\�5;E7���U���(M|�����d�k����d��Qo^l�3��Qo)����$������r1����1��x�����M;}�/��/���1JJ$7�w���U���(K=<�U��*�br�k]��2����@��r�%��+���I�����J�|�~*}�f��*�O'0��$���2��VA�������*�5�L����.Z�
3�CB:6�4JV��K3L��>�(��y|x�2�\�k�:D}8��a��uR"8�"���*o����b�M����I��v�I�����N����8�"�(�������KD��%����vk��b
����'#����l�-{�
�!4Ci����gItS�F:L���Cqn��^��T�=�����A7Z�}��]��=t����ZKg���J/
3�������}W;H�m Z�\V�OY�Hg
��+���N���O/���	���_����(A@{����x"@W�S�B��O&��2\��q�������q�{�V�9�S��z��[��H���_�q���o6[�j8'���3k�=���v�Va� u��Z.H�iiu��f>�r��	�Q^�,6�������^j��C����6(��]������`�yq)�������>)Ws�E��iX��A�+-J��%����Bo���^���#�8������f����f�/A��P2��0��|v��Z>�`NU2���0���3��\D����n���� %e%�m5��'���8���!�U�C��WF^K(�p�h����
i������z+�	�"�����v�O����H�3S@�<��������:oN��\�������M@�V<�Y1����I�gf�W�y���t%��F�q���{�Pr�8�3�q���*�F��v4��`�T:�M�����t�mwG	������J��W��{;�S8:�������;8������K�s&��HE+x$�����>m8�rf�#@a ����4��������F%�&P��|��4�k�)d���e�4�N�@��_o�5p�p��o5{��K����8A24����=E/r������*��������*�[�k�92�_fml�����'�0ax��S(���8�`���
����������9���������i_�x����{�,���wnx�r�oG�IA�m�����
�����df��KZ�}�r�R��)x2u������y�@�2�y{�lSF��������%���e���Oo��,�*Y��
�t	���${� �/`�l���Vk���/���xQ�gV�E!����6@TDb4<���}L..<�������V���p!^	.�5!�g��k������
��n�_O+ErDq�m%WCe��G,)�\t�o+��`�����y�����N�D>�����H;���^.�E0w����I��#E4��r�1��zA1���b>��e���*�e��4������f~[C`��\��`K7�u�p��NmG����:L�U
��c��rw���eZDW����YA�j��M�k7�No���Z����q���D���/��ai�����AN����i#;��� �	7���,���@f"`�*���o��]���&#��~�w	K�;�Wpz�
�������pGD[\J�F����i4��Ak��
j3��E�qI�a������az����P����Je���D��������N���q3�t/��l���Sl��X�F�$Uq��J^x�l�W�1�I_wYR8��w�YN��y}�c�����e
�VK;v�U�/�}����=����/7���N�}�v���+T��	rc��wu�Y��\?;�o�AT�H�SWR�@��/P-N�.���js-*Y�N����!����u|��K�c���,�����f�z�YI�J����R����\V��J�,����U�ki��D5���
'X*�c�,�w>�sb��I�F�n1����s���p��I�*1���A������������.��v�����iNZ�IkR�h�3��G*!wU��W!Z�|�7Uu�+��w	6�pNk���,���Q�=���F���|�,	X-� �,�d�4��i�EqQ�R��U�Q���P�9��
��A��[K����Y�&���D�`��~)P�{Bn]����G�����z����h��n�-v7�k�����c��\�������!��o���D��������Q1/��ka�����{e�+U#;w��_�h����P�J�}� +hn��F)UQ^�C�{j~�%aO��cY�� +�� ����E����������_��1|2Ue��B"7������`��dH%����v��>zz���iY1icr)�h%j�����BU��/�Ei����G��Uu�k��������O�d
f�����,�K�g�1���fV}dR�s����Y�Vc]��{��P�b
���Sn����e�A�fvm
]���E����N����y*6��c$#[�x�+G��f������t)��w�l�Fb���iH�rv7�aA�����/{@F��D����w�pb�==������? �!�c�S/U~	jhQ9'a�+��&����������^��Yb����E��B�<��8��*q�J* q����F�sG�W��n��{����r�������Ka��_�"���G�*��'�N.o��[v]_��2�0i�G�4o�]���+�/,e��tYI�|�3������
�{�!��Y���E��d2k���&�N{8,��<�����,�Z��$��v�.M[��V6��d3����s �Eh&5�O������EQ��:p��V���2��p��|������\�/��.Q�������n�w.�3*k����3tA���8g%}ZW.(���?i��M�e?{��������A��jw�l�-�K��,8V�	]�QJ����u:p�F���7�ne��r��[�O�M�p�*<�zK��5������\�j���D�����������YNI���h4��n�V�l���Te�e������O���(�����4,�	����
�=@_��,�����.s���
�o0:��C�o�)������=~!)�_����~xs|uU�]�b�[���3�7���������,�1��~�EA�-Jl�]����p:�I0�y����bZ�/?�4�7���\�~��W9����DX�E
������=E�:z��A�|X���.��Y�B�FN���6=kC�_m6;���r�� !�+��b�J�������q������~�l���Z����^m=������,����.��������M���=��t:���d?[cJ�k��@��p�(A\f������i�1�^�]gDp��b����Q�L�J�;[�8�<v���?9�xyz�a|qy|~9~����������w�������d��>l��y�I����?�I�w7z������!X����p����G�P:�� ���	<������,�<$���;4������Hb�aU^KT��e0U��T�y[�W3Lg��)�����������W�DQ���Fn���V�����M6�KvKgl��o�8�X�t�t�������A���������{��<�JG����a.�4on9!�����u'�F������[JSa~Y$�A���~���c	p1��*�Ns����u���������X/���Q�~^�,��8��*�&F{�_�e�__�OU��
F���Tb| �O����P��pT�5��i�Ny����O�L���y�6CJ2o�{��Me �U�|l���	9@�v��_��[GM�x�����	����S��_��)-��yx��1��]NS����2-M���h�h���<)����^�.w��;C�N��f>L,�"��c*<F�Nuz�b�h��3���W���6���^/����)��`�1��������y�_Q����y����v2�k�N0��J�P�
W��
�tx(`I���*��jr��J�u�2Z�W�����ov#��F\��P#����c�	]�8�-1����IE����z�����M��q�����p!�l>����]���C��/;�7pr�N��3��k=V|�W ����p&�R@UIs�����@0r���_ 6Vn�������E-	R������1l���|U�q�s�{wuB�vH0�s\��-�w��\m���]�Zt1���H$~�)F	8e����9~{yr��M��x�H����x|�	=��Q�o�{\�)���Z�o��8f����ev2N��i���V�y�D>��yP0���������$A�)�$m%�����U���\P9B���K6K9�V�m�Y���!�D�h�?iJ>n��c*d�=�k�c]j��}����l:@p+�@ �����@�����}t2,���]��2�vMO#n�l�[B�w  ���6x���eY`0!�� TL��3���;��`��7����+��r`a�2�7���#j��|����^XC�^sb��9�2��OoQ�k����k�{4��q� ���4�I��f/�>��o��
6	���E�qC����G+�+7����ag���=������M
�o����d�$l���F���2vf�������f��1��ba�,I`&#Q�~8������m����a�����sy�����78w5��+���!�AX���l�� Mr�1�����_��ll���u�&��|�X:��NDcsj��y�2O�k��k��H�D�����
�O1�N�?}�w
����j����y:]x�gf�l��N��t>�|Z�u�����mi��~=t��.���.X�`/��2����y��[���n�t��O�������5=���tL�$�f�D��<|��V��&���
�
,V��6�p�lE��)�e=S�F���7E�n��d(�k�Y����|�r�	?�o��|@�G�c���sgE5��o��,����9[�F���%Ej���q��$=f��s`+-��8��TQ��M�)�I�)��#����X�v%��`�'�N^_��������n�y���6�()��E����J+��*(?�m��Fc8�
3�4�����l�f<����Rh���L�[�I�v���pfS����I��{��_���9���/�� zR������-/<���{��[�m�9�=(����(r+B~A�mut���>O���*�v��!���0S 
}���;�~�j������||���8=����g�q?������q2��N�����Cz���Dq�)J� A�_8 ������u�����K*v�]�2{Y�p�&���w��6�iD�K3�`�P�@i�tsH(�� 4�E��x�D��)E�:.���p�����Gw��Vg6R���b���#O�DwW�y9��X�6�0|�����v��u��o�r���)������4���8�S�C���fZ'B�_�c��mafe[�����mi������M�y��M��W��N��"�KG
��nn�������L���5}�oW��%�������Q����t�]P��UH�a=Ec���������y,��
&�EM�]m���c���o���������5��O��<�4��r���|
����ux��7�B=�b��*���
[Z`�N���$�������y��QDy�)N5.�9����\�I��}��D���<���\V�=��U
H�t�w�r�}i���GG���=v��*"#���>��#o�C��^8)@�i&o��
R8z��?���=��������W�0�~���]�D'?��D�h��
C@�d�Xr;���T��"����d��h��~V��J�<#]k��l�����q-WPB���G�t�FTJ�9�e����HQ)������'eh������Z&R-�5�\������p�����p��%��csQ�$�,�6����K�����`&R�\\����Z�]��-#�NU5���R��u�P��IeS0������I�{�0,y������P������}���z������������61iMv������g!���t��w�9��H����9��}�5�s��6�z����T�7��W�7�]�fw�u����@�_o�4�3:�i�*���_���_o<q���i&������g>�7l�������W5�q%��r�Hl9�IDK ��
	�������)
o~�$��awe	{�3���GYG�kD#@v��3���Ya�O;e��C�n��_X����us�[�w������H�� ���Q�`�a�Y,~�6��h��%(WOQ vD��O�K�
�{jd�L��5�9�l�fJ
�i%��|�(.����v�������e��Q ��_5����>	����p-��Y��E��:��mp� �%����%x))������x�lcr�v�p��q]��O7��I��-���}����(�����7���9��N@�e�8�"���Y���d5�n��g���:\��&A�Y
\�,�������I�	�8S'�	�u��n�J�?~��/�ou5v'�~:�
hu���~4��j=k6�������������oP��w@;�n�K��~�>�m�����:�n�;�����l0����9&S�gg9/p� ����y��`�4�^�5������������.,��9�:�~:�����y.���N�����i7��
6��9�������/] 
�w�|oL���h�Z����&�i�xU����]5��r��W�Zk��Z�v��f���\l'(�>w������� <ku��e:��Y=�T��g�<H�,�^s�$����G���<\p�J�F�>��c���M��J���&�W��Yh�C�F|��������7.����������|w���c�oX�����z'��}����cxIe�F��l�E��p=��Jx����p
wUx��T�clt=��m�YH�,��0�*1�zc���Q��Kb�8��d�F'6����*2j1AF�K���v��g��L��tT�L�<-�z7���m��S"�:���2��V0@����#>�p��d�)y��%�T�ddu��q9��
������a�,61�
��-��+�3n�����m���CI�����gv!c5���y8��u������ I,1����a"��
�������[����p���H�0������������������t���'w���Z���9�~7�q�"�
A��VBq#�)�2.*���l�����<	RvL�����hO���@�npZ�D��&��>��x�8yc��_&�7f6D5@�J��������*����V��K���,��9��<���sM��'������n��f�|(T;;�7LM_'����x�w��t���MX��h�}P����dF6[W5����o9G��z����PY�5������N��51��������7�md��-~
��z�a�F���"9��e�$��[��
$A�cn!H+�$������e���X�P�F���g�<��j�KS���Z�������7�V��(v�.��t*�@�M@N�w��/�gCo4������Q�
|���d�X;����{X���jL�-e+'��-�co8n��n	�������	�V���]�����.�(������[N��a&�����>�gJ�
��j��X�8j�S�s�)�#n��Mx3[+�Opq5�Yl��zG�|���=��%CpG��K&���Du<0#>{���>�8�(Yq���!!�I�E���]kS{=����Q!�4�T�
�:�����}-W��p���,�h���04����b�$C(f|
�.��7�_R���{0�3�Z%��O��3k��P��P��L�|� ����$6�kQ��������$��2�����""}P�H �S�������*��tS��g������D�\�B�E�JP.���JB=p��,��[#�3�R�vwk��D�;�_C<�r(�;�xc �������q��v���q�2�2�
�@m~\�����P��M���Gl
���N�,D������f"��a�]���dV�Qk�v�����lCW���
�Wc�k���V<��$�Z"G�/g�;��5����Oi�����Q���)J���>\���t|x,t�"���.k���Ng��T��UYZ�A��C9�%���D��A�����f���z�����<RH�k��i�%�Qx9V���+����X�JIk�5��l�$r������������*�~��@�J��_�D��:(1
Z}���'yw��Es-zn^�1icr�q{|%���Z�&�:�:�8�$��������O���A{�~����K��b�����Z�PR8q��=P�6�AcLK���ge���7��"���n���RI6���J�r��,�3�|t�������
`�TH�0-�u��H]�|K��O����D�0!�/y�j}������-3����
`7���d���@%gt����en��A�>��/2��n�'���ve�r�j�V�@Jq�(<w��C���������,}��WI+����1���U���)�����*]����8�+;����0��u������������"�0x�D�����bJ�.$�-�v����.W�4����~�{�����{Q!�=�}wzB���M���K|�	(�?�8~����p�9�N�I(�$�w���jy�����������TD:������o�[�:�L��m�iSs���9��"P�K�i,���@z�mf����,����L�A�[���8�(�|�K��O���e�~�%�m%T����4��D���Z�����0�m��o����o��rK�����|8&������:���~Td�S�_]����C��;����v�����v�$3�F��;���`�'�?�4}��=u"9��)����I��@�2D�HLe@�~�Y���f��k`��-����L�p��&j�1	����,�SV����)��%���� ������K'n�@���L!a��]�j1��
���$�oH���8�b���.��X<������6 -8���P�6j���
�����{��+`XHT/y3��|����^�=}}u���_�����������*;Y[?�m�P��w�
�y�
��c%�US^�(��L���W�v��Md����E��9�VM��|�
 i�u�����|�}O�/1j����\��a�R+�<k�8�� �IH8:���������$�fA�j��D��4K���f�){?y�\�d����Vk``Zx��+�8a�~������k�����D�4�v�*hG�-w����R��AD�&�1�}�q���|P����������p�+�8s2h\��.i���k2���g
=S���`�;��r��Ht6�k�M
�\gXfy����v��h)�HBr��(��,9���u�.�99r�������W?�������+�����?~����������N�E��������P����a�������������v�������v��>�}��9=�=��~0L���7p@��^0�'c�����=|���wE�qc�_���� '�����/t�D��M�dBgM��,FQ��0n�w�����
�V;N��������Tr��s��YX��r����p�9������g��\��c1��&�jk7bh3�[ ��U��v[���/_I�f�!1d�E(2�A:Zmo������g�gohH��j�����=}u)C
�k|����Zog�@���J)4I~�U��oM�x	G�_�pP�^�J����C�"�?\����k11��DG���s�^�P�jT�m�
Wa�6!��^�wHZ
�P���>�<�)Y,�a�����K����� :����O9
�J-�
�j5���n�[��@�����"bu�=��{�y5�'��1��
�X�����8��f[����������\k�A�O��a8��G���5�^`���
��8$|c#P���A:5�C�h*�����)�B�k��=F��;����	�j��xW%�S�1�<]�q�GS����[���F�a��(����@�������Fl����#S;���|=�
����W��s�����t�;@z��-U�����N�p4���n<��A��X���\#�&w�����F ��P�5At4B�V�g �0l��R����E�;b>�
�!�g�"��bk$������[�-�������$K��}�p�i~o���_�����a�������Pa`l�	�FN�?��6	��h��f���_�f6r.���g��������+
���MR��F���v�#SW��7*T�E���0����+W�z�nT�}}|��@��qX�x�%����S�&]��]�_���Z@�k?���i,�5f��e��f�g�[�R?>�:��{bjx]��U����S��uZ��"�.��Y&��v�bR���������7�����Q��������O<:������������}���N���������!�(�R��;�b�D�G���5BBDA}�"|�4��3��N<*(4���� �2����Ah��W=�f�0rT?W��R�rT�f:>��_$���^b���n�����s�
�=	��h���U1����:��m�Hf0"����	7X�Z�
j����|)_L����U��s�:$�H�G��}��S%)r�X�CJ��z���b��.4�R��7H0�a�w��u*N}�_��%��,�n��r��@�	%�/�j��a4�&p{m0��^�s�� ���J��)�G���/Rm2��.&�������"6;|fR	��Q�5�n@�����`T����uY= ��~��?j�&�87{��D�=^I�}T9i������Yx,���z����?q�7�To&f7�wA�`�Z/V!��K��?iX���v��Te����M(�����~���]�g���������bx)@��'������H���ZP�g���[`~a��2Y-�����TP�;��3���/�3-��;��5m���U�8�eI:Tt
�X�����\�5j���V@��
���a��%A�	��5���LbX�
]��/.�Qq�A���=�H��R4�����}I�04���G���E1C`������P�-�m�R����XF3ld�cx�^/R��JS}D�U��?�x��:�4��.D��`�"DmU�#�C�3�cu�0������o�nV ��1��NexA�e�p���p�Q�!�V�/_<��l!���yy��!Vz�s&�
�I��/wi�,��
�VSj�j�!c�w�����EI��*-�]=���=.�G�5LrFS�����^�G����u�3��n�+��������e/�of2-�E�Y�L��i��D����s1��2���w���N����3��<'�.]~it�tI��PX~2����%�)9�a2��{)p���du�-�K�c�`Y���G�2�s2X2G��=1���`�G����Sb�qZg�-�z�����lQ(`0��/�)������$�_\�y��&��t{�v��\�?q�C���v{4�����M:���F������(�0eZ�2k5���GTs�e)�P����,
���/y�����w�����,!RD�hF��za�o�I
��d�s=��QBt��V���"�%q^�`�E]tCN[����+I
��-.�N��f�?����'"�|F���/�d�}�wX/��;��-C��zn�����������"BA�+������ [
���{�HCU/7�.2EY�5�G~C������������p���+kf��X>[���a�>�[�������^^�;NJ��m|�|�~4NM������'��v���1���a^�0�zd��k�>JO��^'q�T���C����������7�����.�����"���8!�;�~2���_���;(4���{����a��o��h�H��r��a������gV�Q���,(�������m��)�
�vMx#?�&���.|��I>�������P���LO�U�o&/g���_LT4%Eh��O�m�&�,r��������;�B�T�^�-TI�v����m�|���U���(���Vd$���>=}K��q���|���+�J���H�������_#���>��[�I�	<�d�6&�!/����	g%�]t����hdwN��rh��Q���<�,���l��`)�yDwd6ih#C�4�����@b&���T��}boh��6�Y|�c��g�p�����^�%�)�8���NW����]=����� �
��}���0aP1?	B��e`����HSI��:���mK��IQ��6�� ����3�<0��z�:(����Q$[l��a��{��g��qw�8����(a
���OI�f�6�H�d��C���&��
��g7��	�-��������k8���f�[�s�}oB��u�8���7��@.,c�j�h��,	1�7%G�j������	��m���(�2����u�>���c���Sx���:��6\�4���"�kAL0���������;x���E��U#B��@U�]�:�a���TT^BUa�Z��
]/|���&�m3(Q�����5�0���"b�hy2� t �I��NN���u=�	g�p�b��se���8Y;�!;�c#3��x��@3u�a�gw�}��<P`+���?KpZ�"��m�h<vfrY�8���X8�l�
-�F��d`�����yUP3{+	�H�'�C���gF���g5?\�O3����4u�L�d3�q�<��S��_0���,����G�mO�#o:P�%��)Y��!Gj���_�E}��N���U�o{��]X��h9�Qoz=�b�����HW$e�)Zi�Jz������������.���l�U;*7I���������W_�i=!�D�C};��[*$<��0��m��*m	n(U,��a(����r�&Sm�������5��s{�����`2�����wU����$$�Wl)�%���w�������
�mV4n�,��XK���x�A��n0�M&U�$}�-j�5U;�����oVMyY�<`Q�W���
n6&�4O���FM��v�w,�t��AA����������KHn��!{m��'��}h`���c���8���S�A�?�xM���t��la��P�}��R���+A��W�.����P�r�h�T>�� �z���t��?P��W�3�2�����*��v8,M�
�0@@��c����Q��z�dwYB"�7�-ILI�8����"��k�d�O�o�9`�������S��oqZQ��N��$����_�`1�v�\j� b��]��
*�R����e0V��^�r�!L���U����W��p/��`C(�Q�`�G�h�T#�v������N���*\�M����0���`� ��g��~$�/9�!E�k���L|�k��5mw'�nU���UF���,Q�	���L �?�J�@����9�<�@����8����&)X�DS�������u�|';+��ds�`�d'���$��jd"���E�Q����'U������Q��(�C��{� �U=Q7e����P��'���I���Gl��������������u0���w�6����p����>�S�����'�!�@�����I���Y�Xn�.E��\d|��0�E��=�*�q�|5�P��S�=j�R�A���.����a/�FV�GAx��D]���/��d	�l�3I&����m|������G^*?w}q�G���8��H(.�����U�F�{D�������I��m{=�3�9�<uo8$G~e%���=�$<J�C�;�(
��J��Q`1��S�����}�o>�Gt�X�~9���*O�{>1����!����FD��{�CB�BTj�$ |+�E�'NP��<"��yY�w����b��p��9`:�xN�MB����w�@���;��?z1�Xg��%�a�P�J��X�H����q�"A�%���P1/��e����6���RR[��!�:�2&��ASfDJ�nTFLef�5����E����{<��v��G��5�ie�jH��e�D]�&���`��6��A�=��$���)��t[�����&}6��VS��-[>f�.�-~�����#���^�_�v�=H�9��c����P���;���O�=�s��;n{��x:�w�}��A���/��?�2-�L���U�2-�L��`X�	2����Pu�R���p��r�X`}����2�
0���������X?g��cjj�*�0�|�eT�ScA
~�c!�$�mIq^u�����3:pf��rt���1��a�E=�P���Q�G�gB��y�QBkm��g6F�|5 #�AS%�N�ep�[��x��aq�1SwIUt��������hT�e<�A���1jH�>���w��L-��t�#�=�W+��b�o]�V��U;�J�8&*��S2�O�I��y��E�\�F�b��V'�2e�f��*>�(���9����c?k*K�m:�����(���M�I�Z�B)c�����\�������]m>��A��+���r��Q��o����n�2���ZGg�}�r��`��^���V���z�'3`����x����qVUO�e�E-���z5<�5����������.A�����F)����/Q�9���m����Lo�����������(pv����`]�%�n9���Q�n(�@#�oMf�'#m��L.��W2��0Z"�udT�<TEv��@���D�I�!�E%�������I�S��I��t]a�5�K'H
<=9�@+Q��O�i:�������'�����XU6�B�l����z"�6�&/]n4�q��.j��'=/���L�nV:mQ�A���J6������o^�}{������\�S�l�@+�-KRb�����{�V�bp%�:�r����Iu������y��LWB���k�kQ6)n(��<�t���u.����������:����B���{�l����.�Ze�/�g��k����U�lU���B18=�����(N)X��:8#������8pd�w������~�������6[*c��O��F;�n)��#R���������W��._�|{|���%l=2��M�4|�,\����gp�\Hle�j6'&�h4�LU�)/���Y	M�	 � ��-!',���G��{�>���8�b"��DJ�}6{n�`>�-:�
@
��L�����!��u,��'b6�{��jgr-	��sh�;��;�a<� �q���%��n�<XbHh+Sj�!�p�����X�������N���k����C�?��������z��?��#o�t����v��!%cg<����J�7��l1��fe�&��jg�[bn�����%�)t	���Z�s��-f!pv�K��1���W�L<
G�F�K��?��C�#��y�hf�m�`�zw���r_������dF�
�/��S��``��SP��;q*�,Hb+*�>>��A%cV����3\6�n�Ld.��6=���pG�C�	E7R�����	n��Z3�2�H�T�������V����v5^�m��J,lS��E��w3�x�|yw<Gy�-�4��`4<�`XO�2u5���?2����@+v����W�[��c��Vhr���S�j|W�{��[~J�B����d��n�J{K�-s��^\_'���)�cV6��$�*�H���`[mZ�0�r���9nQx����5�9���`�c�����S�}Jp��$���5/I��g�{��U��[����W`�	�� ��������6���W�1m}L���?��St?��Z��9� �}����|
{
�hN��E�����k]Rm,�>�*�%��/bq�u5�^Z��Q��%iN|�y���A�m��S,T�SB���'����5�
����{#�!W����{�H��yb�;*�`:(�O�5�6��_�`}H�WZ��Ye�!���
���������C<p�2�lp��{L�[o�^)�k������2�Z�������}�1F���0�!��'�ar<<Yh���V�	�������Q���������X[3�X��S�xj(���
�e,qg��C�"����Kt�i$j������������A��F��������l6h��)Cfj�^���
�d�	��6�N��;�ffE���J+�����m���^7���grE-I�:��o������+]��
(��>��ru�q(t;Y��@��>lPd�(�&�EP�b��#FntQJ��v����
��"AsDR���M�&�l
������j:^�9����$�	<c.��<>f��T�8�r�k\h��c�M����H�����1����i��p{�`��m{:�
z��p{��J���`�iw���oq� #H��Y��������W�����
6���z�"g�J���'����-���Z�[�'6HiWt�V?��M��#���s����Q}��������g����^���r�8]�w������AeSp�����<���.�Dk���G��������D�.T@F�BI��^�s<�����i�J���G	�J+2�{C�xyF��	�!lT���?�'����E�L��]���#��O��AD����������kE�J����
�J��W�(L��x~�J��{��tgx�r��0�p^-�����t@���K��t�a�J�������Z��7�EzuCf��7��>�n��C�X�PI�o�hL\)��-���T���I����#���������r�U�[# ��rL����#�>�����WS�~��B]TY�#)�L�+!�E���(R���o��`�)���
�Yt���>�l,��F��o�Ew��������3�j��~jE|��K���Z�mc�����q�y��O�:� ����!r�-����6!d�� 8
���R�zPn<��'�Cs����sL;,�L�5��q��?�%h���b
8=�L�'S���T,��6�T��lm7;�bC8����]Wx�����H�����n�a��fg���r�d�����"������[���!ZO�5�����4�Q��U	���y�'�ZL�"���`7��9��u�8.�5��i��2��(��*M���3�/�L��;�L�����,rZk�VEa�;��,�8f���"M����0����:���0f��
�H��^�	��<�&����4~��J,pWd7S��&���}T����
*�]�dQs#R�QQV��K����o��n��J9������A�����e���J?�d�x	$�-5�0���d�L:F���)�4���a��������o6�W������Qz��~�����"k������f�EO
��'��c�i�w�.�S��k����
���'��+�����9�����������]~���{��IM^�J��9Y��J�-:6b�7���#c��-"&4?�yf������$���}j�Al�p�6$b���~��ht��F��f�����2�Z
���|)�<��j:����86U�TUh�P�v��j����I����x�'�T?�y6�m��n�^�y�x|��a�s��Q��)zN��7����5�gL}6���;r��f��~
#�����T��d�NK�,�r��fm�3j��AUt�/����Ty����j����l�=�L#w� l*��%i���?x�:W{Xp���/��V�&���M�fW��|�lv?E����m0��;���%r~��:�-����`�xaW��@�<���_Re���e<oh'��K����xJT��YMF�J*;����e��IZ����r��q�A�x���G�n������h���9����J�p�f����k�V���Q2���]�#�@�KS��*6�����	�52�{�p�RS�����
�L�#�u~����:����4g���
�!��*Y��b�9+m�S%�� \��:����Hb��J�+��9���������I=jop�sQ��-w�*��J���Zw���~{1���F���_�^�� d��"���hFtD������{���<�����x_\q���;,�t�p#���u�\>����~��J��
`���y	��m�*�����~��GT�	���t�E(^�c��*8�-9����N�t����,$���/:������: ODY���{1����c\�XX�}� �&�f(��,U�6?VqI�� VFj����Z�8��T��|'��m���=�u����4�6����R�_�b�*!g��CP���a�����;������&���(�	[o6�$����c��?��	�S-���/<��k���zo@��b*�H(�����`�6��`��t�O���'	G�Z���r|���"�9&�o����~����P���Oh��6���iv�=Eh��������
�'z���,3���Q4oAWi�X��)��/��4��V�Df�+��xsu����������o.�Q�d�YD)��m$4��e�'��l�F+�������B_����,t-~�/P��@����8���XM4SY��	�r������o��;9w�N8C��L1|U�W�-% ���������eai<����hqtT�.��XCvP�7\��[#lq�_�L}�B��UT�Y�)���Y��bj�a�F�k���k�|:*�15��@o�/��^�����N���6������<���e��t�u�>F�`�' ,L�����AQ�2b*+f/cr&�O�������:r���*���SU�vZ�?4�|��<��`�:��P��?q�\;��e�(�v�HA/,��b5�_�LE��)?7,��gX\�a�������������>���%0�\F����_e�d1���S��J����G`�t�^S+������{%�a����XvN�^�~�z���b�Z	T$,I�{%b\�����^y�-�������'52�+�Kx\��G�vc�W�#�/�D�nD��v|�-�<5�jF�
�H��������y�<~?���������y�<~?���������y�<~����9�iP
#27Andres Freund
andres@anarazel.de
In reply to: Amit Khandekar (#26)
Re: TupleTableSlot abstraction

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

The attached v11 tar has the above set of changes.

- I've pushed 0003 - although that commit seems to have included a lot
of things unrelated to the commit message. I guess two patches have
accidentally been merged? Could you split out the part of the changes
that was mis-squashed?
- I've pushed an extended version of 0001.
- I've pushed 0002, after some minor polishing
- I've pushed 0004

Greetings,

Andres Freund

#28Andres Freund
andres@anarazel.de
In reply to: Amit Khandekar (#26)
Re: TupleTableSlot abstraction

Hi,

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

Subject: [PATCH 05/14] Use tts_flags instead of previous bool members

Pack the boolean members in TupleTableSlot into a 16 bit tts_flags.
This reduces the size of TupleTableSlot since each bool member takes
at least a byte on the platforms where bool is defined as a char.

Ashutosh Bapat and Andres Freund

+
+/* true = slot is empty */
+#define			TTS_ISEMPTY			(1 << 1)
+#define IS_TTS_EMPTY(slot)	((slot)->tts_flags & TTS_ISEMPTY)
+#define SET_TTS_EMPTY(slot) ((slot)->tts_flags |= TTS_ISEMPTY)
+#define RESET_TTS_EMPTY(slot) ((slot)->tts_flags &= ~TTS_ISEMPTY)

The flag stuff is the right way, but I'm a bit dubious about the
accessor functions. I can see open-coding the accesses, using the
macros, or potentially going towards using bitfields.

Any comments?

- Andres

#29Andres Freund
andres@anarazel.de
In reply to: Amit Khandekar (#26)
Re: TupleTableSlot abstraction

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

The attached v11 tar has the above set of changes.

Subject: [PATCH 07/14] Restructure TupleTableSlot to allow tuples other than
HeapTuple

+
+/*
+ * This is a function used by all getattr() callbacks which deal with a heap
+ * tuple or some tuple format which can be represented as a heap tuple e.g. a
+ * minimal tuple.
+ *
+ * heap_getattr considers any attnum beyond the attributes available in the
+ * tuple as NULL. This function however returns the values of missing
+ * attributes from the tuple descriptor in that case. Also this function does
+ * not support extracting system attributes.
+ *
+ * If the attribute needs to be fetched from the tuple, the function fills in
+ * tts_values and tts_isnull arrays upto the required attnum.
+ */
+Datum
+tts_heap_getattr_common(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+						int attnum, bool
*isnull)

I'm still *vehemently* opposed to the introduction of this.

@@ -2024,7 +2024,18 @@ FormIndexDatum(IndexInfo *indexInfo,
Datum iDatum;
bool isNull;

-		if (keycol != 0)
+		if (keycol < 0)
+		{
+			HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
+
+			/* Only heap tuples have system attributes. */
+			Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
+
+			iDatum = heap_getsysattr(hslot->tuple, keycol,
+									 slot->tts_tupleDescriptor,
+									 &isNull);
+		}
+		else if (keycol != 0)
{
/*
* Plain index column; get the value we need directly from the

This now should access the system column via the slot, right? There's
other places like this IIRC.

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 9d6e25a..1b4e726 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -490,54 +490,21 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_INNER_SYSVAR)
{
-			int			attnum = op->d.var.attnum;
-			Datum		d;
-
-			/* these asserts must match defenses in slot_getattr */
-			Assert(innerslot->tts_tuple != NULL);
-			Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
-
-			/* heap_getsysattr has sufficient defenses against bad attnums */
-			d = heap_getsysattr(innerslot->tts_tuple, attnum,
-								innerslot->tts_tupleDescriptor,
-								op->resnull);
-			*op->resvalue = d;
+			ExecEvalSysVar(state, op, econtext, innerslot);

These changes should be in a separate commit.

+const TupleTableSlotOps TTSOpsHeapTuple = {
+	sizeof(HeapTupleTableSlot),
+	.init = tts_heap_init,

The first field should also use a named field (same in following cases).

@@ -185,6 +1020,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
{
TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);

+ slot->tts_cb->release(slot);
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)
@@ -240,6 +1076,7 @@ void
ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
{
/* This should match ExecResetTupleTable's processing of one slot */
+ slot->tts_cb->release(slot);
Assert(IsA(slot, TupleTableSlot));
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)

ISTM that release should be called *after* clearing the slot.

@@ -56,11 +56,28 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
HeapTuple	tuple;
shm_mq_result result;
+	bool		tuple_copied = false;
+
+	/* Get the tuple out of slot, if necessary converting the slot's contents
+	 * into a heap tuple by copying. In the later case we need to free the copy.
+	 */
+	if (TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot))
+	{
+		tuple = ExecFetchSlotTuple(slot, true);
+		tuple_copied = false;
+	}
+	else
+	{
+		tuple = ExecCopySlotTuple(slot);
+		tuple_copied = true;
+	}

This seems like a bad idea to me. We shouldn't hardcode slots like
this. I've previously argued that we should instead allow
ExecFetchSlotTuple() for all types of tuples, but add a new bool
*shouldFree argument, which will then allow the caller to free the
tuple. We gain zilch by having this kind of logic in multiple callers.

From 280eac5c6758061d0a46b7ef9dd324e9a23226b5 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Fri, 31 Aug 2018 10:53:42 +0530
Subject: [PATCH 08/14] Change tuple table slot creation routines to suite
tuple table slot abstraction

This change requires ExecInitResultTupleSlotTL, ExecInitScanTupleSlot,
ExecCreateScanSlotFromOuterPlan, ExecInitNullTupleSlot,
ExecInitExtraTupleSlot, MakeTupleTableSlot, ExecAllocTableSlot to
accept TupleTableSlotType as a new parameter. Change all their calls.

Ashutosh Bapat and Andres Freund

This by itself won't compile. Neither the tuple table slot abstraction
patch would compile and work without this change. Both of those need
to be committed together.

I don't like this kind of split - all commits should individually
compile. I think we should instead introduce dummy / empty structs for
&TTSOpsHeapTuple etc, and add the parameters necessary to pass them
through. And then move this patch to *before* the "core" abstract slot
patch. That way every commit, but the super verbose stuff is still
split out.

From 06d31f91831a1da78d56e4217f08d3866c7be6f8 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Fri, 31 Aug 2018 11:00:30 +0530
Subject: [PATCH 09/14] Rethink ExecFetchSlotMinimalTuple()

Before this work, a TupleTableSlot could "own" a minimal tuple as
well. Thus ExecFetchSlotMinimalTuple() returned a minimal tuple after
constructing and "owning" it if it was not readily available. When the
slot "owned" the minimal tuple, the memory consumed by the tuple was
freed when a new tuple was stored in it or the slot was cleared.

With this work, not all TupleTableSlot types can "own" a minimal
tuple. When fetching a minimal tuple from a slot that can not "own" a
tuple, memory is allocated to construct the minimal tuple, which needs
to be freed explicitly. Hence ExecFetchSlotMinimalTuple() is modified
to flag the caller whether it should free the memory consumed by the
returned minimal tuple.

Right now only a MinimalTupleTableSlot can own a minimal tuple. But we
may change that in future or a user defined TupleTableSlot type (added
through an extension) may be able to "own" a minimal tuple in it.
Hence instead of relying upon TTS_IS_MINIMAL() macro to tell us
whether the TupleTableSlot can "own" a minimal tuple or not, we rely
on the set of callbacks. A TupleTableSlot which can hold a minimal
tuple implements get_minimal_tuple callback. Other TupleTableSlot
types leave the callback NULL.

The minimal tuple returned by this function is usually copied into a
hash table or a file. But, unlike ExecFetchSlotTuple() it's never
written to. Hence the difference between signatures of the two
functions.

I'm somewhat inclined to think this should be done in an earlier patch,
before the main "abstract slot" work.

Ok, gotta switch to a smaller patch for a bit ;)

Greetings,

Andres Freund

#30Kyotaro HORIGUCHI
horiguchi.kyotaro@lab.ntt.co.jp
In reply to: Andres Freund (#28)
Re: TupleTableSlot abstraction

At Tue, 25 Sep 2018 16:45:09 -0700, Andres Freund <andres@anarazel.de> wrote in <20180925234509.3hrrf6tmvy5tfith@alap3.anarazel.de>

Hi,

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

Subject: [PATCH 05/14] Use tts_flags instead of previous bool members

Pack the boolean members in TupleTableSlot into a 16 bit tts_flags.
This reduces the size of TupleTableSlot since each bool member takes
at least a byte on the platforms where bool is defined as a char.

Ashutosh Bapat and Andres Freund

+
+/* true = slot is empty */
+#define			TTS_ISEMPTY			(1 << 1)
+#define IS_TTS_EMPTY(slot)	((slot)->tts_flags & TTS_ISEMPTY)
+#define SET_TTS_EMPTY(slot) ((slot)->tts_flags |= TTS_ISEMPTY)
+#define RESET_TTS_EMPTY(slot) ((slot)->tts_flags &= ~TTS_ISEMPTY)

The flag stuff is the right way, but I'm a bit dubious about the
accessor functions. I can see open-coding the accesses, using the
macros, or potentially going towards using bitfields.

Any comments?

Currently we have few setter/resetter function(macro)s for such
simple operations. FWIW open-coding in the following two looks
rather easier to me.

if (IS_TTS_EMPTY(slot))
if (slot->tts_flags & TTS_ISEMPTY)

About bitfields, an advantage of it is debugger awareness. We
don't need to look aside to the definitions of bitwise macros
while using debugger. And the current code is preserved in
appearance by using it.

if (slot->tts_isempty)
slot->tts_isempty = true;

In short, +1 from me to use bitfields. Coulnd't we use bitfield
here, possiblly in other places then?

=====
Not related to tuple slots, in other places, like infomask, we
handle a set of bitmap values altogether.

infomask = tuple->t_data->t_infomask;

Bare bitfields are a bit inconvenient for the use. It gets
simpler using C11 anonymous member but not so bothersome even in
C99. Anyway I don't think we jump into that immediately.

infomask.all = tuple->t_data->t_infomask.all;

- if (!HeapTupleHeaderXminCommitted(tuple))
C99> if (tuple->t_infomask.b.xmin_committed)
C11> if (tuple->t_infomask.xmin_committed)

regards.

--
Kyotaro Horiguchi
NTT Open Source Software Center

#31Tom Lane
tgl@sss.pgh.pa.us
In reply to: Kyotaro HORIGUCHI (#30)
Re: TupleTableSlot abstraction

Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> writes:

At Tue, 25 Sep 2018 16:45:09 -0700, Andres Freund <andres@anarazel.de> wrote in <20180925234509.3hrrf6tmvy5tfith@alap3.anarazel.de>

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

Pack the boolean members in TupleTableSlot into a 16 bit tts_flags.
This reduces the size of TupleTableSlot since each bool member takes
at least a byte on the platforms where bool is defined as a char.

About bitfields, an advantage of it is debugger awareness. We
don't need to look aside to the definitions of bitwise macros
while using debugger. And the current code is preserved in
appearance by using it.

FWIW, I would expect a change like this to be a net loss performance-wise
on most platforms. Testing the contents of a byte-wide variable is pretty
cheap on any architecture invented later than ~ 1970. Testing a bit,
though, requires a masking operation that is not free. I am not seeing
how making TupleTableSlot a little smaller buys that back ... we don't
normally have that many active slots in a plan.

regards, tom lane

#32Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Andres Freund (#29)
1 attachment(s)
Re: TupleTableSlot abstraction

I have only done the below two changes yet. After doing that and
rebasing with latest master, in the regression I got crashes, and I
suspect the reason being that I have used Virtual tuple slot for the
destination slot of execute_attr_map_slot(). I am analyzing it. I am
anyway attaching the patches (v12) to give you an idea of how I have
handled the below two items.

On Wed, 26 Sep 2018 at 05:09, Andres Freund <andres@anarazel.de> wrote:

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

The attached v11 tar has the above set of changes.

- I've pushed 0003 - although that commit seems to have included a lot
of things unrelated to the commit message. I guess two patches have
accidentally been merged? Could you split out the part of the changes
that was mis-squashed?

Yeah, it indeed looks like it had unrelated things, mostly the changes
that moved the slot attribute functions into execTuples.c . I have
included this change as the very first patch in the patch series.

From 280eac5c6758061d0a46b7ef9dd324e9a23226b5 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Fri, 31 Aug 2018 10:53:42 +0530
Subject: [PATCH 08/14] Change tuple table slot creation routines to suite
tuple table slot abstraction

This change requires ExecInitResultTupleSlotTL, ExecInitScanTupleSlot,
ExecCreateScanSlotFromOuterPlan, ExecInitNullTupleSlot,
ExecInitExtraTupleSlot, MakeTupleTableSlot, ExecAllocTableSlot to
accept TupleTableSlotType as a new parameter. Change all their calls.

Ashutosh Bapat and Andres Freund

This by itself won't compile. Neither the tuple table slot abstraction
patch would compile and work without this change. Both of those need
to be committed together.

I don't like this kind of split - all commits should individually
compile. I think we should instead introduce dummy / empty structs for
&TTSOpsHeapTuple etc, and add the parameters necessary to pass them
through. And then move this patch to *before* the "core" abstract slot
patch. That way every commit, but the super verbose stuff is still
split out.

Done. Moved this patch before the core one. In this patch, just
declared the global variables of type TupleTableSlotOps, without
initializing them.

I have tried to make sure individual patches compile successfully by
shuffling around the changes to the right patch, but there is one
particular patch that still gives error. Will fix that later.

I will handle the other review comments in the next patch series.

Attachments:

pg_abstract_tts_patches_v12.tar.gzapplication/x-gzip; name=pg_abstract_tts_patches_v12.tar.gzDownload
��L�[�]{w��r�������%��7��7J,%��lW�s�sO�K1�(Yy|��c�$@R"c�mx�5E`1�3�����"���1	B�0�q���3�����{���3������v��������z�n��n����������}�Ah�Bllg���-�?~@���X�������d#p��a��oO��l��0�~c�t�����a�����y�\82h��Tp��-����$�o�p�����/D�S�����|o.L���V_u��ak2hOz��3�[��p8����=�q���Z.�>����hJ�H��8�������Z��k~7?D���.�f����&M�����6B�B���u�o���C�w_t{/���z�V�z9�Y����w'7�� Z����$��)b`
���)�"L�Z���po��/�o`S1�|��X.`d�{+�	�72hX5��[��1���g�9�')|���@LAt���d�<��������K��h4�"����a~��ud���#��s�f�X�H�i���>
����%������p~���%���g����d4�jl�����9S��h�\��{hOBU�����p� 8�`[u�0�>i��������#�J��Z���T4� s�h;N�kW���`j��R6��Iw��L`��~�����*�o�^��F4���@h��7�T��aU�Cq%���N�v L�g)�7��B]������[��~
��M�tTm��mS�	.�U����a�U#����)���zUT*P�v�.�u1�<GBK�9��_�]o��`���.�#�{U�
`��v4������y�H�'������=�y�[x�n�Mc	j�_����kH���74��Y<�aI��^�	����rAn�l��2
f��A����i8����e�mP%!��!�i� �;���Q�Y��,K��I����0|����������F~��JN�H)����c����"+
�����Qp��?��o/�T�L����*���4^)��N���Gb8���!J-�Z�����a�E���!>��!�����6������<�a�EN�
�U���Z"?�H7:m�/����$�;`��;��Z
���/�@�d�2\{�����x�����������X6�Z�w�_2�co���)h���4������?�v?A/��������(�8s�,#q;�d���������$��1Z5x��e����*���2X�$%��J��@�� G��@@����^����q�k����������Ovl����!���(�w8(_6x�n$�I�1o�i���-�g�����}}�d"�0]�m!p�7��d,~���R�rQ���F���gY+�S.�P�X����8fYvG����@���9R<��t���+r�*�
Q^(��f9��a�� a.}0��j2��P�������qSK�Q������z��Lb�tB��RF��1WX���|�9��R�d��D���:oko��}�f `����02%#p=��!�Q� ���B+It�����e@�Z]+���8&����o�gg�Qv��<�B���0�j�
�_�qR���G��H����q�L��2[��Sr��RGL�
n�z��/�9�4@�`�8��x�����+������i�����,E���C��O3D	�da�?�4d�W8`���K��1^W<p�p�gkr!} ����w[;��z{U�L�u�0r"+#cx��~��4���i�����
�yf��������H�DUS�:R{�����
�)uL�0��a���~�9�����*�E�u��Q��`F�J�tC�?�9Z	��v�������jkS�n��y�����[����l���W����k^a��LZ�Z��:B��{�����!�	�#o��T�S�98h�aZ4Ja
�
~�4I#M��D)$�!2E9_�j��)Bc�>�~v��������T�"^��d�A#����'"���`� |g��r� ;4����Q��W6��yJ`J^D�@�F�#i�#�|�j|xV�{�D
p��������������
��wp��Xn�Y���OL>�!&��$S
Qb�8�Yx=i��w'��������V"�%��0����H^|-1drL(��
���}�s������,��
��g-�[,��
Y8�M&D	�Qdxh3�tQ.�����";T���L�<S�p��"���a�	�H��=S���k{Ob���<�A�����n�<U&�'�������>`.oJ2�t�{5��\�����
t�*�9�	�(�r4�90��.�)�E�h��N�o.��Q�{#�xjY�o�`�I�G<&&@,jB���KGb��K�H�?]��mL���������H-���68t�g��_aF�2��+�W/�^#����#���y.4�CP.���&b���X��l��H��kSS����@��D�5���
���$���>���a;��@���Y!+k�Y)����]���S�:W��6�<�WB1ly����U��28��L�<���'�����
�k��]���+��'�N[Ca�4�Q���L�8[*"����%"�<�1)m)�D�N�����,�2@3*�@�,]�(^��ln�M�}��5��	4�����b*�����R����B�yM�_���x�������=�"Lr�p��YU[i�r�t�U2�r����~�>�ca�� !��-n���B�]�b�!�~���zXm:F�];����XP;���PbI,_���U�H�p
2�'�S!x�2�����^�i9O���*^g�d\-�L�'e3r���&=��U5d��=j}��v]����>���3��>��>��Z�6��h�3^�n}F{��L�Ij}F��x��>�=f}F{��LQ��3�� Z�� ��x}&��~�g���3���mu}F��w\����>�UHt���Sn#S���Q��v��k���k�T���W��o��:��\���Z�g��6#�T�'o�Eu^{|u^+���Eh?�:�U��T�����:���:��r�����R��v����I��q��b]�V��j�-�h[V�����:_�MQu~��yiE5���4�������nr��<�/��.�y-�����{/�ym��y��:���:�=�:���:������i��\�����Q���V��v��������.���:�{cu>�����Q����"JQ��T��r�GU��]��ES��T����d6���������Y�ju^K���vyu~%�{du>�����(�&��\�������V����ym�+�T���|>D�^��6T���d�:�=�:q_R�'�%v/�6���Y��������Z�_�a���*����������jw[��R�z*I)~};:���{B�/�~
��p��a4�Y1����1�����T$�ejE�_�SL�l�FU��t���HR~\@��B9��MnJ������d5���+B�u�qT`�EO�n6=�U	f5������w���7'����\J�Vtf���BY���Z��lv����AY�U���m��N]�
���)�Q@+gX=C	��za�.�
�����~�%�
�o#����C��V�����
e�T�W���?�?��\�?�������w3���?"i:����KOH�Z�������"�]�}�����f= �*,�C
��q����<��9D�m8������C�����onN���k�B�����V���\�_�O��p���x���:�-�BH���Ji �s�����o��?���������~�u��S|���d���h�2zc���QR����&���n���at������#��kC�nN�w��o�ZzG�,o�p�E{��7(;����L#S(db�"B&;=��j��AEUI���Fw0�|37��H��N�|x���2*�D��r�?�RH���!B�L����2\�T�e�b.�j�����8i��e\h6g���Vs��,Y��L���/��O{���xD�m}^�_���s=K���F��x[����/=H�H�t�����vx�8ws�~��^18B7=�
��Ot�VR����{vD���C�A���}Zz��qx�5���>�ixu���M;�A��)N������-G���SNV�T"N��d�����R���g��6�$�����5�}�6$�gn��cU�;�����������;�*tH���I
MY`�&�h�`F��\d�M<���z2�����K�&s�x�����'��{��\���0���\���k�a�"�v�fs0��J��}�zK��:h
����K��Y�%��K�R,���V-�� ����PA��:F#�7����i�����1�L
PJ��K��q-�������L��R�o�_�>�:=]���M� .�� �T��4�������:e�����$w��Gi����z�r�H���
��GT�w�%�R�=��;r��a��d�[s�5�
~K����d���7�m���a����
9�a_��/c��55����(�hk��oH�B`l�3����rp��9�3U$��c�E���*�^��Nn�\`JeD��p%����fnP�,����]V��{��v{����-�aV�^���P����d6���rI��bq�|�i�E�Bfk$�k��Bi��U�e�S��3��aY�(�d%����yc�h`�P�!��p�mr�}�*�>Eo*	0��(4��i�X���}���c*��������Ov��kT�4|���<c��i��0��:�!~+���������\A.��<����M$�:�v�`�M��g��f� ���&,P5��,*����$��;�l'��Cv�X��H	���/��BS-�B���RVE�nm$�D%��e�K�K.����M��>�B����Z,�%�8�	����P��P��`���}LjV�����n�]�)v����4��z��"����$���$���d��� �v�O�����)o����Jf�_
tz�(j��o��TfQ��V���v��Hz�+�	�(�@��@��X@1pS��]�(����P{v�O��)5�<��������R��)E�z�x���`�������g� �4���������B#.,8�X����k�:#�r=�!i/�#�/[�]\�R3�4�+g�O���������\DA:�-)x��,�u�b*��X&�Q��Ao����vGl� L�\FL���
B-����I%`;O�a��BT���]xh.64�':S�L����;�U�31����
��|����> ��)�g���������1�r��#]��3�W���)[+g<:�������I��A|^]Zt{z�R�4��L�U�e��{��x�@l~�;�T�-5;�����|)I�����M��A]���u�VR�j����<���K��	.��Z9������L@4S3&�+K
Y����"�DY\A�u�����h��g�����j����x���d����`vi�o��?E�����7��T�L����j;B���};�����&���-|�r����y���w�d��e�a�+�eS���Q������.��e���Z1
�aw�i6�a�Sc�������������7\���/|w������a
�Qo 1no�� )\�U��eHr�D�4^���r!���9�r��ON\s6y��:	\��x=H��g�_Kex����M|(:�z��@��WU�mw�TG��Thv��g*��9��p�B��N�[*8Kj����)K�(K�\�k��!k��J����B�������zs��{|O��ow����o<g���Hw���;|5���8d?"�15{k�'�$�����7���'����E8�J���]\������R\I�N�~/C���j|�.�������|w�d�v��k`���lZ������ *������!��Vj��z'�jW������vE�C��H�����|zg>�#�����q�tx\|���y�)�����=�!!���-
h�,��N����8R��}~/{�oa���g(��ktk�TO0E��.m����$����M�JFuqv~z�������w�7'�^�^_���=;��g�jb%����]6��V���Tbg'������q����K|���Y	��+��(��$*$e'�l^<�����@4w�����uO��0 )���6k���������72�S6���������k5�H'����`X!�M������n�2�'�����������=���Da^���}�y>���cJ�T�	�b�f:�z��z���w����r�ic&����x�����]��l(k��)�E������T�C@_��:[}��P�`�6t�+�������������N�g]y�/��;�0�R���oN�
P��
[�P~������1"��?�l�O�����q �A�)b��ATS�����r����3C%��������,o��a�\<N�S�������I>�Iy�j���A�''g�g/O��oN._}{q������M�"���5��o����bo�f�k��J��D���Y�P�������7����N�%b�1
b�V��]���Cx�,fU?hq�t9��(~�_"T_l�!y��T�p���J��o�J6q��
���c�q���,<k��TKN5X����3���n�r����_���E�Y%���V���u�T8k��L}`�R��Nf�tU�I��K�����",gp��zI< ����4g�He<��:��8)�O1��<"�����s�)��2���9I)1���%C��S�� ����>]�d	!)�f�A�����.���sA��B������t)Y�X�`�i�&\.
Ub����Z���"����8�Zn�T��������9si9Z��ip�i�<������N������Np��	���33y,�W�Wc�w�����{6�qIc�4�����
��k4�i�~�5�Xlo��4�W�#5�Ky�:k�0� ���w�������6t�#����<�h�zog���mx��Ik���
����[PzH#q�C���zen��2��������.Z�v����QA*��{J�h�)>.�	�7��L�l}0�t�����g[=�L������)����E4���h��,)��k���W�R!�6��6������
l�N��4�xY��\�W�z�v��	���c�����_��Pm;���
����?}w���\�������H��2������F%��q�[�����h��3`S<�6E�U��u��x����}�z�HmF���[
�Mp������}��(O���9� ���DMVr���*���)����/�����p9�8>�O����~zAw|������i�NZ�yP�Oa�i��c�w'�dt��W9�3y����_{����@�^�Cb*���NC!�����e4�# �'��4�P��Qg�@p�D�"�.�%��U8X
V�h�ni� �2�v��,�m����4X+Te�������7+����O�yfTKb�$��E���6�X�WM�2�����;�;3~�h�j���1��'$37W�|����:8���v��u��/
����pv��Xv�w���U|��
.Zt�k�c_)���9������*R�;-����@�����f��$3��D&:��]�*�j�:
��91��+-F�5�>�xu~���������������x���J��r��t�����(o��y�P���������d�3��}�m�V��&��2b��3�	i�G��f��2>�BO�?950���/�|+1#x������)I�L�a����	�f�����u=��X~:lhsZ�����C��Y5�xT4�����Q���0ia����:K)�`��XX�&��"Z�S�2�����������iuw����`VHA:mFe�����0KIM�2N���L�_�� ������Y�d�x�|{|1���_/N_)�J�)��%#B�c��"��fB�d�:���N���:Z$�����C<�K^���~�*U�RL�j^��DF�Lo	��-;��''�]ar�� Jg�����S?����S=�c���8����:�jG��V�����iv����?��(��h�y��Qg4�����h8���Yo:�u;�Is0ku��Ng��E�q���.�O������I}���ty��9]��0�������OJ�$���JtX���?D�/)Vn0N<T�s9y+��,�*�t�R�Z%5��?�$�9,f���c�9��X+>		i�*1yV��I�����D�.Z$�FG��A��/��#Fs>74��3��~7;�
. �D����j��>6�n���6��q���/��}m0G��M��T�g����vg��q��P�qJ�*CE������Y���E�
7�s��N:�#0����(G}M�����Em�&��u�O6�:a7���l`�T.q�L<dK��M���k,v=wZ
���@�J���-��gl1:8����T������a�B'����
fWQ3j8m��
>�9Wt<FM��I�P
�qVpbz�����W���qQ�^�mg<gs�=Q�����Q��^N���Qkg|��|xt�*��+ >�����������`3/�W�E����>�d��c3�p)�A9�jq��������)�0I��	t�UD-���k�`�7�J&�v?:x�U�~�e��Cj@yZb6b�E�KRs���6�nYh%.?���<d�`�d��|����_�Z�S��)\�<iJ��P<�Q�r�������;��R
DTf%��Sp4������A�8���e*1�AONS�(�b2���2���T��������n���a))�b�*���X	�z����T����|�o\5�O������n��#�!�z$�##?�ag��!��
������U�C�G<���A�D�]��x�ec��Z�(X�a��N@����\���������`{�B�p��
t5NVI��M�*��0��H��)�ks�W[�\>Z�Sz$�5����X���X,�nt�/����,��1���m!q�5	*�&e�1q��-�+6���(hEK��0D~�,'q�Q�k��FE��vKt�t���,�D����s���p��+*�=@t(V�[���j �Mr�o�����~tT�*�,�P��Ac�Fc�lE�3���s�5Y`�)2�c�+�&)����H6b�1p$�����j VR)���b�����4���������;����r�� ZQ��R������i9?*��3U�x<�n�/:h�9J�E��`������T�-�Al���2s�������c�L�I�v��]]�k�K'���\�V�$X������_���T�S�f�0�lq�y�Ap��}���0�l�J���C�D���V+����I&k��������I�V*Te:���A�1kw&�^�4x�q���LK���8&��^j��1�j8�c����7��k�[�����:�)��]-/�fZ�z2t���h�>QL<k�'Z��,��N��1�)Sr��d��&�n��q'�gf��4/��\]�VE����������.���p.im��-g�|}s��,�L���c���R�o������SM�|��$�=Un��A�?s
4����`�d��~�9�9lO>�'F-W���	]��{�
��+ZT��+a��t���S��3lQ0�#��RIF(������F��T4�Q�]bO#k7$A�����JDg����@�H=���m'K���lV�`�PQm1����w/����Xz<	���9~syr���}�\��G_�������B�Bp��M'���hx�f�����z<F���(���P�?�d���cMD`Qs���^��[��7>z����U�,j���5����dW����1��jI�O�/|)$0e�����~&���l�H�qv�N��?M�o��)��eh[���l�n �����`�i4F��`:(H��1D����(q��Lj��&����,������\�LZu������T�a���z����������1B?�{���oXj#C%���E}��0g�7���%%�C���t�kQ�Dq���lT�/����;%�Q�r#��e�9���y��l4k6�����eT/+���F���5���-#7���|\)���������(���5����5�����dH��>��H��Q�������
�)���]�o��`�����[�sO����o���U���gf68�
�	��` �����+����V��~�J�;�����<�NJ����~F��G���
$��E^*���.?UM��~�G5GF9T�F�AwO����'�W���p�S����q���j/�������1Q ����P5����Q�)�OH�W��>#���:.yI>d$��/�O���_?>?�xq�\����������j��K��
�b�:[5��D.���Xo/���2`HM��#�<�4�0�Sr&�e7�8��H��u��M������A5 `�|\�������~eB��j]�Q�����*S=��5/�@��9P�w�����F��Sw�E�������=2��?j�EB
�:���)[�G�6�Q�<��!j��}qv��%wc���$wcv��#oc����	Yu����C�,��}����P�\d�������;��6}hX�+>�(6��8tKT��e�[r���;��WG����,]����N��U��&�����t7��PC"���|w��r|����������%��������Ci��1]8��;R]����@�+^`T& �}*��������*iI�?���F���i�HO�5��"X����AG��(^V�a�.��u�%(�'}���]���B3������R��+ZiK������]���DD�|����(!��!�l�D|�*��hW<���>kx��A������m=+����t������h�����g��(1������Bw���/0N�WI�X6LaC�'���{��\�q�7d/k�BR#%��������{����������!$�����&u�������ahbU�#�?4��t��bEt��M�����a�^�z��M`�������[CbJ��2�G@���#�
&/D_��U8����������|T���S��?hs��������t��,�h-U2�r�?*�R���������I�)�/|`.�~?����&���"��e8����N5pkH�]��qd��Z����J�]t���9�TQ> =�W��3������Q�����FA
U�����v��	�z��j��ep==����vc..@H/[/��3_��/��M���EV���_�b[=��N3()��&�p���;	��+��T�U�_FQ#��-��H���!O���m4���`�-�w�w����+[V�0Lv��W�)��yV��p>T��C|��/���p���U�����1����2���8�7\����JK�H�K������� �����TEF� �P�H���)+�V�U|'�f@��K����<9~���!��zr~���i��V���/Z���^,�q&��x�\��?���>$_������3|d�T��v4��G����I����Rt��G6o!���2�J7G#���H3�:�!���*EF�v4j��/:N����x7�@������jr.o�����
�B��!�^>1}���kr�?���tX�/)��kzL��i�D�&����A��U��Z����g�bh�������<���D\��3���������K8��Ae�@z����fO�r
�����`����Gc^�X�����,��FG&-�}S��eF���3k���*#=���
�6���x��&�Up:9�L��XfU�1_&����m4�-��[_*�m�+�����"�s>SC�"7�D6��c�������������z	h�������7C�T��=
�����e/�S�f��'�G�����{�����[El��'"jT']!�+������E�MX���/�}�����_*�K��[����������O��p�O���?q�fs������;���3w:�����w��{���/]�����N���Q�Iy@1+��^(����v$�;mD�I�P�|[��P�pB�Wd�#1���9C�Z��~�b����'�8��I'|�!���cL�7aE����g���W0�<w��L
�p�|`xC~=F��4q�����S��9���*M*/�
&�� a{2��syiNv;��D��e����EA)�'~�'`:�l_,0����c{��w��p������kTR��.�wx�|-��]����t�!����3b�R}t�QqGWF��7*'ww��o����#�*��r����c2����������.�F�<6]xQ*���#"��R��cAh5Q���v�1`mtl5���O�Q)�X����)�)��4�JtDY9{�����21�p�����8(�xq�&�vLU���{'/��&��� �1�b�����
���X\�4������@���;"��6w���Xr��;���f����CS�������������g6Y�:~C��Y`��H���__������� �vt�����O�����'�����a�S�;N������| Z�b�;��O��M��+������;�H{�:�e��SRf?l+����������H�Y _�8��-y�a�JhGG)�u�[Z@���:
>'h\)�:"�"y���XaK�����nD�r�Mv��E�N�R���gLuwG��M�7!*�����1������z�2�Q��� �7�{�d{���>\"f�y])B�2	AN�v��u����tPc:�]Nu���7fu�t��u��le��1����f�K��4l@~y�b?�L)&o�[������Y��0�b�o��z�2��wD�O����w\����v�9�l�r���3&��m����c�����!%�!�][�v2�T�i���G�|I�T����Y�1i�@?��D9��^0h4�w���>g�����2���vw�n��9D3��<	�8�>.U�	aD��
}4�0*�D�~Oo?��2lW]��}�N}�P�X�u"�M
���W]|Y9qA����IM�< �R�,��\�r�nP5&N^������p�%#�_^^��"
dZ7����2��p	����;}���/�w�������bN��n��q!�u�=U9�F�fo�i4Z����D�$�g$ZH����&W(�O�dB,���@;GLF
h��x�������m{!��`����~C����DlZ?^�I��Qj}�Gc!DOM�H����AG�_Mq�V98�O{4j�D�'?=G���v���N�9`'���w�\$Xc:ns�v�~�]*G�Y�Z@7���n���n�1�y��?-I�y����� 9��	�^q#�5�������`�����k
�
�L����n�r�����D����>��MG�������*��j���h��U
$��l��iw6������H7$��aH4v�=���CdS��3r�����4[m5q���b�.}
��������:���/s7���B�Wgv�bOf��&��so��u��V����0s(�������L�an���� ��;hwz=@���=�����&�4���h��C����f������W��������.O�������84�
/m�F)i�v�0U�i��7�zAT�8}u~RE)l���_n����iV�X%����j�x=h�VI�
��n�'}����v����]�l�v�(5=b��q�l�T]j���B��7�v�����iY���io������$��h�>;o'�c"_����.	�sG���C�p��$�k$���s�7 ���*�|m����RD��E��3�u�����!�t�C��v�o4\�{�n�����7"��I���!;���?�����]G��{�����f������A���yJ���
�T�-Q�~T��ZRB�f�m��
�GV5�����'�U���s+��������[U��8&}��D ���g:v�k�:&����|x{|�~����������/���c�7����V&������-T����*����P	�����[�T��~{�6��p�t���y��W�%!Y�y>��x`�^��9bRU��P����N�"c��,iwR�%3����]��!�l��'7<��]�x�����D������U�b���Gc"���bPOI��WH��~�,
�10��A�
%�p���_f��8����js�����(/P�K����5 e�=,��e8K� G��b�Z���o5M6�
�c�eFk��rX�O3���+z������\�
K���(��� ~a�D�I��S��c�����1���o���>���F��������7�����>��9�`d#����T���1���4��h�t~�1�����MM�3i`4�7�~���� E)�fdX�h��|b���s��������{����a����g����7xI�^����� 4�OI���#�U����D0��4��5��x�(��~��:{���{	��a��x����P'���`�@�K�?�)�zWhri������E���|o� J�����qW��~&��]�o#�L�����r�n6p�����$#���"!Q>
�*��_i������/;��������ex*�g�!J�i�
��J\^�tW�u�6�+��p��OU��[���r���y�%=x�1l�Z�p�e��wz�&g�O�IeS]"D��r�J$*��+�V��8�����j�K�}�a3T4hR�bS��R�ZV,+�6Y�_���J;U�	J�^��]�������
��
p�ip�$9\���+?[M*�d��2��S&�(�\��'N���9�:_��U&5�7��8����q��T�5
R�>��/��h~�M���u���RJ��;r�����'�6N�m �����p�d]�3�W��������H)���BK**,�2zT6���4���J�vg�����F����_'c��^'�X%�Jb���e����!��|����S�^l����5F0���PE���H���d�9����^�����P�m5M��~T��������q�����0�'i��+�b�@�U=��;^M�~�%�a���U1��u��Y����X�T)�C,�R��q+%pt����6����lh�����ZFKB/q�Q>0����]���QJ+G0�l��sa"����9����E8�� ��bE�p��P��<��q��8�F@jT��cF����cz_�����d���<,j���j�+�v����h���AO�I�c�E[1vQU�#�gOp��0F�(�i�����W<���Y�O��rZ������E�8�tz�I�$�y���tS}N7%:e���}�4�c��M3��k��WZ� 8%x��s*����U�0 ���J�s2\�
�$b��t���S	)1���1���xne�M�9���y��^�"B��������%n�
��J�8�]��h�����]6������!���^�;�M�
�oQ#�%��-ZU`�;��>���S�Jz����pm�Fc�}	��D��f�Z�]��i�o�L�s��x��L����E����`�J�i�qL�TL-=��v���?2A��\��/�}H��/�3���M�/Y�����SoT�9�;�9�p�����G@6�J�B�����o������Ut(U	�a�n���<���,+��b��dO�YL?�--�%��|����;�P5��W��:�!��qhnRY�Z#I�5�rYy�O0��NK���:m#��Y=J��j%�������c�`�22Fh-������%g/�0
��
�|���� �����9f�;�3w�|����v�@�� lw��^���t���{Cq(P���90������wO��Fl��O��������c��u�'���'�O�2/
����;��~�y'�����-ww�Y
�5��r{�����8U�Z����9����l�,����A����!�ywF��1)�����g-�*
���iD�����(����54d 4MJ�C_W�Z���Fnm���7�0Q��AC�u+2�X�z�')�gk>�
�q�|�]vP��l�W���\�d�k,#�����w���#��Z���Lr8���8^�HXr#w97����l/�"J��^��u�'L��[��Bt�F����<M3�S7��R�C8�
6����|�oe$�G}9)����-�c��O��EFA
��:8���xr;F�����Cg\���VvR�8�]6��l��������T�k�
���B��E�8�M9�B<'��d�����;�����!v�Mn�F�&V����t������
����c��x�rP9���������S��8+��8k�"]���������Y��5�F#L���#N'"/��r�����K�-6f��Bl�.�6�����kr��x�����+:��������~b_8cV<�����"^qt0�Ay)bW�?�N��,w&��:����8Lo�i,����r���U�I
0�������){��*1
�\��|[�:��`�hT'\B�]�/���� p�z�H�v��D������GyG���^�j�bg��7�R���������T�b���O��g{F�|]���D
�8�i���������V�LV<�����rT���b�;H�������3�?T�8CE�B�&�g��=�?(;�{�7�N�)�����l����1���m?�fCH�E3?�u1�%l�1u��&��j-�T���j����Q�����U����/S�B�&����R�h�����i��-T�M���e@U$�+q���_��/d�{�]z�<��	X"#v���)���,E�yce
�9����Pu�D4kU��3jA�t7�9t�R���'��F��>kt���@{���^f�8/^��$v�w���`y��7�d,�����\c-�>��6��{%��(���:\<b�
#�]����]?���6l�I�d=�P���f`�]���	�Sn}�_��+����F���8-3@��R5Yj 0���6jl/��.�a�`a�m���"�����-�qb22p�{l:
�c���V�L�odY����dL;��%����.��V.���F�G����c��`�8����5r�$Z��������^h�4��KLC�9�1�U��o���:��w;� �z���?��`B6������`�����^gnv����#�~g���{�/�{�=��D�����V������B��{����^\���p�Iq���	�v�U&�����������m�	m�&~�����,-(��=��``��W��c~�<��LnU/q���}��}������5e�*��@N3. 
����@� ��#���V��ZM�:tVNU���g����;l�����}�>�M��"��/~�������p���s��������������W�5'�W9��J�^�l�&JY��:�n��������O�d�bO5#�^��7�1R$���^����%��|]I��)(PR�v���01�P���������<�i��Y���9��2J����~7`���V�v/R�����;����z�T��7y�};�����W�$�UrN��DNb������Fc6�&�f��hRp�ft�
Z���������l9�;��;�b�0����`$>���#������fWZ���������)n8��8��Nj��~?���2��D2�Xo#m���Ws.m�\�,_|el����.�;��W��_?��N����}8�8�<q��O:|~~�������k��`����j��Cm�P����K���go`��l�Mm�����{�N��#:�R22�?�'I4�S�S\D�����y�F���<�G�'�'P�V����B�n�b�]n����Y�{y������H��8������m$��rk�����d���(V��I>k�:�Z���S�#��sr�\v����O��d���@�R�8v���{�e?ih���p�a�>�}�}���4���c_<�����o���P����Mw�������#� <?c���8n$�B�b�O��g��1p�%��
��)���FL&����_c��K��U�~��e�9�Ws�d>T���C7�=c������d��K��E����U��%~�UL�[�*)F��j��~���gha�V�)�F�I��V����-=Nn�S]�(B����V�x�6u�����g��r�����I5i�%��u��:���!p�/��n����	Nl��wj&��"�w23T���4�3�L���r�%w�8�������-h�"K6)�-��1�?���g���Y�G������xE�c8��U;���1���g��`�>sT�ZER(�x��L3V���"#�f�s���v��i����/��E��"�oX+���_:�C���y4���!*Y<���[��7����tz_v�[��p-i�C�CU
�����iP�����2��8��S��m�h/�X�5���M���]��F%sk��t������2z.k�]W�j������Q�?��|2��|��!:�G�h�jU����r��6Nbp��" V�.����b9Q�=��
g�o,��d[���\��h4{����TN�h;p&����22�g����9U����&@�+_�"e�F��.2:C�D���X���2�j� ��_������66��#�
��}�3s���Z������2�$3`
3��H\��=u#����M�
�o��N�S��8�
9	p�)G��1��+f���Y���v��f*�!��f�'��|�����������{��p��t��N�i(�+},�b�e���>��njJu?[}�	��;������e�AP�����a�:��Z���A�:O�rdY���\%1n�X�u��������9 �g��)����.��%��DEV�����s��y����N\��c��I��bp(�������9������E�Z2�aV����m��=�y,c��Bc�R��u<7M��������Z�.y��0*�������\����^�����m]�3#5O�Gb��K�����#�������
�	�|	#_���J<V"��������`Y�!\RB���+c�@��=}�v���S�)�0�@r?�����)-1��6���(�4�X�a����]zf�2�q|��M����?�w�:b����!����}w|.BuJ=4MH�=V�b������q8$f�����248j��OA�A����'�����{�}�a��w�j��1H�,a��rz�	�0��"��/-d����+��*��m�z�a���Mz�R1���v��vcR���:l����P����xZ�*��wsG:gs��S����G"v�K�?�����Z�c2w��
�"*���o�qf�9��x3��/8'N���n��2���r�
7{_������f�&��:���r�A�;�A���te��M���J�:LG�~�1j
��n�,U���E�������i��M%�)c���$e7���3a,�]��Y��Y�A�%
V3�Ra(��>@���C�~�X��+)���9$G����#����H�����M�� �@
�-�%������|�f��k��`���`��I�j���t�vg���n��Q�?~w��eo[L�[�
�*\��K����@�}�����9�l��������KT��^����F�9���2���b�$�4���=J�� /��Z� ��2��vENL�D��L��T,j*z��u��,�rn�p�c�����Y������V����k����R�C�:u�1W�����D~V�e���Wr��O�����������.c�c���@H�#L�f�V@�^�G
m(�Q��xh�
��c���9rZ/��0��h�����~C��-�����U�%1���V�)�05�`Y��N�q��2��������v��W&y�9���'�X�1$��>-�����/W�y�j������3�>�/���3���Kt��,���+��X�����.�9s�A��v������4��������8�kg�p��&U�Oic����nn{����06�Pa�x��?u�b`���7������|m��h�N���f�c��������aQ�o�������S,m6�������1N	���d#���}v���GhXU�:X���&�c�a���l$;�T��������OUSQ�\�cL$ZOt7�M����d����w��o0����O��$�
��[G��D�`�D�,0�(���B���.��lQG����u�;��@i�xv�~�����s��������8U?����=B�`���Kc+�7��L���������7�^f�8��efl#O��{��
��_����.%^xV���r�O��%PP�A�M����_^��kxn����:�DSe����^��ht��AgT�['9��+)�iD�C���|4�Z�Ak��Z�J�8�6����%�]�����C����K��6I�M��C�J�LCD������s�p�gy�q.�z/���rM*k����3�/���T��������������x#Rr�b�]K�F�$���������l�y�}N�������)}vR'0>}����BN��"���_��<wn�!`?�I�~�F��nK\���$���&yX�=!o�E�)>�Dy�N���l�hL�V�S&��9��S����= �,~X�TjS���>�;o�����/����"�%�Q
�m��^�R_A���$�|�D�F�O#��V����R�4���-u���-m���n�*/�J�����I�
�D���d�E�p��<�)�4b�R����?tG ��f-��3�1�.��[�f����][���U����2WZ��v�7<��E���z�b��)�ce
K��l%q��g
��q'n���L�~o�5���������qv����#�Y�#����U�GY�a.T/>��Hx����uce�5���#��:Kt�W�%���:R�������T�f��uUt�>���9�Dq���	������q
��t�e�j�[�9���tlRi���&�f}7Q
�����m�����u��p��a��uR"8D�:%�yc�fpV�
���D����Nb�
Etr����=�U��g}9�7x�(<��B����n���L���{����h���l�-{��A4Ci��aZJg�tS�F:L���Cqn��^��T�=�����A7Z�c��]��=t����FKW���J/
3������}W;H.�M Z���r?e5"�)4�<_Y�~u��L}z����f J�ew��dT$�+���@30Tpu�q��=���d��-�e����-���p-��������W
�_��x �(y��ew\�fC�����n���������j�En5&�����  ���4�hl���?~�@�Z
�����:s�������s����yn�rF%�){����O.?��?}���*T�C)�X��O�{��������Mu�����`�H�H���C2�������I��)L�B�L�}we�z~��������z���o
�"����}M�H:=3#����J��K�`,0���)90%�9��L"#��^�Jp�����U�$U�p��Ly�����v��P-��u�M��T]��c>�s���8l�?)�O���+���u9d4r���J�y�Dk���>Cv��D�Y=��f�������1+N�s�9`���c,5��R��s��1����Ls�F���^��p^o�5H�����j�2���, �x5G�ce����=�/LG��sN%�aW"�z����8k�9�_fol�����U�n�`._�b����2��R�R�snTu���
����c�n'���>b�=S)j��������dg����T�������
�<,�xR����8��E�y�����d��5cG�w��E����]<��e+z}*����;���A���u5��y?��M��+����`�Y�9]BG���>����WhN��s5�V�q}�9q����kQ�D!�L���"n�y����:$qJ�cr���L|�o�����u.����X"{v
%(`jWX�U]e�*jV
���;J��#����m��5����R�hUB0����]�:UTp��K��0��5�u�E�	��P~BL���"��2(qr�v����&����:{�Iv'�;C�K�������An��<�iK ��L�	-�}"�l�(���fr�'�m�7��.���u��z���������+��POX�l���a�#�&n�
8�h��4���5��Z*�qv�~����J���(���B������M_���J�{��GOv�Ha���>3}��,��l��Sce�M��N�G���L���0�;��h'��%reK��+>�f;�����e�g����e�\�H;N���X�K���7���w.7�/��n�}������������)s��W�I����
�2H�E�y�\���Q�#�SI=��:7��_`V_J�?��W�k��Q�w,����{�����]"+D�d[�^�����^?�
���$z�F��b������`;����U�ki�}����
W�)i�7p������	���X���}��3\U��>��2V��f�u���q{��=n���t�������lw;~i��Qv���#��]���\$�U�����F�=�
��]"b/\���[�2�).s�k'~��iv<�+��H;��j+�H������7%�*����	�
�t����U�I~�����E��\�w�.�8�NG"�0��{0�T��{���(q�T#9DS����Z�Fo��v��QZ�0�N�n�>v=N����_
������=8x�vx~E��~���9����&�1v-�:�Z~�l�=5��S��8:�m��'�T��	���^�R��Ep�L�o��$���2����a�s�n��[T{_�\�}{|���k�<��*�
��^������@Cj!X����t�Gw�Y�=-�'c�BBn�m�]����BhT�����j�v�q��pn���#���{~���3R�rIK���C����-sq���5�������Lly��W����j�6��8���������~{�j�~�<z�]GC7���>Y���<�	��|:O�,\s��I+/q���,��N���^+b��6�p�9���[]��f�,����M�Z��0f�5Z��w<}�N;�%~����/�q��^�L�jhQ9'?F����&6����4������s�Yb,�����T#���G�
���F��*���o
�]8��;���vs��'�lM�I{��I;%�Kc�P�/wa����S�"��['���&v�/je"L���l�GjWA��Ni���r��������03��/�or�}Erh�d���Q���A:�y�����n�-��l�AJ6g-��O~Z'I���d}+����_N�9��"4+/�'�?�����(
�W��h��A�W�q�Cr�,��z���A����+qJT#%lMA�������f�U�*��d��$����OK��v|���N��	����g�(����\�X��v��9����q��R���������u:��d6����q�(;�\�c��� �n��7������d�_�~kKS�[����/�'�_5���M6�v�C�G�p�6��~����H;��j���-)L�J8sS"����qH#�;	�U��E� �k'�B`���dV������i���s
������y�_�K�5)|��_]����A{4���f�3�=-�@;����J�����pX��v�<-�mU�u������t����K���0����T���2���/z�*����������1�4zO��^6�wP&�����K6{�Pa��hv@��u �/7����_k�l�L�+(U.�����W%j��^]���������0n=����8z�����l���A�|����	�ekXe�h�-(],��t1���X���w9���
�����
f����,(h�#8 B�:#�	��`"���P;
��Vizg+b'������w'g.O���/.��/��>�������}�<~Lz�M�k��v�*�GX��y�����x��go�\�\R����A��I=z����<e�v�����Y<D���x?�,��uY�g���tL���U��VF�kn�k�LLB�z1��@�n'�T����F�6w��v���A������9�����z�d���t�$�X���A���r�
1:��a�}%!+F��C�t�5�/}	s��S���S>z��l���Z^�k%
�)���m�~4P��Tbm,.FH�J��k�:l���;������^���
����3R"�v��s���k"������B~�B���0��_����(��x���i��B����9M��u2�M�~�/0s�8��1����h��o]��`��M��ir���������x�����)�5������S��g��
��?c�s���pqGk���w�Mo�h�����|��5^/w��* C�N��f>��vn�15�N�:�v��d�Z��]s�+`}e�Q�_��U���R�`�1��������~�_Q����~����v2�k�N0��J�P�
w���tx(�xv�
u�����_�|q����"�����7{zX��Y��P#����c�	]�8�-�$��H]0���#v��)��?���s�����Y*�%�?4_��p����w�����"��Zq���p�Xp/��K�T�����^g�h��v�xcV��������H��������1���|U�r�s�;wuB�v�0�s���FD��|g�����`>(���������bLk��K,9�o.O�U���?�a:<��k�>����C��#�W��&o��Z�o��n��,����8!��U��Z�z
%�Q^���El,� '���d
�L�t��P%*;PxWc��I-`���d���;�V�m��������D�
�?	$���152���5��.�	7y"��f_��V+�A��H~� !��t�9:��Y�nnG�g���|v����3h�e����A��E0�Y
�HA�; �n�Y<��yY 0!������g4�QYqz>v�
��t�#��������eX5$���ub�|�YUo��u�91N���G����7���j��Z��
zdI�7^P���4"�EUs$�,��`�M��+���x�l�0�h�q����ag�u�=������75T�|����o��,f�V*�j����a`�o��aA\K�8�����ku��V����z�rG��6�����0�bgB��<�����k�]�i��J�%����`�Q���l�� MR�1'"��_��ll���}�3LL��v�tZ�������@Ug���&��+>��@D^����
�O����?\l�5��������t��L��lh�����8��N��~�-����C��2X�o����x�����tm��A�
�1\n8���O������e����4�=����;�_A��h��m��h&h`�"����g+r�N�-��Rn��������ngXPF���&Q�s��;��'�t�]��q��z���}�Tb���]����l	��o������RHz����VZ8O��TQ<�M�.�I�)��#��`M�e�|�|�'oO^]��������n�y���6��r��E����J+���T~���n��5ZnQ�Y�Pi�(h��l�g���4C�q$ z#��+wNj	g6E
Y�����gx��_�'��]�#b76��!W����7*�-�3E�M88�A9��uMc�|�J{d8�JL�a�PIN����v}���*�v��!���)��>�g���W?|3~���+2$�s!NO@<?�6B�8�g7��v�0NF���O9W�;��I��!=��t��5�
�AX5 ������u�����Ki�w�.�\�^�6�ok#���`t����=�`*Y�4L�t�5�%���o�u7>9�?GmJ������<�6�&P�Q��t,h� E�hF����x�$�����5��j�����_���t���C��h�}�f���/:���j�����N�Uzt�������Ts=�l�r�w�BJnA[�y,����}�3��DX�O�� ��_9�X�����_��[���&���k������K�����t�>�������v��9+QH�a=Ec���o�����e,��
F�EM�]m���c��?��L�2����� Ej�<�4��r��'z(���_�7�||�Y��+���R��������� H�ox?����X�-E����P����_���M������H92y<�kXV�=a����Q:��{g�]��4Q����#V�8�v��*+EFv#�����isz���������;0����B�H	��9{���-:%T/�_�N�/���z]�T��n~���N����fjm�mc��D�r��S�b��b7������w�mX��;P������
2��R����l\A��?���6f����^Fz��1b)jE�&	�O*���K�L�ZD1�\R�Mu���B����&�kK�����`I
Y�6����K�����`f����B!e�f�P%G2V���j�u�/������f����`�Y�)�������aY�N'�<&����0")����s���z����1��G9opklb�����M���g#�4����w�	{$�����8s�[
�"1��t��j��w�T���W�7�]�G�U�R	��C��Ni�gt��*�O�_���_o<q���i&������3����^�yE�L�������H��"[��O�h	�5���Q
����6Y�����x�7���la�I[�%_GYW�+�F����g�Mg��8EK��
�'���09w�n�}����R���:JR�"H�x�1Xes��c�X-�����j0�D�|]UP�S+�m���A�����).�J�q�Q�B��-��c-w�L�n	����#2Zqx��� �60F���?�^�Q�}c`-�oN�r��JNmN�?�NO���?�rt�����I����r��9@�(�����i�yA��W��=M���@�0�:\\�E����*G�H#�.
�X�x��!��_�����[���X�{)�B��@T����a5K���#��	�:>�����L^���Z�
�����(�r�?N�G�12G�����F6��ZC�]:&\^����<��c#�T��=S���q8u7��3�\���X��
y2�D3.%�H��-����f�`�c���t����|����mD��<�4�)?���K�w�@A�g�����[i6�������?��Z3��	���P����k"�Q 0���.+w��my�W�F���y������v�?�j��y1z<y�����Sj�B��_eo%���zN�##����U~<o�
x�%��B]8�����!)'�[�
U���s��[�,��Q�}� k��4���u��^�����
�%zb!He���r���B;�4�!K��F�7>4�S=����\���
�A�N��^nj�E{G���9��i��������C���
wc�IY��%`F��z��>0Q�/��7�����D?1/��D���W�T>A��������S=�"T����:��D&��E�z���#����<�M(��~��`�����5��$�i|���1b�=�M�D�kj1�h~ ��k'��c 1�9�B2���Ji'j�c���	��w#f6N
X
���c�m�fR�#����2�O��6����,@�������U��?����H~yM6j,N�^���32d�{��nW�E��C�	h�����(y��a�Q�X;�+u5U���b��6����#����}�dl�'OhNBeF�b���Fx�4z���!��H�����h�`M-l=�X# �Q������=�<�$� ���7�1
M��(�m|#�yZ�C�U��G�E|�#Eh��5���f�;M��zn&1}n��	����<&��<Wf�����
h�#�(��:`�L�J\'��}Lq���~�=X���!>��
����t������w��	n��;��VZz��.[�'
���@�1ht�Q�n�����,�����_?\�0���������T�k�)����)������.� �YM|O��S�S�s+����l;w	�g���=)���)1;��b'h�r7r���v<�����M��Q:�m
i�E�����y�m>U������1����p����=7-f����{�g������)��R���=VwyGTQ�����O�mL5��������eI��g�9%C>�E�E�����o����pv~����l�/��U���t6��.�����
��[��@����������+a!��P����@���`7�\?� ������������k��2���$���?a�����n��1��/���ntKS��������m��q��Eq������5��1�=�!�x�L#��R�\��L�����i��z��_�&|i��
�Lx9�V�����8��~e��R�;�v���V*����/�ou5v'X�i�#�0�����[�g�f�W?��v�����o�:27�%��^���v4�~���v��9��������N��kv�����z�n�����f�����s���gg;D�p����y����q�vg4h��i�4����������?l7�N�=�����.\:��i
�f�9��i7��
��9^� �'�c�?P����'�����I�Z��L�p�����������u���m7[C����>o�#��f�b;A#�s�o�/_}�4{�Z��;b&)�����!3�����)M��,�'�z������7*RZ�_�p��5+�������*�v'�}`P[��p�����U
����(���[�0���1�+�gI����c&"T�&��Rv��:��S��i63�a�G�<up��U�Xm�sB3����faD�I��ko���8���*��]�3�)�����L��S�[��oX7b����Z�\K�)p&��h
i����K?>4�6�QO�2�	 *�D��T�
������"H^��Pb�Whd���T&�xJ~c����?�t~��u��3i�JZIh�,�ld)��_��S+q�xz�������Q��?q�\�t8Ih��rbJtQ�u���r���dH���t�7hx�V�\�����F�?��W6�3��"c5/.��(/P��)�Bm}��\���T>�La�+_�1
�(��"D|����
�=�����(@x������U���_�
��>���{��5W��3�W@�L�K�w�|f�O���w�~��
f&�P��r��������9"@�����87�d��)�I@�sb���1��y%i���Y�u=X��WV�������f(��
�~+\m�4*)���_~�f�S������XG����'��Z��
���W�v�����{1�2���2����"?�c�GxO��l9����	*���?�G�	B�J���R�E����*�W���	ML���d���H���h�n6NM")�I�Y���jF*D��2�
Ml�7++���`��?���0�P�)��H�)��x*$��<�~�hMR�=��\��J�I(�sB��E��M];_��R���2 �n�Z��pFJ���ZPk������2�=�z���%$�^8������/ii��U�A��B��_���T������]���5���.4�1�C2Z����rmp���b�TMuSz}�����a�\n*�y^�d���^IVP���
+<�6]"{88�*y9�&\��cmx��?FvY��C�E��0K6HS9��~�**;Vq�c�8��^:x�����_t�p?+�2]�B�Y���+�-���1=��SF�%d?b.��Sy�oU��<�]��Y7�>���
Bt�`Q���u��k8B��sS�D@�.nS$7A������0�����<�6-�QN
���&�eQ��,c��IC��[�
�1�A��P��J��I�jst5����p�Ad"���h��q��
@Zab*�x>�	����V*&�Ebf���e��FZ����"pTn�`F���^
��
_�1a��	�oW�s������Pi &
�@��|�1�/�s�)
1I���
N��'�B���4�����$VG?��%�+U��
�&c
�@����������D*��!�{�D?������8�����"q����S=;
_��Y9����X�'�v�����:�Z�".5x�7�g����7�w�7�����0��y{_�2I�C'���*�O@:5�J"s
�ms��Pv)��G$_Rdr���3���5~��0���|�����j���i53'K��\�4�(��K��2�9�������8-����c��yt������{|�<d"�1EE��J�f�U�O���?�0�sH�?X��o������0���a���-�����:���'�b�:�H��f)H*_���r�t��Q��m8rk��~�>�VIw�nS�v���59yNn�UyG��hiR6��.��[������2�o����
s��x}�r@�	_���N���2�`��
�l�k�����Y	�����'�!N����������T�s*��e�*�X��	���Y*�E���G5��N�Z!�������T��}��U��V5�k�M���S��PL�3�C��)�:�t��1�{e����#�"�	)������4���`���?t�������e�~�w���#|�;DM����]6;?����[�X�������D�7��gd%%�N�S�hGU,@,?&��Q������J�p[���QW��i���F���i�������p�����gB���'�����.~�
w^���Ca��o��gu�nh������'���T���b���
�k�^U*����l���{Lr�����'j�
����A���P��"�C�e�	]G���jp�k��@���?N})j��^�75�+����P(�,^�Pj��p������|�B�X���z��I,�����a�	� ~��� �2�Mb-e/����|}������4��C��Q,������'2�!���7�7����sS~��P^�
&Ix��zX�����
'��4�`���|z��'��<e&d�]9F��D�kX�����,�/*�s(��sG�S�����$j��]�!@���T9�W�����?�ZQ�P�H��:-�p���B6��=�_����pV)��\���2�������!�L%�!��"�vw
���>f��Y4����������w�;c"n:i���Nm���[�
���(�����a���p���[�T)�`�|�������h���0v`zJ<��b����\��3f���H�|HS�X�p���^s%6u��p��\g|�W�;�7Vxz�()�����0+6�)�r4������>�K�_p�52s(%�����E$u�]��fz���Z>��XK������FBU��`��N��K����0����s�!����-�c�q}�4�"q*Ia;g�O$�(�j�		�S<	��>�u( )���u�xo��C�D"��.<D�kZ6��z`�*��XuhcD��$���V��kE��5��1H#����Sm��3��O+�9��S�����Y"����[����WN�j�Sz
�]�/�F����D��B6��
KN���U�sd�a,D���$�!fA��E�
j�mQ�|0�#\��v�eF������j9UNP���v������7y[Gbl�4�(�����������m��5���������w]R��V��4	2�jlW�7�����e��]�?
�p�}�<Q���������%g�Pk�ir��
J�Z}*z����5s
�M)V��`�]2Y��?��s�n��1�7*�������	 `*>>k��O���\|��;�<9?=~{����v�;=��Y|����f�a*=2�	� ���A�k<�n���0�!�)������jO����l�A��������
�=������,a�hp�f"FGBp��QMS���6h�.������Z_2���z��]�L�m�]%�������0��V�/��4�+�2Wwz�_^�/���d�����������;��w�������lA�Q�z�\7b�p��J�{�.me3��\�O��M2�����fz�*�E��/^�$��,��e�I
�Y��%@��yD��!���=L���n�b�t�����Y�[o5�|�>)�tR���|S�|S��P7�%>|u����v�+��g��s��!6%q�Zn���8�H"������U|�1RqL\����p��m�d�`2U:����(W�X�hLt��������+O|��t2�iVp���-z�_�|
C@�M�;p'Hh��:+�*��Pdv������3�6��g��1�7u�:N��s���}�ss���3�,�-��:9G�V��+��HG��n��LE���)�rz��F�x��=����l���u�:�.�=���~���jsyD��S0g�+�d��f~f9L��G��6�����|1���`����G�>�Y���L/�E����6�jV���RY:�������R	j_CsXVm�������Y�T����2�Z�!PbZj������^j!d����_f/�W��yJ�����v�"!u��=hv�pB��+��Z�)��\;�<��u��^�����&L)7ck�H����m�&�p��8��w��oO���//������t�������k��).��,��_���; ��'�G
�T���n{�!M��8�komR�8O9��E��Q��8gq�3S[�t�<6�)�����9<j�HQ��	���;�/pBR�
�Jq�w'Ps���9�:|J*^���\��>Y)3��?1�+u����'�_��\��7��$�t]s��B�������Y]�F���H'� h=�R=5���ST�����`H��+�I� �����Z��J����2���2���+w��r�$��}LNx��')�3xqZ�lN�&i��T�'#�����J�(Z�RO��&�X��g<������uaA�N�y�f+#���@�z�}��'56*���+�
�t�8�>�%�����fxL��`���z�*a�)#_g0���D�u��Cz�d��~��1�����o��H3��J;+qVk�."��.N�*��g>#G��f�N�}�������O�xGJ3�b&&u�.�Dv���+��������7��=>����<�p?�����H<��������VCA�f����YmNRYOvg�d�����iw���*�x�+gW�/:��y�}����N]�w:���
V��0���g�s�2g�v$��P�.U���jT�>�����g.�Q�4��JnU�Y/	���hE�+����Q�~�a�^W�7�
��> ����/u��"����5���F8�.��Et�jJ�������;�4��6B��q���	K�J�$���O���	AA���	�����W�B�H�,)��[(��~������8a�]��a��t8���.B�KMZ)h�<���u���W����F�8!�����x��vx���<�d�eC��h�pXz��O�&�)����a# 7�8o�\�D���-H�Ccf�K�o�����n��tP�g�@1d�6�c��5���mb���YS{���RNc<3L�g� V�� �vf��D"����`�c:$��� <_FhJ�KCP�.�w��ZN�m.�aM]0M���.��j����f������(�; ��I����R���V��4�i�����qI�*�5�i��S���53Ehj<{��g�����rh!cb"m���W�������e_#�g����f����T�<C���,���b�.��T��R�����T����)������D��($���4/M���C,a�?k>W�>��KB����X����I5G���iPX�H��1Z��H�$����:�(�;�Z������r9�J5h���C�(#/�������;��ku���OFb ]_.>4���%NQ���%��)$6�C�p4�=t5G�2�AQ�J��I'�Rx$��(��K�Y�I9��g��V��C�Aa��&�m(N#)��)KR6q����o|t�W�8q@�(){�Y����
7���i���j���#'Q�����T��T�V�#�����Z�v��4��zT�+��FoWr/���'�W��Ds����b�>"�A�R�R�'D2��X C~](V�����b�&l/���n]�R P�#MQ��Z�����]8�*�"vZ^l�Hba8�����D��a��$���+p#,�"����1/��VLU��i��5��nP�������ca!0�������^��qdY�VsT3��$7bQv��8���m
N��1�ey�/������Q�K���v���Uy��I�S���89rg�F�;���������i�x���mr3�lQ�7�=��uI8��OR��2� �O��"' ��������)���vd��{��/>�U�&>�+��������X
*&`JPu����(��r��E�� ���OG�|�����s���z)�>���<a����5.���c�&W��	�C�X
�T��k{���)��
0����/�z�7 �.�����P���8�c���h$=���Y����ff����;�!�wkPC�~��\bG�9�U�_h�s�N�:���S��R��]%7�G]�3�a����]\^�_}{��OP�9������.SEc���.��e����X��{R��M��{��I��C�����T�*���D�?�:{}2>}�������W�/������'�q9'h�����@������G���#�\�e7�[v�c��������?2�����x��]��D�*��B\v�Y��y���:vb���_�h#pF��N�*��R3�����b~��{m��?�x��v�p_d�g/!c�CG�������}��JI3�	���#��U�{��������H;��������^�9��vi);4cl\���rY\���#�<U5?Sv\���������I��H��p�� ���Vg��+�WN�������5_��V���
'�����J!4�6������)���D���6^���{Q�����1f�`!(�R����\�+5K��U[���ep"YS��*��m������u���"$�I�W<>��'���m����
J����������#"�?��e���OY�q������7_=�Z>N>���#kJ�������~�^�q�����;��*�9
'�|��1���h��C�4/���K:�A����+��:����
�!���)l���_�y�!v=5�k�3Yr�H�{�X������*��L�����H~d��Q�4�R��d���.���	�'�e�^��k�-4�Xv��c��R�n�C�Snr�����p�����L
���:!1>����U����P]�-��o�hKA:���FI���b.`���J�4�v=��h�z��pVV����>����QC	�h���an��qE<��7�J>n���G������c.�*���`�y8�(Ad5\3�I"�`�1��X��ZS,NQ����X�Q�(�*���"j�ck5T�J^���R����I�
���������)b�b����pS��-�z��_�5�d�����tX����|�����������;��^F1��4��c'�|���e��.=��R��o���k��W�/b������1��y<�pO��5��`���`]l���z�C�����RN!��RPpn���*��p�yF05!U��Z�����[�(����!�GG�9P��m��%)r�8�=�U�5��?��'�{Puv~��O��_���������f� M��G���� �#��>���`�	�������W�7���B��[��ld4�����d�%��~6VP=��F�O�����+nl��G�3�����?b]�V>�����QB�fSlA�����$�\�i��j�r�6���,�-�80�L������b�}��<�?���&���m����-id|�E#[�Y�_:M��c���4Q9��Gx�$m�l��nj��d_8dk&3y��Y�7"��x\�t���Xc�8j��'aa���������<9w���w>~x}|y�2E��T�'�������{ �D�	5%��Qw�8)��3$-S��'P�n%��x�z�FW�:�)N9	#/w����<�J$�W���D,q��n'9E�|�w���fFT�@�WO��S*���e���������'�'�kC|������r�^X���������������/��������I���e�$�@;�s��:��Wd[�^���~�G���k?��=��`?���@H��Q����1}r�2w`�����/��3�f�|�#q���2�{�\N
��g�F�Q���p���F��������E��C��������{F��N�u���s��*	�������	A$��B8��������2�:9��7������.��~@[nz2�il�>�N�~Tb���$�����J��a��s��}�0��sV�xaN<������zV�}����59�k���d ��.]s���T�tb��Ts]*�St)_��=�w��
�CI�0�����[�Qm�]F�t�����H��F�1Xe�O��TAo���,b$)N�_R����X�E�����6�h���N��}c7F���b��=�������_-�)��r��6�������j7
G�QR��qX^��n�4i:����%�<�-��z������4��U�&�kk�D)�jL�������VX�U�F�b�75;nKy�pY�q�����B�����������4��
x�]���NB��I_|���mvN9���(��;��G}�<m�GC�%a�|<|��<�����,���#�Q\�0�.N7$�.���I&U*�D..�'UZJ�Z��cb4g�a�i5�QbkS�>\��$�.����v�5Of���09���S�D�d�9��'�Uw�TU���h�����z�Bk��������_�&�+���%q��U��V3c�h���bK���%���a.�d�2�g�~�%�C�^j�bs�����]V��!����s'��z�����;���m?�e����F�^]��#38�O".�:�'��S1:v�a5�v��':aAb�8vg?n�@^���/J�����B������6�<W�wn����8^��$�iK�C�������@l{	;\8&3�n��C,//q��%��8k�M���|/��v57�(���A+3����F����"���Y,

��M��������w4#�G�=��$qx&���2��x��)�df:�������
{a9r.[�o,����1o�����`3���p�)��UQ���.�@l��?�����c)8g��c�4Q�������"N8;|��
�h�D-jS�6����$����\��
������Vj�x�'Q�'?eL&t�#����������l��1�$���,YCX~�������\cZ������R�7T�i������x?����Y�u�T��Du�'Q<]k��{l���	�t�C]/�b�M�+��L1���P����PS�B��s����>����U���f�z��D���Y�F^.�n���P��!�<����	V�>�������SK�
,G<�����]�����&dRu���G� G�C�3�L���`����ex�S��{��IY�)Nl!��oK@u1���b��	f�0��c�����8���b�`���s��$��������`&�����	����U�;TZQq�M��.XS#M�*��]��o��+=Co�������T	��r��FUM����X5�a�	��TW�T<[d�(�~H��_�RG��������������������'�J[� �c-���Y�����B�:����O
H9�m
������p����xnd � ��
�5��3�,bm\���X�s,Y��F����6�������,A�bh|Y�"���7����i�A�� ��:�D����2�4���5j��l��������������Y�`+��;)�Lt~03��#��������R�1a���@J������i�4_����i�|��eZc�hPFgV��;tg2L�^e/���D4'V����W����%�����`��I�?��o��x���I������yw������1yt�����|�1U}0kN0x�T��kw��1��z����U�I����	-��Y5�I��OY���{����w��Skh�4Sqh��^�Ck ���Z���H��a�2`l���Q:��14��;�(S^��sp���Z���u�{���lmbZ���q��)��2�.��$~
%�V�Tx�.qN�'����I���TQ>�Z`W)���$I�
N��;���h;o�B5r��54��SR�����V>�V�! ^�k)R[2S�+QL����4�j������-�����i��}y����U�~��b�4�1�p����Fa�I���OT)�
��o�I��5	�Bt�%7��d�=��J*����b"T������������Vs��Z��E:O'���7�Rng�8������X�����y(r2�L�����>_o7T���e������![<����-�S��r<�V��Qs�B��o�+�W��;��(����Gya~��=�LO�W�����t���k�j���TN�"�H1�q�D�bI2�:�&�����b��/�Uz�8~���a����)�����oe�&$�V�?�U��K9&���
t���������_�*/����<].�@��8�"8aL�R��V�������&�K�����?�e��M	����O_)5����$_x`�R�Nwe���(
�)��jIgh��#�J�
��qy�� 9�d�a�����RA��"{���~���0�Q���G���{�d1K�rDa��RL)O��1�T0�1So��*p�ll%fc��C�)�%�yH�_e3D%��q���p��\�B���i�����v�T	��9|������!Td%@RTP%��D�b�9B.�=������(���#����]����V�z���D�)=VYpD-k�Z�S���b)#I
X�[�A3��L)�p�@��Q�` &����R���l?��W�vXSv���/TR���Ix�FLP)��*��`2W	��
������������15�.]��w	N����+CK\p�����v������/vn���<�s�D	��r��\4j�	��L�>�����+�j������"��C�K9
�/.��/�d��J�����)�U5��Y�������r�����"l����j�S������A" x�P��Z�
�(am|������k�*cu�`��|E
Or],�E<b�����J��J�rB	Wk�sn#�V��W.c��^�s�����.%��R��]R)[���e�o���j���)e�4J��������!�6%��:dm'����������������]�C[��W���3SJ)�S�I�=%��.�k�x��^����j��i�q����>������~�����d�2v�$jZ*'E����I�X	B��`L�d,����#�%(�!j�h{�3���F����x,�Ru���=��[���G�6�1e7���)�Sj0�U�S*������)Z�
�'�F������k	�@��m&�'!����-��QD-�����	>9c	���Gr���4p&���L=(X*8���Rx�m�Hi�?S�5��1e��E�V����"?��L2{Y�g�j�����0�f8
0�.�n`����%�#[�_�,�2�:R�f�ye�\"�)�u�KH�e��d�^*z%�Q �����A���,<L��&�`n E>l8����DV�x`�Y���jK����X����c���7���K2�'��b���4>�
������&Y�U��Q��'��'	�\W��y�p��j;'7e�qS��]��%��
�7sC-�K{�<�t�����g?��w�GoW���c��|^�����T��Z@Ar�-��H��_9:bd���H�\��$I'�j�����()7�<�����IY2�2�K�	=��d��s�L�z#��d)��/�|��q�	���^�
�bD.�	2;���=�q�8�5��*�g�<^����u�~#���j��s4juk���$�v����e�s?���q6��A�:@��*K:�Od����mb&
�G@g��y�h�O�Y����@���;J���G�H�3d}����!�<[��
��[����c���5���}�58��^�@�N�:��A���tv/����J'�<@�*� 6zVI��*Nz�Y���uJ5�����x"������a/�f�������(|G�S�x9|�$'�<2�����5W����f�P��qF����Vzc����k�{[�P�T��� �����Z+���l2Wa��>�2T�f���/�oO�y_�V+:�$����y��������$6��xd�[:��:)QQv�U3���{�<;.#����6�0i��4~����i���0O���>PG�8NT����+�rl����z�z5������AbouEa������/'��P�T�Z
�����q�������\��l��<���v�$��3�w��.89*d��������4��~�����S��K��q�y�e���=[���	:��8j��VK9d�gY��#�����V��}��>Tu'��&��Q�t�,��HG�4����c��b��K���v4G���,S�e.8����fs�<�kC���w�J�?�����<!%$��`?�Tx�������	l{��_N�j���
)�5%?�ZE#�)����B��&`��f��r��N����1��BG�z�Wp��3/�����_.�IX��Z���b�E�Ff//Z[����%����Xn�����R(�N������k#]�����4I���u�U����	������T�f�G�����C���h�����_?��P��z���]�C�K�%7#��V7V���@�z�j�fT�5�X���0"�N���<w�u�f��b�,�^x����?9p��]r��X#OW-/����1��pAnL�pJ&�9���ml�������������
"��,]3��f}++~����~�F{�iBc�P�U6]���6��%�;)y-���j]$w�f���Z';Y0��|�<�9N����A�����`������6�+o%��><�N<�{_'��z'��C91�/�v'����*vb0OS��~�����e�l�U
�b��:���8]�{7
�}��!�y�[M�3���NI�'��2����WwG�a�:pn6�f%I������'�(h�"9�kvm]��v
=�u���[�{��s�K�C;�Q�9��+���M��3���d���}�dv�w*���x���"L����2d���R,d�o�;�O��b��a0�n�R��h
�C#�����~u\� �1P]�f����U�b������*�QR�GM:���\�}`/|�hB��T
`�J����3���9��e��u�$o�b6��'�.�PK]���(��im���E�'g��A��V��3�Sd������L����������\'�)%��@�4�Z�:���o���c��X)f,�zfi	���l���V�*;��������G�y_���{���':�`�F�T�Hn}�$�`C�G@V� M�E��������:3R")�O ��>��Q��
������h���e�HE�HyhJ��z�.H.�x��|/��P���<�w����8H�<h�3�D96Al�R��`���P~�l#UA2�����=�������`���<j�AV����Y��v��q~�_�-�m0O��A`�[����zA���g:e�]�����;��:#���.{���f��u����q�t!��i���|���t��z8gw����=.{�%��b)L��7��=��}PA��(��O"&In����\�K/�|�����
A�}Qn�b����O_���mM))&&�''ZY���L�c�]��G��(�/�]�N��iQ4Q��.f�S5���D9h�f����`����4���6�g�^���dobd�x �~"����B�?��U�$/k�6������H�`�n�y�H�a%p����"�9d��=���G��3a��=��� 8u�F#�nf�)��6a�{[_m����u�#XTK���4���ir�����)0Nr^$%8*��(��\�����1��LE���v3��9��
��TJk���m��� i���pw3'nIED�@���G���%�":��zD��>Z��S�r����K�{|������2�&��(E'(
�=���X�`�1}�+t���Mv��xV��<�G��92�E\��>�����a�t�`�j�V�v����-'h�\uP�V6g3N��M>
��H���}�K��=]%�.mzI\��@�r�]��D*���I��\�y�2m6�C@,�.��Z"3.v-v<�8c��#�Bu�$�QY&�8u^
\�	���8_e��(��H�=~2�����)#�������G�V��;�,|n���TF'��J�1V�7R<T��&����=����'�a��j��t����IO��S���s�F�hL���5��x�����OL�ED�7!�]�jka^�)	��=�v!�%2�>�S��
y'����%�T�%���9
��_/
��q��:j9���k�9�&��%LK�\��W����\�+�4z�p��n���������s>��9�>	����gK���P����F��.�C������"�8�>�-���R���=��B���Ar0����>���i(��������!/g_�5�
8��k~�(�CMu�����9�1c���N�� �PfQ���R�Z��Z�����J�{.I���Q5@X� w�5�m}|���0:�V�%�-:�.���������1�����?
���7��z��;��Q�X���le��#�G�
�p�	� m%X�Wt�3����h����R����b����`�B�la���%�s�W�v�v�����A+� I9��V�[V����E2�H:��j����;���G���R�9��Y��nL3����Yt���>$0����`��F4nx*�������TqiL9���o����p���`9
�(�3���dl�V��7Zp�'�7��\�IV}���-���Y���u�2$eeG�B��.������"���lqA���i�b��B\�+���J�����E��J=�4�]M.L��w�[�Jw����#���]����1N���B�B�C(kO"�H�E<i�4q�IG�S���,&���,dt/'[�~�d��n�B����T�G9&��N##f
�(��
���2A�9����%kI����q��a��C��$9�h�5�%6x��(�jw�5L�/I]���]hH	9Q�)]��NR99h'&I3iU��vd����H��:5�z�&T�����E@A&��Pn����=�a��n$�%�����`�SG6|0���4�qhY�:�s6R��1��X��f����0�	��{�nm�0x��c�� �D^��I�y�������M�1C����.���5�a��o@��s|��j���3V0i�kT��:�Z�@%��xF��5n�n�"1[#�.o�B�p2>]T���W��9/���	=�� ��N$���os4��T�\�x���2�UT�#���a:�2��(		&�M���Xl�b�����c2������xG�Q<0 ��t�9������\�� ���U�uW3XwSR�)k�ZB�	�B1�!l-�������XaX_�=k��Z�6���by����VJ��N���]7��V�T#�|�S ��y���Kz�q�����"�������*�+��"�l��wMf�����(u
f�z��u��"��5D��e4,���p�cs#���P�^*�}�Ixaa���v��"��p���Z�t�#�h��zs�K�{f��-EZA.�������R$@��CC�LB�>u��5"�����e�}�Zh���m�,�v����2���&JO#�����\�:��id`��DGj�j7SJ����~��.��@	X����"��J��k�^������4�������1c��[�U���G��p��BQ$eE����1@
����8���H��9S��z����������Ql�p=)Q�c�Q����+;r�G���<.��Z�&6vp��XZ7����A����U��.C�X�>V�n��m��rV��Z�v����������w�q���7J�M�%v��������o��K�.�kj��}O����h?e�|�D�<S'����6�X�r���d��e��3��9�?����P��u���sxg��wE!Z�7B���Q��0�p�j�u�ED2	�x��<����L���d?"7���6���b<�JWQ��-��[v����QM�x �t�*�A��J����]
��r�bTB�^Bt�u�x
�`���X�
|
��>���m�_A:�sg�}��So8�N����4�a�#�M�l����Db�Aj+��k��b���ex�p>����8x�4��o
�$�7E1���F���D����V����G�
��9�z-�ZG�']�����/���"�Y��M��Jd�LIK����BJ
"����%�l��g�1���#�z���
�8�ULO-`�Op���K��$��4��s`��V���)������l"BQ��?o��x'���	rg���4����_~�5.����3�u�@��f��5i�^�Ir��?��h�����I�*F�����	����=2����sR����d�������	��"�r�2$a>�������/#���	bg�y�C�.R����`��7���'dL�<7Q3A;�/9��^M-W������?2(1ki������=+`���F�w���<4��t���}\���!)�3�1��EWN(7��]r(��wZ��������|��'A� �6s����>�
)gY1M��d1J1���!�b��!�����P���i}PZ����}�)fN{�OZ�Q3N@�[�7<f����p$!��u�q0/mL��-�:{��p�����F�D�5=��sQ���D��e����'�U��M�\=B��&�]�r�T#G�Tk���/�V�ePSJu$jb���� A$S�Q@���%�����mL�y�Q�0���h=}������@��aJ7���:�2�*p^��~��g�Fc6��]8��f���V����V9::*�Fb.��T�>�}����\� �\�3��9���p�#�c�~�8^m7�
M���5������'&�5qJBgX���d;A�I�p����L�Tml�8��[��R&Z6e�s6G� �X*��!�����c�������`��5�a{���i������VcJ�7�'�����(X5�&,6������p9���1�p9������/�D�)Q�%fMV+%R�Z���q�������A����6�7�y���R��e��0#��E�Z������b#D���a��^�D����Uo�c��<������N�f�����>��&VZp�fp0�������-��7����(GS)O9KM�]7��^�K\�+������R>��(�%�<\��c�NVn����)E#�h 1~����s<�wc�/�=�z�������z�XsM��#�xC���6T
G��t���P���E�U7Rma���pu(Y#�%`8	I���������P��M���m%��w�W���Lxa��U�����l�����)�/���rrNZr9�78����V�;}+X���^�Z����
I�X>.��I^��(w���tU�g�Fj����y������h4�g����+t^,���b����/OT�3`����]=:���sR4/@h���
t*�9�~��O�����h���q�f�Yl��8���`l6xa�+����Y.���J������7��.)��o�{\>�R|���-L|��|�2���+��{��u�_��9;?q���W���7<�5�i��m��=~�:���@�k���f����:��<���=��f�����q)���86���Q�b�b3�$�������]����cA��������$��6��@������^��_�����H�7���`
���Gx������2����@4"1�'������c��x��e���l�z���f/V�.�������S\H�9��U">*��p��rp���#�y��q��c�P����zSA%���[Kh��]������__h\�6M�9>BX�����gt,u�U��^�8Q�R�7fF��L���`GT	Xr��+���g�9�h��n�������`�4�#3i-^����7�L����-��A�b������a�z�#Gf�t}-�S�&V��y
�^�{+"����j�x���y���5���s,��X�*�-SP�-3W����s���5�c)
��S���D���%Z��w\bv����y�j�"s��l�=�H���6�[�-b�R� W�`��o���o.����j��%W���u�������4�e�-���s-`f����D��a��iEm�xq���3�W8c�%�s`��Z9�\�q�����Y����ao8)���#��tJ�R]�9��q�����>�G����6�j
���������~�#b������E���r;��b��a�e*���Ua8e��x\T�S��kZ����295U�E�eGB�D��t���0���^����E;z�Tn�XnR��|�bcK3g�@"�N���23R5=_uGZ?
t����8A�\����$^4R��G0`�����>j�#��_�<��J���5�H 3&������nU���!����d�F�{Ez�����?�_�\������.���K	�l�������"�B�V�?6�f�9l��� c�41�hDc�������w�0-��?s.`���7�z���X����6�5�(�'���p�{E���M��O3�eV\�|�Z���+3Z}��
jf�t�k/��������7\Z�8�a���DH�YL�6��[b��S.�(�9M5:MP�*�m5�Q~c���,)w�TKs����n��&y{�;H��9P�n�/*���0��B�X����s��f���+�r�z���4����D������nH����t���$%i7e��R��;����!��W��rc����W��x�h����^w��_I[�j���;t�cY���2{\<d[�1��p���*a���GB�"�gG�(�<c����P�&���T�O �x�B��
)L��r�C��=�;!�~��	�CEG��G����,W��1���s�8j&��5J[�O��R�����_��qrt0�����\
�j�8�2��+�w���F ���r6;lp�g����_Y�R}H��H�[�!�������1Fh��Q�%��������O3�:������5��������c�uA�y�+�H�c"1������Nj�g�B����}���S�]������%0�,�9*y�#�UQ<D8�aT��k�"g�����o9{�@�t���D�;�����7�h��s���w�����VK���|�`X���d������1�#m4�S�U����~d8}�L��AN��\�?�"Ph���p
drX���j����f]�������{xY��E������,��a����R���u�������ne����H���-�o���L����m����5�Ye�vj�w������=�;��g#��22b��R�j^�o���x�\�f������!�[�\s�8����x���/���
DU�n&�[	���G�����
��`e���$�������5w���#8���A�������9G��]��r�.���r����Q����2���.X�s��i\l`W�C��������Z�F���r�=�������j�(2O��H�o���	�������|���u`s���j�UX��*NG���)�4_''g�������\�������s��
nk&��c�I�`�a�Z=w�X���k7
�_���'��19q����S��Xd��l���GE�o<�(3�g�&���o�s�����1�{���5��#`��ls�*y����/��b*��r4>'����-$WM�n.��i�M;@v�zt���f9q����d�i��dq���P�����y�S
��2e�WkuP����{�2�`���������ev��a��$�V���d�T��<%�
����2�rWR�^L����P�����1���4n	
��GZ�����gO��5�M�^���������r��VN������#FQIY8��o������	�`!n�L8{����/�B}������r���_��F�����6X$��aH�"�G��������M��e��Z4%����~)��M�U��P��|v�[�@`1�����1o�������!�C}k�Y5�]5.����z@[�m�-��pO�q|1��T�����?�-��1��~F��H����A�A�h6�*����q�C1��?���d��w���<����<�!mQ�8O������k��a�a	����wJ�@F�F<PF����Y��Xr78bI�����)��_)��{���e:-��+�����5����:�t�Uc��*
�`�����J&��6D\_Q�����u&�j��1��F�H%4�����D:�N�QZo(���3
���
z���+��{�jz^�\�:?�pyv���v�����>�������$�T�����h�i�[��>��i���>��Y���}
`[��������2�����?���%;�}�����������u8����M��3T�����,k�
']	>���:%�h�;��������/?%�g�wZ]�������+��o�����}/RbR���HM����������<�:�q���k]Y��Kp
���BJ���)&�QCKP9���� %��Q8�TNk������d4�-_$����|M�Q&�O� 
T��
�G�	��	I����)7�5Ba�]�����FS/�94��5����*������h�;��	��(���t�d7a�w�L����:�6$����+���j8{9 �d�WZ�y�d��/��c���X��C��\D
��'�_?,���#^.G�qJ�He��#��S��y��6��a�:V��>�7�����<���~}���BV5%�?������J�J���������
���Q��n*�������l��b/!f�<~�K�������Y�7��;�6��R���7���hL��p��#C�8i\�k��&��V��Au���g�R�B�$l���]�j�s���r�����7
����3s���_��D4�?�Sr5��hq��JS�j����v��(e
A��5�����:�t�]K��m�3=H=�u�Z�Sf����C����.%pWf���I-�8�J�Y3�[h8
� �T��"�����p�w�{���K�X�oF�a{����	�&2��.$��NO��q8�)�B��+&`�D��@P���B�����`�zz<��6R�:�����p�ynX����ae<���Z�&M�&��5����3O�r!BD�d�)���;�������Hp�F�Z��s��U�dg�UJ�'9f)j��c�w�F����4���(]��E�����;^��s�x`�W�X�$�d�<��$m�,�����O��5����Z\o(�fq���oX�#���8����n{�q��,{�����P�����������`9�o=��;���g�=P�y���k���\k����6g�F��w�����Q�K����u���s���~���]x9F��q�@�}����B���7���t�v~��^f$v�z�re����`��+x���X�jK:(�g��=�R.���}3�;�� M�x-����%�����E����'��I�gO�o������[8�H�s�Y���(���9���r����C�ew���:�Ec�19�U^���~
4��W����2����`�R�2QK�b��e�������6C��k�^q��
Q����`�y�]"����+�x�fnWU�������W��>���5W��S�?�G�]�����h�s�
�{��:��"�|t�[:���`�w
�C'7#��h�t6ZqBQ��C`�ZB���B'`U����T����l��W%E����'%Gx����!�������`���rK=&���)�z��V�&�\M	P���upPm9����6��S�1s����0
�2�3���XjBIk�l`�g�z��Quu�4�t�2P���X�����=Z��'��H�16[U@T�����\o��?Px���+x�V�F�)�{�N�9j�F�^��o>|�����w��/s���1�+���������&{
J�*��������	���_~<~����p����S$#:���c�S�����q����Rq�#���D�T�{E�
��H��I1,�����)�������i��`��rr������1FOEd�B3����g���4h�h-,P�Qk.�����t*V���-�C���c7������\O��>�#I��"]4���&291+���=�t!Xx�U���r9B��������{�+\��=y[��i����70k����*���&�����3 i:7���!�=��Nw+G���]/�E�Z�8RTXI~+I��5��9l�C��{����H�>�����dX+�������1���M��@�P��r)5��SM����
@�9V��dF9�i8N�^G�!������7NK��N�q�S9�en��Oi���'��'��L2��������8}u�vl�z��a����I�rr4�z�����UU�wiZ�������G������(�"�fg���!�9Gz�����2��BnG#)����,C:��&�I�1���\�iK�����4��NZFb~���}�� `'g�7k�t��>Hj���G	
q�Pra�]��`W�
RWW�'�T	$~.N�����	,���������,f5o�_"�����P��0Q$
C�FiO����!X��RY���c�,~jw�u�]z:��=#tw�}��t��Y����SY���,�2s�n��=��6�c�)�_���w������u&������
3X=��2�=2r`z�����QC;��x��cD�P\�(�������hd3e3y����:�&��T�\�R2ZJ�u6&��������[���������RY	aJ��	�k�m����ad)TD#��\'p!bj$i��)X�Jd��`s���86�Z����*��8�	d6>��]@4I��O7���
w{y�+�o>(�y���}�IL�y����� �w/kO0���+��-[�o?��.OP�����Q�/������\�d��������t�6�2��`��M6���d��D=+9��E�P�Q�oB�)}8��*�JS�y��J�ZpUR��3������q��� T$�uj�F��g�&�:MY��d.�����R��aG	�Q�����,}tD�YLmZ�E��5���L��;��o��N4��*O��d1<M	E��3p���V�=0T���k���PM�^s��T`��0�2�99f_����|>��B�����8
��5q���s������A�Jb������\���LX�3H���l�1Ce%5)=`�Y����|���@Z�a��Y��?r����<<����oJ6q���G�9�;FC��)��7�+�E�&=%2g�GG
Cb2(.7���H�"L
����y�����O�0�a�=%5h-	���DM�L�\g��[�,����S[ry0[������������V���UlUU��{�Uq�U�Kf��fI0���QF��-�!���W�S����_��lMln�Wi-?��J���swr�M��L�]F3��&�$���m�s&]8�g��1������h�Y/#[pv�����<�TP��"��h��iMq���F����)u��!K�����w�f�m�L���plR%y)�bK%5);^2*f�zq�>�?9&�N����1)�b+���N"��q��x/rL��U����g>>��������!7'��P�yb���I=��M�M�{w8t�J�#�)M�
�$���?F
l����U����C�u�R��d��=N�������/��<QW ���QN@���W������Tz��� �y���� �PM)������b	��Kke9,��a��<������9J��R��p�W���a��%+���q���`����]����X
n��������<wpq2�����z�|��Ky������M�!8��]��J�^heq����F�1��!0c#U9m����d�Hl���B\���Jh��{
XR�� �8
,y=R����A��H���uV���U��ch��N��X =\���u�����7oO_]:�F�����������@����F�R������;��q�\�+��D�?����@��>*�?�s�u)z���v��9��������G���G������N����f��N����V�����<�n���~�oP<�g�I�����p0�p����f�3�
����=���\�wK��_9���l>��9�f�U�a�;���vF���. ��{W�7&����HeW� ��I�� ��s��:�9��s����ZC����;M����4+�	����>_���i���Zw3T7����\^�k���O���yJZmtx~��jt��B��@��FEo22o&����
1Nxg ���\�>��j���z���\4�� ����`N����(�ae#"��7;�(�����F%���[\`EF�;n����c��"v�����{�J��`sm���Rm�����t+�Wqxa����iY��N	B��*�jY1rB3�X�5�� �%��.�*�`�g?���
�P_����e�pt��O�����)�]:%{�*����u�(E�T���B�$(�������p�I�"��n���:�f��^�n:U��p���p{u��+d���z�b�Uu��#E���0l

���KlW@dla4���uH�8�0��-�2���5.���O��H�S��@b�Y;�'e|�������N���8��Y����9��*|L�p}�5��w�`�/S�KkL����H(%m��O���X�h�g�`E
�y�)S�~(e0��@�0�|�t(T''������s�cwp���Vmmn���b+�/
�*NfU'��8�t�m�(����/g<��H�h8^���C����0XB����NE�J�6��A�.A?����pU��G�T�kN����yE�:\d��pY����e�Q������a�1�;�Q�L=.k���\V;�:�.e�?�UI�n�T+pxp&y����T���d{]���5�V�_NC�>L�}^] *��J��S����S�V6��k���;|]+uF_�$������T��o�x
��9��C���R�^e�P&h{���|�I��J�<�i���h�d� �4i�#3	�5�!��5h9�C���A]c/./�{(��c-�e�L��7�_��fd�����������n�r'�H��P&���2��2"���4���P�DpF�C	�gP����;E����72���*MB?&M���Qe=��^�Y��r^��3N�g7E�\P���������=�O�4�&�U}*A��"�,<��-#G"L�H�=�]c�3�R�f�H}~e8m�n<�.�m:�����l'�j��T��x �����$`gn�����cX{��O��,�o������2a��/���+�2'�R��gR�X�:_�����_o/��)
V2F	(�6O��
���s���lF�������;����
�9��Se?U�d���<���[�%+�J������7�+�=��������0M�����\�~!���x��5��zU��@w��N��>���r�h"��G@2
��*�BE�
�ducb�Th�F������{�,�t�+;��\n��������i8&�NZ��9
"l_$�Q�>����Y�C���0�QRL������(��}�����������g�2�%���^	��XT(��),�b����~��%D9�w�����NE�Y	���*\�u+�9^e������2��']�>P�(qd��.�]���&�6��f�������]�qu��}�{1��Ol��M�w�������-D�v�V�5���6[����(,�V$V�FM2�����
�8%�����,+�]Fy�XO���}c�3���}�h��+��8��w��6����"Tn����r9T�&[�f����~P%��	�=�k�^x�j��?>�M�/)�����7 ��M���CN�t��q��1%X-k�h���Q��h��e������_���<�T��+�O�q��1h�������r���@I��������H�r��j��a6z���F�����Cv	�vo��}��z�X������mV�8�k3�[1}�'�����T3�|��q�?R�!j{9�W��X����?l�q�$5��Q�W�7��O��K�W�����f�3"��6V��.��O��>(�f�A@�BqM�_�_���O�����mQ��v���o�=�k�����Ob~�Yl�p��{!{<��7(����u5t���Goy�$���gRM�t�)F#6�k&��h�d��3QP�`����������
��N���&��`��%�yGX��?����"n��b5��g�������+!R�A*�enc���5=��\�D�/��1��H�5���O9����O'������O ��?;TE�Xm�ud�_f@w���Z
|�v�@��I�+U��T��=��Y��f�������j��9�V#.��\�H����]�����h�:���DFI(�K�j;8}�
�>|a�R;�2k�t�pv��@<L�$1�Q��j�jY�l���Wfs����}��_�9�*s���a��x�����~��?�������|�E>$
_�
�Q�%�<=���t�w�-�zx��v�FE���
��p����)��G\��%%��'�`����3��]C�T�����}�����cs��jz�>�6�BT
[t��J��"�P�w3�+!?6^��2�%��^��d�^c����y����?�������:9?�����*<�I�(���d6�|���]	�cX&\�g��s8f-7�n������R�C�gP�=�w��|�;�?�s?�7u�w�#�����ht��s[}�m�UG��6�Z����u�]��������������?�F��������9�
�]o0�vG#��N{�Q�?�~!��wX!����?����A���@�?�&c�6#�9��0h�D�{1p�v��N���F�r��sA�U46�1�u������f�m$��:��R���4�st� k�?������,;:[�V���\�#-G���8WcWq�
>:[���?�<�1��]-]��-�N�&���9?��x����74�����S���^|��@��&�����,XG�$G�W��_���I�q���X�E�}����h�dS�{���~�������"�@������1\I"q��x�T-Y��=�S!'Dr����Hc@��Me�N�+0�R�Y�����f���KAw�s�������k�6��U*�#[��o�|�#���*@�����'������O-��~�o1�cKMn��6@����h<}�������E�
�Fg$�^]��a��L�\� ���!��<����^���"�2�%��������B�F�j��U��?s���;p]�SV
b�Cb7f�E����Q��d�������>�U:O��Wdx>�n 1+z��O��:'��5#�<�N���\�=$���������	��C�K��Z�����p)F~�5��E[=>�6r���yl�=��+��������%�1��}�alTP���{�G_{��leO��p�u�q�W�_��9\J)�tC��wG*���X�<E���e�$�,���2�l�k����\H.�r�������s��������V�c�.����f�
a�A��?v���,,��c��@�����"������`����^�r������|HU��V[7d(i7�M��.[ir)M&a��lhYD�e-OE�b�2�������y ]�qY {�%���S�&C����I�F��d���X�������%�J���SsW%�2�#��tH����7a���������_���n���.��P6a�Q�Eu���'�
Z�������~�$���No�{��d�������vg#���'������M�3���C��3��i_��1Wxy��
��=`s�Q�"J��/#���
z�F
V	F$)H��4�ps`����Q��(�E�4`v�Y�Y���)�MB�(���G��i���w���=q�C��n,�d`�:���[�Nt�wK'�������l�2T
Tby���EX��:�hS�o'�h�X�2���J	.�Kti��]�48��� #3�(?������
\S�d� xB���I�1�Z i�T��7y^����z���Q�n�@;��)�G����!�6�XL?^L5�����#Q���6�Q4���g���O�A5V����Z��s�F2�e�������)�L�G���
=�S`�}�%i��
}��`
���� S��j�N��x�UIK����$�ZP:���Ea��4`m��C�|1�n���Ll8]�	y�����Je�.�3me{�CE��z�aq6��L�#�
�^������t����O��.���6��Q;��E�x�ii�=`.�i��`���QjK���[����R4�`�1�F��S�������K�/�Vp$��5��a=V:_t`H���l��� '�|�����)5/���h����:�]F����A�&����f>�Ig<9z#miH�E}�V���w�F�l�#�Q���XuOc}����5I���i��
V>�9�Q%j��U��1�P�%�~������C�c�"���c	'�J��ys��w'���u�	^��)���F�$n\3U����9�C'Yi�2��v�])�}o���B<8��|}��a���-����"����.�����U��pFM%���!��:s��dp�i����O�q�>�0�Uu}WBzU^AoO+���]W��L���������7�3?���/��/�CO�99���h�*,��W�`�
L��5�Is2����
��i7��?�����,Od`�������0��W��-��Kz��������Q��EF�������^����W����C�3���oH�����|�s�[�?��b�O��iv��:�N�7������?����y�����L'^��nu0��l�iM{�Ns�r����k���H��i�3���
~[��U�]�:�fWg����
�3��d*e��]����,a��jF��9v�*��s����Z�	�=��\�J�Q���+���y-n����6 ��B	��d������������_F�&X�
���B"
 ���Oi���M2<������qzbUr�F���rg�a_��P����UEq�������)����$Bvs���4��
vi�N�+���G��L���_(80����e<�LW����������)�;"h�rER$��3����D*��w3�w���nE�G�-TL/'���N3CF�.�}s��s)� ���N�J�S4�k�R#8���d� �g��J�+�	~l�
OPd�I��r����Qz
���E.����A�������w���2Y=wN��@���������n�	=>�H��vG��q%_�����]�.(r���D�q���e��e��:*I��Z�k���������5���}�XB�
RRq����N���h������-��J����JZ���(
�O��0��jRu���/��&*5�d����s�+�w��:ZR$����
�L"E��]�����B���V���9)&����G5����g�\��)�A��a�V�#���V2\�|u��w��WLR!f2�TO�H�c�"V4�I7H���"G_=a�t�Cq(
�q��J����;��P�6\�;{5���� �`?�
�{��l8���I����H��������GK�����i��7��Po�9jMB�,D0��`����,�L%�&7J��dD����4��A��������������b���h%u(T�B��C�T������FC��g�����8�*�=�|��(�A�rpT��~o|��tH���m#���m!�;g5��2�,�m����"\���~�L�� ��u���~�L��^�����i��o���7�!qL��zU5�*��c��O\�6?]'�������DtuC�}���hA���haxH�����Ag��3]�$�-}���LF/n��Z�;�^��g����kr��`�Yc����`���8�qT�"���/'��� I�CtF2u�3+�Yvum���lp�ffu����jj�e�w��>��8:P����i�Kr.����}w,��,JGX�O#%>8N$�*���d4�@pF^k8l���H���m#����mrt���7&����n�M����L��m�A�(�p���/�������l����'�1f��d�r[�co�������������vS>��6b7�B�h��PU��t��.���4�S���w�H�D��)�i#����A������7-��j�]�������h8��L�zj����t��Nb�A���|v��Ph,�a�:{�=��&�P�b��6�"����nK2�6�V���j(���Mz�a���y#���^{�{h7&�p4 �>��������%�#��^&�����^��VK��Qk8t{p�����eX����kS����`H.~X�Y5�m5�<��M�i������2D8�����7Ug��tF@��~����q�5+�*k4�
q�i�3h;=�o��l�k�p`�y�j{�V9�����2������9��Lm�.D���;�P19I��K{}i�jq�n4��z_��z�#T����6��~��c�
+���l�S��dvP��;�bL[�~��]�=�����$Q%�ld����M�o;�@���6q��X'T�A���!7��|�9n+�ksz�I��0��$��Kl��N�K����Si�vKi�S#�@!�-'Vf��%0��������NQ4��w�;��+B�GY����}S����X��l��M�f2����'�!g�eq>l$�`�����>�R���hs���}��f�hx�f���X�3���vkvsf�Ii�b|y,Q)�~J��(��/�������G��3I�>%�*����Ll��Y�,�H�G��%!�'#It[��[94�h��`
"�������c����Q�)<��l�:�F��y�QY�&f:��$3"�R�x��� 4bo�%���_~�-���}0���w��m��Ft���[o��c���E�	nH8�����K�>0J��W��_����/:N�E����;(�T���b����/'�j�Bp���ad�v���2tdEc�w5Zq~W�E�#�+e�9�a���.r��Lp"�+����k�$3���
�_y�����E��<�����GBq��G���z�����^����I�^��j�&�N����{�&<�������z�����]���#�'��8�{L��Qw��s������,�?���,O��>q������xRn���^p����J?�����u��(fy��|G��gkn�V�l���jKa1�2��OlE'������[���Jp��Q�D��Eb�3�'�.CU���@��+���"J�O�#;�bd��5�u�qoT��$6��)�0�\&=`�)�'��0*&@�YRQJ(&��O��5��2�7w���2U�'�e�D��MR^N��ml�A�=���L������V�~	�>��>�����$X����p7���fL�������j���d��v����?�?��l��������n���F���k�&~{4�6�Q�?��]�9������I��f�8?�(���f:F5�JE!skiDj ��&�#JZ��H�j���Ae�U��k~��Qq]n��n</����T�UavM���v�NL�A������[)!�T�V���/�^��	F�2
��E�3�D��B�z���I!�<&�XCB��q�q@ke��'�b�5!�#&��J�;�p(�3�`
�,������K���s�=���
3m��8�	V+G	���R���5e���^�}�|��0�k|��Wa��S��P�D%M$s��$9�x?/�J\��
_/X?�s����)z63FT�i��*d�cZO98��������M~��:��uS��M%
���m������6P�$��p��(�����1�-'xYTl�b7;9����k�T���� �#����h�&#w2,�3b��Od���d���:���6��&���"���a}7|a5���Tj�Y�8v�% �~�4��3~����������m���k�V�;3/��C-W�4h�Nd���Xh���i�7k� ������ �d�-p���D*�?D
"\
gK���@Fe��*���$��nH�*L�(,1�N���m%�dU}�K3��%��(�@j�i���D���	>}.|�$���lJO'���Q�=������K`)6����/R�I
>5����v'_����hZL=h�~�����oO�}8;���?������8X�����;}����D��N:U�T��1Ad��'5����99/7�iJ��b ���'M�
55�8�*����zVG�7�+�i�������4��l�����X�Y_g������:��_j��b�i�B68=���)}��)X��9xOv����=�q����$-~N��F�N�(�[Xi�Tu����-�[J����9{sz�����1������\�=���G����:
�D��|^�n��	����T�������X������%>�R�	d��q���[��,�����2������b�R2�Y������h �TR_R$��G����h���gN�6q'W�i<s.��������r�}����f\����_�~�/�%��������D���k���u������;�����9���o2����7my���u����o�z]��r�C�������Z���ZR��03�Mw��9������������'yy���	��Z%��@�AT�M@���.e�!�d�!���V!���y�zN|	�����8�Y�p��q�5���=��eV�.����z����O�s�G~'@���������T�]|#1��J������n�n�<�����g��Q��yCQG*�7u17o��b��&�V(U���p�em�#���p�p�E�6SAX��a �%X�����!h��bl|��.9�����i=C��x���?2{Q����
Ky_�������>�y��*7��=C]_�DQ��h��n9},
z�����7������S"���>Z���t�N�@\����At|u��'f��t��]S�
,+�Gj�]��r`�����g���x�a����9�
Y�s��D����m�Q�_����{u	��<}��U����,{��9 ��t���A�(�W���=U�|���u��`6p��E�Y/Q�y�A���.�~���p������^��}-�K�����HE7�	DI��
+q-N��f�L*���)���1�}f].�&��"� ~�R�/��*dHp��-X��*2?�o`��Hi
����8�����"��}
V��D���j�1K��UNU��
!Xc9<������:+7�K*.��Jj���T���j���g�~�],#-Y1��x�gO>��<�l�9\`4%��3R9&���B5����xm4�B�q���%�e��+\k@g�vIs�`6��3�"f*�j�L���"�gA�����-^���^����Y=��|�I��}��A��_�Q� Cb��di��XD�1�d�	�����*��"��]��2�T"�vg2�M
��oz��V4�M��Z�@>js�����j~;���������Wo��(�uo���&TT���l���b�]��V4fy���.v����9V[e��H����t�#)���;dpt���5,�o!�����r���L�E$��i\h����jfnd[�$
�\�k�:)�P]���?�K����=� ,�`�����19&�(g���|8��D/���v�c����oO��;w���X�(�U����8_�H��F���\��5��S�+!��V�i5zp����)����d�hE���>%2��Y�Cb�P'��[4	`��F�^m6��������FN��G"IK\*0���t��Ig���:��r���J���]�jK�o�����61�(�Og,\��e�����i��f��_��<
iS�+5��������+'\�_z
�+��KC=z��A��D3��������1�/�p����������	�l�`�]�.W[4��!^���Q0gVD5��1����yH�FpG#���dU�Ez/@#n��l��b.�~o4�5�����a��Fd�!`o���FU�u����K��2(�|.g�Q�"��=`/����r�s�Fi�������Q]���%�X����M�2�.����j��a�)vY����'����JL��~t��!J��%�
�z�v��/�4�0���u��q� z�/}��B��>0x�8[�n�.�H��8d
���F�i�{�MD��8���:@��rJ�����$?���Id�$��3��DT�oDC��8#)d��,�Y���p&I���`s�L�����~�3h�S�>p/��ss�'KY�O	������|��v��hV�#k=�C�������:6��9f��cC�.|@�U�Ad���C�q}�����$�V�o�mK�(�kl����U�p?�q%������'>06 ����$�CS@1�(�X��q6�-�jb��X�]����J_]1�U�`s���=j7��>����9�9������M�y��_\���r�l5�T�6�"����r��H���~���e��/��Y�k�(��2���{�,N���	3i�M��[M|�g�����0L}���� �kf��Z��)!!���|I`�Q����~��_3D�x����0P������&n�g�?B
��	�)J�4R��r����08�*\������Z��N�����^��xvvg��3g�;V���������=��@�����{�5��]�l��bK�n$��	�)G8�[2`8=W�P����2N�_0�E��G�f�b���6��P��$����D����W.4��`�a���t��
�����|z3~k������X-�Z�?_���A#0>Ew��;���i������|��;��VS���?�o����N\�{(n�o'�������\J������b^���|s�	��������<�
-���5zD�(���qK���:�$&��#���f0\�����"�6��|D7�d�N�e��2�C����*��Zg��p_�Q2���1��V��9u�v��o���<<�3��|�������������7k�O�3|���p����<�~����`}��'x���8N��Y`E�����5��x`�}H���X��)[����v���ppbe��e�+�R���������r��/�U���I��B��	���5p��sM�RR���l��B0HBX�|	+��
���5~���t����nY�G��)JE0F��F���k�D�Y�p��OR�g����i�oh$����n<~"�f��������e��E�8K�VZ1���r��s�����j��<��q��yb+�9��;M�F�+�q����kM#j`�e�1����cj�(��6#W���ScF���Q��&mj�u.�j��
\����:�U`���_�gsV������|1%K
ZOV�����7t����Z���3u�J�X��-��h�������T���z�>���E�*�}��P8pY��32ka��.��c/.t��1)���):�b91�m��b|�B-*P��]����3��@G<.��(\1:��q�a�BC>����G7XXIPS�4:��H���u�����q���e�$���*8���#_��/�U������ll�d'R����5�`)m�+2���f��~<�
���^�7rr���5C9$����D�p@`�����'��CI����LHJ�t�T�Lx�s�o��n����m���-��s����OagiI-l����q%���a�V`8�&��)���{���n� ��[^.�{;_N���&"JN��j�8��������w��@s�"����`�����3Z�����c&�*f>�|���J#
�1{,A��c[/��/�S;���H@2*@}��t�E|��EZ8r�b���dC�=�����:�������]�5bAc�x�%^&+i4�VI"7���E�?_���_<��q?8��:�����h�=m������	��*�S��:g/B�iFX�j(�zUP����&���@��������4����C�cwI����j5�N�]eh�m3�1��K��6;����	���+cN{
���Y���������8��cP�N=�/P�8����,
]#�oP'=�P5qc��������:�[�5�
~�m�q5�� ��� ��������Vlk�m���
�FR��7������c��D-������=$�PNL��<�`���`=�1_S��������^;������-9?$��d��,����2pu���q�:�r}l����h�����j����R--���8sGX���2�'g�+��c��X�|K�3WQdb�4YJ'����w��g����c��4Z���,�h=s��f��$ZK�������zf�����l����}�Jau�Y��F��d�/��.J��i��W�_��u����������KB�H�K7QCZ=z��E�z��F-\L��3�4i��I�&M�4i��I�&M�4i��I�&M�4i��I�&M�*���`�
#33Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Amit Khandekar (#32)
Re: TupleTableSlot abstraction

On Thu, 4 Oct 2018 at 22:59, Amit Khandekar <amitdkhan.pg@gmail.com> wrote:

I have only done the below two changes yet. After doing that and
rebasing with latest master, in the regression I got crashes, and I
suspect the reason being that I have used Virtual tuple slot for the
destination slot of execute_attr_map_slot(). I am analyzing it. I am
anyway attaching the patches (v12) to give you an idea of how I have
handled the below two items.

It seems to be some corruption here :

@@ -956,17 +978,39 @@ ExecUpdate(ModifyTableState *mtstate,

- tuple = ExecMaterializeSlot(slot);

+ if (!(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot)))
+ {
+ TupleTableSlot *es_slot = estate->es_dml_input_tuple_slot;
+
+ Assert(es_slot && TTS_IS_HEAPTUPLE(es_slot));
+ if (es_slot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
+ ExecSetSlotDescriptor(es_slot, slot->tts_tupleDescriptor);
+ ExecCopySlot(es_slot, slot);
+ slot = es_slot;
+ }
+
+ tuple = ExecFetchSlotTuple(slot, true);

After the slotification of partition tuple conversion, the input slot
is a virtual tuple, and the above code seems to result in some
corruption which I have not finished analyzing. It only happens for
INSERT ON CONFLICT case with partitions.

On Wed, 26 Sep 2018 at 05:35, Andres Freund <andres@anarazel.de> wrote:

@@ -185,6 +1020,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
{
TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);

+             slot->tts_cb->release(slot);
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)
@@ -240,6 +1076,7 @@ void
ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
{
/* This should match ExecResetTupleTable's processing of one slot */
+     slot->tts_cb->release(slot);
Assert(IsA(slot, TupleTableSlot));
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)

ISTM that release should be called *after* clearing the slot.

I am not sure what was release() designed to do. Currently all of the
implementers of this function are empty. Was it meant for doing
ReleaseTupleDesc(slot->tts_tupleDescriptor) ? Or
ReleaseBuffer(bslot->buffer) ? I think the purpose of keeping this
*before* clearing the tuple might be because the clear() might have
already cleared some handles that release() might need.

@@ -56,11 +56,28 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
HeapTuple       tuple;
shm_mq_result result;
+     bool            tuple_copied = false;
+
+     /* Get the tuple out of slot, if necessary converting the slot's contents
+      * into a heap tuple by copying. In the later case we need to free the copy.
+      */
+     if (TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot))
+     {
+             tuple = ExecFetchSlotTuple(slot, true);
+             tuple_copied = false;
+     }
+     else
+     {
+             tuple = ExecCopySlotTuple(slot);
+             tuple_copied = true;
+     }

This seems like a bad idea to me. We shouldn't hardcode slots like
this. I've previously argued that we should instead allow
ExecFetchSlotTuple() for all types of tuples, but add a new bool
*shouldFree argument, which will then allow the caller to free the
tuple. We gain zilch by having this kind of logic in multiple callers.

How about having a separate ExecFetchSlotHeapTuple() for many of the
callers where it is known that the tuple is a heap/buffer tuple ? And
in rare places such as above where slot type is not known, we can have
ExecFetchSlotTuple() which would have an extra shouldFree parameter.

#34Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Andres Freund (#29)
1 attachment(s)
Re: TupleTableSlot abstraction

On Wed, 26 Sep 2018 at 05:35, Andres Freund <andres@anarazel.de> wrote:

+
+/*
+ * This is a function used by all getattr() callbacks which deal with a heap
+ * tuple or some tuple format which can be represented as a heap tuple e.g. a
+ * minimal tuple.
+ *
+ * heap_getattr considers any attnum beyond the attributes available in the
+ * tuple as NULL. This function however returns the values of missing
+ * attributes from the tuple descriptor in that case. Also this function does
+ * not support extracting system attributes.
+ *
+ * If the attribute needs to be fetched from the tuple, the function fills in
+ * tts_values and tts_isnull arrays upto the required attnum.
+ */
+Datum
+tts_heap_getattr_common(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+                                             int attnum, bool
*isnull)

I'm still *vehemently* opposed to the introduction of this.

You mean, you want to remove the att_isnull() optimization, right ?
Removed that code now. Directly deforming the tuple regardless of the
null attribute.

@@ -2024,7 +2024,18 @@ FormIndexDatum(IndexInfo *indexInfo,
Datum iDatum;
bool isNull;

-             if (keycol != 0)
+             if (keycol < 0)
+             {
+                     HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
+
+                     /* Only heap tuples have system attributes. */
+                     Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
+
+                     iDatum = heap_getsysattr(hslot->tuple, keycol,
+                                                                      slot->tts_tupleDescriptor,
+                                                                      &isNull);
+             }
+             else if (keycol != 0)
{
/*
* Plain index column; get the value we need directly from the

This now should access the system column via the slot, right? There's
other places like this IIRC.

Done. In FormIndexDatum() and ExecInterpExpr(), directly calling
slot_getsysattr() now.

In ExecInterpExpr (), I am no longer using ExecEvalSysVar() now. I am
planning to remove this definition since it would be a single line
function just calling slot_getsysattr().

In build_ExecEvalSysVar(), ExecEvalSysVar() is still used, so I
haven't removed the definition yet. I am planning to create a new
LLVMValueRef FuncSlotGetsysattr, and use that instead, in
build_ExecEvalSysVar(), or for that matter, I am thinking to revert
back build_ExecEvalSysVar() and instead have that code inline as in
HEAD.

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 9d6e25a..1b4e726 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -490,54 +490,21 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
EEO_CASE(EEOP_INNER_SYSVAR)
{
-                     int                     attnum = op->d.var.attnum;
-                     Datum           d;
-
-                     /* these asserts must match defenses in slot_getattr */
-                     Assert(innerslot->tts_tuple != NULL);
-                     Assert(innerslot->tts_tuple != &(innerslot->tts_minhdr));
-
-                     /* heap_getsysattr has sufficient defenses against bad attnums */
-                     d = heap_getsysattr(innerslot->tts_tuple, attnum,
-                                                             innerslot->tts_tupleDescriptor,
-                                                             op->resnull);
-                     *op->resvalue = d;
+                     ExecEvalSysVar(state, op, econtext, innerslot);

These changes should be in a separate commit.

As mentioned above, now I am not using ExecEvalSysVar(), instead, I am
calling slot_getsysattr(). So no need of separate commit for that.

+const TupleTableSlotOps TTSOpsHeapTuple = {
+     sizeof(HeapTupleTableSlot),
+     .init = tts_heap_init,

The first field should also use a named field (same in following cases).

Done.

@@ -185,6 +1020,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
{
TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);

+             slot->tts_cb->release(slot);
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)
@@ -240,6 +1076,7 @@ void
ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
{
/* This should match ExecResetTupleTable's processing of one slot */
+     slot->tts_cb->release(slot);
Assert(IsA(slot, TupleTableSlot));
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)

ISTM that release should be called *after* clearing the slot.

I am copying here what I discussed about this in the earlier reply:

I am not sure what was release() designed to do. Currently all of the
implementers of this function are empty. Was it meant for doing
ReleaseTupleDesc(slot->tts_tupleDescriptor) ? Or
ReleaseBuffer(bslot->buffer) ? I think the purpose of keeping this
*before* clearing the tuple might be because the clear() might have
already cleared some handles that release() might need.

@@ -56,11 +56,28 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
HeapTuple       tuple;
shm_mq_result result;
+     bool            tuple_copied = false;
+
+     /* Get the tuple out of slot, if necessary converting the slot's contents
+      * into a heap tuple by copying. In the later case we need to free the copy.
+      */
+     if (TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot))
+     {
+             tuple = ExecFetchSlotTuple(slot, true);
+             tuple_copied = false;
+     }
+     else
+     {
+             tuple = ExecCopySlotTuple(slot);
+             tuple_copied = true;
+     }

This seems like a bad idea to me. We shouldn't hardcode slots like
this. I've previously argued that we should instead allow
ExecFetchSlotTuple() for all types of tuples, but add a new bool
*shouldFree argument, which will then allow the caller to free the
tuple. We gain zilch by having this kind of logic in multiple callers.

Done. See more comments below.

@@ -56,11 +56,28 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
HeapTuple       tuple;
shm_mq_result result;
+     bool            tuple_copied = false;
+
+     /* Get the tuple out of slot, if necessary converting the slot's contents
+      * into a heap tuple by copying. In the later case we need to free the copy.
+      */
+     if (TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot))
+     {
+             tuple = ExecFetchSlotTuple(slot, true);
+             tuple_copied = false;
+     }
+     else
+     {
+             tuple = ExecCopySlotTuple(slot);
+             tuple_copied = true;
+     }

This seems like a bad idea to me. We shouldn't hardcode slots like
this. I've previously argued that we should instead allow
ExecFetchSlotTuple() for all types of tuples, but add a new bool
*shouldFree argument, which will then allow the caller to free the
tuple. We gain zilch by having this kind of logic in multiple callers.

How about having a separate ExecFetchSlotHeapTuple() for many of the
callers where it is known that the tuple is a heap/buffer tuple ? And
in rare places such as above where slot type is not known, we can have
ExecFetchSlotTuple() which would have an extra shouldFree parameter.

I went ahead and did these changes, but for now, I haven't replaced
ExecFetchSlotTuple() with ExecFetchSlotHeapTuple(). Instead, I
retained ExecFetchSlotTuple() to be called for heap tuples, and added
a new ExecFetchGenericSlotTuple() to be used with shouldFree. I don't
like these names, but until we have concluded, I don't want to go
ahead and replace all the numerous ExecFetchSlotTuple() calls with
ExecFetchSlotHeapTuple().

Have used ExecFetchGenericSlotTuple() for ExecBRInsertTriggers() and
ExecIRInsertTriggers() as well, because in CopyFrom(), now with
partition mps, the input slot to these functions can be a virtual
slot.

rebasing with latest master, in the regression I got crashes, and I
suspect the reason being that I have used Virtual tuple slot for the
destination slot of execute_attr_map_slot(). I am analyzing it. I am
anyway attaching the patches (v12) to give you an idea of how I have
handled the below two items.

It seems to be some corruption here :

@@ -956,17 +978,39 @@ ExecUpdate(ModifyTableState *mtstate,

- tuple = ExecMaterializeSlot(slot);

+ if (!(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot)))
+ {
+ TupleTableSlot *es_slot = estate->es_dml_input_tuple_slot;
+
+ Assert(es_slot && TTS_IS_HEAPTUPLE(es_slot));
+ if (es_slot->tts_tupleDescriptor != slot->tts_tupleDescriptor)
+ ExecSetSlotDescriptor(es_slot, slot->tts_tupleDescriptor);
+ ExecCopySlot(es_slot, slot);
+ slot = es_slot;
+ }
+
+ tuple = ExecFetchSlotTuple(slot, true);

After the slotification of partition tuple conversion, the input slot
is a virtual tuple, and the above code seems to result in some
corruption which I have not finished analyzing. It only happens for
INSERT ON CONFLICT case with partitions.

In ExecInsert() and ExecUpdate(), when it's a partition with different
column order, the input slot is a slot returned by
execute_attr_map_slot(), i.e. a virtual slot. So, in ExecUpdate() the
input slot->tts_values[] datums may even point to existing contents of
estate->es_dml_input_tuple_slot. This happens when the set clause of
UPDATE uses excluded.* columns :

(From insert_conflict.sql)
insert into parted_conflict_test values (3, 'b')
on conflict (a) do update set b = excluded.b;

And ExecSetSlotDescriptor() is called *before* extracting the tuple
out of the virtual slot, so this function clears the tuple of
es_dml_input_tuple_slot, and so the input slot datums pointing to this
slot tuple become dangling pointers.

Basically, we should extract the tuple out of the input slot as early
as possible.

I now have a new function ExecCopySlotWithTupDesc() which extracts the
tuple using dstslot's memory context, and only then changes the tuple
descriptor. Effectively, the dstlot has a materialized tuple.

Used this function for both ExecUpdate() and ExecInsert().

On Fri, 5 Oct 2018 at 20:28, Amit Khandekar <amitdkhan.pg@gmail.com> wrote:

From 06d31f91831a1da78d56e4217f08d3866c7be6f8 Mon Sep 17 00:00:00 2001
From: Ashutosh Bapat <ashutosh.bapat@enterprisedb.com>
Date: Fri, 31 Aug 2018 11:00:30 +0530
Subject: [PATCH 09/14] Rethink ExecFetchSlotMinimalTuple()

Before this work, a TupleTableSlot could "own" a minimal tuple as
well. Thus ExecFetchSlotMinimalTuple() returned a minimal tuple after
constructing and "owning" it if it was not readily available. When the
slot "owned" the minimal tuple, the memory consumed by the tuple was
freed when a new tuple was stored in it or the slot was cleared.

With this work, not all TupleTableSlot types can "own" a minimal
tuple. When fetching a minimal tuple from a slot that can not "own" a
tuple, memory is allocated to construct the minimal tuple, which needs
to be freed explicitly. Hence ExecFetchSlotMinimalTuple() is modified
to flag the caller whether it should free the memory consumed by the
returned minimal tuple.

Right now only a MinimalTupleTableSlot can own a minimal tuple. But we
may change that in future or a user defined TupleTableSlot type (added
through an extension) may be able to "own" a minimal tuple in it.
Hence instead of relying upon TTS_IS_MINIMAL() macro to tell us
whether the TupleTableSlot can "own" a minimal tuple or not, we rely
on the set of callbacks. A TupleTableSlot which can hold a minimal
tuple implements get_minimal_tuple callback. Other TupleTableSlot
types leave the callback NULL.

The minimal tuple returned by this function is usually copied into a
hash table or a file. But, unlike ExecFetchSlotTuple() it's never
written to. Hence the difference between signatures of the two
functions.

I'm somewhat inclined to think this should be done in an earlier patch,
before the main "abstract slot" work.

Yet to do this.

There is still one more regression test failure in polygon.sql which I
am yet to analyze.

Also, there are some more pending points of yours that I haven't addressed yet.

Attached is v13 patch series.

--
Thanks,
-Amit Khandekar
EnterpriseDB Corporation
The Postgres Database Company

Attachments:

pg_abstract_tts_patches_v13.tar.gzapplication/x-gzip; name=pg_abstract_tts_patches_v13.tar.gzDownload
����[�<K�$�U-!>���CDp"w���������N�hwF�3;���%+D�]�=]���V}fvVZCp#�"8a�v� �>���7�D���O������^fVuuu�g�����}[S��/3�{�����=8i���9T�������z�m������R	R�^��x�*5�)U�V��r�Rj�S�r�Y��H}Y��|��!3��5m���w�����j�Zp����n�j�_���Ti4��M�)-k���O8�;�W��I�P��O�R_���o<x&�����H�����z���#,����SS�S�gX,V����b�����)v����&k������U�&�R&<�X�U�����j�����W��_x�����*��*��*��*��*��*=��
~1��|R�������d
Vwc�?�����K����������K�����O���P�1��c�?��A`��������o��������]��K,�?b���S����W����?���n,��c�{��������I,��2�3Ac�������������?��_������l0�X��b�;�������_���)�����b��\�+���_�UZ�UZ�UZ�UZ�UZ�UZ�����.�\H}r����O�R��p��>��"����x*�g�p`�*�O�R_�<�9@
��4�?}�����	�Q&�����]���� �J}���(|��R�o|
�Z�|������l������-�#�_�GX��!�;���|���
�{��|��>�
�,���L��@������_�2��'m��$M�����1�ct@<<A����#�#������=���k;�=Kg�oQ���~q-u�Q��J�I|���[��>k�c�m�i=�������{p��w���}��q.�(
�]G+v�v�YzQ��}j�.�a��h���TU%t�r��tk�J�^/:�NE�THY����n�������l���t������-�����F-A���j�X��F��Z'�1���K��$;��/���q��������s������2���\�mb.g�u�O��c�:1��T�1de��I�\�K���\���s������W�<`L$���M�F��Y^D���o��M�C��fw���"#�������M��;���{�s�_�P�Y-� ��"0���l����A��n�����}����&��y��M��a!!��T[o�S��Z��k�e�iv�l$�@�eX("�^�W��(O��t��L�6|�����)�%&K�f����aA9>aH:�z���n9F;��M
�������\nnR���+�=�e���~�2b���h$$t�~(�\(���B4^H�N�M�*��V�6X�3[��0���G�-Y�����)�Y�I�\��j�\Ei����Sj:
�I9�U���W\z\�l������7�������=Xq�qr�^Z����C/���#����S��=[?���Z��t��v6Y�����)�������m��4����Z�i��wpk�����k�Wv^?~���rQ����B{���9>��i��d��b�D�jy��DDD��]H�v�\�	�z3���z�(��m�&|�
��q	�r�
�V�����'�C�~Kx�]K����CI
�G��,(������$g�js�"
<����9����z�LZ�PkV����T�yz���?�u�����W�k���K�/|�u�+�$��|
�Y������a�����
P�����]x
��K�4��{���2�?��GY�UZ�UZ�UZ�UZ�9��9�/+B�C�Y�������^�yX��3���&�V��1,��tx�!���cW4I8�Y�wb��5Y���ZKN��5�Xa!�0��11�y��Y\A��y��P��l��w�aiu�qc���ik����GZ@P`�v�V��$��L����3�u�p��F�&V�E��ra�&���,�Hr�:9�{�6y�]�w�n���;����EnNl�5��r	#e��r�������K\���8Y�����I:��?��fTQB��t������;G��L���nW.�7/Q}���>5/]?T4������U��qi��0��L����3�3��"6�#v�Prb�2������d�#��a���:�����8��p�8���
��7�{:J/�]���y�/���$�&��iW�K�RY��O���U�y���=��0h�v}���wU��V#�<zE���Cc��?T��j��?���7*���?<����}R�*�N��A�N�S+i���P�[���]R���V-�}�"�l@�MR*]��H�$�h������Wz���= ����{��
�3�8L�NA��[�[�c�@��<��;�z����\�V�_�T�R�WK�c����k�������I�\,��$(�bW2L"���)�QDUl&������a���NG���z�{��Q�C���)2"Z��	�b[g=C�aM�f;�mr��H]?l��z��r{`�y��t)dTU���xn7�����f�]R^_'�:#��K�8�����I�3,��u��Sm�y�0�BO�#�Bb����<'�,�������p�-"�y  �#7�J.#�Sj2�E�e2�b�	L�����`l��U��
�Nm�Q
v3#�	�&���]_��)��7nd�i�0(G�������
�E1��
��X���' ��u0�XL��Z�{x�����#��F��EF�@1�Jt�2Dxm0��A��K�rM���2�>�r����$�g=���?�>\��k�&N���
�Ic���x�`~��ySo`���0���&��Y������^�T��E78����Z�/���\MPl^�Tx��Gh�D���h�������p|(���@wt�3���G	�NX� ��Hy��w���&u�{.���Q����K:�!:�L��	�P	����~��M�[h�C>����%�\A�t��
�����+A}D���X�Z���q�9�b��k���L\���2�(
�
���o�(��a��D������(��!��-�Cw�x��n�O�\n3�!���jg�����.��&2qA��t&�U	���'�s��A1�����fS�7��BD��r���c:N�7����V�G?h_��a����LBv�g�#y(��%MjI������N=�F�cV:}��Q��J�	b�2������������e��������w���F�kh��PbV�;H���N9L���H�SB;�M�M9�e�g��Y��w���?����c�u����U`z�`���U�JJ����>:��z��6\nH:$@:z�"�86-k�|����VoKq�&��#��8b��Ns������*g�f��u�H�'�QH�<�*
��o�yI[H�l�"�.h��
}���F�A����:C��g���������$�5@y��N���*9(�� )��W6��i���(tI�2.�U�Y�qb�L<*�0�.����No��@1Y�8�ld�B�h����s���
Ia���P�D��XRXD]��xg�f���k��$��e��]yj'w����
?G�
��J�o���C��Q���p�O���Q��?m��E��C�������Nf���BT�((�?-,��@�_'���w9�.����9a�"%�	X)�$�stt�(O�j��l/P"c=�!Pp��0�#M>1���{���-�22�G8�1Re���>��D�^�;�(������I3��r-�V�^�Uw�)r#2#M���������X����J�JA�5��jI������h�@�E�T�h��DS��j?���t�Hi��6:Ag�Pv=(B�V�4>���'�s~�J�����#�"��JQQ�.�=(>%&��4���"��s�W���	���k��$���L�H���0A6(�/���	qE��1�
 "�0�cx�=��u�JM ��S\�YX��9-��#f ���8PW"�k�!�Jb����f\�b��%� ��}�\D�b���:x8��S>�!A8t��(#Rb�k���h=@�N����3=��Oz��6u�+D/G�{��	�Nd��� ��b�kO��0���M�����;�;�`���3~VAH(x��b"�`�4
&N����B������O�GP��&4g"Z�t�9n���	��#���g�M���YC��jv������[�b���b���S~����=�4` �u�����T�:�A���^���.�Do�	�5��(��h"k`�V61�I��������}�#��7��X����X����E�'����2����4�^P�����=�F���A��3]�dgoO�Rv��i�����������G<�P@�l[�����g�y�J��&(���~a��kB�<j�+ q����S��	��x����qp����H�T�|�~��0�&G0J�p(\�`(S���r/4��oX��v�5�T�-�8���9f"��u��5��*pGN8������#��(��()O�v�s��w�������/��(a�#s+�Z���"����m�p���m�#~�+w���6��#|��:`"'�Q$��tf�	�&�
�T�(�(^�&�M$c��H.���z-� J�&�$��[;���v��r�w�0���=��e�����������
:�9�|�-t`��9'm�_�\q�p���(��u�6�)�=������'7����jB,|���	ldx�i�4C,�����L)�|f������#<����L��1��I��W��@���3
�����T����Q��?���3bt"�������2cFI��Q��|�3���g�F"�3J�����"�3�%�g���?s���<}E��i���e���2uF��Q�����(���Q��t#jc$:�,#:�,�W��W��+���K��ht^Y8:�\6:/t�<��Pt�k�9������Jrtu(�����JZ�����T5sG���D��M���\����"�y�k"��Xt>���y��yC)����x���'�&):?6�R�b^�.i������h������~?��+��<�)���W��W&D�6$F���D��eD��ZRt>*hG��_���+K��+F��d�Lt~J.��=3:m�b�����M�|%��F��|�E��E��IK��D�����jZF�[����W���ye���'G��<�F��&l������S��e�/��r���25:��P%�,39:7�G�����/��+�������,,UE4����)���m<?�BCgv�/�7��Y*6�z�V�����c��������|�(���O�%��{`#��(�������"zSK�j{�b��`�dyc-Zh�W������1����5iM<�A�����U�2���}��I�Tk���&��`0���g�@`_n�=l��im��>n���e��%����*!��V-�Kz�P�j�z�9E��p��XR)q���/�����������RH��O�f� 7�`��c�x0�^vf�
����<���z�m���fG���%�rQ���=�t�XhK�wG�[z|�iS��F|�
)��]���>���Yb��G�m/W=X��"�od����F������s�J�qCK�/�k�����;���[�
TH�R(j��/o�����+�]����5�	^�v=pU���RT-��p��-�����j�V��]iV����G����e�N�^ktJ�n��k]����+�f�R����5��f�1�����f�����O������X��m�D^/_�4����.�W�p�LJ&�����@2������RTe�3�V���0��������[�HA\w���/{����m%�����*�����E��_��]�����Jr���}��Cib��pH+�&����0��8��$���
E���(%��"�
�y�9�;�6'�l�� Li���6�Z6w7���h�[�4Qw�RH�hh�\��z��4p���r
���f�m�O�x49`���C�AZ�xRKoL���+5G�����c�w0��_�Oi���y6�Z���p���!.pW�7�<-���oH����n�hw�;���R#�M�
����� �o����_�wg�^���%����a��-�oy���JDQ���Y������Q4Ct�p&���hl7u0���8$�X����'�����������6h8)�Qv�V�qs��������.W���f����u��\���ZY��6^���H?zC������B�����q�s����"��^���\%��/��hV�M�)���F�KU!d _�/���y���+��`j�/`L�Q�|sX�E+��|�c*<��������]5N���v~}����7����O���F
����Q��X������yhd50QW��U��������j��~]Y.�������n��P��W����[�[�vm7SR,$
|9I���~�{���P.7�e�lNS��)���E]/�r!07'�L�+����7�&��3�x�"��r��,m'7hl
�t� ffaM3788X������V��y�Z�X�%�+q��W�RaT��%M�������\�"�Y����$Z���2��+���'������s"�$�d����#�Q�FY%���(SIHE]v���j��a������;�6�Ugt�	���C�I��i����kH����V�X'�5�OA��,iBt�:Dr����rb���Vg�c�[��:dCF�X�0�i�"����3.��7h"n���1g;��:P|��B#�Z��7�gH�lp�]t�72*�K��.�_b�1������y���bL���Xj]4�.c"������:��Q�o���7����f���+�`�����F>L4�ze�������H`�������[Ba�,��wPd
����[[r=]g�?Z�?�0����Sv��,R���Y�K�F2pX3�/!�:�i)�Pp���E���c�%��R�&�w���6����^�4�kOB6@$��j�Q�F
�l/�mr��"�;w��c:���@9_��T�S�!ax.2��m��u�1��db�Y��o��@+Uz����b}���l,�5e��D���\��I�R��9W�	��"���Rf:���� @-}�1�O�;��&�������$r�Lz!�[:����aXr�!&���j\t�T��v#�h���WZ{r��G������O��n����W����sw��zAq��}���a�����6�0{�*�)����MZ����![H��M���p�E�JW����7>w����8�2.��c't.����#�Z��5��s��r�T���
�����G�l�&O�2�����< ��HL� �)�
|��I����4�c�	J���g�$�5h���������P6_�������]�A��{�Uu�9z��N9�epSw�a�_]k?q
{��8z��p������;�\&���q���, W��d��n�a�e�a��
�b8L�A�^��I�?sX�!r��Q#�rfw�����7Z��r��%�[7e�#H��+3I��W�/�
��@����Z��7M*:k~e�5v��*I$p
�b{�C~��_Kj�	�Hd�����`�St,E+�/W[	�/���H��������w���sg�^�
�����vc���C����{�^�h,;���F#P1����������0O���`M>�Zf��L=O9�Ss�po��8�5;�u���{�n8�[����;#�A~"�����I\�zC��Zu~�OZ��:����g�Q�w��X;��2�O�V�^�6'�Nw��D�#%q(�-�Q�^��|��8�����7���otf���(�e{�`�o���{3��(2�H���i�pF�l�y�S�`�����N�J����')���"1��8/{o���{�#����Gr�G4������|u��<�
��������O�F���=�<�����������7U��&��u(������:���G_]�h�N���w������j<�N�5E���B0�MC���DeJ�!;=�%�
�)��T3�y8��a��^���(�R�'P����\�����r��]�'�M��1l�F�"���#BFNt�1��L�Y��S���u���������<��u�6������*6t�+�������{�o��+��g]q�/��;�0�R���kL�
P����P~������1$��?�l�O�+��q �A�)b��ATS������r����3C%���������,o��a*z�SN���������Y>�Iy�r���A���g�Gg.��Go�/_}}q������i�������]`Mo�7X��I�5�u�Z ��p���,�Z�Q��is8�������N9Jyc��0�h�;�9�����Y�*�����r8OQ���D����C�lK�<��A|��a����l�4�r1C�r���Y$x0��[�������[�'����8�e>*�B���nd�,���
Rw��mw��+���e��>0{)�FX'
�P�*�$��%g�Yb�3����Q�$���p��z$2�QQ��}�'��n����v�Q����|d������Y�q����]�)���z~[��y�����
���V���P���{�� a^-��)ZN�����&���i���P%�O
M�%��/B����#��K�mH�i���z��3�����G���
�i0���y�9qhq��7
���:3����yEz5&�qwh��N�����46q�)N�_�(���J���W\U�����xxAx�:R���7j��X�p��)E���'wL����s�����_x�����{;�������OZ���o8w-l���C������+�`���1n�c�~���t�"H���V�
R9��R"D�X N�qIM��(��xd�f����E����y����T	�Lp<j��I�*�XD�,l
w������f�Y}�,�an�m}>P1�����6�D��aA����Ax��{����j�����=�1]�m{�v���j�����������,���/���:���VT�57*��c�*�%�D������O��Bat��x�g*�3v��'��^$R��DUs���tc��-���e�<2��!�d�"�1�5�G���)D)����c
�f;��d��#&\N��O���)�����\����M��t��"�����.�:���c�c�N�����?}��?��K������ ����?�� �

�$����Z�@��0��q����@c
�uF��]@��Q��XJ�8P��%`e����Vb< m
I��}�:)@�A�9�BEQ
�r�*��}��s���i�$��F���L�^t7�h#�%{��(e�;:����S���V�(9��yBRs#q��S ������E�#����H\xq�C�������O��{������^Sp���;��J�u����7�W��P�
�i�t�%*O�u�4�/%��'4�1����U�U��i����QM\i1�����������g�N����m����E�4tV���3�'�lWGy��N���G��@��5QF��|&���F�Ko��*�� &WD��N�H�� m6�S��x	m<������kb�0d�����=��;�$-�0%JL�	��&D��J�����(Wc�����i6wNGZ`:tf�l8�Q�l$�*�?F3����mV�r�h,���q�^cai#�@W�p�N�z�p�C�F�b�@���	j��Y!i��1�jf�4%5��8y3Q�=�����s"f�������������8y�d*������������	������6;���i���K�\T/y������T	K1��yy�)-S�%T��L8���w����Q8����O����n�k)���q�_�6��,P;�?5�X��6���=��/���?
;Mw8�N{��vg8q�=o�����`2�O�f��5f;�?-���,v�}��������{f����m��8gp�9�S��nf�jS�'A�TW�J5����_R��`�x�2�r�Vb�Y@U��z���Jj��J~sX�rce��r���V|�RY.b���T#���?��*]��H�'���r��k_>uG4��|n(h��g8��"nv8\@���-J���}��;�HUGmH���!r_Z�'�Z��������5�>QB��"�>��jM��3���U��|�g5X�������n����|t�G`X�K��Q�z?���)��A�A�F��(3<�H�����"h���T��aS��-I��7������Y��i�Uf�J�j�����p���22�R��FSL�/�	�8��^ �+�]I����`�*���\��UL�&-C�I�Y�������^����E
z5��������D��s���G�z9e��zJ����Q���?�sU�~\���g^������/�
6`�yA��.�L_���&���q��K��V�j& $�t}'N��I�������":hyh���\{?[�P�R	�#����S�2��-K�RjZ�%�#�Z��$57k�o�������Sz����;X&��J_�F��F�������d
3O�R�/O~�����.���No��!�Y�"�
���t7�'E�8�jl��J��G���>���L:���9�7U36���s�����[v=�EX��@J���J$�>VB���9�����Aa$/���Wu��~�*�,����H��GH��E����o�Y�oDw.�q���Jh6������#�FX_'S�������j<��1@Q-M,�0yP'�Z���k������HU^jkH�����C7\��]��U�dB���:"L��%�%o�������,�����mM7�63���6�����?XR��H���6��8���h�����8�����Wn����H"��X�����	��Gg�$�@�%�W:e�
\�E�����9B�Dc���%��� ����Vg���p�\y3�~�����`^���
�5#L�h,c�-�q��c��@vN�&k,8EM�����G�q+,3���Dt	3ifI����U�TE
�p)�����=7�q��v������pc��\�?3�V`��-�5�xnZ���C��L�/��7����&��"tG0k���Hg����� ��
�^�9Mu{X�'���s���2����������H�Z,e�G�/wL�j���ho*�)[���d6��������Z���J��F�e%aM��P"Wyg����i�����y�Z�`��H+�s�j���^4;����]�����uEZ�����'';��$���#>�p>G"8���Wo�7��n�lxK��v���O����jy17�j����X��E��#�Y�<�RgQ�%t��5��M����hD�� K
4Qw��;>1��{
����*�=�6���nxA�^sIk[;0l9k���ge��0�g�<G��\��j}�O���z����4�v����q�S��Ao�����z��u������I'�xv�o4���!��$�Z�2E�N�p.U��<�KW������Ge��`bG�����Pn3NW��
��A�h��x�����nH�b	��3�P8I�|�
�C��/�l;Y�
�f�b+��j��_�{������I�`�������s���[���$?���G�����d�kM�����hy�"�����Q+J 3�HU�����v�5�E���x�sn�����L<���fLV�����/��R�N�]1{�&�<j~�%�>Q�����l��o�_�����K�U0#u���k8��G�41�>K�'t��m����������	P������s������Q#J\6 ��Im�.C�3���x���I+/���^�0��?���To�j3�u8Y�}!F��|�9��
Kmd��CS��o��,�&����$v[���p-J�(�����������1q�d5*�Cn��p�#�t���]�^o���� ��!r�:j�9��Nz�4r#}y��U����p��8����r�Zci�Y (�RClN)8�J�$�S��D_���k�m8yx�`�p�B���%�F��F�nz�E0��_�����m01������@>�'���!a<������x�a5�%d����_�/�������������R�C����g��`ui�8g���J"�����e�������(Uh�t�j&,Vy���6�?�	��'�HA��"=���%�����^���)��x��N�L�(�l��	�U4�q�K�!#�ety~��W����������"�������<MW�]2}o@K���1�%rp��/�Fz{IL�Cj"U��-���)��s0�(�YF�_�@�t�K�o�������C��N�:u��0��LBhuXm�k5
����_e��_��!H�<*��N��?������r�m*�(e�m��l��fS�����k�p������bE�2O�n�"o_��;�F���";�����;�����b;�gBV�0�%��P&t<D������!?F'&1wEm!��b��M���}��������3��G�hi��������7�x;K��q2zE����r���	�A���^��pD(�!B���9>���wt����n����>�<�8*����s��K>�Zr�~����d��ER�V���T�B��������[�q�m���1v��VRe�U�]��V�~�.��u�(�'}���]���B3������R��+ZiK�����?\���DD�|ye������Q�m">t�z�+��d`�5<�� �f��s������l��PI���;l����t:S�Up���vl�����;��}�q��J���a2�?9���P����b���!{Y�)f�0�����5o��.�\����eu!�����4�0���TU�u�C��z������KW+:��{od*�PE�(-+�����fm������-�b{P�����8�0����T0y!*������6���n��OK��p{��o�-�:P�TG=��N��2Q)%� c���-�
��K��������L������7Q�Sfz^nB�k�)"*[��(�i�T����TG�������t�y�������I���~,?����+��K�j�j��P�����g�q��v���ES��C�H�j7������������}m�h��Y�S{9�l��7;��$���L�}D��Z�$|�0��SWQ{��0I��j#I�~�<����^����q'���3��yz��0<hZ��0	��r_)'t[�EX�G�]�PY�#�Dv���&?�}��W=+������������P�p����(-],U/)b��� ���3Si��C)#��O��,[QV�=�,��
,�zzqy|��9{C�����2r3����������^�(�O��|��|�Er�k���"��|�R������Sy3���
�&
�>XwJ��0����D`J���*���7"����L
�J�r����/��(Mk�jx3�9��/=f�8�V�sy�����o@��6�����k�\���do��BI��L�c|L$�4A���n���&�
�G�>�C�����LY�^��E'�r��M��y�=>���A&T^D���)j��*���||���'^�^8����_�m��r�ktd�B�W��\f���<�v�2�,����h�L�Wlh"]���C1�T+�eV�yr�J��z��t�����r�6����!�=�S5/2�L�s	;�l�I��]��+�������������}S�I9���@[4
�Y��9emF�zR{�
�������_:�W�&Iz"�F5����om��[X��p�����'�K��nuz��/�����"�(���r�qg�k6��qs2h�nc�L�Y�6f��������q��(�K����|��g��P�F�d
���BL���Y���By<t��#���h#�M������~�z`���"k)��7����"��k�>�t���N2�q�u#�	J$n7>[��������fRW�`8���C���1����s5���_���`�	_������)ar.
�'��:���d���q�A�X���X�\��{�Ey��s����3��Oq�vl/Y���S��7ko���K��V��;<C����.�^�t���\w����~�>��0�#�+�o�����t�������]�\�����1�lv�ewavn�}�r�,�a"�:�#"����cNh5Q���v�1`mtl6�����Q!�X����	�)��$�
tDY9}�����R1�p��������xq�&�vLU����m'
������ �1�b����I���X\�4
������@k�F
vD��o�
e��Y'v|�����;:�$�3.���g0_9���/V�t�nu��|����c�������bS���A*�����^������'�����a�S�;N������|�#Z�b�;����M��+������;�H{�8�E��Rd?l+��������{
\$�,�/[��c���B�y����Q
v]x���9���O�	WJ������H^��+G�k��~�������hw���P����)S���|a��u�
B���9A>vu��w����S�P��0
v�[������G���H~�?3[����!} '��O�:r�}�:�1�.':]R��:b:U���e6SR��]o�w
3�%�G6 �<[��x����-rs����Y��b&���`E�eN�1������o��������$u��p��!�gL���^c^��[
cC
�C��6��x��(�R��
��Z��I�A#/c�N�~����9k����^����Y;�c>u���Yj3r�������4�����0����R�QV�F����pA�3���~�������������^���k���=��/
����e��A�����/+'.�����4)�I�$[j��:����R��
����+5�4Yn�x�������U��L��<��[�CF�.��q�R���'�����;�n����]�#��m8�s�Mv����i��T��l��v�^�{��`���Z��OI�k�1?
������XT��v������$�/U�-���B��1��#���0)
���~�^�����0�6�B�����F
�����n�����r��>{�.Q$���@������w��nr�}���"I���������_o���e����Mj��z�������Iw��f������A��9��
Z��F�k������q��%�����>���7���D�!���>��cMG�������*��i���h��e
$��l��iw6������H7PY���7p������N�dA�����5"g�6�B�B#h��j���F�)Xz7
�c:z�_��&$���j
�^�Y���=�!�� G�����U������afP��!i��i�V����Q�v��o���v���d�#J������h��-�m1jnIa3��a�Y
�+��j������������W�����l���`�
S���mx�D%��WQ�w U���n���J�_��f��U��L!_ A���&����m�t�p�������y[;�Au�.~6�;s�j�<o��
d��k
q�B�t\xg��q�B}��,n
��C�~��@��}����`����K�P�X'h�EM��X�����$W8���H7�������pxQ>�6o^[+�Gw�7����;�b��<�@�d�n����.��AgV��!r0<jDH��\=����_Q�Y~��C���R����b�@	�W����m�<%�������@D/���U-)�q#��`�A
��F��V�������#n�b�q���a�
�qg����c��8�=�M'#OpMR��t����G'��7g���.G���]R��4���^O�|�8IY<�.��K$�,Xa��n��y�d���Jisf�~�����5��s2�d���_���dzH�r|�+w>GL*�?J�G�2T+Rp,9���$�nJ�df@������"��
}��`f���Gp���)3{ko#��� ���z�i����H�����S����_'��iL�w�zC�#��f4���+'&�����\���l����G��������l
HIe+E����H�T�^�=�z�z����e�2VZ���(�G��'�4C�x��G��.������t�����-��'FN���T�k<��z]�D�N"��e4���h "����RU�c�\��n�#�����t��=��P�@R�G�R��~R�/���]xE�������5��1�i{:���;�i���� yY�fd[�h��|b���s���1ow��]���p?Qu0&�����w�G����_���>B3����Qv:raU���J
��H�Z\�����������������H�y#�\g��\�a*:@�l�0�\j��F���@�K����-�4�v��{SQR�{t����D�3����<|��fz������Kw���&���$I��&�e�ihXI
�J����������&����f��4�S!U�Q��H�tP�������
�6^��+G~*�����h���o�N.�AT�7[�nN����
ow�
N>��B*��!:�+������a����c?�����D��6C��E)���,%��E���m3���O?Z���h��������������(���������A��u�M�"����MFa`+��%����y�,�*�3���:X�R#|s3
u���5�YE^� �����r=����i����WBi�qG�;�B�Za�$�F���DRA9.��a����||~~v^u)���_[hIu��T����������r�Bq��A�Z ��a{��������NZ�V����9�R���o������]��f-��x+�i'kb�:���D�<��a-���t$�k/��d�z�M@���4���Q9dG��K���]K�BLt�P��)S�
C9W��@�)�X�O�
��.)�,7����V���vMIW�����R�4b�X����Z	ZM:����������h�8�d������^
��� y��@���,y`����%���\�����j�T'��:�h�]�so1�"j8���cl�d�9t���`# 5���1����s�a�/Y���^���~D��ez5��F;d�[V\4fy}��'��1�����
���'8�~�L��{j����+�L���,��'Y�����V�E�8���q� ��9	d���S=�8%:e2��<� 4
�#1�MR��k��WZ� 8�x�4�s�������0&�����s>\.�$d��t���S	)���1���hn���M�9���Y��^�"B��������%t/
�����O��[��z���U4������!���4^�;�M�
�oQ#�%��0Za�;�l������J������m�F#�}��X��f�j�]��i�7x&���L��
�c�����:�NL��T�
�������
*��S��v��
�������_����|u_(�'��r-������n�?�����{g�o6��-�?���� R&C!��A��7���fs�*�Ha��
��q8��13�eR�1��i6��e����$0C�OC26�r�{U���y5
��"����&���9lI:���k�N�~�����pZ
d���_�R�d�V{(!�G��..l-N���4Bk-^?�e:,9�!GjxS,B���I��Z�4���c���
��o�R\��n�h�d��n��xw�����{po(v���CQ1�w�>���	�f�M��)����\��=[q����������I�C�������yG��7���v����N3�C��f4���d�j�x�M�3oV���9����l�,����XFU7$0�����6&eX����%���t�0���RR��%z�������I�z��[���(�Q�0��+����n��v�J��T+�����K���O��`��~�}�;M����@�,�9Y�@���N�N��������I,V2m�9��vi��%,��;�Y���F�2�~HY��1v����S��S�N�PR�s��I�z��Xj�	���&t�[�����D���/�����oJn��A���ei�Q�B�oy8���1���?����YW����N�'�����-�`U~4��y��t�����|�kY��'��!g�@��x�P���w&�A��P<��������B������t>|�����zuL�\�V*����~�:���(.��$>�Z�H������k�6 zB,v���s�=������Q�Lc#���u���r�[#C�O1_��q���&�y���������A��a�{*$�g��3f��_�8A�-�G@@ws��Bv��S��=Osgb���s�:<�Jr;Mc��0��V4�p�7`�bLR�	��`0q�E
�X��U�i��
�K������G�:�
���~��=��H��E��k�%���PN&�=�:���bW;�;[�%�1WS��p6��.6U��F�~���B�3JH��2�\(j ��O�=��x����TKa��)l�_��a����~� �RF���_���R���a����t�������;_����_�q7z��u�n��-7!B,�����I,ak���/59L���H�����HM��jS_�@��M�2��� Tm�8=�/�&����j�B��t�mZ�T(Ar����5��r�A��7�����4Kd��`��:k��p���2`���8'X��#����f���N�rP0��t�����q��^:���hy2��kt�����k���`��]���h�<X���MS���L#ZX���M�`�����b�[��Lp�1d�acq�*�~"�4��m'1��DlB)�#���v����LN���~�� t��DU����,���K�md����$���������L������y�\3��j�b�G�����K���(h����cXU5y��Md�9�[cX�1O����@�{C�(�Z���E�o�0�8�}�����N����h�G���#k{�E�<-1a1�hHh�DVa��G�n.�@;�i#�8��c�`���	��c��/��u&�w�{�����b��\��Mc?�������i�{C��;m��{?�=�����=�����;.\{R�k�tn��YE��hbF;L:��6�vwq[3B�����9�$KJ���O����X/�����"9u��*��8�����u����G{F���C�Zf ��
�u�����y�{����Xa���R-�[U��S�C���Y�yEx����P�����	T_��s!�����nU6�:e��8���]�=~uYu�y���<�9�6i�B�����;��=w<i4����Av(�T3��5�����"�GT��.>��.p�e�J�NN��B����=����<��`�^F��9O���������[�����wF���a9j�"���������t�GM��~�g��S�{�N�Y� �tMT�v�������wN�9H�I4��M�gD�O�:�a>�-Gp'~r�e���#T������ua�[w��<���AK2��r3���?#�
�?'��I�B��S�k-�-O$C��6"���i{5g�v�����W����+��B�s_|�\��=��x���������c������������g'��R��~�����6[�!�B��*�/�;s���2��y6�w�_z�9;a�
�H
��xzv)N�h����������7���
[�yF�JOrO��,��M6:������z�������R���[);���z/vqL�1����H�G��*9��W���Q��J�Ys�T��_�*����;�������|"0O$��&����������-�YC��[�
��1�k�G�!����	���}#G��2�H�@�n��V�����
���)C���Q#1����!=f��p�$����)��FL&����[c��K��U�~��e�9�Ws�d>T���C7�=#������d��J��E�������%~�U�!�[*)F��l��~���gha�V�)�F����V����,=Nl�]�(B����V�x�6u�����g��r������q5i�%��u��:���!pj/'������	Nl��wj&��"�w25T���$�3�L���r�Uw�>�������-��BK6)�-��1�����g���Y�G����%>���"FGp���v4�#g��4]��=|��F���PR?�nMS�8<X����
�����1�������e�~�dS�k���]`� r�4*�'�h(��;BT�x����o�#�������Z��Z�)�.Z!���3H��<��;
=a.Gq0�	�(D�'���^��lk\g��\���d����n�7�M�>�ymw�.�i���JW���d�`�����Q�?��|R��|��!:�G�h�jU����2��6Nbp��" R�.����b9Q�=��
�Vp���x[�����f�~�>��&�AN����v�L�=��[dd����=Qs*:b-�M�HW�EJ����]dt�;���O����e��A����-���ml8><N8G2������g������=n�x?���e�qf�,b����Xiz�FJ?��7�)P�^�����h��!j�I��M9���y^1�\����O��
������'���C��*g�W���V��!H*�����9q���x�����%����_�,���y�)mt�~k�^��&=�Ht�5������M�W�u���N5����t�R���L�k�.�Kb��H�8'3)5���s@�O��S�@�S9]�{K���������e�Hw��!�9~��Q�P��P��:�P�����{��k�p�o���L`��K�c`a�v�X&�����~e��@S4�8*������K^�2���bA���I�l=�������|�~�������'�#�C�%X��t�A��������N=	BO���b<V,��������`Y�!\RB���+#�@��=y�v���S�)�0�@r?�����))1f�6�k�(�$Y�a����]z��2�q|��M����?�7�:d������K�}st.BuJ<4MH�=V�`��U�[�8
3YN���248j��OcA�A�>��'�����z�}�a��7�r��H�,a��rr�	�0�C��/,d���s�+���\��a�^w������L������=`;��a;0KKB!��b��}h�Pg��;�9�������O�>b��������wl�|���O�_���(�2)�����g���
�73Z|��s��oJ���4SX)��p��%�i�Iql���o+��>��)4�(MW���D�j�*b�������9��;��T�kY�[SVgN��6����9������������`w�f�f!q4X��J��h��1�����b)���z���U;��8?<<S�"	/���4���>5�����jZ��\�+s�a�m�f��M��z��o�'n����(;H�n�q6�H��������q�\�\�����e�0������nYN��g�>\�#��}*��,�yd�D�*�%�,:n���j-#�X/��
�H�+���$<������L/D&3�������X�������uMEo�@��7���m�u��y��9k�P�l�Z^�S�O����-zc�C:u�1W�����X~V�e���7r��O�����%�����.c�c���@H�BL�f�V@�^�G
m(�Q��xh�
��c�0�9t�����0�ThE����~C��������U�%1���V�)�05�`Q��N�q��2�y����~��`��U�Id���f��gG����Z������+��v�^������R�W`�����������m{��a,�����B�"��������
�W��%c�@`iE�V�^�{�I�S��k�@����!�sD�*���2�&.[�|,3���?
���^XC���^4V����V3��berU��h�}����n%�2�;���^���oV�w���HK��v����g'�8��e��o����^6��}���kO��lS
GWs�>?�>
TME�r���H���n^��}�?�HYU�s�����4�7�q�7��6X�o]������������
���|�E�z}#k�=p�`��������������OG��'��8U?����=B�`���Kc+�7O�����������W__��8��Efl#O��{��
�������.%^xV���r�M��%P����H�s����j����B>x<w��cM�m�z�YD�v���4�����q%��#���zx��A#���&M���0�n}�y�Yb����{[�h�MV�%�Il��:U�d"
�fgu���{�+�<���s	�{I���kRQ�%V=�yko9/�����w�^����=n�D����;����@�Z�4Z'q�����^����b���9��7u�C1}�'0:}����JN��"���w���;7���$k/X#cD�%��`��S?,���������i�N��5�������l6�Er?���8���}R���eJ�6e�o�s�����]����(�;A�Kb�*H�!����.�6/TI4�����n�F��z]_u��i��[��{�[��A�dU�+���*&y7���K��~X������&'���Jit��v]���q�7+��'6�.��Z�f���[��������2SZ��v�7<��E���z�|��)�ce
K��lq��g
��q'j%�3���nZ��z��7+��6���;FK��f��|����E���P���� �!&�����I�Q��^�p��,�-[�k�����H
���U��{�S��=3�U�Y�TsJ�T���S$\�j����^�7D7��V����v�����8=N�D&�G-����	��G�MTC�<��an����s�>$v�4r����N	u�X����~�g�7��{����;GC���c~�k���EF�D��
�"
��R!�}�m���h�J�z��x����w6�UR�A4Ci��J�)��I��0�_�
����{���T������h�������M��}�J�-Y�~�*=/�@P�3��W�]Q� ��7�hh1�������t����|����iVS��9��^�	�L(���%��Q�h�\4�^��P�������0.��I��5r����NC����X��f�s�W���4��G��P���Q�q��
��]�?�t��N�?����q��v]�Vc�:�^u~�I#��f�����������=8^���� &��
���f&�s#�3*YN��Ov~|������+�U(�)�X����{�	������Mu���p�](e$�a��!Gy��=������)L�B�L�=we�z~��������z���o|
�"����}M�P:=3#����J��K�`,0���)92��9��T"#��^%Jp�����*Q��H�	U���i����tb�����N��U���v�c�'@|�8��O�z��rz���]�w��� �1�c��W����$Z���s��{0��),6#E�[p��4�Yr"�s��um�+`�Y��"��k-�yMe����K4�N���<��z��Aj���V�����f>���9�c(C����So����(�z��)���6�H$]���\[gm6G������"��0���Jv�-����+\�?��^R�]�x�����6�]?�}���������g*E
�RZ�f��v���}z�p;NK���J����a�a���a����4��:�.y�d^+�k�>)f~��Q�]�v���S��#IP�)[��Q9�V���,�r$���y���oo:���^�/������:�^��Q�������q@sb���:��"��k����P��\�"%8e���q}��G���!�S2���e������`!vm����S�(AS������*c�W^�B(Gw�Q2uY�'o�p3��b����*D��q�����)����\�W��V��=E,&x�����2�r��EjeP��N[�z�����)����!��w"�=@�?,��z\�������#���n�����1�����R�=&wx���}C;��*_7)1���;�K��=��"hs���Lm;�n�V�l�7���z��o�E
8�8�P?j��b%WlL�fo�YY�����/�wQ�������;��0ns|��>�z�y��������&li��#}VT&G^X��N�;��wM�\�R���O��N{���)���M����rY#�8�V[b
�,�vc<z��������x��=�5����J��/�r'��_]#��-7�� Y	��sq�����)��J�q�������RR�����\����#��p��s�{�����X.j��*��=��2���i{V���@�D{vRaY�y��?`������>����������8�Nhd��K{b��e��>y��*�S>
6@����,�i]�ia��p���:!�Ns��=i5Z��W�d���&���l$*�	~��w{c��gO���z���s����v�M���M��z�?�6��~A�F��V[.�c�z'Z�MI���,�y��7���f�GUi�4-�-���h/���$����`L������y��y�.�
�#����<��!�5������"f�	�
�h���O�/��������~?<��lY��Y����ZH�8vM�:�6�n��=j�����Qt"��1�O�)�.��='$"�*����<������I8��e,��	�R��xW����8�<{?��������y<UU�c����?�6����B��1m��q�Qg���Yy�]H����m�k?�X����_7]
��2���V�}��u�NU�}FJ�/i���}�o�_v�B�e&�_�5Gp���Y���-���
�gYX�u����B5��]So8h��4�^���h�]GC7���Y���<�1��|:O�,\u��I+/q���,��N���^+b��6�p�9���[]��f�,����M�Z��0f�%Z�c�w4}�N9$%~����/�q�'^�L�jhQ9'?F�����6����4������s�ib,�����D#���G�
��F��J�w{����}������k��7[�p��p����Qc�P�/wa����S�"��['��G&v�/je)"L��o�GjWA��NI���r��������0S��/�o|�}Erh�d���Q��J�;�M�3��Z��[�):>���o�Z�>�$��N�nMG��V4�7d3���s@�E`V^�O�,Gs�eQ��0���
��.���x���i>{��=%��������)Q�T��Vs��R�@s8�����av�����������������l�i����W���ho.t��u��f�a_L����Z�Gt�F)����v�>�
����8z�h��1�oRu'VK������[2�oA��������u���c
������\�&�f;���{�!�wZ���2e������j�������17%�Y��D1"��`�Q��Y����v�/�FM�Mj*���rV��i4� �;�*�������Q���������U�q1�)[k8i�{�:0��A��i1�qX��tV��^�������i�m����dw�d��;o��_|,��/?�Z�7���\�~��W9�G���X�E�����I��{�8u����A�|�[���.����B�A$���mz�����lBv�����3D��T��S�_M��M4�{u5Z7�d�-V4���c����!��,F�����]�U��s'��a���=��p�,��d?[c��k���/���6���9�+/���a����k)'t�����B�(��\������t;o������<9;]\�_�^}8??>���}[q?&=��&���t�x�C����8?�D�wz�����e�bxL��~��O�������)������|8d��xwh����pb�eU��u��e0���T�[E3����)01	���|l]��E�XSU?f6��&�!�t���A�����b�9�������d���t�$�X���A���r�
1:��a�}%!+F��C�t�5�/}	s9M��l'�8vf�6&
����qN�F�HI,�n�(�����
t�k#	p1B�U�
]��alT��Q������:��(|����A�Kl�Kw^�=��@X���S�����F�R�Nx"����1����eb
q���44�� /4���������03�$S���}f�u�����7���M�"tB�"X�:
`�����lz�4��j�Oh+���+�s��	��r�����?��i5��z}���ec����x��Uv��0�t���`����u:�����&������_�+����z����&�b�i4M��������
����#������^{kt�y��P���U�k����JE�����@;��m�.��*���D�����o� ��Jy����J|G��c�	]�8�-�8��H]0���#v���(��?���s�����wZ*�%�?4^��p����s����?�z������@,�
�r���j��~���p5[��4'�+w�bG_7g��6G�H
FG|_�����������{+�����c��C������6"t�;C�~���AI���^$�dXH$�cZ�e&Xb�9zsy|�h�u^�����o_���W�d(W8��_�5�	�j5�q^���(_l�g'��0�V��k��5��Gy1/
�����x��B�4|�0M�Q�B�x��@�]�-�g&���cV�����,�[A�%�J�?yCr6t��$�����G��d{.����\'��}��6��}���W���? �}��(S�}���X�sf���e���~����v��p�q�����!1�tgU"��@�������'��@`��O	�I��h�����|������x��+"3��A���JF���n�6
���XC�^u"��9S��Oo�!1�R����<���ro��5�IH@��,HYz70�:��WNw7������������x��A���r����G��P�~���_�w�A�0�m4Z���~��B��Y���9q-Y��3�fK����Z���r2��8����[�?�4r&t����.�N^#��N#��W�-Q���os�jed�`�i���8�H��2�gc�����ab�����|���6������8���7@>p^��G,"���le��O�o{�����]���\���j1u�NS�33��)9f����������cK`*���� �]�����N��oO�>K�f&�t� �% ��C@j����(m��P��I��K�1��(�J��y������@P{�f�:6�#`�I�z�"g����)�Vo2�N�_����9e���Ie?�-����O��%:�Q~�7��Y�G�A%�k-�5UU�-a#���"5�����Y�I�Y���J�)B��*�gC���Eu"�>y:vD���lW�/�o���������|������?����3���MCo�^]%���
U*?o�i����M7/�,g�$N�4fc6��i��G���(�I��;'��3�������`��3���/��N��������
foA���������&��v����e���=2Z%��
�b�$'m��L^����v�A�p�K�pCG3�������p���G�_]���O~�
*�������4��!Fub�S�U�N�w�qbH��;�+.EMy$EA�I����va�>�+2�R�]�BW���
����l7(�F��4q�7�J0
'�`�o	�07���g��NN��Q��w��&�8&
�T}�v��~�:H�A6����K4�>	����rM���mD�+ ���/�5�����o�r_��)����������8��C��{f�'�t��\7[���]���[��v	8w�o�T�'2�^z����=�,�� 4B�nn�����������������������������`��;�n4g%
�?��h������<����2��`�X�����6ia�?V^�co�����k��9	(d�������C�D��:����+���_�GM��w�u�--��N�A~���������l�(���1N
,�9��������>h
�C�G���e��f8��O��;t����K�~><du����i����Rd�7R����p:��cN�7wv��0Y&����Y(*�X?g���d�E�������i���Q�k�
���O���)Z|���L
�
B�m���^�||�Vz�B��V�qz��n�
k�v�J�RS�_RA��SJ�Q����i!X�1��IO'nw8h���ycD(���tM6N�T����j�H��b������L���0Bb3�M���T?��E���m�1"���;O����L	sq�B<J�v���d�D;UU��_�y7YC��7������S��O�Y������N|yL*w�CaD\��;��$�g'�z�A�ct;�r������5���2���F�i���E���4H,��gq����Eb4������4��(�`1����ot:�����	�So�z;����]N`+9?�~��;z���y��$�(��C�O}��{E�2=�r|��/#�*�Hl9#�?��% T���G5@����d�7?n����{����m!�|�]�0�{w��6�N
�-�}t6�K�$C�/,���������;�nH����(H�� F��U��`!�i$~�1#I4�������D�Q�IxITA}O���	���c���Lp!Vr�����J�l�^�h��F�spD�9�����[��c�D����@���a�����7'��.�S�S�O��������nU�z��������#Zi�!�O���T�y������xT
�����XT��t�O@2�ti@�B���%�| �:������F�M���K��D��=�+�4�E�GZ�Lt|���;�s�"�������sY�Q��Z�`�j5bd�$5�U���l���0��t|L���Q]�y$���F(��"�3 {4�8W��`�n��gT�(o�c�+\�������"-��P���~���U��%�0X"�)��]�Z��!��H�L���M��/��Q���=��Z�n��,�gS��k�x���@JCC	n��b���F��T�����E����^��_�F�����2����H�%������E<���N�=
��R|]���LCP���9���c��Vy���+������u��N�����$o!(PF��*n��P��F��i�<�1����7����
<��o�-�A*s����>w�����Y"�4���	�r���s�N�z+��;u�[u��Y4��v���#�=#�c3��+���F���>K��������o�&�S��W�����l����+i��[�R��/����O�T�P��;W��*��:%���<�v��o�d�0��'\ 
������O����k��oz%r^��@��]�86G���)����V�H;Q3+eDMx�#1�qR����94klc4��apo�'�)�^���n�f���p7>'����-�IE�\p �F��k�Qcq�� ��e��!����^�p�B/���T8@��UF��M
����2��a^����Z]�V��o����G���%c+>yBs�(3��6�S��K���d�`F����?
7�������1��U��|��#�G"��d�D@���B��6��1V����o$2O�wh�J������/~�M��j�=�Ls�1zCX��$��
��#�^����[������
}���Y�,��]�����(N�z�/�v��6D��!�A�>����2Z��N�0����xGR6�JK��!c�eK����4H?�.7��M�47��Ts|�����+��L�(@�c��8����D�6�A�xb��ko��a�������T��S�S�s+����l;w	�g���=)���)1;N�b���r7r���v<�����M��Q:�m
i�E�����y�m>�������1����p����=7-b����{�bg������9��R���=VwMS4���@k;��1���h&�t�EE�6�*�	�r;rJ�|(��5�:��W���=y����2S�o��_���>w�l��]��GqR�+F����N��������/w�����I��c�Q[���Xr��������_���R���������l����V��}?��Ow���G}�4�t�[�J��m��k*��)�{[���>�MXC�1C�C�����4M.9P���H���{�;��p����*�5I�����6� ���!n��=������W�K��Sj���N�����L�VW#w���&���
���p���~�h4��s�9l�^����&�!q�9P�)Ek�k�N��w�8�^�C��^�>-��h��x�l���f��h����nt���p�����qv���\l7�B��?��:�^�7����t����p6i�����y���O�i�=��w����VN��4��N��h�p�������`����G��?������j��3�O����k��^b���s�/������~�i9��n�Q������������W_;���f����q�� "����^��h2S*1��I��)*�����5*�Y^�j�b4K������r*0v��<�Nc[��p��u��Uu��|s�R�����Iy�������y]��1
�lc�q)��fL�1�i��a�G`;ud��co��@m�sL3����fID�H�������q�������Ha�Sf��-�k��Z�Z���h�fF��z�3R�Lt?Q�2q7�%z�N|
hIk��(��5*c@T���^*)��<7(�)������������	�������PI�~f)�l�3*�Ea�0����:&�0X�
���Q��X�������%Y�
�����r�p��:���B�����e)T���q�(��:]���o��z�T�$Ni%s�������6�-���c5/.��(/P��)�6
}��\����>�La�+O1��(��B�C<�����
�=���/��Gx������R���_���~r��J�j.-g,�������4������S��h�0�LK6E�
�k~�.�&�������z����']��i}fc�X����
�:��d���`K_Y�_Vs��j�l������`������g���]��N@Vs�s��b����+��!�����4�HAM��b$er�oeT��E~�=F����2E�r�	g�T*�|?���	B�J���R�E����*�W���	ML��)����H���h�n6�K"��I�Y����jF*D��&��Ll�7kK��}��?��1�P�(c��H)��x"$+��Z�����4{�X��7%��gx������ �v�t��&X-�� ����k��b)��nkA��+O;�0����A<:`���N��V4�d��`IK��(#X
��g���^��Tz FG�v�vW��;����|��:�b��FX����"s!R5i@�M)�y���r0����)a�Ix�����{%)A�s�z7,�@�t	�Q��d����kp9����
���5��[m�
c,�M��k��+����H�8�P/��x���Fs�~�k�����ta)f��:�����Z�F���O!������[��1�U�-��v�	�e�\{��f[��%D�EunH6��z��E8��M�ah���M��I��s2����C{����$B95$����E)r���x&
Y{?la7L�D-�B�G8*�fLG������������D_�y���&7���A(0��Np�p_���T�0q.�00�����4�"�D'���t��8� �d��,�jdU��[�N+���O�
L@�x>�b��:�'s�b:w��s��W�q���_��\q,��{A�0^��Nlu�#�]a�R�nY�l���	n�kk����C������N����*��^���K����z g��;�������������K	t{�l���n�I�YV��q�:�+�9?{���u�#|�h3��H�C����e����8F-�)w�����k8m���2JQP?"�����\.��9�O��(�����M������U��N��:Y"�x����)�@)�]:�����1~%�|~�9!�`Gx��,��{����W0�C&BST4�-��h*ZE� �������:��R.�hS���������*�K��-���T�OeL�V2�����t�$�/��W:Z������6�5}I�u�m+%�[��A�����<<��J�*��<t�4��FbF{�-�y�B��Ji��������o��u���Mx�E��D�>�}���o0W��3����M�U�>����tv��x*�!N���������W�����Gtf�� V.r6;|m�
l�(d�Q
��s��H����	�>UIe�+W�/uzU��>������4;Q���=x�~�,�(y���^Y�����3AB
�3n�%�:I���_�s����ekh|�m�������������Q��~��6���NOg�%�!�s��9Rv���oYI��s��4�Q	��H��Ab��fD0n�2�*��2�`�U��u'����1�C�����03]�\u"p���P�-�	Bb�R&���������Wj�P2���Y�3�Z�&������+�D�w?��X"*s���W����R���9'�9�3�x�p����Zi��,�J�2.z��H���CitB�,������-P.��O*� ���M��9���xJ���W.�Z+ �h�#bg-�o�@#����`(����y|��=�-��u�XK�J�;�^�����nG5
:���o�nI�3�lg�L��&KGu���#�����S�)���uC��[R��%����b��~������&,���GO6�������,��/G��`��v
�����������E����w�.=�bZ���D�#�D-X�K<d�Z>�(�_��J�a�'���T���	�L��7nBZ:@Z�&����V�-"��=��
�)W1&����pA�z;af�3F�m�2����].�����~M����$�x�~��9D���N���S��?b��wC�#2�1��c�u��m	7���V;e� �8���=�P��nTq��M���O��Q{B"7�k^t��U�)��+4U����
��5�"S�W?���/�r��}c����e~V�Xf�F6e8@�wYYU]��x��N�Jf�Ar��������L�9�Z�|i���q�j��PAE��������������26Lp��n\�,psN����>��I� ����3�'J�k����)�Yb��:�s���
@�7��J"tI��5�
�I\=0w
��rm,94�1��oNA�����e������I���[������J	0Guq��[�9��B$���z��=��)�U�v�i]~������Q�
�4�PqY����n������j5�3��h������;$�,����P�*Mc�-*��z��oUaGPf�_�Q��M�M������R�4�Q��������2M4
�k�e����1�����f����� {7�������J�MB� �J��vE��m��@������`���%h>AWM�Na1 �[Of0	���&������������)8�Y3� ��b�Ly��%�E<���7�!`���z��K`.i������������������������'���k����o��'�1�,`if1���##�����d�F���3VF?$6x����f�	?z����8��t��r]�R����,���v�r�j&btD!���4[l������]��n��%��	����U���f��UR
�����S� mE��k@���*su7�[�����o��G_�����������~sr~���m�������u#
�)(�����V6�����(���'�9yMhh&w���P��{��eLY�<�X��p0��A�Z|T>��@Dmi��t���A/J� �hn��������I����M'��N�7��)epS\��Wg��k����{�j;�^�W�)�+�b���\G�@��p�^�@[�Gc ��uO���K�fOv
&S��i�h�r�3����D�����������c�Ig��f�i�����e��@1��$�w������B����Ef��|�N��<Cks�|�\3y���q���sx���;��QVl��	��q=`t�C�������H���^��FzQ�V~�ktB~�������[�`�N3��%4&j�N��J�g�+��Cm��� �������2�^$�G1�{4�=��7���O�|���o~qR��&A���)���������.d�f���*��/����*����khK��a��X�@�"5'$��j�S^���Cs�$�MK��B77��M,��;�2��������nF��Rg�
<�����||yo�bK�R���3�f��q�v���;k���F����I/;�k�H���m�h���s��(��7G�o�O�FG��������W9���q�����?��R�i�/����
�'�u
�D���~~�P��8l�nLc�8O9�L�1R��8�q��S�[���<��)-����?��yQL+��8A2Hp�R�
�Rq�x'P����9;|J�^r��|��Ai	6��?3�K5�
���,�_��]��W�%��]u�ECJ�����Y]����H�� h=�C��r�S�r���`H��+Rb� �����Z*K`�5��2��\�����+w��rJ%���=Le��u8�������es7I��'�B�����W*HE�e�Z�75&���(��a�ftL����[��`6[yQ�R��P�58�Q�N�iA�h%FAs���_(i0���6�cB�s�V��U7�G����o� 
�T���+x��W�����|CfG�	��pW���s`�t1n^p)�I���y�l6wr���D=8���l��4=R�Ye31����;����h_�kN�����[�mN�)��������1���E�;$@H�3P��63
�����/O����Xh��:|�;��5�|�N�#�RT��sO9E�J���9������#���w�����!P�o��5_�=��c�9��#�"�Jw���]W��������=s)��$��r����zI�DF+R_�*0.���|������a�?�����u}�H!�O�AJ�l4��w��t(��VU*)���Rt\�����`��
E���eOX2��j�]mrW�N
J�O�D�i\��4`D�
`IA�BI���/�Vr�	��2W�����:=K���,T<�����HZ;����uE'�R4=����+���s|[����\�d�PeC��h�pXz����&��=����a�'��(��\�D��[?�cf�K�����4�a��tP�g�n1`g��cy�5���1c�a�iS{���RNc43L�g� ��� �:g���#���`�#:$��� <_Fh{�KCP�&�z4�V�	��6m��&�.����pch�ti�=37���ir1����p�$qQ�S�K����n�
�����eY����$����2���q��� 4U�]b�������9�11���b(�� k�P��R������J�v31z\D*L���QH�LuV�\
c^r*���`	dt~���z�9E�a�� vLH��e�
2q
J�"�6K��`�C�Y��rP���]J��W��5�N�:ZF��H��jG������E:%�p��F��F���W;
�>�k���+U�u��*�F^�������w<::�[y����F!]�.:4�.�%Jh���%*�/$��c�p4�=�MG741ZQ�K.�)*�tSx���(��K�Y�I��g�J�fm�����#����@�LrS�n���Aq�x#�2w��"<Q
-v�=���s-~���TRg�O�7)

G^!�r�K1/)�)(�|��	��iljU���S��a~fUN1�]��(��S��J%��h���k����:�(=&��P,XF��B������6a{Iu��w�����jj��\��
������r[}0[�$�����IKd��� �������Q���`3p�r(��f�lv�0��I�d�YJM�,��8��h��^�?�z�z�7s�^?[����#�[P����m�OR���Sa����4J�?I�����>Ilf����B�QB�G�v'�$�Z��Q~�Qd���7��W��<8Wm�k<�*��%$Y���1�����d��D��t"�K�9��������ap���l���lM�=������	R�H��d#��n�
��'�IBH����V��\
{b-A�p]$'�"��v����8�)K�2D���al����p���8o��_o���h�H� ���I`���[zk�6& �1)A������bjUg�"�O#�@��o�����lI��[�T����D5<z��;��z�\�����\���.r��QE-�1�c#F����������G�*�J�GL��2�|�f`����j�Vw�d�u_0�d_S�G��Fb�+JC�>�����
�'4�����e��!S�^��xH�����<��6��^�o��������"����oD��>`�-�Lv!�+h\����Ng�������o����&�:d4�m��L�����o������B����`����8�^*��FJu����aZ� �_\�_�^}}��/�Z��C��SE�j/�pdU��e���!U;��GJ�8%����������D������C�V���a�[�1�~u��xtr�������W�/��G�G����� 4_�W�G��:	��W�?�T�g���o�O�=6��7�Kn���&�3������+��9�+�w��]T�<xF
*&	"��!�W��A�<�4�'�2�������b��K
���o>3��w,��������>�7��+���A�Gj���>�9$�l�j+��No\�{��l�O�$�{���jKUP��j���g���<j����U���;��%���������l�������<=\���7G�"�X=�E�N�����?��zdB�����t�o8�o��6���|01YyLk���	J�K`�b*%�	�+yQ�����x7fSSb�p�����W.Z0���4����4E��6��m�8 �&�j��!B}�E
��������O�(���h�F�P����&�Fo'�!�9=����G��4�:�p�[�(�+�QY-���r�6��Jk�y1J������WG������>e4|{��aS��R�)����%��G%�J��F��=�����K�a2�^s�<�����P����[9���+��1X��\I�;$���z��mx��1T���f�LG;���q*��q�����(�X���aS�5����9�y����h��������R2r�kWU����������B��m���F��xR���R&/*������)�m)���Z/���a<9���P���Ng����a�������P;�Z������"���j����"r���A����lJ�����#��������Nu�tL>J�I����Z�8�����D+����>0p��X��fX��T���\�X��CAe�-�D,��+[9���+O.� �����a����o�������I_��wM����mx}D9F.��*�6e���br����B�q'���d���6[���C��/����Wd����$)E��K�&�`W�����e��f����<��5�~�x�o��?�Y�F�����xBvc�6�lq8���]O��'j�=Jn��]����8�\;��U��9YR��Re�T4ZZ-*/�F�Cz;���H�#��%�=�@&>�zll�t����#�=��;?~�����#�<�<9;�����C��a�B����IQ)8A���#�Gc� �Fkvt����OM�����e#��"<�6 ��-�l5�����>��F�O���Q������� �~��]F;
����9�6��<�&5�9�q���.t���8p�)qO,�r�=�"��}���W��O���d��)����$��t�n3>�ex�4���i>�D�����w�b�����+b��d9��C!SQ����e;��U�1�@�Jm�T�&,L4:=ykl�����s���[����G��*�a(�H����Y��*��rND���QUr��u�����.C��1)��v+	
�3�m�#�a��0������+�������D��{�aW�w���v�����~�;��nfD��{����tB�K7�Lr^�{=z}����Xsm�/p[v;�j��kv���"$��4q�|i���ri"�(~q��c;�2����������h}���a��z�#{��4)�4A������dj�.���M��������
�T���N�3����=}���=�s15����F)_���������=�x�/z�z���2�/l(�
0
��\x?`�LUW��1�:B�BK�>+��A+�yqS�	g�m��i�3%C5�*�E�s8PM����F��db��pE1]�������$��)�dg����\���odi��nDs�Ym7&����^ �c�I�����6e�B�&��%����Oqh'
�I4'b���*X�p��3�i�P�*�u��8��G�6M��K�o����$�s�� �"�'Xz1���+���2���d�X��E8`�����e��O����h���NY��	���T����>�������H�?���XTx	���6
r��\m���pt\���R++,)?��F#MG:8��R�H�1�p�*�`L��S�7@��F�� �F���:ki�kg��}��J�Jn�����8rI
�����4�e�i�t����<u���� e��X�fZ�S�dL���-n�s���^��rU<�b��O[��P����4�?�S|�?���������#��\�7�.N����.��Fi�U.�X�J�'U"g����ci4g�a�i5��QbkS�>\N��$�.��7M�Dj�C��a:a��5�|�~����4�5N<�H�:�	0M�
#v~�I�	K~���.�����D2���f�Qr��A�F����bK���%���h.�d�R�'���c������������/g�V`Gq�	l�������we���N~n��c��=�Hk�KFvD��I������X9T:d�q���)q1�348?�{bc�����
�K8eP��E�~(�#�w`���
;���Cl.��!j�F2�t�-�� �v���g"���3�C�d����Wz��e���������\����">��I����+~�-�������rT$�E��v�)�������w��f�����T�,H�Irz�|<QU�'3~�9e;+r���9�-�7���h����\�����\_f��	%^Waj�.�@l��?�����b)8i��c�4Q�R�M�_��p=���(����5N���7R��1��=�R��^)�^.j���F|&y�Q��B9���:�:N��q����H�|�J�5����i��*'a���J�C��.����|�D��	�1	t�J~��mTf��Ew��<��a=	��Z;�c���P���
�������k����
U��0�jbR��{���W���r�P��X�f�x��D���Y�F^.�n�m���D9	x�%R��N}H���3�^��PX�x\3&�����)��}����v-(�~F�4�X�^�j
.����.������T�+����S���CK���-�=���.X��w*���_Q�53�U�F���E��T���K�&6n��]��Ukg��m5*�����"�����{m��v����h�U��\�@|{�^�)z���f�����h���67'G�e��Xg�a�	��T�s�T<[d���~H��_�nG����S�{c
c�v�/�N�w_R�)-l�C�L��F�Z�a�i�S���h��� �d���R�s[�<�{�*\���2�)��(��y�rMw��D1��X��&<��~���Q����M���l{���6�Q��W��H�|����hj�wP�=���N3Q��1��:M�zo���9]�f��>z5cG��cz�u�+�r��N
6��k�H�1���b	���b�E�b�;��������2����|q�8����"j�������������W�Kw&#����g���U�e@?E`I��61��~������[}3��$�pbc�C)>8t�����;z;"�����7��/R���G&c�5e��8����]�i����:x���/�3I� �]5��>���0���)5�{O}a�r����B�{j
��f*�W�Kh
�^V\��)���8�����R��J��5���a��`b�+R~	n<�^��4R�.v�,u��ML��v0N�4�T_z,Q�D������
ot���C�'&���I��TQ>�Z`W	��w5sORe�������JY���&�U#�XC���5��gl?m�i����<�e.3����4n�_M����[�i�l�2K�����Q����,�Z��wpI/�aM��
|xn�aA���Ts�b��j�f����N���/�U����������RW	AEb��[��
�^S�{81��U�j��S���H��X��&i��4G��Q�6�;b�t�X�<EN�T���������h����i��2Gbu�s��b��}\��G���"�bN�!Q(���r��9u��������H,/��'������|6y ��%���a��=�����7�@�x�.� _�����	G:�kx,��#��3��&��A��`X?�w.U���[E�	�����t�x�����j�ql���$~������l��,O�K*�{)�?N�*���U��s����	��z���h�Of�zyS��m����_B
~dn8�S0��y��2��In���T���3�]��i%��m����R��N2�0��j�I�<CM�>�HQ?�nd��(Zl��lw�-�m������0II)��'j��_��������I�6��1��!s����<������Z�(H�^8cq�{���@����w�g;Y�P
�����~��g���� )*�}m��#�9B.�=������(���"����]����>��|���D�	=VYpD-kdZ�S���b)#I
X�[�A3��L	�p�@��Q�` &����R���l?��V>�vXv���/TP���Ix��LP)��*C��	��
����M�������11�.]��w	�����+EK�s����'v�������;7���B��P�GF=in.5��C��1TS�F��[��]y�f^���������WA��Q2�m%Ic���������,��A�_��\�W���V����U-p*TT>�A����
C)�k����a�]�Y�3k���bU�w�������4��z_�#���P�,���''��p��>��6F���f�+���M���Uz�as��Y�q�j��N#]���s����r;���z�x����	����!�m4J��@�9��N�w|���Y���x�OJ����-�����x��)���)�$����wN��5w<�f���rS6z���8���sa�`��K���B?��Y{Jb2G;g5
-����~���$���T�0"ur�x����,F+�E���	�P,S=�R���J-X����o���oe72Q�(���P��F��N���W�N�$�|#?�v�ha74��E�/S~��TE���D�X�d�Ft6��x"F�`�2����%O����s��� 2[0��.,M�w	L�V�45
�	�,�Y���b�m�HAMS����1ewR���4����Tl�TU�k� 98k��u7���4!.�2��b�gy��@�T����`)H}J���6���i�:����pIA�X�H:N&#*2�2�w)
3���qZ�l�M+��:/�� >�`Y��<����i�"��&d����E�y=��LO��v���'����B���7���A"*0����uE�)� )��[�1z�p��j;'Wf���\�t�s!�@R���4�9���a����������`��:?/L8FL��6�E:�����/�\�������OV�]�Q#��.��%�%hK�5(���8�$hL��'��dyH���T'�z�bxO�9�����I�=i����1[l��"/��We��3���f��,�v���:J��@�P�����Iu���������j����j��;�������yY����=d���K�'�d�����#����js�I]k�E�g#\y�{QE'����������$E������27VD���c�xR7qr+�7{l�0����T����su����"�������P��*����v���^ ���"��������~��iuz�R��q2q�)����Rr���,���%G8�/���e����d�7�C>��+�pT�-���1:���Jo9 �Z{�-�������y	�S���|��%wI����NM�I�
*sO�}w������N�����C�EY��������g���K�{C~�G&o�����J�����q�D_����q��}V��Q�I+U���t�GO��L�yZqGZP@��8Qy���/������Uk�J����NNU������g����w���P�T[
j����������T�\%�l��?���v�$��:�we9<8�g��x�����4��|������S����q�y������=���
���8j��VK9d�gi*�������V��}����j��R�c���<��	"�q��#p���z�Zp1�_�%y�k����oL��b3���`A�f�1�*�����Q��=p%��T\�`������s*!<Z������	l{*J@N�j����)86�h�&�)����B��&`�J	�;�ri�v����2���G�z�Vp��S/�����'��T,UsQ��c�Z"f#3���-e���Ix$n�q�FYP)�����lw����
�mp��q������ ����b,�RTE�]�����o��5�	������e����P���2�����Qn�����@�E��v(U�*�r�	����c�4(�P�R�?#w���pa�3�����-@�Wx��LO���+'6.=�����n{&�S<N����[}�h�[�oy6�T���U���$�<�\��~%�Al[��N�����������*���_A�+�p:2OF7�����"��N�*�))��~��y��hj)<$��U ���P��F�L�G�5q�6����8�����Y0����t�A������DBrUv�s*.4����X�^��v�A�%����b�L�
��A��RP�O�*��eS�OU�H�������u#�J��������CM�����S���`����Ld�����%�GE�a�tb��{�!��C�x��@`�7K-�����Ch��%3;��\3V90��Y�"����2<O�e�!����,a�y��K�J�{���

�l����p�v�U��!b�Xhybw�����"�����[W���o��x�l��D�b�����W'g�4o����r2mwc��f��;�;�
h{��6&�)�W��F����="����6;����?�;�q���v�������u0C�/�aM�y)�J��3�93�x0��m8
�m��rh#v�F��C[���c�;���)A��������"D6��*��Z�s[�B�L
l��.H��8�}�q�+�E��L���S����,_sd��w:����t���1lV�d��������<��T���F����v��t$�Y�{��s�k�C;�Q���+���M��9����3���}s��v�wZ����y���"L����"d���oZu�����")�{��x)Q�P%��aN�|Ghn��	y4��B��P��1���BCZ
�(��B����\�}`/<�hLk���=PN�.�����qNCw�on*����N�kq�K�4�D3�E�j�qZ�<�S����=h<���hFYJ�Tz`�SB���iS��qRi�����dh��.��>0@����jZ��|~���s��6�Z���	P��1�2F����G���v��>���{	.�5lu�C�&lN(!����H�
]>���!�h,q�<�7�frM�~?�M/��yFDD�A��(A���ld�Ss��:��Q���������t���e�Hm��p;�TD�������8����m�� T��a
��@�����K����3�D��+*�/j��~��t�(��u7c�QL%�@��_n�W�\o�������Zll,���K��I�R���SLsd��������D���su)id����e�?�����?�!���I��xL��P��u����|�u�. 8O���K�mt��K�Z����kr*���7��G��k�B��U)�kIkI:	9L��'�%��av]�Y$n�F��"q�5�--���N�.=<���`+Q��y@b�E���D8XP�3K�
U���l�/���b����]��RL��.���g�)LD|�5-��Na/��|�i.}����L|����Be���_���Sf2��Nu�=%���[L��_��������;����/R�-����������� G��]l���C�#ZFv��`���=�w�<;�{b�U�{�\9K���g��"�U��1����NH?�i�*��2&��mN�M+��(���������������}
�R�y�'�e���Q��Y,kB������[�)��&��y���e��[+��������53�(k>m���kHY�W/xI"������m�+KrG>��~r�9{�k���8x
a�$��-8��Z�O�S����<��\!4���+�y����|����i��Xw^5��C�P>�����:���\�r���$e�j�L���lpb���b�
q���dp������:7xO��h�=���\u8u�r�\��s�r�i����?�YG�>�j�ypf����{�"���H��!��>�c��j�=3S�Ty)co���en�%��y�p�/CaR�8,�� P>v�X �Tw����f��!���Q|(����!�Kv�Qd�a��6�Jv������D��#-ZqAbn��;����n�B,��p������$�����h��UeA�S'���hRAA|�=���z�l�z�9��������Ypu�F���Q���AH�����l
�'��4�+�>4���(4������?�U�
Tqv��j/� ���
Hp��H���\V��n��L% ���T���etb���X�~���dU�Y��n
M�ED���|]�l�w��[yK�K�K�����zi\k�sd���
��������N��(�
A�6�2t!��V.��'�b���Q5��'
N��>~�Qx�`�_�8[21"'�:T�Vt�<�pX�/�q��"�5Hrk�	8�N�X �������\V��c�b�@���)�M�������a%(��=fE�QU�y0;�t�d������gj��������e�ZtJ[�b|��=+E>O��|��J�6�Y��0E��aoks������V�j.)e5h��}n�����Mz}h��W$�1��;]�)��������V���72f8�f���a:�+_�	�F,�~&�D����=�f$v/�x0��V��}��������_��4hU���4�0���lf��+�M�t�o�
Y��w�o ���������5��fx��G��9N�4 0�����F�ex*��P0y2��hIL�hTI7�Z���@��`9��(3������V��7��"^�po\I��V����	���kfq\	�B!dH*m�L�^3�]7UQj��"o�L����F M{��
pE (T�#�,�d;($����k&i���]�"]46��gF\��#����#!���1NR����6B�oy�sM�-�JK���;O:��BVf1fqd!�{y����;d'v#��������1!�t�t����h
���1���>F��,�J����M�5��78`>H����Y�\"�I��2-"��a�#(��]h�?1!P�)E'����$�i��>�v��J�����]E���yY��^�f�Y�s���%�?�lN��
�0wC�.���~��9Oq8�p^�N0k��k�D��9�N|M����;;`i<������o�����AW�!�*�gCM,�P������.U�
���xhl� ��-}p�7�r�J4��o<��1c�f��F�Y����>T�����0c����uw��_�F`CEl�?d
!��h�h�+30����hUJ�9�M�)��X�p"iN�|��2;J7g&l��P��������9�V��8����E��zS0�!���"#��z1rL��t_�{T!o���� ��t�n8g���_��
mp��A�*v�Q3XwSR��*Uv���~������m�n�N��0,���{c-\xCQ�~p�o����)xU����c#���j�S�H�h�<����6$��!��H\��p�}�@��%�"�1){"���i��+�|�1S��p��&6&W+�"�z��c���(N3�Xr�=�M���s\�\#�P��C��T�&A�F6t:���X�;aF��R���o����/E��k84��� &��F�����l��X�l����9��f+9��'�(��4�(z��ol���F
��;��H�z7f��u`�����d(�Qt��BS�{�j��Wb���O�w�\DD[�����"��R��)-�;���7$E2x�L�{���>��B�=!�"�����~����t[�v�5��g\�by��I���5m0A�wD�mh��������hbcg��
s��~�������A�(��9���T���ez�������,����5)&��zk��]�GFF\�������o������DY~�MQ�%X��5�B����m�_T�������[��zY�]�}�qWI��4w����K��h����?��"N:��p��'o�q���7��h�
�]�CF�
*�ax�0��kN��d���RW�Z�OC����v���.����q�w�7�� +ITVMi�|t�[/��#f����j���.W�B�v�%�Wsw)�Rj��Q	=�1z���dZ���������@�J�%����
���;�������w,����
?bPe9���#1
R��T��y|�[|F��M�y�R����Yls7��N<�rhWL�v��`%,�����[A��P�(�:'R�.Q0��B�@��"���E��Pd=�Y�w��)!U��i�S���r�I6����16����A����P��|�����v�F��@�6���1	�|?
���{��:E�i������[�P����[�2��~dd|��.D8*� '���_Do�*�2-l������I�ZL�3w~���{��c3Tp�!cmc�]�k��8o���I��Z�$�E������� PLS�
��k������s�c'������I��NY�Hm�==��6�K��T�D��5�s��3���T�<)���#����m��8�-����p�za�x�/	�q0A�?F��Y�P�18�c��w�r�����ze�K���0V�s��.e�$�3$����@*�9�4�r��0������ V��Xb��TL����Q�����.���uJ����U�{�j
qC%u^&7<&��_w�b��u�q0/mL��-�:���p�����|�Qk�i#��o�6������c�u���f��e!��d��a\��/�L�M���QyA�R,��R�#SkuD	"�*����,������ocB�+�r������3d@�����f�UQ��3.��������&o���g�v����l4z�N	^\�m�����o$���N��S�c����U~b�9�<]�SHE���!�������j��oh��5�"��e�D���S�-����%�1�XO�X�h��d���u��yfH��e/T�ImSf\1gsx�.�$���@�[:[;��l(����g�Y�^oNg���-���P��jL)|�}��l����`�h.����.T�����l�O6GL���D~��o��bml�D9����X��	�2$�I4�kO>�uDT����l���01�Y�
�A-�\4�U�)�\�,L*D��y��E$�>9��c��<����������O����>��&RZp�gp0�����[\�	n!M�	���Yj����0��^��[Q��;����g5�������N����k�h{����d�0�?J�)�g�wc�T�v�z������������q�_���7{�q}h�pT�L������S�0�*�S�A��F���Sd	������$�\t����a�{f\{�����|[�7�8p��<������ D���U��e�����at{��c���V���O�Re��_]�4x��@���zT��HO\���-QF�
t�x	�~��O�7���a~4R]F8���,�Ak����?2��j�NY�����,����C�~y�����9?�V��K^M�
�����}����Y
@B��F["�#aG �J��Fw��_���]mj�������p���Q��(3|����ff�DF�"K���V���[�Ww�#e�S<���j�J���C'o?Pm4_+m�����Vr;0������������������2����":?����OON���=k��`�y3[�.mfk��D����1����y��:���J8C59��t�� �#�u��q��c�~	����zSe@�����%4y��]v"�}g�//4�kk��!,�	_Nv(�3�Du�UX�^�8V�Y�7�i�H�y���ZU��`�����EL�Pt��u7���f/�G0q�������h��
��d�{�~�v�����{������E8"��p�HA�,I\3��T)���woy	V���r��8oX`�{
�����1S;� @e�l���\=.>$� �v��H��
nN	�x4��8��Ng�(?���N���m�Z'DUW���#��F��n���JT���~�Z�w}�"�(os�^U��b^�Z�:���tm�����{0���v�	_03bOU�=\�� �������@6O�Q�
��3�b�8c�+�[�9��\�(�d:���z���t;n��E���=�m(� �,M�?Hb������?e�@V��6�j
�?�������~�#b�����"MM�'���z1Z�0�~P� �Hz^J��P,YG�i�Z�CU.
E�*^bVTe�(b0��[��sN���m�CV��Le1�d�giLU"�B�[�7�)7�~U)�����������
a�2oR�%}T#?���4�M��7E�K�3�G�DzK���n.�y� )�����z�CD2u�������^_�����aLV�����{�l>�������qK6����6���^�6��A��>o)C$\J#JdA�MO���o�y�����s�>�������2$��mY^QD�s�Ef�6*V&�$Ke�633��%0SZ��7���,������h�!XOS[�Y\�OH��:��m�m�&Bz�r��Sa�&{�����Gy�����L��pT�G��I�r�����-�ab�5k����*s�dSs����^TZksa�e���Z��5gv�-�nGWW�If�R
�Sa""v���D��2mN���2k5��A�8I�F�MY��T���`����o��z��7�N_��B�(��@�f:�$��"m�#��o����T#�,2T>��<d[����`���'A���S�._�r�5Pf-�`Z��@6Lm�y��"@�,�BJ�(�����C���������	�CeB�iF�U��QC�%p�������0E��DDA��d.l��O.���6|*G3���1����bx%N�2��+�I�n~����a��-�H<��+����B:���>����'De�ZjcTc��~.k�?�m��L��^�A6��j���{x�iD��W�|��|D$&$�2��V�q��$�������O�8�����o�/��]�N.XprT��G8(��|�y�`6C�m���c�������r��
�������w�����.�������~s�����VK���<�`X�y����H0�������S�E����'�~d8}�L��ANW,��4��������k ��"���V�0�6�r�E]1Z>R��e��'��.���74llcp;Sht�!���1��H['�[�4.�'�dm����w&���6�x��{dt�i/x�������LR&7���=�d�FWV*�&V�I���m��m�k�^���]��U.�5������.�F���b���@TW�f�����vk8h�[�wwP�)�JK�/�:���9��'�;��F�	�e���B�I���wt��53�����@�
�G��'������`��1��q��]
7;e�?zju~������S:L�R�����<��"q��g��_x��i917�k�Q�
�s����M�����V�q:�7�U�f:>>{?�xut:zs|�����w������L����'����1u����d���n�O�����#rq���'�G���'��02*�}��X��>�E0����C��}����`U��i�z>�Mx��������>p�~(VI�����9)��.�l!�y��|w��������N)�*���/������2���?� ���[���+��������$��2e�[m�Q�lW[{�2�`����9�L���ez��a��$�R��Od�S��<�TNS�ycB-���\I�|1����j]{�#�={i�B�)i�����=�B�,6��M1�_�Vw��lCK"��f�����cL$�&�E�7Am����mv(7z&�=l*1��r��Nr���y�������N#�
��~��W,��E�0�w������MZ�!V��&�z��DU-��@j��L�q�"��K��u��1���+
(�s:
\���QZ~k��q�R=��6jQ�U3�U����v����j��na�Sx]�'��@�.�v����s���S��gt����~�z$X�f]�rjI0}�>W�3;+FJ+�y����p�������
L V^t
��+:?��S�2|���R�E�T�Z�8������'�;3O��^��
i���Ou-C�iIe\�E�V��q�M>�A����3Ui�#��,�L2AD8 ���By�lo�3��b����5��*�����$���p,q>�zCAv.%����l�>S_(��'W������������X'�+S����#���vkDRM�����6E�N�~����9�O[F��a����l�Qx�*z�������	%f��z�9[9P�C��W:�������[^m��YY�o�(�����\v�fY�P��J�1��>�)�����������}�9�<����������Wg_��~}�����[��Z5�Gj��^ �70�GU���&��^�U���z]���Fp�R*�M19hZ���=�	�����)�*�`C���W/�'��l�"�����k��SY0~�Q��l�<bM(�LH
 /���q3�P#he������#�h�E5�&~�F�fZ[�d�VZ�(?g�u;�:��%0_�����&l�����Z\���8R��vs�C�X
��i�1U��Vr��h�����ri!�eB�b���H!���m����e�U#�[p9���SzH*�Y���������
����L���A��s�����:�^o}���BV5%;�N����J�J����x����
�$�Q��nb*�������t��|/!f�,g)�K��������Y�7���6d�R���5��W����`�d#C�8I\�j����&��f�<.u���g�R�B����~��Q5��Q�C�q\{�����Ipe��K�J���x����	�sc��(\I%�V��z�B

fP�c `���`�K�`2��%��6�q�R&{�/�z�w{A������^��w$������:��L�+�V5�[h8
F �O�!N����U�w�{������X�xF�a{�+����H��m���:y����T�'<��GI+<��@_Pt<MC�JUe�7��S�1�>rg�NM�v��;�<7L_o���
OL�t@��vJ��*g��<t��^�!"���j������i���8P�V���8P{��2V��j�(�Eao�;�;��B^���KR������S�`��rn�Mwi��H4:��*.+�Ib�,w����ST?mr����t#_��
e#�/l�
+x$��g�u��m�9
�������J_{*�\V��t.����/'���{�N�t>���h�g�����m#���?mu90�uZ����Q�K-������s�{��P���^Q6B�9p�@�|����B���7���t�v���^f�v�z�re���`�K�y���X�jK:(�g��=�R.��}3!6�� Mx-����%������C����'[�I�gO��������[8�H�3�Y���(�$�9���r���z�ew�m�)�yc$19���k��~4��W���������c�P�2QM�"��e�������6C��k�^q��
Q��0g)�K�]"����+�*�jlWe�������W���{��50��S�?�G�]�����h�s�
�{��:��"�lt�Z:��F�s���d�OS�����Ag��[z<��)t0/tV����rN�?���v���p�N�v����q���?{*5$���r�6������taf��8���	5WS��k#�������igT�K��c��$�Wd�`�8MH i
�LU��T�0��vE�J�H��*%hl��\^�`	X����+r	����<
��U}8�o1i������W����;am$gA�[m7��VwX������W���=y����23�!������M��.�
�h���D8E%w[R:T�!�����Go��5��ppA%1@L��"�CN��r���������7���F����� 
,��v������bX0����)���1���i��`��rr��/���0}C��
��k�uZvna��������
	j�E_�{�v��.���E~�s��nd�f�]9M�I��G����e~�K�R�D"������'�.�	��
VY.GH8=`��{�^~�V��u�����������\�sZJvp��d�i�{>_8}��3��������t�tx����BYD�E�#E�Ep�����X�Z���8�8�����4��l(�]M����H�q�l�M��dd1u�q.�R��8�dO�����c��?f�q�����5�rL|���y�4]j��A8��X��������y��k�$�_]������WGoG&�w�fo�{���v&G�����>��O�0v�&��l[��\xq���0�
9Rhv�!J��s�wq�<�9e�/�v420�����-��k���,����z���K�aY��e�����g[sv�w�ax��: <����n
q�w�����ve� u�	xrB5c@�������\����>���ML:L:�|�W�f�%B9����S����R��S�/,n{�,Z���C?���:�.�:��=#tw�|��Rn��,��u0U9����/�2s����=��41�c�)�^���w������u���������[��2�=2��?rT�$���l���#p.l�BQ��hPO���{?�q��|�e��M�f�@�H�D�ser�>I�(������{�#/o����hu����TZ>���eB@�Z|��<tYY��e(������	FZ�r��������r1*N�����e����Q��)'4�N|M��h����n��b�?���f��lP�����b������j��A�^��`h�V�#[� *n}]���JW#���H
��
&�����v�U�Te�R���he{���t�����C�j?rV��DO������yp6��t$MY'���x>h9J�;v���o�s@�����B�9�s#��f�8��4��iJ+�%s�_%�����T:����@����fa�CR�ba�BG(�N~��5em����[TX��J�<�����4%|�� .��jY���_��S�F�)��@�l�z��_�by��LD�~��6l��Yy����21g���[����l��M����d�f���=48iR����n����}�Db�^�tv�`]�� C(l�]�A�zjy���c���]�|�0;9��Q�D�$�mA/�j�u?F���=�XF���Dcp��9J-�
2}�M,6W��,DHu���_I���|�}�,$��@�]���e2Xi�C�`��	%29�lN�mF"�����sn�
�
W��q/���Q:�B���w.�%z��	-�f�������H��O�.�b�=%{5���X5������&�2X��j�Y'�����?[�J����������:��=�*s�j�����8}+a�%��fw1��3����[CJ���*����`��@yp��\���Z|�5R����dN����:�#�(M��!�f:	����w���c�d���f�z���wf�q�c��;�d?O��T7c�H���$�G�&?�lf�xxJf���|���Zg�{�;��d6���lo8��b����������z��9O����f'�/�Z;��!��V�"�X��_d�A��dc����E��'�������L�BuH@��&�\�����7�z}�v�M7�0c�IJ�lC�n-x��a�q�+=`��AU����G&�B�:Rb�x����2<����)�_K�X]���F9Q���:����zN�C<��r���O?���
��!8�t�p�+�)^p}i�?�\c�~���z��ac����� ���qii�/_��� �/�A\7w��_��	R��q�?�7���������+
u``�����]J�o�nq��'M=���",/P�4
�t�����K!;��l�*���p2F	W������,�������(h
�`8��	�*��P���# �A��M72�S(���*���JU
ML��I?����|����^���y{��������I�����<=�jN�Uo�;����[]��qH|$��]�T�y���~��X;������)/��K�;8P�C��^�>-��;��4��n��i5���h���F�?��/�-
�������`����e��Ai���5��V�7m���Ik0nf�5�O��io6t��=��[:��i��F�9��i�^�p����.��`Zl�#��.|�T���C��Z��7��/yYj�=����s���y��>o��F��(]l�x�;t��k��{�l����Q�TJ�/��7���I��	�O���Q<~�q���k�����COK�F�
�4�����o*S�&��s�r	 ,����~r�9E28����u����(�D����O�U�`�
��d�s�n��1q�``����^��<�i�TB�	S�6��1�rVu�)b�-�����)�Yt�
�#�%�Y�+��e�T���@�<
R\�
o���Z��s�� ]�J�y�N��\�GA�C�2fI]�b��q�w�����.�\G'S<2@%=�B�e���������)5���
�|a�]g�l�Ig���N��Nq���`{u�VRd��O]Q��dh�)��z�ak(T�'�b�c{������2��q�i�h�)0H7�q���^W���b�!�b��9����CK}N�iq�>���l���������������i�!?4]��_&b�5���
'�{�9�JzJ`�[�v�k���N�|��*�us�c�B�";�O@�0���P�NN%3oM_�����l���SZ���	Jj�!��(��n���.0(t���]���q~rz-�0����/c<��H�h8^���C���}�/��OxF��S^X��i;���C�� N��*���#|�������1��la����j�2j��mDw&��������t��)��>JN�5��W�F�r\���������A�l&M��������c;������Vub�r�.r*:C�*�U��������*4�o�����:��W�`�����o�a�]m��"_����s�*i�78��JP�<���KrTt��*��|�q�"|�h�4����+����k�r*~i�<�BR#'����9�9��Z�ytdS�X����	n*������s��
�a�%�EEy|D�������u ��;�%��/$+�G	��*����)Z�,�����'����K��G���b8)�G�xu��8Q��um@5��.J��z�q{�|/9E�S����O��JY<�S����=&�5�8c/UuM���$���a�O�����r��O�x���x���r�KUX��Y��Ov����o�<���z�Ty��L&���[(+O�j��-sRob�R&��E���
Y^��u��6N�3�!p@����f��c��/���:����X�����	H:�Y���Sf7hf_+l�����!2�5I:��{�h��h�M���@kFF�{��5��LRh}�pA^�_�i(�[�5��SZQAF����'s]���@��4��q�����U��@�����������#����6�Y���v
���&���	�	���$�+9o!���8�	�~GG��h�{�N���0�Q<L
���4�(��=�����������SN�f������b��8�S��RXx�z���R\OmK���:c.o��
�����S�kVV}��(�!�=�d��H���/|���a���f����?M
��*�����:L�/d���R��>�I�~f�nr�[�0��?j�-k�f������4�9y%����&�V$Kt�
���@I��n����������o�{|M���V�1��$�>d7R��Oj���;Io�Y��
�j��X���m����-�k��_P-O?�����>�l�����1|���^R��/��o@�������uX2�%�ITK�Ja&X-k�wi�{�a��h��e������_��;Ri0�k����g���8�������s���7�r��=f{���:�����lt�����w:;7�G��������/��z���{�w���q��b�5#�pOPkg���$y]��N��VT�r��5���������Ij��:���
���W���r����f�=$��n�.�����>(�f��O�hqM���_���O�����i��L��n�7�D>�d�@����|��&�`d(`���
��O:x�l��0z���Y�SS5��%f�
=��/�F�=�g�D+��q�V������7���~k�n��`�d���������I�'W7RP��=Y��etn�����v%d@�!H�r��ml�d��Q
5�H����# X�T_�a
0���3��.�r������r��YE�d�A�����rO���30�sS�N�\��R��� ��+�*7+�?@J[�VQx��l�0��a�
�$�K*�5k�����1��8dT��D�������x�������i�K��8��cPb%V�� ��9�������	n�^������j��Y�\�d�v��J���(��Jv���<:=>~
���k�H��+�G���Q�������E5����"����7d8�Uj:+���������K�O��<�<5)gf�������+o�'�h9e^$���u�����,Q���i+9��X\B	��0*���x���XW��{1LRr=x��U*A3�������2zsv>������������%��$����V�3�q��_F�N��~���G�+��a��rF+j�d-����Wx���G����3~��G����w������_;�BoS��/D7�����y�����R5ty�lc.�����.P��g��kv~���%����������16[�I������;�x�Y�7�x=w����_������������'�G#��%��q�����/���g�|���\��J��9��_�#3�7����h�������/3Nc2G�
2������������Ag���t�F,r����y���j�r�-����+��j
 �u��������)	�8�\;����OON��)����C<O)��wx�5��AW���j�3b:&I��^���p'�AH�{����b1l��a ��i���'�\70�����G��r:0Jb����{��U��giH}��z�.+��H�82�*)h�����ix	&AJ6�8�����z)��\.�{����v��f���R�d���o<D_X���[�����S0q�����8���m�<����10[o}4d������]K���O_����tF���L�
|5���
rI��"�q�C�e�����$aF�o���[����[r
9�	������l:��z��x���4"�P;�"vc6e��pO5�JL�m��~�Q���tm~E����X���l���^��Q��]S�`)�X����O1��Y�1��L�� aO����?`������u
�b��@\��[���lCgr;�Gf�z����Q��}9�R���~���F]�8`��x���=�V�!)7Z
�L�zU��7�����NH7E{����g ��Q�,{����P3�^�����Z����5L�jI^$"baTqg�N����_�G@��p+K��c[��P5B��� ���r�w�����a��/�7 N�n#�����x��`W�7�^9��]�eDn�5c�k�l3i5@mv�V�EB�I�"�Z�{�hY�Sq��c�}���/aH�g\��@q��k����;���@��i����8(Vj$v7��(�0��d�/4��$�e	��@�HM2�mT��T���{�;��A�C��B��;�.6�#��MPc\�Ga
cvj��}����_���]��%���7k�'�A��v��d��&�Y�������t[�~w��:�����������(�L��G>���#b���`=6�-��'��Q43�A�91�(��SlXgcH���I�7�=��F	"���aL|vf��i(�������$�����yT��)�@��;�g ���z���_��)��A�^�=|u��[:~�u�qc�8�������	^w.�*v�qD��Gx;�H� ���9�D�PBp�eX�K}��B���)�g`�E�y'��OH7pM��1>�������ds�9���L��Y���ZX��7k6S
��h�tc6e�hP w4`�&�������p�
]�8����a;��#l)Yw���a}��Y�f�S�l$�\F�yM����b�����`�������Y�f�������p��Y���U/G������_OE^�ZJ�!���M�Z!�,KV�?�8��Iw��Vem���M�I����~�N�gZ(�v���.�����l�_�,�������o6�<S�/����i���,Hh��XH�#��E�I6��}�����Mt�U��-I��n���K���MF��{�S���NT$����G��^EmV���E�������&k������
����Sb^$i���4�O�Gu�����%�
3,_(/�<T��x(��F�R�������o#����7��C��N?����������������<�\S�&j��e��1�P�%�~�
����+�3��ElU�G�NZ=.J����w����u�	^��)�E+�F�$n\[0U���9�C�\��D<�����@��!z`B��W��-��!RJ6Z������r��V�nCT]��5�X"L�?Z$��MV��U������9t����-�DgT��]	�ey�a4Y�,��b��2]�{K��Z�o�$�����n�d��dg=���BO�u����_�=xn0I	V�7{X@z�9r���K����OI4e��f!,s/oW_�~�������Ki��[�st��m�g�����/R?e�?�&�"#��w�������a���!UOX�+�v���5�����;���������F+������~����H����&������'��p��v��i�&�Y���
;�Fo���?���~��gH�@LCE��(�,������B������:�>dn8�9��%P	�tkI��f	3��W3r�����P������XW�8M��F���"�i_��;�F
9,��$/_ ����
o.��2��@X�C@x�O���<�[�����%d��	 ����A���AC�s!NVL��Jn���coC��� ��X��BE��(�bQ2��8�|���n�a�����]�.��_�deZ4�T���`��9T�Z���'�t�j�v�9��488ezGD-Q�H
�_q��Y4�P�����#e�[��Qz������'��L��o�\=�\
D����iZi{�F�`�Vb���d�l�)��9:�/���]�	
�9)�^f�W/L�aw7���Er��2(w� �{��2��"UB&�����A�V�b������p���V���v�b>���vw�~����E�?{B�h2��~����w�$e��@�p�VD���n�*�4tnw��j�)�����T�B�=���� �5Z���L%c�H~%�HI��P$+}J@�q�����~���UQ�'s�u�S���Qp��pa���%E���-@XY��$R�]��7)19-�j�h5���b�\�xT3���~� ;�����oE=R�T��!Y�)�Z�����)��������ZE�h ��n�J��E��z������P�/�d:z3�;����.��mT����p����.v�T����7��%���$'SN*��'�H�e�6=D�=�X����O�����zS�Q3h��!����U$��hg��*y`6��P" '%�%���9���e�IkP��Z�Iw�/H.v���VR��OU)t,>$�@9f/���m41�m~����{��cQ<Q���7-N�0�-����F�����
IQ�@2�H
2�sFP#�.3���\)*���X�g��(	����hN�)z����mq4>~�[���6��
aHS7���^Uu��J`��E�g.���9��}�����z"��&��^�~� �y[�0<$�FV����������.s��������7rr-��~�]���aT:8��B���V3��z �c{R�`TqW��9���u���
3(�NN��sf8���b�
�����.���PMm�,�����\�*�R�<�wI�%Ui3�������E�	��i$����x[!8��s����F�����H���m#����M���=3jL&8�k1;�������4u�T��a*��x1_Z���u#���k�{�6����2P�-�����QC��`w�^��ThE�)��u�l!G4`y���r��"��~��w���Y�"�R����������I�����d��N�n�e���v����:"6�������?�����iP�R+���2K|���j�*�	�(Q,{�&a(�ux��bI������XZ
����
���u������j����7RAf���RZ�^t��{?�����z�<�Z-��L��n�>�����hXl�]�j���R��E�US�V������vy1�X�����w��FMe���v���y�z�F�|�i�q�5�s��>��Ks!;�������l�(��c��E���[�G�{H���T�a+���;R�9�����B��$�>.�I��=����^�w�nsV���g��C�9~<���g�3�S�PXQ�~��r�&�� F���3�����*z���E�;q�i���N�F�q�{�������^m#��{��UC�a��"�&������mexmN�1z&Y��Xv���4���}�n�9�_�6[���k�(d�e�0���7$����e���p�h�Dw,gV�b���-�y���L\�v�1��k�@����f����8��J�c�"h������}����A��X-FL]�k��t��L���a��-�����WO;v���� ����5�b��Xk�"OA������	|~�;���S��B�����z����S4!l|�8o����o���$�-a����H�EJ0ET��u��
���P���F��ns8�����;�Ya�t4�.t�
I��M�6"�SF�|��7����������W�>���������Mo:��{E�k��o���OpC����=u�������x�����������\T�>��A@Q��7�g#y^~	X�:B�;4��Nx�q�-���#'����t�m*K�}#�+%�9�a���.r��Lp,},�����������
�_y�����E��<����GB���WB��;>�^F�:������{�D���vg������L�S~{	D=
�C�{�.P������c�a���L��Qw��s�����,�?���,OE�>r���mE|<)���S}/���kt
��Z����o�<q�j�����5�s�`6��f���Z��g
���Z-�[���Gv%8[��b�}�����{��C��2�gX� ��xG%�'��Q12�~K�:��7��
zS��]���j.������R`�L��(�cP�'^��f\m�;�@��;
�Iq��|���2j�~�&	/�w��6�� `����a���_~�g�Q��Gkk�pSf��_�\�]��@c3&�P�{��j6z�^<�W��{��_���?������v�={��d��{�N�?�Z�~���������NF�g�A����� ��������� �c&-�$2���~�R!}n�9���\���\T�^%���-0��
�F��h;yMI�Q���������D�H���������H�m��x��u��ad+��]_8eN�>�����^�q�"�c��5$��W��VHz�	��P�9b2h�����u�"8�
�s����������X8G�s��
@��F��{��c�r��n\��KkZS��R����G��<`���G��z��0>��
dNT��A2��������"(E����b��������l�m$�,w�E�,Z�aI��'�3^8N`{���@I�����x��������)Jv�,�
$��f�Y����, /0e��M�Ud��
����+�}��T����O_�<a�nJ��>�cL6S��Zx_U&(g��b���X�tj�P�J^�����VF�f=%�Z+�a��d;�� ����&��Ad{E�;
2�w��	f4���jL,{'bYv����i�#�:��R�/��8���Vy<�<��X���n����c�����f�ecW��M�HA���X��jX���;�8#��zE:S��������Y�H�"��'�
gK�����"�G�v6w���!Q�0�f��t0��'���S��K�J]L��[�&�=���|�>�GlUq�������_����B�6��g,���X?�b|���&E����m�:�!�����M�(��Y���w��W>}����?%����L��=KBb>\�\}8�����V���
7&�L��$�z�����m��LS���(�>�hR\P��9�p���:�eX]��������cy�i�]�^+��������6���s;�kmgi�-,�U���r���$l�S��(�`9Z�rCv��Jq�k4{��4�������BE�H��e{+-����c�/�pKI��Zg�W��n>h���������xK�Ty'f�4|��7�i�3��E&$V��R5��Z4?c�k�On`V�DDSHa&��!\����s�3����'���R�'���h)����J�u�M'�D}�����"Y�
n59\^�GK�?�{�Djc{�A<�g���gd{
�g#�'�}�r�l��C�0������7G��z*7Tw�p	P	>�e���E��v��n\��i�����H��h��^��n��������v����G��w'�v���m�g���O��,��#��1��t������>ppp�xb&��c�IV^��:�N�>wt��\ `3?*�& �cI�2�w����G�Q; �����[�&��Kz��lf�m����+zw��d�f����bc�Xz_�#����7�9�%�'@�������-�����Db2�{b����|J1'~���j���zV@yG�C�	y7R����yc��k���4$^��RE����\���w,���bj[o�a�� ,R�g� �!X�����!�7�bl���[2����:F��`2~�?R{Q��z�6����F����0Z\��R��c��-�(*�'Z����{"&������O*r�?7��X*���h���������L����x>1��S�m�zZ`Y�{�f���.��<]�����5���t�?�����V<�0l@t�����R�z��[��`���g�=_E��������Z�b��n;���6�R~�-�a�U��g4i�]���'�I7���w?�%�z ��u:X��p/_�����{f�9��x�S=-�X$F*�O J�6WX��kqr��(���hs���h������}��d��+��3^`n2$�s��`C��w`��HI
����8�����"��<�K����a���G�1K��UNU��
�_a9<���%a��n��TX:����������8E�h�t3�Z�b�����@c6�60���GR9����B5�����d��Q���
!��b����2�p��,6s��s�!�X��1#�U�4`�-/����gG��d8S=Lg�K�z��l�I��}�oA��[�P� CbjK�4<9�uo2z��x����������-X������
{@�:����u��[�8Q"������� |�S�r9�:��������O��'�(�uo�3�M����������0=�h����;�mE�H?�"����w�9B)�G�.�GR��>9����"�x�a��Q $<�X��`<�b�)_�4�4���Gfn��VI����uX��������M�mO�qN
�������������}| ��pP�8��������
+�^���R�a�P<T�� Jq�xH��F���\��#��S�U�Z)��t���[�.��m��_�z��<Kd�I��Z!���A������\�6�/����7��:�C"����c�7���?�	0������F�������D��=��T���61�(�OY�_������+�q���v��z����R',_���}M?^[�e�ll�\1�3��t��A��D3��t�Tjy���`�ZoG���V%y:f�
;�7���r���,���T:
f���&����\����7��GV�PEQX��4����t:=t�?��'��h+clAX����>�u{F,�%�����������o�T�e���,B9������^.�:1g�a�F��n}�pE�u�,�������a�������f�w�b�)vY����'����JL��
|���!J��%���)zo�y����Q���]����}e�E�6�`p��p2Q1�V���@Ro�"SpT���H*�O"Bn��qFn�zm�#R�7�'���^L"�"u1��@D��F4D��k$a�L��e"����$�^w���Z����1�S��|���4z>3�z��$�5���*\��a����T���aM��bd��t����_x����"��|:����l�R���X�D�Z:�9�������dSX]���^c
#o[�A�^c;|>�
��K�S�[�������e>����"
�@@�P8{�b����1@!jk����&&
��u�s7�����X	6q4N��eqk�F�-�q����#� ��0�k��� Z�����S2P������x���Y�~��S��I��GX
6�i�2�������m�]��z��I�0a&���h��@u��A����*S�L�$��l�[�t3$����$�X���ub#����"U����c���t�����q=-�6����O��=�����G�Q��+�e����+�;q������0$��g7�<b��ZU���
�[�� J2�'���^��u���XJ�jl���S*	� �a����]a�������j���ir��q�����"������Z��s�D�P�?1������>i1�NZ;��RQ�7�o�������\�����������Ro�K����\=	��������M���^�G�N��A�P��l(Z�F�,@�}^[�A��/0�Q=����`���C��l4Y��#��PI�����/C#d}�t���W?#�����	��<��������4���������\����q?��)��34�
�f��4+��'�>y�Z8M�?�����b�*��f���c{�8(��4K�hm(����CKP��}4���a�>��9��m;��Ew�g'Vv�.\�����HB��AU�F�.���H%����h���	�k��Q��&3��$3�E���	��`�h���
8$W����O��?DV���N�����-|~�����RN�@�(��Uy��ts"�,l8��g)�3��u�Z�-2�a7O��4+`����~�L9��k�$��2�b8�������9-��m���N�u�_�is�p�#�"(Q�lq��
;X>�l��=�Sk����	����~m�	 ��a���H�����5�T��6p�vG���V�U��#�J��3?��
����(Y�"�d9_���Ql�y^�����Mi~E�2��1�5���N�����AD�E���o� �d+�~�b-p����4��bA���I!�x\NQ!d���Tc:����P	�f�����C�����@�.R�9F�Y��0I��#�
�t4���EJ�����7�Z'��l�5�5�'E+r<+k]���'H��i�s�%�=�� ���	�~���8`��'? ���/:��3dW�0~"������3����]9$��/��%����g�P�!���"&)��xwIe��V9As�m����<eN�i�'���^N�����������m�)�J"!�a���A�����z�[o��]���	��{^�Vo���|��^p@�)k"z�	�S=L'�gn�L�?m��T�����`,�=Y�����`�6��`�[��e u_H8��r��
{f{�����[��������O�yo^R<������v�@������t1'�`X��������m�[w/-u@���1�����+N�4�^��Dj��EW?�\�z�����������V*_.V�0�������~�����:������Y�j��-*pE[�
*��b�|�H4|F+��
��z�5sS�%�S(�T��{��R��d�U2��B�6��eD-�R�f�6

�����k���ye�G{e�2���8}6P�N}��D<X����X�U#H��&MFH�8�1���`��6F����w��m�"��������=��������$_+�5M�6���Y\���&f�F�`����&R����Q*;MGi1;)�{��	��)������Rv��AUw���9�$��d��m�3t&�H��K����xh;J��=�CJ������W��Lg�Z�S-���nq����KE�L����]�r+� =���[�u�2	E�'��)�&��D�>��.������|L�����IZ�to��.�^���Qo=,	���W��[������
��r~C���RX����7��6'S}��ua���D����4�u�����;�3�t�#�/��	i���3�������Z�L��g�V����le+[��V����le+[��V����le+[��V����le+��������
#35Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Andres Freund (#28)
Re: TupleTableSlot abstraction

On Wed, 26 Sep 2018 at 05:15, Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

Subject: [PATCH 05/14] Use tts_flags instead of previous bool members

Pack the boolean members in TupleTableSlot into a 16 bit tts_flags.
This reduces the size of TupleTableSlot since each bool member takes
at least a byte on the platforms where bool is defined as a char.

Ashutosh Bapat and Andres Freund

+
+/* true = slot is empty */
+#define                      TTS_ISEMPTY                     (1 << 1)
+#define IS_TTS_EMPTY(slot)   ((slot)->tts_flags & TTS_ISEMPTY)
+#define SET_TTS_EMPTY(slot) ((slot)->tts_flags |= TTS_ISEMPTY)
+#define RESET_TTS_EMPTY(slot) ((slot)->tts_flags &= ~TTS_ISEMPTY)

The flag stuff is the right way, but I'm a bit dubious about the
accessor functions. I can see open-coding the accesses, using the
macros, or potentially going towards using bitfields.

Any comments?

I like this abstraction using macros, since this will allow us to
conveniently change the way this information is stored inside the
slot. I think for this same reason we have defined macros
(HeapTupleIsHotUpdated, etc) for each bit of heaptuple infomask.

--
Thanks,
-Amit Khandekar
EnterpriseDB Corporation
The Postgres Database Company

#36Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#31)
Re: TupleTableSlot abstraction

Hi,

On 2018-10-01 22:21:58 -0400, Tom Lane wrote:

Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp> writes:

At Tue, 25 Sep 2018 16:45:09 -0700, Andres Freund <andres@anarazel.de> wrote in <20180925234509.3hrrf6tmvy5tfith@alap3.anarazel.de>

On 2018-09-04 18:35:34 +0530, Amit Khandekar wrote:

Pack the boolean members in TupleTableSlot into a 16 bit tts_flags.
This reduces the size of TupleTableSlot since each bool member takes
at least a byte on the platforms where bool is defined as a char.

About bitfields, an advantage of it is debugger awareness. We
don't need to look aside to the definitions of bitwise macros
while using debugger. And the current code is preserved in
appearance by using it.

FWIW, I would expect a change like this to be a net loss performance-wise
on most platforms. Testing the contents of a byte-wide variable is pretty
cheap on any architecture invented later than ~ 1970. Testing a bit,
though, requires a masking operation that is not free. I am not seeing
how making TupleTableSlot a little smaller buys that back ... we don't
normally have that many active slots in a plan.

I measured it as a speedup on x86-64, mainly because we require fewer
instructions to reset a slot into an empty state, but also because there
are fewer loads. Masking a register is just about free, loading from
memory isn't, even if the cacheline is in L1. The other benefit is that
this allows TupleTableSlots to fit into one cacheline more often, and
that's noticable in cache miss rates.

Greetings,

Andres Freund

#37Andres Freund
andres@anarazel.de
In reply to: Amit Khandekar (#34)
Re: TupleTableSlot abstraction

On 2018-10-09 20:46:04 +0530, Amit Khandekar wrote:

On Wed, 26 Sep 2018 at 05:35, Andres Freund <andres@anarazel.de> wrote:

+
+/*
+ * This is a function used by all getattr() callbacks which deal with a heap
+ * tuple or some tuple format which can be represented as a heap tuple e.g. a
+ * minimal tuple.
+ *
+ * heap_getattr considers any attnum beyond the attributes available in the
+ * tuple as NULL. This function however returns the values of missing
+ * attributes from the tuple descriptor in that case. Also this function does
+ * not support extracting system attributes.
+ *
+ * If the attribute needs to be fetched from the tuple, the function fills in
+ * tts_values and tts_isnull arrays upto the required attnum.
+ */
+Datum
+tts_heap_getattr_common(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+                                             int attnum, bool
*isnull)

I'm still *vehemently* opposed to the introduction of this.

You mean, you want to remove the att_isnull() optimization, right ?

Yes.

Removed that code now. Directly deforming the tuple regardless of the
null attribute.

Good, thanks.

@@ -2024,7 +2024,18 @@ FormIndexDatum(IndexInfo *indexInfo,
Datum iDatum;
bool isNull;

-             if (keycol != 0)
+             if (keycol < 0)
+             {
+                     HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
+
+                     /* Only heap tuples have system attributes. */
+                     Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
+
+                     iDatum = heap_getsysattr(hslot->tuple, keycol,
+                                                                      slot->tts_tupleDescriptor,
+                                                                      &isNull);
+             }
+             else if (keycol != 0)
{
/*
* Plain index column; get the value we need directly from the

This now should access the system column via the slot, right? There's
other places like this IIRC.

Done. In FormIndexDatum() and ExecInterpExpr(), directly calling
slot_getsysattr() now.

In ExecInterpExpr (), I am no longer using ExecEvalSysVar() now. I am
planning to remove this definition since it would be a single line
function just calling slot_getsysattr().

In build_ExecEvalSysVar(), ExecEvalSysVar() is still used, so I
haven't removed the definition yet. I am planning to create a new
LLVMValueRef FuncSlotGetsysattr, and use that instead, in
build_ExecEvalSysVar(), or for that matter, I am thinking to revert
back build_ExecEvalSysVar() and instead have that code inline as in
HEAD.

I'd just have ExecInterpExpr() continue calling ExecEvalSysVar. There's
no reason for it to be inline. And it's simpler for JIT than the
alternative.

@@ -185,6 +1020,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
{
TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);

+             slot->tts_cb->release(slot);
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)
@@ -240,6 +1076,7 @@ void
ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
{
/* This should match ExecResetTupleTable's processing of one slot */
+     slot->tts_cb->release(slot);
Assert(IsA(slot, TupleTableSlot));
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)

ISTM that release should be called *after* clearing the slot.

I am copying here what I discussed about this in the earlier reply:

I am not sure what was release() designed to do. Currently all of the
implementers of this function are empty.

So additional deallocations can happen in a slot. We might need this
e.g. at some point for zheap which needs larger, longer-lived, buffers
in slots.

Was it meant for doing
ReleaseTupleDesc(slot->tts_tupleDescriptor) ? Or
ReleaseBuffer(bslot->buffer) ?

No. The former lives in generic code, the latter is in ClearTuple.

I think the purpose of keeping this *before* clearing the tuple might
be because the clear() might have already cleared some handles that
release() might need.

It's just plainly wrong to call it this way round.

I went ahead and did these changes, but for now, I haven't replaced
ExecFetchSlotTuple() with ExecFetchSlotHeapTuple(). Instead, I
retained ExecFetchSlotTuple() to be called for heap tuples, and added
a new ExecFetchGenericSlotTuple() to be used with shouldFree. I don't
like these names, but until we have concluded, I don't want to go
ahead and replace all the numerous ExecFetchSlotTuple() calls with
ExecFetchSlotHeapTuple().

Why not?

Greetings,

Andres Freund

#38Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Andres Freund (#37)
Re: TupleTableSlot abstraction

On Sat, 13 Oct 2018 at 04:02, Andres Freund <andres@anarazel.de> wrote:

@@ -2024,7 +2024,18 @@ FormIndexDatum(IndexInfo *indexInfo,
Datum iDatum;
bool isNull;

-             if (keycol != 0)
+             if (keycol < 0)
+             {
+                     HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
+
+                     /* Only heap tuples have system attributes. */
+                     Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
+
+                     iDatum = heap_getsysattr(hslot->tuple, keycol,
+                                                                      slot->tts_tupleDescriptor,
+                                                                      &isNull);
+             }
+             else if (keycol != 0)
{
/*
* Plain index column; get the value we need directly from the

This now should access the system column via the slot, right? There's
other places like this IIRC.

Done. In FormIndexDatum() and ExecInterpExpr(), directly calling
slot_getsysattr() now.

In ExecInterpExpr (), I am no longer using ExecEvalSysVar() now. I am
planning to remove this definition since it would be a single line
function just calling slot_getsysattr().

In build_ExecEvalSysVar(), ExecEvalSysVar() is still used, so I
haven't removed the definition yet. I am planning to create a new
LLVMValueRef FuncSlotGetsysattr, and use that instead, in
build_ExecEvalSysVar(), or for that matter, I am thinking to revert
back build_ExecEvalSysVar() and instead have that code inline as in
HEAD.

I'd just have ExecInterpExpr() continue calling ExecEvalSysVar. There's
no reason for it to be inline.

Can you explain more why you think there should be a ExecEvalSysVar()
definition ? As I mentioned earlier it would just call
slot_getsysattr() and do nothing else.

And it's simpler for JIT than the alternative.

You mean it would be simpler for JIT to call ExecEvalSysVar() than
slot_getsysattr() ? I didn't get why it is simpler.

Or are you talking considering build_ExecEvalSysVar() ? I am ok with
retaining build_ExecEvalSysVar() , but I was saying even inside this
function, we could do :
LLVMBuildCall(.... , llvm_get_decl(mod, FuncSlotGetsysattr) , .....)
rather than:
LLVMFunctionType(,...)
LLVMAddFunction("ExecEvalSysVar", ....)
LLVMBuildCall(...)

@@ -185,6 +1020,7 @@ ExecResetTupleTable(List *tupleTable, /* tuple table */
{
TupleTableSlot *slot = lfirst_node(TupleTableSlot, lc);

+             slot->tts_cb->release(slot);
/* Always release resources and reset the slot to empty */
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)
@@ -240,6 +1076,7 @@ void
ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
{
/* This should match ExecResetTupleTable's processing of one slot */
+     slot->tts_cb->release(slot);
Assert(IsA(slot, TupleTableSlot));
ExecClearTuple(slot);
if (slot->tts_tupleDescriptor)

ISTM that release should be called *after* clearing the slot.

I am copying here what I discussed about this in the earlier reply:

I am not sure what was release() designed to do. Currently all of the
implementers of this function are empty.

So additional deallocations can happen in a slot. We might need this
e.g. at some point for zheap which needs larger, longer-lived, buffers
in slots.

Was it meant for doing
ReleaseTupleDesc(slot->tts_tupleDescriptor) ? Or
ReleaseBuffer(bslot->buffer) ?

No. The former lives in generic code, the latter is in ClearTuple.

I think the purpose of keeping this *before* clearing the tuple might
be because the clear() might have already cleared some handles that
release() might need.

It's just plainly wrong to call it this way round.

Ok.

I went ahead and did these changes, but for now, I haven't replaced
ExecFetchSlotTuple() with ExecFetchSlotHeapTuple(). Instead, I
retained ExecFetchSlotTuple() to be called for heap tuples, and added
a new ExecFetchGenericSlotTuple() to be used with shouldFree. I don't
like these names, but until we have concluded, I don't want to go
ahead and replace all the numerous ExecFetchSlotTuple() calls with
ExecFetchSlotHeapTuple().

Why not?

I haven't gone ahead because I wanted to know if you are ok with the names.

--
Thanks,
-Amit Khandekar
EnterpriseDB Corporation
The Postgres Database Company

#39Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Amit Khandekar (#34)
Re: TupleTableSlot abstraction

On Tue, 9 Oct 2018 at 20:46, Amit Khandekar <amitdkhan.pg@gmail.com> wrote:

There is still one more regression test failure in polygon.sql which I
am yet to analyze.

Below is a narrowed down testcase which reproduces the failure in polygon.sql :

create table tab (n int, dist int, id integer);
insert into tab values (1, 2, 3);

-- Force a hash join
set enable_nestloop TO f;
set enable_mergejoin TO f;

-- Expected to return a row
SELECT * FROM tab t1 , tab t2 where t1.id = t2.id;
n | dist | id | n | dist | id
---+------+----+---+------+----
(0 rows)

In MultiExecPrivateHash(), to generate the hash table, the tuples are
retrieved one by one from the scan of outer plan state. For each
tuple, ExecHashGetHashValue() is called to get the join attribute
value of the tuple. Here, when the attribute is retrieved by a
jit-compiled slot-deforming function built by slot_compile_deform(),
the attribute value is a junk value. So the hash join condition fails
and the join returns no rows.

Root cause :

In llvm_compile_expr(), for the switch case : EEOP_INNER_FETCHSOME,
innerPlanState(parent)->ps_ResultTupleSlot->tts_cb is passed to
slot_compile_deform(). And in slot_compile_deform(), this tts_cb is
used to determine whether the inner slot is a minimal slot or a
buffer/heap tuple slot, and accordingly v_tupleheaderp is calculated
using StructMinimalTupleTableSlot or StructHeapTupleTableSlot.

In the above hash join scenario, the ps_ResultTupleSlot is a minimal tuple slot.
But at runtime, when MultiExecPrivateHash()=>ExecHashGetHashValue() is
called, the slot returned by outer node (Seqscan) is a buffer heap
tuple slot; this is because the seq scan does not return using its
ps_ResultTupleSlot, instead it directly returns its scan slot since
there is no projection info needed. Hence the tuple is retrieved using
a wrong offset inside the Tuple table slot, because the jit function
was compiled assuming it's going to be a minimal tuple slot.

So, although we can safely use
innerPlanState(parent)->ps_ResultTupleSlot to get the tuple descriptor
for slot_compile_deform(), we should not use the same tuple slot to
know what kind of a tuple slot it will be. That can be known only at
runtime.

Possible Fix :

I am thinking, in slot_compile_deform(), we need to include the logic
instructions to determine the slot type. Have a new
FIELDNO_TUPLETABLESLOT_OPS to retrieve TupleTableSlot.tts_cb, and then
accordingly calculate the tuple offset. I am not sure if this will
turn out to have a performance impact on jit execution, or whether it
is feasible to do such conditional thing in llvm; trying to
understand.

Comments ?

--
Thanks,
-Amit Khandekar
EnterpriseDB Corporation
The Postgres Database Company

#40Andres Freund
andres@anarazel.de
In reply to: Amit Khandekar (#38)
Re: TupleTableSlot abstraction

Hi,

On 2018-10-15 12:12:03 +0530, Amit Khandekar wrote:

On Sat, 13 Oct 2018 at 04:02, Andres Freund <andres@anarazel.de> wrote:

I'd just have ExecInterpExpr() continue calling ExecEvalSysVar. There's
no reason for it to be inline.

Can you explain more why you think there should be a ExecEvalSysVar()
definition ? As I mentioned earlier it would just call
slot_getsysattr() and do nothing else.

I think it's superflous to have three opcodes for this, and we should
instead just have one sysvar instruction that chooses the slot based on
a parameter of the opcode. Inline code in the interpreter isn't free.

And it's simpler for JIT than the alternative.

You mean it would be simpler for JIT to call ExecEvalSysVar() than
slot_getsysattr() ? I didn't get why it is simpler.

Because there'd be no special code at all. We can just use the code that
existing ExecEval* routines use.

Or are you talking considering build_ExecEvalSysVar() ? I am ok with
retaining build_ExecEvalSysVar() , but I was saying even inside this
function, we could do :
LLVMBuildCall(.... , llvm_get_decl(mod, FuncSlotGetsysattr) , .....)
rather than:
LLVMFunctionType(,...)
LLVMAddFunction("ExecEvalSysVar", ....)
LLVMBuildCall(...)

That'd probably generate more work than it'd save, because llvm_get_decl
requires that the function is present in llvmjit_types.c.

I went ahead and did these changes, but for now, I haven't replaced
ExecFetchSlotTuple() with ExecFetchSlotHeapTuple(). Instead, I
retained ExecFetchSlotTuple() to be called for heap tuples, and added
a new ExecFetchGenericSlotTuple() to be used with shouldFree. I don't
like these names, but until we have concluded, I don't want to go
ahead and replace all the numerous ExecFetchSlotTuple() calls with
ExecFetchSlotHeapTuple().

Why not?

I haven't gone ahead because I wanted to know if you are ok with the names.

Just renaming a function is cheap, it's just a oneliner script ;)

FWIW, I dislike ExecFetchGenericSlotTuple() as well. It's still a
HeapTuple, there's absolutely nothing Generic about it. I don't see why
we'd not just use ExecFetchSlotHeapTuple() with a new shouldFree
parameter?

Greetings,

Andres Freund

#41Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#1)
7 attachment(s)
Re: TupleTableSlot abstraction

Hi,

Attached is a heavily revised version of the patchset developed in this
thread. It's based on the last version posted by Amit Khandekar at [1]http://archives.postgresql.org/message-id/CAJ3gD9eq38XhLsLTie%2B3NHsCRkLO0xHLA4MQX_3sr6or7xws4Q%40mail.gmail.com.

The largest issue this resolves is that, for JITing, we need to know
what kind of slot we're going to deal with. E.g. in contrast to right
now, we do not want to generate bespoke deform function for virtual
slots, and we need to be able to discern between slots we know to deform
and slots where we don't. Up to now generated a deform function
whenever we can figure out what the tupledesc for an EEOP_*_FETCHSOME
operation is, using the fairly ugly hack for looking at
PlanState->scanslot the scan desc, and the right/left tree's for
INNER/OUTER. That kind of works as far as descriptors go, but doesn't
for the slot types - it's far from uncommon that the slot type inside a
node differs from the result type from the left/right tree.

I've tried various approaches for this, and what I settled on is that
every PlanState signals in new fields what its scan result type and slot
type is, if known; normally that's automatic due to using
ExecInitScanTupleSlot(), ExecInitResultSlot(). By default, the right /
left (aka inner/outer) are inferred using ExecGetResultSlotOps on the
subsidiary node, but can be overriden too. This gets rid of similar
logic previously present in llvmjit_expr.c, by moving the relevant
knowledge into ExprEvalOp.d.fetch.

While this primarily benefits JITing, it also allows for future
optimizations like eliding slot_getsomattr() / EEOP_*_FETCHSOME calls
for Vars on slots known to be virtual (which is a large percentage, due
to ExecProject() etc).

To avoid bugs around this, I've added assertions that check that hte
slot type is as expected. This, unsurprisingly, caught a number of bugs.

While this approach isn't perfect (in particular, it adds a few new
fields to PlanState), I've tried hard ot find other solutions, and
didn't come up with anything that's meaningfully better. If anybody has
better ideas, please call now.

The second bigger change is that I've removed ExecFetchGenericSlotTuple
- I really disliked having both that and ExecFetchSlotTuple. Now
ExecFetchSlotTuple has a new *shouldFree parameter that indicates
whether the returned value is allocated in the current context, or
not. I've also renamed it to ExecFetchSlotHeapTuple. It's currently
still used for places where we modify the returned tuple in-place (to
set oid etc), but subsequent patches in the pluggable storage patchset,
get rid of that too.

I've done a bit of benchmarking (TPCH and pgench), and after some
performance fixes the patchset either has no performance effect, or a
very small performance benefit (when using JITing, it reduces the
overhead).

Further changes:
- changed the split of patches, so they now all pass the
tests, and individually make (some) sense.
- virtual tuple table slots can now be materialized (by serializing
!byval columns into a single allocation, that's then pointed to by
tts_values).
- The responsibility for filling missing columns is now again in
slot_getsomeattrs, rather than the per-slot callbacks (which can still
do so if desired, but normally I don't see much point).
- lots of bugfixes
- comment cleanups
- performance improvements
- Reduction in the number of callbacks. getattr, attisnull are gone.

What I'm now planning to do is to go through the big comment in
tuptable.h and update that to the new world. While I'm not convinced
that that that's the best place for it, it needs to be accurate.

Furthermore:
- More comment polishing
- I'll probably split the commits up a bit further (particulary JIT
ignoring virtual tuple slots, inlining the hot path of
slot_getsomeattrs())
- serious commit message polishing

After this, I hope Amit Khandekar will rebase a patch he's sent me
internally that converts triggers to use slots. I'll work on rebasing
the pluggable storage patch ontop of this.

[1]: http://archives.postgresql.org/message-id/CAJ3gD9eq38XhLsLTie%2B3NHsCRkLO0xHLA4MQX_3sr6or7xws4Q%40mail.gmail.com

Greetings,

Andres Freund

Attachments:

v14-0001-Rejigger-materializing-and-fetching-a-HeapTuple-.patchtext/x-diff; charset=us-asciiDownload
From dd2e6f1351379deba29c7c3831e72fa4ac0f12d8 Mon Sep 17 00:00:00 2001
From: Amit Khandekar <amit.khandekar@enterprisedb.com>
Date: Thu, 4 Oct 2018 15:00:01 +0530
Subject: [PATCH v14 1/7] Rejigger materializing and fetching a HeapTuple from
 a slot.

Author: Ashutosh Bapat and Andres Freund
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 contrib/postgres_fdw/postgres_fdw.c    |  5 +-
 src/backend/commands/copy.c            |  4 +-
 src/backend/commands/createas.c        |  2 +-
 src/backend/commands/matview.c         |  5 +-
 src/backend/commands/trigger.c         | 46 ++++++++++-----
 src/backend/executor/execMain.c        |  2 +-
 src/backend/executor/execReplication.c |  4 +-
 src/backend/executor/execSRF.c         |  2 +-
 src/backend/executor/execTuples.c      | 79 +++++++++++++++-----------
 src/backend/executor/functions.c       |  2 +-
 src/backend/executor/nodeForeignscan.c |  2 +-
 src/backend/executor/nodeHash.c        | 24 ++++++--
 src/backend/executor/nodeHashjoin.c    | 17 +++++-
 src/backend/executor/nodeModifyTable.c | 26 ++++-----
 src/backend/executor/tqueue.c          | 10 +++-
 src/include/executor/tuptable.h        |  9 +--
 16 files changed, 154 insertions(+), 85 deletions(-)

diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index fd20aa96aa9..6f9c6e193fc 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -3947,11 +3947,12 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
 	ExecStoreVirtualTuple(resultSlot);
 
 	/*
-	 * If we have any system columns to return, install them.
+	 * If we have any system columns to return, materialize a heap tuple in the
+	 * slot from column values set above and install system columns in that tuple.
 	 */
 	if (dmstate->hasSystemCols)
 	{
-		HeapTuple	resultTup = ExecMaterializeSlot(resultSlot);
+		HeapTuple	resultTup = ExecFetchSlotHeapTuple(resultSlot, true, NULL);
 
 		/* ctid */
 		if (dmstate->ctidAttno)
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index b58a74f4e3d..a9471c5ef6a 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2899,7 +2899,7 @@ CopyFrom(CopyState cstate)
 			if (slot == NULL)	/* "do nothing" */
 				skip_tuple = true;
 			else				/* trigger might have changed tuple */
-				tuple = ExecMaterializeSlot(slot);
+				tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 		}
 
 		if (!skip_tuple)
@@ -2975,7 +2975,7 @@ CopyFrom(CopyState cstate)
 							continue;	/* next tuple please */
 
 						/* FDW might have changed tuple */
-						tuple = ExecMaterializeSlot(slot);
+						tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 						/*
 						 * AFTER ROW Triggers might reference the tableoid
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index d5cb62da15b..d8002e5b776 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -589,7 +589,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 	 * get the heap tuple out of the tuple table slot, making sure we have a
 	 * writable copy
 	 */
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecCopySlotTuple(slot);
 
 	/*
 	 * force assignment of new OID (see comments in ExecInsert)
diff --git a/src/backend/commands/matview.c b/src/backend/commands/matview.c
index e1eb7c374b8..9957c7074de 100644
--- a/src/backend/commands/matview.c
+++ b/src/backend/commands/matview.c
@@ -484,7 +484,7 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
 	 * get the heap tuple out of the tuple table slot, making sure we have a
 	 * writable copy
 	 */
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecCopySlotTuple(slot);
 
 	heap_insert(myState->transientrel,
 				tuple,
@@ -494,6 +494,9 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
 
 	/* We know this is a newly created relation, so there are no indexes */
 
+	/* Free the copied tuple. */
+	heap_freetuple(tuple);
+
 	return true;
 }
 
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index ccb5706c162..d6f33ecbd04 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2517,7 +2517,8 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 					 TupleTableSlot *slot)
 {
 	TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
-	HeapTuple	slottuple = ExecMaterializeSlot(slot);
+	bool		should_free;
+	HeapTuple	slottuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
 	HeapTuple	newtuple = slottuple;
 	HeapTuple	oldtuple;
 	TriggerData LocTriggerData;
@@ -2556,7 +2557,11 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		if (oldtuple != newtuple && oldtuple != slottuple)
 			heap_freetuple(oldtuple);
 		if (newtuple == NULL)
+		{
+			if (should_free)
+				heap_freetuple(slottuple);
 			return NULL;		/* "do nothing" */
+		}
 	}
 
 	if (newtuple != slottuple)
@@ -2575,6 +2580,9 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		ExecStoreHeapTuple(newtuple, newslot, false);
 		slot = newslot;
 	}
+
+	if (should_free)
+		heap_freetuple(slottuple);
 	return slot;
 }
 
@@ -2598,7 +2606,8 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 					 TupleTableSlot *slot)
 {
 	TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
-	HeapTuple	slottuple = ExecMaterializeSlot(slot);
+	bool		should_free;
+	HeapTuple	slottuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
 	HeapTuple	newtuple = slottuple;
 	HeapTuple	oldtuple;
 	TriggerData LocTriggerData;
@@ -2637,7 +2646,11 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		if (oldtuple != newtuple && oldtuple != slottuple)
 			heap_freetuple(oldtuple);
 		if (newtuple == NULL)
+		{
+			if (should_free)
+				heap_freetuple(slottuple);
 			return NULL;		/* "do nothing" */
+		}
 	}
 
 	if (newtuple != slottuple)
@@ -2656,6 +2669,9 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
 		ExecStoreHeapTuple(newtuple, newslot, false);
 		slot = newslot;
 	}
+
+	if (should_free)
+		heap_freetuple(slottuple);
 	return slot;
 }
 
@@ -2976,7 +2992,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 					 TupleTableSlot *slot)
 {
 	TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
-	HeapTuple	slottuple = ExecMaterializeSlot(slot);
+	HeapTuple	slottuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 	HeapTuple	newtuple = slottuple;
 	TriggerData LocTriggerData;
 	HeapTuple	trigtuple;
@@ -3018,7 +3034,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
 	if (newSlot != NULL)
 	{
 		slot = ExecFilterJunk(relinfo->ri_junkFilter, newSlot);
-		slottuple = ExecMaterializeSlot(slot);
+		slottuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 		newtuple = slottuple;
 	}
 
@@ -3132,7 +3148,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
 					 HeapTuple trigtuple, TupleTableSlot *slot)
 {
 	TriggerDesc *trigdesc = relinfo->ri_TrigDesc;
-	HeapTuple	slottuple = ExecMaterializeSlot(slot);
+	HeapTuple	slottuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 	HeapTuple	newtuple = slottuple;
 	TriggerData LocTriggerData;
 	HeapTuple	oldtuple;
@@ -4262,22 +4278,22 @@ AfterTriggerExecute(AfterTriggerEvent event,
 		case AFTER_TRIGGER_FDW_REUSE:
 
 			/*
-			 * Using ExecMaterializeSlot() rather than ExecFetchSlotTuple()
-			 * ensures that tg_trigtuple does not reference tuplestore memory.
-			 * (It is formally possible for the trigger function to queue
-			 * trigger events that add to the same tuplestore, which can push
-			 * other tuples out of memory.)  The distinction is academic,
-			 * because we start with a minimal tuple that ExecFetchSlotTuple()
-			 * must materialize anyway.
+			 * Materialize tuple in the slot so that tg_trigtuple does not
+			 * reference tuplestore memory.  (It is formally possible for the
+			 * trigger function to queue trigger events that add to the same
+			 * tuplestore, which can push other tuples out of memory.)  The
+			 * distinction is academic, because we start with a minimal tuple
+			 * that is stored as a heap tuple, constructed in different memory
+			 * context, in the slot anyway.
 			 */
-			LocTriggerData.tg_trigtuple =
-				ExecMaterializeSlot(trig_tuple_slot1);
+			LocTriggerData.tg_trigtuple = ExecFetchSlotHeapTuple(trig_tuple_slot1,
+																	true, NULL);
 			LocTriggerData.tg_trigtuplebuf = InvalidBuffer;
 
 			LocTriggerData.tg_newtuple =
 				((evtshared->ats_event & TRIGGER_EVENT_OPMASK) ==
 				 TRIGGER_EVENT_UPDATE) ?
-				ExecMaterializeSlot(trig_tuple_slot2) : NULL;
+				ExecFetchSlotHeapTuple(trig_tuple_slot2, true, NULL) : NULL;
 			LocTriggerData.tg_newtuplebuf = InvalidBuffer;
 
 			break;
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index ba156f8c5fc..d10e533fd16 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -2549,7 +2549,7 @@ EvalPlanQual(EState *estate, EPQState *epqstate,
 	 * is to guard against early re-use of the EPQ query.
 	 */
 	if (!TupIsNull(slot))
-		(void) ExecMaterializeSlot(slot);
+		ExecMaterializeSlot(slot);
 
 	/*
 	 * Clear out the test tuple.  This is needed in case the EPQ query is
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index 25ba93e03c3..071ba8762d4 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -418,7 +418,7 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
 			ExecPartitionCheck(resultRelInfo, slot, estate, true);
 
 		/* Materialize slot into a tuple that we can scribble upon. */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		/* OK, store the tuple and create index entries for it */
 		simple_heap_insert(rel, tuple);
@@ -485,7 +485,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 			ExecPartitionCheck(resultRelInfo, slot, estate, true);
 
 		/* Materialize slot into a tuple that we can scribble upon. */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		/* OK, update the tuple and index entries for it */
 		simple_heap_update(rel, &searchslot->tts_tuple->t_self,
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index b97b8d797ec..3bffb0ea71f 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -521,7 +521,7 @@ restart:
 			{
 				/* We must return the whole tuple as a Datum. */
 				*isNull = false;
-				return ExecFetchSlotTupleDatum(fcache->funcResultSlot);
+				return ExecFetchSlotHeapTupleDatum(fcache->funcResultSlot);
 			}
 			else
 			{
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index 9f0d9daa829..ca2ca7f2d63 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -676,23 +676,27 @@ ExecCopySlotMinimalTuple(TupleTableSlot *slot)
 								   slot->tts_isnull);
 }
 
-/* --------------------------------
- *		ExecFetchSlotTuple
- *			Fetch the slot's regular physical tuple.
+/*
+ * ExecFetchSlotHeapTuple - fetch HeapTuple representing the slot's content
  *
- *		If the slot contains a virtual tuple, we convert it to physical
- *		form.  The slot retains ownership of the physical tuple.
- *		If it contains a minimal tuple we convert to regular form and store
- *		that in addition to the minimal tuple (not instead of, because
- *		callers may hold pointers to Datums within the minimal tuple).
+ * The returned HeapTuple represents the slot's content as closely as
+ * possible.
  *
- * The main difference between this and ExecMaterializeSlot() is that this
- * does not guarantee that the contained tuple is local storage.
- * Hence, the result must be treated as read-only.
- * --------------------------------
+ * If materialize is true, the contents of the slots will be made independent
+ * from the underlying storage (i.e. all buffer pins are release, memory is
+ * allocated in the slot's context).
+ *
+ * If shouldFree is not-NULL it'll be set to true if the returned tuple has
+ * been allocated in the calling memory context, and must be freed by the
+ * caller (via explicit pfree() or a memory context reset).
+ *
+ * NB: If materialize is true, modifications of the returned tuple are
+ * allowed. But it depends on the type of the slot whether such modifications
+ * will also affect the slot's contents. While that is not the nicest
+ * behaviour, all such modifcations are in the process of being removed.
  */
 HeapTuple
-ExecFetchSlotTuple(TupleTableSlot *slot)
+ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
 {
 	/*
 	 * sanity checks
@@ -700,6 +704,9 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
 	Assert(slot != NULL);
 	Assert(!TTS_EMPTY(slot));
 
+	if (shouldFree)
+		*shouldFree = false;
+
 	/*
 	 * If we have a regular physical tuple then just return it.
 	 */
@@ -722,7 +729,9 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
 	/*
 	 * Otherwise materialize the slot...
 	 */
-	return ExecMaterializeSlot(slot);
+	ExecMaterializeSlot(slot);
+
+	return slot->tts_tuple;
 }
 
 /* --------------------------------
@@ -739,7 +748,7 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
  * --------------------------------
  */
 MinimalTuple
-ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
+ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
 {
 	MemoryContext oldContext;
 
@@ -749,6 +758,8 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
 	Assert(slot != NULL);
 	Assert(!TTS_EMPTY(slot));
 
+	if (shouldFree)
+		*shouldFree = false;
 
 	/*
 	 * If we have a minimal physical tuple (local or not) then just return it.
@@ -779,40 +790,44 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
 }
 
 /* --------------------------------
- *		ExecFetchSlotTupleDatum
+ *		ExecFetchSlotHeapTupleDatum
  *			Fetch the slot's tuple as a composite-type Datum.
  *
  *		The result is always freshly palloc'd in the caller's memory context.
  * --------------------------------
  */
 Datum
-ExecFetchSlotTupleDatum(TupleTableSlot *slot)
+ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
 {
 	HeapTuple	tup;
 	TupleDesc	tupdesc;
+	bool		shouldFree;
+	Datum		ret;
 
 	/* Fetch slot's contents in regular-physical-tuple form */
-	tup = ExecFetchSlotTuple(slot);
+	tup = ExecFetchSlotHeapTuple(slot, false, &shouldFree);
 	tupdesc = slot->tts_tupleDescriptor;
 
 	/* Convert to Datum form */
-	return heap_copy_tuple_as_datum(tup, tupdesc);
+	ret = heap_copy_tuple_as_datum(tup, tupdesc);
+
+	if (shouldFree)
+		pfree(tup);
+
+	return ret;
 }
 
-/* --------------------------------
- *		ExecMaterializeSlot
- *			Force a slot into the "materialized" state.
+/* ExecMaterializeSlot - force a slot into the "materialized" state.
  *
- *		This causes the slot's tuple to be a local copy not dependent on
- *		any external storage.  A pointer to the contained tuple is returned.
+ * This causes the slot's tuple to be a local copy not dependent on any
+ * external storage (i.e. pointing into a Buffer, or having allocations in
+ * another memory context).
  *
- *		A typical use for this operation is to prepare a computed tuple
- *		for being stored on disk.  The original data may or may not be
- *		virtual, but in any case we need a private copy for heap_insert
- *		to scribble on.
- * --------------------------------
+ * A typical use for this operation is to prepare a computed tuple for being
+ * stored on disk.  The original data may or may not be virtual, but in any
+ * case we need a private copy for heap_insert to scribble on.
  */
-HeapTuple
+void
 ExecMaterializeSlot(TupleTableSlot *slot)
 {
 	MemoryContext oldContext;
@@ -828,7 +843,7 @@ ExecMaterializeSlot(TupleTableSlot *slot)
 	 * nothing to do.
 	 */
 	if (slot->tts_tuple && TTS_SHOULDFREE(slot))
-		return slot->tts_tuple;
+		return;
 
 	/*
 	 * Otherwise, copy or build a physical tuple, and store it into the slot.
@@ -868,8 +883,6 @@ ExecMaterializeSlot(TupleTableSlot *slot)
 	 */
 	if (!TTS_SHOULDFREEMIN(slot))
 		slot->tts_mintuple = NULL;
-
-	return slot->tts_tuple;
 }
 
 /* --------------------------------
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 23545896d4d..f4dd5732198 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -969,7 +969,7 @@ postquel_get_single_result(TupleTableSlot *slot,
 	{
 		/* We must return the whole tuple as a Datum. */
 		fcinfo->isnull = false;
-		value = ExecFetchSlotTupleDatum(slot);
+		value = ExecFetchSlotHeapTupleDatum(slot);
 	}
 	else
 	{
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index 5d2cd0ed717..f7eef32f6fe 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -62,7 +62,7 @@ ForeignNext(ForeignScanState *node)
 	 */
 	if (plan->fsSystemCol && !TupIsNull(slot))
 	{
-		HeapTuple	tup = ExecMaterializeSlot(slot);
+		HeapTuple	tup = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		tup->t_tableOid = RelationGetRelid(node->ss.ss_currentRelation);
 	}
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index a9f812d66b8..5a9f1ea3c55 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -1590,7 +1590,8 @@ ExecHashTableInsert(HashJoinTable hashtable,
 					TupleTableSlot *slot,
 					uint32 hashvalue)
 {
-	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+	bool		shouldFree;
+	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
 	int			bucketno;
 	int			batchno;
 
@@ -1664,6 +1665,9 @@ ExecHashTableInsert(HashJoinTable hashtable,
 							  hashvalue,
 							  &hashtable->innerBatchFile[batchno]);
 	}
+
+	if (shouldFree)
+		heap_free_minimal_tuple(tuple);
 }
 
 /*
@@ -1675,7 +1679,8 @@ ExecParallelHashTableInsert(HashJoinTable hashtable,
 							TupleTableSlot *slot,
 							uint32 hashvalue)
 {
-	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+	bool		shouldFree;
+	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
 	dsa_pointer shared;
 	int			bucketno;
 	int			batchno;
@@ -1723,6 +1728,9 @@ retry:
 					 tuple);
 	}
 	++hashtable->batches[batchno].ntuples;
+
+	if (shouldFree)
+		heap_free_minimal_tuple(tuple);
 }
 
 /*
@@ -1736,7 +1744,8 @@ ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable,
 										TupleTableSlot *slot,
 										uint32 hashvalue)
 {
-	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+	bool		shouldFree;
+	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
 	HashJoinTuple hashTuple;
 	dsa_pointer shared;
 	int			batchno;
@@ -1752,6 +1761,9 @@ ExecParallelHashTableInsertCurrentBatch(HashJoinTable hashtable,
 	HeapTupleHeaderClearMatch(HJTUPLE_MINTUPLE(hashTuple));
 	ExecParallelHashPushTuple(&hashtable->buckets.shared[bucketno],
 							  hashTuple, shared);
+
+	if (shouldFree)
+		heap_free_minimal_tuple(tuple);
 }
 
 /*
@@ -2391,7 +2403,8 @@ ExecHashSkewTableInsert(HashJoinTable hashtable,
 						uint32 hashvalue,
 						int bucketNumber)
 {
-	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot);
+	bool		shouldFree;
+	MinimalTuple tuple = ExecFetchSlotMinimalTuple(slot, &shouldFree);
 	HashJoinTuple hashTuple;
 	int			hashTupleSize;
 
@@ -2419,6 +2432,9 @@ ExecHashSkewTableInsert(HashJoinTable hashtable,
 	/* Check we are not over the total spaceAllowed, either */
 	if (hashtable->spaceUsed > hashtable->spaceAllowed)
 		ExecHashIncreaseNumBatches(hashtable);
+
+	if (shouldFree)
+		heap_free_minimal_tuple(tuple);
 }
 
 /*
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index 08a8bb3426c..d6a6ef770dd 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -389,16 +389,22 @@ ExecHashJoinImpl(PlanState *pstate, bool parallel)
 				if (batchno != hashtable->curbatch &&
 					node->hj_CurSkewBucketNo == INVALID_SKEW_BUCKET_NO)
 				{
+					bool		shouldFree;
+					MinimalTuple mintuple = ExecFetchSlotMinimalTuple(outerTupleSlot,
+																	  &shouldFree);
+
 					/*
 					 * Need to postpone this outer tuple to a later batch.
 					 * Save it in the corresponding outer-batch file.
 					 */
 					Assert(parallel_state == NULL);
 					Assert(batchno > hashtable->curbatch);
-					ExecHashJoinSaveTuple(ExecFetchSlotMinimalTuple(outerTupleSlot),
-										  hashvalue,
+					ExecHashJoinSaveTuple(mintuple, hashvalue,
 										  &hashtable->outerBatchFile[batchno]);
 
+					if (shouldFree)
+						heap_free_minimal_tuple(mintuple);
+
 					/* Loop around, staying in HJ_NEED_NEW_OUTER state */
 					continue;
 				}
@@ -1404,11 +1410,16 @@ ExecParallelHashJoinPartitionOuter(HashJoinState *hjstate)
 		{
 			int			batchno;
 			int			bucketno;
+			bool		shouldFree;
+			MinimalTuple mintup = ExecFetchSlotMinimalTuple(slot, &shouldFree);
 
 			ExecHashGetBucketAndBatch(hashtable, hashvalue, &bucketno,
 									  &batchno);
 			sts_puttuple(hashtable->batches[batchno].outer_tuples,
-						 &hashvalue, ExecFetchSlotMinimalTuple(slot));
+						 &hashvalue, mintup);
+
+			if (shouldFree)
+				heap_free_minimal_tuple(mintup);
 		}
 		CHECK_FOR_INTERRUPTS();
 	}
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index e2836b75ff3..ca7ece3235f 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -181,7 +181,7 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo,
 		 * initialize t_tableOid before evaluating them.
 		 */
 		Assert(!TupIsNull(econtext->ecxt_scantuple));
-		tuple = ExecMaterializeSlot(econtext->ecxt_scantuple);
+		tuple = ExecFetchSlotHeapTuple(econtext->ecxt_scantuple, true, NULL);
 		tuple->t_tableOid = RelationGetRelid(resultRelInfo->ri_RelationDesc);
 	}
 	econtext->ecxt_outertuple = planSlot;
@@ -280,7 +280,7 @@ ExecInsert(ModifyTableState *mtstate,
 	 * get the heap tuple out of the tuple table slot, making sure we have a
 	 * writable copy
 	 */
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 	/*
 	 * get information on the (current) result relation
@@ -321,7 +321,7 @@ ExecInsert(ModifyTableState *mtstate,
 			return NULL;
 
 		/* trigger might have changed tuple */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 	}
 
 	/* INSTEAD OF ROW INSERT Triggers */
@@ -334,7 +334,7 @@ ExecInsert(ModifyTableState *mtstate,
 			return NULL;
 
 		/* trigger might have changed tuple */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		newId = InvalidOid;
 	}
@@ -352,7 +352,7 @@ ExecInsert(ModifyTableState *mtstate,
 			return NULL;
 
 		/* FDW might have changed tuple */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		/*
 		 * AFTER ROW Triggers or RETURNING expressions might reference the
@@ -701,7 +701,7 @@ ExecDelete(ModifyTableState *mtstate,
 		 */
 		if (TTS_EMPTY(slot))
 			ExecStoreAllNullTuple(slot);
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 		tuple->t_tableOid = RelationGetRelid(resultRelationDesc);
 	}
 	else
@@ -959,7 +959,7 @@ ExecUpdate(ModifyTableState *mtstate,
 	 * get the heap tuple out of the tuple table slot, making sure we have a
 	 * writable copy
 	 */
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 	/*
 	 * get information on the (current) result relation
@@ -978,7 +978,7 @@ ExecUpdate(ModifyTableState *mtstate,
 			return NULL;
 
 		/* trigger might have changed tuple */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 	}
 
 	/* INSTEAD OF ROW UPDATE Triggers */
@@ -992,7 +992,7 @@ ExecUpdate(ModifyTableState *mtstate,
 			return NULL;
 
 		/* trigger might have changed tuple */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 	}
 	else if (resultRelInfo->ri_FdwRoutine)
 	{
@@ -1008,7 +1008,7 @@ ExecUpdate(ModifyTableState *mtstate,
 			return NULL;
 
 		/* FDW might have changed tuple */
-		tuple = ExecMaterializeSlot(slot);
+		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		/*
 		 * AFTER ROW Triggers or RETURNING expressions might reference the
@@ -1135,7 +1135,7 @@ lreplace:;
 				else
 				{
 					slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot);
-					tuple = ExecMaterializeSlot(slot);
+					tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 					goto lreplace;
 				}
 			}
@@ -1274,7 +1274,7 @@ lreplace:;
 					{
 						*tupleid = hufd.ctid;
 						slot = ExecFilterJunk(resultRelInfo->ri_junkFilter, epqslot);
-						tuple = ExecMaterializeSlot(slot);
+						tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 						goto lreplace;
 					}
 				}
@@ -1751,7 +1751,7 @@ ExecPrepareTupleRouting(ModifyTableState *mtstate,
 	estate->es_result_relation_info = partrel;
 
 	/* Get the heap tuple out of the given slot. */
-	tuple = ExecMaterializeSlot(slot);
+	tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 	/*
 	 * If we're capturing transition tuples, we might need to convert from the
diff --git a/src/backend/executor/tqueue.c b/src/backend/executor/tqueue.c
index ecdbe7f79f6..efce1bedf58 100644
--- a/src/backend/executor/tqueue.c
+++ b/src/backend/executor/tqueue.c
@@ -56,11 +56,19 @@ tqueueReceiveSlot(TupleTableSlot *slot, DestReceiver *self)
 	TQueueDestReceiver *tqueue = (TQueueDestReceiver *) self;
 	HeapTuple	tuple;
 	shm_mq_result result;
+	bool		should_free;
+
+	/* Get the tuple out of slot, if necessary converting the slot's contents
+	 * into a heap tuple by copying. In the later case we need to free the copy.
+	 */
+	tuple = ExecFetchSlotHeapTuple(slot, true, &should_free);
 
 	/* Send the tuple itself. */
-	tuple = ExecMaterializeSlot(slot);
 	result = shm_mq_send(tqueue->queue, tuple->t_len, tuple->t_data, false);
 
+	if (should_free)
+		heap_freetuple(tuple);
+
 	/* Check for failure. */
 	if (result == SHM_MQ_DETACHED)
 		return false;
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index b41b400ef18..8bfa73c30ea 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -185,10 +185,11 @@ extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
 extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
 extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot);
 extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot);
-extern HeapTuple ExecFetchSlotTuple(TupleTableSlot *slot);
-extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot);
-extern Datum ExecFetchSlotTupleDatum(TupleTableSlot *slot);
-extern HeapTuple ExecMaterializeSlot(TupleTableSlot *slot);
+extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shoulFree);
+extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
+						  bool *shouldFree);
+extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
+extern void ExecMaterializeSlot(TupleTableSlot *slot);
 extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
 			 TupleTableSlot *srcslot);
 extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
-- 
2.18.0.rc2.dirty

v14-0002-Change-tuple-table-slot-creation-routines-to-sui.patchtext/x-diff; charset=us-asciiDownload
From ff9b927e8c8e08d7fd2ad767505bd1f3537097f8 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 13 Nov 2018 12:57:56 -0800
Subject: [PATCH v14 2/7] Change tuple table slot creation routines to suite
 tuple table slot abstraction.

This change requires ExecInitResultTupleSlotTL, ExecInitScanTupleSlot,
ExecCreateScanSlotFromOuterPlan, ExecInitNullTupleSlot,
ExecInitExtraTupleSlot, MakeTupleTableSlot, ExecAllocTableSlot to
accept TupleTableSlotOps as a new parameter. Change all their calls.

For this commit, all the global variables corresponding to different
types of TupleTableSlots are empty. In the subsequent commit,
they will be assigned real structure fields.

Author: Ashutosh Bapat and Andres Freund, with changes by Amit Khandekar
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 src/backend/access/heap/heapam.c              |  3 +-
 src/backend/catalog/index.c                   |  9 ++-
 src/backend/catalog/indexing.c                |  3 +-
 src/backend/commands/analyze.c                |  3 +-
 src/backend/commands/constraint.c             |  3 +-
 src/backend/commands/copy.c                   |  6 +-
 src/backend/commands/explain.c                |  3 +-
 src/backend/commands/functioncmds.c           |  3 +-
 src/backend/commands/subscriptioncmds.c       |  2 +-
 src/backend/commands/tablecmds.c              |  6 +-
 src/backend/commands/trigger.c                | 10 +--
 src/backend/executor/execExpr.c               |  3 +-
 src/backend/executor/execGrouping.c           |  3 +-
 src/backend/executor/execIndexing.c           |  3 +-
 src/backend/executor/execJunk.c               |  4 +-
 src/backend/executor/execMain.c               | 10 +--
 src/backend/executor/execPartition.c          |  7 +-
 src/backend/executor/execSRF.c                |  3 +-
 src/backend/executor/execTuples.c             | 64 +++++++++++++------
 src/backend/executor/execUtils.c              | 44 ++++++++++++-
 src/backend/executor/functions.c              | 24 +++++--
 src/backend/executor/nodeAgg.c                | 17 +++--
 src/backend/executor/nodeAppend.c             |  6 +-
 src/backend/executor/nodeBitmapHeapscan.c     |  3 +-
 src/backend/executor/nodeCtescan.c            |  3 +-
 src/backend/executor/nodeCustom.c             | 12 ++--
 src/backend/executor/nodeForeignscan.c        | 10 ++-
 src/backend/executor/nodeFunctionscan.c       |  6 +-
 src/backend/executor/nodeGather.c             |  8 ++-
 src/backend/executor/nodeGatherMerge.c        | 10 ++-
 src/backend/executor/nodeGroup.c              |  5 +-
 src/backend/executor/nodeHash.c               |  2 +-
 src/backend/executor/nodeHashjoin.c           | 13 ++--
 src/backend/executor/nodeIndexonlyscan.c      |  2 +-
 src/backend/executor/nodeIndexscan.c          |  3 +-
 src/backend/executor/nodeLimit.c              |  4 ++
 src/backend/executor/nodeLockRows.c           |  5 ++
 src/backend/executor/nodeMaterial.c           | 10 ++-
 src/backend/executor/nodeMergeAppend.c        |  6 +-
 src/backend/executor/nodeMergejoin.c          | 15 +++--
 src/backend/executor/nodeModifyTable.c        | 14 ++--
 .../executor/nodeNamedtuplestorescan.c        |  3 +-
 src/backend/executor/nodeNestloop.c           |  5 +-
 src/backend/executor/nodeProjectSet.c         |  2 +-
 src/backend/executor/nodeResult.c             |  2 +-
 src/backend/executor/nodeSamplescan.c         |  3 +-
 src/backend/executor/nodeSeqscan.c            |  3 +-
 src/backend/executor/nodeSetOp.c              |  4 +-
 src/backend/executor/nodeSort.c               |  4 +-
 src/backend/executor/nodeSubplan.c            |  4 +-
 src/backend/executor/nodeSubqueryscan.c       | 13 +++-
 src/backend/executor/nodeTableFuncscan.c      |  3 +-
 src/backend/executor/nodeTidscan.c            |  3 +-
 src/backend/executor/nodeUnique.c             |  2 +-
 src/backend/executor/nodeValuesscan.c         |  2 +-
 src/backend/executor/nodeWindowAgg.c          | 27 +++++---
 src/backend/executor/nodeWorktablescan.c      |  7 +-
 src/backend/partitioning/partbounds.c         |  2 +-
 src/backend/replication/logical/tablesync.c   |  4 +-
 src/backend/replication/logical/worker.c      | 21 ++++--
 src/backend/replication/walsender.c           |  6 +-
 src/backend/tcop/pquery.c                     |  2 +-
 src/backend/utils/adt/orderedsetaggs.c        |  6 +-
 src/backend/utils/adt/selfuncs.c              |  3 +-
 src/backend/utils/misc/guc.c                  |  4 +-
 src/backend/utils/sort/tuplesort.c            |  2 +-
 src/include/executor/executor.h               | 25 +++++---
 src/include/executor/tuptable.h               | 35 ++++++++--
 src/include/nodes/execnodes.h                 | 36 +++++++++++
 69 files changed, 432 insertions(+), 171 deletions(-)

diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index fb63471a0e0..da2a8f34c20 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -4503,7 +4503,8 @@ ProjIndexIsUnchanged(Relation relation, HeapTuple oldtup, HeapTuple newtup)
 	List	   *indexoidlist = RelationGetIndexList(relation);
 	EState	   *estate = CreateExecutorState();
 	ExprContext *econtext = GetPerTupleExprContext(estate);
-	TupleTableSlot *slot = MakeSingleTupleTableSlot(RelationGetDescr(relation));
+	TupleTableSlot *slot = MakeSingleTupleTableSlot(RelationGetDescr(relation),
+													&TTSOpsHeapTuple);
 	bool		equals = true;
 	Datum		old_values[INDEX_MAX_KEYS];
 	bool		old_isnull[INDEX_MAX_KEYS];
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 4088286151a..21bdf794da6 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2510,7 +2510,8 @@ IndexBuildHeapRangeScan(Relation heapRelation,
 	 */
 	estate = CreateExecutorState();
 	econtext = GetPerTupleExprContext(estate);
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									&TTSOpsHeapTuple);
 
 	/* Arrange for econtext's scan tuple to be the tuple under test */
 	econtext->ecxt_scantuple = slot;
@@ -2997,7 +2998,8 @@ IndexCheckExclusion(Relation heapRelation,
 	 */
 	estate = CreateExecutorState();
 	econtext = GetPerTupleExprContext(estate);
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									&TTSOpsHeapTuple);
 
 	/* Arrange for econtext's scan tuple to be the tuple under test */
 	econtext->ecxt_scantuple = slot;
@@ -3315,7 +3317,8 @@ validate_index_heapscan(Relation heapRelation,
 	 */
 	estate = CreateExecutorState();
 	econtext = GetPerTupleExprContext(estate);
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									&TTSOpsHeapTuple);
 
 	/* Arrange for econtext's scan tuple to be the tuple under test */
 	econtext->ecxt_scantuple = slot;
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index daf7ae2eb2b..c5f6efba2b6 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -95,7 +95,8 @@ CatalogIndexInsert(CatalogIndexState indstate, HeapTuple heapTuple)
 	heapRelation = indstate->ri_RelationDesc;
 
 	/* Need a slot to hold the tuple being examined */
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRelation),
+									&TTSOpsHeapTuple);
 	ExecStoreHeapTuple(heapTuple, slot, false);
 
 	/*
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 8ac868ad733..b8445dc3728 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -730,7 +730,8 @@ compute_index_stats(Relation onerel, double totalrows,
 		estate = CreateExecutorState();
 		econtext = GetPerTupleExprContext(estate);
 		/* Need a slot to hold the current heap tuple, too */
-		slot = MakeSingleTupleTableSlot(RelationGetDescr(onerel));
+		slot = MakeSingleTupleTableSlot(RelationGetDescr(onerel),
+										&TTSOpsHeapTuple);
 
 		/* Arrange for econtext's scan tuple to be the tuple under test */
 		econtext->ecxt_scantuple = slot;
diff --git a/src/backend/commands/constraint.c b/src/backend/commands/constraint.c
index f472355b48f..b0b2cb2a146 100644
--- a/src/backend/commands/constraint.c
+++ b/src/backend/commands/constraint.c
@@ -122,7 +122,8 @@ unique_key_recheck(PG_FUNCTION_ARGS)
 	/*
 	 * The heap tuple must be put into a slot for FormIndexDatum.
 	 */
-	slot = MakeSingleTupleTableSlot(RelationGetDescr(trigdata->tg_relation));
+	slot = MakeSingleTupleTableSlot(RelationGetDescr(trigdata->tg_relation),
+									&TTSOpsHeapTuple);
 
 	ExecStoreHeapTuple(new_row, slot, false);
 
diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index a9471c5ef6a..e62e3d8fba2 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -2488,9 +2488,11 @@ CopyFrom(CopyState cstate)
 	ExecInitRangeTable(estate, cstate->range_table);
 
 	/* Set up a tuple slot too */
-	myslot = ExecInitExtraTupleSlot(estate, tupDesc);
+	myslot = ExecInitExtraTupleSlot(estate, tupDesc,
+									&TTSOpsHeapTuple);
 	/* Triggers might need a slot as well */
-	estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
+	estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
+														&TTSOpsHeapTuple);
 
 	/*
 	 * Set up a ModifyTableState so we can let FDW(s) init themselves for
diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c
index 799a22e9d55..ab2c84ff98a 100644
--- a/src/backend/commands/explain.c
+++ b/src/backend/commands/explain.c
@@ -266,7 +266,8 @@ ExplainQuery(ParseState *pstate, ExplainStmt *stmt, const char *queryString,
 	Assert(es->indent == 0);
 
 	/* output tuples */
-	tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt));
+	tstate = begin_tup_output_tupdesc(dest, ExplainResultDesc(stmt),
+									  &TTSOpsVirtual);
 	if (es->format == EXPLAIN_FORMAT_TEXT)
 		do_text_output_multiline(tstate, es->str->data);
 	else
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 3925fb83a54..f6e12a33532 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -2347,7 +2347,8 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
 		tupTypmod = HeapTupleHeaderGetTypMod(td);
 		retdesc = lookup_rowtype_tupdesc(tupType, tupTypmod);
 
-		tstate = begin_tup_output_tupdesc(dest, retdesc);
+		tstate = begin_tup_output_tupdesc(dest, retdesc,
+										  &TTSOpsHeapTuple);
 
 		rettupdata.t_len = HeapTupleHeaderGetDatumLength(td);
 		ItemPointerSetInvalid(&(rettupdata.t_self));
diff --git a/src/backend/commands/subscriptioncmds.c b/src/backend/commands/subscriptioncmds.c
index f138e61a8d3..0efbfec4751 100644
--- a/src/backend/commands/subscriptioncmds.c
+++ b/src/backend/commands/subscriptioncmds.c
@@ -1148,7 +1148,7 @@ fetch_table_list(WalReceiverConn *wrconn, List *publications)
 						res->err)));
 
 	/* Process tables. */
-	slot = MakeSingleTupleTableSlot(res->tupledesc);
+	slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
 	while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
 	{
 		char	   *nspname;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 946119fa860..18a2b54b8e9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -4729,8 +4729,8 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
 		 * tuples are the same, the tupDescs might not be (consider ADD COLUMN
 		 * without a default).
 		 */
-		oldslot = MakeSingleTupleTableSlot(oldTupDesc);
-		newslot = MakeSingleTupleTableSlot(newTupDesc);
+		oldslot = MakeSingleTupleTableSlot(oldTupDesc, &TTSOpsHeapTuple);
+		newslot = MakeSingleTupleTableSlot(newTupDesc, &TTSOpsHeapTuple);
 
 		/* Preallocate values/isnull arrays */
 		i = Max(newTupDesc->natts, oldTupDesc->natts);
@@ -8520,7 +8520,7 @@ validateCheckConstraint(Relation rel, HeapTuple constrtup)
 
 	econtext = GetPerTupleExprContext(estate);
 	tupdesc = RelationGetDescr(rel);
-	slot = MakeSingleTupleTableSlot(tupdesc);
+	slot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsHeapTuple);
 	econtext->ecxt_scantuple = slot;
 
 	snapshot = RegisterSnapshot(GetLatestSnapshot());
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index d6f33ecbd04..b91ebdb3d04 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -3525,7 +3525,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
 			{
 				oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
 				estate->es_trig_oldtup_slot =
-					ExecInitExtraTupleSlot(estate, NULL);
+					ExecInitExtraTupleSlot(estate, NULL, &TTSOpsHeapTuple);
 				MemoryContextSwitchTo(oldContext);
 			}
 			oldslot = estate->es_trig_oldtup_slot;
@@ -3539,7 +3539,7 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
 			{
 				oldContext = MemoryContextSwitchTo(estate->es_query_cxt);
 				estate->es_trig_newtup_slot =
-					ExecInitExtraTupleSlot(estate, NULL);
+					ExecInitExtraTupleSlot(estate, NULL, &TTSOpsHeapTuple);
 				MemoryContextSwitchTo(oldContext);
 			}
 			newslot = estate->es_trig_newtup_slot;
@@ -4546,8 +4546,10 @@ afterTriggerInvokeEvents(AfterTriggerEventList *events,
 							ExecDropSingleTupleTableSlot(slot1);
 							ExecDropSingleTupleTableSlot(slot2);
 						}
-						slot1 = MakeSingleTupleTableSlot(rel->rd_att);
-						slot2 = MakeSingleTupleTableSlot(rel->rd_att);
+						slot1 = MakeSingleTupleTableSlot(rel->rd_att,
+														 &TTSOpsMinimalTuple);
+						slot2 = MakeSingleTupleTableSlot(rel->rd_att,
+														 &TTSOpsMinimalTuple);
 					}
 					if (trigdesc == NULL)	/* should not happen */
 						elog(ERROR, "relation %u has no triggers",
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 885da18306a..82b5a0b404a 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -2423,7 +2423,8 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
 				scratch->d.wholerow.junkFilter =
 					ExecInitJunkFilter(subplan->plan->targetlist,
 									   ExecGetResultType(subplan)->tdhasoid,
-									   ExecInitExtraTupleSlot(parent->state, NULL));
+									   ExecInitExtraTupleSlot(parent->state, NULL,
+															  &TTSOpsVirtual));
 			}
 		}
 	}
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index c4d0e040587..5bc200e4dc3 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -202,7 +202,8 @@ BuildTupleHashTable(PlanState *parent,
 	 * We copy the input tuple descriptor just for safety --- we assume all
 	 * input tuples will have equivalent descriptors.
 	 */
-	hashtable->tableslot = MakeSingleTupleTableSlot(CreateTupleDescCopy(inputDesc));
+	hashtable->tableslot = MakeSingleTupleTableSlot(CreateTupleDescCopy(inputDesc),
+													&TTSOpsMinimalTuple);
 
 	/* build comparator for all columns */
 	hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
diff --git a/src/backend/executor/execIndexing.c b/src/backend/executor/execIndexing.c
index 9927ad70e66..8b35bb458de 100644
--- a/src/backend/executor/execIndexing.c
+++ b/src/backend/executor/execIndexing.c
@@ -706,7 +706,8 @@ check_exclusion_or_unique_constraint(Relation heap, Relation index,
 	 * to this slot.  Be sure to save and restore caller's value for
 	 * scantuple.
 	 */
-	existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap));
+	existing_slot = MakeSingleTupleTableSlot(RelationGetDescr(heap),
+											 &TTSOpsHeapTuple);
 
 	econtext = GetPerTupleExprContext(estate);
 	save_scantuple = econtext->ecxt_scantuple;
diff --git a/src/backend/executor/execJunk.c b/src/backend/executor/execJunk.c
index 57d74e57c1a..26558282e9c 100644
--- a/src/backend/executor/execJunk.c
+++ b/src/backend/executor/execJunk.c
@@ -78,7 +78,7 @@ ExecInitJunkFilter(List *targetList, bool hasoid, TupleTableSlot *slot)
 	if (slot)
 		ExecSetSlotDescriptor(slot, cleanTupType);
 	else
-		slot = MakeSingleTupleTableSlot(cleanTupType);
+		slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
 
 	/*
 	 * Now calculate the mapping between the original tuple's attributes and
@@ -149,7 +149,7 @@ ExecInitJunkFilterConversion(List *targetList,
 	if (slot)
 		ExecSetSlotDescriptor(slot, cleanTupType);
 	else
-		slot = MakeSingleTupleTableSlot(cleanTupType);
+		slot = MakeSingleTupleTableSlot(cleanTupType, &TTSOpsVirtual);
 
 	/*
 	 * Calculate the mapping between the original tuple's attributes and the
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index d10e533fd16..4843550a6f1 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -1055,7 +1055,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 
 			j = ExecInitJunkFilter(planstate->plan->targetlist,
 								   tupType->tdhasoid,
-								   ExecInitExtraTupleSlot(estate, NULL));
+								   ExecInitExtraTupleSlot(estate, NULL, &TTSOpsVirtual));
 			estate->es_junkFilter = j;
 
 			/* Want to return the cleaned tuple type */
@@ -1928,7 +1928,7 @@ ExecPartitionCheckEmitError(ResultRelInfo *resultRelInfo,
 		 */
 		if (map != NULL)
 			slot = execute_attr_map_slot(map, slot,
-										 MakeTupleTableSlot(tupdesc));
+										 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
 	}
 
 	insertedCols = GetInsertedColumns(resultRelInfo, estate);
@@ -2009,7 +2009,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
 					 */
 					if (map != NULL)
 						slot = execute_attr_map_slot(map, slot,
-													 MakeTupleTableSlot(tupdesc));
+													 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
 				}
 
 				insertedCols = GetInsertedColumns(resultRelInfo, estate);
@@ -2059,7 +2059,7 @@ ExecConstraints(ResultRelInfo *resultRelInfo,
 				 */
 				if (map != NULL)
 					slot = execute_attr_map_slot(map, slot,
-												 MakeTupleTableSlot(tupdesc));
+												 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
 			}
 
 			insertedCols = GetInsertedColumns(resultRelInfo, estate);
@@ -2167,7 +2167,7 @@ ExecWithCheckOptions(WCOKind kind, ResultRelInfo *resultRelInfo,
 						 */
 						if (map != NULL)
 							slot = execute_attr_map_slot(map, slot,
-														 MakeTupleTableSlot(tupdesc));
+														 MakeTupleTableSlot(tupdesc, &TTSOpsVirtual));
 					}
 
 					insertedCols = GetInsertedColumns(resultRelInfo, estate);
diff --git a/src/backend/executor/execPartition.c b/src/backend/executor/execPartition.c
index 1e72e9fb3f5..53cbd34be86 100644
--- a/src/backend/executor/execPartition.c
+++ b/src/backend/executor/execPartition.c
@@ -144,7 +144,8 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate, Relation rel)
 		 * We need an additional tuple slot for storing transient tuples that
 		 * are converted to the root table descriptor.
 		 */
-		proute->root_tuple_slot = MakeTupleTableSlot(RelationGetDescr(rel));
+		proute->root_tuple_slot = MakeTupleTableSlot(RelationGetDescr(rel),
+													 &TTSOpsHeapTuple);
 	}
 
 	i = 0;
@@ -740,7 +741,7 @@ ExecInitRoutingInfo(ModifyTableState *mtstate,
 		 */
 		proute->partition_tuple_slots[partidx] =
 			ExecInitExtraTupleSlot(estate,
-								   RelationGetDescr(partrel));
+								   RelationGetDescr(partrel), &TTSOpsHeapTuple);
 	}
 
 	/*
@@ -974,7 +975,7 @@ get_partition_dispatch_recurse(Relation rel, Relation parent,
 		 * using the correct tuple descriptor when computing its partition key
 		 * for tuple routing.
 		 */
-		pd->tupslot = MakeSingleTupleTableSlot(tupdesc);
+		pd->tupslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsHeapTuple);
 		pd->tupmap = convert_tuples_by_name_map_if_req(RelationGetDescr(parent),
 													   tupdesc,
 													   gettext_noop("could not convert row type"));
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index 3bffb0ea71f..248283f2543 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -873,7 +873,8 @@ ExecPrepareTuplestoreResult(SetExprState *sexpr,
 			slotDesc = NULL;	/* keep compiler quiet */
 		}
 
-		sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc);
+		sexpr->funcResultSlot = MakeSingleTupleTableSlot(slotDesc,
+														 &TTSOpsMinimalTuple);
 		MemoryContextSwitchTo(oldcontext);
 	}
 
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index ca2ca7f2d63..bb618e94f5d 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -72,6 +72,10 @@
 static TupleDesc ExecTypeFromTLInternal(List *targetList,
 					   bool hasoid, bool skipjunk);
 
+const TupleTableSlotOps TTSOpsVirtual;
+const TupleTableSlotOps TTSOpsHeapTuple;
+const TupleTableSlotOps TTSOpsMinimalTuple;
+const TupleTableSlotOps TTSOpsBufferTuple;
 
 /* ----------------------------------------------------------------
  *				  tuple table create/delete functions
@@ -87,7 +91,8 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
  * --------------------------------
  */
 TupleTableSlot *
-MakeTupleTableSlot(TupleDesc tupleDesc)
+MakeTupleTableSlot(TupleDesc tupleDesc,
+				   const TupleTableSlotOps *tts_cb)
 {
 	Size		sz;
 	TupleTableSlot *slot;
@@ -104,6 +109,8 @@ MakeTupleTableSlot(TupleDesc tupleDesc)
 		sz = sizeof(TupleTableSlot);
 
 	slot = palloc0(sz);
+	/* const for optimization purposes, OK to modify at allocation time */
+	*((const TupleTableSlotOps **) &slot->tts_cb) = tts_cb;
 	slot->type = T_TupleTableSlot;
 	slot->tts_flags |= TTS_FLAG_EMPTY;
 	if (tupleDesc != NULL)
@@ -140,9 +147,10 @@ MakeTupleTableSlot(TupleDesc tupleDesc)
  * --------------------------------
  */
 TupleTableSlot *
-ExecAllocTableSlot(List **tupleTable, TupleDesc desc)
+ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
+				   const TupleTableSlotOps *tts_cb)
 {
-	TupleTableSlot *slot = MakeTupleTableSlot(desc);
+	TupleTableSlot *slot = MakeTupleTableSlot(desc, tts_cb);
 
 	*tupleTable = lappend(*tupleTable, slot);
 
@@ -198,16 +206,17 @@ ExecResetTupleTable(List *tupleTable,	/* tuple table */
 /* --------------------------------
  *		MakeSingleTupleTableSlot
  *
- *		This is a convenience routine for operations that need a
- *		standalone TupleTableSlot not gotten from the main executor
- *		tuple table.  It makes a single slot and initializes it
- *		to use the given tuple descriptor.
+ *		This is a convenience routine for operations that need a standalone
+ *		TupleTableSlot not gotten from the main executor tuple table.  It makes
+ *		a single slot of given TupleTableSlotType and initializes it to use the
+ *		given tuple descriptor.
  * --------------------------------
  */
 TupleTableSlot *
-MakeSingleTupleTableSlot(TupleDesc tupdesc)
+MakeSingleTupleTableSlot(TupleDesc tupdesc,
+						 const TupleTableSlotOps *tts_cb)
 {
-	TupleTableSlot *slot = MakeTupleTableSlot(tupdesc);
+	TupleTableSlot *slot = MakeTupleTableSlot(tupdesc, tts_cb);
 
 	return slot;
 }
@@ -962,13 +971,17 @@ ExecInitResultTypeTL(PlanState *planstate)
  * ----------------
  */
 void
-ExecInitResultSlot(PlanState *planstate)
+ExecInitResultSlot(PlanState *planstate, const TupleTableSlotOps *tts_cb)
 {
 	TupleTableSlot *slot;
 
 	slot = ExecAllocTableSlot(&planstate->state->es_tupleTable,
-							  planstate->ps_ResultTupleDesc);
+							  planstate->ps_ResultTupleDesc, tts_cb);
 	planstate->ps_ResultTupleSlot = slot;
+
+	planstate->resultopsfixed = planstate->ps_ResultTupleDesc != NULL;
+	planstate->resultops = tts_cb;
+	planstate->resultopsset = true;
 }
 
 /* ----------------
@@ -978,10 +991,10 @@ ExecInitResultSlot(PlanState *planstate)
  * ----------------
  */
 void
-ExecInitResultTupleSlotTL(PlanState *planstate)
+ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_cb)
 {
 	ExecInitResultTypeTL(planstate);
-	ExecInitResultSlot(planstate);
+	ExecInitResultSlot(planstate, tts_cb);
 }
 
 /* ----------------
@@ -989,11 +1002,15 @@ ExecInitResultTupleSlotTL(PlanState *planstate)
  * ----------------
  */
 void
-ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
+ExecInitScanTupleSlot(EState *estate, ScanState *scanstate,
+					  TupleDesc tupledesc, const TupleTableSlotOps *tts_cb)
 {
 	scanstate->ss_ScanTupleSlot = ExecAllocTableSlot(&estate->es_tupleTable,
-													 tupledesc);
+													 tupledesc, tts_cb);
 	scanstate->ps.scandesc = tupledesc;
+	scanstate->ps.scanopsfixed = tupledesc != NULL;
+	scanstate->ps.scanops = tts_cb;
+	scanstate->ps.scanopsset = true;
 }
 
 /* ----------------
@@ -1005,9 +1022,11 @@ ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupledesc)
  * ----------------
  */
 TupleTableSlot *
-ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
+ExecInitExtraTupleSlot(EState *estate,
+					   TupleDesc tupledesc,
+					   const TupleTableSlotOps *tts_cb)
 {
-	return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc);
+	return ExecAllocTableSlot(&estate->es_tupleTable, tupledesc, tts_cb);
 }
 
 /* ----------------
@@ -1019,9 +1038,10 @@ ExecInitExtraTupleSlot(EState *estate, TupleDesc tupledesc)
  * ----------------
  */
 TupleTableSlot *
-ExecInitNullTupleSlot(EState *estate, TupleDesc tupType)
+ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
+					  const TupleTableSlotOps *tts_cb)
 {
-	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType);
+	TupleTableSlot *slot = ExecInitExtraTupleSlot(estate, tupType, tts_cb);
 
 	return ExecStoreAllNullTuple(slot);
 }
@@ -1545,13 +1565,15 @@ HeapTupleHeaderGetDatum(HeapTupleHeader tuple)
  * table function capability. Currently used by EXPLAIN and SHOW ALL.
  */
 TupOutputState *
-begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc)
+begin_tup_output_tupdesc(DestReceiver *dest,
+						 TupleDesc tupdesc,
+						 const TupleTableSlotOps *tts_cb)
 {
 	TupOutputState *tstate;
 
 	tstate = (TupOutputState *) palloc(sizeof(TupOutputState));
 
-	tstate->slot = MakeSingleTupleTableSlot(tupdesc);
+	tstate->slot = MakeSingleTupleTableSlot(tupdesc, tts_cb);
 	tstate->dest = dest;
 
 	tstate->dest->rStartup(tstate->dest, (int) CMD_SELECT, tupdesc);
diff --git a/src/backend/executor/execUtils.c b/src/backend/executor/execUtils.c
index f9e7bb479f1..e66b8322069 100644
--- a/src/backend/executor/execUtils.c
+++ b/src/backend/executor/execUtils.c
@@ -454,6 +454,32 @@ ExecGetResultType(PlanState *planstate)
 	return planstate->ps_ResultTupleDesc;
 }
 
+const TupleTableSlotOps *
+ExecGetResultSlotOps(PlanState *planstate, bool *isfixed)
+{
+	if (planstate->resultopsset && planstate->resultops)
+	{
+		if (isfixed)
+			*isfixed = planstate->resultopsfixed;
+		return planstate->resultops;
+	}
+
+	if (isfixed)
+	{
+		if (planstate->resultopsset)
+			*isfixed = planstate->resultopsfixed;
+		else if (planstate->ps_ResultTupleSlot)
+			*isfixed = TTS_FIXED(planstate->ps_ResultTupleSlot);
+		else
+			*isfixed = false;
+	}
+
+	if (!planstate->ps_ResultTupleSlot)
+		return &TTSOpsVirtual;
+
+	return planstate->ps_ResultTupleSlot->tts_cb;
+}
+
 
 /* ----------------
  *		ExecAssignProjectionInfo
@@ -492,11 +518,21 @@ ExecConditionalAssignProjectionInfo(PlanState *planstate, TupleDesc inputDesc,
 							  planstate->plan->targetlist,
 							  varno,
 							  inputDesc))
+	{
 		planstate->ps_ProjInfo = NULL;
+		planstate->resultopsset = planstate->scanopsset;
+		planstate->resultopsfixed = planstate->scanopsfixed;
+		planstate->resultops = planstate->scanops;
+	}
 	else
 	{
 		if (!planstate->ps_ResultTupleSlot)
-			ExecInitResultSlot(planstate);
+		{
+			ExecInitResultSlot(planstate, &TTSOpsVirtual);
+			planstate->resultops = &TTSOpsVirtual;
+			planstate->resultopsfixed = true;
+			planstate->resultopsset = true;
+		}
 		ExecAssignProjectionInfo(planstate, inputDesc);
 	}
 }
@@ -611,7 +647,9 @@ ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc)
  * ----------------
  */
 void
-ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
+ExecCreateScanSlotFromOuterPlan(EState *estate,
+								ScanState *scanstate,
+								const TupleTableSlotOps *tts_cb)
 {
 	PlanState  *outerPlan;
 	TupleDesc	tupDesc;
@@ -619,7 +657,7 @@ ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
 	outerPlan = outerPlanState(scanstate);
 	tupDesc = ExecGetResultType(outerPlan);
 
-	ExecInitScanTupleSlot(estate, scanstate, tupDesc);
+	ExecInitScanTupleSlot(estate, scanstate, tupDesc, tts_cb);
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index f4dd5732198..ae5c7c5490b 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -1717,7 +1717,8 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 
 		/* Set up junk filter if needed */
 		if (junkFilter)
-			*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+			*junkFilter = ExecInitJunkFilter(tlist, false,
+											 MakeSingleTupleTableSlot(NULL, &TTSOpsMinimalTuple));
 	}
 	else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)
 	{
@@ -1770,7 +1771,12 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 				}
 				/* Set up junk filter if needed */
 				if (junkFilter)
-					*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+				{
+					TupleTableSlot *slot =
+						MakeSingleTupleTableSlot(NULL, &TTSOpsMinimalTuple);
+
+					*junkFilter = ExecInitJunkFilter(tlist, false, slot);
+				}
 				return false;	/* NOT returning whole tuple */
 			}
 		}
@@ -1786,7 +1792,12 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 			 * what the caller expects will happen at runtime.
 			 */
 			if (junkFilter)
-				*junkFilter = ExecInitJunkFilter(tlist, false, NULL);
+			{
+				TupleTableSlot *slot;
+
+				slot = MakeSingleTupleTableSlot(NULL, &TTSOpsMinimalTuple);
+				*junkFilter = ExecInitJunkFilter(tlist, false, slot);
+			}
 			return true;
 		}
 		Assert(tupdesc);
@@ -1927,9 +1938,14 @@ check_sql_fn_retval(Oid func_id, Oid rettype, List *queryTreeList,
 
 		/* Set up junk filter if needed */
 		if (junkFilter)
+		{
+			TupleTableSlot *slot =
+				MakeSingleTupleTableSlot(NULL, &TTSOpsMinimalTuple);
+
 			*junkFilter = ExecInitJunkFilterConversion(tlist,
 													   CreateTupleDescCopy(tupdesc),
-													   NULL);
+													   slot);
+		}
 
 		/* Report that we are returning entire tuple result */
 		return true;
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 85f1ec7140f..20d6d8e9cbb 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1403,7 +1403,8 @@ find_hash_columns(AggState *aggstate)
 							  &perhash->eqfuncoids,
 							  &perhash->hashfunctions);
 		perhash->hashslot =
-			ExecAllocTableSlot(&estate->es_tupleTable, hashDesc);
+			ExecAllocTableSlot(&estate->es_tupleTable, hashDesc,
+							   &TTSOpsMinimalTuple);
 
 		list_free(hashTlist);
 		bms_free(colnos);
@@ -2211,15 +2212,17 @@ ExecInitAgg(Agg *node, EState *estate, int eflags)
 	/*
 	 * initialize source tuple type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &aggstate->ss,
+									ExecGetResultSlotOps(outerPlanState(&aggstate->ss), NULL));
 	scanDesc = aggstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
 	if (node->chain)
-		aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+		aggstate->sort_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+													 &TTSOpsMinimalTuple);
 
 	/*
 	 * Initialize result type, slot and projection.
 	 */
-	ExecInitResultTupleSlotTL(&aggstate->ss.ps);
+	ExecInitResultTupleSlotTL(&aggstate->ss.ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&aggstate->ss.ps, NULL);
 
 	/*
@@ -3062,7 +3065,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 	{
 		pertrans->sortdesc = ExecTypeFromTL(aggref->args, false);
 		pertrans->sortslot =
-			ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
+			ExecInitExtraTupleSlot(estate, pertrans->sortdesc,
+								   &TTSOpsMinimalTuple);
 	}
 
 	if (numSortCols > 0)
@@ -3084,7 +3088,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		{
 			/* we will need an extra slot to store prior values */
 			pertrans->uniqslot =
-				ExecInitExtraTupleSlot(estate, pertrans->sortdesc);
+				ExecInitExtraTupleSlot(estate, pertrans->sortdesc,
+									   &TTSOpsMinimalTuple);
 		}
 
 		/* Extract the sort information for use later */
diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c
index 94a17c7c67c..8c4abe12882 100644
--- a/src/backend/executor/nodeAppend.c
+++ b/src/backend/executor/nodeAppend.c
@@ -196,7 +196,11 @@ ExecInitAppend(Append *node, EState *estate, int eflags)
 	/*
 	 * Initialize result tuple type and slot.
 	 */
-	ExecInitResultTupleSlotTL(&appendstate->ps);
+	ExecInitResultTupleSlotTL(&appendstate->ps, &TTSOpsVirtual);
+
+	/* node returns slots from each of its subnodes, therefore not fixed */
+	appendstate->ps.resultopsset = true;
+	appendstate->ps.resultopsfixed = false;
 
 	appendplanstates = (PlanState **) palloc(nplans *
 											 sizeof(PlanState *));
diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c
index c153d74f411..1c27bfc412c 100644
--- a/src/backend/executor/nodeBitmapHeapscan.c
+++ b/src/backend/executor/nodeBitmapHeapscan.c
@@ -913,7 +913,8 @@ ExecInitBitmapHeapScan(BitmapHeapScan *node, EState *estate, int eflags)
 	 * get the scan type from the relation descriptor.
 	 */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  RelationGetDescr(currentRelation));
+						  RelationGetDescr(currentRelation),
+						  &TTSOpsBufferTuple);
 
 
 	/*
diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c
index 017b8772775..133aaf2d3b7 100644
--- a/src/backend/executor/nodeCtescan.c
+++ b/src/backend/executor/nodeCtescan.c
@@ -260,7 +260,8 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags)
 	 * table) is the same as the result rowtype of the CTE query.
 	 */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  ExecGetResultType(scanstate->cteplanstate));
+						  ExecGetResultType(scanstate->cteplanstate),
+						  &TTSOpsMinimalTuple);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeCustom.c b/src/backend/executor/nodeCustom.c
index ab3e34790e8..a015d72bf92 100644
--- a/src/backend/executor/nodeCustom.c
+++ b/src/backend/executor/nodeCustom.c
@@ -66,20 +66,24 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 	/*
 	 * Determine the scan tuple type.  If the custom scan provider provided a
 	 * targetlist describing the scan tuples, use that; else use base
-	 * relation's rowtype.
+	 * relation's rowtype. XXX: Probably we should let BeginCustomScan create
+	 * scan tuple slot with appropriate type of slot. But that means the
+	 * existing custom scan APIs need to be updated. Having a virtual tuple
+	 * table slot works since a custom scan can always decompose a tuple into
+	 * attributes and fill up the slot.
 	 */
 	if (cscan->custom_scan_tlist != NIL || scan_rel == NULL)
 	{
 		TupleDesc	scan_tupdesc;
 
 		scan_tupdesc = ExecTypeFromTL(cscan->custom_scan_tlist, false);
-		ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc);
+		ExecInitScanTupleSlot(estate, &css->ss, scan_tupdesc, &TTSOpsVirtual);
 		/* Node's targetlist will contain Vars with varno = INDEX_VAR */
 		tlistvarno = INDEX_VAR;
 	}
 	else
 	{
-		ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel));
+		ExecInitScanTupleSlot(estate, &css->ss, RelationGetDescr(scan_rel), &TTSOpsVirtual);
 		/* Node's targetlist will contain Vars with varno = scanrelid */
 		tlistvarno = scanrelid;
 	}
@@ -87,7 +91,7 @@ ExecInitCustomScan(CustomScan *cscan, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&css->ss.ps);
+	ExecInitResultTupleSlotTL(&css->ss.ps, &TTSOpsVirtual);
 	ExecAssignScanProjectionInfoWithVarno(&css->ss, tlistvarno);
 
 	/* initialize child expressions */
diff --git a/src/backend/executor/nodeForeignscan.c b/src/backend/executor/nodeForeignscan.c
index f7eef32f6fe..a2ab2d265b3 100644
--- a/src/backend/executor/nodeForeignscan.c
+++ b/src/backend/executor/nodeForeignscan.c
@@ -180,7 +180,8 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 		TupleDesc	scan_tupdesc;
 
 		scan_tupdesc = ExecTypeFromTL(node->fdw_scan_tlist, false);
-		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
+		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
+							  &TTSOpsHeapTuple);
 		/* Node's targetlist will contain Vars with varno = INDEX_VAR */
 		tlistvarno = INDEX_VAR;
 	}
@@ -190,11 +191,16 @@ ExecInitForeignScan(ForeignScan *node, EState *estate, int eflags)
 
 		/* don't trust FDWs to return tuples fulfilling NOT NULL constraints */
 		scan_tupdesc = CreateTupleDescCopy(RelationGetDescr(currentRelation));
-		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
+		ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
+							  &TTSOpsHeapTuple);
 		/* Node's targetlist will contain Vars with varno = scanrelid */
 		tlistvarno = scanrelid;
 	}
 
+	/* Don't know what an FDW might return */
+	scanstate->ss.ps.scanopsfixed = false;
+	scanstate->ss.ps.scanopsset = true;
+
 	/*
 	 * Initialize result slot, type and projection.
 	 */
diff --git a/src/backend/executor/nodeFunctionscan.c b/src/backend/executor/nodeFunctionscan.c
index 0596adbb2f1..b6a1fa14560 100644
--- a/src/backend/executor/nodeFunctionscan.c
+++ b/src/backend/executor/nodeFunctionscan.c
@@ -424,7 +424,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 		 */
 		if (!scanstate->simple)
 		{
-			fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc);
+			fs->func_slot = ExecInitExtraTupleSlot(estate, fs->tupdesc,
+												   &TTSOpsMinimalTuple);
 		}
 		else
 			fs->func_slot = NULL;
@@ -482,7 +483,8 @@ ExecInitFunctionScan(FunctionScan *node, EState *estate, int eflags)
 	/*
 	 * Initialize scan slot and type.
 	 */
-	ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, scan_tupdesc,
+						  &TTSOpsMinimalTuple);
 
 	/*
 	 * Initialize result slot, type and projection.
diff --git a/src/backend/executor/nodeGather.c b/src/backend/executor/nodeGather.c
index afddb0a0394..e45e07f0a1a 100644
--- a/src/backend/executor/nodeGather.c
+++ b/src/backend/executor/nodeGather.c
@@ -91,6 +91,11 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
 	outerPlanState(gatherstate) = ExecInitNode(outerNode, estate, eflags);
 	tupDesc = ExecGetResultType(outerPlanState(gatherstate));
 
+	/* this node uses tuples from the tuple queue as scan slot */
+	gatherstate->ps.scanops = &TTSOpsHeapTuple;
+	gatherstate->ps.scanopsfixed = true;
+	gatherstate->ps.scanopsset = true;
+
 	/*
 	 * Initialize result type and projection.
 	 */
@@ -100,7 +105,8 @@ ExecInitGather(Gather *node, EState *estate, int eflags)
 	/*
 	 * Initialize funnel slot to same tuple descriptor as outer plan.
 	 */
-	gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc);
+	gatherstate->funnel_slot = ExecInitExtraTupleSlot(estate, tupDesc,
+													  &TTSOpsHeapTuple);
 
 	/*
 	 * Gather doesn't support checking a qual (it's always more efficient to
diff --git a/src/backend/executor/nodeGatherMerge.c b/src/backend/executor/nodeGatherMerge.c
index 7ae067f9ebf..90aa7e42d50 100644
--- a/src/backend/executor/nodeGatherMerge.c
+++ b/src/backend/executor/nodeGatherMerge.c
@@ -122,6 +122,13 @@ ExecInitGatherMerge(GatherMerge *node, EState *estate, int eflags)
 	ExecInitResultTypeTL(&gm_state->ps);
 	ExecConditionalAssignProjectionInfo(&gm_state->ps, tupDesc, OUTER_VAR);
 
+	/* leader accesses ExecProcNode result directly, others go through tuple queue */
+	if (gm_state->ps.ps_ProjInfo == NULL)
+	{
+		gm_state->ps.resultopsset = true;
+		gm_state->ps.resultopsfixed = false;
+	}
+
 	/*
 	 * initialize sort-key information
 	 */
@@ -404,7 +411,8 @@ gather_merge_setup(GatherMergeState *gm_state)
 
 		/* Initialize tuple slot for worker */
 		gm_state->gm_slots[i + 1] =
-			ExecInitExtraTupleSlot(gm_state->ps.state, gm_state->tupDesc);
+			ExecInitExtraTupleSlot(gm_state->ps.state, gm_state->tupDesc,
+				&TTSOpsHeapTuple);
 	}
 
 	/* Allocate the resources for the merge */
diff --git a/src/backend/executor/nodeGroup.c b/src/backend/executor/nodeGroup.c
index 9c1e51bc954..124753618a6 100644
--- a/src/backend/executor/nodeGroup.c
+++ b/src/backend/executor/nodeGroup.c
@@ -188,12 +188,13 @@ ExecInitGroup(Group *node, EState *estate, int eflags)
 	/*
 	 * Initialize scan slot and type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &grpstate->ss,
+									ExecGetResultSlotOps(outerPlanState(&grpstate->ss), NULL));
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&grpstate->ss.ps);
+	ExecInitResultTupleSlotTL(&grpstate->ss.ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&grpstate->ss.ps, NULL);
 
 	/*
diff --git a/src/backend/executor/nodeHash.c b/src/backend/executor/nodeHash.c
index 5a9f1ea3c55..ba2f6686cf6 100644
--- a/src/backend/executor/nodeHash.c
+++ b/src/backend/executor/nodeHash.c
@@ -382,7 +382,7 @@ ExecInitHash(Hash *node, EState *estate, int eflags)
 	 * initialize our result slot and type. No need to build projection
 	 * because this node doesn't do projections.
 	 */
-	ExecInitResultTupleSlotTL(&hashstate->ps);
+	ExecInitResultTupleSlotTL(&hashstate->ps, &TTSOpsMinimalTuple);
 	hashstate->ps.ps_ProjInfo = NULL;
 
 	/*
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index d6a6ef770dd..d9afd0bdded 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -650,13 +650,14 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&hjstate->js.ps);
+	ExecInitResultTupleSlotTL(&hjstate->js.ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&hjstate->js.ps, NULL);
 
 	/*
 	 * tuple table initialization
 	 */
-	hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc);
+	hjstate->hj_OuterTupleSlot = ExecInitExtraTupleSlot(estate, outerDesc,
+														ExecGetResultSlotOps(outerPlanState(hjstate), NULL));
 
 	/*
 	 * detect whether we need only consider the first matching inner tuple
@@ -673,17 +674,17 @@ ExecInitHashJoin(HashJoin *node, EState *estate, int eflags)
 		case JOIN_LEFT:
 		case JOIN_ANTI:
 			hjstate->hj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
 			break;
 		case JOIN_RIGHT:
 			hjstate->hj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
 			break;
 		case JOIN_FULL:
 			hjstate->hj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
 			hjstate->hj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
 			break;
 		default:
 			elog(ERROR, "unrecognized join type: %d",
diff --git a/src/backend/executor/nodeIndexonlyscan.c b/src/backend/executor/nodeIndexonlyscan.c
index 865a056c027..4e5e52cec3b 100644
--- a/src/backend/executor/nodeIndexonlyscan.c
+++ b/src/backend/executor/nodeIndexonlyscan.c
@@ -527,7 +527,7 @@ ExecInitIndexOnlyScan(IndexOnlyScan *node, EState *estate, int eflags)
 	 * suitable data anyway.)
 	 */
 	tupDesc = ExecTypeFromTL(node->indextlist, false);
-	ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc);
+	ExecInitScanTupleSlot(estate, &indexstate->ss, tupDesc, &TTSOpsHeapTuple);
 
 	/*
 	 * Initialize result type and projection info.  The node's targetlist will
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 8593c0e3050..83038e31f66 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -945,7 +945,8 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	 * get the scan type from the relation descriptor.
 	 */
 	ExecInitScanTupleSlot(estate, &indexstate->ss,
-						  RelationGetDescr(currentRelation));
+						  RelationGetDescr(currentRelation),
+						  &TTSOpsBufferTuple); /* FIXME: wrong for reorder case */
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index f0b68191400..6792f9e86c7 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -380,6 +380,10 @@ ExecInitLimit(Limit *node, EState *estate, int eflags)
 	 */
 	ExecInitResultTypeTL(&limitstate->ps);
 
+	limitstate->ps.resultopsset = true;
+	limitstate->ps.resultops = ExecGetResultSlotOps(outerPlanState(limitstate),
+													&limitstate->ps.resultopsfixed);
+
 	/*
 	 * limit nodes do no projections, so initialize projection info for this
 	 * node appropriately
diff --git a/src/backend/executor/nodeLockRows.c b/src/backend/executor/nodeLockRows.c
index 961798cecb3..7887388b9e9 100644
--- a/src/backend/executor/nodeLockRows.c
+++ b/src/backend/executor/nodeLockRows.c
@@ -390,6 +390,11 @@ ExecInitLockRows(LockRows *node, EState *estate, int eflags)
 	 */
 	outerPlanState(lrstate) = ExecInitNode(outerPlan, estate, eflags);
 
+	/* node returns unmodified slots from the outer plan */
+	lrstate->ps.resultopsset = true;
+	lrstate->ps.resultops = ExecGetResultSlotOps(outerPlanState(lrstate),
+													&lrstate->ps.resultopsfixed);
+
 	/*
 	 * LockRows nodes do no projections, so initialize projection info for
 	 * this node appropriately
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c
index 4ede428f908..657814cd0db 100644
--- a/src/backend/executor/nodeMaterial.c
+++ b/src/backend/executor/nodeMaterial.c
@@ -146,10 +146,8 @@ ExecMaterial(PlanState *pstate)
 		if (tuplestorestate)
 			tuplestore_puttupleslot(tuplestorestate, outerslot);
 
-		/*
-		 * We can just return the subplan's returned tuple, without copying.
-		 */
-		return outerslot;
+		ExecCopySlot(slot, outerslot);
+		return slot;
 	}
 
 	/*
@@ -223,13 +221,13 @@ ExecInitMaterial(Material *node, EState *estate, int eflags)
 	 *
 	 * material nodes only return tuples from their materialized relation.
 	 */
-	ExecInitResultTupleSlotTL(&matstate->ss.ps);
+	ExecInitResultTupleSlotTL(&matstate->ss.ps, &TTSOpsMinimalTuple);
 	matstate->ss.ps.ps_ProjInfo = NULL;
 
 	/*
 	 * initialize tuple type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss, &TTSOpsMinimalTuple);
 
 	return matstate;
 }
diff --git a/src/backend/executor/nodeMergeAppend.c b/src/backend/executor/nodeMergeAppend.c
index dbed667d164..188e76b60cd 100644
--- a/src/backend/executor/nodeMergeAppend.c
+++ b/src/backend/executor/nodeMergeAppend.c
@@ -167,7 +167,11 @@ ExecInitMergeAppend(MergeAppend *node, EState *estate, int eflags)
 	 * MergeAppend nodes do have Result slots, which hold pointers to tuples,
 	 * so we have to initialize them.  FIXME
 	 */
-	ExecInitResultTupleSlotTL(&mergestate->ps);
+	ExecInitResultTupleSlotTL(&mergestate->ps, &TTSOpsVirtual);
+
+	/* node returns slots from each of its subnodes, therefore not fixed */
+	mergestate->ps.resultopsset = true;
+	mergestate->ps.resultopsfixed = false;
 
 	/*
 	 * call ExecInitNode on each of the valid plans to be executed and save
diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c
index 9c978313318..1c90291d127 100644
--- a/src/backend/executor/nodeMergejoin.c
+++ b/src/backend/executor/nodeMergejoin.c
@@ -1438,6 +1438,7 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 	MergeJoinState *mergestate;
 	TupleDesc	outerDesc,
 				innerDesc;
+	const TupleTableSlotOps *innerOps;
 
 	/* check for unsupported flags */
 	Assert(!(eflags & (EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK)));
@@ -1512,13 +1513,15 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&mergestate->js.ps);
+	ExecInitResultTupleSlotTL(&mergestate->js.ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&mergestate->js.ps, NULL);
 
 	/*
 	 * tuple table initialization
 	 */
-	mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc);
+	innerOps = ExecGetResultSlotOps(innerPlanState(mergestate), NULL);
+	mergestate->mj_MarkedTupleSlot = ExecInitExtraTupleSlot(estate, innerDesc,
+															innerOps);
 
 	/*
 	 * initialize child expressions
@@ -1548,13 +1551,13 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 			mergestate->mj_FillOuter = true;
 			mergestate->mj_FillInner = false;
 			mergestate->mj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
 			break;
 		case JOIN_RIGHT:
 			mergestate->mj_FillOuter = false;
 			mergestate->mj_FillInner = true;
 			mergestate->mj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
 
 			/*
 			 * Can't handle right or full join with non-constant extra
@@ -1570,9 +1573,9 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags)
 			mergestate->mj_FillOuter = true;
 			mergestate->mj_FillInner = true;
 			mergestate->mj_NullOuterTupleSlot =
-				ExecInitNullTupleSlot(estate, outerDesc);
+				ExecInitNullTupleSlot(estate, outerDesc, &TTSOpsVirtual);
 			mergestate->mj_NullInnerTupleSlot =
-				ExecInitNullTupleSlot(estate, innerDesc);
+				ExecInitNullTupleSlot(estate, innerDesc, &TTSOpsVirtual);
 
 			/*
 			 * Can't handle right or full join with non-constant extra
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index ca7ece3235f..9cc499d6533 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2407,7 +2407,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		mtstate->ps.plan->targetlist = (List *) linitial(node->returningLists);
 
 		/* Set up a slot for the output of the RETURNING projection(s) */
-		ExecInitResultTupleSlotTL(&mtstate->ps);
+		ExecInitResultTupleSlotTL(&mtstate->ps, &TTSOpsVirtual);
 		slot = mtstate->ps.ps_ResultTupleSlot;
 
 		/* Need an econtext too */
@@ -2476,7 +2476,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		mtstate->mt_existing =
 			ExecInitExtraTupleSlot(mtstate->ps.state,
 								   mtstate->mt_partition_tuple_routing ?
-								   NULL : relationDesc);
+								   NULL : relationDesc, &TTSOpsBufferTuple);
 
 		/* carried forward solely for the benefit of explain */
 		mtstate->mt_excludedtlist = node->exclRelTlist;
@@ -2498,7 +2498,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		mtstate->mt_conflproj =
 			ExecInitExtraTupleSlot(mtstate->ps.state,
 								   mtstate->mt_partition_tuple_routing ?
-								   NULL : tupDesc);
+								   NULL : tupDesc, &TTSOpsHeapTuple);
 		resultRelInfo->ri_onConflict->oc_ProjTupdesc = tupDesc;
 
 		/* build UPDATE SET projection state */
@@ -2609,7 +2609,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 
 				j = ExecInitJunkFilter(subplan->targetlist,
 									   resultRelInfo->ri_RelationDesc->rd_att->tdhasoid,
-									   ExecInitExtraTupleSlot(estate, NULL));
+									   ExecInitExtraTupleSlot(estate, NULL, &TTSOpsHeapTuple));
 
 				if (operation == CMD_UPDATE || operation == CMD_DELETE)
 				{
@@ -2656,10 +2656,12 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 	/*
 	 * Set up a tuple table slot for use for trigger output tuples. In a plan
 	 * containing multiple ModifyTable nodes, all can share one such slot, so
-	 * we keep it in the estate.
+	 * we keep it in the estate. The tuple being inserted doesn't come from a
+	 * buffer.
 	 */
 	if (estate->es_trig_tuple_slot == NULL)
-		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
+		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
+															&TTSOpsHeapTuple);
 
 	/*
 	 * Lastly, if this is not the primary (canSetTag) ModifyTable node, add it
diff --git a/src/backend/executor/nodeNamedtuplestorescan.c b/src/backend/executor/nodeNamedtuplestorescan.c
index cf1b7b4f872..cd8a1fceac5 100644
--- a/src/backend/executor/nodeNamedtuplestorescan.c
+++ b/src/backend/executor/nodeNamedtuplestorescan.c
@@ -137,7 +137,8 @@ ExecInitNamedTuplestoreScan(NamedTuplestoreScan *node, EState *estate, int eflag
 	/*
 	 * The scan tuple type is specified for the tuplestore.
 	 */
-	ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, scanstate->tupdesc,
+						  &TTSOpsMinimalTuple);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c
index 8dbec685eb1..0cb6f9dd4cd 100644
--- a/src/backend/executor/nodeNestloop.c
+++ b/src/backend/executor/nodeNestloop.c
@@ -304,7 +304,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&nlstate->js.ps);
+	ExecInitResultTupleSlotTL(&nlstate->js.ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&nlstate->js.ps, NULL);
 
 	/*
@@ -332,7 +332,8 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags)
 		case JOIN_ANTI:
 			nlstate->nl_NullInnerTupleSlot =
 				ExecInitNullTupleSlot(estate,
-									  ExecGetResultType(innerPlanState(nlstate)));
+									  ExecGetResultType(innerPlanState(nlstate)),
+									  &TTSOpsVirtual);
 			break;
 		default:
 			elog(ERROR, "unrecognized join type: %d",
diff --git a/src/backend/executor/nodeProjectSet.c b/src/backend/executor/nodeProjectSet.c
index e4dd4142177..06a7da8f77e 100644
--- a/src/backend/executor/nodeProjectSet.c
+++ b/src/backend/executor/nodeProjectSet.c
@@ -256,7 +256,7 @@ ExecInitProjectSet(ProjectSet *node, EState *estate, int eflags)
 	/*
 	 * tuple table and result type initialization
 	 */
-	ExecInitResultTupleSlotTL(&state->ps);
+	ExecInitResultTupleSlotTL(&state->ps, &TTSOpsVirtual);
 
 	/* Create workspace for per-tlist-entry expr state & SRF-is-done state */
 	state->nelems = list_length(node->plan.targetlist);
diff --git a/src/backend/executor/nodeResult.c b/src/backend/executor/nodeResult.c
index 2bbb2e78848..63428c7ffe0 100644
--- a/src/backend/executor/nodeResult.c
+++ b/src/backend/executor/nodeResult.c
@@ -217,7 +217,7 @@ ExecInitResult(Result *node, EState *estate, int eflags)
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&resstate->ps);
+	ExecInitResultTupleSlotTL(&resstate->ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&resstate->ps, NULL);
 
 	/*
diff --git a/src/backend/executor/nodeSamplescan.c b/src/backend/executor/nodeSamplescan.c
index cfa26535d7b..55e7bd2f6cf 100644
--- a/src/backend/executor/nodeSamplescan.c
+++ b/src/backend/executor/nodeSamplescan.c
@@ -146,7 +146,8 @@ ExecInitSampleScan(SampleScan *node, EState *estate, int eflags)
 
 	/* and create slot with appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  RelationGetDescr(scanstate->ss.ss_currentRelation));
+						  RelationGetDescr(scanstate->ss.ss_currentRelation),
+						  &TTSOpsBufferTuple);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeSeqscan.c b/src/backend/executor/nodeSeqscan.c
index b4bea67610f..307ad9ccd53 100644
--- a/src/backend/executor/nodeSeqscan.c
+++ b/src/backend/executor/nodeSeqscan.c
@@ -172,7 +172,8 @@ ExecInitSeqScan(SeqScan *node, EState *estate, int eflags)
 
 	/* and create slot with the appropriate rowtype */
 	ExecInitScanTupleSlot(estate, &scanstate->ss,
-						  RelationGetDescr(scanstate->ss.ss_currentRelation));
+						  RelationGetDescr(scanstate->ss.ss_currentRelation),
+						  &TTSOpsBufferTuple);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeSetOp.c b/src/backend/executor/nodeSetOp.c
index 46bf77775c4..44c43e99a02 100644
--- a/src/backend/executor/nodeSetOp.c
+++ b/src/backend/executor/nodeSetOp.c
@@ -532,7 +532,9 @@ ExecInitSetOp(SetOp *node, EState *estate, int eflags)
 	 * Initialize result slot and type. Setop nodes do no projections, so
 	 * initialize projection info for this node appropriately.
 	 */
-	ExecInitResultTupleSlotTL(&setopstate->ps);
+	ExecInitResultTupleSlotTL(&setopstate->ps,
+							  node->strategy == SETOP_HASHED ?
+							  &TTSOpsMinimalTuple : &TTSOpsHeapTuple);
 	setopstate->ps.ps_ProjInfo = NULL;
 
 	/*
diff --git a/src/backend/executor/nodeSort.c b/src/backend/executor/nodeSort.c
index 5492cd45579..750292b1014 100644
--- a/src/backend/executor/nodeSort.c
+++ b/src/backend/executor/nodeSort.c
@@ -211,13 +211,13 @@ ExecInitSort(Sort *node, EState *estate, int eflags)
 	/*
 	 * Initialize scan slot and type.
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &sortstate->ss, &TTSOpsVirtual);
 
 	/*
 	 * Initialize return slot and type. No need to initialize projection info
 	 * because this node doesn't do projections.
 	 */
-	ExecInitResultTupleSlotTL(&sortstate->ss.ps);
+	ExecInitResultTupleSlotTL(&sortstate->ss.ps, &TTSOpsMinimalTuple);
 	sortstate->ss.ps.ps_ProjInfo = NULL;
 
 	SO1_printf("ExecInitSort: %s\n",
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 63de981034d..62811ed0302 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -968,7 +968,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 		 * own innerecontext.
 		 */
 		tupDescLeft = ExecTypeFromTL(lefttlist, false);
-		slot = ExecInitExtraTupleSlot(estate, tupDescLeft);
+		slot = ExecInitExtraTupleSlot(estate, tupDescLeft, &TTSOpsVirtual);
 		sstate->projLeft = ExecBuildProjectionInfo(lefttlist,
 												   NULL,
 												   slot,
@@ -976,7 +976,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 												   NULL);
 
 		sstate->descRight = tupDescRight = ExecTypeFromTL(righttlist, false);
-		slot = ExecInitExtraTupleSlot(estate, tupDescRight);
+		slot = ExecInitExtraTupleSlot(estate, tupDescRight, &TTSOpsVirtual);
 		sstate->projRight = ExecBuildProjectionInfo(righttlist,
 													sstate->innerecontext,
 													slot,
diff --git a/src/backend/executor/nodeSubqueryscan.c b/src/backend/executor/nodeSubqueryscan.c
index b84c6892d50..71a5711362b 100644
--- a/src/backend/executor/nodeSubqueryscan.c
+++ b/src/backend/executor/nodeSubqueryscan.c
@@ -129,7 +129,18 @@ ExecInitSubqueryScan(SubqueryScan *node, EState *estate, int eflags)
 	 * Initialize scan slot and type (needed by ExecAssignScanProjectionInfo)
 	 */
 	ExecInitScanTupleSlot(estate, &subquerystate->ss,
-						  ExecGetResultType(subquerystate->subplan));
+						  ExecGetResultType(subquerystate->subplan),
+						  ExecGetResultSlotOps(subquerystate->subplan, NULL));
+	/*
+	 * The slot used as the scantuple isn't the slot above (outside of EPQ),
+	 * therefore only mark it as fixed if node below is.
+	 */
+	subquerystate->ss.ps.scanopsfixed = subquerystate->subplan->resultopsfixed;
+	subquerystate->ss.ps.scanopsset = subquerystate->subplan->resultopsset;
+
+	subquerystate->ss.ps.resultops = subquerystate->subplan->resultops;
+	subquerystate->ss.ps.resultopsfixed = subquerystate->subplan->resultopsfixed;
+	subquerystate->ss.ps.resultopsset = subquerystate->subplan->resultopsset;
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeTableFuncscan.c b/src/backend/executor/nodeTableFuncscan.c
index b0c94d7e063..a79e4cb2cf5 100644
--- a/src/backend/executor/nodeTableFuncscan.c
+++ b/src/backend/executor/nodeTableFuncscan.c
@@ -147,7 +147,8 @@ ExecInitTableFuncScan(TableFuncScan *node, EState *estate, int eflags)
 								 tf->coltypmods,
 								 tf->colcollations);
 	/* and the corresponding scan slot */
-	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc,
+						  &TTSOpsMinimalTuple);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeTidscan.c b/src/backend/executor/nodeTidscan.c
index bc859e3d516..939ece2faa1 100644
--- a/src/backend/executor/nodeTidscan.c
+++ b/src/backend/executor/nodeTidscan.c
@@ -543,7 +543,8 @@ ExecInitTidScan(TidScan *node, EState *estate, int eflags)
 	 * get the scan type from the relation descriptor.
 	 */
 	ExecInitScanTupleSlot(estate, &tidstate->ss,
-						  RelationGetDescr(currentRelation));
+						  RelationGetDescr(currentRelation),
+						  &TTSOpsBufferTuple);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeUnique.c b/src/backend/executor/nodeUnique.c
index c791f89b48c..c5e4232e68c 100644
--- a/src/backend/executor/nodeUnique.c
+++ b/src/backend/executor/nodeUnique.c
@@ -141,7 +141,7 @@ ExecInitUnique(Unique *node, EState *estate, int eflags)
 	 * Initialize result slot and type. Unique nodes do no projections, so
 	 * initialize projection info for this node appropriately.
 	 */
-	ExecInitResultTupleSlotTL(&uniquestate->ps);
+	ExecInitResultTupleSlotTL(&uniquestate->ps, &TTSOpsMinimalTuple);
 	uniquestate->ps.ps_ProjInfo = NULL;
 
 	/*
diff --git a/src/backend/executor/nodeValuesscan.c b/src/backend/executor/nodeValuesscan.c
index fa49d0470fc..6351cdac27a 100644
--- a/src/backend/executor/nodeValuesscan.c
+++ b/src/backend/executor/nodeValuesscan.c
@@ -261,7 +261,7 @@ ExecInitValuesScan(ValuesScan *node, EState *estate, int eflags)
 	 * Get info about values list, initialize scan slot with it.
 	 */
 	tupdesc = ExecTypeFromExprList((List *) linitial(node->values_lists));
-	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc);
+	ExecInitScanTupleSlot(estate, &scanstate->ss, tupdesc, &TTSOpsVirtual);
 
 	/*
 	 * Initialize result type and projection.
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index 6e597e82856..9cb99cab72c 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -2316,16 +2316,25 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 	 * initialize source tuple type (which is also the tuple type that we'll
 	 * store in the tuplestore and use in all our working slots).
 	 */
-	ExecCreateScanSlotFromOuterPlan(estate, &winstate->ss);
+	ExecCreateScanSlotFromOuterPlan(estate, &winstate->ss, &TTSOpsMinimalTuple);
 	scanDesc = winstate->ss.ss_ScanTupleSlot->tts_tupleDescriptor;
 
+	/* the outer tuple isn't the child's tuple, but always a minimal tuple */
+	winstate->ss.ps.leftopsset = true;
+	winstate->ss.ps.leftops = &TTSOpsMinimalTuple;
+	winstate->ss.ps.leftopsfixed = true;
+
 	/*
 	 * tuple table initialization
 	 */
-	winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc);
-	winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc);
-	winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc);
-	winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc);
+	winstate->first_part_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+													   &TTSOpsMinimalTuple);
+	winstate->agg_row_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+													&TTSOpsMinimalTuple);
+	winstate->temp_slot_1 = ExecInitExtraTupleSlot(estate, scanDesc,
+												   &TTSOpsMinimalTuple);
+	winstate->temp_slot_2 = ExecInitExtraTupleSlot(estate, scanDesc,
+												   &TTSOpsMinimalTuple);
 
 	/*
 	 * create frame head and tail slots only if needed (must create slots in
@@ -2339,17 +2348,19 @@ ExecInitWindowAgg(WindowAgg *node, EState *estate, int eflags)
 		if (((frameOptions & FRAMEOPTION_START_CURRENT_ROW) &&
 			 node->ordNumCols != 0) ||
 			(frameOptions & FRAMEOPTION_START_OFFSET))
-			winstate->framehead_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+			winstate->framehead_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+															  &TTSOpsMinimalTuple);
 		if (((frameOptions & FRAMEOPTION_END_CURRENT_ROW) &&
 			 node->ordNumCols != 0) ||
 			(frameOptions & FRAMEOPTION_END_OFFSET))
-			winstate->frametail_slot = ExecInitExtraTupleSlot(estate, scanDesc);
+			winstate->frametail_slot = ExecInitExtraTupleSlot(estate, scanDesc,
+															  &TTSOpsMinimalTuple);
 	}
 
 	/*
 	 * Initialize result slot, type and projection.
 	 */
-	ExecInitResultTupleSlotTL(&winstate->ss.ps);
+	ExecInitResultTupleSlotTL(&winstate->ss.ps, &TTSOpsVirtual);
 	ExecAssignProjectionInfo(&winstate->ss.ps, NULL);
 
 	/* Set up data for comparing tuples */
diff --git a/src/backend/executor/nodeWorktablescan.c b/src/backend/executor/nodeWorktablescan.c
index 1ce8ae9f026..a432926fe15 100644
--- a/src/backend/executor/nodeWorktablescan.c
+++ b/src/backend/executor/nodeWorktablescan.c
@@ -160,7 +160,12 @@ ExecInitWorkTableScan(WorkTableScan *node, EState *estate, int eflags)
 	 * tuple table initialization
 	 */
 	ExecInitResultTypeTL(&scanstate->ss.ps);
-	ExecInitScanTupleSlot(estate, &scanstate->ss, NULL);
+
+	/* signal that return type is not yet known */
+	scanstate->ss.ps.resultopsset = true;
+	scanstate->ss.ps.resultopsfixed = false;
+
+	ExecInitScanTupleSlot(estate, &scanstate->ss, NULL, &TTSOpsMinimalTuple);
 
 	/*
 	 * initialize child expressions
diff --git a/src/backend/partitioning/partbounds.c b/src/backend/partitioning/partbounds.c
index c94f73aadc1..1d6d1b31a2d 100644
--- a/src/backend/partitioning/partbounds.c
+++ b/src/backend/partitioning/partbounds.c
@@ -705,7 +705,7 @@ check_default_partition_contents(Relation parent, Relation default_rel,
 		econtext = GetPerTupleExprContext(estate);
 		snapshot = RegisterSnapshot(GetLatestSnapshot());
 		scan = heap_beginscan(part_rel, snapshot, 0, NULL);
-		tupslot = MakeSingleTupleTableSlot(tupdesc);
+		tupslot = MakeSingleTupleTableSlot(tupdesc, &TTSOpsHeapTuple);
 
 		/*
 		 * Switch to per-tuple memory context and reset it for each tuple
diff --git a/src/backend/replication/logical/tablesync.c b/src/backend/replication/logical/tablesync.c
index 6e420d893cf..9e682331d2f 100644
--- a/src/backend/replication/logical/tablesync.c
+++ b/src/backend/replication/logical/tablesync.c
@@ -685,7 +685,7 @@ fetch_remote_table_info(char *nspname, char *relname,
 				(errmsg("could not fetch table info for table \"%s.%s\" from publisher: %s",
 						nspname, relname, res->err)));
 
-	slot = MakeSingleTupleTableSlot(res->tupledesc);
+	slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
 	if (!tuplestore_gettupleslot(res->tuplestore, true, false, slot))
 		ereport(ERROR,
 				(errmsg("table \"%s.%s\" not found on publisher",
@@ -727,7 +727,7 @@ fetch_remote_table_info(char *nspname, char *relname,
 	lrel->attkeys = NULL;
 
 	natt = 0;
-	slot = MakeSingleTupleTableSlot(res->tupledesc);
+	slot = MakeSingleTupleTableSlot(res->tupledesc, &TTSOpsMinimalTuple);
 	while (tuplestore_gettupleslot(res->tuplestore, true, false, slot))
 	{
 		lrel->attnames[natt] =
diff --git a/src/backend/replication/logical/worker.c b/src/backend/replication/logical/worker.c
index 277da69fa6c..fa17e1b3bb1 100644
--- a/src/backend/replication/logical/worker.c
+++ b/src/backend/replication/logical/worker.c
@@ -213,7 +213,8 @@ create_estate_for_relation(LogicalRepRelMapEntry *rel)
 
 	/* Triggers might need a slot */
 	if (resultRelInfo->ri_TrigDesc)
-		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL);
+		estate->es_trig_tuple_slot = ExecInitExtraTupleSlot(estate, NULL,
+															&TTSOpsVirtual);
 
 	/* Prepare to catch AFTER triggers. */
 	AfterTriggerBeginQuery();
@@ -609,7 +610,8 @@ apply_handle_insert(StringInfo s)
 	/* Initialize the executor state. */
 	estate = create_estate_for_relation(rel);
 	remoteslot = ExecInitExtraTupleSlot(estate,
-										RelationGetDescr(rel->localrel));
+										RelationGetDescr(rel->localrel),
+										&TTSOpsHeapTuple);
 
 	/* Input functions may need an active snapshot, so get one */
 	PushActiveSnapshot(GetTransactionSnapshot());
@@ -715,9 +717,11 @@ apply_handle_update(StringInfo s)
 	/* Initialize the executor state. */
 	estate = create_estate_for_relation(rel);
 	remoteslot = ExecInitExtraTupleSlot(estate,
-										RelationGetDescr(rel->localrel));
+										RelationGetDescr(rel->localrel),
+										&TTSOpsHeapTuple);
 	localslot = ExecInitExtraTupleSlot(estate,
-									   RelationGetDescr(rel->localrel));
+									   RelationGetDescr(rel->localrel),
+									   &TTSOpsHeapTuple);
 	EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
 
 	PushActiveSnapshot(GetTransactionSnapshot());
@@ -756,7 +760,8 @@ apply_handle_update(StringInfo s)
 	{
 		/* Process and store remote tuple in the slot */
 		oldctx = MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
-		ExecStoreHeapTuple(localslot->tts_tuple, remoteslot, false);
+		ExecStoreHeapTuple(ExecFetchSlotHeapTuple(localslot, false, NULL), remoteslot,
+						   false);
 		slot_modify_cstrings(remoteslot, rel, newtup.values, newtup.changed);
 		MemoryContextSwitchTo(oldctx);
 
@@ -833,9 +838,11 @@ apply_handle_delete(StringInfo s)
 	/* Initialize the executor state. */
 	estate = create_estate_for_relation(rel);
 	remoteslot = ExecInitExtraTupleSlot(estate,
-										RelationGetDescr(rel->localrel));
+										RelationGetDescr(rel->localrel),
+										&TTSOpsVirtual);
 	localslot = ExecInitExtraTupleSlot(estate,
-									   RelationGetDescr(rel->localrel));
+									   RelationGetDescr(rel->localrel),
+									   &TTSOpsHeapTuple);
 	EvalPlanQualInit(&epqstate, estate, NULL, NIL, -1);
 
 	PushActiveSnapshot(GetTransactionSnapshot());
diff --git a/src/backend/replication/walsender.c b/src/backend/replication/walsender.c
index 2683385ca6e..39337d2f1f8 100644
--- a/src/backend/replication/walsender.c
+++ b/src/backend/replication/walsender.c
@@ -403,7 +403,7 @@ IdentifySystem(void)
 							  TEXTOID, -1, 0);
 
 	/* prepare for projection of tuples */
-	tstate = begin_tup_output_tupdesc(dest, tupdesc);
+	tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
 	/* column 1: system identifier */
 	values[0] = CStringGetTextDatum(sysid);
@@ -735,7 +735,7 @@ StartReplication(StartReplicationCmd *cmd)
 								  TEXTOID, -1, 0);
 
 		/* prepare for projection of tuple */
-		tstate = begin_tup_output_tupdesc(dest, tupdesc);
+		tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
 		values[0] = Int64GetDatum((int64) sendTimeLineNextTLI);
 		values[1] = CStringGetTextDatum(startpos_str);
@@ -1007,7 +1007,7 @@ CreateReplicationSlot(CreateReplicationSlotCmd *cmd)
 							  TEXTOID, -1, 0);
 
 	/* prepare for projection of tuples */
-	tstate = begin_tup_output_tupdesc(dest, tupdesc);
+	tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
 	/* slot_name */
 	slot_name = NameStr(MyReplicationSlot->data.name);
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 66cc5c35c68..b44438bf088 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -1071,7 +1071,7 @@ RunFromStore(Portal portal, ScanDirection direction, uint64 count,
 	uint64		current_tuple_count = 0;
 	TupleTableSlot *slot;
 
-	slot = MakeSingleTupleTableSlot(portal->tupDesc);
+	slot = MakeSingleTupleTableSlot(portal->tupDesc, &TTSOpsMinimalTuple);
 
 	dest->rStartup(dest, CMD_SELECT, portal->tupDesc);
 
diff --git a/src/backend/utils/adt/orderedsetaggs.c b/src/backend/utils/adt/orderedsetaggs.c
index be9422dcfb6..8871aed9045 100644
--- a/src/backend/utils/adt/orderedsetaggs.c
+++ b/src/backend/utils/adt/orderedsetaggs.c
@@ -239,7 +239,8 @@ ordered_set_startup(FunctionCallInfo fcinfo, bool use_tuples)
 			}
 
 			/* Create slot we'll use to store/retrieve rows */
-			qstate->tupslot = MakeSingleTupleTableSlot(qstate->tupdesc);
+			qstate->tupslot = MakeSingleTupleTableSlot(qstate->tupdesc,
+													   &TTSOpsMinimalTuple);
 		}
 		else
 		{
@@ -1375,7 +1376,8 @@ hypothetical_dense_rank_final(PG_FUNCTION_ARGS)
 	 * previous row available for comparisons.  This is accomplished by
 	 * swapping the slot pointer variables after each row.
 	 */
-	extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc);
+	extraslot = MakeSingleTupleTableSlot(osastate->qstate->tupdesc,
+										 &TTSOpsMinimalTuple);
 	slot2 = extraslot;
 
 	/* iterate till we find the hypothetical row */
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
index e0ece74bb92..dbbbcc979b4 100644
--- a/src/backend/utils/adt/selfuncs.c
+++ b/src/backend/utils/adt/selfuncs.c
@@ -5534,7 +5534,8 @@ get_actual_variable_range(PlannerInfo *root, VariableStatData *vardata,
 			indexInfo = BuildIndexInfo(indexRel);
 
 			/* some other stuff */
-			slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel));
+			slot = MakeSingleTupleTableSlot(RelationGetDescr(heapRel),
+											&TTSOpsHeapTuple);
 			econtext->ecxt_scantuple = slot;
 			get_typlenbyval(vardata->atttype, &typLen, &typByVal);
 			InitNonVacuumableSnapshot(SnapshotNonVacuumable, RecentGlobalXmin);
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 0327b295da8..f9074215a2d 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -8262,7 +8262,7 @@ ShowGUCConfigOption(const char *name, DestReceiver *dest)
 							  TEXTOID, -1, 0);
 
 	/* prepare for projection of tuples */
-	tstate = begin_tup_output_tupdesc(dest, tupdesc);
+	tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
 	/* Send it */
 	do_text_output_oneline(tstate, value);
@@ -8292,7 +8292,7 @@ ShowAllGUCConfig(DestReceiver *dest)
 							  TEXTOID, -1, 0);
 
 	/* prepare for projection of tuples */
-	tstate = begin_tup_output_tupdesc(dest, tupdesc);
+	tstate = begin_tup_output_tupdesc(dest, tupdesc, &TTSOpsVirtual);
 
 	for (i = 0; i < num_guc_variables; i++)
 	{
diff --git a/src/backend/utils/sort/tuplesort.c b/src/backend/utils/sort/tuplesort.c
index 5909404e1e5..ee7fd83c02c 100644
--- a/src/backend/utils/sort/tuplesort.c
+++ b/src/backend/utils/sort/tuplesort.c
@@ -933,7 +933,7 @@ tuplesort_begin_cluster(TupleDesc tupDesc,
 		 * scantuple has to point to that slot, too.
 		 */
 		state->estate = CreateExecutorState();
-		slot = MakeSingleTupleTableSlot(tupDesc);
+		slot = MakeSingleTupleTableSlot(tupDesc, &TTSOpsVirtual);
 		econtext = GetPerTupleExprContext(state->estate);
 		econtext->ecxt_scantuple = slot;
 	}
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 84412657845..4f156f4a5e7 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -430,13 +430,17 @@ extern void ExecScanReScan(ScanState *node);
  * prototypes from functions in execTuples.c
  */
 extern void ExecInitResultTypeTL(PlanState *planstate);
-extern void ExecInitResultSlot(PlanState *planstate);
-extern void ExecInitResultTupleSlotTL(PlanState *planstate);
-extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc);
+extern void ExecInitResultSlot(PlanState *planstate,
+							   const TupleTableSlotOps *tts_cb);
+extern void ExecInitResultTupleSlotTL(PlanState *planstate,
+									  const TupleTableSlotOps *tts_cb);
+extern void ExecInitScanTupleSlot(EState *estate, ScanState *scanstate, TupleDesc tupleDesc,
+								  const TupleTableSlotOps *tts_cb);
 extern TupleTableSlot *ExecInitExtraTupleSlot(EState *estate,
-					   TupleDesc tupleDesc);
-extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate,
-					  TupleDesc tupType);
+					   TupleDesc tupledesc,
+					   const TupleTableSlotOps *tts_cb);
+extern TupleTableSlot *ExecInitNullTupleSlot(EState *estate, TupleDesc tupType,
+					  const TupleTableSlotOps *tts_cb);
 extern TupleDesc ExecTypeFromTL(List *targetList, bool hasoid);
 extern TupleDesc ExecCleanTypeFromTL(List *targetList, bool hasoid);
 extern TupleDesc ExecTypeFromExprList(List *exprList);
@@ -450,7 +454,8 @@ typedef struct TupOutputState
 } TupOutputState;
 
 extern TupOutputState *begin_tup_output_tupdesc(DestReceiver *dest,
-						 TupleDesc tupdesc);
+						 TupleDesc tupdesc,
+						 const TupleTableSlotOps *tts_cb);
 extern void do_tup_output(TupOutputState *tstate, Datum *values, bool *isnull);
 extern void do_text_output_multiline(TupOutputState *tstate, const char *txt);
 extern void end_tup_output(TupOutputState *tstate);
@@ -504,13 +509,17 @@ extern ExprContext *MakePerTupleExprContext(EState *estate);
 
 extern void ExecAssignExprContext(EState *estate, PlanState *planstate);
 extern TupleDesc ExecGetResultType(PlanState *planstate);
+extern TupleTableSlot ExecGetResultSlot(PlanState *planstate);
+extern const TupleTableSlotOps *ExecGetResultSlotOps(PlanState *planstate, bool *isfixed);
 extern void ExecAssignProjectionInfo(PlanState *planstate,
 						 TupleDesc inputDesc);
 extern void ExecConditionalAssignProjectionInfo(PlanState *planstate,
 									TupleDesc inputDesc, Index varno);
 extern void ExecFreeExprContext(PlanState *planstate);
 extern void ExecAssignScanType(ScanState *scanstate, TupleDesc tupDesc);
-extern void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate);
+extern void ExecCreateScanSlotFromOuterPlan(EState *estate,
+								ScanState *scanstate,
+								const TupleTableSlotOps *tts_cb);
 
 extern bool ExecRelationIsTargetRelation(EState *estate, Index scanrelid);
 
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index 8bfa73c30ea..a6f6084f0a9 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -132,6 +132,9 @@
 #define			TTS_FLAG_FIXED		(1 << 5)
 #define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
 
+struct TupleTableSlotOps;
+typedef struct TupleTableSlotOps TupleTableSlotOps;
+
 typedef struct TupleTableSlot
 {
 	NodeTag		type;
@@ -141,20 +144,35 @@ typedef struct TupleTableSlot
 	AttrNumber	tts_nvalid;		/* # of valid values in tts_values */
 #define FIELDNO_TUPLETABLESLOT_TUPLE 3
 	HeapTuple	tts_tuple;		/* physical tuple, or NULL if virtual */
-#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
+	const TupleTableSlotOps *const tts_cb; /* implementation of slot */
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 5
 	TupleDesc	tts_tupleDescriptor;	/* slot's tuple descriptor */
 	MemoryContext tts_mcxt;		/* slot itself is in this context */
 	Buffer		tts_buffer;		/* tuple's buffer, or InvalidBuffer */
-#define FIELDNO_TUPLETABLESLOT_OFF 7
+#define FIELDNO_TUPLETABLESLOT_OFF 8
 	uint32		tts_off;		/* saved state for slot_deform_tuple */
-#define FIELDNO_TUPLETABLESLOT_VALUES 8
+#define FIELDNO_TUPLETABLESLOT_VALUES 9
 	Datum	   *tts_values;		/* current per-attribute values */
-#define FIELDNO_TUPLETABLESLOT_ISNULL 9
+#define FIELDNO_TUPLETABLESLOT_ISNULL 10
 	bool	   *tts_isnull;		/* current per-attribute isnull flags */
 	MinimalTuple tts_mintuple;	/* minimal tuple, or NULL if none */
 	HeapTupleData tts_minhdr;	/* workspace for minimal-tuple-only case */
 } TupleTableSlot;
 
+/* routines for a TupleTableSlot implementation */
+struct TupleTableSlotOps
+{
+};
+
+/*
+ * Predefined TupleTableSlotOps for various types of TupleTableSlotOps. The
+ * same are used to identify the type of a given slot.
+ */
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsVirtual;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
+extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferTuple;
+
 #define TTS_HAS_PHYSICAL_TUPLE(slot)  \
 	((slot)->tts_tuple != NULL && (slot)->tts_tuple != &((slot)->tts_minhdr))
 
@@ -165,10 +183,13 @@ typedef struct TupleTableSlot
 	((slot) == NULL || TTS_EMPTY(slot))
 
 /* in executor/execTuples.c */
-extern TupleTableSlot *MakeTupleTableSlot(TupleDesc desc);
-extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc);
+extern TupleTableSlot *MakeTupleTableSlot(TupleDesc tupleDesc,
+				   const TupleTableSlotOps *tts_cb);
+extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
+				   const TupleTableSlotOps *tts_cb);
 extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
-extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc);
+extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc,
+						 const TupleTableSlotOps *tts_cb);
 extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
 extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
 extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 18544566f70..d0e8cbddac4 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -977,6 +977,42 @@ typedef struct PlanState
 	 * descriptor, without encoding knowledge about all executor nodes.
 	 */
 	TupleDesc	scandesc;
+
+	/*
+	 * Define the slot types for right (inner), left (outer) and scanslots for
+	 * expression contexts with this state as a parent.  If *opsset is set,
+	 * then *opsfixed indicates whether *ops is guaranteed to be the type of
+	 * slot used. That means that every slot in the corresponding
+	 * ExprContext.ecxt_*tuple will point to a slot of that type, while
+	 * evaluating the expression.  If *opsfixed is false, but *ops is set,
+	 * that indicates the most likely type of slot.
+	 *
+	 * The scan* fields are set by ExecInitScanTupleSlot(). If that's not
+	 * called, nodes can initialize the fields themselves.
+	 *
+	 * If left/rightopsset is false, the information is inferred on-demand
+	 * using ExecGetResultSlotOps() on ->righttree/lefttree, using the
+	 * corresponding node's resultops* fields.
+	 *
+	 * The result* fields are automatically set when ExecInitResultSlot is
+	 * used (be it directly or when the slot is created by
+	 * ExecAssignScanProjectionInfo() /
+	 * ExecConditionalAssignProjectionInfo()).  If no projection is necessary
+	 * ExecConditionalAssignProjectionInfo() defaults those fields to the scan
+	 * operations.
+	 */
+	const TupleTableSlotOps *scanops;
+	const TupleTableSlotOps *leftops;
+	const TupleTableSlotOps *rightops;
+	const TupleTableSlotOps *resultops;
+	bool scanopsfixed;
+	bool leftopsfixed;
+	bool rightopsfixed;
+	bool resultopsfixed;
+	bool scanopsset;
+	bool leftopsset;
+	bool rightopsset;
+	bool resultopsset;
 } PlanState;
 
 /* ----------------
-- 
2.18.0.rc2.dirty

v14-0003-Use-separate-tuple-table-slot-to-return-tuples-f.patchtext/x-diff; charset=us-asciiDownload
From 2c90e8c6cf96c11caafd33c9dc5d9f20d6159ab4 Mon Sep 17 00:00:00 2001
From: Amit Khandekar <amit.khandekar@enterprisedb.com>
Date: Tue, 9 Oct 2018 20:26:48 +0530
Subject: [PATCH v14 3/7] Use separate tuple table slot to return tuples from
 reorder queue.

Index scan uses reorder queue in some cases. Tuples are stored reorder
queue as heap tuples without any associated buffer. While returning a
tuple from reorder queue, IndexNextWithReorder() should use
TupleTableSlot of type HeapTupleTableSlot. A tuple returned directly
from an index scan has a buffer associated with it, so should use
TupleTableSlot of type BufferHeapTupleTableSlot. So, use different
kinds of slots for an index scan.

Author: Ashutosh Bapat
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 src/backend/executor/nodeIndexscan.c | 18 ++++++++++++------
 src/include/nodes/execnodes.h        |  1 +
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 83038e31f66..bad2ce7ec56 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -208,8 +208,6 @@ IndexNextWithReorder(IndexScanState *node)
 
 	scandesc = node->iss_ScanDesc;
 	econtext = node->ss.ps.ps_ExprContext;
-	slot = node->ss.ss_ScanTupleSlot;
-
 	if (scandesc == NULL)
 	{
 		/*
@@ -245,6 +243,7 @@ IndexNextWithReorder(IndexScanState *node)
 		 */
 		if (!pairingheap_is_empty(node->iss_ReorderQueue))
 		{
+			slot = node->iss_ReorderQueueSlot;
 			topmost = (ReorderTuple *) pairingheap_first(node->iss_ReorderQueue);
 
 			if (node->iss_ReachedEnd ||
@@ -264,13 +263,15 @@ IndexNextWithReorder(IndexScanState *node)
 		else if (node->iss_ReachedEnd)
 		{
 			/* Queue is empty, and no more tuples from index.  We're done. */
-			return ExecClearTuple(slot);
+			ExecClearTuple(node->iss_ReorderQueueSlot);
+			return ExecClearTuple(node->ss.ss_ScanTupleSlot);
 		}
 
 		/*
 		 * Fetch next tuple from the index.
 		 */
 next_indextuple:
+		slot = node->ss.ss_ScanTupleSlot;
 		tuple = index_getnext(scandesc, ForwardScanDirection);
 		if (!tuple)
 		{
@@ -372,7 +373,8 @@ next_indextuple:
 	 * if we get here it means the index scan failed so we are at the end of
 	 * the scan..
 	 */
-	return ExecClearTuple(slot);
+	ExecClearTuple(node->iss_ReorderQueueSlot);
+	return ExecClearTuple(node->ss.ss_ScanTupleSlot);
 }
 
 /*
@@ -946,7 +948,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 	 */
 	ExecInitScanTupleSlot(estate, &indexstate->ss,
 						  RelationGetDescr(currentRelation),
-						  &TTSOpsBufferTuple); /* FIXME: wrong for reorder case */
+						  &TTSOpsBufferTuple);
 
 	/*
 	 * Initialize result type and projection.
@@ -1077,9 +1079,13 @@ ExecInitIndexScan(IndexScan *node, EState *estate, int eflags)
 		indexstate->iss_OrderByNulls = (bool *)
 			palloc(numOrderByKeys * sizeof(bool));
 
-		/* and initialize the reorder queue */
+		/* and initialize the reorder queue and the corresponding slot */
 		indexstate->iss_ReorderQueue = pairingheap_allocate(reorderqueue_cmp,
 															indexstate);
+		indexstate->iss_ReorderQueueSlot =
+			ExecAllocTableSlot(&estate->es_tupleTable,
+							   RelationGetDescr(currentRelation),
+							   &TTSOpsHeapTuple);
 	}
 
 	/*
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index d0e8cbddac4..59fb3c15833 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1365,6 +1365,7 @@ typedef struct IndexScanState
 	bool	   *iss_OrderByTypByVals;
 	int16	   *iss_OrderByTypLens;
 	Size		iss_PscanLen;
+	TupleTableSlot *iss_ReorderQueueSlot;
 } IndexScanState;
 
 /* ----------------
-- 
2.18.0.rc2.dirty

v14-0004-Compute-information-about-EEOP_-_FETCHSOME-at-ex.patchtext/x-diff; charset=us-asciiDownload
From 232fbef9fe528e4128e3f217dcc8494de89f484f Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 13 Nov 2018 12:09:42 -0800
Subject: [PATCH v14 4/7] Compute information about EEOP_*_FETCHSOME at
 expression init time.

Previously this information was computed when JIT compiling an
expression.  But the information is useful for assertions in the
non-JIT case too (for assertions), therefore it makes sense to move
it.

This will, in a followup commit, allow to treat different slot types
differently. E.g. for virtual slots there's no need to generate a JIT
function to deform the slot.

Author: Andres Freund
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 src/backend/executor/execExpr.c     | 104 ++++++++++++++++++++++++++++
 src/backend/jit/llvm/llvmjit_expr.c |  44 ++++--------
 src/include/executor/execExpr.h     |   5 ++
 3 files changed, 124 insertions(+), 29 deletions(-)

diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 82b5a0b404a..a4099c23176 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -65,6 +65,7 @@ static void ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args,
 static void ExecInitExprSlots(ExprState *state, Node *node);
 static void ExecPushExprSlots(ExprState *state, LastAttnumInfo *info);
 static bool get_last_attnums_walker(Node *node, LastAttnumInfo *info);
+static void ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op);
 static void ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable,
 					ExprState *state);
 static void ExecInitArrayRef(ExprEvalStep *scratch, ArrayRef *aref,
@@ -2288,21 +2289,30 @@ ExecPushExprSlots(ExprState *state, LastAttnumInfo *info)
 	{
 		scratch.opcode = EEOP_INNER_FETCHSOME;
 		scratch.d.fetch.last_var = info->last_inner;
+		scratch.d.fetch.fixed = false;
+		scratch.d.fetch.kind = NULL;
 		scratch.d.fetch.known_desc = NULL;
+		ExecComputeSlotInfo(state, &scratch);
 		ExprEvalPushStep(state, &scratch);
 	}
 	if (info->last_outer > 0)
 	{
 		scratch.opcode = EEOP_OUTER_FETCHSOME;
 		scratch.d.fetch.last_var = info->last_outer;
+		scratch.d.fetch.fixed = false;
+		scratch.d.fetch.kind = NULL;
 		scratch.d.fetch.known_desc = NULL;
+		ExecComputeSlotInfo(state, &scratch);
 		ExprEvalPushStep(state, &scratch);
 	}
 	if (info->last_scan > 0)
 	{
 		scratch.opcode = EEOP_SCAN_FETCHSOME;
 		scratch.d.fetch.last_var = info->last_scan;
+		scratch.d.fetch.fixed = false;
+		scratch.d.fetch.kind = NULL;
 		scratch.d.fetch.known_desc = NULL;
+		ExecComputeSlotInfo(state, &scratch);
 		ExprEvalPushStep(state, &scratch);
 	}
 }
@@ -2355,6 +2365,94 @@ get_last_attnums_walker(Node *node, LastAttnumInfo *info)
 								  (void *) info);
 }
 
+/*
+ * Compute additional information for EEOP_*_FETCHSOME ops.
+ *
+ * The goal is to determine whether a slot is 'fixed', that is, every
+ * evaluation of the the expression will have the same type of slot, with an
+ * equivalent descriptor.
+ */
+static void
+ExecComputeSlotInfo(ExprState *state, ExprEvalStep *op)
+{
+	PlanState *parent = state->parent;
+	TupleDesc	desc = NULL;
+	const TupleTableSlotOps *tts_cb = NULL;
+	bool isfixed = false;
+
+	if (op->d.fetch.known_desc != NULL)
+	{
+		desc = op->d.fetch.known_desc;
+		tts_cb = op->d.fetch.kind;
+		isfixed = op->d.fetch.kind != NULL;
+	}
+	else if (!parent)
+	{
+		isfixed = false;
+	}
+	else if (op->opcode == EEOP_INNER_FETCHSOME)
+	{
+		PlanState  *is = innerPlanState(parent);
+
+		if (parent->rightopsset && !parent->rightopsfixed)
+		{
+			isfixed = false;
+		}
+		else if (parent->rightopsset && parent->rightops)
+		{
+			isfixed = true;
+			tts_cb = parent->rightops;
+		}
+		else if (is)
+		{
+			tts_cb = ExecGetResultSlotOps(is, &isfixed);
+			desc = ExecGetResultType(is);
+		}
+	}
+	else if (op->opcode == EEOP_OUTER_FETCHSOME)
+	{
+		PlanState  *os = outerPlanState(parent);
+
+		if (parent->leftopsset && !parent->leftopsfixed)
+		{
+			isfixed = false;
+		}
+		else if (parent->leftopsset && parent->leftops)
+		{
+			isfixed = true;
+			tts_cb = parent->leftops;
+		}
+		else if (os)
+		{
+			tts_cb = ExecGetResultSlotOps(os, &isfixed);
+			desc = ExecGetResultType(os);
+		}
+	}
+	else if (op->opcode == EEOP_SCAN_FETCHSOME)
+	{
+		desc = parent->scandesc;
+
+		if (parent && parent->scanops)
+			tts_cb = parent->scanops;
+
+		if (parent->scanopsset)
+			isfixed = parent->scanopsfixed;
+	}
+
+	if (isfixed && desc != NULL && tts_cb != NULL)
+	{
+		op->d.fetch.fixed = true;
+		op->d.fetch.kind = tts_cb;
+		op->d.fetch.known_desc = desc;
+	}
+	else
+	{
+		op->d.fetch.fixed = false;
+		op->d.fetch.kind = NULL;
+		op->d.fetch.known_desc = NULL;
+	}
+}
+
 /*
  * Prepare step for the evaluation of a whole-row variable.
  * The caller still has to push the step.
@@ -3254,12 +3352,18 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 	/* push deform steps */
 	scratch.opcode = EEOP_INNER_FETCHSOME;
 	scratch.d.fetch.last_var = maxatt;
+	scratch.d.fetch.fixed = false;
 	scratch.d.fetch.known_desc = ldesc;
+	scratch.d.fetch.kind = NULL;
+	ExecComputeSlotInfo(state, &scratch);
 	ExprEvalPushStep(state, &scratch);
 
 	scratch.opcode = EEOP_OUTER_FETCHSOME;
 	scratch.d.fetch.last_var = maxatt;
+	scratch.d.fetch.fixed = false;
 	scratch.d.fetch.known_desc = rdesc;
+	scratch.d.fetch.kind = NULL;
+	ExecComputeSlotInfo(state, &scratch);
 	ExprEvalPushStep(state, &scratch);
 
 	/*
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 0dbc1e41062..63b921517c6 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -276,6 +276,8 @@ llvm_compile_expr(ExprState *state)
 					LLVMValueRef v_slot;
 					LLVMBasicBlockRef b_fetch;
 					LLVMValueRef v_nvalid;
+					LLVMValueRef l_jit_deform = NULL;
+					const TupleTableSlotOps *tts_cb = NULL;
 
 					b_fetch = l_bb_before_v(opblocks[i + 1],
 											"op.%d.fetch", i);
@@ -283,40 +285,22 @@ llvm_compile_expr(ExprState *state)
 					if (op->d.fetch.known_desc)
 						desc = op->d.fetch.known_desc;
 
+					if (op->d.fetch.fixed)
+						tts_cb = op->d.fetch.kind;
+
 					if (opcode == EEOP_INNER_FETCHSOME)
-					{
-						PlanState  *is = innerPlanState(parent);
-
 						v_slot = v_innerslot;
-
-						if (!desc &&
-							is &&
-							is->ps_ResultTupleSlot &&
-							TTS_FIXED(is->ps_ResultTupleSlot))
-							desc = is->ps_ResultTupleSlot->tts_tupleDescriptor;
-					}
 					else if (opcode == EEOP_OUTER_FETCHSOME)
-					{
-						PlanState  *os = outerPlanState(parent);
-
 						v_slot = v_outerslot;
-
-						if (!desc &&
-							os &&
-							os->ps_ResultTupleSlot &&
-							TTS_FIXED(os->ps_ResultTupleSlot))
-							desc = os->ps_ResultTupleSlot->tts_tupleDescriptor;
-					}
 					else
-					{
 						v_slot = v_scanslot;
-						if (!desc && parent)
-							desc = parent->scandesc;
-					}
 
 					/*
 					 * Check if all required attributes are available, or
 					 * whether deforming is required.
+					 *
+					 * TODO: skip nvalid check if slot is fixed and known to
+					 * be a virtual slot.
 					 */
 					v_nvalid =
 						l_load_struct_gep(b, v_slot,
@@ -336,19 +320,21 @@ llvm_compile_expr(ExprState *state)
 					 * function specific to tupledesc and the exact number of
 					 * to-be-extracted attributes.
 					 */
-					if (desc && (context->base.flags & PGJIT_DEFORM))
+					if (tts_cb && desc && (context->base.flags & PGJIT_DEFORM))
 					{
-						LLVMValueRef params[1];
-						LLVMValueRef l_jit_deform;
-
 						l_jit_deform =
 							slot_compile_deform(context, desc,
 												op->d.fetch.last_var);
+					}
+
+					if (l_jit_deform)
+					{
+						LLVMValueRef params[1];
+
 						params[0] = v_slot;
 
 						LLVMBuildCall(b, l_jit_deform,
 									  params, lengthof(params), "");
-
 					}
 					else
 					{
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index ac53935d700..194bf46e0f5 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -262,7 +262,12 @@ typedef struct ExprEvalStep
 		{
 			/* attribute number up to which to fetch (inclusive) */
 			int			last_var;
+			/* will the type of slot be the same for every invocation */
+			bool		fixed;
+			/* tuple descriptor, if known */
 			TupleDesc	known_desc;
+			/* type of slot, can only be relied upon if fixed is set */
+			const TupleTableSlotOps *kind;
 		}			fetch;
 
 		/* for EEOP_INNER/OUTER/SCAN_[SYS]VAR[_FIRST] */
-- 
2.18.0.rc2.dirty

v14-0005-Verify-that-expected-slot-types-match-returned-s.patchtext/x-diff; charset=us-asciiDownload
From e50ed0d5cbf12511fb51fac52cfce054d0689fd4 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 13 Nov 2018 12:13:20 -0800
Subject: [PATCH v14 5/7] Verify that expected slot types match returned slot
 types.

This is important so JIT compilation knows what kind of tuple slot the
deforming routine can expect. There's also optimization potential for
expression initialization without JIT compilation. It e.g. seems
plausible to elide EEOP_*_FETCHSOME ops entirely when dealing with
virtual slots.

Author: Andres Freund
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 src/backend/executor/execExprInterp.c | 52 +++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index f7eac2a5723..357eae41cc3 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -143,6 +143,7 @@ static void ExecInitInterpreter(void);
 
 /* support functions */
 static void CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype);
+static void CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot);
 static TupleDesc get_cached_rowtype(Oid type_id, int32 typmod,
 				   TupleDesc *cache_field, ExprContext *econtext);
 static void ShutdownTupleDescRef(Datum arg);
@@ -425,6 +426,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 		EEO_CASE(EEOP_INNER_FETCHSOME)
 		{
+			CheckOpSlotCompatibility(op, innerslot);
+
 			/* XXX: worthwhile to check tts_nvalid inline first? */
 			slot_getsomeattrs(innerslot, op->d.fetch.last_var);
 
@@ -433,6 +436,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 		EEO_CASE(EEOP_OUTER_FETCHSOME)
 		{
+			CheckOpSlotCompatibility(op, outerslot);
+
 			slot_getsomeattrs(outerslot, op->d.fetch.last_var);
 
 			EEO_NEXT();
@@ -440,6 +445,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 		EEO_CASE(EEOP_SCAN_FETCHSOME)
 		{
+			CheckOpSlotCompatibility(op, scanslot);
+
 			slot_getsomeattrs(scanslot, op->d.fetch.last_var);
 
 			EEO_NEXT();
@@ -1854,6 +1861,39 @@ CheckVarSlotCompatibility(TupleTableSlot *slot, int attnum, Oid vartype)
 	}
 }
 
+/*
+ * Verify that the slot is compatible with a EEOP_*_FETCHSOME operation.
+ */
+static void
+CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot)
+{
+#ifdef USE_ASSERT_CHECKING
+	/* there's nothing to check */
+	if (!op->d.fetch.fixed)
+		return;
+
+	/*
+	 * Should probably fixed at some point, but for now it's easier to allow
+	 * buffer and heap tuples to be used interchangably.
+	 */
+	if (slot->tts_cb == &TTSOpsBufferTuple &&
+		op->d.fetch.kind == &TTSOpsHeapTuple)
+		return;
+	if (slot->tts_cb == &TTSOpsHeapTuple &&
+		op->d.fetch.kind == &TTSOpsBufferTuple)
+		return;
+
+	/*
+	 * At the moment we consider it OK if a virtual slot is used instead of a
+	 * specific type of slot, as a virtual slot never needs to be deformed.
+	 */
+	if (slot->tts_cb == &TTSOpsVirtual)
+		return;
+
+	Assert(op->d.fetch.kind == slot->tts_cb);
+#endif
+}
+
 /*
  * get_cached_rowtype: utility function to lookup a rowtype tupdesc
  *
@@ -1921,6 +1961,8 @@ ExecJustInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	int			attnum = op->d.var.attnum + 1;
 	TupleTableSlot *slot = econtext->ecxt_innertuple;
 
+	CheckOpSlotCompatibility(&state->steps[0], slot);
+
 	/*
 	 * Since we use slot_getattr(), we don't need to implement the FETCHSOME
 	 * step explicitly, and we also needn't Assert that the attnum is in range
@@ -1937,6 +1979,8 @@ ExecJustOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	int			attnum = op->d.var.attnum + 1;
 	TupleTableSlot *slot = econtext->ecxt_outertuple;
 
+	CheckOpSlotCompatibility(&state->steps[0], slot);
+
 	/* See comments in ExecJustInnerVar */
 	return slot_getattr(slot, attnum, isnull);
 }
@@ -1949,6 +1993,8 @@ ExecJustScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	int			attnum = op->d.var.attnum + 1;
 	TupleTableSlot *slot = econtext->ecxt_scantuple;
 
+	CheckOpSlotCompatibility(&state->steps[0], slot);
+
 	/* See comments in ExecJustInnerVar */
 	return slot_getattr(slot, attnum, isnull);
 }
@@ -1973,6 +2019,8 @@ ExecJustAssignInnerVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	TupleTableSlot *inslot = econtext->ecxt_innertuple;
 	TupleTableSlot *outslot = state->resultslot;
 
+	CheckOpSlotCompatibility(&state->steps[0], inslot);
+
 	/*
 	 * We do not need CheckVarSlotCompatibility here; that was taken care of
 	 * at compilation time.
@@ -1996,6 +2044,8 @@ ExecJustAssignOuterVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	TupleTableSlot *inslot = econtext->ecxt_outertuple;
 	TupleTableSlot *outslot = state->resultslot;
 
+	CheckOpSlotCompatibility(&state->steps[0], inslot);
+
 	/* See comments in ExecJustAssignInnerVar */
 	outslot->tts_values[resultnum] =
 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
@@ -2012,6 +2062,8 @@ ExecJustAssignScanVar(ExprState *state, ExprContext *econtext, bool *isnull)
 	TupleTableSlot *inslot = econtext->ecxt_scantuple;
 	TupleTableSlot *outslot = state->resultslot;
 
+	CheckOpSlotCompatibility(&state->steps[0], inslot);
+
 	/* See comments in ExecJustAssignInnerVar */
 	outslot->tts_values[resultnum] =
 		slot_getattr(inslot, attnum, &outslot->tts_isnull[resultnum]);
-- 
2.18.0.rc2.dirty

v14-0006-Restructure-TupleTableSlot-to-allow-tuples-other.patchtext/x-diff; charset=us-asciiDownload
From 964fbae8acdea781a6fa299f7a6661a26bd509ee Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 13 Nov 2018 12:58:25 -0800
Subject: [PATCH v14 6/7] Restructure TupleTableSlot to allow tuples other than
 HeapTuple

Author: Andres Freund and  Ashutosh Bapat, with changes by Amit Khandekar
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 src/backend/access/common/heaptuple.c  |  184 +--
 src/backend/catalog/index.c            |    4 +-
 src/backend/executor/execCurrent.c     |   18 +-
 src/backend/executor/execExpr.c        |    5 +-
 src/backend/executor/execExprInterp.c  |   13 +-
 src/backend/executor/execGrouping.c    |    5 +-
 src/backend/executor/execReplication.c |   41 +-
 src/backend/executor/execScan.c        |    4 +-
 src/backend/executor/execTuples.c      | 1665 ++++++++++++++++--------
 src/backend/executor/nodeAgg.c         |    5 +-
 src/backend/executor/nodeHashjoin.c    |   17 +-
 src/backend/executor/nodeModifyTable.c |   13 +
 src/backend/executor/nodeSubplan.c     |    1 +
 src/backend/jit/llvm/llvmjit.c         |    8 +-
 src/backend/jit/llvm/llvmjit_deform.c  |   52 +-
 src/backend/jit/llvm/llvmjit_expr.c    |    3 +-
 src/backend/jit/llvm/llvmjit_types.c   |    4 +-
 src/include/access/htup_details.h      |    2 -
 src/include/executor/executor.h        |    1 +
 src/include/executor/tuptable.h        |  305 ++++-
 src/include/jit/llvmjit.h              |    7 +-
 src/include/nodes/execnodes.h          |    1 +
 22 files changed, 1562 insertions(+), 796 deletions(-)

diff --git a/src/backend/access/common/heaptuple.c b/src/backend/access/common/heaptuple.c
index 28127b311f5..ccb69bdd616 100644
--- a/src/backend/access/common/heaptuple.c
+++ b/src/backend/access/common/heaptuple.c
@@ -71,6 +71,8 @@
 #define VARLENA_ATT_IS_PACKABLE(att) \
 	((att)->attstorage != 'p')
 
+static Datum getmissingattr(TupleDesc tupleDesc, int attnum, bool *isnull);
+
 
 /* ----------------------------------------------------------------
  *						misc support routines
@@ -80,7 +82,7 @@
 /*
  * Return the missing value of an attribute, or NULL if there isn't one.
  */
-Datum
+static Datum
 getmissingattr(TupleDesc tupleDesc,
 			   int attnum, bool *isnull)
 {
@@ -1350,186 +1352,6 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
 		values[attnum] = getmissingattr(tupleDesc, attnum + 1, &isnull[attnum]);
 }
 
-/*
- * slot_deform_tuple
- *		Given a TupleTableSlot, extract data from the slot's physical tuple
- *		into its Datum/isnull arrays.  Data is extracted up through the
- *		natts'th column (caller must ensure this is a legal column number).
- *
- *		This is essentially an incremental version of heap_deform_tuple:
- *		on each call we extract attributes up to the one needed, without
- *		re-computing information about previously extracted attributes.
- *		slot->tts_nvalid is the number of attributes already extracted.
- */
-void
-slot_deform_tuple(TupleTableSlot *slot, int natts)
-{
-	HeapTuple	tuple = slot->tts_tuple;
-	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
-	Datum	   *values = slot->tts_values;
-	bool	   *isnull = slot->tts_isnull;
-	HeapTupleHeader tup = tuple->t_data;
-	bool		hasnulls = HeapTupleHasNulls(tuple);
-	int			attnum;
-	char	   *tp;				/* ptr to tuple data */
-	uint32		off;			/* offset in tuple data */
-	bits8	   *bp = tup->t_bits;	/* ptr to null bitmap in tuple */
-	bool		slow;			/* can we use/set attcacheoff? */
-
-	/*
-	 * Check whether the first call for this tuple, and initialize or restore
-	 * loop state.
-	 */
-	attnum = slot->tts_nvalid;
-	if (attnum == 0)
-	{
-		/* Start from the first attribute */
-		off = 0;
-		slow = false;
-	}
-	else
-	{
-		/* Restore state from previous execution */
-		off = slot->tts_off;
-		slow = TTS_SLOW(slot);
-	}
-
-	tp = (char *) tup + tup->t_hoff;
-
-	for (; attnum < natts; attnum++)
-	{
-		Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
-
-		if (hasnulls && att_isnull(attnum, bp))
-		{
-			values[attnum] = (Datum) 0;
-			isnull[attnum] = true;
-			slow = true;		/* can't use attcacheoff anymore */
-			continue;
-		}
-
-		isnull[attnum] = false;
-
-		if (!slow && thisatt->attcacheoff >= 0)
-			off = thisatt->attcacheoff;
-		else if (thisatt->attlen == -1)
-		{
-			/*
-			 * We can only cache the offset for a varlena attribute if the
-			 * offset is already suitably aligned, so that there would be no
-			 * pad bytes in any case: then the offset will be valid for either
-			 * an aligned or unaligned value.
-			 */
-			if (!slow &&
-				off == att_align_nominal(off, thisatt->attalign))
-				thisatt->attcacheoff = off;
-			else
-			{
-				off = att_align_pointer(off, thisatt->attalign, -1,
-										tp + off);
-				slow = true;
-			}
-		}
-		else
-		{
-			/* not varlena, so safe to use att_align_nominal */
-			off = att_align_nominal(off, thisatt->attalign);
-
-			if (!slow)
-				thisatt->attcacheoff = off;
-		}
-
-		values[attnum] = fetchatt(thisatt, tp + off);
-
-		off = att_addlength_pointer(off, thisatt->attlen, tp + off);
-
-		if (thisatt->attlen <= 0)
-			slow = true;		/* can't use attcacheoff anymore */
-	}
-
-	/*
-	 * Save state for next execution
-	 */
-	slot->tts_nvalid = attnum;
-	slot->tts_off = off;
-	if (slow)
-		slot->tts_flags |= TTS_FLAG_SLOW;
-	else
-		slot->tts_flags &= ~TTS_FLAG_SLOW;
-}
-
-/*
- * slot_attisnull
- *		Detect whether an attribute of the slot is null, without
- *		actually fetching it.
- */
-bool
-slot_attisnull(TupleTableSlot *slot, int attnum)
-{
-	HeapTuple	tuple = slot->tts_tuple;
-	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
-
-	/*
-	 * system attributes are handled by heap_attisnull
-	 */
-	if (attnum <= 0)
-	{
-		if (tuple == NULL)		/* internal error */
-			elog(ERROR, "cannot extract system attribute from virtual tuple");
-		if (tuple == &(slot->tts_minhdr))	/* internal error */
-			elog(ERROR, "cannot extract system attribute from minimal tuple");
-		return heap_attisnull(tuple, attnum, tupleDesc);
-	}
-
-	/*
-	 * fast path if desired attribute already cached
-	 */
-	if (attnum <= slot->tts_nvalid)
-		return slot->tts_isnull[attnum - 1];
-
-	/*
-	 * return NULL if attnum is out of range according to the tupdesc
-	 */
-	if (attnum > tupleDesc->natts)
-		return true;
-
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
-
-	/* and let the tuple tell it */
-	return heap_attisnull(tuple, attnum, tupleDesc);
-}
-
-/*
- * slot_getsysattr
- *		This function fetches a system attribute of the slot's current tuple.
- *		Unlike slot_getattr, if the slot does not contain system attributes,
- *		this will return false (with a NULL attribute value) instead of
- *		throwing an error.
- */
-bool
-slot_getsysattr(TupleTableSlot *slot, int attnum,
-				Datum *value, bool *isnull)
-{
-	HeapTuple	tuple = slot->tts_tuple;
-
-	Assert(attnum < 0);			/* else caller error */
-	if (tuple == NULL ||
-		tuple == &(slot->tts_minhdr))
-	{
-		/* No physical tuple, or minimal tuple, so fail */
-		*value = (Datum) 0;
-		*isnull = true;
-		return false;
-	}
-	*value = heap_getsysattr(tuple, attnum, slot->tts_tupleDescriptor, isnull);
-	return true;
-}
-
 /*
  * heap_freetuple
  */
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 21bdf794da6..a980202a7b1 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2041,7 +2041,9 @@ FormIndexDatum(IndexInfo *indexInfo,
 		Datum		iDatum;
 		bool		isNull;
 
-		if (keycol != 0)
+		if (keycol < 0)
+			iDatum = slot_getsysattr(slot, keycol, &isNull);
+		else if (keycol != 0)
 		{
 			/*
 			 * Plain index column; get the value we need directly from the
diff --git a/src/backend/executor/execCurrent.c b/src/backend/executor/execCurrent.c
index aadf7493827..39c462a4e59 100644
--- a/src/backend/executor/execCurrent.c
+++ b/src/backend/executor/execCurrent.c
@@ -218,27 +218,25 @@ execCurrentOf(CurrentOfExpr *cexpr,
 			ItemPointer tuple_tid;
 
 #ifdef USE_ASSERT_CHECKING
-			if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
-								 TableOidAttributeNumber,
-								 &ldatum,
-								 &lisnull))
+			ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
+									 TableOidAttributeNumber,
+									 &lisnull);
+			if (lisnull)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_CURSOR_STATE),
 						 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
 								cursor_name, table_name)));
-			Assert(!lisnull);
 			Assert(DatumGetObjectId(ldatum) == table_oid);
 #endif
 
-			if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
-								 SelfItemPointerAttributeNumber,
-								 &ldatum,
-								 &lisnull))
+			ldatum = slot_getsysattr(scanstate->ss_ScanTupleSlot,
+									 SelfItemPointerAttributeNumber,
+									 &lisnull);
+			if (lisnull)
 				ereport(ERROR,
 						(errcode(ERRCODE_INVALID_CURSOR_STATE),
 						 errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
 								cursor_name, table_name)));
-			Assert(!lisnull);
 			tuple_tid = (ItemPointer) DatumGetPointer(ldatum);
 
 			*current_tid = *tuple_tid;
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index a4099c23176..914d04186bd 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -3313,6 +3313,7 @@ ExecBuildAggTransCall(ExprState *state, AggState *aggstate,
  */
 ExprState *
 ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
+					   const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
 					   int numCols,
 					   AttrNumber *keyColIdx,
 					   Oid *eqfunctions,
@@ -3354,7 +3355,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 	scratch.d.fetch.last_var = maxatt;
 	scratch.d.fetch.fixed = false;
 	scratch.d.fetch.known_desc = ldesc;
-	scratch.d.fetch.kind = NULL;
+	scratch.d.fetch.kind = lops;
 	ExecComputeSlotInfo(state, &scratch);
 	ExprEvalPushStep(state, &scratch);
 
@@ -3362,7 +3363,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 	scratch.d.fetch.last_var = maxatt;
 	scratch.d.fetch.fixed = false;
 	scratch.d.fetch.known_desc = rdesc;
-	scratch.d.fetch.kind = NULL;
+	scratch.d.fetch.kind = rops;
 	ExecComputeSlotInfo(state, &scratch);
 	ExprEvalPushStep(state, &scratch);
 
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 357eae41cc3..dbf2445a21d 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -428,7 +428,6 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		{
 			CheckOpSlotCompatibility(op, innerslot);
 
-			/* XXX: worthwhile to check tts_nvalid inline first? */
 			slot_getsomeattrs(innerslot, op->d.fetch.last_var);
 
 			EEO_NEXT();
@@ -4026,15 +4025,15 @@ void
 ExecEvalSysVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext,
 			   TupleTableSlot *slot)
 {
-	bool success;
+	Datum d;
 
 	/* slot_getsysattr has sufficient defenses against bad attnums */
-	success = slot_getsysattr(slot,
-							  op->d.var.attnum,
-							  op->resvalue,
-							  op->resnull);
+	d = slot_getsysattr(slot,
+						op->d.var.attnum,
+						op->resnull);
+	*op->resvalue = d;
 	/* this ought to be unreachable, but it's cheap enough to check */
-	if (unlikely(!success))
+	if (unlikely(*op->resnull))
 		elog(ERROR, "failed to fetch attribute from slot");
 }
 
diff --git a/src/backend/executor/execGrouping.c b/src/backend/executor/execGrouping.c
index 5bc200e4dc3..abce1e95cb6 100644
--- a/src/backend/executor/execGrouping.c
+++ b/src/backend/executor/execGrouping.c
@@ -75,7 +75,8 @@ execTuplesMatchPrepare(TupleDesc desc,
 		eqFunctions[i] = get_opcode(eqOperators[i]);
 
 	/* build actual expression */
-	expr = ExecBuildGroupingEqual(desc, desc, numCols, keyColIdx, eqFunctions,
+	expr = ExecBuildGroupingEqual(desc, desc, NULL, NULL,
+								  numCols, keyColIdx, eqFunctions,
 								  parent);
 
 	return expr;
@@ -206,7 +207,9 @@ BuildTupleHashTable(PlanState *parent,
 													&TTSOpsMinimalTuple);
 
 	/* build comparator for all columns */
+	/* XXX: should we support non-minimal tuples for the inputslot? */
 	hashtable->tab_eq_func = ExecBuildGroupingEqual(inputDesc, inputDesc,
+													&TTSOpsMinimalTuple, &TTSOpsMinimalTuple,
 													numCols,
 													keyColIdx, eqfuncoids,
 													parent);
diff --git a/src/backend/executor/execReplication.c b/src/backend/executor/execReplication.c
index 071ba8762d4..727770eab56 100644
--- a/src/backend/executor/execReplication.c
+++ b/src/backend/executor/execReplication.c
@@ -170,8 +170,11 @@ retry:
 		HeapUpdateFailureData hufd;
 		HTSU_Result res;
 		HeapTupleData locktup;
+		HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)outslot;
 
-		ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+		/* Only a heap tuple has item pointers. */
+		Assert(TTS_IS_HEAPTUPLE(outslot) || TTS_IS_BUFFERTUPLE(outslot));
+		ItemPointerCopy(&hslot->tuple->t_self, &locktup.t_self);
 
 		PushActiveSnapshot(GetLatestSnapshot());
 
@@ -334,8 +337,12 @@ retry:
 		HeapUpdateFailureData hufd;
 		HTSU_Result res;
 		HeapTupleData locktup;
+		HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)outslot;
 
-		ItemPointerCopy(&outslot->tts_tuple->t_self, &locktup.t_self);
+		/* Only a heap tuple has item pointers. */
+		Assert(TTS_IS_HEAPTUPLE(outslot) || TTS_IS_BUFFERTUPLE(outslot));
+
+		ItemPointerCopy(&hslot->tuple->t_self, &locktup.t_self);
 
 		PushActiveSnapshot(GetLatestSnapshot());
 
@@ -456,6 +463,12 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 	HeapTuple	tuple;
 	ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
 	Relation	rel = resultRelInfo->ri_RelationDesc;
+	HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot;
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *)slot;
+
+	/* We expect both searchslot and the slot to contain a heap tuple. */
+	Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot));
+	Assert(TTS_IS_HEAPTUPLE(slot) || TTS_IS_BUFFERTUPLE(slot));
 
 	/* For now we support only tables. */
 	Assert(rel->rd_rel->relkind == RELKIND_RELATION);
@@ -467,8 +480,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 		resultRelInfo->ri_TrigDesc->trig_update_before_row)
 	{
 		slot = ExecBRUpdateTriggers(estate, epqstate, resultRelInfo,
-									&searchslot->tts_tuple->t_self,
-									NULL, slot);
+									&hsearchslot->tuple->t_self, NULL, slot);
 
 		if (slot == NULL)		/* "do nothing" */
 			skip_tuple = true;
@@ -488,19 +500,18 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
 		tuple = ExecFetchSlotHeapTuple(slot, true, NULL);
 
 		/* OK, update the tuple and index entries for it */
-		simple_heap_update(rel, &searchslot->tts_tuple->t_self,
-						   slot->tts_tuple);
+		simple_heap_update(rel, &hsearchslot->tuple->t_self, hslot->tuple);
 
 		if (resultRelInfo->ri_NumIndices > 0 &&
-			!HeapTupleIsHeapOnly(slot->tts_tuple))
+			!HeapTupleIsHeapOnly(hslot->tuple))
 			recheckIndexes = ExecInsertIndexTuples(slot, &(tuple->t_self),
 												   estate, false, NULL,
 												   NIL);
 
 		/* AFTER ROW UPDATE Triggers */
 		ExecARUpdateTriggers(estate, resultRelInfo,
-							 &searchslot->tts_tuple->t_self,
-							 NULL, tuple, recheckIndexes, NULL);
+							 &hsearchslot->tuple->t_self, NULL, tuple,
+							 recheckIndexes, NULL);
 
 		list_free(recheckIndexes);
 	}
@@ -519,9 +530,11 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
 	bool		skip_tuple = false;
 	ResultRelInfo *resultRelInfo = estate->es_result_relation_info;
 	Relation	rel = resultRelInfo->ri_RelationDesc;
+	HeapTupleTableSlot *hsearchslot = (HeapTupleTableSlot *)searchslot;
 
-	/* For now we support only tables. */
+	/* For now we support only tables and heap tuples. */
 	Assert(rel->rd_rel->relkind == RELKIND_RELATION);
+	Assert(TTS_IS_HEAPTUPLE(searchslot) || TTS_IS_BUFFERTUPLE(searchslot));
 
 	CheckCmdReplicaIdentity(rel, CMD_DELETE);
 
@@ -530,8 +543,8 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
 		resultRelInfo->ri_TrigDesc->trig_delete_before_row)
 	{
 		skip_tuple = !ExecBRDeleteTriggers(estate, epqstate, resultRelInfo,
-										   &searchslot->tts_tuple->t_self,
-										   NULL, NULL);
+										   &hsearchslot->tuple->t_self, NULL,
+										   NULL);
 	}
 
 	if (!skip_tuple)
@@ -539,11 +552,11 @@ ExecSimpleRelationDelete(EState *estate, EPQState *epqstate,
 		List	   *recheckIndexes = NIL;
 
 		/* OK, delete the tuple */
-		simple_heap_delete(rel, &searchslot->tts_tuple->t_self);
+		simple_heap_delete(rel, &hsearchslot->tuple->t_self);
 
 		/* AFTER ROW DELETE Triggers */
 		ExecARDeleteTriggers(estate, resultRelInfo,
-							 &searchslot->tts_tuple->t_self, NULL, NULL);
+							 &hsearchslot->tuple->t_self, NULL, NULL);
 
 		list_free(recheckIndexes);
 	}
diff --git a/src/backend/executor/execScan.c b/src/backend/executor/execScan.c
index 233cc280608..d90bb16b570 100644
--- a/src/backend/executor/execScan.c
+++ b/src/backend/executor/execScan.c
@@ -78,8 +78,8 @@ ExecScanFetch(ScanState *node,
 				return ExecClearTuple(slot);
 
 			/* Store test tuple in the plan node's scan slot */
-			ExecStoreHeapTuple(estate->es_epqTuple[scanrelid - 1],
-							   slot, false);
+			ExecForceStoreHeapTuple(estate->es_epqTuple[scanrelid - 1],
+									slot);
 
 			/* Check if it meets the access-method conditions */
 			if (!(*recheckMtd) (node, slot))
diff --git a/src/backend/executor/execTuples.c b/src/backend/executor/execTuples.c
index bb618e94f5d..bf49c4789cb 100644
--- a/src/backend/executor/execTuples.c
+++ b/src/backend/executor/execTuples.c
@@ -71,12 +71,1024 @@
 
 static TupleDesc ExecTypeFromTLInternal(List *targetList,
 					   bool hasoid, bool skipjunk);
+static void tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer);
 
 const TupleTableSlotOps TTSOpsVirtual;
 const TupleTableSlotOps TTSOpsHeapTuple;
 const TupleTableSlotOps TTSOpsMinimalTuple;
 const TupleTableSlotOps TTSOpsBufferTuple;
 
+/*
+ * slot_deform_heap_tuple
+ *		Given a TupleTableSlot, extract data from the slot's physical tuple
+ *		into its Datum/isnull arrays.  Data is extracted up through the
+ *		natts'th column (caller must ensure this is a legal column number).
+ *
+ *		This is essentially an incremental version of heap_deform_tuple:
+ *		on each call we extract attributes up to the one needed, without
+ *		re-computing information about previously extracted attributes.
+ *		slot->tts_nvalid is the number of attributes already extracted.
+ */
+static inline void __attribute__((always_inline))
+slot_deform_heap_tuple(TupleTableSlot *slot, HeapTuple tuple, uint32 *offp,
+					   int natts)
+{
+	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
+	Datum	   *values = slot->tts_values;
+	bool	   *isnull = slot->tts_isnull;
+	HeapTupleHeader tup = tuple->t_data;
+	bool		hasnulls = HeapTupleHasNulls(tuple);
+	int			attnum;
+	char	   *tp;				/* ptr to tuple data */
+	uint32		off;			/* offset in tuple data */
+	bits8	   *bp = tup->t_bits;	/* ptr to null bitmap in tuple */
+	bool		slow;			/* can we use/set attcacheoff? */
+
+	/* We can only fetch as many attributes as the tuple has. */
+	natts = Min(HeapTupleHeaderGetNatts(tuple->t_data), natts);
+
+	/*
+	 * Check whether the first call for this tuple, and initialize or restore
+	 * loop state.
+	 */
+	attnum = slot->tts_nvalid;
+	if (attnum == 0)
+	{
+		/* Start from the first attribute */
+		off = 0;
+		slow = false;
+	}
+	else
+	{
+		/* Restore state from previous execution */
+		off = *offp;
+		slow = TTS_SLOW(slot);
+	}
+
+	tp = (char *) tup + tup->t_hoff;
+
+	for (; attnum < natts; attnum++)
+	{
+		Form_pg_attribute thisatt = TupleDescAttr(tupleDesc, attnum);
+
+		if (hasnulls && att_isnull(attnum, bp))
+		{
+			values[attnum] = (Datum) 0;
+			isnull[attnum] = true;
+			slow = true;		/* can't use attcacheoff anymore */
+			continue;
+		}
+
+		isnull[attnum] = false;
+
+		if (!slow && thisatt->attcacheoff >= 0)
+			off = thisatt->attcacheoff;
+		else if (thisatt->attlen == -1)
+		{
+			/*
+			 * We can only cache the offset for a varlena attribute if the
+			 * offset is already suitably aligned, so that there would be no
+			 * pad bytes in any case: then the offset will be valid for either
+			 * an aligned or unaligned value.
+			 */
+			if (!slow &&
+				off == att_align_nominal(off, thisatt->attalign))
+				thisatt->attcacheoff = off;
+			else
+			{
+				off = att_align_pointer(off, thisatt->attalign, -1,
+										tp + off);
+				slow = true;
+			}
+		}
+		else
+		{
+			/* not varlena, so safe to use att_align_nominal */
+			off = att_align_nominal(off, thisatt->attalign);
+
+			if (!slow)
+				thisatt->attcacheoff = off;
+		}
+
+		values[attnum] = fetchatt(thisatt, tp + off);
+
+		off = att_addlength_pointer(off, thisatt->attlen, tp + off);
+
+		if (thisatt->attlen <= 0)
+			slow = true;		/* can't use attcacheoff anymore */
+	}
+
+	/*
+	 * Save state for next execution
+	 */
+	slot->tts_nvalid = attnum;
+	*offp = off;
+	if (slow)
+		slot->tts_flags |= TTS_FLAG_SLOW;
+	else
+		slot->tts_flags &= ~TTS_FLAG_SLOW;
+}
+
+/*
+ * TupleTableSlotOps implementations.
+ */
+
+/*
+ * TupleTableSlotOps implementation for VirtualTupleTableSlot.
+ */
+static void
+tts_virtual_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_virtual_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_virtual_clear(TupleTableSlot *slot)
+{
+	if (unlikely(TTS_SHOULDFREE(slot)))
+	{
+		VirtualTupleTableSlot *vslot = (VirtualTupleTableSlot *) slot;
+
+		pfree(vslot->data);
+		vslot->data = NULL;
+
+		slot->tts_flags = ~TTS_FLAG_SHOULDFREE;
+	}
+
+	slot->tts_nvalid = 0;
+	slot->tts_flags |= TTS_FLAG_EMPTY;
+}
+
+/*
+ * Attribute values are readily available in tts_values and tts_isnull array
+ * in a VirtualTupleTableSlot. So there should be no need to call either of the
+ * following two functions.
+ */
+static void
+tts_virtual_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	elog(ERROR, "getsomeattrs is not required to be called on a virtual tuple table slot");
+}
+
+static Datum
+tts_virtual_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+	elog(ERROR, "virtual tuple table slot does not have system atttributes");
+}
+
+/*
+ * To materialize a virtual slot all the datums that aren't passed by value
+ * have to be copied into the slot's memory context.  To do so, count the
+ * required size, and allocate enough memory to store all attributes.  That
+ * both gains efficiency, and makes it easier to release all the memory at
+ * once.
+ */
+static void
+tts_virtual_materialize(TupleTableSlot *slot)
+{
+	VirtualTupleTableSlot *vslot = (VirtualTupleTableSlot *) slot;
+	TupleDesc	desc = slot->tts_tupleDescriptor;
+	Size		sz = 0;
+	char	   *data;
+
+	/* already materialized */
+	if (TTS_SHOULDFREE(slot))
+		return;
+
+	/* compute size of memory required */
+	for (int natt = 0; natt < desc->natts; natt++)
+	{
+		Form_pg_attribute att = TupleDescAttr(desc, natt);
+		Datum val;
+
+		if (att->attbyval || slot->tts_isnull[natt])
+			continue;
+
+		val = slot->tts_values[natt];
+
+		if (att->attlen == -1 &&
+			VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
+		{
+			/*
+			 * We want to flatten the expanded value so that the materialized
+			 * slot doesn't depend on it.
+			 */
+			sz = att_align_nominal(sz, att->attalign);
+			sz += EOH_get_flat_size(DatumGetEOHP(val));
+		}
+		else
+		{
+			sz = att_align_nominal(sz, att->attalign);
+			sz = att_addlength_datum(sz, att->attlen, val);
+		}
+
+		/* FIXME: any reason to expand default args? */
+	}
+
+	/* all data is byval */
+	if (sz == 0)
+		return;
+
+	/* allocate memory */
+	vslot->data = data = MemoryContextAlloc(slot->tts_mcxt, sz);
+	slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+
+	/* and copy all attributes into the pre-allocated space */
+	for (int natt = 0; natt < desc->natts; natt++)
+	{
+		Form_pg_attribute att = TupleDescAttr(desc, natt);
+		Datum val;
+
+		if (att->attbyval || slot->tts_isnull[natt])
+			continue;
+
+		val = slot->tts_values[natt];
+
+		if (att->attlen == -1 &&
+			VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(val)))
+		{
+			Size data_length;
+
+			/*
+			 * We want to flatten the expanded value so that the materialized
+			 * slot doesn't depend on it.
+			 */
+			ExpandedObjectHeader *eoh = DatumGetEOHP(val);
+
+			data = (char *) att_align_nominal(data,
+											  att->attalign);
+			data_length = EOH_get_flat_size(eoh);
+			EOH_flatten_into(eoh, data, data_length);
+
+			slot->tts_values[natt] = PointerGetDatum(data);
+			data += data_length;
+		}
+		else
+		{
+			Size data_length = 0;
+
+			data = (char *) att_align_nominal(data, att->attalign);
+			data_length = att_addlength_datum(data_length, att->attlen, val);
+
+			memcpy(data, DatumGetPointer(val), data_length);
+
+			slot->tts_values[natt] = PointerGetDatum(data);
+			data += data_length;
+		}
+		/* FIXME: any reason to expand default args? */
+	}
+}
+
+/*
+ * A virtual tuple table slot can not copy the datums into its own storage. So
+ * it can not copy contents of the other slot into its own memory context.
+ */
+static void
+tts_virtual_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+	TupleDesc	srcdesc = dstslot->tts_tupleDescriptor;
+
+	Assert(srcdesc->natts <= dstslot->tts_tupleDescriptor->natts);
+
+	tts_virtual_clear(dstslot);
+
+	slot_getallattrs(srcslot);
+
+	for (int natt = 0; natt < srcdesc->natts; natt++)
+	{
+		dstslot->tts_values[natt] = srcslot->tts_values[natt];
+		dstslot->tts_isnull[natt] = srcslot->tts_isnull[natt];
+	}
+
+	dstslot->tts_nvalid = srcdesc->natts;
+	dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
+
+	/* make sure storage doesn't depend on external memory */
+	tts_virtual_materialize(dstslot);
+}
+
+static HeapTuple
+tts_virtual_copy_heap_tuple(TupleTableSlot *slot)
+{
+	Assert(!TTS_EMPTY(slot));
+
+	return heap_form_tuple(slot->tts_tupleDescriptor,
+						   slot->tts_values,
+						   slot->tts_isnull);
+
+}
+
+static MinimalTuple
+tts_virtual_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	Assert(!TTS_EMPTY(slot));
+
+	return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
+								   slot->tts_values,
+								   slot->tts_isnull);
+}
+
+/*
+ * TupleTableSlotOps implementation for HeapTupleTableSlot.
+ */
+
+static void
+tts_heap_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_heap_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_heap_clear(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	/* Free the memory for the heap tuple if it's allowed. */
+	if (TTS_SHOULDFREE(slot))
+	{
+		heap_freetuple(hslot->tuple);
+		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+	}
+
+	slot->tts_nvalid = 0;
+	slot->tts_flags |= TTS_FLAG_EMPTY;
+	hslot->off = 0;
+	hslot->tuple = NULL;
+}
+
+static void
+tts_heap_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	slot_deform_heap_tuple(slot, hslot->tuple, &hslot->off, natts);
+}
+
+static Datum
+tts_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	return heap_getsysattr(hslot->tuple, attnum,
+						   slot->tts_tupleDescriptor, isnull);
+}
+
+/*
+ * Materialize the heap tuple contained in the given slot into its own memory
+ * context.
+ */
+static void
+tts_heap_materialize(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+	MemoryContext oldContext;
+
+	Assert(!TTS_EMPTY(slot));
+
+	/* This slot has it's tuple already materialized. Nothing to do. */
+	if (TTS_SHOULDFREE(slot))
+		return;
+
+	slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+
+	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+	if (!hslot->tuple)
+		hslot->tuple = heap_form_tuple(slot->tts_tupleDescriptor,
+									   slot->tts_values,
+									   slot->tts_isnull);
+	else
+	{
+		/*
+		 * The tuple contained in this slot is not allocated in the memory
+		 * context of the given slot (else it would have TTS_SHOULDFREE set).
+		 * Copy the tuple into the given slot's memory context.
+		 */
+		hslot->tuple = heap_copytuple(hslot->tuple);
+	}
+
+	slot->tts_nvalid = 0;
+	hslot->off = 0;
+
+	MemoryContextSwitchTo(oldContext);
+}
+
+/*
+ * Copy contents of the srcslot into dstslot, on which this callback has been
+ * invoked, in dstslot's memory context. We do this by creating a heap tuple
+ * from the source slot's contents in the memory context of the destination
+ * slot and then storing that heap tuple in the destination slot.
+ */
+static void
+tts_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+	HeapTuple tuple;
+	MemoryContext oldcontext;
+
+	oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
+	tuple = ExecCopySlotTuple(srcslot);
+	MemoryContextSwitchTo(oldcontext);
+
+	ExecStoreHeapTuple(tuple, dstslot, true);
+}
+
+/*
+ * Return the heap tuple in the slot as is if it contains one. Otherwise,
+ * materialize a heap tuple using contents of the slot and return it.
+ */
+static HeapTuple
+tts_heap_get_heap_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return hslot->tuple;
+}
+
+/*
+ * Return a copy of heap tuple contained in the slot, materialising one if
+ * necessary.
+ */
+static HeapTuple
+tts_heap_copy_heap_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return heap_copytuple(hslot->tuple);
+}
+
+/*
+ * Return a minimal tuple constructed from the contents of the slot.
+ *
+ * We always return a new minimal tuple so no copy, per say, is needed.
+ */
+static MinimalTuple
+tts_heap_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	if (!hslot->tuple)
+		tts_heap_materialize(slot);
+
+	return minimal_tuple_from_heap_tuple(hslot->tuple);
+}
+
+/*
+ * Store the given tuple into the given HeapTupleTableSlot. If the slot
+ * already contains a tuple, we will free the memory for the same before
+ * storing a new one there.
+ */
+static void
+tts_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, bool shouldFree)
+{
+	HeapTupleTableSlot *hslot = (HeapTupleTableSlot *) slot;
+
+	tts_heap_clear(slot);
+
+	slot->tts_nvalid = 0;
+	hslot->tuple = tuple;
+	hslot->off = 0;
+	slot->tts_flags &= ~TTS_FLAG_EMPTY;
+
+	if (shouldFree)
+		slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+}
+
+
+static void
+tts_minimal_init(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	/*
+	 * Initialize the heap tuple pointer to access attributes of the minimal
+	 * tuple contained in the slot as if its a heap tuple.
+	 */
+	mslot->tuple = &mslot->minhdr;
+}
+
+static void
+tts_minimal_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_minimal_clear(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	if (TTS_SHOULDFREE(slot))
+	{
+		heap_free_minimal_tuple(mslot->mintuple);
+		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+	}
+
+	slot->tts_nvalid = 0;
+	slot->tts_flags |= TTS_FLAG_EMPTY;
+	mslot->off = 0;
+	mslot->mintuple = NULL;
+}
+
+static void
+tts_minimal_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	slot_deform_heap_tuple(slot, mslot->tuple, &mslot->off, natts);
+}
+
+static Datum
+tts_minimal_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+	elog(ERROR, "minimal tuple table slot does not have system atttributes");
+}
+
+/*
+ * Materialize the minimal tuple contained in the given slot into its own
+ * memory context.
+ */
+static void
+tts_minimal_materialize(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+	MemoryContext oldContext;
+
+	Assert(!TTS_EMPTY(slot));
+
+	/* This slot has it's tuple already materialized. Nothing to do. */
+	if (TTS_SHOULDFREE(slot))
+		return;
+
+	slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+	if (!mslot->mintuple)
+		mslot->mintuple = heap_form_minimal_tuple(slot->tts_tupleDescriptor,
+												  slot->tts_values,
+												  slot->tts_isnull);
+	else
+	{
+		/*
+		 * The minimal tuple contained in this slot is not allocated in the
+		 * memory context of the given slot (else it would have TTS_SHOULDFREE
+		 * set).  Copy the minimal tuple into the given slot's memory context.
+		 */
+		mslot->mintuple = heap_copy_minimal_tuple(mslot->mintuple);
+	}
+
+	Assert(mslot->tuple == &mslot->minhdr);
+
+	mslot->minhdr.t_len = mslot->mintuple->t_len + MINIMAL_TUPLE_OFFSET;
+	mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mslot->mintuple - MINIMAL_TUPLE_OFFSET);
+
+	MemoryContextSwitchTo(oldContext);
+
+	slot->tts_nvalid = 0;
+	mslot->off = 0;
+}
+
+/*
+ * Copy contents of the srcslot into dstslot, on which this callback has been
+ * invoked, in dstslot's memory context. We do this by creating a minimal tuple
+ * from the source slot's contents in the memory context of the destination
+ * slot and then storing that minimal tuple in the destination slot.
+ */
+static void
+tts_minimal_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+	MemoryContext oldcontext;
+	MinimalTuple mintuple;
+
+	oldcontext = MemoryContextSwitchTo(dstslot->tts_mcxt);
+	mintuple = ExecCopySlotMinimalTuple(srcslot);
+	MemoryContextSwitchTo(oldcontext);
+
+	ExecStoreMinimalTuple(mintuple, dstslot, true);
+}
+
+/*
+ * Return the minimal tuple if slot contains one. Otherwise materialize the
+ * contents of slot into a minimal tuple and return that.
+ */
+static MinimalTuple
+tts_minimal_get_minimal_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	if (!mslot->mintuple)
+		tts_minimal_materialize(slot);
+
+	return mslot->mintuple;
+}
+
+/*
+ * Return a heap tuple constructed from the minimal tuple contained in the slot.
+ *
+ * We always construct a new heap tuple, so there is nothing to copy as such.
+ */
+static HeapTuple
+tts_minimal_copy_heap_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	/* Materialize the minimal tuple if not already present. */
+	if (!mslot->mintuple)
+		tts_minimal_materialize(slot);
+
+	return heap_tuple_from_minimal_tuple(mslot->mintuple);
+}
+
+/*
+ * Return a copy of minimal tuple contained in the slot, materializing one if
+ * necessary.
+ */
+static MinimalTuple
+tts_minimal_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	if (!mslot->mintuple)
+		tts_minimal_materialize(slot);
+
+	return heap_copy_minimal_tuple(mslot->mintuple);
+}
+
+/*
+ * Store the given minimal tuple into the given MinimalTupleTableSlot. If the
+ * slot already contains a tuple, we will free the memory for the same before
+ * storing a new one there.
+ */
+static void
+tts_minimal_store_tuple(TupleTableSlot *slot, MinimalTuple mtup, bool shouldFree)
+{
+	MinimalTupleTableSlot *mslot = (MinimalTupleTableSlot *) slot;
+
+	tts_minimal_clear(slot);
+
+	Assert(!TTS_SHOULDFREE(slot));
+	Assert(TTS_EMPTY(slot));
+
+	slot->tts_flags &= ~TTS_FLAG_EMPTY;
+	slot->tts_nvalid = 0;
+	mslot->off = 0;
+
+	mslot->mintuple = mtup;
+	Assert(mslot->tuple == &mslot->minhdr);
+	mslot->minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
+	mslot->minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
+	/* no need to set t_self or t_tableOid since we won't allow access */
+
+	if (shouldFree)
+		slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+	else
+		Assert(!TTS_SHOULDFREE(slot));
+}
+
+/*
+ * TupleTableSlotOps implementation for BufferHeapTupleTableSlot.
+ */
+
+static void
+tts_buffer_heap_init(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_buffer_heap_release(TupleTableSlot *slot)
+{
+}
+
+static void
+tts_buffer_heap_clear(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	/*
+	 * Free the memory for heap tuple if allowed. A tuple coming from buffer
+	 * can never be freed. But we may have materialized a tuple from buffer.
+	 * Such a tuple can be freed.
+	 */
+	if (TTS_SHOULDFREE(slot))
+	{
+		/* We should have unpinned the buffer while materializing the tuple. */
+		Assert(!BufferIsValid(bslot->buffer));
+
+		heap_freetuple(bslot->base.tuple);
+		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+
+		Assert(!BufferIsValid(bslot->buffer));
+	}
+
+	if (BufferIsValid(bslot->buffer))
+		ReleaseBuffer(bslot->buffer);
+
+	slot->tts_nvalid = 0;
+	slot->tts_flags |= TTS_FLAG_EMPTY;
+	bslot->base.tuple = NULL;
+	bslot->base.off = 0;
+	bslot->buffer = InvalidBuffer;
+}
+
+static void
+tts_buffer_heap_getsomeattrs(TupleTableSlot *slot, int natts)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	slot_deform_heap_tuple(slot, bslot->base.tuple, &bslot->base.off, natts);
+}
+
+static Datum
+tts_buffer_heap_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	return heap_getsysattr(bslot->base.tuple, attnum,
+						   slot->tts_tupleDescriptor, isnull);
+}
+
+/*
+ * Materialize the heap tuple contained in the given slot into its own memory
+ * context.
+ */
+static void
+tts_buffer_heap_materialize(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+	MemoryContext oldContext;
+
+	Assert(!TTS_EMPTY(slot));
+
+	/* If already materialized nothing to do. */
+	if (TTS_SHOULDFREE(slot))
+		return;
+
+	slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+
+	if (!bslot->base.tuple)
+	{
+		/*
+		 * A heap tuple stored in a BufferHeapTupleTableSlot should have a
+		 * buffer associated with it, unless it's materialized. Thus it will
+		 * never happen that there is no heap tuple stored in this slot but
+		 * tts_values and tts_isnull is set. IOW, we should never require to construct a
+		 * tuple from tts_values and tts_isnull in this slot.
+		 */
+		elog(ERROR, "a buffer tuple table slot should never require to construct a tuple from datums");
+	}
+	bslot->base.tuple = heap_copytuple(bslot->base.tuple);
+	MemoryContextSwitchTo(oldContext);
+
+	/*
+	 * A heap tuple stored in a BufferHeapTupleTableSlot should have a buffer
+	 * associated with it, unless it's materialized.
+	 */
+	Assert(BufferIsValid(bslot->buffer));
+	ReleaseBuffer(bslot->buffer);
+	bslot->buffer = InvalidBuffer;
+
+	bslot->base.off = 0;
+	slot->tts_nvalid = 0;
+}
+
+/*
+ * A buffer tuple table slot is used to store an on-disk tuple in it, at least
+ * to start with. So a need to copy into a buffer tuple table slot should not
+ * arise. May be we could support copying from a buffer tuple table slot, but
+ * it is not clear why it's required to do that.
+ */
+static void
+tts_buffer_heap_copyslot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+	BufferHeapTupleTableSlot *bsrcslot = (BufferHeapTupleTableSlot *) srcslot;
+	BufferHeapTupleTableSlot *bdstslot = (BufferHeapTupleTableSlot *) dstslot;
+
+	Assert(dstslot->tts_cb == srcslot->tts_cb);
+
+	if (TTS_SHOULDFREE(srcslot))
+	{
+		MemoryContext oldContext;
+
+		ExecClearTuple(dstslot);
+		dstslot->tts_flags |= TTS_FLAG_SHOULDFREE;
+		dstslot->tts_flags &= ~TTS_FLAG_EMPTY;
+		oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
+		bdstslot->base.tuple = heap_copytuple(bsrcslot->base.tuple);
+		MemoryContextSwitchTo(oldContext);
+	}
+	else
+	{
+		tts_buffer_heap_store_tuple(dstslot, bsrcslot->base.tuple, bsrcslot->buffer);
+		tts_buffer_heap_materialize(dstslot);
+	}
+}
+
+/*
+ * Return the heap tuple in the slot as is if it contains one. Otherwise,
+ * materialize a heap tuple using contents of the slot and return it.
+ */
+static HeapTuple
+tts_buffer_heap_get_heap_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	/* Is this even possible for a buffer tuple? */
+	if (!bslot->base.tuple)
+		tts_buffer_heap_materialize(slot);
+
+	return bslot->base.tuple;
+}
+
+/*
+ * Return a copy of heap tuple contained in the slot, materialising one if
+ * necessary.
+ */
+static HeapTuple
+tts_buffer_heap_copy_heap_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	/* Is this even possible for a buffer tuple? */
+	if (!bslot->base.tuple)
+		tts_buffer_heap_materialize(slot);
+
+	return heap_copytuple(bslot->base.tuple);
+}
+
+/*
+ * Return a minimal tuple constructed from the contents of the slot.
+ *
+ * We always return a new minimal tuple so no copy, per say, is needed.
+ */
+static MinimalTuple
+tts_buffer_heap_copy_minimal_tuple(TupleTableSlot *slot)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	Assert(!TTS_EMPTY(slot));
+
+	/* Is this even possible for a buffer tuple? */
+	if (!bslot->base.tuple)
+		tts_buffer_heap_materialize(slot);
+
+	return minimal_tuple_from_heap_tuple(bslot->base.tuple);
+}
+
+/*
+ * Store the given tuple into the given BufferHeapTupleTableSlot and pin the
+ * given buffer. If the tuple already contained in the slot can be freed free
+ * it.
+ */
+static void
+tts_buffer_heap_store_tuple(TupleTableSlot *slot, HeapTuple tuple, Buffer buffer)
+{
+	BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
+
+	if (TTS_SHOULDFREE(slot))
+	{
+		/*
+		 * A heap tuple stored in a BufferHeapTupleTableSlot should have a
+		 * buffer associated with it, unless it's materialized.
+		 */
+		Assert(!BufferIsValid(bslot->buffer));
+
+		heap_freetuple(bslot->base.tuple);
+		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
+	}
+
+	slot->tts_flags &= ~TTS_FLAG_EMPTY;
+	slot->tts_nvalid = 0;
+	bslot->base.tuple = tuple;
+	bslot->base.off = 0;
+
+	/*
+	 * If tuple is on a disk page, keep the page pinned as long as we hold a
+	 * pointer into it.  We assume the caller already has such a pin.
+	 *
+	 * This is coded to optimize the case where the slot previously held a
+	 * tuple on the same disk page: in that case releasing and re-acquiring
+	 * the pin is a waste of cycles.  This is a common situation during
+	 * seqscans, so it's worth troubling over.
+	 */
+	if (bslot->buffer != buffer)
+	{
+		if (BufferIsValid(bslot->buffer))
+			ReleaseBuffer(bslot->buffer);
+		bslot->buffer = buffer;
+		IncrBufferRefCount(buffer);
+	}
+}
+
+/*
+ * TupleTableSlotOps for each of TupleTableSlotTypes. These are used to
+ * identify the type of slot.
+ */
+const TupleTableSlotOps TTSOpsVirtual = {
+	.base_slot_size = sizeof(VirtualTupleTableSlot),
+	.init = tts_virtual_init,
+	.release = tts_virtual_release,
+	.clear = tts_virtual_clear,
+	.getsomeattrs = tts_virtual_getsomeattrs,
+	.getsysattr = tts_virtual_getsysattr,
+	.materialize = tts_virtual_materialize,
+	.copyslot = tts_virtual_copyslot,
+
+	/*
+	 * A virtual tuple table slot can not "own" a heap tuple or a minimal
+	 * tuple.
+	 */
+	.get_heap_tuple = NULL,
+	.get_minimal_tuple = NULL,
+	.copy_heap_tuple = tts_virtual_copy_heap_tuple,
+	.copy_minimal_tuple = tts_virtual_copy_minimal_tuple
+};
+
+const TupleTableSlotOps TTSOpsHeapTuple = {
+	.base_slot_size = sizeof(HeapTupleTableSlot),
+	.init = tts_heap_init,
+	.release = tts_heap_release,
+	.clear = tts_heap_clear,
+	.getsomeattrs = tts_heap_getsomeattrs,
+	.getsysattr = tts_heap_getsysattr,
+	.materialize = tts_heap_materialize,
+	.copyslot = tts_heap_copyslot,
+	.get_heap_tuple = tts_heap_get_heap_tuple,
+
+	/* A heap tuple table slot can not "own" a minimal tuple. */
+	.get_minimal_tuple = NULL,
+	.copy_heap_tuple = tts_heap_copy_heap_tuple,
+	.copy_minimal_tuple = tts_heap_copy_minimal_tuple
+};
+
+const TupleTableSlotOps TTSOpsMinimalTuple = {
+	.base_slot_size = sizeof(MinimalTupleTableSlot),
+	.init = tts_minimal_init,
+	.release = tts_minimal_release,
+	.clear = tts_minimal_clear,
+	.getsomeattrs = tts_minimal_getsomeattrs,
+	.getsysattr = tts_minimal_getsysattr,
+	.materialize = tts_minimal_materialize,
+	.copyslot = tts_minimal_copyslot,
+
+	/*
+	 * A minimal tuple table slot can not "own" a heap tuple. As mentioned in
+	 * the prologue of MinimalTupleData, a minimal tuple may be presented as a
+	 * heap tuple, but such a representation does not have memory to hold
+	 * system attributes in it and should be used for accessing/manipulating
+	 * tuple through a slot. Hence we do not return heap tuple representation
+	 * crafted from a minimal tuple to be returned in get_heap_tuple callback
+	 * of this TupleTableSlotType.
+	 */
+	.get_heap_tuple = NULL,
+	.get_minimal_tuple = tts_minimal_get_minimal_tuple,
+	.copy_heap_tuple = tts_minimal_copy_heap_tuple,
+	.copy_minimal_tuple = tts_minimal_copy_minimal_tuple
+};
+
+const TupleTableSlotOps TTSOpsBufferTuple = {
+	.base_slot_size = sizeof(BufferHeapTupleTableSlot),
+	.init = tts_buffer_heap_init,
+	.release = tts_buffer_heap_release,
+	.clear = tts_buffer_heap_clear,
+	.getsomeattrs = tts_buffer_heap_getsomeattrs,
+	.getsysattr = tts_buffer_heap_getsysattr,
+	.materialize = tts_buffer_heap_materialize,
+	.copyslot = tts_buffer_heap_copyslot,
+	.get_heap_tuple = tts_buffer_heap_get_heap_tuple,
+
+	/* A buffer heap tuple table slot can not "own" a minimal tuple. */
+	.get_minimal_tuple = NULL,
+	.copy_heap_tuple = tts_buffer_heap_copy_heap_tuple,
+	.copy_minimal_tuple = tts_buffer_heap_copy_minimal_tuple
+};
+
 /* ----------------------------------------------------------------
  *				  tuple table create/delete functions
  * ----------------------------------------------------------------
@@ -85,58 +1097,60 @@ const TupleTableSlotOps TTSOpsBufferTuple;
 /* --------------------------------
  *		MakeTupleTableSlot
  *
- *		Basic routine to make an empty TupleTableSlot. If tupleDesc is
- *		specified the slot's descriptor is fixed for it's lifetime, gaining
- *		some efficiency. If that's undesirable, pass NULL.
+ *		Basic routine to make an empty TupleTableSlot of given
+ *		TupleTableSlotType. If tupleDesc is specified the slot's descriptor is
+ *		fixed for it's lifetime, gaining some efficiency. If that's
+ *		undesirable, pass NULL.
  * --------------------------------
  */
 TupleTableSlot *
 MakeTupleTableSlot(TupleDesc tupleDesc,
 				   const TupleTableSlotOps *tts_cb)
 {
-	Size		sz;
+	Size		basesz, allocsz;
 	TupleTableSlot *slot;
+	basesz = tts_cb->base_slot_size;
 
 	/*
 	 * When a fixed descriptor is specified, we can reduce overhead by
 	 * allocating the entire slot in one go.
 	 */
 	if (tupleDesc)
-		sz = MAXALIGN(sizeof(TupleTableSlot)) +
+		allocsz = MAXALIGN(basesz) +
 			MAXALIGN(tupleDesc->natts * sizeof(Datum)) +
 			MAXALIGN(tupleDesc->natts * sizeof(bool));
 	else
-		sz = sizeof(TupleTableSlot);
+		allocsz = basesz;
 
-	slot = palloc0(sz);
+	slot = palloc0(allocsz);
 	/* const for optimization purposes, OK to modify at allocation time */
 	*((const TupleTableSlotOps **) &slot->tts_cb) = tts_cb;
 	slot->type = T_TupleTableSlot;
 	slot->tts_flags |= TTS_FLAG_EMPTY;
 	if (tupleDesc != NULL)
 		slot->tts_flags |= TTS_FLAG_FIXED;
-	slot->tts_tuple = NULL;
 	slot->tts_tupleDescriptor = tupleDesc;
 	slot->tts_mcxt = CurrentMemoryContext;
-	slot->tts_buffer = InvalidBuffer;
 	slot->tts_nvalid = 0;
-	slot->tts_values = NULL;
-	slot->tts_isnull = NULL;
-	slot->tts_mintuple = NULL;
 
 	if (tupleDesc != NULL)
 	{
 		slot->tts_values = (Datum *)
 			(((char *) slot)
-			 + MAXALIGN(sizeof(TupleTableSlot)));
+			 + MAXALIGN(basesz));
 		slot->tts_isnull = (bool *)
 			(((char *) slot)
-			 + MAXALIGN(sizeof(TupleTableSlot))
+			 + MAXALIGN(basesz)
 			 + MAXALIGN(tupleDesc->natts * sizeof(Datum)));
 
 		PinTupleDesc(tupleDesc);
 	}
 
+	/*
+	 * And allow slot type specific initialization.
+	 */
+	slot->tts_cb->init(slot);
+
 	return slot;
 }
 
@@ -178,6 +1192,7 @@ ExecResetTupleTable(List *tupleTable,	/* tuple table */
 
 		/* Always release resources and reset the slot to empty */
 		ExecClearTuple(slot);
+		slot->tts_cb->release(slot);
 		if (slot->tts_tupleDescriptor)
 		{
 			ReleaseTupleDesc(slot->tts_tupleDescriptor);
@@ -234,6 +1249,7 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
 	/* This should match ExecResetTupleTable's processing of one slot */
 	Assert(IsA(slot, TupleTableSlot));
 	ExecClearTuple(slot);
+	slot->tts_cb->release(slot);
 	if (slot->tts_tupleDescriptor)
 		ReleaseTupleDesc(slot->tts_tupleDescriptor);
 	if (!TTS_FIXED(slot))
@@ -334,36 +1350,9 @@ ExecStoreHeapTuple(HeapTuple tuple,
 	Assert(slot != NULL);
 	Assert(slot->tts_tupleDescriptor != NULL);
 
-	/*
-	 * Free any old physical tuple belonging to the slot.
-	 */
-	if (TTS_SHOULDFREE(slot))
-	{
-		heap_freetuple(slot->tts_tuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
-	}
-	if (TTS_SHOULDFREEMIN(slot))
-	{
-		heap_free_minimal_tuple(slot->tts_mintuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
-	}
-
-	/*
-	 * Store the new tuple into the specified slot.
-	 */
-	slot->tts_flags &= ~TTS_FLAG_EMPTY;
-	if (shouldFree)
-		slot->tts_flags |= TTS_FLAG_SHOULDFREE;
-	slot->tts_tuple = tuple;
-	slot->tts_mintuple = NULL;
-
-	/* Mark extracted state invalid */
-	slot->tts_nvalid = 0;
-
-	/* Unpin any buffer pinned by the slot. */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-	slot->tts_buffer = InvalidBuffer;
+	if (!TTS_IS_HEAPTUPLE(slot))
+		elog(ERROR, "trying to store a heap tuple into wrong type of slot");
+	tts_heap_store_tuple(slot, tuple, shouldFree);
 
 	return slot;
 }
@@ -397,46 +1386,9 @@ ExecStoreBufferHeapTuple(HeapTuple tuple,
 	Assert(slot->tts_tupleDescriptor != NULL);
 	Assert(BufferIsValid(buffer));
 
-	/*
-	 * Free any old physical tuple belonging to the slot.
-	 */
-	if (TTS_SHOULDFREE(slot))
-	{
-		heap_freetuple(slot->tts_tuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
-	}
-	if (TTS_SHOULDFREEMIN(slot))
-	{
-		heap_free_minimal_tuple(slot->tts_mintuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
-	}
-
-	/*
-	 * Store the new tuple into the specified slot.
-	 */
-	slot->tts_flags &= ~TTS_FLAG_EMPTY;
-	slot->tts_tuple = tuple;
-	slot->tts_mintuple = NULL;
-
-	/* Mark extracted state invalid */
-	slot->tts_nvalid = 0;
-
-	/*
-	 * Keep the disk page containing the given tuple pinned as long as we hold
-	 * a pointer into it.  We assume the caller already has such a pin.
-	 *
-	 * This is coded to optimize the case where the slot previously held a
-	 * tuple on the same disk page: in that case releasing and re-acquiring the
-	 * pin is a waste of cycles.  This is a common situation during seqscans,
-	 * so it's worth troubling over.
-	 */
-	if (slot->tts_buffer != buffer)
-	{
-		if (BufferIsValid(slot->tts_buffer))
-			ReleaseBuffer(slot->tts_buffer);
-		slot->tts_buffer = buffer;
-		IncrBufferRefCount(buffer);
-	}
+	if (!TTS_IS_BUFFERTUPLE(slot))
+		elog(ERROR, "trying to store an on-disk heap tuple into wrong type of slot");
+	tts_buffer_heap_store_tuple(slot, tuple, buffer);
 
 	return slot;
 }
@@ -461,93 +1413,9 @@ ExecStoreMinimalTuple(MinimalTuple mtup,
 	Assert(slot != NULL);
 	Assert(slot->tts_tupleDescriptor != NULL);
 
-	/*
-	 * Free any old physical tuple belonging to the slot.
-	 */
-	if (TTS_SHOULDFREE(slot))
-	{
-		heap_freetuple(slot->tts_tuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
-	}
-	if (TTS_SHOULDFREEMIN(slot))
-	{
-		heap_free_minimal_tuple(slot->tts_mintuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
-	}
-
-	/*
-	 * Drop the pin on the referenced buffer, if there is one.
-	 */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-
-	slot->tts_buffer = InvalidBuffer;
-
-	/*
-	 * Store the new tuple into the specified slot.
-	 */
-	slot->tts_flags &= ~TTS_FLAG_EMPTY;
-	if (shouldFree)
-		slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN;
-	slot->tts_tuple = &slot->tts_minhdr;
-	slot->tts_mintuple = mtup;
-
-	slot->tts_minhdr.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
-	slot->tts_minhdr.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
-	/* no need to set t_self or t_tableOid since we won't allow access */
-
-	/* Mark extracted state invalid */
-	slot->tts_nvalid = 0;
-
-	return slot;
-}
-
-/* --------------------------------
- *		ExecClearTuple
- *
- *		This function is used to clear out a slot in the tuple table.
- *
- *		NB: only the tuple is cleared, not the tuple descriptor (if any).
- * --------------------------------
- */
-TupleTableSlot *				/* return: slot passed */
-ExecClearTuple(TupleTableSlot *slot)	/* slot in which to store tuple */
-{
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-
-	/*
-	 * Free the old physical tuple if necessary.
-	 */
-	if (TTS_SHOULDFREE(slot))
-	{
-		heap_freetuple(slot->tts_tuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREE;
-	}
-	if (TTS_SHOULDFREEMIN(slot))
-	{
-		heap_free_minimal_tuple(slot->tts_mintuple);
-		slot->tts_flags &= ~TTS_FLAG_SHOULDFREEMIN;
-	}
-
-	slot->tts_tuple = NULL;
-	slot->tts_mintuple = NULL;
-
-	/*
-	 * Drop the pin on the referenced buffer, if there is one.
-	 */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-
-	slot->tts_buffer = InvalidBuffer;
-
-	/*
-	 * Mark it empty.
-	 */
-	slot->tts_flags |= TTS_FLAG_EMPTY;
-	slot->tts_nvalid = 0;
+	if (!TTS_IS_MINIMALTUPLE(slot))
+		elog(ERROR, "trying to store a minimal tuple into wrong type of slot");
+	tts_minimal_store_tuple(slot, mtup, shouldFree);
 
 	return slot;
 }
@@ -611,79 +1479,19 @@ ExecStoreAllNullTuple(TupleTableSlot *slot)
 }
 
 /* --------------------------------
- *		ExecCopySlotTuple
- *			Obtain a copy of a slot's regular physical tuple.  The copy is
- *			palloc'd in the current memory context.
- *			The slot itself is undisturbed.
+ *		ExecFetchSlotTuple
+ *			Fetch the slot's regular physical tuple.
  *
- *		This works even if the slot contains a virtual or minimal tuple;
- *		however the "system columns" of the result will not be meaningful.
+ *		This is a thin wrapper around TupleTableSlotType specific
+ *		get_heap_tuple callback. The callback is expected to return a heap
+ *		tuple as is if it holds one and continue to have ownership of the heap
+ *		tuple. If materialize is true, the function calls TupleTableSlotType
+ *		specific materialize() callback which is expected to materialize the
+ *		tuple within the slot so that the slot "owns" it. If materialize is
+ *		false, the returned tuple is not guaranteed to have storage local to
+ *		the slot and hence should be treated as read-only.
  * --------------------------------
  */
-HeapTuple
-ExecCopySlotTuple(TupleTableSlot *slot)
-{
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-	Assert(!TTS_EMPTY(slot));
-
-	/*
-	 * If we have a physical tuple (either format) then just copy it.
-	 */
-	if (TTS_HAS_PHYSICAL_TUPLE(slot))
-		return heap_copytuple(slot->tts_tuple);
-	if (slot->tts_mintuple)
-		return heap_tuple_from_minimal_tuple(slot->tts_mintuple);
-
-	/*
-	 * Otherwise we need to build a tuple from the Datum array.
-	 */
-	return heap_form_tuple(slot->tts_tupleDescriptor,
-						   slot->tts_values,
-						   slot->tts_isnull);
-}
-
-/* --------------------------------
- *		ExecCopySlotMinimalTuple
- *			Obtain a copy of a slot's minimal physical tuple.  The copy is
- *			palloc'd in the current memory context.
- *			The slot itself is undisturbed.
- * --------------------------------
- */
-MinimalTuple
-ExecCopySlotMinimalTuple(TupleTableSlot *slot)
-{
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-	Assert(!TTS_EMPTY(slot));
-
-	/*
-	 * If we have a physical tuple then just copy it.  Prefer to copy
-	 * tts_mintuple since that's a tad cheaper.
-	 */
-	if (slot->tts_mintuple)
-		return heap_copy_minimal_tuple(slot->tts_mintuple);
-	if (slot->tts_tuple)
-	{
-		if (HeapTupleHeaderGetNatts(slot->tts_tuple->t_data)
-			< slot->tts_tupleDescriptor->natts)
-			return minimal_expand_tuple(slot->tts_tuple,
-										slot->tts_tupleDescriptor);
-		else
-			return minimal_tuple_from_heap_tuple(slot->tts_tuple);
-	}
-
-	/*
-	 * Otherwise we need to build a tuple from the Datum array.
-	 */
-	return heap_form_minimal_tuple(slot->tts_tupleDescriptor,
-								   slot->tts_values,
-								   slot->tts_isnull);
-}
 
 /*
  * ExecFetchSlotHeapTuple - fetch HeapTuple representing the slot's content
@@ -713,89 +1521,67 @@ ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree)
 	Assert(slot != NULL);
 	Assert(!TTS_EMPTY(slot));
 
-	if (shouldFree)
-		*shouldFree = false;
+	/* Materialize the tuple so that the slot "owns" it, if requested. */
+	if (materialize)
+		slot->tts_cb->materialize(slot);
 
-	/*
-	 * If we have a regular physical tuple then just return it.
-	 */
-	if (TTS_HAS_PHYSICAL_TUPLE(slot))
+	if (slot->tts_cb->get_heap_tuple == NULL)
 	{
-		if (HeapTupleHeaderGetNatts(slot->tts_tuple->t_data) <
-			slot->tts_tupleDescriptor->natts)
-		{
-			HeapTuple	tuple;
-			MemoryContext oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
-
-			tuple = heap_expand_tuple(slot->tts_tuple,
-									  slot->tts_tupleDescriptor);
-			MemoryContextSwitchTo(oldContext);
-			slot = ExecStoreHeapTuple(tuple, slot, true);
-		}
-		return slot->tts_tuple;
+		if (shouldFree)
+			*shouldFree = true;
+		return slot->tts_cb->copy_heap_tuple(slot);
+	}
+	else
+	{
+		if (shouldFree)
+			*shouldFree = false;
+		return slot->tts_cb->get_heap_tuple(slot);
 	}
-
-	/*
-	 * Otherwise materialize the slot...
-	 */
-	ExecMaterializeSlot(slot);
-
-	return slot->tts_tuple;
 }
 
 /* --------------------------------
  *		ExecFetchSlotMinimalTuple
  *			Fetch the slot's minimal physical tuple.
  *
- *		If the slot contains a virtual tuple, we convert it to minimal
- *		physical form.  The slot retains ownership of the minimal tuple.
- *		If it contains a regular tuple we convert to minimal form and store
- *		that in addition to the regular tuple (not instead of, because
- *		callers may hold pointers to Datums within the regular tuple).
+ *		If the given tuple table slot can hold a minimal tuple, indicated by a
+ *		non-NULL get_minimal_tuple callback, the function returns the minimal
+ *		tuple returned by that callback. It assumes that the minimal tuple
+ *		returned by the callback is "owned" by the slot i.e. the slot is
+ *		responsible for freeing the memory consumed by the tuple. Hence it sets
+ *		*shouldFree to false, indicating that the caller should not free the
+ *		memory consumed by the minimal tuple. In this case the returned minimal
+ *		tuple should be considered as read-only.
  *
- * As above, the result must be treated as read-only.
+ *		If that callback is not supported, it calls copy_minimal_tuple callback
+ *		which is expected to return a copy of minimal tuple represnting the
+ *		contents of the slot. In this case *shouldFree is set to true,
+ *		indicating the caller that it should free the memory consumed by the
+ *		minimal tuple. In this case the returned minimal tuple may be written
+ *		up.
  * --------------------------------
  */
 MinimalTuple
-ExecFetchSlotMinimalTuple(TupleTableSlot *slot, bool *shouldFree)
+ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
+						  bool *shouldFree)
 {
-	MemoryContext oldContext;
-
 	/*
 	 * sanity checks
 	 */
 	Assert(slot != NULL);
 	Assert(!TTS_EMPTY(slot));
 
-	if (shouldFree)
-		*shouldFree = false;
-
-	/*
-	 * If we have a minimal physical tuple (local or not) then just return it.
-	 */
-	if (slot->tts_mintuple)
-		return slot->tts_mintuple;
-
-	/*
-	 * Otherwise, copy or build a minimal tuple, and store it into the slot.
-	 *
-	 * We may be called in a context that is shorter-lived than the tuple
-	 * slot, but we have to ensure that the materialized tuple will survive
-	 * anyway.
-	 */
-	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
-	slot->tts_mintuple = ExecCopySlotMinimalTuple(slot);
-	slot->tts_flags |= TTS_FLAG_SHOULDFREEMIN;
-	MemoryContextSwitchTo(oldContext);
-
-	/*
-	 * Note: we may now have a situation where we have a local minimal tuple
-	 * attached to a virtual or non-local physical tuple.  There seems no harm
-	 * in that at the moment, but if any materializes, we should change this
-	 * function to force the slot into minimal-tuple-only state.
-	 */
-
-	return slot->tts_mintuple;
+	if (slot->tts_cb->get_minimal_tuple)
+	{
+		if (shouldFree)
+			*shouldFree = false;
+		return slot->tts_cb->get_minimal_tuple(slot);
+	}
+	else
+	{
+		if (shouldFree)
+			*shouldFree = true;
+		return slot->tts_cb->copy_minimal_tuple(slot);
+	}
 }
 
 /* --------------------------------
@@ -826,103 +1612,58 @@ ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)
 	return ret;
 }
 
-/* ExecMaterializeSlot - force a slot into the "materialized" state.
- *
- * This causes the slot's tuple to be a local copy not dependent on any
- * external storage (i.e. pointing into a Buffer, or having allocations in
- * another memory context).
- *
- * A typical use for this operation is to prepare a computed tuple for being
- * stored on disk.  The original data may or may not be virtual, but in any
- * case we need a private copy for heap_insert to scribble on.
- */
 void
-ExecMaterializeSlot(TupleTableSlot *slot)
+ExecForceStoreHeapTuple(HeapTuple tuple,
+						TupleTableSlot *slot)
 {
-	MemoryContext oldContext;
+	if (TTS_IS_HEAPTUPLE(slot))
+	{
+		ExecStoreHeapTuple(tuple, slot, false);
+	}
+	else if (TTS_IS_BUFFERTUPLE(slot))
+	{
+		MemoryContext oldContext;
+		BufferHeapTupleTableSlot *bslot = (BufferHeapTupleTableSlot *) slot;
 
-	/*
-	 * sanity checks
-	 */
-	Assert(slot != NULL);
-	Assert(!TTS_EMPTY(slot));
-
-	/*
-	 * If we have a regular physical tuple, and it's locally palloc'd, we have
-	 * nothing to do.
-	 */
-	if (slot->tts_tuple && TTS_SHOULDFREE(slot))
-		return;
-
-	/*
-	 * Otherwise, copy or build a physical tuple, and store it into the slot.
-	 *
-	 * We may be called in a context that is shorter-lived than the tuple
-	 * slot, but we have to ensure that the materialized tuple will survive
-	 * anyway.
-	 */
-	oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
-	slot->tts_tuple = ExecCopySlotTuple(slot);
-	slot->tts_flags |= TTS_FLAG_SHOULDFREE;
-	MemoryContextSwitchTo(oldContext);
-
-	/*
-	 * Drop the pin on the referenced buffer, if there is one.
-	 */
-	if (BufferIsValid(slot->tts_buffer))
-		ReleaseBuffer(slot->tts_buffer);
-
-	slot->tts_buffer = InvalidBuffer;
-
-	/*
-	 * Mark extracted state invalid.  This is important because the slot is
-	 * not supposed to depend any more on the previous external data; we
-	 * mustn't leave any dangling pass-by-reference datums in tts_values.
-	 * However, we have not actually invalidated any such datums, if there
-	 * happen to be any previously fetched from the slot.  (Note in particular
-	 * that we have not pfree'd tts_mintuple, if there is one.)
-	 */
-	slot->tts_nvalid = 0;
-
-	/*
-	 * On the same principle of not depending on previous remote storage,
-	 * forget the mintuple if it's not local storage.  (If it is local
-	 * storage, we must not pfree it now, since callers might have already
-	 * fetched datum pointers referencing it.)
-	 */
-	if (!TTS_SHOULDFREEMIN(slot))
-		slot->tts_mintuple = NULL;
+		ExecClearTuple(slot);
+		slot->tts_flags |= TTS_FLAG_SHOULDFREE;
+		slot->tts_flags &= ~TTS_FLAG_EMPTY;
+		oldContext = MemoryContextSwitchTo(slot->tts_mcxt);
+		bslot->base.tuple = heap_copytuple(tuple);
+		MemoryContextSwitchTo(oldContext);
+	}
+	else
+	{
+		ExecClearTuple(slot);
+		heap_deform_tuple(tuple, slot->tts_tupleDescriptor,
+						  slot->tts_values, slot->tts_isnull);
+		ExecStoreVirtualTuple(slot);
+	}
 }
 
-/* --------------------------------
- *		ExecCopySlot
- *			Copy the source slot's contents into the destination slot.
- *
- *		The destination acquires a private copy that will not go away
- *		if the source is cleared.
- *
- *		The caller must ensure the slots have compatible tupdescs.
- * --------------------------------
- */
-TupleTableSlot *
-ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+void
+ExecForceStoreMinimalTuple(MinimalTuple mtup,
+						   TupleTableSlot *slot,
+						   bool shouldFree)
 {
-	HeapTuple	newTuple;
-	MemoryContext oldContext;
+	if (TTS_IS_MINIMALTUPLE(slot))
+	{
+		tts_minimal_store_tuple(slot, mtup, shouldFree);
+	}
+	else
+	{
+		HeapTupleData htup;
 
-	/*
-	 * There might be ways to optimize this when the source is virtual, but
-	 * for now just always build a physical copy.  Make sure it is in the
-	 * right context.
-	 */
-	oldContext = MemoryContextSwitchTo(dstslot->tts_mcxt);
-	newTuple = ExecCopySlotTuple(srcslot);
-	MemoryContextSwitchTo(oldContext);
+		ExecClearTuple(slot);
 
-	return ExecStoreHeapTuple(newTuple, dstslot, true);
+		htup.t_len = mtup->t_len + MINIMAL_TUPLE_OFFSET;
+		htup.t_data = (HeapTupleHeader) ((char *) mtup - MINIMAL_TUPLE_OFFSET);
+		heap_deform_tuple(&htup, slot->tts_tupleDescriptor,
+						  slot->tts_values, slot->tts_isnull);
+		ExecStoreVirtualTuple(slot);
+	}
 }
 
-
 /* ----------------------------------------------------------------
  *				convenience initialization routines
  * ----------------------------------------------------------------
@@ -1062,7 +1803,6 @@ void
 slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
 {
 	AttrMissing *attrmiss = NULL;
-	int			missattnum;
 
 	if (slot->tts_tupleDescriptor->constr)
 		attrmiss = slot->tts_tupleDescriptor->constr->missing;
@@ -1077,6 +1817,8 @@ slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
 	}
 	else
 	{
+		int			missattnum;
+
 		/* if there is a missing values array we must process them one by one */
 		for (missattnum = startAttNum;
 			 missattnum < lastAttNum;
@@ -1085,143 +1827,36 @@ slot_getmissingattrs(TupleTableSlot *slot, int startAttNum, int lastAttNum)
 			slot->tts_values[missattnum] = attrmiss[missattnum].am_value;
 			slot->tts_isnull[missattnum] = !attrmiss[missattnum].am_present;
 		}
+
 	}
 }
 
 /*
- * slot_getattr
- *		This function fetches an attribute of the slot's current tuple.
- *		It is functionally equivalent to heap_getattr, but fetches of
- *		multiple attributes of the same tuple will be optimized better,
- *		because we avoid O(N^2) behavior from multiple calls of
- *		nocachegetattr(), even when attcacheoff isn't usable.
+ * slot_getsomeattrs_int
  *
- *		A difference from raw heap_getattr is that attnums beyond the
- *		slot's tupdesc's last attribute will be considered NULL even
- *		when the physical tuple is longer than the tupdesc.
- */
-Datum
-slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)
-{
-	HeapTuple	tuple = slot->tts_tuple;
-	TupleDesc	tupleDesc = slot->tts_tupleDescriptor;
-	HeapTupleHeader tup;
-
-	/*
-	 * system attributes are handled by heap_getsysattr
-	 */
-	if (attnum <= 0)
-	{
-		if (tuple == NULL)		/* internal error */
-			elog(ERROR, "cannot extract system attribute from virtual tuple");
-		if (tuple == &(slot->tts_minhdr))	/* internal error */
-			elog(ERROR, "cannot extract system attribute from minimal tuple");
-		return heap_getsysattr(tuple, attnum, tupleDesc, isnull);
-	}
-
-	/*
-	 * fast path if desired attribute already cached
-	 */
-	if (attnum <= slot->tts_nvalid)
-	{
-		*isnull = slot->tts_isnull[attnum - 1];
-		return slot->tts_values[attnum - 1];
-	}
-
-	/*
-	 * return NULL if attnum is out of range according to the tupdesc
-	 */
-	if (attnum > tupleDesc->natts)
-	{
-		*isnull = true;
-		return (Datum) 0;
-	}
-
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
-
-	/*
-	 * return NULL or missing value if attnum is out of range according to the
-	 * tuple
-	 *
-	 * (We have to check this separately because of various inheritance and
-	 * table-alteration scenarios: the tuple could be either longer or shorter
-	 * than the tupdesc.)
-	 */
-	tup = tuple->t_data;
-	if (attnum > HeapTupleHeaderGetNatts(tup))
-		return getmissingattr(slot->tts_tupleDescriptor, attnum, isnull);
-
-	/*
-	 * check if target attribute is null: no point in groveling through tuple
-	 */
-	if (HeapTupleHasNulls(tuple) && att_isnull(attnum - 1, tup->t_bits))
-	{
-		*isnull = true;
-		return (Datum) 0;
-	}
-
-	/*
-	 * Extract the attribute, along with any preceding attributes.
-	 */
-	slot_deform_tuple(slot, attnum);
-
-	/*
-	 * The result is acquired from tts_values array.
-	 */
-	*isnull = slot->tts_isnull[attnum - 1];
-	return slot->tts_values[attnum - 1];
-}
-
-/*
- * slot_getsomeattrs
- *		This function forces the entries of the slot's Datum/isnull
- *		arrays to be valid at least up through the attnum'th entry.
  */
 void
-slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+slot_getsomeattrs_int(TupleTableSlot *slot, int attnum)
 {
-	HeapTuple	tuple;
-	int			attno;
+	/* Check for caller errors */
+	Assert(slot->tts_nvalid < attnum); /* slot_getsomeattr checked */
+	Assert(attnum > 0);
 
-	/* Quick out if we have 'em all already */
-	if (slot->tts_nvalid >= attnum)
-		return;
-
-	/* Check for caller error */
-	if (attnum <= 0 || attnum > slot->tts_tupleDescriptor->natts)
+	if (unlikely(attnum > slot->tts_tupleDescriptor->natts))
 		elog(ERROR, "invalid attribute number %d", attnum);
 
-	/*
-	 * otherwise we had better have a physical tuple (tts_nvalid should equal
-	 * natts in all virtual-tuple cases)
-	 */
-	tuple = slot->tts_tuple;
-	if (tuple == NULL)			/* internal error */
-		elog(ERROR, "cannot extract attribute from empty tuple slot");
+	/* Fetch as many attributes as possible from the underlying tuple. */
+	slot->tts_cb->getsomeattrs(slot, attnum);
 
 	/*
-	 * load up any slots available from physical tuple
+	 * If the underlying tuple doesn't have enough attributes, tuple descriptor
+	 * must have the missing attributes.
 	 */
-	attno = HeapTupleHeaderGetNatts(tuple->t_data);
-	attno = Min(attno, attnum);
-
-	slot_deform_tuple(slot, attno);
-
-	attno = slot->tts_nvalid;
-
-	/*
-	 * If tuple doesn't have all the atts indicated by attnum, read the rest
-	 * as NULLs or missing values
-	 */
-	if (attno < attnum)
-		slot_getmissingattrs(slot, attno, attnum);
-
-	slot->tts_nvalid = attnum;
+	if (unlikely(slot->tts_nvalid < attnum))
+	{
+		slot_getmissingattrs(slot, slot->tts_nvalid, attnum);
+		slot->tts_nvalid = attnum;
+	}
 }
 
 /* ----------------------------------------------------------------
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 20d6d8e9cbb..2a1a6123d3b 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -1800,9 +1800,8 @@ agg_retrieve_direct(AggState *aggstate)
 				 * reserved for it.  The tuple will be deleted when it is
 				 * cleared from the slot.
 				 */
-				ExecStoreHeapTuple(aggstate->grp_firstTuple,
-								   firstSlot,
-								   true);
+				ExecForceStoreHeapTuple(aggstate->grp_firstTuple,
+								   firstSlot);
 				aggstate->grp_firstTuple = NULL;	/* don't keep two pointers */
 
 				/* set up for first advance_aggregates call */
diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c
index d9afd0bdded..8fb477f45c3 100644
--- a/src/backend/executor/nodeHashjoin.c
+++ b/src/backend/executor/nodeHashjoin.c
@@ -929,9 +929,10 @@ ExecParallelHashJoinOuterGetTuple(PlanState *outerNode,
 									   hashvalue);
 		if (tuple != NULL)
 		{
-			slot = ExecStoreMinimalTuple(tuple,
-										 hjstate->hj_OuterTupleSlot,
-										 false);
+			ExecForceStoreMinimalTuple(tuple,
+									   hjstate->hj_OuterTupleSlot,
+									   false);
+			slot = hjstate->hj_OuterTupleSlot;
 			return slot;
 		}
 		else
@@ -1158,9 +1159,10 @@ ExecParallelHashJoinNewBatch(HashJoinState *hjstate)
 					while ((tuple = sts_parallel_scan_next(inner_tuples,
 														   &hashvalue)))
 					{
-						slot = ExecStoreMinimalTuple(tuple,
-													 hjstate->hj_HashTupleSlot,
-													 false);
+						ExecForceStoreMinimalTuple(tuple,
+												   hjstate->hj_HashTupleSlot,
+												   false);
+						slot = hjstate->hj_HashTupleSlot;
 						ExecParallelHashTableInsertCurrentBatch(hashtable, slot,
 																hashvalue);
 					}
@@ -1294,7 +1296,8 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate,
 		ereport(ERROR,
 				(errcode_for_file_access(),
 				 errmsg("could not read from hash-join temporary file: %m")));
-	return ExecStoreMinimalTuple(tuple, tupleSlot, true);
+	ExecForceStoreMinimalTuple(tuple, tupleSlot, true);
+	return tupleSlot;
 }
 
 
diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index 9cc499d6533..d29162bab79 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -2059,6 +2059,15 @@ ExecModifyTable(PlanState *pstate)
 				break;
 		}
 
+		/*
+		 * Ensure input tuple is the right format for the target relation.
+		 */
+		if (node->mt_scans[node->mt_whichplan]->tts_cb != planSlot->tts_cb)
+		{
+			ExecCopySlot(node->mt_scans[node->mt_whichplan], planSlot);
+			planSlot = node->mt_scans[node->mt_whichplan];
+		}
+
 		/*
 		 * If resultRelInfo->ri_usesFdwDirectModify is true, all we need to do
 		 * here is compute the RETURNING expressions.
@@ -2242,6 +2251,7 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 
 	mtstate->mt_plans = (PlanState **) palloc0(sizeof(PlanState *) * nplans);
 	mtstate->resultRelInfo = estate->es_result_relations + node->resultRelIndex;
+	mtstate->mt_scans = (TupleTableSlot **) palloc0(sizeof(TupleTableSlot *) * nplans);
 
 	/* If modifying a partitioned table, initialize the root table info */
 	if (node->rootResultRelIndex >= 0)
@@ -2308,6 +2318,9 @@ ExecInitModifyTable(ModifyTable *node, EState *estate, int eflags)
 		/* Now init the plan for this result rel */
 		estate->es_result_relation_info = resultRelInfo;
 		mtstate->mt_plans[i] = ExecInitNode(subplan, estate, eflags);
+		mtstate->mt_scans[i] =
+			ExecInitExtraTupleSlot(mtstate->ps.state, ExecGetResultType(mtstate->mt_plans[i]),
+								   &TTSOpsHeapTuple);
 
 		/* Also let FDWs init themselves for foreign-table result rels */
 		if (!resultRelInfo->ri_usesFdwDirectModify &&
diff --git a/src/backend/executor/nodeSubplan.c b/src/backend/executor/nodeSubplan.c
index 62811ed0302..b42e60576e3 100644
--- a/src/backend/executor/nodeSubplan.c
+++ b/src/backend/executor/nodeSubplan.c
@@ -988,6 +988,7 @@ ExecInitSubPlan(SubPlan *subplan, PlanState *parent)
 		 * across-type comparison).
 		 */
 		sstate->cur_eq_comp = ExecBuildGroupingEqual(tupDescLeft, tupDescRight,
+													 &TTSOpsVirtual, &TTSOpsMinimalTuple,
 													 ncols,
 													 sstate->keyColIdx,
 													 sstate->tab_eq_funcoids,
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 168072afd2f..162d1be89bd 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -65,6 +65,8 @@ LLVMTypeRef StructFormPgAttribute;
 LLVMTypeRef StructTupleConstr;
 LLVMTypeRef StructtupleDesc;
 LLVMTypeRef StructTupleTableSlot;
+LLVMTypeRef StructHeapTupleTableSlot;
+LLVMTypeRef StructMinimalTupleTableSlot;
 LLVMTypeRef StructMemoryContextData;
 LLVMTypeRef StructPGFinfoRecord;
 LLVMTypeRef StructFmgrInfo;
@@ -79,7 +81,7 @@ LLVMTypeRef StructAggStatePerTransData;
 LLVMValueRef AttributeTemplate;
 LLVMValueRef FuncStrlen;
 LLVMValueRef FuncVarsizeAny;
-LLVMValueRef FuncSlotGetsomeattrs;
+LLVMValueRef FuncSlotGetsomeattrsInt;
 LLVMValueRef FuncSlotGetmissingattrs;
 LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
 LLVMValueRef FuncExecEvalArrayRefSubscript;
@@ -811,6 +813,8 @@ llvm_create_types(void)
 	StructFunctionCallInfoData = load_type(mod, "StructFunctionCallInfoData");
 	StructMemoryContextData = load_type(mod, "StructMemoryContextData");
 	StructTupleTableSlot = load_type(mod, "StructTupleTableSlot");
+	StructHeapTupleTableSlot = load_type(mod, "StructHeapTupleTableSlot");
+	StructMinimalTupleTableSlot = load_type(mod, "StructMinimalTupleTableSlot");
 	StructHeapTupleData = load_type(mod, "StructHeapTupleData");
 	StructtupleDesc = load_type(mod, "StructtupleDesc");
 	StructAggState = load_type(mod, "StructAggState");
@@ -820,7 +824,7 @@ llvm_create_types(void)
 	AttributeTemplate = LLVMGetNamedFunction(mod, "AttributeTemplate");
 	FuncStrlen = LLVMGetNamedFunction(mod, "strlen");
 	FuncVarsizeAny = LLVMGetNamedFunction(mod, "varsize_any");
-	FuncSlotGetsomeattrs = LLVMGetNamedFunction(mod, "slot_getsomeattrs");
+	FuncSlotGetsomeattrsInt = LLVMGetNamedFunction(mod, "slot_getsomeattrs_int");
 	FuncSlotGetmissingattrs = LLVMGetNamedFunction(mod, "slot_getmissingattrs");
 	FuncMakeExpandedObjectReadOnlyInternal = LLVMGetNamedFunction(mod, "MakeExpandedObjectReadOnlyInternal");
 	FuncExecEvalArrayRefSubscript = LLVMGetNamedFunction(mod, "ExecEvalArrayRefSubscript");
diff --git a/src/backend/jit/llvm/llvmjit_deform.c b/src/backend/jit/llvm/llvmjit_deform.c
index 59e38d2d955..e430cd9eda4 100644
--- a/src/backend/jit/llvm/llvmjit_deform.c
+++ b/src/backend/jit/llvm/llvmjit_deform.c
@@ -31,7 +31,7 @@
  * Create a function that deforms a tuple of type desc up to natts columns.
  */
 LLVMValueRef
-slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
+slot_compile_deform(LLVMJitContext *context, TupleDesc desc, const TupleTableSlotOps *ops, int natts)
 {
 	char	   *funcname;
 
@@ -88,6 +88,16 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 
 	int			attnum;
 
+	if (ops != &TTSOpsHeapTuple && ops != &TTSOpsBufferTuple &&
+		ops != &TTSOpsMinimalTuple)
+	{
+		/*
+		 * Decline to JIT for slot types we don't know to handle, or don't
+		 * want to handle (say virtual slots).
+		 */
+		return NULL;
+	}
+
 	mod = llvm_mutable_module(context);
 
 	funcname = llvm_expand_funcname(context, "deform");
@@ -166,14 +176,44 @@ slot_compile_deform(LLVMJitContext *context, TupleDesc desc, int natts)
 	v_tts_nulls =
 		l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_ISNULL,
 						  "tts_ISNULL");
-
-	v_slotoffp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_OFF, "");
 	v_flagsp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_FLAGS, "");
 	v_nvalidp = LLVMBuildStructGEP(b, v_slot, FIELDNO_TUPLETABLESLOT_NVALID, "");
 
-	v_tupleheaderp =
-		l_load_struct_gep(b, v_slot, FIELDNO_TUPLETABLESLOT_TUPLE,
-						  "tupleheader");
+	if (ops == &TTSOpsHeapTuple || ops == &TTSOpsBufferTuple)
+	{
+		LLVMValueRef v_heapslot;
+
+		v_heapslot =
+			LLVMBuildBitCast(b,
+							 v_slot,
+							 l_ptr(StructHeapTupleTableSlot),
+							 "heapslot");
+		v_slotoffp = LLVMBuildStructGEP(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_OFF, "");
+		v_tupleheaderp =
+			l_load_struct_gep(b, v_heapslot, FIELDNO_HEAPTUPLETABLESLOT_TUPLE,
+							  "tupleheader");
+
+	}
+	else if (ops == &TTSOpsMinimalTuple)
+	{
+		LLVMValueRef v_minimalslot;
+
+		v_minimalslot =
+			LLVMBuildBitCast(b,
+							 v_slot,
+							 l_ptr(StructMinimalTupleTableSlot),
+							 "minimalslotslot");
+		v_slotoffp = LLVMBuildStructGEP(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_OFF, "");
+		v_tupleheaderp =
+			l_load_struct_gep(b, v_minimalslot, FIELDNO_MINIMALTUPLETABLESLOT_TUPLE,
+							  "tupleheader");
+	}
+	else
+	{
+		/* should've returned at the start of the function */
+		pg_unreachable();
+	}
+
 	v_tuplep =
 		l_load_struct_gep(b, v_tupleheaderp, FIELDNO_HEAPTUPLEDATA_DATA,
 						  "tuple");
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 63b921517c6..f3414ef9caf 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -324,6 +324,7 @@ llvm_compile_expr(ExprState *state)
 					{
 						l_jit_deform =
 							slot_compile_deform(context, desc,
+												tts_cb,
 												op->d.fetch.last_var);
 					}
 
@@ -344,7 +345,7 @@ llvm_compile_expr(ExprState *state)
 						params[1] = l_int32_const(op->d.fetch.last_var);
 
 						LLVMBuildCall(b,
-									  llvm_get_decl(mod, FuncSlotGetsomeattrs),
+									  llvm_get_decl(mod, FuncSlotGetsomeattrsInt),
 									  params, lengthof(params), "");
 					}
 
diff --git a/src/backend/jit/llvm/llvmjit_types.c b/src/backend/jit/llvm/llvmjit_types.c
index 855a6977ee5..2df1882b750 100644
--- a/src/backend/jit/llvm/llvmjit_types.c
+++ b/src/backend/jit/llvm/llvmjit_types.c
@@ -59,6 +59,8 @@ FunctionCallInfoData StructFunctionCallInfoData;
 HeapTupleData StructHeapTupleData;
 MemoryContextData StructMemoryContextData;
 TupleTableSlot StructTupleTableSlot;
+HeapTupleTableSlot StructHeapTupleTableSlot;
+MinimalTupleTableSlot StructMinimalTupleTableSlot;
 struct tupleDesc StructtupleDesc;
 
 
@@ -97,7 +99,7 @@ void	   *referenced_functions[] =
 {
 	strlen,
 	varsize_any,
-	slot_getsomeattrs,
+	slot_getsomeattrs_int,
 	slot_getmissingattrs,
 	MakeExpandedObjectReadOnlyInternal,
 	ExecEvalArrayRefSubscript,
diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h
index 97d240fdbb0..1867a70f6f3 100644
--- a/src/include/access/htup_details.h
+++ b/src/include/access/htup_details.h
@@ -835,7 +835,5 @@ extern MinimalTuple minimal_tuple_from_heap_tuple(HeapTuple htup);
 extern size_t varsize_any(void *p);
 extern HeapTuple heap_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
 extern MinimalTuple minimal_expand_tuple(HeapTuple sourceTuple, TupleDesc tupleDesc);
-struct TupleTableSlot;
-extern void slot_deform_tuple(struct TupleTableSlot *slot, int natts);
 
 #endif							/* HTUP_DETAILS_H */
diff --git a/src/include/executor/executor.h b/src/include/executor/executor.h
index 4f156f4a5e7..8b48a23d13e 100644
--- a/src/include/executor/executor.h
+++ b/src/include/executor/executor.h
@@ -249,6 +249,7 @@ extern List *ExecInitExprList(List *nodes, PlanState *parent);
 extern ExprState *ExecBuildAggTrans(AggState *aggstate, struct AggStatePerPhaseData *phase,
 				  bool doSort, bool doHash);
 extern ExprState *ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
+					   const TupleTableSlotOps *lops, const TupleTableSlotOps *rops,
 					   int numCols,
 					   AttrNumber *keyColIdx,
 					   Oid *eqfunctions,
diff --git a/src/include/executor/tuptable.h b/src/include/executor/tuptable.h
index a6f6084f0a9..f78853488a9 100644
--- a/src/include/executor/tuptable.h
+++ b/src/include/executor/tuptable.h
@@ -65,7 +65,7 @@
  * ie, only as needed.  This serves to avoid repeated extraction of data
  * from the physical tuple.
  *
- * A TupleTableSlot can also be "empty", indicated by flag TTS_EMPTY set in
+ * A TupleTableSlot can also be "empty", indicated by flag TTS_FLAG_EMPTY set in
  * tts_flags, holding no valid data.  This is the only valid state for a
  * freshly-created slot that has not yet had a tuple descriptor assigned to it.
  * In this state, TTS_SHOULDFREE should not be set in tts_flag, tts_tuple must
@@ -116,25 +116,22 @@
 #define			TTS_FLAG_EMPTY			(1 << 1)
 #define TTS_EMPTY(slot)	(((slot)->tts_flags & TTS_FLAG_EMPTY) != 0)
 
-/* should pfree tts_tuple? */
+/* should pfree tuple "owned" by the slot? */
 #define			TTS_FLAG_SHOULDFREE		(1 << 2)
 #define TTS_SHOULDFREE(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREE) != 0)
 
-/* should pfree tts_mintuple? */
-#define			TTS_FLAG_SHOULDFREEMIN	(1 << 3)
-#define TTS_SHOULDFREEMIN(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREEMIN) != 0)
-
 /* saved state for slot_deform_tuple */
-#define			TTS_FLAG_SLOW		(1 << 4)
+#define			TTS_FLAG_SLOW		(1 << 3)
 #define TTS_SLOW(slot) (((slot)->tts_flags & TTS_FLAG_SLOW) != 0)
 
 /* fixed tuple descriptor */
-#define			TTS_FLAG_FIXED		(1 << 5)
+#define			TTS_FLAG_FIXED		(1 << 4)
 #define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
 
 struct TupleTableSlotOps;
 typedef struct TupleTableSlotOps TupleTableSlotOps;
 
+/* virtual or base type */
 typedef struct TupleTableSlot
 {
 	NodeTag		type;
@@ -142,26 +139,98 @@ typedef struct TupleTableSlot
 	uint16		tts_flags;		/* Boolean states */
 #define FIELDNO_TUPLETABLESLOT_NVALID 2
 	AttrNumber	tts_nvalid;		/* # of valid values in tts_values */
-#define FIELDNO_TUPLETABLESLOT_TUPLE 3
-	HeapTuple	tts_tuple;		/* physical tuple, or NULL if virtual */
 	const TupleTableSlotOps *const tts_cb; /* implementation of slot */
-#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 5
+#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
 	TupleDesc	tts_tupleDescriptor;	/* slot's tuple descriptor */
-	MemoryContext tts_mcxt;		/* slot itself is in this context */
-	Buffer		tts_buffer;		/* tuple's buffer, or InvalidBuffer */
-#define FIELDNO_TUPLETABLESLOT_OFF 8
-	uint32		tts_off;		/* saved state for slot_deform_tuple */
-#define FIELDNO_TUPLETABLESLOT_VALUES 9
+#define FIELDNO_TUPLETABLESLOT_VALUES 5
 	Datum	   *tts_values;		/* current per-attribute values */
-#define FIELDNO_TUPLETABLESLOT_ISNULL 10
+#define FIELDNO_TUPLETABLESLOT_ISNULL 6
 	bool	   *tts_isnull;		/* current per-attribute isnull flags */
-	MinimalTuple tts_mintuple;	/* minimal tuple, or NULL if none */
-	HeapTupleData tts_minhdr;	/* workspace for minimal-tuple-only case */
+	MemoryContext tts_mcxt;		/* slot itself is in this context */
 } TupleTableSlot;
 
 /* routines for a TupleTableSlot implementation */
 struct TupleTableSlotOps
 {
+	/* Minimum size of the slot */
+	size_t			base_slot_size;
+
+	/* Initialization. */
+	void (*init)(TupleTableSlot *slot);
+
+	/* Destruction. */
+	void (*release)(TupleTableSlot *slot);
+
+	/*
+	 * Clear the contents of the slot. Only the contents are expected to be
+	 * cleared and not the tuple descriptor. Typically an implementation of
+	 * this callback should free the memory allocated for the tuple contained
+	 * in the slot.
+	 */
+	void (*clear)(TupleTableSlot *slot);
+
+	/*
+	 * Fill up first natts entries of tts_values and tts_isnull arrays with
+	 * values from the tuple contained in the slot. The function may be called
+	 * with natts more than the number of attributes available in the tuple,
+	 * in which case it should set tts_nvalid to the number of returned
+	 * columns.
+	 */
+	void (*getsomeattrs)(TupleTableSlot *slot, int natts);
+
+	/*
+	 * Returns value of the given system attribute as a datum and sets isnull
+	 * to false, if it's not NULL. Throws an error if the slot type does not
+	 * support system attributes.
+	 */
+	Datum (*getsysattr)(TupleTableSlot *slot, int attnum, bool *isnull);
+
+	/*
+	 * Make the contents of the slot solely depend on the slot, and not on
+	 * underlying resources (like another memory context, buffers, etc).
+	 */
+	void (*materialize)(TupleTableSlot *slot);
+
+	/*
+	 * Copy the contents of the source slot into the destination slot's own
+	 * context. Invoked using callback of the destination slot.
+	 */
+	void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
+
+	/*
+	 * Return a heap tuple "owned" by the slot. It is slot's responsibility to
+	 * free the memory consumed by the heap tuple. If the slot can not "own" a
+	 * heap tuple, it should not implement this callback and should set it as
+	 * NULL.
+	 */
+	HeapTuple (*get_heap_tuple)(TupleTableSlot *slot);
+
+	/*
+	 * Return a minimal tuple "owned" by the slot. It is slot's responsibility
+	 * to free the memory consumed by the minimal tuple. If the slot can not
+	 * "own" a minimal tuple, it should not implement this callback and should
+	 * set it as NULL.
+	 */
+	MinimalTuple (*get_minimal_tuple)(TupleTableSlot *slot);
+
+	/*
+	 * Return a copy of heap tuple representing the contents of the slot. The
+	 * returned heap tuple should be writable. The copy should be palloc'd in
+	 * the current memory context. The slot itself is expected to remain
+	 * undisturbed. It is *not* expected to have meaningful "system columns"
+	 * in the copy. The copy is not be "owned" by the slot i.e. the caller has
+	 * to take responsibilty to free memory consumed by the slot.
+	 */
+	HeapTuple (*copy_heap_tuple)(TupleTableSlot *slot);
+
+	/*
+	 * Return a copy of minimal tuple representing the contents of the slot.
+	 * The returned minimal tuple should be writable. The copy should be
+	 * palloc'd in the current memory context. The slot itself is expected to
+	 * remain undisturbed. The copy is not be "owned" by the slot i.e. the
+	 * caller has to take responsibilty to free memory consumed by the slot.
+	 */
+	MinimalTuple (*copy_minimal_tuple)(TupleTableSlot *slot);
 };
 
 /*
@@ -173,8 +242,44 @@ extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
 extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
 extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferTuple;
 
-#define TTS_HAS_PHYSICAL_TUPLE(slot)  \
-	((slot)->tts_tuple != NULL && (slot)->tts_tuple != &((slot)->tts_minhdr))
+#define TTS_IS_VIRTUAL(slot) ((slot)->tts_cb == &TTSOpsVirtual)
+#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_cb == &TTSOpsHeapTuple)
+#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_cb == &TTSOpsMinimalTuple)
+#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_cb == &TTSOpsBufferTuple)
+
+
+typedef struct VirtualTupleTableSlot
+{
+	TupleTableSlot base;
+	char	   *data;		/* data for materialized slots */
+} VirtualTupleTableSlot;
+
+typedef struct HeapTupleTableSlot
+{
+	TupleTableSlot base;
+#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
+	HeapTuple	tuple;		/* physical tuple */
+#define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
+	uint32		off;		/* saved state for slot_deform_tuple */
+} HeapTupleTableSlot;
+
+/* heap tuple residing in a buffer */
+typedef struct BufferHeapTupleTableSlot
+{
+	HeapTupleTableSlot base;
+	Buffer		buffer;		/* tuple's buffer, or InvalidBuffer */
+} BufferHeapTupleTableSlot;
+
+typedef struct MinimalTupleTableSlot
+{
+	TupleTableSlot base;
+#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
+	HeapTuple	tuple;		/* tuple wrapper */
+	MinimalTuple mintuple;	/* minimal tuple, or NULL if none */
+	HeapTupleData minhdr;	/* workspace for minimal-tuple-only case */
+#define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
+	uint32		off;		/* saved state for slot_deform_tuple */
+} MinimalTupleTableSlot;
 
 /*
  * TupIsNull -- is a TupleTableSlot empty?
@@ -195,39 +300,38 @@ extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
 extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
 				   TupleTableSlot *slot,
 				   bool shouldFree);
+extern void ExecForceStoreHeapTuple(HeapTuple tuple, TupleTableSlot *slot);
 extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
 						 TupleTableSlot *slot,
 						 Buffer buffer);
 extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
 					  TupleTableSlot *slot,
 					  bool shouldFree);
-extern TupleTableSlot *ExecClearTuple(TupleTableSlot *slot);
+extern void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot,
+									   bool shouldFree);
 extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
 extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
-extern HeapTuple ExecCopySlotTuple(TupleTableSlot *slot);
-extern MinimalTuple ExecCopySlotMinimalTuple(TupleTableSlot *slot);
-extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shoulFree);
+extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree);
 extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
 						  bool *shouldFree);
 extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
-extern void ExecMaterializeSlot(TupleTableSlot *slot);
-extern TupleTableSlot *ExecCopySlot(TupleTableSlot *dstslot,
-			 TupleTableSlot *srcslot);
 extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
 					 int lastAttNum);
-extern Datum slot_getattr(TupleTableSlot *slot, int attnum,
-			 bool *isnull);
-extern void slot_getsomeattrs(TupleTableSlot *slot, int attnum);
-
-/* in access/common/heaptuple.c */
-extern bool slot_attisnull(TupleTableSlot *slot, int attnum);
-extern bool slot_getsysattr(TupleTableSlot *slot, int attnum,
-				Datum *value, bool *isnull);
-extern Datum getmissingattr(TupleDesc tupleDesc,
-			   int attnum, bool *isnull);
+extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
 
 #ifndef FRONTEND
 
+/*
+ * This function forces the entries of the slot's Datum/isnull arrays to be
+ * valid at least up through the attnum'th entry.
+ */
+static inline void
+slot_getsomeattrs(TupleTableSlot *slot, int attnum)
+{
+	if (slot->tts_nvalid < attnum)
+		slot_getsomeattrs_int(slot, attnum);
+}
+
 /*
  * slot_getallattrs
  *		This function forces all the entries of the slot's Datum/isnull
@@ -240,6 +344,129 @@ slot_getallattrs(TupleTableSlot *slot)
 	slot_getsomeattrs(slot, slot->tts_tupleDescriptor->natts);
 }
 
-#endif
+
+/*
+ * slot_attisnull
+ *
+ * Detect whether an attribute of the slot is null, without actually fetching
+ * it.
+ */
+static inline bool
+slot_attisnull(TupleTableSlot *slot, int attnum)
+{
+	AssertArg(attnum > 0);
+
+	if (attnum > slot->tts_nvalid)
+		slot_getsomeattrs(slot, attnum);
+
+	return slot->tts_isnull[attnum - 1];
+}
+
+static inline Datum
+slot_getattr(TupleTableSlot *slot, int attnum,
+			 bool *isnull)
+{
+	AssertArg(attnum > 0);
+
+	if (attnum > slot->tts_nvalid)
+		slot_getsomeattrs(slot, attnum);
+
+	*isnull = slot->tts_isnull[attnum - 1];
+
+	return slot->tts_values[attnum - 1];
+}
+
+/*
+ * slot_getsysattr
+ *		This function fetches a system attribute of the slot's current tuple.
+ *		If the slot type does not contain system attributes, this will throw
+ *		an error.  Hence before calling this function, callers should make sure
+ *		that the slot type is the one that supports system attributes, namely,
+ *		heap tuple slot and buffer tuple slot.
+ */
+static inline Datum
+slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
+{
+	AssertArg(attnum < 0);		/* caller error */
+
+	/* Fetch the system attribute from the underlying tuple. */
+	return slot->tts_cb->getsysattr(slot, attnum, isnull);
+}
+
+/*
+ * ExecClearTuple
+ *
+ * A thin wrapper around calling TupleTableSlotType specific clear() method.
+ */
+static inline TupleTableSlot *
+ExecClearTuple(TupleTableSlot *slot)
+{
+	slot->tts_cb->clear(slot);
+
+	return slot;
+}
+
+/* ExecMaterializeSlot - force a slot into the "materialized" state.
+ *
+ * This causes the slot's tuple to be a local copy not dependent on any
+ * external storage (i.e. pointing into a Buffer, or having allocations in
+ * another memory context).
+ *
+ * A typical use for this operation is to prepare a computed tuple for being
+ * stored on disk.  The original data may or may not be virtual, but in any
+ * case we need a private copy for heap_insert to scribble on.
+ */
+static inline void
+ExecMaterializeSlot(TupleTableSlot *slot)
+{
+	slot->tts_cb->materialize(slot);
+}
+
+/*
+ * ExecCopySlotTuple
+ *
+ * A thin wrapper calling TupleTableSlotType specific copy_heap_tuple()
+ * method.
+ */
+static inline HeapTuple
+ExecCopySlotTuple(TupleTableSlot *slot)
+{
+	/*
+	 * sanity checks
+	 */
+	Assert(slot != NULL);
+	Assert(!TTS_EMPTY(slot));
+
+	return slot->tts_cb->copy_heap_tuple(slot);
+}
+
+/*
+ * ExecCopySlotMinimalTuple
+ *
+ * A thin wrapper around calling TupleTableSlotType specific
+ * copy_minimal_tuple() method.
+ */
+static inline MinimalTuple
+ExecCopySlotMinimalTuple(TupleTableSlot *slot)
+{
+	return slot->tts_cb->copy_minimal_tuple(slot);
+}
+
+/*
+ * ExecCopySlot
+ *
+ * A thin wrapper calling TupleTableSlotType specific copyslot callback.
+ *
+ * The caller must ensure the slots have compatible tupdescs.
+ */
+static inline TupleTableSlot *
+ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
+{
+	dstslot->tts_cb->copyslot(dstslot, srcslot);
+
+	return dstslot;
+}
+
+#endif							/* FRONTEND */
 
 #endif							/* TUPTABLE_H */
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index f3ea2492835..b4b0a16d1ae 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -65,6 +65,8 @@ extern LLVMTypeRef TypeStorageBool;
 extern LLVMTypeRef StructtupleDesc;
 extern LLVMTypeRef StructHeapTupleData;
 extern LLVMTypeRef StructTupleTableSlot;
+extern LLVMTypeRef StructHeapTupleTableSlot;
+extern LLVMTypeRef StructMinimalTupleTableSlot;
 extern LLVMTypeRef StructMemoryContextData;
 extern LLVMTypeRef StructFunctionCallInfoData;
 extern LLVMTypeRef StructExprContext;
@@ -77,7 +79,7 @@ extern LLVMTypeRef StructAggStatePerGroupData;
 extern LLVMValueRef AttributeTemplate;
 extern LLVMValueRef FuncStrlen;
 extern LLVMValueRef FuncVarsizeAny;
-extern LLVMValueRef FuncSlotGetsomeattrs;
+extern LLVMValueRef FuncSlotGetsomeattrsInt;
 extern LLVMValueRef FuncSlotGetmissingattrs;
 extern LLVMValueRef FuncMakeExpandedObjectReadOnlyInternal;
 extern LLVMValueRef FuncExecEvalArrayRefSubscript;
@@ -111,7 +113,8 @@ extern void llvm_inline(LLVMModuleRef mod);
  ****************************************************************************
  */
 extern bool llvm_compile_expr(struct ExprState *state);
-extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc, int natts);
+struct TupleTableSlotOps;
+extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDesc desc, const struct TupleTableSlotOps *ops, int natts);
 
 /*
  ****************************************************************************
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 59fb3c15833..149916093a2 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -1100,6 +1100,7 @@ typedef struct ModifyTableState
 	PlanState **mt_plans;		/* subplans (one per target rel) */
 	int			mt_nplans;		/* number of plans in the array */
 	int			mt_whichplan;	/* which one is being executed (0..n-1) */
+	TupleTableSlot** mt_scans;	/* input tuple for underlying plan */
 	ResultRelInfo *resultRelInfo;	/* per-subplan target relations */
 	ResultRelInfo *rootResultRelInfo;	/* root target relation (partitioned
 										 * table root) */
-- 
2.18.0.rc2.dirty

v14-0007-Rationalize-expression-context-reset-in-ExecModi.patchtext/x-diff; charset=us-asciiDownload
From 9126f6f737828295947f9b3d82dc5174f2ff64b4 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Tue, 13 Nov 2018 12:18:25 -0800
Subject: [PATCH v14 7/7] Rationalize expression context reset in
 ExecModifyTable().

The current pattern of reseting expressions both in
ExecProcessReturning() and ExecOnConflictUpdate() makes it harder than
necessary to reason about memory lifetimes.  It also requires
materializing slots unnecessarily, although this patch doesn't take
advantage of the fact that that's not necessary anymore.

Instead reset the expression context once for each input tuple.

Author: Ashutosh Bapat
Discussion: https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
---
 src/backend/executor/nodeModifyTable.c | 22 +++++++++-------------
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/src/backend/executor/nodeModifyTable.c b/src/backend/executor/nodeModifyTable.c
index d29162bab79..71074ebe120 100644
--- a/src/backend/executor/nodeModifyTable.c
+++ b/src/backend/executor/nodeModifyTable.c
@@ -163,12 +163,6 @@ ExecProcessReturning(ResultRelInfo *resultRelInfo,
 	ProjectionInfo *projectReturning = resultRelInfo->ri_projectReturning;
 	ExprContext *econtext = projectReturning->pi_exprContext;
 
-	/*
-	 * Reset per-tuple memory context to free any expression evaluation
-	 * storage allocated in the previous cycle.
-	 */
-	ResetExprContext(econtext);
-
 	/* Make tuple and any needed join variables available to ExecProject */
 	if (tupleSlot)
 		econtext->ecxt_scantuple = tupleSlot;
@@ -1453,13 +1447,7 @@ ExecOnConflictUpdate(ModifyTableState *mtstate,
 			elog(ERROR, "unrecognized heap_lock_tuple status: %u", test);
 	}
 
-	/*
-	 * Success, the tuple is locked.
-	 *
-	 * Reset per-tuple memory context to free any expression evaluation
-	 * storage allocated in the previous cycle.
-	 */
-	ResetExprContext(econtext);
+	/* Success, the tuple is locked. */
 
 	/*
 	 * Verify that the tuple is visible to our MVCC snapshot if the current
@@ -2028,6 +2016,14 @@ ExecModifyTable(PlanState *pstate)
 		 */
 		ResetPerTupleExprContext(estate);
 
+		/*
+		 * Reset per-tuple memory context used for processing on conflict and
+		 * returning clauses, to free any expression evaluation storage
+		 * allocated in the previous cycle.
+		 */
+		if (pstate->ps_ExprContext)
+			ResetExprContext(pstate->ps_ExprContext);
+
 		planSlot = ExecProcNode(subplanstate);
 
 		if (TupIsNull(planSlot))
-- 
2.18.0.rc2.dirty

#42Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#41)
Re: TupleTableSlot abstraction

Hi,

On 2018-11-13 15:30:21 -0800, Andres Freund wrote:

What I'm now planning to do is to go through the big comment in
tuptable.h and update that to the new world. While I'm not convinced
that that that's the best place for it, it needs to be accurate.

Furthermore:
- More comment polishing
- I'll probably split the commits up a bit further (particulary JIT
ignoring virtual tuple slots, inlining the hot path of
slot_getsomeattrs())
- serious commit message polishing

I've done all of that now, and pushed it. Thanks Ashutosh, Amit
Khandekar and everyone else.

On to pluggable storage...

Regards,

Andres

#43Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Andres Freund (#41)
Re: TupleTableSlot abstraction

On Wed, 14 Nov 2018 at 05:00, Andres Freund <andres@anarazel.de> wrote:

After this, I hope Amit Khandekar will rebase a patch he's sent me
internally that converts triggers to use slots. I'll work on rebasing
the pluggable storage patch ontop of this.

Shared this patch in a separate mail thread :
/messages/by-id/CAJ3gD9fjpoPHSHB-Ufj7ciT8nV0JSA2gdJUdtxo-bMyPrpjk=Q@mail.gmail.com
--
Thanks,
-Amit Khandekar
EnterpriseDB Corporation
The Postgres Database Company

#44Jeff Janes
jeff.janes@gmail.com
In reply to: Andres Freund (#42)
1 attachment(s)
Re: TupleTableSlot abstraction

On Fri, Nov 16, 2018 at 7:46 PM Andres Freund <andres@anarazel.de> wrote:

Hi,

On 2018-11-13 15:30:21 -0800, Andres Freund wrote:

What I'm now planning to do is to go through the big comment in
tuptable.h and update that to the new world. While I'm not convinced
that that that's the best place for it, it needs to be accurate.

Furthermore:
- More comment polishing
- I'll probably split the commits up a bit further (particulary JIT
ignoring virtual tuple slots, inlining the hot path of
slot_getsomeattrs())
- serious commit message polishing

I've done all of that now, and pushed it. Thanks Ashutosh, Amit
Khandekar and everyone else.

Hi Andres and all,

This commit 763f2edd92095b1ca2 "Rejigger materializing and fetching a
HeapTuple from a slot" introduces a memory leak into the ExecutorState
context which is invoked by this statement:

CREATE TABLE tbloom AS
SELECT
(random() * 1000000)::int as i1,
(random() * 1000000)::int as i2,
(random() * 1000000)::int as i3,
(random() * 1000000)::int as i4,
(random() * 1000000)::int as i5,
(random() * 1000000)::int as i6
FROM
generate_series(1,50000000);

By blind analogy to the changes made to matview.c, I think that createas.c
is missing a heap_freetuple, as attached.

It fixes the leak, and still passes "make check".
Cheers,

Jeff

Attachments:

createas_leak_fix.patchapplication/octet-stream; name=createas_leak_fix.patchDownload
diff --git a/src/backend/commands/createas.c b/src/backend/commands/createas.c
index 2bc8f92..6517ecb 100644
--- a/src/backend/commands/createas.c
+++ b/src/backend/commands/createas.c
@@ -587,6 +587,9 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
 
 	/* We know this is a newly created relation, so there are no indexes */
 
+	/* Free the copied tuple. */
+	heap_freetuple(tuple);
+
 	return true;
 }
 
#45Michael Paquier
michael@paquier.xyz
In reply to: Jeff Janes (#44)
Re: TupleTableSlot abstraction

On Sat, Feb 16, 2019 at 05:07:44PM -0500, Jeff Janes wrote:

By blind analogy to the changes made to matview.c, I think that createas.c
is missing a heap_freetuple, as attached.

I think that you are right. CTAS and materialized views share a lot
when it comes to relation creation and initial table loading. I have
reproduced the leak and could notice that your fix is correct. So
committed.
--
Michael

#46Andres Freund
andres@anarazel.de
In reply to: Michael Paquier (#45)
Re: TupleTableSlot abstraction

Hi,

On 2019-02-27 14:21:52 +0900, Michael Paquier wrote:

On Sat, Feb 16, 2019 at 05:07:44PM -0500, Jeff Janes wrote:

By blind analogy to the changes made to matview.c, I think that createas.c
is missing a heap_freetuple, as attached.

First, sorry to have been slow answering. I was whacking around code
further modifying this, and thought I'd just solve the immediate issue
here by committing the followup work that removes getting the tuple out
of the slot entirely. That took longer than planned, so it makes sense
to commit an interim fix.

I think that you are right. CTAS and materialized views share a lot
when it comes to relation creation and initial table loading. I have
reproduced the leak and could notice that your fix is correct. So
committed.

I'm not so sure that's the architecturally correct fix however. Is it
actually guaranteed, given expanded tuples, toasting, etc, that there's
no other memory leak here? I wonder if we shouldn't work twoards using a
short lived memory context here. Note how e.g. printtup() uses a short
lived context for its work.

Greetings,

Andres Freund

#47Michael Paquier
michael@paquier.xyz
In reply to: Andres Freund (#46)
Re: TupleTableSlot abstraction

On Tue, Feb 26, 2019 at 09:42:38PM -0800, Andres Freund wrote:

I'm not so sure that's the architecturally correct fix however. Is it
actually guaranteed, given expanded tuples, toasting, etc, that there's
no other memory leak here? I wonder if we shouldn't work twoards using a
short lived memory context here. Note how e.g. printtup() uses a short
lived context for its work.

Perhaps. I got to wonder if this change would not impact code using
their own DestReceiver, resulting in similar leaks when they insert
tuples on-the-fly. Such issues can be surprising for fork an plugin
developers. I was playing a bit with some refactoring of relation
creation for CTAS in the scope of temporary matviews, and noticed this
issue on the CF list, so that was a bit annoying, and issues like that
tend to be easily forgotten..
--
Michael

#48Andres Freund
andres@anarazel.de
In reply to: Michael Paquier (#47)
Re: TupleTableSlot abstraction

Hi,

On 2019-02-27 15:34:07 +0900, Michael Paquier wrote:

On Tue, Feb 26, 2019 at 09:42:38PM -0800, Andres Freund wrote:

I'm not so sure that's the architecturally correct fix however. Is it
actually guaranteed, given expanded tuples, toasting, etc, that there's
no other memory leak here? I wonder if we shouldn't work twoards using a
short lived memory context here. Note how e.g. printtup() uses a short
lived context for its work.

Perhaps. I got to wonder if this change would not impact code using
their own DestReceiver, resulting in similar leaks when they insert
tuples on-the-fly.

Im not sure I understand. How can adding a memory context + reset to
ctas and matview receivers negatively impact other dest receivers?

I was playing a bit with some refactoring of relation creation for
CTAS in the scope of temporary matviews, and noticed this issue on the
CF list, so that was a bit annoying, and issues like that tend to be
easily forgotten..

It's been 10 days since the report, nobody pinged, and obviously I'm
working on pluggable storage, so ...

Greetings,

Andres Freund

#49Michael Paquier
michael@paquier.xyz
In reply to: Andres Freund (#48)
Re: TupleTableSlot abstraction

On Tue, Feb 26, 2019 at 10:38:45PM -0800, Andres Freund wrote:

Im not sure I understand. How can adding a memory context + reset to
ctas and matview receivers negatively impact other dest receivers?

I don't think you got my point here: imagine that a plugin use the
current receiveSlot logic from createas.c or matview.c, and forgets to
free the tuple copied. On v11, that works fine. On current HEAD,
they win silently a new leak.
--
Michael

#50Andres Freund
andres@anarazel.de
In reply to: Michael Paquier (#49)
Re: TupleTableSlot abstraction

On 2019-02-27 15:42:50 +0900, Michael Paquier wrote:

On Tue, Feb 26, 2019 at 10:38:45PM -0800, Andres Freund wrote:

Im not sure I understand. How can adding a memory context + reset to
ctas and matview receivers negatively impact other dest receivers?

I don't think you got my point here: imagine that a plugin use the
current receiveSlot logic from createas.c or matview.c, and forgets to
free the tuple copied. On v11, that works fine. On current HEAD,
they win silently a new leak.

The copy was made in intorel_receive()?