| 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);
|
|
|