Enable Release ASSERT in ANGLE.

This will mainly affect the Chromium bots.

BUG=angleproject:790

Change-Id: I0c4318e83eedba851f15b3b139551cdb6a2fde12
Reviewed-on: https://chromium-review.googlesource.com/346103
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Kenneth Russell <kbr@chromium.org>
Commit-Queue: Jamie Madill <jmadill@chromium.org>
diff --git a/BUILD.gn b/BUILD.gn
index 707a488..08799ee 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 # import the use_x11 variable
+import("//build/config/dcheck_always_on.gni")
 import("//build/config/ui.gni")
 import("//third_party/angle/build/angle_common.gni")
 
@@ -107,6 +108,12 @@
   }
 }
 
+config("angle_release_asserts_config") {
+  if (dcheck_always_on) {
+    defines = [ "ANGLE_ENABLE_RELEASE_ASSERTS" ]
+  }
+}
+
 static_library("angle_common") {
   sources = rebase_path(gles_gypi.libangle_common_sources, ".", "src")
 
@@ -120,6 +127,7 @@
   public_deps = [
     ":commit_id",
   ]
+  public_configs = [ ":angle_release_asserts_config" ]
 }
 
 static_library("translator_lib") {
diff --git a/src/angle.gyp b/src/angle.gyp
index c11b116..6591893 100644
--- a/src/angle.gyp
+++ b/src/angle.gyp
@@ -21,6 +21,7 @@
         'angle_enable_hlsl%': 0,
         'angle_link_glx%': 0,
         'angle_gl_library_type%': 'shared_library',
+        'dcheck_always_on%': 0,
         'conditions':
         [
             ['OS=="win"',
@@ -80,6 +81,19 @@
                 ],
                 'conditions':
                 [
+                    ['dcheck_always_on==1',
+                    {
+                        'configurations':
+                        {
+                            'Release_Base':
+                            {
+                                'defines':
+                                [
+                                    'ANGLE_ENABLE_RELEASE_ASSERTS',
+                                ],
+                            },
+                        },
+                    }],
                     ['OS=="win"',
                     {
                         'configurations':
@@ -97,6 +111,19 @@
             },
             'conditions':
             [
+                ['dcheck_always_on==1',
+                {
+                    'configurations':
+                    {
+                        'Release_Base':
+                        {
+                            'defines':
+                            [
+                                'ANGLE_ENABLE_RELEASE_ASSERTS',
+                            ],
+                        },
+                    },
+                }],
                 ['OS=="win"',
                 {
                     'configurations':
diff --git a/src/common/debug.cpp b/src/common/debug.cpp
index 1fcc062..746da5e 100644
--- a/src/common/debug.cpp
+++ b/src/common/debug.cpp
@@ -7,19 +7,54 @@
 // debug.cpp: Debugging utilities.
 
 #include "common/debug.h"
-#include "common/platform.h"
-#include "common/angleutils.h"
 
 #include <stdarg.h>
-#include <vector>
-#include <fstream>
+
 #include <cstdio>
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include "common/angleutils.h"
+#include "common/platform.h"
+#include "common/Optional.h"
 
 namespace gl
 {
 
 namespace
 {
+
+class FormattedString final : angle::NonCopyable
+{
+  public:
+    FormattedString(const char *format, va_list vararg) : mFormat(format)
+    {
+        va_copy(mVarArg, vararg);
+    }
+
+    const char *c_str() { return str().c_str(); }
+
+    const std::string &str()
+    {
+        if (!mMessage.valid())
+        {
+            mMessage = FormatString(mFormat, mVarArg);
+        }
+        return mMessage.value();
+    }
+
+    size_t length()
+    {
+        c_str();
+        return mMessage.value().length();
+    }
+
+  private:
+    const char *mFormat;
+    va_list mVarArg;
+    Optional<std::string> mMessage;
+};
 enum DebugTraceOutputType
 {
    DebugTraceOutputTypeNone,
@@ -52,19 +87,15 @@
         }
     }
 
-    std::string formattedMessage;
-    UNUSED_VARIABLE(formattedMessage);
+    FormattedString formattedMessage(format, vararg);
 
-#if !defined(NDEBUG) && defined(_MSC_VER)
     if (messageType == MESSAGE_ERR)
     {
-        if (formattedMessage.empty())
-        {
-            formattedMessage = FormatString(format, vararg);
-        }
+        std::cerr << formattedMessage.c_str();
+#if !defined(NDEBUG) && defined(_MSC_VER)
         OutputDebugStringA(formattedMessage.c_str());
+#endif  // !defined(NDEBUG) && defined(_MSC_VER)
     }
-#endif
 
 #if defined(ANGLE_ENABLE_DEBUG_TRACE)
 #if defined(NDEBUG)
@@ -72,12 +103,7 @@
     {
         return;
     }
-#endif // NDEBUG
-    if (formattedMessage.empty())
-    {
-        formattedMessage = FormatString(format, vararg);
-    }
-
+#endif  // NDEBUG
     static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
     if (file)
     {
@@ -87,9 +113,9 @@
 
 #if defined(ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER)
     OutputDebugStringA(formattedMessage.c_str());
-#endif // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
+#endif  // ANGLE_ENABLE_DEBUG_TRACE_TO_DEBUGGER
 
-#endif // ANGLE_ENABLE_DEBUG_TRACE
+#endif  // ANGLE_ENABLE_DEBUG_TRACE
 }
 
 } // namespace
diff --git a/src/common/debug.h b/src/common/debug.h
index 64cfef4..ccc80e8 100644
--- a/src/common/debug.h
+++ b/src/common/debug.h
@@ -64,6 +64,9 @@
 #endif
 
 #define ANGLE_EMPTY_STATEMENT for (;;) break
+#if !defined(NDEBUG) || defined(ANGLE_ENABLE_RELEASE_ASSERTS)
+#define ANGLE_ENABLE_ASSERTS
+#endif
 
 // A macro to output a trace of a function call and its arguments to the debugging log
 #if defined(ANGLE_TRACE_ENABLED)
@@ -80,7 +83,7 @@
 #endif
 
 // A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(ANGLE_TRACE_ENABLED)
+#if defined(ANGLE_TRACE_ENABLED) || defined(ANGLE_ENABLE_ASSERTS)
 #define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
 #else
 #define ERR(message, ...) (void(0))
@@ -101,13 +104,24 @@
 #undef ANGLE_TRACE_ENABLED
 #endif
 
-// A macro asserting a condition and outputting failures to the debug log
 #if !defined(NDEBUG)
-#define ASSERT(expression) { \
-    if(!(expression)) \
-        ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
-        assert(expression); \
-    } ANGLE_EMPTY_STATEMENT
+#define ANGLE_ASSERT_IMPL(expression) assert(expression)
+#else
+// TODO(jmadill): Detect if debugger is attached and break.
+#define ANGLE_ASSERT_IMPL(expression) abort()
+#endif  // !defined(NDEBUG)
+
+// A macro asserting a condition and outputting failures to the debug log
+#if defined(ANGLE_ENABLE_ASSERTS)
+#define ASSERT(expression)                                                                 \
+    {                                                                                      \
+        if (!(expression))                                                                 \
+        {                                                                                  \
+            ERR("\t! Assert failed in %s(%d): %s\n", __FUNCTION__, __LINE__, #expression); \
+            ANGLE_ASSERT_IMPL(expression);                                                 \
+        }                                                                                  \
+    }                                                                                      \
+    ANGLE_EMPTY_STATEMENT
 #define UNUSED_ASSERTION_VARIABLE(variable)
 #else
 #define ASSERT(expression) (void(0))