1a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Copyright 2008 the V8 project authors. All rights reserved.
2a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Redistribution and use in source and binary forms, with or without
3a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// modification, are permitted provided that the following conditions are
4a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// met:
5a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
6a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions of source code must retain the above copyright
7a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       notice, this list of conditions and the following disclaimer.
8a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Redistributions in binary form must reproduce the above
9a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       copyright notice, this list of conditions and the following
10a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       disclaimer in the documentation and/or other materials provided
11a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       with the distribution.
12a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//     * Neither the name of Google Inc. nor the names of its
13a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       contributors may be used to endorse or promote products derived
14a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//       from this software without specific prior written permission.
15a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block//
16a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
28a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
29a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include <stdlib.h>
30a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
31a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "v8.h"
32a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
33a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ast.h"
34589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "char-predicates-inl.h"
35589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "cctest.h"
36a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "jsregexp.h"
37589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "parser.h"
38a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler.h"
39a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "regexp-macro-assembler-irregexp.h"
40589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "string-stream.h"
41589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch#include "zone-inl.h"
426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifdef V8_INTERPRETED_REGEXP
436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#include "interpreter-irregexp.h"
446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else  // V8_INTERPRETED_REGEXP
453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "macro-assembler.h"
463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "code.h"
47a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef V8_TARGET_ARCH_ARM
483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "arm/assembler-arm.h"
49a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/macro-assembler-arm.h"
50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "arm/regexp-macro-assembler-arm.h"
51a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
5244f0eee88ff00398ff7f715fab053374d808c90dSteve Block#ifdef V8_TARGET_ARCH_MIPS
533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "mips/assembler-mips.h"
5444f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "mips/macro-assembler-mips.h"
5544f0eee88ff00398ff7f715fab053374d808c90dSteve Block#include "mips/regexp-macro-assembler-mips.h"
5644f0eee88ff00398ff7f715fab053374d808c90dSteve Block#endif
57a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef V8_TARGET_ARCH_X64
583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "x64/assembler-x64.h"
59a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "x64/macro-assembler-x64.h"
60a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "x64/regexp-macro-assembler-x64.h"
61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef V8_TARGET_ARCH_IA32
633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#include "ia32/assembler-ia32.h"
64a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ia32/macro-assembler-ia32.h"
65a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#include "ia32/regexp-macro-assembler-ia32.h"
66a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // V8_INTERPRETED_REGEXP
68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
69a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockusing namespace v8::internal;
70a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
71a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
72e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarkestatic bool CheckParse(const char* input) {
73e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  V8::Initialize(NULL);
74e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  v8::HandleScope scope;
75257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
7644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FlatStringReader reader(Isolate::Current(), CStrVector(input));
77e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  RegExpCompileData result;
783e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  return v8::internal::RegExpParser::ParseRegExp(&reader, false, &result);
79e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
80e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
81e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
82589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic SmartArrayPointer<const char> Parse(const char* input) {
83a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
85257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
8644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FlatStringReader reader(Isolate::Current(), CStrVector(input));
87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpCompileData result;
883e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.tree != NULL);
90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.error.is_null());
91589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<const char> output = result.tree->ToString();
92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return output;
93a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
94a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
95a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool CheckSimple(const char* input) {
96a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
97a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
98d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  unibrow::Utf8InputBuffer<> buffer(input, StrLength(input));
99257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
10044f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FlatStringReader reader(Isolate::Current(), CStrVector(input));
101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpCompileData result;
1023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.tree != NULL);
104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.error.is_null());
105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return result.simple;
106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstruct MinMaxPair {
109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int min_match;
110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int max_match;
111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic MinMaxPair CheckMinMaxMatch(const char* input) {
114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
116d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  unibrow::Utf8InputBuffer<> buffer(input, StrLength(input));
117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
11844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FlatStringReader reader(Isolate::Current(), CStrVector(input));
119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpCompileData result;
1203e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  CHECK(v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.tree != NULL);
122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.error.is_null());
123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int min_match = result.tree->min_match();
124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int max_match = result.tree->max_match();
125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  MinMaxPair pair = { min_match, max_match };
126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return pair;
127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
130e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#define CHECK_PARSE_ERROR(input) CHECK(!CheckParse(input))
131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CHECK_PARSE_EQ(input, expected) CHECK_EQ(expected, *Parse(input))
132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CHECK_SIMPLE(input, simple) CHECK_EQ(simple, CheckSimple(input));
133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CHECK_MIN_MAX(input, min, max)                                         \
134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  { MinMaxPair min_max = CheckMinMaxMatch(input);                              \
135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(min, min_max.min_match);                                          \
136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(max, min_max.max_match);                                          \
137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Parser) {
140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
141e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
142e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_ERROR("?");
143e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("abc", "'abc'");
145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("", "%");
146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("abc|def", "(| 'abc' 'def')");
147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("abc|def|ghi", "(| 'abc' 'def' 'ghi')");
148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("^xxx$", "(: @^i 'xxx' @$i)");
149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("ab\\b\\d\\bcd", "(: 'ab' @b [0-9] @b 'cd')");
150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\w|\\d", "(| [0-9 A-Z _ a-z] [0-9])");
151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a*", "(# 0 - g 'a')");
152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a*?", "(# 0 - n 'a')");
153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("abc+", "(: 'ab' (# 1 - g 'c'))");
154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("abc+?", "(: 'ab' (# 1 - n 'c'))");
155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz?", "(: 'xy' (# 0 1 g 'z'))");
156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz??", "(: 'xy' (# 0 1 n 'z'))");
157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{0,1}", "(: 'xy' (# 0 1 g 'z'))");
158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{0,1}?", "(: 'xy' (# 0 1 n 'z'))");
159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{93}", "(: 'xy' (# 93 93 g 'z'))");
160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{93}?", "(: 'xy' (# 93 93 n 'z'))");
161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{1,32}", "(: 'xy' (# 1 32 g 'z'))");
162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{1,32}?", "(: 'xy' (# 1 32 n 'z'))");
163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{1,}", "(: 'xy' (# 1 - g 'z'))");
164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("xyz{1,}?", "(: 'xy' (# 1 - n 'z'))");
165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a\\fb\\nc\\rd\\te\\vf", "'a\\x0cb\\x0ac\\x0dd\\x09e\\x0bf'");
166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a\\nb\\bc", "(: 'a\\x0ab' @b 'c')");
167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?:foo)", "'foo'");
168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?: foo )", "' foo '");
169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(foo|bar|baz)", "(^ (| 'foo' 'bar' 'baz'))");
170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("foo|(bar|baz)|quux", "(| 'foo' (^ (| 'bar' 'baz')) 'quux')");
171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("foo(?=bar)baz", "(: 'foo' (-> + 'bar') 'baz')");
172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("foo(?!bar)baz", "(: 'foo' (-> - 'bar') 'baz')");
173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("()", "(^ %)");
174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?=)", "(-> + %)");
175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[]", "^[\\x00-\\uffff]");   // Doesn't compile on windows
176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[^]", "[\\x00-\\uffff]");   // \uffff isn't in codepage 1252
177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[x]", "[x]");
178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[xyz]", "[x y z]");
179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[a-zA-Z0-9]", "[a-z A-Z 0-9]");
180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[-123]", "[- 1 2 3]");
181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[^123]", "^[1 2 3]");
182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("]", "']'");
183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("}", "'}'");
184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[a-b-c]", "[a-b - c]");
185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\d]", "[0-9]");
186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[x\\dz]", "[x 0-9 z]");
187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\d-z]", "[0-9 - z]");
188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\d-\\d]", "[0-9 - 0-9]");
189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[z-\\d]", "[z - 0-9]");
190086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Control character outside character class.
191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\cj\\cJ\\ci\\cI\\ck\\cK",
192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                 "'\\x0a\\x0a\\x09\\x09\\x0b\\x0b'");
193086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("\\c!", "'\\c!'");
194086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("\\c_", "'\\c_'");
195086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("\\c~", "'\\c~'");
196086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("\\c1", "'\\c1'");
197086aeeaae12517475c22695a200be45495516549Ben Murdoch  // Control character inside character class.
198086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\c!]", "[\\ c !]");
199086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\c_]", "[\\x1f]");
200086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\c~]", "[\\ c ~]");
201086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\ca]", "[\\x01]");
202086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\cz]", "[\\x1a]");
203086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\cA]", "[\\x01]");
204086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\cZ]", "[\\x1a]");
205086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("[\\c1]", "[\\x11]");
206086aeeaae12517475c22695a200be45495516549Ben Murdoch
207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[a\\]c]", "[a ] c]");
208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ", "'[]{}()%^# '");
209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ]", "[[ ] { } ( ) % ^ #  ]");
210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\0", "'\\x00'");
211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\8", "'8'");
212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\9", "'9'");
213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\11", "'\\x09'");
214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\11a", "'\\x09a'");
215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\011", "'\\x09'");
216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\00011", "'\\x0011'");
217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\118", "'\\x098'");
218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\111", "'I'");
219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\1111", "'I1'");
220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\1", "(: (^ 'x') (^ 'x') (^ 'x') (<- 1))");
221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\2", "(: (^ 'x') (^ 'x') (^ 'x') (<- 2))");
222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\3", "(: (^ 'x') (^ 'x') (^ 'x') (<- 3))");
223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\4", "(: (^ 'x') (^ 'x') (^ 'x') '\\x04')");
224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\1*", "(: (^ 'x') (^ 'x') (^ 'x')"
225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               " (# 0 - g (<- 1)))");
226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\2*", "(: (^ 'x') (^ 'x') (^ 'x')"
227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               " (# 0 - g (<- 2)))");
228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\3*", "(: (^ 'x') (^ 'x') (^ 'x')"
229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               " (# 0 - g (<- 3)))");
230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)\\4*", "(: (^ 'x') (^ 'x') (^ 'x')"
231a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                               " (# 0 - g '\\x04'))");
232a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\10",
233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "(: (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x')"
234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              " (^ 'x') (^ 'x') (^ 'x') (^ 'x') (<- 10))");
235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\11",
236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              "(: (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x') (^ 'x')"
237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              " (^ 'x') (^ 'x') (^ 'x') (^ 'x') '\\x09')");
238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(a)\\1", "(: (^ 'a') (<- 1))");
239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(a\\1)", "(^ 'a')");
240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(\\1a)", "(^ 'a')");
241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?=a)?a", "'a'");
242a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?=a){0,10}a", "'a'");
243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?=a){1,10}a", "(: (-> + 'a') 'a')");
244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?=a){9,10}a", "(: (-> + 'a') 'a')");
245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?!a)?a", "'a'");
246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\1(a)", "(^ 'a')");
247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?!(a))\\1", "(: (-> - (^ 'a')) (<- 1))");
248a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("(?!\\1(a\\1)\\1)\\1", "(: (-> - (: (^ 'a') (<- 1))) (<- 1))");
249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\0]", "[\\x00]");
250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\11]", "[\\x09]");
251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\11a]", "[\\x09 a]");
252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\011]", "[\\x09]");
253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\00011]", "[\\x00 1 1]");
254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\118]", "[\\x09 8]");
255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\111]", "[I]");
256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[\\1111]", "[I 1]");
257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\x34", "'\x34'");
258a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\x60", "'\x60'");
259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\x3z", "'x3z'");
260086aeeaae12517475c22695a200be45495516549Ben Murdoch  CHECK_PARSE_EQ("\\c", "'\\c'");
261a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\u0034", "'\x34'");
262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("\\u003z", "'u003z'");
263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("foo[z]*", "(: 'foo' (# 0 - g [z]))");
264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a", true);
266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a|b", false);
267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\n", false);
268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("^a", false);
269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a$", false);
270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\b!", false);
271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\Bb", false);
272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a*", false);
273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a*?", false);
274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a?", false);
275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a??", false);
276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a{0,1}?", false);
277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a{1,1}?", false);
278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a{1,2}?", false);
279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a+?", false);
280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(a)", false);
281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(a)\\1", false);
282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(\\1a)", false);
283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\1(a)", false);
284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\s", false);
285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\S", false);
286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\d", false);
287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\D", false);
288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\w", false);
289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\W", false);
290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a.", false);
291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a\\q", false);
292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a[a]", false);
293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a[^a]", false);
294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a[a-z]", false);
295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a[\\q]", false);
296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a(?:b)", false);
297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a(?=b)", false);
298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("a(?!b)", false);
299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\x60", false);
300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\u0060", false);
301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\cA", false);
302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\q", false);
303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\1112", false);
304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("\\0", false);
305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(a)\\1", false);
306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(?=a)?a", false);
307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(?!a)?a\\1", false);
308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_SIMPLE("(?:(?=a))a\\1", false);
309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{}", "'a{}'");
311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{,}", "'a{,}'");
312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{", "'a{'");
313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{z}", "'a{z}'");
314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{1z}", "'a{1z}'");
315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{12z}", "'a{12z}'");
316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{12,", "'a{12,'");
317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{12,3b", "'a{12,3b'");
318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{}", "'{}'");
319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{,}", "'{,}'");
320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{", "'{'");
321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{z}", "'{z}'");
322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{1z}", "'{1z}'");
323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{12z}", "'{12z}'");
324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{12,", "'{12,'");
325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{12,3b", "'{12,3b'");
326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a", 1, 1);
328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("abc", 3, 3);
329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a[bc]d", 3, 3);
330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a|bc", 1, 2);
331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("ab|c", 1, 2);
332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a||bc", 0, 2);
333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("|", 0, 0);
334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab)", 2, 2);
335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab|cde)", 2, 3);
336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab)|cde", 2, 3);
337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(ab)", 2, 2);
338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(ab|cde)", 2, 3);
339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(ab)\\1", 2, 4);
340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(ab|cde)\\1", 2, 6);
341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab)?", 0, 2);
342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab)*", 0, RegExpTree::kInfinity);
343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab)+", 2, RegExpTree::kInfinity);
344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a?", 0, 1);
345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a*", 0, RegExpTree::kInfinity);
346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a+", 1, RegExpTree::kInfinity);
347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a??", 0, 1);
348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a*?", 0, RegExpTree::kInfinity);
349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a+?", 1, RegExpTree::kInfinity);
350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a?)?", 0, 1);
351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a*)?", 0, RegExpTree::kInfinity);
352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a+)?", 0, RegExpTree::kInfinity);
353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a?)+", 0, RegExpTree::kInfinity);
354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a*)+", 0, RegExpTree::kInfinity);
355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a+)+", 1, RegExpTree::kInfinity);
356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a?)*", 0, RegExpTree::kInfinity);
357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a*)*", 0, RegExpTree::kInfinity);
358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a+)*", 0, RegExpTree::kInfinity);
359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a{0}", 0, 0);
360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a+){0}", 0, 0);
361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a+){0,0}", 0, 0);
362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a*b", 1, RegExpTree::kInfinity);
363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a+b", 2, RegExpTree::kInfinity);
364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a*b|c", 1, RegExpTree::kInfinity);
365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a+b|c", 1, RegExpTree::kInfinity);
366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:a{5,1000000}){3,1000000}", 15, RegExpTree::kInfinity);
367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("(?:ab){4,7}", 8, 14);
368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a\\bc", 2, 2);
369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a\\Bc", 2, 2);
370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a\\sc", 3, 3);
371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a\\Sc", 3, 3);
372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a(?=b)c", 2, 2);
373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a(?=bbb|bb)c", 2, 2);
374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_MIN_MAX("a(?!bbb|bb)c", 2, 2);
375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(ParserRegression) {
378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("[A-Z$-][x]", "(! [A-Z $ -] [x])");
379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a{3,4*}", "(: 'a{3,' (# 0 - g '4') '}')");
380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("{", "'{'");
381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_PARSE_EQ("a|", "(| 'a' %)");
382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void ExpectError(const char* input,
385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                        const char* expected) {
386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
38944f0eee88ff00398ff7f715fab053374d808c90dSteve Block  FlatStringReader reader(Isolate::Current(), CStrVector(input));
390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpCompileData result;
3913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  CHECK(!v8::internal::RegExpParser::ParseRegExp(&reader, false, &result));
392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(result.tree == NULL);
393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!result.error.is_null());
394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<char> str = result.error->ToCString(ALLOW_NULLS);
395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(expected, *str);
396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Errors) {
400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* kEndBackslash = "\\ at end of pattern";
402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("\\", kEndBackslash);
403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* kUnterminatedGroup = "Unterminated group";
404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("(foo", kUnterminatedGroup);
405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* kInvalidGroup = "Invalid group";
406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("(?", kInvalidGroup);
407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* kUnterminatedCharacterClass = "Unterminated character class";
408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("[", kUnterminatedCharacterClass);
409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("[a-", kUnterminatedCharacterClass);
410a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* kNothingToRepeat = "Nothing to repeat";
411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("*", kNothingToRepeat);
412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("?", kNothingToRepeat);
413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("+", kNothingToRepeat);
414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("{1}", kNothingToRepeat);
415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("{1,2}", kNothingToRepeat);
416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError("{1,}", kNothingToRepeat);
417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that we don't allow more than kMaxCapture captures
419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int kMaxCaptures = 1 << 16;  // Must match RegExpParser::kMaxCaptures.
420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const char* kTooManyCaptures = "Too many captures";
421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  HeapStringAllocator allocator;
422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  StringStream accumulator(&allocator);
423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i <= kMaxCaptures; i++) {
424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    accumulator.Add("()");
425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
426589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch  SmartArrayPointer<const char> many_captures(accumulator.ToCString());
427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ExpectError(*many_captures, kTooManyCaptures);
428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IsDigit(uc16 c) {
432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ('0' <= c && c <= '9');
433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NotDigit(uc16 c) {
437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !IsDigit(c);
438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool IsWhiteSpace(uc16 c) {
442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  switch (c) {
443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x09:
444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x0A:
445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x0B:
446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x0C:
447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x0d:
448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x20:
449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0xA0:
450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x2028:
451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    case 0x2029:
4523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch    case 0xFEFF:
453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    default:
455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return unibrow::Space::Is(c);
456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NotWhiteSpace(uc16 c) {
461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !IsWhiteSpace(c);
462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool NotWord(uc16 c) {
466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return !IsRegExpWord(c);
467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void TestCharacterClassEscapes(uc16 c, bool (pred)(uc16 c)) {
471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope scope(Isolate::Current(), DELETE_ON_EXIT);
472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<CharacterRange>* ranges = new ZoneList<CharacterRange>(2);
473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CharacterRange::AddClassEscape(c, ranges);
474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (unsigned i = 0; i < (1 << 16); i++) {
475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool in_class = false;
476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; !in_class && j < ranges->length(); j++) {
477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CharacterRange& range = ranges->at(j);
478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      in_class = (range.from() <= i && i <= range.to());
479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(pred(i), in_class);
481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
482a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
483a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
484a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
485a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(CharacterClassEscapes) {
48644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
487a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('.', IsRegExpNewline);
488a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('d', IsDigit);
489a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('D', NotDigit);
490a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('s', IsWhiteSpace);
491a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('S', NotWhiteSpace);
492a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('w', IsRegExpWord);
493a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestCharacterClassEscapes('W', NotWord);
494a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
495a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
496a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
497a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic RegExpNode* Compile(const char* input, bool multiline, bool is_ascii) {
498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
4998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Isolate* isolate = Isolate::Current();
5008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  FlatStringReader reader(isolate, CStrVector(input));
501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpCompileData compile_data;
5023e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu  if (!v8::internal::RegExpParser::ParseRegExp(&reader, multiline,
5033e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu                                               &compile_data))
504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return NULL;
5058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> pattern = isolate->factory()->
5068b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      NewStringFromUtf8(CStrVector(input));
507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpEngine::Compile(&compile_data, false, multiline, pattern, is_ascii);
508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return compile_data.node;
509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void Execute(const char* input,
513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    bool multiline,
514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    bool is_ascii,
515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                    bool dot_output = false) {
516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope;
517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpNode* node = Compile(input, multiline, is_ascii);
519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  USE(node);
520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG
521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (dot_output) {
522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    RegExpEngine::DotPrint(input, node, false);
523a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    exit(0);
524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif  // DEBUG
526a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass TestConfig {
530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef int Key;
532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  typedef int Value;
533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kNoKey;
5343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  static int NoValue() { return 0; }
535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static inline int Compare(int a, int b) {
536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (a < b)
537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return -1;
538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else if (a > b)
539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 1;
540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    else
541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return 0;
542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
544a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockconst int TestConfig::kNoKey = 0;
547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic unsigned PseudoRandom(int i, int j) {
550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return ~(~((i * 781) ^ (j * 329)));
551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(SplayTreeSimple) {
55544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const unsigned kLimit = 1000;
557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneSplayTree<TestConfig> tree;
559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  bool seen[kLimit];
560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (unsigned i = 0; i < kLimit; i++) seen[i] = false;
561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define CHECK_MAPS_EQUAL() do {                                      \
562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (unsigned k = 0; k < kLimit; k++)                            \
563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK_EQ(seen[k], tree.Find(k, &loc));                         \
564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } while (false)
565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < 50; i++) {
566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < 50; j++) {
567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      unsigned next = PseudoRandom(i, j) % kLimit;
568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (seen[next]) {
569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // We've already seen this one.  Check the value and remove
570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // it.
571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ZoneSplayTree<TestConfig>::Locator loc;
572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(tree.Find(next, &loc));
573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(next, loc.key());
574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(3 * next, loc.value());
575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        tree.Remove(next);
576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        seen[next] = false;
577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_MAPS_EQUAL();
578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      } else {
579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        // Check that it wasn't there already and then add it.
580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ZoneSplayTree<TestConfig>::Locator loc;
581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(!tree.Find(next, &loc));
582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(tree.Insert(next, &loc));
583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(next, loc.key());
584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        loc.set_value(3 * next);
585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        seen[next] = true;
586a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_MAPS_EQUAL();
587a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int val = PseudoRandom(j, i) % kLimit;
589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (seen[val]) {
590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ZoneSplayTree<TestConfig>::Locator loc;
591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(tree.FindGreatestLessThan(val, &loc));
592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(loc.key(), val);
593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      val = PseudoRandom(i + j, i - j) % kLimit;
596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (seen[val]) {
597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        ZoneSplayTree<TestConfig>::Locator loc;
598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK(tree.FindLeastGreaterThan(val, &loc));
599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(loc.key(), val);
600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        break;
601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(DispatchTableConstruction) {
60844f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Initialize test data.
610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kLimit = 1000;
611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kRangeCount = 8;
612a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kRangeSize = 16;
613a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc16 ranges[kRangeCount][2 * kRangeSize];
614a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kRangeCount; i++) {
615a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    Vector<uc16> range(ranges[i], 2 * kRangeSize);
616a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < 2 * kRangeSize; j++) {
617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      range[j] = PseudoRandom(i + 25, j + 87) % kLimit;
618a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    range.Sort();
620a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 1; j < 2 * kRangeSize; j++) {
621a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(range[j-1] <= range[j]);
622a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
623a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
624a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Enter test data into dispatch table.
625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DispatchTable table;
627a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < kRangeCount; i++) {
628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc16* range = ranges[i];
629a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < 2 * kRangeSize; j += 2)
630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      table.AddRange(CharacterRange(range[j], range[j + 1]), i);
631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that the table looks as we would expect
633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int p = 0; p < kLimit; p++) {
634a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    OutSet* outs = table.Get(p);
635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < kRangeCount; j++) {
636a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      uc16* range = ranges[j];
637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      bool is_on = false;
638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int k = 0; !is_on && (k < 2 * kRangeSize); k += 2)
639a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        is_on = (range[k] <= p && p <= range[k + 1]);
640a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK_EQ(is_on, outs->Get(j));
641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
644a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke// Test of debug-only syntax.
646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#ifdef DEBUG
647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTEST(ParsePossessiveRepetition) {
649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  bool old_flag_value = FLAG_regexp_possessive_quantifier;
650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Enable possessive quantifier syntax.
652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  FLAG_regexp_possessive_quantifier = true;
653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_EQ("a*+", "(# 0 - p 'a')");
655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_EQ("a++", "(# 1 - p 'a')");
656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_EQ("a?+", "(# 0 1 p 'a')");
657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_EQ("a{10,20}+", "(# 10 20 p 'a')");
658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_EQ("za{10,20}+b", "(: 'z' (# 10 20 p 'a') 'b')");
659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  // Disable possessive quantifier syntax.
661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  FLAG_regexp_possessive_quantifier = false;
662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_ERROR("a*+");
664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_ERROR("a++");
665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_ERROR("a?+");
666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_ERROR("a{10,20}+");
667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CHECK_PARSE_ERROR("a{10,20}+b");
668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  FLAG_regexp_possessive_quantifier = old_flag_value;
670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
672e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke#endif
673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Tests of interpreter.
675a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
676a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
6776ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#ifndef V8_INTERPRETED_REGEXP
678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
679a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#if V8_TARGET_ARCH_IA32
680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef RegExpMacroAssemblerIA32 ArchRegExpMacroAssembler;
681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_TARGET_ARCH_X64
682a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef RegExpMacroAssemblerX64 ArchRegExpMacroAssembler;
683a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#elif V8_TARGET_ARCH_ARM
684a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blocktypedef RegExpMacroAssemblerARM ArchRegExpMacroAssembler;
6853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#elif V8_TARGET_ARCH_MIPS
68644f0eee88ff00398ff7f715fab053374d808c90dSteve Blocktypedef RegExpMacroAssemblerMIPS ArchRegExpMacroAssembler;
687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif
688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass ContextInitializer {
690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public:
691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer()
692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch      : env_(), scope_(), zone_(Isolate::Current(), DELETE_ON_EXIT) {
693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env_ = v8::Context::New();
694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env_->Enter();
695a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ~ContextInitializer() {
697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env_->Exit();
698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    env_.Dispose();
699a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block private:
701a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::Persistent<v8::Context> env_;
702a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::HandleScope scope_;
703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::internal::ZoneScope zone_;
704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block};
705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
706a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
707a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic ArchRegExpMacroAssembler::Result Execute(Code* code,
708a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                String* input,
709a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                int start_offset,
710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                const byte* input_start,
711a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                                const byte* input_end,
712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                                                int* captures) {
713a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return NativeRegExpMacroAssembler::Execute(
714a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      code,
715a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      input,
716a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      start_offset,
717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      input_start,
718a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      input_end,
71944f0eee88ff00398ff7f715fab053374d808c90dSteve Block      captures,
72044f0eee88ff00398ff7f715fab053374d808c90dSteve Block      Isolate::Current());
721a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
722a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
723a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
724a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeSuccess) {
725a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
726a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
7278b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
728a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
730a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
731a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
732a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7338b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector(""));
734a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
735a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
737a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int captures[4] = {42, 37, 87, 117};
7388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo"));
739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const byte* start_adr =
741a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      reinterpret_cast<const byte*>(seq_input->GetCharsAddress());
742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
743a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
744a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
748a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + seq_input->length(),
749d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              captures);
750a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
751a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
752a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[0]);
753a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[1]);
754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[2]);
755a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[3]);
756a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
757a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
758a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
759a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeSimple) {
760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
7628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
763a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
764a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc16 foo_chars[3] = {'f', 'o', 'o'};
767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector<const uc16> foo(foo_chars, 3);
768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fail;
770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckCharacters(foo, 0, &fail, true);
771a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(3);
773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 0);
774a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
7788b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector("^foo"));
779a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
780a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
781a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
782a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int captures[4] = {42, 37, 87, 117};
7838b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo"));
784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
785a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
786a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
787a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
788a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
793d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              captures);
794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, captures[0]);
797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, captures[1]);
798a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[2]);
799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[3]);
800a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8018b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  input = factory->NewStringFromAscii(CStrVector("barbarbar"));
802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  seq_input = Handle<SeqAsciiString>::cast(input);
803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  start_adr = seq_input->GetCharsAddress();
804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
805a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = Execute(*code,
806a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   *input,
807a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   0,
808a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   start_adr,
809a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   start_adr + input->length(),
810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                   captures);
811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::FAILURE, result);
813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
814a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
815a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
816a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeSimpleUC16) {
817a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
8198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
821a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 4);
822a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
823a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc16 foo_chars[3] = {'f', 'o', 'o'};
824a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector<const uc16> foo(foo_chars, 3);
825a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
826a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fail;
827a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckCharacters(foo, 0, &fail, true);
828a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
829a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(3);
830a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 0);
831a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
834a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8358b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector("^foo"));
836a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
837a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
838a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
839a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int captures[4] = {42, 37, 87, 117};
8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const uc16 input_data[6] = {'f', 'o', 'o', 'f', 'o',
8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                              static_cast<uc16>('\xa0')};
842a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> input =
8438b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
846a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
847a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
848a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
852a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
853d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              captures);
854a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
855a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, captures[0]);
857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, captures[1]);
858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[2]);
859a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, captures[3]);
860a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch  const uc16 input_data2[9] = {'b', 'a', 'r', 'b', 'a', 'r', 'b', 'a',
8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch                               static_cast<uc16>('\xa0')};
8638b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  input = factory->NewStringFromTwoByte(Vector<const uc16>(input_data2, 9));
864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  seq_input = Handle<SeqTwoByteString>::cast(input);
865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  start_adr = seq_input->GetCharsAddress();
866a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
867a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = Execute(*code,
868a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   *input,
869a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   0,
870a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   start_adr,
871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   start_adr + input->length() * 2,
872d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                   captures);
873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
874a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::FAILURE, result);
875a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
876a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeBacktrack) {
879a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
8818b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
882a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
883a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0);
884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
885a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fail;
886a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label backtrack;
887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.LoadCurrentCharacter(10, &fail);
888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushBacktrack(&backtrack);
891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.LoadCurrentCharacter(10, NULL);
892a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&backtrack);
894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
895a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
8968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector(".........."));
897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
899a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> input = factory->NewStringFromAscii(CStrVector("foofoo"));
901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
902a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
903a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
904a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
907a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
909a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
910d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              NULL);
911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
912a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::FAILURE, result);
913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
914a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
915a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
916a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeBackReferenceASCII) {
917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
9198b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
920a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
921a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
923a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
924a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(2);
925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 0);
926a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label nomatch;
927a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReference(0, &nomatch);
928a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&nomatch);
930a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(2);
931a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label missing_match;
932a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReference(0, &missing_match);
933a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(2, 0);
934a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
935a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&missing_match);
936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9388b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector("^(..)..\1"));
939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> input = factory->NewStringFromAscii(CStrVector("fooofo"));
943a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int output[4];
947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
953d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              output);
954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, output[0]);
957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, output[1]);
958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, output[2]);
959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, output[3]);
960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeBackReferenceUC16) {
964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
9668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::UC16, 4);
969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(2);
972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 0);
973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label nomatch;
974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReference(0, &nomatch);
975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&nomatch);
977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(2);
978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label missing_match;
979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReference(0, &missing_match);
980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(2, 0);
981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&missing_match);
983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
9858b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector("^(..)..\1"));
986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const uc16 input_data[6] = {'f', 0x2028, 'o', 'o', 'f', 0x2028};
990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> input =
9918b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromTwoByte(Vector<const uc16>(input_data, 6));
992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqTwoByteString> seq_input = Handle<SeqTwoByteString>::cast(input);
993a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int output[4];
996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  *input,
999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  0,
1000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  start_adr,
1001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                  start_adr + input->length() * 2,
1002d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                  output);
1003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
1005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, output[0]);
1006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, output[1]);
1007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, output[2]);
1008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, output[3]);
1009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblernativeAtStart) {
1014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
1015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
10168b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
1017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0);
1019a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label not_at_start, newline, fail;
1021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotAtStart(&not_at_start);
1022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that prevchar = '\n' and current = 'f'.
1023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckCharacter('\n', &newline);
1024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
1025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&newline);
1027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.LoadCurrentCharacter(0, &fail);
1028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotCharacter('f', &fail);
1029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&not_at_start);
1032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that prevchar = 'o' and current = 'b'.
1033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label prevo;
1034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckCharacter('o', &prevo);
1035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&prevo);
1037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.LoadCurrentCharacter(0, &fail);
1038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotCharacter('b', &fail);
1039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10418b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector("(^f|ob)"));
1042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
1043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
1044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
10458b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> input = factory->NewStringFromAscii(CStrVector("foobar"));
1046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
1047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
1048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
1050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
1051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
1052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
1053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
1054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
1055d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              NULL);
1056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
1058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  result = Execute(*code,
1060a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   *input,
1061a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   3,
1062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   start_adr + 3,
1063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                   start_adr + input->length(),
1064d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke                   NULL);
1065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
1067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1068a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeBackRefNoCase) {
1071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
1072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
10738b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
1074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1075a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 4);
1076a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1077a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fail, succ;
1078a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1079a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
1080a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(2, 0);
1081a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(3);
1082a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(3, 0);
1083a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReferenceIgnoreCase(2, &fail);  // Match "AbC".
1084a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReferenceIgnoreCase(2, &fail);  // Match "ABC".
1085a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label expected_fail;
1086a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReferenceIgnoreCase(2, &expected_fail);
1087a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
1088a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1089a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1090a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&expected_fail);
1091a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(3);  // Skip "xYz"
1092a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReferenceIgnoreCase(2, &succ);
1093a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1094a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1095a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&succ);
1096a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 0);
1097a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1098a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1099a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> source =
11008b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("^(abc)\1\1(?!\1)...(?!\1)"));
1101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
1102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
1103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> input =
11058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("aBcAbCABCxYzab"));
1106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
1107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
1108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1109a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int output[4];
1110a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
1111a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
1112a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
1113a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
1114a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
1115a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
1116d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              output);
1117a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1118a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
1119a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, output[0]);
1120a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(12, output[1]);
1121a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, output[2]);
1122a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, output[3]);
1123a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1124a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1125a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1126a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1127a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeRegisters) {
1128a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
1129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
11308b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = Isolate::Current()->factory();
1131a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1132a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 6);
1133a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1134a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc16 foo_chars[3] = {'f', 'o', 'o'};
1135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector<const uc16> foo(foo_chars, 3);
1136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  enum registers { out1, out2, out3, out4, out5, out6, sp, loop_cnt };
1138a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fail;
1139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label backtrack;
1140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(out1, 0);  // Output: [0]
1141a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushRegister(out1, RegExpMacroAssembler::kNoStackLimitCheck);
1142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushBacktrack(&backtrack);
1143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteStackPointerToRegister(sp);
1144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Fill stack and registers
1145a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(2);
1146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(out1, 0);
1147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushRegister(out1, RegExpMacroAssembler::kNoStackLimitCheck);
1148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushBacktrack(&fail);
1149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Drop backtrack stack frames.
1150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.ReadStackPointerFromRegister(sp);
1151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // And take the first backtrack (to &backtrack)
1152a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Backtrack();
1153a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1154a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushCurrentPosition();
1155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(2);
1156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PopCurrentPosition();
1157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1158a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&backtrack);
1159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PopRegister(out1);
1160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.ReadCurrentPositionFromRegister(out1);
1161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(3);
1162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(out2, 0);  // [0,3]
1163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop;
1165a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.SetRegister(loop_cnt, 0);  // loop counter
1166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&loop);
1167a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceRegister(loop_cnt, 1);
1168a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(1);
1169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.IfRegisterLT(loop_cnt, 3, &loop);
1170a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(out3, 0);  // [0,3,6]
1171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1172a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop2;
1173a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.SetRegister(loop_cnt, 2);  // loop counter
1174a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&loop2);
1175a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceRegister(loop_cnt, -1);
1176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(1);
1177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.IfRegisterGE(loop_cnt, 0, &loop2);
1178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(out4, 0);  // [0,3,6,9]
1179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop3;
1181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label exit_loop3;
1182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushRegister(out4, RegExpMacroAssembler::kNoStackLimitCheck);
1183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushRegister(out4, RegExpMacroAssembler::kNoStackLimitCheck);
1184a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.ReadCurrentPositionFromRegister(out3);
1185a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&loop3);
1186a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(1);
1187a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckGreedyLoop(&exit_loop3);
1188a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.GoTo(&loop3);
1189a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&exit_loop3);
1190a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PopCurrentPosition();
1191a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(out5, 0);  // [0,3,6,9,9,-1]
1192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
1196a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> source =
11998b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("<loop test>"));
1200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
1201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
1202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // String long enough for test (content doesn't matter).
1204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> input =
12058b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("foofoofoofoofoo"));
1206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
1207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
1208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int output[6];
1210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
1211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
1212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
1213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
1214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
1215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
1216d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              output);
1217a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
1219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, output[0]);
1220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, output[1]);
1221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(6, output[2]);
1222a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(9, output[3]);
1223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(9, output[4]);
1224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(-1, output[5]);
1225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1228a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerStackOverflow) {
1229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
1230a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
12318b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Isolate* isolate = Isolate::Current();
12328b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = isolate->factory();
1233a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 0);
1235a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label loop;
1237a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&loop);
1238a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushBacktrack(&loop);
1239a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.GoTo(&loop);
1240a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1241a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> source =
12428b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("<stack overflow test>"));
1243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
1244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
1245a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1246a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // String long enough for test (content doesn't matter).
1247a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> input =
12488b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("dummy"));
1249a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
1250a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
1251a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1252a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
1253a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
1254a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
1255a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
1256a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
1257a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
1258d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              NULL);
1259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1260a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::EXCEPTION, result);
12618b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(isolate->has_pending_exception());
12628b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  isolate->clear_pending_exception();
1263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssemblerNativeLotsOfRegisters) {
1267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  v8::V8::Initialize();
1268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ContextInitializer initializer;
12698b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Isolate* isolate = Isolate::Current();
12708b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = isolate->factory();
1271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ArchRegExpMacroAssembler m(NativeRegExpMacroAssembler::ASCII, 2);
1273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // At least 2048, to ensure the allocated space for registers
1275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // span one full page.
1276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const int large_number = 8000;
1277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(large_number, 42);
1278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
1279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 1);
1280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label done;
1281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckNotBackReference(0, &done);  // Performs a system-stack push.
1282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&done);
1283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushRegister(large_number, RegExpMacroAssembler::kNoStackLimitCheck);
1284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PopRegister(1);
1285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> source =
12888b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("<huge register space test>"));
1289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Object> code_object = m.GetCode(source);
1290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<Code> code = Handle<Code>::cast(code_object);
1291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // String long enough for test (content doesn't matter).
1293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> input =
12948b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromAscii(CStrVector("sample text"));
1295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<SeqAsciiString> seq_input = Handle<SeqAsciiString>::cast(input);
1296a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Address start_adr = seq_input->GetCharsAddress();
1297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int captures[2];
1299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  NativeRegExpMacroAssembler::Result result =
1300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      Execute(*code,
1301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              *input,
1302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              0,
1303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr,
1304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block              start_adr + input->length(),
1305d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke              captures);
1306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1307a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(NativeRegExpMacroAssembler::SUCCESS, result);
1308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, captures[0]);
1309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, captures[1]);
1310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13118b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  isolate->clear_pending_exception();
1312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#else  // V8_INTERPRETED_REGEXP
1315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(MacroAssembler) {
1317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
1318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  byte codes[1024];
1319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  RegExpMacroAssemblerIrregexp m(Vector<byte>(codes, 1024));
1320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // ^f(o)o.
1321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Label fail, fail2, start;
1322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  uc16 foo_chars[3];
1323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo_chars[0] = 'f';
1324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo_chars[1] = 'o';
1325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  foo_chars[2] = 'o';
1326a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector<const uc16> foo(foo_chars, 3);
1327a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.SetRegister(4, 42);
1328a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushRegister(4, RegExpMacroAssembler::kNoStackLimitCheck);
1329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceRegister(4, 42);
1330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.GoTo(&start);
1331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&start);
1333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushBacktrack(&fail2);
1334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.CheckCharacters(foo, 0, &fail, true);
1335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(0, 0);
1336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PushCurrentPosition();
1337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(3);
1338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(1, 0);
1339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PopCurrentPosition();
1340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(1);
1341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(2, 0);
1342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.AdvanceCurrentPosition(1);
1343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.WriteCurrentPositionToRegister(3, 0);
1344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail);
1347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Backtrack();
1348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Succeed();
1349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Bind(&fail2);
1351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.PopRegister(0);
1352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  m.Fail();
1353a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13548b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Isolate* isolate = Isolate::Current();
13558b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Factory* factory = isolate->factory();
13568b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  HandleScope scope(isolate);
1357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13588b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  Handle<String> source = factory->NewStringFromAscii(CStrVector("^f(o)o"));
1359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<ByteArray> array = Handle<ByteArray>::cast(m.GetCode(source));
1360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int captures[5];
1361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const uc16 str1[] = {'f', 'o', 'o', 'b', 'a', 'r'};
1363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> f1_16 =
13648b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromTwoByte(Vector<const uc16>(str1, 6));
1365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13668b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(IrregexpInterpreter::Match(isolate, array, f1_16, captures, 0));
1367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(0, captures[0]);
1368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(3, captures[1]);
1369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(1, captures[2]);
1370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(2, captures[3]);
1371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(84, captures[4]);
1372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  const uc16 str2[] = {'b', 'a', 'r', 'f', 'o', 'o'};
1374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Handle<String> f2_16 =
13758b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch      factory->NewStringFromTwoByte(Vector<const uc16>(str2, 6));
1376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13778b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch  CHECK(!IrregexpInterpreter::Match(isolate, array, f2_16, captures, 0));
1378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(42, captures[0]);
1379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
13816ded16be15dd865a9b21ea304d5273c8be299c87Steve Block#endif  // V8_INTERPRETED_REGEXP
1382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(AddInverseToTable) {
138544f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
1386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kLimit = 1000;
1387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  static const int kRangeCount = 16;
1388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int t = 0; t < 10; t++) {
1389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch    ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    ZoneList<CharacterRange>* ranges =
1391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        new ZoneList<CharacterRange>(kRangeCount);
1392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < kRangeCount; i++) {
1393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int from = PseudoRandom(t + 87, i + 25) % kLimit;
1394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int to = from + (PseudoRandom(i + 87, t + 25) % (kLimit / 20));
1395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      if (to > kLimit) to = kLimit;
1396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      ranges->Add(CharacterRange(from, to));
1397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DispatchTable table;
1399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    DispatchTableConstructor cons(&table, false);
1400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cons.set_choice_index(0);
1401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    cons.AddInverse(ranges);
1402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int i = 0; i < kLimit; i++) {
1403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      bool is_on = false;
1404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int j = 0; !is_on && j < kRangeCount; j++)
1405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        is_on = ranges->at(j).Contains(i);
1406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      OutSet* set = table.Get(i);
1407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK_EQ(is_on, set->Get(0) == false);
1408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1411a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<CharacterRange>* ranges =
1412a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          new ZoneList<CharacterRange>(1);
1413a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ranges->Add(CharacterRange(0xFFF0, 0xFFFE));
1414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DispatchTable table;
1415a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  DispatchTableConstructor cons(&table, false);
1416a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cons.set_choice_index(0);
1417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  cons.AddInverse(ranges);
1418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(!table.Get(0xFFFE)->Get(0));
1419a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK(table.Get(0xFFFF)->Get(0));
1420a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic uc32 canonicalize(uc32 c) {
1424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::uchar canon[unibrow::Ecma262Canonicalize::kMaxWidth];
1425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = unibrow::Ecma262Canonicalize::Convert(c, '\0', canon, NULL);
1426a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (count == 0) {
1427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return c;
1428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, count);
1430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return canon[0];
1431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(LatinCanonicalize) {
1436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> un_canonicalize;
1437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (char lower = 'a'; lower <= 'z'; lower++) {
1438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    char upper = lower + ('A' - 'a');
1439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(canonicalize(lower), canonicalize(upper));
1440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unibrow::uchar uncanon[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1441a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int length = un_canonicalize.get(lower, '\0', uncanon);
1442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(2, length);
1443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(upper, uncanon[0]);
1444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(lower, uncanon[1]);
1445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (uc32 c = 128; c < (1 << 21); c++)
1447a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_GE(canonicalize(c), 128);
1448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::Mapping<unibrow::ToUppercase> to_upper;
1449bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  // Canonicalization is only defined for the Basic Multilingual Plane.
1450bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  for (uc32 c = 0; c < (1 << 16); c++) {
1451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    unibrow::uchar upper[unibrow::ToUppercase::kMaxWidth];
1452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int length = to_upper.get(c, '\0', upper);
1453a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (length == 0) {
1454a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      length = 1;
1455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      upper[0] = c;
1456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    uc32 u = upper[0];
1458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (length > 1 || (c >= 128 && u < 128))
1459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      u = c;
1460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(u, canonicalize(c));
1461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1465bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdochstatic uc32 CanonRangeEnd(uc32 c) {
1466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::uchar canon[unibrow::CanonicalizationRange::kMaxWidth];
1467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = unibrow::CanonicalizationRange::Convert(c, '\0', canon, NULL);
1468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (count == 0) {
1469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return c;
1470a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  } else {
1471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(1, count);
1472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return canon[0];
1473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1474a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1475a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1476a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1477a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(RangeCanonicalization) {
1478a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Check that we arrive at the same result when using the basic
1479a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // range canonicalization primitives as when using immediate
1480a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // canonicalization.
1481a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> un_canonicalize;
1482bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  int block_start = 0;
1483bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch  while (block_start <= 0xFFFF) {
1484bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    uc32 block_end = CanonRangeEnd(block_start);
1485bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    unsigned block_length = block_end - block_start + 1;
1486bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    if (block_length > 1) {
1487bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      unibrow::uchar first[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1488bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      int first_length = un_canonicalize.get(block_start, '\0', first);
1489bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch      for (unsigned i = 1; i < block_length; i++) {
1490bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        unibrow::uchar succ[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1491bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        int succ_length = un_canonicalize.get(block_start + i, '\0', succ);
1492bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        CHECK_EQ(first_length, succ_length);
1493bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        for (int j = 0; j < succ_length; j++) {
1494bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          int calc = first[j] + i;
1495bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          int found = succ[j];
1496bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch          CHECK_EQ(calc, found);
1497bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch        }
1498a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1499a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1500bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch    block_start = block_start + block_length;
1501a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1502a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1503a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1504a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1505a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(UncanonicalizeEquivalence) {
1506a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::Mapping<unibrow::Ecma262UnCanonicalize> un_canonicalize;
1507a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1508a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < (1 << 16); i++) {
1509a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    int length = un_canonicalize.get(i, '\0', chars);
1510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    for (int j = 0; j < length; j++) {
1511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      unibrow::uchar chars2[unibrow::Ecma262UnCanonicalize::kMaxWidth];
1512a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      int length2 = un_canonicalize.get(chars[j], '\0', chars2);
1513a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK_EQ(length, length2);
1514a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int k = 0; k < length; k++)
1515a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        CHECK_EQ(static_cast<int>(chars[k]), static_cast<int>(chars2[k]));
1516a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1517a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1518a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1519a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1520a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1521a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void TestRangeCaseIndependence(CharacterRange input,
1522a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                      Vector<CharacterRange> expected) {
1523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1524a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  int count = expected.length();
1525a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(count);
1526d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block  input.AddCaseEquivalents(list, false);
1527a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CHECK_EQ(count, list->length());
1528a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < list->length(); i++) {
1529a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(expected[i].from(), list->at(i).from());
1530a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CHECK_EQ(expected[i].to(), list->at(i).to());
1531a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1532a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1533a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1534a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1535a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void TestSimpleRangeCaseIndependence(CharacterRange input,
1536a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                            CharacterRange expected) {
1537a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  EmbeddedVector<CharacterRange, 1> vector;
1538a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  vector[0] = expected;
1539a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestRangeCaseIndependence(input, vector);
1540a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1541a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1542a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1543a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(CharacterRangeCaseIndependence) {
154444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
1545a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange::Singleton('a'),
1546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange::Singleton('A'));
1547a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange::Singleton('z'),
1548a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange::Singleton('Z'));
1549a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('a', 'z'),
1550a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('A', 'Z'));
1551a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('c', 'f'),
1552a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('C', 'F'));
1553a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('a', 'b'),
1554a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('A', 'B'));
1555a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('y', 'z'),
1556a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('Y', 'Z'));
1557a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('a' - 1, 'z' + 1),
1558a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('A', 'Z'));
1559a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('A', 'Z'),
1560a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('a', 'z'));
1561a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('C', 'F'),
1562a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('c', 'f'));
1563a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('A' - 1, 'Z' + 1),
1564a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('a', 'z'));
1565a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // Here we need to add [l-z] to complete the case independence of
1566a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // [A-Za-z] but we expect [a-z] to be added since we always add a
1567a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  // whole block at a time.
1568a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  TestSimpleRangeCaseIndependence(CharacterRange('A', 'k'),
1569a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block                                  CharacterRange('a', 'z'));
1570a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1571a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1573a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic bool InClass(uc16 c, ZoneList<CharacterRange>* ranges) {
1574a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  if (ranges == NULL)
1575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    return false;
1576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < ranges->length(); i++) {
1577a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    CharacterRange range = ranges->at(i);
1578a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (range.from() <= c && c <= range.to())
1579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      return true;
1580a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1581a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  return false;
1582a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1583a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1584a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1585a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(CharClassDifference) {
158644f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
1587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1588a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<CharacterRange>* base = new ZoneList<CharacterRange>(1);
1589a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  base->Add(CharacterRange::Everything());
1590a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  Vector<const uc16> overlay = CharacterRange::GetWordBounds();
1591a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<CharacterRange>* included = NULL;
1592a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  ZoneList<CharacterRange>* excluded = NULL;
1593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  CharacterRange::Split(base, overlay, &included, &excluded);
1594a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  for (int i = 0; i < (1 << 16); i++) {
1595a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    bool in_base = InClass(i, base);
1596a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    if (in_base) {
1597a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      bool in_overlay = false;
1598a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      for (int j = 0; !in_overlay && j < overlay.length(); j += 2) {
1599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block        if (overlay[j] <= i && i <= overlay[j+1])
1600a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block          in_overlay = true;
1601a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      }
1602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK_EQ(in_overlay, InClass(i, included));
1603a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK_EQ(!in_overlay, InClass(i, excluded));
1604a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    } else {
1605a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(!InClass(i, included));
1606a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block      CHECK(!InClass(i, excluded));
1607a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block    }
1608a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  }
1609a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1610a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1611a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block
1612e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon ClarkeTEST(CanonicalizeCharacterSets) {
161344f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope scope(Isolate::Current(), DELETE_ON_EXIT);
1615e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ZoneList<CharacterRange>* list = new ZoneList<CharacterRange>(4);
1616e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  CharacterSet set(list);
1617e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1618e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(10, 20));
1619e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(30, 40));
1620e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(50, 60));
1621e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  set.Canonicalize();
1622e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(3, list->length());
1623e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(10, list->at(0).from());
1624e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(20, list->at(0).to());
1625e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(30, list->at(1).from());
1626e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(40, list->at(1).to());
1627e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(50, list->at(2).from());
1628e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(60, list->at(2).to());
1629e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1630e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Rewind(0);
1631e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(10, 20));
1632e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(50, 60));
1633e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(30, 40));
1634e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  set.Canonicalize();
1635e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(3, list->length());
1636e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(10, list->at(0).from());
1637e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(20, list->at(0).to());
1638e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(30, list->at(1).from());
1639e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(40, list->at(1).to());
1640e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(50, list->at(2).from());
1641e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(60, list->at(2).to());
1642e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1643e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Rewind(0);
1644e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(30, 40));
1645e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(10, 20));
1646e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(25, 25));
1647e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(100, 100));
1648e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(1, 1));
1649e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  set.Canonicalize();
1650e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(5, list->length());
1651e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, list->at(0).from());
1652e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, list->at(0).to());
1653e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(10, list->at(1).from());
1654e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(20, list->at(1).to());
1655e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(25, list->at(2).from());
1656e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(25, list->at(2).to());
1657e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(30, list->at(3).from());
1658e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(40, list->at(3).to());
1659e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(100, list->at(4).from());
1660e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(100, list->at(4).to());
1661e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1662e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Rewind(0);
1663e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(10, 19));
1664e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(21, 30));
1665e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  list->Add(CharacterRange(20, 20));
1666e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  set.Canonicalize();
1667e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(1, list->length());
1668e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(10, list->at(0).from());
1669e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  ASSERT_EQ(30, list->at(0).to());
1670e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke}
1671e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1672d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke// Checks whether a character is in the set represented by a list of ranges.
1673d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarkestatic bool CharacterInSet(ZoneList<CharacterRange>* set, uc16 value) {
1674d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < set->length(); i++) {
1675d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CharacterRange range = set->at(i);
1676d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    if (range.from() <= value && value <= range.to()) {
1677d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke      return true;
1678d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    }
1679d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1680d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  return false;
1681d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1682d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1683d91b9f7d46489a9ee00f9cb415630299c76a502bLeon ClarkeTEST(CharacterRangeMerge) {
168444f0eee88ff00398ff7f715fab053374d808c90dSteve Block  v8::internal::V8::Initialize(NULL);
1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch  ZoneScope zone_scope(Isolate::Current(), DELETE_ON_EXIT);
1686d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ZoneList<CharacterRange> l1(4);
1687d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ZoneList<CharacterRange> l2(4);
1688d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Create all combinations of intersections of ranges, both singletons and
1689d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // longer.
1690d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1691d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  int offset = 0;
1692d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1693d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The five kinds of singleton intersections:
1694d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //     X
1695d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //   Y      - outside before
1696d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    Y     - outside touching start
1697d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //     Y    - overlap
1698d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //      Y   - outside touching end
1699d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //       Y  - outside after
1700d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1701d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < 5; i++) {
1702d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l1.Add(CharacterRange::Singleton(offset + 2));
1703d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l2.Add(CharacterRange::Singleton(offset + i));
1704d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    offset += 6;
1705d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1706d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1707d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The seven kinds of singleton/non-singleton intersections:
1708d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    XXX
1709d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //  Y        - outside before
1710d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //   Y       - outside touching start
1711d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //    Y      - inside touching start
1712d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //     Y     - entirely inside
1713d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //      Y    - inside touching end
1714d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //       Y   - outside touching end
1715d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //        Y  - disjoint after
1716d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1717d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < 7; i++) {
1718d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l1.Add(CharacterRange::Range(offset + 2, offset + 4));
1719d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l2.Add(CharacterRange::Singleton(offset + i));
1720d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    offset += 8;
1721d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1722d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1723d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // The eleven kinds of non-singleton intersections:
1724d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //
1725d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //       XXXXXXXX
1726d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // YYYY                  - outside before.
1727d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //   YYYY                - outside touching start.
1728d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //     YYYY              - overlapping start
1729d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //       YYYY            - inside touching start
1730d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //         YYYY          - entirely inside
1731d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //           YYYY        - inside touching end
1732d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //             YYYY      - overlapping end
1733d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //               YYYY    - outside touching end
1734d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //                 YYYY  - outside after
1735d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //       YYYYYYYY        - identical
1736d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //     YYYYYYYYYYYY      - containing entirely.
1737d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1738d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < 9; i++) {
1739d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l1.Add(CharacterRange::Range(offset + 6, offset + 15));  // Length 8.
1740d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l2.Add(CharacterRange::Range(offset + 2 * i, offset + 2 * i + 3));
1741d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    offset += 22;
1742d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1743d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  l1.Add(CharacterRange::Range(offset + 6, offset + 15));
1744d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  l2.Add(CharacterRange::Range(offset + 6, offset + 15));
1745d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  offset += 22;
1746d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  l1.Add(CharacterRange::Range(offset + 6, offset + 15));
1747d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  l2.Add(CharacterRange::Range(offset + 4, offset + 17));
1748d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  offset += 22;
1749d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1750d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Different kinds of multi-range overlap:
1751d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // XXXXXXXXXXXXXXXXXXXXXX         XXXXXXXXXXXXXXXXXXXXXX
1752d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  //   YYYY  Y  YYYY  Y  YYYY  Y  YYYY  Y  YYYY  Y  YYYY  Y
1753d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1754d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  l1.Add(CharacterRange::Range(offset, offset + 21));
1755d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  l1.Add(CharacterRange::Range(offset + 31, offset + 52));
1756d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (int i = 0; i < 6; i++) {
1757d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l2.Add(CharacterRange::Range(offset + 2, offset + 5));
1758d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    l2.Add(CharacterRange::Singleton(offset + 8));
1759d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    offset += 9;
1760d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1761d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1762d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(CharacterRange::IsCanonical(&l1));
1763d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ASSERT(CharacterRange::IsCanonical(&l2));
1764d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1765d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ZoneList<CharacterRange> first_only(4);
1766d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ZoneList<CharacterRange> second_only(4);
1767d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ZoneList<CharacterRange> both(4);
1768d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1769d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Merge one direction.
1770d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CharacterRange::Merge(&l1, &l2, &first_only, &second_only, &both);
1771d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1772d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&first_only));
1773d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&second_only));
1774d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&both));
1775d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1776d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (uc16 i = 0; i < offset; i++) {
1777d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_first = CharacterInSet(&l1, i);
1778d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_second = CharacterInSet(&l2, i);
1779d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((in_first && !in_second) == CharacterInSet(&first_only, i));
1780d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((!in_first && in_second) == CharacterInSet(&second_only, i));
1781d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((in_first && in_second) == CharacterInSet(&both, i));
1782d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1783d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1784d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  first_only.Clear();
1785d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  second_only.Clear();
1786d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  both.Clear();
1787d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1788d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Merge other direction.
1789d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CharacterRange::Merge(&l2, &l1, &second_only, &first_only, &both);
1790d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1791d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&first_only));
1792d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&second_only));
1793d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&both));
1794d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1795d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (uc16 i = 0; i < offset; i++) {
1796d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_first = CharacterInSet(&l1, i);
1797d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_second = CharacterInSet(&l2, i);
1798d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((in_first && !in_second) == CharacterInSet(&first_only, i));
1799d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((!in_first && in_second) == CharacterInSet(&second_only, i));
1800d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((in_first && in_second) == CharacterInSet(&both, i));
1801d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1802d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1803d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  first_only.Clear();
1804d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  second_only.Clear();
1805d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  both.Clear();
1806d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1807d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Merge but don't record all combinations.
1808d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CharacterRange::Merge(&l1, &l2, NULL, NULL, &both);
1809d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1810d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&both));
1811d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1812d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (uc16 i = 0; i < offset; i++) {
1813d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_first = CharacterInSet(&l1, i);
1814d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_second = CharacterInSet(&l2, i);
1815d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((in_first && in_second) == CharacterInSet(&both, i));
1816d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1817d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1818d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  // Merge into same set.
1819d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  ZoneList<CharacterRange> all(4);
1820d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CharacterRange::Merge(&l1, &l2, &all, &all, &all);
1821d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1822d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  CHECK(CharacterRange::IsCanonical(&all));
1823d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke
1824d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  for (uc16 i = 0; i < offset; i++) {
1825d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_first = CharacterInSet(&l1, i);
1826d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    bool in_second = CharacterInSet(&l2, i);
1827d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke    CHECK((in_first || in_second) == CharacterInSet(&all, i));
1828d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke  }
1829d91b9f7d46489a9ee00f9cb415630299c76a502bLeon Clarke}
1830e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1831e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke
1832a7e24c173cf37484693b9abb38e494fa7bd7baebSteve BlockTEST(Graph) {
1833a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block  V8::Initialize(NULL);
1834e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke  Execute("\\b\\w+\\b", false, true, true);
1835a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}
1836