3021 option for time-ordered output from dtrace(1M)
authorAdam H. Leventhal <ahl@delphix.com>
Wed, 25 Jul 2012 19:05:31 -0400
changeset 13758 23432da34147
parent 13757 2e70a48f5fe2
child 13759 32a39c8dbb42
3021 option for time-ordered output from dtrace(1M) 3022 DTrace: keys should not affect the sort order when sorting by value 3023 it should be possible to dereference dynamic variables 3024 D integer narrowing needs some work 3025 register leak in D code generation 3026 libdtrace should set LD_NOLAZYLOAD=1 to help the pid provider Reviewed by: Bryan Cantrill <[email protected]> Reviewed by: Eric Schrock <[email protected]> Reviewed by: Matt Ahrens <[email protected]> Approved by: Garrett D'Amore <[email protected]>
usr/src/cmd/dtrace/dtrace.c
usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl
usr/src/cmd/dtrace/test/tst/common/aggs/tst.sizedkeys.d
usr/src/cmd/dtrace/test/tst/common/aggs/tst.sizedkeys.d.out
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.basics.d.out
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compcast.d
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compcast.d.out
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.complex.d
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compnarrowassign.d
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compnarrowassign.d.out
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.execcast.d
usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.execcast.d.out
usr/src/cmd/dtrace/test/tst/common/buffering/tst.fill1.d
usr/src/cmd/dtrace/test/tst/common/buffering/tst.ring3.d
usr/src/cmd/dtrace/test/tst/common/cg/err.D_NOREG.noreg.d
usr/src/cmd/dtrace/test/tst/common/cg/err.baddif.d
usr/src/cmd/dtrace/test/tst/common/env/err.D_PRAGMA_OPTSET.setfromscript.d
usr/src/cmd/dtrace/test/tst/common/env/err.D_PRAGMA_OPTSET.unsetfromscript.d
usr/src/cmd/dtrace/test/tst/common/env/tst.ld_nolazyload.ksh
usr/src/cmd/dtrace/test/tst/common/env/tst.ld_nolazyload.ksh.out
usr/src/cmd/dtrace/test/tst/common/env/tst.setenv1.ksh
usr/src/cmd/dtrace/test/tst/common/env/tst.setenv1.ksh.out
usr/src/cmd/dtrace/test/tst/common/env/tst.setenv2.ksh
usr/src/cmd/dtrace/test/tst/common/env/tst.setenv2.ksh.out
usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv1.ksh
usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv1.ksh.out
usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv2.ksh
usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv2.ksh.out
usr/src/cmd/dtrace/test/tst/common/pid/tst.newprobes.ksh
usr/src/cmd/dtrace/test/tst/common/pointers/tst.assigncast1.d
usr/src/cmd/dtrace/test/tst/common/pointers/tst.assigncast2.d
usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal.ksh
usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal2.ksh
usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal3.d
usr/src/cmd/dtrace/test/tst/common/predicates/tst.predcache.ksh
usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_DYN.bad.d
usr/src/cmd/dtrace/test/tst/common/print/tst.dyn.d
usr/src/cmd/dtrace/test/tst/common/print/tst.xlate.d
usr/src/cmd/dtrace/test/tst/common/print/tst.xlate.d.out
usr/src/cmd/dtrace/test/tst/common/printf/tst.ints.d.out
usr/src/cmd/dtrace/test/tst/common/printf/tst.signs.d
usr/src/cmd/dtrace/test/tst/common/printf/tst.signs.d.out
usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations1.d
usr/src/cmd/dtrace/test/tst/common/speculation/tst.SpecSizeVariations3.d
usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_DYN.bad.d
usr/src/cmd/dtrace/test/tst/common/trace/tst.dyn.d
usr/src/cmd/dtrace/test/tst/common/translators/man.TestTransStability.d
usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability1.ksh
usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability1.ksh.out
usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability2.ksh
usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability2.ksh.out
usr/src/lib/libdtrace/Makefile.com
usr/src/lib/libdtrace/common/dt_aggregate.c
usr/src/lib/libdtrace/common/dt_cc.c
usr/src/lib/libdtrace/common/dt_cg.c
usr/src/lib/libdtrace/common/dt_consume.c
usr/src/lib/libdtrace/common/dt_dis.c
usr/src/lib/libdtrace/common/dt_error.c
usr/src/lib/libdtrace/common/dt_errtags.h
usr/src/lib/libdtrace/common/dt_impl.h
usr/src/lib/libdtrace/common/dt_open.c
usr/src/lib/libdtrace/common/dt_options.c
usr/src/lib/libdtrace/common/dt_parser.c
usr/src/lib/libdtrace/common/dt_pq.c
usr/src/lib/libdtrace/common/dt_pq.h
usr/src/lib/libdtrace/common/dt_printf.c
usr/src/lib/libdtrace/common/dt_proc.c
usr/src/lib/libdtrace/common/dt_proc.h
usr/src/lib/libdtrace/common/dt_regset.c
usr/src/lib/libdtrace/common/dt_regset.h
usr/src/lib/libdtrace/common/dt_subr.c
usr/src/lib/libdtrace/i386/dt_isadep.c
usr/src/pkg/manifests/system-dtrace-tests.mf
usr/src/uts/common/dtrace/dtrace.c
usr/src/uts/common/sys/dtrace.h
usr/src/uts/common/sys/dtrace_impl.h
--- a/usr/src/cmd/dtrace/dtrace.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/dtrace.c	Wed Jul 25 19:05:31 2012 -0400
@@ -23,8 +23,9 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -1339,6 +1340,7 @@
 
 	(void) dtrace_setopt(g_dtp, "bufsize", "4m");
 	(void) dtrace_setopt(g_dtp, "aggsize", "4m");
