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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -78,7 +78,8 @@ bool Expression::IsUndefinedLiteral(Isolate* isolate) const {
// The global identifier "undefined" is immutable. Everything // The global identifier "undefined" is immutable. Everything
// else could be reassigned. // else could be reassigned.
return var != NULL && var->location() == Variable::UNALLOCATED && 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; emit_store_ = true;
key_ = key; key_ = key;
value_ = value; value_ = value;
Object* k = *key->value(); Handle<Object> k = key->value();
if (k->IsInternalizedString() && 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; kind_ = PROTOTYPE;
} else if (value_->AsMaterializedLiteral() != NULL) { } else if (value_->AsMaterializedLiteral() != NULL) {
kind_ = MATERIALIZED_LITERAL; kind_ = MATERIALIZED_LITERAL;

View File

@ -1394,7 +1394,7 @@ class Literal V8_FINAL : public Expression {
static bool Match(void* literal1, void* literal2) { static bool Match(void* literal1, void* literal2) {
Handle<String> s1 = static_cast<Literal*>(literal1)->ToString(); Handle<String> s1 = static_cast<Literal*>(literal1)->ToString();
Handle<String> s2 = static_cast<Literal*>(literal2)->ToString(); Handle<String> s2 = static_cast<Literal*>(literal2)->ToString();
return s1->Equals(*s2); return String::Equals(s1, s2);
} }
TypeFeedbackId LiteralFeedbackId() const { return reuse(id()); } 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? // Were both scripts tagged by the embedder as being shared cross-origin?
if (is_shared_cross_origin != script->is_shared_cross_origin()) return false; if (is_shared_cross_origin != script->is_shared_cross_origin()) return false;
// Compare the two name strings for equality. // 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()) { } else if (context->IsCatchContext()) {
// Catch contexts have the variable name in the extension slot. // 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) { if (FLAG_trace_contexts) {
PrintF("=> found in catch context\n"); PrintF("=> found in catch context\n");
} }

View File

@ -56,7 +56,7 @@ double StringToDouble(UnicodeCache* unicode_cache,
double StringToDouble(UnicodeCache* unicode_cache, double StringToDouble(UnicodeCache* unicode_cache,
Vector<const char> str, Vector<const uint8_t> str,
int flags, int flags,
double empty_string_val) { double empty_string_val) {
// We cast to const uint8_t* here to avoid instantiating the // 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) { const char* DoubleToCString(double v, Vector<char> buffer) {
switch (fpclassify(v)) { switch (fpclassify(v)) {
case FP_NAN: return "NaN"; 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 // Converts a string into a double value according to ECMA-262 9.3.1
double StringToDouble(UnicodeCache* unicode_cache, double StringToDouble(UnicodeCache* unicode_cache,
Vector<const char> str, Vector<const uint8_t> str,
int flags, int flags,
double empty_string_val = 0); double empty_string_val = 0);
double StringToDouble(UnicodeCache* unicode_cache, double StringToDouble(UnicodeCache* unicode_cache,
@ -135,6 +135,16 @@ double StringToDouble(UnicodeCache* unicode_cache,
int flags, int flags,
double empty_string_val = 0); 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; const int kDoubleToCStringMinBufferSize = 100;
// Converts a double to a string value according to ECMA-262 9.8.1. // 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) { Handle<Object> Factory::GlobalConstantFor(Handle<String> name) {
Heap* h = isolate()->heap(); if (String::Equals(name, undefined_string())) return undefined_value();
if (name->Equals(h->undefined_string())) return undefined_value(); if (String::Equals(name, nan_string())) return nan_value();
if (name->Equals(h->nan_string())) return nan_value(); if (String::Equals(name, infinity_string())) return infinity_value();
if (name->Equals(h->infinity_string())) return infinity_value();
return Handle<Object>::null(); return Handle<Object>::null();
} }

View File

@ -55,14 +55,16 @@ void FuncNameInferrer::PushEnclosingName(Handle<String> name) {
void FuncNameInferrer::PushLiteralName(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()); names_stack_.Add(Name(name, kLiteralName), zone());
} }
} }
void FuncNameInferrer::PushVariableName(Handle<String> name) { 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()); 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 Heap::AdjustAmountOfExternalAllocatedMemory(
int64_t change_in_bytes) { int64_t change_in_bytes) {
ASSERT(HasBeenSetUp()); ASSERT(HasBeenSetUp());

View File

@ -1169,15 +1169,6 @@ class Heap {
// NULL is returned if string is in new space or not flattened. // NULL is returned if string is in new space or not flattened.
Map* InternalizedStringMapForString(String* str); 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. // Converts the given boolean condition to JavaScript boolean value.
inline Object* ToBoolean(bool condition); inline Object* ToBoolean(bool condition);

View File

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

View File

@ -4536,12 +4536,13 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
} }
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 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); __ JumpIfSmi(eax, if_true);
__ cmp(FieldOperand(eax, HeapObject::kMapOffset), __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->heap_number_map()); isolate()->factory()->heap_number_map());
Split(equal, if_true, if_false, fall_through); 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); __ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx); __ CmpObjectType(eax, FIRST_NONSTRING_TYPE, edx);
__ j(above_equal, if_false); __ j(above_equal, if_false);
@ -4549,20 +4550,20 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ test_b(FieldOperand(edx, Map::kBitFieldOffset), __ test_b(FieldOperand(edx, Map::kBitFieldOffset),
1 << Map::kIsUndetectable); 1 << Map::kIsUndetectable);
Split(zero, if_true, if_false, fall_through); 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); __ JumpIfSmi(eax, if_false);
__ CmpObjectType(eax, SYMBOL_TYPE, edx); __ CmpObjectType(eax, SYMBOL_TYPE, edx);
Split(equal, if_true, if_false, fall_through); 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()); __ cmp(eax, isolate()->factory()->true_value());
__ j(equal, if_true); __ j(equal, if_true);
__ cmp(eax, isolate()->factory()->false_value()); __ cmp(eax, isolate()->factory()->false_value());
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof && } else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) { String::Equals(check, factory->null_string())) {
__ cmp(eax, isolate()->factory()->null_value()); __ cmp(eax, isolate()->factory()->null_value());
Split(equal, if_true, if_false, fall_through); 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()); __ cmp(eax, isolate()->factory()->undefined_value());
__ j(equal, if_true); __ j(equal, if_true);
__ JumpIfSmi(eax, if_false); __ JumpIfSmi(eax, if_false);
@ -4571,14 +4572,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset)); __ movzx_b(ecx, FieldOperand(edx, Map::kBitFieldOffset));
__ test(ecx, Immediate(1 << Map::kIsUndetectable)); __ test(ecx, Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through); 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); __ JumpIfSmi(eax, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CmpObjectType(eax, JS_FUNCTION_TYPE, edx); __ CmpObjectType(eax, JS_FUNCTION_TYPE, edx);
__ j(equal, if_true); __ j(equal, if_true);
__ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE); __ CmpInstanceType(edx, JS_FUNCTION_PROXY_TYPE);
Split(equal, if_true, if_false, fall_through); 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); __ JumpIfSmi(eax, if_false);
if (!FLAG_harmony_typeof) { if (!FLAG_harmony_typeof) {
__ cmp(eax, isolate()->factory()->null_value()); __ 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::Distance false_distance = right_block == next_block ? Label::kNear
: Label::kFar; : Label::kFar;
Condition final_branch_condition = no_condition; 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); __ JumpIfSmi(input, true_label, true_distance);
__ cmp(FieldOperand(input, HeapObject::kMapOffset), __ cmp(FieldOperand(input, HeapObject::kMapOffset),
factory()->heap_number_map()); factory()->heap_number_map());
final_branch_condition = equal; 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); __ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
__ j(above_equal, false_label, false_distance); __ j(above_equal, false_label, false_distance);
@ -6108,22 +6108,23 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
1 << Map::kIsUndetectable); 1 << Map::kIsUndetectable);
final_branch_condition = zero; 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); __ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, SYMBOL_TYPE, input); __ CmpObjectType(input, SYMBOL_TYPE, input);
final_branch_condition = equal; 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()); __ cmp(input, factory()->true_value());
__ j(equal, true_label, true_distance); __ j(equal, true_label, true_distance);
__ cmp(input, factory()->false_value()); __ cmp(input, factory()->false_value());
final_branch_condition = equal; 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()); __ cmp(input, factory()->null_value());
final_branch_condition = equal; 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()); __ cmp(input, factory()->undefined_value());
__ j(equal, true_label, true_distance); __ j(equal, true_label, true_distance);
__ JumpIfSmi(input, false_label, false_distance); __ JumpIfSmi(input, false_label, false_distance);
@ -6133,7 +6134,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
1 << Map::kIsUndetectable); 1 << Map::kIsUndetectable);
final_branch_condition = not_zero; 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); STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label, false_distance); __ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input); __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
@ -6141,7 +6142,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
final_branch_condition = equal; 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); __ JumpIfSmi(input, false_label, false_distance);
if (!FLAG_harmony_typeof) { if (!FLAG_harmony_typeof) {
__ cmp(input, factory()->null_value()); __ cmp(input, factory()->null_value());

View File

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

View File

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

View File

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

View File

@ -5524,7 +5524,8 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
// register. // register.
Condition final_branch_condition = kNoCondition; Condition final_branch_condition = kNoCondition;
Register scratch = scratch0(); 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); __ JumpIfSmi(input, true_label);
__ lw(input, FieldMemOperand(input, HeapObject::kMapOffset)); __ lw(input, FieldMemOperand(input, HeapObject::kMapOffset));
__ LoadRoot(at, Heap::kHeapNumberMapRootIndex); __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
@ -5532,7 +5533,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(at); cmp2 = Operand(at);
final_branch_condition = eq; 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); __ JumpIfSmi(input, false_label);
__ GetObjectType(input, input, scratch); __ GetObjectType(input, input, scratch);
__ Branch(USE_DELAY_SLOT, false_label, __ Branch(USE_DELAY_SLOT, false_label,
@ -5545,14 +5546,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(zero_reg); cmp2 = Operand(zero_reg);
final_branch_condition = eq; 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); __ JumpIfSmi(input, false_label);
__ GetObjectType(input, input, scratch); __ GetObjectType(input, input, scratch);
cmp1 = scratch; cmp1 = scratch;
cmp2 = Operand(SYMBOL_TYPE); cmp2 = Operand(SYMBOL_TYPE);
final_branch_condition = eq; 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); __ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
__ LoadRoot(at, Heap::kFalseValueRootIndex); __ LoadRoot(at, Heap::kFalseValueRootIndex);
@ -5560,13 +5561,14 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(input); cmp2 = Operand(input);
final_branch_condition = eq; 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); __ LoadRoot(at, Heap::kNullValueRootIndex);
cmp1 = at; cmp1 = at;
cmp2 = Operand(input); cmp2 = Operand(input);
final_branch_condition = eq; 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); __ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input)); __ Branch(USE_DELAY_SLOT, true_label, eq, at, Operand(input));
// The first instruction of JumpIfSmi is an And - it is safe in the delay // 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); cmp2 = Operand(zero_reg);
final_branch_condition = ne; 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); STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label); __ JumpIfSmi(input, false_label);
__ GetObjectType(input, scratch, input); __ GetObjectType(input, scratch, input);
@ -5589,7 +5591,7 @@ Condition LCodeGen::EmitTypeofIs(Label* true_label,
cmp2 = Operand(JS_FUNCTION_PROXY_TYPE); cmp2 = Operand(JS_FUNCTION_PROXY_TYPE);
final_branch_condition = eq; 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); __ JumpIfSmi(input, false_label);
if (!FLAG_harmony_typeof) { if (!FLAG_harmony_typeof) {
__ LoadRoot(at, Heap::kNullValueRootIndex); __ 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, name, Object, kNameOffset)
ACCESSORS(Symbol, flags, Smi, kFlagsOffset) ACCESSORS(Symbol, flags, Smi, kFlagsOffset)
BOOL_ACCESSORS(Symbol, flags, is_private, kPrivateBit) 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) { Handle<String> String::Flatten(Handle<String> string, PretenureFlag pretenure) {
if (!string->IsConsString()) return string; if (!string->IsConsString()) return string;
Handle<ConsString> cons = Handle<ConsString>::cast(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) { uint16_t String::Get(int index) {
ASSERT(index >= 0 && index < length()); ASSERT(index >= 0 && index < length());
switch (StringShape(this).full_representation_tag()) { 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_first(*result);
cons->set_second(isolate->heap()->empty_string()); cons->set_second(isolate->heap()->empty_string());
ASSERT(result->IsFlat());
return result; 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) { bool String::MakeExternal(v8::String::ExternalStringResource* resource) {
// Externalizing twice leaks the external resource, so it's // 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( void JSReceiver::LocalLookup(
Name* name, LookupResult* result, bool search_hidden_prototypes) { Name* name, LookupResult* result, bool search_hidden_prototypes) {
ASSERT(name->IsName()); ASSERT(name->IsName());
@ -6577,8 +6503,8 @@ bool JSObject::DefineFastAccessor(Handle<JSObject> object,
if (result.IsFound()) { if (result.IsFound()) {
Handle<Map> target(result.GetTransitionTarget()); Handle<Map> target(result.GetTransitionTarget());
int descriptor_number = target->LastAdded(); int descriptor_number = target->LastAdded();
ASSERT(target->instance_descriptors()->GetKey(descriptor_number) ASSERT(Name::Equals(name,
->Equals(*name)); handle(target->instance_descriptors()->GetKey(descriptor_number))));
return TryAccessorTransition(object, target, descriptor_number, return TryAccessorTransition(object, target, descriptor_number,
component, accessor, attributes); component, accessor, attributes);
} }
@ -8330,7 +8256,7 @@ String::FlatContent String::GetFlatContent() {
} else { } else {
start = ExternalAsciiString::cast(string)->GetChars(); start = ExternalAsciiString::cast(string)->GetChars();
} }
return FlatContent(Vector<const uint8_t>(start + offset, length)); return FlatContent(start + offset, length);
} else { } else {
ASSERT(shape.encoding_tag() == kTwoByteStringTag); ASSERT(shape.encoding_tag() == kTwoByteStringTag);
const uc16* start; const uc16* start;
@ -8339,7 +8265,7 @@ String::FlatContent String::GetFlatContent() {
} else { } else {
start = ExternalTwoByteString::cast(string)->GetChars(); 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) { bool String::SlowEquals(String* other) {
DisallowHeapAllocation no_gc;
// Fast check: negative check with lengths. // Fast check: negative check with lengths.
int len = length(); int len = length();
if (len != other->length()) return false; if (len != other->length()) return false;
@ -9008,14 +8935,10 @@ bool String::SlowEquals(String* other) {
// before we try to flatten the strings. // before we try to flatten the strings.
if (this->Get(0) != other->Get(0)) return false; 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. // TODO(dcarney): Compare all types of flat strings with a Visitor.
if (StringShape(lhs).IsSequentialAscii() && if (IsSeqOneByteString() && other->IsSeqOneByteString()) {
StringShape(rhs).IsSequentialAscii()) { const uint8_t* str1 = SeqOneByteString::cast(this)->GetChars();
const uint8_t* str1 = SeqOneByteString::cast(lhs)->GetChars(); const uint8_t* str2 = SeqOneByteString::cast(other)->GetChars();
const uint8_t* str2 = SeqOneByteString::cast(rhs)->GetChars();
return CompareRawStringContents(str1, str2, len); return CompareRawStringContents(str1, str2, len);
} }
@ -9023,7 +8946,57 @@ bool String::SlowEquals(String* other) {
StringComparator comparator(isolate->objects_string_compare_iterator_a(), StringComparator comparator(isolate->objects_string_compare_iterator_a(),
isolate->objects_string_compare_iterator_b()); 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. // Casting.
static inline Map* cast(Object* obj); static inline Map* cast(Object* obj);
// Locate an accessor in the instance descriptor.
AccessorDescriptor* FindAccessor(Name* name);
// Code cache operations. // Code cache operations.
// Clears the code cache. // Clears the code cache.
@ -8791,6 +8788,7 @@ class Name: public HeapObject {
// Equality operations. // Equality operations.
inline bool Equals(Name* other); inline bool Equals(Name* other);
inline static bool Equals(Handle<Name> one, Handle<Name> two);
// Conversion. // Conversion.
inline bool AsArrayIndex(uint32_t* index); inline bool AsArrayIndex(uint32_t* index);
@ -8927,28 +8925,37 @@ class String: public Name {
// true. // true.
Vector<const uint8_t> ToOneByteVector() { Vector<const uint8_t> ToOneByteVector() {
ASSERT_EQ(ASCII, state_); 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() // Return the two-byte content of the string. Only use if IsTwoByte()
// returns true. // returns true.
Vector<const uc16> ToUC16Vector() { Vector<const uc16> ToUC16Vector() {
ASSERT_EQ(TWO_BYTE, state_); 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: private:
enum State { NON_FLAT, ASCII, TWO_BYTE }; enum State { NON_FLAT, ASCII, TWO_BYTE };
// Constructors only used by String::GetFlatContent(). // Constructors only used by String::GetFlatContent().
explicit FlatContent(Vector<const uint8_t> chars) explicit FlatContent(const uint8_t* start, int length)
: buffer_(chars), : onebyte_start(start), length_(length), state_(ASCII) { }
state_(ASCII) { } explicit FlatContent(const uc16* start, int length)
explicit FlatContent(Vector<const uc16> chars) : twobyte_start(start), length_(length), state_(TWO_BYTE) { }
: buffer_(Vector<const byte>::cast(chars)), FlatContent() : onebyte_start(NULL), length_(0), state_(NON_FLAT) { }
state_(TWO_BYTE) { }
FlatContent() : buffer_(), state_(NON_FLAT) { }
Vector<const uint8_t> buffer_; union {
const uint8_t* onebyte_start;
const uc16* twobyte_start;
};
int length_;
State state_; State state_;
friend class String; friend class String;
@ -8986,7 +8993,7 @@ class String: public Name {
// to this method are not efficient unless the string is flat. // to this method are not efficient unless the string is flat.
INLINE(uint16_t Get(int index)); 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. // necessary. Does nothing if the string is not a cons string.
// Flattening allocates a sequential string with the same data as // Flattening allocates a sequential string with the same data as
// the given string and mutates the cons string to a degenerate // 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 // Degenerate cons strings are handled specially by the garbage
// collector (see IsShortcutCandidate). // 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, static inline Handle<String> Flatten(Handle<String> string,
PretenureFlag pretenure = NOT_TENURED); 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 // Tries to return the content of a flat string as a structure holding either
// a flat vector of char or of uc16. // a flat vector of char or of uc16.
// If the string isn't flat, and therefore doesn't have flat content, the // 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. // String equality operations.
inline bool Equals(String* other); 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 IsUtf8EqualTo(Vector<const char> str, bool allow_prefix_match = false);
bool IsOneByteEqualTo(Vector<const uint8_t> str); bool IsOneByteEqualTo(Vector<const uint8_t> str);
bool IsTwoByteEqualTo(Vector<const uc16> str); bool IsTwoByteEqualTo(Vector<const uc16> str);
@ -9202,15 +9197,15 @@ class String: public Name {
private: private:
friend class Name; friend class Name;
// Try to flatten the top level ConsString that is hiding behind this static Handle<String> SlowFlatten(Handle<ConsString> cons,
// string. This is a no-op unless the string is a ConsString. Flatten PretenureFlag tenure);
// mutates the ConsString and might return a failure.
MUST_USE_RESULT MaybeObject* SlowTryFlatten(PretenureFlag pretenure);
// Slow case of String::Equals. This implementation works on any strings // Slow case of String::Equals. This implementation works on any strings
// but it is most efficient on strings that are almost flat. // but it is most efficient on strings that are almost flat.
bool SlowEquals(String* other); bool SlowEquals(String* other);
static bool SlowEquals(Handle<String> one, Handle<String> two);
// Slow case of AsArrayIndex. // Slow case of AsArrayIndex.
bool SlowAsArrayIndex(uint32_t* index); bool SlowAsArrayIndex(uint32_t* index);

View File

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

View File

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

View File

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

View File

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

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, double StringToDouble(UnicodeCache* unicode_cache,
String* str, String* string,
int flags, 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, inline bool TryNumberToSize(Isolate* isolate,
Object* number, size_t* result) { Object* number, size_t* result) {

View File

@ -4530,12 +4530,13 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
} }
PrepareForBailoutBeforeSplit(expr, true, if_true, if_false); 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); __ JumpIfSmi(rax, if_true);
__ movp(rax, FieldOperand(rax, HeapObject::kMapOffset)); __ movp(rax, FieldOperand(rax, HeapObject::kMapOffset));
__ CompareRoot(rax, Heap::kHeapNumberMapRootIndex); __ CompareRoot(rax, Heap::kHeapNumberMapRootIndex);
Split(equal, if_true, if_false, fall_through); 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); __ JumpIfSmi(rax, if_false);
// Check for undetectable objects => false. // Check for undetectable objects => false.
__ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx); __ CmpObjectType(rax, FIRST_NONSTRING_TYPE, rdx);
@ -4543,20 +4544,20 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ testb(FieldOperand(rdx, Map::kBitFieldOffset), __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable)); Immediate(1 << Map::kIsUndetectable));
Split(zero, if_true, if_false, fall_through); 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); __ JumpIfSmi(rax, if_false);
__ CmpObjectType(rax, SYMBOL_TYPE, rdx); __ CmpObjectType(rax, SYMBOL_TYPE, rdx);
Split(equal, if_true, if_false, fall_through); 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); __ CompareRoot(rax, Heap::kTrueValueRootIndex);
__ j(equal, if_true); __ j(equal, if_true);
__ CompareRoot(rax, Heap::kFalseValueRootIndex); __ CompareRoot(rax, Heap::kFalseValueRootIndex);
Split(equal, if_true, if_false, fall_through); Split(equal, if_true, if_false, fall_through);
} else if (FLAG_harmony_typeof && } else if (FLAG_harmony_typeof &&
check->Equals(isolate()->heap()->null_string())) { String::Equals(check, factory->null_string())) {
__ CompareRoot(rax, Heap::kNullValueRootIndex); __ CompareRoot(rax, Heap::kNullValueRootIndex);
Split(equal, if_true, if_false, fall_through); 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); __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, if_true); __ j(equal, if_true);
__ JumpIfSmi(rax, if_false); __ JumpIfSmi(rax, if_false);
@ -4565,14 +4566,14 @@ void FullCodeGenerator::EmitLiteralCompareTypeof(Expression* expr,
__ testb(FieldOperand(rdx, Map::kBitFieldOffset), __ testb(FieldOperand(rdx, Map::kBitFieldOffset),
Immediate(1 << Map::kIsUndetectable)); Immediate(1 << Map::kIsUndetectable));
Split(not_zero, if_true, if_false, fall_through); 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); __ JumpIfSmi(rax, if_false);
STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2); STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx); __ CmpObjectType(rax, JS_FUNCTION_TYPE, rdx);
__ j(equal, if_true); __ j(equal, if_true);
__ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE); __ CmpInstanceType(rdx, JS_FUNCTION_PROXY_TYPE);
Split(equal, if_true, if_false, fall_through); 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); __ JumpIfSmi(rax, if_false);
if (!FLAG_harmony_typeof) { if (!FLAG_harmony_typeof) {
__ CompareRoot(rax, Heap::kNullValueRootIndex); __ 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::Distance false_distance = right_block == next_block ? Label::kNear
: Label::kFar; : Label::kFar;
Condition final_branch_condition = no_condition; 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); __ JumpIfSmi(input, true_label, true_distance);
__ CompareRoot(FieldOperand(input, HeapObject::kMapOffset), __ CompareRoot(FieldOperand(input, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex); Heap::kHeapNumberMapRootIndex);
final_branch_condition = equal; 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); __ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, FIRST_NONSTRING_TYPE, input); __ CmpObjectType(input, FIRST_NONSTRING_TYPE, input);
__ j(above_equal, false_label, false_distance); __ j(above_equal, false_label, false_distance);
@ -5386,22 +5387,23 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
Immediate(1 << Map::kIsUndetectable)); Immediate(1 << Map::kIsUndetectable));
final_branch_condition = zero; 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); __ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, SYMBOL_TYPE, input); __ CmpObjectType(input, SYMBOL_TYPE, input);
final_branch_condition = equal; 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); __ CompareRoot(input, Heap::kTrueValueRootIndex);
__ j(equal, true_label, true_distance); __ j(equal, true_label, true_distance);
__ CompareRoot(input, Heap::kFalseValueRootIndex); __ CompareRoot(input, Heap::kFalseValueRootIndex);
final_branch_condition = equal; 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); __ CompareRoot(input, Heap::kNullValueRootIndex);
final_branch_condition = equal; 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); __ CompareRoot(input, Heap::kUndefinedValueRootIndex);
__ j(equal, true_label, true_distance); __ j(equal, true_label, true_distance);
__ JumpIfSmi(input, false_label, false_distance); __ JumpIfSmi(input, false_label, false_distance);
@ -5411,7 +5413,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
Immediate(1 << Map::kIsUndetectable)); Immediate(1 << Map::kIsUndetectable));
final_branch_condition = not_zero; 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); STATIC_ASSERT(NUM_OF_CALLABLE_SPEC_OBJECT_TYPES == 2);
__ JumpIfSmi(input, false_label, false_distance); __ JumpIfSmi(input, false_label, false_distance);
__ CmpObjectType(input, JS_FUNCTION_TYPE, input); __ CmpObjectType(input, JS_FUNCTION_TYPE, input);
@ -5419,7 +5421,7 @@ Condition LCodeGen::EmitTypeofIs(LTypeofIsAndBranch* instr, Register input) {
__ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE); __ CmpInstanceType(input, JS_FUNCTION_PROXY_TYPE);
final_branch_condition = equal; 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); __ JumpIfSmi(input, false_label, false_distance);
if (!FLAG_harmony_typeof) { if (!FLAG_harmony_typeof) {
__ CompareRoot(input, Heap::kNullValueRootIndex); __ 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. // Check that preparser and parser produce the same error.
i::Handle<i::String> preparser_message = FormatMessage(&data); 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( i::OS::Print(
"Expected parser and preparser to produce the same error on:\n" "Expected parser and preparser to produce the same error on:\n"
"\t%s\n" "\t%s\n"