Fixed incorrect instruction usage in KeyedLoadIC for byte and word
authorkbr@chromium.org <kbr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Nov 2009 20:29:11 +0000 (20:29 +0000)
committerkbr@chromium.org <kbr@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Wed, 25 Nov 2009 20:29:11 +0000 (20:29 +0000)
external array types. Added regression test based on real-world
failing code and verified that it would have caught this error.

Review URL: http://codereview.chromium.org/437052

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@3366 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/ia32/ic-ia32.cc
src/x64/ic-x64.cc
test/cctest/test-api.cc

index d209fbe..6988fe0 100644 (file)
@@ -388,13 +388,13 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
       __ movsx_b(eax, Operand(ecx, eax, times_1, 0));
       break;
     case kExternalUnsignedByteArray:
-      __ mov_b(eax, Operand(ecx, eax, times_1, 0));
+      __ movzx_b(eax, Operand(ecx, eax, times_1, 0));
       break;
     case kExternalShortArray:
       __ movsx_w(eax, Operand(ecx, eax, times_2, 0));
       break;
     case kExternalUnsignedShortArray:
-      __ mov_w(eax, Operand(ecx, eax, times_2, 0));
+      __ movzx_w(eax, Operand(ecx, eax, times_2, 0));
       break;
     case kExternalIntArray:
     case kExternalUnsignedIntArray:
index b5cc26a..b241573 100644 (file)
@@ -398,7 +398,7 @@ void KeyedLoadIC::GenerateExternalArray(MacroAssembler* masm,
       __ movsxbq(rax, Operand(rcx, rax, times_1, 0));
       break;
     case kExternalUnsignedByteArray:
-      __ movb(rax, Operand(rcx, rax, times_1, 0));
+      __ movzxbq(rax, Operand(rcx, rax, times_1, 0));
       break;
     case kExternalShortArray:
       __ movsxwq(rax, Operand(rcx, rax, times_2, 0));
index 9b6a9cd..c650dce 100644 (file)
@@ -8083,6 +8083,66 @@ static void ExternalArrayTestHelper(v8::ExternalArrayType array_type,
   result = CompileRun("ext_array[1] = 23;");
   CHECK_EQ(23, result->Int32Value());
 
+  // Test more complex manipulations which cause eax to contain values
+  // that won't be completely overwritten by loads from the arrays.
+  // This catches bugs in the instructions used for the KeyedLoadIC
+  // for byte and word types.
+  {
+    const int kXSize = 300;
+    const int kYSize = 300;
+    const int kLargeElementCount = kXSize * kYSize * 4;
+    ElementType* large_array_data =
+        static_cast<ElementType*>(malloc(kLargeElementCount * element_size));
+    i::Handle<ExternalArrayClass> large_array =
+        i::Handle<ExternalArrayClass>::cast(
+            i::Factory::NewExternalArray(kElementCount, array_type, array_data));
+    v8::Handle<v8::Object> large_obj = v8::Object::New();
+    // Set the elements to be the external array.
+    large_obj->SetIndexedPropertiesToExternalArrayData(large_array_data,
+                                                       array_type,
+                                                       kLargeElementCount);
+    context->Global()->Set(v8_str("large_array"), large_obj);
+    result = CompileRun("for (var y = 0; y < 300; y++) {"
+                        "  for (var x = 0; x < 300; x++) {"
+                        "    large_array[4 * 300 * y + 4 * x + 0] = 127;"
+                        "    large_array[4 * 300 * y + 4 * x + 1] = 0;"
+                        "    large_array[4 * 300 * y + 4 * x + 2] = 0;"
+                        "    large_array[4 * 300 * y + 4 * x + 3] = 127;"
+                        "  }"
+                        "}"
+                        "var failed = false;"
+                        "var offset = 0;"
+                        "for (var i = 0; i < 300; i++) {"
+                        "  if (large_array[4 * i] != 127 ||"
+                        "      large_array[4 * i + 1] != 0 ||"
+                        "      large_array[4 * i + 2] != 0 ||"
+                        "      large_array[4 * i + 3] != 127) {"
+                        "    failed = true;"
+                        "  }"
+                        "}"
+                        "offset = 150 * 300 * 4;"
+                        "for (var i = 0; i < 300; i++) {"
+                        "  if (large_array[offset + 4 * i] != 127 ||"
+                        "      large_array[offset + 4 * i + 1] != 0 ||"
+                        "      large_array[offset + 4 * i + 2] != 0 ||"
+                        "      large_array[offset + 4 * i + 3] != 127) {"
+                        "    failed = true;"
+                        "  }"
+                        "}"
+                        "offset = 298 * 300 * 4;"
+                        "for (var i = 0; i < 300; i++) {"
+                        "  if (large_array[offset + 4 * i] != 127 ||"
+                        "      large_array[offset + 4 * i + 1] != 0 ||"
+                        "      large_array[offset + 4 * i + 2] != 0 ||"
+                        "      large_array[offset + 4 * i + 3] != 127) {"
+                        "    failed = true;"
+                        "  }"
+                        "}"
+                        "!failed;");
+    CHECK_EQ(true, result->BooleanValue());
+    free(large_array_data);
+  }
+
   free(array_data);
 }