Fix the 'in' operator so it works correctly for negative indices.
authorager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Sep 2008 07:34:21 +0000 (07:34 +0000)
committerager@chromium.org <ager@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 3 Sep 2008 07:34:21 +0000 (07:34 +0000)
git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@117 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/codegen-arm.cc
src/codegen-ia32.cc
src/codegen.cc
src/codegen.h
src/runtime.js
test/mjsunit/in.js

index 19dc9a8..c4d3f38 100644 (file)
@@ -285,6 +285,7 @@ class ArmCodeGenerator: public CodeGenerator {
   virtual void GenerateSquashFrame(ZoneList<Expression*>* args);
   virtual void GenerateExpandFrame(ZoneList<Expression*>* args);
   virtual void GenerateIsSmi(ZoneList<Expression*>* args);
+  virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
   virtual void GenerateIsArray(ZoneList<Expression*>* args);
 
   virtual void GenerateArgumentsLength(ZoneList<Expression*>* args);
@@ -3938,6 +3939,16 @@ void ArmCodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
 }
 
 
+void ArmCodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+  Load(args->at(0));
+  __ pop(r0);
+  __ tst(r0, Operand(kSmiTagMask | 0x80000000));
+  cc_reg_ = eq;
+}
+
+
+
 // This should generate code that performs a charCodeAt() call or returns
 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
 // It is not yet implemented on ARM, so it always goes to the slow case.
index e60ba39..6d38136 100644 (file)
@@ -304,6 +304,7 @@ class Ia32CodeGenerator: public CodeGenerator {
   virtual void GenerateSquashFrame(ZoneList<Expression*>* args);
   virtual void GenerateExpandFrame(ZoneList<Expression*>* args);
   virtual void GenerateIsSmi(ZoneList<Expression*>* args);
+  virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args);
   virtual void GenerateIsArray(ZoneList<Expression*>* args);
 
   virtual void GenerateArgumentsLength(ZoneList<Expression*>* args);
@@ -4022,6 +4023,15 @@ void Ia32CodeGenerator::GenerateIsSmi(ZoneList<Expression*>* args) {
 }
 
 
+void Ia32CodeGenerator::GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) {
+  ASSERT(args->length() == 1);
+  Load(args->at(0));
+  __ pop(eax);
+  __ test(eax, Immediate(kSmiTagMask | 0x80000000));
+  cc_reg_ = zero;
+}
+
+
 // This generates code that performs a charCodeAt() call or returns
 // undefined in order to trigger the slow case, Runtime_StringCharCodeAt.
 // It can handle flat and sliced strings, 8 and 16 bit characters and
index d450595..14ab511 100644 (file)
@@ -243,6 +243,8 @@ bool CodeGenerator::CheckForInlineRuntimeCall(CallRuntime* node) {
      "_ExpandFrame"},
     {&v8::internal::CodeGenerator::GenerateIsSmi,
      "_IsSmi"},
+    {&v8::internal::CodeGenerator::GenerateIsNonNegativeSmi,
+     "_IsNonNegativeSmi"},
     {&v8::internal::CodeGenerator::GenerateIsArray,
      "_IsArray"},
     {&v8::internal::CodeGenerator::GenerateArgumentsLength,
index ed03dd2..9833445 100644 (file)
@@ -159,6 +159,7 @@ class CodeGenerator: public Visitor {
   virtual void GenerateSquashFrame(ZoneList<Expression*>* args) = 0;
   virtual void GenerateExpandFrame(ZoneList<Expression*>* args) = 0;
   virtual void GenerateIsSmi(ZoneList<Expression*>* args) = 0;
+  virtual void GenerateIsNonNegativeSmi(ZoneList<Expression*>* args) = 0;
   virtual void GenerateIsArray(ZoneList<Expression*>* args) = 0;
 
   // Support for arguments.length and arguments[?].
index aa624a7..78c20c1 100644 (file)
@@ -267,7 +267,7 @@ function IN(x) {
   if (x == null || (!IS_OBJECT(x) && !IS_FUNCTION(x))) {
     throw %MakeTypeError('invalid_in_operator_use', [this, x]);
   }
-  return %_IsSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
+  return %_IsNonNegativeSmi(this) ? %HasElement(x, this) : %HasProperty(x, %ToString(this));
 };
 
 
index b2b6cd5..06adb71 100644 (file)
@@ -156,3 +156,10 @@ assertFalse(-Infinity in a,"-Infinity in a");
 assertFalse(-0 in a,"-0 in a");
 assertFalse(+0 in a,"+0 in a");
 assertTrue('toString' in a, "toString");
+
+// -------------
+// Check negative indices in arrays.
+var a = [];
+assertFalse(-1 in a);
+a[-1] = 43;
+assertTrue(-1 in a);