| Index: src/arm/ic-arm.cc
|
| ===================================================================
|
| --- src/arm/ic-arm.cc (revision 4975)
|
| +++ src/arm/ic-arm.cc (working copy)
|
| @@ -64,12 +64,12 @@
|
|
|
| // Generated code falls through if the receiver is a regular non-global
|
| // JS object with slow properties and no interceptors.
|
| -static void GenerateDictionaryLoadReceiverCheck(MacroAssembler* masm,
|
| - Register receiver,
|
| - Register elements,
|
| - Register t0,
|
| - Register t1,
|
| - Label* miss) {
|
| +static void GenerateStringDictionaryReceiverCheck(MacroAssembler* masm,
|
| + Register receiver,
|
| + Register elements,
|
| + Register t0,
|
| + Register t1,
|
| + Label* miss) {
|
| // Register usage:
|
| // receiver: holds the receiver on entry and is unchanged.
|
| // elements: holds the property dictionary on fall through.
|
| @@ -105,33 +105,16 @@
|
| }
|
|
|
|
|
| -// Helper function used from LoadIC/CallIC GenerateNormal.
|
| -//
|
| -// elements: Property dictionary. It is not clobbered if a jump to the miss
|
| -// label is done.
|
| -// name: Property name. It is not clobbered if a jump to the miss label is
|
| -// done
|
| -// result: Register for the result. It is only updated if a jump to the miss
|
| -// label is not done. Can be the same as elements or name clobbering
|
| -// one of these in the case of not jumping to the miss label.
|
| -// The two scratch registers need to be different from elements, name and
|
| -// result.
|
| -// The generated code assumes that the receiver has slow properties,
|
| -// is not a global object and does not have interceptors.
|
| -static void GenerateDictionaryLoad(MacroAssembler* masm,
|
| - Label* miss,
|
| - Register elements,
|
| - Register name,
|
| - Register result,
|
| - Register scratch1,
|
| - Register scratch2) {
|
| - // Main use of the scratch registers.
|
| - // scratch1: Used as temporary and to hold the capacity of the property
|
| - // dictionary.
|
| - // scratch2: Used as temporary.
|
| -
|
| - Label done;
|
| -
|
| +// Probe the string dictionary in the |elements| register. Jump to the
|
| +// |done| label if a property with the given name is found. Jump to
|
| +// the |miss| label otherwise.
|
| +static void GenerateStringDictionaryProbes(MacroAssembler* masm,
|
| + Label* miss,
|
| + Label* done,
|
| + Register elements,
|
| + Register name,
|
| + Register scratch1,
|
| + Register scratch2) {
|
| // Compute the capacity mask.
|
| const int kCapacityOffset = StringDictionary::kHeaderSize +
|
| StringDictionary::kCapacityIndex * kPointerSize;
|
| @@ -170,16 +153,56 @@
|
| __ ldr(ip, FieldMemOperand(scratch2, kElementsStartOffset));
|
| __ cmp(name, Operand(ip));
|
| if (i != kProbes - 1) {
|
| - __ b(eq, &done);
|
| + __ b(eq, done);
|
| } else {
|
| __ b(ne, miss);
|
| }
|
| }
|
| +}
|
|
|
| - // Check that the value is a normal property.
|
| +
|
| +// Helper function used from LoadIC/CallIC GenerateNormal.
|
| +//
|
| +// elements: Property dictionary. It is not clobbered if a jump to the miss
|
| +// label is done.
|
| +// name: Property name. It is not clobbered if a jump to the miss label is
|
| +// done
|
| +// result: Register for the result. It is only updated if a jump to the miss
|
| +// label is not done. Can be the same as elements or name clobbering
|
| +// one of these in the case of not jumping to the miss label.
|
| +// The two scratch registers need to be different from elements, name and
|
| +// result.
|
| +// The generated code assumes that the receiver has slow properties,
|
| +// is not a global object and does not have interceptors.
|
| +static void GenerateDictionaryLoad(MacroAssembler* masm,
|
| + Label* miss,
|
| + Register elements,
|
| + Register name,
|
| + Register result,
|
| + Register scratch1,
|
| + Register scratch2) {
|
| + // Main use of the scratch registers.
|
| + // scratch1: Used as temporary and to hold the capacity of the property
|
| + // dictionary.
|
| + // scratch2: Used as temporary.
|
| + Label done;
|
| +
|
| + // Probe the dictionary.
|
| + GenerateStringDictionaryProbes(masm,
|
| + miss,
|
| + &done,
|
| + elements,
|
| + name,
|
| + scratch1,
|
| + scratch2);
|
| +
|
| + // If probing finds an entry check that the value is a normal
|
| + // property.
|
| __ bind(&done); // scratch2 == elements + 4 * index
|
| - __ ldr(scratch1,
|
| - FieldMemOperand(scratch2, kElementsStartOffset + 2 * kPointerSize));
|
| + const int kElementsStartOffset = StringDictionary::kHeaderSize +
|
| + StringDictionary::kElementsStartIndex * kPointerSize;
|
| + const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
|
| + __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
|
| __ tst(scratch1, Operand(PropertyDetails::TypeField::mask() << kSmiTagSize));
|
| __ b(ne, miss);
|
|
|
| @@ -189,6 +212,63 @@
|
| }
|
|
|
|
|
| +// Helper function used from StoreIC::GenerateNormal.
|
| +//
|
| +// elements: Property dictionary. It is not clobbered if a jump to the miss
|
| +// label is done.
|
| +// name: Property name. It is not clobbered if a jump to the miss label is
|
| +// done
|
| +// value: The value to store.
|
| +// The two scratch registers need to be different from elements, name and
|
| +// result.
|
| +// The generated code assumes that the receiver has slow properties,
|
| +// is not a global object and does not have interceptors.
|
| +static void GenerateDictionaryStore(MacroAssembler* masm,
|
| + Label* miss,
|
| + Register elements,
|
| + Register name,
|
| + Register value,
|
| + Register scratch1,
|
| + Register scratch2) {
|
| + // Main use of the scratch registers.
|
| + // scratch1: Used as temporary and to hold the capacity of the property
|
| + // dictionary.
|
| + // scratch2: Used as temporary.
|
| + Label done;
|
| +
|
| + // Probe the dictionary.
|
| + GenerateStringDictionaryProbes(masm,
|
| + miss,
|
| + &done,
|
| + elements,
|
| + name,
|
| + scratch1,
|
| + scratch2);
|
| +
|
| + // If probing finds an entry in the dictionary check that the value
|
| + // is a normal property that is not read only.
|
| + __ bind(&done); // scratch2 == elements + 4 * index
|
| + const int kElementsStartOffset = StringDictionary::kHeaderSize +
|
| + StringDictionary::kElementsStartIndex * kPointerSize;
|
| + const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize;
|
| + const int kTypeAndReadOnlyMask
|
| + = (PropertyDetails::TypeField::mask() |
|
| + PropertyDetails::AttributesField::encode(READ_ONLY)) << kSmiTagSize;
|
| + __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset));
|
| + __ tst(scratch1, Operand(kTypeAndReadOnlyMask));
|
| + __ b(ne, miss);
|
| +
|
| + // Store the value at the masked, scaled index and return.
|
| + const int kValueOffset = kElementsStartOffset + kPointerSize;
|
| + __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag));
|
| + __ str(value, MemOperand(scratch2));
|
| +
|
| + // Update the write barrier. Make sure not to clobber the value.
|
| + __ mov(scratch1, value);
|
| + __ RecordWrite(elements, scratch2, scratch1);
|
| +}
|
| +
|
| +
|
| static void GenerateNumberDictionaryLoad(MacroAssembler* masm,
|
| Label* miss,
|
| Register elements,
|
| @@ -560,7 +640,7 @@
|
| // Get the receiver of the function from the stack into r1.
|
| __ ldr(r1, MemOperand(sp, argc * kPointerSize));
|
|
|
| - GenerateDictionaryLoadReceiverCheck(masm, r1, r0, r3, r4, &miss);
|
| + GenerateStringDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss);
|
|
|
| // r0: elements
|
| // Search the dictionary - put result in register r1.
|
| @@ -815,7 +895,7 @@
|
| // -----------------------------------
|
| Label miss;
|
|
|
| - GenerateDictionaryLoadReceiverCheck(masm, r0, r1, r3, r4, &miss);
|
| + GenerateStringDictionaryReceiverCheck(masm, r0, r1, r3, r4, &miss);
|
|
|
| // r1: elements
|
| GenerateDictionaryLoad(masm, &miss, r1, r2, r0, r3, r4);
|
| @@ -2138,6 +2218,27 @@
|
| }
|
|
|
|
|
| +void StoreIC::GenerateNormal(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- r0 : value
|
| + // -- r1 : receiver
|
| + // -- r2 : name
|
| + // -- lr : return address
|
| + // -----------------------------------
|
| + Label miss;
|
| +
|
| + GenerateStringDictionaryReceiverCheck(masm, r1, r3, r4, r5, &miss);
|
| +
|
| + GenerateDictionaryStore(masm, &miss, r3, r2, r0, r4, r5);
|
| + __ IncrementCounter(&Counters::store_normal_hit, 1, r4, r5);
|
| + __ Ret();
|
| +
|
| + __ bind(&miss);
|
| + __ IncrementCounter(&Counters::store_normal_miss, 1, r4, r5);
|
| + GenerateMiss(masm);
|
| +}
|
| +
|
| +
|
| #undef __
|
|
|
|
|
|
|