Commit 540ac179 authored by danno@chromium.org's avatar danno@chromium.org

MIPS: Port array literal changes on ARM.

Port r10085 (1ef7d5eb2).

This patch also contains a fix for StoreArrayLiteralElementStub::Generate which is only used from this code.

Original commit message:
Includes general array boilerplate copier and re-introduction FAST_ELEMENT optimizations in full-codegen.

BUG=
TEST=

Review URL: http://codereview.chromium.org/8743010
Patch from Daniel Kalmard <kalmard@homejinni.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10129 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 830f763b
...@@ -255,21 +255,61 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) { ...@@ -255,21 +255,61 @@ void FastNewBlockContextStub::Generate(MacroAssembler* masm) {
} }
void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { static void GenerateFastCloneShallowArrayCommon(
// Stack layout on entry: MacroAssembler* masm,
// [sp]: constant elements. int length,
// [sp + kPointerSize]: literal index. FastCloneShallowArrayStub::Mode mode,
// [sp + (2 * kPointerSize)]: literals array. Label* fail) {
// Registers on entry:
// a3: boilerplate literal array.
ASSERT(mode != FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS);
// All sizes here are multiples of kPointerSize. // All sizes here are multiples of kPointerSize.
int elements_size = 0; int elements_size = 0;
if (length_ > 0) { if (length > 0) {
elements_size = mode_ == CLONE_DOUBLE_ELEMENTS elements_size = mode == FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS
? FixedDoubleArray::SizeFor(length_) ? FixedDoubleArray::SizeFor(length)
: FixedArray::SizeFor(length_); : FixedArray::SizeFor(length);
} }
int size = JSArray::kSize + elements_size; int size = JSArray::kSize + elements_size;
// Allocate both the JS array and the elements array in one big
// allocation. This avoids multiple limit checks.
__ AllocateInNewSpace(size,
v0,
a1,
a2,
fail,
TAG_OBJECT);
// Copy the JS array part.
for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
if ((i != JSArray::kElementsOffset) || (length == 0)) {
__ lw(a1, FieldMemOperand(a3, i));
__ sw(a1, FieldMemOperand(v0, i));
}
}
if (length > 0) {
// Get hold of the elements array of the boilerplate and setup the
// elements pointer in the resulting object.
__ lw(a3, FieldMemOperand(a3, JSArray::kElementsOffset));
__ Addu(a2, v0, Operand(JSArray::kSize));
__ sw(a2, FieldMemOperand(v0, JSArray::kElementsOffset));
// Copy the elements array.
ASSERT((elements_size % kPointerSize) == 0);
__ CopyFields(a2, a3, a1.bit(), elements_size / kPointerSize);
}
}
void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
// Stack layout on entry:
//
// [sp]: constant elements.
// [sp + kPointerSize]: literal index.
// [sp + (2 * kPointerSize)]: literals array.
// Load boilerplate object into r3 and check if we need to create a // Load boilerplate object into r3 and check if we need to create a
// boilerplate. // boilerplate.
Label slow_case; Label slow_case;
...@@ -282,17 +322,42 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { ...@@ -282,17 +322,42 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
__ LoadRoot(t1, Heap::kUndefinedValueRootIndex); __ LoadRoot(t1, Heap::kUndefinedValueRootIndex);
__ Branch(&slow_case, eq, a3, Operand(t1)); __ Branch(&slow_case, eq, a3, Operand(t1));
FastCloneShallowArrayStub::Mode mode = mode_;
if (mode == CLONE_ANY_ELEMENTS) {
Label double_elements, check_fast_elements;
__ lw(v0, FieldMemOperand(a3, JSArray::kElementsOffset));
__ lw(v0, FieldMemOperand(v0, HeapObject::kMapOffset));
__ LoadRoot(t1, Heap::kFixedCOWArrayMapRootIndex);
__ Branch(&check_fast_elements, ne, v0, Operand(t1));
GenerateFastCloneShallowArrayCommon(masm, 0,
COPY_ON_WRITE_ELEMENTS, &slow_case);
// Return and remove the on-stack parameters.
__ DropAndRet(3);
__ bind(&check_fast_elements);
__ LoadRoot(t1, Heap::kFixedArrayMapRootIndex);
__ Branch(&double_elements, ne, v0, Operand(t1));
GenerateFastCloneShallowArrayCommon(masm, length_,
CLONE_ELEMENTS, &slow_case);
// Return and remove the on-stack parameters.
__ DropAndRet(3);
__ bind(&double_elements);
mode = CLONE_DOUBLE_ELEMENTS;
// Fall through to generate the code to handle double elements.
}
if (FLAG_debug_code) { if (FLAG_debug_code) {
const char* message; const char* message;
Heap::RootListIndex expected_map_index; Heap::RootListIndex expected_map_index;
if (mode_ == CLONE_ELEMENTS) { if (mode == CLONE_ELEMENTS) {
message = "Expected (writable) fixed array"; message = "Expected (writable) fixed array";
expected_map_index = Heap::kFixedArrayMapRootIndex; expected_map_index = Heap::kFixedArrayMapRootIndex;
} else if (mode_ == CLONE_DOUBLE_ELEMENTS) { } else if (mode == CLONE_DOUBLE_ELEMENTS) {
message = "Expected (writable) fixed double array"; message = "Expected (writable) fixed double array";
expected_map_index = Heap::kFixedDoubleArrayMapRootIndex; expected_map_index = Heap::kFixedDoubleArrayMapRootIndex;
} else { } else {
ASSERT(mode_ == COPY_ON_WRITE_ELEMENTS); ASSERT(mode == COPY_ON_WRITE_ELEMENTS);
message = "Expected copy-on-write fixed array"; message = "Expected copy-on-write fixed array";
expected_map_index = Heap::kFixedCOWArrayMapRootIndex; expected_map_index = Heap::kFixedCOWArrayMapRootIndex;
} }
...@@ -304,35 +369,7 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) { ...@@ -304,35 +369,7 @@ void FastCloneShallowArrayStub::Generate(MacroAssembler* masm) {
__ pop(a3); __ pop(a3);
} }
// Allocate both the JS array and the elements array in one big GenerateFastCloneShallowArrayCommon(masm, length_, mode, &slow_case);
// allocation. This avoids multiple limit checks.
// Return new object in v0.
__ AllocateInNewSpace(size,
v0,
a1,
a2,
&slow_case,
TAG_OBJECT);
// Copy the JS array part.
for (int i = 0; i < JSArray::kSize; i += kPointerSize) {
if ((i != JSArray::kElementsOffset) || (length_ == 0)) {
__ lw(a1, FieldMemOperand(a3, i));
__ sw(a1, FieldMemOperand(v0, i));
}
}
if (length_ > 0) {
// Get hold of the elements array of the boilerplate and setup the
// elements pointer in the resulting object.
__ lw(a3, FieldMemOperand(a3, JSArray::kElementsOffset));
__ Addu(a2, v0, Operand(JSArray::kSize));
__ sw(a2, FieldMemOperand(v0, JSArray::kElementsOffset));
// Copy the elements array.
ASSERT((elements_size % kPointerSize) == 0);
__ CopyFields(a2, a3, a1.bit(), elements_size / kPointerSize);
}
// Return and remove the on-stack parameters. // Return and remove the on-stack parameters.
__ Addu(sp, sp, Operand(3 * kPointerSize)); __ Addu(sp, sp, Operand(3 * kPointerSize));
...@@ -7474,7 +7511,8 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { ...@@ -7474,7 +7511,8 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
// Update the write barrier for the array store. // Update the write barrier for the array store.
__ RecordWrite(t1, t2, a0, kRAHasNotBeenSaved, kDontSaveFPRegs, __ RecordWrite(t1, t2, a0, kRAHasNotBeenSaved, kDontSaveFPRegs,
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ Ret(); __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
// Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or
// FAST_ELEMENTS, and value is Smi. // FAST_ELEMENTS, and value is Smi.
...@@ -7483,14 +7521,16 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { ...@@ -7483,14 +7521,16 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) {
__ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize); __ sll(t2, a3, kPointerSizeLog2 - kSmiTagSize);
__ Addu(t2, t1, t2); __ Addu(t2, t1, t2);
__ sw(a0, FieldMemOperand(t2, FixedArray::kHeaderSize)); __ sw(a0, FieldMemOperand(t2, FixedArray::kHeaderSize));
__ Ret(); __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
// Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
__ bind(&double_elements); __ bind(&double_elements);
__ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset)); __ lw(t1, FieldMemOperand(a1, JSObject::kElementsOffset));
__ StoreNumberToDoubleElements(a0, a3, a1, t1, t2, t3, t5, t6, __ StoreNumberToDoubleElements(a0, a3, a1, t1, t2, t3, t5, t6,
&slow_elements); &slow_elements);
__ Ret(); __ Ret(USE_DELAY_SLOT);
__ mov(v0, a0);
} }
......
...@@ -1546,6 +1546,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -1546,6 +1546,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
ASSERT_EQ(2, constant_elements->length()); ASSERT_EQ(2, constant_elements->length());
ElementsKind constant_elements_kind = ElementsKind constant_elements_kind =
static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value()); static_cast<ElementsKind>(Smi::cast(constant_elements->get(0))->value());
bool has_fast_elements = constant_elements_kind == FAST_ELEMENTS;
Handle<FixedArrayBase> constant_elements_values( Handle<FixedArrayBase> constant_elements_values(
FixedArrayBase::cast(constant_elements->get(1))); FixedArrayBase::cast(constant_elements->get(1)));
...@@ -1555,7 +1556,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -1555,7 +1556,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ li(a2, Operand(Smi::FromInt(expr->literal_index()))); __ li(a2, Operand(Smi::FromInt(expr->literal_index())));
__ li(a1, Operand(constant_elements)); __ li(a1, Operand(constant_elements));
__ Push(a3, a2, a1); __ Push(a3, a2, a1);
if (constant_elements_values->map() == if (has_fast_elements && constant_elements_values->map() ==
isolate()->heap()->fixed_cow_array_map()) { isolate()->heap()->fixed_cow_array_map()) {
FastCloneShallowArrayStub stub( FastCloneShallowArrayStub stub(
FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length); FastCloneShallowArrayStub::COPY_ON_WRITE_ELEMENTS, length);
...@@ -1570,10 +1571,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -1570,10 +1571,9 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
ASSERT(constant_elements_kind == FAST_ELEMENTS || ASSERT(constant_elements_kind == FAST_ELEMENTS ||
constant_elements_kind == FAST_SMI_ONLY_ELEMENTS || constant_elements_kind == FAST_SMI_ONLY_ELEMENTS ||
FLAG_smi_only_arrays); FLAG_smi_only_arrays);
FastCloneShallowArrayStub::Mode mode = FastCloneShallowArrayStub::Mode mode = has_fast_elements
constant_elements_kind == FAST_DOUBLE_ELEMENTS ? FastCloneShallowArrayStub::CLONE_ELEMENTS
? FastCloneShallowArrayStub::CLONE_DOUBLE_ELEMENTS : FastCloneShallowArrayStub::CLONE_ANY_ELEMENTS;
: FastCloneShallowArrayStub::CLONE_ELEMENTS;
FastCloneShallowArrayStub stub(mode, length); FastCloneShallowArrayStub stub(mode, length);
__ CallStub(&stub); __ CallStub(&stub);
} }
...@@ -1595,65 +1595,30 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { ...@@ -1595,65 +1595,30 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
__ push(v0); __ push(v0);
result_saved = true; result_saved = true;
} }
VisitForAccumulatorValue(subexpr); VisitForAccumulatorValue(subexpr);
__ lw(t6, MemOperand(sp)); // Copy of array literal. if (constant_elements_kind == FAST_ELEMENTS) {
__ lw(a1, FieldMemOperand(t6, JSObject::kElementsOffset));
__ lw(a2, FieldMemOperand(t6, JSObject::kMapOffset));
int offset = FixedArray::kHeaderSize + (i * kPointerSize); int offset = FixedArray::kHeaderSize + (i * kPointerSize);
__ lw(t2, MemOperand(sp)); // Copy of array literal.
Label element_done; __ lw(a1, FieldMemOperand(t2, JSObject::kElementsOffset));
Label double_elements;
Label smi_element;
Label slow_elements;
Label fast_elements;
__ CheckFastElements(a2, a3, &double_elements);
// FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS
__ JumpIfSmi(result_register(), &smi_element);
__ CheckFastSmiOnlyElements(a2, a3, &fast_elements);
// Store into the array literal requires a elements transition. Call into
// the runtime.
__ bind(&slow_elements);
__ push(t6); // Copy of array literal.
__ li(a1, Operand(Smi::FromInt(i)));
__ li(a2, Operand(Smi::FromInt(NONE))); // PropertyAttributes
StrictModeFlag strict_mode_flag = (language_mode() == CLASSIC_MODE)
? kNonStrictMode : kStrictMode;
__ li(a3, Operand(Smi::FromInt(strict_mode_flag))); // Strict mode.
__ Push(a1, result_register(), a2, a3);
__ CallRuntime(Runtime::kSetProperty, 5);
__ Branch(&element_done);
// Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS.
__ bind(&double_elements);
__ li(a3, Operand(Smi::FromInt(i)));
__ StoreNumberToDoubleElements(result_register(), a3, t6, a1, t0, t1, t5,
t3, &slow_elements);
__ Branch(&element_done);
// Array literal has ElementsKind of FAST_ELEMENTS and value is an object.
__ bind(&fast_elements);
__ sw(result_register(), FieldMemOperand(a1, offset)); __ sw(result_register(), FieldMemOperand(a1, offset));
// Update the write barrier for the array store. // Update the write barrier for the array store.
__ RecordWriteField(a1, offset, result_register(), a2,
__ RecordWriteField( kRAHasBeenSaved, kDontSaveFPRegs,
a1, offset, result_register(), a2, kRAHasBeenSaved, kDontSaveFPRegs, EMIT_REMEMBERED_SET, INLINE_SMI_CHECK);
EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); } else {
__ Branch(&element_done); __ lw(a1, MemOperand(sp)); // Copy of array literal.
__ lw(a2, FieldMemOperand(a1, JSObject::kMapOffset));
// Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or __ li(a3, Operand(Smi::FromInt(i)));
// FAST_ELEMENTS, and value is Smi. __ li(t0, Operand(Smi::FromInt(expr->literal_index())));
__ bind(&smi_element); __ mov(a0, result_register());
__ sw(result_register(), FieldMemOperand(a1, offset)); StoreArrayLiteralElementStub stub;
// Fall through __ CallStub(&stub);
}
__ bind(&element_done);
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
} }
if (result_saved) { if (result_saved) {
context()->PlugTOS(); context()->PlugTOS();
} else { } else {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment