Add builders for tracing event's structural arguments

The new classes allow building JSON-like structural arguments. Current implementation uses base::Value as backing store but that can be replaced in the future with something more efficient without changing client code.

All clients of cc/debug/traced_value.h should eventually switch to use the new builders.

BUG=361045

Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=286849

[email protected], [email protected], [email protected], [email protected]

Review URL: https://codereview.chromium.org/380763002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@286984 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 72cf5be..9c3ef5b 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -154,6 +154,8 @@
     "debug/stack_trace_win.cc",
     "debug/trace_event.h",
     "debug/trace_event_android.cc",
+    "debug/trace_event_argument.cc",
+    "debug/trace_event_argument.h",
     "debug/trace_event_impl.cc",
     "debug/trace_event_impl.h",
     "debug/trace_event_impl_constants.cc",
@@ -1070,6 +1072,7 @@
     "debug/leak_tracker_unittest.cc",
     "debug/proc_maps_linux_unittest.cc",
     "debug/stack_trace_unittest.cc",
+    "debug/trace_event_argument_unittest.cc",
     "debug/trace_event_memory_unittest.cc",
     "debug/trace_event_synthetic_delay_unittest.cc",
     "debug/trace_event_system_stats_monitor_unittest.cc",
diff --git a/base/base.gyp b/base/base.gyp
index 988feee..f934b23 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -448,6 +448,7 @@
         'debug/leak_tracker_unittest.cc',
         'debug/proc_maps_linux_unittest.cc',
         'debug/stack_trace_unittest.cc',
+        'debug/trace_event_argument_unittest.cc',
         'debug/trace_event_memory_unittest.cc',
         'debug/trace_event_synthetic_delay_unittest.cc',
         'debug/trace_event_system_stats_monitor_unittest.cc',
diff --git a/base/base.gypi b/base/base.gypi
index 079355e9..d5eb0ca 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -160,6 +160,8 @@
           'debug/stack_trace_win.cc',
           'debug/trace_event.h',
           'debug/trace_event_android.cc',
+          'debug/trace_event_argument.cc',
+          'debug/trace_event_argument.h',
           'debug/trace_event_impl.cc',
           'debug/trace_event_impl.h',
           'debug/trace_event_impl_constants.cc',
diff --git a/base/debug/trace_event_argument.cc b/base/debug/trace_event_argument.cc
new file mode 100644
index 0000000..90e924f1
--- /dev/null
+++ b/base/debug/trace_event_argument.cc
@@ -0,0 +1,117 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/trace_event_argument.h"
+
+#include "base/json/json_writer.h"
+#include "base/values.h"
+
+namespace base {
+namespace debug {
+
+TracedValue::TracedValue() : root_(new DictionaryValue()) {
+  stack_.push_back(root_.get());
+}
+
+TracedValue::~TracedValue() {
+  DCHECK_EQ(1u, stack_.size());
+}
+
+void TracedValue::SetInteger(const char* name, int value) {
+  GetCurrentDictionary()->SetInteger(name, value);
+}
+
+void TracedValue::SetDouble(const char* name, double value) {
+  GetCurrentDictionary()->SetDouble(name, value);
+}
+
+void TracedValue::SetBoolean(const char* name, bool value) {
+  GetCurrentDictionary()->SetBoolean(name, value);
+}
+
+void TracedValue::SetString(const char* name, const std::string& value) {
+  GetCurrentDictionary()->SetString(name, value);
+}
+
+void TracedValue::SetValue(const char* name, Value* value) {
+  GetCurrentDictionary()->Set(name, value);
+}
+
+void TracedValue::BeginDictionary(const char* name) {
+  DictionaryValue* dictionary = new DictionaryValue();
+  GetCurrentDictionary()->Set(name, dictionary);
+  stack_.push_back(dictionary);
+}
+
+void TracedValue::BeginArray(const char* name) {
+  ListValue* array = new ListValue();
+  GetCurrentDictionary()->Set(name, array);
+  stack_.push_back(array);
+}
+
+void TracedValue::EndDictionary() {
+  DCHECK_GT(stack_.size(), 1u);
+  DCHECK(GetCurrentDictionary());
+  stack_.pop_back();
+}
+
+void TracedValue::AppendInteger(int value) {
+  GetCurrentArray()->AppendInteger(value);
+}
+
+void TracedValue::AppendDouble(double value) {
+  GetCurrentArray()->AppendDouble(value);
+}
+
+void TracedValue::AppendBoolean(bool value) {
+  GetCurrentArray()->AppendBoolean(value);
+}
+
+void TracedValue::AppendString(const std::string& value) {
+  GetCurrentArray()->AppendString(value);
+}
+
+void TracedValue::BeginArray() {
+  ListValue* array = new ListValue();
+  GetCurrentArray()->Append(array);
+  stack_.push_back(array);
+}
+
+void TracedValue::BeginDictionary() {
+  DictionaryValue* dictionary = new DictionaryValue();
+  GetCurrentArray()->Append(dictionary);
+  stack_.push_back(dictionary);
+}
+
+void TracedValue::EndArray() {
+  DCHECK_GT(stack_.size(), 1u);
+  DCHECK(GetCurrentArray());
+  stack_.pop_back();
+}
+
+DictionaryValue* TracedValue::GetCurrentDictionary() {
+  DCHECK(!stack_.empty());
+  DictionaryValue* dictionary = NULL;
+  stack_.back()->GetAsDictionary(&dictionary);
+  DCHECK(dictionary);
+  return dictionary;
+}
+
+ListValue* TracedValue::GetCurrentArray() {
+  DCHECK(!stack_.empty());
+  ListValue* list = NULL;
+  stack_.back()->GetAsList(&list);
+  DCHECK(list);
+  return list;
+}
+
+void TracedValue::AppendAsTraceFormat(std::string* out) const {
+  std::string tmp;
+  JSONWriter::Write(stack_.front(), &tmp);
+  *out += tmp;
+  DCHECK_EQ(1u, stack_.size()) << tmp;
+}
+
+}  // namespace debug
+}  // namespace base
diff --git a/base/debug/trace_event_argument.h b/base/debug/trace_event_argument.h
new file mode 100644
index 0000000..9d35358
--- /dev/null
+++ b/base/debug/trace_event_argument.h
@@ -0,0 +1,59 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
+#define BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/debug/trace_event.h"
+#include "base/memory/scoped_ptr.h"
+
+namespace base {
+class DictionaryValue;
+class ListValue;
+class Value;
+
+namespace debug {
+
+class BASE_EXPORT TracedValue : public ConvertableToTraceFormat {
+ public:
+  TracedValue();
+
+  void EndDictionary();
+  void EndArray();
+
+  void SetInteger(const char* name, int value);
+  void SetDouble(const char* name, double);
+  void SetBoolean(const char* name, bool value);
+  void SetString(const char* name, const std::string& value);
+  void SetValue(const char* name, Value* value);
+  void BeginDictionary(const char* name);
+  void BeginArray(const char* name);
+
+  void AppendInteger(int);
+  void AppendDouble(double);
+  void AppendBoolean(bool);
+  void AppendString(const std::string&);
+  void BeginArray();
+  void BeginDictionary();
+
+  virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE;
+
+ private:
+  virtual ~TracedValue();
+
+  DictionaryValue* GetCurrentDictionary();
+  ListValue* GetCurrentArray();
+
+  scoped_ptr<base::Value> root_;
+  std::vector<Value*> stack_;
+  DISALLOW_COPY_AND_ASSIGN(TracedValue);
+};
+
+}  // namespace debug
+}  // namespace base
+
+#endif  // BASE_DEBUG_TRACE_EVENT_ARGUMENT_H_
diff --git a/base/debug/trace_event_argument_unittest.cc b/base/debug/trace_event_argument_unittest.cc
new file mode 100644
index 0000000..06a7697
--- /dev/null
+++ b/base/debug/trace_event_argument_unittest.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/debug/trace_event_argument.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace debug {
+
+TEST(TraceEventArgumentTest, FlatDictionary) {
+  scoped_refptr<TracedValue> value = new TracedValue();
+  value->SetInteger("int", 2014);
+  value->SetDouble("double", 0.0);
+  value->SetBoolean("bool", true);
+  value->SetString("string", "string");
+  std::string json;
+  value->AppendAsTraceFormat(&json);
+  EXPECT_EQ("{\"bool\":true,\"double\":0.0,\"int\":2014,\"string\":\"string\"}",
+            json);
+}
+
+TEST(TraceEventArgumentTest, Hierarchy) {
+  scoped_refptr<TracedValue> value = new TracedValue();
+  value->SetInteger("i0", 2014);
+  value->BeginDictionary("dict1");
+  value->SetInteger("i1", 2014);
+  value->BeginDictionary("dict2");
+  value->SetBoolean("b2", false);
+  value->EndDictionary();
+  value->SetString("s1", "foo");
+  value->EndDictionary();
+  value->SetDouble("d0", 0.0);
+  value->SetBoolean("b0", true);
+  value->BeginArray("a1");
+  value->AppendInteger(1);
+  value->AppendBoolean(true);
+  value->BeginDictionary();
+  value->SetInteger("i2", 3);
+  value->EndDictionary();
+  value->EndArray();
+  value->SetString("s0", "foo");
+  std::string json;
+  value->AppendAsTraceFormat(&json);
+  EXPECT_EQ(
+      "{\"a1\":[1,true,{\"i2\":3}],\"b0\":true,\"d0\":0.0,\"dict1\":{\"dict2\":"
+      "{\"b2\":false},\"i1\":2014,\"s1\":\"foo\"},\"i0\":2014,\"s0\":"
+      "\"foo\"}",
+      json);
+}
+
+}  // namespace debug
+}  // namespace base
diff --git a/base/debug/trace_event_impl.h b/base/debug/trace_event_impl.h
index 7b191b8..146ca8f2 100644
--- a/base/debug/trace_event_impl.h
+++ b/base/debug/trace_event_impl.h
@@ -64,7 +64,8 @@
 
 // For any argument of type TRACE_VALUE_TYPE_CONVERTABLE the provided
 // class must implement this interface.
