X87: Add fast-path OOB support to KeyedLoadIC_Generic

port 79ed8f173c.

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}
This commit is contained in:
chunyang.dai 2015-01-18 21:44:00 -08:00 committed by Commit bot
parent f7e92b037b
commit 5e2b37cc92

View File

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