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:
kmillikin@chromium.org 2009-11-05 16:08:48 +00:00
parent 930ab041a8
commit debb5f8b48
5 changed files with 34 additions and 12 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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');

View File

@ -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);

View File

@ -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;