Reviewers: fschneider, danno, Paul Lind, kisg,

Description:
MIPS: Improve performance of keyed loads/stores which have a HeapNumber index.

Port r11282 (bd2ab07).

Original commit message:

Some GWT compiled code results in array access that has a heap number (e.g. -0)
as an index. Until now this would result in a generic IC.

For example:

a[-0] === a[0] or

a[0.25 * 4] === a[1]

This change detects heap numbers that are representable as a smi
and converts them. As a result we can still use the fast keyed monomorphic
ICs. Optimized code already handles keyed access with a double-key efficiently.

As a result the frame rate on the reported benchmark improves by roughly 2x.

BUG=
TEST=


Please review this at http://codereview.chromium.org/10068012/

SVN Base: https://v8.googlecode.com/svn/branches/bleeding_edge

Affected files:
  M src/mips/stub-cache-mips.cc


Index: src/mips/stub-cache-mips.cc
diff --git a/src/mips/stub-cache-mips.cc b/src/mips/stub-cache-mips.cc
index 4d18c942db86b0d185e3fc6cf3d50e8dc32dbbfd..a319011d0fa809344e3d311956b804102118e4ff 100644
--- a/src/mips/stub-cache-mips.cc
+++ b/src/mips/stub-cache-mips.cc
@@ -3371,6 +3371,45 @@ static bool IsElementTypeSigned(ElementsKind elements_kind) {
 }


+static void GenerateSmiKeyCheck(MacroAssembler* masm,
+                                Register key,
+                                Register scratch0,
+                                Register scratch1,
+                                FPURegister double_scratch0,
+                                Label* fail) {
+  if (CpuFeatures::IsSupported(FPU)) {
+    CpuFeatures::Scope scope(FPU);
+    Label key_ok;
+    // Check for smi or a smi inside a heap number.  We convert the heap
+    // number and check if the conversion is exact and fits into the smi
+    // range.
+    __ JumpIfSmi(key, &key_ok);
+    __ CheckMap(key,
+                scratch0,
+                Heap::kHeapNumberMapRootIndex,
+                fail,
+                DONT_DO_SMI_CHECK);
+ __ ldc1(double_scratch0, FieldMemOperand(key, HeapNumber::kValueOffset));
+    __ EmitFPUTruncate(kRoundToZero,
+                       double_scratch0,
+                       double_scratch0,
+                       scratch0,
+                       scratch1,
+                       kCheckForInexactConversion);
+
+    __ Branch(fail, ne, scratch1, Operand(zero_reg));
+
+    __ mfc1(scratch0, double_scratch0);
+    __ SmiTagCheckOverflow(key, scratch0, scratch1);
+    __ BranchOnOverflow(fail, scratch1);
+    __ bind(&key_ok);
+  } else {
+    // Check that the key is a smi.
+    __ JumpIfNotSmi(key, fail);
+  }
+}
+
+
 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
     MacroAssembler* masm,
     ElementsKind elements_kind) {
@@ -3387,8 +3426,8 @@ void KeyedLoadStubCompiler::GenerateLoadExternalArray(
   // This stub is meant to be tail-jumped to, the receiver must already
   // have been verified by the caller to not be a smi.

-  // Check that the key is a smi.
-  __ JumpIfNotSmi(key, &miss_force_generic);
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic);

   __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));
   // a3: elements array
@@ -3726,8 +3765,8 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
   // This stub is meant to be tail-jumped to, the receiver must already
   // have been verified by the caller to not be a smi.

-    // Check that the key is a smi.
-  __ JumpIfNotSmi(key, &miss_force_generic);
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key, t0, t1, f2, &miss_force_generic);

   __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset));

@@ -4106,9 +4145,8 @@ void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
   // This stub is meant to be tail-jumped to, the receiver must already
   // have been verified by the caller to not be a smi.

-  // Check that the key is a smi.
-  __ JumpIfNotSmi(a0, &miss_force_generic, at, USE_DELAY_SLOT);
-  // The delay slot can be safely used here, a1 is an object pointer.
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, a0, t0, t1, f2, &miss_force_generic);

   // Get the elements array.
   __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset));
@@ -4158,8 +4196,8 @@ void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
   // This stub is meant to be tail-jumped to, the receiver must already
   // have been verified by the caller to not be a smi.

-  // Check that the key is a smi.
-  __ JumpIfNotSmi(key_reg, &miss_force_generic);
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic);

   // Get the elements array.
   __ lw(elements_reg,
@@ -4233,8 +4271,8 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
   // This stub is meant to be tail-jumped to, the receiver must already
   // have been verified by the caller to not be a smi.

-  // Check that the key is a smi.
-  __ JumpIfNotSmi(key_reg, &miss_force_generic);
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic);

   if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
     __ JumpIfNotSmi(value_reg, &transition_elements_kind);
@@ -4400,7 +4438,9 @@ void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(

   // This stub is meant to be tail-jumped to, the receiver must already
   // have been verified by the caller to not be a smi.
-  __ JumpIfNotSmi(key_reg, &miss_force_generic);
+
+  // Check that the key is a smi or a heap number convertible to a smi.
+  GenerateSmiKeyCheck(masm, key_reg, t0, t1, f2, &miss_force_generic);

   __ lw(elements_reg,
          FieldMemOperand(receiver_reg, JSObject::kElementsOffset));


--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to