Introduce ENABLE_LATIN_1 compile flag
Mostly a bunch of renaming when flag is disabled. R=yangguo@chromium.org BUG= Review URL: https://chromiumcodereview.appspot.com/11759008 Patch from Dan Carney <dcarney@google.com>. git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13340 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9188bb67f2
commit
45f20e366a
@ -66,6 +66,8 @@
|
||||
# Default arch variant for MIPS.
|
||||
'mips_arch_variant%': 'mips32r2',
|
||||
|
||||
'v8_enable_latin_1%': 0,
|
||||
|
||||
'v8_enable_debugger_support%': 1,
|
||||
|
||||
'v8_enable_backtrace%': 0,
|
||||
@ -107,6 +109,9 @@
|
||||
},
|
||||
'target_defaults': {
|
||||
'conditions': [
|
||||
['v8_enable_latin_1==1', {
|
||||
'defines': ['ENABLE_LATIN_1',],
|
||||
}],
|
||||
['v8_enable_debugger_support==1', {
|
||||
'defines': ['ENABLE_DEBUGGER_SUPPORT',],
|
||||
}],
|
||||
|
@ -3124,7 +3124,7 @@ Local<String> v8::Object::ObjectProtoToString() {
|
||||
|
||||
} else {
|
||||
i::Handle<i::String> class_name = i::Handle<i::String>::cast(name);
|
||||
if (class_name->IsEqualTo(i::CStrVector("Arguments"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Arguments"))) {
|
||||
return v8::String::New("[object Object]");
|
||||
|
||||
} else {
|
||||
@ -4145,7 +4145,7 @@ int String::WriteAscii(char* buffer,
|
||||
FlattenString(str); // Flatten the string for efficiency.
|
||||
}
|
||||
|
||||
if (str->IsOneByteRepresentation()) {
|
||||
if (str->HasOnlyAsciiChars()) {
|
||||
// WriteToFlat is faster than using the StringCharacterStream.
|
||||
if (length == -1) length = str->length() + 1;
|
||||
int len = i::Min(length, str->length() - start);
|
||||
@ -5183,14 +5183,14 @@ void v8::Date::DateTimeConfigurationChangeNotification() {
|
||||
|
||||
|
||||
static i::Handle<i::String> RegExpFlagsToString(RegExp::Flags flags) {
|
||||
char flags_buf[3];
|
||||
uint8_t flags_buf[3];
|
||||
int num_flags = 0;
|
||||
if ((flags & RegExp::kGlobal) != 0) flags_buf[num_flags++] = 'g';
|
||||
if ((flags & RegExp::kMultiline) != 0) flags_buf[num_flags++] = 'm';
|
||||
if ((flags & RegExp::kIgnoreCase) != 0) flags_buf[num_flags++] = 'i';
|
||||
ASSERT(num_flags <= static_cast<int>(ARRAY_SIZE(flags_buf)));
|
||||
return FACTORY->LookupOneByteSymbol(
|
||||
i::Vector<const char>(flags_buf, num_flags));
|
||||
i::Vector<const uint8_t>(flags_buf, num_flags));
|
||||
}
|
||||
|
||||
|
||||
|
@ -5661,10 +5661,10 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
// Fast case of Heap::LookupSingleCharacterStringFromCode.
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
STATIC_ASSERT(kSmiShiftSize == 0);
|
||||
ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
|
||||
ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1));
|
||||
__ tst(code_,
|
||||
Operand(kSmiTagMask |
|
||||
((~String::kMaxAsciiCharCode) << kSmiTagSize)));
|
||||
((~String::kMaxOneByteCharCode) << kSmiTagSize)));
|
||||
__ b(ne, &slow_case_);
|
||||
|
||||
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
|
||||
|
@ -138,7 +138,7 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ stop("stop-at");
|
||||
}
|
||||
#endif
|
||||
|
@ -121,7 +121,7 @@ bool LCodeGen::GeneratePrologue() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ stop("stop_at");
|
||||
}
|
||||
#endif
|
||||
@ -2562,7 +2562,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
|
||||
__ JumpIfSmi(input, is_false);
|
||||
|
||||
if (class_name->IsEqualTo(CStrVector("Function"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) {
|
||||
// Assuming the following assertions, we can use the same compares to test
|
||||
// for both being a function type and being in the object type range.
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
@ -2593,7 +2593,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ CompareObjectType(temp, temp2, temp2, JS_FUNCTION_TYPE);
|
||||
if (class_name->IsEqualTo(CStrVector("Object"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) {
|
||||
__ b(ne, is_true);
|
||||
} else {
|
||||
__ b(ne, is_false);
|
||||
@ -4625,7 +4625,7 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
ASSERT(!char_code.is(result));
|
||||
|
||||
__ cmp(char_code, Operand(String::kMaxAsciiCharCode));
|
||||
__ cmp(char_code, Operand(String::kMaxOneByteCharCode));
|
||||
__ b(hi, deferred->entry());
|
||||
__ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
|
||||
__ add(result, result, Operand(char_code, LSL, kPointerSizeLog2));
|
||||
|
@ -261,7 +261,7 @@ void RegExpMacroAssemblerARM::CheckCharacters(Vector<const uc16> str,
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
if (mode_ == ASCII) {
|
||||
__ ldrb(r1, MemOperand(r0, char_size(), PostIndex));
|
||||
ASSERT(str[i] <= String::kMaxAsciiCharCode);
|
||||
ASSERT(str[i] <= String::kMaxOneByteCharCode);
|
||||
__ cmp(r1, Operand(str[i]));
|
||||
} else {
|
||||
__ ldrh(r1, MemOperand(r0, char_size(), PostIndex));
|
||||
@ -508,7 +508,7 @@ void RegExpMacroAssemblerARM::CheckBitInTable(
|
||||
Handle<ByteArray> table,
|
||||
Label* on_bit_set) {
|
||||
__ mov(r0, Operand(table));
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) {
|
||||
__ and_(r1, current_character(), Operand(kTableSize - 1));
|
||||
__ add(r1, r1, Operand(ByteArray::kHeaderSize - kHeapObjectTag));
|
||||
} else {
|
||||
|
@ -1083,8 +1083,9 @@ void AstConstructionVisitor::VisitCallRuntime(CallRuntime* node) {
|
||||
// optimize them.
|
||||
add_flag(kDontInline);
|
||||
} else if (node->function()->intrinsic_type == Runtime::INLINE &&
|
||||
(node->name()->IsEqualTo(CStrVector("_ArgumentsLength")) ||
|
||||
node->name()->IsEqualTo(CStrVector("_Arguments")))) {
|
||||
(node->name()->IsOneByteEqualTo(
|
||||
STATIC_ASCII_VECTOR("_ArgumentsLength")) ||
|
||||
node->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_Arguments")))) {
|
||||
// Don't inline the %_ArgumentsLength or %_Arguments because their
|
||||
// implementation will not work. There is no stack frame to get them
|
||||
// from.
|
||||
|
@ -499,7 +499,8 @@ Handle<JSFunction> Genesis::CreateEmptyFunction(Isolate* isolate) {
|
||||
Builtins::kEmptyFunction));
|
||||
empty_function->set_code(*code);
|
||||
empty_function->shared()->set_code(*code);
|
||||
Handle<String> source = factory->NewStringFromAscii(CStrVector("() {}"));
|
||||
Handle<String> source =
|
||||
factory->NewStringFromOneByte(STATIC_ASCII_VECTOR("() {}"));
|
||||
Handle<Script> script = factory->NewScript(source);
|
||||
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
|
||||
empty_function->shared()->set_script(*script);
|
||||
|
@ -55,7 +55,7 @@ class SourceCodeCache BASE_EMBEDDED {
|
||||
bool Lookup(Vector<const char> name, Handle<SharedFunctionInfo>* handle) {
|
||||
for (int i = 0; i < cache_->length(); i+=2) {
|
||||
SeqOneByteString* str = SeqOneByteString::cast(cache_->get(i));
|
||||
if (str->IsEqualTo(name)) {
|
||||
if (str->IsUtf8EqualTo(name)) {
|
||||
*handle = Handle<SharedFunctionInfo>(
|
||||
SharedFunctionInfo::cast(cache_->get(i + 1)));
|
||||
return true;
|
||||
|
@ -174,7 +174,7 @@ bool CodeGenerator::ShouldGenerateLog(Expression* type) {
|
||||
}
|
||||
Handle<String> name = Handle<String>::cast(type->AsLiteral()->handle());
|
||||
if (FLAG_log_regexp) {
|
||||
if (name->IsEqualTo(CStrVector("regexp")))
|
||||
if (name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("regexp")))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -316,8 +316,8 @@ OptimizingCompiler::Status OptimizingCompiler::CreateGraph() {
|
||||
if (*FLAG_hydrogen_filter != '\0') {
|
||||
Vector<const char> filter = CStrVector(FLAG_hydrogen_filter);
|
||||
if ((filter[0] == '-'
|
||||
&& name->IsEqualTo(filter.SubVector(1, filter.length())))
|
||||
|| (filter[0] != '-' && !name->IsEqualTo(filter))) {
|
||||
&& name->IsUtf8EqualTo(filter.SubVector(1, filter.length())))
|
||||
|| (filter[0] != '-' && !name->IsUtf8EqualTo(filter))) {
|
||||
info()->SetCode(code);
|
||||
return SetLastStatus(BAILED_OUT);
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ Handle<String> Factory::LookupSymbol(Handle<String> string) {
|
||||
String);
|
||||
}
|
||||
|
||||
Handle<String> Factory::LookupOneByteSymbol(Vector<const char> string) {
|
||||
Handle<String> Factory::LookupOneByteSymbol(Vector<const uint8_t> string) {
|
||||
CALL_HEAP_FUNCTION(isolate(),
|
||||
isolate()->heap()->LookupOneByteSymbol(string),
|
||||
String);
|
||||
@ -196,8 +196,8 @@ Handle<String> Factory::LookupTwoByteSymbol(Vector<const uc16> string) {
|
||||
}
|
||||
|
||||
|
||||
Handle<String> Factory::NewStringFromAscii(Vector<const char> string,
|
||||
PretenureFlag pretenure) {
|
||||
Handle<String> Factory::NewStringFromOneByte(Vector<const uint8_t> string,
|
||||
PretenureFlag pretenure) {
|
||||
CALL_HEAP_FUNCTION(
|
||||
isolate(),
|
||||
isolate()->heap()->AllocateStringFromOneByte(string, pretenure),
|
||||
|
@ -84,7 +84,7 @@ class Factory {
|
||||
return LookupUtf8Symbol(CStrVector(str));
|
||||
}
|
||||
Handle<String> LookupSymbol(Handle<String> str);
|
||||
Handle<String> LookupOneByteSymbol(Vector<const char> str);
|
||||
Handle<String> LookupOneByteSymbol(Vector<const uint8_t> str);
|
||||
Handle<String> LookupOneByteSymbol(Handle<SeqOneByteString>,
|
||||
int from,
|
||||
int length);
|
||||
@ -113,9 +113,15 @@ class Factory {
|
||||
// two byte.
|
||||
//
|
||||
// ASCII strings are pretenured when used as keys in the SourceCodeCache.
|
||||
Handle<String> NewStringFromAscii(
|
||||
Vector<const char> str,
|
||||
Handle<String> NewStringFromOneByte(
|
||||
Vector<const uint8_t> str,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
// TODO(dcarney): remove this function.
|
||||
inline Handle<String> NewStringFromAscii(
|
||||
Vector<const char> str,
|
||||
PretenureFlag pretenure = NOT_TENURED) {
|
||||
return NewStringFromOneByte(Vector<const uint8_t>::cast(str), pretenure);
|
||||
}
|
||||
|
||||
// UTF8 strings are pretenured when used for regexp literal patterns and
|
||||
// flags in the parser.
|
||||
|
@ -253,15 +253,13 @@ const int kBinary32ExponentShift = 23;
|
||||
// other bits set.
|
||||
const uint64_t kQuietNaNMask = static_cast<uint64_t>(0xfff) << 51;
|
||||
|
||||
// ASCII/UTF-16 constants
|
||||
// Latin1/UTF-16 constants
|
||||
// Code-point values in Unicode 4.0 are 21 bits wide.
|
||||
// Code units in UTF-16 are 16 bits wide.
|
||||
typedef uint16_t uc16;
|
||||
typedef int32_t uc32;
|
||||
const int kASCIISize = kCharSize;
|
||||
const int kOneByteSize = kCharSize;
|
||||
const int kUC16Size = sizeof(uc16); // NOLINT
|
||||
const uc32 kMaxAsciiCharCode = 0x7f;
|
||||
const uint32_t kMaxAsciiCharCodeU = 0x7fu;
|
||||
|
||||
|
||||
// The expression OFFSET_OF(type, field) computes the byte-offset
|
||||
|
@ -112,10 +112,12 @@ bool inline Heap::IsOneByte(String* str, int chars) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateSymbol(Vector<const char> str,
|
||||
int chars,
|
||||
uint32_t hash_field) {
|
||||
if (IsOneByte(str, chars)) return AllocateAsciiSymbol(str, hash_field);
|
||||
MaybeObject* Heap::AllocateSymbolFromUtf8(Vector<const char> str,
|
||||
int chars,
|
||||
uint32_t hash_field) {
|
||||
if (IsOneByte(str, chars)) {
|
||||
return AllocateOneByteSymbol(Vector<const uint8_t>::cast(str), hash_field);
|
||||
}
|
||||
return AllocateInternalSymbol<false>(str, chars, hash_field);
|
||||
}
|
||||
|
||||
@ -129,7 +131,7 @@ MaybeObject* Heap::AllocateInternalSymbol(T t, int chars, uint32_t hash_field) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateAsciiSymbol(Vector<const char> str,
|
||||
MaybeObject* Heap::AllocateOneByteSymbol(Vector<const uint8_t> str,
|
||||
uint32_t hash_field) {
|
||||
if (str.length() > SeqOneByteString::kMaxLength) {
|
||||
return Failure::OutOfMemoryException();
|
||||
|
57
src/heap.cc
57
src/heap.cc
@ -2785,7 +2785,7 @@ bool Heap::CreateInitialObjects() {
|
||||
// hash code in place. The hash code for the hidden_symbol is zero to ensure
|
||||
// that it will always be at the first entry in property descriptors.
|
||||
{ MaybeObject* maybe_obj =
|
||||
AllocateSymbol(CStrVector(""), 0, String::kEmptyStringHash);
|
||||
AllocateOneByteSymbol(OneByteVector("", 0), String::kEmptyStringHash);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
hidden_symbol_ = String::cast(obj);
|
||||
@ -2838,9 +2838,9 @@ bool Heap::CreateInitialObjects() {
|
||||
}
|
||||
set_number_string_cache(FixedArray::cast(obj));
|
||||
|
||||
// Allocate cache for single character ASCII strings.
|
||||
// Allocate cache for single character one byte strings.
|
||||
{ MaybeObject* maybe_obj =
|
||||
AllocateFixedArray(String::kMaxAsciiCharCode + 1, TENURED);
|
||||
AllocateFixedArray(String::kMaxOneByteCharCode + 1, TENURED);
|
||||
if (!maybe_obj->ToObject(&obj)) return false;
|
||||
}
|
||||
set_single_character_string_cache(FixedArray::cast(obj));
|
||||
@ -3309,9 +3309,9 @@ MUST_USE_RESULT static inline MaybeObject* MakeOrFindTwoCharacterString(
|
||||
return symbol;
|
||||
// Now we know the length is 2, we might as well make use of that fact
|
||||
// when building the new string.
|
||||
} else if (static_cast<unsigned>(c1 | c2) <= String::kMaxAsciiCharCodeU) {
|
||||
} else if (static_cast<unsigned>(c1 | c2) <= String::kMaxOneByteCharCodeU) {
|
||||
// We can do this.
|
||||
ASSERT(IsPowerOf2(String::kMaxAsciiCharCodeU + 1)); // because of this.
|
||||
ASSERT(IsPowerOf2(String::kMaxOneByteCharCodeU + 1)); // because of this.
|
||||
Object* result;
|
||||
{ MaybeObject* maybe_result = heap->AllocateRawOneByteString(2);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
@ -3355,10 +3355,9 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
|
||||
return MakeOrFindTwoCharacterString(this, c1, c2);
|
||||
}
|
||||
|
||||
bool first_is_ascii = first->IsOneByteRepresentation();
|
||||
bool second_is_ascii = second->IsOneByteRepresentation();
|
||||
bool is_ascii = first_is_ascii && second_is_ascii;
|
||||
|
||||
bool first_is_one_byte = first->IsOneByteRepresentation();
|
||||
bool second_is_one_byte = second->IsOneByteRepresentation();
|
||||
bool is_one_byte = first_is_one_byte && second_is_one_byte;
|
||||
// Make sure that an out of memory exception is thrown if the length
|
||||
// of the new cons string is too large.
|
||||
if (length > String::kMaxLength || length < 0) {
|
||||
@ -3367,7 +3366,7 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
|
||||
}
|
||||
|
||||
bool is_ascii_data_in_two_byte_string = false;
|
||||
if (!is_ascii) {
|
||||
if (!is_one_byte) {
|
||||
// At least one of the strings uses two-byte representation so we
|
||||
// can't use the fast case code for short ASCII strings below, but
|
||||
// we can try to save memory if all chars actually fit in ASCII.
|
||||
@ -3384,7 +3383,7 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
|
||||
STATIC_ASSERT(ConsString::kMinLength <= SlicedString::kMinLength);
|
||||
ASSERT(first->IsFlat());
|
||||
ASSERT(second->IsFlat());
|
||||
if (is_ascii) {
|
||||
if (is_one_byte) {
|
||||
Object* result;
|
||||
{ MaybeObject* maybe_result = AllocateRawOneByteString(length);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
@ -3433,7 +3432,7 @@ MaybeObject* Heap::AllocateConsString(String* first, String* second) {
|
||||
}
|
||||
}
|
||||
|
||||
Map* map = (is_ascii || is_ascii_data_in_two_byte_string) ?
|
||||
Map* map = (is_one_byte || is_ascii_data_in_two_byte_string) ?
|
||||
cons_ascii_string_map() : cons_string_map();
|
||||
|
||||
Object* result;
|
||||
@ -3481,15 +3480,15 @@ MaybeObject* Heap::AllocateSubString(String* buffer,
|
||||
// WriteToFlat takes care of the case when an indirect string has a
|
||||
// different encoding from its underlying string. These encodings may
|
||||
// differ because of externalization.
|
||||
bool is_ascii = buffer->IsOneByteRepresentation();
|
||||
{ MaybeObject* maybe_result = is_ascii
|
||||
bool is_one_byte = buffer->IsOneByteRepresentation();
|
||||
{ MaybeObject* maybe_result = is_one_byte
|
||||
? AllocateRawOneByteString(length, pretenure)
|
||||
: AllocateRawTwoByteString(length, pretenure);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
}
|
||||
String* string_result = String::cast(result);
|
||||
// Copy the characters into the new object.
|
||||
if (is_ascii) {
|
||||
if (is_one_byte) {
|
||||
ASSERT(string_result->IsOneByteRepresentation());
|
||||
char* dest = SeqOneByteString::cast(string_result)->GetChars();
|
||||
String::WriteToFlat(buffer, dest, start, end);
|
||||
@ -3580,11 +3579,11 @@ MaybeObject* Heap::AllocateExternalStringFromTwoByte(
|
||||
}
|
||||
|
||||
// For small strings we check whether the resource contains only
|
||||
// ASCII characters. If yes, we use a different string map.
|
||||
// one byte characters. If yes, we use a different string map.
|
||||
static const size_t kAsciiCheckLengthLimit = 32;
|
||||
bool is_ascii = length <= kAsciiCheckLengthLimit &&
|
||||
String::IsAscii(resource->data(), static_cast<int>(length));
|
||||
Map* map = is_ascii ?
|
||||
bool is_one_byte = length <= kAsciiCheckLengthLimit &&
|
||||
String::IsOneByte(resource->data(), static_cast<int>(length));
|
||||
Map* map = is_one_byte ?
|
||||
external_string_with_ascii_data_map() : external_string_map();
|
||||
Object* result;
|
||||
{ MaybeObject* maybe_result = Allocate(map, NEW_SPACE);
|
||||
@ -3601,15 +3600,15 @@ MaybeObject* Heap::AllocateExternalStringFromTwoByte(
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupSingleCharacterStringFromCode(uint16_t code) {
|
||||
if (code <= String::kMaxAsciiCharCode) {
|
||||
if (code <= String::kMaxOneByteCharCode) {
|
||||
Object* value = single_character_string_cache()->get(code);
|
||||
if (value != undefined_value()) return value;
|
||||
|
||||
char buffer[1];
|
||||
buffer[0] = static_cast<char>(code);
|
||||
uint8_t buffer[1];
|
||||
buffer[0] = static_cast<uint8_t>(code);
|
||||
Object* result;
|
||||
MaybeObject* maybe_result =
|
||||
LookupOneByteSymbol(Vector<const char>(buffer, 1));
|
||||
LookupOneByteSymbol(Vector<const uint8_t>(buffer, 1));
|
||||
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
single_character_string_cache()->set(code, result);
|
||||
@ -4520,7 +4519,7 @@ MaybeObject* Heap::ReinitializeJSGlobalProxy(JSFunction* constructor,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::AllocateStringFromOneByte(Vector<const char> string,
|
||||
MaybeObject* Heap::AllocateStringFromOneByte(Vector<const uint8_t> string,
|
||||
PretenureFlag pretenure) {
|
||||
int length = string.length();
|
||||
if (length == 1) {
|
||||
@ -4533,7 +4532,9 @@ MaybeObject* Heap::AllocateStringFromOneByte(Vector<const char> string,
|
||||
}
|
||||
|
||||
// Copy the characters into the new object.
|
||||
CopyChars(SeqOneByteString::cast(result)->GetChars(), string.start(), length);
|
||||
CopyChars(SeqOneByteString::cast(result)->GetCharsU(),
|
||||
string.start(),
|
||||
length);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -4579,11 +4580,11 @@ MaybeObject* Heap::AllocateStringFromTwoByte(Vector<const uc16> string,
|
||||
int length = string.length();
|
||||
const uc16* start = string.start();
|
||||
|
||||
if (String::IsAscii(start, length)) {
|
||||
if (String::IsOneByte(start, length)) {
|
||||
MaybeObject* maybe_result = AllocateRawOneByteString(length, pretenure);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
CopyChars(SeqOneByteString::cast(result)->GetChars(), start, length);
|
||||
} else { // It's not an ASCII string.
|
||||
} else { // It's not a one byte string.
|
||||
MaybeObject* maybe_result = AllocateRawTwoByteString(length, pretenure);
|
||||
if (!maybe_result->ToObject(&result)) return maybe_result;
|
||||
CopyChars(SeqTwoByteString::cast(result)->GetChars(), start, length);
|
||||
@ -5628,7 +5629,7 @@ MaybeObject* Heap::LookupUtf8Symbol(Vector<const char> string) {
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* Heap::LookupOneByteSymbol(Vector<const char> string) {
|
||||
MaybeObject* Heap::LookupOneByteSymbol(Vector<const uint8_t> string) {
|
||||
Object* symbol = NULL;
|
||||
Object* new_table;
|
||||
{ MaybeObject* maybe_new_table =
|
||||
|
22
src/heap.h
22
src/heap.h
@ -699,8 +699,15 @@ class Heap {
|
||||
// failed.
|
||||
// Please note this does not perform a garbage collection.
|
||||
MUST_USE_RESULT MaybeObject* AllocateStringFromOneByte(
|
||||
Vector<const char> str,
|
||||
Vector<const uint8_t> str,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
// TODO(dcarney): remove this function.
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateStringFromOneByte(
|
||||
Vector<const char> str,
|
||||
PretenureFlag pretenure = NOT_TENURED) {
|
||||
return AllocateStringFromOneByte(Vector<const uint8_t>::cast(str),
|
||||
pretenure);
|
||||
}
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateStringFromUtf8(
|
||||
Vector<const char> str,
|
||||
PretenureFlag pretenure = NOT_TENURED);
|
||||
@ -716,12 +723,13 @@ class Heap {
|
||||
// Returns Failure::RetryAfterGC(requested_bytes, space) if the allocation
|
||||
// failed.
|
||||
// Please note this function does not perform a garbage collection.
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateSymbol(Vector<const char> str,
|
||||
int chars,
|
||||
uint32_t hash_field);
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateSymbolFromUtf8(
|
||||
Vector<const char> str,
|
||||
int chars,
|
||||
uint32_t hash_field);
|
||||
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateAsciiSymbol(
|
||||
Vector<const char> str,
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateOneByteSymbol(
|
||||
Vector<const uint8_t> str,
|
||||
uint32_t hash_field);
|
||||
|
||||
MUST_USE_RESULT inline MaybeObject* AllocateTwoByteSymbol(
|
||||
@ -1038,7 +1046,7 @@ class Heap {
|
||||
MUST_USE_RESULT MaybeObject* LookupUtf8Symbol(const char* str) {
|
||||
return LookupUtf8Symbol(CStrVector(str));
|
||||
}
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(Vector<const char> str);
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(Vector<const uint8_t> str);
|
||||
MUST_USE_RESULT MaybeObject* LookupTwoByteSymbol(Vector<const uc16> str);
|
||||
MUST_USE_RESULT MaybeObject* LookupSymbol(String* str);
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(
|
||||
|
@ -6606,7 +6606,7 @@ bool HOptimizedGraphBuilder::TryArgumentsAccess(Property* expr) {
|
||||
HInstruction* result = NULL;
|
||||
if (expr->key()->IsPropertyName()) {
|
||||
Handle<String> name = expr->key()->AsLiteral()->AsPropertyName();
|
||||
if (!name->IsEqualTo(CStrVector("length"))) return false;
|
||||
if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("length"))) return false;
|
||||
|
||||
if (function_state()->outer() == NULL) {
|
||||
HInstruction* elements = AddInstruction(
|
||||
@ -8502,7 +8502,9 @@ static bool IsClassOfTest(CompareOperation* expr) {
|
||||
Literal* literal = expr->right()->AsLiteral();
|
||||
if (literal == NULL) return false;
|
||||
if (!literal->handle()->IsString()) return false;
|
||||
if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
|
||||
if (!call->name()->IsOneByteEqualTo(STATIC_ASCII_VECTOR("_ClassOf"))) {
|
||||
return false;
|
||||
}
|
||||
ASSERT(call->arguments()->length() == 1);
|
||||
return true;
|
||||
}
|
||||
|
@ -5501,10 +5501,10 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
// Fast case of Heap::LookupSingleCharacterStringFromCode.
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
STATIC_ASSERT(kSmiShiftSize == 0);
|
||||
ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
|
||||
ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1));
|
||||
__ test(code_,
|
||||
Immediate(kSmiTagMask |
|
||||
((~String::kMaxAsciiCharCode) << kSmiTagSize)));
|
||||
((~String::kMaxOneByteCharCode) << kSmiTagSize)));
|
||||
__ j(not_zero, &slow_case_);
|
||||
|
||||
Factory* factory = masm->isolate()->factory();
|
||||
|
@ -127,7 +127,7 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ int3();
|
||||
}
|
||||
#endif
|
||||
|
@ -135,7 +135,7 @@ bool LCodeGen::GeneratePrologue() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ int3();
|
||||
}
|
||||
#endif
|
||||
@ -2411,7 +2411,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
ASSERT(!temp.is(temp2));
|
||||
__ JumpIfSmi(input, is_false);
|
||||
|
||||
if (class_name->IsEqualTo(CStrVector("Function"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) {
|
||||
// Assuming the following assertions, we can use the same compares to test
|
||||
// for both being a function type and being in the object type range.
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
@ -2441,7 +2441,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
__ mov(temp, FieldOperand(temp, Map::kConstructorOffset));
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ CmpObjectType(temp, JS_FUNCTION_TYPE, temp2);
|
||||
if (class_name->IsEqualTo(CStrVector("Object"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) {
|
||||
__ j(not_equal, is_true);
|
||||
} else {
|
||||
__ j(not_equal, is_false);
|
||||
@ -4432,7 +4432,7 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
ASSERT(!char_code.is(result));
|
||||
|
||||
__ cmp(char_code, String::kMaxAsciiCharCode);
|
||||
__ cmp(char_code, String::kMaxOneByteCharCode);
|
||||
__ j(above, deferred->entry());
|
||||
__ Set(result, Immediate(factory()->single_character_string_cache()));
|
||||
__ mov(result, FieldOperand(result,
|
||||
|
@ -217,7 +217,7 @@ void RegExpMacroAssemblerIA32::CheckCharacters(Vector<const uc16> str,
|
||||
// If input is ASCII, don't even bother calling here if the string to
|
||||
// match contains a non-ASCII character.
|
||||
if (mode_ == ASCII) {
|
||||
ASSERT(String::IsAscii(str.start(), str.length()));
|
||||
ASSERT(String::IsOneByte(str.start(), str.length()));
|
||||
}
|
||||
#endif
|
||||
int byte_length = str.length() * char_size();
|
||||
@ -569,7 +569,7 @@ void RegExpMacroAssemblerIA32::CheckBitInTable(
|
||||
Label* on_bit_set) {
|
||||
__ mov(eax, Immediate(table));
|
||||
Register index = current_character();
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) {
|
||||
__ mov(ebx, kTableSize - 1);
|
||||
__ and_(ebx, current_character());
|
||||
index = ebx;
|
||||
|
@ -526,7 +526,7 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
|
||||
// in the ASCII sink.
|
||||
if (sizeof(SinkChar) == kUC16Size ||
|
||||
seq_ascii ||
|
||||
c0_ <= kMaxAsciiCharCode) {
|
||||
c0_ <= String::kMaxOneByteCharCode) {
|
||||
SeqStringSet(seq_str, count++, c0_);
|
||||
Advance();
|
||||
} else {
|
||||
@ -566,7 +566,8 @@ Handle<String> JsonParser<seq_ascii>::SlowScanJsonString(
|
||||
}
|
||||
value = value * 16 + digit;
|
||||
}
|
||||
if (sizeof(SinkChar) == kUC16Size || value <= kMaxAsciiCharCode) {
|
||||
if (sizeof(SinkChar) == kUC16Size ||
|
||||
value <= String::kMaxOneByteCharCode) {
|
||||
SeqStringSet(seq_str, count++, value);
|
||||
break;
|
||||
} else {
|
||||
@ -649,8 +650,8 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
int length = position - position_;
|
||||
uint32_t hash = (length <= String::kMaxHashCalcLength)
|
||||
? StringHasher::GetHashCore(running_hash) : length;
|
||||
Vector<const char> string_vector(
|
||||
seq_source_->GetChars() + position_, length);
|
||||
Vector<const uint8_t> string_vector(
|
||||
seq_source_->GetCharsU() + position_, length);
|
||||
SymbolTable* symbol_table = isolate()->heap()->symbol_table();
|
||||
uint32_t capacity = symbol_table->Capacity();
|
||||
uint32_t entry = SymbolTable::FirstProbe(hash, capacity);
|
||||
@ -662,7 +663,7 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
break;
|
||||
}
|
||||
if (element != isolate()->heap()->the_hole_value() &&
|
||||
String::cast(element)->IsAsciiEqualTo(string_vector)) {
|
||||
String::cast(element)->IsOneByteEqualTo(string_vector)) {
|
||||
// Lookup success, update the current position.
|
||||
position_ = position;
|
||||
// Advance past the last '"'.
|
||||
@ -679,7 +680,7 @@ Handle<String> JsonParser<seq_ascii>::ScanJsonString() {
|
||||
// Check for control character (0x00-0x1f) or unterminated string (<0).
|
||||
if (c0_ < 0x20) return Handle<String>::null();
|
||||
if (c0_ != '\\') {
|
||||
if (seq_ascii || c0_ <= kMaxAsciiCharCode) {
|
||||
if (seq_ascii || c0_ <= String::kMaxOneByteCharCode) {
|
||||
Advance();
|
||||
} else {
|
||||
return SlowScanJsonString<SeqTwoByteString, uc16>(source_,
|
||||
|
112
src/jsregexp.cc
112
src/jsregexp.cc
@ -1681,7 +1681,7 @@ static int GetCaseIndependentLetters(Isolate* isolate,
|
||||
letters[0] = character;
|
||||
length = 1;
|
||||
}
|
||||
if (!ascii_subject || character <= String::kMaxAsciiCharCode) {
|
||||
if (!ascii_subject || character <= String::kMaxOneByteCharCode) {
|
||||
return length;
|
||||
}
|
||||
// The standard requires that non-ASCII characters cannot have ASCII
|
||||
@ -1732,7 +1732,7 @@ static inline bool EmitAtomNonLetter(Isolate* isolate,
|
||||
bool checked = false;
|
||||
// We handle the length > 1 case in a later pass.
|
||||
if (length == 1) {
|
||||
if (ascii && c > String::kMaxAsciiCharCodeU) {
|
||||
if (ascii && c > String::kMaxOneByteCharCodeU) {
|
||||
// Can't match - see above.
|
||||
return false; // Bounds not checked.
|
||||
}
|
||||
@ -1753,7 +1753,7 @@ static bool ShortCutEmitCharacterPair(RegExpMacroAssembler* macro_assembler,
|
||||
Label* on_failure) {
|
||||
uc16 char_mask;
|
||||
if (ascii) {
|
||||
char_mask = String::kMaxAsciiCharCode;
|
||||
char_mask = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
char_mask = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -2007,7 +2007,7 @@ static void SplitSearchSpace(ZoneList<int>* ranges,
|
||||
// range with a single not-taken branch, speeding up this important
|
||||
// character range (even non-ASCII charset-based text has spaces and
|
||||
// punctuation).
|
||||
if (*border - 1 > String::kMaxAsciiCharCode && // ASCII case.
|
||||
if (*border - 1 > String::kMaxOneByteCharCode && // ASCII case.
|
||||
end_index - start_index > (*new_start_index - start_index) * 2 &&
|
||||
last - first > kSize * 2 &&
|
||||
binary_chop_index > *new_start_index &&
|
||||
@ -2211,7 +2211,7 @@ static void EmitCharClass(RegExpMacroAssembler* macro_assembler,
|
||||
|
||||
int max_char;
|
||||
if (ascii) {
|
||||
max_char = String::kMaxAsciiCharCode;
|
||||
max_char = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
max_char = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -2513,7 +2513,7 @@ bool QuickCheckDetails::Rationalize(bool asc) {
|
||||
bool found_useful_op = false;
|
||||
uint32_t char_mask;
|
||||
if (asc) {
|
||||
char_mask = String::kMaxAsciiCharCode;
|
||||
char_mask = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
char_mask = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -2522,7 +2522,7 @@ bool QuickCheckDetails::Rationalize(bool asc) {
|
||||
int char_shift = 0;
|
||||
for (int i = 0; i < characters_; i++) {
|
||||
Position* pos = &positions_[i];
|
||||
if ((pos->mask & String::kMaxAsciiCharCode) != 0) {
|
||||
if ((pos->mask & String::kMaxOneByteCharCode) != 0) {
|
||||
found_useful_op = true;
|
||||
}
|
||||
mask_ |= (pos->mask & char_mask) << char_shift;
|
||||
@ -2565,7 +2565,7 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
|
||||
// load so the value is already masked down.
|
||||
uint32_t char_mask;
|
||||
if (compiler->ascii()) {
|
||||
char_mask = String::kMaxAsciiCharCode;
|
||||
char_mask = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
char_mask = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -2575,7 +2575,11 @@ bool RegExpNode::EmitQuickCheck(RegExpCompiler* compiler,
|
||||
// For 2-character preloads in ASCII mode or 1-character preloads in
|
||||
// TWO_BYTE mode we also use a 16 bit load with zero extend.
|
||||
if (details->characters() == 2 && compiler->ascii()) {
|
||||
if ((mask & 0x7f7f) == 0x7f7f) need_mask = false;
|
||||
#ifndef ENABLE_LATIN_1
|
||||
if ((mask & 0x7f7f) == 0xffff) need_mask = false;
|
||||
#else
|
||||
if ((mask & 0xffff) == 0xffff) need_mask = false;
|
||||
#endif
|
||||
} else if (details->characters() == 1 && !compiler->ascii()) {
|
||||
if ((mask & 0xffff) == 0xffff) need_mask = false;
|
||||
} else {
|
||||
@ -2617,7 +2621,7 @@ void TextNode::GetQuickCheckDetails(QuickCheckDetails* details,
|
||||
int characters = details->characters();
|
||||
int char_mask;
|
||||
if (compiler->ascii()) {
|
||||
char_mask = String::kMaxAsciiCharCode;
|
||||
char_mask = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
char_mask = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -2834,24 +2838,24 @@ class VisitMarker {
|
||||
};
|
||||
|
||||
|
||||
RegExpNode* SeqRegExpNode::FilterASCII(int depth) {
|
||||
RegExpNode* SeqRegExpNode::FilterASCII(int depth, bool ignore_case) {
|
||||
if (info()->replacement_calculated) return replacement();
|
||||
if (depth < 0) return this;
|
||||
ASSERT(!info()->visited);
|
||||
VisitMarker marker(info());
|
||||
return FilterSuccessor(depth - 1);
|
||||
return FilterSuccessor(depth - 1, ignore_case);
|
||||
}
|
||||
|
||||
|
||||
RegExpNode* SeqRegExpNode::FilterSuccessor(int depth) {
|
||||
RegExpNode* next = on_success_->FilterASCII(depth - 1);
|
||||
RegExpNode* SeqRegExpNode::FilterSuccessor(int depth, bool ignore_case) {
|
||||
RegExpNode* next = on_success_->FilterASCII(depth - 1, ignore_case);
|
||||
if (next == NULL) return set_replacement(NULL);
|
||||
on_success_ = next;
|
||||
return set_replacement(this);
|
||||
}
|
||||
|
||||
|
||||
RegExpNode* TextNode::FilterASCII(int depth) {
|
||||
RegExpNode* TextNode::FilterASCII(int depth, bool ignore_case) {
|
||||
if (info()->replacement_calculated) return replacement();
|
||||
if (depth < 0) return this;
|
||||
ASSERT(!info()->visited);
|
||||
@ -2862,15 +2866,40 @@ RegExpNode* TextNode::FilterASCII(int depth) {
|
||||
if (elm.type == TextElement::ATOM) {
|
||||
Vector<const uc16> quarks = elm.data.u_atom->data();
|
||||
for (int j = 0; j < quarks.length(); j++) {
|
||||
// We don't need special handling for case independence
|
||||
// because of the rule that case independence cannot make
|
||||
// a non-ASCII character match an ASCII character.
|
||||
if (quarks[j] > String::kMaxAsciiCharCode) {
|
||||
#ifndef ENABLE_LATIN_1
|
||||
if (quarks[j] > String::kMaxOneByteCharCode) {
|
||||
return set_replacement(NULL);
|
||||
}
|
||||
#else
|
||||
if (quarks[j] <= String::kMaxOneByteCharCode) continue;
|
||||
if (!ignore_case) return set_replacement(NULL);
|
||||
// Here, we need to check for characters whose upper and lower cases
|
||||
// are outside the Latin-1 range.
|
||||
// TODO(dcarney): Replace this code with a simple
|
||||
// table lookup in unibrow::Latin-1.
|
||||
// TODO(dcarney): Test cases!.
|
||||
unibrow::uchar result;
|
||||
int chars;
|
||||
chars = unibrow::ToLowercase::Convert(quarks[j], 0, &result, NULL);
|
||||
if (chars > 1 ||
|
||||
(chars == 1 && result <= String::kMaxOneByteCharCodeU)) {
|
||||
continue;
|
||||
}
|
||||
chars = unibrow::ToUppercase::Convert(quarks[j], 0, &result, NULL);
|
||||
if (chars > 1 ||
|
||||
(chars == 1 && result <= String::kMaxOneByteCharCodeU)) {
|
||||
continue;
|
||||
}
|
||||
// This character is definitely not in the Latin-1 range.
|
||||
return set_replacement(NULL);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
ASSERT(elm.type == TextElement::CHAR_CLASS);
|
||||
#ifdef ENABLE_LATIN_1
|
||||
// TODO(dcarney): Can this be improved?
|
||||
if (ignore_case) continue;
|
||||
#endif
|
||||
RegExpCharacterClass* cc = elm.data.u_char_class;
|
||||
ZoneList<CharacterRange>* ranges = cc->ranges(zone());
|
||||
if (!CharacterRange::IsCanonical(ranges)) {
|
||||
@ -2881,39 +2910,40 @@ RegExpNode* TextNode::FilterASCII(int depth) {
|
||||
if (cc->is_negated()) {
|
||||
if (range_count != 0 &&
|
||||
ranges->at(0).from() == 0 &&
|
||||
ranges->at(0).to() >= String::kMaxAsciiCharCode) {
|
||||
ranges->at(0).to() >= String::kMaxOneByteCharCode) {
|
||||
return set_replacement(NULL);
|
||||
}
|
||||
} else {
|
||||
if (range_count == 0 ||
|
||||
ranges->at(0).from() > String::kMaxAsciiCharCode) {
|
||||
ranges->at(0).from() > String::kMaxOneByteCharCode) {
|
||||
return set_replacement(NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return FilterSuccessor(depth - 1);
|
||||
return FilterSuccessor(depth - 1, ignore_case);
|
||||
}
|
||||
|
||||
|
||||
RegExpNode* LoopChoiceNode::FilterASCII(int depth) {
|
||||
RegExpNode* LoopChoiceNode::FilterASCII(int depth, bool ignore_case) {
|
||||
if (info()->replacement_calculated) return replacement();
|
||||
if (depth < 0) return this;
|
||||
if (info()->visited) return this;
|
||||
{
|
||||
VisitMarker marker(info());
|
||||
|
||||
RegExpNode* continue_replacement = continue_node_->FilterASCII(depth - 1);
|
||||
RegExpNode* continue_replacement =
|
||||
continue_node_->FilterASCII(depth - 1, ignore_case);
|
||||
// If we can't continue after the loop then there is no sense in doing the
|
||||
// loop.
|
||||
if (continue_replacement == NULL) return set_replacement(NULL);
|
||||
}
|
||||
|
||||
return ChoiceNode::FilterASCII(depth - 1);
|
||||
return ChoiceNode::FilterASCII(depth - 1, ignore_case);
|
||||
}
|
||||
|
||||
|
||||
RegExpNode* ChoiceNode::FilterASCII(int depth) {
|
||||
RegExpNode* ChoiceNode::FilterASCII(int depth, bool ignore_case) {
|
||||
if (info()->replacement_calculated) return replacement();
|
||||
if (depth < 0) return this;
|
||||
if (info()->visited) return this;
|
||||
@ -2932,7 +2962,8 @@ RegExpNode* ChoiceNode::FilterASCII(int depth) {
|
||||
RegExpNode* survivor = NULL;
|
||||
for (int i = 0; i < choice_count; i++) {
|
||||
GuardedAlternative alternative = alternatives_->at(i);
|
||||
RegExpNode* replacement = alternative.node()->FilterASCII(depth - 1);
|
||||
RegExpNode* replacement =
|
||||
alternative.node()->FilterASCII(depth - 1, ignore_case);
|
||||
ASSERT(replacement != this); // No missing EMPTY_MATCH_CHECK.
|
||||
if (replacement != NULL) {
|
||||
alternatives_->at(i).set_node(replacement);
|
||||
@ -2952,7 +2983,7 @@ RegExpNode* ChoiceNode::FilterASCII(int depth) {
|
||||
new(zone()) ZoneList<GuardedAlternative>(surviving, zone());
|
||||
for (int i = 0; i < choice_count; i++) {
|
||||
RegExpNode* replacement =
|
||||
alternatives_->at(i).node()->FilterASCII(depth - 1);
|
||||
alternatives_->at(i).node()->FilterASCII(depth - 1, ignore_case);
|
||||
if (replacement != NULL) {
|
||||
alternatives_->at(i).set_node(replacement);
|
||||
new_alternatives->Add(alternatives_->at(i), zone());
|
||||
@ -2963,7 +2994,8 @@ RegExpNode* ChoiceNode::FilterASCII(int depth) {
|
||||
}
|
||||
|
||||
|
||||
RegExpNode* NegativeLookaheadChoiceNode::FilterASCII(int depth) {
|
||||
RegExpNode* NegativeLookaheadChoiceNode::FilterASCII(int depth,
|
||||
bool ignore_case) {
|
||||
if (info()->replacement_calculated) return replacement();
|
||||
if (depth < 0) return this;
|
||||
if (info()->visited) return this;
|
||||
@ -2971,12 +3003,12 @@ RegExpNode* NegativeLookaheadChoiceNode::FilterASCII(int depth) {
|
||||
// Alternative 0 is the negative lookahead, alternative 1 is what comes
|
||||
// afterwards.
|
||||
RegExpNode* node = alternatives_->at(1).node();
|
||||
RegExpNode* replacement = node->FilterASCII(depth - 1);
|
||||
RegExpNode* replacement = node->FilterASCII(depth - 1, ignore_case);
|
||||
if (replacement == NULL) return set_replacement(NULL);
|
||||
alternatives_->at(1).set_node(replacement);
|
||||
|
||||
RegExpNode* neg_node = alternatives_->at(0).node();
|
||||
RegExpNode* neg_replacement = neg_node->FilterASCII(depth - 1);
|
||||
RegExpNode* neg_replacement = neg_node->FilterASCII(depth - 1, ignore_case);
|
||||
// If the negative lookahead is always going to fail then
|
||||
// we don't need to check it.
|
||||
if (neg_replacement == NULL) return set_replacement(replacement);
|
||||
@ -3299,7 +3331,7 @@ void TextNode::TextEmitPass(RegExpCompiler* compiler,
|
||||
switch (pass) {
|
||||
case NON_ASCII_MATCH:
|
||||
ASSERT(ascii);
|
||||
if (quarks[j] > String::kMaxAsciiCharCode) {
|
||||
if (quarks[j] > String::kMaxOneByteCharCode) {
|
||||
assembler->GoTo(backtrack);
|
||||
return;
|
||||
}
|
||||
@ -3498,7 +3530,7 @@ RegExpNode* TextNode::GetSuccessorOfOmnivorousTextNode(
|
||||
if (ranges->length() != 1) return NULL;
|
||||
uint32_t max_char;
|
||||
if (compiler->ascii()) {
|
||||
max_char = String::kMaxAsciiCharCode;
|
||||
max_char = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
max_char = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -3698,7 +3730,7 @@ BoyerMooreLookahead::BoyerMooreLookahead(
|
||||
: length_(length),
|
||||
compiler_(compiler) {
|
||||
if (compiler->ascii()) {
|
||||
max_char_ = String::kMaxAsciiCharCode;
|
||||
max_char_ = String::kMaxOneByteCharCode;
|
||||
} else {
|
||||
max_char_ = String::kMaxUtf16CodeUnit;
|
||||
}
|
||||
@ -5337,8 +5369,8 @@ void CharacterRange::AddCaseEquivalents(ZoneList<CharacterRange>* ranges,
|
||||
uc16 bottom = from();
|
||||
uc16 top = to();
|
||||
if (is_ascii) {
|
||||
if (bottom > String::kMaxAsciiCharCode) return;
|
||||
if (top > String::kMaxAsciiCharCode) top = String::kMaxAsciiCharCode;
|
||||
if (bottom > String::kMaxOneByteCharCode) return;
|
||||
if (top > String::kMaxOneByteCharCode) top = String::kMaxOneByteCharCode;
|
||||
}
|
||||
unibrow::uchar chars[unibrow::Ecma262UnCanonicalize::kMaxWidth];
|
||||
if (top == bottom) {
|
||||
@ -5885,7 +5917,7 @@ void TextNode::FillInBMInfo(int initial_offset,
|
||||
int length = GetCaseIndependentLetters(
|
||||
ISOLATE,
|
||||
character,
|
||||
bm->max_char() == String::kMaxAsciiCharCode,
|
||||
bm->max_char() == String::kMaxOneByteCharCode,
|
||||
chars);
|
||||
for (int j = 0; j < length; j++) {
|
||||
bm->Set(offset, chars[j]);
|
||||
@ -6099,10 +6131,12 @@ RegExpEngine::CompilationResult RegExpEngine::Compile(
|
||||
}
|
||||
}
|
||||
if (is_ascii) {
|
||||
node = node->FilterASCII(RegExpCompiler::kMaxRecursion);
|
||||
node = node->FilterASCII(RegExpCompiler::kMaxRecursion, ignore_case);
|
||||
// Do it again to propagate the new nodes to places where they were not
|
||||
// put because they had not been calculated yet.
|
||||
if (node != NULL) node = node->FilterASCII(RegExpCompiler::kMaxRecursion);
|
||||
if (node != NULL) {
|
||||
node = node->FilterASCII(RegExpCompiler::kMaxRecursion, ignore_case);
|
||||
}
|
||||
}
|
||||
|
||||
if (node == NULL) node = new(zone) EndNode(EndNode::BACKTRACK, zone);
|
||||
|
@ -628,7 +628,7 @@ class RegExpNode: public ZoneObject {
|
||||
// If we know that the input is ASCII then there are some nodes that can
|
||||
// never match. This method returns a node that can be substituted for
|
||||
// itself, or NULL if the node can never match.
|
||||
virtual RegExpNode* FilterASCII(int depth) { return this; }
|
||||
virtual RegExpNode* FilterASCII(int depth, bool ignore_case) { return this; }
|
||||
// Helper for FilterASCII.
|
||||
RegExpNode* replacement() {
|
||||
ASSERT(info()->replacement_calculated);
|
||||
@ -723,7 +723,7 @@ class SeqRegExpNode: public RegExpNode {
|
||||
: RegExpNode(on_success->zone()), on_success_(on_success) { }
|
||||
RegExpNode* on_success() { return on_success_; }
|
||||
void set_on_success(RegExpNode* node) { on_success_ = node; }
|
||||
virtual RegExpNode* FilterASCII(int depth);
|
||||
virtual RegExpNode* FilterASCII(int depth, bool ignore_case);
|
||||
virtual void FillInBMInfo(int offset,
|
||||
int recursion_depth,
|
||||
int budget,
|
||||
@ -735,7 +735,7 @@ class SeqRegExpNode: public RegExpNode {
|
||||
}
|
||||
|
||||
protected:
|
||||
RegExpNode* FilterSuccessor(int depth);
|
||||
RegExpNode* FilterSuccessor(int depth, bool ignore_case);
|
||||
|
||||
private:
|
||||
RegExpNode* on_success_;
|
||||
@ -861,7 +861,7 @@ class TextNode: public SeqRegExpNode {
|
||||
BoyerMooreLookahead* bm,
|
||||
bool not_at_start);
|
||||
void CalculateOffsets();
|
||||
virtual RegExpNode* FilterASCII(int depth);
|
||||
virtual RegExpNode* FilterASCII(int depth, bool ignore_case);
|
||||
|
||||
private:
|
||||
enum TextEmitPassType {
|
||||
@ -1097,7 +1097,7 @@ class ChoiceNode: public RegExpNode {
|
||||
void set_not_at_start() { not_at_start_ = true; }
|
||||
void set_being_calculated(bool b) { being_calculated_ = b; }
|
||||
virtual bool try_to_emit_quick_check_for_alternative(int i) { return true; }
|
||||
virtual RegExpNode* FilterASCII(int depth);
|
||||
virtual RegExpNode* FilterASCII(int depth, bool ignore_case);
|
||||
|
||||
protected:
|
||||
int GreedyLoopTextLengthForAlternative(GuardedAlternative* alternative);
|
||||
@ -1155,7 +1155,7 @@ class NegativeLookaheadChoiceNode: public ChoiceNode {
|
||||
// characters, but on a negative lookahead the negative branch did not take
|
||||
// part in that calculation (EatsAtLeast) so the assumptions don't hold.
|
||||
virtual bool try_to_emit_quick_check_for_alternative(int i) { return i != 0; }
|
||||
virtual RegExpNode* FilterASCII(int depth);
|
||||
virtual RegExpNode* FilterASCII(int depth, bool ignore_case);
|
||||
};
|
||||
|
||||
|
||||
@ -1185,7 +1185,7 @@ class LoopChoiceNode: public ChoiceNode {
|
||||
RegExpNode* continue_node() { return continue_node_; }
|
||||
bool body_can_be_zero_length() { return body_can_be_zero_length_; }
|
||||
virtual void Accept(NodeVisitor* visitor);
|
||||
virtual RegExpNode* FilterASCII(int depth);
|
||||
virtual RegExpNode* FilterASCII(int depth, bool ignore_case);
|
||||
|
||||
private:
|
||||
// AddAlternative is made private for loop nodes because alternatives
|
||||
|
@ -393,7 +393,7 @@ class Logger::NameBuffer {
|
||||
int previous = unibrow::Utf16::kNoPreviousCharacter;
|
||||
for (int i = 0; i < uc16_length && utf8_pos_ < kUtf8BufferSize; ++i) {
|
||||
uc16 c = utf16_buffer[i];
|
||||
if (c <= String::kMaxAsciiCharCodeU) {
|
||||
if (c <= unibrow::Utf8::kMaxOneByteChar) {
|
||||
utf8_buffer_[utf8_pos_++] = static_cast<char>(c);
|
||||
} else {
|
||||
int char_length = unibrow::Utf8::Length(c, previous);
|
||||
|
@ -5769,11 +5769,11 @@ void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
|
||||
STATIC_ASSERT(kSmiTag == 0);
|
||||
STATIC_ASSERT(kSmiShiftSize == 0);
|
||||
ASSERT(IsPowerOf2(String::kMaxAsciiCharCode + 1));
|
||||
ASSERT(IsPowerOf2(String::kMaxOneByteCharCode + 1));
|
||||
__ And(t0,
|
||||
code_,
|
||||
Operand(kSmiTagMask |
|
||||
((~String::kMaxAsciiCharCode) << kSmiTagSize)));
|
||||
((~String::kMaxOneByteCharCode) << kSmiTagSize)));
|
||||
__ Branch(&slow_case_, ne, t0, Operand(zero_reg));
|
||||
|
||||
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
|
||||
|
@ -147,7 +147,7 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ stop("stop-at");
|
||||
}
|
||||
#endif
|
||||
|
@ -122,7 +122,7 @@ bool LCodeGen::GeneratePrologue() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ stop("stop_at");
|
||||
}
|
||||
#endif
|
||||
@ -2214,7 +2214,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
|
||||
__ JumpIfSmi(input, is_false);
|
||||
|
||||
if (class_name->IsEqualTo(CStrVector("Function"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) {
|
||||
// Assuming the following assertions, we can use the same compares to test
|
||||
// for both being a function type and being in the object type range.
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
@ -2243,7 +2243,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ GetObjectType(temp, temp2, temp2);
|
||||
if (class_name->IsEqualTo(CStrVector("Object"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) {
|
||||
__ Branch(is_true, ne, temp2, Operand(JS_FUNCTION_TYPE));
|
||||
} else {
|
||||
__ Branch(is_false, ne, temp2, Operand(JS_FUNCTION_TYPE));
|
||||
@ -4315,7 +4315,7 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
|
||||
ASSERT(!char_code.is(result));
|
||||
|
||||
__ Branch(deferred->entry(), hi,
|
||||
char_code, Operand(String::kMaxAsciiCharCode));
|
||||
char_code, Operand(String::kMaxOneByteCharCode));
|
||||
__ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
|
||||
__ sll(scratch, char_code, kPointerSizeLog2);
|
||||
__ Addu(result, result, scratch);
|
||||
|
@ -262,7 +262,7 @@ void RegExpMacroAssemblerMIPS::CheckCharacters(Vector<const uc16> str,
|
||||
if (mode_ == ASCII) {
|
||||
__ lbu(a1, MemOperand(a0, 0));
|
||||
__ addiu(a0, a0, char_size());
|
||||
ASSERT(str[i] <= String::kMaxAsciiCharCode);
|
||||
ASSERT(str[i] <= String::kMaxOneByteCharCode);
|
||||
BranchOrBacktrack(on_failure, ne, a1, Operand(str[i]));
|
||||
} else {
|
||||
__ lhu(a1, MemOperand(a0, 0));
|
||||
@ -511,7 +511,7 @@ void RegExpMacroAssemblerMIPS::CheckBitInTable(
|
||||
Handle<ByteArray> table,
|
||||
Label* on_bit_set) {
|
||||
__ li(a0, Operand(table));
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) {
|
||||
__ And(a1, current_character(), Operand(kTableSize - 1));
|
||||
__ Addu(a0, a0, a1);
|
||||
} else {
|
||||
|
@ -473,7 +473,9 @@ void String::StringVerify() {
|
||||
|
||||
|
||||
void SeqOneByteString::SeqOneByteStringVerify() {
|
||||
CHECK(String::IsAscii(GetChars(), length()));
|
||||
#ifndef ENABLE_LATIN_1
|
||||
CHECK(!HasOnlyAsciiChars() || String::IsAscii(GetChars(), length()));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -345,6 +345,11 @@ bool String::HasOnlyAsciiChars() {
|
||||
}
|
||||
|
||||
|
||||
bool String::IsOneByteConvertible() {
|
||||
return HasOnlyAsciiChars() || IsOneByteRepresentation();
|
||||
}
|
||||
|
||||
|
||||
bool StringShape::IsCons() {
|
||||
return (type_ & kStringRepresentationMask) == kConsStringTag;
|
||||
}
|
||||
@ -2605,7 +2610,7 @@ uint16_t SeqOneByteString::SeqOneByteStringGet(int index) {
|
||||
|
||||
|
||||
void SeqOneByteString::SeqOneByteStringSet(int index, uint16_t value) {
|
||||
ASSERT(index >= 0 && index < length() && value <= kMaxAsciiCharCode);
|
||||
ASSERT(index >= 0 && index < length() && value <= kMaxOneByteCharCode);
|
||||
WRITE_BYTE_FIELD(this, kHeaderSize + index * kCharSize,
|
||||
static_cast<byte>(value));
|
||||
}
|
||||
@ -2621,6 +2626,11 @@ char* SeqOneByteString::GetChars() {
|
||||
}
|
||||
|
||||
|
||||
uint8_t* SeqOneByteString::GetCharsU() {
|
||||
return reinterpret_cast<uint8_t*>(GetCharsAddress());
|
||||
}
|
||||
|
||||
|
||||
Address SeqTwoByteString::GetCharsAddress() {
|
||||
return FIELD_ADDR(this, kHeaderSize);
|
||||
}
|
||||
|
@ -7284,7 +7284,7 @@ bool String::MarkAsUndetectable() {
|
||||
}
|
||||
|
||||
|
||||
bool String::IsEqualTo(Vector<const char> str) {
|
||||
bool String::IsUtf8EqualTo(Vector<const char> str) {
|
||||
int slen = length();
|
||||
// Can't check exact length equality, but we can check bounds.
|
||||
int str_len = str.length();
|
||||
@ -7313,12 +7313,12 @@ bool String::IsEqualTo(Vector<const char> str) {
|
||||
}
|
||||
|
||||
|
||||
bool String::IsAsciiEqualTo(Vector<const char> str) {
|
||||
bool String::IsOneByteEqualTo(Vector<const uint8_t> str) {
|
||||
int slen = length();
|
||||
if (str.length() != slen) return false;
|
||||
FlatContent content = GetFlatContent();
|
||||
if (content.IsAscii()) {
|
||||
return CompareChars(content.ToAsciiVector().start(),
|
||||
return CompareChars(content.ToOneByteVector().start(),
|
||||
str.start(), slen) == 0;
|
||||
}
|
||||
for (int i = 0; i < slen; i++) {
|
||||
@ -11443,7 +11443,7 @@ class Utf8SymbolKey : public HashTableKey {
|
||||
: string_(string), hash_field_(0), seed_(seed) { }
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
return String::cast(string)->IsEqualTo(string_);
|
||||
return String::cast(string)->IsUtf8EqualTo(string_);
|
||||
}
|
||||
|
||||
uint32_t Hash() {
|
||||
@ -11460,7 +11460,7 @@ class Utf8SymbolKey : public HashTableKey {
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
return Isolate::Current()->heap()->AllocateSymbol(
|
||||
return Isolate::Current()->heap()->AllocateSymbolFromUtf8(
|
||||
string_, chars_, hash_field_);
|
||||
}
|
||||
|
||||
@ -11499,25 +11499,25 @@ class SequentialSymbolKey : public HashTableKey {
|
||||
|
||||
|
||||
|
||||
class AsciiSymbolKey : public SequentialSymbolKey<char> {
|
||||
class OneByteSymbolKey : public SequentialSymbolKey<uint8_t> {
|
||||
public:
|
||||
AsciiSymbolKey(Vector<const char> str, uint32_t seed)
|
||||
: SequentialSymbolKey<char>(str, seed) { }
|
||||
OneByteSymbolKey(Vector<const uint8_t> str, uint32_t seed)
|
||||
: SequentialSymbolKey<uint8_t>(str, seed) { }
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
return String::cast(string)->IsAsciiEqualTo(string_);
|
||||
return String::cast(string)->IsOneByteEqualTo(string_);
|
||||
}
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
return HEAP->AllocateAsciiSymbol(string_, hash_field_);
|
||||
return HEAP->AllocateOneByteSymbol(string_, hash_field_);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SubStringAsciiSymbolKey : public HashTableKey {
|
||||
class SubStringOneByteSymbolKey : public HashTableKey {
|
||||
public:
|
||||
explicit SubStringAsciiSymbolKey(Handle<SeqOneByteString> string,
|
||||
explicit SubStringOneByteSymbolKey(Handle<SeqOneByteString> string,
|
||||
int from,
|
||||
int length)
|
||||
: string_(string), from_(from), length_(length) { }
|
||||
@ -11539,14 +11539,16 @@ class SubStringAsciiSymbolKey : public HashTableKey {
|
||||
}
|
||||
|
||||
bool IsMatch(Object* string) {
|
||||
Vector<const char> chars(string_->GetChars() + from_, length_);
|
||||
return String::cast(string)->IsAsciiEqualTo(chars);
|
||||
Vector<const uint8_t> chars(string_->GetCharsU() + from_, length_);
|
||||
return String::cast(string)->IsOneByteEqualTo(chars);
|
||||
}
|
||||
|
||||
MaybeObject* AsObject() {
|
||||
if (hash_field_ == 0) Hash();
|
||||
Vector<const char> chars(string_->GetChars() + from_, length_);
|
||||
return HEAP->AllocateAsciiSymbol(chars, hash_field_);
|
||||
Vector<const uint8_t> chars(
|
||||
reinterpret_cast<uint8_t*>(string_->GetChars()) + from_,
|
||||
length_);
|
||||
return HEAP->AllocateOneByteSymbol(chars, hash_field_);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -12467,9 +12469,9 @@ MaybeObject* SymbolTable::LookupUtf8Symbol(Vector<const char> str,
|
||||
}
|
||||
|
||||
|
||||
MaybeObject* SymbolTable::LookupOneByteSymbol(Vector<const char> str,
|
||||
MaybeObject* SymbolTable::LookupOneByteSymbol(Vector<const uint8_t> str,
|
||||
Object** s) {
|
||||
AsciiSymbolKey key(str, GetHeap()->HashSeed());
|
||||
OneByteSymbolKey key(str, GetHeap()->HashSeed());
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
@ -12479,7 +12481,7 @@ MaybeObject* SymbolTable::LookupSubStringOneByteSymbol(
|
||||
int from,
|
||||
int length,
|
||||
Object** s) {
|
||||
SubStringAsciiSymbolKey key(str, from, length);
|
||||
SubStringOneByteSymbolKey key(str, from, length);
|
||||
return LookupKey(&key, s);
|
||||
}
|
||||
|
||||
|
@ -3033,7 +3033,7 @@ class SymbolTable: public HashTable<SymbolTableShape, HashTableKey*> {
|
||||
// pointer *s is set to the symbol found.
|
||||
MUST_USE_RESULT MaybeObject* LookupUtf8Symbol(Vector<const char> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(Vector<const char> str,
|
||||
MUST_USE_RESULT MaybeObject* LookupOneByteSymbol(Vector<const uint8_t> str,
|
||||
Object** s);
|
||||
MUST_USE_RESULT MaybeObject* LookupSubStringOneByteSymbol(
|
||||
Handle<SeqOneByteString> str,
|
||||
@ -7088,12 +7088,19 @@ class String: public HeapObject {
|
||||
// Returns true if the structure contains two-byte content.
|
||||
bool IsTwoByte() { return state_ == TWO_BYTE; }
|
||||
|
||||
// TODO(dcarney): Remove this function.
|
||||
// Return the ASCII content of the string. Only use if IsAscii() returns
|
||||
// true.
|
||||
Vector<const char> ToAsciiVector() {
|
||||
ASSERT_EQ(ASCII, state_);
|
||||
return Vector<const char>::cast(buffer_);
|
||||
}
|
||||
// Return the one byte content of the string. Only use if IsAscii() returns
|
||||
// true.
|
||||
Vector<const uint8_t> ToOneByteVector() {
|
||||
ASSERT_EQ(ASCII, state_);
|
||||
return buffer_;
|
||||
}
|
||||
// Return the two-byte content of the string. Only use if IsTwoByte()
|
||||
// returns true.
|
||||
Vector<const uc16> ToUC16Vector() {
|
||||
@ -7144,6 +7151,8 @@ class String: public HeapObject {
|
||||
// possible.
|
||||
inline bool HasOnlyAsciiChars();
|
||||
|
||||
inline bool IsOneByteConvertible();
|
||||
|
||||
// Get and set individual two byte chars in the string.
|
||||
inline void Set(int index, uint16_t value);
|
||||
// Get individual two byte char in the string. Repeated calls
|
||||
@ -7194,8 +7203,8 @@ class String: public HeapObject {
|
||||
|
||||
// String equality operations.
|
||||
inline bool Equals(String* other);
|
||||
bool IsEqualTo(Vector<const char> str);
|
||||
bool IsAsciiEqualTo(Vector<const char> str);
|
||||
bool IsUtf8EqualTo(Vector<const char> str);
|
||||
bool IsOneByteEqualTo(Vector<const uint8_t> str);
|
||||
bool IsTwoByteEqualTo(Vector<const uc16> str);
|
||||
|
||||
// Return a UTF8 representation of the string. The string is null
|
||||
@ -7271,9 +7280,9 @@ class String: public HeapObject {
|
||||
// value into an array index.
|
||||
static const int kMaxArrayIndexSize = 10;
|
||||
|
||||
// Max ASCII char code.
|
||||
static const int kMaxAsciiCharCode = unibrow::Utf8::kMaxOneByteChar;
|
||||
static const unsigned kMaxAsciiCharCodeU = unibrow::Utf8::kMaxOneByteChar;
|
||||
// Max char codes.
|
||||
static const int32_t kMaxOneByteCharCode = unibrow::Latin1::kMaxChar;
|
||||
static const uint32_t kMaxOneByteCharCodeU = unibrow::Latin1::kMaxChar;
|
||||
static const int kMaxUtf16CodeUnit = 0xffff;
|
||||
|
||||
// Mask constant for checking if a string has a computed hash code
|
||||
@ -7358,7 +7367,7 @@ class String: public HeapObject {
|
||||
const char* start = chars;
|
||||
const char* limit = chars + length;
|
||||
#ifdef V8_HOST_CAN_READ_UNALIGNED
|
||||
ASSERT(kMaxAsciiCharCode == 0x7F);
|
||||
ASSERT(unibrow::Utf8::kMaxOneByteChar == 0x7F);
|
||||
const uintptr_t non_ascii_mask = kUintptrAllBitsSet / 0xFF * 0x80;
|
||||
while (chars + sizeof(uintptr_t) <= limit) {
|
||||
if (*reinterpret_cast<const uintptr_t*>(chars) & non_ascii_mask) {
|
||||
@ -7368,7 +7377,7 @@ class String: public HeapObject {
|
||||
}
|
||||
#endif
|
||||
while (chars < limit) {
|
||||
if (static_cast<uint8_t>(*chars) > kMaxAsciiCharCodeU) {
|
||||
if (static_cast<uint8_t>(*chars) > unibrow::Utf8::kMaxOneByteChar) {
|
||||
return static_cast<int>(chars - start);
|
||||
}
|
||||
++chars;
|
||||
@ -7380,18 +7389,18 @@ class String: public HeapObject {
|
||||
return NonAsciiStart(chars, length) >= length;
|
||||
}
|
||||
|
||||
static inline int NonAsciiStart(const uc16* chars, int length) {
|
||||
static inline int NonOneByteStart(const uc16* chars, int length) {
|
||||
const uc16* limit = chars + length;
|
||||
const uc16* start = chars;
|
||||
while (chars < limit) {
|
||||
if (*chars > kMaxAsciiCharCodeU) return static_cast<int>(chars - start);
|
||||
if (*chars > kMaxOneByteCharCodeU) return static_cast<int>(chars - start);
|
||||
++chars;
|
||||
}
|
||||
return static_cast<int>(chars - start);
|
||||
}
|
||||
|
||||
static inline bool IsAscii(const uc16* chars, int length) {
|
||||
return NonAsciiStart(chars, length) >= length;
|
||||
static inline bool IsOneByte(const uc16* chars, int length) {
|
||||
return NonOneByteStart(chars, length) >= length;
|
||||
}
|
||||
|
||||
template<class Visitor, class ConsOp>
|
||||
@ -7456,7 +7465,9 @@ class SeqOneByteString: public SeqString {
|
||||
// Get the address of the characters in this string.
|
||||
inline Address GetCharsAddress();
|
||||
|
||||
// TODO(dcarney): remove GetChars and rename GetCharsU to GetChars.
|
||||
inline char* GetChars();
|
||||
inline uint8_t* GetCharsU();
|
||||
|
||||
// Casting
|
||||
static inline SeqOneByteString* cast(Object* obj);
|
||||
|
@ -255,7 +255,7 @@ Handle<String> Parser::LookupSymbol(int symbol_id) {
|
||||
>= static_cast<unsigned>(symbol_cache_.length())) {
|
||||
if (scanner().is_literal_ascii()) {
|
||||
return isolate()->factory()->LookupOneByteSymbol(
|
||||
scanner().literal_ascii_string());
|
||||
Vector<const uint8_t>::cast(scanner().literal_ascii_string()));
|
||||
} else {
|
||||
return isolate()->factory()->LookupTwoByteSymbol(
|
||||
scanner().literal_utf16_string());
|
||||
@ -276,7 +276,7 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
|
||||
if (result.is_null()) {
|
||||
if (scanner().is_literal_ascii()) {
|
||||
result = isolate()->factory()->LookupOneByteSymbol(
|
||||
scanner().literal_ascii_string());
|
||||
Vector<const uint8_t>::cast(scanner().literal_ascii_string()));
|
||||
} else {
|
||||
result = isolate()->factory()->LookupTwoByteSymbol(
|
||||
scanner().literal_utf16_string());
|
||||
@ -1429,7 +1429,7 @@ Statement* Parser::ParseExportDeclaration(bool* ok) {
|
||||
case Token::IDENTIFIER: {
|
||||
Handle<String> name = ParseIdentifier(CHECK_OK);
|
||||
// Handle 'module' as a context-sensitive keyword.
|
||||
if (!name->IsEqualTo(CStrVector("module"))) {
|
||||
if (!name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("module"))) {
|
||||
names.Add(name, zone());
|
||||
while (peek() == Token::COMMA) {
|
||||
Consume(Token::COMMA);
|
||||
@ -4711,7 +4711,7 @@ void Parser::ExpectContextualKeyword(const char* keyword, bool* ok) {
|
||||
if (!*ok) return;
|
||||
Handle<String> symbol = GetSymbol(ok);
|
||||
if (!*ok) return;
|
||||
if (!symbol->IsEqualTo(CStrVector(keyword))) {
|
||||
if (!symbol->IsUtf8EqualTo(CStrVector(keyword))) {
|
||||
*ok = false;
|
||||
ReportUnexpectedToken(scanner().current_token());
|
||||
}
|
||||
|
@ -2990,7 +2990,8 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithString(
|
||||
if (is_global &&
|
||||
regexp->TypeTag() == JSRegExp::ATOM &&
|
||||
simple_replace) {
|
||||
if (subject->HasOnlyAsciiChars() && replacement->HasOnlyAsciiChars()) {
|
||||
if (subject->IsOneByteConvertible() &&
|
||||
replacement->IsOneByteConvertible()) {
|
||||
return StringReplaceAtomRegExpWithString<SeqOneByteString>(
|
||||
isolate, subject, regexp, replacement, last_match_info);
|
||||
} else {
|
||||
@ -3081,7 +3082,7 @@ MUST_USE_RESULT static MaybeObject* StringReplaceRegExpWithEmptyString(
|
||||
if (is_global &&
|
||||
regexp->TypeTag() == JSRegExp::ATOM) {
|
||||
Handle<String> empty_string = isolate->factory()->empty_string();
|
||||
if (subject->HasOnlyAsciiChars()) {
|
||||
if (subject->IsOneByteRepresentation()) {
|
||||
return StringReplaceAtomRegExpWithString<SeqOneByteString>(
|
||||
isolate,
|
||||
subject,
|
||||
@ -3210,7 +3211,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
|
||||
ASSERT(last_match_info->HasFastObjectElements());
|
||||
|
||||
if (replacement->length() == 0) {
|
||||
if (subject->HasOnlyAsciiChars()) {
|
||||
if (subject->IsOneByteConvertible()) {
|
||||
return StringReplaceRegExpWithEmptyString<SeqOneByteString>(
|
||||
isolate, subject, regexp, last_match_info);
|
||||
} else {
|
||||
@ -3377,7 +3378,7 @@ static int StringMatchBackwards(Vector<const schar> subject,
|
||||
if (sizeof(schar) == 1 && sizeof(pchar) > 1) {
|
||||
for (int i = 0; i < pattern_length; i++) {
|
||||
uc16 c = pattern[i];
|
||||
if (c > String::kMaxAsciiCharCode) {
|
||||
if (c > String::kMaxOneByteCharCode) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -5258,14 +5259,14 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
|
||||
|
||||
source->TryFlatten();
|
||||
|
||||
bool ascii = true;
|
||||
bool one_byte = true;
|
||||
int length = source->length();
|
||||
|
||||
int unescaped_length = 0;
|
||||
for (int i = 0; i < length; unescaped_length++) {
|
||||
int step;
|
||||
if (Unescape(source, i, length, &step) > String::kMaxAsciiCharCode) {
|
||||
ascii = false;
|
||||
if (Unescape(source, i, length, &step) > String::kMaxOneByteCharCode) {
|
||||
one_byte = false;
|
||||
}
|
||||
i += step;
|
||||
}
|
||||
@ -5276,7 +5277,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_URIUnescape) {
|
||||
|
||||
Object* o;
|
||||
{ MaybeObject* maybe_o =
|
||||
ascii ?
|
||||
one_byte ?
|
||||
isolate->heap()->AllocateRawOneByteString(unescaped_length) :
|
||||
isolate->heap()->AllocateRawTwoByteString(unescaped_length);
|
||||
if (!maybe_o->ToObject(&o)) return maybe_o;
|
||||
@ -5933,6 +5934,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCase(
|
||||
// Assume that the string is not empty; we need this assumption later
|
||||
if (length == 0) return s;
|
||||
|
||||
#ifndef ENABLE_LATIN_1
|
||||
// Simpler handling of ASCII strings.
|
||||
//
|
||||
// NOTE: This assumes that the upper/lower case of an ASCII
|
||||
@ -5949,6 +5951,7 @@ MUST_USE_RESULT static MaybeObject* ConvertCase(
|
||||
result->GetChars(), SeqOneByteString::cast(s)->GetChars(), length);
|
||||
return has_changed_character ? result : s;
|
||||
}
|
||||
#endif
|
||||
|
||||
Object* answer;
|
||||
{ MaybeObject* maybe_answer =
|
||||
@ -6461,7 +6464,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
if (first->IsString()) return first;
|
||||
}
|
||||
|
||||
bool ascii = special->HasOnlyAsciiChars();
|
||||
bool one_byte = special->IsOneByteConvertible();
|
||||
int position = 0;
|
||||
for (int i = 0; i < array_length; i++) {
|
||||
int increment = 0;
|
||||
@ -6502,8 +6505,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
String* element = String::cast(elt);
|
||||
int element_length = element->length();
|
||||
increment = element_length;
|
||||
if (ascii && !element->HasOnlyAsciiChars()) {
|
||||
ascii = false;
|
||||
if (one_byte && !element->IsOneByteConvertible()) {
|
||||
one_byte = false;
|
||||
}
|
||||
} else {
|
||||
ASSERT(!elt->IsTheHole());
|
||||
@ -6519,7 +6522,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderConcat) {
|
||||
int length = position;
|
||||
Object* object;
|
||||
|
||||
if (ascii) {
|
||||
if (one_byte) {
|
||||
{ MaybeObject* maybe_object =
|
||||
isolate->heap()->AllocateRawOneByteString(length);
|
||||
if (!maybe_object->ToObject(&object)) return maybe_object;
|
||||
@ -6624,7 +6627,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringBuilderJoin) {
|
||||
}
|
||||
ASSERT(sink == end);
|
||||
|
||||
ASSERT(!answer->HasOnlyAsciiChars()); // Use %_FastAsciiArrayJoin instead.
|
||||
// Use %_FastAsciiArrayJoin instead.
|
||||
ASSERT(!answer->IsOneByteRepresentation());
|
||||
return answer;
|
||||
}
|
||||
|
||||
@ -8016,7 +8020,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_OptimizeFunctionOnNextCall) {
|
||||
if (args.length() == 2 &&
|
||||
unoptimized->kind() == Code::FUNCTION) {
|
||||
CONVERT_ARG_HANDLE_CHECKED(String, type, 1);
|
||||
CHECK(type->IsEqualTo(CStrVector("osr")));
|
||||
CHECK(type->IsOneByteEqualTo(STATIC_ASCII_VECTOR("osr")));
|
||||
isolate->runtime_profiler()->AttemptOnStackReplacement(*function);
|
||||
unoptimized->set_allow_osr_at_loop_nesting_level(
|
||||
Code::kMaxLoopNestingMarker);
|
||||
|
@ -183,9 +183,9 @@ class LiteralBuffer {
|
||||
INLINE(void AddChar(uint32_t code_unit)) {
|
||||
if (position_ >= backing_store_.length()) ExpandBuffer();
|
||||
if (is_ascii_) {
|
||||
if (code_unit < kMaxAsciiCharCodeU) {
|
||||
if (code_unit <= unibrow::Latin1::kMaxChar) {
|
||||
backing_store_[position_] = static_cast<byte>(code_unit);
|
||||
position_ += kASCIISize;
|
||||
position_ += kOneByteSize;
|
||||
return;
|
||||
}
|
||||
ConvertToUtf16();
|
||||
@ -250,7 +250,7 @@ class LiteralBuffer {
|
||||
} else {
|
||||
new_store = backing_store_;
|
||||
}
|
||||
char* src = reinterpret_cast<char*>(backing_store_.start());
|
||||
uint8_t* src = backing_store_.start();
|
||||
uc16* dst = reinterpret_cast<uc16*>(new_store.start());
|
||||
for (int i = position_ - 1; i >= 0; i--) {
|
||||
dst[i] = src[i];
|
||||
|
@ -61,12 +61,12 @@ class StringSearchBase {
|
||||
// to compensate for the algorithmic overhead compared to simple brute force.
|
||||
static const int kBMMinPatternLength = 7;
|
||||
|
||||
static inline bool IsAsciiString(Vector<const char>) {
|
||||
static inline bool IsOneByteString(Vector<const char> string) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool IsAsciiString(Vector<const uc16> string) {
|
||||
return String::IsAscii(string.start(), string.length());
|
||||
static inline bool IsOneByteString(Vector<const uc16> string) {
|
||||
return String::IsOneByte(string.start(), string.length());
|
||||
}
|
||||
|
||||
friend class Isolate;
|
||||
@ -81,7 +81,7 @@ class StringSearch : private StringSearchBase {
|
||||
pattern_(pattern),
|
||||
start_(Max(0, pattern.length() - kBMMaxShift)) {
|
||||
if (sizeof(PatternChar) > sizeof(SubjectChar)) {
|
||||
if (!IsAsciiString(pattern_)) {
|
||||
if (!IsOneByteString(pattern_)) {
|
||||
strategy_ = &FailSearch;
|
||||
return;
|
||||
}
|
||||
@ -156,7 +156,7 @@ class StringSearch : private StringSearchBase {
|
||||
return bad_char_occurrence[static_cast<int>(char_code)];
|
||||
}
|
||||
if (sizeof(PatternChar) == 1) {
|
||||
if (static_cast<unsigned int>(char_code) > String::kMaxAsciiCharCodeU) {
|
||||
if (static_cast<unsigned int>(char_code) > String::kMaxOneByteCharCodeU) {
|
||||
return -1;
|
||||
}
|
||||
return bad_char_occurrence[static_cast<unsigned int>(char_code)];
|
||||
@ -223,7 +223,8 @@ int StringSearch<PatternChar, SubjectChar>::SingleCharSearch(
|
||||
return static_cast<int>(pos - subject.start());
|
||||
} else {
|
||||
if (sizeof(PatternChar) > sizeof(SubjectChar)) {
|
||||
if (static_cast<uc16>(pattern_first_char) > String::kMaxAsciiCharCodeU) {
|
||||
if (static_cast<uc16>(pattern_first_char) >
|
||||
String::kMaxOneByteCharCodeU) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -825,6 +825,7 @@ function StringFromCharCode(code) {
|
||||
var code = %_Arguments(i);
|
||||
if (!%_IsSmi(code)) code = ToNumber(code) & 0xffff;
|
||||
if (code < 0) code = code & 0xffff;
|
||||
// TODO(dcarney): Fix for Latin-1.
|
||||
if (code > 0x7f) break;
|
||||
%_OneByteSeqStringSetChar(one_byte, i, code);
|
||||
}
|
||||
|
@ -133,6 +133,14 @@ class Utf16 {
|
||||
}
|
||||
};
|
||||
|
||||
class Latin1 {
|
||||
public:
|
||||
#ifndef ENABLE_LATIN_1
|
||||
static const unsigned kMaxChar = 0x7f;
|
||||
#else
|
||||
static const unsigned kMaxChar = 0xff;
|
||||
#endif
|
||||
};
|
||||
|
||||
class Utf8 {
|
||||
public:
|
||||
|
42
src/utils.h
42
src/utils.h
@ -523,12 +523,21 @@ class ScopedVector : public Vector<T> {
|
||||
};
|
||||
|
||||
#define STATIC_ASCII_VECTOR(x) \
|
||||
v8::internal::Vector<const char>(x, ARRAY_SIZE(x)-1)
|
||||
v8::internal::Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(x), \
|
||||
ARRAY_SIZE(x)-1)
|
||||
|
||||
inline Vector<const char> CStrVector(const char* data) {
|
||||
return Vector<const char>(data, StrLength(data));
|
||||
}
|
||||
|
||||
inline Vector<const uint8_t> OneByteVector(const char* data, int length) {
|
||||
return Vector<const uint8_t>(reinterpret_cast<const uint8_t*>(data), length);
|
||||
}
|
||||
|
||||
inline Vector<const uint8_t> OneByteVector(const char* data) {
|
||||
return OneByteVector(data, StrLength(data));
|
||||
}
|
||||
|
||||
inline Vector<char> MutableCStrVector(char* data) {
|
||||
return Vector<char>(data, StrLength(data));
|
||||
}
|
||||
@ -767,7 +776,9 @@ class SequenceCollector : public Collector<T, growth_factor, max_growth> {
|
||||
|
||||
// Compare ASCII/16bit chars to ASCII/16bit chars.
|
||||
template <typename lchar, typename rchar>
|
||||
inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
|
||||
inline int CompareCharsUnsigned(const lchar* lhs,
|
||||
const rchar* rhs,
|
||||
int chars) {
|
||||
const lchar* limit = lhs + chars;
|
||||
#ifdef V8_HOST_CAN_READ_UNALIGNED
|
||||
if (sizeof(*lhs) == sizeof(*rhs)) {
|
||||
@ -792,6 +803,33 @@ inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename lchar, typename rchar>
|
||||
inline int CompareChars(const lchar* lhs, const rchar* rhs, int chars) {
|
||||
ASSERT(sizeof(lchar) <= 2);
|
||||
ASSERT(sizeof(rchar) <= 2);
|
||||
if (sizeof(lchar) == 1) {
|
||||
if (sizeof(rchar) == 1) {
|
||||
return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
|
||||
reinterpret_cast<const uint8_t*>(rhs),
|
||||
chars);
|
||||
} else {
|
||||
return CompareCharsUnsigned(reinterpret_cast<const uint8_t*>(lhs),
|
||||
reinterpret_cast<const uint16_t*>(rhs),
|
||||
chars);
|
||||
}
|
||||
} else {
|
||||
if (sizeof(rchar) == 1) {
|
||||
return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
|
||||
reinterpret_cast<const uint8_t*>(rhs),
|
||||
chars);
|
||||
} else {
|
||||
return CompareCharsUnsigned(reinterpret_cast<const uint16_t*>(lhs),
|
||||
reinterpret_cast<const uint16_t*>(rhs),
|
||||
chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Calculate 10^exponent.
|
||||
inline int TenToThe(int exponent) {
|
||||
|
@ -202,13 +202,44 @@ Vector<const char> ReadFile(FILE* file,
|
||||
bool verbose = true);
|
||||
|
||||
|
||||
template <typename sourcechar, typename sinkchar>
|
||||
INLINE(static void CopyCharsUnsigned(sinkchar* dest,
|
||||
const sourcechar* src,
|
||||
int chars));
|
||||
|
||||
// Copy from ASCII/16bit chars to ASCII/16bit chars.
|
||||
template <typename sourcechar, typename sinkchar>
|
||||
INLINE(void CopyChars(sinkchar* dest, const sourcechar* src, int chars));
|
||||
|
||||
template<typename sourcechar, typename sinkchar>
|
||||
void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
|
||||
ASSERT(sizeof(sourcechar) <= 2);
|
||||
ASSERT(sizeof(sinkchar) <= 2);
|
||||
if (sizeof(sinkchar) == 1) {
|
||||
if (sizeof(sourcechar) == 1) {
|
||||
CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
|
||||
reinterpret_cast<const uint8_t*>(src),
|
||||
chars);
|
||||
} else {
|
||||
CopyCharsUnsigned(reinterpret_cast<uint8_t*>(dest),
|
||||
reinterpret_cast<const uint16_t*>(src),
|
||||
chars);
|
||||
}
|
||||
} else {
|
||||
if (sizeof(sourcechar) == 1) {
|
||||
CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
|
||||
reinterpret_cast<const uint8_t*>(src),
|
||||
chars);
|
||||
} else {
|
||||
CopyCharsUnsigned(reinterpret_cast<uint16_t*>(dest),
|
||||
reinterpret_cast<const uint16_t*>(src),
|
||||
chars);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename sourcechar, typename sinkchar>
|
||||
void CopyChars(sinkchar* dest, const sourcechar* src, int chars) {
|
||||
void CopyCharsUnsigned(sinkchar* dest, const sourcechar* src, int chars) {
|
||||
sinkchar* limit = dest + chars;
|
||||
#ifdef V8_HOST_CAN_READ_UNALIGNED
|
||||
if (sizeof(*dest) == sizeof(*src)) {
|
||||
|
@ -4562,7 +4562,7 @@ void StringCharCodeAtGenerator::GenerateSlow(
|
||||
void StringCharFromCodeGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
// Fast case of Heap::LookupSingleCharacterStringFromCode.
|
||||
__ JumpIfNotSmi(code_, &slow_case_);
|
||||
__ SmiCompare(code_, Smi::FromInt(String::kMaxAsciiCharCode));
|
||||
__ SmiCompare(code_, Smi::FromInt(String::kMaxOneByteCharCode));
|
||||
__ j(above, &slow_case_);
|
||||
|
||||
__ LoadRoot(result_, Heap::kSingleCharacterStringCacheRootIndex);
|
||||
|
@ -127,7 +127,7 @@ void FullCodeGenerator::Generate() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ int3();
|
||||
}
|
||||
#endif
|
||||
|
@ -124,7 +124,7 @@ bool LCodeGen::GeneratePrologue() {
|
||||
|
||||
#ifdef DEBUG
|
||||
if (strlen(FLAG_stop_at) > 0 &&
|
||||
info_->function()->name()->IsEqualTo(CStrVector(FLAG_stop_at))) {
|
||||
info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) {
|
||||
__ int3();
|
||||
}
|
||||
#endif
|
||||
@ -2224,7 +2224,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
|
||||
__ JumpIfSmi(input, is_false);
|
||||
|
||||
if (class_name->IsEqualTo(CStrVector("Function"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Function"))) {
|
||||
// Assuming the following assertions, we can use the same compares to test
|
||||
// for both being a function type and being in the object type range.
|
||||
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
|
||||
@ -2255,7 +2255,7 @@ void LCodeGen::EmitClassOfTest(Label* is_true,
|
||||
|
||||
// Objects with a non-function constructor have class 'Object'.
|
||||
__ CmpObjectType(temp, JS_FUNCTION_TYPE, kScratchRegister);
|
||||
if (class_name->IsEqualTo(CStrVector("Object"))) {
|
||||
if (class_name->IsOneByteEqualTo(STATIC_ASCII_VECTOR("Object"))) {
|
||||
__ j(not_equal, is_true);
|
||||
} else {
|
||||
__ j(not_equal, is_false);
|
||||
@ -4249,7 +4249,7 @@ void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) {
|
||||
Register result = ToRegister(instr->result());
|
||||
ASSERT(!char_code.is(result));
|
||||
|
||||
__ cmpl(char_code, Immediate(String::kMaxAsciiCharCode));
|
||||
__ cmpl(char_code, Immediate(String::kMaxOneByteCharCode));
|
||||
__ j(above, deferred->entry());
|
||||
__ LoadRoot(result, Heap::kSingleCharacterStringCacheRootIndex);
|
||||
__ movq(result, FieldOperand(result,
|
||||
|
@ -234,7 +234,7 @@ void RegExpMacroAssemblerX64::CheckCharacters(Vector<const uc16> str,
|
||||
// If input is ASCII, don't even bother calling here if the string to
|
||||
// match contains a non-ASCII character.
|
||||
if (mode_ == ASCII) {
|
||||
ASSERT(String::IsAscii(str.start(), str.length()));
|
||||
ASSERT(String::IsOneByte(str.start(), str.length()));
|
||||
}
|
||||
#endif
|
||||
int byte_length = str.length() * char_size();
|
||||
@ -610,7 +610,7 @@ void RegExpMacroAssemblerX64::CheckBitInTable(
|
||||
Label* on_bit_set) {
|
||||
__ Move(rax, table);
|
||||
Register index = current_character();
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxAsciiCharCode) {
|
||||
if (mode_ != ASCII || kTableMask != String::kMaxOneByteCharCode) {
|
||||
__ movq(rbx, current_character());
|
||||
__ and_(rbx, Immediate(kTableMask));
|
||||
index = rbx;
|
||||
|
@ -12225,8 +12225,8 @@ static bool NamedGetAccessBlockAandH(Local<v8::Object> obj,
|
||||
if (!name->IsString()) return false;
|
||||
i::Handle<i::String> name_handle =
|
||||
v8::Utils::OpenHandle(String::Cast(*name));
|
||||
return !name_handle->IsEqualTo(i::CStrVector(kPropertyA))
|
||||
&& !name_handle->IsEqualTo(i::CStrVector(kPropertyH));
|
||||
return !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyA))
|
||||
&& !name_handle->IsUtf8EqualTo(i::CStrVector(kPropertyH));
|
||||
}
|
||||
|
||||
|
||||
|
@ -49,7 +49,7 @@ static v8::Persistent<v8::Context> env;
|
||||
#define __ masm->
|
||||
|
||||
|
||||
void generate(MacroAssembler* masm, i::Vector<const char> string) {
|
||||
void generate(MacroAssembler* masm, i::Vector<const uint8_t> string) {
|
||||
// GenerateHashInit takes the first character as an argument so it can't
|
||||
// handle the zero length string.
|
||||
ASSERT(string.length() > 0);
|
||||
@ -152,7 +152,7 @@ void generate(MacroAssembler* masm, uint32_t key) {
|
||||
}
|
||||
|
||||
|
||||
void check(i::Vector<const char> string) {
|
||||
void check(i::Vector<const uint8_t> string) {
|
||||
v8::HandleScope scope;
|
||||
v8::internal::byte buffer[2048];
|
||||
MacroAssembler masm(Isolate::Current(), buffer, sizeof buffer);
|
||||
@ -168,7 +168,7 @@ void check(i::Vector<const char> string) {
|
||||
CHECK(code->IsCode());
|
||||
|
||||
HASH_FUNCTION hash = FUNCTION_CAST<HASH_FUNCTION>(code->entry());
|
||||
Handle<String> v8_string = FACTORY->NewStringFromAscii(string);
|
||||
Handle<String> v8_string = FACTORY->NewStringFromOneByte(string);
|
||||
v8_string->set_hash_field(String::kEmptyHashField);
|
||||
#ifdef USE_SIMULATOR
|
||||
uint32_t codegen_hash =
|
||||
@ -181,6 +181,11 @@ void check(i::Vector<const char> string) {
|
||||
}
|
||||
|
||||
|
||||
void check(i::Vector<const char> s) {
|
||||
check(i::Vector<const uint8_t>::cast(s));
|
||||
}
|
||||
|
||||
|
||||
void check(uint32_t key) {
|
||||
v8::HandleScope scope;
|
||||
v8::internal::byte buffer[2048];
|
||||
@ -211,9 +216,9 @@ void check(uint32_t key) {
|
||||
}
|
||||
|
||||
|
||||
void check_twochars(char a, char b) {
|
||||
char ab[2] = {a, b};
|
||||
check(i::Vector<const char>(ab, 2));
|
||||
void check_twochars(uint8_t a, uint8_t b) {
|
||||
uint8_t ab[2] = {a, b};
|
||||
check(i::Vector<const uint8_t>(ab, 2));
|
||||
}
|
||||
|
||||
|
||||
@ -224,12 +229,12 @@ static uint32_t PseudoRandom(uint32_t i, uint32_t j) {
|
||||
|
||||
TEST(StringHash) {
|
||||
if (env.IsEmpty()) env = v8::Context::New();
|
||||
for (int a = 0; a < String::kMaxAsciiCharCode; a++) {
|
||||
for (int a = 0; a < String::kMaxOneByteCharCode; a++) {
|
||||
// Numbers are hashed differently.
|
||||
if (a >= '0' && a <= '9') continue;
|
||||
for (int b = 0; b < String::kMaxAsciiCharCode; b++) {
|
||||
for (int b = 0; b < String::kMaxOneByteCharCode; b++) {
|
||||
if (b >= '0' && b <= '9') continue;
|
||||
check_twochars(static_cast<char>(a), static_cast<char>(b));
|
||||
check_twochars(static_cast<uint8_t>(a), static_cast<uint8_t>(b));
|
||||
}
|
||||
}
|
||||
check(i::Vector<const char>("*", 1));
|
||||
|
@ -62,7 +62,7 @@ static void CheckOddball(Object* obj, const char* string) {
|
||||
CHECK(obj->IsOddball());
|
||||
bool exc;
|
||||
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
|
||||
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
|
||||
CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@ static void CheckSmi(int value, const char* string) {
|
||||
bool exc;
|
||||
Object* print_string =
|
||||
*Execution::ToString(Handle<Object>(Smi::FromInt(value)), &exc);
|
||||
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
|
||||
CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
|
||||
}
|
||||
|
||||
|
||||
@ -79,7 +79,7 @@ static void CheckNumber(double value, const char* string) {
|
||||
CHECK(obj->IsNumber());
|
||||
bool exc;
|
||||
Object* print_string = *Execution::ToString(Handle<Object>(obj), &exc);
|
||||
CHECK(String::cast(print_string)->IsEqualTo(CStrVector(string)));
|
||||
CHECK(String::cast(print_string)->IsUtf8EqualTo(CStrVector(string)));
|
||||
}
|
||||
|
||||
|
||||
@ -551,7 +551,7 @@ static void CheckSymbols(const char** strings) {
|
||||
MaybeObject* maybe_b = HEAP->LookupUtf8Symbol(string);
|
||||
if (!maybe_b->ToObject(&b)) continue;
|
||||
CHECK_EQ(b, a);
|
||||
CHECK(String::cast(b)->IsEqualTo(CStrVector(string)));
|
||||
CHECK(String::cast(b)->IsUtf8EqualTo(CStrVector(string)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -800,7 +800,7 @@ TEST(StringAllocation) {
|
||||
FACTORY->LookupUtf8Symbol(Vector<const char>(non_ascii, 3 * length));
|
||||
CHECK_EQ(length, non_ascii_sym->length());
|
||||
Handle<String> ascii_sym =
|
||||
FACTORY->LookupOneByteSymbol(Vector<const char>(ascii, length));
|
||||
FACTORY->LookupOneByteSymbol(OneByteVector(ascii, length));
|
||||
CHECK_EQ(length, ascii_sym->length());
|
||||
Handle<String> non_ascii_str =
|
||||
FACTORY->NewStringFromUtf8(Vector<const char>(non_ascii, 3 * length));
|
||||
|
@ -1273,5 +1273,5 @@ TEST(StringReplaceAtomTwoByteResult) {
|
||||
|
||||
TEST(IsAscii) {
|
||||
CHECK(String::IsAscii(static_cast<char*>(NULL), 0));
|
||||
CHECK(String::IsAscii(static_cast<uc16*>(NULL), 0));
|
||||
CHECK(String::IsOneByte(static_cast<uc16*>(NULL), 0));
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2012 the V8 project authors. All rights reserved.
|
||||
// Copyright 2013 the V8 project authors. All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
@ -25,14 +25,9 @@
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
var x = [];
|
||||
assertSame(0, x.length);
|
||||
assertSame(undefined, x[0]);
|
||||
assertEquals(String.fromCharCode(97, 220, 256), 'a' + '\u00DC' + '\u0100');
|
||||
assertEquals(String.fromCharCode(97, 220, 256), 'a\u00DC\u0100');
|
||||
|
||||
Object.defineProperty(x, '0', { value: 7, configurable: false });
|
||||
assertSame(1, x.length);
|
||||
assertSame(7, x[0]);
|
||||
assertEquals(['a', 'b', '\xdc'], ['b', '\xdc', 'a'].sort());
|
||||
assertEquals(['\xfc\xdc', '\xfc'], new RegExp('(\xdc)\\1', 'i').exec('\xfc\xdc'));
|
||||
|
||||
x.length = 0;
|
||||
assertSame(1, x.length);
|
||||
assertSame(7, x[0]);
|
||||
|
Loading…
Reference in New Issue
Block a user