-class ConvertableToTraceFormat : public RefCounted<ConvertableToTraceFormat> {
+class BASE_EXPORT ConvertableToTraceFormat
+    : public RefCounted<ConvertableToTraceFormat> {
  public:
   // Append the class info to the provided |out| string. The appended
   // data must be a valid JSON object. Strings must be properly quoted, and
@@ -72,6 +73,12 @@
   // appended.
   virtual void AppendAsTraceFormat(std::string* out) const = 0;
 
+  std::string ToString() const {
+    std::string result;
+    AppendAsTraceFormat(&result);
+    return result;
+  }
+
  protected:
   virtual ~ConvertableToTraceFormat() {}
 
diff --git a/cc/base/math_util.cc b/cc/base/math_util.cc
index 07ad77b..fd8e796 100644
--- a/cc/base/math_util.cc
+++ b/cc/base/math_util.cc
@@ -8,6 +8,7 @@
 #include <cmath>
 #include <limits>
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "ui/gfx/quad_f.h"
 #include "ui/gfx/rect.h"
@@ -547,13 +548,6 @@
   return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::SizeF& s) {
-  scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
-  res->SetDouble("width", s.width());
-  res->SetDouble("height", s.height());
-  return res.PassAs<base::Value>();
-}
-
 scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Rect& r) {
   scoped_ptr<base::ListValue> res(new base::ListValue());
   res->AppendInteger(r.x());
@@ -591,23 +585,47 @@
   return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Point3F& pt) {
-  scoped_ptr<base::ListValue> res(new base::ListValue());
+void MathUtil::AddToTracedValue(const gfx::Size& s,
+                                base::debug::TracedValue* res) {
+  res->SetDouble("width", s.width());
+  res->SetDouble("height", s.height());
+}
+
+void MathUtil::AddToTracedValue(const gfx::SizeF& s,
+                                base::debug::TracedValue* res) {
+  res->SetDouble("width", s.width());
+  res->SetDouble("height", s.height());
+}
+
+void MathUtil::AddToTracedValue(const gfx::Rect& r,
+                                base::debug::TracedValue* res) {
+  res->AppendInteger(r.x());
+  res->AppendInteger(r.y());
+  res->AppendInteger(r.width());
+  res->AppendInteger(r.height());
+}
+
+void MathUtil::AddToTracedValue(const gfx::PointF& pt,
+                                base::debug::TracedValue* res) {
+  res->AppendDouble(pt.x());
+  res->AppendDouble(pt.y());
+}
+
+void MathUtil::AddToTracedValue(const gfx::Point3F& pt,
+                                base::debug::TracedValue* res) {
   res->AppendDouble(pt.x());
   res->AppendDouble(pt.y());
   res->AppendDouble(pt.z());
-  return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Vector2d& v) {
-  scoped_ptr<base::ListValue> res(new base::ListValue());
+void MathUtil::AddToTracedValue(const gfx::Vector2d& v,
+                                base::debug::TracedValue* res) {
   res->AppendInteger(v.x());
   res->AppendInteger(v.y());
-  return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::QuadF& q) {
-  scoped_ptr<base::ListValue> res(new base::ListValue());
+void MathUtil::AddToTracedValue(const gfx::QuadF& q,
+                                base::debug::TracedValue* res) {
   res->AppendDouble(q.p1().x());
   res->AppendDouble(q.p1().y());
   res->AppendDouble(q.p2().x());
@@ -616,47 +634,41 @@
   res->AppendDouble(q.p3().y());
   res->AppendDouble(q.p4().x());
   res->AppendDouble(q.p4().y());
-  return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::RectF& rect) {
-  scoped_ptr<base::ListValue> res(new base::ListValue());
+void MathUtil::AddToTracedValue(const gfx::RectF& rect,
+                                base::debug::TracedValue* res) {
   res->AppendDouble(rect.x());
   res->AppendDouble(rect.y());
   res->AppendDouble(rect.width());
   res->AppendDouble(rect.height());
-  return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::Transform& transform) {
-  scoped_ptr<base::ListValue> res(new base::ListValue());
+void MathUtil::AddToTracedValue(const gfx::Transform& transform,
+                                base::debug::TracedValue* res) {
   const SkMatrix44& m = transform.matrix();
   for (int row = 0; row < 4; ++row) {
     for (int col = 0; col < 4; ++col)
       res->AppendDouble(m.getDouble(row, col));
   }
-  return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValue(const gfx::BoxF& box) {
-  scoped_ptr<base::ListValue> res(new base::ListValue());
+void MathUtil::AddToTracedValue(const gfx::BoxF& box,
+                                base::debug::TracedValue* res) {
   res->AppendInteger(box.x());
   res->AppendInteger(box.y());
   res->AppendInteger(box.z());
   res->AppendInteger(box.width());
   res->AppendInteger(box.height());
   res->AppendInteger(box.depth());
-  return res.PassAs<base::Value>();
 }
 
-scoped_ptr<base::Value> MathUtil::AsValueSafely(double value) {
-  return scoped_ptr<base::Value>(new base::FundamentalValue(
-      std::min(value, std::numeric_limits<double>::max())));
+double MathUtil::AsDoubleSafely(double value) {
+  return std::min(value, std::numeric_limits<double>::max());
 }
 
-scoped_ptr<base::Value> MathUtil::AsValueSafely(float value) {
-  return scoped_ptr<base::Value>(new base::FundamentalValue(
-      std::min(value, std::numeric_limits<float>::max())));
+float MathUtil::AsFloatSafely(float value) {
+  return std::min(value, std::numeric_limits<float>::max());
 }
 
 }  // namespace cc
diff --git a/cc/base/math_util.h b/cc/base/math_util.h
index 3af21021..4301add 100644
--- a/cc/base/math_util.h
+++ b/cc/base/math_util.h
@@ -17,7 +17,12 @@
 #include "ui/gfx/size.h"
 #include "ui/gfx/transform.h"
 
-namespace base { class Value; }
+namespace base {
+class Value;
+namespace debug {
+class TracedValue;
+}
+}
 
 namespace gfx {
 class QuadF;
@@ -174,21 +179,35 @@
 
   // Conversion to value.
   static scoped_ptr<base::Value> AsValue(const gfx::Size& s);
-  static scoped_ptr<base::Value> AsValue(const gfx::SizeF& s);
   static scoped_ptr<base::Value> AsValue(const gfx::Rect& r);
   static bool FromValue(const base::Value*, gfx::Rect* out_rect);
   static scoped_ptr<base::Value> AsValue(const gfx::PointF& q);
-  static scoped_ptr<base::Value> AsValue(const gfx::Point3F&);
-  static scoped_ptr<base::Value> AsValue(const gfx::Vector2d& v);
-  static scoped_ptr<base::Value> AsValue(const gfx::QuadF& q);
-  static scoped_ptr<base::Value> AsValue(const gfx::RectF& rect);
-  static scoped_ptr<base::Value> AsValue(const gfx::Transform& transform);
-  static scoped_ptr<base::Value> AsValue(const gfx::BoxF& box);
+
+  static void AddToTracedValue(const gfx::Size& s,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::SizeF& s,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::Rect& r,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::PointF& q,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::Point3F&,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::Vector2d& v,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::QuadF& q,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::RectF& rect,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::Transform& transform,
+                               base::debug::TracedValue* res);
+  static void AddToTracedValue(const gfx::BoxF& box,
+                               base::debug::TracedValue* res);
 
   // Returns a base::Value representation of the floating point value.
   // If the value is inf, returns max double/float representation.
-  static scoped_ptr<base::Value> AsValueSafely(double value);
-  static scoped_ptr<base::Value> AsValueSafely(float value);
+  static double AsDoubleSafely(double value);
+  static float AsFloatSafely(float value);
 };
 
 }  // namespace cc
diff --git a/cc/base/region.cc b/cc/base/region.cc
index 906bc6e..79c30ec8 100644
--- a/cc/base/region.cc
+++ b/cc/base/region.cc
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "cc/base/region.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 
 namespace cc {
@@ -120,6 +121,16 @@
   return result.PassAs<base::Value>();
 }
 
+void Region::AsValueInto(base::debug::TracedValue* result) const {
+  for (Iterator it(*this); it.has_rect(); it.next()) {
+    gfx::Rect rect(it.rect());
+    result->AppendInteger(rect.x());
+    result->AppendInteger(rect.y());
+    result->AppendInteger(rect.width());
+    result->AppendInteger(rect.height());
+  }
+}
+
 Region::Iterator::Iterator() {
 }
 
diff --git a/cc/base/region.h b/cc/base/region.h
index 06fe731..3ef32dbf 100644
--- a/cc/base/region.h
+++ b/cc/base/region.h
@@ -16,6 +16,9 @@
 
 namespace base {
 class Value;
+namespace debug {
+class TracedValue;
+}
 }
 
 namespace cc {
@@ -59,6 +62,7 @@
 
   std::string ToString() const;
   scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* array) const;
 
   class CC_EXPORT Iterator {
    public:
diff --git a/cc/debug/frame_viewer_instrumentation.h b/cc/debug/frame_viewer_instrumentation.h
index 16cf4335..7d97b52e 100644
--- a/cc/debug/frame_viewer_instrumentation.h
+++ b/cc/debug/frame_viewer_instrumentation.h
@@ -23,17 +23,18 @@
 const char kAnalyzeTask[] = "AnalyzeTask";
 const char kRasterTask[] = "RasterTask";
 
-scoped_ptr<base::Value> TileDataAsValue(const void* tile_id,
-                                        TileResolution tile_resolution,
-                                        int source_frame_number,
-                                        int layer_id) {
-  scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue);
-  res->Set(internal::kTileId, TracedValue::CreateIDRef(tile_id).release());
-  res->Set(internal::kTileResolution,
-           TileResolutionAsValue(tile_resolution).release());
+scoped_refptr<base::debug::ConvertableToTraceFormat> TileDataAsValue(
+    const void* tile_id,
+    TileResolution tile_resolution,
+    int source_frame_number,
+    int layer_id) {
+  scoped_refptr<base::debug::TracedValue> res(new base::debug::TracedValue());
+  TracedValue::SetIDRef(tile_id, res, internal::kTileId);
+  res->SetString(internal::kTileResolution,
+                 TileResolutionToString(tile_resolution));
   res->SetInteger(internal::kSourceFrameNumber, source_frame_number);
   res->SetInteger(internal::kLayerId, layer_id);
-  return res.PassAs<base::Value>();
+  return res;
 }
 
 }  // namespace internal
@@ -48,10 +49,8 @@
         internal::kCategory,
         internal::kAnalyzeTask,
         internal::kTileData,
-        TracedValue::FromValue(internal::TileDataAsValue(tile_id,
-                                                         tile_resolution,
-                                                         source_frame_number,
-                                                         layer_id).release()));
+        internal::TileDataAsValue(
+            tile_id, tile_resolution, source_frame_number, layer_id));
   }
   ~ScopedAnalyzeTask() {
     TRACE_EVENT_END0(internal::kCategory, internal::kAnalyzeTask);
@@ -72,12 +71,10 @@
         internal::kCategory,
         internal::kRasterTask,
         internal::kTileData,
-        TracedValue::FromValue(internal::TileDataAsValue(tile_id,
-                                                         tile_resolution,
-                                                         source_frame_number,
-                                                         layer_id).release()),
+        internal::TileDataAsValue(
+            tile_id, tile_resolution, source_frame_number, layer_id),
         internal::kRasterMode,
-        TracedValue::FromValue(RasterModeAsValue(raster_mode).release()));
+        RasterModeToString(raster_mode));
   }
   ~ScopedRasterTask() {
     TRACE_EVENT_END0(internal::kCategory, internal::kRasterTask);
diff --git a/cc/debug/rendering_stats.cc b/cc/debug/rendering_stats.cc
index 47bc7c7..b5989fc 100644
--- a/cc/debug/rendering_stats.cc
+++ b/cc/debug/rendering_stats.cc
@@ -16,14 +16,12 @@
   values.push_back(value);
 }
 
-scoped_ptr<base::ListValue>
-RenderingStats::TimeDeltaList::AsListValueInMilliseconds() const {
-  scoped_ptr<base::ListValue> list_value(new base::ListValue);
+void RenderingStats::TimeDeltaList::AddToTracedValue(
+    base::debug::TracedValue* list_value) const {
   std::list<base::TimeDelta>::const_iterator iter;
   for (iter = values.begin(); iter != values.end(); ++iter) {
     list_value->AppendDouble(iter->InMillisecondsF());
   }
-  return list_value.Pass();
 }
 
 void RenderingStats::TimeDeltaList::Add(const TimeDeltaList& other) {
@@ -39,13 +37,14 @@
 
 scoped_refptr<base::debug::ConvertableToTraceFormat>
 RenderingStats::MainThreadRenderingStats::AsTraceableData() const {
-  scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
+  scoped_refptr<base::debug::TracedValue> record_data =
+      new base::debug::TracedValue();
   record_data->SetInteger("frame_count", frame_count);
   record_data->SetDouble("paint_time", paint_time.InSecondsF());
   record_data->SetInteger("painted_pixel_count", painted_pixel_count);
   record_data->SetDouble("record_time", record_time.InSecondsF());
   record_data->SetInteger("recorded_pixel_count", recorded_pixel_count);
-  return TracedValue::FromValue(record_data.release());
+  return record_data;
 }
 
 void RenderingStats::MainThreadRenderingStats::Add(
@@ -69,34 +68,39 @@
 
 scoped_refptr<base::debug::ConvertableToTraceFormat>
 RenderingStats::ImplThreadRenderingStats::AsTraceableData() const {
-  scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
+  scoped_refptr<base::debug::TracedValue> record_data =
+      new base::debug::TracedValue();
   record_data->SetInteger("frame_count", frame_count);
   record_data->SetDouble("rasterize_time", rasterize_time.InSecondsF());
   record_data->SetInteger("rasterized_pixel_count", rasterized_pixel_count);
   record_data->SetInteger("visible_content_area", visible_content_area);
   record_data->SetInteger("approximated_visible_content_area",
                           approximated_visible_content_area);
-  record_data->Set("draw_duration_ms",
-                   draw_duration.AsListValueInMilliseconds().release());
-  record_data->Set(
-      "draw_duration_estimate_ms",
-      draw_duration_estimate.AsListValueInMilliseconds().release());
-  record_data->Set(
-      "begin_main_frame_to_commit_duration_ms",
-      begin_main_frame_to_commit_duration.AsListValueInMilliseconds()
-          .release());
-  record_data->Set(
-      "begin_main_frame_to_commit_duration_estimate_ms",
-      begin_main_frame_to_commit_duration_estimate.AsListValueInMilliseconds()
-          .release());
-  record_data->Set(
-      "commit_to_activate_duration_ms",
-      commit_to_activate_duration.AsListValueInMilliseconds().release());
-  record_data->Set(
-      "commit_to_activate_duration_estimate_ms",
-      commit_to_activate_duration_estimate.AsListValueInMilliseconds()
-          .release());
-  return TracedValue::FromValue(record_data.release());
+  record_data->BeginArray("draw_duration_ms");
+  draw_duration.AddToTracedValue(record_data.get());
+  record_data->EndArray();
+
+  record_data->BeginArray("draw_duration_estimate_ms");
+  draw_duration_estimate.AddToTracedValue(record_data.get());
+  record_data->EndArray();
+
+  record_data->BeginArray("begin_main_frame_to_commit_duration_ms");
+  begin_main_frame_to_commit_duration.AddToTracedValue(record_data.get());
+  record_data->EndArray();
+
+  record_data->BeginArray("begin_main_frame_to_commit_duration_estimate_ms");
+  begin_main_frame_to_commit_duration_estimate.AddToTracedValue(
+      record_data.get());
+  record_data->EndArray();
+
+  record_data->BeginArray("commit_to_activate_duration_ms");
+  commit_to_activate_duration.AddToTracedValue(record_data.get());
+  record_data->EndArray();
+
+  record_data->BeginArray("commit_to_activate_duration_estimate_ms");
+  commit_to_activate_duration_estimate.AddToTracedValue(record_data.get());
+  record_data->EndArray();
+  return record_data;
 }
 
 void RenderingStats::ImplThreadRenderingStats::Add(
diff --git a/cc/debug/rendering_stats.h b/cc/debug/rendering_stats.h
index a6edff1e..73ca9c4 100644
--- a/cc/debug/rendering_stats.h
+++ b/cc/debug/rendering_stats.h
@@ -8,6 +8,7 @@
 #include <list>
 
 #include "base/basictypes.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "cc/base/cc_export.h"
@@ -23,7 +24,8 @@
     ~TimeDeltaList();
 
     void Append(base::TimeDelta value);
-    scoped_ptr<base::ListValue> AsListValueInMilliseconds() const;
+    void AddToTracedValue(base::debug::TracedValue* list_value) const;
+
     void Add(const TimeDeltaList& other);
 
    private:
diff --git a/cc/debug/rendering_stats_unittest.cc b/cc/debug/rendering_stats_unittest.cc
index ea0276c..a634093 100644
--- a/cc/debug/rendering_stats_unittest.cc
+++ b/cc/debug/rendering_stats_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <string>
+
 #include "base/time/time.h"
 #include "base/values.h"
 #include "cc/debug/rendering_stats.h"
@@ -10,20 +12,18 @@
 namespace cc {
 namespace {
 
-void CompareDoubleValue(const base::ListValue& list_value,
-                        int index,
-                        double expected_value) {
-  double value;
-  EXPECT_TRUE(list_value.GetDouble(index, &value));
-  EXPECT_EQ(expected_value, value);
+static std::string ToString(const RenderingStats::TimeDeltaList& list) {
+  scoped_refptr<base::debug::TracedValue> value =
+      new base::debug::TracedValue();
+  value->BeginArray("list_value");
+  list.AddToTracedValue(value.get());
+  value->EndArray();
+  return value->ToString();
 }
 
 TEST(RenderingStatsTest, TimeDeltaListEmpty) {
   RenderingStats::TimeDeltaList time_delta_list;
-  scoped_ptr<base::ListValue> list_value =
-      time_delta_list.AsListValueInMilliseconds();
-  EXPECT_TRUE(list_value->empty());
-  EXPECT_EQ(0ul, list_value->GetSize());
+  EXPECT_EQ("{\"list_value\":[]}", ToString(time_delta_list));
 }
 
 TEST(RenderingStatsTest, TimeDeltaListNonEmpty) {
@@ -31,13 +31,7 @@
   time_delta_list.Append(base::TimeDelta::FromMilliseconds(234));
   time_delta_list.Append(base::TimeDelta::FromMilliseconds(827));
 
-  scoped_ptr<base::ListValue> list_value =
-      time_delta_list.AsListValueInMilliseconds();
-  EXPECT_FALSE(list_value->empty());
-  EXPECT_EQ(2ul, list_value->GetSize());
-
-  CompareDoubleValue(*list_value.get(), 0, 234);
-  CompareDoubleValue(*list_value.get(), 1, 827);
+  EXPECT_EQ("{\"list_value\":[234.0,827.0]}", ToString(time_delta_list));
 }
 
 TEST(RenderingStatsTest, TimeDeltaListAdd) {
@@ -51,16 +45,8 @@
   time_delta_list_b.Append(base::TimeDelta::FromMilliseconds(2));
 
   time_delta_list_a.Add(time_delta_list_b);
-  scoped_ptr<base::ListValue> list_value =
-      time_delta_list_a.AsListValueInMilliseconds();
-  EXPECT_FALSE(list_value->empty());
-  EXPECT_EQ(5ul, list_value->GetSize());
-
-  CompareDoubleValue(*list_value.get(), 0, 810);
-  CompareDoubleValue(*list_value.get(), 1, 32);
-  CompareDoubleValue(*list_value.get(), 2, 43);
-  CompareDoubleValue(*list_value.get(), 3, 938);
-  CompareDoubleValue(*list_value.get(), 4, 2);
+  EXPECT_EQ("{\"list_value\":[810.0,32.0,43.0,938.0,2.0]}",
+            ToString(time_delta_list_a));
 }
 
 }  // namespace
diff --git a/cc/debug/traced_picture.cc b/cc/debug/traced_picture.cc
index 89d988fe..2db549234 100644
--- a/cc/debug/traced_picture.cc
+++ b/cc/debug/traced_picture.cc
@@ -7,7 +7,6 @@
 #include "base/json/json_writer.h"
 #include "base/strings/stringprintf.h"
 #include "base/values.h"
-#include "cc/debug/traced_value.h"
 
 namespace cc {
 
diff --git a/cc/debug/traced_value.cc b/cc/debug/traced_value.cc
index 3b506ae..5828cb8 100644
--- a/cc/debug/traced_value.cc
+++ b/cc/debug/traced_value.cc
@@ -4,26 +4,34 @@
 
 #include "cc/debug/traced_value.h"
 
-#include "base/json/json_writer.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/strings/stringprintf.h"
-#include "base/values.h"
 
 namespace cc {
 
-scoped_ptr<base::Value> TracedValue::CreateIDRef(const void* id) {
-  scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
-  res->SetString("id_ref", base::StringPrintf("%p", id));
-  return res.PassAs<base::Value>();
+void TracedValue::AppendIDRef(const void* id, base::debug::TracedValue* state) {
+  state->BeginDictionary();
+  state->SetString("id_ref", base::StringPrintf("%p", id));
+  state->EndDictionary();
 }
 
-void TracedValue::MakeDictIntoImplicitSnapshot(
-    base::DictionaryValue* dict, const char* object_name, const void* id) {
+void TracedValue::SetIDRef(const void* id,
+                           base::debug::TracedValue* state,
+                           const char* name) {
+  state->BeginDictionary(name);
+  state->SetString("id_ref", base::StringPrintf("%p", id));
+  state->EndDictionary();
+}
+
+void TracedValue::MakeDictIntoImplicitSnapshot(base::debug::TracedValue* dict,
+                                               const char* object_name,
+                                               const void* id) {
   dict->SetString("id", base::StringPrintf("%s/%p", object_name, id));
 }
 
 void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
     const char* category,
-    base::DictionaryValue* dict,
+    base::debug::TracedValue* dict,
     const char* object_name,
     const void* id) {
   dict->SetString("cat", category);
@@ -32,7 +40,7 @@
 
 void TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
     const char* category,
-    base::DictionaryValue* dict,
+    base::debug::TracedValue* dict,
     const char* object_base_type_name,
     const char* object_name,
     const void* id) {
@@ -41,23 +49,4 @@
   MakeDictIntoImplicitSnapshot(dict, object_name, id);
 }
 
-scoped_refptr<base::debug::ConvertableToTraceFormat> TracedValue::FromValue(
-    base::Value* value) {
-  return scoped_refptr<base::debug::ConvertableToTraceFormat>(
-      new TracedValue(value));
-}
-
-TracedValue::TracedValue(base::Value* value)
-  : value_(value) {
-}
-
-TracedValue::~TracedValue() {
-}
-
-void TracedValue::AppendAsTraceFormat(std::string* out) const {
-  std::string tmp;
-  base::JSONWriter::Write(value_.get(), &tmp);
-  *out += tmp;
-}
-
 }  // namespace cc
diff --git a/cc/debug/traced_value.h b/cc/debug/traced_value.h
index 560eaf8..c5ea30a 100644
--- a/cc/debug/traced_value.h
+++ b/cc/debug/traced_value.h
@@ -5,58 +5,36 @@
 #ifndef CC_DEBUG_TRACED_VALUE_H_
 #define CC_DEBUG_TRACED_VALUE_H_
 
-#include <string>
-
-#include "base/debug/trace_event.h"
-#include "base/memory/scoped_ptr.h"
-
 namespace base {
-class DictionaryValue;
-class Value;
+namespace debug {
+class TracedValue;
 }
+}
+
 namespace cc {
 
-class TracedValue : public base::debug::ConvertableToTraceFormat {
+class TracedValue {
  public:
-  static scoped_ptr<base::Value> CreateIDRef(const void* id);
-  static void MakeDictIntoImplicitSnapshot(
-      base::DictionaryValue* dict, const char* object_name, const void* id);
+  static void AppendIDRef(const void* id, base::debug::TracedValue* array);
+  static void SetIDRef(const void* id,
+                       base::debug::TracedValue* dict,
+                       const char* name);
+  static void MakeDictIntoImplicitSnapshot(base::debug::TracedValue* dict,
+                                           const char* object_name,
+                                           const void* id);
   static void MakeDictIntoImplicitSnapshotWithCategory(
       const char* category,
-      base::DictionaryValue* dict,
+      base::debug::TracedValue* dict,
       const char* object_name,
       const void* id);
   static void MakeDictIntoImplicitSnapshotWithCategory(
       const char* category,
-      base::DictionaryValue* dict,
+      base::debug::TracedValue* dict,
       const char* object_base_type_name,
       const char* object_name,
       const void* id);
-  static scoped_refptr<base::debug::ConvertableToTraceFormat> FromValue(
-      base::Value* value);
-
-  virtual void AppendAsTraceFormat(std::string* out) const OVERRIDE;
-
- private:
-  explicit TracedValue(base::Value* value);
-  virtual ~TracedValue();
-
-  scoped_ptr<base::Value> value_;
-
-  DISALLOW_COPY_AND_ASSIGN(TracedValue);
 };
 
-template <class T>
-static scoped_refptr<base::debug::ConvertableToTraceFormat> ToTrace(T* t) {
-  return TracedValue::FromValue(t->AsValue().release());
-}
-
-template <class T>
-static scoped_refptr<base::debug::ConvertableToTraceFormat> ToTrace(
-    const T& t) {
-  return ToTrace(&t);
-}
-
 }  // namespace cc
 
 #endif  // CC_DEBUG_TRACED_VALUE_H_
diff --git a/cc/layers/heads_up_display_layer_impl.cc b/cc/layers/heads_up_display_layer_impl.cc
index c031bd4..0ccd4ed 100644
--- a/cc/layers/heads_up_display_layer_impl.cc
+++ b/cc/layers/heads_up_display_layer_impl.cc
@@ -7,11 +7,12 @@
 #include <algorithm>
 #include <vector>
 
+#include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/strings/stringprintf.h"
 #include "cc/debug/debug_colors.h"
 #include "cc/debug/frame_rate_counter.h"
 #include "cc/debug/paint_time_counter.h"
-#include "cc/debug/traced_value.h"
 #include "cc/output/renderer.h"
 #include "cc/quads/texture_draw_quad.h"
 #include "cc/resources/memory_history.h"
@@ -761,7 +762,8 @@
   return "cc::HeadsUpDisplayLayerImpl";
 }
 
-void HeadsUpDisplayLayerImpl::AsValueInto(base::DictionaryValue* dict) const {
+void HeadsUpDisplayLayerImpl::AsValueInto(
+    base::debug::TracedValue* dict) const {
   LayerImpl::AsValueInto(dict);
   dict->SetString("layer_name", "Heads Up Display Layer");
 }
diff --git a/cc/layers/heads_up_display_layer_impl.h b/cc/layers/heads_up_display_layer_impl.h
index b5fa355..8ee386c 100644
--- a/cc/layers/heads_up_display_layer_impl.h
+++ b/cc/layers/heads_up_display_layer_impl.h
@@ -72,7 +72,7 @@
 
   virtual const char* LayerTypeAsString() const OVERRIDE;
 
-  virtual void AsValueInto(base::DictionaryValue* dict) const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
 
   void UpdateHudContents();
   void DrawHudContents(SkCanvas* canvas);
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc
index 7a23e66..bd9a2d7 100644
--- a/cc/layers/layer_impl.cc
+++ b/cc/layers/layer_impl.cc
@@ -5,6 +5,7 @@
 #include "cc/layers/layer_impl.h"
 
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/json/json_reader.h"
 #include "base/strings/stringprintf.h"
 #include "cc/animation/animation_registrar.h"
@@ -1390,7 +1391,7 @@
       parent_->RemoveDependentNeedsPushProperties();
 }
 
-void LayerImpl::AsValueInto(base::DictionaryValue* state) const {
+void LayerImpl::AsValueInto(base::debug::TracedValue* state) const {
   TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
       TRACE_DISABLED_BY_DEFAULT("cc.debug"),
       state,
@@ -1398,50 +1399,75 @@
       LayerTypeAsString(),
       this);
   state->SetInteger("layer_id", id());
-  state->Set("bounds", MathUtil::AsValue(bounds_).release());
-  state->Set("position", MathUtil::AsValue(position_).release());
+  state->BeginDictionary("bounds");
+  MathUtil::AddToTracedValue(bounds_, state);
+  state->EndDictionary();
+
+  state->BeginArray("position");
+  MathUtil::AddToTracedValue(position_, state);
+  state->EndArray();
+
   state->SetInteger("draws_content", DrawsContent());
   state->SetInteger("gpu_memory_usage", GPUMemoryUsageInBytes());
-  state->Set("scroll_offset", MathUtil::AsValue(scroll_offset_).release());
-  state->Set("transform_origin",
-             MathUtil::AsValue(transform_origin_).release());
+
+  state->BeginArray("scroll_offset");
+  MathUtil::AddToTracedValue(scroll_offset_, state);
+  state->EndArray();
+
+  state->BeginArray("transform_origin");
+  MathUtil::AddToTracedValue(transform_origin_, state);
+  state->EndArray();
 
   bool clipped;
   gfx::QuadF layer_quad = MathUtil::MapQuad(
       screen_space_transform(),
       gfx::QuadF(gfx::Rect(content_bounds())),
       &clipped);
-  state->Set("layer_quad", MathUtil::AsValue(layer_quad).release());
-
+  state->BeginArray("layer_quad");
+  MathUtil::AddToTracedValue(layer_quad, state);
+  state->EndArray();
   if (!touch_event_handler_region_.IsEmpty()) {
-    state->Set("touch_event_handler_region",
-               touch_event_handler_region_.AsValue().release());
+    state->BeginArray("touch_event_handler_region");
+    touch_event_handler_region_.AsValueInto(state);
+    state->EndArray();
   }
   if (have_wheel_event_handlers_) {
     gfx::Rect wheel_rect(content_bounds());
     Region wheel_region(wheel_rect);
-    state->Set("wheel_event_handler_region",
-               wheel_region.AsValue().release());
+    state->BeginArray("wheel_event_handler_region");
+    wheel_region.AsValueInto(state);
+    state->EndArray();
   }
   if (have_scroll_event_handlers_) {
     gfx::Rect scroll_rect(content_bounds());
     Region scroll_region(scroll_rect);
-    state->Set("scroll_event_handler_region",
-               scroll_region.AsValue().release());
+    state->BeginArray("scroll_event_handler_region");
+    scroll_region.AsValueInto(state);
+    state->EndArray();
   }
   if (!non_fast_scrollable_region_.IsEmpty()) {
-    state->Set("non_fast_scrollable_region",
-               non_fast_scrollable_region_.AsValue().release());
+    state->BeginArray("non_fast_scrollable_region");
+    non_fast_scrollable_region_.AsValueInto(state);
+    state->EndArray();
   }
 
-  scoped_ptr<base::ListValue> children_list(new base::ListValue());
-  for (size_t i = 0; i < children_.size(); ++i)
-    children_list->Append(children_[i]->AsValue().release());
-  state->Set("children", children_list.release());
-  if (mask_layer_)
-    state->Set("mask_layer", mask_layer_->AsValue().release());
-  if (replica_layer_)
-    state->Set("replica_layer", replica_layer_->AsValue().release());
+  state->BeginArray("children");
+  for (size_t i = 0; i < children_.size(); ++i) {
+    state->BeginDictionary();
+    children_[i]->AsValueInto(state);
+    state->EndDictionary();
+  }
+  state->EndArray();
+  if (mask_layer_) {
+    state->BeginDictionary("mask_layer");
+    mask_layer_->AsValueInto(state);
+    state->EndDictionary();
+  }
+  if (replica_layer_) {
+    state->BeginDictionary("replica_layer");
+    replica_layer_->AsValueInto(state);
+    state->EndDictionary();
+  }
 
   if (scroll_parent_)
     state->SetInteger("scroll_parent", scroll_parent_->id());
@@ -1457,8 +1483,11 @@
       layer_animation_controller()->HasAnimationThatInflatesBounds());
 
   gfx::BoxF box;
-  if (LayerUtils::GetAnimationBounds(*this, &box))
-    state->Set("animation_bounds", MathUtil::AsValue(box).release());
+  if (LayerUtils::GetAnimationBounds(*this, &box)) {
+    state->BeginArray("animation_bounds");
+    MathUtil::AddToTracedValue(box, state);
+    state->EndArray();
+  }
 
   if (debug_info_.get()) {
     std::string str;
@@ -1471,7 +1500,10 @@
       bool converted_to_dictionary =
           debug_info_value->GetAsDictionary(&dictionary_value);
       DCHECK(converted_to_dictionary);
-      state->MergeDictionary(dictionary_value);
+      for (base::DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd();
+           it.Advance()) {
+        state->SetValue(it.key().data(), it.value().DeepCopy());
+      }
     } else {
       NOTREACHED();
     }
@@ -1485,12 +1517,6 @@
 
 size_t LayerImpl::GPUMemoryUsageInBytes() const { return 0; }
 
-scoped_ptr<base::Value> LayerImpl::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  AsValueInto(state.get());
-  return state.PassAs<base::Value>();
-}
-
 void LayerImpl::RunMicroBenchmark(MicroBenchmarkImpl* benchmark) {
   benchmark->RunOnLayer(this);
 }
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h
index 979d2e0..c1ce9df 100644
--- a/cc/layers/layer_impl.h
+++ b/cc/layers/layer_impl.h
@@ -39,6 +39,7 @@
 namespace base {
 namespace debug {
 class ConvertableToTraceFormat;
+class TracedValue;
 }
 
 class DictionaryValue;
@@ -521,7 +522,8 @@
   virtual scoped_ptr<LayerImpl> CreateLayerImpl(LayerTreeImpl* tree_impl);
   virtual void PushPropertiesTo(LayerImpl* layer);
 
-  scoped_ptr<base::Value> AsValue() const;
+  virtual void AsValueInto(base::debug::TracedValue* dict) const;
+
   virtual size_t GPUMemoryUsageInBytes() const;
 
   void SetNeedsPushProperties();
@@ -563,8 +565,6 @@
                              SkColor color,
                              float width) const;
 
-  virtual void AsValueInto(base::DictionaryValue* dict) const;
-
   void NoteLayerPropertyChanged();
   void NoteLayerPropertyChangedForSubtree();
 
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 2544c0d7..dcbcc7474 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <limits>
 
+#include "base/debug/trace_event_argument.h"
 #include "base/time/time.h"
 #include "cc/base/math_util.h"
 #include "cc/base/util.h"
@@ -1335,31 +1336,42 @@
   *width = DebugColors::TiledContentLayerBorderWidth(layer_tree_impl());
 }
 
-void PictureLayerImpl::AsValueInto(base::DictionaryValue* state) const {
+void PictureLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
   const_cast<PictureLayerImpl*>(this)->DoPostCommitInitializationIfNeeded();
   LayerImpl::AsValueInto(state);
   state->SetDouble("ideal_contents_scale", ideal_contents_scale_);
   state->SetDouble("geometry_contents_scale", MaximumTilingContentsScale());
-  state->Set("tilings", tilings_->AsValue().release());
-  state->Set("pictures", pile_->AsValue().release());
-  state->Set("invalidation", invalidation_.AsValue().release());
+  state->BeginArray("tilings");
+  tilings_->AsValueInto(state);
+  state->EndArray();
 
-  scoped_ptr<base::ListValue> coverage_tiles(new base::ListValue);
+  state->BeginArray("pictures");
+  pile_->AsValueInto(state);
+  state->EndArray();
+
+  state->BeginArray("invalidation");
+  invalidation_.AsValueInto(state);
+  state->EndArray();
+
+  state->BeginArray("coverage_tiles");
   for (PictureLayerTilingSet::CoverageIterator iter(tilings_.get(),
                                                     contents_scale_x(),
                                                     gfx::Rect(content_bounds()),
                                                     ideal_contents_scale_);
        iter;
        ++iter) {
-    scoped_ptr<base::DictionaryValue> tile_data(new base::DictionaryValue);
-    tile_data->Set("geometry_rect",
-                   MathUtil::AsValue(iter.geometry_rect()).release());
-    if (*iter)
-      tile_data->Set("tile", TracedValue::CreateIDRef(*iter).release());
+    state->BeginDictionary();
 
-    coverage_tiles->Append(tile_data.release());
+    state->BeginArray("geometry_rect");
+    MathUtil::AddToTracedValue(iter.geometry_rect(), state);
+    state->EndArray();
+
+    if (*iter)
+      TracedValue::SetIDRef(*iter, state, "tile");
+
+    state->EndDictionary();
   }
-  state->Set("coverage_tiles", coverage_tiles.release());
+  state->EndArray();
 }
 
 size_t PictureLayerImpl::GPUMemoryUsageInBytes() const {
diff --git a/cc/layers/picture_layer_impl.h b/cc/layers/picture_layer_impl.h
index fcf92fe..ff36c15 100644
--- a/cc/layers/picture_layer_impl.h
+++ b/cc/layers/picture_layer_impl.h
@@ -180,7 +180,7 @@
 
   virtual void GetDebugBorderProperties(
       SkColor* color, float* width) const OVERRIDE;
-  virtual void AsValueInto(base::DictionaryValue* dict) const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
 
   virtual void UpdateIdealScales();
   float MaximumTilingContentsScale() const;
diff --git a/cc/layers/surface_layer_impl.cc b/cc/layers/surface_layer_impl.cc
index 80c6da0..fb0d2a981 100644
--- a/cc/layers/surface_layer_impl.cc
+++ b/cc/layers/surface_layer_impl.cc
@@ -4,6 +4,7 @@
 
 #include "cc/layers/surface_layer_impl.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "cc/debug/debug_colors.h"
 #include "cc/quads/surface_draw_quad.h"
 #include "cc/trees/occlusion_tracker.h"
@@ -66,7 +67,7 @@
   *width = DebugColors::SurfaceLayerBorderWidth(layer_tree_impl());
 }
 
-void SurfaceLayerImpl::AsValueInto(base::DictionaryValue* dict) const {
+void SurfaceLayerImpl::AsValueInto(base::debug::TracedValue* dict) const {
   LayerImpl::AsValueInto(dict);
   dict->SetInteger("surface_id", surface_id_.id);
 }
diff --git a/cc/layers/surface_layer_impl.h b/cc/layers/surface_layer_impl.h
index 65120aa..712ea14 100644
--- a/cc/layers/surface_layer_impl.h
+++ b/cc/layers/surface_layer_impl.h
@@ -35,7 +35,7 @@
  private:
   virtual void GetDebugBorderProperties(SkColor* color,
                                         float* width) const OVERRIDE;
-  virtual void AsValueInto(base::DictionaryValue* dict) const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
   virtual const char* LayerTypeAsString() const OVERRIDE;
 
   SurfaceId surface_id_;
diff --git a/cc/layers/tiled_layer_impl.cc b/cc/layers/tiled_layer_impl.cc
index 5b932ca9..86f90b9 100644
--- a/cc/layers/tiled_layer_impl.cc
+++ b/cc/layers/tiled_layer_impl.cc
@@ -5,6 +5,7 @@
 #include "cc/layers/tiled_layer_impl.h"
 
 #include "base/basictypes.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/strings/stringprintf.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/debug_colors.h"
@@ -99,9 +100,11 @@
   return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>();
 }
 
-void TiledLayerImpl::AsValueInto(base::DictionaryValue* state) const {
+void TiledLayerImpl::AsValueInto(base::debug::TracedValue* state) const {
   LayerImpl::AsValueInto(state);
-  state->Set("invalidation", MathUtil::AsValue(update_rect()).release());
+  state->BeginArray("invalidation");
+  MathUtil::AddToTracedValue(update_rect(), state);
+  state->EndArray();
 }
 
 size_t TiledLayerImpl::GPUMemoryUsageInBytes() const {
diff --git a/cc/layers/tiled_layer_impl.h b/cc/layers/tiled_layer_impl.h
index 7fc43470..e3d38a0 100644
--- a/cc/layers/tiled_layer_impl.h
+++ b/cc/layers/tiled_layer_impl.h
@@ -58,7 +58,7 @@
 
   virtual void GetDebugBorderProperties(SkColor* color, float* width) const
       OVERRIDE;
-  virtual void AsValueInto(base::DictionaryValue* state) const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* dict) const OVERRIDE;
 
  private:
   virtual const char* LayerTypeAsString() const OVERRIDE;
diff --git a/cc/output/begin_frame_args.cc b/cc/output/begin_frame_args.cc
index 4d1b270..b45eee8 100644
--- a/cc/output/begin_frame_args.cc
+++ b/cc/output/begin_frame_args.cc
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "cc/output/begin_frame_args.h"
+
+#include "base/debug/trace_event_argument.h"
 #include "ui/gfx/frame_time.h"
 
 namespace cc {
@@ -27,13 +29,19 @@
   return BeginFrameArgs(frame_time, deadline, interval);
 }
 
-scoped_ptr<base::Value> BeginFrameArgs::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
+scoped_refptr<base::debug::ConvertableToTraceFormat> BeginFrameArgs::AsValue()
+    const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
+  AsValueInto(state.get());
+  return state;
+}
+
+void BeginFrameArgs::AsValueInto(base::debug::TracedValue* state) const {
   state->SetString("type", "BeginFrameArgs");
   state->SetDouble("frame_time_us", frame_time.ToInternalValue());
   state->SetDouble("deadline_us", deadline.ToInternalValue());
   state->SetDouble("interval_us", interval.InMicroseconds());
-  return state.PassAs<base::Value>();
 }
 
 BeginFrameArgs BeginFrameArgs::CreateForSynchronousCompositor(
diff --git a/cc/output/begin_frame_args.h b/cc/output/begin_frame_args.h
index 91ad182..b23a81e 100644
--- a/cc/output/begin_frame_args.h
+++ b/cc/output/begin_frame_args.h
@@ -5,10 +5,18 @@
 #ifndef CC_OUTPUT_BEGIN_FRAME_ARGS_H_
 #define CC_OUTPUT_BEGIN_FRAME_ARGS_H_
 
+#include "base/memory/ref_counted.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "cc/base/cc_export.h"
 
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
 namespace cc {
 
 struct CC_EXPORT BeginFrameArgs {
@@ -39,7 +47,8 @@
 
   bool IsValid() const { return interval >= base::TimeDelta(); }
 
-  scoped_ptr<base::Value> AsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   base::TimeTicks frame_time;
   base::TimeTicks deadline;
diff --git a/cc/output/filter_operation.cc b/cc/output/filter_operation.cc
index 096f6ba..173985b 100644
--- a/cc/output/filter_operation.cc
+++ b/cc/output/filter_operation.cc
@@ -4,6 +4,7 @@
 
 #include <algorithm>
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/output/filter_operation.h"
@@ -254,8 +255,7 @@
   return blended_filter;
 }
 
-scoped_ptr<base::Value> FilterOperation::AsValue() const {
-  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue);
+void FilterOperation::AsValueInto(base::debug::TracedValue* value) const {
   value->SetInteger("type", type_);
   switch (type_) {
     case FilterOperation::GRAYSCALE:
@@ -272,14 +272,16 @@
       break;
     case FilterOperation::DROP_SHADOW:
       value->SetDouble("std_deviation", amount_);
-      value->Set("offset", MathUtil::AsValue(drop_shadow_offset_).release());
+      value->BeginArray("offset");
+      MathUtil::AddToTracedValue(drop_shadow_offset_, value);
+      value->EndArray();
       value->SetInteger("color", drop_shadow_color_);
       break;
     case FilterOperation::COLOR_MATRIX: {
-      scoped_ptr<base::ListValue> matrix(new base::ListValue);
+      value->BeginArray("matrix");
       for (size_t i = 0; i < arraysize(matrix_); ++i)
-        matrix->AppendDouble(matrix_[i]);
-      value->Set("matrix", matrix.release());
+        value->AppendDouble(matrix_[i]);
+      value->EndArray();
       break;
     }
     case FilterOperation::ZOOM:
@@ -302,17 +304,17 @@
         value->SetDouble("inner_threshold", amount_);
         value->SetDouble("outer_threshold", outer_threshold_);
         scoped_ptr<base::ListValue> region_value(new base::ListValue());
+        value->BeginArray("region");
         for (SkRegion::Iterator it(region_); !it.done(); it.next()) {
-          region_value->AppendInteger(it.rect().x());
-          region_value->AppendInteger(it.rect().y());
-          region_value->AppendInteger(it.rect().width());
-          region_value->AppendInteger(it.rect().height());
+          value->AppendInteger(it.rect().x());
+          value->AppendInteger(it.rect().y());
+          value->AppendInteger(it.rect().width());
+          value->AppendInteger(it.rect().height());
         }
-        value->Set("region", region_value.release());
+        value->EndArray();
       }
       break;
   }
-  return value.PassAs<base::Value>();
 }
 
 }  // namespace cc
diff --git a/cc/output/filter_operation.h b/cc/output/filter_operation.h
index cfaf5290..fc14cb1 100644
--- a/cc/output/filter_operation.h
+++ b/cc/output/filter_operation.h
@@ -16,6 +16,9 @@
 #include "ui/gfx/geometry/point.h"
 
 namespace base {
+namespace debug {
+class TracedValue;
+}
 class Value;
 }
 
@@ -220,7 +223,7 @@
                                const FilterOperation* to,
                                double progress);
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* value) const;
 
  private:
   FilterOperation(FilterType type, float amount);
diff --git a/cc/output/filter_operations.cc b/cc/output/filter_operations.cc
index 443d7eca..dcdd480 100644
--- a/cc/output/filter_operations.cc
+++ b/cc/output/filter_operations.cc
@@ -2,10 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include <cmath>
-
 #include "cc/output/filter_operations.h"
 
+#include <cmath>
+
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/output/filter_operation.h"
 
@@ -196,11 +197,12 @@
   return blended_filters;
 }
 
-scoped_ptr<base::Value> FilterOperations::AsValue() const {
-  scoped_ptr<base::ListValue> value(new base::ListValue);
-  for (size_t i = 0; i < operations_.size(); ++i)
-    value->Append(operations_[i].AsValue().release());
-  return value.PassAs<base::Value>();
+void FilterOperations::AsValueInto(base::debug::TracedValue* value) const {
+  for (size_t i = 0; i < operations_.size(); ++i) {
+    value->BeginDictionary();
+    operations_[i].AsValueInto(value);
+    value->EndDictionary();
+  }
 }
 
 }  // namespace cc
diff --git a/cc/output/filter_operations.h b/cc/output/filter_operations.h
index 66f5865..a8c206ea 100644
--- a/cc/output/filter_operations.h
+++ b/cc/output/filter_operations.h
@@ -12,6 +12,9 @@
 #include "cc/output/filter_operation.h"
 
 namespace base {
+namespace debug {
+class TracedValue;
+}
 class Value;
 }
 
@@ -67,8 +70,7 @@
   // a copy of this.
   FilterOperations Blend(const FilterOperations& from, double progress) const;
 
-
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* value) const;
 
  private:
   std::vector<FilterOperation> operations_;
diff --git a/cc/quads/checkerboard_draw_quad.cc b/cc/quads/checkerboard_draw_quad.cc
index b6c5f82..14517666 100644
--- a/cc/quads/checkerboard_draw_quad.cc
+++ b/cc/quads/checkerboard_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/checkerboard_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 
@@ -42,7 +43,7 @@
   return static_cast<const CheckerboardDrawQuad*>(quad);
 }
 
-void CheckerboardDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void CheckerboardDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   value->SetInteger("color", color);
 }
 
diff --git a/cc/quads/checkerboard_draw_quad.h b/cc/quads/checkerboard_draw_quad.h
index ffbf698..f99531d 100644
--- a/cc/quads/checkerboard_draw_quad.h
+++ b/cc/quads/checkerboard_draw_quad.h
@@ -36,7 +36,7 @@
   static const CheckerboardDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/content_draw_quad_base.cc b/cc/quads/content_draw_quad_base.cc
index 18d3d10..fd6e91b2 100644
--- a/cc/quads/content_draw_quad_base.cc
+++ b/cc/quads/content_draw_quad_base.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/content_draw_quad_base.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -49,9 +50,15 @@
   this->swizzle_contents = swizzle_contents;
 }
 
-void ContentDrawQuadBase::ExtendValue(base::DictionaryValue* value) const {
-  value->Set("tex_coord_rect", MathUtil::AsValue(tex_coord_rect).release());
-  value->Set("texture_size", MathUtil::AsValue(texture_size).release());
+void ContentDrawQuadBase::ExtendValue(base::debug::TracedValue* value) const {
+  value->BeginArray("tex_coord_rect");
+  MathUtil::AddToTracedValue(tex_coord_rect, value);
+  value->EndArray();
+
+  value->BeginDictionary("texture_size");
+  MathUtil::AddToTracedValue(texture_size, value);
+  value->EndDictionary();
+
   value->SetBoolean("swizzle_contents", swizzle_contents);
 }
 
diff --git a/cc/quads/content_draw_quad_base.h b/cc/quads/content_draw_quad_base.h
index a286e100..5173d6c 100644
--- a/cc/quads/content_draw_quad_base.h
+++ b/cc/quads/content_draw_quad_base.h
@@ -42,7 +42,7 @@
  protected:
   ContentDrawQuadBase();
   virtual ~ContentDrawQuadBase();
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/debug_border_draw_quad.cc b/cc/quads/debug_border_draw_quad.cc
index 4254e02..c907be79 100644
--- a/cc/quads/debug_border_draw_quad.cc
+++ b/cc/quads/debug_border_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/debug_border_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 
@@ -49,7 +50,7 @@
   return static_cast<const DebugBorderDrawQuad*>(quad);
 }
 
-void DebugBorderDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void DebugBorderDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   value->SetInteger("color", color);
   value->SetInteger("width", width);
 }
