Reviewers: Weiliang, Jakob,

Message:
WL.
PTAL.
thanks

Description:
X87: Add fast-path OOB support to KeyedLoadIC_Generic

port 79ed8f173ce1624f6d7821ea6b44ce75efa97912.

original commit message:
  Add fast-path OOB support to KeyedLoadIC_Generic

BUG=

Please review this at https://codereview.chromium.org/862443002/

Base URL: https://chromium.googlesource.com/v8/v8.git@master

Affected files (+43, -20 lines):
  M src/ic/x87/ic-x87.cc


Index: src/ic/x87/ic-x87.cc
diff --git a/src/ic/x87/ic-x87.cc b/src/ic/x87/ic-x87.cc
index 1004ac036b89c4b4e4dd7adb694c0340776effbc..49252ef8b964d4ebac682a7ee03d32b911a6bcfe 100644
--- a/src/ic/x87/ic-x87.cc
+++ b/src/ic/x87/ic-x87.cc
@@ -169,42 +169,65 @@ static void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm,


 // Loads an indexed element from a fast case array.
-// If not_fast_array is NULL, doesn't perform the elements map check.
 static void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver,
                                   Register key, Register scratch,
-                                  Register result, Label* not_fast_array,
-                                  Label* out_of_range) {
+                                  Register scratch2, Register result,
+                                  Label* slow) {
   // Register use:
   //   receiver - holds the receiver and is unchanged.
   //   key - holds the key and is unchanged (must be a smi).
   // Scratch registers:
// scratch - used to hold elements of the receiver and the loaded value.
+  //   scratch2 - holds maps and prototypes during prototype chain check.
   //   result - holds the result on exit if the load succeeds and
   //            we fall through.
+  Label check_prototypes, check_next_prototype;
+  Label done, in_bounds, return_undefined;

   __ mov(scratch, FieldOperand(receiver, JSObject::kElementsOffset));
-  if (not_fast_array != NULL) {
-    // Check that the object is in fast mode and writable.
-    __ CheckMap(scratch,
-                masm->isolate()->factory()->fixed_array_map(),
-                not_fast_array,
-                DONT_DO_SMI_CHECK);
-  } else {
-    __ AssertFastElements(scratch);
-  }
+  __ AssertFastElements(scratch);
+
   // Check that the key (index) is within bounds.
   __ cmp(key, FieldOperand(scratch, FixedArray::kLengthOffset));
-  __ j(above_equal, out_of_range);
+  __ j(below, &in_bounds);
+  // Out-of-bounds. Check the prototype chain to see if we can just return
+  // 'undefined'.
+  __ cmp(key, 0);
+  __ j(less, slow);  // Negative keys can't take the fast OOB path.
+  __ bind(&check_prototypes);
+  __ mov(scratch2, FieldOperand(receiver, HeapObject::kMapOffset));
+  __ bind(&check_next_prototype);
+  __ mov(scratch2, FieldOperand(scratch2, Map::kPrototypeOffset));
+  // scratch2: current prototype
+  __ cmp(scratch2, masm->isolate()->factory()->null_value());
+  __ j(equal, &return_undefined);
+  __ mov(scratch, FieldOperand(scratch2, JSObject::kElementsOffset));
+  __ mov(scratch2, FieldOperand(scratch2, HeapObject::kMapOffset));
+  // scratch: elements of current prototype
+  // scratch2: map of current prototype
+  __ CmpInstanceType(scratch2, JS_OBJECT_TYPE);
+  __ j(below, slow);
+  __ test_b(
+      FieldOperand(scratch2, Map::kBitFieldOffset),
+ (1 << Map::kIsAccessCheckNeeded) | (1 << Map::kHasIndexedInterceptor));
+  __ j(not_zero, slow);
+  __ cmp(scratch, masm->isolate()->factory()->empty_fixed_array());
+  __ j(not_equal, slow);
+  __ jmp(&check_next_prototype);
+
+  __ bind(&return_undefined);
+  __ mov(result, masm->isolate()->factory()->undefined_value());
+  __ jmp(&done);
+
+  __ bind(&in_bounds);
   // Fast case: Do the load.
STATIC_ASSERT((kPointerSize == 4) && (kSmiTagSize == 1) && (kSmiTag == 0)); __ mov(scratch, FieldOperand(scratch, key, times_2, FixedArray::kHeaderSize));
   __ cmp(scratch, Immediate(masm->isolate()->factory()->the_hole_value()));
-  // In case the loaded value is the_hole we have to consult GetProperty
-  // to ensure the prototype chain is searched.
-  __ j(equal, out_of_range);
-  if (!result.is(scratch)) {
-    __ mov(result, scratch);
-  }
+ // In case the loaded value is the_hole we have to check the prototype chain.
+  __ j(equal, &check_prototypes);
+  __ Move(result, scratch);
+  __ bind(&done);
 }


@@ -329,7 +352,7 @@ void KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) {
   // Check the receiver's map to see if it has fast elements.
   __ CheckFastElements(eax, &check_number_dictionary);

-  GenerateFastArrayLoad(masm, receiver, key, eax, eax, NULL, &slow);
+  GenerateFastArrayLoad(masm, receiver, key, eax, ebx, eax, &slow);
   Isolate* isolate = masm->isolate();
   Counters* counters = isolate->counters();
   __ IncrementCounter(counters->keyed_load_generic_smi(), 1);


--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to