+	(void) dtrace_setopt(g_dtp, "temporal", "yes");
 
 	/*
 	 * If -G is specified, enable -xlink=dynamic and -xunodefs to permit
--- a/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl	Wed Jul 25 19:05:31 2012 -0400
@@ -27,6 +27,7 @@
 
 #
 # Copyright (c) 2011, Joyent, Inc. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
 #
 require 5.8.4;
 
@@ -612,6 +613,8 @@
 die "$PNAME: failed to open $PNAME.$$.log: $!\n"
     unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
 
+$ENV{'DTRACE_DEBUG_REGSET'} = 'true';
+
 if ($opt_g) {
 	$ENV{'UMEM_DEBUG'} = 'default,verbose';
 	$ENV{'UMEM_LOGGING'} = 'fail,contents';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/aggs/tst.sizedkeys.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,35 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option quiet
+
+/*
+ * Make sure the sizes of compatible keys doesn't affect the sort order.
+ */
+
+BEGIN
+{
+	@[(int)1, 0] = sum(10);
+	@[(uint64_t)2, 0] = sum(20);
+	@[(int)3, 0] = sum(30);
+	@[(uint64_t)4, 0] = sum(40);
+	printa(@);
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/aggs/tst.sizedkeys.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,6 @@
+
+        1        0               10
+                2        0               20
+        3        0               30
+                4        0               40
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.basics.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,8 @@
+The value of i is 6
+The value of i is 18
+The value of i is 72
+The value of i is 25920
+The value of i is 935761216
+The value of i is -91738734
+The value of i is -91738729
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compcast.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,50 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Test compile-time casting between integer types of different size.
+ */
+
+#pragma D option quiet
+
+int64_t x;
+
+BEGIN
+{
+	x = (int32_t)(int16_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (int32_t)(uint16_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint32_t)(int16_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint32_t)(uint16_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	printf("\n");
+
+	x = (int16_t)(int32_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (int16_t)(uint32_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint16_t)(int32_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint16_t)(uint32_t)0xfff0;
+	printf("%16x %20d %20u\n", x, x, x);
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compcast.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,10 @@
+fffffffffffffff0                  -16 18446744073709551600
+            fff0                65520                65520
+        fffffff0           4294967280           4294967280
+            fff0                65520                65520
+
+fffffffffffffff0                  -16 18446744073709551600
+fffffffffffffff0                  -16 18446744073709551600
+            fff0                65520                65520
+            fff0                65520                65520
+
--- a/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.complex.d	Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma	ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * ASSERTION:
- * 	Complex expressions.
- *	Call complex expressions and make sure test succeeds.
- *	Match expected output in tst.complex.d.out
- *
- * SECTION: Types, Operators, and Expressions/Arithmetic Operators
- *
- */
-
-#pragma D option quiet
-
-BEGIN
-{
-	i = 0;
-	i = i++ + ++i;
-	printf("The value of i is %d\n", i);
-	i = i-- - --i;
-	printf("The value of i is %d\n", i);
-	i = i-- + ++i;
-	printf("The value of i is %d\n", i);
-	i += i++ + -- i + ++i - ++i * i ;
-	printf("The value of i is %d\n", i);
-	i -= i++ * 3;
-	printf("The value of i is %d\n", i);
-	i = i++/i--+i++-++i-++i;
-	printf("The value of i is %d\n", i);
-	exit (0);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compnarrowassign.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,36 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Test narrowing at assignment.
+ */
+
+#pragma D option quiet
+
+uint16_t x;
+uint32_t y;
+
+BEGIN
+{
+	x = 0xbeefcafe;
+	y = x;
+	printf("%x", y); /* where's the beef? */
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.compnarrowassign.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,1 @@
+cafe
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.execcast.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,52 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Test execution-time casting between integer types of different size.
+ */
+
+#pragma D option quiet
+
+int64_t x;
+
+BEGIN
+{
+	z = 0xfff0;
+
+	x = (int32_t)(int16_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (int32_t)(uint16_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint32_t)(int16_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint32_t)(uint16_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	printf("\n");
+
+	x = (int16_t)(int32_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (int16_t)(uint32_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint16_t)(int32_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+	x = (uint16_t)(uint32_t)z;
+	printf("%16x %20d %20u\n", x, x, x);
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/arithmetic/tst.execcast.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,10 @@
+fffffffffffffff0                  -16 18446744073709551600
+            fff0                65520                65520
+        fffffff0           4294967280           4294967280
+            fff0                65520                65520
+
+fffffffffffffff0                  -16 18446744073709551600
+fffffffffffffff0                  -16 18446744073709551600
+            fff0                65520                65520
+            fff0                65520                65520
+
--- a/usr/src/cmd/dtrace/test/tst/common/buffering/tst.fill1.d	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/buffering/tst.fill1.d	Wed Jul 25 19:05:31 2012 -0400
@@ -23,26 +23,29 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 /*
  * ASSERTION:
  *   Positive test for fill buffer policy.
  *
  * SECTION: Buffers and Buffering/fill Policy;
- * 	Buffers and Buffering/Buffer Sizes;
+ *	Buffers and Buffering/Buffer Sizes;
  *	Options and Tunables/bufsize;
  *	Options and Tunables/bufpolicy;
  *	Options and Tunables/statusrate
  */
 /*
- * This is a brute-force way of testing fill buffers.  We assume that each
- * printf() stores 8 bytes.  Because each fill buffer is per-CPU, we must
- * fill up our buffer in one series of enablings on a single CPU.
+ * This is a brute-force way of testing fill buffers.  We assume that
+ * each printf() stores 16 bytes (4x 32-bit words for EPID, timestamp
+ * lo, timestamp hi, and the variable i).  Because each fill buffer is
+ * per-CPU, we must fill up our buffer in one series of enablings on a
+ * single CPU.
  */
 #pragma D option bufpolicy=fill
-#pragma D option bufsize=64
+#pragma D option bufsize=128
 #pragma D option statusrate=10ms
 #pragma D option quiet
 
--- a/usr/src/cmd/dtrace/test/tst/common/buffering/tst.ring3.d	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/buffering/tst.ring3.d	Wed Jul 25 19:05:31 2012 -0400
@@ -23,8 +23,9 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 /*
  * ASSERTION:
@@ -37,19 +38,20 @@
  */
 
 /*
- * We make some regrettable assumptions about the implementation in this test.
- * First, we assume that each entry for the printf() of an int takes _exactly_
- * eight bytes (four bytes for the EPID, four bytes for the payload).  Second,
- * we assume that by allocating storage for n + 1 records, we will get exactly
- * n.  Here is why:  the final predicate that evaluates to false will reserve
- * space that it won't use.  This act of reservation will advance the wrapped
- * offset.  That record won't be subsequently used, but the wrapped offset has
- * advanced.  (And in this case, that old record is clobbered by the exit()
- * anyway.)  Thirdly:  we rely on t_cpu/cpu_id.  Finally:  we rely on being
- * able to run on the CPU that we first ran on.
+ * We make some regrettable assumptions about the implementation in this
+ * test.  First, we assume that each entry for the printf() of an int
+ * takes _exactly_ 16 bytes (4 bytes for the EPID, 8 bytes for the
+ * timestamp, 4 bytes for the payload).  Second, we assume that by
+ * allocating storage for n + 1 records, we will get exactly n.  Here is
+ * why:  the final predicate that evaluates to false will reserve space
+ * that it won't use.  This act of reservation will advance the wrapped
+ * offset.  That record won't be subsequently used, but the wrapped
+ * offset has advanced.  (And in this case, that old record is clobbered
+ * by the exit() anyway.)  Thirdly:  we rely on t_cpu/cpu_id.  Finally:
+ * we rely on being able to run on the CPU that we first ran on.
  */
 #pragma D option bufpolicy=ring
-#pragma D option bufsize=40
+#pragma D option bufsize=80
 #pragma D option quiet
 
 int n;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/cg/err.D_NOREG.noreg.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,41 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Compile some code that requires exactly 9 registers. This should run out
+ * of registers.
+ *
+ * Changes to the code generator might cause this test to succeeed in which
+ * case the code should be changed to another sequence that exhausts the
+ * available internal registers.
+ *
+ * Note that this and err.baddif.d should be kept in sync.
+ */
+
+BEGIN
+{
+	a = 4;
+	trace((a + a) * ((a + a) * ((a + a) * ((a + a) * ((a + a) *
+	    ((a + a) * (a + a)))))));
+}
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/cg/err.baddif.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,44 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Compile some code that requires exactly 9 registers. This should generate
+ * invalid DIF because the kernel will flag the fact that we're using more
+ * registers than are available internally.
+ *
+ * Changes to the code generator might cause this test to succeeed in which
+ * case the code should be changed to another sequence that exhausts the
+ * available internal registers.
+ *
+ * Note that this and err.D_NOREG.noreg.d should be kept in sync.
+ */
+
+#pragma D option iregs=9
+
+BEGIN
+{
+	a = 4;
+	trace((a + a) * ((a + a) * ((a + a) * ((a + a) * ((a + a) *
+	    ((a + a) * (a + a)))))));
+}
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/err.D_PRAGMA_OPTSET.setfromscript.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,25 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option setenv=balloon=something_bad_happens
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/err.D_PRAGMA_OPTSET.unsetfromscript.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,25 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option unsetenv=rectalexambot
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.ld_nolazyload.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Check that the LD_NOLAZYLOAD variable is set to 1 as expected.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -c 'printenv LD_NOLAZYLOAD'
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.ld_nolazyload.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,2 @@
+1
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv1.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Reset an environment variable we already know to be set.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xsetenv=LD_NOLAZYLOAD=0 -c 'printenv LD_NOLAZYLOAD'
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv1.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,2 @@
+0
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv2.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test setting a variable that we isn't already set.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xsetenv=CORPORATIONS=PEOPLE -c 'printenv CORPORATIONS'
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.setenv2.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,2 @@
+PEOPLE
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv1.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test unsetting a variable we know to be set.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xunsetenv=LD_NOLAZYLOAD -c 'printenv LD_NOLAZYLOAD'
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv1.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,1 @@
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv2.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test invalid syntax to the unsetenv option.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -Z -n doogle -xunsetenv=ed=screven -c 'true' 2>&1
+
+[[ $? -eq 1 ]] && exit 0
+
+exit 1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/env/tst.unsetenv2.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,1 @@
+dtrace: failed to set -x unsetenv: Invalid value for specified option
--- a/usr/src/cmd/dtrace/test/tst/common/pid/tst.newprobes.ksh	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pid/tst.newprobes.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -24,7 +24,9 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
 #
 
 if [ $# != 1 ]; then
@@ -49,13 +51,13 @@
 tick-1s
 /(i % 2) == 0/
 {
-	system("dtrace -c date -ln 'pid\$target::main:entry' >/dev/null");
+	system("dtrace -c date -n 'pid\$target::main:entry' >/dev/null");
 }
 
 tick-1s
 /(i % 2) == 1/
 {
-	system("dtrace -c date -ln 'pid\$target::main:return' >/dev/null");
+	system("dtrace -c date -n 'pid\$target::main:return' >/dev/null");
 }
 EOF
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/tst.assigncast1.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,28 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+	*((int *)alloca(4)) = 1;
+}
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pointers/tst.assigncast2.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+	this->a = alloca(4);
+	*((int *)this->a) = 1;
+}
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,106 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+############################################################################
+# ASSERTION:
+#	temporal option causes output to be sorted
+#
+# SECTION: Pragma
+#
+# NOTES: The temporal option has no effect on a single-CPU system, so
+#    this needs to be run on a multi-CPU system to effectively test the
+#    temporal option.
+#
+############################################################################
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+file=/tmp/out.$$
+
+rm -f $file
+
+$dtrace -o $file -c 'sleep 3' -s /dev/stdin <<EOF
+	#pragma D option quiet
+	#pragma D option temporal
+
+	BEGIN
+	{
+		@lines = count();
+		printf("0 begin\n");
+	}
+
+	END
+	{
+		/* Bump @lines every time we print a line. */
+		@lines = count();
+		printf("%u end\n", timestamp);
+		@lines = count();
+		printa("99999999999999999 lines %@u\n", @lines);
+	}
+
+	profile-97hz
+	{
+		@lines = count();
+		printf("%u\n", timestamp);
+	}
+EOF
+
+status=$?
+if [ "$status" -ne 0 ]; then
+	echo $tst: dtrace failed
+	exit $status
+fi
+
+# dtrace outputs a blank line at the end, which will sort to the beginning,
+# so use head to remove the blank line.
+head -n -1 $file > $file.2
+
+sort -n $file.2 | diff $file.2 -
+status=$?
+if [ "$status" -ne 0 ]; then
+	echo $tst: output is not sorted
+	exit $status
+fi
+
+head -n 1 $file.2 | grep begin >/dev/null
+status=$?
+if [ "$status" -ne 0 ]; then
+	echo $tst: begin probe did not fire
+	exit $status
+fi
+
+tail -n 2 $file.2 | grep end >/dev/null
+status=$?
+if [ "$status" -ne 0 ]; then
+	echo $tst: end probe did not fire
+	exit $status
+fi
+
+if [ $(tail -n 1 $file.2 | cut -f3 -d ' ') -ne \
+    $(wc -l $file.2) ]; then
+	echo $tst: incorrect number of lines output
+	exit 1
+fi
+
+exit $status
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal2.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,102 @@
+#!/bin/ksh -p
+#
+# CDDL HEADER START
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+############################################################################
+# ASSERTION:
+#	temporal option causes output to be sorted, even when some
+#	buffers are empty
+#
+# SECTION: Pragma
+#
+# NOTES: The temporal option has no effect on a single-CPU system, so
+#    this needs to be run on a multi-CPU system to effectively test the
+#    temporal option.
+#
+############################################################################
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+file=/tmp/out.$$
+
+rm -f $file
+
+$dtrace -o $file -s /dev/stdin <<EOF
+	#pragma D option quiet
+	#pragma D option destructive
+	#pragma D option temporal
+	#pragma D option switchrate=1000hz
+
+	/*
+	 * Use two enablings of the same probe, so that cpu 0 will always
+	 * record its data just a little bit before the other cpus.
+	 * We don't want to use the chill() action in the same enabling
+	 * that we record the timestamp, because chill() causes the
+	 * timestamp to be re-read, and thus not match the timestamp
+	 * which libdtrace uses to sort the records.
+	 */
+
+	profile-401
+	/cpu == 0/
+	{
+		printf("%d\n", timestamp);
+	}
+
+	profile-401
+	/cpu != 0/
+	{
+		chill(1000); /* one microsecond */
+	}
+
+	profile-401
+	/cpu != 0/
+	{
+		printf("%d\n", timestamp);
+	}
+
+	tick-1s
+	/k++ == 10/
+	{
+		printf("%d\n", timestamp);
+		exit(0);
+	}
+EOF
+
+status=$?
+if [ "$status" -ne 0 ]; then
+	echo $tst: dtrace failed
+	exit $status
+fi
+
+# dtrace outputs a blank line at the end, which will sort to the beginning,
+# so use grep to remove the blank line.
+head -n -1 $file > $file.2
+
+sort -n $file.2 | diff $file.2 -
+status=$?
+if [ "$status" -ne 0 ]; then
+	echo $tst: output is not sorted
+	exit $status
+fi
+
+exit $status
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/pragma/tst.temporal3.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * This test excercises the "remnant" handling of the temporal option.
+ * At the end of one pass of retrieving and printing data from all CPUs,
+ * some unprocessed data will remain, because its timestamp is after the
+ * time covered by all CPUs' buffers.  This unprocessed data is
+ * rearranged in a more space-efficient manner.  If this is done
+ * incorrectly, an alignment error may occur.  To test this, we use a
+ * high-frequency probe so that data will be recorded in subsequent
+ * CPU's buffers after the first CPU's buffer is obtained.  The
+ * combination of data traced here (a 8-byte value and a 4-byte value)
+ * is effective to cause alignment problems with an incorrect
+ * implementation.
+ *
+ * This test needs to be run on a multi-CPU system to be effective.
+ */
+
+#pragma D option quiet
+#pragma D option temporal
+
+profile-4997
+{
+	printf("%u %u", 1ULL, 2);
+}
+
+tick-1
+/i++ == 10/
+{
+	exit(0);
+}
--- a/usr/src/cmd/dtrace/test/tst/common/predicates/tst.predcache.ksh	Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-
-#
-# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
-# ident	"%Z%%M%	%I%	%E% SMI"
-
-unload()
-{
-	#
-	# Get the list of services whose processes have USDT probes.  Ideally
-	# it would be possible to unload the fasttrap provider while USDT
-	# probes exist -- once that fix is integrated, this hack can go away
-	# We create two lists -- one of regular SMF services and one of legacy
-	# services -- since each must be enabled and disabled using a specific
-	# mechanism.
-	#
-	pids=$(dtrace -l | \
-	    perl -ne 'print "$1\n" if (/^\s*\S+\s+\S*\D(\d+)\s+/);' | \
-	    sort | uniq | tr '\n' ',')
-
-	ctids=$(ps -p $pids -o ctid | tail +2 | sort | uniq)
-	svcs=
-	lrcs=
-
-	for ct in $ctids
-	do
-		line=$(svcs -o fmri,ctid | grep " $ct\$")
-		svc=$(echo $line | cut -d' ' -f1)
-
-		if [[ $(svcs -Ho STA $svc) == "LRC" ]]; then
-			lrc=$(svcs -Ho SVC $svc | tr _ '?')
-			lrcs="$lrcs $lrc"
-		else
-			svcs="$svcs $svc"
-	fi
-	done
-
-	for svc in $svcs
-	do
-		svcadm disable -ts $svc
-	done
-
-	for lrc in $lrcs
-	do
-		#
-		# Does it seem a little paternalistic that lsvcrun requires
-		# this environment variable to be set? I'd say so...
-		#
-		SMF_RESTARTER=svc:/system/svc/restarter:default \
-		    /lib/svc/bin/lsvcrun $lrc stop
-	done
-
-	modunload -i 0
-	modunload -i 0
-	modunload -i 0
-	modinfo | grep dtrace
-	success=$?
-
-	for svc in $svcs
-	do
-		svcadm enable -ts $svc
-	done
-
-	for lrc in $lrcs
-	do
-		SMF_RESTARTER=svc:/system/svc/restarter:default \
-		    /lib/svc/bin/lsvcrun $lrc start
-	done
-
-	if [ ! $success ]; then
-		echo $tst: could not unload dtrace
-		exit 1
-	fi
-}
-
-script1()
-{
-	$dtrace -s /dev/stdin <<EOF
-	syscall:::entry
-	/pid != $ppid/
-	{
-		@a[probefunc] = count();
-	}
-
-	tick-1sec
-	/i++ == 5/
-	{
-		exit(0);
-	}
-EOF
-}
-
-script2()
-{
-	$dtrace -s /dev/stdin <<EOF
-
-	#pragma D option statusrate=1ms
-
-	syscall:::entry
-	/pid == $ppid/
-	{
-		ttl++;
-	}
-
-	tick-1sec
-	/i++ == 5/
-	{
-		exit(2);
-	}
-
-	END
-	/ttl/
-	{
-		printf("success; ttl is %d", ttl);
-		exit(0);
-	}
-
-	END
-	/ttl == 0/
-	{
-		printf("error -- total should be non-zero");
-		exit(1);
-	}
-EOF
-}
-
-if [ $# != 1 ]; then
-	echo expected one argument: '<'dtrace-path'>'
-	exit 2
-fi
-
-ppid=$$
-dtrace=$1
-
-unload
-script1 &
-child=$!
-
-let waited=0
-
-while [ "$waited" -lt 5 ]; do
-	seconds=`date +%S`
-
-	if [ "$seconds" -ne "$last" ]; then
-		last=$seconds
-		let waited=waited+1
-	fi
-done
-
-wait $child
-status=$?
-
-if [ "$status" -ne 0 ]; then
-	echo $tst: first dtrace failed
-	exit $status
-fi
-
-unload
-script2 &
-child=$!
-
-let waited=0
-
-while [ "$waited" -lt 10 ]; do
-	seconds=`date +%S`
-
-	if [ "$seconds" -ne "$last" ]; then
-		last=$seconds
-		let waited=waited+1
-	fi
-done
-
-wait $child
-status=$?
-
-exit $status
--- a/usr/src/cmd/dtrace/test/tst/common/print/err.D_PRINT_DYN.bad.d	Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
-
-BEGIN
-{
-	print(*curpsinfo);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/print/tst.dyn.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,28 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+	print(*curpsinfo);
+}
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/print/tst.xlate.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,42 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#pragma D option quiet
+
+typedef struct pancakes {
+	int i;
+	string s;
+	timespec_t t;
+} pancakes_t;
+
+translator pancakes_t < void *V > {
+	i = 2 * 10;
+	s = strjoin("I like ", "pancakes");
+	t = *(timespec_t *)`dtrace_zero;
+};
+
+BEGIN
+{
+	print(*(xlate < pancakes_t * > ((void *)NULL)));
+}
+
+BEGIN
+{
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/print/tst.xlate.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,8 @@
+pancakes_t {
+    int i = 0x14
+    string s = [ "I like pancakes" ]
+    timespec_t t = {
+        time_t tv_sec = 0
+        long tv_nsec = 0
+    }
+}
--- a/usr/src/cmd/dtrace/test/tst/common/printf/tst.ints.d.out	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/printf/tst.ints.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -1,6 +1,6 @@
 
-239
-52719
+-17
+-12817
 -1867788817
 1311768467294899695
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/printf/tst.signs.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,38 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Check %d v. %i v. %u.
+ */
+
+#pragma D option quiet
+
+uint16_t x;
+int16_t y;
+
+BEGIN
+{
+	x = 0xffffffff;
+	y = 0xffffffff;
+
+	printf("%d %i %u\n", x, x, x);
+	printf("%d %i %u\n", y, y, y);
+
+	exit(0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/printf/tst.signs.d.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,3 @@
+65535 -1 65535
+-1 -1 65535
+
--- a/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations1.d	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/speculation/err.BufSizeVariations1.d	Wed Jul 25 19:05:31 2012 -0400
@@ -24,7 +24,10 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 
 /*
  * ASSERTION:
@@ -35,17 +38,10 @@
  *
  * NOTES: This test behaves differently depending on the values
  * assigned to bufsize.
- * 1. 0 > bufsize.
- * 2. 0 == bufsize.
- * 3. 0 < bufsize <= 7
- * 4. 8 <= bufsize <= 31
- * 5. 32 <= bufsize <= 47
- * 6. 48 <= bufsize <= 71
- * 7. 72 <= bufsize
  */
 
 #pragma D option quiet
-#pragma D option bufsize=41
+#pragma D option bufsize=49
 
 BEGIN
 {
--- a/usr/src/cmd/dtrace/test/tst/common/speculation/tst.SpecSizeVariations3.d	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/speculation/tst.SpecSizeVariations3.d	Wed Jul 25 19:05:31 2012 -0400
@@ -24,7 +24,10 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 /*
  * ASSERTION:
  * Verify the behavior of speculations with changes in specsize.
@@ -35,7 +38,7 @@
  */
 
 #pragma D option quiet
-#pragma D option specsize=40
+#pragma D option specsize=48
 
 BEGIN
 {
--- a/usr/src/cmd/dtrace/test/tst/common/trace/err.D_TRACE_DYN.bad.d	Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,29 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright (c) 2011 by Delphix. All rights reserved.
- */
-
-BEGIN
-{
-	trace(*curpsinfo);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/trace/tst.dyn.d	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,28 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+BEGIN
+{
+	trace(*curpsinfo);
+}
+
+BEGIN
+{
+	exit(0);
+}
--- a/usr/src/cmd/dtrace/test/tst/common/translators/man.TestTransStability.d	Tue Jul 24 03:56:16 2012 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,61 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-
-/*
- * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * ASSERTION:
- * The D inline translation mechanism can be used to facilitate stable
- * translations.
- *
- * SECTION: Translators/ Translator Declarations
- * SECTION: Translators/ Translate Operator
- * SECTION: Translators/Stable Translations
- *
- * NOTES: Uncomment the pragma that explicitly resets the attributes of
- * myinfo identifier to Stable/Stable/Common from Private/Private/Unknown.
- * Run the program with and without the comments as:
- * /usr/sbin/dtrace -vs man.TestTransStability.d
- */
-
-#pragma D option quiet
-
-inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
-
-/*
-#pragma D attributes Stable/Stable/Common myinfo
-*/
-
-BEGIN
-{
-	trace(myinfo->pr_flag);
-	exit(0);
-}
-
-ERROR
-{
-	exit(1);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability1.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,62 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test the output for stable translations.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -v -s /dev/stdin <<EOF
+
+#pragma D option quiet
+
+inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
+
+#pragma D attributes Stable/Stable/Common myinfo
+
+BEGIN
+{
+	this->a = myinfo->pr_flag;
+	exit(0);
+}
+
+BEGIN
+{
+	exit(1);
+}
+EOF
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability1.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,14 @@
+
+Stability attributes for script /dev/stdin:
+
+	Minimum Probe Description Attributes
+		Identifier Names: Unstable
+		Data Semantics:   Unstable
+		Dependency Class: Common
+
+	Minimum Statement Attributes
+		Identifier Names: Stable
+		Data Semantics:   Stable
+		Dependency Class: Common
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability2.ksh	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,60 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+#
+# Test the output of unstable translations.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+$dtrace -v -s /dev/stdin <<EOF
+
+#pragma D option quiet
+
+inline lwpsinfo_t *myinfo = xlate < lwpsinfo_t *> (curthread);
+
+BEGIN
+{
+	this->a = myinfo->pr_flag;
+	exit(0);
+}
+
+BEGIN
+{
+	exit(1);
+}
+EOF
+
+exit $?
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/translators/tst.TestTransStability2.ksh.out	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,14 @@
+
+Stability attributes for script /dev/stdin:
+
+	Minimum Probe Description Attributes
+		Identifier Names: Unstable
+		Data Semantics:   Unstable
+		Dependency Class: Common
+
+	Minimum Statement Attributes
+		Identifier Names: Private
+		Data Semantics:   Private
+		Dependency Class: Unknown
+
+
--- a/usr/src/lib/libdtrace/Makefile.com	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/Makefile.com	Wed Jul 25 19:05:31 2012 -0400
@@ -20,7 +20,7 @@
 #
 #
 # Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright (c) 2011 by Delphix. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
 #
 
 LIBRARY = libdtrace.a
@@ -52,6 +52,7 @@
 	dt_parser.c \
 	dt_pcb.c \
 	dt_pid.c \
+	dt_pq.c \
 	dt_pragma.c \
 	dt_print.c \
 	dt_printf.c \
--- a/usr/src/lib/libdtrace/common/dt_aggregate.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_aggregate.c	Wed Jul 25 19:05:31 2012 -0400
@@ -26,6 +26,7 @@
 
 /*
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <stdlib.h>
@@ -884,33 +885,14 @@
 	caddr_t rdata = rh->dtahe_data.dtada_data;
 	dtrace_recdesc_t *lrec, *rrec;
 	int64_t *laddr, *raddr;
-	int rval, i;
-
-	if ((rval = dt_aggregate_hashcmp(lhs, rhs)) != 0)
-		return (rval);
+	int rval;
 
-	if (lagg->dtagd_nrecs > ragg->dtagd_nrecs)
-		return (DT_GREATERTHAN);
-
-	if (lagg->dtagd_nrecs < ragg->dtagd_nrecs)
-		return (DT_LESSTHAN);
+	assert(lagg->dtagd_nrecs == ragg->dtagd_nrecs);
 
-	for (i = 0; i < lagg->dtagd_nrecs; i++) {
-		lrec = &lagg->dtagd_rec[i];
-		rrec = &ragg->dtagd_rec[i];
-
-		if (lrec->dtrd_offset < rrec->dtrd_offset)
-			return (DT_LESSTHAN);
+	lrec = &lagg->dtagd_rec[lagg->dtagd_nrecs - 1];
+	rrec = &ragg->dtagd_rec[ragg->dtagd_nrecs - 1];
 
-		if (lrec->dtrd_offset > rrec->dtrd_offset)
-			return (DT_GREATERTHAN);
-
-		if (lrec->dtrd_action < rrec->dtrd_action)
-			return (DT_LESSTHAN);
-
-		if (lrec->dtrd_action > rrec->dtrd_action)
-			return (DT_GREATERTHAN);
-	}
+	assert(lrec->dtrd_action == rrec->dtrd_action);
 
 	laddr = (int64_t *)(uintptr_t)(ldata + lrec->dtrd_offset);
 	raddr = (int64_t *)(uintptr_t)(rdata + rrec->dtrd_offset);
--- a/usr/src/lib/libdtrace/common/dt_cc.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_cc.c	Wed Jul 25 19:05:31 2012 -0400
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -663,63 +663,48 @@
 dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
 {
 	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
+	boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
+	const char *act = istrace ?  "trace" : "print";
 
 	if (dt_node_is_void(dnp->dn_args)) {
-		dnerror(dnp->dn_args, D_TRACE_VOID,
-		    "trace( ) may not be applied to a void expression\n");
+		dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
+		    "%s( ) may not be applied to a void expression\n", act);
 	}
 
-	if (dt_node_is_dynamic(dnp->dn_args)) {
-		dnerror(dnp->dn_args, D_TRACE_DYN,
-		    "trace( ) may not be applied to a dynamic expression\n");
+	if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
+		dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
+		    "%s( ) may not be applied to a translated pointer\n", act);
 	}
 
 	dt_cg(yypcb, dnp->dn_args);
-	ap->dtad_difo = dt_as(yypcb);
-	ap->dtad_kind = DTRACEACT_DIFEXPR;
-}
-
-/*
- * The print() action behaves identically to trace(), except that it stores the
- * CTF type of the argument (if present) within the DOF for the DIFEXPR action.
- * To do this, we set the 'dtsd_strdata' to point to the fully-qualified CTF
- * type ID for the result of the DIF action.  We use the ID instead of the name
- * to handles complex types like arrays and function pointers that can't be
- * resolved by ctf_type_lookup().  This is later processed by
- * dtrace_dof_create() and turned into a reference into the string table so
- * that we can get the type information when we process the data after the
- * fact.
- */
-static void
-dt_action_print(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
-{
-	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
-	dt_node_t *dret;
-	size_t len;
-	dt_module_t *dmp;
-
-	if (dt_node_is_void(dnp->dn_args)) {
-		dnerror(dnp->dn_args, D_PRINT_VOID,
-		    "print( ) may not be applied to a void expression\n");
+
+	/*
+	 * The print() action behaves identically to trace(), except that it
+	 * stores the CTF type of the argument (if present) within the DOF for
+	 * the DIFEXPR action.  To do this, we set the 'dtsd_strdata' to point
+	 * to the fully-qualified CTF type ID for the result of the DIF
+	 * action.  We use the ID instead of the name to handles complex types
+	 * like arrays and function pointers that can't be resolved by
+	 * ctf_type_lookup().  This is later processed by dtrace_dof_create()
+	 * and turned into a reference into the string table so that we can
+	 * get the type information when we process the data after the fact.
+	 */
+	if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
+		dt_node_t *dret;
+		size_t n;
+		dt_module_t *dmp;
+
+		dret = yypcb->pcb_dret;
+		dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
+
+		n = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
+		sdp->dtsd_strdata = dt_alloc(dtp, n);
+		if (sdp->dtsd_strdata == NULL)
+			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
+		(void) snprintf(sdp->dtsd_strdata, n, "%s`%d", dmp->dm_name,
+		    dret->dn_type);
 	}
 
-	if (dt_node_is_dynamic(dnp->dn_args)) {
-		dnerror(dnp->dn_args, D_PRINT_DYN,
-		    "print( ) may not be applied to a dynamic expression\n");
-	}
-
-	dt_cg(yypcb, dnp->dn_args);
-
-	dret = yypcb->pcb_dret;
-	dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
-
-	len = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
-	sdp->dtsd_strdata = dt_alloc(dtp, len);
-	if (sdp->dtsd_strdata == NULL)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
-	(void) snprintf(sdp->dtsd_strdata, len, "%s`%d", dmp->dm_name,
-	    dret->dn_type);
-
 	ap->dtad_difo = dt_as(yypcb);
 	ap->dtad_kind = DTRACEACT_DIFEXPR;
 }
@@ -1073,6 +1058,9 @@
 	case DT_ACT_PANIC:
 		dt_action_panic(dtp, dnp->dn_expr, sdp);
 		break;
+	case DT_ACT_PRINT:
+		dt_action_trace(dtp, dnp->dn_expr, sdp);
+		break;
 	case DT_ACT_PRINTA:
 		dt_action_printa(dtp, dnp->dn_expr, sdp);
 		break;
@@ -1103,9 +1091,6 @@
 	case DT_ACT_TRACE:
 		dt_action_trace(dtp, dnp->dn_expr, sdp);
 		break;
-	case DT_ACT_PRINT:
-		dt_action_print(dtp, dnp->dn_expr, sdp);
-		break;
 	case DT_ACT_TRACEMEM:
 		dt_action_tracemem(dtp, dnp->dn_expr, sdp);
 		break;
@@ -2462,7 +2447,8 @@
 	}
 
 out:
-	if (context != DT_CTX_DTYPE && DT_TREEDUMP_PASS(dtp, 3))
+	if (context != DT_CTX_DTYPE && yypcb->pcb_root != NULL &&
+	    DT_TREEDUMP_PASS(dtp, 3))
 		dt_node_printr(yypcb->pcb_root, stderr, 0);
 
 	if (dtp->dt_cdefs_fd != -1 && (ftruncate64(dtp->dt_cdefs_fd, 0) == -1 ||
--- a/usr/src/lib/libdtrace/common/dt_cg.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_cg.c	Wed Jul 25 19:05:31 2012 -0400
@@ -19,12 +19,15 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/sysmacros.h>
@@ -193,9 +196,6 @@
 	ssize_t size;
 	int sreg;
 
-	if ((sreg = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
 	type = ctf_type_resolve(ctfp, dnp->dn_type);
 	kind = ctf_type_kind(ctfp, type);
 	assert(kind == CTF_K_POINTER || kind == CTF_K_ARRAY);
@@ -212,6 +212,7 @@
 	if ((size = ctf_type_size(ctfp, type)) == 1)
 		return; /* multiply or divide by one can be omitted */
 
+	sreg = dt_regset_alloc(drp);
 	dt_cg_setx(dlp, sreg, size);
 	instr = DIF_INSTR_FMT(op, dreg, sreg, dreg);
 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -251,9 +252,7 @@
 
 	assert(dnp->dn_op == DT_TOK_PTR || dnp->dn_op == DT_TOK_DOT);
 	r1 = dnp->dn_left->dn_reg;
-
-	if ((r2 = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	r2 = dt_regset_alloc(drp);
 
 	/*
 	 * On little-endian architectures, ctm_offset counts from the right so
@@ -356,10 +355,9 @@
 		    "bits %u\n", m.ctm_offset, m.ctm_type, e.cte_bits);
 	}
 
-	if ((r1 = dt_regset_alloc(drp)) == -1 ||
-	    (r2 = dt_regset_alloc(drp)) == -1 ||
-	    (r3 = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	r1 = dt_regset_alloc(drp);
+	r2 = dt_regset_alloc(drp);
+	r3 = dt_regset_alloc(drp);
 
 	/*
 	 * Compute shifts and masks.  We need to compute "shift" as the amount
@@ -423,8 +421,7 @@
 		size = dt_node_type_size(src);
 
 	if (src->dn_flags & DT_NF_REF) {
-		if ((reg = dt_regset_alloc(drp)) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+		reg = dt_regset_alloc(drp);
 		dt_cg_setx(dlp, reg, size);
 		instr = DIF_INSTR_COPYS(src->dn_reg, reg, dst->dn_reg);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -474,30 +471,58 @@
 	size_t dstsize = dt_node_type_size(dst);
 
 	dif_instr_t instr;
-	int reg, n;
+	int rg;
+
+	if (!dt_node_is_scalar(dst))
+		return; /* not a scalar */
+	if (dstsize == srcsize &&
+	    ((src->dn_flags ^ dst->dn_flags) & DT_NF_SIGNED) != 0)
+		return; /* not narrowing or changing signed-ness */
+	if (dstsize > srcsize && (src->dn_flags & DT_NF_SIGNED) == 0)
+		return; /* nothing to do in this case */
 
-	if (dt_node_is_scalar(dst) && (dstsize < srcsize ||
-	    (src->dn_flags & DT_NF_SIGNED) ^ (dst->dn_flags & DT_NF_SIGNED))) {
-		if ((reg = dt_regset_alloc(drp)) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	rg = dt_regset_alloc(drp);
+
+	if (dstsize > srcsize) {
+		int n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
+		int s = (dstsize - srcsize) * NBBY;
+
+		dt_cg_setx(dlp, rg, n);
+
+		instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 
-		if (dstsize < srcsize)
-			n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
-		else
-			n = sizeof (uint64_t) * NBBY - srcsize * NBBY;
+		if ((dst->dn_flags & DT_NF_SIGNED) || n == s) {
+			instr = DIF_INSTR_FMT(DIF_OP_SRA,
+			    dst->dn_reg, rg, dst->dn_reg);
+			dt_irlist_append(dlp,
+			    dt_cg_node_alloc(DT_LBL_NONE, instr));
+		} else {
+			dt_cg_setx(dlp, rg, s);
+			instr = DIF_INSTR_FMT(DIF_OP_SRA,
+			    dst->dn_reg, rg, dst->dn_reg);
+			dt_irlist_append(dlp,
+			    dt_cg_node_alloc(DT_LBL_NONE, instr));
+			dt_cg_setx(dlp, rg, n - s);
+			instr = DIF_INSTR_FMT(DIF_OP_SRL,
+			    dst->dn_reg, rg, dst->dn_reg);
+			dt_irlist_append(dlp,
+			    dt_cg_node_alloc(DT_LBL_NONE, instr));
+		}
+	} else if (dstsize != sizeof (uint64_t)) {
+		int n = sizeof (uint64_t) * NBBY - dstsize * NBBY;
 
-		dt_cg_setx(dlp, reg, n);
+		dt_cg_setx(dlp, rg, n);
 
-		instr = DIF_INSTR_FMT(DIF_OP_SLL,
-		    src->dn_reg, reg, dst->dn_reg);
+		instr = DIF_INSTR_FMT(DIF_OP_SLL, src->dn_reg, rg, dst->dn_reg);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
 
 		instr = DIF_INSTR_FMT((dst->dn_flags & DT_NF_SIGNED) ?
-		    DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, reg, dst->dn_reg);
-
+		    DIF_OP_SRA : DIF_OP_SRL, dst->dn_reg, rg, dst->dn_reg);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
-		dt_regset_free(drp, reg);
 	}
+
+	dt_regset_free(drp, rg);
 }
 
 /*
@@ -523,8 +548,7 @@
 	for (dnp = args; dnp != NULL; dnp = dnp->dn_list)
 		dt_cg_node(dnp, dlp, drp);
 
-	dt_irlist_append(dlp,
-	    dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
 
 	for (dnp = args; dnp != NULL; dnp = dnp->dn_list, i++) {
 		dtrace_diftype_t t;
@@ -538,17 +562,18 @@
 		dt_cg_typecast(dnp, &isp->dis_args[i], dlp, drp);
 		isp->dis_args[i].dn_reg = -1;
 
-		if (t.dtdt_flags & DIF_TF_BYREF)
+		if (t.dtdt_flags & DIF_TF_BYREF) {
 			op = DIF_OP_PUSHTR;
-		else
+			if (t.dtdt_size != 0) {
+				reg = dt_regset_alloc(drp);
+				dt_cg_setx(dlp, reg, t.dtdt_size);
+			} else {
+				reg = DIF_REG_R0;
+			}
+		} else {
 			op = DIF_OP_PUSHTV;
-
-		if (t.dtdt_size != 0) {
-			if ((reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-			dt_cg_setx(dlp, reg, t.dtdt_size);
-		} else
 			reg = DIF_REG_R0;
+		}
 
 		instr = DIF_INSTR_PUSHTS(op, t.dtdt_kind, reg, dnp->dn_reg);
 		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -629,9 +654,7 @@
 	dt_cg_node(dnp->dn_child, dlp, drp);
 	dnp->dn_reg = dnp->dn_child->dn_reg;
 
-	if ((reg = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+	reg = dt_regset_alloc(drp);
 	dt_cg_setx(dlp, reg, size);
 
 	instr = DIF_INSTR_FMT(op, dnp->dn_reg, reg, dnp->dn_reg);
@@ -688,9 +711,7 @@
 	dt_cg_node(dnp->dn_child, dlp, drp);
 	dnp->dn_reg = dnp->dn_child->dn_reg;
 
-	if ((nreg = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+	nreg = dt_regset_alloc(drp);
 	dt_cg_setx(dlp, nreg, size);
 	instr = DIF_INSTR_FMT(op, dnp->dn_reg, nreg, nreg);
 	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1008,9 +1029,7 @@
 		 * set it to the size of our data structure, and then replace
 		 * it with the result of an allocs of the specified size.
 		 */
-		if ((r1 = dt_regset_alloc(drp)) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+		r1 = dt_regset_alloc(drp);
 		dt_cg_setx(dlp, r1,
 		    ctf_type_size(dxp->dx_dst_ctfp, dxp->dx_dst_base));
 
@@ -1054,8 +1073,7 @@
 			 * and add r1 to it before storing the result.
 			 */
 			if (ctm.ctm_offset != 0) {
-				if ((r2 = dt_regset_alloc(drp)) == -1)
-					longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+				r2 = dt_regset_alloc(drp);
 
 				/*
 				 * Add the member offset rounded down to the
@@ -1142,8 +1160,7 @@
 
 	dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
 
-	if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+	dnp->dn_reg = dt_regset_alloc(drp);
 
 	if (dnp->dn_ident->di_flags & DT_IDFLG_TLS)
 		op = DIF_OP_LDTAA;
@@ -1273,9 +1290,7 @@
 	if ((size = dt_node_type_size(dnp)) == sizeof (uint64_t))
 		return;
 
-	if ((reg = dt_regset_alloc(drp)) == -1)
-		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+	reg = dt_regset_alloc(drp);
 	assert(size < sizeof (uint64_t));
 	n = sizeof (uint64_t) * NBBY - size * NBBY;
 
@@ -1338,6 +1353,162 @@
 	}
 }
 
+typedef struct dt_xlmemb {
+	dt_ident_t *dtxl_idp;		/* translated ident */
+	dt_irlist_t *dtxl_dlp;		/* instruction list */
+	dt_regset_t *dtxl_drp;		/* register set */
+	int dtxl_sreg;			/* location of the translation input */
+	int dtxl_dreg;			/* location of our allocated buffer */
+} dt_xlmemb_t;
+
+/*ARGSUSED*/
+static int
+dt_cg_xlate_member(const char *name, ctf_id_t type, ulong_t off, void *arg)
+{
+	dt_xlmemb_t *dx = arg;
+	dt_ident_t *idp = dx->dtxl_idp;
+	dt_irlist_t *dlp = dx->dtxl_dlp;
+	dt_regset_t *drp = dx->dtxl_drp;
+
+	dt_node_t *mnp;
+	dt_xlator_t *dxp;
+
+	int reg, treg;
+	uint32_t instr;
+	size_t size;
+
+	/* Generate code for the translation. */
+	dxp = idp->di_data;
+	mnp = dt_xlator_member(dxp, name);
+
+	/* If there's no translator for the given member, skip it. */
+	if (mnp == NULL)
+		return (0);
+
+	dxp->dx_ident->di_flags |= DT_IDFLG_CGREG;
+	dxp->dx_ident->di_id = dx->dtxl_sreg;
+
+	dt_cg_node(mnp->dn_membexpr, dlp, drp);
+
+	dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
+	dxp->dx_ident->di_id = 0;
+
+	treg = mnp->dn_membexpr->dn_reg;
+
+	/* Compute the offset into our buffer and store the result there. */
+	reg = dt_regset_alloc(drp);
+
+	dt_cg_setx(dlp, reg, off / NBBY);
+	instr = DIF_INSTR_FMT(DIF_OP_ADD, dx->dtxl_dreg, reg, reg);
+	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+	size = ctf_type_size(mnp->dn_membexpr->dn_ctfp,
+	    mnp->dn_membexpr->dn_type);
+	if (dt_node_is_scalar(mnp->dn_membexpr)) {
+		/*
+		 * Copying scalars is simple.
+		 */
+		switch (size) {
+		case 1:
+			instr = DIF_INSTR_STORE(DIF_OP_STB, treg, reg);
+			break;
+		case 2:
+			instr = DIF_INSTR_STORE(DIF_OP_STH, treg, reg);
+			break;
+		case 4:
+			instr = DIF_INSTR_STORE(DIF_OP_STW, treg, reg);
+			break;
+		case 8:
+			instr = DIF_INSTR_STORE(DIF_OP_STX, treg, reg);
+			break;
+		default:
+			xyerror(D_UNKNOWN, "internal error -- unexpected "
+			    "size: %lu\n", (ulong_t)size);
+		}
+
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+	} else if (dt_node_is_string(mnp->dn_membexpr)) {
+		int szreg;
+
+		/*
+		 * Use the copys instruction for strings.
+		 */
+		szreg = dt_regset_alloc(drp);
+		dt_cg_setx(dlp, szreg, size);
+		instr = DIF_INSTR_COPYS(treg, szreg, reg);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		dt_regset_free(drp, szreg);
+	} else {
+		int szreg;
+
+		/*
+		 * If it's anything else then we'll just bcopy it.
+		 */
+		szreg = dt_regset_alloc(drp);
+		dt_cg_setx(dlp, szreg, size);
+		dt_irlist_append(dlp,
+		    dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+		instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+		    DIF_REG_R0, treg);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+		    DIF_REG_R0, reg);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF,
+		    DIF_REG_R0, szreg);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		instr = DIF_INSTR_CALL(DIF_SUBR_BCOPY, szreg);
+		dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+		dt_regset_free(drp, szreg);
+	}
+
+	dt_regset_free(drp, reg);
+	dt_regset_free(drp, treg);
+
+	return (0);
+}
+
+/*
+ * If we're expanding a translated type, we create an appropriately sized
+ * buffer with alloca() and then translate each member into it.
+ */
+static int
+dt_cg_xlate_expand(dt_node_t *dnp, dt_ident_t *idp, dt_irlist_t *dlp,
+    dt_regset_t *drp)
+{
+	dt_xlmemb_t dlm;
+	uint32_t instr;
+	int dreg;
+	size_t size;
+
+	dreg = dt_regset_alloc(drp);
+	size = ctf_type_size(dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
+
+	/* Call alloca() to create the buffer. */
+	dt_cg_setx(dlp, dreg, size);
+
+	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, DIF_INSTR_FLUSHTS));
+
+	instr = DIF_INSTR_PUSHTS(DIF_OP_PUSHTV, DIF_TYPE_CTF, DIF_REG_R0, dreg);
+	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+	instr = DIF_INSTR_CALL(DIF_SUBR_ALLOCA, dreg);
+	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
+
+	/* Generate the translation for each member. */
+	dlm.dtxl_idp = idp;
+	dlm.dtxl_dlp = dlp;
+	dlm.dtxl_drp = drp;
+	dlm.dtxl_sreg = dnp->dn_reg;
+	dlm.dtxl_dreg = dreg;
+	(void) ctf_member_iter(dnp->dn_ident->di_ctfp,
+	    dnp->dn_ident->di_type, dt_cg_xlate_member,
+	    &dlm);
+
+	return (dreg);
+}
+
 static void
 dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 {
@@ -1350,7 +1521,6 @@
 	dt_ident_t *idp;
 	ssize_t stroff;
 	uint_t op;
-	int reg;
 
 	switch (dnp->dn_op) {
 	case DT_TOK_COMMA:
@@ -1552,7 +1722,16 @@
 		dt_cg_node(dnp->dn_child, dlp, drp);
 		dnp->dn_reg = dnp->dn_child->dn_reg;
 
-		if (!(dnp->dn_flags & DT_NF_REF)) {
+		if (dt_node_is_dynamic(dnp->dn_child)) {
+			int reg;
+			idp = dt_node_resolve(dnp->dn_child, DT_IDENT_XLPTR);
+			assert(idp != NULL);
+			reg = dt_cg_xlate_expand(dnp, idp, dlp, drp);
+
+			dt_regset_free(drp, dnp->dn_child->dn_reg);
+			dnp->dn_reg = reg;
+
+		} else if (!(dnp->dn_flags & DT_NF_REF)) {
 			uint_t ubit = dnp->dn_flags & DT_NF_USERLAND;
 
 			/*
@@ -1588,10 +1767,7 @@
 
 	case DT_TOK_SIZEOF: {
 		size_t size = dt_node_sizeof(dnp->dn_child);
-
-		if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+		dnp->dn_reg = dt_regset_alloc(drp);
 		assert(size != 0);
 		dt_cg_setx(dlp, dnp->dn_reg, size);
 		break;
@@ -1616,8 +1792,7 @@
 			assert(dxp->dx_ident->di_flags & DT_IDFLG_CGREG);
 			assert(dxp->dx_ident->di_id != 0);
 
-			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+			dnp->dn_reg = dt_regset_alloc(drp);
 
 			if (dxp->dx_arg == -1) {
 				instr = DIF_INSTR_MOV(
@@ -1701,8 +1876,9 @@
 		}
 
 		if (m.ctm_offset != 0) {
-			if ((reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+			int reg;
+
+			reg = dt_regset_alloc(drp);
 
 			/*
 			 * If the offset is not aligned on a byte boundary, it
@@ -1748,8 +1924,7 @@
 		break;
 
 	case DT_TOK_STRING:
-		if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+		dnp->dn_reg = dt_regset_alloc(drp);
 
 		assert(dnp->dn_kind == DT_NODE_STRING);
 		stroff = dt_strtab_insert(yypcb->pcb_strtab, dnp->dn_string);
@@ -1772,8 +1947,7 @@
 		 */
 		if (dnp->dn_kind == DT_NODE_VAR &&
 		    (dnp->dn_ident->di_flags & DT_IDFLG_CGREG)) {
-			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+			dnp->dn_reg = dt_regset_alloc(drp);
 			instr = DIF_INSTR_MOV(dnp->dn_ident->di_id,
 			    dnp->dn_reg);
 			dt_irlist_append(dlp,
@@ -1803,11 +1977,9 @@
 
 			dt_cg_arglist(dnp->dn_ident, dnp->dn_args, dlp, drp);
 
-			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
-			instr = DIF_INSTR_CALL(
-			    dnp->dn_ident->di_id, dnp->dn_reg);
+			dnp->dn_reg = dt_regset_alloc(drp);
+			instr = DIF_INSTR_CALL(dnp->dn_ident->di_id,
+			    dnp->dn_reg);
 
 			dt_irlist_append(dlp,
 			    dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1834,8 +2006,7 @@
 				break;
 			}
 
-			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+			dnp->dn_reg = dt_regset_alloc(drp);
 
 			if (dnp->dn_ident->di_flags & DT_IDFLG_LOCAL)
 				op = DIF_OP_LDLS;
@@ -1865,9 +2036,7 @@
 				    dtrace_errmsg(dtp, dtrace_errno(dtp)));
 			}
 
-			if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-				longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+			dnp->dn_reg = dt_regset_alloc(drp);
 			dt_cg_xsetx(dlp, dnp->dn_ident,
 			    DT_LBL_NONE, dnp->dn_reg, sym.st_value);
 
@@ -1887,9 +2056,7 @@
 		break;
 
 	case DT_TOK_INT:
-		if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
-			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
-
+		dnp->dn_reg = dt_regset_alloc(drp);
 		dt_cg_setx(dlp, dnp->dn_reg, dnp->dn_value);
 		break;
 
@@ -1904,6 +2071,7 @@
 {
 	dif_instr_t instr;
 	dt_xlator_t *dxp;
+	dt_ident_t *idp;
 
 	if (pcb->pcb_regs == NULL && (pcb->pcb_regs =
 	    dt_regset_create(pcb->pcb_hdl->dt_conf.dtc_difintregs)) == NULL)
@@ -1930,9 +2098,9 @@
 	assert(pcb->pcb_dret == NULL);
 	pcb->pcb_dret = dnp;
 
-	if (dt_node_is_dynamic(dnp)) {
+	if (dt_node_resolve(dnp, DT_IDENT_XLPTR) != NULL) {
 		dnerror(dnp, D_CG_DYN, "expression cannot evaluate to result "
-		    "of dynamic type\n");
+		    "of a translated pointer\n");
 	}
 
 	/*
@@ -1948,6 +2116,14 @@
 	}
 
 	dt_cg_node(dnp, &pcb->pcb_ir, pcb->pcb_regs);
+
+	if ((idp = dt_node_resolve(dnp, DT_IDENT_XLSOU)) != NULL) {
+		int reg = dt_cg_xlate_expand(dnp, idp,
+		    &pcb->pcb_ir, pcb->pcb_regs);
+		dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
+		dnp->dn_reg = reg;
+	}
+
 	instr = DIF_INSTR_RET(dnp->dn_reg);
 	dt_regset_free(pcb->pcb_regs, dnp->dn_reg);
 	dt_irlist_append(&pcb->pcb_ir, dt_cg_node_alloc(DT_LBL_NONE, instr));
@@ -1957,4 +2133,7 @@
 		dxp->dx_ident->di_id = 0;
 		dxp->dx_ident->di_flags &= ~DT_IDFLG_CGREG;
 	}
+
+	dt_regset_free(pcb->pcb_regs, 0);
+	dt_regset_assert_free(pcb->pcb_regs);
 }
--- a/usr/src/lib/libdtrace/common/dt_consume.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_consume.c	Wed Jul 25 19:05:31 2012 -0400
@@ -25,7 +25,7 @@
 
 /*
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <stdlib.h>
@@ -37,6 +37,7 @@
 #include <ctype.h>
 #include <alloca.h>
 #include <dt_impl.h>
+#include <dt_pq.h>
 
 #define	DT_MASK_LO 0x00000000FFFFFFFFULL
 
@@ -438,17 +439,8 @@
 		offs += epd->dtepd_size;
 
 		do {
-			if (offs >= buf->dtbd_size) {
-				/*
-				 * We're at the end -- maybe.  If the oldest
-				 * record is non-zero, we need to wrap.
-				 */
-				if (buf->dtbd_oldest != 0) {
-					offs = 0;
-				} else {
-					goto out;
-				}
-			}
+			if (offs >= buf->dtbd_size)
+				goto out;
 
 			next = *(uint32_t *)((uintptr_t)buf->dtbd_data + offs);
 
@@ -1700,26 +1692,27 @@
 }
 
 static int
-dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu, dtrace_bufdesc_t *buf,
+dt_consume_cpu(dtrace_hdl_t *dtp, FILE *fp, int cpu,
+    dtrace_bufdesc_t *buf, boolean_t just_one,
     dtrace_consume_probe_f *efunc, dtrace_consume_rec_f *rfunc, void *arg)
 {
 	dtrace_epid_t id;
-	size_t offs, start = buf->dtbd_oldest, end = buf->dtbd_size;
+	size_t offs;
 	int flow = (dtp->dt_options[DTRACEOPT_FLOWINDENT] != DTRACEOPT_UNSET);
 	int quiet = (dtp->dt_options[DTRACEOPT_QUIET] != DTRACEOPT_UNSET);
 	int rval, i, n;
-	dtrace_epid_t last = DTRACE_EPIDNONE;
 	uint64_t tracememsize = 0;
 	dtrace_probedata_t data;
 	uint64_t drops;
-	caddr_t addr;
 
 	bzero(&data, sizeof (data));
 	data.dtpda_handle = dtp;
 	data.dtpda_cpu = cpu;
-
-again:
-	for (offs = start; offs < end; ) {
+	data.dtpda_flow = dtp->dt_flow;
+	data.dtpda_indent = dtp->dt_indent;
+	data.dtpda_prefix = dtp->dt_prefix;
+
+	for (offs = buf->dtbd_oldest; offs < buf->dtbd_size; ) {
 		dtrace_eprobedesc_t *epd;
 
 		/*
@@ -1754,7 +1747,8 @@
 		}
 
 		if (flow)
-			(void) dt_flowindent(dtp, &data, last, buf, offs);
+			(void) dt_flowindent(dtp, &data, dtp->dt_last_epid,
+			    buf, offs);
 
 		rval = (*efunc)(&data, arg);
 
@@ -1773,6 +1767,7 @@
 			return (dt_set_errno(dtp, EDT_BADRVAL));
 
 		for (i = 0; i < epd->dtepd_nrecs; i++) {
+			caddr_t addr;
 			dtrace_recdesc_t *rec = &epd->dtepd_rec[i];
 			dtrace_actkind_t act = rec->dtrd_action;
 
@@ -2132,14 +2127,16 @@
 		rval = (*rfunc)(&data, NULL, arg);
 nextepid:
 		offs += epd->dtepd_size;
-		last = id;
+		dtp->dt_last_epid = id;
+		if (just_one) {
+			buf->dtbd_oldest = offs;
+			break;
+		}
 	}
 
-	if (buf->dtbd_oldest != 0 && start == buf->dtbd_oldest) {
-		end = buf->dtbd_oldest;
-		start = 0;
-		goto again;
-	}
+	dtp->dt_flow = data.dtpda_flow;
+	dtp->dt_indent = data.dtpda_indent;
+	dtp->dt_prefix = data.dtpda_prefix;
 
 	if ((drops = buf->dtbd_drops) == 0)
 		return (0);
@@ -2152,6 +2149,126 @@
 	return (dt_handle_cpudrop(dtp, cpu, DTRACEDROP_PRINCIPAL, drops));
 }
 
+/*
+ * Reduce memory usage by shrinking the buffer if it's no more than half full.
+ * Note, we need to preserve the alignment of the data at dtbd_oldest, which is
+ * only 4-byte aligned.
+ */
+static void
+dt_realloc_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf, int cursize)
+{
+	uint64_t used = buf->dtbd_size - buf->dtbd_oldest;
+	if (used < cursize / 2) {
+		int misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
+		char *newdata = dt_alloc(dtp, used + misalign);
+		if (newdata == NULL)
+			return;
+		bzero(newdata, misalign);
+		bcopy(buf->dtbd_data + buf->dtbd_oldest,
+		    newdata + misalign, used);
+		dt_free(dtp, buf->dtbd_data);
+		buf->dtbd_oldest = misalign;
+		buf->dtbd_size = used + misalign;
+		buf->dtbd_data = newdata;
+	}
+}
+
+/*
+ * If the ring buffer has wrapped, the data is not in order.  Rearrange it
+ * so that it is.  Note, we need to preserve the alignment of the data at
+ * dtbd_oldest, which is only 4-byte aligned.
+ */
+static int
+dt_unring_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
+{
+	int misalign;
+	char *newdata, *ndp;
+
+	if (buf->dtbd_oldest == 0)
+		return (0);
+
+	misalign = buf->dtbd_oldest & (sizeof (uint64_t) - 1);
+	newdata = ndp = dt_alloc(dtp, buf->dtbd_size + misalign);
+
+	if (newdata == NULL)
+		return (-1);
+
+	assert(0 == (buf->dtbd_size & (sizeof (uint64_t) - 1)));
+
+	bzero(ndp, misalign);
+	ndp += misalign;
+
+	bcopy(buf->dtbd_data + buf->dtbd_oldest, ndp,
+	    buf->dtbd_size - buf->dtbd_oldest);
+	ndp += buf->dtbd_size - buf->dtbd_oldest;
+
+	bcopy(buf->dtbd_data, ndp, buf->dtbd_oldest);
+
+	dt_free(dtp, buf->dtbd_data);
+	buf->dtbd_oldest = 0;
+	buf->dtbd_data = newdata;
+	buf->dtbd_size += misalign;
+
+	return (0);
+}
+
+static void
+dt_put_buf(dtrace_hdl_t *dtp, dtrace_bufdesc_t *buf)
+{
+	dt_free(dtp, buf->dtbd_data);
+	dt_free(dtp, buf);
+}
+
+/*
+ * Returns 0 on success, in which case *cbp will be filled in if we retrieved
+ * data, or NULL if there is no data for this CPU.
+ * Returns -1 on failure and sets dt_errno.
+ */
+static int
+dt_get_buf(dtrace_hdl_t *dtp, int cpu, dtrace_bufdesc_t **bufp)
+{
+	dtrace_optval_t size;
+	dtrace_bufdesc_t *buf = dt_zalloc(dtp, sizeof (*buf));
+	int error;
+
+	if (buf == NULL)
+		return (-1);
+
+	(void) dtrace_getopt(dtp, "bufsize", &size);
+	buf->dtbd_data = dt_alloc(dtp, size);
+	if (buf->dtbd_data == NULL) {
+		dt_free(dtp, buf);
+		return (-1);
+	}
+	buf->dtbd_size = size;
+	buf->dtbd_cpu = cpu;
+
+	if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
+		dt_put_buf(dtp, buf);
+		/*
+		 * If we failed with ENOENT, it may be because the
+		 * CPU was unconfigured -- this is okay.  Any other
+		 * error, however, is unexpected.
+		 */
+		if (errno == ENOENT) {
+			*bufp = NULL;
+			return (0);
+		}
+
+		return (dt_set_errno(dtp, errno));
+	}
+
+	error = dt_unring_buf(dtp, buf);
+	if (error != 0) {
+		dt_put_buf(dtp, buf);
+		return (error);
+	}
+	dt_realloc_buf(dtp, buf, size);
+
+	*bufp = buf;
+	return (0);
+}
+
 typedef struct dt_begin {
 	dtrace_consume_probe_f *dtbgn_probefunc;
 	dtrace_consume_rec_f *dtbgn_recfunc;
@@ -2164,7 +2281,7 @@
 static int
 dt_consume_begin_probe(const dtrace_probedata_t *data, void *arg)
 {
-	dt_begin_t *begin = (dt_begin_t *)arg;
+	dt_begin_t *begin = arg;
 	dtrace_probedesc_t *pd = data->dtpda_pdesc;
 
 	int r1 = (strcmp(pd->dtpd_provider, "dtrace") == 0);
@@ -2189,7 +2306,7 @@
 dt_consume_begin_record(const dtrace_probedata_t *data,
     const dtrace_recdesc_t *rec, void *arg)
 {
-	dt_begin_t *begin = (dt_begin_t *)arg;
+	dt_begin_t *begin = arg;
 
 	return (begin->dtbgn_recfunc(data, rec, begin->dtbgn_arg));
 }
@@ -2215,7 +2332,7 @@
 }
 
 static int
-dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp, dtrace_bufdesc_t *buf,
+dt_consume_begin(dtrace_hdl_t *dtp, FILE *fp,
     dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
 {
 	/*
@@ -2239,26 +2356,19 @@
 	 * first pass, and that we only process ERROR enablings _not_ induced
 	 * by BEGIN enablings in the second pass.
 	 */
+
 	dt_begin_t begin;
 	processorid_t cpu = dtp->dt_beganon;
-	dtrace_bufdesc_t nbuf;
 	int rval, i;
 	static int max_ncpus;
-	dtrace_optval_t size;
+	dtrace_bufdesc_t *buf;
 
 	dtp->dt_beganon = -1;
 
-	if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
-		/*
-		 * We really don't expect this to fail, but it is at least
-		 * technically possible for this to fail with ENOENT.  In this
-		 * case, we just drive on...
-		 */
-		if (errno == ENOENT)
-			return (0);
-
-		return (dt_set_errno(dtp, errno));
-	}
+	if (dt_get_buf(dtp, cpu, &buf) != 0)
+		return (-1);
+	if (buf == NULL)
+		return (0);
 
 	if (!dtp->dt_stopped || buf->dtbd_cpu != dtp->dt_endedon) {
 		/*
@@ -2266,7 +2376,10 @@
 		 * we are, we actually processed any END probes on another
 		 * CPU.  We can simply consume this buffer and return.
 		 */
-		return (dt_consume_cpu(dtp, fp, cpu, buf, pf, rf, arg));
+		rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+		    pf, rf, arg);
+		dt_put_buf(dtp, buf);
+		return (rval);
 	}
 
 	begin.dtbgn_probefunc = pf;
@@ -2283,56 +2396,41 @@
 	dtp->dt_errhdlr = dt_consume_begin_error;
 	dtp->dt_errarg = &begin;
 
-	rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
-	    dt_consume_begin_record, &begin);
+	rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+	    dt_consume_begin_probe, dt_consume_begin_record, &begin);
 
 	dtp->dt_errhdlr = begin.dtbgn_errhdlr;
 	dtp->dt_errarg = begin.dtbgn_errarg;
 
-	if (rval != 0)
+	if (rval != 0) {
+		dt_put_buf(dtp, buf);
 		return (rval);
-
-	/*
-	 * Now allocate a new buffer.  We'll use this to deal with every other
-	 * CPU.
-	 */
-	bzero(&nbuf, sizeof (dtrace_bufdesc_t));
-	(void) dtrace_getopt(dtp, "bufsize", &size);
-	if ((nbuf.dtbd_data = malloc(size)) == NULL)
-		return (dt_set_errno(dtp, EDT_NOMEM));
+	}
 
 	if (max_ncpus == 0)
 		max_ncpus = dt_sysconf(dtp, _SC_CPUID_MAX) + 1;
 
 	for (i = 0; i < max_ncpus; i++) {
-		nbuf.dtbd_cpu = i;
-
+		dtrace_bufdesc_t *nbuf;
 		if (i == cpu)
 			continue;
 
-		if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, &nbuf) == -1) {
-			/*
-			 * If we failed with ENOENT, it may be because the
-			 * CPU was unconfigured -- this is okay.  Any other
-			 * error, however, is unexpected.
-			 */
-			if (errno == ENOENT)
-				continue;
-
-			free(nbuf.dtbd_data);
-
-			return (dt_set_errno(dtp, errno));
+		if (dt_get_buf(dtp, i, &nbuf) != 0) {
+			dt_put_buf(dtp, buf);
+			return (-1);
 		}
-
-		if ((rval = dt_consume_cpu(dtp, fp,
-		    i, &nbuf, pf, rf, arg)) != 0) {
-			free(nbuf.dtbd_data);
+		if (nbuf == NULL)
+			continue;
+
+		rval = dt_consume_cpu(dtp, fp, i, nbuf, B_FALSE,
+		    pf, rf, arg);
+		dt_put_buf(dtp, nbuf);
+		if (rval != 0) {
+			dt_put_buf(dtp, buf);
 			return (rval);
 		}
 	}
 
-	free(nbuf.dtbd_data);
-
 	/*
 	 * Okay -- we're done with the other buffers.  Now we want to
 	 * reconsume the first buffer -- but this time we're looking for
@@ -2347,8 +2445,8 @@
 	dtp->dt_errhdlr = dt_consume_begin_error;
 	dtp->dt_errarg = &begin;
 
-	rval = dt_consume_cpu(dtp, fp, cpu, buf, dt_consume_begin_probe,
-	    dt_consume_begin_record, &begin);
+	rval = dt_consume_cpu(dtp, fp, cpu, buf, B_FALSE,
+	    dt_consume_begin_probe, dt_consume_begin_record, &begin);
 
 	dtp->dt_errhdlr = begin.dtbgn_errhdlr;
 	dtp->dt_errarg = begin.dtbgn_errarg;
@@ -2356,11 +2454,31 @@
 	return (rval);
 }
 
+/* ARGSUSED */
+static uint64_t
+dt_buf_oldest(void *elem, void *arg)
+{
+	dtrace_bufdesc_t *buf = elem;
+	size_t offs = buf->dtbd_oldest;
+
+	while (offs < buf->dtbd_size) {
+		dtrace_rechdr_t *dtrh =
+		    (dtrace_rechdr_t *)(buf->dtbd_data + offs);
+		if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
+			offs += sizeof (dtrace_epid_t);
+		} else {
+			return (DTRACE_RECORD_LOAD_TIMESTAMP(dtrh));
+		}
+	}
+
+	/* There are no records left; use the time the buffer was retrieved. */
+	return (buf->dtbd_timestamp);
+}
+
 int
 dtrace_consume(dtrace_hdl_t *dtp, FILE *fp,
     dtrace_consume_probe_f *pf, dtrace_consume_rec_f *rf, void *arg)
 {
-	dtrace_bufdesc_t *buf = &dtp->dt_buf;
 	dtrace_optval_t size;
 	static int max_ncpus;
 	int i, rval;
@@ -2388,71 +2506,158 @@
 	if (rf == NULL)
 		rf = (dtrace_consume_rec_f *)dt_nullrec;
 
-	if (buf->dtbd_data == NULL) {
+	if (dtp->dt_options[DTRACEOPT_TEMPORAL] == DTRACEOPT_UNSET) {
+		/*
+		 * The output will not be in the order it was traced.  Rather,
+		 * we will consume all of the data from each CPU's buffer in
+		 * turn.  We apply special handling for the records from BEGIN
+		 * and END probes so that they are consumed first and last,
+		 * respectively.
+		 *
+		 * If we have just begun, we want to first process the CPU that
+		 * executed the BEGIN probe (if any).
+		 */
+		if (dtp->dt_active && dtp->dt_beganon != -1 &&
+		    (rval = dt_consume_begin(dtp, fp, pf, rf, arg)) != 0)
+			return (rval);
+
+		for (i = 0; i < max_ncpus; i++) {
+			dtrace_bufdesc_t *buf;
+
+			/*
+			 * If we have stopped, we want to process the CPU on
+			 * which the END probe was processed only _after_ we
+			 * have processed everything else.
+			 */
+			if (dtp->dt_stopped && (i == dtp->dt_endedon))
+				continue;
+
+			if (dt_get_buf(dtp, i, &buf) != 0)
+				return (-1);
+			if (buf == NULL)
+				continue;
+
+			dtp->dt_flow = 0;
+			dtp->dt_indent = 0;
+			dtp->dt_prefix = NULL;
+			rval = dt_consume_cpu(dtp, fp, i,
+			    buf, B_FALSE, pf, rf, arg);
+			dt_put_buf(dtp, buf);
+			if (rval != 0)
+				return (rval);
+		}
+		if (dtp->dt_stopped) {
+			dtrace_bufdesc_t *buf;
+
+			if (dt_get_buf(dtp, dtp->dt_endedon, &buf) != 0)
+				return (-1);
+			if (buf == NULL)
+				return (0);
+
+			rval = dt_consume_cpu(dtp, fp, dtp->dt_endedon,
+			    buf, B_FALSE, pf, rf, arg);
+			dt_put_buf(dtp, buf);
+			return (rval);
+		}
+	} else {
+		/*
+		 * The output will be in the order it was traced (or for
+		 * speculations, when it was committed).  We retrieve a buffer
+		 * from each CPU and put it into a priority queue, which sorts
+		 * based on the first entry in the buffer.  This is sufficient
+		 * because entries within a buffer are already sorted.
+		 *
+		 * We then consume records one at a time, always consuming the
+		 * oldest record, as determined by the priority queue.  When
+		 * we reach the end of the time covered by these buffers,
+		 * we need to stop and retrieve more records on the next pass.
+		 * The kernel tells us the time covered by each buffer, in
+		 * dtbd_timestamp.  The first buffer's timestamp tells us the
+		 * time covered by all buffers, as subsequently retrieved
+		 * buffers will cover to a more recent time.
+		 */
+
+		uint64_t *drops = alloca(max_ncpus * sizeof (uint64_t));
+		uint64_t first_timestamp = 0;
+		uint_t cookie = 0;
+		dtrace_bufdesc_t *buf;
+
+		bzero(drops, max_ncpus * sizeof (uint64_t));
+
+		if (dtp->dt_bufq == NULL) {
+			dtp->dt_bufq = dt_pq_init(dtp, max_ncpus * 2,
+			    dt_buf_oldest, NULL);
+			if (dtp->dt_bufq == NULL) /* ENOMEM */
+				return (-1);
+		}
+
+		/* Retrieve data from each CPU. */
 		(void) dtrace_getopt(dtp, "bufsize", &size);
-		if ((buf->dtbd_data = malloc(size)) == NULL)
-			return (dt_set_errno(dtp, EDT_NOMEM));
-
-		buf->dtbd_size = size;
-	}
-
-	/*
-	 * If we have just begun, we want to first process the CPU that
-	 * executed the BEGIN probe (if any).
-	 */
-	if (dtp->dt_active && dtp->dt_beganon != -1) {
-		buf->dtbd_cpu = dtp->dt_beganon;
-		if ((rval = dt_consume_begin(dtp, fp, buf, pf, rf, arg)) != 0)
-			return (rval);
-	}
-
-	for (i = 0; i < max_ncpus; i++) {
-		buf->dtbd_cpu = i;
+		for (i = 0; i < max_ncpus; i++) {
+			dtrace_bufdesc_t *buf;
+
+			if (dt_get_buf(dtp, i, &buf) != 0)
+				return (-1);
+			if (buf != NULL) {
+				if (first_timestamp == 0)
+					first_timestamp = buf->dtbd_timestamp;
+				assert(buf->dtbd_timestamp >= first_timestamp);
+
+				dt_pq_insert(dtp->dt_bufq, buf);
+				drops[i] = buf->dtbd_drops;
+				buf->dtbd_drops = 0;
+			}
+		}
+
+		/* Consume records. */
+		for (;;) {
+			dtrace_bufdesc_t *buf = dt_pq_pop(dtp->dt_bufq);
+			uint64_t timestamp;
+
+			if (buf == NULL)
+				break;
+
+			timestamp = dt_buf_oldest(buf, dtp);
+			assert(timestamp >= dtp->dt_last_timestamp);
+			dtp->dt_last_timestamp = timestamp;
+
+			if (timestamp == buf->dtbd_timestamp) {
+				/*
+				 * We've reached the end of the time covered
+				 * by this buffer.  If this is the oldest
+				 * buffer, we must do another pass
+				 * to retrieve more data.
+				 */
+				dt_put_buf(dtp, buf);
+				if (timestamp == first_timestamp &&
+				    !dtp->dt_stopped)
+					break;
+				continue;
+			}
+
+			if ((rval = dt_consume_cpu(dtp, fp,
+			    buf->dtbd_cpu, buf, B_TRUE, pf, rf, arg)) != 0)
+				return (rval);
+			dt_pq_insert(dtp->dt_bufq, buf);
+		}
+
+		/* Consume drops. */
+		for (i = 0; i < max_ncpus; i++) {
+			if (drops[i] != 0) {
+				int error = dt_handle_cpudrop(dtp, i,
+				    DTRACEDROP_PRINCIPAL, drops[i]);
+				if (error != 0)
+					return (error);
+			}
+		}
 
 		/*
-		 * If we have stopped, we want to process the CPU on which the
-		 * END probe was processed only _after_ we have processed
-		 * everything else.
+		 * Reduce memory usage by re-allocating smaller buffers
+		 * for the "remnants".
 		 */
-		if (dtp->dt_stopped && (i == dtp->dt_endedon))
-			continue;
-
-		if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
-			/*
-			 * If we failed with ENOENT, it may be because the
-			 * CPU was unconfigured -- this is okay.  Any other
-			 * error, however, is unexpected.
-			 */
-			if (errno == ENOENT)
-				continue;
-
-			return (dt_set_errno(dtp, errno));
-		}
-
-		if ((rval = dt_consume_cpu(dtp, fp, i, buf, pf, rf, arg)) != 0)
-			return (rval);
+		while (buf = dt_pq_walk(dtp->dt_bufq, &cookie))
+			dt_realloc_buf(dtp, buf, buf->dtbd_size);
 	}
 
-	if (!dtp->dt_stopped)
-		return (0);
-
-	buf->dtbd_cpu = dtp->dt_endedon;
-
-	if (dt_ioctl(dtp, DTRACEIOC_BUFSNAP, buf) == -1) {
-		/*
-		 * This _really_ shouldn't fail, but it is strictly speaking
-		 * possible for this to return ENOENT if the CPU that called
-		 * the END enabling somehow managed to become unconfigured.
-		 * It's unclear how the user can possibly expect anything
-		 * rational to happen in this case -- the state has been thrown
-		 * out along with the unconfigured CPU -- so we'll just drive
-		 * on...
-		 */
-		if (errno == ENOENT)
-			return (0);
-
-		return (dt_set_errno(dtp, errno));
-	}
-
-	return (dt_consume_cpu(dtp, fp, dtp->dt_endedon, buf, pf, rf, arg));
+	return (0);
 }
--- a/usr/src/lib/libdtrace/common/dt_dis.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_dis.c	Wed Jul 25 19:05:31 2012 -0400
@@ -19,12 +19,15 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 #include <strings.h>
 #include <stdio.h>
@@ -212,12 +215,22 @@
 {
 	static const char *const tnames[] = { "D type", "string" };
 	uint_t type = DIF_INSTR_TYPE(in);
+	const char *pad;
 
-	(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
-	    name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
+	if (DIF_INSTR_OP(in) == DIF_OP_PUSHTV) {
+		(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u",
+		    name, type, DIF_INSTR_RS(in));
+		pad = "\t\t";
+	} else {
+		(void) fprintf(fp, "%-4s DT_TYPE(%u), %%r%u, %%r%u",
+		    name, type, DIF_INSTR_R2(in), DIF_INSTR_RS(in));
+		pad = "\t";
+	}
 
-	if (type < sizeof (tnames) / sizeof (tnames[0]))
-		(void) fprintf(fp, "\t! DT_TYPE(%u) = %s", type, tnames[type]);
+	if (type < sizeof (tnames) / sizeof (tnames[0])) {
+		(void) fprintf(fp, "%s! DT_TYPE(%u) = %s", pad,
+		    type, tnames[type]);
+	}
 }
 
 static void
--- a/usr/src/lib/libdtrace/common/dt_error.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_error.c	Wed Jul 25 19:05:31 2012 -0400
@@ -18,11 +18,16 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 #include <strings.h>
 #include <dt_impl.h>
 
@@ -36,7 +41,6 @@
 	{ EDT_VERSREDUCED, "Requested version conflicts with earlier setting" },
 	{ EDT_CTF,	"Unexpected libctf error" },
 	{ EDT_COMPILER, "Error in D program compilation" },
-	{ EDT_NOREG,	"Insufficient registers to generate code" },
 	{ EDT_NOTUPREG,	"Insufficient tuple registers to generate code" },
 	{ EDT_NOMEM,	"Memory allocation failure" },
 	{ EDT_INT2BIG,	"Integer constant table limit exceeded" },
--- a/usr/src/lib/libdtrace/common/dt_errtags.h	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_errtags.h	Wed Jul 25 19:05:31 2012 -0400
@@ -26,7 +26,7 @@
 
 /*
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef	_DT_ERRTAGS_H
@@ -259,7 +259,8 @@
 	D_LLQUANT_FACTORNSTEPS,		/* llquantize() # steps < factor */
 	D_LLQUANT_FACTOREVEN,		/* llquantize() bad # steps/factor */
 	D_LLQUANT_FACTORSMALL,		/* llquantize() magnitude too small */
-	D_LLQUANT_MAGTOOBIG		/* llquantize() high mag too large */
+	D_LLQUANT_MAGTOOBIG,		/* llquantize() high mag too large */
+	D_NOREG				/* no available internal registers */
 } dt_errtag_t;
 
 extern const char *dt_errtag(dt_errtag_t);
--- a/usr/src/lib/libdtrace/common/dt_impl.h	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_impl.h	Wed Jul 25 19:05:31 2012 -0400
@@ -26,7 +26,7 @@
 
 /*
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef	_DT_IMPL_H
@@ -55,6 +55,7 @@
 #include <dt_proc.h>
 #include <dt_dof.h>
 #include <dt_pcb.h>
+#include <dt_pq.h>
 
 struct dt_module;		/* see below */
 struct dt_pfdict;		/* see <dt_printf.h> */
@@ -226,6 +227,7 @@
 	uint_t dt_provbuckets;	/* number of provider hash buckets */
 	uint_t dt_nprovs;	/* number of providers in hash and list */
 	dt_proc_hash_t *dt_procs; /* hash table of grabbed process handles */
+	char **dt_proc_env;	/* additional environment variables */
 	dt_intdesc_t dt_ints[6]; /* cached integer type descriptions */
 	ctf_id_t dt_type_func;	/* cached CTF identifier for function type */
 	ctf_id_t dt_type_fptr;	/* cached CTF identifier for function pointer */
@@ -244,7 +246,7 @@
 	int dt_maxstrdata;	/* max strdata ID */
 	char **dt_strdata;	/* pointer to strdata array */
 	dt_aggregate_t dt_aggregate; /* aggregate */
-	dtrace_bufdesc_t dt_buf; /* staging buffer */
+	dt_pq_t *dt_bufq;	/* CPU-specific data queue */
 	struct dt_pfdict *dt_pfdict; /* dictionary of printf conversions */
 	dt_version_t dt_vmax;	/* optional ceiling on program API binding */
 	dtrace_attribute_t dt_amin; /* optional floor on program attributes */
@@ -305,6 +307,11 @@
 	struct utsname dt_uts;	/* uname(2) information for system */
 	dt_list_t dt_lib_dep;	/* scratch linked-list of lib dependencies */
 	dt_list_t dt_lib_dep_sorted;	/* dependency sorted library list */
+	dtrace_flowkind_t dt_flow;	/* flow kind */
+	const char *dt_prefix;	/* recommended flow prefix */
+	int dt_indent;		/* recommended flow indent */
+	dtrace_epid_t dt_last_epid;	/* most recently consumed EPID */
+	uint64_t dt_last_timestamp;	/* most recently consumed timestamp */
 };
 
 /*
@@ -438,7 +445,6 @@
 	EDT_VERSREDUCED,	/* requested API version has been reduced */
 	EDT_CTF,		/* libctf called failed (dt_ctferr has more) */
 	EDT_COMPILER,		/* error in D program compilation */
-	EDT_NOREG,		/* register allocation failure */
 	EDT_NOTUPREG,		/* tuple register allocation failure */
 	EDT_NOMEM,		/* memory allocation failure */
 	EDT_INT2BIG,		/* integer limit exceeded */
--- a/usr/src/lib/libdtrace/common/dt_open.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_open.c	Wed Jul 25 19:05:31 2012 -0400
@@ -22,7 +22,7 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2011 by Delphix. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -81,7 +81,7 @@
 
 /*
  * The version number should be increased for every customer visible release
- * of Solaris. The major number should be incremented when a fundamental
+ * of DTrace. The major number should be incremented when a fundamental
  * change has been made that would affect all consumers, and would reflect
  * sweeping changes to DTrace or the D language. The minor number should be
  * incremented when a change is introduced that could break scripts that had
@@ -110,8 +110,9 @@
 #define	DT_VERS_1_8	DT_VERSION_NUMBER(1, 8, 0)
 #define	DT_VERS_1_8_1	DT_VERSION_NUMBER(1, 8, 1)
 #define	DT_VERS_1_9	DT_VERSION_NUMBER(1, 9, 0)
-#define	DT_VERS_LATEST	DT_VERS_1_9
-#define	DT_VERS_STRING	"Sun D 1.9"
+#define	DT_VERS_1_9_1	DT_VERSION_NUMBER(1, 9, 1)
+#define	DT_VERS_LATEST	DT_VERS_1_9_1
+#define	DT_VERS_STRING	"Sun D 1.9.1"
 
 const dt_version_t _dtrace_versions[] = {
 	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -132,6 +133,7 @@
 	DT_VERS_1_8,	/* D API 1.8 */
 	DT_VERS_1_8_1,	/* D API 1.8.1 */
 	DT_VERS_1_9,	/* D API 1.9 */
+	DT_VERS_1_9_1,	/* D API 1.9.1 */
 	0
 };
 
@@ -937,7 +939,7 @@
 	dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
 	dtp->dt_provbuckets = _dtrace_strbuckets;
 	dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
-	dt_proc_hash_create(dtp);
+	dt_proc_init(dtp);
 	dtp->dt_vmax = DT_VERS_LATEST;
 	dtp->dt_cpp_path = strdup(_dtrace_defcpp);
 	dtp->dt_cpp_argv = malloc(sizeof (char *));
@@ -951,8 +953,9 @@
 	(void) uname(&dtp->dt_uts);
 
 	if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
-	    dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
-	    dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
+	    dtp->dt_procs == NULL || dtp->dt_proc_env == NULL ||
+	    dtp->dt_ld_path == NULL || dtp->dt_cpp_path == NULL ||
+	    dtp->dt_cpp_argv == NULL)
 		return (set_open_errno(dtp, errp, EDT_NOMEM));
 
 	for (i = 0; i < DTRACEOPT_MAX; i++)
@@ -1318,7 +1321,7 @@
 	int i;
 
 	if (dtp->dt_procs != NULL)
-		dt_proc_hash_destroy(dtp);
+		dt_proc_fini(dtp);
 
 	while ((pgp = dt_list_next(&dtp->dt_programs)) != NULL)
 		dt_program_destroy(dtp, pgp);
@@ -1365,7 +1368,6 @@
 	dt_strdata_destroy(dtp);
 	dt_buffered_destroy(dtp);
 	dt_aggregate_destroy(dtp);
-	free(dtp->dt_buf.dtbd_data);
 	dt_pfdict_destroy(dtp);
 	dt_provmod_destroy(&dtp->dt_provmod);
 	dt_dof_fini(dtp);
--- a/usr/src/lib/libdtrace/common/dt_options.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_options.c	Wed Jul 25 19:05:31 2012 -0400
@@ -24,6 +24,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 #include <sys/resource.h>
 #include <sys/mman.h>
 #include <sys/types.h>
@@ -364,6 +368,61 @@
 	return (0);
 }
 
+static int
+dt_opt_setenv(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
+{
+	char **p;
+	char *var;
+	int i;
+
+	/*
+	 * We can't effectively set environment variables from #pragma lines
+	 * since the processes have already been spawned.
+	 */
+	if (dtp->dt_pcb != NULL)
+		return (dt_set_errno(dtp, EDT_BADOPTCTX));
+
+	if (arg == NULL)
+		return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+	if (!option && strchr(arg, '=') != NULL)
+		return (dt_set_errno(dtp, EDT_BADOPTVAL));
+
+	for (i = 1, p = dtp->dt_proc_env; *p != NULL; i++, p++)
+		continue;
+
+	for (p = dtp->dt_proc_env; *p != NULL; p++) {
+		var = strchr(*p, '=');
+		if (var == NULL)
+			var = *p + strlen(*p);
+		if (strncmp(*p, arg, var - *p) == 0) {
+			dt_free(dtp, *p);
+			*p = dtp->dt_proc_env[i - 1];
+			dtp->dt_proc_env[i - 1] = NULL;
+			i--;
+		}
+	}
+
+	if (option) {
+		if ((var = strdup(arg)) == NULL)
+			return (dt_set_errno(dtp, EDT_NOMEM));
+
+		if ((p = dt_alloc(dtp, sizeof (char *) * (i + 1))) == NULL) {
+			dt_free(dtp, var);
+			return (dt_set_errno(dtp, EDT_NOMEM));
+		}
+
+		bcopy(dtp->dt_proc_env, p, sizeof (char *) * i);
+		dt_free(dtp, dtp->dt_proc_env);
+		dtp->dt_proc_env = p;
+
+		dtp->dt_proc_env[i - 1] = var;
+		dtp->dt_proc_env[i] = NULL;
+	}
+
+	return (0);
+}
+
 /*ARGSUSED*/
 static int
 dt_opt_stdc(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -407,7 +466,6 @@
 	return (0);
 }
 
-
 /*ARGSUSED*/
 static int
 dt_opt_tree(dtrace_hdl_t *dtp, const char *arg, uintptr_t option)
@@ -874,6 +932,7 @@
 	{ "nolibs", dt_opt_cflags, DTRACE_C_NOLIBS },
 	{ "pgmax", dt_opt_pgmax },
 	{ "pspec", dt_opt_cflags, DTRACE_C_PSPEC },
+	{ "setenv", dt_opt_setenv, 1 },
 	{ "stdc", dt_opt_stdc },
 	{ "strip", dt_opt_dflags, DTRACE_D_STRIP },
 	{ "syslibdir", dt_opt_syslibdir },
@@ -882,6 +941,7 @@
 	{ "udefs", dt_opt_invcflags, DTRACE_C_UNODEF },
 	{ "undef", dt_opt_cpp_opts, (uintptr_t)"-U" },
 	{ "unodefs", dt_opt_cflags, DTRACE_C_UNODEF },
+	{ "unsetenv", dt_opt_setenv, 0 },
 	{ "verbose", dt_opt_cflags, DTRACE_C_DIFV },
 	{ "version", dt_opt_version },
 	{ "zdefs", dt_opt_cflags, DTRACE_C_ZDEFS },
@@ -909,6 +969,7 @@
 	{ "statusrate", dt_opt_rate, DTRACEOPT_STATUSRATE },
 	{ "strsize", dt_opt_strsize, DTRACEOPT_STRSIZE },
 	{ "ustackframes", dt_opt_runtime, DTRACEOPT_USTACKFRAMES },
+	{ "temporal", dt_opt_runtime, DTRACEOPT_TEMPORAL },
 	{ NULL }
 };
 
--- a/usr/src/lib/libdtrace/common/dt_parser.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_parser.c	Wed Jul 25 19:05:31 2012 -0400
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -93,6 +94,7 @@
  */
 
 #include <sys/param.h>
+#include <sys/sysmacros.h>
 #include <limits.h>
 #include <setjmp.h>
 #include <strings.h>
@@ -1856,6 +1858,38 @@
 	return (dnp);
 }
 
+/*
+ * If an integer constant is being cast to another integer type, we can
+ * perform the cast as part of integer constant folding in this pass. We must
+ * take action when the integer is being cast to a smaller type or if it is
+ * changing signed-ness. If so, we first shift rp's bits bits high (losing
+ * excess bits if narrowing) and then shift them down with either a logical
+ * shift (unsigned) or arithmetic shift (signed).
+ */
+static void
+dt_cast(dt_node_t *lp, dt_node_t *rp)
+{
+	size_t srcsize = dt_node_type_size(rp);
+	size_t dstsize = dt_node_type_size(lp);
+
+	if (dstsize < srcsize) {
+		int n = (sizeof (uint64_t) - dstsize) * NBBY;
+		rp->dn_value <<= n;
+		rp->dn_value >>= n;
+	} else if (dstsize > srcsize) {
+		int n = (sizeof (uint64_t) - srcsize) * NBBY;
+		int s = (dstsize - srcsize) * NBBY;
+
+		rp->dn_value <<= n;
+		if (rp->dn_flags & DT_NF_SIGNED) {
+			rp->dn_value = (intmax_t)rp->dn_value >> s;
+			rp->dn_value >>= n - s;
+		} else {
+			rp->dn_value >>= n;
+		}
+	}
+}
+
 dt_node_t *
 dt_node_op2(int op, dt_node_t *lp, dt_node_t *rp)
 {
@@ -2005,32 +2039,9 @@
 		}
 	}
 
-	/*
-	 * If an integer constant is being cast to another integer type, we can
-	 * perform the cast as part of integer constant folding in this pass.
-	 * We must take action when the integer is being cast to a smaller type
-	 * or if it is changing signed-ness.  If so, we first shift rp's bits
-	 * bits high (losing excess bits if narrowing) and then shift them down
-	 * with either a logical shift (unsigned) or arithmetic shift (signed).
-	 */
 	if (op == DT_TOK_LPAR && rp->dn_kind == DT_NODE_INT &&
 	    dt_node_is_integer(lp)) {
-		size_t srcsize = dt_node_type_size(rp);
-		size_t dstsize = dt_node_type_size(lp);
-
-		if ((dstsize < srcsize) || ((lp->dn_flags & DT_NF_SIGNED) ^
-		    (rp->dn_flags & DT_NF_SIGNED))) {
-			int n = dstsize < srcsize ?
-			    (sizeof (uint64_t) * NBBY - dstsize * NBBY) :
-			    (sizeof (uint64_t) * NBBY - srcsize * NBBY);
-
-			rp->dn_value <<= n;
-			if (lp->dn_flags & DT_NF_SIGNED)
-				rp->dn_value = (intmax_t)rp->dn_value >> n;
-			else
-				rp->dn_value = rp->dn_value >> n;
-		}
-
+		dt_cast(lp, rp);
 		dt_node_type_propagate(lp, rp);
 		dt_node_attr_assign(rp, dt_attr_min(lp->dn_attr, rp->dn_attr));
 		dt_node_free(lp);
@@ -2889,14 +2900,14 @@
 	case DT_TOK_DEREF:
 		/*
 		 * If the deref operator is applied to a translated pointer,
-		 * we can just set our output type to the base translation.
+		 * we set our output type to the output of the translation.
 		 */
 		if ((idp = dt_node_resolve(cp, DT_IDENT_XLPTR)) != NULL) {
 			dt_xlator_t *dxp = idp->di_data;
 
 			dnp->dn_ident = &dxp->dx_souid;
 			dt_node_type_assign(dnp,
-			    DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+			    dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
 			break;
 		}
 
@@ -3072,6 +3083,31 @@
 	return (dnp);
 }
 
+static void
+dt_assign_common(dt_node_t *dnp)
+{
+	dt_node_t *lp = dnp->dn_left;
+	dt_node_t *rp = dnp->dn_right;
+	int op = dnp->dn_op;
+
+	if (rp->dn_kind == DT_NODE_INT)
+		dt_cast(lp, rp);
+
+	if (!(lp->dn_flags & DT_NF_LVALUE)) {
+		xyerror(D_OP_LVAL, "operator %s requires modifiable "
+		    "lvalue as an operand\n", opstr(op));
+		/* see K&R[A7.17] */
+	}
+
+	if (!(lp->dn_flags & DT_NF_WRITABLE)) {
+		xyerror(D_OP_WRITE, "operator %s can only be applied "
+		    "to a writable variable\n", opstr(op));
+	}
+
+	dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
+	dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+}
+
 static dt_node_t *
 dt_cook_op2(dt_node_t *dnp, uint_t idflags)
 {
@@ -3550,19 +3586,7 @@
 			}
 		}
 asgn_common:
-		if (!(lp->dn_flags & DT_NF_LVALUE)) {
-			xyerror(D_OP_LVAL, "operator %s requires modifiable "
-			    "lvalue as an operand\n", opstr(op));
-			/* see K&R[A7.17] */
-		}
-
-		if (!(lp->dn_flags & DT_NF_WRITABLE)) {
-			xyerror(D_OP_WRITE, "operator %s can only be applied "
-			    "to a writable variable\n", opstr(op));
-		}
-
-		dt_node_type_propagate(lp, dnp); /* see K&R[A7.17] */
-		dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+		dt_assign_common(dnp);
 		break;
 
 	case DT_TOK_PTR:
@@ -3867,6 +3891,14 @@
 
 		dt_node_type_propagate(lp, dnp); /* see K&R[A7.5] */
 		dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
+
+		/*
+		 * If it's a pointer then should be able to (attempt to)
+		 * assign to it.
+		 */
+		if (lkind == CTF_K_POINTER)
+			dnp->dn_flags |= DT_NF_WRITABLE;
+
 		break;
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dt_pq.c	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#include <dtrace.h>
+#include <dt_impl.h>
+#include <dt_pq.h>
+#include <assert.h>
+
+/*
+ * Create a new priority queue.
+ *
+ * size is the maximum number of items that will be stored in the priority
+ * queue at one time.
+ */
+dt_pq_t *
+dt_pq_init(dtrace_hdl_t *dtp, uint_t size, dt_pq_value_f value_cb, void *cb_arg)
+{
+	dt_pq_t *p;
+	assert(size > 1);
+
+	if ((p = dt_zalloc(dtp, sizeof (dt_pq_t))) == NULL)
+		return (NULL);
+
+	p->dtpq_items = dt_zalloc(dtp, size * sizeof (p->dtpq_items[0]));
+	if (p->dtpq_items == NULL) {
+		dt_free(dtp, p);
+		return (NULL);
+	}
+
+	p->dtpq_hdl = dtp;
+	p->dtpq_size = size;
+	p->dtpq_last = 1;
+	p->dtpq_value = value_cb;
+	p->dtpq_arg = cb_arg;
+
+	return (p);
+}
+
+void
+dt_pq_fini(dt_pq_t *p)
+{
+	dtrace_hdl_t *dtp = p->dtpq_hdl;
+
+	dt_free(dtp, p->dtpq_items);
+	dt_free(dtp, p);
+}
+
+static uint64_t
+dt_pq_getvalue(dt_pq_t *p, uint_t index)
+{
+	void *item = p->dtpq_items[index];
+	return (p->dtpq_value(item, p->dtpq_arg));
+}
+
+void
+dt_pq_insert(dt_pq_t *p, void *item)
+{
+	uint_t i;
+
+	assert(p->dtpq_last < p->dtpq_size);
+
+	i = p->dtpq_last++;
+	p->dtpq_items[i] = item;
+
+	while (i > 1 && dt_pq_getvalue(p, i) < dt_pq_getvalue(p, i / 2)) {
+		void *tmp = p->dtpq_items[i];
+		p->dtpq_items[i] = p->dtpq_items[i / 2];
+		p->dtpq_items[i / 2] = tmp;
+		i /= 2;
+	}
+}
+
+/*
+ * Return elements from the priority queue.  *cookie should be zero when first
+ * called.  Returns NULL when there are no more elements.
+ */
+void *
+dt_pq_walk(dt_pq_t *p, uint_t *cookie)
+{
+	(*cookie)++;
+	if (*cookie >= p->dtpq_last)
+		return (NULL);
+
+	return (p->dtpq_items[*cookie]);
+}
+
+void *
+dt_pq_pop(dt_pq_t *p)
+{
+	uint_t i = 1;
+	void *ret;
+
+	assert(p->dtpq_last > 0);
+
+	if (p->dtpq_last == 1)
+		return (NULL);
+
+	ret = p->dtpq_items[1];
+
+	p->dtpq_last--;
+	p->dtpq_items[1] = p->dtpq_items[p->dtpq_last];
+	p->dtpq_items[p->dtpq_last] = NULL;
+
+	for (;;) {
+		uint_t lc = i * 2;
+		uint_t rc = i * 2 + 1;
+		uint_t c;
+		uint64_t v;
+		void *tmp;
+
+		if (lc >= p->dtpq_last)
+			break;
+
+		if (rc >= p->dtpq_last) {
+			c = lc;
+			v = dt_pq_getvalue(p, lc);
+		} else {
+			uint64_t lv = dt_pq_getvalue(p, lc);
+			uint64_t rv = dt_pq_getvalue(p, rc);
+
+			if (lv < rv) {
+				c = lc;
+				v = lv;
+			} else {
+				c = rc;
+				v = rv;
+			}
+		}
+
+		if (v >= dt_pq_getvalue(p, i))
+			break;
+
+		tmp = p->dtpq_items[i];
+		p->dtpq_items[i] = p->dtpq_items[c];
+		p->dtpq_items[c] = tmp;
+
+		i = c;
+	}
+
+	return (ret);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dt_pq.h	Wed Jul 25 19:05:31 2012 -0400
@@ -0,0 +1,51 @@
+/*
+ * CDDL HEADER START
+ *
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#ifndef	_DT_PQ_H
+#define	_DT_PQ_H
+
+#include <dtrace.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+typedef uint64_t (*dt_pq_value_f)(void *, void *);
+
+typedef struct dt_pq {
+	dtrace_hdl_t *dtpq_hdl;		/* dtrace handle */
+	void **dtpq_items;		/* array of elements */
+	uint_t dtpq_size;		/* count of allocated elements */
+	uint_t dtpq_last;		/* next free slot */
+	dt_pq_value_f dtpq_value;	/* callback to get the value */
+	void *dtpq_arg;			/* callback argument */
+} dt_pq_t;
+
+extern dt_pq_t *dt_pq_init(dtrace_hdl_t *, uint_t size, dt_pq_value_f, void *);
+extern void dt_pq_fini(dt_pq_t *);
+
+extern void dt_pq_insert(dt_pq_t *, void *);
+extern void *dt_pq_pop(dt_pq_t *);
+extern void *dt_pq_walk(dt_pq_t *, uint_t *);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _DT_PQ_H */
--- a/usr/src/lib/libdtrace/common/dt_printf.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_printf.c	Wed Jul 25 19:05:31 2012 -0400
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <sys/sysmacros.h>
@@ -154,7 +155,7 @@
 pfcheck_dint(dt_pfargv_t *pfv, dt_pfargd_t *pfd, dt_node_t *dnp)
 {
 	if (dnp->dn_flags & DT_NF_SIGNED)
-		pfd->pfd_flags |= DT_PFCONV_SIGNED;
+		pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'i';
 	else
 		pfd->pfd_fmt[strlen(pfd->pfd_fmt) - 1] = 'u';
 
@@ -642,7 +643,7 @@
 { "hu", "u", "unsigned short", pfcheck_type, pfprint_uint },
 { "hx", "x", "short", pfcheck_xshort, pfprint_uint },
 { "hX", "X", "short", pfcheck_xshort, pfprint_uint },
-{ "i", "i", pfproto_xint, pfcheck_dint, pfprint_dint },
+{ "i", "i", pfproto_xint, pfcheck_xint, pfprint_sint },
 { "I", "s", pfproto_cstr, pfcheck_str, pfprint_inetaddr },
 { "k", "s", "stack", pfcheck_stack, pfprint_stack },
 { "lc", "lc", "int", pfcheck_type, pfprint_sint }, /* a.k.a. wint_t */
--- a/usr/src/lib/libdtrace/common/dt_proc.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_proc.c	Wed Jul 25 19:05:31 2012 -0400
@@ -25,6 +25,10 @@
  */
 
 /*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
  * DTrace Process Control
  *
  * This file provides a set of routines that permit libdtrace and its clients
@@ -460,7 +464,7 @@
 	dt_proc_control_data_t *datap = arg;
 	dtrace_hdl_t *dtp = datap->dpcd_hdl;
 	dt_proc_t *dpr = datap->dpcd_proc;
-	dt_proc_hash_t *dph = dpr->dpr_hdl->dt_procs;
+	dt_proc_hash_t *dph = dtp->dt_procs;
 	struct ps_prochandle *P = dpr->dpr_proc;
 
 	int pfd = Pctlfd(P);
@@ -870,7 +874,8 @@
 	(void) pthread_mutex_init(&dpr->dpr_lock, NULL);
 	(void) pthread_cond_init(&dpr->dpr_cv, NULL);
 
-	if ((dpr->dpr_proc = Pcreate(file, argv, &err, NULL, 0)) == NULL) {
+	dpr->dpr_proc = Pxcreate(file, argv, dtp->dt_proc_env, &err, NULL, 0);
+	if (dpr->dpr_proc == NULL) {
 		return (dt_proc_error(dtp, dpr,
 		    "failed to execute %s: %s\n", file, Pcreate_error(err)));
 	}
@@ -1034,30 +1039,75 @@
 }
 
 void
-dt_proc_hash_create(dtrace_hdl_t *dtp)
+dt_proc_init(dtrace_hdl_t *dtp)
 {
+	extern char **environ;
+	static char *envdef[] = {
+		"LD_NOLAZYLOAD=1",	/* linker lazy loading hides funcs */
+		NULL
+	};
+	char **p;
+	int i;
+
 	if ((dtp->dt_procs = dt_zalloc(dtp, sizeof (dt_proc_hash_t) +
-	    sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) != NULL) {
+	    sizeof (dt_proc_t *) * _dtrace_pidbuckets - 1)) == NULL)
+		return;
+
+	(void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
+	(void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
+
+	dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
+	dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
+
 
-		(void) pthread_mutex_init(&dtp->dt_procs->dph_lock, NULL);
-		(void) pthread_cond_init(&dtp->dt_procs->dph_cv, NULL);
+	/*
+	 * Count how big our environment needs to be.
+	 */
+	for (i = 1, p = environ; *p != NULL; i++, p++)
+		continue;
+	for (p = envdef; *p != NULL; i++, p++)
+		continue;
+
+	if ((dtp->dt_proc_env = dt_zalloc(dtp, sizeof (char *) * i)) == NULL)
+		return;
 
-		dtp->dt_procs->dph_hashlen = _dtrace_pidbuckets;
-		dtp->dt_procs->dph_lrulim = _dtrace_pidlrulim;
+	for (i = 0, p = environ; *p != NULL; i++, p++) {
+		if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
+			goto err;
+	}
+	for (p = envdef; *p != NULL; i++, p++) {
+		if ((dtp->dt_proc_env[i] = strdup(*p)) == NULL)
+			goto err;
 	}
+
+	return;
+
+err:
+	while (--i != 0) {
+		dt_free(dtp, dtp->dt_proc_env[i]);
+	}
+	dt_free(dtp, dtp->dt_proc_env);
+	dtp->dt_proc_env = NULL;
 }
 
 void
-dt_proc_hash_destroy(dtrace_hdl_t *dtp)
+dt_proc_fini(dtrace_hdl_t *dtp)
 {
 	dt_proc_hash_t *dph = dtp->dt_procs;
 	dt_proc_t *dpr;
+	char **p;
 
 	while ((dpr = dt_list_next(&dph->dph_lrulist)) != NULL)
 		dt_proc_destroy(dtp, dpr->dpr_proc);
 
 	dtp->dt_procs = NULL;
 	dt_free(dtp, dph);
+
+	for (p = dtp->dt_proc_env; *p != NULL; p++)
+		dt_free(dtp, *p);
+
+	dt_free(dtp, dtp->dt_proc_env);
+	dtp->dt_proc_env = NULL;
 }
 
 struct ps_prochandle *
--- a/usr/src/lib/libdtrace/common/dt_proc.h	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_proc.h	Wed Jul 25 19:05:31 2012 -0400
@@ -24,11 +24,13 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 #ifndef	_DT_PROC_H
 #define	_DT_PROC_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <libproc.h>
 #include <dtrace.h>
 #include <pthread.h>
@@ -106,8 +108,8 @@
 extern void dt_proc_unlock(dtrace_hdl_t *, struct ps_prochandle *);
 extern dt_proc_t *dt_proc_lookup(dtrace_hdl_t *, struct ps_prochandle *, int);
 
-extern void dt_proc_hash_create(dtrace_hdl_t *);
-extern void dt_proc_hash_destroy(dtrace_hdl_t *);
+extern void dt_proc_init(dtrace_hdl_t *);
+extern void dt_proc_fini(dtrace_hdl_t *);
 
 #ifdef	__cplusplus
 }
--- a/usr/src/lib/libdtrace/common/dt_regset.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_regset.c	Wed Jul 25 19:05:31 2012 -0400
@@ -19,12 +19,15 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/bitmap.h>
@@ -33,18 +36,19 @@
 #include <stdlib.h>
 
 #include <dt_regset.h>
+#include <dt_impl.h>
 
 dt_regset_t *
-dt_regset_create(ulong_t size)
+dt_regset_create(ulong_t nregs)
 {
-	ulong_t n = BT_BITOUL(size + 1); /* + 1 for %r0 */
+	ulong_t n = BT_BITOUL(nregs);
 	dt_regset_t *drp = malloc(sizeof (dt_regset_t));
 
 	if (drp == NULL)
 		return (NULL);
 
 	drp->dr_bitmap = malloc(sizeof (ulong_t) * n);
-	drp->dr_size = size + 1;
+	drp->dr_size = nregs;
 
 	if (drp->dr_bitmap == NULL) {
 		dt_regset_destroy(drp);
@@ -68,6 +72,25 @@
 	bzero(drp->dr_bitmap, sizeof (ulong_t) * BT_BITOUL(drp->dr_size));
 }
 
+void
+dt_regset_assert_free(dt_regset_t *drp)
+{
+	int reg;
+	boolean_t fail = B_FALSE;
+	for (reg = 0; reg < drp->dr_size; reg++) {
+		if (BT_TEST(drp->dr_bitmap, reg) != 0)  {
+			dt_dprintf("%%r%d was left allocated\n", reg);
+			fail = B_TRUE;
+		}
+	}
+
+	/*
+	 * We set this during dtest runs to check for register leaks.
+	 */
+	if (fail && getenv("DTRACE_DEBUG_REGSET") != NULL)
+		abort();
+}
+
 int
 dt_regset_alloc(dt_regset_t *drp)
 {
@@ -95,13 +118,15 @@
 		}
 	}
 
-	return (-1); /* no available registers */
+	xyerror(D_NOREG, "Insufficient registers to generate code");
+	/*NOTREACHED*/
+	return (-1);
 }
 
 void
 dt_regset_free(dt_regset_t *drp, int reg)
 {
-	assert(reg > 0 && reg < drp->dr_size);
+	assert(reg >= 0 && reg < drp->dr_size);
 	assert(BT_TEST(drp->dr_bitmap, reg) != 0);
 	BT_CLEAR(drp->dr_bitmap, reg);
 }
--- a/usr/src/lib/libdtrace/common/dt_regset.h	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_regset.h	Wed Jul 25 19:05:31 2012 -0400
@@ -19,16 +19,19 @@
  *
  * CDDL HEADER END
  */
+
 /*
  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 #ifndef	_DT_REGSET_H
 #define	_DT_REGSET_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 
 #ifdef	__cplusplus
@@ -45,6 +48,7 @@
 extern void dt_regset_reset(dt_regset_t *);
 extern int dt_regset_alloc(dt_regset_t *);
 extern void dt_regset_free(dt_regset_t *, int);
+extern void dt_regset_assert_free(dt_regset_t *);
 
 #ifdef	__cplusplus
 }
--- a/usr/src/lib/libdtrace/common/dt_subr.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/common/dt_subr.c	Wed Jul 25 19:05:31 2012 -0400
@@ -21,6 +21,7 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #include <sys/sysmacros.h>
@@ -577,8 +578,8 @@
 		size_t avail;
 
 		/*
-		 * It's not legal to use buffered ouput if there is not a
-		 * handler for buffered output.
+		 * Using buffered output is not allowed if a handler has
+		 * not been installed.
 		 */
 		if (dtp->dt_bufhdlr == NULL) {
 			va_end(ap);
--- a/usr/src/lib/libdtrace/i386/dt_isadep.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/lib/libdtrace/i386/dt_isadep.c	Wed Jul 25 19:05:31 2012 -0400
@@ -24,6 +24,10 @@
  * Use is subject to license terms.
  */
 
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
 #include <stdlib.h>
 #include <assert.h>
 #include <errno.h>
@@ -481,7 +485,8 @@
 	 * another debugger attached to this process. The original instruction
 	 * can't be recovered so this must fail.
 	 */
-	if (x86dis.d86_len == 1 && instr[0] == FASTTRAP_INSTR)
+	if (x86dis.d86_len == 1 &&
+	    (uchar_t)x86dis.d86_bytes[0] == FASTTRAP_INSTR)
 		return (-1);
 
 	return (x86dis.d86_len);
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf	Wed Jul 25 19:05:31 2012 -0400
@@ -21,7 +21,7 @@
 
 #
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright (c) 2011 by Delphix. All rights reserved.
+# Copyright (c) 2012 by Delphix. All rights reserved.
 #
 
 set name=pkg.fmri value=pkg:/system/dtrace/tests@$(PKGVERS)
@@ -52,6 +52,7 @@
 dir path=opt/SUNWdtrt/tst/common/bitfields
 dir path=opt/SUNWdtrt/tst/common/buffering
 dir path=opt/SUNWdtrt/tst/common/builtinvar
+dir path=opt/SUNWdtrt/tst/common/cg
 dir path=opt/SUNWdtrt/tst/common/clauses
 dir path=opt/SUNWdtrt/tst/common/cpc
 dir path=opt/SUNWdtrt/tst/common/decls
@@ -59,6 +60,7 @@
 dir path=opt/SUNWdtrt/tst/common/dtraceUtil
 dir path=opt/SUNWdtrt/tst/common/end
 dir path=opt/SUNWdtrt/tst/common/enum
+dir path=opt/SUNWdtrt/tst/common/env
 dir path=opt/SUNWdtrt/tst/common/error
 dir path=opt/SUNWdtrt/tst/common/exit
 dir path=opt/SUNWdtrt/tst/common/fbtprovider
@@ -333,6 +335,8 @@
 file path=opt/SUNWdtrt/tst/common/aggs/tst.signedkeys.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/aggs/tst.signedkeyspos.d mode=0444
 file path=opt/SUNWdtrt/tst/common/aggs/tst.signedkeyspos.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/aggs/tst.sizedkeys.d mode=0444
+file path=opt/SUNWdtrt/tst/common/aggs/tst.sizedkeys.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/aggs/tst.stddev.d mode=0444
 file path=opt/SUNWdtrt/tst/common/aggs/tst.stddev.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/aggs/tst.subr.d mode=0444
@@ -357,7 +361,14 @@
 file path=opt/SUNWdtrt/tst/common/arithmetic/err.D_SYNTAX.muladd.d mode=0444
 file path=opt/SUNWdtrt/tst/common/arithmetic/err.D_SYNTAX.muldiv.d mode=0444
 file path=opt/SUNWdtrt/tst/common/arithmetic/tst.basics.d mode=0444
-file path=opt/SUNWdtrt/tst/common/arithmetic/tst.complex.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.basics.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compcast.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compcast.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compnarrowassign.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.compnarrowassign.d.out \
+    mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.execcast.d mode=0444
+file path=opt/SUNWdtrt/tst/common/arithmetic/tst.execcast.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/arrays/err.D_ARR_BADREF.bad.d mode=0444
 file path=opt/SUNWdtrt/tst/common/arrays/err.D_DECL_ARRBIG.toobig.d mode=0444
 file path=opt/SUNWdtrt/tst/common/arrays/err.D_DECL_ARRNULL.bad.d mode=0444
@@ -474,6 +485,8 @@
 file path=opt/SUNWdtrt/tst/common/builtinvar/tst.tid1.d mode=0444
 file path=opt/SUNWdtrt/tst/common/builtinvar/tst.timestamp.d mode=0444
 file path=opt/SUNWdtrt/tst/common/builtinvar/tst.vtimestamp.d mode=0444
+file path=opt/SUNWdtrt/tst/common/cg/err.D_NOREG.noreg.d mode=0444
+file path=opt/SUNWdtrt/tst/common/cg/err.baddif.d mode=0444
 file path=opt/SUNWdtrt/tst/common/clauses/err.D_IDENT_UNDEF.aggfun.d mode=0444
 file path=opt/SUNWdtrt/tst/common/clauses/err.D_IDENT_UNDEF.aggtup.d mode=0444
 file path=opt/SUNWdtrt/tst/common/clauses/err.D_IDENT_UNDEF.arrtup.d mode=0444
@@ -720,6 +733,20 @@
 file path=opt/SUNWdtrt/tst/common/enum/tst.EnumEquality.d mode=0444
 file path=opt/SUNWdtrt/tst/common/enum/tst.EnumSameValue.d mode=0444
 file path=opt/SUNWdtrt/tst/common/enum/tst.EnumValAssign.d mode=0444
+file path=opt/SUNWdtrt/tst/common/env/err.D_PRAGMA_OPTSET.setfromscript.d \
+    mode=0444
+file path=opt/SUNWdtrt/tst/common/env/err.D_PRAGMA_OPTSET.unsetfromscript.d \
+    mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.ld_nolazyload.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.ld_nolazyload.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv1.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv1.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.setenv2.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv1.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv1.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/env/tst.unsetenv2.ksh.out mode=0444
 file path=opt/SUNWdtrt/tst/common/error/tst.DTRACEFLT_BADADDR.d mode=0444
 file path=opt/SUNWdtrt/tst/common/error/tst.DTRACEFLT_DIVZERO.d mode=0444
 file path=opt/SUNWdtrt/tst/common/error/tst.DTRACEFLT_UNKNOWN.d mode=0444
@@ -1153,6 +1180,8 @@
 file path=opt/SUNWdtrt/tst/common/pointers/tst.ValidPointer1.d mode=0444
 file path=opt/SUNWdtrt/tst/common/pointers/tst.ValidPointer2.d mode=0444
 file path=opt/SUNWdtrt/tst/common/pointers/tst.VoidCast.d mode=0444
+file path=opt/SUNWdtrt/tst/common/pointers/tst.assigncast1.d mode=0444
+file path=opt/SUNWdtrt/tst/common/pointers/tst.assigncast2.d mode=0444
 file path=opt/SUNWdtrt/tst/common/pointers/tst.basic1.d mode=0444
 file path=opt/SUNWdtrt/tst/common/pointers/tst.basic2.d mode=0444
 file path=opt/SUNWdtrt/tst/common/pragma/err.D_PRAGERR.d mode=0444
@@ -1168,6 +1197,9 @@
 file path=opt/SUNWdtrt/tst/common/pragma/tst.libdepfullyconnected.ksh \
     mode=0444
 file path=opt/SUNWdtrt/tst/common/pragma/tst.libdepsepdir.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/pragma/tst.temporal.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/pragma/tst.temporal2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/pragma/tst.temporal3.d mode=0444
 file path=opt/SUNWdtrt/tst/common/predicates/err.D_PRED_SCALAR.NonScalarPred.d \
     mode=0444
 file path=opt/SUNWdtrt/tst/common/predicates/err.D_SYNTAX.invalid.d mode=0444
@@ -1177,7 +1209,6 @@
 file path=opt/SUNWdtrt/tst/common/predicates/tst.basics.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/predicates/tst.complex.d mode=0444
 file path=opt/SUNWdtrt/tst/common/predicates/tst.complex.d.out mode=0444
-file path=opt/SUNWdtrt/tst/common/predicates/tst.predcache.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/preprocessor/err.D_IDENT_UNDEF.afterprobe.d \
     mode=0444
 file path=opt/SUNWdtrt/tst/common/preprocessor/err.D_PRAGCTL_INVAL.tabdefine.d \
@@ -1222,17 +1253,19 @@
 file path=opt/SUNWdtrt/tst/common/preprocessor/tst.preexpifelse.d.out \
     mode=0444
 file path=opt/SUNWdtrt/tst/common/preprocessor/tst.withinprobe.d mode=0444
-file path=opt/SUNWdtrt/tst/common/print/err.D_PRINT_DYN.bad.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/err.D_PRINT_VOID.bad.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/err.D_PROTO_LEN.bad.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.array.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.array.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.bitfield.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.bitfield.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/print/tst.dyn.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.primitive.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.primitive.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.struct.d mode=0444
 file path=opt/SUNWdtrt/tst/common/print/tst.struct.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/print/tst.xlate.d mode=0444
+file path=opt/SUNWdtrt/tst/common/print/tst.xlate.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/printa/err.D_PRINTA_AGGARG.badagg.d \
     mode=0444
 file path=opt/SUNWdtrt/tst/common/printa/err.D_PRINTA_AGGARG.badfmt.d \
@@ -1313,6 +1346,8 @@
 file path=opt/SUNWdtrt/tst/common/printf/tst.printgG.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/printf/tst.rawfmt.d mode=0444
 file path=opt/SUNWdtrt/tst/common/printf/tst.rawfmt.d.out mode=0444
+file path=opt/SUNWdtrt/tst/common/printf/tst.signs.d mode=0444
+file path=opt/SUNWdtrt/tst/common/printf/tst.signs.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/printf/tst.str.d mode=0444
 file path=opt/SUNWdtrt/tst/common/printf/tst.str.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/printf/tst.sym.d mode=0444
@@ -1766,8 +1801,8 @@
 file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickusec.d mode=0444
 file path=opt/SUNWdtrt/tst/common/tick-n/tst.tickusec.d.out mode=0444
 file path=opt/SUNWdtrt/tst/common/trace/err.D_PROTO_LEN.bad.d mode=0444
-file path=opt/SUNWdtrt/tst/common/trace/err.D_TRACE_DYN.bad.d mode=0444
 file path=opt/SUNWdtrt/tst/common/trace/err.D_TRACE_VOID.bad.d mode=0444
+file path=opt/SUNWdtrt/tst/common/trace/tst.dyn.d mode=0444
 file path=opt/SUNWdtrt/tst/common/trace/tst.misc.d mode=0444
 file path=opt/SUNWdtrt/tst/common/trace/tst.qstring.d mode=0444
 file path=opt/SUNWdtrt/tst/common/trace/tst.qstring.d.out mode=0444
@@ -1838,6 +1873,14 @@
     mode=0444
 file path=opt/SUNWdtrt/tst/common/translators/tst.StructureAssignment.d \
     mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability1.ksh \
+    mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability1.ksh.out \
+    mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability2.ksh \
+    mode=0444
+file path=opt/SUNWdtrt/tst/common/translators/tst.TestTransStability2.ksh.out \
+    mode=0444
 file path=opt/SUNWdtrt/tst/common/translators/tst.TransNonPointer.d mode=0444
 file path=opt/SUNWdtrt/tst/common/translators/tst.TransOutputPointer.d \
     mode=0444
--- a/usr/src/uts/common/dtrace/dtrace.c	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/uts/common/dtrace/dtrace.c	Wed Jul 25 19:05:31 2012 -0400
@@ -22,6 +22,7 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -2401,9 +2402,10 @@
 {
 	dtrace_speculation_t *spec;
 	dtrace_buffer_t *src, *dest;
-	uintptr_t daddr, saddr, dlimit;
+	uintptr_t daddr, saddr, dlimit, slimit;
 	dtrace_speculation_state_t current, new;
 	intptr_t offs;
+	uint64_t timestamp;
 
 	if (which == 0)
 		return;
@@ -2479,7 +2481,37 @@
 	}
 
 	/*
-	 * We have the space; copy the buffer across.  (Note that this is a
+	 * We have sufficient space to copy the speculative buffer into the
+	 * primary buffer.  First, modify the speculative buffer, filling
+	 * in the timestamp of all entries with the current time.  The data
+	 * must have the commit() time rather than the time it was traced,
+	 * so that all entries in the primary buffer are in timestamp order.
+	 */
+	timestamp = dtrace_gethrtime();
+	saddr = (uintptr_t)src->dtb_tomax;
+	slimit = saddr + src->dtb_offset;
+	while (saddr < slimit) {
+		size_t size;
+		dtrace_rechdr_t *dtrh = (dtrace_rechdr_t *)saddr;
+
+		if (dtrh->dtrh_epid == DTRACE_EPIDNONE) {
+			saddr += sizeof (dtrace_epid_t);
+			continue;
+		}
+		ASSERT3U(dtrh->dtrh_epid, <=, state->dts_necbs);
+		size = state->dts_ecbs[dtrh->dtrh_epid - 1]->dte_size;
+
+		ASSERT3U(saddr + size, <=, slimit);
+		ASSERT3U(size, >=, sizeof (dtrace_rechdr_t));
+		ASSERT3U(DTRACE_RECORD_LOAD_TIMESTAMP(dtrh), ==, UINT64_MAX);
+
+		DTRACE_RECORD_STORE_TIMESTAMP(dtrh, timestamp);
+
+		saddr += size;
+	}
+
+	/*
+	 * Copy the buffer across.  (Note that this is a
 	 * highly subobtimal bcopy(); in the unlikely event that this becomes
 	 * a serious performance issue, a high-performance DTrace-specific
 	 * bcopy() should obviously be invented.)
@@ -5951,7 +5983,7 @@
 		if (now - state->dts_alive > dtrace_deadman_timeout) {
 			/*
 			 * We seem to be dead.  Unless we (a) have kernel
-			 * destructive permissions (b) have expicitly enabled
+			 * destructive permissions (b) have explicitly enabled
 			 * destructive actions and (c) destructive actions have
 			 * not been disabled, we're going to transition into
 			 * the KILLED state, from which no further processing
@@ -5979,8 +6011,18 @@
 		tomax = buf->dtb_tomax;
 		ASSERT(tomax != NULL);
 
-		if (ecb->dte_size != 0)
-			DTRACE_STORE(uint32_t, tomax, offs, ecb->dte_epid);
+		if (ecb->dte_size != 0) {
+			dtrace_rechdr_t dtrh;
+			if (!(mstate.dtms_present & DTRACE_MSTATE_TIMESTAMP)) {
+				mstate.dtms_timestamp = dtrace_gethrtime();
+				mstate.dtms_present |= DTRACE_MSTATE_TIMESTAMP;
+			}
+			ASSERT3U(ecb->dte_size, >=, sizeof (dtrace_rechdr_t));
+			dtrh.dtrh_epid = ecb->dte_epid;
+			DTRACE_RECORD_STORE_TIMESTAMP(&dtrh,
+			    mstate.dtms_timestamp);
+			*((dtrace_rechdr_t *)(tomax + offs)) = dtrh;
+		}
 
 		mstate.dtms_epid = ecb->dte_epid;
 		mstate.dtms_present |= DTRACE_MSTATE_EPID;
@@ -6144,7 +6186,9 @@
 				continue;
 
 			switch (act->dta_kind) {
-			case DTRACEACT_SPECULATE:
+			case DTRACEACT_SPECULATE: {
+				dtrace_rechdr_t *dtrh;
+
 				ASSERT(buf == &state->dts_buffer[cpuid]);
 				buf = dtrace_speculation_buffer(state,
 				    cpuid, val);
@@ -6166,10 +6210,23 @@
 				tomax = buf->dtb_tomax;
 				ASSERT(tomax != NULL);
 
-				if (ecb->dte_size != 0)
-					DTRACE_STORE(uint32_t, tomax, offs,
-					    ecb->dte_epid);
+				if (ecb->dte_size == 0)
+					continue;
+
+				ASSERT3U(ecb->dte_size, >=,
+				    sizeof (dtrace_rechdr_t));
+				dtrh = ((void *)(tomax + offs));
+				dtrh->dtrh_epid = ecb->dte_epid;
+				/*
+				 * When the speculation is committed, all of
+				 * the records in the speculative buffer will
+				 * have their timestamps set to the commit
+				 * time.  Until then, it is set to a sentinel
+				 * value, for debugability.
+				 */
+				DTRACE_RECORD_STORE_TIMESTAMP(dtrh, UINT64_MAX);
 				continue;
+			}
 
 			case DTRACEACT_CHILL:
 				if (dtrace_priv_kernel_destructive(state))
@@ -9369,9 +9426,9 @@
 
 	/*
 	 * The default size is the size of the default action: recording
-	 * the epid.
-	 */
-	ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
+	 * the header.
+	 */
+	ecb->dte_size = ecb->dte_needed = sizeof (dtrace_rechdr_t);
 	ecb->dte_alignment = sizeof (dtrace_epid_t);
 
 	epid = state->dts_epid++;
@@ -9470,122 +9527,89 @@
 static void
 dtrace_ecb_resize(dtrace_ecb_t *ecb)
 {
-	uint32_t maxalign = sizeof (dtrace_epid_t);
-	uint32_t align = sizeof (uint8_t), offs, diff;
 	dtrace_action_t *act;
-	int wastuple = 0;
+	uint32_t curneeded = UINT32_MAX;
 	uint32_t aggbase = UINT32_MAX;
-	dtrace_state_t *state = ecb->dte_state;
-
-	/*
-	 * If we record anything, we always record the epid.  (And we always
-	 * record it first.)
-	 */
-	offs = sizeof (dtrace_epid_t);
-	ecb->dte_size = ecb->dte_needed = sizeof (dtrace_epid_t);
+
+	/*
+	 * If we record anything, we always record the dtrace_rechdr_t.  (And
+	 * we always record it first.)
+	 */
+	ecb->dte_size = sizeof (dtrace_rechdr_t);
+	ecb->dte_alignment = sizeof (dtrace_epid_t);
 
 	for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
 		dtrace_recdesc_t *rec = &act->dta_rec;
-
-		if ((align = rec->dtrd_alignment) > maxalign)
-			maxalign = align;
-
-		if (!wastuple && act->dta_intuple) {
-			/*
-			 * This is the first record in a tuple.  Align the
-			 * offset to be at offset 4 in an 8-byte aligned
-			 * block.
-			 */
-			diff = offs + sizeof (dtrace_aggid_t);
-
-			if (diff = (diff & (sizeof (uint64_t) - 1)))
-				offs += sizeof (uint64_t) - diff;
-
-			aggbase = offs - sizeof (dtrace_aggid_t);
-			ASSERT(!(aggbase & (sizeof (uint64_t) - 1)));
-		}
-
-		/*LINTED*/
-		if (rec->dtrd_size != 0 && (diff = (offs & (align - 1)))) {
-			/*
-			 * The current offset is not properly aligned; align it.
-			 */
-			offs += align - diff;
-		}
-
-		rec->dtrd_offset = offs;
-
-		if (offs + rec->dtrd_size > ecb->dte_needed) {
-			ecb->dte_needed = offs + rec->dtrd_size;
-
-			if (ecb->dte_needed > state->dts_needed)
-				state->dts_needed = ecb->dte_needed;
-		}
+		ASSERT(rec->dtrd_size > 0 || rec->dtrd_alignment == 1);
+
+		ecb->dte_alignment = MAX(ecb->dte_alignment,
+		    rec->dtrd_alignment);
 
 		if (DTRACEACT_ISAGG(act->dta_kind)) {
 			dtrace_aggregation_t *agg = (dtrace_aggregation_t *)act;
-			dtrace_action_t *first = agg->dtag_first, *prev;
-
-			ASSERT(rec->dtrd_size != 0 && first != NULL);
-			ASSERT(wastuple);
+
+			ASSERT(rec->dtrd_size != 0);
+			ASSERT(agg->dtag_first != NULL);
+			ASSERT(act->dta_prev->dta_intuple);
 			ASSERT(aggbase != UINT32_MAX);
+			ASSERT(curneeded != UINT32_MAX);
 
 			agg->dtag_base = aggbase;
 
-			while ((prev = first->dta_prev) != NULL &&
-			    DTRACEACT_ISAGG(prev->dta_kind)) {
-				agg = (dtrace_aggregation_t *)prev;
-				first = agg->dtag_first;
-			}
-
-			if (prev != NULL) {
-				offs = prev->dta_rec.dtrd_offset +
-				    prev->dta_rec.dtrd_size;
-			} else {
-				offs = sizeof (dtrace_epid_t);
-			}
-			wastuple = 0;
+			curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
+			rec->dtrd_offset = curneeded;
+			curneeded += rec->dtrd_size;
+			ecb->dte_needed = MAX(ecb->dte_needed, curneeded);
+
+			aggbase = UINT32_MAX;
+			curneeded = UINT32_MAX;
+		} else if (act->dta_intuple) {
+			if (curneeded == UINT32_MAX) {
+				/*
+				 * This is the first record in a tuple.  Align
+				 * curneeded to be at offset 4 in an 8-byte
+				 * aligned block.
+				 */
+				ASSERT(act->dta_prev == NULL ||
+				    !act->dta_prev->dta_intuple);
+				ASSERT3U(aggbase, ==, UINT32_MAX);
+				curneeded = P2PHASEUP(ecb->dte_size,
+				    sizeof (uint64_t), sizeof (dtrace_aggid_t));
+
+				aggbase = curneeded - sizeof (dtrace_aggid_t);
+				ASSERT(IS_P2ALIGNED(aggbase,
+				    sizeof (uint64_t)));
+			}
+			curneeded = P2ROUNDUP(curneeded, rec->dtrd_alignment);
+			rec->dtrd_offset = curneeded;
+			curneeded += rec->dtrd_size;
 		} else {
-			if (!act->dta_intuple)
-				ecb->dte_size = offs + rec->dtrd_size;
-
-			offs += rec->dtrd_size;
-		}
-
-		wastuple = act->dta_intuple;
+			/* tuples must be followed by an aggregation */
+			ASSERT(act->dta_prev == NULL ||
+			    !act->dta_prev->dta_intuple);
+
+			ecb->dte_size = P2ROUNDUP(ecb->dte_size,
+			    rec->dtrd_alignment);
+			rec->dtrd_offset = ecb->dte_size;
+			ecb->dte_size += rec->dtrd_size;
+			ecb->dte_needed = MAX(ecb->dte_needed, ecb->dte_size);
+		}
 	}
 
 	if ((act = ecb->dte_action) != NULL &&
 	    !(act->dta_kind == DTRACEACT_SPECULATE && act->dta_next == NULL) &&
-	    ecb->dte_size == sizeof (dtrace_epid_t)) {
-		/*
-		 * If the size is still sizeof (dtrace_epid_t), then all
+	    ecb->dte_size == sizeof (dtrace_rechdr_t)) {
+		/*
+		 * If the size is still sizeof (dtrace_rechdr_t), then all
 		 * actions store no data; set the size to 0.
 		 */
-		ecb->dte_alignment = maxalign;
 		ecb->dte_size = 0;
-
-		/*
-		 * If the needed space is still sizeof (dtrace_epid_t), then
-		 * all actions need no additional space; set the needed
-		 * size to 0.
-		 */
-		if (ecb->dte_needed == sizeof (dtrace_epid_t))
-			ecb->dte_needed = 0;
-
-		return;
-	}
-
-	/*
-	 * Set our alignment, and make sure that the dte_size and dte_needed
-	 * are aligned to the size of an EPID.
-	 */
-	ecb->dte_alignment = maxalign;
-	ecb->dte_size = (ecb->dte_size + (sizeof (dtrace_epid_t) - 1)) &
-	    ~(sizeof (dtrace_epid_t) - 1);
-	ecb->dte_needed = (ecb->dte_needed + (sizeof (dtrace_epid_t) - 1)) &
-	    ~(sizeof (dtrace_epid_t) - 1);
-	ASSERT(ecb->dte_size <= ecb->dte_needed);
+	}
+
+	ecb->dte_size = P2ROUNDUP(ecb->dte_size, sizeof (dtrace_epid_t));
+	ecb->dte_needed = P2ROUNDUP(ecb->dte_needed, (sizeof (dtrace_epid_t)));
+	ecb->dte_state->dts_needed = MAX(ecb->dte_state->dts_needed,
+	    ecb->dte_needed);
 }
 
 static dtrace_action_t *
@@ -9955,7 +9979,7 @@
 			break;
 
 		case DTRACEACT_SPECULATE:
-			if (ecb->dte_size > sizeof (dtrace_epid_t))
+			if (ecb->dte_size > sizeof (dtrace_rechdr_t))
 				return (EINVAL);
 
 			if (dp == NULL)
@@ -10068,7 +10092,7 @@
 
 	ecb->dte_action = NULL;
 	ecb->dte_action_last = NULL;
-	ecb->dte_size = sizeof (dtrace_epid_t);
+	ecb->dte_size = 0;
 }
 
 static void
@@ -10339,12 +10363,13 @@
 	caddr_t tomax = buf->dtb_tomax;
 	caddr_t xamot = buf->dtb_xamot;
 	dtrace_icookie_t cookie;
-	hrtime_t now = dtrace_gethrtime();
+	hrtime_t now;
 
 	ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
 	ASSERT(!(buf->dtb_flags & DTRACEBUF_RING));
 
 	cookie = dtrace_interrupt_disable();
+	now = dtrace_gethrtime();
 	buf->dtb_tomax = xamot;
 	buf->dtb_xamot = tomax;
 	buf->dtb_xamot_drops = buf->dtb_drops;
@@ -10639,7 +10664,7 @@
 			if (epid == DTRACE_EPIDNONE) {
 				size = sizeof (uint32_t);
 			} else {
-				ASSERT(epid <= state->dts_necbs);
+				ASSERT3U(epid, <=, state->dts_necbs);
 				ASSERT(state->dts_ecbs[epid - 1] != NULL);
 
 				size = state->dts_ecbs[epid - 1]->dte_size;
@@ -15623,6 +15648,7 @@
 			desc.dtbd_drops = buf->dtb_drops;
 			desc.dtbd_errors = buf->dtb_errors;
 			desc.dtbd_oldest = buf->dtb_xamot_offset;
+			desc.dtbd_timestamp = dtrace_gethrtime();
 
 			mutex_exit(&dtrace_lock);
 
@@ -15675,6 +15701,7 @@
 		desc.dtbd_drops = buf->dtb_xamot_drops;
 		desc.dtbd_errors = buf->dtb_xamot_errors;
 		desc.dtbd_oldest = 0;
+		desc.dtbd_timestamp = buf->dtb_switched;
 
 		mutex_exit(&dtrace_lock);
 
--- a/usr/src/uts/common/sys/dtrace.h	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/uts/common/sys/dtrace.h	Wed Jul 25 19:05:31 2012 -0400
@@ -26,6 +26,7 @@
 
 /*
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef _SYS_DTRACE_H
@@ -919,10 +920,10 @@
  * DTrace Metadata Description Structures
  *
  * DTrace separates the trace data stream from the metadata stream.  The only
- * metadata tokens placed in the data stream are enabled probe identifiers
- * (EPIDs) or (in the case of aggregations) aggregation identifiers.  In order
- * to determine the structure of the data, DTrace consumers pass the token to
- * the kernel, and receive in return a corresponding description of the enabled
+ * metadata tokens placed in the data stream are the dtrace_rechdr_t (EPID +
+ * timestamp) or (in the case of aggregations) aggregation identifiers.  To
+ * determine the structure of the data, DTrace consumers pass the token to the
+ * kernel, and receive in return a corresponding description of the enabled
  * probe (via the dtrace_eprobedesc structure) or the aggregation (via the
  * dtrace_aggdesc structure).  Both of these structures are expressed in terms
  * of record descriptions (via the dtrace_recdesc structure) that describe the
@@ -1017,7 +1018,8 @@
 #define	DTRACEOPT_AGGSORTREV	24	/* reverse-sort aggregations */
 #define	DTRACEOPT_AGGSORTPOS	25	/* agg. position to sort on */
 #define	DTRACEOPT_AGGSORTKEYPOS	26	/* agg. key position to sort on */
-#define	DTRACEOPT_MAX		27	/* number of options */
+#define	DTRACEOPT_TEMPORAL	27	/* temporally ordered output */
+#define	DTRACEOPT_MAX		28	/* number of options */
 
 #define	DTRACEOPT_UNSET		(dtrace_optval_t)-2	/* unset option */
 
@@ -1037,7 +1039,9 @@
  * where user-level wishes the kernel to snapshot the buffer to (the
  * dtbd_data field).  The kernel uses the same structure to pass back some
  * information regarding the buffer:  the size of data actually copied out, the
- * number of drops, the number of errors, and the offset of the oldest record.
+ * number of drops, the number of errors, the offset of the oldest record,
+ * and the time of the snapshot.
+ *
  * If the buffer policy is a "switch" policy, taking a snapshot of the
  * principal buffer has the additional effect of switching the active and
  * inactive buffers.  Taking a snapshot of the aggregation buffer _always_ has
@@ -1050,9 +1054,30 @@
 	uint64_t dtbd_drops;			/* number of drops */
 	DTRACE_PTR(char, dtbd_data);		/* data */
 	uint64_t dtbd_oldest;			/* offset of oldest record */
+	uint64_t dtbd_timestamp;		/* hrtime of snapshot */
 } dtrace_bufdesc_t;
 
 /*
+ * Each record in the buffer (dtbd_data) begins with a header that includes
+ * the epid and a timestamp.  The timestamp is split into two 4-byte parts
+ * so that we do not require 8-byte alignment.
+ */
+typedef struct dtrace_rechdr {
+	dtrace_epid_t dtrh_epid;		/* enabled probe id */
+	uint32_t dtrh_timestamp_hi;		/* high bits of hrtime_t */
+	uint32_t dtrh_timestamp_lo;		/* low bits of hrtime_t */
+} dtrace_rechdr_t;
+
+#define	DTRACE_RECORD_LOAD_TIMESTAMP(dtrh)			\
+	((dtrh)->dtrh_timestamp_lo +				\
+	((uint64_t)(dtrh)->dtrh_timestamp_hi << 32))
+
+#define	DTRACE_RECORD_STORE_TIMESTAMP(dtrh, hrtime) {		\
+	(dtrh)->dtrh_timestamp_lo = (uint32_t)hrtime;		\
+	(dtrh)->dtrh_timestamp_hi = hrtime >> 32;		\
+}
+
+/*
  * DTrace Status
  *
  * The status of DTrace is relayed via the dtrace_status structure.  This
--- a/usr/src/uts/common/sys/dtrace_impl.h	Tue Jul 24 03:56:16 2012 +0000
+++ b/usr/src/uts/common/sys/dtrace_impl.h	Wed Jul 25 19:05:31 2012 -0400
@@ -26,6 +26,7 @@
 
 /*
  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 #ifndef _SYS_DTRACE_IMPL_H
@@ -199,15 +200,18 @@
  * predicate is non-NULL, the DIF object is executed.  If the result is
  * non-zero, the action list is processed, with each action being executed
  * accordingly.  When the action list has been completely executed, processing
- * advances to the next ECB.  processing advances to the next ECB.  If the
- * result is non-zero; For each ECB, it first determines the The ECB
- * abstraction allows disjoint consumers to multiplex on single probes.
+ * advances to the next ECB. The ECB abstraction allows disjoint consumers
+ * to multiplex on single probes.
+ *
+ * Execution of the ECB results in consuming dte_size bytes in the buffer
+ * to record data.  During execution, dte_needed bytes must be available in
+ * the buffer.  This space is used for both recorded data and tuple data.
  */
 struct dtrace_ecb {
 	dtrace_epid_t dte_epid;			/* enabled probe ID */
 	uint32_t dte_alignment;			/* required alignment */
-	size_t dte_needed;			/* bytes needed */
-	size_t dte_size;			/* total size of payload */
+	size_t dte_needed;			/* space needed for execution */
+	size_t dte_size;			/* size of recorded payload */
 	dtrace_predicate_t *dte_predicate;	/* predicate, if any */
 	dtrace_action_t *dte_action;		/* actions, if any */
 	dtrace_ecb_t *dte_next;			/* next ECB on probe */
@@ -265,27 +269,30 @@
  * the EPID, the consumer can determine the data layout.  (The data buffer
  * layout is shown schematically below.)  By assuring that one can determine
  * data layout from the EPID, the metadata stream can be separated from the
- * data stream -- simplifying the data stream enormously.
+ * data stream -- simplifying the data stream enormously.  The ECB always
+ * proceeds the recorded data as part of the dtrace_rechdr_t structure that
+ * includes the EPID and a high-resolution timestamp used for output ordering
+ * consistency.
  *
- *      base of data buffer --->  +------+--------------------+------+
- *                                | EPID | data               | EPID |
- *                                +------+--------+------+----+------+
- *                                | data          | EPID | data      |
- *                                +---------------+------+-----------+
- *                                | data, cont.                      |
- *                                +------+--------------------+------+
- *                                | EPID | data               |      |
- *                                +------+--------------------+      |
- *                                |                ||                |
- *                                |                ||                |
- *                                |                \/                |
- *                                :                                  :
- *                                .                                  .
- *                                .                                  .
- *                                .                                  .
- *                                :                                  :
- *                                |                                  |
- *     limit of data buffer --->  +----------------------------------+
+ *      base of data buffer --->  +--------+--------------------+--------+
+ *                                | rechdr | data               | rechdr |
+ *                                +--------+------+--------+----+--------+
+ *                                | data          | rechdr | data        |
+ *                                +---------------+--------+-------------+
+ *                                | data, cont.                          |
+ *                                +--------+--------------------+--------+
+ *                                | rechdr | data               |        |
+ *                                +--------+--------------------+        |
+ *                                |                ||                    |
+ *                                |                ||                    |
+ *                                |                \/                    |
+ *                                :                                      :
+ *                                .                                      .
+ *                                .                                      .
+ *                                .                                      .
+ *                                :                                      :
+ *                                |                                      |
+ *     limit of data buffer --->  +--------------------------------------+
  *
  * When evaluating an ECB, dtrace_probe() determines if the ECB's needs of the
  * principal buffer (both scratch and payload) exceed the available space.  If