ARM: Support %_SwapElements in the full compiler

Review URL: http://codereview.chromium.org/6597106

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@7033 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
sgjesse@chromium.org 2011-03-03 07:36:04 +00:00
parent 37214d189d
commit 39efab0df6

View File

@ -3113,7 +3113,80 @@ void FullCodeGenerator::EmitSwapElements(ZoneList<Expression*>* args) {
VisitForStackValue(args->at(0));
VisitForStackValue(args->at(1));
VisitForStackValue(args->at(2));
Label done;
Label slow_case;
Register object = r0;
Register index1 = r1;
Register index2 = r2;
Register elements = r3;
Register scratch1 = r4;
Register scratch2 = r5;
__ ldr(object, MemOperand(sp, 2 * kPointerSize));
// 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, scratch1, scratch2, FIRST_JS_OBJECT_TYPE);
__ b(lt, &slow_case);
// Map is now in scratch1.
__ ldrb(scratch2, FieldMemOperand(scratch1, Map::kBitFieldOffset));
__ tst(scratch2, Operand(KeyedLoadIC::kSlowCaseBitFieldMask));
__ b(ne, &slow_case);
// Check the object's elements are in fast case and writable.
__ ldr(elements, FieldMemOperand(object, JSObject::kElementsOffset));
__ ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kFixedArrayMapRootIndex);
__ cmp(scratch1, ip);
__ b(ne, &slow_case);
// Check that both indices are smis.
__ ldr(index1, MemOperand(sp, 1 * kPointerSize));
__ ldr(index2, MemOperand(sp, 0));
__ JumpIfNotBothSmi(index1, index2, &slow_case);
// Check that both indices are valid.
__ ldr(scratch1, FieldMemOperand(object, JSArray::kLengthOffset));
__ cmp(scratch1, index1);
__ cmp(scratch1, index2, hi);
__ b(ls, &slow_case);
// Bring the address of the elements into index1 and index2.
__ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
__ add(index1,
scratch1,
Operand(index1, LSL, kPointerSizeLog2 - kSmiTagSize));
__ add(index2,
scratch1,
Operand(index2, LSL, kPointerSizeLog2 - kSmiTagSize));
// Swap elements.
__ ldr(scratch1, MemOperand(index1, 0));
__ ldr(scratch2, MemOperand(index2, 0)));
__ str(scratch1, MemOperand(index2, 0));
__ str(scratch2, MemOperand(index1, 0));
Label new_space;
__ InNewSpace(elements, scratch1, eq, &new_space);
// Possible optimization: do a check that both values are Smis
// (or them and test against Smi mask.)
__ mov(scratch1, elements);
__ RecordWriteHelper(elements, index1, scratch2);
__ RecordWriteHelper(scratch1, index2, scratch2); // scratch1 holds elements.
__ bind(&done);
__ bind(&new_space);
// We are done. Drop elements from the stack, and return undefined.
__ Drop(3);
__ LoadRoot(r0, Heap::kUndefinedValueRootIndex);
__ jmp(&done);
__ bind(&slow_case);
__ CallRuntime(Runtime::kSwapElements, 3);
__ bind(&done);
context()->Plug(r0);
}