[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH] Add "%define assert" to variants.
From: |
Akim Demaille |
Subject: |
[PATCH] Add "%define assert" to variants. |
Date: |
Fri, 07 Nov 2008 20:38:14 -0000 |
This is used to help the user catch cases where some value gets
ovewritten by a new one. This should not happen, as this will
probably leak.
Unfortunately this uncovered a bug in the C++ parser itself: the
lookahead value was not destroyed between two calls to yylex. For
instance if the previous lookahead was a std::string, and then an int,
then the value of the std::string was correctly taken (i.e., the
lookahead was now an empty string), but std::string structure itself
was not reclaimed.
This is now done in variant::build(other&) (which is used to take the
value of the lookahead): other is not only stolen from its value, it
is also destroyed. This incurs a new performance penalty of a few
percent, and union becomes faster again.
* data/lalr1-fusion.cc (variant::build(other&)): Destroy other.
(b4_variant_if): New.
(variant::built): New.
Use it whereever the status of the variant changes.
* etc/bench.pl.in: Check the penalty of %define assert.
---
ChangeLog | 25 +++++++++++++++++++++++++
data/lalr1-fusion.cc | 31 ++++++++++++++++++++++++++-----
etc/bench.pl.in | 1 +
3 files changed, 52 insertions(+), 5 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 8054b25..b7cac25 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,30 @@
2008-11-07 Akim Demaille <address@hidden>
+ Add "%define assert" to variants.
+ This is used to help the user catch cases where some value gets
+ ovewritten by a new one. This should not happen, as this will
+ probably leak.
+
+ Unfortunately this uncovered a bug in the C++ parser itself: the
+ lookahead value was not destroyed between two calls to yylex. For
+ instance if the previous lookahead was a std::string, and then an int,
+ then the value of the std::string was correctly taken (i.e., the
+ lookahead was now an empty string), but std::string structure itself
+ was not reclaimed.
+
+ This is now done in variant::build(other&) (which is used to take the
+ value of the lookahead): other is not only stolen from its value, it
+ is also destroyed. This incurs a new performance penalty of a few
+ percent, and union becomes faster again.
+
+ * data/lalr1-fusion.cc (variant::build(other&)): Destroy other.
+ (b4_variant_if): New.
+ (variant::built): New.
+ Use it whereever the status of the variant changes.
+ * etc/bench.pl.in: Check the penalty of %define assert.
+
+2008-11-07 Akim Demaille <address@hidden>
+
Use "%define variant" in bench.pl.
* etc/bench.pl.in: No longer use the pseudo directive %variants,
just use %define variants.
diff --git a/data/lalr1-fusion.cc b/data/lalr1-fusion.cc
index 63bc1d5..1f1129a 100644
--- a/data/lalr1-fusion.cc
+++ b/data/lalr1-fusion.cc
@@ -40,6 +40,12 @@ b4_variant_if([
]) # b4_variant_if
+# b4_assert_if([IF-ASSERTIONS-ARE-USED], [IF-NOT])
+# ----------------------------------------------------
+m4_define([b4_assert_if],
+[b4_percent_define_ifdef([[assert]], [$1], [$2])])
+
+
# b4_rhs_value(RULE-LENGTH, NUM, [TYPE])
# --------------------------------------
# Expansion of $<TYPE>NUM, where the current rule has RULE-LENGTH
@@ -161,6 +167,7 @@ dnl FIXME: This is wrong, we want computed header guards.
]b4_percent_code_get([[requires]])[
+]b4_assert_if([#include <cassert>])[
#include <string>
#include <iostream>
#include "stack.hh"
@@ -177,12 +184,22 @@ dnl FIXME: This is wrong, we want computed header guards.
/// via the current state.
template <size_t S>
struct variant
- {
+ {]b4_assert_if([
+ /// Whether something is contained.
+ bool built;
+
+ /// Initially uninitialized.
+ variant ()
+ : built(false)
+ {}])[
+
/// Instantiate a \a T in here.
template <typename T>
inline T&
build()
- {
+ {]b4_assert_if([
+ assert(!built);
+ built = true;])[
return *new (buffer) T;
}
@@ -190,7 +207,8 @@ dnl FIXME: This is wrong, we want computed header guards.
template <typename T>
inline T&
as()
- {
+ {]b4_assert_if([
+ assert(built);])[
return reinterpret_cast<T&>(buffer);
}
@@ -198,7 +216,8 @@ dnl FIXME: This is wrong, we want computed header guards.
template <typename T>
inline const T&
as() const
- {
+ {]b4_assert_if([
+ assert(built);])[
return reinterpret_cast<const T&>(buffer);
}
@@ -218,6 +237,7 @@ dnl FIXME: This is wrong, we want computed header guards.
{
build<T>();
swap<T>(other);
+ other.destroy<T>();
}
/// Destroy the stored \a T.
@@ -225,7 +245,8 @@ dnl FIXME: This is wrong, we want computed header guards.
inline void
destroy()
{
- as<T>().~T();
+ as<T>().~T();]b4_assert_if([
+ built = false;])[
}
/// A buffer large enough to store any of the semantic values.
diff --git a/etc/bench.pl.in b/etc/bench.pl.in
index f4f5a7e..97facb5 100755
--- a/etc/bench.pl.in
+++ b/etc/bench.pl.in
@@ -816,6 +816,7 @@ sub bench_variant_parser ()
"f-var-deb" => ['%skeleton "lalr1-fusion.cc"', '%debug', '%define
variant'],
"f-var-dtr" => ['%skeleton "lalr1-fusion.cc"', '%define variant',
"%code {\n#define VARIANT_DESTROY\n}"],
"f-var-deb-dtr" => ['%skeleton "lalr1-fusion.cc"', '%debug', '%define
variant', "%code {\n#define VARIANT_DESTROY\n}"],
+ "f-var-deb-dtr-ass" => ['%skeleton "lalr1-fusion.cc"', '%debug',
'%define variant', "%code {\n#define VARIANT_DESTROY\n}", "%define assert"],
)
);
}
--
1.6.0.2.588.g3102
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [PATCH] Add "%define assert" to variants.,
Akim Demaille <=