| Index: src/ia32/codegen-ia32.cc
|
| diff --git a/src/ia32/codegen-ia32.cc b/src/ia32/codegen-ia32.cc
|
| index e1f2d666331bdac8caf5d974367756e45d39b23a..5fa8255a1ae76ac4e53843282619ca6b2d259ee9 100644
|
| --- a/src/ia32/codegen-ia32.cc
|
| +++ b/src/ia32/codegen-ia32.cc
|
| @@ -6607,6 +6607,121 @@ void CodeGenerator::GenerateNumberToString(ZoneList<Expression*>* args) {
|
| }
|
|
|
|
|
| +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) {
|
| + // Note: this code assumes that indices are passed are within
|
| + // elements' bounds and refer to valid (not holes) values.
|
| + Comment cmnt(masm_, "[ GenerateSwapElements");
|
| +
|
| + ASSERT_EQ(3, args->length());
|
| +
|
| + Load(args->at(0));
|
| + Load(args->at(1));
|
| + Load(args->at(2));
|
| +
|
| + Result index2 = frame_->Pop();
|
| + index2.ToRegister();
|
| +
|
| + Result index1 = frame_->Pop();
|
| + index1.ToRegister();
|
| +
|
| + Result object = frame_->Pop();
|
| + object.ToRegister();
|
| +
|
| + Result tmp1 = allocator()->Allocate();
|
| + tmp1.ToRegister();
|
| + Result tmp2 = allocator()->Allocate();
|
| + tmp2.ToRegister();
|
| +
|
| + frame_->Spill(object.reg());
|
| + frame_->Spill(index1.reg());
|
| + frame_->Spill(index2.reg());
|
| +
|
| + DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(),
|
| + index1.reg(),
|
| + index2.reg());
|
| +
|
| + // Fetch the map and check if array is in fast case.
|
| + // Check that object doesn't require security checks and
|
| + // has no indexed interceptor.
|
| + __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
|
| + deferred->Branch(less);
|
| + __ movzx_b(tmp1.reg(), FieldOperand(tmp1.reg(), Map::kBitFieldOffset));
|
| + __ test(tmp1.reg(), Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
|
| + deferred->Branch(not_zero);
|
| +
|
| + // Check the object's elements are in fast case.
|
| + __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
|
| + __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
|
| + Immediate(Factory::fixed_array_map()));
|
| + deferred->Branch(not_equal);
|
| +
|
| + // Smi-tagging is equivalent to multiplying by 2.
|
| + STATIC_ASSERT(kSmiTag == 0);
|
| + STATIC_ASSERT(kSmiTagSize == 1);
|
| +
|
| + // Check that both indices are smis.
|
| + __ mov(tmp2.reg(), index1.reg());
|
| + __ or_(tmp2.reg(), Operand(index2.reg()));
|
| + __ test(tmp2.reg(), Immediate(kSmiTagMask));
|
| + deferred->Branch(not_zero);
|
| +
|
| + // Bring addresses into index1 and index2.
|
| + __ lea(index1.reg(), FieldOperand(tmp1.reg(),
|
| + index1.reg(),
|
| + times_half_pointer_size, // index1 is Smi
|
| + FixedArray::kHeaderSize));
|
| + __ lea(index2.reg(), FieldOperand(tmp1.reg(),
|
| + index2.reg(),
|
| + times_half_pointer_size, // index2 is Smi
|
| + FixedArray::kHeaderSize));
|
| +
|
| + // Swap elements.
|
| + __ mov(object.reg(), Operand(index1.reg(), 0));
|
| + __ mov(tmp2.reg(), Operand(index2.reg(), 0));
|
| + __ mov(Operand(index2.reg(), 0), object.reg());
|
| + __ mov(Operand(index1.reg(), 0), tmp2.reg());
|
| +
|
| + Label done;
|
| + __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
|
| + // Possible optimization: do a check that both values are Smis
|
| + // (or them and test against Smi mask.)
|
| +
|
| + __ mov(tmp2.reg(), tmp1.reg());
|
| + RecordWriteStub recordWrite1(tmp2.reg(), index1.reg(), object.reg());
|
| + __ CallStub(&recordWrite1);
|
| +
|
| + RecordWriteStub recordWrite2(tmp1.reg(), index2.reg(), object.reg());
|
| + __ CallStub(&recordWrite2);
|
| +
|
| + __ bind(&done);
|
| +
|
| + deferred->BindExit();
|
| + frame_->Push(Factory::undefined_value());
|
| +}
|
| +
|
| +
|
| void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
|
| Comment cmnt(masm_, "[ GenerateCallFunction");
|
|
|
|
|