Home | History | Annotate | Download | only in tools
      1 // Copyright 2013 the V8 project authors. All rights reserved.
      2 // Redistribution and use in source and binary forms, with or without
      3 // modification, are permitted provided that the following conditions are
      4 // met:
      5 //
      6 //     * Redistributions of source code must retain the above copyright
      7 //       notice, this list of conditions and the following disclaimer.
      8 //     * Redistributions in binary form must reproduce the above
      9 //       copyright notice, this list of conditions and the following
     10 //       disclaimer in the documentation and/or other materials provided
     11 //       with the distribution.
     12 //     * Neither the name of Google Inc. nor the names of its
     13 //       contributors may be used to endorse or promote products derived
     14 //       from this software without specific prior written permission.
     15 //
     16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 #include <assert.h>
     29 #include <string.h>
     30 #include <stdio.h>
     31 #include <stdlib.h>
     32 #include <string>
     33 #include <vector>
     34 #include "src/v8.h"
     35 
     36 #include "src/api.h"
     37 #include "src/messages.h"
     38 #include "src/platform.h"
     39 #include "src/runtime.h"
     40 #include "src/scanner-character-streams.h"
     41 #include "src/scopeinfo.h"
     42 #include "tools/shell-utils.h"
     43 #include "src/string-stream.h"
     44 #include "src/scanner.h"
     45 
     46 
     47 using namespace v8::internal;
     48 
     49 
     50 class BaselineScanner {
     51  public:
     52   BaselineScanner(const char* fname,
     53                   Isolate* isolate,
     54                   Encoding encoding,
     55                   ElapsedTimer* timer,
     56                   int repeat)
     57       : stream_(NULL) {
     58     int length = 0;
     59     source_ = ReadFileAndRepeat(fname, &length, repeat);
     60     unicode_cache_ = new UnicodeCache();
     61     scanner_ = new Scanner(unicode_cache_);
     62     switch (encoding) {
     63       case UTF8:
     64         stream_ = new Utf8ToUtf16CharacterStream(source_, length);
     65         break;
     66       case UTF16: {
     67         Handle<String> result = isolate->factory()->NewStringFromTwoByte(
     68             Vector<const uint16_t>(
     69                 reinterpret_cast<const uint16_t*>(source_),
     70                 length / 2)).ToHandleChecked();
     71         stream_ =
     72             new GenericStringUtf16CharacterStream(result, 0, result->length());
     73         break;
     74       }
     75       case LATIN1: {
     76         Handle<String> result = isolate->factory()->NewStringFromOneByte(
     77             Vector<const uint8_t>(source_, length)).ToHandleChecked();
     78         stream_ =
     79             new GenericStringUtf16CharacterStream(result, 0, result->length());
     80         break;
     81       }
     82     }
     83     timer->Start();
     84     scanner_->Initialize(stream_);
     85   }
     86 
     87   ~BaselineScanner() {
     88     delete scanner_;
     89     delete stream_;
     90     delete unicode_cache_;
     91     delete[] source_;
     92   }
     93 
     94   Token::Value Next(int* beg_pos, int* end_pos) {
     95     Token::Value res = scanner_->Next();
     96     *beg_pos = scanner_->location().beg_pos;
     97     *end_pos = scanner_->location().end_pos;
     98     return res;
     99   }
    100 
    101  private:
    102   UnicodeCache* unicode_cache_;
    103   Scanner* scanner_;
    104   const byte* source_;
    105   BufferedUtf16CharacterStream* stream_;
    106 };
    107 
    108 
    109 struct TokenWithLocation {
    110   Token::Value value;
    111   size_t beg;
    112   size_t end;
    113   TokenWithLocation() : value(Token::ILLEGAL), beg(0), end(0) { }
    114   TokenWithLocation(Token::Value value, size_t beg, size_t end) :
    115       value(value), beg(beg), end(end) { }
    116   bool operator==(const TokenWithLocation& other) {
    117     return value == other.value && beg == other.beg && end == other.end;
    118   }
    119   bool operator!=(const TokenWithLocation& other) {
    120     return !(*this == other);
    121   }
    122   void Print(const char* prefix) const {
    123     printf("%s %11s at (%d, %d)\n",
    124            prefix, Token::Name(value),
    125            static_cast<int>(beg), static_cast<int>(end));
    126   }
    127 };
    128 
    129 
    130 TimeDelta RunBaselineScanner(const char* fname,
    131                              Isolate* isolate,
    132                              Encoding encoding,
    133                              bool dump_tokens,
    134                              std::vector<TokenWithLocation>* tokens,
    135                              int repeat) {
    136   ElapsedTimer timer;
    137   BaselineScanner scanner(fname, isolate, encoding, &timer, repeat);
    138   Token::Value token;
    139   int beg, end;
    140   do {
    141     token = scanner.Next(&beg, &end);
    142     if (dump_tokens) {
    143       tokens->push_back(TokenWithLocation(token, beg, end));
    144     }
    145   } while (token != Token::EOS);
    146   return timer.Elapsed();
    147 }
    148 
    149 
    150 void PrintTokens(const char* name,
    151                  const std::vector<TokenWithLocation>& tokens) {
    152   printf("No of tokens: %d\n",
    153          static_cast<int>(tokens.size()));
    154   printf("%s:\n", name);
    155   for (size_t i = 0; i < tokens.size(); ++i) {
    156     tokens[i].Print("=>");
    157   }
    158 }
    159 
    160 
    161 TimeDelta ProcessFile(
    162     const char* fname,
    163     Encoding encoding,
    164     Isolate* isolate,
    165     bool print_tokens,
    166     int repeat) {
    167   if (print_tokens) {
    168     printf("Processing file %s\n", fname);
    169   }
    170   HandleScope handle_scope(isolate);
    171   std::vector<TokenWithLocation> baseline_tokens;
    172   TimeDelta baseline_time;
    173   baseline_time = RunBaselineScanner(
    174       fname, isolate, encoding, print_tokens,
    175       &baseline_tokens, repeat);
    176   if (print_tokens) {
    177     PrintTokens("Baseline", baseline_tokens);
    178   }
    179   return baseline_time;
    180 }
    181 
    182 
    183 int main(int argc, char* argv[]) {
    184   v8::V8::InitializeICU();
    185   v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
    186   Encoding encoding = LATIN1;
    187   bool print_tokens = false;
    188   std::vector<std::string> fnames;
    189   std::string benchmark;
    190   int repeat = 1;
    191   for (int i = 0; i < argc; ++i) {
    192     if (strcmp(argv[i], "--latin1") == 0) {
    193       encoding = LATIN1;
    194     } else if (strcmp(argv[i], "--utf8") == 0) {
    195       encoding = UTF8;
    196     } else if (strcmp(argv[i], "--utf16") == 0) {
    197       encoding = UTF16;
    198     } else if (strcmp(argv[i], "--print-tokens") == 0) {
    199       print_tokens = true;
    200     } else if (strncmp(argv[i], "--benchmark=", 12) == 0) {
    201       benchmark = std::string(argv[i]).substr(12);
    202     } else if (strncmp(argv[i], "--repeat=", 9) == 0) {
    203       std::string repeat_str = std::string(argv[i]).substr(9);
    204       repeat = atoi(repeat_str.c_str());
    205     } else if (i > 0 && argv[i][0] != '-') {
    206       fnames.push_back(std::string(argv[i]));
    207     }
    208   }
    209   v8::Isolate* isolate = v8::Isolate::New();
    210   {
    211     v8::Isolate::Scope isolate_scope(isolate);
    212     v8::HandleScope handle_scope(isolate);
    213     v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(isolate);
    214     v8::Local<v8::Context> context = v8::Context::New(isolate, NULL, global);
    215     ASSERT(!context.IsEmpty());
    216     {
    217       v8::Context::Scope scope(context);
    218       double baseline_total = 0;
    219       for (size_t i = 0; i < fnames.size(); i++) {
    220         TimeDelta time;
    221         time = ProcessFile(fnames[i].c_str(), encoding,
    222                            reinterpret_cast<Isolate*>(isolate), print_tokens,
    223                            repeat);
    224         baseline_total += time.InMillisecondsF();
    225       }
    226       if (benchmark.empty()) benchmark = "Baseline";
    227       printf("%s(RunTime): %.f ms\n", benchmark.c_str(), baseline_total);
    228     }
    229   }
    230   v8::V8::Dispose();
    231   return 0;
    232 }
    233