Commit 65b1ea22 authored by yangguo@chromium.org's avatar yangguo@chromium.org

Porting r9392 to x64 (smi-only arrays).

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9416 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 2e40bc24
......@@ -3936,7 +3936,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
__ JumpIfNotSmi(eax, &miss_force_generic);
// ecx is a smi, don't use times_half_pointer_size istead of
// ecx is a smi, use times_half_pointer_size instead of
// times_pointer_size
__ mov(FieldOperand(edi,
ecx,
......@@ -3945,7 +3945,7 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
} else {
ASSERT(elements_kind == FAST_ELEMENTS);
// Do the store and update the write barrier.
// ecx is a smi, don't use times_half_pointer_size istead of
// ecx is a smi, use times_half_pointer_size instead of
// times_pointer_size
__ lea(ecx, FieldOperand(edi,
ecx,
......
......@@ -1455,13 +1455,25 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForAccumulatorValue(subexpr);
// Store the subexpression value in the array's elements.
__ movq(rbx, Operand(rsp, 0)); // Copy of array literal.
__ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset));
__ movq(r8, Operand(rsp, 0)); // Copy of array literal.
__ movq(rbx, FieldOperand(r8, JSObject::kElementsOffset));
int offset = FixedArray::kHeaderSize + (i * kPointerSize);
__ movq(FieldOperand(rbx, offset), result_register());
Label no_map_change;
__ JumpIfSmi(result_register(), &no_map_change);
// Update the write barrier for the array store.
__ RecordWriteField(rbx, offset, result_register(), rcx, kDontSaveFPRegs);
__ RecordWriteField(rbx, offset, result_register(), rcx,
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
if (FLAG_smi_only_arrays) {
__ movq(rdi, FieldOperand(rbx, JSObject::kMapOffset));
__ CheckFastSmiOnlyElements(rdi, &no_map_change, Label::kNear);
__ push(r8);
__ CallRuntime(Runtime::kNonSmiElementStored, 1);
}
__ bind(&no_map_change);
PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS);
}
......
......@@ -692,14 +692,22 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm,
// rax: value
// rbx: receiver's elements array (a FixedArray)
// rcx: index
Label non_smi_value;
__ JumpIfNotSmi(rax, &non_smi_value);
// It's irrelevant whether array is smi-only or not when writing a smi.
__ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
rax);
__ JumpIfNotSmi(rax, &non_smi_value, Label::kNear);
__ ret(0);
__ bind(&non_smi_value);
// Slow case that needs to retain rcx for use by RecordWrite.
// Update write barrier for the elements array address.
if (FLAG_smi_only_arrays) {
// Writing a non-smi, check whether array allows non-smi elements.
__ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
__ CheckFastObjectElements(rdi, &slow, Label::kNear);
}
__ movq(FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize),
rax);
__ movq(rdx, rax);
__ lea(rcx,
FieldOperand(rbx, rcx, times_pointer_size, FixedArray::kHeaderSize));
......
......@@ -2656,6 +2656,30 @@ void MacroAssembler::CheckFastElements(Register map,
}
void MacroAssembler::CheckFastObjectElements(Register map,
Label* fail,
Label::Distance distance) {
STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
STATIC_ASSERT(FAST_ELEMENTS == 1);
cmpb(FieldOperand(map, Map::kBitField2Offset),
Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue));
j(below_equal, fail, distance);
cmpb(FieldOperand(map, Map::kBitField2Offset),
Immediate(Map::kMaximumBitField2FastElementValue));
j(above, fail, distance);
}
void MacroAssembler::CheckFastSmiOnlyElements(Register map,
Label* fail,
Label::Distance distance) {
STATIC_ASSERT(FAST_SMI_ONLY_ELEMENTS == 0);
cmpb(FieldOperand(map, Map::kBitField2Offset),
Immediate(Map::kMaximumBitField2FastSmiOnlyElementValue));
j(above, fail, distance);
}
void MacroAssembler::CheckMap(Register obj,
Handle<Map> map,
Label* fail,
......
......@@ -847,6 +847,18 @@ class MacroAssembler: public Assembler {
Label* fail,
Label::Distance distance = Label::kFar);
// Check if a map for a JSObject indicates that the object can have both smi
// and HeapObject elements. Jump to the specified label if it does not.
void CheckFastObjectElements(Register map,
Label* fail,
Label::Distance distance = Label::kFar);
// Check if a map for a JSObject indicates that the object has fast smi only
// elements. Jump to the specified label if it does not.
void CheckFastSmiOnlyElements(Register map,
Label* fail,
Label::Distance distance = Label::kFar);
// Check if the map of an object is equal to a specified map and
// branch to label if not. Skip the smi check if not required
// (object is known to be a heap object)
......
......@@ -1442,28 +1442,42 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ cmpl(rax, rcx);
__ j(greater, &attempt_to_grow_elements);
// Check if value is a smi.
__ movq(rcx, Operand(rsp, argc * kPointerSize));
__ JumpIfNotSmi(rcx, &with_write_barrier);
// Save new length.
__ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
// Push the element.
__ movq(rcx, Operand(rsp, argc * kPointerSize));
__ lea(rdx, FieldOperand(rbx,
rax, times_pointer_size,
FixedArray::kHeaderSize - argc * kPointerSize));
__ movq(Operand(rdx, 0), rcx);
// Check if value is a smi.
__ Integer32ToSmi(rax, rax); // Return new length as smi.
__ JumpIfNotSmi(rcx, &with_write_barrier);
__ ret((argc + 1) * kPointerSize);
__ bind(&with_write_barrier);
if (FLAG_smi_only_arrays) {
__ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
__ CheckFastObjectElements(rdi, &call_builtin);
}
// Save new length.
__ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
// Push the element.
__ lea(rdx, FieldOperand(rbx,
rax, times_pointer_size,
FixedArray::kHeaderSize - argc * kPointerSize));
__ movq(Operand(rdx, 0), rcx);
__ RecordWrite(
rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
__ Integer32ToSmi(rax, rax); // Return new length as smi.
__ ret((argc + 1) * kPointerSize);
__ bind(&attempt_to_grow_elements);
......@@ -1471,6 +1485,17 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
__ jmp(&call_builtin);
}
__ movq(rdi, Operand(rsp, argc * kPointerSize));
if (FLAG_smi_only_arrays) {
// Growing elements that are SMI-only requires special handling in case
// the new element is non-Smi. For now, delegate to the builtin.
Label no_fast_elements_check;
__ JumpIfSmi(rdi, &no_fast_elements_check);
__ movq(rsi, FieldOperand(rdx, HeapObject::kMapOffset));
__ CheckFastObjectElements(rsi, &call_builtin, Label::kFar);
__ bind(&no_fast_elements_check);
}
ExternalReference new_space_allocation_top =
ExternalReference::new_space_allocation_top_address(isolate());
ExternalReference new_space_allocation_limit =
......@@ -1494,10 +1519,9 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
// We fit and could grow elements.
__ Store(new_space_allocation_top, rcx);
__ movq(rcx, Operand(rsp, argc * kPointerSize));
// Push the argument...
__ movq(Operand(rdx, 0), rcx);
__ movq(Operand(rdx, 0), rdi);
// ... and fill the rest with holes.
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
for (int i = 1; i < kAllocationDelta; i++) {
......@@ -1509,7 +1533,7 @@ MaybeObject* CallStubCompiler::CompileArrayPushCall(Object* object,
// tell the incremental marker to rescan the object that we just grew. We
// don't need to worry about the holes because they are in old space and
// already marked black.
__ RecordWrite(rbx, rdx, rcx, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
__ RecordWrite(rbx, rdx, rdi, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
// Restore receiver to rdx as finish sequence assumes it's here.
__ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
......@@ -3699,13 +3723,19 @@ void KeyedStoreStubCompiler::GenerateStoreFastElement(
// Do the store and update the write barrier.
__ SmiToInteger32(rcx, rcx);
__ lea(rcx,
FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
__ movq(Operand(rcx, 0), rax);
// Make sure to preserve the value in register rax.
__ movq(rdx, rax);
ASSERT(elements_kind == FAST_ELEMENTS);
__ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs);
if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
__ JumpIfNotSmi(rax, &miss_force_generic);
__ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
rax);
} else {
ASSERT(elements_kind == FAST_ELEMENTS);
__ lea(rcx,
FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
__ movq(Operand(rcx, 0), rax);
// Make sure to preserve the value in register rax.
__ movq(rdx, rax);
__ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs);
}
// Done.
__ ret(0);
......
......@@ -47,7 +47,7 @@ var element_kind = {
}
// We expect an object to only be of one element kind.
function assertKind(expected, obj){
function assertKind(expected, obj) {
if (support_smi_only_arrays) {
assertEquals(expected == element_kind.fast_smi_only_elements,
%HasFastSmiOnlyElements(obj));
......@@ -100,7 +100,7 @@ assertKind(element_kind.fast_smi_only_elements, too);
// Make sure the element kind transitions from smionly when a non-smi is stored.
var you = new Array();
assertKind(element_kind.fast_smi_only_elements, you);
for(i = 0; i < 1337; i++) {
for (var i = 0; i < 1337; i++) {
var val = i;
if (i == 1336) {
assertKind(element_kind.fast_smi_only_elements, you);
......@@ -110,10 +110,11 @@ for(i = 0; i < 1337; i++) {
}
assertKind(element_kind.fast_elements, you);
assertKind(element_kind.dictionary_elements, new Array(0xC0C0A));
// fast_double_elements not yet available
assertKind(element_kind.dictionary_elements, new Array(0xDECAF));
var fast_double_array = new Array(0xDECAF);
for (var i = 0; i < 0xDECAF; i++) fast_double_array[i] = i / 2;
assertKind(element_kind.fast_double_elements, fast_double_array);
assertKind(element_kind.external_byte_elements, new Int8Array(9001));
assertKind(element_kind.external_unsigned_byte_elements, new Uint8Array(007));
......
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