// Now that we have the types we might as well check for
// internalized-internalized.
- Label not_internalized;
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(r2, r2, Operand(kIsNotStringMask | kIsInternalizedMask));
- __ cmp(r2, Operand(kInternalizedTag | kStringTag));
- __ b(ne, ¬_internalized); // r2 (rhs) is not an internalized string
-
- __ and_(r3, r3, Operand(kIsNotStringMask | kIsInternalizedMask));
- __ cmp(r3, Operand(kInternalizedTag | kStringTag));
- __ b(eq, &return_not_equal); // both rhs and lhs are internalized strings
-
- __ bind(¬_internalized);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ __ orr(r2, r2, Operand(r3));
+ __ tst(r2, Operand(kIsNotStringMask | kIsNotInternalizedMask));
+ __ b(eq, &return_not_equal);
}
// r2 is object type of rhs.
Label object_test;
- STATIC_ASSERT(kInternalizedTag != 0);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
__ tst(r2, Operand(kIsNotStringMask));
__ b(ne, &object_test);
- __ tst(r2, Operand(kIsInternalizedMask));
- __ b(eq, possible_strings);
+ __ tst(r2, Operand(kIsNotInternalizedMask));
+ __ b(ne, possible_strings);
__ CompareObjectType(lhs, r3, r3, FIRST_NONSTRING_TYPE);
__ b(ge, not_both_strings);
- __ tst(r3, Operand(kIsInternalizedMask));
- __ b(eq, possible_strings);
+ __ tst(r3, Operand(kIsNotInternalizedMask));
+ __ b(ne, possible_strings);
// Both are internalized. We already checked they weren't the same pointer
// so they are not equal.
__ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
__ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
__ ldrb(tmp2, FieldMemOperand(tmp2, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kInternalizedTag != 0);
-
- __ and_(tmp1, tmp1, Operand(kIsNotStringMask | kIsInternalizedMask));
- __ cmp(tmp1, Operand(kInternalizedTag | kStringTag));
- __ b(ne, &miss);
-
- __ and_(tmp2, tmp2, Operand(kIsNotStringMask | kIsInternalizedMask));
- __ cmp(tmp2, Operand(kInternalizedTag | kStringTag));
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ __ orr(tmp1, tmp1, Operand(tmp2));
+ __ tst(tmp1, Operand(kIsNotStringMask | kIsNotInternalizedMask));
__ b(ne, &miss);
// Internalized strings are compared by identity.
// Check that both operands are unique names. This leaves the instance
// types loaded in tmp1 and tmp2.
- STATIC_ASSERT(kInternalizedTag != 0);
__ ldr(tmp1, FieldMemOperand(left, HeapObject::kMapOffset));
__ ldr(tmp2, FieldMemOperand(right, HeapObject::kMapOffset));
__ ldrb(tmp1, FieldMemOperand(tmp1, Map::kInstanceTypeOffset));
// strings.
if (equality) {
ASSERT(GetCondition() == eq);
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(tmp3, tmp1, Operand(tmp2));
- __ tst(tmp3, Operand(kIsInternalizedMask));
+ STATIC_ASSERT(kInternalizedTag == 0);
+ __ orr(tmp3, tmp1, Operand(tmp2));
+ __ tst(tmp3, Operand(kIsNotInternalizedMask));
// Make sure r0 is non-zero. At this point input operands are
// guaranteed to be non-zero.
ASSERT(right.is(r0));
- __ Ret(ne);
+ __ Ret(eq);
}
// Check that both strings are sequential ASCII.
// bit test is enough.
// map: key map
__ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kInternalizedTag != 0);
- __ tst(hash, Operand(kIsInternalizedMask));
- __ b(eq, not_unique);
+ STATIC_ASSERT(kInternalizedTag == 0);
+ __ tst(hash, Operand(kIsNotInternalizedMask));
+ __ b(ne, not_unique);
__ bind(&unique);
}
void MacroAssembler::JumpIfNotUniqueName(Register reg,
Label* not_unique_name) {
- STATIC_ASSERT(((SYMBOL_TYPE - 1) & kIsInternalizedMask) == kInternalizedTag);
- cmp(reg, Operand(kInternalizedTag));
- b(lt, not_unique_name);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ Label succeed;
+ tst(reg, Operand(kIsNotStringMask | kIsNotInternalizedMask));
+ b(eq, &succeed);
cmp(reg, Operand(SYMBOL_TYPE));
- b(gt, not_unique_name);
+ b(ne, not_unique_name);
+
+ bind(&succeed);
}
*tag = kStringTag;
return;
case IS_INTERNALIZED_STRING:
- *mask = kIsInternalizedMask;
+ *mask = kIsNotInternalizedMask;
*tag = kInternalizedTag;
return;
default:
__ JumpIfSmi(object, label);
__ mov(scratch, FieldOperand(object, HeapObject::kMapOffset));
__ movzx_b(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset));
- __ and_(scratch, kIsInternalizedMask | kIsNotStringMask);
- __ cmp(scratch, kInternalizedTag | kStringTag);
- __ j(not_equal, label);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ __ test(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
+ __ j(not_zero, label);
}
__ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
__ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
__ movzx_b(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(tmp1, Immediate(kIsNotStringMask | kIsInternalizedMask));
- __ cmpb(tmp1, kInternalizedTag | kStringTag);
- __ j(not_equal, &miss, Label::kNear);
-
- __ and_(tmp2, Immediate(kIsNotStringMask | kIsInternalizedMask));
- __ cmpb(tmp2, kInternalizedTag | kStringTag);
- __ j(not_equal, &miss, Label::kNear);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ __ or_(tmp1, tmp2);
+ __ test(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
+ __ j(not_zero, &miss, Label::kNear);
// Internalized strings are compared by identity.
Label done;
// Check that both operands are unique names. This leaves the instance
// types loaded in tmp1 and tmp2.
- STATIC_ASSERT(kInternalizedTag != 0);
__ mov(tmp1, FieldOperand(left, HeapObject::kMapOffset));
__ mov(tmp2, FieldOperand(right, HeapObject::kMapOffset));
__ movzx_b(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
// also know they are both strings.
if (equality) {
Label do_compare;
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(tmp1, tmp2);
- __ test(tmp1, Immediate(kIsInternalizedMask));
- __ j(zero, &do_compare, Label::kNear);
+ STATIC_ASSERT(kInternalizedTag == 0);
+ __ or_(tmp1, tmp2);
+ __ test(tmp1, Immediate(kIsNotInternalizedMask));
+ __ j(not_zero, &do_compare, Label::kNear);
// Make sure eax is non-zero. At this point input operands are
// guaranteed to be non-zero.
ASSERT(right.is(eax));
// Is the string internalized? We already know it's a string so a single
// bit test is enough.
- STATIC_ASSERT(kInternalizedTag != 0);
- __ test_b(FieldOperand(map, Map::kInstanceTypeOffset), kIsInternalizedMask);
- __ j(zero, not_unique);
+ STATIC_ASSERT(kNotInternalizedTag != 0);
+ __ test_b(FieldOperand(map, Map::kInstanceTypeOffset),
+ kIsNotInternalizedMask);
+ __ j(not_zero, not_unique);
__ bind(&unique);
}
void MacroAssembler::JumpIfNotUniqueName(Operand operand,
Label* not_unique_name,
Label::Distance distance) {
- STATIC_ASSERT(((SYMBOL_TYPE - 1) & kIsInternalizedMask) == kInternalizedTag);
- cmp(operand, Immediate(kInternalizedTag));
- j(less, not_unique_name, distance);
- cmp(operand, Immediate(SYMBOL_TYPE));
- j(greater, not_unique_name, distance);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ Label succeed;
+ test(operand, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
+ j(zero, &succeed);
+ cmpb(operand, static_cast<uint8_t>(SYMBOL_TYPE));
+ j(not_equal, not_unique_name, distance);
+
+ bind(&succeed);
}
bool Object::IsInternalizedString() {
if (!this->IsHeapObject()) return false;
uint32_t type = HeapObject::cast(this)->map()->instance_type();
- STATIC_ASSERT(kInternalizedTag != 0);
- return (type & (kIsNotStringMask | kIsInternalizedMask)) ==
- (kInternalizedTag | kStringTag);
+ STATIC_ASSERT(kNotInternalizedTag != 0);
+ return (type & (kIsNotStringMask | kIsNotInternalizedMask)) ==
+ (kStringTag | kInternalizedTag);
}
bool StringShape::IsInternalized() {
ASSERT(valid());
- STATIC_ASSERT(kInternalizedTag != 0);
- return (type_ & (kIsNotStringMask | kIsInternalizedMask)) ==
- (kInternalizedTag | kStringTag);
+ STATIC_ASSERT(kNotInternalizedTag != 0);
+ return (type_ & (kIsNotStringMask | kIsNotInternalizedMask)) ==
+ (kStringTag | kInternalizedTag);
}
// Bit 6 indicates that the object is an internalized string (if set) or not.
// Bit 7 has to be clear as well.
-const uint32_t kIsInternalizedMask = 0x40;
-const uint32_t kNotInternalizedTag = 0x0;
-const uint32_t kInternalizedTag = 0x40;
+const uint32_t kIsNotInternalizedMask = 0x40;
+const uint32_t kNotInternalizedTag = 0x40;
+const uint32_t kInternalizedTag = 0x0;
// If bit 7 is clear then bit 2 indicates whether the string consists of
// two-byte characters or one-byte characters.
// See heap.cc and mark-compact.cc.
const uint32_t kShortcutTypeMask =
kIsNotStringMask |
- kIsInternalizedMask |
+ kIsNotInternalizedMask |
kStringRepresentationMask;
-const uint32_t kShortcutTypeTag = kConsStringTag;
+const uint32_t kShortcutTypeTag = kConsStringTag | kNotInternalizedTag;
enum InstanceType {
// String types.
- STRING_TYPE = kTwoByteStringTag | kSeqStringTag,
- ASCII_STRING_TYPE = kOneByteStringTag | kSeqStringTag,
- CONS_STRING_TYPE = kTwoByteStringTag | kConsStringTag,
- CONS_ASCII_STRING_TYPE = kOneByteStringTag | kConsStringTag,
- SLICED_STRING_TYPE = kTwoByteStringTag | kSlicedStringTag,
- SLICED_ASCII_STRING_TYPE = kOneByteStringTag | kSlicedStringTag,
- EXTERNAL_STRING_TYPE = kTwoByteStringTag | kExternalStringTag,
- EXTERNAL_ASCII_STRING_TYPE = kOneByteStringTag | kExternalStringTag,
- EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
- EXTERNAL_STRING_TYPE | kOneByteDataHintTag,
- SHORT_EXTERNAL_STRING_TYPE = EXTERNAL_STRING_TYPE | kShortExternalStringTag,
- SHORT_EXTERNAL_ASCII_STRING_TYPE =
- EXTERNAL_ASCII_STRING_TYPE | kShortExternalStringTag,
- SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
- EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE | kShortExternalStringTag,
-
- INTERNALIZED_STRING_TYPE = STRING_TYPE | kInternalizedTag,
- ASCII_INTERNALIZED_STRING_TYPE = ASCII_STRING_TYPE | kInternalizedTag,
- CONS_INTERNALIZED_STRING_TYPE = CONS_STRING_TYPE | kInternalizedTag,
- CONS_ASCII_INTERNALIZED_STRING_TYPE =
- CONS_ASCII_STRING_TYPE | kInternalizedTag,
- EXTERNAL_INTERNALIZED_STRING_TYPE = EXTERNAL_STRING_TYPE | kInternalizedTag,
- EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE =
- EXTERNAL_ASCII_STRING_TYPE | kInternalizedTag,
+ INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kSeqStringTag
+ | kInternalizedTag,
+ ASCII_INTERNALIZED_STRING_TYPE = kOneByteStringTag | kSeqStringTag
+ | kInternalizedTag,
+ CONS_INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kConsStringTag
+ | kInternalizedTag,
+ CONS_ASCII_INTERNALIZED_STRING_TYPE = kOneByteStringTag | kConsStringTag
+ | kInternalizedTag,
+ EXTERNAL_INTERNALIZED_STRING_TYPE = kTwoByteStringTag | kExternalStringTag
+ | kInternalizedTag,
+ EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE = kOneByteStringTag
+ | kExternalStringTag | kInternalizedTag,
EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE =
- EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE | kInternalizedTag,
+ EXTERNAL_INTERNALIZED_STRING_TYPE | kOneByteDataHintTag
+ | kInternalizedTag,
SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE =
- SHORT_EXTERNAL_STRING_TYPE | kInternalizedTag,
+ EXTERNAL_INTERNALIZED_STRING_TYPE | kShortExternalStringTag
+ | kInternalizedTag,
SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE =
- SHORT_EXTERNAL_ASCII_STRING_TYPE | kInternalizedTag,
+ EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE | kShortExternalStringTag
+ | kInternalizedTag,
SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE =
- SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE | kInternalizedTag,
+ EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE
+ | kShortExternalStringTag | kInternalizedTag,
+
+ STRING_TYPE = INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ ASCII_STRING_TYPE = ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ CONS_STRING_TYPE = CONS_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ CONS_ASCII_STRING_TYPE =
+ CONS_ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+
+ SLICED_STRING_TYPE =
+ kTwoByteStringTag | kSlicedStringTag | kNotInternalizedTag,
+ SLICED_ASCII_STRING_TYPE =
+ kOneByteStringTag | kSlicedStringTag | kNotInternalizedTag,
+ EXTERNAL_STRING_TYPE =
+ EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ EXTERNAL_ASCII_STRING_TYPE =
+ EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
+ EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE
+ | kNotInternalizedTag,
+ SHORT_EXTERNAL_STRING_TYPE =
+ SHORT_EXTERNAL_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ SHORT_EXTERNAL_ASCII_STRING_TYPE =
+ SHORT_EXTERNAL_ASCII_INTERNALIZED_STRING_TYPE | kNotInternalizedTag,
+ SHORT_EXTERNAL_STRING_WITH_ONE_BYTE_DATA_TYPE =
+ SHORT_EXTERNAL_INTERNALIZED_STRING_WITH_ONE_BYTE_DATA_TYPE
+ | kNotInternalizedTag,
// Non-string names
SYMBOL_TYPE = kNotStringTag, // LAST_NAME_TYPE, FIRST_NONSTRING_TYPE
__ movq(scratch, FieldOperand(object, HeapObject::kMapOffset));
__ movzxbq(scratch,
FieldOperand(scratch, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(scratch, Immediate(kIsNotStringMask | kIsInternalizedMask));
- __ cmpb(scratch, Immediate(kInternalizedTag | kStringTag));
- __ j(not_equal, label);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ __ testb(scratch, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
+ __ j(not_zero, label);
}
__ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
__ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
__ movzxbq(tmp2, FieldOperand(tmp2, Map::kInstanceTypeOffset));
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(tmp1, Immediate(kIsNotStringMask | kIsInternalizedMask));
- __ cmpb(tmp1, Immediate(kInternalizedTag | kStringTag));
- __ j(not_equal, &miss, Label::kNear);
-
- __ and_(tmp2, Immediate(kIsNotStringMask | kIsInternalizedMask));
- __ cmpb(tmp2, Immediate(kInternalizedTag | kStringTag));
- __ j(not_equal, &miss, Label::kNear);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ __ or_(tmp1, tmp2);
+ __ testb(tmp1, Immediate(kIsNotStringMask | kIsNotInternalizedMask));
+ __ j(not_zero, &miss, Label::kNear);
// Internalized strings are compared by identity.
Label done;
// Check that both operands are unique names. This leaves the instance
// types loaded in tmp1 and tmp2.
- STATIC_ASSERT(kInternalizedTag != 0);
__ movq(tmp1, FieldOperand(left, HeapObject::kMapOffset));
__ movq(tmp2, FieldOperand(right, HeapObject::kMapOffset));
__ movzxbq(tmp1, FieldOperand(tmp1, Map::kInstanceTypeOffset));
// strings.
if (equality) {
Label do_compare;
- STATIC_ASSERT(kInternalizedTag != 0);
- __ and_(tmp1, tmp2);
- __ testb(tmp1, Immediate(kIsInternalizedMask));
- __ j(zero, &do_compare, Label::kNear);
+ STATIC_ASSERT(kInternalizedTag == 0);
+ __ or_(tmp1, tmp2);
+ __ testb(tmp1, Immediate(kIsNotInternalizedMask));
+ __ j(not_zero, &do_compare, Label::kNear);
// Make sure rax is non-zero. At this point input operands are
// guaranteed to be non-zero.
ASSERT(right.is(rax));
// Is the string internalized? We already know it's a string so a single
// bit test is enough.
- STATIC_ASSERT(kInternalizedTag != 0);
+ STATIC_ASSERT(kNotInternalizedTag != 0);
__ testb(FieldOperand(map, Map::kInstanceTypeOffset),
- Immediate(kIsInternalizedMask));
- __ j(zero, not_unique);
+ Immediate(kIsNotInternalizedMask));
+ __ j(not_zero, not_unique);
__ bind(&unique);
}
T operand_or_register,
Label* not_unique_name,
Label::Distance distance) {
- STATIC_ASSERT(((SYMBOL_TYPE - 1) & kIsInternalizedMask) == kInternalizedTag);
- masm->cmpb(operand_or_register, Immediate(kInternalizedTag));
- masm->j(less, not_unique_name, distance);
- masm->cmpb(operand_or_register, Immediate(SYMBOL_TYPE));
- masm->j(greater, not_unique_name, distance);
+ STATIC_ASSERT(kInternalizedTag == 0 && kStringTag == 0);
+ Label succeed;
+ masm->testb(operand_or_register,
+ Immediate(kIsNotStringMask | kIsNotInternalizedMask));
+ masm->j(zero, &succeed, Label::kNear);
+ masm->cmpb(operand_or_register, Immediate(static_cast<uint8_t>(SYMBOL_TYPE)));
+ masm->j(not_equal, not_unique_name, distance);
+
+ masm->bind(&succeed);
}