Change the special handling of typeof comparisons to strings for
authorkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 5 Nov 2009 16:08:48 +0000 (16:08 +0000)
committerkmillikin@chromium.org <kmillikin@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 5 Nov 2009 16:08:48 +0000 (16:08 +0000)
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

src/arm/codegen-arm.cc
src/ia32/codegen-ia32.cc
src/macros.py
src/x64/codegen-x64.cc
test/mjsunit/mjsunit.js

index dc4592f..2165f4c 100644 (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 {
index d49718b..a3b5570 100644 (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);
index ddd2f13..d6a2426 100644 (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');
index d65960a..210076d 100644 (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);
index 1fb3f02..8ced011 100644 (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;