1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/renderer/benchmarking_extension.h"
6
7#include "base/command_line.h"
8#include "base/metrics/stats_table.h"
9#include "base/time/time.h"
10#include "content/public/common/content_switches.h"
11#include "content/public/renderer/render_thread.h"
12#include "v8/include/v8.h"
13
14const char kBenchmarkingExtensionName[] = "v8/Benchmarking";
15
16namespace extensions_v8 {
17
18class BenchmarkingWrapper : public v8::Extension {
19 public:
20  BenchmarkingWrapper() :
21      v8::Extension(kBenchmarkingExtensionName,
22        "if (typeof(chrome) == 'undefined') {"
23        "  chrome = {};"
24        "};"
25        "if (typeof(chrome.benchmarking) == 'undefined') {"
26        "  chrome.benchmarking = {};"
27        "};"
28        "chrome.benchmarking.counter = function(name) {"
29        "  native function GetCounter();"
30        "  return GetCounter(name);"
31        "};"
32        "chrome.benchmarking.isSingleProcess = function() {"
33        "  native function IsSingleProcess();"
34        "  return IsSingleProcess();"
35        "};"
36        "chrome.Interval = function() {"
37        "  var start_ = 0;"
38        "  var stop_ = 0;"
39        "  native function HiResTime();"
40        "  this.start = function() {"
41        "    stop_ = 0;"
42        "    start_ = HiResTime();"
43        "  };"
44        "  this.stop = function() {"
45        "    stop_ = HiResTime();"
46        "    if (start_ == 0)"
47        "      stop_ = 0;"
48        "  };"
49        "  this.microseconds = function() {"
50        "    var stop = stop_;"
51        "    if (stop == 0 && start_ != 0)"
52        "      stop = HiResTime();"
53        "    return Math.ceil(stop - start_);"
54        "  };"
55        "}"
56        ) {}
57
58  virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
59      v8::Handle<v8::String> name) OVERRIDE {
60    if (name->Equals(v8::String::New("GetCounter"))) {
61      return v8::FunctionTemplate::New(GetCounter);
62    } else if (name->Equals(v8::String::New("IsSingleProcess"))) {
63      return v8::FunctionTemplate::New(IsSingleProcess);
64    } else if (name->Equals(v8::String::New("HiResTime"))) {
65      return v8::FunctionTemplate::New(HiResTime);
66    }
67
68    return v8::Handle<v8::FunctionTemplate>();
69  }
70
71  static void GetCounter(const v8::FunctionCallbackInfo<v8::Value>& args) {
72    if (!args.Length() || !args[0]->IsString() || !base::StatsTable::current())
73      return;
74
75    // Extract the name argument
76    char name[256];
77    name[0] = 'c';
78    name[1] = ':';
79    args[0]->ToString()->WriteUtf8(&name[2], sizeof(name) - 3);
80
81    int counter = base::StatsTable::current()->GetCounterValue(name);
82    args.GetReturnValue().Set(static_cast<int32_t>(counter));
83  }
84
85  static void IsSingleProcess(const v8::FunctionCallbackInfo<v8::Value>& args) {
86    args.GetReturnValue().Set(
87       CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
88  }
89
90  static void HiResTime(const v8::FunctionCallbackInfo<v8::Value>& args) {
91    args.GetReturnValue().Set(
92        static_cast<double>(base::TimeTicks::HighResNow().ToInternalValue()));
93  }
94};
95
96v8::Extension* BenchmarkingExtension::Get() {
97  return new BenchmarkingWrapper();
98}
99
100}  // namespace extensions_v8
101