Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |