From 8bdb3ffbcafbc389dcdeda92b14d315198d9a493 Mon Sep 17 00:00:00 2001 From: "danno@chromium.org" Date: Fri, 11 Nov 2011 14:49:16 +0000 Subject: [PATCH] ARM: Implement runtime function for array literal transitions. Also simplify ia32 and x64 handing of the trace_elements_transition flag. R=jkummerow@chromium.org BUG=none TEST=array-literal-transitions.js Review URL: http://codereview.chromium.org/8539011 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@9979 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/code-stubs-arm.cc | 60 +++++++++++++++++++++++++++++ src/arm/full-codegen-arm.cc | 54 +++----------------------- src/builtins.cc | 6 ++- src/ia32/code-stubs-ia32.cc | 92 +++++++++++++++++++++------------------------ src/objects-inl.h | 12 ++++++ src/objects.cc | 3 ++ src/objects.h | 2 + src/x64/code-stubs-x64.cc | 86 ++++++++++++++++++++---------------------- 8 files changed, 169 insertions(+), 146 deletions(-) diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc index bd3d2e6..b37855b 100644 --- a/src/arm/code-stubs-arm.cc +++ b/src/arm/code-stubs-arm.cc @@ -6888,6 +6888,8 @@ struct AheadOfTimeWriteBarrierStubList kAheadOfTime[] = { // ElementsTransitionGenerator::GenerateDoubleToObject { r6, r2, r0, EMIT_REMEMBERED_SET }, { r2, r6, r9, EMIT_REMEMBERED_SET }, + // StoreArrayLiteralElementStub::Generate + { r5, r0, r6, EMIT_REMEMBERED_SET }, // Null termination. { no_reg, no_reg, no_reg, EMIT_REMEMBERED_SET} }; @@ -7124,6 +7126,64 @@ void RecordWriteStub::CheckNeedsToInformIncrementalMarker( // Fall through when we need to inform the incremental marker. } + +void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { + // ----------- S t a t e ------------- + // -- r0 : element value to store + // -- r1 : array literal + // -- r2 : map of array literal + // -- r3 : element index as smi + // -- r4 : array literal index in function as smi + // ----------------------------------- + + Label element_done; + Label double_elements; + Label smi_element; + Label slow_elements; + Label fast_elements; + + __ CheckFastElements(r2, r5, &double_elements); + // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS + __ JumpIfSmi(r0, &smi_element); + __ CheckFastSmiOnlyElements(r2, r5, &fast_elements); + + // Store into the array literal requires a elements transition. Call into + // the runtime. + __ bind(&slow_elements); + // call. + __ Push(r1, r3, r0); + __ ldr(r5, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); + __ ldr(r5, FieldMemOperand(r5, JSFunction::kLiteralsOffset)); + __ Push(r5, r4); + __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); + + // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. + __ bind(&fast_elements); + __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); + __ add(r6, r5, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); + __ add(r6, r6, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); + __ str(r0, MemOperand(r6, 0)); + // Update the write barrier for the array store. + __ RecordWrite(r5, r6, r0, kLRHasNotBeenSaved, kDontSaveFPRegs, + EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); + __ Ret(); + + // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or + // FAST_ELEMENTS, and value is Smi. + __ bind(&smi_element); + __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); + __ add(r6, r5, Operand(r3, LSL, kPointerSizeLog2 - kSmiTagSize)); + __ str(r0, FieldMemOperand(r6, FixedArray::kHeaderSize)); + __ Ret(); + + // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. + __ bind(&double_elements); + __ ldr(r5, FieldMemOperand(r1, JSObject::kElementsOffset)); + __ StoreNumberToDoubleElements(r0, r3, r1, r5, r6, r7, r9, r10, + &slow_elements); + __ Ret(); +} + #undef __ } } // namespace v8::internal diff --git a/src/arm/full-codegen-arm.cc b/src/arm/full-codegen-arm.cc index 8decb19..e8a2cb0 100644 --- a/src/arm/full-codegen-arm.cc +++ b/src/arm/full-codegen-arm.cc @@ -1580,56 +1580,12 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) { } VisitForAccumulatorValue(subexpr); - __ ldr(r6, MemOperand(sp)); // Copy of array literal. - __ ldr(r1, FieldMemOperand(r6, JSObject::kElementsOffset)); - __ ldr(r2, FieldMemOperand(r6, JSObject::kMapOffset)); - int offset = FixedArray::kHeaderSize + (i * kPointerSize); - - Label element_done; - Label double_elements; - Label smi_element; - Label slow_elements; - Label fast_elements; - __ CheckFastElements(r2, r3, &double_elements); - - // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS - __ JumpIfSmi(result_register(), &smi_element); - __ CheckFastSmiOnlyElements(r2, r3, &fast_elements); - - // Store into the array literal requires a elements transition. Call into - // the runtime. - __ bind(&slow_elements); - __ push(r6); // Copy of array literal. - __ mov(r1, Operand(Smi::FromInt(i))); - __ mov(r2, Operand(Smi::FromInt(NONE))); // PropertyAttributes - __ mov(r3, Operand(Smi::FromInt(strict_mode_flag()))); // Strict mode. - __ Push(r1, result_register(), r2, r3); - __ CallRuntime(Runtime::kSetProperty, 5); - __ b(&element_done); - - // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. - __ bind(&double_elements); + __ ldr(r1, MemOperand(sp)); // Copy of array literal. + __ ldr(r2, FieldMemOperand(r1, JSObject::kMapOffset)); __ mov(r3, Operand(Smi::FromInt(i))); - __ StoreNumberToDoubleElements(result_register(), r3, r6, r1, r4, r5, r9, - r7, &slow_elements); - __ b(&element_done); - - // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. - __ bind(&fast_elements); - __ str(result_register(), FieldMemOperand(r1, offset)); - // Update the write barrier for the array store. - __ RecordWriteField( - r1, offset, result_register(), r2, kLRHasBeenSaved, kDontSaveFPRegs, - EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); - __ b(&element_done); - - // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or - // FAST_ELEMENTS, and value is Smi. - __ bind(&smi_element); - __ str(result_register(), FieldMemOperand(r1, offset)); - // Fall through - - __ bind(&element_done); + __ mov(r4, Operand(Smi::FromInt(expr->literal_index()))); + StoreArrayLiteralElementStub stub; + __ CallStub(&stub); PrepareForBailoutForId(expr->GetIdForElement(i), NO_REGISTERS); } diff --git a/src/builtins.cc b/src/builtins.cc index 49053db..e542e4d 100644 --- a/src/builtins.cc +++ b/src/builtins.cc @@ -775,7 +775,8 @@ BUILTIN(ArraySlice) { // Set the ElementsKind. ElementsKind elements_kind = JSObject::cast(receiver)->GetElementsKind(); - if (result_array->GetElementsKind() != elements_kind) { + if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(), + elements_kind)) { MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind); if (maybe->IsFailure()) return maybe; } @@ -875,7 +876,8 @@ BUILTIN(ArraySplice) { // Set the ElementsKind. ElementsKind elements_kind = array->GetElementsKind(); - if (result_array->GetElementsKind() != elements_kind) { + if (IsMoreGeneralElementsKindTransition(result_array->GetElementsKind(), + elements_kind)) { MaybeObject* maybe = result_array->TransitionElementsKind(elements_kind); if (maybe->IsFailure()) return maybe; } diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc index 4d69bf8..23bea4f 100644 --- a/src/ia32/code-stubs-ia32.cc +++ b/src/ia32/code-stubs-ia32.cc @@ -7046,16 +7046,14 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { Label slow_elements_from_double; Label fast_elements; - if (!FLAG_trace_elements_transitions) { - __ CheckFastElements(edi, &double_elements); + __ CheckFastElements(edi, &double_elements); - // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS - __ JumpIfSmi(eax, &smi_element); - __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear); + // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS + __ JumpIfSmi(eax, &smi_element); + __ CheckFastSmiOnlyElements(edi, &fast_elements, Label::kNear); - // Store into the array literal requires a elements transition. Call into - // the runtime. - } + // Store into the array literal requires a elements transition. Call into + // the runtime. __ bind(&slow_elements); __ pop(edi); // Pop return address and remember to put back later for tail @@ -7070,49 +7068,45 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { // place. __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); - if (!FLAG_trace_elements_transitions) { - // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. - __ bind(&double_elements); + __ bind(&slow_elements_from_double); + __ pop(edx); + __ jmp(&slow_elements); + + // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. + __ bind(&fast_elements); + __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); + __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size, + FixedArrayBase::kHeaderSize)); + __ mov(Operand(ecx, 0), eax); + // Update the write barrier for the array store. + __ RecordWrite(ebx, ecx, eax, + kDontSaveFPRegs, + EMIT_REMEMBERED_SET, + OMIT_SMI_CHECK); + __ ret(0); - __ push(edx); - __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset)); - __ StoreNumberToDoubleElements(eax, - edx, - ecx, - edi, - xmm0, - &slow_elements_from_double, - false); - __ pop(edx); - __ jmp(&element_done); + // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or + // FAST_ELEMENTS, and value is Smi. + __ bind(&smi_element); + __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); + __ mov(FieldOperand(ebx, ecx, times_half_pointer_size, + FixedArrayBase::kHeaderSize), eax); + __ ret(0); - __ bind(&slow_elements_from_double); - __ pop(edx); - __ jmp(&slow_elements); - - // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. - __ bind(&fast_elements); - __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); - __ lea(ecx, FieldOperand(ebx, ecx, times_half_pointer_size, - FixedArrayBase::kHeaderSize)); - __ mov(Operand(ecx, 0), eax); - // Update the write barrier for the array store. - __ RecordWrite(ebx, ecx, eax, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - __ jmp(&element_done); - - // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or - // FAST_ELEMENTS, and value is Smi. - __ bind(&smi_element); - __ mov(ebx, FieldOperand(ebx, JSObject::kElementsOffset)); - __ mov(FieldOperand(ebx, ecx, times_half_pointer_size, - FixedArrayBase::kHeaderSize), eax); - // Fall through - __ bind(&element_done); - __ ret(0); - } + // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. + __ bind(&double_elements); + + __ push(edx); + __ mov(edx, FieldOperand(ebx, JSObject::kElementsOffset)); + __ StoreNumberToDoubleElements(eax, + edx, + ecx, + edi, + xmm0, + &slow_elements_from_double, + false); + __ pop(edx); + __ ret(0); } #undef __ diff --git a/src/objects-inl.h b/src/objects-inl.h index 1e5a4da..24501c8 100644 --- a/src/objects-inl.h +++ b/src/objects-inl.h @@ -119,6 +119,18 @@ PropertyDetails PropertyDetails::AsDeleted() { } +bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, + ElementsKind to_kind) { + if (to_kind == FAST_ELEMENTS) { + return from_kind == FAST_SMI_ONLY_ELEMENTS || + from_kind == FAST_DOUBLE_ELEMENTS; + } else { + return to_kind == FAST_DOUBLE_ELEMENTS && + from_kind == FAST_SMI_ONLY_ELEMENTS; + } +} + + bool Object::IsFixedArrayBase() { return IsFixedArray() || IsFixedDoubleArray(); } diff --git a/src/objects.cc b/src/objects.cc index 238fe1e..9a2319a 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -9501,6 +9501,9 @@ MUST_USE_RESULT MaybeObject* JSObject::TransitionElementsKind( MaybeObject* maybe_new_map = GetElementsTransitionMap(FAST_ELEMENTS); Map* new_map; if (!maybe_new_map->To(&new_map)) return maybe_new_map; + if (FLAG_trace_elements_transitions) { + PrintElementsTransition(stdout, from_kind, elms, FAST_ELEMENTS, elms); + } set_map(new_map); return this; } diff --git a/src/objects.h b/src/objects.h index b521231..fbaee6b 100644 --- a/src/objects.h +++ b/src/objects.h @@ -167,6 +167,8 @@ static const int kElementsKindCount = void PrintElementsKind(FILE* out, ElementsKind kind); +inline bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, + ElementsKind to_kind); // Setter that skips the write barrier if mode is SKIP_WRITE_BARRIER. enum WriteBarrierMode { SKIP_WRITE_BARRIER, UPDATE_WRITE_BARRIER }; diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc index e608a53..bf50869 100644 --- a/src/x64/code-stubs-x64.cc +++ b/src/x64/code-stubs-x64.cc @@ -5971,16 +5971,14 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { Label slow_elements; Label fast_elements; - if (!FLAG_trace_elements_transitions) { - __ CheckFastElements(rdi, &double_elements); + __ CheckFastElements(rdi, &double_elements); - // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS - __ JumpIfSmi(rax, &smi_element); - __ CheckFastSmiOnlyElements(rdi, &fast_elements); + // FAST_SMI_ONLY_ELEMENTS or FAST_ELEMENTS + __ JumpIfSmi(rax, &smi_element); + __ CheckFastSmiOnlyElements(rdi, &fast_elements); - // Store into the array literal requires a elements transition. Call into - // the runtime. - } + // Store into the array literal requires a elements transition. Call into + // the runtime. __ bind(&slow_elements); __ pop(rdi); // Pop return address and remember to put back later for tail @@ -5995,44 +5993,40 @@ void StoreArrayLiteralElementStub::Generate(MacroAssembler* masm) { // place. __ TailCallRuntime(Runtime::kStoreArrayLiteralElement, 5, 1); - if (!FLAG_trace_elements_transitions) { - // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. - __ bind(&double_elements); - - __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset)); - __ SmiToInteger32(r11, rcx); - __ StoreNumberToDoubleElements(rax, - r9, - r11, - xmm0, - &slow_elements); - __ jmp(&element_done); - - // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. - __ bind(&fast_elements); - __ SmiToInteger32(kScratchRegister, rcx); - __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); - __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size, - FixedArrayBase::kHeaderSize)); - __ movq(Operand(rcx, 0), rax); - // Update the write barrier for the array store. - __ RecordWrite(rbx, rcx, rax, - kDontSaveFPRegs, - EMIT_REMEMBERED_SET, - OMIT_SMI_CHECK); - __ jmp(&element_done); - - // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or - // FAST_ELEMENTS, and value is Smi. - __ bind(&smi_element); - __ SmiToInteger32(kScratchRegister, rcx); - __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); - __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size, - FixedArrayBase::kHeaderSize), rax); - // Fall through - __ bind(&element_done); - __ ret(0); - } + // Array literal has ElementsKind of FAST_ELEMENTS and value is an object. + __ bind(&fast_elements); + __ SmiToInteger32(kScratchRegister, rcx); + __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); + __ lea(rcx, FieldOperand(rbx, kScratchRegister, times_pointer_size, + FixedArrayBase::kHeaderSize)); + __ movq(Operand(rcx, 0), rax); + // Update the write barrier for the array store. + __ RecordWrite(rbx, rcx, rax, + kDontSaveFPRegs, + EMIT_REMEMBERED_SET, + OMIT_SMI_CHECK); + __ ret(0); + + // Array literal has ElementsKind of FAST_SMI_ONLY_ELEMENTS or + // FAST_ELEMENTS, and value is Smi. + __ bind(&smi_element); + __ SmiToInteger32(kScratchRegister, rcx); + __ movq(rbx, FieldOperand(rbx, JSObject::kElementsOffset)); + __ movq(FieldOperand(rbx, kScratchRegister, times_pointer_size, + FixedArrayBase::kHeaderSize), rax); + __ ret(0); + + // Array literal has ElementsKind of FAST_DOUBLE_ELEMENTS. + __ bind(&double_elements); + + __ movq(r9, FieldOperand(rbx, JSObject::kElementsOffset)); + __ SmiToInteger32(r11, rcx); + __ StoreNumberToDoubleElements(rax, + r9, + r11, + xmm0, + &slow_elements); + __ ret(0); } #undef __ -- 2.7.4