Revision: 10645
Author: [email protected]
Date: Wed Feb 8 06:43:36 2012
Log: MIPS: Handle single element array growth + transition in generic
KeyedStoreIC
Port r10583 (505679e).
BUG=
TEST=
Review URL: https://chromiumcodereview.appspot.com/9316061
Patch from Daniel Kalmar <[email protected]>.
http://code.google.com/p/v8/source/detail?r=10645
Modified:
/branches/bleeding_edge/src/mips/builtins-mips.cc
/branches/bleeding_edge/src/mips/ic-mips.cc
/branches/bleeding_edge/src/mips/macro-assembler-mips.cc
/branches/bleeding_edge/src/mips/macro-assembler-mips.h
=======================================
--- /branches/bleeding_edge/src/mips/builtins-mips.cc Mon Jan 30 02:58:22
2012
+++ /branches/bleeding_edge/src/mips/builtins-mips.cc Wed Feb 8 06:43:36
2012
@@ -116,7 +116,7 @@
Label* gc_required) {
const int initial_capacity = JSArray::kPreallocatedArrayElements;
STATIC_ASSERT(initial_capacity >= 0);
- __ LoadGlobalInitialConstructedArrayMap(array_function, scratch2,
scratch1);
+ __ LoadInitialArrayMap(array_function, scratch2, scratch1);
// Allocate the JSArray object together with space for a fixed array
with the
// requested elements.
@@ -212,8 +212,7 @@
bool fill_with_hole,
Label* gc_required) {
// Load the initial map from the array function.
- __ LoadGlobalInitialConstructedArrayMap(array_function, scratch2,
- elements_array_storage);
+ __ LoadInitialArrayMap(array_function, scratch2, elements_array_storage);
if (FLAG_debug_code) { // Assert that array size is not zero.
__ Assert(
=======================================
--- /branches/bleeding_edge/src/mips/ic-mips.cc Mon Jan 23 08:18:10 2012
+++ /branches/bleeding_edge/src/mips/ic-mips.cc Wed Feb 8 06:43:36 2012
@@ -1,4 +1,4 @@
-// Copyright 2011 the V8 project authors. All rights reserved.
+// Copyright 2012 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@@ -1198,14 +1198,16 @@
Label slow, array, extra, check_if_double_array;
Label fast_object_with_map_check, fast_object_without_map_check;
Label fast_double_with_map_check, fast_double_without_map_check;
+ Label transition_smi_elements, finish_object_store, non_double_value;
+ Label transition_double_elements;
// Register usage.
Register value = a0;
Register key = a1;
Register receiver = a2;
- Register elements = a3; // Elements array of the receiver.
+ Register receiver_map = a3;
Register elements_map = t2;
- Register receiver_map = t3;
+ Register elements = t3; // Elements array of the receiver.
// t0 and t1 are used as general scratch registers.
// Check that the key is a smi.
@@ -1298,9 +1300,11 @@
__ mov(v0, value);
__ bind(&non_smi_value);
- // Escape to slow case when writing non-smi into smi-only array.
- __ CheckFastObjectElements(receiver_map, scratch_value, &slow);
+ // Escape to elements kind transition case.
+ __ CheckFastObjectElements(receiver_map, scratch_value,
+ &transition_smi_elements);
// Fast elements array, store the value to the elements backing store.
+ __ bind(&finish_object_store);
__ Addu(address, elements, Operand(FixedArray::kHeaderSize -
kHeapObjectTag));
__ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize);
__ Addu(address, address, scratch_value);
@@ -1326,13 +1330,57 @@
key,
receiver,
elements,
+ a3,
t0,
t1,
t2,
- t3,
- &slow);
+ &transition_double_elements);
__ Ret(USE_DELAY_SLOT);
__ mov(v0, value);
+
+ __ bind(&transition_smi_elements);
+ // Transition the array appropriately depending on the value type.
+ __ lw(t0, FieldMemOperand(value, HeapObject::kMapOffset));
+ __ LoadRoot(at, Heap::kHeapNumberMapRootIndex);
+ __ Branch(&non_double_value, ne, t0, Operand(at));
+
+ // Value is a double. Transition FAST_SMI_ONLY_ELEMENTS ->
+ // FAST_DOUBLE_ELEMENTS and complete the store.
+ __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
+ FAST_DOUBLE_ELEMENTS,
+ receiver_map,
+ t0,
+ &slow);
+ ASSERT(receiver_map.is(a3)); // Transition code expects map in a3
+ ElementsTransitionGenerator::GenerateSmiOnlyToDouble(masm, &slow);
+ __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+ __ jmp(&fast_double_without_map_check);
+
+ __ bind(&non_double_value);
+ // Value is not a double, FAST_SMI_ONLY_ELEMENTS -> FAST_ELEMENTS
+ __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
+ FAST_ELEMENTS,
+ receiver_map,
+ t0,
+ &slow);
+ ASSERT(receiver_map.is(a3)); // Transition code expects map in a3
+ ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm);
+ __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+ __ jmp(&finish_object_store);
+
+ __ bind(&transition_double_elements);
+ // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a
+ // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS
and
+ // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS
+ __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS,
+ FAST_ELEMENTS,
+ receiver_map,
+ t0,
+ &slow);
+ ASSERT(receiver_map.is(a3)); // Transition code expects map in a3
+ ElementsTransitionGenerator::GenerateDoubleToObject(masm, &slow);
+ __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
+ __ jmp(&finish_object_store);
}
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Wed Feb 8
06:41:10 2012
+++ /branches/bleeding_edge/src/mips/macro-assembler-mips.cc Wed Feb 8
06:43:36 2012
@@ -4279,26 +4279,41 @@
}
-void MacroAssembler::LoadGlobalInitialConstructedArrayMap(
+void MacroAssembler::LoadTransitionedArrayMapConditional(
+ ElementsKind expected_kind,
+ ElementsKind transitioned_kind,
+ Register map_in_out,
+ Register scratch,
+ Label* no_map_match) {
+ // Load the global or builtins object from the current context.
+ lw(scratch, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX)));
+ lw(scratch, FieldMemOperand(scratch,
GlobalObject::kGlobalContextOffset));
+
+ // Check that the function's map is the same as the expected cached map.
+ int expected_index =
+ Context::GetContextMapIndexFromElementsKind(expected_kind);
+ lw(at, MemOperand(scratch, Context::SlotOffset(expected_index)));
+ Branch(no_map_match, ne, map_in_out, Operand(at));
+
+ // Use the transitioned cached map.
+ int trans_index =
+ Context::GetContextMapIndexFromElementsKind(transitioned_kind);
+ lw(map_in_out, MemOperand(scratch, Context::SlotOffset(trans_index)));
+}
+
+
+void MacroAssembler::LoadInitialArrayMap(
Register function_in, Register scratch, Register map_out) {
ASSERT(!function_in.is(map_out));
Label done;
lw(map_out, FieldMemOperand(function_in,
JSFunction::kPrototypeOrInitialMapOffset));
if (!FLAG_smi_only_arrays) {
- // Load the global or builtins object from the current context.
- lw(scratch, MemOperand(cp,
Context::SlotOffset(Context::GLOBAL_INDEX)));
- lw(scratch, FieldMemOperand(scratch,
GlobalObject::kGlobalContextOffset));
-
- // Check that the function's map is same as the cached map.
- lw(at, MemOperand(
- scratch, Context::SlotOffset(Context::SMI_JS_ARRAY_MAP_INDEX)));
- Branch(&done, ne, map_out, Operand(at));
-
- // Use the cached transitioned map.
- lw(map_out,
- MemOperand(scratch,
-
Context::SlotOffset(Context::OBJECT_JS_ARRAY_MAP_INDEX)));
+ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS,
+ FAST_ELEMENTS,
+ map_out,
+ scratch,
+ &done);
}
bind(&done);
}
=======================================
--- /branches/bleeding_edge/src/mips/macro-assembler-mips.h Tue Jan 31
04:45:27 2012
+++ /branches/bleeding_edge/src/mips/macro-assembler-mips.h Wed Feb 8
06:43:36 2012
@@ -772,10 +772,21 @@
void LoadContext(Register dst, int context_chain_length);
- // Load the initial map for new Arrays of a given type.
- void LoadGlobalInitialConstructedArrayMap(Register function_in,
- Register scratch,
- Register map_out);
+ // Conditionally load the cached Array transitioned map of type
+ // transitioned_kind from the global context if the map in register
+ // map_in_out is the cached Array map in the global context of
+ // expected_kind.
+ void LoadTransitionedArrayMapConditional(
+ ElementsKind expected_kind,
+ ElementsKind transitioned_kind,
+ Register map_in_out,
+ Register scratch,
+ Label* no_map_match);
+
+ // Load the initial map for new Arrays from a JSFunction.
+ void LoadInitialArrayMap(Register function_in,
+ Register scratch,
+ Register map_out);
void LoadGlobalFunction(int index, Register function);
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev