Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(203)

Side by Side Diff: test/cctest/test-log.cc

Issue 113641: Fix test-log/EquivalenceOfLoggingAndTraversal for the snapshot case. (Closed)
Patch Set: Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 the V8 project authors. All rights reserved.
2 // 2 //
3 // Tests of logging functions from log.h 3 // Tests of logging functions from log.h
4 4
5 #ifdef ENABLE_LOGGING_AND_PROFILING 5 #ifdef ENABLE_LOGGING_AND_PROFILING
6 6
7 #include "v8.h" 7 #include "v8.h"
8 8
9 #include "log.h" 9 #include "log.h"
10 #include "cctest.h" 10 #include "cctest.h"
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 123
124 static bool Consume(const char* str, char** buf) { 124 static bool Consume(const char* str, char** buf) {
125 if (IsStringEqualTo(str, *buf)) { 125 if (IsStringEqualTo(str, *buf)) {
126 *buf += strlen(str); 126 *buf += strlen(str);
127 return true; 127 return true;
128 } 128 }
129 return false; 129 return false;
130 } 130 }
131 131
132 132
133 static void ParseAddress(char* start, Address* min_addr, Address* max_addr) {
134 Address addr = reinterpret_cast<Address>(strtoul(start, NULL, 16)); // NOLINT
135 if (addr < *min_addr) *min_addr = addr;
136 if (addr > *max_addr) *max_addr = addr;
137 }
138
139
140 static Address ConsumeAddress(
141 char** start, Address min_addr, Address max_addr) {
142 char* end_ptr;
143 Address addr =
144 reinterpret_cast<Address>(strtoul(*start, &end_ptr, 16)); // NOLINT
145 CHECK_GE(addr, min_addr);
146 CHECK_GE(max_addr, addr);
147 *start = end_ptr;
148 return addr;
149 }
150
151
152 namespace { 133 namespace {
153 134
154 // A code entity is a pointer to a position of code-creation event in buffer log 135 // A code entity is a pointer to a position of code-creation event in buffer log
155 // offset to a point where entity size begins, i.e.: '255,"func"\n'. This makes 136 // offset to a point where entity size begins, i.e.: '255,"func"\n'. This makes
156 // comparing code entities pretty easy. 137 // comparing code entities pretty easy.
157 typedef char* CodeEntityInfo; 138 typedef char* CodeEntityInfo;
158 139
140 class Interval {
141 public:
142 Interval()
143 : min_addr(reinterpret_cast<Address>(-1)),
144 max_addr(reinterpret_cast<Address>(0)), next(NULL) {}
145
146 ~Interval() { delete next; }
147
148 size_t Length() {
149 size_t result = max_addr - min_addr + 1;
150 if (next != NULL) result += next->Length();
151 return result;
152 }
153
154 void CloneFrom(Interval* src) {
155 while (src != NULL) {
156 RegisterAddress(src->min_addr);
157 RegisterAddress(src->max_addr);
158 src = src->next;
159 }
160 }
161
162 bool Contains(Address addr) {
163 if (min_addr <= addr && addr <= max_addr) {
164 return true;
165 }
166 if (next != NULL) return next->Contains(addr);
Søren Thygesen Gjesse 2009/05/25 08:45:53 Please add {}'s for one statement if. Maybe use an
Mikhail Naganov 2009/05/25 09:32:10 Usually, there is no 'next' at all. 'next' appears
167 return false;
168 }
169
170 size_t GetIndex(Address addr) {
171 if (min_addr <= addr && addr <= max_addr) {
172 return addr - min_addr;
173 }
174 CHECK_NE(NULL, next);
175 return (max_addr - min_addr + 1) + next->GetIndex(addr);
176 }
177
178 Address GetMinAddr() {
179 return next == NULL ? min_addr : i::Min(min_addr, next->GetMinAddr());
180 }
181
182 Address GetMaxAddr() {
183 return next == NULL ? max_addr : i::Max(max_addr, next->GetMaxAddr());
184 }
185
186 void RegisterAddress(Address addr) {
187 if (min_addr == reinterpret_cast<Address>(-1)
188 || (size_t)(addr > min_addr ?
189 addr - min_addr : min_addr - addr) < MAX_DELTA) {
190 if (addr < min_addr) min_addr = addr;
191 if (addr > max_addr) max_addr = addr;
192 } else {
193 if (next == NULL) next = new Interval();
194 next->RegisterAddress(addr);
195 }
196 }
197
198 Address raw_min_addr() { return min_addr; }
199
200 Address raw_max_addr() { return max_addr; }
201
202 Interval* get_next() { return next; }
203
204 private:
205 static const size_t MAX_DELTA = 0x100000;
206 Address min_addr;
Søren Thygesen Gjesse 2009/05/25 08:45:53 Missing trailing underscores?
Mikhail Naganov 2009/05/25 09:32:10 Done.
207 Address max_addr;
208 Interval* next;
209 };
210
211
159 // A structure used to return log parsing results. 212 // A structure used to return log parsing results.
160 class ParseLogResult { 213 class ParseLogResult {
161 public: 214 public:
162 ParseLogResult() 215 ParseLogResult()
163 : min_addr(reinterpret_cast<Address>(-1)), 216 : entities_map(NULL), entities(NULL),
164 max_addr(reinterpret_cast<Address>(0)),
165 entities_map(NULL), entities(NULL),
166 max_entities(0) {} 217 max_entities(0) {}
167 218
168 ~ParseLogResult() { 219 ~ParseLogResult() {
169 // See allocation code below. 220 i::DeleteArray(entities_map);
170 if (entities_map != NULL) {
171 i::DeleteArray(entities_map - 1);
172 }
173 i::DeleteArray(entities); 221 i::DeleteArray(entities);
174 } 222 }
175 223
176 void AllocateEntities() { 224 void AllocateEntities() {
177 // Make sure that the test doesn't operate on a bogus log. 225 // Make sure that the test doesn't operate on a bogus log.
178 CHECK_GT(max_entities, 0); 226 CHECK_GT(max_entities, 0);
179 CHECK_GT(min_addr, 0); 227 CHECK_GT(bounds.GetMinAddr(), 0);
180 CHECK_GT(max_addr, min_addr); 228 CHECK_GT(bounds.GetMaxAddr(), bounds.GetMinAddr());
181 229
182 entities = i::NewArray<CodeEntityInfo>(max_entities); 230 entities = i::NewArray<CodeEntityInfo>(max_entities);
183 for (int i = 0; i < max_entities; ++i) { 231 for (int i = 0; i < max_entities; ++i) {
184 entities[i] = NULL; 232 entities[i] = NULL;
185 } 233 }
186 // We're adding fake items at [-1] and [size + 1] to simplify 234 const size_t map_length = bounds.Length();
187 // comparison code.
188 const int map_length = max_addr - min_addr + 1 + 2; // 2 fakes.
189 entities_map = i::NewArray<int>(map_length); 235 entities_map = i::NewArray<int>(map_length);
190 for (int i = 0; i < map_length; ++i) { 236 for (size_t i = 0; i < map_length; ++i) {
191 entities_map[i] = -1; 237 entities_map[i] = -1;
192 } 238 }
193 entities_map += 1; // Hide the -1 item, this is compensated on delete.
194 } 239 }
195 240
196 // Minimal code entity address. 241 bool HasIndexForAddress(Address addr) {
197 Address min_addr; 242 return bounds.Contains(addr);
198 // Maximal code entity address. 243 }
199 Address max_addr; 244
200 // Memory map of entities start addresses. Biased by min_addr. 245 size_t GetIndexForAddress(Address addr) {
246 CHECK(HasIndexForAddress(addr));
247 return bounds.GetIndex(addr);
248 }
249
250 CodeEntityInfo GetEntity(Address addr) {
251 if (HasIndexForAddress(addr)) {
252 size_t idx = GetIndexForAddress(addr);
253 int item = entities_map[idx];
254 return item != -1 ? entities[item] : NULL;
255 }
256 return NULL;
257 }
258
259 void ParseAddress(char* start) {
260 Address addr =
261 reinterpret_cast<Address>(strtoul(start, NULL, 16)); // NOLINT
262 bounds.RegisterAddress(addr);
263 }
264
265 Address ConsumeAddress(char** start) {
266 char* end_ptr;
267 Address addr =
268 reinterpret_cast<Address>(strtoul(*start, &end_ptr, 16)); // NOLINT
269 CHECK(HasIndexForAddress(addr));
270 *start = end_ptr;
271 return addr;
272 }
273
274 Interval bounds;
Søren Thygesen Gjesse 2009/05/25 08:45:53 Missing trailing underscores?
Mikhail Naganov 2009/05/25 09:32:10 Um, actually encapsulation is sort of leaking here
275 // Memory map of entities start addresses. Biased by bounds.min_addr.
201 int* entities_map; 276 int* entities_map;
202 // An array of code entities. 277 // An array of code entities.
203 CodeEntityInfo* entities; 278 CodeEntityInfo* entities;
204 // Maximal entities count. Actual entities count can be lower, 279 // Maximal entities count. Actual entities count can be lower,
205 // empty entity slots are pointing to NULL. 280 // empty entity slots are pointing to NULL.
206 int max_entities; 281 int max_entities;
207 }; 282 };
208 283
209 } // namespace 284 } // namespace
210 285
(...skipping 25 matching lines...) Expand all
236 } else if (Consume(code_move, &start)) { 311 } else if (Consume(code_move, &start)) {
237 block_move(start, end, result); 312 block_move(start, end, result);
238 } 313 }
239 while (start < end && *start != '\n') ++start; 314 while (start < end && *start != '\n') ++start;
240 ++start; 315 ++start;
241 } 316 }
242 } 317 }
243 318
244 319
245 static void Pass1CodeCreation(char* start, char* end, ParseLogResult* result) { 320 static void Pass1CodeCreation(char* start, char* end, ParseLogResult* result) {
246 ParseAddress(start, &result->min_addr, &result->max_addr); 321 result->ParseAddress(start);
247 ++result->max_entities; 322 ++result->max_entities;
248 } 323 }
249 324
250 325
251 static void Pass1CodeDelete(char* start, char* end, ParseLogResult* result) { 326 static void Pass1CodeDelete(char* start, char* end, ParseLogResult* result) {
252 ParseAddress(start, &result->min_addr, &result->max_addr); 327 result->ParseAddress(start);
253 } 328 }
254 329
255 330
256 static void Pass1CodeMove(char* start, char* end, ParseLogResult* result) { 331 static void Pass1CodeMove(char* start, char* end, ParseLogResult* result) {
332 result->ParseAddress(start);
257 // Skip old address. 333 // Skip old address.
258 while (start < end && *start != ',') ++start; 334 while (start < end && *start != ',') ++start;
259 CHECK_GT(end, start); 335 CHECK_GT(end, start);
260 ++start; // Skip ','. 336 ++start; // Skip ','.
261 ParseAddress(start, &result->min_addr, &result->max_addr); 337 result->ParseAddress(start);
262 } 338 }
263 339
264 340
265 static void Pass2CodeCreation(char* start, char* end, ParseLogResult* result) { 341 static void Pass2CodeCreation(char* start, char* end, ParseLogResult* result) {
266 Address addr = ConsumeAddress(&start, result->min_addr, result->max_addr); 342 Address addr = result->ConsumeAddress(&start);
267 CHECK_GT(end, start); 343 CHECK_GT(end, start);
268 ++start; // Skip ','. 344 ++start; // Skip ','.
269 345
270 int idx = addr - result->min_addr; 346 size_t idx = result->GetIndexForAddress(addr);
271 result->entities_map[idx] = -1; 347 result->entities_map[idx] = -1;
272 for (int i = 0; i < result->max_entities; ++i) { 348 for (int i = 0; i < result->max_entities; ++i) {
273 // Find an empty slot and fill it. 349 // Find an empty slot and fill it.
274 if (result->entities[i] == NULL) { 350 if (result->entities[i] == NULL) {
275 result->entities[i] = start; 351 result->entities[i] = start;
276 result->entities_map[idx] = i; 352 result->entities_map[idx] = i;
277 break; 353 break;
278 } 354 }
279 } 355 }
280 // Make sure that a slot was found. 356 // Make sure that a slot was found.
281 CHECK_GE(result->entities_map[idx], 0); 357 CHECK_GE(result->entities_map[idx], 0);
282 } 358 }
283 359
284 360
285 static void Pass2CodeDelete(char* start, char* end, ParseLogResult* result) { 361 static void Pass2CodeDelete(char* start, char* end, ParseLogResult* result) {
286 Address addr = ConsumeAddress(&start, result->min_addr, result->max_addr); 362 Address addr = result->ConsumeAddress(&start);
287 int idx = addr - result->min_addr; 363 size_t idx = result->GetIndexForAddress(addr);
288 // There can be code deletes that are not related to JS code. 364 // There can be code deletes that are not related to JS code.
289 if (result->entities_map[idx] >= 0) { 365 if (result->entities_map[idx] >= 0) {
290 result->entities[result->entities_map[idx]] = NULL; 366 result->entities[result->entities_map[idx]] = NULL;
291 result->entities_map[idx] = -1; 367 result->entities_map[idx] = -1;
292 } 368 }
293 } 369 }
294 370
295 371
296 static void Pass2CodeMove(char* start, char* end, ParseLogResult* result) { 372 static void Pass2CodeMove(char* start, char* end, ParseLogResult* result) {
297 Address from_addr = ConsumeAddress( 373 Address from_addr = result->ConsumeAddress(&start);
298 &start, result->min_addr, result->max_addr);
299 CHECK_GT(end, start); 374 CHECK_GT(end, start);
300 ++start; // Skip ','. 375 ++start; // Skip ','.
301 Address to_addr = ConsumeAddress(&start, result->min_addr, result->max_addr); 376 Address to_addr = result->ConsumeAddress(&start);
302 CHECK_GT(end, start); 377 CHECK_GT(end, start);
303 378
304 int from_idx = from_addr - result->min_addr; 379 size_t from_idx = result->GetIndexForAddress(from_addr);
305 int to_idx = to_addr - result->min_addr; 380 size_t to_idx = result->GetIndexForAddress(to_addr);
306 // There can be code moves that are not related to JS code. 381 // There can be code moves that are not related to JS code.
307 if (from_idx != to_idx && result->entities_map[from_idx] >= 0) { 382 if (from_idx != to_idx && result->entities_map[from_idx] >= 0) {
308 CHECK_EQ(-1, result->entities_map[to_idx]); 383 CHECK_EQ(-1, result->entities_map[to_idx]);
309 result->entities_map[to_idx] = result->entities_map[from_idx]; 384 result->entities_map[to_idx] = result->entities_map[from_idx];
310 result->entities_map[from_idx] = -1; 385 result->entities_map[from_idx] = -1;
311 }; 386 };
312 } 387 }
313 388
314 389
315 static void ParseLog(char* start, char* end, ParseLogResult* result) { 390 static void ParseLog(char* start, char* end, ParseLogResult* result) {
316 // Pass 1: Calculate boundaries of addresses and entities count. 391 // Pass 1: Calculate boundaries of addresses and entities count.
317 ParserCycle(start, end, result, 392 ParserCycle(start, end, result,
318 Pass1CodeCreation, Pass1CodeDelete, Pass1CodeMove); 393 Pass1CodeCreation, Pass1CodeDelete, Pass1CodeMove);
319 394
320 printf("min_addr: %p, max_addr: %p, entities: %d\n", 395 printf("min_addr: %p, max_addr: %p, entities: %d\n",
321 result->min_addr, result->max_addr, result->max_entities); 396 result->bounds.GetMinAddr(), result->bounds.GetMaxAddr(),
397 result->max_entities);
322 398
323 result->AllocateEntities(); 399 result->AllocateEntities();
324 400
325 // Pass 2: Fill in code entries data. 401 // Pass 2: Fill in code entries data.
326 ParserCycle(start, end, result, 402 ParserCycle(start, end, result,
327 Pass2CodeCreation, Pass2CodeDelete, Pass2CodeMove); 403 Pass2CodeCreation, Pass2CodeDelete, Pass2CodeMove);
328 } 404 }
329 405
330 406
331 static inline void PrintCodeEntityInfo(CodeEntityInfo entity) { 407 static inline void PrintCodeEntityInfo(CodeEntityInfo entity) {
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
459 const int new_log_size = Logger::GetLogLines( 535 const int new_log_size = Logger::GetLogLines(
460 log_size, new_log_start, buffer.length() - log_size); 536 log_size, new_log_start, buffer.length() - log_size);
461 CHECK_GT(new_log_size, 0); 537 CHECK_GT(new_log_size, 0);
462 CHECK_GT(buffer.length(), log_size + new_log_size); 538 CHECK_GT(buffer.length(), log_size + new_log_size);
463 539
464 // Fill an equivalent map of compiled code objects. 540 // Fill an equivalent map of compiled code objects.
465 ParseLogResult new_result; 541 ParseLogResult new_result;
466 ParseLog(new_log_start, new_log_start + new_log_size, &new_result); 542 ParseLog(new_log_start, new_log_start + new_log_size, &new_result);
467 543
468 // Test their actual equivalence. 544 // Test their actual equivalence.
545 Interval combined;
546 combined.CloneFrom(&ref_result.bounds);
547 combined.CloneFrom(&new_result.bounds);
548 Interval* iter = &combined;
469 bool results_equal = true; 549 bool results_equal = true;
470 int ref_idx = -1, new_idx = -1, ref_inc = 1, new_inc = 1; 550
471 while (ref_inc > 0 || new_inc > 0) { 551 while (iter != NULL) {
472 const Address ref_addr = ref_result.min_addr + ref_idx; 552 for (Address addr = iter->raw_min_addr();
473 const Address new_addr = new_result.min_addr + new_idx; 553 addr <= iter->raw_max_addr(); ++addr) {
474 ref_inc = ref_addr <= ref_result.max_addr && ref_addr <= new_addr ? 1 : 0; 554 CodeEntityInfo ref_entity = ref_result.GetEntity(addr);
475 new_inc = new_addr <= new_result.max_addr && new_addr <= ref_addr ? 1 : 0; 555 CodeEntityInfo new_entity = new_result.GetEntity(addr);
476 const int ref_item = ref_result.entities_map[ref_idx]; 556 if (ref_entity != NULL || new_entity != NULL) {
477 const int new_item = new_result.entities_map[new_idx]; 557 const bool equal = AreEntitiesEqual(ref_entity, new_entity);
478 if (ref_item != -1 || new_item != -1) { 558 if (!equal) results_equal = false;
479 CodeEntityInfo ref_entity = 559 PrintCodeEntitiesInfo(equal, addr, ref_entity, new_entity);
480 ref_item != -1 ? ref_result.entities[ref_item] : NULL; 560 }
481 CodeEntityInfo new_entity =
482 new_item != -1 ? new_result.entities[new_item] : NULL;
483 const bool equal = AreEntitiesEqual(ref_entity, new_entity);
484 if (!equal) results_equal = false;
485 PrintCodeEntitiesInfo(
486 equal, ref_inc != 0 ? ref_addr : new_addr,
487 ref_entity, new_entity);
488 } 561 }
489 ref_idx += ref_inc; 562 iter = iter->get_next();
490 new_idx += new_inc;
491 } 563 }
492 // Make sure that all log data is written prior crash due to CHECK failure. 564 // Make sure that all log data is written prior crash due to CHECK failure.
493 fflush(stdout); 565 fflush(stdout);
494 CHECK(results_equal); 566 CHECK(results_equal);
495 567
496 env->Exit(); 568 env->Exit();
497 v8::V8::Dispose(); 569 v8::V8::Dispose();
498 i::FLAG_always_compact = saved_always_compact; 570 i::FLAG_always_compact = saved_always_compact;
499 } 571 }
500 572
501 573
502 #endif // ENABLE_LOGGING_AND_PROFILING 574 #endif // ENABLE_LOGGING_AND_PROFILING
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698