From: chunyang.dai Date: Mon, 19 Jan 2015 05:44:00 +0000 (-0800) Subject: X87: Add fast-path OOB support to KeyedLoadIC_Generic X-Git-Tag: upstream/4.7.83~4917 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5e2b37cc92b4c46e6b8a051841689f2843dc9629;p=platform%2Fupstream%2Fv8.git X87: Add fast-path OOB support to KeyedLoadIC_Generic port 79ed8f173ce1624f6d7821ea6b44ce75efa97912. original commit message: Add fast-path OOB support to KeyedLoadIC_Generic BUG= Review URL: https://codereview.chromium.org/862443002 Cr-Commit-Position: refs/heads/master@{#26123} --- diff --git a/src/ic/x87/ic-x87.cc b/src/ic/x87/ic-x87.cc index 1004ac0..49252ef 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);