Home | History | Annotate | Download | only in renderer
      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 
     14 const char kBenchmarkingExtensionName[] = "v8/Benchmarking";
     15 
     16 namespace extensions_v8 {
     17 
     18 class 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.counterForRenderer = function(name) {"
     33         "  native function GetCounterForRenderer();"
     34         "  return GetCounterForRenderer(name);"
     35         "};"
     36         "chrome.benchmarking.isSingleProcess = function() {"
     37         "  native function IsSingleProcess();"
     38         "  return IsSingleProcess();"
     39         "};"
     40         "chrome.Interval = function() {"
     41         "  var start_ = 0;"
     42         "  var stop_ = 0;"
     43         "  native function HiResTime();"
     44         "  this.start = function() {"
     45         "    stop_ = 0;"
     46         "    start_ = HiResTime();"
     47         "  };"
     48         "  this.stop = function() {"
     49         "    stop_ = HiResTime();"
     50         "    if (start_ == 0)"
     51         "      stop_ = 0;"
     52         "  };"
     53         "  this.microseconds = function() {"
     54         "    var stop = stop_;"
     55         "    if (stop == 0 && start_ != 0)"
     56         "      stop = HiResTime();"
     57         "    return Math.ceil(stop - start_);"
     58         "  };"
     59         "}"
     60         ) {}
     61 
     62   virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
     63       v8::Isolate* isolate,
     64       v8::Handle<v8::String> name) OVERRIDE {
     65     if (name->Equals(v8::String::NewFromUtf8(isolate, "GetCounter"))) {
     66       return v8::FunctionTemplate::New(isolate, GetCounter);
     67     } else if (name->Equals(
     68                    v8::String::NewFromUtf8(isolate, "GetCounterForRenderer"))) {
     69       return v8::FunctionTemplate::New(isolate, GetCounterForRenderer);
     70     } else if (name->Equals(
     71                    v8::String::NewFromUtf8(isolate, "IsSingleProcess"))) {
     72       return v8::FunctionTemplate::New(isolate, IsSingleProcess);
     73     } else if (name->Equals(v8::String::NewFromUtf8(isolate, "HiResTime"))) {
     74       return v8::FunctionTemplate::New(isolate, HiResTime);
     75     }
     76 
     77     return v8::Handle<v8::FunctionTemplate>();
     78   }
     79 
     80   /*
     81    * Extract the counter name from arguments.
     82    */
     83   static void ExtractCounterName(
     84       const v8::FunctionCallbackInfo<v8::Value>& args,
     85       char* name,
     86       size_t capacity) {
     87     name[0] = 'c';
     88     name[1] = ':';
     89     args[0]->ToString()->WriteUtf8(&name[2], capacity - 3);
     90   }
     91 
     92   static void GetCounter(const v8::FunctionCallbackInfo<v8::Value>& args) {
     93     if (!args.Length() || !args[0]->IsString() || !base::StatsTable::current())
     94       return;
     95 
     96     char name[256];
     97     ExtractCounterName(args, name, sizeof(name));
     98     int counter = base::StatsTable::current()->GetCounterValue(name);
     99     args.GetReturnValue().Set(static_cast<int32_t>(counter));
    100   }
    101 
    102   static void GetCounterForRenderer(
    103       const v8::FunctionCallbackInfo<v8::Value>& args) {
    104     if (!args.Length() || !args[0]->IsString() || !base::StatsTable::current())
    105       return;
    106 
    107     char name[256];
    108     ExtractCounterName(args, name, sizeof(name));
    109     int counter = base::StatsTable::current()->GetCounterValue(
    110         name,
    111         base::GetCurrentProcId());
    112     args.GetReturnValue().Set(static_cast<int32_t>(counter));
    113   }
    114 
    115   static void IsSingleProcess(const v8::FunctionCallbackInfo<v8::Value>& args) {
    116     args.GetReturnValue().Set(
    117        CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess));
    118   }
    119 
    120   static void HiResTime(const v8::FunctionCallbackInfo<v8::Value>& args) {
    121     args.GetReturnValue().Set(
    122         static_cast<double>(base::TimeTicks::HighResNow().ToInternalValue()));
    123   }
    124 };
    125 
    126 v8::Extension* BenchmarkingExtension::Get() {
    127   return new BenchmarkingWrapper();
    128 }
    129 
    130 }  // namespace extensions_v8
    131