X64: Add inline SwapElements to fundamental code generator on x64 platform.

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@6995 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
whesse@chromium.org 2011-03-01 14:29:27 +00:00
parent 7b0f5d4110
commit 505976cd53

View File

@ -2952,7 +2952,73 @@ 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 = rax;
Register index_1 = rbx;
Register index_2 = rcx;
Register elements = rdi;
Register temp = rdx;
__ movq(object, Operand(rsp, 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.
__ CmpObjectType(object, FIRST_JS_OBJECT_TYPE, temp);
__ j(below, &slow_case);
__ testb(FieldOperand(temp, Map::kBitFieldOffset),
Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
__ j(not_zero, &slow_case);
// Check the object's elements are in fast case and writable.
__ movq(elements, FieldOperand(object, JSObject::kElementsOffset));
__ CompareRoot(FieldOperand(elements, HeapObject::kMapOffset),
Heap::kFixedArrayMapRootIndex);
__ j(not_equal, &slow_case);
// Check that both indices are smis.
__ movq(index_1, Operand(rsp, 1 * kPointerSize));
__ movq(index_2, Operand(rsp, 0 * kPointerSize));
__ JumpIfNotBothSmi(index_1, index_2, &slow_case);
// Check that both indices are valid.
// The JSArray length field is a smi since the array is in fast case mode.
__ movq(temp, FieldOperand(object, JSArray::kLengthOffset));
__ SmiCompare(temp, index_1);
__ j(below_equal, &slow_case);
__ SmiCompare(temp, index_2);
__ j(below_equal, &slow_case);
__ SmiToInteger32(index_1, index_1);
__ SmiToInteger32(index_2, index_2);
// Bring addresses into index1 and index2.
__ lea(index_1, FieldOperand(elements, index_1, times_pointer_size,
FixedArray::kHeaderSize));
__ lea(index_2, FieldOperand(elements, index_2, times_pointer_size,
FixedArray::kHeaderSize));
// Swap elements. Use object and temp as scratch registers.
__ movq(object, Operand(index_1, 0));
__ movq(temp, Operand(index_2, 0));
__ movq(Operand(index_2, 0), object);
__ movq(Operand(index_1, 0), temp);
Label new_space;
__ InNewSpace(elements, temp, equal, &new_space);
__ movq(object, elements);
__ RecordWriteHelper(object, index_1, temp);
__ RecordWriteHelper(elements, index_2, temp);
__ bind(&new_space);
// We are done. Drop elements from the stack, and return undefined.
__ addq(rsp, Immediate(3 * kPointerSize));
__ LoadRoot(rax, Heap::kUndefinedValueRootIndex);
__ jmp(&done);
__ bind(&slow_case);
__ CallRuntime(Runtime::kSwapElements, 3);
__ bind(&done);
context()->Plug(rax);
}