diff --git a/cc/quads/debug_border_draw_quad.h b/cc/quads/debug_border_draw_quad.h
index 18dd869..828d4e0 100644
--- a/cc/quads/debug_border_draw_quad.h
+++ b/cc/quads/debug_border_draw_quad.h
@@ -39,7 +39,7 @@
   static const DebugBorderDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/draw_quad.cc b/cc/quads/draw_quad.cc
index b669ad7..38b24b0 100644
--- a/cc/quads/draw_quad.cc
+++ b/cc/quads/draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -56,48 +57,59 @@
 DrawQuad::~DrawQuad() {
 }
 
-scoped_ptr<base::Value> DrawQuad::AsValue() const {
-  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+void DrawQuad::AsValueInto(base::debug::TracedValue* value) const {
   value->SetInteger("material", material);
-  value->Set("shared_state",
-             TracedValue::CreateIDRef(shared_quad_state).release());
+  TracedValue::SetIDRef(shared_quad_state, value, "shared_state");
 
-  value->Set("content_space_rect", MathUtil::AsValue(rect).release());
+  value->BeginArray("content_space_rect");
+  MathUtil::AddToTracedValue(rect, value);
+  value->EndArray();
+
   bool rect_is_clipped;
   gfx::QuadF rect_as_target_space_quad = MathUtil::MapQuad(
       shared_quad_state->content_to_target_transform,
       gfx::QuadF(rect),
       &rect_is_clipped);
-  value->Set("rect_as_target_space_quad",
-             MathUtil::AsValue(rect_as_target_space_quad).release());
+  value->BeginArray("rect_as_target_space_quad");
+  MathUtil::AddToTracedValue(rect_as_target_space_quad, value);
+  value->EndArray();
+
   value->SetBoolean("rect_is_clipped", rect_is_clipped);
 
-  value->Set("content_space_opaque_rect",
-             MathUtil::AsValue(opaque_rect).release());
+  value->BeginArray("content_space_opaque_rect");
+  MathUtil::AddToTracedValue(opaque_rect, value);
+  value->EndArray();
+
   bool opaque_rect_is_clipped;
   gfx::QuadF opaque_rect_as_target_space_quad = MathUtil::MapQuad(
       shared_quad_state->content_to_target_transform,
       gfx::QuadF(opaque_rect),
       &opaque_rect_is_clipped);
-  value->Set("opaque_rect_as_target_space_quad",
-             MathUtil::AsValue(opaque_rect_as_target_space_quad).release());
+  value->BeginArray("opaque_rect_as_target_space_quad");
+  MathUtil::AddToTracedValue(opaque_rect_as_target_space_quad, value);
+  value->EndArray();
+
   value->SetBoolean("opaque_rect_is_clipped", opaque_rect_is_clipped);
 
-  value->Set("content_space_visible_rect",
-             MathUtil::AsValue(visible_rect).release());
+  value->BeginArray("content_space_visible_rect");
+  MathUtil::AddToTracedValue(visible_rect, value);
+  value->EndArray();
+
   bool visible_rect_is_clipped;
   gfx::QuadF visible_rect_as_target_space_quad = MathUtil::MapQuad(
       shared_quad_state->content_to_target_transform,
       gfx::QuadF(visible_rect),
       &visible_rect_is_clipped);
-  value->Set("visible_rect_as_target_space_quad",
-             MathUtil::AsValue(visible_rect_as_target_space_quad).release());
+
+  value->BeginArray("visible_rect_as_target_space_quad");
+  MathUtil::AddToTracedValue(visible_rect_as_target_space_quad, value);
+  value->EndArray();
+
   value->SetBoolean("visible_rect_is_clipped", visible_rect_is_clipped);
 
   value->SetBoolean("needs_blending", needs_blending);
   value->SetBoolean("should_draw_with_blending", ShouldDrawWithBlending());
-  ExtendValue(value.get());
-  return value.PassAs<base::Value>();
+  ExtendValue(value);
 }
 
 }  // namespace cc
diff --git a/cc/quads/draw_quad.h b/cc/quads/draw_quad.h
index 07193cd..61ca358 100644
--- a/cc/quads/draw_quad.h
+++ b/cc/quads/draw_quad.h
@@ -11,6 +11,9 @@
 #include "cc/resources/resource_provider.h"
 
 namespace base {
+namespace debug {
+class TracedValue;
+}
 class Value;
 class DictionaryValue;
 }
@@ -123,7 +126,7 @@
     return IsLeftEdge() || IsTopEdge() || IsRightEdge() || IsBottomEdge();
   }
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* value) const;
 
  protected:
   DrawQuad();
@@ -134,7 +137,7 @@
               const gfx::Rect& opaque_rect,
               const gfx::Rect& visible_rect,
               bool needs_blending);
-  virtual void ExtendValue(base::DictionaryValue* value) const = 0;
+  virtual void ExtendValue(base::debug::TracedValue* value) const = 0;
 };
 
 }  // namespace cc
diff --git a/cc/quads/io_surface_draw_quad.cc b/cc/quads/io_surface_draw_quad.cc
index cc3581bd..e565a43 100644
--- a/cc/quads/io_surface_draw_quad.cc
+++ b/cc/quads/io_surface_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/io_surface_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -56,8 +57,11 @@
   return static_cast<const IOSurfaceDrawQuad*>(quad);
 }
 
