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:
yangguo@chromium.org 2013-01-09 10:30:54 +00:00
parent 9188bb67f2
commit 45f20e366a
51 changed files with 408 additions and 241 deletions

View File

@ -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',],
}],

View File

@ -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));
}

View File

@ -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);

View File

@ -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

View File

@ -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));

View File

@ -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 {

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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);
}

View File

@ -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),

View File

@ -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.

View File

@ -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

View File

@ -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();

View File

@ -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 =

View File

@ -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(

View File

@ -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;
}

View File

@ -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();

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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_,

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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 {

View File

@ -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
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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());
}

View File

@ -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);

View File

@ -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];

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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:

View File

@ -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) {

View File

@ -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)) {

View File

@ -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);

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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));
}

View File

@ -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));

View File

@ -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));

View File

@ -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));
}

View File

@ -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]);