| Index: src/a64/stub-cache-a64.cc
|
| diff --git a/src/a64/stub-cache-a64.cc b/src/a64/stub-cache-a64.cc
|
| index 203fcc3715e0621f212cc74e3d0be0ca1dc947b3..2cdc1b97fc5da7760111ece4f55a041e8907f54d 100644
|
| --- a/src/a64/stub-cache-a64.cc
|
| +++ b/src/a64/stub-cache-a64.cc
|
| @@ -170,39 +170,6 @@ static void ProbeTable(Isolate* isolate,
|
| }
|
|
|
|
|
| -// Check if key is a smi or can be converted into a smi.
|
| -// If not jump on 'fail' and fall-through otherwise.
|
| -static void GenerateSmiKeyCheck(MacroAssembler* masm,
|
| - Register key,
|
| - Register scratch0,
|
| - FPRegister double_scratch0,
|
| - FPRegister double_scratch1,
|
| - Label* fail) {
|
| - Label key_ok;
|
| - __ JumpIfSmi(key, &key_ok);
|
| -
|
| - // The key is not a smi. Check for a smi inside a heap number.
|
| - __ CheckMap(key,
|
| - scratch0,
|
| - masm->isolate()->factory()->heap_number_map(),
|
| - fail,
|
| - DONT_DO_SMI_CHECK);
|
| -
|
| - __ Ldr(scratch0, FieldMemOperand(key, HeapNumber::kValueOffset));
|
| - __ Fmov(double_scratch0, scratch0);
|
| - __ TryConvertDoubleToInt32(scratch0.W(),
|
| - double_scratch0,
|
| - double_scratch1,
|
| - NULL,
|
| - fail);
|
| - // The double value has been coverted to a 32-bit signed integer.
|
| - // We just need to tag it.
|
| - __ SmiTag(key, scratch0);
|
| -
|
| - __ Bind(&key_ok);
|
| -}
|
| -
|
| -
|
| void StubCache::GenerateProbe(MacroAssembler* masm,
|
| Code::Flags flags,
|
| Register receiver,
|
| @@ -3287,474 +3254,6 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
| }
|
|
|
|
|
| -static void GenerateStoreSmiToExternalArray(
|
| - MacroAssembler* masm,
|
| - ElementsKind elements_kind,
|
| - Register value,
|
| - Register key_raw, // Untagged 'key'.
|
| - Register elements_ext, // elements[ExternalArray::kExternalPointerOffset]
|
| - Register scratch,
|
| - FPRegister double_scratch) {
|
| - // Convert the smi in value (x0) to the specified element kind, and store it
|
| - // in the external array. No input registers are clobbered by this helper,
|
| - // other than the scratch registers.
|
| -
|
| - ASSERT(!AreAliased(value, key_raw, elements_ext, scratch, double_scratch));
|
| -
|
| - switch (elements_kind) {
|
| - case EXTERNAL_PIXEL_ELEMENTS:
|
| - __ SmiUntag(scratch, value);
|
| - // Clamp the value to [0..255].
|
| - __ Cmp(scratch, Operand(scratch, UXTB));
|
| - // If scratch < scratch & 0xff, it must be < 0, so saturate to 0.
|
| - __ CzeroX(scratch, lt);
|
| - // If scratch > scratch & 0xff, it must be > 255, so saturate to 255.
|
| - // This actually generates ~0, but it doesn't matter if we use strb.
|
| - __ Csinv(scratch, scratch, xzr, le);
|
| - __ Strb(scratch.W(), MemOperand(elements_ext, key_raw));
|
| - break;
|
| - case EXTERNAL_BYTE_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ SmiUntag(scratch, value);
|
| - __ Strb(scratch.W(), MemOperand(elements_ext, key_raw));
|
| - break;
|
| - case EXTERNAL_SHORT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ SmiUntag(scratch, value);
|
| - __ Strh(scratch.W(),
|
| - MemOperand(elements_ext, key_raw, LSL, kHalfWordSizeInBytesLog2));
|
| - break;
|
| - case EXTERNAL_INT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ SmiUntag(scratch, value);
|
| - __ Str(scratch.W(),
|
| - MemOperand(elements_ext, key_raw, LSL, kWordSizeInBytesLog2));
|
| - break;
|
| - case EXTERNAL_FLOAT_ELEMENTS:
|
| - __ SmiUntagToFloat(double_scratch.S(), value);
|
| - __ Str(double_scratch.S(),
|
| - MemOperand(elements_ext, key_raw, LSL, kSRegSizeInBytesLog2));
|
| - break;
|
| - case EXTERNAL_DOUBLE_ELEMENTS:
|
| - __ SmiUntagToDouble(double_scratch, value);
|
| - __ Str(double_scratch,
|
| - MemOperand(elements_ext, key_raw, LSL, kDRegSizeInBytesLog2));
|
| - 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;
|
| - }
|
| -}
|
| -
|
| -
|
| -static void GenerateStoreHeapNumberToExternalArray(
|
| - MacroAssembler* masm,
|
| - ElementsKind elements_kind,
|
| - Register value,
|
| - Register key_raw, // Untagged 'key'.
|
| - Register elements_ext, // elements[ExternalArray::kExternalPointerOffset]
|
| - Register scratch,
|
| - FPRegister double_scratch1,
|
| - FPRegister double_scratch2) {
|
| - // Convert the heap number in value (x0) to the specified element kind, and
|
| - // store it in the external array. No input registers are clobbered by this
|
| - // helper, other than the scratch registers.
|
| -
|
| - ASSERT(!AreAliased(value, key_raw, elements_ext, scratch,
|
| - double_scratch1, double_scratch2));
|
| -
|
| - FPRegister value_d = double_scratch1;
|
| - __ Ldr(value_d, FieldMemOperand(value, HeapNumber::kValueOffset));
|
| -
|
| - // Convert the (double) input to an integral type.
|
| - switch (elements_kind) {
|
| - case EXTERNAL_FLOAT_ELEMENTS:
|
| - __ Fcvt(s16, value_d);
|
| - __ Str(s16, MemOperand(elements_ext, key_raw, LSL, 2));
|
| - break;
|
| - case EXTERNAL_DOUBLE_ELEMENTS:
|
| - __ Str(value_d, MemOperand(elements_ext, key_raw, LSL, 3));
|
| - break;
|
| - case EXTERNAL_PIXEL_ELEMENTS:
|
| - // This conversion follows the WebIDL "[Clamp]" rules:
|
| - // - Inputs lower than 0 (including -infinity) produce 0.
|
| - // - Inputs higher than 255 (including +infinity) produce 255.
|
| - // Also, it seems that PIXEL types use round-to-nearest rather than
|
| - // round-towards-zero.
|
| -
|
| - // Squash +infinity before the conversion, since Fcvtnu will normally
|
| - // convert it to 0.
|
| - __ Fmov(double_scratch2, 255);
|
| - __ Fmin(double_scratch2, double_scratch2, value_d);
|
| -
|
| - // Convert double to unsigned integer. Values less than zero become zero.
|
| - // Values greater than 255 have already been clamped to 255.
|
| - __ Fcvtnu(scratch.W(), double_scratch2);
|
| -
|
| - __ Strb(scratch.W(), MemOperand(elements_ext, key_raw));
|
| - break;
|
| - case EXTERNAL_BYTE_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ ECMA262ToInt32(scratch, value_d, x11, x12, MacroAssembler::INT32_IN_W);
|
| - __ Strb(scratch.W(), MemOperand(elements_ext, key_raw));
|
| - break;
|
| - case EXTERNAL_SHORT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ ECMA262ToInt32(scratch, value_d, x11, x12, MacroAssembler::INT32_IN_W);
|
| - __ Strh(scratch.W(),
|
| - MemOperand(elements_ext, key_raw, LSL, kHalfWordSizeInBytesLog2));
|
| - break;
|
| - case EXTERNAL_INT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ ECMA262ToInt32(scratch, value_d, x11, x12, MacroAssembler::INT32_IN_W);
|
| - __ Str(scratch.W(),
|
| - MemOperand(elements_ext, key_raw, LSL, kWordSizeInBytesLog2));
|
| - 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;
|
| - }
|
| -}
|
| -
|
| -
|
| -void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| - MacroAssembler* masm,
|
| - ElementsKind elements_kind) {
|
| - // ---------- S t a t e --------------
|
| - // -- lr : return address
|
| - // -- x0 : value
|
| - // -- x1 : key
|
| - // -- x2 : receiver
|
| - // -----------------------------------
|
| - Label slow, check_heap_number, miss_force_generic;
|
| -
|
| - // Register usage.
|
| - Register value = x0;
|
| - Register key = x1;
|
| - Register receiver = x2;
|
| -
|
| - // This stub is meant to be tail-jumped to, the receiver must already
|
| - // have been verified by the caller to not be a smi.
|
| - if (__ emit_debug_code()) {
|
| - __ AssertNotSmi(receiver);
|
| - }
|
| -
|
| - // Check that the key is a smi or a heap number convertible to a smi.
|
| - GenerateSmiKeyCheck(masm, key, x10, d16, d17, &miss_force_generic);
|
| -
|
| - Register elements = x3;
|
| - __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| -
|
| - Register key_raw = x4;
|
| - __ SmiUntag(key_raw, key);
|
| -
|
| - // Check that the key is within bounds. An unsigned comparison catches both
|
| - // negative and out-of-bound indexes.
|
| - __ Ldrsw(x10,
|
| - UntagSmiFieldMemOperand(elements, ExternalArray::kLengthOffset));
|
| - __ Cmp(key_raw.W(), w10);
|
| - __ B(&miss_force_generic, hs);
|
| -
|
| - // Get the externally-stored elements.
|
| - Register elements_ext = x5;
|
| - __ Ldr(elements_ext,
|
| - FieldMemOperand(elements, ExternalArray::kExternalPointerOffset));
|
| -
|
| - // x0: value
|
| - // x1: key
|
| - // x2: receiver
|
| - // x3: elements
|
| - // x4: key_raw Untagged 'key'.
|
| - // x5: elements_ext From elements[ExternalArray::kExternalPointerOffset].
|
| -
|
| - // Handle both smis and HeapNumbers in the fast path. Go to the
|
| - // runtime for all other kinds of values.
|
| - __ JumpIfNotSmi(value, &check_heap_number);
|
| -
|
| - GenerateStoreSmiToExternalArray(
|
| - masm, elements_kind, value, key_raw, elements_ext, x10, d16);
|
| - // Entry registers are intact and x0 holds 'value', which is the return value.
|
| - __ Ret();
|
| -
|
| - __ Bind(&check_heap_number);
|
| - // Convert the double at 'value' to the specified element kind.
|
| - //
|
| - // x0: value
|
| - // x1: key
|
| - // x2: receiver
|
| - // x3: elements
|
| - // x4: key_raw Untagged 'key'.
|
| - // x5: elements_ext From elements[ExternalArray::kExternalPointerOffset].
|
| - __ JumpIfNotObjectType(value, x10, x11, HEAP_NUMBER_TYPE, &slow);
|
| -
|
| - GenerateStoreHeapNumberToExternalArray(
|
| - masm, elements_kind, value, key_raw, elements_ext, x10, d16, d17);
|
| - // Entry registers are intact and x0 holds 'value', which is the return value.
|
| - __ Ret();
|
| -
|
| - __ Bind(&slow);
|
| - // ---------- S t a t e --------------
|
| - // -- lr : return address
|
| - // -- x0 : value
|
| - // -- x1 : key
|
| - // -- x2 : receiver
|
| - // -----------------------------------
|
| - __ IncrementCounter(
|
| - masm->isolate()->counters()->keyed_load_external_array_slow(),
|
| - 1, x10, x11);
|
| -
|
| - TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
| -
|
| - // Miss case, call the runtime.
|
| - __ Bind(&miss_force_generic);
|
| - // ---------- S t a t e --------------
|
| - // -- lr : return address
|
| - // -- x0 : value
|
| - // -- x1 : key
|
| - // -- x2 : receiver
|
| - // -----------------------------------
|
| -
|
| - TailCallBuiltin(masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
| -}
|
| -
|
| -
|
| -static void GenerateStoreFastSmiOrDoubleElement(
|
| - MacroAssembler* masm,
|
| - bool is_js_array,
|
| - ElementsKind elements_kind,
|
| - KeyedAccessStoreMode store_mode,
|
| - bool store_double) {
|
| - Label miss_force_generic, transition_elements_kind, grow, slow;
|
| - Label finish_store, check_capacity;
|
| -
|
| - Register value = x0;
|
| - Register key = x1;
|
| - Register receiver = x2;
|
| -
|
| - // This stub is meant to be tail-jumped to, the receiver must already
|
| - // have been verified by the caller to not be a smi.
|
| - if (__ emit_debug_code()) {
|
| - __ AssertNotSmi(receiver);
|
| - }
|
| -
|
| - // Check that the key is a smi or a heap number convertible to a smi.
|
| - GenerateSmiKeyCheck(masm, key, x10, d16, d17, &miss_force_generic);
|
| -
|
| - if (!store_double && IsFastSmiElementsKind(elements_kind)) {
|
| - __ JumpIfNotSmi(value, &transition_elements_kind);
|
| - }
|
| -
|
| - Register elements = x3;
|
| - __ Ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| -
|
| - // Check that the key is within bounds.
|
| - Register length = x4;
|
| - if (is_js_array) {
|
| - __ Ldr(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| - } else {
|
| - __ Ldr(length, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
| - }
|
| - // Compare smis. An unsigned comparison catches both negative and out-of-bound
|
| - // indexes.
|
| - __ Cmp(key, length);
|
| - if (is_js_array && IsGrowStoreMode(store_mode)) {
|
| - // We can handle the case where the array needs to grow by a single element
|
| - // without falling back to run-time.
|
| - __ B(&grow, eq);
|
| - }
|
| - // Fall back to the run-time if the key is out of bounds.
|
| - __ B(&miss_force_generic, hs);
|
| -
|
| - if (store_double) {
|
| - __ Bind(&finish_store);
|
| - __ StoreNumberToDoubleElements(value, key, elements, x10, d16, d17,
|
| - &transition_elements_kind);
|
| - } else {
|
| - // Make sure elements is a fast element array, not 'cow'.
|
| - // TODO(jbramley): Why is this only done when storing a smi?
|
| - __ CheckMap(elements, x10,
|
| - Heap::kFixedArrayMapRootIndex,
|
| - &miss_force_generic,
|
| - DONT_DO_SMI_CHECK);
|
| -
|
| - __ Bind(&finish_store);
|
| -
|
| - STATIC_ASSERT(kSmiTag == 0 && kSmiShift > kPointerSizeLog2);
|
| - __ Add(x10, elements, FixedArray::kHeaderSize - kHeapObjectTag);
|
| - __ Add(x10, x10, Operand::UntagSmiAndScale(key, kPointerSizeLog2));
|
| - __ Str(value, MemOperand(x10));
|
| - if (!IsFastSmiElementsKind(elements_kind)) {
|
| - ASSERT(IsFastObjectElementsKind(elements_kind));
|
| - __ Mov(receiver, value);
|
| - __ RecordWrite(elements, // Object.
|
| - x10, // Address.
|
| - receiver, // Value.
|
| - kLRHasNotBeenSaved,
|
| - kDontSaveFPRegs,
|
| - EMIT_REMEMBERED_SET,
|
| - INLINE_SMI_CHECK,
|
| - EXPECT_PREGENERATED);
|
| - }
|
| - // Value (x0) is preserved.
|
| - }
|
| - __ Ret();
|
| -
|
| - __ Bind(&miss_force_generic);
|
| - KeyedStoreStubCompiler::TailCallBuiltin(
|
| - masm, Builtins::kKeyedStoreIC_MissForceGeneric);
|
| -
|
| - __ Bind(&transition_elements_kind);
|
| - KeyedStoreStubCompiler::TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Miss);
|
| -
|
| - if (is_js_array && IsGrowStoreMode(store_mode)) {
|
| - // Grow a JSArray by a single element.
|
| - __ Bind(&grow);
|
| -
|
| - // x1: key
|
| - // x2: receiver
|
| - // x3: elements From receiver[JSObject::kElementsOffset].
|
| - // x4: length From receiver[JSArray::kLengthOffset].
|
| -
|
| - if (__ emit_debug_code()) {
|
| - // Check that 'elements' and 'length' are pre-loaded.
|
| - __ Ldr(x10, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| - __ Cmp(x10, x3);
|
| - __ Ldr(x11, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| - __ Ccmp(x11, x4, NoFlag, eq);
|
| -
|
| - // Check that the key is equal to length, so we need to extend the array
|
| - // by one element.
|
| - __ Ccmp(x1, x4, NoFlag, eq);
|
| -
|
| - __ Check(eq, kPreconditionsWereNotMet);
|
| - }
|
| -
|
| - __ JumpIfNotRoot(elements, Heap::kEmptyFixedArrayRootIndex,
|
| - &check_capacity);
|
| -
|
| - // The array is currently empty, so allocate a new backing store.
|
| - int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements);
|
| - __ Allocate(size, elements, x10, x11, &slow, TAG_OBJECT);
|
| - Heap::RootListIndex root_index = store_double
|
| - ? Heap::kFixedDoubleArrayMapRootIndex
|
| - : Heap::kFixedArrayMapRootIndex;
|
| - __ LoadRoot(x12, root_index);
|
| - __ Str(x12, FieldMemOperand(elements, JSObject::kMapOffset));
|
| - __ Mov(x13, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements)));
|
| - __ Str(x13, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
| -
|
| - // Store the element at index zero, and fill the rest with the hole value.
|
| - if (store_double) {
|
| - __ StoreNumberToDoubleElements(value,
|
| - key,
|
| - elements,
|
| - x10,
|
| - d16,
|
| - d17,
|
| - &transition_elements_kind);
|
| - __ Fmov(d16, rawbits_to_double(kHoleNanInt64));
|
| - for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) {
|
| - __ Str(d16, FieldMemOperand(elements,
|
| - FixedDoubleArray::OffsetOfElementAt(i)));
|
| - }
|
| - } else {
|
| - __ Str(value, FieldMemOperand(elements, FixedArray::SizeFor(0)));
|
| - __ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
|
| - for (int i = 1; i < JSArray::kPreallocatedArrayElements; i++) {
|
| - __ Str(x10, FieldMemOperand(elements,
|
| - FixedArray::OffsetOfElementAt(i)));
|
| - }
|
| - }
|
| -
|
| - // Install the new backing store in the JSArray.
|
| - __ Str(elements, FieldMemOperand(receiver, JSObject::kElementsOffset));
|
| - __ RecordWriteField(receiver, JSObject::kElementsOffset, elements,
|
| - x10, kLRHasNotBeenSaved, kDontSaveFPRegs,
|
| - EMIT_REMEMBERED_SET, OMIT_SMI_CHECK,
|
| - EXPECT_PREGENERATED);
|
| -
|
| - // Increment the length of the array.
|
| - __ Mov(length, Operand(Smi::FromInt(1)));
|
| - __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| - __ Ret();
|
| -
|
| - __ Bind(&check_capacity);
|
| -
|
| - if (!store_double) {
|
| - // Check for cow elements, in general they are not handled by this stub
|
| - // TODO(jbramley): Why is this only done when storing a smi?
|
| - __ CheckMap(elements, x10,
|
| - Heap::kFixedCOWArrayMapRootIndex,
|
| - &miss_force_generic,
|
| - DONT_DO_SMI_CHECK);
|
| - }
|
| -
|
| - // See if there are any free preallocated slots. If not, defer to the
|
| - // runtime to extend the backing store.
|
| - __ Ldr(x10, FieldMemOperand(elements, FixedArray::kLengthOffset));
|
| - __ Cmp(length, x10);
|
| - __ B(&slow, hs);
|
| -
|
| - // Grow the array and finish the store.
|
| - __ Add(length, length, Operand(Smi::FromInt(1)));
|
| - __ Str(length, FieldMemOperand(receiver, JSArray::kLengthOffset));
|
| - __ B(&finish_store);
|
| -
|
| - __ Bind(&slow);
|
| - KeyedStoreStubCompiler::TailCallBuiltin(masm, Builtins::kKeyedStoreIC_Slow);
|
| - }
|
| -}
|
| -
|
| -
|
| -void KeyedStoreStubCompiler::GenerateStoreFastElement(
|
| - MacroAssembler* masm,
|
| - bool is_js_array,
|
| - ElementsKind elements_kind,
|
| - KeyedAccessStoreMode store_mode) {
|
| -
|
| - // ----------- S t a t e -------------
|
| - // -- lr : return address
|
| - // -- x0 : value
|
| - // -- x1 : key
|
| - // -- x2 : receiver
|
| - // -----------------------------------
|
| -
|
| - GenerateStoreFastSmiOrDoubleElement(masm, is_js_array, elements_kind,
|
| - store_mode, false);
|
| -}
|
| -
|
| -
|
| -void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
|
| - MacroAssembler* masm,
|
| - bool is_js_array,
|
| - KeyedAccessStoreMode store_mode) {
|
| -
|
| - // ----------- S t a t e -------------
|
| - // -- lr : return address
|
| - // -- x0 : value
|
| - // -- x1 : key
|
| - // -- x2 : receiver
|
| - // ----------- S t a t e -------------
|
| -
|
| - GenerateStoreFastSmiOrDoubleElement(masm, is_js_array, FAST_DOUBLE_ELEMENTS,
|
| - store_mode, true);
|
| -}
|
| -
|
| -
|
| } } // namespace v8::internal
|
|
|
| #endif // V8_TARGET_ARCH_A64
|
|
|