-void IOSurfaceDrawQuad::ExtendValue(base::DictionaryValue* value) const {
-  value->Set("io_surface_size", MathUtil::AsValue(io_surface_size).release());
+void IOSurfaceDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+  value->BeginDictionary("io_surface_size");
+  MathUtil::AddToTracedValue(io_surface_size, value);
+  value->EndDictionary();
+
   value->SetInteger("io_surface_resource_id", io_surface_resource_id);
   const char* orientation_string = NULL;
   switch (orientation) {
diff --git a/cc/quads/io_surface_draw_quad.h b/cc/quads/io_surface_draw_quad.h
index 988afeb..86b4d52 100644
--- a/cc/quads/io_surface_draw_quad.h
+++ b/cc/quads/io_surface_draw_quad.h
@@ -49,7 +49,7 @@
   static const IOSurfaceDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/picture_draw_quad.cc b/cc/quads/picture_draw_quad.cc
index cb1c2c1..af120a4 100644
--- a/cc/quads/picture_draw_quad.cc
+++ b/cc/quads/picture_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/picture_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/resources/platform_color.h"
@@ -79,9 +80,11 @@
   return static_cast<const PictureDrawQuad*>(quad);
 }
 
-void PictureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void PictureDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   ContentDrawQuadBase::ExtendValue(value);
-  value->Set("content_rect", MathUtil::AsValue(content_rect).release());
+  value->BeginArray("content_rect");
+  MathUtil::AddToTracedValue(content_rect, value);
+  value->EndArray();
   value->SetDouble("contents_scale", contents_scale);
   value->SetInteger("texture_format", texture_format);
   // TODO(piman): picture_pile?
diff --git a/cc/quads/picture_draw_quad.h b/cc/quads/picture_draw_quad.h
index 944a8fb..4fb6b4be 100644
--- a/cc/quads/picture_draw_quad.h
+++ b/cc/quads/picture_draw_quad.h
@@ -56,7 +56,7 @@
   static const PictureDrawQuad* MaterialCast(const DrawQuad* quad);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/render_pass.cc b/cc/quads/render_pass.cc
index c7f83a36..43bb7cd 100644
--- a/cc/quads/render_pass.cc
+++ b/cc/quads/render_pass.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/render_pass.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/traced_value.h"
@@ -157,27 +158,39 @@
   DCHECK(shared_quad_state_list.empty());
 }
 
-scoped_ptr<base::Value> RenderPass::AsValue() const {
-  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
-  value->Set("output_rect", MathUtil::AsValue(output_rect).release());
-  value->Set("damage_rect", MathUtil::AsValue(damage_rect).release());
+void RenderPass::AsValueInto(base::debug::TracedValue* value) const {
+  value->BeginArray("output_rect");
+  MathUtil::AddToTracedValue(output_rect, value);
+  value->EndArray();
+
+  value->BeginArray("damage_rect");
+  MathUtil::AddToTracedValue(damage_rect, value);
+  value->EndArray();
+
   value->SetBoolean("has_transparent_background", has_transparent_background);
   value->SetInteger("copy_requests", copy_requests.size());
-  scoped_ptr<base::ListValue> shared_states_value(new base::ListValue());
+
+  value->BeginArray("shared_quad_state_list");
   for (size_t i = 0; i < shared_quad_state_list.size(); ++i) {
-    shared_states_value->Append(shared_quad_state_list[i]->AsValue().release());
+    value->BeginDictionary();
+    shared_quad_state_list[i]->AsValueInto(value);
+    value->EndDictionary();
   }
-  value->Set("shared_quad_state_list", shared_states_value.release());
-  scoped_ptr<base::ListValue> quad_list_value(new base::ListValue());
+  value->EndArray();
+
+  value->BeginArray("quad_list");
   for (size_t i = 0; i < quad_list.size(); ++i) {
-    quad_list_value->Append(quad_list[i]->AsValue().release());
+    value->BeginDictionary();
+    quad_list[i]->AsValueInto(value);
+    value->EndDictionary();
   }
-  value->Set("quad_list", quad_list_value.release());
+  value->EndArray();
 
   TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
       TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
-      value.get(), "cc::RenderPass", id.AsTracingId());
-  return value.PassAs<base::Value>();
+      value,
+      "cc::RenderPass",
+      id.AsTracingId());
 }
 
 SharedQuadState* RenderPass::CreateAndAppendSharedQuadState() {
diff --git a/cc/quads/render_pass.h b/cc/quads/render_pass.h
index 3032f05..8d41142 100644
--- a/cc/quads/render_pass.h
+++ b/cc/quads/render_pass.h
@@ -18,6 +18,9 @@
 #include "ui/gfx/transform.h"
 
 namespace base {
+namespace debug {
+class TracedValue;
+}
 class Value;
 };
 
@@ -87,7 +90,7 @@
               const gfx::Transform& transform_to_root_target,
               bool has_transparent_background);
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   SharedQuadState* CreateAndAppendSharedQuadState();
   template <typename DrawQuadType>
diff --git a/cc/quads/render_pass_draw_quad.cc b/cc/quads/render_pass_draw_quad.cc
index 6259fdf..380f2f6 100644
--- a/cc/quads/render_pass_draw_quad.cc
+++ b/cc/quads/render_pass_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/render_pass_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/traced_value.h"
@@ -81,16 +82,24 @@
   return static_cast<const RenderPassDrawQuad*>(quad);
 }
 
-void RenderPassDrawQuad::ExtendValue(base::DictionaryValue* value) const {
-  value->Set("render_pass_id",
-             TracedValue::CreateIDRef(render_pass_id.AsTracingId()).release());
+void RenderPassDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+  TracedValue::SetIDRef(render_pass_id.AsTracingId(), value, "render_pass_id");
   value->SetBoolean("is_replica", is_replica);
   value->SetInteger("mask_resource_id", mask_resource_id);
-  value->Set("contents_changed_since_last_frame",
-             MathUtil::AsValue(contents_changed_since_last_frame).release());
-  value->Set("mask_uv_rect", MathUtil::AsValue(mask_uv_rect).release());
-  value->Set("filters", filters.AsValue().release());
-  value->Set("background_filters", background_filters.AsValue().release());
+  value->BeginArray("contents_changed_since_last_frame");
+  MathUtil::AddToTracedValue(contents_changed_since_last_frame, value);
+  value->EndArray();
+
+  value->BeginArray("mask_uv_rect");
+  MathUtil::AddToTracedValue(mask_uv_rect, value);
+  value->EndArray();
+  value->BeginDictionary("filters");
+  filters.AsValueInto(value);
+  value->EndDictionary();
+
+  value->BeginDictionary("background_filters");
+  background_filters.AsValueInto(value);
+  value->EndDictionary();
 }
 
 }  // namespace cc
diff --git a/cc/quads/render_pass_draw_quad.h b/cc/quads/render_pass_draw_quad.h
index e3d6f14..7237a854 100644
--- a/cc/quads/render_pass_draw_quad.h
+++ b/cc/quads/render_pass_draw_quad.h
@@ -63,7 +63,7 @@
   static const RenderPassDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/shared_quad_state.cc b/cc/quads/shared_quad_state.cc
index 57959e3..83df3657 100644
--- a/cc/quads/shared_quad_state.cc
+++ b/cc/quads/shared_quad_state.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/shared_quad_state.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/traced_value.h"
@@ -45,22 +46,32 @@
   this->sorting_context_id = sorting_context_id;
 }
 
-scoped_ptr<base::Value> SharedQuadState::AsValue() const {
-  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
-  value->Set("transform",
-             MathUtil::AsValue(content_to_target_transform).release());
-  value->Set("layer_content_bounds",
-             MathUtil::AsValue(content_bounds).release());
-  value->Set("layer_visible_content_rect",
-             MathUtil::AsValue(visible_content_rect).release());
+void SharedQuadState::AsValueInto(base::debug::TracedValue* value) const {
+  value->BeginArray("transform");
+  MathUtil::AddToTracedValue(content_to_target_transform, value);
+  value->EndArray();
+
+  value->BeginDictionary("layer_content_bounds");
+  MathUtil::AddToTracedValue(content_bounds, value);
+  value->EndDictionary();
+
+  value->BeginArray("layer_visible_content_rect");
+  MathUtil::AddToTracedValue(visible_content_rect, value);
+  value->EndArray();
+
   value->SetBoolean("is_clipped", is_clipped);
-  value->Set("clip_rect", MathUtil::AsValue(clip_rect).release());
+
+  value->BeginArray("clip_rect");
+  MathUtil::AddToTracedValue(clip_rect, value);
+  value->EndArray();
+
   value->SetDouble("opacity", opacity);
   value->SetString("blend_mode", SkXfermode::ModeName(blend_mode));
   TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
       TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"),
-      value.get(), "cc::SharedQuadState", this);
-  return value.PassAs<base::Value>();
+      value,
+      "cc::SharedQuadState",
+      this);
 }
 
 }  // namespace cc
diff --git a/cc/quads/shared_quad_state.h b/cc/quads/shared_quad_state.h
index 30a1e25..dde87a8 100644
--- a/cc/quads/shared_quad_state.h
+++ b/cc/quads/shared_quad_state.h
@@ -12,6 +12,9 @@
 #include "ui/gfx/transform.h"
 
 namespace base {
+namespace debug {
+class TracedValue;
+}
 class Value;
 }
 
@@ -37,7 +40,7 @@
               float opacity,
               SkXfermode::Mode blend_mode,
               int sorting_context_id);
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   // Transforms from quad's original content space to its target content space.
   gfx::Transform content_to_target_transform;
diff --git a/cc/quads/solid_color_draw_quad.cc b/cc/quads/solid_color_draw_quad.cc
index 333ee17..a11b151 100644
--- a/cc/quads/solid_color_draw_quad.cc
+++ b/cc/quads/solid_color_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/solid_color_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 
@@ -47,7 +48,7 @@
   return static_cast<const SolidColorDrawQuad*>(quad);
 }
 
-void SolidColorDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void SolidColorDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   value->SetInteger("color", color);
   value->SetBoolean("force_anti_aliasing_off", force_anti_aliasing_off);
 }
diff --git a/cc/quads/solid_color_draw_quad.h b/cc/quads/solid_color_draw_quad.h
index 1e746e0..bfb6022 100644
--- a/cc/quads/solid_color_draw_quad.h
+++ b/cc/quads/solid_color_draw_quad.h
@@ -39,7 +39,7 @@
   static const SolidColorDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.cc b/cc/quads/stream_video_draw_quad.cc
index 683d4e5..6b5a509 100644
--- a/cc/quads/stream_video_draw_quad.cc
+++ b/cc/quads/stream_video_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/stream_video_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -49,9 +50,11 @@
   return static_cast<const StreamVideoDrawQuad*>(quad);
 }
 
-void StreamVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void StreamVideoDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   value->SetInteger("resource_id", resource_id);
-  value->Set("matrix", MathUtil::AsValue(matrix).release());
+  value->BeginArray("matrix");
+  MathUtil::AddToTracedValue(matrix, value);
+  value->EndArray();
 }
 
 }  // namespace cc
diff --git a/cc/quads/stream_video_draw_quad.h b/cc/quads/stream_video_draw_quad.h
index 0570f31..5db7c3b 100644
--- a/cc/quads/stream_video_draw_quad.h
+++ b/cc/quads/stream_video_draw_quad.h
@@ -40,7 +40,7 @@
   static const StreamVideoDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/surface_draw_quad.cc b/cc/quads/surface_draw_quad.cc
index 04645da..7ed8f2eb 100644
--- a/cc/quads/surface_draw_quad.cc
+++ b/cc/quads/surface_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/surface_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 
@@ -42,7 +43,7 @@
   return static_cast<const SurfaceDrawQuad*>(quad);
 }
 
-void SurfaceDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void SurfaceDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   value->SetInteger("surface_id", surface_id.id);
 }
 
diff --git a/cc/quads/surface_draw_quad.h b/cc/quads/surface_draw_quad.h
index 7b22ed5..91e5668 100644
--- a/cc/quads/surface_draw_quad.h
+++ b/cc/quads/surface_draw_quad.h
@@ -36,7 +36,7 @@
   static const SurfaceDrawQuad* MaterialCast(const DrawQuad* quad);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/texture_draw_quad.cc b/cc/quads/texture_draw_quad.cc
index 6637e4f..72435c2 100644
--- a/cc/quads/texture_draw_quad.cc
+++ b/cc/quads/texture_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/texture_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -83,16 +84,24 @@
   return static_cast<const TextureDrawQuad*>(quad);
 }
 
-void TextureDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void TextureDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   value->SetInteger("resource_id", resource_id);
   value->SetBoolean("premultiplied_alpha", premultiplied_alpha);
-  value->Set("uv_top_left", MathUtil::AsValue(uv_top_left).release());
-  value->Set("uv_bottom_right", MathUtil::AsValue(uv_bottom_right).release());
+  value->BeginArray("uv_top_left");
+  MathUtil::AddToTracedValue(uv_top_left, value);
+  value->EndArray();
+
+  value->BeginArray("uv_bottom_right");
+  MathUtil::AddToTracedValue(uv_bottom_right, value);
+  value->EndArray();
+
   value->SetInteger("background_color", background_color);
-  scoped_ptr<base::ListValue> vertex_opacity_value(new base::ListValue);
+
+  value->BeginArray("vertex_opacity");
   for (size_t i = 0; i < 4; ++i)
-    vertex_opacity_value->AppendDouble(vertex_opacity[i]);
-  value->Set("vertex_opacity", vertex_opacity_value.release());
+    value->AppendDouble(vertex_opacity[i]);
+  value->EndArray();
+
   value->SetBoolean("flipped", flipped);
 }
 
diff --git a/cc/quads/texture_draw_quad.h b/cc/quads/texture_draw_quad.h
index 409679b..ef8090c3 100644
--- a/cc/quads/texture_draw_quad.h
+++ b/cc/quads/texture_draw_quad.h
@@ -55,7 +55,7 @@
   static const TextureDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/tile_draw_quad.cc b/cc/quads/tile_draw_quad.cc
index 839f0de..ea3a14a9 100644
--- a/cc/quads/tile_draw_quad.cc
+++ b/cc/quads/tile_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/tile_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "third_party/khronos/GLES2/gl2.h"
@@ -61,7 +62,7 @@
   return static_cast<const TileDrawQuad*>(quad);
 }
 
-void TileDrawQuad::ExtendValue(base::DictionaryValue* value) const {
+void TileDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
   ContentDrawQuadBase::ExtendValue(value);
   value->SetInteger("resource_id", resource_id);
 }
diff --git a/cc/quads/tile_draw_quad.h b/cc/quads/tile_draw_quad.h
index 2d3c2ee..72e6bba 100644
--- a/cc/quads/tile_draw_quad.h
+++ b/cc/quads/tile_draw_quad.h
@@ -41,7 +41,7 @@
   static const TileDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/quads/yuv_video_draw_quad.cc b/cc/quads/yuv_video_draw_quad.cc
index d2443ba9..612362e 100644
--- a/cc/quads/yuv_video_draw_quad.cc
+++ b/cc/quads/yuv_video_draw_quad.cc
@@ -4,6 +4,7 @@
 
 #include "cc/quads/yuv_video_draw_quad.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -74,8 +75,10 @@
   return static_cast<const YUVVideoDrawQuad*>(quad);
 }
 
-void YUVVideoDrawQuad::ExtendValue(base::DictionaryValue* value) const {
-  value->Set("tex_coord_rect", MathUtil::AsValue(tex_coord_rect).release());
+void YUVVideoDrawQuad::ExtendValue(base::debug::TracedValue* value) const {
+  value->BeginArray("tex_coord_rect");
+  MathUtil::AddToTracedValue(tex_coord_rect, value);
+  value->EndArray();
   value->SetInteger("y_plane_resource_id", y_plane_resource_id);
   value->SetInteger("u_plane_resource_id", u_plane_resource_id);
   value->SetInteger("v_plane_resource_id", v_plane_resource_id);
diff --git a/cc/quads/yuv_video_draw_quad.h b/cc/quads/yuv_video_draw_quad.h
index 93975d7..930c8215 100644
--- a/cc/quads/yuv_video_draw_quad.h
+++ b/cc/quads/yuv_video_draw_quad.h
@@ -61,7 +61,7 @@
   static const YUVVideoDrawQuad* MaterialCast(const DrawQuad*);
 
  private:
-  virtual void ExtendValue(base::DictionaryValue* value) const OVERRIDE;
+  virtual void ExtendValue(base::debug::TracedValue* value) const OVERRIDE;
 };
 
 }  // namespace cc
diff --git a/cc/resources/image_copy_raster_worker_pool.cc b/cc/resources/image_copy_raster_worker_pool.cc
index f3f88849..2a9b7f1 100644
--- a/cc/resources/image_copy_raster_worker_pool.cc
+++ b/cc/resources/image_copy_raster_worker_pool.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/resource_pool.h"
 #include "cc/resources/scoped_resource.h"
@@ -141,12 +142,7 @@
   resource_pool_->ReduceResourceUsage();
 
   TRACE_EVENT_ASYNC_STEP_INTO1(
-      "cc",
-      "ScheduledTasks",
-      this,
-      "rasterizing",
-      "state",
-      TracedValue::FromValue(StateAsValue().release()));
+      "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
 }
 
 void ImageCopyRasterWorkerPool::CheckForCompletedTasks() {
@@ -223,12 +219,7 @@
   DCHECK(raster_tasks_required_for_activation_pending_);
   raster_tasks_required_for_activation_pending_ = false;
   TRACE_EVENT_ASYNC_STEP_INTO1(
-      "cc",
-      "ScheduledTasks",
-      this,
-      "rasterizing",
-      "state",
-      TracedValue::FromValue(StateAsValue().release()));
+      "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
   client_->DidFinishRunningTasksRequiredForActivation();
 }
 
@@ -240,19 +231,22 @@
   has_performed_copy_since_last_flush_ = false;
 }
 
-scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StateAsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+ImageCopyRasterWorkerPool::StateAsValue() const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
 
   state->SetInteger("pending_count", raster_task_states_.size());
   state->SetBoolean("tasks_required_for_activation_pending",
                     raster_tasks_required_for_activation_pending_);
-  state->Set("staging_state", StagingStateAsValue().release());
+  state->BeginDictionary("staging_state");
+  StagingStateAsValueInto(state.get());
+  state->EndDictionary();
 
-  return state.PassAs<base::Value>();
+  return state;
 }
-scoped_ptr<base::Value> ImageCopyRasterWorkerPool::StagingStateAsValue() const {
-  scoped_ptr<base::DictionaryValue> staging_state(new base::DictionaryValue);
-
+void ImageCopyRasterWorkerPool::StagingStateAsValueInto(
+    base::debug::TracedValue* staging_state) const {
   staging_state->SetInteger("staging_resource_count",
                             resource_pool_->total_resource_count());
   staging_state->SetInteger("bytes_used_for_staging_resources",
@@ -263,8 +257,6 @@
   staging_state->SetInteger("bytes_pending_copy",
                             resource_pool_->total_memory_usage_bytes() -
                                 resource_pool_->acquired_memory_usage_bytes());
-
-  return staging_state.PassAs<base::Value>();
 }
 
 }  // namespace cc
diff --git a/cc/resources/image_copy_raster_worker_pool.h b/cc/resources/image_copy_raster_worker_pool.h
index 8f9d678..62cf3d06 100644
--- a/cc/resources/image_copy_raster_worker_pool.h
+++ b/cc/resources/image_copy_raster_worker_pool.h
@@ -13,6 +13,13 @@
 #include "cc/resources/raster_worker_pool.h"
 #include "cc/resources/rasterizer.h"
 
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
 namespace cc {
 class ResourcePool;
 class ResourceProvider;
@@ -77,8 +84,8 @@
   void OnRasterFinished();
   void OnRasterRequiredForActivationFinished();
   void FlushCopies();
-  scoped_ptr<base::Value> StateAsValue() const;
-  scoped_ptr<base::Value> StagingStateAsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+  void StagingStateAsValueInto(base::debug::TracedValue* staging_state) const;
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   TaskGraphRunner* task_graph_runner_;
diff --git a/cc/resources/image_raster_worker_pool.cc b/cc/resources/image_raster_worker_pool.cc
index 79cfe37..8ac59d3 100644
--- a/cc/resources/image_raster_worker_pool.cc
+++ b/cc/resources/image_raster_worker_pool.cc
@@ -5,6 +5,7 @@
 #include "cc/resources/image_raster_worker_pool.h"
 
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/resource.h"
 
@@ -118,12 +119,7 @@
       new_raster_required_for_activation_finished_task;
 
   TRACE_EVENT_ASYNC_STEP_INTO1(
-      "cc",
-      "ScheduledTasks",
-      this,
-      "rasterizing",
-      "state",
-      TracedValue::FromValue(StateAsValue().release()));
+      "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
 }
 
 void ImageRasterWorkerPool::CheckForCompletedTasks() {
@@ -174,21 +170,18 @@
   DCHECK(raster_tasks_required_for_activation_pending_);
   raster_tasks_required_for_activation_pending_ = false;
   TRACE_EVENT_ASYNC_STEP_INTO1(
-      "cc",
-      "ScheduledTasks",
-      this,
-      "rasterizing",
-      "state",
-      TracedValue::FromValue(StateAsValue().release()));
+      "cc", "ScheduledTasks", this, "rasterizing", "state", StateAsValue());
   client_->DidFinishRunningTasksRequiredForActivation();
 }
 
-scoped_ptr<base::Value> ImageRasterWorkerPool::StateAsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+ImageRasterWorkerPool::StateAsValue() const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
 
   state->SetBoolean("tasks_required_for_activation_pending",
                     raster_tasks_required_for_activation_pending_);
-  return state.PassAs<base::Value>();
+  return state;
 }
 
 }  // namespace cc
