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:
parent
1a9fa3a673
commit
a640707213
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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);
|
||||||
|
@ -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) {
|
||||||
|
@ -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) {
|
||||||
|
@ -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());
|
||||||
|
@ -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;
|
||||||
|
@ -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()); }
|
||||||
|
@ -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())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
@ -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";
|
||||||
|
@ -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.
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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());
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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());
|
||||||
|
@ -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());
|
||||||
|
11
src/ic.cc
11
src/ic.cc
@ -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);
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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()) {
|
||||||
|
147
src/objects.cc
147
src/objects.cc
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
200
src/runtime.cc
200
src/runtime.cc
@ -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 .
|
// than '9' except 'I' and .
|
||||||
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);
|
||||||
|
@ -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)) {
|
||||||
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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);
|
||||||
|
@ -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);
|
||||||
|
@ -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"
|
||||||
|
Loading…
Reference in New Issue
Block a user