From: danno@chromium.org Date: Wed, 8 Feb 2012 14:43:36 +0000 (+0000) Subject: MIPS: Handle single element array growth + transition in generic KeyedStoreIC X-Git-Tag: upstream/4.7.83~17416 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7639836eca6bcb943c3f283bba4fbabd80542448;p=platform%2Fupstream%2Fv8.git 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 . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10645 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- diff --git a/src/mips/builtins-mips.cc b/src/mips/builtins-mips.cc index d122e9a..9b899bd 100644 --- a/src/mips/builtins-mips.cc +++ b/src/mips/builtins-mips.cc @@ -116,7 +116,7 @@ static void AllocateEmptyJSArray(MacroAssembler* masm, 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 @@ static void AllocateJSArray(MacroAssembler* masm, 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( diff --git a/src/mips/ic-mips.cc b/src/mips/ic-mips.cc index 3489936..c3cdb4c 100644 --- a/src/mips/ic-mips.cc +++ b/src/mips/ic-mips.cc @@ -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 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 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 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, __ 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 @@ void KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 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); } diff --git a/src/mips/macro-assembler-mips.cc b/src/mips/macro-assembler-mips.cc index f559d71..c4908ac 100644 --- a/src/mips/macro-assembler-mips.cc +++ b/src/mips/macro-assembler-mips.cc @@ -4279,26 +4279,41 @@ void MacroAssembler::LoadContext(Register dst, int context_chain_length) { } -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); } diff --git a/src/mips/macro-assembler-mips.h b/src/mips/macro-assembler-mips.h index 24dfceb..f7d1c12 100644 --- a/src/mips/macro-assembler-mips.h +++ b/src/mips/macro-assembler-mips.h @@ -772,10 +772,21 @@ class MacroAssembler: public Assembler { 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);