Revision: 9416
Author: [email protected]
Date: Fri Sep 23 07:19:04 2011
Log: Porting r9392 to x64 (smi-only arrays).
Review URL: http://codereview.chromium.org/7992003
http://code.google.com/p/v8/source/detail?r=9416
Modified:
/branches/bleeding_edge/src/ia32/stub-cache-ia32.cc
/branches/bleeding_edge/src/x64/full-codegen-x64.cc
/branches/bleeding_edge/src/x64/ic-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.cc
/branches/bleeding_edge/src/x64/macro-assembler-x64.h
/branches/bleeding_edge/src/x64/stub-cache-x64.cc
/branches/bleeding_edge/test/mjsunit/element-kind.js
=======================================
--- /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Thu Sep 22 04:30:04
2011
+++ /branches/bleeding_edge/src/ia32/stub-cache-ia32.cc Fri Sep 23 07:19:04
2011
@@ -3936,7 +3936,7 @@
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 @@
} 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,
=======================================
--- /branches/bleeding_edge/src/x64/full-codegen-x64.cc Wed Sep 21 07:46:54
2011
+++ /branches/bleeding_edge/src/x64/full-codegen-x64.cc Fri Sep 23 07:19:04
2011
@@ -1455,13 +1455,25 @@
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);
}
=======================================
--- /branches/bleeding_edge/src/x64/ic-x64.cc Mon Sep 19 11:36:47 2011
+++ /branches/bleeding_edge/src/x64/ic-x64.cc Fri Sep 23 07:19:04 2011
@@ -692,14 +692,22 @@
// 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));
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Thu Sep 22
04:30:04 2011
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.cc Fri Sep 23
07:19:04 2011
@@ -2654,6 +2654,30 @@
Immediate(Map::kMaximumBitField2FastElementValue));
j(above, fail, distance);
}
+
+
+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,
=======================================
--- /branches/bleeding_edge/src/x64/macro-assembler-x64.h Tue Sep 20
06:32:27 2011
+++ /branches/bleeding_edge/src/x64/macro-assembler-x64.h Fri Sep 23
07:19:04 2011
@@ -847,6 +847,18 @@
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)
=======================================
--- /branches/bleeding_edge/src/x64/stub-cache-x64.cc Thu Sep 22 04:30:04
2011
+++ /branches/bleeding_edge/src/x64/stub-cache-x64.cc Fri Sep 23 07:19:04
2011
@@ -1442,34 +1442,59 @@
__ 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);
if (!FLAG_inline_new) {
__ 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());
@@ -1494,10 +1519,9 @@
// 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 @@
// 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 @@
// 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);
=======================================
--- /branches/bleeding_edge/test/mjsunit/element-kind.js Thu Sep 22
04:30:04 2011
+++ /branches/bleeding_edge/test/mjsunit/element-kind.js Fri Sep 23
07:19:04 2011
@@ -47,7 +47,7 @@
}
// 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 @@
// 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 @@
}
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));
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev