| Index: src/arm/ic-arm.cc
|
| ===================================================================
|
| --- src/arm/ic-arm.cc (revision 3935)
|
| +++ src/arm/ic-arm.cc (working copy)
|
| @@ -59,7 +59,7 @@
|
| // r3 - used as temporary and to hold the capacity of the property
|
| // dictionary.
|
| //
|
| - // r2 - holds the name of the property and is unchanges.
|
| + // r2 - holds the name of the property and is unchanged.
|
|
|
| Label done;
|
|
|
| @@ -171,7 +171,7 @@
|
|
|
| __ ldr(r0, MemOperand(sp, 0));
|
|
|
| - StubCompiler::GenerateLoadStringLength2(masm, r0, r1, r3, &miss);
|
| + StubCompiler::GenerateLoadStringLength(masm, r0, r1, r3, &miss);
|
| // Cache miss: Jump to runtime.
|
| __ bind(&miss);
|
| StubCompiler::GenerateLoadMiss(masm, Code::LOAD_IC);
|
| @@ -200,14 +200,13 @@
|
|
|
| void CallIC::GenerateMegamorphic(MacroAssembler* masm, int argc) {
|
| // ----------- S t a t e -------------
|
| - // -- lr: return address
|
| + // -- r2 : name
|
| + // -- lr : return address
|
| // -----------------------------------
|
| Label number, non_number, non_string, boolean, probe, miss;
|
|
|
| // Get the receiver of the function from the stack into r1.
|
| __ ldr(r1, MemOperand(sp, argc * kPointerSize));
|
| - // Get the name of the function from the stack; 1 ~ receiver.
|
| - __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
|
|
|
| // Probe the stub cache.
|
| Code::Flags flags =
|
| @@ -276,9 +275,9 @@
|
|
|
| // Patch the receiver with the global proxy if necessary.
|
| if (is_global_object) {
|
| - __ ldr(r2, MemOperand(sp, argc * kPointerSize));
|
| - __ ldr(r2, FieldMemOperand(r2, GlobalObject::kGlobalReceiverOffset));
|
| - __ str(r2, MemOperand(sp, argc * kPointerSize));
|
| + __ ldr(r0, MemOperand(sp, argc * kPointerSize));
|
| + __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset));
|
| + __ str(r0, MemOperand(sp, argc * kPointerSize));
|
| }
|
|
|
| // Invoke the function.
|
| @@ -289,14 +288,13 @@
|
|
|
| void CallIC::GenerateNormal(MacroAssembler* masm, int argc) {
|
| // ----------- S t a t e -------------
|
| - // -- lr: return address
|
| + // -- r2 : name
|
| + // -- lr : return address
|
| // -----------------------------------
|
| Label miss, global_object, non_global_object;
|
|
|
| // Get the receiver of the function from the stack into r1.
|
| __ ldr(r1, MemOperand(sp, argc * kPointerSize));
|
| - // Get the name of the function from the stack; 1 ~ receiver.
|
| - __ ldr(r2, MemOperand(sp, (argc + 1) * kPointerSize));
|
|
|
| // Check that the receiver isn't a smi.
|
| __ tst(r1, Operand(kSmiTagMask));
|
| @@ -349,18 +347,17 @@
|
|
|
| void CallIC::GenerateMiss(MacroAssembler* masm, int argc) {
|
| // ----------- S t a t e -------------
|
| - // -- lr: return address
|
| + // -- r2 : name
|
| + // -- lr : return address
|
| // -----------------------------------
|
|
|
| // Get the receiver of the function from the stack.
|
| - __ ldr(r2, MemOperand(sp, argc * kPointerSize));
|
| - // Get the name of the function to call from the stack.
|
| - __ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
|
| + __ ldr(r3, MemOperand(sp, argc * kPointerSize));
|
|
|
| __ EnterInternalFrame();
|
|
|
| // Push the receiver and the name of the function.
|
| - __ stm(db_w, sp, r1.bit() | r2.bit());
|
| + __ stm(db_w, sp, r2.bit() | r3.bit());
|
|
|
| // Call the entry.
|
| __ mov(r0, Operand(2));
|
| @@ -413,7 +410,7 @@
|
| StubCache::GenerateProbe(masm, flags, r0, r2, r3, no_reg);
|
|
|
| // Cache miss: Jump to runtime.
|
| - Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
|
| + GenerateMiss(masm);
|
| }
|
|
|
|
|
| @@ -456,16 +453,11 @@
|
|
|
| // Cache miss: Restore receiver from stack and jump to runtime.
|
| __ bind(&miss);
|
| - Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
|
| + GenerateMiss(masm);
|
| }
|
|
|
|
|
| void LoadIC::GenerateMiss(MacroAssembler* masm) {
|
| - Generate(masm, ExternalReference(IC_Utility(kLoadIC_Miss)));
|
| -}
|
| -
|
| -
|
| -void LoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
|
| // ----------- S t a t e -------------
|
| // -- r2 : name
|
| // -- lr : return address
|
| @@ -476,7 +468,7 @@
|
| __ stm(db_w, sp, r2.bit() | r3.bit());
|
|
|
| // Perform tail call to the entry.
|
| - __ TailCallRuntime(f, 2, 1);
|
| + __ TailCallRuntime(ExternalReference(IC_Utility(kLoadIC_Miss)), 2, 1);
|
| }
|
|
|
|
|
| @@ -504,11 +496,20 @@
|
|
|
|
|
| void KeyedLoadIC::GenerateMiss(MacroAssembler* masm) {
|
| - Generate(masm, ExternalReference(IC_Utility(kKeyedLoadIC_Miss)));
|
| + // ---------- S t a t e --------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| +
|
| + __ ldm(ia, sp, r2.bit() | r3.bit());
|
| + __ stm(db_w, sp, r2.bit() | r3.bit());
|
| +
|
| + __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedLoadIC_Miss)), 2, 1);
|
| }
|
|
|
|
|
| -void KeyedLoadIC::Generate(MacroAssembler* masm, const ExternalReference& f) {
|
| +void KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) {
|
| // ---------- S t a t e --------------
|
| // -- lr : return address
|
| // -- sp[0] : key
|
| @@ -518,7 +519,7 @@
|
| __ ldm(ia, sp, r2.bit() | r3.bit());
|
| __ stm(db_w, sp, r2.bit() | r3.bit());
|
|
|
| - __ TailCallRuntime(f, 2, 1);
|
| + __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2, 1);
|
| }
|
|
|
|
|
| @@ -532,17 +533,11 @@
|
|
|
| // Get the key and receiver object from the stack.
|
| __ ldm(ia, sp, r0.bit() | r1.bit());
|
| - // Check that the key is a smi.
|
| - __ tst(r0, Operand(kSmiTagMask));
|
| - __ b(ne, &slow);
|
| - __ mov(r0, Operand(r0, ASR, kSmiTagSize));
|
| +
|
| // Check that the object isn't a smi.
|
| - __ tst(r1, Operand(kSmiTagMask));
|
| - __ b(eq, &slow);
|
| -
|
| + __ BranchOnSmi(r1, &slow);
|
| // Get the map of the receiver.
|
| __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
| -
|
| // Check bit field.
|
| __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
|
| __ tst(r3, Operand(kSlowCaseBitFieldMask));
|
| @@ -556,6 +551,10 @@
|
| __ cmp(r2, Operand(JS_OBJECT_TYPE));
|
| __ b(lt, &slow);
|
|
|
| + // Check that the key is a smi.
|
| + __ BranchOnNotSmi(r0, &slow);
|
| + __ mov(r0, Operand(r0, ASR, kSmiTagSize));
|
| +
|
| // Get the elements array of the object.
|
| __ ldr(r1, FieldMemOperand(r1, JSObject::kElementsOffset));
|
| // Check that the object is in fast mode (not dictionary).
|
| @@ -571,10 +570,7 @@
|
| // Slow case: Push extra copies of the arguments (2).
|
| __ bind(&slow);
|
| __ IncrementCounter(&Counters::keyed_load_generic_slow, 1, r0, r1);
|
| - __ ldm(ia, sp, r0.bit() | r1.bit());
|
| - __ stm(db_w, sp, r0.bit() | r1.bit());
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(ExternalReference(Runtime::kGetProperty), 2, 1);
|
| + GenerateRuntimeGetProperty(masm);
|
|
|
| // Fast case: Do the load.
|
| __ bind(&fast);
|
| @@ -608,9 +604,48 @@
|
| }
|
|
|
|
|
| -void KeyedStoreIC::Generate(MacroAssembler* masm,
|
| - const ExternalReference& f) {
|
| +void KeyedLoadIC::GenerateIndexedInterceptor(MacroAssembler* masm) {
|
| // ---------- S t a t e --------------
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[4] : receiver
|
| + // -----------------------------------
|
| + Label slow;
|
| +
|
| + // Get the key and receiver object from the stack.
|
| + __ ldm(ia, sp, r0.bit() | r1.bit());
|
| +
|
| + // Check that the receiver isn't a smi.
|
| + __ BranchOnSmi(r1, &slow);
|
| +
|
| + // Check that the key is a smi.
|
| + __ BranchOnNotSmi(r0, &slow);
|
| +
|
| + // Get the map of the receiver.
|
| + __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset));
|
| +
|
| + // Check that it has indexed interceptor and access checks
|
| + // are not enabled for this object.
|
| + __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
|
| + __ and_(r3, r3, Operand(kSlowCaseBitFieldMask));
|
| + __ cmp(r3, Operand(1 << Map::kHasIndexedInterceptor));
|
| + __ b(ne, &slow);
|
| +
|
| + // Everything is fine, call runtime.
|
| + __ push(r1); // receiver
|
| + __ push(r0); // key
|
| +
|
| + // Perform tail call to the entry.
|
| + __ TailCallRuntime(ExternalReference(
|
| + IC_Utility(kKeyedLoadPropertyWithInterceptor)), 2, 1);
|
| +
|
| + __ bind(&slow);
|
| + GenerateMiss(masm);
|
| +}
|
| +
|
| +
|
| +void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) {
|
| + // ---------- S t a t e --------------
|
| // -- r0 : value
|
| // -- lr : return address
|
| // -- sp[0] : key
|
| @@ -620,10 +655,24 @@
|
| __ ldm(ia, sp, r2.bit() | r3.bit());
|
| __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
|
|
|
| - __ TailCallRuntime(f, 3, 1);
|
| + __ TailCallRuntime(ExternalReference(IC_Utility(kKeyedStoreIC_Miss)), 3, 1);
|
| }
|
|
|
|
|
| +void KeyedStoreIC::GenerateRuntimeSetProperty(MacroAssembler* masm) {
|
| + // ---------- S t a t e --------------
|
| + // -- r0 : value
|
| + // -- lr : return address
|
| + // -- sp[0] : key
|
| + // -- sp[1] : receiver
|
| + // -----------------------------------
|
| + __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object
|
| + __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
|
| +
|
| + __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1);
|
| +}
|
| +
|
| +
|
| void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm) {
|
| // ---------- S t a t e --------------
|
| // -- r0 : value
|
| @@ -675,12 +724,9 @@
|
| __ b(lo, &fast);
|
|
|
|
|
| - // Slow case: Push extra copies of the arguments (3).
|
| + // Slow case:
|
| __ bind(&slow);
|
| - __ ldm(ia, sp, r1.bit() | r3.bit()); // r0 == value, r1 == key, r3 == object
|
| - __ stm(db_w, sp, r0.bit() | r1.bit() | r3.bit());
|
| - // Do tail-call to runtime routine.
|
| - __ TailCallRuntime(ExternalReference(Runtime::kSetProperty), 3, 1);
|
| + GenerateRuntimeSetProperty(masm);
|
|
|
| // Extra capacity case: Check if there is extra capacity to
|
| // perform the store and update the length. Used for adding one
|
| @@ -751,33 +797,15 @@
|
| }
|
|
|
|
|
| -void KeyedStoreIC::GenerateExtendStorage(MacroAssembler* masm) {
|
| - // ---------- S t a t e --------------
|
| - // -- r0 : value
|
| - // -- lr : return address
|
| - // -- sp[0] : key
|
| - // -- sp[1] : receiver
|
| - // ----------- S t a t e -------------
|
| -
|
| - __ ldm(ia, sp, r2.bit() | r3.bit());
|
| - __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
|
| -
|
| - // Perform tail call to the entry.
|
| - __ TailCallRuntime(
|
| - ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
|
| -}
|
| -
|
| -
|
| void StoreIC::GenerateMegamorphic(MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- r0 : value
|
| + // -- r1 : receiver
|
| // -- r2 : name
|
| // -- lr : return address
|
| - // -- [sp] : receiver
|
| // -----------------------------------
|
|
|
| // Get the receiver from the stack and probe the stub cache.
|
| - __ ldr(r1, MemOperand(sp));
|
| Code::Flags flags = Code::ComputeFlags(Code::STORE_IC,
|
| NOT_IN_LOOP,
|
| MONOMORPHIC);
|
| @@ -788,36 +816,66 @@
|
| }
|
|
|
|
|
| -void StoreIC::GenerateExtendStorage(MacroAssembler* masm) {
|
| +void StoreIC::GenerateMiss(MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- r0 : value
|
| + // -- r1 : receiver
|
| // -- r2 : name
|
| // -- lr : return address
|
| - // -- [sp] : receiver
|
| // -----------------------------------
|
|
|
| - __ ldr(r3, MemOperand(sp)); // copy receiver
|
| - __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
|
| + __ push(r1);
|
| + __ stm(db_w, sp, r2.bit() | r0.bit());
|
|
|
| // Perform tail call to the entry.
|
| - __ TailCallRuntime(
|
| - ExternalReference(IC_Utility(kSharedStoreIC_ExtendStorage)), 3, 1);
|
| + __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1);
|
| }
|
|
|
|
|
| -void StoreIC::GenerateMiss(MacroAssembler* masm) {
|
| +void StoreIC::GenerateArrayLength(MacroAssembler* masm) {
|
| // ----------- S t a t e -------------
|
| // -- r0 : value
|
| + // -- r1 : receiver
|
| // -- r2 : name
|
| // -- lr : return address
|
| - // -- [sp] : receiver
|
| // -----------------------------------
|
| + //
|
| + // This accepts as a receiver anything JSObject::SetElementsLength accepts
|
| + // (currently anything except for external and pixel arrays which means
|
| + // anything with elements of FixedArray type.), but currently is restricted
|
| + // to JSArray.
|
| + // Value must be a number, but only smis are accepted as the most common case.
|
|
|
| - __ ldr(r3, MemOperand(sp)); // copy receiver
|
| - __ stm(db_w, sp, r0.bit() | r2.bit() | r3.bit());
|
| + Label miss;
|
|
|
| - // Perform tail call to the entry.
|
| - __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_Miss)), 3, 1);
|
| + Register receiver = r1;
|
| + Register value = r0;
|
| + Register scratch = r3;
|
| +
|
| + // Check that the receiver isn't a smi.
|
| + __ BranchOnSmi(receiver, &miss);
|
| +
|
| + // Check that the object is a JS array.
|
| + __ CompareObjectType(receiver, scratch, scratch, JS_ARRAY_TYPE);
|
| + __ b(ne, &miss);
|
| +
|
| + // Check that elements are FixedArray.
|
| + __ ldr(scratch, FieldMemOperand(receiver, JSArray::kElementsOffset));
|
| + __ CompareObjectType(scratch, scratch, scratch, FIXED_ARRAY_TYPE);
|
| + __ b(ne, &miss);
|
| +
|
| + // Check that value is a smi.
|
| + __ BranchOnNotSmi(value, &miss);
|
| +
|
| + // Prepare tail call to StoreIC_ArrayLength.
|
| + __ push(receiver);
|
| + __ push(value);
|
| +
|
| + __ TailCallRuntime(ExternalReference(IC_Utility(kStoreIC_ArrayLength)), 2, 1);
|
| +
|
| + __ bind(&miss);
|
| +
|
| + GenerateMiss(masm);
|
| }
|
|
|
|
|
|
|