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