| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 4574)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -4507,6 +4507,28 @@
|
| }
|
|
|
|
|
| +class DeferredSwapElements: public DeferredCode {
|
| + public:
|
| + DeferredSwapElements(Register object, Register index1, Register index2)
|
| + : object_(object), index1_(index1), index2_(index2) {
|
| + set_comment("[ DeferredSwapElements");
|
| + }
|
| +
|
| + virtual void Generate();
|
| +
|
| + private:
|
| + Register object_, index1_, index2_;
|
| +};
|
| +
|
| +
|
| +void DeferredSwapElements::Generate() {
|
| + __ push(object_);
|
| + __ push(index1_);
|
| + __ push(index2_);
|
| + __ CallRuntime(Runtime::kSwapElements, 3);
|
| +}
|
| +
|
| +
|
| void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
|
| Comment cmnt(masm_, "[ GenerateSwapElements");
|
|
|
| @@ -4516,8 +4538,76 @@
|
| Load(args->at(1));
|
| Load(args->at(2));
|
|
|
| - frame_->CallRuntime(Runtime::kSwapElements, 3);
|
| - frame_->EmitPush(r0);
|
| + Register index2 = r2;
|
| + Register index1 = r1;
|
| + Register object = r0;
|
| + Register tmp1 = r3;
|
| + Register tmp2 = r4;
|
| +
|
| + frame_->EmitPop(index2);
|
| + frame_->EmitPop(index1);
|
| + frame_->EmitPop(object);
|
| +
|
| + DeferredSwapElements* deferred =
|
| + new DeferredSwapElements(object, index1, index2);
|
| +
|
| + // Fetch the map and check if array is in fast case.
|
| + // Check that object doesn't require security checks and
|
| + // has no indexed interceptor.
|
| + __ CompareObjectType(object, tmp1, tmp2, FIRST_JS_OBJECT_TYPE);
|
| + deferred->Branch(lt);
|
| + __ ldrb(tmp2, FieldMemOperand(tmp1, Map::kBitFieldOffset));
|
| + __ tst(tmp2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
|
| + deferred->Branch(nz);
|
| +
|
| + // Check the object's elements are in fast case.
|
| + __ ldr(tmp1, FieldMemOperand(object, JSObject::kElementsOffset));
|
| + __ ldr(tmp2, FieldMemOperand(tmp1, HeapObject::kMapOffset));
|
| + __ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
|
| + __ cmp(tmp2, ip);
|
| + deferred->Branch(ne);
|
| +
|
| + // Smi-tagging is equivalent to multiplying by 2.
|
| + STATIC_ASSERT(kSmiTag == 0);
|
| + STATIC_ASSERT(kSmiTagSize == 1);
|
| +
|
| + // Check that both indices are smis.
|
| + __ mov(tmp2, index1);
|
| + __ orr(tmp2, tmp2, index2);
|
| + __ tst(tmp2, Operand(kSmiTagMask));
|
| + deferred->Branch(nz);
|
| +
|
| + // Bring the offsets into the fixed array in tmp1 into index1 and
|
| + // index2.
|
| + __ mov(tmp2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
|
| + __ add(index1, tmp2, Operand(index1, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| + __ add(index2, tmp2, Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize));
|
| +
|
| + // Swap elements.
|
| + Register tmp3 = object;
|
| + object = no_reg;
|
| + __ ldr(tmp3, MemOperand(tmp1, index1));
|
| + __ ldr(tmp2, MemOperand(tmp1, index2));
|
| + __ str(tmp3, MemOperand(tmp1, index2));
|
| + __ str(tmp2, MemOperand(tmp1, index1));
|
| +
|
| + Label done;
|
| + __ InNewSpace(tmp1, tmp2, eq, &done);
|
| + // Possible optimization: do a check that both values are Smis
|
| + // (or them and test against Smi mask.)
|
| +
|
| + __ mov(tmp2, tmp1);
|
| + RecordWriteStub recordWrite1(tmp1, index1, tmp3);
|
| + __ CallStub(&recordWrite1);
|
| +
|
| + RecordWriteStub recordWrite2(tmp2, index2, tmp3);
|
| + __ CallStub(&recordWrite2);
|
| +
|
| + __ bind(&done);
|
| +
|
| + deferred->BindExit();
|
| + __ LoadRoot(tmp1, Heap::kUndefinedValueRootIndex);
|
| + frame_->EmitPush(tmp1);
|
| }
|
|
|
|
|
| @@ -6503,6 +6593,12 @@
|
| }
|
|
|
|
|
| +void RecordWriteStub::Generate(MacroAssembler* masm) {
|
| + __ RecordWriteHelper(object_, offset_, scratch_);
|
| + __ Ret();
|
| +}
|
| +
|
| +
|
| // On entry r0 (rhs) and r1 (lhs) are the values to be compared.
|
| // On exit r0 is 0, positive or negative to indicate the result of
|
| // the comparison.
|
|
|