1355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org// Copyright 2012 the V8 project authors. All rights reserved.
2750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// Redistribution and use in source and binary forms, with or without
3750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// modification, are permitted provided that the following conditions are
4750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// met:
5750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//
6750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//     * Redistributions of source code must retain the above copyright
7750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//       notice, this list of conditions and the following disclaimer.
8750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//     * Redistributions in binary form must reproduce the above
9750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//       copyright notice, this list of conditions and the following
10750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//       disclaimer in the documentation and/or other materials provided
11750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//       with the distribution.
12750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//     * Neither the name of Google Inc. nor the names of its
13750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//       contributors may be used to endorse or promote products derived
14750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//       from this software without specific prior written permission.
15750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org//
16750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26750145ab1b720c97adf2b548cc8fbd28c8b8e06dulan@chromium.org// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
279a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
289a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// Check that we can traverse very deep stacks of ConsStrings using
294cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org// StringCharacterStram.  Check that Get(int) works on very deep stacks
309a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// of ConsStrings.  These operations may not be very fast, but they
319a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com// should be possible without getting errors due to too deep recursion.
329a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
339a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com#include <stdlib.h>
349a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
35196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/v8.h"
369a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
37196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/api.h"
38196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/factory.h"
39196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "src/objects.h"
40196eb601290dc49c3754da728dc58700dff2de1bmachenbach@chromium.org#include "test/cctest/cctest.h"
419a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
42c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org// Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry
43c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgclass MyRandomNumberGenerator {
44c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org public:
45c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  MyRandomNumberGenerator() {
46c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    init();
47c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  }
48c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org
49c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  void init(uint32_t seed = 0x5688c73e) {
50c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    static const uint32_t phi = 0x9e3779b9;
51c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    c = 362436;
52c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    i = kQSize-1;
53c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    Q[0] = seed;
54c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    Q[1] = seed + phi;
55c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    Q[2] = seed + phi + phi;
56c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    for (unsigned j = 3; j < kQSize; j++) {
57c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org      Q[j] = Q[j - 3] ^ Q[j - 2] ^ phi ^ j;
58c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    }
59c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  }
60c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org
61c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  uint32_t next() {
62c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    uint64_t a = 18782;
63c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    uint32_t r = 0xfffffffe;
64c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    i = (i + 1) & (kQSize-1);
65c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    uint64_t t = a * Q[i] + c;
66c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    c = (t >> 32);
67c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    uint32_t x = static_cast<uint32_t>(t + c);
68c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    if (x < c) {
69c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org      x++;
70c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org      c++;
71c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    }
72c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    return (Q[i] = r - x);
73c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  }
74c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org
75c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  uint32_t next(int max) {
76c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    return next() % max;
77c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  }
78c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org
79c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  bool next(double threshold) {
80e3c177a423baa3c30225c4e422b6f6c76d38b951machenbach@chromium.org    DCHECK(threshold >= 0.0 && threshold <= 1.0);
81c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    if (threshold == 1.0) return true;
82c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    if (threshold == 0.0) return false;
83c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    uint32_t value = next() % 100000;
84c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org    return threshold > static_cast<double>(value)/100000.0;
85c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  }
86c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org
87c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org private:
88c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  static const uint32_t kQSize = 4096;
89c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  uint32_t Q[kQSize];
90c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  uint32_t c;
91c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org  uint32_t i;
92c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org};
93c00ec2b94bc5505fa81f81daefd956f5a8776a09danno@chromium.org
949a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
959a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comusing namespace v8::internal;
969a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
979a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
989a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic const int DEEP_DEPTH = 8 * 1024;
999a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic const int SUPER_DEEP_DEPTH = 80 * 1024;
1009a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
1019a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
1026f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.orgclass Resource: public v8::String::ExternalStringResource {
1034af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org public:
1046f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  Resource(const uc16* data, size_t length): data_(data), length_(length) {}
1056f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  ~Resource() { i::DeleteArray(data_); }
1064af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  virtual const uint16_t* data() const { return data_; }
1074af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  virtual size_t length() const { return length_; }
1084af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1094af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org private:
1104af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  const uc16* data_;
1114af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org  size_t length_;
1124af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org};
1134af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1144af710e493dc8583f3b7b7ce65127ad4e7c3f8a1ager@chromium.org
1152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgclass OneByteResource : public v8::String::ExternalOneByteStringResource {
116ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org public:
1172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  OneByteResource(const char* data, size_t length)
1186f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      : data_(data), length_(length) {}
1192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  ~OneByteResource() { i::DeleteArray(data_); }
120ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  virtual const char* data() const { return data_; }
121ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  virtual size_t length() const { return length_; }
122ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
123ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org private:
124ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  const char* data_;
125ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  size_t length_;
126ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org};
127ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
128ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
129a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic void InitializeBuildingBlocks(Handle<String>* building_blocks,
130a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org                                     int bb_length,
131a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org                                     bool long_blocks,
1326f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org                                     MyRandomNumberGenerator* rng) {
13341826e77311db718135ef6517b846933dfd275f3ager@chromium.org  // A list of pointers that we don't have any interest in cleaning up.
13441826e77311db718135ef6517b846933dfd275f3ager@chromium.org  // If they are reachable from a root then leak detection won't complain.
135528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Isolate* isolate = CcTest::i_isolate();
136d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Factory* factory = isolate->factory();
137a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int i = 0; i < bb_length; i++) {
138a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int len = rng->next(16);
139a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int slice_head_chars = 0;
140a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int slice_tail_chars = 0;
141a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int slice_depth = 0;
142a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    for (int j = 0; j < 3; j++) {
143a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      if (rng->next(0.35)) slice_depth++;
144a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
145a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Must truncate something for a slice string. Loop until
146a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // at least one end will be sliced.
147a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    while (slice_head_chars == 0 && slice_tail_chars == 0) {
148a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      slice_head_chars = rng->next(15);
149a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      slice_tail_chars = rng->next(12);
150a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
151a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (long_blocks) {
152a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Generate building blocks which will never be merged
153a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      len += ConsString::kMinLength + 1;
154a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    } else if (len > 14) {
1559a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      len += 1234;
1569a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
157a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Don't slice 0 length strings.
158a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (len == 0) slice_depth = 0;
159a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int slice_length = slice_depth*(slice_head_chars + slice_tail_chars);
160a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    len += slice_length;
161a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    switch (rng->next(4)) {
1629a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      case 0: {
1639a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        uc16 buf[2000];
1649a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
165a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          buf[j] = rng->next(0x10000);
1669a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1678496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        building_blocks[i] = factory->NewStringFromTwoByte(
1688496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org            Vector<const uc16>(buf, len)).ToHandleChecked();
1699a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
170bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
1719a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1729a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        break;
1739a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      }
1749a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      case 1: {
1759a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        char buf[2000];
1769a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
177a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          buf[j] = rng->next(0x80);
1789a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1798496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org        building_blocks[i] = factory->NewStringFromAscii(
1808496027a525ad457b6d5729faf41f29100a27264machenbach@chromium.org            Vector<const char>(buf, len)).ToHandleChecked();
1819a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
182bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
1839a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1849a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        break;
1859a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      }
1869a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      case 2: {
1876f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org        uc16* buf = NewArray<uc16>(len);
1889a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
189a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          buf[j] = rng->next(0x10000);
1909a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1916f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org        Resource* resource = new Resource(buf, len);
1926f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org        building_blocks[i] =
1936f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org            v8::Utils::OpenHandle(
1946f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org                *v8::String::NewExternal(CcTest::isolate(), resource));
1959a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
196bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
1979a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
1989a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        break;
1999a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      }
2009a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      case 3: {
2016f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org        char* buf = NewArray<char>(len);
2029a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
203a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          buf[j] = rng->next(0x80);
2049a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
2052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        OneByteResource* resource = new OneByteResource(buf, len);
2066f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org        building_blocks[i] =
2076f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org            v8::Utils::OpenHandle(
2086f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org                *v8::String::NewExternal(CcTest::isolate(), resource));
2099a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        for (int j = 0; j < len; j++) {
210bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org          CHECK_EQ(buf[j], building_blocks[i]->Get(j));
2119a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        }
2129a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com        break;
2139a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com      }
2149a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    }
215a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    for (int j = slice_depth; j > 0; j--) {
216d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org      building_blocks[i] = factory->NewSubString(
217a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          building_blocks[i],
218a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          slice_head_chars,
219a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org          building_blocks[i]->length() - slice_tail_chars);
220a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
221a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK(len == building_blocks[i]->length() + slice_length);
222a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
223a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
224a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
225a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
226a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass ConsStringStats {
227a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org public:
228a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  ConsStringStats() {
229a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Reset();
230a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
231a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  void Reset();
232a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  void VerifyEqual(const ConsStringStats& that) const;
2333484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int leaves_;
2343484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int empty_leaves_;
2353484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int chars_;
2363484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int left_traversals_;
2373484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int right_traversals_;
238a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org private:
239a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  DISALLOW_COPY_AND_ASSIGN(ConsStringStats);
240a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org};
241a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
242a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
243a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid ConsStringStats::Reset() {
244a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  leaves_ = 0;
245a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  empty_leaves_ = 0;
246a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  chars_ = 0;
247a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  left_traversals_ = 0;
248a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  right_traversals_ = 0;
249a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
250a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
251a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
252a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid ConsStringStats::VerifyEqual(const ConsStringStats& that) const {
2533484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  CHECK_EQ(this->leaves_, that.leaves_);
2543484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  CHECK_EQ(this->empty_leaves_, that.empty_leaves_);
2553484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  CHECK_EQ(this->chars_, that.chars_);
2563484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  CHECK_EQ(this->left_traversals_, that.left_traversals_);
2573484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  CHECK_EQ(this->right_traversals_, that.right_traversals_);
258a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
259a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
260a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
261a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgclass ConsStringGenerationData {
262a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org public:
263a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kNumberOfBuildingBlocks = 256;
2646f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  explicit ConsStringGenerationData(bool long_blocks);
265a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  void Reset();
266a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  inline Handle<String> block(int offset);
267a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  inline Handle<String> block(uint32_t offset);
268a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Input variables.
269a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  double early_termination_threshold_;
270a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  double leftness_;
271a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  double rightness_;
272a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  double empty_leaf_threshold_;
2733484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int max_leaves_;
274a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Cached data.
275a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> building_blocks_[kNumberOfBuildingBlocks];
276a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  String* empty_string_;
277c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  MyRandomNumberGenerator rng_;
278a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Stats.
279a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  ConsStringStats stats_;
2803484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int early_terminations_;
281a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org private:
282a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  DISALLOW_COPY_AND_ASSIGN(ConsStringGenerationData);
283a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org};
284a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
285a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
2866f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.orgConsStringGenerationData::ConsStringGenerationData(bool long_blocks) {
287a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  rng_.init();
288a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  InitializeBuildingBlocks(
2896f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org      building_blocks_, kNumberOfBuildingBlocks, long_blocks, &rng_);
290528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  empty_string_ = CcTest::heap()->empty_string();
291a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Reset();
292a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
293a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
294a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
295a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgHandle<String> ConsStringGenerationData::block(uint32_t offset) {
296a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  return building_blocks_[offset % kNumberOfBuildingBlocks ];
297a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
298a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
299a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
300a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgHandle<String> ConsStringGenerationData::block(int offset) {
301a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK_GE(offset, 0);
302a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  return building_blocks_[offset % kNumberOfBuildingBlocks];
303a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
304a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
305a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
306a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid ConsStringGenerationData::Reset() {
307a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  early_termination_threshold_ = 0.01;
308a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  leftness_ = 0.75;
309a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  rightness_ = 0.75;
310a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  empty_leaf_threshold_ = 0.02;
311a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  max_leaves_ = 1000;
312a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats_.Reset();
313a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  early_terminations_ = 0;
314a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  rng_.init();
315a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
316a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
317a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
318a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid AccumulateStats(ConsString* cons_string, ConsStringStats* stats) {
319a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  int left_length = cons_string->first()->length();
320a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  int right_length = cons_string->second()->length();
321a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(cons_string->length() == left_length + right_length);
322a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Check left side.
323a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  bool left_is_cons = cons_string->first()->IsConsString();
324a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (left_is_cons) {
325a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->left_traversals_++;
326a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    AccumulateStats(ConsString::cast(cons_string->first()), stats);
327a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  } else {
328a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK_NE(left_length, 0);
329a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->leaves_++;
330a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->chars_ += left_length;
331a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
332a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Check right side.
333a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (cons_string->second()->IsConsString()) {
334a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->right_traversals_++;
335a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    AccumulateStats(ConsString::cast(cons_string->second()), stats);
336a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  } else {
337a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (right_length == 0) {
338a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      stats->empty_leaves_++;
339a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      CHECK(!left_is_cons);
340a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
341a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->leaves_++;
342a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->chars_ += right_length;
3439a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
3449a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
3459a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
3469a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
347a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid AccumulateStats(Handle<String> cons_string, ConsStringStats* stats) {
34879e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org  DisallowHeapAllocation no_allocation;
349a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (cons_string->IsConsString()) {
350a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    return AccumulateStats(ConsString::cast(*cons_string), stats);
351a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
352a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // This string got flattened by gc.
353a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats->chars_ += cons_string->length();
354a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
355a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
356a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
357a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid AccumulateStatsWithOperator(
358a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsString* cons_string, ConsStringStats* stats) {
3593484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  ConsStringIteratorOp op(cons_string);
3603484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  String* string;
3613484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  int offset;
3623484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  while (NULL != (string = op.Next(&offset))) {
363a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Accumulate stats.
3643484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org    CHECK_EQ(0, offset);
365a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->leaves_++;
366a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    stats->chars_ += string->length();
367a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
368a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
369a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
370a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
371a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid VerifyConsString(Handle<String> root, ConsStringGenerationData* data) {
372a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Verify basic data.
373a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(root->IsConsString());
3743484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org  CHECK_EQ(root->length(), data->stats_.chars_);
375a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Recursive verify.
376a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  ConsStringStats stats;
377a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  AccumulateStats(ConsString::cast(*root), &stats);
378a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.VerifyEqual(data->stats_);
379a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Iteratively verify.
380a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.Reset();
381a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  AccumulateStatsWithOperator(ConsString::cast(*root), &stats);
382a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Don't see these. Must copy over.
383a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.empty_leaves_ = data->stats_.empty_leaves_;
384a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.left_traversals_ = data->stats_.left_traversals_;
385a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.right_traversals_ = data->stats_.right_traversals_;
386a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Adjust total leaves to compensate.
387a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.leaves_ += stats.empty_leaves_;
388a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  stats.VerifyEqual(data->stats_);
389a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
390a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
391a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
392a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic Handle<String> ConstructRandomString(ConsStringGenerationData* data,
393a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org                                            unsigned max_recursion) {
394528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
395a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Compute termination characteristics.
396a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  bool terminate = false;
397a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  bool flat = data->rng_.next(data->empty_leaf_threshold_);
398a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  bool terminate_early = data->rng_.next(data->early_termination_threshold_);
399a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (terminate_early) data->early_terminations_++;
400a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // The obvious condition.
401a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  terminate |= max_recursion == 0;
402a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Flat cons string terminate by definition.
403a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  terminate |= flat;
404a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Cap for max leaves.
405a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  terminate |= data->stats_.leaves_ >= data->max_leaves_;
406a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Roll the dice.
407a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  terminate |= terminate_early;
408a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Compute termination characteristics for each side.
409a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  bool terminate_left = terminate || !data->rng_.next(data->leftness_);
410a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  bool terminate_right = terminate || !data->rng_.next(data->rightness_);
411a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Generate left string.
412a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> left;
413a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (terminate_left) {
414a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    left = data->block(data->rng_.next());
415a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.leaves_++;
416a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += left->length();
417a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  } else {
418a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.left_traversals_++;
419a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
420a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Generate right string.
421a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> right;
422a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (terminate_right) {
423a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    right = data->block(data->rng_.next());
424a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.leaves_++;
425a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += right->length();
426a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  } else {
427a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.right_traversals_++;
428a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
429a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Generate the necessary sub-nodes recursively.
430a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (!terminate_right) {
431a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Need to balance generation fairly.
432a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (!terminate_left && data->rng_.next(0.5)) {
433a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      left = ConstructRandomString(data, max_recursion - 1);
434a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
435a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    right = ConstructRandomString(data, max_recursion - 1);
436a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
437a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (!terminate_left && left.is_null()) {
438a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    left = ConstructRandomString(data, max_recursion - 1);
439a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
440a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Build the cons string.
441255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  Handle<String> root = factory->NewConsString(left, right).ToHandleChecked();
442a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(root->IsConsString() && !root->IsFlat());
443a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Special work needed for flat string.
444a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (flat) {
445a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.empty_leaves_++;
4469e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org    String::Flatten(root);
447a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK(root->IsConsString() && root->IsFlat());
448a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
449a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  return root;
450a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
451a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
452a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
4539a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic Handle<String> ConstructLeft(
454a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsStringGenerationData* data,
4559a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    int depth) {
456528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
4572c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Handle<String> answer = factory->NewStringFromStaticChars("");
458a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->stats_.leaves_++;
4599a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  for (int i = 0; i < depth; i++) {
460a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Handle<String> block = data->block(i);
461255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org    Handle<String> next =
462255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org        factory->NewConsString(answer, block).ToHandleChecked();
463a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (next->IsConsString()) data->stats_.leaves_++;
464a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += block->length();
465a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    answer = next;
4669a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
467a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->stats_.left_traversals_ = data->stats_.leaves_ - 2;
4689a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  return answer;
4699a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
4709a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
4719a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
4729a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic Handle<String> ConstructRight(
473a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsStringGenerationData* data,
4749a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    int depth) {
475528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
4762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Handle<String> answer = factory->NewStringFromStaticChars("");
477a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->stats_.leaves_++;
4789a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  for (int i = depth - 1; i >= 0; i--) {
479a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Handle<String> block = data->block(i);
480255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org    Handle<String> next =
481255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org        factory->NewConsString(block, answer).ToHandleChecked();
482a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (next->IsConsString()) data->stats_.leaves_++;
483a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += block->length();
484a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    answer = next;
4859a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
486a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->stats_.right_traversals_ = data->stats_.leaves_ - 2;
4879a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  return answer;
4889a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
4899a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
4909a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
4919a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic Handle<String> ConstructBalancedHelper(
492a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsStringGenerationData* data,
4939a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    int from,
4949a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    int to) {
495528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
4963a37e9b96c768f6b5b6b09542e1cb1a1ece7a022ager@chromium.org  CHECK(to > from);
4979a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  if (to - from == 1) {
498a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += data->block(from)->length();
499a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    return data->block(from);
5009a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
5019a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  if (to - from == 2) {
502a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += data->block(from)->length();
503a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->stats_.chars_ += data->block(from+1)->length();
504255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org    return factory->NewConsString(data->block(from), data->block(from+1))
505255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org        .ToHandleChecked();
5069a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
507870a0b67c822d289024711912e2512af01b66c3bager@chromium.org  Handle<String> part1 =
508a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConstructBalancedHelper(data, from, from + ((to - from) / 2));
509870a0b67c822d289024711912e2512af01b66c3bager@chromium.org  Handle<String> part2 =
510a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConstructBalancedHelper(data, from + ((to - from) / 2), to);
511a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (part1->IsConsString()) data->stats_.left_traversals_++;
512a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  if (part2->IsConsString()) data->stats_.right_traversals_++;
513255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  return factory->NewConsString(part1, part2).ToHandleChecked();
5149a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
5159a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5169a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5179a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic Handle<String> ConstructBalanced(
518a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsStringGenerationData* data, int depth = DEEP_DEPTH) {
519a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> string = ConstructBalancedHelper(data, 0, depth);
520a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->stats_.leaves_ =
521a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.left_traversals_ + data->stats_.right_traversals_ + 2;
522a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  return string;
5239a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
5249a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5259a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
526a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic ConsStringIteratorOp cons_string_iterator_op_1;
527a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic ConsStringIteratorOp cons_string_iterator_op_2;
5289a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5299a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic void Traverse(Handle<String> s1, Handle<String> s2) {
5309a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  int i = 0;
5314cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  StringCharacterStream character_stream_1(*s1, &cons_string_iterator_op_1);
5324cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  StringCharacterStream character_stream_2(*s2, &cons_string_iterator_op_2);
5334cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  while (character_stream_1.HasMore()) {
534a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK(character_stream_2.HasMore());
5354cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    uint16_t c = character_stream_1.GetNext();
536a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK_EQ(c, character_stream_2.GetNext());
5379a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    i++;
5389a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
539a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(!character_stream_1.HasMore());
540a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(!character_stream_2.HasMore());
5419a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  CHECK_EQ(s1->length(), i);
5429a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  CHECK_EQ(s2->length(), i);
5439a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
5449a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5459a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5469a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comstatic void TraverseFirst(Handle<String> s1, Handle<String> s2, int chars) {
5479a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  int i = 0;
5484cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  StringCharacterStream character_stream_1(*s1, &cons_string_iterator_op_1);
5494cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  StringCharacterStream character_stream_2(*s2, &cons_string_iterator_op_2);
5504cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org  while (character_stream_1.HasMore() && i < chars) {
551a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK(character_stream_2.HasMore());
5524cd70b470729dd5850dd4120a350f01363d16837yangguo@chromium.org    uint16_t c = character_stream_1.GetNext();
553a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK_EQ(c, character_stream_2.GetNext());
5549a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    i++;
5559a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
556bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  s1->Get(s1->length() - 1);
557bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  s2->Get(s2->length() - 1);
5589a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
5599a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5609a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
5619a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.comTEST(Traverse) {
5629a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("TestTraverse\n");
563e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
564e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
5656f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  ConsStringGenerationData data(false);
566a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> flat = ConstructBalanced(&data);
5679e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  String::Flatten(flat);
568a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> left_asymmetric = ConstructLeft(&data, DEEP_DEPTH);
569a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> right_asymmetric = ConstructRight(&data, DEEP_DEPTH);
570a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  Handle<String> symmetric = ConstructBalanced(&data);
5719a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("1\n");
5729a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Traverse(flat, symmetric);
5739a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("2\n");
5749a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Traverse(flat, left_asymmetric);
5759a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("3\n");
5769a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Traverse(flat, right_asymmetric);
5779a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("4\n");
5789a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Handle<String> left_deep_asymmetric =
579a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      ConstructLeft(&data, SUPER_DEEP_DEPTH);
5809a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Handle<String> right_deep_asymmetric =
581a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      ConstructRight(&data, SUPER_DEEP_DEPTH);
5829a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("5\n");
5839a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  TraverseFirst(left_asymmetric, left_deep_asymmetric, 1050);
5849a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("6\n");
5859a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  TraverseFirst(left_asymmetric, right_deep_asymmetric, 65536);
5869a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("7\n");
5879e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  String::Flatten(left_asymmetric);
5889a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("10\n");
5899a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Traverse(flat, left_asymmetric);
5909a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("11\n");
5919e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  String::Flatten(right_asymmetric);
5929a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("12\n");
5939a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Traverse(flat, right_asymmetric);
5949a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("14\n");
5959e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  String::Flatten(symmetric);
5969a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("15\n");
5979a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  Traverse(flat, symmetric);
5989a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("16\n");
5999e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  String::Flatten(left_deep_asymmetric);
6009a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  printf("18\n");
6019a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
6029a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
6039a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
604a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic void VerifyCharacterStream(
605a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    String* flat_string, String* cons_string) {
606a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Do not want to test ConString traversal on flat string.
607a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(flat_string->IsFlat() && !flat_string->IsConsString());
608a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  CHECK(cons_string->IsConsString());
609a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // TODO(dcarney) Test stream reset as well.
610a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  int length = flat_string->length();
611a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Iterate start search in multiple places in the string.
612a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  int outer_iterations = length > 20 ? 20 : length;
613a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int j = 0; j <= outer_iterations; j++) {
614a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int offset = length * j / outer_iterations;
615a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (offset < 0) offset = 0;
616a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Want to test the offset == length case.
617a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    if (offset > length) offset = length;
618a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    StringCharacterStream flat_stream(
6193484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org        flat_string, &cons_string_iterator_op_1, offset);
620a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    StringCharacterStream cons_stream(
6213484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org        cons_string, &cons_string_iterator_op_2, offset);
622a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    for (int i = offset; i < length; i++) {
623a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      uint16_t c = flat_string->Get(i);
624a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      CHECK(flat_stream.HasMore());
625a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      CHECK(cons_stream.HasMore());
626a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      CHECK_EQ(c, flat_stream.GetNext());
627a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      CHECK_EQ(c, cons_stream.GetNext());
628a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    }
629a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK(!flat_stream.HasMore());
630a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    CHECK(!cons_stream.HasMore());
631a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
632a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
633a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
634a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
635a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic inline void PrintStats(const ConsStringGenerationData& data) {
636a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org#ifdef DEBUG
637a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgprintf(
638a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "%s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d], %s: [%d]\n",
639a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "leaves", data.stats_.leaves_,
640a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "empty", data.stats_.empty_leaves_,
641a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "chars", data.stats_.chars_,
642a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "lefts", data.stats_.left_traversals_,
643a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "rights", data.stats_.right_traversals_,
644a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    "early_terminations", data.early_terminations_);
645a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org#endif
646a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
647a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
648a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
649a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgtemplate<typename BuildString>
650a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgvoid TestStringCharacterStream(BuildString build, int test_cases) {
651e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
652528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Isolate* isolate = CcTest::i_isolate();
653a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  HandleScope outer_scope(isolate);
6546f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  ConsStringGenerationData data(true);
655a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int i = 0; i < test_cases; i++) {
656a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    printf("%d\n", i);
657a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    HandleScope inner_scope(isolate);
6585697144afb43181fed170b81c194fe1cc0fce3b6machenbach@chromium.org    AlwaysAllocateScope always_allocate(isolate);
659a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Build flat version of cons string.
660a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Handle<String> flat_string = build(i, &data);
661a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsStringStats flat_string_stats;
662a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    AccumulateStats(flat_string, &flat_string_stats);
663a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Flatten string.
6649e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org    String::Flatten(flat_string);
665a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Build unflattened version of cons string to test.
666a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    Handle<String> cons_string = build(i, &data);
667a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    ConsStringStats cons_string_stats;
668a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    AccumulateStats(cons_string, &cons_string_stats);
66979e7902fa5f94747b5383dd40f3002dd8b62303arossberg@chromium.org    DisallowHeapAllocation no_allocation;
670a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    PrintStats(data);
671a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    // Full verify of cons string.
672a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    cons_string_stats.VerifyEqual(flat_string_stats);
673a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    cons_string_stats.VerifyEqual(data.stats_);
674a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    VerifyConsString(cons_string, &data);
675a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    String* flat_string_ptr =
676a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        flat_string->IsConsString() ?
677a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        ConsString::cast(*flat_string)->first() :
678a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        *flat_string;
679a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    VerifyCharacterStream(flat_string_ptr, *cons_string);
680a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
681a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
682a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
683a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
684a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic const int kCharacterStreamNonRandomCases = 8;
685a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
686a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
687a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic Handle<String> BuildEdgeCaseConsString(
688a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int test_case, ConsStringGenerationData* data) {
689528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
690a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->Reset();
691a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  switch (test_case) {
692a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 0:
693a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      return ConstructBalanced(data, 71);
694a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 1:
695a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      return ConstructLeft(data, 71);
696a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 2:
697a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      return ConstructRight(data, 71);
698a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 3:
699a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      return ConstructLeft(data, 10);
700a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 4:
701a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      return ConstructRight(data, 10);
702a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 5:
703a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // 2 element balanced tree.
704a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(0)->length();
705a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(1)->length();
706a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.leaves_ += 2;
707255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org      return factory->NewConsString(data->block(0), data->block(1))
708255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org                 .ToHandleChecked();
709a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 6:
710a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Simple flattened tree.
711a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(0)->length();
712a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(1)->length();
713a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.leaves_ += 2;
714a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.empty_leaves_ += 1;
715a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      {
716a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        Handle<String> string =
717255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org            factory->NewConsString(data->block(0), data->block(1))
718255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org                .ToHandleChecked();
7199e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        String::Flatten(string);
720a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        return string;
721a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
722a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 7:
723a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Left node flattened.
724a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(0)->length();
725a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(1)->length();
726a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(2)->length();
727a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.leaves_ += 3;
728a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.empty_leaves_ += 1;
729a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.left_traversals_ += 1;
730a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      {
731a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        Handle<String> left =
732255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org            factory->NewConsString(data->block(0), data->block(1))
733255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org                .ToHandleChecked();
7349e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        String::Flatten(left);
735255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org        return factory->NewConsString(left, data->block(2)).ToHandleChecked();
736a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
737a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 8:
738a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Left node and right node flattened.
739a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(0)->length();
740a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(1)->length();
741a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(2)->length();
742a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.chars_ += data->block(3)->length();
743a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.leaves_ += 4;
744a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.empty_leaves_ += 2;
745a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.left_traversals_ += 1;
746a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->stats_.right_traversals_ += 1;
747a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      {
748a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        Handle<String> left =
749255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org            factory->NewConsString(data->block(0), data->block(1))
750255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org                .ToHandleChecked();
7519e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        String::Flatten(left);
752a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org        Handle<String> right =
753255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org            factory->NewConsString(data->block(2), data->block(2))
754255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org                .ToHandleChecked();
7559e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org        String::Flatten(right);
756255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org        return factory->NewConsString(left, right).ToHandleChecked();
757a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      }
758a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
759a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  UNREACHABLE();
760a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  return Handle<String>();
761a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
762a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
763a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
764a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgTEST(StringCharacterStreamEdgeCases) {
765a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  printf("TestStringCharacterStreamEdgeCases\n");
766a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  TestStringCharacterStream(
767a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      BuildEdgeCaseConsString, kCharacterStreamNonRandomCases);
768a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
769a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
770a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
771a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic const int kBalances = 3;
772a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic const int kTreeLengths = 4;
773a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic const int kEmptyLeaves = 4;
774a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic const int kUniqueRandomParameters =
775a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    kBalances*kTreeLengths*kEmptyLeaves;
776a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
777a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
778a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic void InitializeGenerationData(
779a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int test_case, ConsStringGenerationData* data) {
780a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Clear the settings and reinit the rng.
781a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->Reset();
782a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Spin up the rng to a known location that is unique per test.
783a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  static const int kPerTestJump = 501;
784a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  for (int j = 0; j < test_case*kPerTestJump; j++) {
785a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    data->rng_.next();
786a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
787a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Choose balanced, left or right heavy trees.
788a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  switch (test_case % kBalances) {
789a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 0:
790a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Nothing to do.  Already balanced.
791a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
792a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 1:
793a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Left balanced.
794a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->leftness_ = 0.90;
795a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->rightness_ = 0.15;
796a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
797a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 2:
798a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      // Right balanced.
799a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->leftness_ = 0.15;
800a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->rightness_ = 0.90;
801a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
802a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    default:
803a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      UNREACHABLE();
804a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
805a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
806a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Must remove the influence of the above decision.
807a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  test_case /= kBalances;
808a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Choose tree length.
809a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  switch (test_case % kTreeLengths) {
810a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 0:
811a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->max_leaves_ = 16;
812a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->early_termination_threshold_ = 0.2;
813a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
814a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 1:
815a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->max_leaves_ = 50;
816a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->early_termination_threshold_ = 0.05;
817a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
818a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 2:
819a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->max_leaves_ = 500;
820a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->early_termination_threshold_ = 0.03;
821a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
822a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    case 3:
823a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->max_leaves_ = 5000;
824a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      data->early_termination_threshold_ = 0.001;
825a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
826a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    default:
827a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      UNREACHABLE();
828a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      break;
829a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  }
830a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Must remove the influence of the above decision.
831a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  test_case /= kTreeLengths;
832a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  // Choose how much we allow empty nodes, including not at all.
833a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  data->empty_leaf_threshold_ =
834a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org      0.03 * static_cast<double>(test_case % kEmptyLeaves);
835a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
836a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
837a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
838a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgstatic Handle<String> BuildRandomConsString(
839a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org    int test_case, ConsStringGenerationData* data) {
840a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  InitializeGenerationData(test_case, data);
841a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  return ConstructRandomString(data, 200);
842a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
843a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
844a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
845a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.orgTEST(StringCharacterStreamRandom) {
846a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  printf("StringCharacterStreamRandom\n");
847a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org  TestStringCharacterStream(BuildRandomConsString, kUniqueRandomParameters*7);
848a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org}
849a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
850a6bbcc801f63c451f814d6da77a1a48fba3d36c6yangguo@chromium.org
8512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgstatic const int kDeepOneByteDepth = 100000;
8529a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
8539a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
8542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgTEST(DeepOneByte) {
855e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
856528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
857e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
8589a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
8592c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  char* foo = NewArray<char>(kDeepOneByteDepth);
8602c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  for (int i = 0; i < kDeepOneByteDepth; i++) {
8619a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com    foo[i] = "foo "[i % 4];
8629a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
8632c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Handle<String> string =
8642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      factory->NewStringFromOneByte(OneByteVector(foo, kDeepOneByteDepth))
8652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org          .ToHandleChecked();
8662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  Handle<String> foo_string = factory->NewStringFromStaticChars("foo");
8672c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  for (int i = 0; i < kDeepOneByteDepth; i += 10) {
868255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org    string = factory->NewConsString(string, foo_string).ToHandleChecked();
8699a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
870255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  Handle<String> flat_string =
871255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org      factory->NewConsString(string, foo_string).ToHandleChecked();
8729e41f9ecf5042292a9efcb36e264b37621199553machenbach@chromium.org  String::Flatten(flat_string);
8739a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com
8749a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  for (int i = 0; i < 500; i++) {
8752c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    TraverseFirst(flat_string, string, kDeepOneByteDepth);
8769a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com  }
877bb29dc9819bb6f495ab6eddd2543965eb97a8e43ager@chromium.org  DeleteArray<char>(foo);
8789a4089a092cad9ff23b6416b92cd5d818dc101d1mads.s.ager@gmail.com}
8799258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
8809258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org
8819258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.orgTEST(Utf8Conversion) {
8829258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // Smoke test for converting strings to utf-8.
883e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
884e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope handle_scope(CcTest::isolate());
8852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // A simple one-byte string
8862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  const char* one_byte_string = "abcdef12345";
8872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  int len = v8::String::NewFromUtf8(CcTest::isolate(), one_byte_string,
888f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org                                    v8::String::kNormalString,
8892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                    StrLength(one_byte_string))->Utf8Length();
8902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  CHECK_EQ(StrLength(one_byte_string), len);
8912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // A mixed one-byte and two-byte string
8929258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // U+02E4 -> CB A4
8939258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // U+0064 -> 64
8949258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // U+12E4 -> E1 8B A4
8959258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // U+0030 -> 30
8969258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // U+3045 -> E3 81 85
8979258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  const uint16_t mixed_string[] = {0x02E4, 0x0064, 0x12E4, 0x0030, 0x3045};
8989258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // The characters we expect to be output
8999258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  const unsigned char as_utf8[11] = {0xCB, 0xA4, 0x64, 0xE1, 0x8B, 0xA4, 0x30,
9009258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      0xE3, 0x81, 0x85, 0x00};
9019258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // The number of bytes expected to be written for each length
9029258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  const int lengths[12] = {0, 0, 2, 3, 3, 3, 6, 7, 7, 7, 10, 11};
903357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org  const int char_lengths[12] = {0, 0, 1, 2, 2, 2, 3, 4, 4, 4, 5, 5};
904f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org  v8::Handle<v8::String> mixed = v8::String::NewFromTwoByte(
905f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org      CcTest::isolate(), mixed_string, v8::String::kNormalString, 5);
9069258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  CHECK_EQ(10, mixed->Utf8Length());
9079258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  // Try encoding the string with all capacities
9089258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  char buffer[11];
9099258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  const char kNoChar = static_cast<char>(-1);
9109258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  for (int i = 0; i <= 11; i++) {
9119258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    // Clear the buffer before reusing it
9129258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    for (int j = 0; j < 11; j++)
9139258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      buffer[j] = kNoChar;
914357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    int chars_written;
915357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    int written = mixed->WriteUtf8(buffer, i, &chars_written);
9169258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    CHECK_EQ(lengths[i], written);
917357bf65ed5309ac3a2c4bf20b6ce7770488787c2ager@chromium.org    CHECK_EQ(char_lengths[i], chars_written);
9189258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    // Check that the contents are correct
9199258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    for (int j = 0; j < lengths[i]; j++)
9209258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      CHECK_EQ(as_utf8[j], static_cast<unsigned char>(buffer[j]));
9219258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    // Check that the rest of the buffer hasn't been touched
9229258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org    for (int j = lengths[i]; j < 11; j++)
9239258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org      CHECK_EQ(kNoChar, buffer[j]);
9249258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org  }
9259258b6bc66e09368ada54001f619d53b4fc976d5ager@chromium.org}
926acae37894ae73146c7a4788ca8af931d446bd2cakasperl@chromium.org
927acae37894ae73146c7a4788ca8af931d446bd2cakasperl@chromium.org
928ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.orgTEST(ExternalShortStringAdd) {
929528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  LocalContext context;
930e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope handle_scope(CcTest::isolate());
931acae37894ae73146c7a4788ca8af931d446bd2cakasperl@chromium.org
932ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  // Make sure we cover all always-flat lengths and at least one above.
933ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  static const int kMaxLength = 20;
9342efb900e7350b14be905abdeab077f3a64c583cfulan@chromium.org  CHECK_GT(kMaxLength, i::ConsString::kMinLength);
935ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
936ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  // Allocate two JavaScript arrays for holding short strings.
9372c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  v8::Handle<v8::Array> one_byte_external_strings =
9389f18d9111f676f2899d9aa2444130c985eb75395machenbach@chromium.org      v8::Array::New(CcTest::isolate(), kMaxLength + 1);
9392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  v8::Handle<v8::Array> non_one_byte_external_strings =
9409f18d9111f676f2899d9aa2444130c985eb75395machenbach@chromium.org      v8::Array::New(CcTest::isolate(), kMaxLength + 1);
941ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
9422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Generate short one-byte and two-byte external strings.
943ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  for (int i = 0; i <= kMaxLength; i++) {
9442c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    char* one_byte = NewArray<char>(i + 1);
945ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    for (int j = 0; j < i; j++) {
9462c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      one_byte[j] = 'a';
947ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    }
948ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    // Terminating '\0' is left out on purpose. It is not required for external
949ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    // string data.
9502c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    OneByteResource* one_byte_resource = new OneByteResource(one_byte, i);
9512c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    v8::Local<v8::String> one_byte_external_string =
9522c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        v8::String::NewExternal(CcTest::isolate(), one_byte_resource);
953ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
9542c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    one_byte_external_strings->Set(v8::Integer::New(CcTest::isolate(), i),
9552c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                   one_byte_external_string);
9562c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    uc16* non_one_byte = NewArray<uc16>(i + 1);
957ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    for (int j = 0; j < i; j++) {
9582c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      non_one_byte[j] = 0x1234;
959ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    }
960ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    // Terminating '\0' is left out on purpose. It is not required for external
961ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org    // string data.
9622c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    Resource* resource = new Resource(non_one_byte, i);
9632c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    v8::Local<v8::String> non_one_byte_external_string =
9642c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org        v8::String::NewExternal(CcTest::isolate(), resource);
9652c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    non_one_byte_external_strings->Set(v8::Integer::New(CcTest::isolate(), i),
9662c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org                                       non_one_byte_external_string);
967ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  }
968acae37894ae73146c7a4788ca8af931d446bd2cakasperl@chromium.org
969ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  // Add the arrays with the short external strings in the global object.
970528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  v8::Handle<v8::Object> global = context->Global();
9712c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  global->Set(v8_str("external_one_byte"), one_byte_external_strings);
9722c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  global->Set(v8_str("external_non_one_byte"), non_one_byte_external_strings);
9730f13e74b7310d8b14f19c6b93b36ff95059f97f6ulan@chromium.org  global->Set(v8_str("max_length"),
9740f13e74b7310d8b14f19c6b93b36ff95059f97f6ulan@chromium.org              v8::Integer::New(CcTest::isolate(), kMaxLength));
975ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org
9762c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  // Add short external one-byte and two-byte strings checking the result.
977ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org  static const char* source =
9782c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "function test() {"
9792c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  var one_byte_chars = 'aaaaaaaaaaaaaaaaaaaa';"
9802c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  var non_one_byte_chars = "
9812c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "'\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1"
9822c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\u1234\\"
9832c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "u1234';"  // NOLINT
9842c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  if (one_byte_chars.length != max_length) return 1;"
9852c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  if (non_one_byte_chars.length != max_length) return 2;"
9862c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  var one_byte = Array(max_length + 1);"
9872c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  var non_one_byte = Array(max_length + 1);"
9882c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  for (var i = 0; i <= max_length; i++) {"
9892c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "    one_byte[i] = one_byte_chars.substring(0, i);"
9902c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "    non_one_byte[i] = non_one_byte_chars.substring(0, i);"
9912c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  };"
9922c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  for (var i = 0; i <= max_length; i++) {"
9932c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "    if (one_byte[i] != external_one_byte[i]) return 3;"
9942c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "    if (non_one_byte[i] != external_non_one_byte[i]) return 4;"
9952c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "    for (var j = 0; j < i; j++) {"
9962c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (external_one_byte[i] !="
9972c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "          (external_one_byte[j] + external_one_byte[i - j])) return "
9982c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "5;"
9992c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (external_non_one_byte[i] !="
10002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "          (external_non_one_byte[j] + external_non_one_byte[i - "
10012c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "j])) return 6;"
10022c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (non_one_byte[i] != (non_one_byte[j] + non_one_byte[i - "
10032c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "j])) return 7;"
10042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (one_byte[i] != (one_byte[j] + one_byte[i - j])) return 8;"
10052c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (one_byte[i] != (external_one_byte[j] + one_byte[i - j])) "
10062c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "return 9;"
10072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (one_byte[i] != (one_byte[j] + external_one_byte[i - j])) "
10082c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "return 10;"
10092c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (non_one_byte[i] !="
10102c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "          (external_non_one_byte[j] + non_one_byte[i - j])) return "
10112c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "11;"
10122c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "      if (non_one_byte[i] !="
10132c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "          (non_one_byte[j] + external_non_one_byte[i - j])) return "
10142c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "12;"
10152c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "    }"
10162c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  }"
10172c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "  return 0;"
10182c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "};"
10192c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "test()";
10204668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK_EQ(0, CompileRun(source)->Int32Value());
1021ac6aa175ab59d65cfb7a88dbb621e1d7f1a80b8fsgjesse@chromium.org}
10221af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
10231af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
1024c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.orgTEST(JSONStringifySliceMadeExternal) {
1025c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CcTest::InitializeVM();
1026c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // Create a sliced string from a one-byte string.  The latter is turned
1027c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  // into a two-byte external string.  Check that JSON.stringify works.
1028c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  v8::HandleScope handle_scope(CcTest::isolate());
1029c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  v8::Handle<v8::String> underlying =
1030c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      CompileRun("var underlying = 'abcdefghijklmnopqrstuvwxyz';"
1031c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                 "underlying")->ToString();
1032c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  v8::Handle<v8::String> slice =
1033c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org      CompileRun("var slice = underlying.slice(1);"
1034c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org                 "slice")->ToString();
1035c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString());
1036c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CHECK(v8::Utils::OpenHandle(*underlying)->IsSeqOneByteString());
1037c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1038c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  int length = underlying->Length();
10396f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  uc16* two_byte = NewArray<uc16>(length + 1);
1040c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  underlying->Write(two_byte);
10416f1040e5c87d24f21c8afc2e08dc26cd1bfc5d1fmachenbach@chromium.org  Resource* resource = new Resource(two_byte, length);
1042c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CHECK(underlying->MakeExternal(resource));
1043c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CHECK(v8::Utils::OpenHandle(*slice)->IsSlicedString());
1044c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CHECK(v8::Utils::OpenHandle(*underlying)->IsExternalTwoByteString());
1045c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1046c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org  CHECK_EQ("\"bcdefghijklmnopqrstuvwxyz\"",
1047c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org           *v8::String::Utf8Value(CompileRun("JSON.stringify(slice)")));
1048c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org}
1049c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
1050c5d4971574b7a205fa0e788d8121dc79485e5e67hpayer@chromium.org
10511af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.orgTEST(CachedHashOverflow) {
1052528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  CcTest::InitializeVM();
10531af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // We incorrectly allowed strings to be tagged as array indices even if their
10541af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // values didn't fit in the hash field.
10551af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // See http://code.google.com/p/v8/issues/detail?id=728
1056528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Isolate* isolate = CcTest::i_isolate();
10571af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
1058e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope handle_scope(CcTest::isolate());
10591af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // Lines must be executed sequentially. Combining them into one script
10601af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  // makes the bug go away.
10611af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  const char* lines[] = {
10621af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "var x = [];",
10631af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "x[4] = 42;",
10641af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "var s = \"1073741828\";",
10651af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "x[s];",
10661af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "x[s] = 37;",
10671af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "x[4];",
10681af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      "x[s];",
10691af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org      NULL
10701af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  };
10711af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
107209d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org  Handle<Smi> fortytwo(Smi::FromInt(42), isolate);
107309d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org  Handle<Smi> thirtyseven(Smi::FromInt(37), isolate);
107409d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org  Handle<Object> results[] = { isolate->factory()->undefined_value(),
107509d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org                               fortytwo,
107609d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org                               isolate->factory()->undefined_value(),
107709d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org                               isolate->factory()->undefined_value(),
107809d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org                               thirtyseven,
107909d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org                               fortytwo,
108009d7ab5aba54ebac170eac755664c45eefb0be7dulan@chromium.org                               thirtyseven  // Bug yielded 42 here.
10811af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  };
10821af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org
10831af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  const char* line;
10841af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  for (int i = 0; (line = lines[i]); i++) {
10851af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org    printf("%s\n", line);
1086f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org    v8::Local<v8::Value> result = v8::Script::Compile(
1087f9841897146bc10dbb3c45f0632bb79254602c75machenbach@chromium.org        v8::String::NewFromUtf8(CcTest::isolate(), line))->Run();
10881af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org    CHECK_EQ(results[i]->IsUndefined(), result->IsUndefined());
10891af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org    CHECK_EQ(results[i]->IsNumber(), result->IsNumber());
10901af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org    if (result->IsNumber()) {
10913484964a86451e86dcf04be9bd8c0d76ee04f081rossberg@chromium.org      CHECK_EQ(Object::ToSmi(isolate, results[i]).ToHandleChecked()->value(),
10921af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org               result->ToInt32()->Value());
10931af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org    }
10941af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org  }
10951af7e1b5f676e5556c041fe09a5c4f5a906f27a0lrn@chromium.org}
10964668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
10974668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
10984668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.orgTEST(SliceFromCons) {
10994668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  FLAG_string_slices = true;
1100e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
1101528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
1102e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
11034668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Handle<String> string =
11042c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      factory->NewStringFromStaticChars("parentparentparent");
1105255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  Handle<String> parent =
1106255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org      factory->NewConsString(string, string).ToHandleChecked();
11074668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(parent->IsConsString());
11084668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(!parent->IsFlat());
1109d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Handle<String> slice = factory->NewSubString(parent, 1, 25);
11104668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // After slicing, the original string becomes a flat cons.
11114668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(parent->IsFlat());
11124668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(slice->IsSlicedString());
11134668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK_EQ(SlicedString::cast(*slice)->parent(),
11147bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org           // Parent could have been short-circuited.
11157bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org           parent->IsConsString() ? ConsString::cast(*parent)->first()
11167bd87f0fe09b5d7c12de8f1db0bdb759dc4130acjkummerow@chromium.org                                  : *parent);
11174668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(SlicedString::cast(*slice)->parent()->IsSeqString());
11184668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(slice->IsFlat());
11194668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org}
11204668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11214668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11222c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.orgclass OneByteVectorResource : public v8::String::ExternalOneByteStringResource {
1123c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com public:
11242c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  explicit OneByteVectorResource(i::Vector<const char> vector)
1125c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      : data_(vector) {}
11262c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  virtual ~OneByteVectorResource() {}
1127c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  virtual size_t length() const { return data_.length(); }
1128c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  virtual const char* data() const { return data_.start(); }
1129c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com private:
1130c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  i::Vector<const char> data_;
1131c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com};
1132c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1133c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1134c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.comTEST(SliceFromExternal) {
1135c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  FLAG_string_slices = true;
1136e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
1137528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
1138e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
11392c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  OneByteVectorResource resource(
1140c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com      i::Vector<const char>("abcdefghijklmnopqrstuvwxyz", 26));
1141255043f8054e713a64509c707cfabadd42344683machenbach@chromium.org  Handle<String> string =
11422c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      factory->NewExternalStringFromOneByte(&resource).ToHandleChecked();
1143c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CHECK(string->IsExternalString());
1144d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  Handle<String> slice = factory->NewSubString(string, 1, 25);
1145c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CHECK(slice->IsSlicedString());
1146c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CHECK(string->IsExternalString());
1147c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CHECK_EQ(SlicedString::cast(*slice)->parent(), *string);
1148c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CHECK(SlicedString::cast(*slice)->parent()->IsExternalString());
1149c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com  CHECK(slice->IsFlat());
1150c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com}
1151c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
1152c3b670ff19220959730d7886892bc4beb95d2ebaerik.corry@gmail.com
11534668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.orgTEST(TrivialSlice) {
11544668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // This tests whether a slice that contains the entire parent string
11554668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  // actually creates a new string (it should not).
11564668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  FLAG_string_slices = true;
1157e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
1158528ce02b8680a3ab6d75c7079f180a4016c69b7amachenbach@chromium.org  Factory* factory = CcTest::i_isolate()->factory();
1159e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
11604668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  v8::Local<v8::Value> result;
11614668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  Handle<String> string;
11624668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  const char* init = "var str = 'abcdefghijklmnopqrstuvwxyz';";
11634668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  const char* check = "str.slice(0,26)";
11644668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  const char* crosscheck = "str.slice(1,25)";
11654668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11664668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CompileRun(init);
11674668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
11684668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  result = CompileRun(check);
11694668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(result->IsString());
11704668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
11714668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(!string->IsSlicedString());
11724668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org
1173d4be0f0c0edfc0a0b46e745055c3dc497c0ffcb5verwaest@chromium.org  string = factory->NewSubString(string, 0, 26);
11744668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(!string->IsSlicedString());
11754668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  result = CompileRun(crosscheck);
11764668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(result->IsString());
11774668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
11784668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org  CHECK(string->IsSlicedString());
1179afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  CHECK_EQ("bcdefghijklmnopqrstuvwxy", string->ToCString().get());
11804668a2c7a746d01b382f23aa32e163701e3075f8ricow@chromium.org}
11811805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
11821805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
11831805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.orgTEST(SliceFromSlice) {
11841805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // This tests whether a slice that contains the entire parent string
11851805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  // actually creates a new string (it should not).
11861805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  FLAG_string_slices = true;
1187e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
1188e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
11891805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  v8::Local<v8::Value> result;
11901805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  Handle<String> string;
11911805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  const char* init = "var str = 'abcdefghijklmnopqrstuvwxyz';";
11921805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  const char* slice = "var slice = str.slice(1,-1); slice";
11931805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  const char* slice_from_slice = "slice.slice(1,-1);";
11941805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
11951805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CompileRun(init);
11961805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  result = CompileRun(slice);
11971805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CHECK(result->IsString());
11981805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
11991805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CHECK(string->IsSlicedString());
12001805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CHECK(SlicedString::cast(*string)->parent()->IsSeqString());
1201afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  CHECK_EQ("bcdefghijklmnopqrstuvwxy", string->ToCString().get());
12021805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org
12031805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  result = CompileRun(slice_from_slice);
12041805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CHECK(result->IsString());
12051805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
12061805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CHECK(string->IsSlicedString());
12071805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org  CHECK(SlicedString::cast(*string)->parent()->IsSeqString());
1208afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  CHECK_EQ("cdefghijklmnopqrstuvwx", string->ToCString().get());
12091805e21b0aece8c05f4960a5c0751c4463557891fschneider@chromium.org}
12107d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
12117d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org
1212d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.orgUNINITIALIZED_TEST(OneByteArrayJoin) {
1213d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  v8::Isolate::CreateParams create_params;
12147d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org  // Set heap limits.
1215d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  create_params.constraints.set_max_semi_space_size(1);
1216d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  create_params.constraints.set_max_old_space_size(4);
1217d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  v8::Isolate* isolate = v8::Isolate::New(create_params);
1218d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  isolate->Enter();
1219d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org
1220d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  {
1221d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    // String s is made of 2^17 = 131072 'c' characters and a is an array
1222d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    // starting with 'bad', followed by 2^14 times the string s. That means the
1223d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    // total length of the concatenated strings is 2^31 + 3. So on 32bit systems
1224d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    // summing the lengths of the strings (as Smis) overflows and wraps.
1225d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    LocalContext context(isolate);
1226d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    v8::HandleScope scope(isolate);
1227d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    v8::TryCatch try_catch;
1228d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    CHECK(CompileRun(
1229d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              "var two_14 = Math.pow(2, 14);"
1230d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              "var two_17 = Math.pow(2, 17);"
1231d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              "var s = Array(two_17 + 1).join('c');"
1232d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              "var a = ['bad'];"
1233d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              "for (var i = 1; i <= two_14; i++) a.push(s);"
1234d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              "a.join("
1235d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org              ");").IsEmpty());
1236d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org    CHECK(try_catch.HasCaught());
1237d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  }
1238d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  isolate->Exit();
1239d3df75b4472c9d5d4d2615aaea74d2adce4160f8machenbach@chromium.org  isolate->Dispose();
12407d10be581a91ab5eefa1139ff0b86c64ac8f6e59fschneider@chromium.org}
1241ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1242ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1243ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comstatic void CheckException(const char* source) {
1244ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // An empty handle is returned upon exception.
1245ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CHECK(CompileRun(source).IsEmpty());
1246ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
1247ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1248ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1249ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.comTEST(RobustSubStringStub) {
1250ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // This tests whether the SubStringStub can handle unsafe arguments.
1251ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // If not recognized, those unsafe arguments lead to out-of-bounds reads.
1252ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  FLAG_allow_natives_syntax = true;
1253e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
1254e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
1255ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  v8::Local<v8::Value> result;
1256ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  Handle<String> string;
1257ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CompileRun("var short = 'abcdef';");
1258ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1259ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Invalid indices.
1260ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(short,     0,    10000);");
1261ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(short, -1234,        5);");
1262ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(short,     5,        2);");
1263ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Special HeapNumbers.
1264ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(short,     1, Infinity);");
1265ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(short,   NaN,        5);");
1266ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // String arguments.
1267ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(short,    '2',     '5');");
1268ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Ordinary HeapNumbers can be handled (in runtime).
1269ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  result = CompileRun("%_SubString(short, Math.sqrt(4), 5.1);");
1270ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
1271afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  CHECK_EQ("cde", string->ToCString().get());
1272ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1273ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CompileRun("var long = 'abcdefghijklmnopqrstuvwxyz';");
1274ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Invalid indices.
1275ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(long,     0,    10000);");
1276ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(long, -1234,       17);");
1277ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(long,    17,        2);");
1278ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Special HeapNumbers.
1279ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(long,     1, Infinity);");
1280ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(long,   NaN,       17);");
1281ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // String arguments.
1282ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(long,    '2',    '17');");
1283ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Ordinary HeapNumbers within bounds can be handled (in runtime).
1284ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  result = CompileRun("%_SubString(long, Math.sqrt(4), 17.1);");
1285ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  string = v8::Utils::OpenHandle(v8::String::Cast(*result));
1286afbdadc5f06365a7889e7c1c1fdb7dbf596cce68machenbach@chromium.org  CHECK_EQ("cdefghijklmnopq", string->ToCString().get());
1287ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com
1288ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // Test that out-of-bounds substring of a slice fails when the indices
1289ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  // would have been valid for the underlying string.
1290ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CompileRun("var slice = long.slice(1, 15);");
1291ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com  CheckException("%_SubString(slice, 0, 17);");
1292ed49e965b5cafa35395084dbfb79f4e07930f10ferik.corry@gmail.com}
1293400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
1294400388edd471bd4d4a97b21c52c1024cd1cc5708rossberg@chromium.org
1295355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.orgTEST(StringReplaceAtomTwoByteResult) {
1296e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  CcTest::InitializeVM();
1297e27d617298263725e8a48c2aa14029759b952623mstarzinger@chromium.org  v8::HandleScope scope(CcTest::isolate());
1298355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  LocalContext context;
1299355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  v8::Local<v8::Value> result = CompileRun(
13002c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org      "var subject = 'one_byte~only~string~'; "
1301355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      "var replace = '\x80';            "
1302355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org      "subject.replace(/~/g, replace);  ");
1303355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  CHECK(result->IsString());
1304355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  Handle<String> string = v8::Utils::OpenHandle(v8::String::Cast(*result));
1305355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  CHECK(string->IsSeqTwoByteString());
1306355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org
13072c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org  v8::Local<v8::String> expected = v8_str("one_byte\x80only\x80string\x80");
1308355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org  CHECK(expected->Equals(result));
1309355cfd19c23ac613f2738a40e356ea48297f7d5eyangguo@chromium.org}
1310412fa510dce700c25e3ff85ee85dd32dd6cb6b87danno@chromium.org
1311412fa510dce700c25e3ff85ee85dd32dd6cb6b87danno@chromium.org
1312412fa510dce700c25e3ff85ee85dd32dd6cb6b87danno@chromium.orgTEST(IsAscii) {
1313412fa510dce700c25e3ff85ee85dd32dd6cb6b87danno@chromium.org  CHECK(String::IsAscii(static_cast<char*>(NULL), 0));
131459297c735ad2a41156ae9c723a39ff259ad061e0jkummerow@chromium.org  CHECK(String::IsOneByte(static_cast<uc16*>(NULL), 0));
1315412fa510dce700c25e3ff85ee85dd32dd6cb6b87danno@chromium.org}
131646a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
131746a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
13186bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13196bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgtemplate<typename Op, bool return_first>
13206bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgstatic uint16_t ConvertLatin1(uint16_t c) {
13216bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  uint32_t result[Op::kMaxWidth];
132246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  int chars;
13236bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  chars = Op::Convert(c, 0, result, NULL);
13246bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (chars == 0) return 0;
13256bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  CHECK_LE(chars, static_cast<int>(sizeof(result)));
13266bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (!return_first && chars > 1) {
13276bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    return 0;
132846a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  }
13296bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  return result[0];
133046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org}
133146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
133246a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org
13336bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgstatic void CheckCanonicalEquivalence(uint16_t c, uint16_t test) {
13346bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  uint16_t expect = ConvertLatin1<unibrow::Ecma262UnCanonicalize, true>(c);
13356bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  if (expect > unibrow::Latin1::kMaxChar) expect = 0;
13366bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  CHECK_EQ(expect, test);
13376bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org}
13386bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13396bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org
13406bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.orgTEST(Latin1IgnoreCase) {
13416bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  using namespace unibrow;
13426bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org  for (uint16_t c = Latin1::kMaxChar + 1; c != 0; c++) {
13436bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    uint16_t lower = ConvertLatin1<ToLowercase, false>(c);
13446bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    uint16_t upper = ConvertLatin1<ToUppercase, false>(c);
13456bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    uint16_t test = Latin1::ConvertNonLatin1ToLatin1(c);
13466bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    // Filter out all character whose upper is not their lower or vice versa.
13476bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    if (lower == 0 && upper == 0) {
13486bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      CheckCanonicalEquivalence(c, test);
13496bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      continue;
13506bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    }
13516bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    if (lower > Latin1::kMaxChar && upper > Latin1::kMaxChar) {
13526bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      CheckCanonicalEquivalence(c, test);
13536bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      continue;
13546bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    }
13556bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    if (lower == 0 && upper != 0) {
13566bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      lower = ConvertLatin1<ToLowercase, false>(upper);
13576bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    }
13586bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    if (upper == 0 && lower != c) {
13596bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      upper = ConvertLatin1<ToUppercase, false>(lower);
13606bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    }
13616bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    if (lower > Latin1::kMaxChar && upper > Latin1::kMaxChar) {
13626bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      CheckCanonicalEquivalence(c, test);
13636bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      continue;
13646bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    }
13656bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    if (upper != c && lower != c) {
13666bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      CheckCanonicalEquivalence(c, test);
13676bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org      continue;
13686bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    }
13696bec0093ef661b53a1e338a233d7aafb9536a307mvstanton@chromium.org    CHECK_EQ(Min(upper, lower), test);
137046a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org  }
137146a2a51ad190697e0f62c3060ce02a9de5820a07yangguo@chromium.org}
1372b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1373b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1374b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.orgclass DummyResource: public v8::String::ExternalStringResource {
1375b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org public:
1376b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  virtual const uint16_t* data() const { return NULL; }
1377b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  virtual size_t length() const { return 1 << 30; }
1378b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org};
1379b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1380b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1381b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.orgclass DummyOneByteResource: public v8::String::ExternalOneByteStringResource {
1382b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org public:
1383b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  virtual const char* data() const { return NULL; }
1384b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  virtual size_t length() const { return 1 << 30; }
1385b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org};
1386b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1387b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1388b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.orgTEST(InvalidExternalString) {
1389b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  CcTest::InitializeVM();
1390b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  LocalContext context;
1391b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  Isolate* isolate = CcTest::i_isolate();
1392b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  { HandleScope scope(isolate);
1393b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    DummyOneByteResource r;
13942c81ceb7f1e1ccf5f304be0646f4c1375941a7f2machenbach@chromium.org    CHECK(isolate->factory()->NewExternalStringFromOneByte(&r).is_null());
1395b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    CHECK(isolate->has_pending_exception());
1396b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    isolate->clear_pending_exception();
1397b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  }
1398b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1399b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  { HandleScope scope(isolate);
1400b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    DummyResource r;
1401b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    CHECK(isolate->factory()->NewExternalStringFromTwoByte(&r).is_null());
1402b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    CHECK(isolate->has_pending_exception());
1403b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    isolate->clear_pending_exception();
1404b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  }
1405b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org}
1406b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1407b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1408b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org#define INVALID_STRING_TEST(FUN, TYPE)                                         \
1409b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  TEST(StringOOM##FUN) {                                                       \
1410b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    CcTest::InitializeVM();                                                    \
1411b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    LocalContext context;                                                      \
1412b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    Isolate* isolate = CcTest::i_isolate();                                    \
1413b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    STATIC_ASSERT(String::kMaxLength < kMaxInt);                               \
1414b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    static const int invalid = String::kMaxLength + 1;                         \
1415b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    HandleScope scope(isolate);                                                \
1416b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    Vector<TYPE> dummy = Vector<TYPE>::New(invalid);                           \
1417b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    CHECK(isolate->factory()->FUN(Vector<const TYPE>::cast(dummy)).is_null()); \
1418b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    memset(dummy.start(), 0x20, dummy.length() * sizeof(TYPE));                \
1419b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    CHECK(isolate->has_pending_exception());                                   \
1420b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    isolate->clear_pending_exception();                                        \
1421b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org    dummy.Dispose();                                                           \
1422b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org  }
1423b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1424b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.orgINVALID_STRING_TEST(NewStringFromAscii, char)
1425b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.orgINVALID_STRING_TEST(NewStringFromUtf8, char)
1426b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.orgINVALID_STRING_TEST(NewStringFromOneByte, uint8_t)
1427b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org
1428b5ed9300c59e8590c9dc588727b6564c244b0f5cmachenbach@chromium.org#undef INVALID_STRING_TEST
1429