Index: src/x64/stub-cache-x64.cc |
diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc |
index 0e8e74ed60de3dcfbcad660823d2850dfb3fbdf1..3227b20906d90e40dbdc32b045dbb0eaddceeb53 100644 |
--- a/src/x64/stub-cache-x64.cc |
+++ b/src/x64/stub-cache-x64.cc |
@@ -2702,12 +2702,19 @@ Handle<Code> KeyedStoreStubCompiler::CompileStoreElement( |
ElementsKind elements_kind = receiver_map->elements_kind(); |
bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; |
- Handle<Code> stub = |
- KeyedStoreElementStub(is_js_array, |
- elements_kind, |
- store_mode_).GetCode(isolate()); |
- |
- __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
+ if (receiver_map->has_fast_elements() || |
+ receiver_map->has_external_array_elements()) { |
+ Handle<Code> stub = KeyedStoreFastElementStub( |
+ is_js_array, |
+ elements_kind, |
+ store_mode_).GetCode(isolate()); |
+ __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
+ } else { |
+ Handle<Code> stub = |
+ KeyedStoreElementStub(is_js_array, elements_kind, |
+ store_mode_).GetCode(isolate()); |
+ __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); |
+ } |
Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
__ jmp(ic, RelocInfo::CODE_TARGET); |
@@ -3142,195 +3149,6 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm, |
} |
-void KeyedStoreStubCompiler::GenerateStoreExternalArray( |
- MacroAssembler* masm, |
- ElementsKind elements_kind) { |
- // ----------- S t a t e ------------- |
- // -- rax : value |
- // -- rcx : key |
- // -- rdx : receiver |
- // -- rsp[0] : return address |
- // ----------------------------------- |
- Label slow, miss_force_generic; |
- |
- // This stub is meant to be tail-jumped to, the receiver must already |
- // have been verified by the caller to not be a smi. |
- |
- // Check that the key is a smi or a heap number convertible to a smi. |
- GenerateSmiKeyCheck(masm, rcx, rbx, xmm0, xmm1, &miss_force_generic); |
- |
- // Check that the index is in range. |
- __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
- __ SmiToInteger32(rdi, rcx); // Untag the index. |
- __ cmpq(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
- // Unsigned comparison catches both negative and too-large values. |
- __ j(above_equal, &miss_force_generic); |
- |
- // Handle both smis and HeapNumbers in the fast path. Go to the |
- // runtime for all other kinds of values. |
- // rax: value |
- // rcx: key (a smi) |
- // rdx: receiver (a JSObject) |
- // rbx: elements array |
- // rdi: untagged key |
- Label check_heap_number; |
- if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { |
- // Float to pixel conversion is only implemented in the runtime for now. |
- __ JumpIfNotSmi(rax, &slow); |
- } else { |
- __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear); |
- } |
- // No more branches to slow case on this path. Key and receiver not needed. |
- __ SmiToInteger32(rdx, rax); |
- __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
- // rbx: base pointer of external storage |
- switch (elements_kind) { |
- case EXTERNAL_PIXEL_ELEMENTS: |
- { // Clamp the value to [0..255]. |
- Label done; |
- __ testl(rdx, Immediate(0xFFFFFF00)); |
- __ j(zero, &done, Label::kNear); |
- __ setcc(negative, rdx); // 1 if negative, 0 if positive. |
- __ decb(rdx); // 0 if negative, 255 if positive. |
- __ bind(&done); |
- } |
- __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
- break; |
- case EXTERNAL_BYTE_ELEMENTS: |
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
- __ movb(Operand(rbx, rdi, times_1, 0), rdx); |
- break; |
- case EXTERNAL_SHORT_ELEMENTS: |
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
- __ movw(Operand(rbx, rdi, times_2, 0), rdx); |
- break; |
- case EXTERNAL_INT_ELEMENTS: |
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
- __ movl(Operand(rbx, rdi, times_4, 0), rdx); |
- break; |
- case EXTERNAL_FLOAT_ELEMENTS: |
- // Need to perform int-to-float conversion. |
- __ cvtlsi2ss(xmm0, rdx); |
- __ movss(Operand(rbx, rdi, times_4, 0), xmm0); |
- break; |
- case EXTERNAL_DOUBLE_ELEMENTS: |
- // Need to perform int-to-float conversion. |
- __ cvtlsi2sd(xmm0, rdx); |
- __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); |
- break; |
- case FAST_ELEMENTS: |
- case FAST_SMI_ELEMENTS: |
- case FAST_DOUBLE_ELEMENTS: |
- case FAST_HOLEY_ELEMENTS: |
- case FAST_HOLEY_SMI_ELEMENTS: |
- case FAST_HOLEY_DOUBLE_ELEMENTS: |
- case DICTIONARY_ELEMENTS: |
- case NON_STRICT_ARGUMENTS_ELEMENTS: |
- UNREACHABLE(); |
- break; |
- } |
- __ ret(0); |
- |
- // TODO(danno): handle heap number -> pixel array conversion |
- if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { |
- __ bind(&check_heap_number); |
- // rax: value |
- // rcx: key (a smi) |
- // rdx: receiver (a JSObject) |
- // rbx: elements array |
- // rdi: untagged key |
- __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); |
- __ j(not_equal, &slow); |
- // No more branches to slow case on this path. |
- |
- // The WebGL specification leaves the behavior of storing NaN and |
- // +/-Infinity into integer arrays basically undefined. For more |
- // reproducible behavior, convert these to zero. |
- __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); |
- __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
- // rdi: untagged index |
- // rbx: base pointer of external storage |
- // top of FPU stack: value |
- if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { |
- __ cvtsd2ss(xmm0, xmm0); |
- __ movss(Operand(rbx, rdi, times_4, 0), xmm0); |
- __ ret(0); |
- } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { |
- __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); |
- __ ret(0); |
- } else { |
- // Perform float-to-int conversion with truncation (round-to-zero) |
- // behavior. |
- // Fast path: use machine instruction to convert to int64. If that |
- // fails (out-of-range), go into the runtime. |
- __ cvttsd2siq(r8, xmm0); |
- __ Set(kScratchRegister, V8_UINT64_C(0x8000000000000000)); |
- __ cmpq(r8, kScratchRegister); |
- __ j(equal, &slow); |
- |
- // rdx: value (converted to an untagged integer) |
- // rdi: untagged index |
- // rbx: base pointer of external storage |
- switch (elements_kind) { |
- case EXTERNAL_BYTE_ELEMENTS: |
- case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
- __ movb(Operand(rbx, rdi, times_1, 0), r8); |
- break; |
- case EXTERNAL_SHORT_ELEMENTS: |
- case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
- __ movw(Operand(rbx, rdi, times_2, 0), r8); |
- break; |
- case EXTERNAL_INT_ELEMENTS: |
- case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
- __ movl(Operand(rbx, rdi, times_4, 0), r8); |
- break; |
- case EXTERNAL_PIXEL_ELEMENTS: |
- case EXTERNAL_FLOAT_ELEMENTS: |
- case EXTERNAL_DOUBLE_ELEMENTS: |
- case FAST_ELEMENTS: |
- case FAST_SMI_ELEMENTS: |
- case FAST_DOUBLE_ELEMENTS: |
- case FAST_HOLEY_ELEMENTS: |
- case FAST_HOLEY_SMI_ELEMENTS: |
- case FAST_HOLEY_DOUBLE_ELEMENTS: |
- case DICTIONARY_ELEMENTS: |
- case NON_STRICT_ARGUMENTS_ELEMENTS: |
- UNREACHABLE(); |
- break; |
- } |
- __ ret(0); |
- } |
- } |
- |
- // Slow case: call runtime. |
- __ bind(&slow); |
- |
- // ----------- S t a t e ------------- |
- // -- rax : value |
- // -- rcx : key |
- // -- rdx : receiver |
- // -- rsp[0] : return address |
- // ----------------------------------- |
- |
- Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); |
- __ jmp(ic, RelocInfo::CODE_TARGET); |
- |
- // Miss case: call runtime. |
- __ bind(&miss_force_generic); |
- |
- // ----------- S t a t e ------------- |
- // -- rax : value |
- // -- rcx : key |
- // -- rdx : receiver |
- // -- rsp[0] : return address |
- // ----------------------------------- |
- |
- Handle<Code> miss_ic = |
- masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
- __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
-} |
- |
- |
void KeyedStoreStubCompiler::GenerateStoreFastElement( |
MacroAssembler* masm, |
bool is_js_array, |