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

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

Issue 11548023: Cleanup tests for StringCharacterStream (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 8 years 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 | Annotate | Revision Log
« 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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 2
3 // Check that we can traverse very deep stacks of ConsStrings using 3 // Check that we can traverse very deep stacks of ConsStrings using
4 // StringInputBuffer. Check that Get(int) works on very deep stacks 4 // StringInputBuffer. Check that Get(int) works on very deep stacks
5 // of ConsStrings. These operations may not be very fast, but they 5 // of ConsStrings. These operations may not be very fast, but they
6 // should be possible without getting errors due to too deep recursion. 6 // should be possible without getting errors due to too deep recursion.
7 7
8 #include <stdlib.h> 8 #include <stdlib.h>
9 9
10 #include "v8.h" 10 #include "v8.h"
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 v8::HandleScope scope; 78 v8::HandleScope scope;
79 const char* extensions[] = { "v8/print" }; 79 const char* extensions[] = { "v8/print" };
80 v8::ExtensionConfiguration config(1, extensions); 80 v8::ExtensionConfiguration config(1, extensions);
81 env = v8::Context::New(&config); 81 env = v8::Context::New(&config);
82 } 82 }
83 v8::HandleScope scope; 83 v8::HandleScope scope;
84 env->Enter(); 84 env->Enter();
85 } 85 }
86 86
87 87
88 static const int NUMBER_OF_BUILDING_BLOCKS = 256;
89 static const int DEEP_DEPTH = 8 * 1024; 88 static const int DEEP_DEPTH = 8 * 1024;
90 static const int SUPER_DEEP_DEPTH = 80 * 1024; 89 static const int SUPER_DEEP_DEPTH = 80 * 1024;
91 90
92 91
93 class Resource: public v8::String::ExternalStringResource, 92 class Resource: public v8::String::ExternalStringResource,
94 public ZoneObject { 93 public ZoneObject {
95 public: 94 public:
96 explicit Resource(Vector<const uc16> string): data_(string.start()) { 95 explicit Resource(Vector<const uc16> string): data_(string.start()) {
97 length_ = string.length(); 96 length_ = string.length();
98 } 97 }
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 Resource* resource = new(zone) Resource(Vector<const uc16>(buf, len)); 183 Resource* resource = new(zone) Resource(Vector<const uc16>(buf, len));
185 building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource); 184 building_blocks[i] = FACTORY->NewExternalStringFromTwoByte(resource);
186 for (int j = 0; j < len; j++) { 185 for (int j = 0; j < len; j++) {
187 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); 186 CHECK_EQ(buf[j], building_blocks[i]->Get(j));
188 } 187 }
189 break; 188 break;
190 } 189 }
191 case 3: { 190 case 3: {
192 char* buf = zone->NewArray<char>(len); 191 char* buf = zone->NewArray<char>(len);
193 for (int j = 0; j < len; j++) { 192 for (int j = 0; j < len; j++) {
194 buf[j] = rng->next(128); 193 buf[j] = rng->next(0x80);
195 } 194 }
196 AsciiResource* resource = 195 AsciiResource* resource =
197 new(zone) AsciiResource(Vector<const char>(buf, len)); 196 new(zone) AsciiResource(Vector<const char>(buf, len));
198 building_blocks[i] = FACTORY->NewExternalStringFromAscii(resource); 197 building_blocks[i] = FACTORY->NewExternalStringFromAscii(resource);
199 for (int j = 0; j < len; j++) { 198 for (int j = 0; j < len; j++) {
200 CHECK_EQ(buf[j], building_blocks[i]->Get(j)); 199 CHECK_EQ(buf[j], building_blocks[i]->Get(j));
201 } 200 }
202 break; 201 break;
203 } 202 }
204 } 203 }
205 for (int j = slice_depth; j > 0; j--) { 204 for (int j = slice_depth; j > 0; j--) {
206 building_blocks[i] = FACTORY->NewSubString( 205 building_blocks[i] = FACTORY->NewSubString(
207 building_blocks[i], 206 building_blocks[i],
208 slice_head_chars, 207 slice_head_chars,
209 building_blocks[i]->length() - slice_tail_chars); 208 building_blocks[i]->length() - slice_tail_chars);
210 } 209 }
211 CHECK(len == building_blocks[i]->length() + slice_length); 210 CHECK(len == building_blocks[i]->length() + slice_length);
212 } 211 }
213 } 212 }
214 213
215 214
216 static Handle<String> ConstructLeft(
217 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
218 int depth) {
219 Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
220 for (int i = 0; i < depth; i++) {
221 answer = FACTORY->NewConsString(
222 answer,
223 building_blocks[i % NUMBER_OF_BUILDING_BLOCKS]);
224 }
225 return answer;
226 }
227
228
229 static Handle<String> ConstructRight(
230 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
231 int depth) {
232 Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
233 for (int i = depth - 1; i >= 0; i--) {
234 answer = FACTORY->NewConsString(
235 building_blocks[i % NUMBER_OF_BUILDING_BLOCKS],
236 answer);
237 }
238 return answer;
239 }
240
241
242 static Handle<String> ConstructBalancedHelper(
243 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS],
244 int from,
245 int to) {
246 CHECK(to > from);
247 if (to - from == 1) {
248 return building_blocks[from % NUMBER_OF_BUILDING_BLOCKS];
249 }
250 if (to - from == 2) {
251 return FACTORY->NewConsString(
252 building_blocks[from % NUMBER_OF_BUILDING_BLOCKS],
253 building_blocks[(from+1) % NUMBER_OF_BUILDING_BLOCKS]);
254 }
255 Handle<String> part1 =
256 ConstructBalancedHelper(building_blocks, from, from + ((to - from) / 2));
257 Handle<String> part2 =
258 ConstructBalancedHelper(building_blocks, from + ((to - from) / 2), to);
259 return FACTORY->NewConsString(part1, part2);
260 }
261
262
263 static Handle<String> ConstructBalanced(
264 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS]) {
265 return ConstructBalancedHelper(building_blocks, 0, DEEP_DEPTH);
266 }
267
268
269 static StringInputBuffer buffer;
270 static ConsStringIteratorOp cons_string_iterator_op_1;
271 static ConsStringIteratorOp cons_string_iterator_op_2;
272
273 static void Traverse(Handle<String> s1, Handle<String> s2) {
274 int i = 0;
275 buffer.Reset(*s1);
276 StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
277 StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
278 StringInputBuffer buffer2(*s2);
279 while (buffer.has_more()) {
280 CHECK(buffer2.has_more());
281 CHECK(character_stream_1.HasMore());
282 CHECK(character_stream_2.HasMore());
283 uint16_t c = buffer.GetNext();
284 CHECK_EQ(c, buffer2.GetNext());
285 CHECK_EQ(c, character_stream_1.GetNext());
286 CHECK_EQ(c, character_stream_2.GetNext());
287 i++;
288 }
289 CHECK(!character_stream_1.HasMore());
290 CHECK(!character_stream_2.HasMore());
291 CHECK_EQ(s1->length(), i);
292 CHECK_EQ(s2->length(), i);
293 }
294
295
296 static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
297 int i = 0;
298 buffer.Reset(*s1);
299 StringInputBuffer buffer2(*s2);
300 StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
301 StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
302 while (buffer.has_more() && i < chars) {
303 CHECK(buffer2.has_more());
304 CHECK(character_stream_1.HasMore());
305 CHECK(character_stream_2.HasMore());
306 uint16_t c = buffer.GetNext();
307 CHECK_EQ(c, buffer2.GetNext());
308 CHECK_EQ(c, character_stream_1.GetNext());
309 CHECK_EQ(c, character_stream_2.GetNext());
310 i++;
311 }
312 s1->Get(s1->length() - 1);
313 s2->Get(s2->length() - 1);
314 }
315
316
317 TEST(Traverse) {
318 printf("TestTraverse\n");
319 InitializeVM();
320 v8::HandleScope scope;
321 Handle<String> building_blocks[NUMBER_OF_BUILDING_BLOCKS];
322 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
323 RandomNumberGenerator rng;
324 rng.init();
325 InitializeBuildingBlocks(
326 building_blocks, NUMBER_OF_BUILDING_BLOCKS, false, &rng);
327 Handle<String> flat = ConstructBalanced(building_blocks);
328 FlattenString(flat);
329 Handle<String> left_asymmetric = ConstructLeft(building_blocks, DEEP_DEPTH);
330 Handle<String> right_asymmetric = ConstructRight(building_blocks, DEEP_DEPTH);
331 Handle<String> symmetric = ConstructBalanced(building_blocks);
332 printf("1\n");
333 Traverse(flat, symmetric);
334 printf("2\n");
335 Traverse(flat, left_asymmetric);
336 printf("3\n");
337 Traverse(flat, right_asymmetric);
338 printf("4\n");
339 Handle<String> left_deep_asymmetric =
340 ConstructLeft(building_blocks, SUPER_DEEP_DEPTH);
341 Handle<String> right_deep_asymmetric =
342 ConstructRight(building_blocks, SUPER_DEEP_DEPTH);
343 printf("5\n");
344 TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
345 printf("6\n");
346 TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
347 printf("7\n");
348 FlattenString(left_asymmetric);
349 printf("10\n");
350 Traverse(flat, left_asymmetric);
351 printf("11\n");
352 FlattenString(right_asymmetric);
353 printf("12\n");
354 Traverse(flat, right_asymmetric);
355 printf("14\n");
356 FlattenString(symmetric);
357 printf("15\n");
358 Traverse(flat, symmetric);
359 printf("16\n");
360 FlattenString(left_deep_asymmetric);
361 printf("18\n");
362 }
363
364
365 class ConsStringStats { 215 class ConsStringStats {
366 public: 216 public:
367 ConsStringStats() { 217 ConsStringStats() {
368 Reset(); 218 Reset();
369 } 219 }
370 void Reset(); 220 void Reset();
371 void VerifyEqual(const ConsStringStats& that) const; 221 void VerifyEqual(const ConsStringStats& that) const;
372 unsigned leaves_; 222 unsigned leaves_;
373 unsigned empty_leaves_; 223 unsigned empty_leaves_;
374 unsigned chars_; 224 unsigned chars_;
(...skipping 17 matching lines...) Expand all
392 CHECK(this->leaves_ == that.leaves_); 242 CHECK(this->leaves_ == that.leaves_);
393 CHECK(this->empty_leaves_ == that.empty_leaves_); 243 CHECK(this->empty_leaves_ == that.empty_leaves_);
394 CHECK(this->chars_ == that.chars_); 244 CHECK(this->chars_ == that.chars_);
395 CHECK(this->left_traversals_ == that.left_traversals_); 245 CHECK(this->left_traversals_ == that.left_traversals_);
396 CHECK(this->right_traversals_ == that.right_traversals_); 246 CHECK(this->right_traversals_ == that.right_traversals_);
397 } 247 }
398 248
399 249
400 class ConsStringGenerationData { 250 class ConsStringGenerationData {
401 public: 251 public:
402 ConsStringGenerationData(); 252 static const int kNumberOfBuildingBlocks = 256;
253 explicit ConsStringGenerationData(bool long_blocks);
403 void Reset(); 254 void Reset();
255 inline Handle<String> block(int offset);
256 inline Handle<String> block(uint32_t offset);
404 // Input variables. 257 // Input variables.
405 double early_termination_threshold_; 258 double early_termination_threshold_;
406 double leftness_; 259 double leftness_;
407 double rightness_; 260 double rightness_;
408 double empty_leaf_threshold_; 261 double empty_leaf_threshold_;
409 unsigned max_leaves_; 262 unsigned max_leaves_;
410 // Cached data. 263 // Cached data.
411 Handle<String> building_blocks_[NUMBER_OF_BUILDING_BLOCKS]; 264 Handle<String> building_blocks_[kNumberOfBuildingBlocks];
412 String* empty_string_; 265 String* empty_string_;
413 RandomNumberGenerator rng_; 266 RandomNumberGenerator rng_;
414 // Stats. 267 // Stats.
415 ConsStringStats stats_; 268 ConsStringStats stats_;
416 unsigned early_terminations_; 269 unsigned early_terminations_;
417 private: 270 private:
418 DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData); 271 DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData);
419 }; 272 };
420 273
421 274
422 ConsStringGenerationData::ConsStringGenerationData() { 275 ConsStringGenerationData::ConsStringGenerationData(bool long_blocks) {
423 rng_.init(); 276 rng_.init();
424 InitializeBuildingBlocks( 277 InitializeBuildingBlocks(
425 building_blocks_, NUMBER_OF_BUILDING_BLOCKS, true, &rng_); 278 building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_);
426 empty_string_ = Isolate::Current()->heap()->empty_string(); 279 empty_string_ = Isolate::Current()->heap()->empty_string();
427 Reset(); 280 Reset();
428 } 281 }
429 282
430 283
284 Handle<String> ConsStringGenerationData::block(uint32_t offset) {
285 return building_blocks_[offset % kNumberOfBuildingBlocks ];
286 }
287
288
289 Handle<String> ConsStringGenerationData::block(int offset) {
290 CHECK_GE(offset, 0);
291 return building_blocks_[offset % kNumberOfBuildingBlocks];
292 }
293
294
431 void ConsStringGenerationData::Reset() { 295 void ConsStringGenerationData::Reset() {
432 early_termination_threshold_ = 0.01; 296 early_termination_threshold_ = 0.01;
433 leftness_ = 0.75; 297 leftness_ = 0.75;
434 rightness_ = 0.75; 298 rightness_ = 0.75;
435 empty_leaf_threshold_ = 0.02; 299 empty_leaf_threshold_ = 0.02;
436 max_leaves_ = 1000; 300 max_leaves_ = 1000;
437 stats_.Reset(); 301 stats_.Reset();
438 early_terminations_ = 0; 302 early_terminations_ = 0;
303 rng_.init();
439 } 304 }
440 305
441 306
442 void VerifyConsString(ConsString* cons_string, ConsStringStats* stats) { 307 void AccumulateStats(ConsString* cons_string, ConsStringStats* stats) {
443 int left_length = cons_string->first()->length(); 308 int left_length = cons_string->first()->length();
444 int right_length = cons_string->second()->length(); 309 int right_length = cons_string->second()->length();
445 CHECK(cons_string->length() == left_length + right_length); 310 CHECK(cons_string->length() == left_length + right_length);
446 // Check left side. 311 // Check left side.
447 if (cons_string->first()->IsConsString()) { 312 bool left_is_cons = cons_string->first()->IsConsString();
313 if (left_is_cons) {
448 stats->left_traversals_++; 314 stats->left_traversals_++;
449 VerifyConsString(ConsString::cast(cons_string->first()), stats); 315 AccumulateStats(ConsString::cast(cons_string->first()), stats);
450 } else { 316 } else {
451 CHECK_NE(left_length, 0); 317 CHECK_NE(left_length, 0);
452 stats->leaves_++; 318 stats->leaves_++;
453 stats->chars_ += left_length; 319 stats->chars_ += left_length;
454 } 320 }
455 // Check right side. 321 // Check right side.
456 if (cons_string->second()->IsConsString()) { 322 if (cons_string->second()->IsConsString()) {
457 stats->right_traversals_++; 323 stats->right_traversals_++;
458 VerifyConsString(ConsString::cast(cons_string->second()), stats); 324 AccumulateStats(ConsString::cast(cons_string->second()), stats);
459 } else { 325 } else {
460 if (right_length == 0) stats->empty_leaves_++; 326 if (right_length == 0) {
327 stats->empty_leaves_++;
328 CHECK(!left_is_cons);
329 }
461 stats->leaves_++; 330 stats->leaves_++;
462 stats->chars_ += right_length; 331 stats->chars_ += right_length;
463 } 332 }
464 } 333 }
465 334
466 335
467 void VerifyConsStringWithOperator( 336 void AccumulateStats(Handle<String> cons_string, ConsStringStats* stats) {
337 AssertNoAllocation no_alloc;
338 if (cons_string->IsConsString()) {
339 return AccumulateStats(ConsString::cast(*cons_string), stats);
340 }
341 // This string got flattened by gc.
342 stats->chars_ += cons_string->length();
343 }
344
345
346 void AccumulateStatsWithOperator(
468 ConsString* cons_string, ConsStringStats* stats) { 347 ConsString* cons_string, ConsStringStats* stats) {
469 // Init op. 348 // Init op.
470 ConsStringIteratorOp op; 349 ConsStringIteratorOp op;
471 op.Reset(); 350 op.Reset();
472 // Use response for initial search and on blown stack. 351 // Use response for initial search and on blown stack.
473 ConsStringIteratorOp::ContinueResponse response; 352 ConsStringIteratorOp::ContinueResponse response;
474 response.string_ = cons_string; 353 response.string_ = cons_string;
475 response.offset_ = 0; 354 response.offset_ = 0;
476 response.type_ = cons_string->map()->instance_type(); 355 response.type_ = cons_string->map()->instance_type();
477 response.length_ = (uint32_t) cons_string->length(); 356 response.length_ = (uint32_t) cons_string->length();
(...skipping 21 matching lines...) Expand all
499 }; 378 };
500 } 379 }
501 380
502 381
503 void VerifyConsString(Handle<String> root, ConsStringGenerationData* data) { 382 void VerifyConsString(Handle<String> root, ConsStringGenerationData* data) {
504 // Verify basic data. 383 // Verify basic data.
505 CHECK(root->IsConsString()); 384 CHECK(root->IsConsString());
506 CHECK((unsigned)root->length() == data->stats_.chars_); 385 CHECK((unsigned)root->length() == data->stats_.chars_);
507 // Recursive verify. 386 // Recursive verify.
508 ConsStringStats stats; 387 ConsStringStats stats;
509 VerifyConsString(ConsString::cast(*root), &stats); 388 AccumulateStats(ConsString::cast(*root), &stats);
510 stats.VerifyEqual(data->stats_); 389 stats.VerifyEqual(data->stats_);
511 // Iteratively verify. 390 // Iteratively verify.
512 stats.Reset(); 391 stats.Reset();
513 VerifyConsStringWithOperator(ConsString::cast(*root), &stats); 392 AccumulateStatsWithOperator(ConsString::cast(*root), &stats);
514 // Don't see these. Must copy over. 393 // Don't see these. Must copy over.
515 stats.empty_leaves_ = data->stats_.empty_leaves_; 394 stats.empty_leaves_ = data->stats_.empty_leaves_;
516 stats.left_traversals_ = data->stats_.left_traversals_; 395 stats.left_traversals_ = data->stats_.left_traversals_;
517 stats.right_traversals_ = data->stats_.right_traversals_; 396 stats.right_traversals_ = data->stats_.right_traversals_;
518 // Adjust total leaves to compensate. 397 // Adjust total leaves to compensate.
519 stats.leaves_ += stats.empty_leaves_; 398 stats.leaves_ += stats.empty_leaves_;
520 stats.VerifyEqual(data->stats_); 399 stats.VerifyEqual(data->stats_);
521 } 400 }
522 401
523 402
(...skipping 11 matching lines...) Expand all
535 // Cap for max leaves. 414 // Cap for max leaves.
536 terminate |= data->stats_.leaves_ >= data->max_leaves_; 415 terminate |= data->stats_.leaves_ >= data->max_leaves_;
537 // Roll the dice. 416 // Roll the dice.
538 terminate |= terminate_early; 417 terminate |= terminate_early;
539 // Compute termination characteristics for each side. 418 // Compute termination characteristics for each side.
540 bool terminate_left = terminate || !data->rng_.next(data->leftness_); 419 bool terminate_left = terminate || !data->rng_.next(data->leftness_);
541 bool terminate_right = terminate || !data->rng_.next(data->rightness_); 420 bool terminate_right = terminate || !data->rng_.next(data->rightness_);
542 // Generate left string. 421 // Generate left string.
543 Handle<String> left; 422 Handle<String> left;
544 if (terminate_left) { 423 if (terminate_left) {
545 left = data->building_blocks_[data->rng_.next(NUMBER_OF_BUILDING_BLOCKS)]; 424 left = data->block(data->rng_.next());
546 data->stats_.leaves_++; 425 data->stats_.leaves_++;
547 data->stats_.chars_ += left->length(); 426 data->stats_.chars_ += left->length();
548 } else { 427 } else {
549 left = ConstructRandomString(data, max_recursion - 1);
550 data->stats_.left_traversals_++; 428 data->stats_.left_traversals_++;
551 } 429 }
552 // Generate right string. 430 // Generate right string.
553 Handle<String> right; 431 Handle<String> right;
554 if (terminate_right) { 432 if (terminate_right) {
555 right = data->building_blocks_[data->rng_.next(NUMBER_OF_BUILDING_BLOCKS)]; 433 right = data->block(data->rng_.next());
556 data->stats_.leaves_++; 434 data->stats_.leaves_++;
557 data->stats_.chars_ += right->length(); 435 data->stats_.chars_ += right->length();
558 } else { 436 } else {
437 data->stats_.right_traversals_++;
438 }
439 // Generate the necessary sub-nodes recursively.
440 if (!terminate_right) {
441 // Need to balance generation fairly.
442 if (!terminate_left && data->rng_.next(0.5)) {
443 left = ConstructRandomString(data, max_recursion - 1);
444 }
559 right = ConstructRandomString(data, max_recursion - 1); 445 right = ConstructRandomString(data, max_recursion - 1);
560 data->stats_.right_traversals_++; 446 }
447 if (!terminate_left && left.is_null()) {
448 left = ConstructRandomString(data, max_recursion - 1);
561 } 449 }
562 // Build the cons string. 450 // Build the cons string.
563 Handle<String> root = FACTORY->NewConsString(left, right); 451 Handle<String> root = FACTORY->NewConsString(left, right);
564 CHECK(root->IsConsString() && !root->IsFlat()); 452 CHECK(root->IsConsString() && !root->IsFlat());
565 // Special work needed for flat string. 453 // Special work needed for flat string.
566 if (flat) { 454 if (flat) {
567 data->stats_.empty_leaves_++; 455 data->stats_.empty_leaves_++;
568 FlattenString(root); 456 FlattenString(root);
569 CHECK(root->IsConsString() && root->IsFlat()); 457 CHECK(root->IsConsString() && root->IsFlat());
570 } 458 }
571 return root; 459 return root;
572 } 460 }
573 461
574 462
575 static const int kCharacterStreamRandomCases = 150; 463 static Handle<String> ConstructLeft(
576 static const int kCharacterStreamEdgeCases = 464 ConsStringGenerationData* data,
577 kCharacterStreamRandomCases + 5; 465 int depth) {
466 Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
467 data->stats_.leaves_++;
468 for (int i = 0; i < depth; i++) {
469 Handle<String> block = data->block(i);
470 Handle<String> next = FACTORY->NewConsString(answer, block);
471 if (next->IsConsString()) data->stats_.leaves_++;
472 data->stats_.chars_ += block->length();
473 answer = next;
474 }
475 data->stats_.left_traversals_ = data->stats_.leaves_ - 2;
476 return answer;
477 }
578 478
579 479
580 static Handle<String> BuildConsStrings(int testCase, 480 static Handle<String> ConstructRight(
581 ConsStringGenerationData* data) { 481 ConsStringGenerationData* data,
582 // For random constructions, need to reset the generator. 482 int depth) {
583 data->rng_.init(); 483 Handle<String> answer = FACTORY->NewStringFromAscii(CStrVector(""));
584 for (int j = 0; j < testCase * 50; j++) { 484 data->stats_.leaves_++;
585 data->rng_.next(); 485 for (int i = depth - 1; i >= 0; i--) {
486 Handle<String> block = data->block(i);
487 Handle<String> next = FACTORY->NewConsString(block, answer);
488 if (next->IsConsString()) data->stats_.leaves_++;
489 data->stats_.chars_ += block->length();
490 answer = next;
586 } 491 }
587 Handle<String> string; 492 data->stats_.right_traversals_ = data->stats_.leaves_ - 2;
588 switch (testCase) { 493 return answer;
589 case 0: 494 }
590 return ConstructBalanced(data->building_blocks_); 495
591 case 1: 496
592 return ConstructLeft(data->building_blocks_, DEEP_DEPTH); 497 static Handle<String> ConstructBalancedHelper(
593 case 2: 498 ConsStringGenerationData* data,
594 return ConstructRight(data->building_blocks_, DEEP_DEPTH); 499 int from,
595 case 3: 500 int to) {
596 return ConstructLeft(data->building_blocks_, 10); 501 CHECK(to > from);
597 case 4: 502 if (to - from == 1) {
598 return ConstructRight(data->building_blocks_, 10); 503 data->stats_.chars_ += data->block(from)->length();
599 case 5: 504 return data->block(from);
600 return FACTORY->NewConsString( 505 }
601 data->building_blocks_[0], data->building_blocks_[1]); 506 if (to - from == 2) {
602 default: 507 data->stats_.chars_ += data->block(from)->length();
603 if (testCase >= kCharacterStreamEdgeCases) { 508 data->stats_.chars_ += data->block(from+1)->length();
604 CHECK(false); 509 return FACTORY->NewConsString(data->block(from), data->block(from+1));
605 return string; 510 }
606 } 511 Handle<String> part1 =
607 // Random test case. 512 ConstructBalancedHelper(data, from, from + ((to - from) / 2));
608 data->Reset(); 513 Handle<String> part2 =
609 string = ConstructRandomString(data, 200); 514 ConstructBalancedHelper(data, from + ((to - from) / 2), to);
610 AssertNoAllocation no_alloc; 515 if (part1->IsConsString()) data->stats_.left_traversals_++;
611 VerifyConsString(string, data); 516 if (part2->IsConsString()) data->stats_.right_traversals_++;
612 #ifdef DEBUG 517 return FACTORY->NewConsString(part1, part2);
613 printf( 518 }
614 "%s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d]\n", 519
615 "leaves", data->stats_.leaves_, 520
616 "empty", data->stats_.empty_leaves_, 521 static Handle<String> ConstructBalanced(
617 "chars", data->stats_.chars_, 522 ConsStringGenerationData* data, int depth = DEEP_DEPTH) {
618 "lefts", data->stats_.left_traversals_, 523 Handle<String> string = ConstructBalancedHelper(data, 0, depth);
619 "rights", data->stats_.right_traversals_, 524 data->stats_.leaves_ =
620 "early_terminations", data->early_terminations_); 525 data->stats_.left_traversals_ + data->stats_.right_traversals_ + 2;
621 #endif 526 return string;
622 return string; 527 }
623 } 528
529
530 static StringInputBuffer buffer;
531 static ConsStringIteratorOp cons_string_iterator_op_1;
532 static ConsStringIteratorOp cons_string_iterator_op_2;
533
534 static void Traverse(Handle<String> s1, Handle<String> s2) {
535 int i = 0;
536 buffer.Reset(*s1);
537 StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
538 StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
539 StringInputBuffer buffer2(*s2);
540 while (buffer.has_more()) {
541 CHECK(buffer2.has_more());
542 CHECK(character_stream_1.HasMore());
543 CHECK(character_stream_2.HasMore());
544 uint16_t c = buffer.GetNext();
545 CHECK_EQ(c, buffer2.GetNext());
546 CHECK_EQ(c, character_stream_1.GetNext());
547 CHECK_EQ(c, character_stream_2.GetNext());
548 i++;
549 }
550 CHECK(!character_stream_1.HasMore());
551 CHECK(!character_stream_2.HasMore());
552 CHECK_EQ(s1->length(), i);
553 CHECK_EQ(s2->length(), i);
554 }
555
556
557 static void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
558 int i = 0;
559 buffer.Reset(*s1);
560 StringInputBuffer buffer2(*s2);
561 StringCharacterStream character_stream_1(*s1, 0, &cons_string_iterator_op_1);
562 StringCharacterStream character_stream_2(*s2, 0, &cons_string_iterator_op_2);
563 while (buffer.has_more() && i < chars) {
564 CHECK(buffer2.has_more());
565 CHECK(character_stream_1.HasMore());
566 CHECK(character_stream_2.HasMore());
567 uint16_t c = buffer.GetNext();
568 CHECK_EQ(c, buffer2.GetNext());
569 CHECK_EQ(c, character_stream_1.GetNext());
570 CHECK_EQ(c, character_stream_2.GetNext());
571 i++;
572 }
573 s1->Get(s1->length() - 1);
574 s2->Get(s2->length() - 1);
575 }
576
577
578 TEST(Traverse) {
579 printf("TestTraverse\n");
580 InitializeVM();
581 v8::HandleScope scope;
582 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
583 ConsStringGenerationData data(false);
584 Handle<String> flat = ConstructBalanced(&data);
585 FlattenString(flat);
586 Handle<String> left_asymmetric = ConstructLeft(&data, DEEP_DEPTH);
587 Handle<String> right_asymmetric = ConstructRight(&data, DEEP_DEPTH);
588 Handle<String> symmetric = ConstructBalanced(&data);
589 printf("1\n");
590 Traverse(flat, symmetric);
591 printf("2\n");
592 Traverse(flat, left_asymmetric);
593 printf("3\n");
594 Traverse(flat, right_asymmetric);
595 printf("4\n");
596 Handle<String> left_deep_asymmetric =
597 ConstructLeft(&data, SUPER_DEEP_DEPTH);
598 Handle<String> right_deep_asymmetric =
599 ConstructRight(&data, SUPER_DEEP_DEPTH);
600 printf("5\n");
601 TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
602 printf("6\n");
603 TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
604 printf("7\n");
605 FlattenString(left_asymmetric);
606 printf("10\n");
607 Traverse(flat, left_asymmetric);
608 printf("11\n");
609 FlattenString(right_asymmetric);
610 printf("12\n");
611 Traverse(flat, right_asymmetric);
612 printf("14\n");
613 FlattenString(symmetric);
614 printf("15\n");
615 Traverse(flat, symmetric);
616 printf("16\n");
617 FlattenString(left_deep_asymmetric);
618 printf("18\n");
624 } 619 }
625 620
626 621
627 static void VerifyCharacterStream( 622 static void VerifyCharacterStream(
628 String* flat_string, String* cons_string) { 623 String* flat_string, String* cons_string) {
629 // Do not want to test ConString traversal on flat string. 624 // Do not want to test ConString traversal on flat string.
630 CHECK(flat_string->IsFlat()); 625 CHECK(flat_string->IsFlat() && !flat_string->IsConsString());
631 CHECK(!flat_string->IsConsString());
632 CHECK(cons_string->IsConsString()); 626 CHECK(cons_string->IsConsString());
633 // TODO(dcarney) Test stream reset as well. 627 // TODO(dcarney) Test stream reset as well.
634 int length = flat_string->length(); 628 int length = flat_string->length();
635 // Iterate start search in multiple places in the string. 629 // Iterate start search in multiple places in the string.
636 int outer_iterations = length > 20 ? 20 : length; 630 int outer_iterations = length > 20 ? 20 : length;
637 for (int j = 0; j <= outer_iterations; j++) { 631 for (int j = 0; j <= outer_iterations; j++) {
638 int offset = length * j / outer_iterations; 632 int offset = length * j / outer_iterations;
639 if (offset < 0) offset = 0; 633 if (offset < 0) offset = 0;
640 // Want to test the offset == length case. 634 // Want to test the offset == length case.
641 if (offset > length) offset = length; 635 if (offset > length) offset = length;
642 StringCharacterStream flat_stream( 636 StringCharacterStream flat_stream(
643 flat_string, (unsigned) offset, &cons_string_iterator_op_1); 637 flat_string, (unsigned) offset, &cons_string_iterator_op_1);
644 StringCharacterStream cons_stream( 638 StringCharacterStream cons_stream(
645 cons_string, (unsigned) offset, &cons_string_iterator_op_2); 639 cons_string, (unsigned) offset, &cons_string_iterator_op_2);
646 for (int i = offset; i < length; i++) { 640 for (int i = offset; i < length; i++) {
647 uint16_t c = flat_string->Get(i); 641 uint16_t c = flat_string->Get(i);
648 CHECK(flat_stream.HasMore()); 642 CHECK(flat_stream.HasMore());
649 CHECK(cons_stream.HasMore()); 643 CHECK(cons_stream.HasMore());
650 CHECK_EQ(c, flat_stream.GetNext()); 644 CHECK_EQ(c, flat_stream.GetNext());
651 CHECK_EQ(c, cons_stream.GetNext()); 645 CHECK_EQ(c, cons_stream.GetNext());
652 } 646 }
653 CHECK(!flat_stream.HasMore()); 647 CHECK(!flat_stream.HasMore());
654 CHECK(!cons_stream.HasMore()); 648 CHECK(!cons_stream.HasMore());
655 } 649 }
656 } 650 }
657 651
658 652
659 TEST(StringCharacterStreamEdgeCases) { 653 static inline void PrintStats(const ConsStringGenerationData& data) {
660 printf("TestStringCharacterStreamEdgeCases\n"); 654 #ifdef DEBUG
655 printf(
656 "%s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d]\n",
657 "leaves", data.stats_.leaves_,
658 "empty", data.stats_.empty_leaves_,
659 "chars", data.stats_.chars_,
660 "lefts", data.stats_.left_traversals_,
661 "rights", data.stats_.right_traversals_,
662 "early_terminations", data.early_terminations_);
663 #endif
664 }
665
666
667 template<typename BuildString>
668 void TestStringCharacterStream(BuildString build, int test_cases) {
661 InitializeVM(); 669 InitializeVM();
662 Isolate* isolate = Isolate::Current(); 670 Isolate* isolate = Isolate::Current();
663 HandleScope outer_scope(isolate); 671 HandleScope outer_scope(isolate);
664 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT); 672 ZoneScope zone(Isolate::Current()->runtime_zone(), DELETE_ON_EXIT);
665 ConsStringGenerationData data; 673 ConsStringGenerationData data(true);
666 for (int i = 0; i < kCharacterStreamEdgeCases; i++) { 674 bool last_test_did_gc = false;
675 for (int i = 0; i < test_cases; i++) {
667 printf("%d\n", i); 676 printf("%d\n", i);
668 isolate->heap()->CollectAllGarbage(
669 Heap::kNoGCFlags, "must not allocate in loop");
670 AlwaysAllocateScope always_allocate;
671 HandleScope inner_scope(isolate); 677 HandleScope inner_scope(isolate);
672 Handle<String> cons_string = BuildConsStrings(i, &data); 678 // Build flat version of cons string.
673 Handle<String> flat_string = BuildConsStrings(i, &data); 679 Handle<String> flat_string = build(i, &data);
680 ConsStringStats flat_string_stats;
681 AccumulateStats(flat_string, &flat_string_stats);
682 // Flatten string.
674 FlattenString(flat_string); 683 FlattenString(flat_string);
684 // Build unflattened version of cons string to test.
685 Handle<String> cons_string = build(i, &data);
686 ConsStringStats cons_string_stats;
687 AccumulateStats(cons_string, &cons_string_stats);
688 // Check if gc changed our data structure.
689 bool broken_by_gc =
690 cons_string_stats.leaves_ != data.stats_.leaves_ ||
691 cons_string_stats.leaves_ != flat_string_stats.leaves_;
692 // If gc altered the data structure, do a full collection and retry test.
693 if (broken_by_gc) {
694 // Bail if test runs twice.
695 if (last_test_did_gc) CHECK(false);
696 printf("forcing gc\n");
697 isolate->heap()->CollectAllGarbage(Heap::kNoGCFlags, "retry test");
698 // Retry test.
699 last_test_did_gc = true;
700 i--;
701 continue;
702 }
703 last_test_did_gc = false;
675 AssertNoAllocation no_alloc; 704 AssertNoAllocation no_alloc;
676 CHECK(flat_string->IsConsString() && flat_string->IsFlat()); 705 PrintStats(data);
677 VerifyCharacterStream(ConsString::cast(*flat_string)->first(), 706 // Full verify of cons string.
678 *cons_string); 707 cons_string_stats.VerifyEqual(flat_string_stats);
679 } 708 cons_string_stats.VerifyEqual(data.stats_);
709 VerifyConsString(cons_string, &data);
710 String* flat_string_ptr =
711 flat_string->IsConsString() ?
712 ConsString::cast(*flat_string)->first() :
713 *flat_string;
714 VerifyCharacterStream(flat_string_ptr, *cons_string);
715 }
716 }
717
718
719 static const int kCharacterStreamNonRandomCases = 8;
720
721
722 static Handle<String> BuildEdgeCaseConsString(
723 int test_case, ConsStringGenerationData* data) {
724 data->Reset();
725 switch (test_case) {
726 case 0:
727 return ConstructBalanced(data, 71);
728 case 1:
729 return ConstructLeft(data, 71);
730 case 2:
731 return ConstructRight(data, 71);
732 case 3:
733 return ConstructLeft(data, 10);
734 case 4:
735 return ConstructRight(data, 10);
736 case 5:
737 // 2 element balanced tree.
738 data->stats_.chars_ += data->block(0)->length();
739 data->stats_.chars_ += data->block(1)->length();
740 data->stats_.leaves_ += 2;
741 return FACTORY->NewConsString(data->block(0), data->block(1));
742 case 6:
743 // Simple flattened tree.
744 data->stats_.chars_ += data->block(0)->length();
745 data->stats_.chars_ += data->block(1)->length();
746 data->stats_.leaves_ += 2;
747 data->stats_.empty_leaves_ += 1;
748 {
749 Handle<String> string =
750 FACTORY->NewConsString(data->block(0), data->block(1));
751 FlattenString(string);
752 return string;
753 }
754 case 7:
755 // Left node flattened.
756 data->stats_.chars_ += data->block(0)->length();
757 data->stats_.chars_ += data->block(1)->length();
758 data->stats_.chars_ += data->block(2)->length();
759 data->stats_.leaves_ += 3;
760 data->stats_.empty_leaves_ += 1;
761 data->stats_.left_traversals_ += 1;
762 {
763 Handle<String> left =
764 FACTORY->NewConsString(data->block(0), data->block(1));
765 FlattenString(left);
766 return FACTORY->NewConsString(left, data->block(2));
767 }
768 case 8:
769 // Left node and right node flattened.
770 data->stats_.chars_ += data->block(0)->length();
771 data->stats_.chars_ += data->block(1)->length();
772 data->stats_.chars_ += data->block(2)->length();
773 data->stats_.chars_ += data->block(3)->length();
774 data->stats_.leaves_ += 4;
775 data->stats_.empty_leaves_ += 2;
776 data->stats_.left_traversals_ += 1;
777 data->stats_.right_traversals_ += 1;
778 {
779 Handle<String> left =
780 FACTORY->NewConsString(data->block(0), data->block(1));
781 FlattenString(left);
782 Handle<String> right =
783 FACTORY->NewConsString(data->block(2), data->block(2));
784 FlattenString(right);
785 return FACTORY->NewConsString(left, right);
786 }
787 }
788 UNREACHABLE();
789 return Handle<String>();
790 }
791
792
793 TEST(StringCharacterStreamEdgeCases) {
794 printf("TestStringCharacterStreamEdgeCases\n");
795 TestStringCharacterStream(
796 BuildEdgeCaseConsString, kCharacterStreamNonRandomCases);
797 }
798
799
800 static const int kBalances = 3;
801 static const int kTreeLengths = 4;
802 static const int kEmptyLeaves = 4;
803 static const int kUniqueRandomParameters =
804 kBalances*kTreeLengths*kEmptyLeaves;
805
806
807 static void InitializeGenerationData(
808 int test_case, ConsStringGenerationData* data) {
809 // Clear the settings and reinit the rng.
810 data->Reset();
811 // Spin up the rng to a known location that is unique per test.
812 static const int kPerTestJump = 501;
813 for (int j = 0; j < test_case*kPerTestJump; j++) {
814 data->rng_.next();
815 }
816 // Choose balanced, left or right heavy trees.
817 switch (test_case % kBalances) {
818 case 0:
819 // Nothing to do. Already balanced.
820 break;
821 case 1:
822 // Left balanced.
823 data->leftness_ = 0.90;
824 data->rightness_ = 0.15;
825 break;
826 case 2:
827 // Right balanced.
828 data->leftness_ = 0.15;
829 data->rightness_ = 0.90;
830 break;
831 default:
832 UNREACHABLE();
833 break;
834 }
835 // Must remove the influence of the above decision.
836 test_case /= kBalances;
837 // Choose tree length.
838 switch (test_case % kTreeLengths) {
839 case 0:
840 data->max_leaves_ = 16;
841 data->early_termination_threshold_ = 0.2;
842 break;
843 case 1:
844 data->max_leaves_ = 50;
845 data->early_termination_threshold_ = 0.05;
846 break;
847 case 2:
848 data->max_leaves_ = 500;
849 data->early_termination_threshold_ = 0.03;
850 break;
851 case 3:
852 data->max_leaves_ = 5000;
853 data->early_termination_threshold_ = 0.001;
854 break;
855 default:
856 UNREACHABLE();
857 break;
858 }
859 // Must remove the influence of the above decision.
860 test_case /= kTreeLengths;
861 // Choose how much we allow empty nodes, including not at all.
862 data->empty_leaf_threshold_ =
863 0.03 * static_cast<double>(test_case % kEmptyLeaves);
864 }
865
866
867 static Handle<String> BuildRandomConsString(
868 int test_case, ConsStringGenerationData* data) {
869 InitializeGenerationData(test_case, data);
870 return ConstructRandomString(data, 200);
871 }
872
873
874 TEST(StringCharacterStreamRandom) {
Michael Starzinger 2012/12/14 09:23:07 This test is failing on the GC Stress builder. ht
875 printf("StringCharacterStreamRandom\n");
876 TestStringCharacterStream(BuildRandomConsString, kUniqueRandomParameters*7);
680 } 877 }
681 878
682 879
683 static const int DEEP_ASCII_DEPTH = 100000; 880 static const int DEEP_ASCII_DEPTH = 100000;
684 881
685 882
686 TEST(DeepAscii) { 883 TEST(DeepAscii) {
687 printf("TestDeepAscii\n"); 884 printf("TestDeepAscii\n");
688 InitializeVM(); 885 InitializeVM();
689 v8::HandleScope scope; 886 v8::HandleScope scope;
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after
1113 1310
1114 v8::Local<v8::String> expected = v8_str("ascii\x80only\x80string\x80"); 1311 v8::Local<v8::String> expected = v8_str("ascii\x80only\x80string\x80");
1115 CHECK(expected->Equals(result)); 1312 CHECK(expected->Equals(result));
1116 } 1313 }
1117 1314
1118 1315
1119 TEST(IsAscii) { 1316 TEST(IsAscii) {
1120 CHECK(String::IsAscii(static_cast<char*>(NULL), 0)); 1317 CHECK(String::IsAscii(static_cast<char*>(NULL), 0));
1121 CHECK(String::IsAscii(static_cast<uc16*>(NULL), 0)); 1318 CHECK(String::IsAscii(static_cast<uc16*>(NULL), 0));
1122 } 1319 }
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