diff --git a/cc/resources/image_raster_worker_pool.h b/cc/resources/image_raster_worker_pool.h
index 2e11a22..39ac7237 100644
--- a/cc/resources/image_raster_worker_pool.h
+++ b/cc/resources/image_raster_worker_pool.h
@@ -10,6 +10,12 @@
 #include "cc/resources/raster_worker_pool.h"
 #include "cc/resources/rasterizer.h"
 
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+}
+
 namespace cc {
 class ResourceProvider;
 
@@ -45,7 +51,7 @@
  private:
   void OnRasterFinished();
   void OnRasterRequiredForActivationFinished();
-  scoped_ptr<base::Value> StateAsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   TaskGraphRunner* task_graph_runner_;
diff --git a/cc/resources/managed_tile_state.cc b/cc/resources/managed_tile_state.cc
index c760eb77..7109237 100644
--- a/cc/resources/managed_tile_state.cc
+++ b/cc/resources/managed_tile_state.cc
@@ -5,43 +5,36 @@
 #include "cc/resources/managed_tile_state.h"
 
 #include <limits>
+#include <string>
 
+#include "base/debug/trace_event_argument.h"
 #include "cc/base/math_util.h"
 
 namespace cc {
 
-scoped_ptr<base::Value> ManagedTileBinAsValue(ManagedTileBin bin) {
+std::string ManagedTileBinToString(ManagedTileBin bin) {
   switch (bin) {
     case NOW_AND_READY_TO_DRAW_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("NOW_AND_READY_TO_DRAW_BIN"));
+      return "NOW_AND_READY_TO_DRAW_BIN";
     case NOW_BIN:
-      return scoped_ptr<base::Value>(new base::StringValue("NOW_BIN"));
+      return "NOW_BIN";
     case SOON_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("SOON_BIN"));
+      return "SOON_BIN";
     case EVENTUALLY_AND_ACTIVE_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("EVENTUALLY_AND_ACTIVE_BIN"));
+      return "EVENTUALLY_AND_ACTIVE_BIN";
     case EVENTUALLY_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("EVENTUALLY_BIN"));
+      return "EVENTUALLY_BIN";
     case AT_LAST_AND_ACTIVE_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("AT_LAST_AND_ACTIVE_BIN"));
+      return "AT_LAST_AND_ACTIVE_BIN";
     case AT_LAST_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("AT_LAST_BIN"));
+      return "AT_LAST_BIN";
     case NEVER_BIN:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("NEVER_BIN"));
+      return "NEVER_BIN";
     case NUM_BINS:
       NOTREACHED();
-      return scoped_ptr<base::Value>(
-          new base::StringValue("Invalid Bin (NUM_BINS)"));
+      return "Invalid Bin (NUM_BINS)";
   }
-  return scoped_ptr<base::Value>(
-      new base::StringValue("Invalid Bin (UNKNOWN)"));
+  return "Invalid Bin (UNKNOWN)";
 }
 
 ManagedTileState::ManagedTileState()
@@ -80,7 +73,7 @@
 
 ManagedTileState::~ManagedTileState() {}
 
-scoped_ptr<base::Value> ManagedTileState::AsValue() const {
+void ManagedTileState::AsValueInto(base::debug::TracedValue* state) const {
   bool has_resource = false;
   bool has_active_task = false;
   for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
@@ -90,14 +83,13 @@
 
   bool is_using_gpu_memory = has_resource || has_active_task;
 
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
   state->SetBoolean("has_resource", has_resource);
   state->SetBoolean("is_using_gpu_memory", is_using_gpu_memory);
-  state->Set("bin", ManagedTileBinAsValue(bin).release());
-  state->Set("resolution", TileResolutionAsValue(resolution).release());
-  state->Set("priority_bin", TilePriorityBinAsValue(priority_bin).release());
-  state->Set("distance_to_visible",
-             MathUtil::AsValueSafely(distance_to_visible).release());
+  state->SetString("bin", ManagedTileBinToString(bin));
+  state->SetString("resolution", TileResolutionToString(resolution));
+  state->SetString("priority_bin", TilePriorityBinToString(priority_bin));
+  state->SetDouble("distance_to_visible",
+                   MathUtil::AsFloatSafely(distance_to_visible));
   state->SetBoolean("required_for_activation", required_for_activation);
   state->SetBoolean(
       "is_solid_color",
@@ -107,7 +99,6 @@
       tile_versions[raster_mode].mode_ == TileVersion::SOLID_COLOR_MODE &&
           !SkColorGetA(tile_versions[raster_mode].solid_color_));
   state->SetInteger("scheduled_priority", scheduled_priority);
-  return state.PassAs<base::Value>();
 }
 
 }  // namespace cc
diff --git a/cc/resources/managed_tile_state.h b/cc/resources/managed_tile_state.h
index 7224dd6..faa7c63 100644
--- a/cc/resources/managed_tile_state.h
+++ b/cc/resources/managed_tile_state.h
@@ -104,7 +104,7 @@
   ManagedTileState();
   ~ManagedTileState();
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   // Persisted state: valid all the time.
   TileVersion tile_versions[NUM_RASTER_MODES];
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 959e64cd..e206e8d 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -10,6 +10,7 @@
 
 #include "base/base64.h"
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 #include "cc/base/util.h"
@@ -586,18 +587,22 @@
 
 scoped_refptr<base::debug::ConvertableToTraceFormat>
     Picture::AsTraceableRasterData(float scale) const {
-  scoped_ptr<base::DictionaryValue> raster_data(new base::DictionaryValue());
-  raster_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
+  scoped_refptr<base::debug::TracedValue> raster_data =
+      new base::debug::TracedValue();
+  TracedValue::SetIDRef(this, raster_data.get(), "picture_id");
   raster_data->SetDouble("scale", scale);
-  return TracedValue::FromValue(raster_data.release());
+  return raster_data;
 }
 
 scoped_refptr<base::debug::ConvertableToTraceFormat>
     Picture::AsTraceableRecordData() const {
-  scoped_ptr<base::DictionaryValue> record_data(new base::DictionaryValue());
-  record_data->Set("picture_id", TracedValue::CreateIDRef(this).release());
-  record_data->Set("layer_rect", MathUtil::AsValue(layer_rect_).release());
-  return TracedValue::FromValue(record_data.release());
+  scoped_refptr<base::debug::TracedValue> record_data =
+      new base::debug::TracedValue();
+  TracedValue::SetIDRef(this, record_data.get(), "picture_id");
+  record_data->BeginArray("layer_rect");
+  MathUtil::AddToTracedValue(layer_rect_, record_data.get());
+  record_data->EndArray();
+  return record_data;
 }
 
 }  // namespace cc
diff --git a/cc/resources/picture_layer_tiling.cc b/cc/resources/picture_layer_tiling.cc
index 64661c1a..2809d70 100644
--- a/cc/resources/picture_layer_tiling.cc
+++ b/cc/resources/picture_layer_tiling.cc
@@ -9,6 +9,7 @@
 #include <limits>
 
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "cc/base/math_util.h"
 #include "cc/resources/tile.h"
 #include "cc/resources/tile_priority.h"
@@ -658,12 +659,12 @@
   }
 }
 
-scoped_ptr<base::Value> PictureLayerTiling::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
+void PictureLayerTiling::AsValueInto(base::debug::TracedValue* state) const {
   state->SetInteger("num_tiles", tiles_.size());
   state->SetDouble("content_scale", contents_scale_);
-  state->Set("tiling_size", MathUtil::AsValue(tiling_size()).release());
-  return state.PassAs<base::Value>();
+  state->BeginDictionary("tiling_size");
+  MathUtil::AddToTracedValue(tiling_size(), state);
+  state->EndDictionary();
 }
 
 size_t PictureLayerTiling::GPUMemoryUsageInBytes() const {
diff --git a/cc/resources/picture_layer_tiling.h b/cc/resources/picture_layer_tiling.h
index a8164505..285f64d 100644
--- a/cc/resources/picture_layer_tiling.h
+++ b/cc/resources/picture_layer_tiling.h
@@ -18,6 +18,12 @@
 #include "cc/resources/tile_priority.h"
 #include "ui/gfx/rect.h"
 
+namespace base {
+namespace debug {
+class TracedValue;
+}
+}
+
 namespace cc {
 
 template <typename LayerType>
@@ -242,7 +248,7 @@
     return frame_time_in_seconds != last_impl_frame_time_in_seconds_;
   }
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* array) const;
   size_t GPUMemoryUsageInBytes() const;
 
   struct RectExpansionCache {
diff --git a/cc/resources/picture_layer_tiling_set.cc b/cc/resources/picture_layer_tiling_set.cc
index e24fb52..c799235 100644
--- a/cc/resources/picture_layer_tiling_set.cc
+++ b/cc/resources/picture_layer_tiling_set.cc
@@ -317,11 +317,12 @@
     tilings_[i]->DidBecomeRecycled();
 }
 
-scoped_ptr<base::Value> PictureLayerTilingSet::AsValue() const {
-  scoped_ptr<base::ListValue> state(new base::ListValue());
-  for (size_t i = 0; i < tilings_.size(); ++i)
-    state->Append(tilings_[i]->AsValue().release());
-  return state.PassAs<base::Value>();
+void PictureLayerTilingSet::AsValueInto(base::debug::TracedValue* state) const {
+  for (size_t i = 0; i < tilings_.size(); ++i) {
+    state->BeginDictionary();
+    tilings_[i]->AsValueInto(state);
+    state->EndDictionary();
+  }
 }
 
 size_t PictureLayerTilingSet::GPUMemoryUsageInBytes() const {
diff --git a/cc/resources/picture_layer_tiling_set.h b/cc/resources/picture_layer_tiling_set.h
index d37d9d5..f19c1b87 100644
--- a/cc/resources/picture_layer_tiling_set.h
+++ b/cc/resources/picture_layer_tiling_set.h
@@ -10,6 +10,12 @@
 #include "cc/resources/picture_layer_tiling.h"
 #include "ui/gfx/size.h"
 
+namespace base {
+namespace debug {
+class TracedValue;
+}
+}
+
 namespace cc {
 
 class CC_EXPORT PictureLayerTilingSet {
@@ -115,7 +121,7 @@
     Region::Iterator region_iter_;
   };
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* array) const;
   size_t GPUMemoryUsageInBytes() const;
 
   TilingRange GetTilingRange(TilingRangeType type) const;
diff --git a/cc/resources/picture_pile_base.cc b/cc/resources/picture_pile_base.cc
index 55209db..146c886 100644
--- a/cc/resources/picture_pile_base.cc
+++ b/cc/resources/picture_pile_base.cc
@@ -8,6 +8,7 @@
 #include <set>
 #include <vector>
 
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
@@ -198,8 +199,7 @@
   return padded_rect;
 }
 
-scoped_ptr<base::Value> PicturePileBase::AsValue() const {
-  scoped_ptr<base::ListValue> pictures(new base::ListValue());
+void PicturePileBase::AsValueInto(base::debug::TracedValue* pictures) const {
   gfx::Rect tiling_rect(tiling_.tiling_size());
   std::set<void*> appended_pictures;
   bool include_borders = true;
@@ -213,10 +213,9 @@
     Picture* picture = map_iter->second.GetPicture();
     if (picture && (appended_pictures.count(picture) == 0)) {
       appended_pictures.insert(picture);
-      pictures->Append(TracedValue::CreateIDRef(picture).release());
+      TracedValue::AppendIDRef(picture, pictures);
     }
   }
-  return pictures.PassAs<base::Value>();
 }
 
 PicturePileBase::PictureInfo::PictureInfo() : last_frame_number_(0) {}
diff --git a/cc/resources/picture_pile_base.h b/cc/resources/picture_pile_base.h
index f244f8f..b188df7d 100644
--- a/cc/resources/picture_pile_base.h
+++ b/cc/resources/picture_pile_base.h
@@ -18,6 +18,9 @@
 #include "ui/gfx/size.h"
 
 namespace base {
+namespace debug {
+class TracedValue;
+}
 class Value;
 }
 
@@ -52,7 +55,7 @@
   void SetTileGridSize(const gfx::Size& tile_grid_size);
   TilingData& tiling() { return tiling_; }
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* array) const;
 
  protected:
   class CC_EXPORT PictureInfo {
diff --git a/cc/resources/pixel_buffer_raster_worker_pool.cc b/cc/resources/pixel_buffer_raster_worker_pool.cc
index def15c41..d7554736 100644
--- a/cc/resources/pixel_buffer_raster_worker_pool.cc
+++ b/cc/resources/pixel_buffer_raster_worker_pool.cc
@@ -8,6 +8,7 @@
 
 #include "base/containers/stack_container.h"
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/resource.h"
 #include "gpu/command_buffer/client/gles2_interface.h"
@@ -222,12 +223,7 @@
   check_for_completed_raster_task_notifier_.Schedule();
 
   TRACE_EVENT_ASYNC_STEP_INTO1(
-      "cc",
-      "ScheduledTasks",
-      this,
-      StateName(),
-      "state",
-      TracedValue::FromValue(StateAsValue().release()));
+      "cc", "ScheduledTasks", this, StateName(), "state", StateAsValue());
 }
 
 void PixelBufferRasterWorkerPool::CheckForCompletedTasks() {
@@ -460,12 +456,7 @@
     ScheduleMoreTasks();
 
   TRACE_EVENT_ASYNC_STEP_INTO1(
-      "cc",
-      "ScheduledTasks",
-      this,
-      StateName(),
-      "state",
-      TracedValue::FromValue(StateAsValue().release()));
+      "cc", "ScheduledTasks", this, StateName(), "state", StateAsValue());
 
   // Schedule another check for completed raster tasks while there are
   // pending raster tasks or pending uploads.
@@ -742,29 +733,29 @@
   completed_tasks_.clear();
 }
 
-scoped_ptr<base::Value> PixelBufferRasterWorkerPool::StateAsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
-
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+PixelBufferRasterWorkerPool::StateAsValue() const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
   state->SetInteger("completed_count", completed_raster_tasks_.size());
   state->SetInteger("pending_count", raster_task_states_.size());
   state->SetInteger("pending_upload_count",
                     raster_tasks_with_pending_upload_.size());
   state->SetInteger("pending_required_for_activation_count",
                     raster_tasks_required_for_activation_count_);
-  state->Set("throttle_state", ThrottleStateAsValue().release());
-  return state.PassAs<base::Value>();
+  state->BeginDictionary("throttle_state");
+  ThrottleStateAsValueInto(state.get());
+  state->EndDictionary();
+  return state;
 }
 
-scoped_ptr<base::Value> PixelBufferRasterWorkerPool::ThrottleStateAsValue()
-    const {
-  scoped_ptr<base::DictionaryValue> throttle_state(new base::DictionaryValue);
-
+void PixelBufferRasterWorkerPool::ThrottleStateAsValueInto(
+    base::debug::TracedValue* throttle_state) const {
   throttle_state->SetInteger("bytes_available_for_upload",
                              max_bytes_pending_upload_ - bytes_pending_upload_);
   throttle_state->SetInteger("bytes_pending_upload", bytes_pending_upload_);
   throttle_state->SetInteger("scheduled_raster_task_count",
                              scheduled_raster_task_count_);
-  return throttle_state.PassAs<base::Value>();
 }
 
 }  // namespace cc
diff --git a/cc/resources/pixel_buffer_raster_worker_pool.h b/cc/resources/pixel_buffer_raster_worker_pool.h
index aa1a345..d4fc088 100644
--- a/cc/resources/pixel_buffer_raster_worker_pool.h
+++ b/cc/resources/pixel_buffer_raster_worker_pool.h
@@ -15,6 +15,13 @@
 #include "cc/resources/raster_worker_pool.h"
 #include "cc/resources/rasterizer.h"
 
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
 namespace cc {
 class ResourceProvider;
 
@@ -90,8 +97,8 @@
   void CheckForCompletedRasterizerTasks();
 
   const char* StateName() const;
-  scoped_ptr<base::Value> StateAsValue() const;
-  scoped_ptr<base::Value> ThrottleStateAsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> StateAsValue() const;
+  void ThrottleStateAsValueInto(base::debug::TracedValue* throttle_state) const;
 
   scoped_refptr<base::SequencedTaskRunner> task_runner_;
   TaskGraphRunner* task_graph_runner_;
diff --git a/cc/resources/raster_mode.cc b/cc/resources/raster_mode.cc
index 5da8ee7..d67fdd85 100644
--- a/cc/resources/raster_mode.cc
+++ b/cc/resources/raster_mode.cc
@@ -10,18 +10,15 @@
 
 namespace cc {
 
-scoped_ptr<base::Value> RasterModeAsValue(RasterMode raster_mode) {
+std::string RasterModeToString(RasterMode raster_mode) {
   switch (raster_mode) {
     case HIGH_QUALITY_RASTER_MODE:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("HIGH_QUALITY_RASTER_MODE"));
+      return "HIGH_QUALITY_RASTER_MODE";
     case LOW_QUALITY_RASTER_MODE:
-      return scoped_ptr<base::Value>(
-          new base::StringValue("LOW_QUALITY_RASTER_MODE"));
+      return "LOW_QUALITY_RASTER_MODE";
     default:
       NOTREACHED() << "Unrecognized RasterMode value " << raster_mode;
-      return scoped_ptr<base::Value>(
-          new base::StringValue("<unknown RasterMode value>"));
+      return "<unknown RasterMode value>";
   }
 }
 
diff --git a/cc/resources/raster_mode.h b/cc/resources/raster_mode.h
index 0a2b4c9..ec9ec27 100644
--- a/cc/resources/raster_mode.h
+++ b/cc/resources/raster_mode.h
@@ -5,6 +5,8 @@
 #ifndef CC_RESOURCES_RASTER_MODE_H_
 #define CC_RESOURCES_RASTER_MODE_H_
 
+#include <string>
+
 #include "base/memory/scoped_ptr.h"
 
 namespace base {
@@ -21,7 +23,7 @@
   NUM_RASTER_MODES = 2
 };
 
-scoped_ptr<base::Value> RasterModeAsValue(RasterMode mode);
+std::string RasterModeToString(RasterMode mode);
 
 }  // namespace cc
 
diff --git a/cc/resources/tile.cc b/cc/resources/tile.cc
index 48a10db7..2725a936 100644
--- a/cc/resources/tile.cc
+++ b/cc/resources/tile.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/debug/trace_event_argument.h"
 #include "cc/base/math_util.h"
 #include "cc/debug/traced_value.h"
 #include "cc/resources/tile_manager.h"
@@ -61,20 +62,31 @@
   tile_manager_->DidChangeTilePriority(this);
 }
 
-scoped_ptr<base::Value> Tile::AsValue() const {
-  scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue());
+void Tile::AsValueInto(base::debug::TracedValue* res) const {
   TracedValue::MakeDictIntoImplicitSnapshotWithCategory(
-      TRACE_DISABLED_BY_DEFAULT("cc.debug"), res.get(), "cc::Tile", this);
-  res->Set("picture_pile",
-           TracedValue::CreateIDRef(picture_pile_.get()).release());
+      TRACE_DISABLED_BY_DEFAULT("cc.debug"), res, "cc::Tile", this);
+  TracedValue::SetIDRef(picture_pile_.get(), res, "picture_pile");
   res->SetDouble("contents_scale", contents_scale_);
-  res->Set("content_rect", MathUtil::AsValue(content_rect_).release());
+
+  res->BeginArray("content_rect");
+  MathUtil::AddToTracedValue(content_rect_, res);
+  res->EndArray();
+
   res->SetInteger("layer_id", layer_id_);
-  res->Set("active_priority", priority_[ACTIVE_TREE].AsValue().release());
-  res->Set("pending_priority", priority_[PENDING_TREE].AsValue().release());
-  res->Set("managed_state", managed_state_.AsValue().release());
+
+  res->BeginDictionary("active_priority");
+  priority_[ACTIVE_TREE].AsValueInto(res);
+  res->EndDictionary();
+
+  res->BeginDictionary("pending_priority");
+  priority_[PENDING_TREE].AsValueInto(res);
+  res->EndDictionary();
+
+  res->BeginDictionary("managed_state");
+  managed_state_.AsValueInto(res);
+  res->EndDictionary();
+
   res->SetBoolean("use_picture_analysis", use_picture_analysis());
-  return res.PassAs<base::Value>();
 }
 
 size_t Tile::GPUMemoryUsageInBytes() const {
diff --git a/cc/resources/tile.h b/cc/resources/tile.h
index 9aeabfa1..8d91446 100644
--- a/cc/resources/tile.h
+++ b/cc/resources/tile.h
@@ -103,7 +103,7 @@
     return false;
   }
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   inline bool IsReadyToDraw() const {
     for (int mode = 0; mode < NUM_RASTER_MODES; ++mode) {
diff --git a/cc/resources/tile_manager.cc b/cc/resources/tile_manager.cc
index bf10d95..f6405bf 100644
--- a/cc/resources/tile_manager.cc
+++ b/cc/resources/tile_manager.cc
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/bind.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/json/json_writer.h"
 #include "base/logging.h"
 #include "base/metrics/histogram.h"
@@ -336,12 +337,13 @@
 RasterTaskCompletionStats::RasterTaskCompletionStats()
     : completed_count(0u), canceled_count(0u) {}
 
-scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
-    const RasterTaskCompletionStats& stats) {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats) {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
   state->SetInteger("completed_count", stats.completed_count);
   state->SetInteger("canceled_count", stats.canceled_count);
-  return state.PassAs<base::Value>();
+  return state;
 }
 
 // static
@@ -667,7 +669,7 @@
                        "DidManage",
                        TRACE_EVENT_SCOPE_THREAD,
                        "state",
-                       TracedValue::FromValue(BasicStateAsValue().release()));
+                       BasicStateAsValue());
 
   TRACE_COUNTER_ID1("cc",
                     "unused_memory_bytes",
@@ -687,8 +689,7 @@
       "DidUpdateVisibleTiles",
       TRACE_EVENT_SCOPE_THREAD,
       "stats",
-      TracedValue::FromValue(RasterTaskCompletionStatsAsValue(
-                                 update_visible_tiles_stats_).release()));
+      RasterTaskCompletionStatsAsValue(update_visible_tiles_stats_));
   update_visible_tiles_stats_ = RasterTaskCompletionStats();
 
   bool did_initialize_visible_tile = did_initialize_visible_tile_;
