Change the special handling of typeof comparisons to strings for
regular expressions to be consistent with typeof in other contexts. Typeof regular expressions should now be 'function' in all contexts. In the JS natives, IS_FUNCTION, IS_OBJECT, and IS_REGEXP return the same answers as before. Review URL: http://codereview.chromium.org/360053 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3231 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
930ab041a8
commit
debb5f8b48
@ -3978,28 +3978,35 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
|
||||
} else if (check->Equals(Heap::function_symbol())) {
|
||||
__ tst(r1, Operand(kSmiTagMask));
|
||||
false_target()->Branch(eq);
|
||||
__ CompareObjectType(r1, r1, r1, JS_FUNCTION_TYPE);
|
||||
Register map_reg = r2;
|
||||
__ CompareObjectType(r1, map_reg, r1, JS_FUNCTION_TYPE);
|
||||
true_target()->Branch(eq);
|
||||
// Regular expressions are callable so typeof == 'function'.
|
||||
__ CompareInstanceType(map_reg, r1, JS_REGEXP_TYPE);
|
||||
cc_reg_ = eq;
|
||||
|
||||
} else if (check->Equals(Heap::object_symbol())) {
|
||||
__ tst(r1, Operand(kSmiTagMask));
|
||||
false_target()->Branch(eq);
|
||||
|
||||
__ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
||||
__ LoadRoot(ip, Heap::kNullValueRootIndex);
|
||||
__ cmp(r1, ip);
|
||||
true_target()->Branch(eq);
|
||||
|
||||
Register map_reg = r2;
|
||||
__ CompareObjectType(r1, map_reg, r1, JS_REGEXP_TYPE);
|
||||
false_target()->Branch(eq);
|
||||
|
||||
// It can be an undetectable object.
|
||||
__ ldrb(r1, FieldMemOperand(r2, Map::kBitFieldOffset));
|
||||
__ ldrb(r1, FieldMemOperand(map_reg, Map::kBitFieldOffset));
|
||||
__ and_(r1, r1, Operand(1 << Map::kIsUndetectable));
|
||||
__ cmp(r1, Operand(1 << Map::kIsUndetectable));
|
||||
false_target()->Branch(eq);
|
||||
|
||||
__ ldrb(r2, FieldMemOperand(r2, Map::kInstanceTypeOffset));
|
||||
__ cmp(r2, Operand(FIRST_JS_OBJECT_TYPE));
|
||||
__ ldrb(r1, FieldMemOperand(map_reg, Map::kInstanceTypeOffset));
|
||||
__ cmp(r1, Operand(FIRST_JS_OBJECT_TYPE));
|
||||
false_target()->Branch(lt);
|
||||
__ cmp(r2, Operand(LAST_JS_OBJECT_TYPE));
|
||||
__ cmp(r1, Operand(LAST_JS_OBJECT_TYPE));
|
||||
cc_reg_ = le;
|
||||
|
||||
} else {
|
||||
|
@ -5777,6 +5777,9 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
|
||||
destination()->false_target()->Branch(zero);
|
||||
frame_->Spill(answer.reg());
|
||||
__ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg());
|
||||
destination()->true_target()->Branch(equal);
|
||||
// Regular expressions are callable so typeof == 'function'.
|
||||
__ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE);
|
||||
answer.Unuse();
|
||||
destination()->Split(equal);
|
||||
|
||||
@ -5786,10 +5789,13 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
|
||||
__ cmp(answer.reg(), Factory::null_value());
|
||||
destination()->true_target()->Branch(equal);
|
||||
|
||||
// It can be an undetectable object.
|
||||
Result map = allocator()->Allocate();
|
||||
ASSERT(map.is_valid());
|
||||
__ mov(map.reg(), FieldOperand(answer.reg(), HeapObject::kMapOffset));
|
||||
// Regular expressions are typeof == 'function', not 'object'.
|
||||
__ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, map.reg());
|
||||
destination()->false_target()->Branch(equal);
|
||||
|
||||
// It can be an undetectable object.
|
||||
__ movzx_b(map.reg(), FieldOperand(map.reg(), Map::kBitFieldOffset));
|
||||
__ test(map.reg(), Immediate(1 << Map::kIsUndetectable));
|
||||
destination()->false_target()->Branch(not_zero);
|
||||
|
@ -77,12 +77,13 @@ const kMonthShift = 5;
|
||||
macro IS_NULL(arg) = (arg === null);
|
||||
macro IS_NULL_OR_UNDEFINED(arg) = (arg == null);
|
||||
macro IS_UNDEFINED(arg) = (typeof(arg) === 'undefined');
|
||||
macro IS_FUNCTION(arg) = (typeof(arg) === 'function');
|
||||
macro IS_NUMBER(arg) = (typeof(arg) === 'number');
|
||||
macro IS_STRING(arg) = (typeof(arg) === 'string');
|
||||
macro IS_OBJECT(arg) = (typeof(arg) === 'object');
|
||||
macro IS_OBJECT(arg) = (typeof(arg) === 'object' || %_ClassOf(arg) == 'RegExp');
|
||||
macro IS_BOOLEAN(arg) = (typeof(arg) === 'boolean');
|
||||
macro IS_ARRAY(arg) = (%_IsArray(arg));
|
||||
# IS_FUNCTION uses %_ClassOf rather than typeof so as to exclude regexps.
|
||||
macro IS_FUNCTION(arg) = (%_ClassOf(arg) === 'Function');
|
||||
macro IS_REGEXP(arg) = (%_ClassOf(arg) === 'RegExp');
|
||||
macro IS_DATE(arg) = (%_ClassOf(arg) === 'Date');
|
||||
macro IS_NUMBER_WRAPPER(arg) = (%_ClassOf(arg) === 'Number');
|
||||
|
@ -3495,6 +3495,9 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
|
||||
destination()->false_target()->Branch(is_smi);
|
||||
frame_->Spill(answer.reg());
|
||||
__ CmpObjectType(answer.reg(), JS_FUNCTION_TYPE, answer.reg());
|
||||
destination()->true_target()->Branch(equal);
|
||||
// Regular expressions are callable so typeof == 'function'.
|
||||
__ CmpInstanceType(answer.reg(), JS_REGEXP_TYPE);
|
||||
answer.Unuse();
|
||||
destination()->Split(equal);
|
||||
|
||||
@ -3504,9 +3507,11 @@ void CodeGenerator::VisitCompareOperation(CompareOperation* node) {
|
||||
__ CompareRoot(answer.reg(), Heap::kNullValueRootIndex);
|
||||
destination()->true_target()->Branch(equal);
|
||||
|
||||
// Regular expressions are typeof == 'function', not 'object'.
|
||||
__ CmpObjectType(answer.reg(), JS_REGEXP_TYPE, kScratchRegister);
|
||||
destination()->false_target()->Branch(equal);
|
||||
|
||||
// It can be an undetectable object.
|
||||
__ movq(kScratchRegister,
|
||||
FieldOperand(answer.reg(), HeapObject::kMapOffset));
|
||||
__ testb(FieldOperand(kScratchRegister, Map::kBitFieldOffset),
|
||||
Immediate(1 << Map::kIsUndetectable));
|
||||
destination()->false_target()->Branch(not_zero);
|
||||
|
@ -75,6 +75,9 @@ function deepEquals(a, b) {
|
||||
if (typeof a == "number" && typeof b == "number" && isNaN(a) && isNaN(b)) {
|
||||
return true;
|
||||
}
|
||||
if (a.constructor === RegExp || b.constructor === RegExp) {
|
||||
return (a.constructor === b.constructor) && (a.toString === b.toString);
|
||||
}
|
||||
if ((typeof a) !== 'object' || (typeof b) !== 'object' ||
|
||||
(a === null) || (b === null))
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user