Implement handlified String::Equals and Name::Equals.

R=ulan@chromium.org

Review URL: https://codereview.chromium.org/225823003

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20669 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
yangguo@chromium.org 2014-04-11 07:27:25 +00:00
parent 1a9fa3a673
commit a640707213
34 changed files with 385 additions and 448 deletions

View File

@ -80,10 +80,10 @@ MaybeObject* Accessors::ReadOnlySetAccessor(Isolate* isolate,
static V8_INLINE bool CheckForName(Handle<String> name,
String* property_name,
Handle<String> property_name,
int offset,
int* object_offset) {
if (name->Equals(property_name)) {
if (String::Equals(name, property_name)) {
*object_offset = offset;
return true;
}
@ -100,7 +100,7 @@ bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
Isolate* isolate = name->GetIsolate();
if (type->Is(T::String())) {
return CheckForName(name, isolate->heap()->length_string(),
return CheckForName(name, isolate->factory()->length_string(),
String::kLengthOffset, object_offset);
}
@ -110,25 +110,25 @@ bool Accessors::IsJSObjectFieldAccessor(typename T::TypeHandle type,
switch (map->instance_type()) {
case JS_ARRAY_TYPE:
return
CheckForName(name, isolate->heap()->length_string(),
CheckForName(name, isolate->factory()->length_string(),
JSArray::kLengthOffset, object_offset);
case JS_TYPED_ARRAY_TYPE:
return
CheckForName(name, isolate->heap()->length_string(),
CheckForName(name, isolate->factory()->length_string(),
JSTypedArray::kLengthOffset, object_offset) ||
CheckForName(name, isolate->heap()->byte_length_string(),
CheckForName(name, isolate->factory()->byte_length_string(),
JSTypedArray::kByteLengthOffset, object_offset) ||
CheckForName(name, isolate->heap()->byte_offset_string(),
CheckForName(name, isolate->factory()->byte_offset_string(),
JSTypedArray::kByteOffsetOffset, object_offset);
case JS_ARRAY_BUFFER_TYPE:
return
CheckForName(name, isolate->heap()->byte_length_string(),
CheckForName(name, isolate->factory()->byte_length_string(),
JSArrayBuffer::kByteLengthOffset, object_offset);
case JS_DATA_VIEW_TYPE:
return
CheckForName(name, isolate->heap()->byte_length_string(),
CheckForName(name, isolate->factory()->byte_length_string(),
JSDataView::kByteLengthOffset, object_offset) ||
CheckForName(name, isolate->heap()->byte_offset_string(),
CheckForName(name, isolate->factory()->byte_offset_string(),
JSDataView::kByteOffsetOffset, object_offset);
default:
return false;

View File

@ -3011,7 +3011,8 @@ bool Value::StrictEquals(Handle<Value> that) const {
return other->IsNumber() && obj->Number() == other->Number();
} else if (obj->IsString()) {
return other->IsString() &&
i::String::cast(*obj)->Equals(i::String::cast(*other));
i::String::Equals(i::Handle<i::String>::cast(obj),
i::Handle<i::String>::cast(other));
} else if (obj->IsUndefined() || obj->IsUndetectableObject()) {
return other->IsUndefined() || other->IsUndetectableObject();
} else {

View File

@ -4525,13 +4525,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(r0, if_true);
__ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(r0, ip);
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->string_string())) {
} else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(r0, if_false);
// Check for undetectable objects => false.
__ CompareObjectType(r0, r0, r1, FIRST_NONSTRING_TYPE);
@ -4539,20 +4540,20 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ ldrb(r1, FieldMemOperand(r0, Map::kBitFieldOffset));
__ tst(r1, Operand(1 << Map::kIsUndetectable));
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->symbol_string())) {
} else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(r0, if_false);
__ CompareObjectType(r0, r0, r1, SYMBOL_TYPE);
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
} else if (String::Equals(check, factory->boolean_string())) {
__ CompareRoot(r0, Heap::kTrueValueRootIndex);
__ b(eq, if_true);
__ CompareRoot(r0, Heap::kFalseValueRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) {
String::Equals(check, factory->null_string())) {
__ CompareRoot(r0, Heap::kNullValueRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->undefined_string())) {
} else if (String::Equals(check, factory->undefined_string())) {
__ CompareRoot(r0, Heap::kUndefinedValueRootIndex);
__ b(eq, if_true);
__ JumpIfSmi(r0, if_false);
@ -4562,14 +4563,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ tst(r1, Operand(1 << Map::kIsUndetectable));
Split(ne, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->function_string())) {
} else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(r0, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CompareObjectType(r0, r0, r1, JS_FUNCTION_TYPE);
__ b(eq, if_true);
__ cmp(r1, Operand(JS_FUNCTION_PROXY_TYPE));
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->object_string())) {
} else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(r0, if_false);
if (!FLAG_harmony_typeof) {
__ CompareRoot(r0, Heap::kNullValueRootIndex);

View File

@ -5496,13 +5496,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
Handle<String> type_name) {
Condition final_branch_condition = kNoCondition;
Register scratch = scratch0();
if (type_name->Equals(heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label);
__ ldr(scratch, FieldMemOperand(input, HeapObject::kMapOffset));
__ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->string_string())) {
} else if (String::Equals(type_name, factory->string_string())) {
__ JumpIfSmi(input, false_label);
__ CompareObjectType(input, scratch, no_reg, FIRST_NONSTRING_TYPE);
__ b(ge, false_label);
@ -5510,22 +5511,23 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = eq;
} else if (type_name->Equals(heap()->symbol_string())) {
} else if (String::Equals(type_name, factory->symbol_string())) {
__ JumpIfSmi(input, false_label);
__ CompareObjectType(input, scratch, no_reg, SYMBOL_TYPE);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->boolean_string())) {
} else if (String::Equals(type_name, factory->boolean_string())) {
__ CompareRoot(input, Heap::kTrueValueRootIndex);
__ b(eq, true_label);
__ CompareRoot(input, Heap::kFalseValueRootIndex);
final_branch_condition = eq;
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
} else if (FLAG_harmony_typeof &&
String::Equals(type_name, factory->null_string())) {
__ CompareRoot(input, Heap::kNullValueRootIndex);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->undefined_string())) {
} else if (String::Equals(type_name, factory->undefined_string())) {
__ CompareRoot(input, Heap::kUndefinedValueRootIndex);
__ b(eq, true_label);
__ JumpIfSmi(input, false_label);
@ -5535,7 +5537,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ tst(scratch, Operand(1 << Map::kIsUndetectable));
final_branch_condition = ne;
} else if (type_name->Equals(heap()->function_string())) {
} else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
Register type_reg = scratch;
__ JumpIfSmi(input, false_label);
@ -5544,7 +5546,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
__ cmp(type_reg, Operand(JS_FUNCTION_PROXY_TYPE));
final_branch_condition = eq;
} else if (type_name->Equals(heap()->object_string())) {
} else if (String::Equals(type_name, factory->object_string())) {
Register map = scratch;
__ JumpIfSmi(input, false_label);
if (!FLAG_harmony_typeof) {

View File

@ -4238,13 +4238,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(check, factory->number_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof number_string");
__ JumpIfSmi(x0, if_true);
__ Ldr(x0, FieldMemOperand(x0, HeapObject::kMapOffset));
__ CompareRoot(x0, Heap::kHeapNumberMapRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->string_string())) {
} else if (String::Equals(check, factory->string_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof string_string");
__ JumpIfSmi(x0, if_false);
// Check for undetectable objects => false.
@ -4252,22 +4253,22 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
__ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_true, if_false,
fall_through);
} else if (check->Equals(isolate()->heap()->symbol_string())) {
} else if (String::Equals(check, factory->symbol_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof symbol_string");
__ JumpIfSmi(x0, if_false);
__ CompareObjectType(x0, x0, x1, SYMBOL_TYPE);
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
} else if (String::Equals(check, factory->boolean_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof boolean_string");
__ JumpIfRoot(x0, Heap::kTrueValueRootIndex, if_true);
__ CompareRoot(x0, Heap::kFalseValueRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) {
String::Equals(check, factory->null_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof null_string");
__ CompareRoot(x0, Heap::kNullValueRootIndex);
Split(eq, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->undefined_string())) {
} else if (String::Equals(check, factory->undefined_string())) {
ASM_LOCATION(
"FullCodeGenerator::EmitLiteralCompareTypeof undefined_string");
__ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex, if_true);
@ -4277,7 +4278,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ Ldrb(x1, FieldMemOperand(x0, Map::kBitFieldOffset));
__ TestAndSplit(x1, 1 << Map::kIsUndetectable, if_false, if_true,
fall_through);
} else if (check->Equals(isolate()->heap()->function_string())) {
} else if (String::Equals(check, factory->function_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof function_string");
__ JumpIfSmi(x0, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
@ -4285,7 +4286,7 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ CompareAndSplit(x11, JS_FUNCTION_PROXY_TYPE, eq, if_true, if_false,
fall_through);
} else if (check->Equals(isolate()->heap()->object_string())) {
} else if (String::Equals(check, factory->object_string())) {
ASM_LOCATION("FullCodeGenerator::EmitLiteralCompareTypeof object_string");
__ JumpIfSmi(x0, if_false);
if (!FLAG_harmony_typeof) {

View File

@ -5715,7 +5715,8 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
Label* false_label = instr->FalseLabel(chunk_);
Register value = ToRegister(instr->value());
if (type_name->Equals(heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(type_name, factory->number_string())) {
ASSERT(instr->temp1() != NULL);
Register map = ToRegister(instr->temp1());
@ -5724,7 +5725,7 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
__ CompareRoot(map, Heap::kHeapNumberMapRootIndex);
EmitBranch(instr, eq);
} else if (type_name->Equals(heap()->string_string())) {
} else if (String::Equals(type_name, factory->string_string())) {
ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL));
Register map = ToRegister(instr->temp1());
Register scratch = ToRegister(instr->temp2());
@ -5735,7 +5736,7 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
__ Ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset));
EmitTestAndBranch(instr, eq, scratch, 1 << Map::kIsUndetectable);
} else if (type_name->Equals(heap()->symbol_string())) {
} else if (String::Equals(type_name, factory->symbol_string())) {
ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL));
Register map = ToRegister(instr->temp1());
Register scratch = ToRegister(instr->temp2());
@ -5744,16 +5745,17 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
__ CompareObjectType(value, map, scratch, SYMBOL_TYPE);
EmitBranch(instr, eq);
} else if (type_name->Equals(heap()->boolean_string())) {
} else if (String::Equals(type_name, factory->boolean_string())) {
__ JumpIfRoot(value, Heap::kTrueValueRootIndex, true_label);
__ CompareRoot(value, Heap::kFalseValueRootIndex);
EmitBranch(instr, eq);
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
} else if (FLAG_harmony_typeof &&
String::Equals(type_name, factory->null_string())) {
__ CompareRoot(value, Heap::kNullValueRootIndex);
EmitBranch(instr, eq);
} else if (type_name->Equals(heap()->undefined_string())) {
} else if (String::Equals(type_name, factory->undefined_string())) {
ASSERT(instr->temp1() != NULL);
Register scratch = ToRegister(instr->temp1());
@ -5764,7 +5766,7 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
__ Ldrb(scratch, FieldMemOperand(scratch, Map::kBitFieldOffset));
EmitTestAndBranch(instr, ne, scratch, 1 << Map::kIsUndetectable);
} else if (type_name->Equals(heap()->function_string())) {
} else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
ASSERT(instr->temp1() != NULL);
Register type = ToRegister(instr->temp1());
@ -5774,7 +5776,7 @@ void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) {
// HeapObject's type has been loaded into type register by JumpIfObjectType.
EmitCompareAndBranch(instr, eq, type, JS_FUNCTION_PROXY_TYPE);
} else if (type_name->Equals(heap()->object_string())) {
} else if (String::Equals(type_name, factory->object_string())) {
ASSERT((instr->temp1() != NULL) && (instr->temp2() != NULL));
Register map = ToRegister(instr->temp1());
Register scratch = ToRegister(instr->temp2());

View File

@ -78,7 +78,8 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
// The global identifier "undefined" is immutable. Everything
// else could be reassigned.
return var != NULL && var->location() == Variable::UNALLOCATED &&
var_proxy->name()->Equals(isolate->heap()->undefined_string());
String::Equals(var_proxy->name(),
isolate->factory()->undefined_string());
}
@ -207,9 +208,10 @@ ObjectLiteralProperty::ObjectLiteralProperty(
emit_store_ = true;
key_ = key;
value_ = value;
Object* k = *key->value();
Handle<Object> k = key->value();
if (k->IsInternalizedString() &&
zone->isolate()->heap()->proto_string()->Equals(String::cast(k))) {
String::Equals(Handle<String>::cast(k),
zone->isolate()->factory()->proto_string())) {
kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL;

View File

@ -1394,7 +1394,7 @@ class Literal V8_FINAL : public Expression {
static bool Match(void* literal1, void* literal2) {
Handle<String> s1 = static_cast<Literal*>(literal1)->ToString();
Handle<String> s2 = static_cast<Literal*>(literal2)->ToString();
return s1->Equals(*s2);
return String::Equals(s1, s2);
}
TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); }

View File

@ -161,7 +161,8 @@ bool CompilationCacheScript::HasOrigin(
// Were both scripts tagged by the embedder as being shared cross-origin?
if (is_shared_cross_origin != script->is_shared_cross_origin()) return false;
// Compare the two name strings for equality.
return String::cast(*name)->Equals(String::cast(script->name()));
return String::Equals(Handle<String>::cast(name),
Handle<String>(String::cast(script->name())));
}

View File

@ -231,7 +231,7 @@ Handle<Object> Context::Lookup(Handle<String> name,
} else if (context->IsCatchContext()) {
// Catch contexts have the variable name in the extension slot.
if (name->Equals(String::cast(context->extension()))) {
if (String::Equals(name, handle(String::cast(context->extension())))) {
if (FLAG_trace_contexts) {
PrintF("=> found in catch context\n");
}

View File

@ -56,7 +56,7 @@ double StringToDouble(UnicodeCache* unicode_cache,
double StringToDouble(UnicodeCache* unicode_cache,
Vector<const char> str,
Vector<const uint8_t> str,
int flags,
double empty_string_val) {
// We cast to const uint8_t* here to avoid instantiating the
@ -78,6 +78,23 @@ double StringToDouble(UnicodeCache* unicode_cache,
}
// Converts a string into an integer.
double StringToInt(UnicodeCache* unicode_cache,
Vector<const uint8_t> vector,
int radix) {
return InternalStringToInt(
unicode_cache, vector.start(), vector.start() + vector.length(), radix);
}
double StringToInt(UnicodeCache* unicode_cache,
Vector<const uc16> vector,
int radix) {
return InternalStringToInt(
unicode_cache, vector.start(), vector.start() + vector.length(), radix);
}
const char* DoubleToCString(double v, Vector<char> buffer) {
switch (fpclassify(v)) {
case FP_NAN: return "NaN";

View File

@ -122,7 +122,7 @@ enum ConversionFlags {
// Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache,
Vector<const char> str,
Vector<const uint8_t> str,
int flags,
double empty_string_val = 0);
double StringToDouble(UnicodeCache* unicode_cache,
@ -135,6 +135,16 @@ double StringToDouble(UnicodeCache* unicode_cache,
int flags,
double empty_string_val = 0);
// Converts a string into an integer.
double StringToInt(UnicodeCache* unicode_cache,
Vector<const uint8_t> vector,
int radix);
double StringToInt(UnicodeCache* unicode_cache,
Vector<const uc16> vector,
int radix);
const int kDoubleToCStringMinBufferSize = 100;
// Converts a double to a string value according to ECMA-262 9.8.1.

View File

@ -2009,10 +2009,9 @@ void Factory::ConfigureInstance(Handle<FunctionTemplateInfo> desc,
Handle<Object> Factory::GlobalConstantFor(Handle<String> name) {
Heap* h = isolate()->heap();
if (name->Equals(h->undefined_string())) return undefined_value();
if (name->Equals(h->nan_string())) return nan_value();
if (name->Equals(h->infinity_string())) return infinity_value();
if (String::Equals(name, undefined_string())) return undefined_value();
if (String::Equals(name, nan_string())) return nan_value();
if (String::Equals(name, infinity_string())) return infinity_value();
return Handle<Object>::null();
}

View File

@ -55,14 +55,16 @@ void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
void FuncNameInferrer::PushLiteralName(Handle<String> name) {
if (IsOpen() && !isolate()->heap()->prototype_string()->Equals(*name)) {
if (IsOpen() &&
!String::Equals(isolate()->factory()->prototype_string(), name)) {
names_stack_.Add(Name(name, kLiteralName), zone());
}
}
void FuncNameInferrer::PushVariableName(Handle<String> name) {
if (IsOpen() && !isolate()->heap()->dot_result_string()->Equals(*name)) {
if (IsOpen() &&
!String::Equals(isolate()->factory()->dot_result_string(), name)) {
names_stack_.Add(Name(name, kVariableName), zone());
}
}

View File

@ -560,25 +560,6 @@ bool Heap::CollectGarbage(AllocationSpace space,
}
MaybeObject* Heap::PrepareForCompare(String* str) {
// Always flatten small strings and force flattening of long strings
// after we have accumulated a certain amount we failed to flatten.
static const int kMaxAlwaysFlattenLength = 32;
static const int kFlattenLongThreshold = 16*KB;
const int length = str->length();
MaybeObject* obj = str->TryFlatten();
if (length <= kMaxAlwaysFlattenLength ||
unflattened_strings_length_ >= kFlattenLongThreshold) {
return obj;
}
if (obj->IsFailure()) {
unflattened_strings_length_ += length;
}
return str;
}
int64_t Heap::AdjustAmountOfExternalAllocatedMemory(
int64_t change_in_bytes) {
ASSERT(HasBeenSetUp());

View File

@ -1169,15 +1169,6 @@ class Heap {
// NULL is returned if string is in new space or not flattened.
Map* InternalizedStringMapForString(String* str);
// Tries to flatten a string before compare operation.
//
// Returns a failure in case it was decided that flattening was
// necessary and failed. Note, if flattening is not necessary the
// string might stay non-flat even when not a failure is returned.
//
// Please note this function does not perform a garbage collection.
MUST_USE_RESULT inline MaybeObject* PrepareForCompare(String* str);
// Converts the given boolean condition to JavaScript boolean value.
inline Object* ToBoolean(bool condition);

View File

@ -2393,10 +2393,10 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
int offset;
if (Accessors::IsJSObjectFieldAccessor<Type>(type_, name_, &offset)) {
if (type_->Is(Type::String())) {
ASSERT(name_->Equals(isolate()->heap()->length_string()));
ASSERT(String::Equals(isolate()->factory()->length_string(), name_));
*access = HObjectAccess::ForStringLength();
} else if (type_->Is(Type::Array())) {
ASSERT(name_->Equals(isolate()->heap()->length_string()));
ASSERT(String::Equals(isolate()->factory()->length_string(), name_));
*access = HObjectAccess::ForArrayLength(map()->elements_kind());
} else {
*access = HObjectAccess::ForMapAndOffset(map(), offset);

View File

@ -4536,12 +4536,13 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(eax, if_true);
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map());
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->string_string())) {
} else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
__ j(above_equal, if_false);
@ -4549,20 +4550,20 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ test_b(FieldOperand(edx, Map::kBitFieldOffset),
1 << Map::kIsUndetectable);
Split(zero, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->symbol_string())) {
} else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, SYMBOL_TYPE, edx);
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
} else if (String::Equals(check, factory->boolean_string())) {
__ cmp(eax, isolate()->factory()->true_value());
__ j(equal, if_true);
__ cmp(eax, isolate()->factory()->false_value());
Split(equal, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) {
String::Equals(check, factory->null_string())) {
__ cmp(eax, isolate()->factory()->null_value());
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->undefined_string())) {
} else if (String::Equals(check, factory->undefined_string())) {
__ cmp(eax, isolate()->factory()->undefined_value());
__ j(equal, if_true);
__ JumpIfSmi(eax, if_false);
@ -4571,14 +4572,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ test(ecx, Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->function_string())) {
} else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(eax, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
__ j(equal, if_true);
__ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->object_string())) {
} else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(eax, if_false);
if (!FLAG_harmony_typeof) {
__ cmp(eax, isolate()->factory()->null_value());

View File

@ -6094,13 +6094,13 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
Label::Distance false_distance = right_block == next_block ? Label::kNear
: Label::kFar;
Condition final_branch_condition = no_condition;
if (type_name->Equals(heap()->number_string())) {
if (String::Equals(type_name, factory()->number_string())) {
__ JumpIfSmi(input, true_label, true_distance);
__ cmp(FieldOperand(input, HeapObject::kMapOffset),
factory()->heap_number_map());
final_branch_condition = equal;
} else if (type_name->Equals(heap()->string_string())) {
} else if (String::Equals(type_name, factory()->string_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
__ j(above_equal, false_label, false_distance);
@ -6108,22 +6108,23 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
1 << Map::kIsUndetectable);
final_branch_condition = zero;
} else if (type_name->Equals(heap()->symbol_string())) {
} else if (String::Equals(type_name, factory()->symbol_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, SYMBOL_TYPE, input);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->boolean_string())) {
} else if (String::Equals(type_name, factory()->boolean_string())) {
__ cmp(input, factory()->true_value());
__ j(equal, true_label, true_distance);
__ cmp(input, factory()->false_value());
final_branch_condition = equal;
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
} else if (FLAG_harmony_typeof &&
String::Equals(type_name, factory()->null_string())) {
__ cmp(input, factory()->null_value());
final_branch_condition = equal;
} else if (type_name->Equals(heap()->undefined_string())) {
} else if (String::Equals(type_name, factory()->undefined_string())) {
__ cmp(input, factory()->undefined_value());
__ j(equal, true_label, true_distance);
__ JumpIfSmi(input, false_label, false_distance);
@ -6133,7 +6134,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
1 << Map::kIsUndetectable);
final_branch_condition = not_zero;
} else if (type_name->Equals(heap()->function_string())) {
} else if (String::Equals(type_name, factory()->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
@ -6141,7 +6142,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->object_string())) {
} else if (String::Equals(type_name, factory()->object_string())) {
__ JumpIfSmi(input, false_label, false_distance);
if (!FLAG_harmony_typeof) {
__ cmp(input, factory()->null_value());

View File

@ -547,7 +547,7 @@ MaybeObject* LoadIC::Load(Handle<Object> object,
if (FLAG_use_ic) {
// Use specialized code for getting prototype of functions.
if (object->IsJSFunction() &&
name->Equals(isolate()->heap()->prototype_string()) &&
String::Equals(isolate()->factory()->prototype_string(), name) &&
Handle<JSFunction>::cast(object)->should_have_prototype()) {
Handle<Code> stub;
if (state() == UNINITIALIZED) {
@ -890,13 +890,14 @@ Handle<Code> LoadIC::CompileHandler(LookupResult* lookup,
Handle<String> name,
Handle<Object> unused,
InlineCacheHolderFlag cache_holder) {
if (object->IsString() && name->Equals(isolate()->heap()->length_string())) {
if (object->IsString() &&
String::Equals(isolate()->factory()->length_string(), name)) {
int length_index = String::kLengthOffset / kPointerSize;
return SimpleFieldLoad(length_index);
}
if (object->IsStringWrapper() &&
name->Equals(isolate()->heap()->length_string())) {
String::Equals(isolate()->factory()->length_string(), name)) {
if (kind() == Code::LOAD_IC) {
StringLengthStub string_length_stub;
return string_length_stub.GetCode(isolate());
@ -1216,7 +1217,7 @@ MaybeObject* StoreIC::Store(Handle<Object> object,
// The length property of string values is read-only. Throw in strict mode.
if (strict_mode() == STRICT && object->IsString() &&
name->Equals(isolate()->heap()->length_string())) {
String::Equals(isolate()->factory()->length_string(), name)) {
return TypeError("strict_read_only_property", object, name);
}
@ -1403,7 +1404,7 @@ Handle<Code> StoreIC::CompileHandler(LookupResult* lookup,
// properties. Slow properties might indicate redefinition of the length
// property.
if (receiver->IsJSArray() &&
name->Equals(isolate()->heap()->length_string()) &&
String::Equals(isolate()->factory()->length_string(), name) &&
Handle<JSArray>::cast(receiver)->AllowsSetElementsLength() &&
receiver->HasFastProperties()) {
return compiler.CompileStoreArrayLength(receiver, lookup, name);

View File

@ -539,17 +539,16 @@ Handle<Object> JsonParser<seq_ascii>::ParseJsonNumber() {
if (seq_ascii) {
Vector<const uint8_t> chars(seq_source_->GetChars() + beg_pos, length);
number = StringToDouble(isolate()->unicode_cache(),
Vector<const char>::cast(chars),
NO_FLAGS, // Hex, octal or trailing junk.
OS::nan_value());
chars,
NO_FLAGS, // Hex, octal or trailing junk.
OS::nan_value());
} else {
Vector<uint8_t> buffer = Vector<uint8_t>::New(length);
String::WriteToFlat(*source_, buffer.start(), beg_pos, position_);
Vector<const uint8_t> result =
Vector<const uint8_t>(buffer.start(), length);
number = StringToDouble(isolate()->unicode_cache(),
// TODO(dcarney): Convert StringToDouble to uint_t.
Vector<const char>::cast(result),
result,
NO_FLAGS, // Hex, octal or trailing junk.
0.0);
buffer.Dispose();

View File

@ -4575,12 +4575,13 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(v0, if_true);
__ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
Split(eq, v0, Operand(at), if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->string_string())) {
} else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(v0, if_false);
// Check for undetectable objects => false.
__ GetObjectType(v0, v0, a1);
@ -4589,20 +4590,20 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ And(a1, a1, Operand(1 << Map::kIsUndetectable));
Split(eq, a1, Operand(zero_reg),
if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->symbol_string())) {
} else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(v0, if_false);
__ GetObjectType(v0, v0, a1);
Split(eq, a1, Operand(SYMBOL_TYPE), if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
} else if (String::Equals(check, factory->boolean_string())) {
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(if_true, eq, v0, Operand(at));
__ LoadRoot(at, Heap::kFalseValueRootIndex);
Split(eq, v0, Operand(at), if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) {
String::Equals(check, factory->null_string())) {
__ LoadRoot(at, Heap::kNullValueRootIndex);
Split(eq, v0, Operand(at), if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->undefined_string())) {
} else if (String::Equals(check, factory->undefined_string())) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(if_true, eq, v0, Operand(at));
__ JumpIfSmi(v0, if_false);
@ -4611,14 +4612,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ lbu(a1, FieldMemOperand(v0, Map::kBitFieldOffset));
__ And(a1, a1, Operand(1 << Map::kIsUndetectable));
Split(ne, a1, Operand(zero_reg), if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->function_string())) {
} else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(v0, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ GetObjectType(v0, v0, a1);
__ Branch(if_true, eq, a1, Operand(JS_FUNCTION_TYPE));
Split(eq, a1, Operand(JS_FUNCTION_PROXY_TYPE),
if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->object_string())) {
} else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(v0, if_false);
if (!FLAG_harmony_typeof) {
__ LoadRoot(at, Heap::kNullValueRootIndex);

View File

@ -5524,7 +5524,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
// register.
Condition final_branch_condition = kNoCondition;
Register scratch = scratch0();
if (type_name->Equals(heap()->number_string())) {
Factory* factory = isolate()->factory();facto
if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label);
__ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
@ -5532,7 +5533,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(at);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->string_string())) {
} else if (String::Equals(type_name, factory->string_string())) {
__ JumpIfSmi(input, false_label);
__ GetObjectType(input, input, scratch);
__ Branch(USE_DELAY_SLOT, false_label,
@ -5545,14 +5546,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(zero_reg);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->symbol_string())) {
} else if (String::Equals(type_name, factory->symbol_string())) {
__ JumpIfSmi(input, false_label);
__ GetObjectType(input, input, scratch);
cmp1 = scratch;
cmp2 = Operand(SYMBOL_TYPE);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->boolean_string())) {
} else if (String::Equals(type_name, factory->boolean_string())) {
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
__ LoadRoot(at, Heap::kFalseValueRootIndex);
@ -5560,13 +5561,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(input);
final_branch_condition = eq;
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
} else if (FLAG_harmony_typeof &&
String::Equals(type_name, factory->null_string())) {
__ LoadRoot(at, Heap::kNullValueRootIndex);
cmp1 = at;
cmp2 = Operand(input);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->undefined_string())) {
} else if (String::Equals(type_name, factory->undefined_string())) {
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
// The first instruction of JumpIfSmi is an And - it is safe in the delay
@ -5580,7 +5582,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(zero_reg);
final_branch_condition = ne;
} else if (type_name->Equals(heap()->function_string())) {
} else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label);
__ GetObjectType(input, scratch, input);
@ -5589,7 +5591,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(JS_FUNCTION_PROXY_TYPE);
final_branch_condition = eq;
} else if (type_name->Equals(heap()->object_string())) {
} else if (String::Equals(type_name, factory->object_string())) {
__ JumpIfSmi(input, false_label);
if (!FLAG_harmony_typeof) {
__ LoadRoot(at, Heap::kNullValueRootIndex);

View File

@ -3043,6 +3043,17 @@ bool Name::Equals(Name* other) {
}
bool Name::Equals(Handle<Name> one, Handle<Name> two) {
if (one.is_identical_to(two)) return true;
if ((one->IsInternalizedString() && two->IsInternalizedString()) ||
one->IsSymbol() || two->IsSymbol()) {
return false;
}
return String::SlowEquals(Handle<String>::cast(one),
Handle<String>::cast(two));
}
ACCESSORS(Symbol, name, Object, kNameOffset)
ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit)
@ -3057,6 +3068,15 @@ bool String::Equals(String* other) {
}
bool String::Equals(Handle<String> one, Handle<String> two) {
if (one.is_identical_to(two)) return true;
if (one->IsInternalizedString() && two->IsInternalizedString()) {
return false;
}
return SlowEquals(one, two);
}
Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
if (!string->IsConsString()) return string;
Handle<ConsString> cons = Handle<ConsString>::cast(string);
@ -3065,22 +3085,6 @@ Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
}
MaybeObject* String::TryFlatten(PretenureFlag pretenure) {
if (!StringShape(this).IsCons()) return this;
ConsString* cons = ConsString::cast(this);
if (cons->IsFlat()) return cons->first();
return SlowTryFlatten(pretenure);
}
String* String::TryFlattenGetString(PretenureFlag pretenure) {
MaybeObject* flat = TryFlatten(pretenure);
Object* successfully_flattened;
if (!flat->ToObject(&successfully_flattened)) return this;
return String::cast(successfully_flattened);
}
uint16_t String::Get(int index) {
ASSERT(index >= 0 && index < length());
switch (StringShape(this).full_representation_tag()) {

View File

@ -1214,73 +1214,11 @@ Handle<String> String::SlowFlatten(Handle<ConsString> cons,
}
cons->set_first(*result);
cons->set_second(isolate->heap()->empty_string());
ASSERT(result->IsFlat());
return result;
}
MaybeObject* String::SlowTryFlatten(PretenureFlag pretenure) {
#ifdef DEBUG
// Do not attempt to flatten in debug mode when allocation is not
// allowed. This is to avoid an assertion failure when allocating.
// Flattening strings is the only case where we always allow
// allocation because no GC is performed if the allocation fails.
if (!AllowHeapAllocation::IsAllowed()) return this;
#endif
Heap* heap = GetHeap();
switch (StringShape(this).representation_tag()) {
case kConsStringTag: {
ConsString* cs = ConsString::cast(this);
if (cs->second()->length() == 0) {
return cs->first();
}
// There's little point in putting the flat string in new space if the
// cons string is in old space. It can never get GCed until there is
// an old space GC.
PretenureFlag tenure = heap->InNewSpace(this) ? pretenure : TENURED;
int len = length();
Object* object;
String* result;
if (IsOneByteRepresentation()) {
{ MaybeObject* maybe_object =
heap->AllocateRawOneByteString(len, tenure);
if (!maybe_object->ToObject(&object)) return maybe_object;
}
result = String::cast(object);
String* first = cs->first();
int first_length = first->length();
uint8_t* dest = SeqOneByteString::cast(result)->GetChars();
WriteToFlat(first, dest, 0, first_length);
String* second = cs->second();
WriteToFlat(second,
dest + first_length,
0,
len - first_length);
} else {
{ MaybeObject* maybe_object =
heap->AllocateRawTwoByteString(len, tenure);
if (!maybe_object->ToObject(&object)) return maybe_object;
}
result = String::cast(object);
uc16* dest = SeqTwoByteString::cast(result)->GetChars();
String* first = cs->first();
int first_length = first->length();
WriteToFlat(first, dest, 0, first_length);
String* second = cs->second();
WriteToFlat(second,
dest + first_length,
0,
len - first_length);
}
cs->set_first(result);
cs->set_second(heap->empty_string(), SKIP_WRITE_BARRIER);
return result;
}
default:
return this;
}
}
bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
// Externalizing twice leaks the external resource, so it's
@ -6070,18 +6008,6 @@ int Map::NextFreePropertyIndex() {
}
AccessorDescriptor* Map::FindAccessor(Name* name) {
DescriptorArray* descs = instance_descriptors();
int number_of_own_descriptors = NumberOfOwnDescriptors();
for (int i = 0; i < number_of_own_descriptors; i++) {
if (descs->GetType(i) == CALLBACKS && name->Equals(descs->GetKey(i))) {
return descs->GetCallbacks(i);
}
}
return NULL;
}
void JSReceiver::LocalLookup(
Name* name, LookupResult* result, bool search_hidden_prototypes) {
ASSERT(name->IsName());
@ -6577,8 +6503,8 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> object,
if (result.IsFound()) {
Handle<Map> target(result.GetTransitionTarget());
int descriptor_number = target->LastAdded();
ASSERT(target->instance_descriptors()->GetKey(descriptor_number)
->Equals(*name));
ASSERT(Name::Equals(name,
handle(target->instance_descriptors()->GetKey(descriptor_number))));
return TryAccessorTransition(object, target, descriptor_number,
component, accessor, attributes);
}
@ -8330,7 +8256,7 @@ String::FlatContent String::GetFlatContent() {
} else {
start = ExternalAsciiString::cast(string)->GetChars();
}
return FlatContent(Vector<const uint8_t>(start + offset, length));
return FlatContent(start + offset, length);
} else {
ASSERT(shape.encoding_tag() == kTwoByteStringTag);
const uc16* start;
@ -8339,7 +8265,7 @@ String::FlatContent String::GetFlatContent() {
} else {
start = ExternalTwoByteString::cast(string)->GetChars();
}
return FlatContent(Vector<const uc16>(start + offset, length));
return FlatContent(start + offset, length);
}
}
@ -8979,6 +8905,7 @@ class StringComparator {
bool String::SlowEquals(String* other) {
DisallowHeapAllocation no_gc;
// Fast check: negative check with lengths.
int len = length();
if (len != other->length()) return false;
@ -9008,14 +8935,10 @@ bool String::SlowEquals(String* other) {
// before we try to flatten the strings.
if (this->Get(0) != other->Get(0)) return false;
String* lhs = this->TryFlattenGetString();
String* rhs = other->TryFlattenGetString();
// TODO(dcarney): Compare all types of flat strings with a Visitor.
if (StringShape(lhs).IsSequentialAscii() &&
StringShape(rhs).IsSequentialAscii()) {
const uint8_t* str1 = SeqOneByteString::cast(lhs)->GetChars();
const uint8_t* str2 = SeqOneByteString::cast(rhs)->GetChars();
if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
return CompareRawStringContents(str1, str2, len);
}
@ -9023,7 +8946,57 @@ bool String::SlowEquals(String* other) {
StringComparator comparator(isolate->objects_string_compare_iterator_a(),
isolate->objects_string_compare_iterator_b());
return comparator.Equals(static_cast<unsigned>(len), lhs, rhs);
return comparator.Equals(static_cast<unsigned>(len), this, other);
}
bool String::SlowEquals(Handle<String> one, Handle<String> two) {
// Fast check: negative check with lengths.
int one_length = one->length();
if (one_length != two->length()) return false;
if (one_length == 0) return true;
// Fast check: if hash code is computed for both strings
// a fast negative check can be performed.
if (one->HasHashCode() && two->HasHashCode()) {
#ifdef ENABLE_SLOW_ASSERTS
if (FLAG_enable_slow_asserts) {
if (one->Hash() != two->Hash()) {
bool found_difference = false;
for (int i = 0; i < one_length; i++) {
if (one->Get(i) != two->Get(i)) {
found_difference = true;
break;
}
}
ASSERT(found_difference);
}
}
#endif
if (one->Hash() != two->Hash()) return false;
}
// We know the strings are both non-empty. Compare the first chars
// before we try to flatten the strings.
if (one->Get(0) != two->Get(0)) return false;
one = String::Flatten(one);
two = String::Flatten(two);
DisallowHeapAllocation no_gc;
String::FlatContent flat1 = one->GetFlatContent();
String::FlatContent flat2 = two->GetFlatContent();
if (flat1.IsAscii() && flat2.IsAscii()) {
return CompareRawStringContents(flat1.ToOneByteVector().start(),
flat2.ToOneByteVector().start(),
one_length);
} else {
for (int i = 0; i < one_length; i++) {
if (flat1.Get(i) != flat2.Get(i)) return false;
}
return true;
}
}

View File

@ -6466,9 +6466,6 @@ class Map: public HeapObject {
// Casting.
static inline Map* cast(Object* obj);
// Locate an accessor in the instance descriptor.
AccessorDescriptor* FindAccessor(Name* name);
// Code cache operations.
// Clears the code cache.
@ -8791,6 +8788,7 @@ class Name: public HeapObject {
// Equality operations.
inline bool Equals(Name* other);
inline static bool Equals(Handle<Name> one, Handle<Name> two);
// Conversion.
inline bool AsArrayIndex(uint32_t* index);
@ -8927,28 +8925,37 @@ class String: public Name {
// true.
Vector<const uint8_t> ToOneByteVector() {
ASSERT_EQ(ASCII, state_);
return buffer_;
return Vector<const uint8_t>(onebyte_start, length_);
}
// Return the two-byte content of the string. Only use if IsTwoByte()
// returns true.
Vector<const uc16> ToUC16Vector() {
ASSERT_EQ(TWO_BYTE, state_);
return Vector<const uc16>::cast(buffer_);
return Vector<const uc16>(twobyte_start, length_);
}
uc16 Get(int i) {
ASSERT(i < length_);
ASSERT(state_ != NON_FLAT);
if (state_ == ASCII) return onebyte_start[i];
return twobyte_start[i];
}
private:
enum State { NON_FLAT, ASCII, TWO_BYTE };
// Constructors only used by String::GetFlatContent().
explicit FlatContent(Vector<const uint8_t> chars)
: buffer_(chars),
state_(ASCII) { }
explicit FlatContent(Vector<const uc16> chars)
: buffer_(Vector<const byte>::cast(chars)),
state_(TWO_BYTE) { }
FlatContent() : buffer_(), state_(NON_FLAT) { }
explicit FlatContent(const uint8_t* start, int length)
: onebyte_start(start), length_(length), state_(ASCII) { }
explicit FlatContent(const uc16* start, int length)
: twobyte_start(start), length_(length), state_(TWO_BYTE) { }
FlatContent() : onebyte_start(NULL), length_(0), state_(NON_FLAT) { }
Vector<const uint8_t> buffer_;
union {
const uint8_t* onebyte_start;
const uc16* twobyte_start;
};
int length_;
State state_;
friend class String;
@ -8986,7 +8993,7 @@ class String: public Name {
// to this method are not efficient unless the string is flat.
INLINE(uint16_t Get(int index));
// Try to flatten the string. Checks first inline to see if it is
// Flattens the string. Checks first inline to see if it is
// necessary. Does nothing if the string is not a cons string.
// Flattening allocates a sequential string with the same data as
// the given string and mutates the cons string to a degenerate
@ -8998,23 +9005,10 @@ class String: public Name {
//
// Degenerate cons strings are handled specially by the garbage
// collector (see IsShortcutCandidate).
//
// Use FlattenString from Handles.cc to flatten even in case an
// allocation failure happens.
inline MaybeObject* TryFlatten(PretenureFlag pretenure = NOT_TENURED);
// Convenience function. Has exactly the same behavior as
// TryFlatten(), except in the case of failure returns the original
// string.
inline String* TryFlattenGetString(PretenureFlag pretenure = NOT_TENURED);
static inline Handle<String> Flatten(Handle<String> string,
PretenureFlag pretenure = NOT_TENURED);
static Handle<String> SlowFlatten(Handle<ConsString> cons,
PretenureFlag tenure);
// Tries to return the content of a flat string as a structure holding either
// a flat vector of char or of uc16.
// If the string isn't flat, and therefore doesn't have flat content, the
@ -9032,6 +9026,7 @@ class String: public Name {
// String equality operations.
inline bool Equals(String* other);
inline static bool Equals(Handle<String> one, Handle<String> two);
bool IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match = false);
bool IsOneByteEqualTo(Vector<const uint8_t> str);
bool IsTwoByteEqualTo(Vector<const uc16> str);
@ -9202,15 +9197,15 @@ class String: public Name {
private:
friend class Name;
// Try to flatten the top level ConsString that is hiding behind this
// string. This is a no-op unless the string is a ConsString. Flatten
// mutates the ConsString and might return a failure.
MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
static Handle<String> SlowFlatten(Handle<ConsString> cons,
PretenureFlag tenure);
// Slow case of String::Equals. This implementation works on any strings
// but it is most efficient on strings that are almost flat.
bool SlowEquals(String* other);
static bool SlowEquals(Handle<String> one, Handle<String> two);
// Slow case of AsArrayIndex.
bool SlowAsArrayIndex(uint32_t* index);

View File

@ -1126,7 +1126,8 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
// Check "use strict" directive (ES5 14.1).
if (strict_mode() == SLOPPY &&
directive->Equals(isolate()->heap()->use_strict_string()) &&
String::Equals(isolate()->factory()->use_strict_string(),
directive) &&
token_loc.end_pos - token_loc.beg_pos ==
isolate()->heap()->use_strict_string()->length() + 2) {
// TODO(mstarzinger): Global strict eval calls, need their own scope
@ -1195,8 +1196,8 @@ Statement* Parser::ParseModuleElement(ZoneStringList* labels,
ExpressionStatement* estmt = stmt->AsExpressionStatement();
if (estmt != NULL &&
estmt->expression()->AsVariableProxy() != NULL &&
estmt->expression()->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_string()) &&
String::Equals(isolate()->factory()->module_string(),
estmt->expression()->AsVariableProxy()->name()) &&
!scanner()->literal_contains_escapes()) {
return ParseModuleDeclaration(NULL, ok);
}
@ -2393,8 +2394,8 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
!scanner()->HasAnyLineTerminatorBeforeNext() &&
expr != NULL &&
expr->AsVariableProxy() != NULL &&
expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->native_string()) &&
String::Equals(isolate()->factory()->native_string(),
expr->AsVariableProxy()->name()) &&
!scanner()->literal_contains_escapes()) {
return ParseNativeDeclaration(ok);
}
@ -2405,8 +2406,8 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
peek() != Token::IDENTIFIER ||
scanner()->HasAnyLineTerminatorBeforeNext() ||
expr->AsVariableProxy() == NULL ||
!expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->module_string()) ||
!String::Equals(isolate()->factory()->module_string(),
expr->AsVariableProxy()->name()) ||
scanner()->literal_contains_escapes()) {
ExpectSemicolon(CHECK_OK);
}

View File

@ -4373,8 +4373,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringIndexOf) {
if (!index->ToArrayIndex(&start_index)) return Smi::FromInt(-1);
RUNTIME_ASSERT(start_index <= static_cast<uint32_t>(sub->length()));
int position =
Runtime::StringMatch(isolate, sub, pat, start_index);
int position = Runtime::StringMatch(isolate, sub, pat, start_index);
return Smi::FromInt(position);
}
@ -4474,13 +4473,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLastIndexOf) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
SealHandleScope shs(isolate);
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(String, str1, 0);
CONVERT_ARG_CHECKED(String, str2, 1);
CONVERT_ARG_HANDLE_CHECKED(String, str1, 0);
CONVERT_ARG_HANDLE_CHECKED(String, str2, 1);
if (str1 == str2) return Smi::FromInt(0); // Equal.
if (str1.is_identical_to(str2)) return Smi::FromInt(0); // Equal.
int str1_length = str1->length();
int str2_length = str2->length();
@ -4500,21 +4499,17 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringLocaleCompare) {
int d = str1->Get(0) - str2->Get(0);
if (d != 0) return Smi::FromInt(d);
str1->TryFlatten();
str2->TryFlatten();
str1 = String::Flatten(str1);
str2 = String::Flatten(str2);
ConsStringIteratorOp* op1 =
isolate->runtime_state()->string_locale_compare_it1();
ConsStringIteratorOp* op2 =
isolate->runtime_state()->string_locale_compare_it2();
// TODO(dcarney) Can do array compares here more efficiently.
StringCharacterStream stream1(str1, op1);
StringCharacterStream stream2(str2, op2);
DisallowHeapAllocation no_gc;
String::FlatContent flat1 = str1->GetFlatContent();
String::FlatContent flat2 = str2->GetFlatContent();
for (int i = 0; i < end; i++) {
uint16_t char1 = stream1.GetNext();
uint16_t char2 = stream2.GetNext();
if (char1 != char2) return Smi::FromInt(char1 - char2);
if (flat1.Get(i) != flat2.Get(i)) {
return Smi::FromInt(flat1.Get(i) - flat2.Get(i));
}
}
return Smi::FromInt(str1_length - str2_length);
@ -6085,8 +6080,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetArgumentsProperty) {
}
// Handle special arguments properties.
if (key->Equals(isolate->heap()->length_string())) return Smi::FromInt(n);
if (key->Equals(isolate->heap()->callee_string())) {
if (String::Equals(isolate->factory()->length_string(), key)) {
return Smi::FromInt(n);
}
if (String::Equals(isolate->factory()->callee_string(), key)) {
JSFunction* function = frame->function();
if (function->shared()->strict_mode() == STRICT) {
return isolate->Throw(*isolate->factory()->NewTypeError(
@ -6189,17 +6186,18 @@ static int ParseDecimalInteger(const uint8_t*s, int from, int to) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
SealHandleScope shs(isolate);
HandleScope handle_scope(isolate);
ASSERT(args.length() == 1);
CONVERT_ARG_CHECKED(String, subject, 0);
subject->TryFlatten();
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
subject = String::Flatten(subject);
// Fast case: short integer or some sorts of junk values.
int len = subject->length();
if (subject->IsSeqOneByteString()) {
int len = subject->length();
if (len == 0) return Smi::FromInt(0);
uint8_t const* data = SeqOneByteString::cast(subject)->GetChars();
DisallowHeapAllocation no_gc;
uint8_t const* data = Handle<SeqOneByteString>::cast(subject)->GetChars();
bool minus = (data[0] == '-');
int start_pos = (minus ? 1 : 0);
@ -6207,15 +6205,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
return isolate->heap()->nan_value();
} else if (data[start_pos] > '9') {
// Fast check for a junk value. A valid string may start from a
// whitespace, a sign ('+' or '-'), the decimal point, a decimal digit or
// the 'I' character ('Infinity'). All of that have codes not greater than
// '9' except 'I' and &nbsp;.
// whitespace, a sign ('+' or '-'), the decimal point, a decimal digit
// or the 'I' character ('Infinity'). All of that have codes not greater
// than '9' except 'I' and &nbsp;.
if (data[start_pos] != 'I' && data[start_pos] != 0xa0) {
return isolate->heap()->nan_value();
}
} else if (len - start_pos < 10 && AreDigits(data, start_pos, len)) {
// The maximal/minimal smi has 10 digits. If the string has less digits we
// know it will fit into the smi-data type.
// The maximal/minimal smi has 10 digits. If the string has less digits
// we know it will fit into the smi-data type.
int d = ParseDecimalInteger(data, start_pos, len);
if (minus) {
if (d == 0) return isolate->heap()->minus_zero_value();
@ -6244,8 +6242,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringToNumber) {
// Type", https://bugs.ecmascript.org/show_bug.cgi?id=1584
flags |= ALLOW_OCTAL | ALLOW_BINARY;
}
return isolate->heap()->NumberFromDouble(
StringToDouble(isolate->unicode_cache(), subject, flags));
return *isolate->factory()->NewNumber(StringToDouble(
isolate->unicode_cache(), *subject, flags));
}
@ -6319,29 +6318,40 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_BasicJSONStringify) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseInt) {
SealHandleScope shs(isolate);
CONVERT_ARG_CHECKED(String, s, 0);
HandleScope handle_scope(isolate);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
CONVERT_NUMBER_CHECKED(int, radix, Int32, args[1]);
s->TryFlatten();
RUNTIME_ASSERT(radix == 0 || (2 <= radix && radix <= 36));
double value = StringToInt(isolate->unicode_cache(), s, radix);
return isolate->heap()->NumberFromDouble(value);
subject = String::Flatten(subject);
double value;
{ DisallowHeapAllocation no_gc;
String::FlatContent flat = subject->GetFlatContent();
// ECMA-262 section 15.1.2.3, empty string is NaN
if (flat.IsAscii()) {
value = StringToInt(
isolate->unicode_cache(), flat.ToOneByteVector(), radix);
} else {
value = StringToInt(
isolate->unicode_cache(), flat.ToUC16Vector(), radix);
}
}
return *isolate->factory()->NewNumber(value);
}
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringParseFloat) {
SealHandleScope shs(isolate);
CONVERT_ARG_CHECKED(String, str, 0);
HandleScope shs(isolate);
CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
// ECMA-262 section 15.1.2.3, empty string is NaN
double value = StringToDouble(isolate->unicode_cache(),
str, ALLOW_TRAILING_JUNK, OS::nan_value());
subject = String::Flatten(subject);
double value = StringToDouble(
isolate->unicode_cache(), *subject, ALLOW_TRAILING_JUNK, OS::nan_value());
// Create a number object from the value.
return isolate->heap()->NumberFromDouble(value);
return *isolate->factory()->NewNumber(value);
}
@ -7516,13 +7526,13 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_NumberEquals) {
RUNTIME_FUNCTION(MaybeObject*, Runtime_StringEquals) {
SealHandleScope shs(isolate);
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(String, x, 0);
CONVERT_ARG_CHECKED(String, y, 1);
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
bool not_equal = !x->Equals(y);
bool not_equal = !String::Equals(x, y);
// This is slightly convoluted because the value that signifies
// equality is 0 and inequality is 1 so we have to negate the result
// from String::Equals.
@ -7623,27 +7633,33 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_SmiLexicographicCompare) {
}
static Object* StringCharacterStreamCompare(RuntimeState* state,
String* x,
String* y) {
StringCharacterStream stream_x(x, state->string_iterator_compare_x());
StringCharacterStream stream_y(y, state->string_iterator_compare_y());
while (stream_x.HasMore() && stream_y.HasMore()) {
int d = stream_x.GetNext() - stream_y.GetNext();
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
HandleScope handle_scope(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_HANDLE_CHECKED(String, x, 0);
CONVERT_ARG_HANDLE_CHECKED(String, y, 1);
isolate->counters()->string_compare_runtime()->Increment();
// A few fast case tests before we flatten.
if (x.is_identical_to(y)) return Smi::FromInt(EQUAL);
if (y->length() == 0) {
if (x->length() == 0) return Smi::FromInt(EQUAL);
return Smi::FromInt(GREATER);
} else if (x->length() == 0) {
return Smi::FromInt(LESS);
}
// x is (non-trivial) prefix of y:
if (stream_y.HasMore()) return Smi::FromInt(LESS);
// y is prefix of x:
return Smi::FromInt(stream_x.HasMore() ? GREATER : EQUAL);
}
int d = x->Get(0) - y->Get(0);
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
// Slow case.
x = String::Flatten(x);
y = String::Flatten(y);
static Object* FlatStringCompare(String* x, String* y) {
ASSERT(x->IsFlat());
ASSERT(y->IsFlat());
DisallowHeapAllocation no_gc;
Object* equal_prefix_result = Smi::FromInt(EQUAL);
int prefix_length = x->length();
if (y->length() < prefix_length) {
@ -7653,7 +7669,6 @@ static Object* FlatStringCompare(String* x, String* y) {
equal_prefix_result = Smi::FromInt(LESS);
}
int r;
DisallowHeapAllocation no_gc;
String::FlatContent x_content = x->GetFlatContent();
String::FlatContent y_content = y->GetFlatContent();
if (x_content.IsAscii()) {
@ -7681,47 +7696,10 @@ static Object* FlatStringCompare(String* x, String* y) {
} else {
result = (r < 0) ? Smi::FromInt(LESS) : Smi::FromInt(GREATER);
}
ASSERT(result ==
StringCharacterStreamCompare(x->GetIsolate()->runtime_state(), x, y));
return result;
}
RUNTIME_FUNCTION(MaybeObject*, RuntimeHidden_StringCompare) {
HandleScope shs(isolate);
ASSERT(args.length() == 2);
CONVERT_ARG_CHECKED(String, x, 0);
CONVERT_ARG_CHECKED(String, y, 1);
isolate->counters()->string_compare_runtime()->Increment();
// A few fast case tests before we flatten.
if (x == y) return Smi::FromInt(EQUAL);
if (y->length() == 0) {
if (x->length() == 0) return Smi::FromInt(EQUAL);
return Smi::FromInt(GREATER);
} else if (x->length() == 0) {
return Smi::FromInt(LESS);
}
int d = x->Get(0) - y->Get(0);
if (d < 0) return Smi::FromInt(LESS);
else if (d > 0) return Smi::FromInt(GREATER);
Object* obj;
{ MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(x);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
{ MaybeObject* maybe_obj = isolate->heap()->PrepareForCompare(y);
if (!maybe_obj->ToObject(&obj)) return maybe_obj;
}
return (x->IsFlat() && y->IsFlat()) ? FlatStringCompare(x, y)
: StringCharacterStreamCompare(isolate->runtime_state(), x, y);
}
#define RUNTIME_UNARY_MATH(Name, name) \
RUNTIME_FUNCTION(MaybeObject*, Runtime_Math##Name) { \
SealHandleScope shs(isolate); \
@ -11596,7 +11574,7 @@ static bool SetContextLocalValue(Isolate* isolate,
Handle<Object> new_value) {
for (int i = 0; i < scope_info->ContextLocalCount(); i++) {
Handle<String> next_name(scope_info->ContextLocalName(i));
if (variable_name->Equals(*next_name)) {
if (String::Equals(variable_name, next_name)) {
VariableMode mode;
InitializationFlag init_flag;
int context_index =
@ -11628,7 +11606,8 @@ static bool SetLocalVariableValue(Isolate* isolate,
// Parameters.
for (int i = 0; i < scope_info->ParameterCount(); ++i) {
if (scope_info->ParameterName(i)->Equals(*variable_name)) {
HandleScope scope(isolate);
if (String::Equals(handle(scope_info->ParameterName(i)), variable_name)) {
frame->SetParameterValue(i, *new_value);
// Argument might be shadowed in heap context, don't stop here.
default_result = true;
@ -11637,7 +11616,8 @@ static bool SetLocalVariableValue(Isolate* isolate,
// Stack locals.
for (int i = 0; i < scope_info->StackLocalCount(); ++i) {
if (scope_info->StackLocalName(i)->Equals(*variable_name)) {
HandleScope scope(isolate);
if (String::Equals(handle(scope_info->StackLocalName(i)), variable_name)) {
frame->SetExpression(i, *new_value);
return true;
}
@ -11780,7 +11760,7 @@ static bool SetCatchVariableValue(Isolate* isolate,
Handle<Object> new_value) {
ASSERT(context->IsCatchContext());
Handle<String> name(String::cast(context->extension()));
if (!name->Equals(*variable_name)) {
if (!String::Equals(name, variable_name)) {
return false;
}
context->set(Context::THROWN_OBJECT_INDEX, *new_value);

View File

@ -1142,7 +1142,8 @@ Handle<String> Scanner::AllocateInternalizedString(Isolate* isolate) {
double Scanner::DoubleValue() {
ASSERT(is_literal_one_byte());
return StringToDouble(
unicode_cache_, Vector<const char>::cast(literal_one_byte_string()),
unicode_cache_,
literal_one_byte_string(),
ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
}
@ -1201,7 +1202,7 @@ int DuplicateFinder::AddNumber(Vector<const uint8_t> key, int value) {
int flags = ALLOW_HEX | ALLOW_OCTAL | ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY;
double double_value = StringToDouble(
unicode_constants_, Vector<const char>::cast(key), flags, 0.0);
unicode_constants_, key, flags, 0.0);
int length;
const char* string;
if (!std::isfinite(double_value)) {

View File

@ -30,6 +30,7 @@
#include "v8.h"
#include "assert-scope.h"
#include "conversions-inl.h"
#include "v8conversions.h"
#include "dtoa.h"
@ -81,51 +82,18 @@ void StringCharacterStreamIterator::operator++() {
double StringToDouble(UnicodeCache* unicode_cache,
String* str, int flags, double empty_string_val) {
StringShape shape(str);
// TODO(dcarney): Use a Visitor here.
if (shape.IsSequentialAscii()) {
const uint8_t* begin = SeqOneByteString::cast(str)->GetChars();
const uint8_t* end = begin + str->length();
return InternalStringToDouble(unicode_cache, begin, end, flags,
empty_string_val);
} else if (shape.IsSequentialTwoByte()) {
const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
const uc16* end = begin + str->length();
return InternalStringToDouble(unicode_cache, begin, end, flags,
empty_string_val);
String* string,
int flags,
double empty_string_val) {
DisallowHeapAllocation no_gc;
String::FlatContent flat = string->GetFlatContent();
// ECMA-262 section 15.1.2.3, empty string is NaN
if (flat.IsAscii()) {
return StringToDouble(
unicode_cache, flat.ToOneByteVector(), flags, empty_string_val);
} else {
ConsStringIteratorOp op;
StringCharacterStream stream(str, &op);
return InternalStringToDouble(unicode_cache,
StringCharacterStreamIterator(&stream),
StringCharacterStreamIterator::EndMarker(),
flags,
empty_string_val);
}
}
double StringToInt(UnicodeCache* unicode_cache,
String* str,
int radix) {
StringShape shape(str);
// TODO(dcarney): Use a Visitor here.
if (shape.IsSequentialAscii()) {
const uint8_t* begin = SeqOneByteString::cast(str)->GetChars();
const uint8_t* end = begin + str->length();
return InternalStringToInt(unicode_cache, begin, end, radix);
} else if (shape.IsSequentialTwoByte()) {
const uc16* begin = SeqTwoByteString::cast(str)->GetChars();
const uc16* end = begin + str->length();
return InternalStringToInt(unicode_cache, begin, end, radix);
} else {
ConsStringIteratorOp op;
StringCharacterStream stream(str, &op);
return InternalStringToInt(unicode_cache,
StringCharacterStreamIterator(&stream),
StringCharacterStreamIterator::EndMarker(),
radix);
return StringToDouble(
unicode_cache, flat.ToUC16Vector(), flags, empty_string_val);
}
}

View File

@ -64,14 +64,11 @@ inline uint32_t NumberToUint32(Object* number) {
}
// Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache,
String* str,
String* string,
int flags,
double empty_string_val = 0);
double empty_string_val = 0.0);
// Converts a string into an integer.
double StringToInt(UnicodeCache* unicode_cache, String* str, int radix);
inline bool TryNumberToSize(Isolate* isolate,
Object* number, size_t* result) {

View File

@ -4530,12 +4530,13 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
}
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false);
if (check->Equals(isolate()->heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(check, factory->number_string())) {
__ JumpIfSmi(rax, if_true);
__ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
__ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->string_string())) {
} else if (String::Equals(check, factory->string_string())) {
__ JumpIfSmi(rax, if_false);
// Check for undetectable objects => false.
__ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
@ -4543,20 +4544,20 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
Split(zero, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->symbol_string())) {
} else if (String::Equals(check, factory->symbol_string())) {
__ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, SYMBOL_TYPE, rdx);
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->boolean_string())) {
} else if (String::Equals(check, factory->boolean_string())) {
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
__ j(equal, if_true);
__ CompareRoot(rax, Heap::kFalseValueRootIndex);
Split(equal, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) {
String::Equals(check, factory->null_string())) {
__ CompareRoot(rax, Heap::kNullValueRootIndex);
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->undefined_string())) {
} else if (String::Equals(check, factory->undefined_string())) {
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, if_true);
__ JumpIfSmi(rax, if_false);
@ -4565,14 +4566,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->function_string())) {
} else if (String::Equals(check, factory->function_string())) {
__ JumpIfSmi(rax, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
__ j(equal, if_true);
__ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
Split(equal, if_true, if_false, fall_through);
} else if (check->Equals(isolate()->heap()->object_string())) {
} else if (String::Equals(check, factory->object_string())) {
__ JumpIfSmi(rax, if_false);
if (!FLAG_harmony_typeof) {
__ CompareRoot(rax, Heap::kNullValueRootIndex);

View File

@ -5371,14 +5371,15 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
Label::Distance false_distance = right_block == next_block ? Label::kNear
: Label::kFar;
Condition final_branch_condition = no_condition;
if (type_name->Equals(heap()->number_string())) {
Factory* factory = isolate()->factory();
if (String::Equals(type_name, factory->number_string())) {
__ JumpIfSmi(input, true_label, true_distance);
__ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->string_string())) {
} else if (String::Equals(type_name, factory->string_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
__ j(above_equal, false_label, false_distance);
@ -5386,22 +5387,23 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
Immediate(1 << Map::kIsUndetectable));
final_branch_condition = zero;
} else if (type_name->Equals(heap()->symbol_string())) {
} else if (String::Equals(type_name, factory->symbol_string())) {
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, SYMBOL_TYPE, input);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->boolean_string())) {
} else if (String::Equals(type_name, factory->boolean_string())) {
__ CompareRoot(input, Heap::kTrueValueRootIndex);
__ j(equal, true_label, true_distance);
__ CompareRoot(input, Heap::kFalseValueRootIndex);
final_branch_condition = equal;
} else if (FLAG_harmony_typeof && type_name->Equals(heap()->null_string())) {
} else if (FLAG_harmony_typeof &&
String::Equals(type_name, factory->null_string())) {
__ CompareRoot(input, Heap::kNullValueRootIndex);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->undefined_string())) {
} else if (String::Equals(type_name, factory->undefined_string())) {
__ CompareRoot(input, Heap::kUndefinedValueRootIndex);
__ j(equal, true_label, true_distance);
__ JumpIfSmi(input, false_label, false_distance);
@ -5411,7 +5413,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
Immediate(1 << Map::kIsUndetectable));
final_branch_condition = not_zero;
} else if (type_name->Equals(heap()->function_string())) {
} else if (String::Equals(type_name, factory->function_string())) {
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input);
@ -5419,7 +5421,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
final_branch_condition = equal;
} else if (type_name->Equals(heap()->object_string())) {
} else if (String::Equals(type_name, factory->object_string())) {
__ JumpIfSmi(input, false_label, false_distance);
if (!FLAG_harmony_typeof) {
__ CompareRoot(input, Heap::kNullValueRootIndex);

View File

@ -1368,7 +1368,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
}
// Check that preparser and parser produce the same error.
i::Handle<i::String> preparser_message = FormatMessage(&data);
if (!message_string->Equals(*preparser_message)) {
if (!i::String::Equals(message_string, preparser_message)) {
i::OS::Print(
"Expected parser and preparser to produce the same error on:\n"
"\t%s\n"