@@ -696,19 +697,27 @@
   return did_initialize_visible_tile;
 }
 
-scoped_ptr<base::Value> TileManager::BasicStateAsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  state->SetInteger("tile_count", tiles_.size());
-  state->Set("global_state", global_state_.AsValue().release());
-  return state.PassAs<base::Value>();
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+TileManager::BasicStateAsValue() const {
+  scoped_refptr<base::debug::TracedValue> value =
+      new base::debug::TracedValue();
+  BasicStateAsValueInto(value.get());
+  return value;
 }
 
-scoped_ptr<base::Value> TileManager::AllTilesAsValue() const {
-  scoped_ptr<base::ListValue> state(new base::ListValue());
-  for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
-    state->Append(it->second->AsValue().release());
+void TileManager::BasicStateAsValueInto(base::debug::TracedValue* state) const {
+  state->SetInteger("tile_count", tiles_.size());
+  state->BeginDictionary("global_state");
+  global_state_.AsValueInto(state);
+  state->EndDictionary();
+}
 
-  return state.PassAs<base::Value>();
+void TileManager::AllTilesAsValueInto(base::debug::TracedValue* state) const {
+  for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
+    state->BeginDictionary();
+    it->second->AsValueInto(state);
+    state->EndDictionary();
+  }
 }
 
 void TileManager::AssignGpuMemoryToTiles(
diff --git a/cc/resources/tile_manager.h b/cc/resources/tile_manager.h
index 686d0d06..d4c549c3 100644
--- a/cc/resources/tile_manager.h
+++ b/cc/resources/tile_manager.h
@@ -27,6 +27,13 @@
 #include "cc/resources/resource_pool.h"
 #include "cc/resources/tile.h"
 
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+class TracedValue;
+}
+}
+
 namespace cc {
 class PictureLayerImpl;
 class ResourceProvider;
@@ -70,8 +77,8 @@
   size_t completed_count;
   size_t canceled_count;
 };
-scoped_ptr<base::Value> RasterTaskCompletionStatsAsValue(
-    const RasterTaskCompletionStats& stats);
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+    RasterTaskCompletionStatsAsValue(const RasterTaskCompletionStats& stats);
 
 // This class manages tiles, deciding which should get rasterized and which
 // should no longer have any memory assigned to them. Tile objects are "owned"
@@ -102,8 +109,10 @@
                                  int source_frame_number,
                                  int flags);
 
-  scoped_ptr<base::Value> BasicStateAsValue() const;
-  scoped_ptr<base::Value> AllTilesAsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> BasicStateAsValue()
+      const;
+  void BasicStateAsValueInto(base::debug::TracedValue* dict) const;
+  void AllTilesAsValueInto(base::debug::TracedValue* array) const;
   const MemoryHistory::Entry& memory_stats_from_last_assign() const {
     return memory_stats_from_last_assign_;
   }
diff --git a/cc/resources/tile_priority.cc b/cc/resources/tile_priority.cc
index 18678d2..26826af 100644
--- a/cc/resources/tile_priority.cc
+++ b/cc/resources/tile_priority.cc
@@ -4,110 +4,95 @@
 
 #include "cc/resources/tile_priority.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "base/values.h"
 #include "cc/base/math_util.h"
 
 namespace cc {
 
-scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree) {
+std::string WhichTreeToString(WhichTree tree) {
   switch (tree) {
   case ACTIVE_TREE:
-      return scoped_ptr<base::Value>(new base::StringValue("ACTIVE_TREE"));
+    return "ACTIVE_TREE";
   case PENDING_TREE:
-      return scoped_ptr<base::Value>(new base::StringValue("PENDING_TREE"));
+    return "PENDING_TREE";
   default:
       DCHECK(false) << "Unrecognized WhichTree value " << tree;
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "<unknown WhichTree value>"));
+      return "<unknown WhichTree value>";
   }
 }
 
-scoped_ptr<base::Value> TileResolutionAsValue(
-    TileResolution resolution) {
+std::string TileResolutionToString(TileResolution resolution) {
   switch (resolution) {
   case LOW_RESOLUTION:
-    return scoped_ptr<base::Value>(new base::StringValue("LOW_RESOLUTION"));
+    return "LOW_RESOLUTION";
   case HIGH_RESOLUTION:
-    return scoped_ptr<base::Value>(new base::StringValue("HIGH_RESOLUTION"));
+    return "HIGH_RESOLUTION";
   case NON_IDEAL_RESOLUTION:
-      return scoped_ptr<base::Value>(new base::StringValue(
-        "NON_IDEAL_RESOLUTION"));
+    return "NON_IDEAL_RESOLUTION";
   }
   DCHECK(false) << "Unrecognized TileResolution value " << resolution;
-  return scoped_ptr<base::Value>(new base::StringValue(
-      "<unknown TileResolution value>"));
+  return "<unknown TileResolution value>";
 }
 
-scoped_ptr<base::Value> TilePriorityBinAsValue(TilePriority::PriorityBin bin) {
+std::string TilePriorityBinToString(TilePriority::PriorityBin bin) {
   switch (bin) {
     case TilePriority::NOW:
-      return scoped_ptr<base::Value>(new base::StringValue("NOW"));
+      return "NOW";
     case TilePriority::SOON:
-      return scoped_ptr<base::Value>(new base::StringValue("SOON"));
+      return "SOON";
     case TilePriority::EVENTUALLY:
-      return scoped_ptr<base::Value>(new base::StringValue("EVENTUALLY"));
+      return "EVENTUALLY";
   }
   DCHECK(false) << "Unrecognized TilePriority::PriorityBin value " << bin;
-  return scoped_ptr<base::Value>(
-      new base::StringValue("<unknown TilePriority::PriorityBin value>"));
+  return "<unknown TilePriority::PriorityBin value>";
 }
 
-scoped_ptr<base::Value> TilePriority::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  state->Set("resolution", TileResolutionAsValue(resolution).release());
-  state->Set("priority_bin", TilePriorityBinAsValue(priority_bin).release());
-  state->Set("distance_to_visible",
-             MathUtil::AsValueSafely(distance_to_visible).release());
-  return state.PassAs<base::Value>();
+void TilePriority::AsValueInto(base::debug::TracedValue* state) const {
+  state->SetString("resolution", TileResolutionToString(resolution));
+  state->SetString("priority_bin", TilePriorityBinToString(priority_bin));
+  state->SetDouble("distance_to_visible",
+                   MathUtil::AsDoubleSafely(distance_to_visible));
 }
 
-scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue(
-    TileMemoryLimitPolicy policy) {
+std::string TileMemoryLimitPolicyToString(TileMemoryLimitPolicy policy) {
   switch (policy) {
   case ALLOW_NOTHING:
-      return scoped_ptr<base::Value>(new base::StringValue("ALLOW_NOTHING"));
+    return "ALLOW_NOTHING";
   case ALLOW_ABSOLUTE_MINIMUM:
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "ALLOW_ABSOLUTE_MINIMUM"));
+    return "ALLOW_ABSOLUTE_MINIMUM";
   case ALLOW_PREPAINT_ONLY:
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "ALLOW_PREPAINT_ONLY"));
+    return "ALLOW_PREPAINT_ONLY";
   case ALLOW_ANYTHING:
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "ALLOW_ANYTHING"));
+    return "ALLOW_ANYTHING";
   default:
       DCHECK(false) << "Unrecognized policy value";
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "<unknown>"));
+      return "<unknown>";
   }
 }
 
-scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio) {
+std::string TreePriorityToString(TreePriority prio) {
   switch (prio) {
   case SAME_PRIORITY_FOR_BOTH_TREES:
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "SAME_PRIORITY_FOR_BOTH_TREES"));
+    return "SAME_PRIORITY_FOR_BOTH_TREES";
   case SMOOTHNESS_TAKES_PRIORITY:
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "SMOOTHNESS_TAKES_PRIORITY"));
+    return "SMOOTHNESS_TAKES_PRIORITY";
   case NEW_CONTENT_TAKES_PRIORITY:
-      return scoped_ptr<base::Value>(new base::StringValue(
-          "NEW_CONTENT_TAKES_PRIORITY"));
+    return "NEW_CONTENT_TAKES_PRIORITY";
   default:
     DCHECK(false) << "Unrecognized priority value " << prio;
-    return scoped_ptr<base::Value>(new base::StringValue("<unknown>"));
+    return "<unknown>";
   }
 }
 
-scoped_ptr<base::Value> GlobalStateThatImpactsTilePriority::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  state->Set("memory_limit_policy",
-             TileMemoryLimitPolicyAsValue(memory_limit_policy).release());
+void GlobalStateThatImpactsTilePriority::AsValueInto(
+    base::debug::TracedValue* state) const {
+  state->SetString("memory_limit_policy",
+                   TileMemoryLimitPolicyToString(memory_limit_policy));
   state->SetInteger("soft_memory_limit_in_bytes", soft_memory_limit_in_bytes);
   state->SetInteger("hard_memory_limit_in_bytes", hard_memory_limit_in_bytes);
   state->SetInteger("num_resources_limit", num_resources_limit);
-  state->Set("tree_priority", TreePriorityAsValue(tree_priority).release());
-  return state.PassAs<base::Value>();
+  state->SetString("tree_priority", TreePriorityToString(tree_priority));
 }
 
 }  // namespace cc
diff --git a/cc/resources/tile_priority.h b/cc/resources/tile_priority.h
index a0903f1..02aadae9 100644
--- a/cc/resources/tile_priority.h
+++ b/cc/resources/tile_priority.h
@@ -7,6 +7,7 @@
 
 #include <algorithm>
 #include <limits>
+#include <string>
 
 #include "base/memory/ref_counted.h"
 #include "base/memory/scoped_ptr.h"
@@ -29,16 +30,14 @@
   NUM_TREES = 2
   // Be sure to update WhichTreeAsValue when adding new fields.
 };
-scoped_ptr<base::Value> WhichTreeAsValue(
-    WhichTree tree);
+scoped_ptr<base::Value> WhichTreeAsValue(WhichTree tree);
 
 enum TileResolution {
   LOW_RESOLUTION = 0 ,
   HIGH_RESOLUTION = 1,
   NON_IDEAL_RESOLUTION = 2,
 };
-scoped_ptr<base::Value> TileResolutionAsValue(
-    TileResolution resolution);
+std::string TileResolutionToString(TileResolution resolution);
 
 struct CC_EXPORT TilePriority {
   enum PriorityBin { NOW, SOON, EVENTUALLY };
@@ -83,7 +82,7 @@
     }
   }
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   bool operator ==(const TilePriority& other) const {
     return resolution == other.resolution &&
@@ -108,7 +107,7 @@
   float distance_to_visible;
 };
 
-scoped_ptr<base::Value> TilePriorityBinAsValue(TilePriority::PriorityBin bin);
+std::string TilePriorityBinToString(TilePriority::PriorityBin bin);
 
 enum TileMemoryLimitPolicy {
   // Nothing.
@@ -128,8 +127,7 @@
   // NOTE: Be sure to update TreePriorityAsValue and kBinPolicyMap when adding
   // or reordering fields.
 };
-scoped_ptr<base::Value> TileMemoryLimitPolicyAsValue(
-    TileMemoryLimitPolicy policy);
+std::string TileMemoryLimitPolicyToString(TileMemoryLimitPolicy policy);
 
 enum TreePriority {
   SAME_PRIORITY_FOR_BOTH_TREES,
@@ -138,7 +136,7 @@
   NUM_TREE_PRIORITIES
   // Be sure to update TreePriorityAsValue when adding new fields.
 };
-scoped_ptr<base::Value> TreePriorityAsValue(TreePriority prio);
+std::string TreePriorityToString(TreePriority prio);
 
 class GlobalStateThatImpactsTilePriority {
  public:
@@ -168,7 +166,7 @@
     return !(*this == other);
   }
 
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 };
 
 }  // namespace cc
diff --git a/cc/scheduler/delay_based_time_source.cc b/cc/scheduler/delay_based_time_source.cc
index 2be3d3d..cd214fd9 100644
--- a/cc/scheduler/delay_based_time_source.cc
+++ b/cc/scheduler/delay_based_time_source.cc
@@ -10,6 +10,7 @@
 
 #include "base/bind.h"
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/location.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
@@ -289,31 +290,25 @@
   return "DelayBasedTimeSourceHighRes";
 }
 
-scoped_ptr<base::Value> DelayBasedTimeSource::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
+void DelayBasedTimeSource::AsValueInto(base::debug::TracedValue* state) const {
   state->SetString("type", TypeString());
   state->SetDouble("last_tick_time_us", LastTickTime().ToInternalValue());
   state->SetDouble("next_tick_time_us", NextTickTime().ToInternalValue());
 
-  scoped_ptr<base::DictionaryValue> state_current_parameters(
-      new base::DictionaryValue);
-  state_current_parameters->SetDouble(
-      "interval_us", current_parameters_.interval.InMicroseconds());
-  state_current_parameters->SetDouble(
-      "tick_target_us", current_parameters_.tick_target.ToInternalValue());
-  state->Set("current_parameters", state_current_parameters.release());
+  state->BeginDictionary("current_parameters");
+  state->SetDouble("interval_us",
+                   current_parameters_.interval.InMicroseconds());
+  state->SetDouble("tick_target_us",
+                   current_parameters_.tick_target.ToInternalValue());
+  state->EndDictionary();
 
-  scoped_ptr<base::DictionaryValue> state_next_parameters(
-      new base::DictionaryValue);
-  state_next_parameters->SetDouble("interval_us",
-                                   next_parameters_.interval.InMicroseconds());
-  state_next_parameters->SetDouble(
-      "tick_target_us", next_parameters_.tick_target.ToInternalValue());
-  state->Set("next_parameters", state_next_parameters.release());
+  state->BeginDictionary("next_parameters");
+  state->SetDouble("interval_us", next_parameters_.interval.InMicroseconds());
+  state->SetDouble("tick_target_us",
+                   next_parameters_.tick_target.ToInternalValue());
+  state->EndDictionary();
 
   state->SetBoolean("active", active_);
-
-  return state.PassAs<base::Value>();
 }
 
 }  // namespace cc
diff --git a/cc/scheduler/delay_based_time_source.h b/cc/scheduler/delay_based_time_source.h
index 18c8002..e503bdf 100644
--- a/cc/scheduler/delay_based_time_source.h
+++ b/cc/scheduler/delay_based_time_source.h
@@ -11,7 +11,12 @@
 #include "base/values.h"
 #include "cc/base/cc_export.h"
 
-namespace base { class SingleThreadTaskRunner; }
+namespace base {
+namespace debug {
+class TracedValue;
+}
+class SingleThreadTaskRunner;
+}
 
 namespace cc {
 
@@ -49,7 +54,7 @@
   // Virtual for testing.
   virtual base::TimeTicks Now() const;
 
-  virtual scoped_ptr<base::Value> AsValue() const;
+  virtual void AsValueInto(base::debug::TracedValue* dict) const;
 
  protected:
   DelayBasedTimeSource(base::TimeDelta interval,
diff --git a/cc/scheduler/scheduler.cc b/cc/scheduler/scheduler.cc
index 52e0f9e..1451237 100644
--- a/cc/scheduler/scheduler.cc
+++ b/cc/scheduler/scheduler.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include "base/auto_reset.h"
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/logging.h"
 #include "base/single_thread_task_runner.h"
 #include "cc/debug/devtools_instrumentation.h"
@@ -61,8 +62,9 @@
   scheduler_->BeginFrame(begin_frame_args);
 }
 
-scoped_ptr<base::Value> Scheduler::SyntheticBeginFrameSource::AsValue() const {
-  return time_source_->AsValue();
+void Scheduler::SyntheticBeginFrameSource::AsValueInto(
+    base::debug::TracedValue* state) const {
+  time_source_->AsValueInto(state);
 }
 
 BeginFrameArgs
@@ -93,7 +95,7 @@
   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
                "Scheduler::Scheduler",
                "settings",
-               ToTrace(settings_));
+               settings_.AsValue());
   DCHECK(client_);
   DCHECK(!state_machine_.BeginFrameNeeded());
   if (settings_.main_frame_before_activation_enabled) {
@@ -399,7 +401,7 @@
 // If the scheduler is busy, we queue the BeginFrame to be handled later as
 // a BeginRetroFrame.
 void Scheduler::BeginFrame(const BeginFrameArgs& args) {
-  TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", ToTrace(args));
+  TRACE_EVENT1("cc", "Scheduler::BeginFrame", "args", args.AsValue());
   DCHECK(settings_.throttle_frame_production);
 
   BeginFrameArgs adjusted_args(args);
@@ -496,7 +498,7 @@
 // for a BeginMainFrame+activation to complete before it times out and draws
 // any asynchronous animation and scroll/pinch updates.
 void Scheduler::BeginImplFrame(const BeginFrameArgs& args) {
-  TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", ToTrace(args));
+  TRACE_EVENT1("cc", "Scheduler::BeginImplFrame", "args", args.AsValue());
   DCHECK(state_machine_.begin_impl_frame_state() ==
          SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_IDLE);
   DCHECK(state_machine_.HasInitializedOutputSurface());
@@ -626,7 +628,7 @@
     TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler"),
                  "SchedulerStateMachine",
                  "state",
-                 ToTrace(this));
+                 AsValue());
     state_machine_.UpdateState(action);
     base::AutoReset<SchedulerStateMachine::Action>
         mark_inside_action(&inside_action_, action);
@@ -680,51 +682,54 @@
   return !state_machine_.PendingDrawsShouldBeAborted();
 }
 
-scoped_ptr<base::Value> Scheduler::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
-  state->Set("state_machine", state_machine_.AsValue().release());
-  if (synthetic_begin_frame_source_)
-    state->Set("synthetic_begin_frame_source_",
-               synthetic_begin_frame_source_->AsValue().release());
+scoped_refptr<base::debug::ConvertableToTraceFormat> Scheduler::AsValue()
+    const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
+  state->BeginDictionary("state_machine");
+  state_machine_.AsValueInto(state);
+  state->EndDictionary();
+  if (synthetic_begin_frame_source_) {
+    state->BeginDictionary("synthetic_begin_frame_source_");
+    synthetic_begin_frame_source_->AsValueInto(state);
+    state->EndDictionary();
+  }
 
-  scoped_ptr<base::DictionaryValue> scheduler_state(new base::DictionaryValue);
-  scheduler_state->SetDouble(
+  state->BeginDictionary("scheduler_state");
+  state->SetDouble(
       "time_until_anticipated_draw_time_ms",
       (AnticipatedDrawTime() - base::TimeTicks::Now()).InMillisecondsF());
-  scheduler_state->SetDouble("vsync_interval_ms",
-                             vsync_interval_.InMillisecondsF());
-  scheduler_state->SetDouble("estimated_parent_draw_time_ms",
-                             estimated_parent_draw_time_.InMillisecondsF());
-  scheduler_state->SetBoolean("last_set_needs_begin_frame_",
-                              last_set_needs_begin_frame_);
-  scheduler_state->SetBoolean("begin_unthrottled_frame_posted_",
-                              begin_unthrottled_frame_posted_);
-  scheduler_state->SetBoolean("begin_retro_frame_posted_",
-                              begin_retro_frame_posted_);
-  scheduler_state->SetInteger("begin_retro_frame_args_",
-                              begin_retro_frame_args_.size());
-  scheduler_state->SetBoolean("begin_impl_frame_deadline_task_",
-                              !begin_impl_frame_deadline_task_.IsCancelled());
-  scheduler_state->SetBoolean("poll_for_draw_triggers_task_",
-                              !poll_for_draw_triggers_task_.IsCancelled());
-  scheduler_state->SetBoolean("advance_commit_state_task_",
-                              !advance_commit_state_task_.IsCancelled());
-  scheduler_state->Set("begin_impl_frame_args",
-                       begin_impl_frame_args_.AsValue().release());
+  state->SetDouble("vsync_interval_ms", vsync_interval_.InMillisecondsF());
+  state->SetDouble("estimated_parent_draw_time_ms",
+                   estimated_parent_draw_time_.InMillisecondsF());
+  state->SetBoolean("last_set_needs_begin_frame_", last_set_needs_begin_frame_);
+  state->SetBoolean("begin_unthrottled_frame_posted_",
+                    begin_unthrottled_frame_posted_);
+  state->SetBoolean("begin_retro_frame_posted_", begin_retro_frame_posted_);
+  state->SetInteger("begin_retro_frame_args_", begin_retro_frame_args_.size());
+  state->SetBoolean("begin_impl_frame_deadline_task_",
+                    !begin_impl_frame_deadline_task_.IsCancelled());
+  state->SetBoolean("poll_for_draw_triggers_task_",
+                    !poll_for_draw_triggers_task_.IsCancelled());
+  state->SetBoolean("advance_commit_state_task_",
+                    !advance_commit_state_task_.IsCancelled());
+  state->BeginDictionary("begin_impl_frame_args");
+  begin_impl_frame_args_.AsValueInto(state);
+  state->EndDictionary();
 
-  state->Set("scheduler_state", scheduler_state.release());
+  state->EndDictionary();
 
-  scoped_ptr<base::DictionaryValue> client_state(new base::DictionaryValue);
-  client_state->SetDouble("draw_duration_estimate_ms",
-                          client_->DrawDurationEstimate().InMillisecondsF());
-  client_state->SetDouble(
+  state->BeginDictionary("client_state");
+  state->SetDouble("draw_duration_estimate_ms",
+                   client_->DrawDurationEstimate().InMillisecondsF());
+  state->SetDouble(
       "begin_main_frame_to_commit_duration_estimate_ms",
       client_->BeginMainFrameToCommitDurationEstimate().InMillisecondsF());
-  client_state->SetDouble(
+  state->SetDouble(
       "commit_to_activate_duration_estimate_ms",
       client_->CommitToActivateDurationEstimate().InMillisecondsF());
-  state->Set("client_state", client_state.release());
-  return state.PassAs<base::Value>();
+  state->EndDictionary();
+  return state;
 }
 
 bool Scheduler::CanCommitAndActivateBeforeDeadline() const {
@@ -741,7 +746,7 @@
       "time_left_after_drawing_ms",
       (begin_impl_frame_args_.deadline - estimated_draw_time).InMillisecondsF(),
       "state",
-      ToTrace(this));
+      AsValue());
 
   return estimated_draw_time < begin_impl_frame_args_.deadline;
 }
