| Index: src/x64/stub-cache-x64.cc
|
| diff --git a/src/x64/stub-cache-x64.cc b/src/x64/stub-cache-x64.cc
|
| index 032996686e312dd1daf3b9c95cf24895d2cd9585..683aa9d40904bcaf3cd75c7e510d50f5d9a1f014 100644
|
| --- a/src/x64/stub-cache-x64.cc
|
| +++ b/src/x64/stub-cache-x64.cc
|
| @@ -3210,19 +3210,12 @@ Handle<Code> KeyedLoadStubCompiler::CompileLoadElement(
|
| // -- rsp[0] : return address
|
| // -----------------------------------
|
| ElementsKind elements_kind = receiver_map->elements_kind();
|
| - if (receiver_map->has_fast_elements() ||
|
| - receiver_map->has_external_array_elements()) {
|
| - Handle<Code> stub = KeyedLoadFastElementStub(
|
| - receiver_map->instance_type() == JS_ARRAY_TYPE,
|
| - elements_kind).GetCode();
|
| - __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
|
| - } else {
|
| - Handle<Code> stub =
|
| - KeyedLoadDictionaryElementStub().GetCode();
|
| - __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
|
| - }
|
| + Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode();
|
|
|
| - GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
|
| + __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK);
|
| +
|
| + Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
|
| + __ jmp(ic, RelocInfo::CODE_TARGET);
|
|
|
| // Return the generated code.
|
| return GetCode(Code::NORMAL, factory()->empty_string());
|
| @@ -3464,6 +3457,140 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm,
|
| }
|
|
|
|
|
| +void KeyedLoadStubCompiler::GenerateLoadExternalArray(
|
| + MacroAssembler* masm,
|
| + ElementsKind elements_kind) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : 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, rax, rcx, xmm0, xmm1, &miss_force_generic);
|
| +
|
| + // Check that the index is in range.
|
| + __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
|
| + __ SmiToInteger32(rcx, rax);
|
| + __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset));
|
| + // Unsigned comparison catches both negative and too-large values.
|
| + __ j(above_equal, &miss_force_generic);
|
| +
|
| + // rax: index (as a smi)
|
| + // rdx: receiver (JSObject)
|
| + // rcx: untagged index
|
| + // rbx: elements array
|
| + __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
|
| + // rbx: base pointer of external storage
|
| + switch (elements_kind) {
|
| + case EXTERNAL_BYTE_ELEMENTS:
|
| + __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
|
| + break;
|
| + case EXTERNAL_PIXEL_ELEMENTS:
|
| + case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| + __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
|
| + break;
|
| + case EXTERNAL_SHORT_ELEMENTS:
|
| + __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
|
| + break;
|
| + case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| + __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
|
| + break;
|
| + case EXTERNAL_INT_ELEMENTS:
|
| + __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
|
| + break;
|
| + case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| + __ movl(rcx, Operand(rbx, rcx, times_4, 0));
|
| + break;
|
| + case EXTERNAL_FLOAT_ELEMENTS:
|
| + __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
|
| + break;
|
| + case EXTERNAL_DOUBLE_ELEMENTS:
|
| + __ movsd(xmm0, Operand(rbx, rcx, times_8, 0));
|
| + break;
|
| + default:
|
| + UNREACHABLE();
|
| + break;
|
| + }
|
| +
|
| + // rax: index
|
| + // rdx: receiver
|
| + // For integer array types:
|
| + // rcx: value
|
| + // For floating-point array type:
|
| + // xmm0: value as double.
|
| +
|
| + ASSERT(kSmiValueSize == 32);
|
| + if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) {
|
| + // For the UnsignedInt array type, we need to see whether
|
| + // the value can be represented in a Smi. If not, we need to convert
|
| + // it to a HeapNumber.
|
| + Label box_int;
|
| +
|
| + __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear);
|
| +
|
| + __ Integer32ToSmi(rax, rcx);
|
| + __ ret(0);
|
| +
|
| + __ bind(&box_int);
|
| +
|
| + // Allocate a HeapNumber for the int and perform int-to-double
|
| + // conversion.
|
| + // The value is zero-extended since we loaded the value from memory
|
| + // with movl.
|
| + __ cvtqsi2sd(xmm0, rcx);
|
| +
|
| + __ AllocateHeapNumber(rcx, rbx, &slow);
|
| + // Set the value.
|
| + __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
|
| + __ movq(rax, rcx);
|
| + __ ret(0);
|
| + } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS ||
|
| + elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
| + // For the floating-point array type, we need to always allocate a
|
| + // HeapNumber.
|
| + __ AllocateHeapNumber(rcx, rbx, &slow);
|
| + // Set the value.
|
| + __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
|
| + __ movq(rax, rcx);
|
| + __ ret(0);
|
| + } else {
|
| + __ Integer32ToSmi(rax, rcx);
|
| + __ ret(0);
|
| + }
|
| +
|
| + // Slow case: Jump to runtime.
|
| + __ bind(&slow);
|
| + Counters* counters = masm->isolate()->counters();
|
| + __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
|
| +
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| +
|
| + Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
|
| + __ jmp(ic, RelocInfo::CODE_TARGET);
|
| +
|
| + // Miss case: Jump to runtime.
|
| + __ bind(&miss_force_generic);
|
| +
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + Handle<Code> miss_ic =
|
| + masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| MacroAssembler* masm,
|
| ElementsKind elements_kind) {
|
| @@ -3653,6 +3780,98 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| }
|
|
|
|
|
| +void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + Label 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, rax, rcx, xmm0, xmm1, &miss_force_generic);
|
| +
|
| + // Get the elements array.
|
| + __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
|
| + __ AssertFastElements(rcx);
|
| +
|
| + // Check that the key is within bounds.
|
| + __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
|
| + __ j(above_equal, &miss_force_generic);
|
| +
|
| + // Load the result and make sure it's not the hole.
|
| + SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
|
| + __ movq(rbx, FieldOperand(rcx,
|
| + index.reg,
|
| + index.scale,
|
| + FixedArray::kHeaderSize));
|
| + __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
|
| + __ j(equal, &miss_force_generic);
|
| + __ movq(rax, rbx);
|
| + __ ret(0);
|
| +
|
| + __ bind(&miss_force_generic);
|
| + Code* code = masm->isolate()->builtins()->builtin(
|
| + Builtins::kKeyedLoadIC_MissForceGeneric);
|
| + Handle<Code> ic(code);
|
| + __ jmp(ic, RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| +void KeyedLoadStubCompiler::GenerateLoadFastDoubleElement(
|
| + MacroAssembler* masm) {
|
| + // ----------- S t a t e -------------
|
| + // -- rax : key
|
| + // -- rdx : receiver
|
| + // -- rsp[0] : return address
|
| + // -----------------------------------
|
| + Label miss_force_generic, slow_allocate_heapnumber;
|
| +
|
| + // 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, rax, rcx, xmm0, xmm1, &miss_force_generic);
|
| +
|
| + // Get the elements array.
|
| + __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
|
| + __ AssertFastElements(rcx);
|
| +
|
| + // Check that the key is within bounds.
|
| + __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
|
| + __ j(above_equal, &miss_force_generic);
|
| +
|
| + // Check for the hole
|
| + __ SmiToInteger32(kScratchRegister, rax);
|
| + uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32);
|
| + __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset),
|
| + Immediate(kHoleNanUpper32));
|
| + __ j(equal, &miss_force_generic);
|
| +
|
| + // Always allocate a heap number for the result.
|
| + __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8,
|
| + FixedDoubleArray::kHeaderSize));
|
| + __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber);
|
| + // Set the value.
|
| + __ movq(rax, rcx);
|
| + __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
|
| + __ ret(0);
|
| +
|
| + __ bind(&slow_allocate_heapnumber);
|
| + Handle<Code> slow_ic =
|
| + masm->isolate()->builtins()->KeyedLoadIC_Slow();
|
| + __ jmp(slow_ic, RelocInfo::CODE_TARGET);
|
| +
|
| + __ bind(&miss_force_generic);
|
| + Handle<Code> miss_ic =
|
| + masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
|
| + __ jmp(miss_ic, RelocInfo::CODE_TARGET);
|
| +}
|
| +
|
| +
|
| void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
| MacroAssembler* masm,
|
| bool is_js_array,
|
|
|