diff --git a/cc/scheduler/scheduler.h b/cc/scheduler/scheduler.h
index 3653c30..afb9e9d 100644
--- a/cc/scheduler/scheduler.h
+++ b/cc/scheduler/scheduler.h
@@ -20,6 +20,9 @@
 #include "cc/scheduler/scheduler_state_machine.h"
 
 namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
 class SingleThreadTaskRunner;
 }
 
@@ -129,7 +132,7 @@
   void PollForAnticipatedDrawTriggers();
   void PollToAdvanceCommitState();
 
-  scoped_ptr<base::Value> AsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
 
   bool IsInsideAction(SchedulerStateMachine::Action action) {
     return inside_action_ == action;
@@ -161,7 +164,7 @@
     // TimeSourceClient implementation of OnTimerTick triggers a BeginFrame.
     virtual void OnTimerTick() OVERRIDE;
 
-    scoped_ptr<base::Value> AsValue() const;
+    void AsValueInto(base::debug::TracedValue* dict) const;
 
    private:
     BeginFrameArgs CreateSyntheticBeginFrameArgs(base::TimeTicks frame_time);
diff --git a/cc/scheduler/scheduler_settings.cc b/cc/scheduler/scheduler_settings.cc
index f1bf60e7..ea714e3 100644
--- a/cc/scheduler/scheduler_settings.cc
+++ b/cc/scheduler/scheduler_settings.cc
@@ -4,6 +4,7 @@
 
 #include "cc/scheduler/scheduler_settings.h"
 
+#include "base/debug/trace_event_argument.h"
 #include "cc/trees/layer_tree_settings.h"
 
 namespace cc {
@@ -36,8 +37,10 @@
 
 SchedulerSettings::~SchedulerSettings() {}
 
-scoped_ptr<base::Value> SchedulerSettings::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+SchedulerSettings::AsValue() const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
   state->SetBoolean("begin_frame_scheduling_enabled",
                     begin_frame_scheduling_enabled);
   state->SetBoolean("main_frame_before_draw_enabled",
@@ -52,7 +55,7 @@
   state->SetBoolean("using_synchronous_renderer_compositor",
                     using_synchronous_renderer_compositor);
   state->SetBoolean("throttle_frame_production", throttle_frame_production);
-  return state.PassAs<base::Value>();
+  return state;
 }
 
 }  // namespace cc
diff --git a/cc/scheduler/scheduler_settings.h b/cc/scheduler/scheduler_settings.h
index c282cf6..65d29c87 100644
--- a/cc/scheduler/scheduler_settings.h
+++ b/cc/scheduler/scheduler_settings.h
@@ -5,10 +5,16 @@
 #ifndef CC_SCHEDULER_SCHEDULER_SETTINGS_H_
 #define CC_SCHEDULER_SCHEDULER_SETTINGS_H_
 
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ref_counted.h"
 #include "base/values.h"
 #include "cc/base/cc_export.h"
 
+namespace base {
+namespace debug {
+class ConvertableToTraceFormat;
+}
+}
+
 namespace cc {
 class LayerTreeSettings;
 
@@ -27,7 +33,7 @@
   bool using_synchronous_renderer_compositor;
   bool throttle_frame_production;
 
-  scoped_ptr<base::Value> AsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
 };
 
 }  // namespace cc
diff --git a/cc/scheduler/scheduler_state_machine.cc b/cc/scheduler/scheduler_state_machine.cc
index 7070c7a..a37a74a 100644
--- a/cc/scheduler/scheduler_state_machine.cc
+++ b/cc/scheduler/scheduler_state_machine.cc
@@ -5,6 +5,7 @@
 #include "cc/scheduler/scheduler_state_machine.h"
 
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/format_macros.h"
 #include "base/logging.h"
 #include "base/strings/stringprintf.h"
@@ -147,98 +148,96 @@
   return "???";
 }
 
-scoped_ptr<base::Value> SchedulerStateMachine::AsValue() const  {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue);
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+SchedulerStateMachine::AsValue() const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
+  AsValueInto(state);
+  return state;
+}
 
-  scoped_ptr<base::DictionaryValue> major_state(new base::DictionaryValue);
-  major_state->SetString("next_action", ActionToString(NextAction()));
-  major_state->SetString("begin_impl_frame_state",
-                         BeginImplFrameStateToString(begin_impl_frame_state_));
-  major_state->SetString("commit_state", CommitStateToString(commit_state_));
-  major_state->SetString("output_surface_state_",
-                         OutputSurfaceStateToString(output_surface_state_));
-  major_state->SetString(
-      "forced_redraw_state",
-      ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
-  state->Set("major_state", major_state.release());
+void SchedulerStateMachine::AsValueInto(base::debug::TracedValue* state) const {
+  state->BeginDictionary("major_state");
+  state->SetString("next_action", ActionToString(NextAction()));
+  state->SetString("begin_impl_frame_state",
+                   BeginImplFrameStateToString(begin_impl_frame_state_));
+  state->SetString("commit_state", CommitStateToString(commit_state_));
+  state->SetString("output_surface_state_",
+                   OutputSurfaceStateToString(output_surface_state_));
+  state->SetString("forced_redraw_state",
+                   ForcedRedrawOnTimeoutStateToString(forced_redraw_state_));
+  state->EndDictionary();
 
-  scoped_ptr<base::DictionaryValue> timestamps_state(new base::DictionaryValue);
+  state->BeginDictionary("major_timestamps_in_ms");
   base::TimeTicks now = gfx::FrameTime::Now();
-  timestamps_state->SetDouble(
-      "0_interval", begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
-  timestamps_state->SetDouble(
+  state->SetDouble("0_interval",
+                   begin_impl_frame_args_.interval.InMicroseconds() / 1000.0L);
+  state->SetDouble(
       "1_now_to_deadline",
       (begin_impl_frame_args_.deadline - now).InMicroseconds() / 1000.0L);
-  timestamps_state->SetDouble(
+  state->SetDouble(
       "2_frame_time_to_now",
       (now - begin_impl_frame_args_.frame_time).InMicroseconds() / 1000.0L);
-  timestamps_state->SetDouble(
-      "3_frame_time_to_deadline",
-      (begin_impl_frame_args_.deadline - begin_impl_frame_args_.frame_time)
-              .InMicroseconds() /
-          1000.0L);
-  timestamps_state->SetDouble(
-      "4_now", (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
-  timestamps_state->SetDouble(
+  state->SetDouble("3_frame_time_to_deadline",
+                   (begin_impl_frame_args_.deadline -
+                    begin_impl_frame_args_.frame_time).InMicroseconds() /
+                       1000.0L);
+  state->SetDouble("4_now",
+                   (now - base::TimeTicks()).InMicroseconds() / 1000.0L);
+  state->SetDouble(
       "5_frame_time",
       (begin_impl_frame_args_.frame_time - base::TimeTicks()).InMicroseconds() /
           1000.0L);
-  timestamps_state->SetDouble(
+  state->SetDouble(
       "6_deadline",
       (begin_impl_frame_args_.deadline - base::TimeTicks()).InMicroseconds() /
           1000.0L);
-  state->Set("major_timestamps_in_ms", timestamps_state.release());
+  state->EndDictionary();
 
-  scoped_ptr<base::DictionaryValue> minor_state(new base::DictionaryValue);
-  minor_state->SetInteger("commit_count", commit_count_);
-  minor_state->SetInteger("current_frame_number", current_frame_number_);
+  state->BeginDictionary("minor_state");
+  state->SetInteger("commit_count", commit_count_);
+  state->SetInteger("current_frame_number", current_frame_number_);
 
-  minor_state->SetInteger("last_frame_number_animate_performed",
-                          last_frame_number_animate_performed_);
-  minor_state->SetInteger("last_frame_number_swap_performed",
-                          last_frame_number_swap_performed_);
-  minor_state->SetInteger("last_frame_number_swap_requested",
-                          last_frame_number_swap_requested_);
-  minor_state->SetInteger(
-      "last_frame_number_begin_main_frame_sent",
-      last_frame_number_begin_main_frame_sent_);
-  minor_state->SetInteger(
-      "last_frame_number_update_visible_tiles_was_called",
-      last_frame_number_update_visible_tiles_was_called_);
+  state->SetInteger("last_frame_number_animate_performed",
+                    last_frame_number_animate_performed_);
+  state->SetInteger("last_frame_number_swap_performed",
+                    last_frame_number_swap_performed_);
+  state->SetInteger("last_frame_number_swap_requested",
+                    last_frame_number_swap_requested_);
+  state->SetInteger("last_frame_number_begin_main_frame_sent",
+                    last_frame_number_begin_main_frame_sent_);
+  state->SetInteger("last_frame_number_update_visible_tiles_was_called",
+                    last_frame_number_update_visible_tiles_was_called_);
 
-  minor_state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
-  minor_state->SetInteger("consecutive_checkerboard_animations",
-                          consecutive_checkerboard_animations_);
-  minor_state->SetInteger("max_pending_swaps_", max_pending_swaps_);
-  minor_state->SetInteger("pending_swaps_", pending_swaps_);
-  minor_state->SetBoolean("needs_redraw", needs_redraw_);
-  minor_state->SetBoolean("needs_animate_", needs_animate_);
-  minor_state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
-  minor_state->SetBoolean("swap_used_incomplete_tile",
-                          swap_used_incomplete_tile_);
-  minor_state->SetBoolean("needs_commit", needs_commit_);
-  minor_state->SetBoolean("visible", visible_);
-  minor_state->SetBoolean("can_start", can_start_);
-  minor_state->SetBoolean("can_draw", can_draw_);
-  minor_state->SetBoolean("has_pending_tree", has_pending_tree_);
-  minor_state->SetBoolean("pending_tree_is_ready_for_activation",
-                          pending_tree_is_ready_for_activation_);
-  minor_state->SetBoolean("active_tree_needs_first_draw",
-                          active_tree_needs_first_draw_);
-  minor_state->SetBoolean("did_create_and_initialize_first_output_surface",
-                          did_create_and_initialize_first_output_surface_);
-  minor_state->SetBoolean("smoothness_takes_priority",
-                          smoothness_takes_priority_);
-  minor_state->SetBoolean("main_thread_is_in_high_latency_mode",
-                          MainThreadIsInHighLatencyMode());
-  minor_state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
-                          skip_begin_main_frame_to_reduce_latency_);
-  minor_state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
-                          skip_next_begin_main_frame_to_reduce_latency_);
-  minor_state->SetBoolean("continuous_painting", continuous_painting_);
-  state->Set("minor_state", minor_state.release());
-
-  return state.PassAs<base::Value>();
+  state->SetInteger("manage_tiles_funnel", manage_tiles_funnel_);
+  state->SetInteger("consecutive_checkerboard_animations",
+                    consecutive_checkerboard_animations_);
+  state->SetInteger("max_pending_swaps_", max_pending_swaps_);
+  state->SetInteger("pending_swaps_", pending_swaps_);
+  state->SetBoolean("needs_redraw", needs_redraw_);
+  state->SetBoolean("needs_animate_", needs_animate_);
+  state->SetBoolean("needs_manage_tiles", needs_manage_tiles_);
+  state->SetBoolean("swap_used_incomplete_tile", swap_used_incomplete_tile_);
+  state->SetBoolean("needs_commit", needs_commit_);
+  state->SetBoolean("visible", visible_);
+  state->SetBoolean("can_start", can_start_);
+  state->SetBoolean("can_draw", can_draw_);
+  state->SetBoolean("has_pending_tree", has_pending_tree_);
+  state->SetBoolean("pending_tree_is_ready_for_activation",
+                    pending_tree_is_ready_for_activation_);
+  state->SetBoolean("active_tree_needs_first_draw",
+                    active_tree_needs_first_draw_);
+  state->SetBoolean("did_create_and_initialize_first_output_surface",
+                    did_create_and_initialize_first_output_surface_);
+  state->SetBoolean("smoothness_takes_priority", smoothness_takes_priority_);
+  state->SetBoolean("main_thread_is_in_high_latency_mode",
+                    MainThreadIsInHighLatencyMode());
+  state->SetBoolean("skip_begin_main_frame_to_reduce_latency",
+                    skip_begin_main_frame_to_reduce_latency_);
+  state->SetBoolean("skip_next_begin_main_frame_to_reduce_latency",
+                    skip_next_begin_main_frame_to_reduce_latency_);
+  state->SetBoolean("continuous_painting", continuous_painting_);
+  state->EndDictionary();
 }
 
 void SchedulerStateMachine::AdvanceCurrentFrameNumber() {
@@ -810,26 +809,27 @@
 void SchedulerStateMachine::OnBeginImplFrame(const BeginFrameArgs& args) {
   AdvanceCurrentFrameNumber();
   begin_impl_frame_args_ = args;
-  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE) << *AsValue();
+  DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_IDLE)
+      << AsValue()->ToString();
   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING;
 }
 
 void SchedulerStateMachine::OnBeginImplFrameDeadlinePending() {
   DCHECK_EQ(begin_impl_frame_state_,
             BEGIN_IMPL_FRAME_STATE_BEGIN_FRAME_STARTING)
-      << *AsValue();
+      << AsValue()->ToString();
   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME;
 }
 
 void SchedulerStateMachine::OnBeginImplFrameDeadline() {
   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_BEGIN_FRAME)
-      << *AsValue();
+      << AsValue()->ToString();
   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE;
 }
 
 void SchedulerStateMachine::OnBeginImplFrameIdle() {
   DCHECK_EQ(begin_impl_frame_state_, BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE)
-      << *AsValue();
+      << AsValue()->ToString();
   begin_impl_frame_state_ = BEGIN_IMPL_FRAME_STATE_IDLE;
 }
 
@@ -1009,7 +1009,8 @@
 void SchedulerStateMachine::SetNeedsCommit() { needs_commit_ = true; }
 
 void SchedulerStateMachine::NotifyReadyToCommit() {
-  DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED) << *AsValue();
+  DCHECK(commit_state_ == COMMIT_STATE_BEGIN_MAIN_FRAME_STARTED)
+      << AsValue()->ToString();
   commit_state_ = COMMIT_STATE_READY_TO_COMMIT;
 }
 
diff --git a/cc/scheduler/scheduler_state_machine.h b/cc/scheduler/scheduler_state_machine.h
index 0fbdf41..d92a352f 100644
--- a/cc/scheduler/scheduler_state_machine.h
+++ b/cc/scheduler/scheduler_state_machine.h
@@ -16,6 +16,10 @@
 #include "cc/scheduler/scheduler_settings.h"
 
 namespace base {
+namespace debug {
+class ConvertableToTraceForamt;
+class TracedValue;
+}
 class Value;
 }
 
@@ -102,7 +106,8 @@
   };
   static const char* ActionToString(Action action);
 
-  scoped_ptr<base::Value> AsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   Action NextAction() const;
   void UpdateState(Action action);
diff --git a/cc/scheduler/scheduler_state_machine_unittest.cc b/cc/scheduler/scheduler_state_machine_unittest.cc
index c89da2f..1dd9788 100644
--- a/cc/scheduler/scheduler_state_machine_unittest.cc
+++ b/cc/scheduler/scheduler_state_machine_unittest.cc
@@ -4,17 +4,18 @@
 
 #include "cc/scheduler/scheduler_state_machine.h"
 
+#include "base/debug/trace_event.h"
 #include "cc/scheduler/scheduler.h"
 #include "cc/test/begin_frame_args_test.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 #define EXPECT_ACTION_UPDATE_STATE(action)                                   \
-  EXPECT_EQ(action, state.NextAction()) << *state.AsValue();                 \
+  EXPECT_EQ(action, state.NextAction()) << state.AsValue()->ToString();      \
   if (action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE ||   \
       action == SchedulerStateMachine::ACTION_DRAW_AND_SWAP_FORCED) {        \
     EXPECT_EQ(SchedulerStateMachine::BEGIN_IMPL_FRAME_STATE_INSIDE_DEADLINE, \
               state.begin_impl_frame_state())                                \
-        << *state.AsValue();                                                 \
+        << state.AsValue()->ToString();                                      \
   }                                                                          \
   state.UpdateState(action);                                                 \
   if (action == SchedulerStateMachine::ACTION_NONE) {                        \
@@ -690,7 +691,7 @@
       state.SetNeedsCommit();
       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
                 state.NextAction())
-          << *state.AsValue();
+          << state.AsValue()->ToString();
     }
   }
 
@@ -716,16 +717,18 @@
     } else {
       expected_action = SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE;
       EXPECT_EQ(state.NextAction(), SchedulerStateMachine::ACTION_ANIMATE)
-          << *state.AsValue();
+          << state.AsValue()->ToString();
       state.UpdateState(state.NextAction());
     }
 
     // Case 1: needs_commit=false.
-    EXPECT_EQ(state.NextAction(), expected_action) << *state.AsValue();
+    EXPECT_EQ(state.NextAction(), expected_action)
+        << state.AsValue()->ToString();
 
     // Case 2: needs_commit=true.
     state.SetNeedsCommit();
-    EXPECT_EQ(state.NextAction(), expected_action) << *state.AsValue();
+    EXPECT_EQ(state.NextAction(), expected_action)
+        << state.AsValue()->ToString();
   }
 }
 
@@ -757,7 +760,7 @@
       state.SetNeedsCommit();
       EXPECT_NE(SchedulerStateMachine::ACTION_DRAW_AND_SWAP_IF_POSSIBLE,
                 state.NextAction())
-          << *state.AsValue();
+          << state.AsValue()->ToString();
     }
   }
 }
@@ -1655,7 +1658,7 @@
   // main thread will just abort anyway.
   state.SetVisible(false);
   EXPECT_EQ(SchedulerStateMachine::ACTION_NONE, state.NextAction())
-      << *state.AsValue();
+      << state.AsValue()->ToString();
 }
 
 TEST(SchedulerStateMachineTest, ReportIfNotDrawing) {
diff --git a/cc/scheduler/scheduler_unittest.cc b/cc/scheduler/scheduler_unittest.cc
index aa61af7..f416cec 100644
--- a/cc/scheduler/scheduler_unittest.cc
+++ b/cc/scheduler/scheduler_unittest.cc
@@ -6,6 +6,7 @@
 #include <string>
 #include <vector>
 
+#include "base/debug/trace_event.h"
 #include "base/logging.h"
 #include "base/memory/scoped_vector.h"
 #include "base/message_loop/message_loop.h"
@@ -110,7 +111,7 @@
   int num_draws() const { return num_draws_; }
   int num_actions_() const { return static_cast<int>(actions_.size()); }
   const char* Action(int i) const { return actions_[i]; }
-  base::Value& StateForAction(int i) const { return *states_[i]; }
+  std::string StateForAction(int i) const { return states_[i]->ToString(); }
   base::TimeTicks posted_begin_impl_frame_deadline() const {
     return posted_begin_impl_frame_deadline_;
   }
@@ -147,24 +148,24 @@
   // SchedulerClient implementation.
   virtual void SetNeedsBeginFrame(bool enable) OVERRIDE {
     actions_.push_back("SetNeedsBeginFrame");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
     needs_begin_frame_ = enable;
   }
   virtual void WillBeginImplFrame(const BeginFrameArgs& args) OVERRIDE {
     actions_.push_back("WillBeginImplFrame");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual void ScheduledActionSendBeginMainFrame() OVERRIDE {
     actions_.push_back("ScheduledActionSendBeginMainFrame");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual void ScheduledActionAnimate() OVERRIDE {
     actions_.push_back("ScheduledActionAnimate");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual DrawResult ScheduledActionDrawAndSwapIfPossible() OVERRIDE {
     actions_.push_back("ScheduledActionDrawAndSwapIfPossible");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
     num_draws_++;
     DrawResult result =
         draw_will_happen_ ? DRAW_SUCCESS : DRAW_ABORTED_CHECKERBOARD_ANIMATIONS;
@@ -186,30 +187,30 @@
   }
   virtual DrawResult ScheduledActionDrawAndSwapForced() OVERRIDE {
     actions_.push_back("ScheduledActionDrawAndSwapForced");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
     return DRAW_SUCCESS;
   }
   virtual void ScheduledActionCommit() OVERRIDE {
     actions_.push_back("ScheduledActionCommit");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual void ScheduledActionUpdateVisibleTiles() OVERRIDE {
     actions_.push_back("ScheduledActionUpdateVisibleTiles");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
     if (redraw_will_happen_if_update_visible_tiles_happens_)
       scheduler_->SetNeedsRedraw();
   }
   virtual void ScheduledActionActivateSyncTree() OVERRIDE {
     actions_.push_back("ScheduledActionActivateSyncTree");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual void ScheduledActionBeginOutputSurfaceCreation() OVERRIDE {
     actions_.push_back("ScheduledActionBeginOutputSurfaceCreation");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual void ScheduledActionManageTiles() OVERRIDE {
     actions_.push_back("ScheduledActionManageTiles");
-    states_.push_back(scheduler_->AsValue().release());
+    states_.push_back(scheduler_->AsValue());
   }
   virtual void DidAnticipatedDrawTimeChange(base::TimeTicks) OVERRIDE {
     if (log_anticipated_draw_time_change_)
@@ -238,7 +239,7 @@
   bool redraw_will_happen_if_update_visible_tiles_happens_;
   base::TimeTicks posted_begin_impl_frame_deadline_;
   std::vector<const char*> actions_;
-  ScopedVector<base::Value> states_;
+  std::vector<scoped_refptr<base::debug::ConvertableToTraceFormat> > states_;
   scoped_ptr<TestScheduler> scheduler_;
   scoped_refptr<OrderedSimpleTaskRunner> task_runner_;
 };
@@ -1167,7 +1168,7 @@
   for (int i = 0; i < 3; ++i) {
     EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
               client.task_runner().NextPendingTaskDelay().InMicroseconds())
-        << *scheduler->AsValue();
+        << scheduler->AsValue()->ToString();
     client.task_runner().RunPendingTasks();
     EXPECT_GT(client.num_actions_(), actions_so_far);
     EXPECT_STREQ(client.Action(client.num_actions_() - 1),
@@ -1180,7 +1181,7 @@
   for (int i = 0; i < 3; ++i) {
     EXPECT_EQ((frame_args.interval * 2).InMicroseconds(),
               client.task_runner().NextPendingTaskDelay().InMicroseconds())
-        << *scheduler->AsValue();
+        << scheduler->AsValue()->ToString();
     client.task_runner().RunPendingTasks();
     EXPECT_GT(client.num_actions_(), actions_so_far);
     EXPECT_STREQ(client.Action(client.num_actions_() - 1),
diff --git a/cc/test/fake_proxy.cc b/cc/test/fake_proxy.cc
index facf83132..7d0ad47 100644
--- a/cc/test/fake_proxy.cc
+++ b/cc/test/fake_proxy.cc
@@ -36,9 +36,7 @@
 
 bool FakeProxy::CommitPendingForTesting() { return false; }
 
-scoped_ptr<base::Value> FakeProxy::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  return state.PassAs<base::Value>();
+void FakeProxy::AsValueInto(base::debug::TracedValue*) const {
 }
 
 }  // namespace cc
diff --git a/cc/test/fake_proxy.h b/cc/test/fake_proxy.h
index 2a700906..dc04c701 100644
--- a/cc/test/fake_proxy.h
+++ b/cc/test/fake_proxy.h
@@ -43,7 +43,7 @@
   virtual bool SupportsImplScrolling() const OVERRIDE;
   virtual void SetDebugState(const LayerTreeDebugState& debug_state) OVERRIDE {}
   virtual bool CommitPendingForTesting() OVERRIDE;
-  virtual scoped_ptr<base::Value> AsValue() const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* state) const OVERRIDE;
 
   virtual RendererCapabilities& GetRendererCapabilities();
   void SetMaxPartialTextureUpdates(size_t max);
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc
index 2ef991c..ed7472d6 100644
--- a/cc/trees/layer_tree_host.cc
+++ b/cc/trees/layer_tree_host.cc
@@ -12,6 +12,7 @@
 #include "base/bind.h"
 #include "base/command_line.h"
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/message_loop/message_loop.h"
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
@@ -1153,10 +1154,10 @@
                  animate));
 }
 
-scoped_ptr<base::Value> LayerTreeHost::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  state->Set("proxy", proxy_->AsValue().release());
-  return state.PassAs<base::Value>();
+void LayerTreeHost::AsValueInto(base::debug::TracedValue* state) const {
+  state->BeginDictionary("proxy");
+  proxy_->AsValueInto(state);
+  state->EndDictionary();
 }
 
 void LayerTreeHost::AnimateLayers(base::TimeTicks monotonic_time) {
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h
index d7a618a..2fa5b58 100644
--- a/cc/trees/layer_tree_host.h
+++ b/cc/trees/layer_tree_host.h
@@ -257,7 +257,7 @@
   }
 
   // Obtains a thorough dump of the LayerTreeHost as a value.
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* value) const;
 
   bool in_paint_layer_contents() const { return in_paint_layer_contents_; }
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index fdf8e5c..e155be6 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -9,6 +9,7 @@
 
 #include "base/basictypes.h"
 #include "base/containers/hash_tables.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/json/json_writer.h"
 #include "base/metrics/histogram.h"
 #include "base/stl_util.h"
@@ -528,8 +529,8 @@
   }
 }
 
-scoped_ptr<base::Value> LayerTreeHostImpl::FrameData::AsValue() const {
-  scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+void LayerTreeHostImpl::FrameData::AsValueInto(
+    base::debug::TracedValue* value) const {
   value->SetBoolean("contains_incomplete_tile", contains_incomplete_tile);
   value->SetBoolean("has_no_damage", has_no_damage);
 
@@ -539,12 +540,14 @@
   TRACE_EVENT_CATEGORY_GROUP_ENABLED(
       TRACE_DISABLED_BY_DEFAULT("cc.debug.quads"), &quads_enabled);
   if (quads_enabled) {
-    scoped_ptr<base::ListValue> render_pass_list(new base::ListValue());
-    for (size_t i = 0; i < render_passes.size(); ++i)
-      render_pass_list->Append(render_passes[i]->AsValue().release());
-    value->Set("render_passes", render_pass_list.release());
+    value->BeginArray("render_passes");
+    for (size_t i = 0; i < render_passes.size(); ++i) {
+      value->BeginDictionary();
+      render_passes[i]->AsValueInto(value);
+      value->EndDictionary();
+    }
+    value->EndArray();
   }
-  return value.PassAs<base::Value>();
 }
 
 void LayerTreeHostImpl::FrameData::AppendRenderPass(
@@ -1543,7 +1546,7 @@
        TRACE_DISABLED_BY_DEFAULT("devtools.timeline.layers"),
        "cc::LayerTreeHostImpl",
        id_,
-       TracedValue::FromValue(AsValueWithFrame(frame).release()));
+       AsValueWithFrame(frame));
   }
 
   const DrawMode draw_mode = GetDrawMode();
@@ -3169,29 +3172,66 @@
   return gfx::FrameTime::Now();
 }
 
-scoped_ptr<base::Value> LayerTreeHostImpl::AsValueWithFrame(
-    FrameData* frame) const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  if (this->pending_tree_)
-      state->Set("activation_state", ActivationStateAsValue().release());
-  state->Set("device_viewport_size",
-             MathUtil::AsValue(device_viewport_size_).release());
-  if (tile_manager_)
-    state->Set("tiles", tile_manager_->AllTilesAsValue().release());
-  state->Set("active_tree", active_tree_->AsValue().release());
-  if (pending_tree_)
-    state->Set("pending_tree", pending_tree_->AsValue().release());
-  if (frame)
-    state->Set("frame", frame->AsValue().release());
-  return state.PassAs<base::Value>();
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+LayerTreeHostImpl::AsValue() const {
+  return AsValueWithFrame(NULL);
 }
 
-scoped_ptr<base::Value> LayerTreeHostImpl::ActivationStateAsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  state->Set("lthi", TracedValue::CreateIDRef(this).release());
-  if (tile_manager_)
-    state->Set("tile_manager", tile_manager_->BasicStateAsValue().release());
-  return state.PassAs<base::Value>();
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+LayerTreeHostImpl::AsValueWithFrame(FrameData* frame) const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
+  AsValueWithFrameInto(frame, state.get());
+  return state;
+}
+
+void LayerTreeHostImpl::AsValueWithFrameInto(
+    FrameData* frame,
+    base::debug::TracedValue* state) const {
+  if (this->pending_tree_) {
+    state->BeginDictionary("activation_state");
+    ActivationStateAsValueInto(state);
+    state->EndDictionary();
+  }
+  state->BeginDictionary("device_viewport_size");
+  MathUtil::AddToTracedValue(device_viewport_size_, state);
+  state->EndDictionary();
+  if (tile_manager_) {
+    state->BeginArray("tiles");
+    tile_manager_->AllTilesAsValueInto(state);
+    state->EndArray();
+  }
+  state->BeginDictionary("active_tree");
+  active_tree_->AsValueInto(state);
+  state->EndDictionary();
+  if (pending_tree_) {
+    state->BeginDictionary("pending_tree");
+    pending_tree_->AsValueInto(state);
+    state->EndDictionary();
+  }
+  if (frame) {
+    state->BeginDictionary("frame");
+    frame->AsValueInto(state);
+    state->EndDictionary();
+  }
+}
+
+scoped_refptr<base::debug::ConvertableToTraceFormat>
+LayerTreeHostImpl::ActivationStateAsValue() const {
+  scoped_refptr<base::debug::TracedValue> state =
+      new base::debug::TracedValue();
+  ActivationStateAsValueInto(state.get());
+  return state;
+}
+
+void LayerTreeHostImpl::ActivationStateAsValueInto(
+    base::debug::TracedValue* state) const {
+  TracedValue::SetIDRef(this, state, "lthi");
+  if (tile_manager_) {
+    state->BeginDictionary("tile_manager");
+    tile_manager_->BasicStateAsValueInto(state);
+    state->EndDictionary();
+  }
 }
 
 void LayerTreeHostImpl::SetDebugState(
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h
index 7b3c3fd..821028fa 100644
--- a/cc/trees/layer_tree_host_impl.h
+++ b/cc/trees/layer_tree_host_impl.h
@@ -165,7 +165,7 @@
   struct CC_EXPORT FrameData : public RenderPassSink {
     FrameData();
     virtual ~FrameData();
-    scoped_ptr<base::Value> AsValue() const;
+    void AsValueInto(base::debug::TracedValue* value) const;
 
     std::vector<gfx::Rect> occluding_screen_space_rects;
     std::vector<gfx::Rect> non_occluding_screen_space_rects;
@@ -434,9 +434,17 @@
     return begin_impl_frame_interval_;
   }
 
-  scoped_ptr<base::Value> AsValue() const { return AsValueWithFrame(NULL); }
-  scoped_ptr<base::Value> AsValueWithFrame(FrameData* frame) const;
-  scoped_ptr<base::Value> ActivationStateAsValue() const;
+  void AsValueInto(base::debug::TracedValue* value) const {
+    return AsValueWithFrameInto(NULL, value);
+  }
+  void AsValueWithFrameInto(FrameData* frame,
+                            base::debug::TracedValue* value) const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValue() const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> AsValueWithFrame(
+      FrameData* frame) const;
+  scoped_refptr<base::debug::ConvertableToTraceFormat> ActivationStateAsValue()
+      const;
+  void ActivationStateAsValueInto(base::debug::TracedValue* value) const;
 
   bool page_scale_animation_active() const { return !!page_scale_animation_; }
 
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc
index 4b21b14..c054b78 100644
--- a/cc/trees/layer_tree_impl.cc
+++ b/cc/trees/layer_tree_impl.cc
@@ -8,6 +8,7 @@
 #include <set>
 
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "cc/animation/keyframed_animation_curve.h"
 #include "cc/animation/scrollbar_animation_controller.h"
 #include "cc/animation/scrollbar_animation_controller_linear_fade.h"
@@ -820,26 +821,23 @@
   return layer_tree_host_impl_->animation_registrar();
 }
 
-scoped_ptr<base::Value> LayerTreeImpl::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  TracedValue::MakeDictIntoImplicitSnapshot(
-      state.get(), "cc::LayerTreeImpl", this);
+void LayerTreeImpl::AsValueInto(base::debug::TracedValue* state) const {
+  TracedValue::MakeDictIntoImplicitSnapshot(state, "cc::LayerTreeImpl", this);
 
-  state->Set("root_layer", root_layer_->AsValue().release());
+  state->BeginDictionary("root_layer");
+  root_layer_->AsValueInto(state);
+  state->EndDictionary();
 
-  scoped_ptr<base::ListValue> render_surface_layer_list(new base::ListValue());
+  state->BeginArray("render_surface_layer_list");
   typedef LayerIterator<LayerImpl> LayerIteratorType;
   LayerIteratorType end = LayerIteratorType::End(&render_surface_layer_list_);
   for (LayerIteratorType it = LayerIteratorType::Begin(
            &render_surface_layer_list_); it != end; ++it) {
     if (!it.represents_itself())
       continue;
-    render_surface_layer_list->Append(TracedValue::CreateIDRef(*it).release());
+    TracedValue::AppendIDRef(*it, state);
   }
-
-  state->Set("render_surface_layer_list",
-             render_surface_layer_list.release());
-  return state.PassAs<base::Value>();
+  state->EndArray();
 }
 
 void LayerTreeImpl::SetRootLayerScrollOffsetDelegate(
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h
index e602872b..fa6d63a9 100644
--- a/cc/trees/layer_tree_impl.h
+++ b/cc/trees/layer_tree_impl.h
@@ -28,6 +28,12 @@
 }  // namespace BASE_HASH_NAMESPACE
 #endif  // COMPILER
 
+namespace base {
+namespace debug {
+class TracedValue;
+}
+}
+
 namespace cc {
 
 class ContextProvider;
@@ -106,7 +112,7 @@
   const LayerTreeDebugState& debug_state() const;
   float device_scale_factor() const;
   DebugRectHistory* debug_rect_history() const;
-  scoped_ptr<base::Value> AsValue() const;
+  void AsValueInto(base::debug::TracedValue* dict) const;
 
   // Other public methods
   // ---------------------------------------------------------------------------
diff --git a/cc/trees/proxy.cc b/cc/trees/proxy.cc
index 9258355b..3136c65 100644
--- a/cc/trees/proxy.cc
+++ b/cc/trees/proxy.cc
@@ -83,8 +83,4 @@
   DCHECK(IsMainThread());
 }
 
-scoped_ptr<base::Value> Proxy::SchedulerAsValueForTesting() {
-  return make_scoped_ptr(base::Value::CreateNullValue());
-}
-
 }  // namespace cc
diff --git a/cc/trees/proxy.h b/cc/trees/proxy.h
index 7854edc..6100562 100644
--- a/cc/trees/proxy.h
+++ b/cc/trees/proxy.h
@@ -16,7 +16,12 @@
 #include "base/values.h"
 #include "cc/base/cc_export.h"
 
-namespace base { class SingleThreadTaskRunner; }
+namespace base {
+namespace debug {
+class TracedValue;
+}
+class SingleThreadTaskRunner;
+}
 
 namespace gfx {
 class Rect;
@@ -91,13 +96,12 @@
 
   virtual bool SupportsImplScrolling() const = 0;
 
-  virtual scoped_ptr<base::Value> AsValue() const = 0;
+  virtual void AsValueInto(base::debug::TracedValue* value) const = 0;
 
   virtual void SetDebugState(const LayerTreeDebugState& debug_state) = 0;
 
   // Testing hooks
   virtual bool CommitPendingForTesting() = 0;
-  virtual scoped_ptr<base::Value> SchedulerAsValueForTesting();
 
  protected:
   Proxy(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner,
diff --git a/cc/trees/single_thread_proxy.cc b/cc/trees/single_thread_proxy.cc
index 45dbe89..2f67740d 100644
--- a/cc/trees/single_thread_proxy.cc
+++ b/cc/trees/single_thread_proxy.cc
@@ -369,18 +369,15 @@
   }
 }
 
-scoped_ptr<base::Value> SingleThreadProxy::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-  {
-    // The following line casts away const modifiers because it is just
-    // setting debug state. We still want the AsValue() function and its
-    // call chain to be const throughout.
-    DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
+void SingleThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
+  // The following line casts away const modifiers because it is just
+  // setting debug state. We still want the AsValue() function and its
+  // call chain to be const throughout.
+  DebugScopedSetImplThread impl(const_cast<SingleThreadProxy*>(this));
 
-    state->Set("layer_tree_host_impl",
-               layer_tree_host_impl_->AsValue().release());
-  }
-  return state.PassAs<base::Value>();
+  state->BeginDictionary("layer_tree_host_impl");
+  layer_tree_host_impl_->AsValueInto(state);
+  state->EndDictionary();
 }
 
 void SingleThreadProxy::ForceSerializeOnSwapBuffers() {
diff --git a/cc/trees/single_thread_proxy.h b/cc/trees/single_thread_proxy.h
index cd593ac..2b70d705 100644
--- a/cc/trees/single_thread_proxy.h
+++ b/cc/trees/single_thread_proxy.h
@@ -49,7 +49,7 @@
   virtual size_t MaxPartialTextureUpdates() const OVERRIDE;
   virtual void ForceSerializeOnSwapBuffers() OVERRIDE;
   virtual bool SupportsImplScrolling() const OVERRIDE;
-  virtual scoped_ptr<base::Value> AsValue() const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* state) const OVERRIDE;
   virtual bool CommitPendingForTesting() OVERRIDE;
 
   // LayerTreeHostImplClient implementation
diff --git a/cc/trees/thread_proxy.cc b/cc/trees/thread_proxy.cc
index 03e7afc8..b18b93a 100644
--- a/cc/trees/thread_proxy.cc
+++ b/cc/trees/thread_proxy.cc
@@ -10,6 +10,7 @@
 #include "base/auto_reset.h"
 #include "base/bind.h"
 #include "base/debug/trace_event.h"
+#include "base/debug/trace_event_argument.h"
 #include "base/debug/trace_event_synthetic_delay.h"
 #include "cc/base/swap_promise.h"
 #include "cc/debug/benchmark_instrumentation.h"
@@ -1295,28 +1296,27 @@
 
 ThreadProxy::BeginMainFrameAndCommitState::~BeginMainFrameAndCommitState() {}
 
-scoped_ptr<base::Value> ThreadProxy::AsValue() const {
-  scoped_ptr<base::DictionaryValue> state(new base::DictionaryValue());
-
+void ThreadProxy::AsValueInto(base::debug::TracedValue* state) const {
   CompletionEvent completion;
   {
     DebugScopedSetMainThreadBlocked main_thread_blocked(
         const_cast<ThreadProxy*>(this));
+    scoped_refptr<base::debug::TracedValue> state_refptr(state);
     Proxy::ImplThreadTaskRunner()->PostTask(
         FROM_HERE,
         base::Bind(&ThreadProxy::AsValueOnImplThread,
                    impl_thread_weak_ptr_,
                    &completion,
-                   state.get()));
+                   state_refptr));
     completion.Wait();
   }
-  return state.PassAs<base::Value>();
 }
 
 void ThreadProxy::AsValueOnImplThread(CompletionEvent* completion,
-                                      base::DictionaryValue* state) const {
-  state->Set("layer_tree_host_impl",
-             impl().layer_tree_host_impl->AsValue().release());
+                                      base::debug::TracedValue* state) const {
+  state->BeginDictionary("layer_tree_host_impl");
+  impl().layer_tree_host_impl->AsValueInto(state);
+  state->EndDictionary();
   completion->Signal();
 }
 
@@ -1345,30 +1345,6 @@
   request->completion.Signal();
 }
 
-scoped_ptr<base::Value> ThreadProxy::SchedulerAsValueForTesting() {
-  if (IsImplThread())
-    return impl().scheduler->AsValue().Pass();
-
-  SchedulerStateRequest scheduler_state_request;
-  {
-    DebugScopedSetMainThreadBlocked main_thread_blocked(this);
-    Proxy::ImplThreadTaskRunner()->PostTask(
-        FROM_HERE,
-        base::Bind(&ThreadProxy::SchedulerAsValueOnImplThreadForTesting,
-                   impl_thread_weak_ptr_,
-                   &scheduler_state_request));
-    scheduler_state_request.completion.Wait();
-  }
-  return scheduler_state_request.state.Pass();
-}
-
-void ThreadProxy::SchedulerAsValueOnImplThreadForTesting(
-    SchedulerStateRequest* request) {
-  DCHECK(IsImplThread());
-  request->state = impl().scheduler->AsValue();
-  request->completion.Signal();
-}
-
 void ThreadProxy::RenewTreePriority() {
   DCHECK(IsImplThread());
   bool smoothness_takes_priority =
diff --git a/cc/trees/thread_proxy.h b/cc/trees/thread_proxy.h
index a28068e6a..1bea3bf 100644
--- a/cc/trees/thread_proxy.h
+++ b/cc/trees/thread_proxy.h
@@ -173,9 +173,8 @@
   virtual void ForceSerializeOnSwapBuffers() OVERRIDE;
   virtual bool SupportsImplScrolling() const OVERRIDE;
   virtual void SetDebugState(const LayerTreeDebugState& debug_state) OVERRIDE;
-  virtual scoped_ptr<base::Value> AsValue() const OVERRIDE;
+  virtual void AsValueInto(base::debug::TracedValue* value) const OVERRIDE;
   virtual bool CommitPendingForTesting() OVERRIDE;
-  virtual scoped_ptr<base::Value> SchedulerAsValueForTesting() OVERRIDE;
 
   // LayerTreeHostImplClient implementation
   virtual void UpdateRendererCapabilitiesOnImplThread() OVERRIDE;
@@ -277,9 +276,8 @@
   void ForceSerializeOnSwapBuffersOnImplThread(CompletionEvent* completion);
   void CheckOutputSurfaceStatusOnImplThread();
   void CommitPendingOnImplThreadForTesting(CommitPendingRequest* request);
-  void SchedulerAsValueOnImplThreadForTesting(SchedulerStateRequest* request);
   void AsValueOnImplThread(CompletionEvent* completion,
-                           base::DictionaryValue* state) const;
+                           base::debug::TracedValue* state) const;
   void SetSwapUsedIncompleteTileOnImplThread(bool used_incomplete_tile);
   void MainThreadHasStoppedFlingingOnImplThread();
   void SetInputThrottledUntilCommitOnImplThread(bool is_throttled);