| Index: src/arm/stub-cache-arm.cc
|
| diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc
|
| index 676fa0f5ea743889644c2fd26411fb4e354989ec..d03eb36e07646010c114432c91148e80b06af621 100644
|
| --- a/src/arm/stub-cache-arm.cc
|
| +++ b/src/arm/stub-cache-arm.cc
|
| @@ -975,66 +975,11 @@ static void StoreIntAsFloat(MacroAssembler* masm,
|
| Register dst,
|
| Register wordoffset,
|
| Register ival,
|
| - Register fval,
|
| - Register scratch1,
|
| - Register scratch2) {
|
| - if (CpuFeatures::IsSupported(VFP2)) {
|
| - CpuFeatureScope scope(masm, VFP2);
|
| - __ vmov(s0, ival);
|
| - __ add(scratch1, dst, Operand(wordoffset, LSL, 2));
|
| - __ vcvt_f32_s32(s0, s0);
|
| - __ vstr(s0, scratch1, 0);
|
| - } else {
|
| - Label not_special, done;
|
| - // Move sign bit from source to destination. This works because the sign
|
| - // bit in the exponent word of the double has the same position and polarity
|
| - // as the 2's complement sign bit in a Smi.
|
| - ASSERT(kBinary32SignMask == 0x80000000u);
|
| -
|
| - __ and_(fval, ival, Operand(kBinary32SignMask), SetCC);
|
| - // Negate value if it is negative.
|
| - __ rsb(ival, ival, Operand::Zero(), LeaveCC, ne);
|
| -
|
| - // We have -1, 0 or 1, which we treat specially. Register ival contains
|
| - // absolute value: it is either equal to 1 (special case of -1 and 1),
|
| - // greater than 1 (not a special case) or less than 1 (special case of 0).
|
| - __ cmp(ival, Operand(1));
|
| - __ b(gt, ¬_special);
|
| -
|
| - // For 1 or -1 we need to or in the 0 exponent (biased).
|
| - static const uint32_t exponent_word_for_1 =
|
| - kBinary32ExponentBias << kBinary32ExponentShift;
|
| -
|
| - __ orr(fval, fval, Operand(exponent_word_for_1), LeaveCC, eq);
|
| - __ b(&done);
|
| -
|
| - __ bind(¬_special);
|
| - // Count leading zeros.
|
| - // Gets the wrong answer for 0, but we already checked for that case above.
|
| - Register zeros = scratch2;
|
| - __ CountLeadingZeros(zeros, ival, scratch1);
|
| -
|
| - // Compute exponent and or it into the exponent register.
|
| - __ rsb(scratch1,
|
| - zeros,
|
| - Operand((kBitsPerInt - 1) + kBinary32ExponentBias));
|
| -
|
| - __ orr(fval,
|
| - fval,
|
| - Operand(scratch1, LSL, kBinary32ExponentShift));
|
| -
|
| - // Shift up the source chopping the top bit off.
|
| - __ add(zeros, zeros, Operand(1));
|
| - // This wouldn't work for 1 and -1 as the shift would be 32 which means 0.
|
| - __ mov(ival, Operand(ival, LSL, zeros));
|
| - // And the top (top 20 bits).
|
| - __ orr(fval,
|
| - fval,
|
| - Operand(ival, LSR, kBitsPerInt - kBinary32MantissaBits));
|
| -
|
| - __ bind(&done);
|
| - __ str(fval, MemOperand(dst, wordoffset, LSL, 2));
|
| - }
|
| + Register scratch1) {
|
| + __ vmov(s0, ival);
|
| + __ add(scratch1, dst, Operand(wordoffset, LSL, 2));
|
| + __ vcvt_f32_s32(s0, s0);
|
| + __ vstr(s0, scratch1, 0);
|
| }
|
|
|
|
|
| @@ -2082,11 +2027,6 @@ Handle<Code> CallStubCompiler::CompileMathFloorCall(
|
| // -- sp[argc * 4] : receiver
|
| // -----------------------------------
|
|
|
| - if (!CpuFeatures::IsSupported(VFP2)) {
|
| - return Handle<Code>::null();
|
| - }
|
| -
|
| - CpuFeatureScope scope_vfp2(masm(), VFP2);
|
| const int argc = arguments().immediate();
|
| // If the object is not a JSObject or we got an unexpected number of
|
| // arguments, bail out to the regular call.
|
| @@ -3126,36 +3066,6 @@ void KeyedLoadStubCompiler::GenerateLoadDictionaryElement(
|
| }
|
|
|
|
|
| -static bool IsElementTypeSigned(ElementsKind elements_kind) {
|
| - switch (elements_kind) {
|
| - case EXTERNAL_BYTE_ELEMENTS:
|
| - case EXTERNAL_SHORT_ELEMENTS:
|
| - case EXTERNAL_INT_ELEMENTS:
|
| - return true;
|
| -
|
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - case EXTERNAL_PIXEL_ELEMENTS:
|
| - return false;
|
| -
|
| - 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();
|
| - return false;
|
| - }
|
| - return false;
|
| -}
|
| -
|
| -
|
| static void GenerateSmiKeyCheck(MacroAssembler* masm,
|
| Register key,
|
| Register scratch0,
|
| @@ -3163,29 +3073,23 @@ static void GenerateSmiKeyCheck(MacroAssembler* masm,
|
| DwVfpRegister double_scratch0,
|
| DwVfpRegister double_scratch1,
|
| Label* fail) {
|
| - if (CpuFeatures::IsSupported(VFP2)) {
|
| - CpuFeatureScope scope(masm, VFP2);
|
| - Label key_ok;
|
| - // Check for smi or a smi inside a heap number. We convert the heap
|
| - // number and check if the conversion is exact and fits into the smi
|
| - // range.
|
| - __ JumpIfSmi(key, &key_ok);
|
| - __ CheckMap(key,
|
| - scratch0,
|
| - Heap::kHeapNumberMapRootIndex,
|
| - fail,
|
| - DONT_DO_SMI_CHECK);
|
| - __ sub(ip, key, Operand(kHeapObjectTag));
|
| - __ vldr(double_scratch0, ip, HeapNumber::kValueOffset);
|
| - __ TryDoubleToInt32Exact(scratch0, double_scratch0, double_scratch1);
|
| - __ b(ne, fail);
|
| - __ TrySmiTag(scratch0, fail, scratch1);
|
| - __ mov(key, scratch0);
|
| - __ bind(&key_ok);
|
| - } else {
|
| - // Check that the key is a smi.
|
| - __ JumpIfNotSmi(key, fail);
|
| - }
|
| + Label key_ok;
|
| + // Check for smi or a smi inside a heap number. We convert the heap
|
| + // number and check if the conversion is exact and fits into the smi
|
| + // range.
|
| + __ JumpIfSmi(key, &key_ok);
|
| + __ CheckMap(key,
|
| + scratch0,
|
| + Heap::kHeapNumberMapRootIndex,
|
| + fail,
|
| + DONT_DO_SMI_CHECK);
|
| + __ sub(ip, key, Operand(kHeapObjectTag));
|
| + __ vldr(double_scratch0, ip, HeapNumber::kValueOffset);
|
| + __ TryDoubleToInt32Exact(scratch0, double_scratch0, double_scratch1);
|
| + __ b(ne, fail);
|
| + __ TrySmiTag(scratch0, fail, scratch1);
|
| + __ mov(key, scratch0);
|
| + __ bind(&key_ok);
|
| }
|
|
|
|
|
| @@ -3255,28 +3159,18 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| case EXTERNAL_FLOAT_ELEMENTS:
|
| // Perform int-to-float conversion and store to memory.
|
| __ SmiUntag(r4, key);
|
| - StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
|
| + StoreIntAsFloat(masm, r3, r4, r5, r7);
|
| break;
|
| case EXTERNAL_DOUBLE_ELEMENTS:
|
| __ add(r3, r3, Operand(key, LSL, 2));
|
| // r3: effective address of the double element
|
| FloatingPointHelper::Destination destination;
|
| - if (CpuFeatures::IsSupported(VFP2)) {
|
| - destination = FloatingPointHelper::kVFPRegisters;
|
| - } else {
|
| - destination = FloatingPointHelper::kCoreRegisters;
|
| - }
|
| + destination = FloatingPointHelper::kVFPRegisters;
|
| FloatingPointHelper::ConvertIntToDouble(
|
| masm, r5, destination,
|
| d0, r6, r7, // These are: double_dst, dst_mantissa, dst_exponent.
|
| r4, s2); // These are: scratch2, single_scratch.
|
| - if (destination == FloatingPointHelper::kVFPRegisters) {
|
| - CpuFeatureScope scope(masm, VFP2);
|
| - __ vstr(d0, r3, 0);
|
| - } else {
|
| - __ str(r6, MemOperand(r3, 0));
|
| - __ str(r7, MemOperand(r3, Register::kSizeInBytes));
|
| - }
|
| + __ vstr(d0, r3, 0);
|
| break;
|
| case FAST_ELEMENTS:
|
| case FAST_SMI_ELEMENTS:
|
| @@ -3306,201 +3200,59 @@ void KeyedStoreStubCompiler::GenerateStoreExternalArray(
|
| // The WebGL specification leaves the behavior of storing NaN and
|
| // +/-Infinity into integer arrays basically undefined. For more
|
| // reproducible behavior, convert these to zero.
|
| - if (CpuFeatures::IsSupported(VFP2)) {
|
| - CpuFeatureScope scope(masm, VFP2);
|
| -
|
| - if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
| - // vldr requires offset to be a multiple of 4 so we can not
|
| - // include -kHeapObjectTag into it.
|
| - __ sub(r5, r0, Operand(kHeapObjectTag));
|
| - __ vldr(d0, r5, HeapNumber::kValueOffset);
|
| - __ add(r5, r3, Operand(key, LSL, 1));
|
| - __ vcvt_f32_f64(s0, d0);
|
| - __ vstr(s0, r5, 0);
|
| - } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
| - __ sub(r5, r0, Operand(kHeapObjectTag));
|
| - __ vldr(d0, r5, HeapNumber::kValueOffset);
|
| - __ add(r5, r3, Operand(key, LSL, 2));
|
| - __ vstr(d0, r5, 0);
|
| - } else {
|
| - // Hoisted load. vldr requires offset to be a multiple of 4 so we can
|
| - // not include -kHeapObjectTag into it.
|
| - __ sub(r5, value, Operand(kHeapObjectTag));
|
| - __ vldr(d0, r5, HeapNumber::kValueOffset);
|
| - __ ECMAToInt32VFP(r5, d0, d1, r6, r7, r9);
|
| -
|
| - switch (elements_kind) {
|
| - case EXTERNAL_BYTE_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ strb(r5, MemOperand(r3, key, LSR, 1));
|
| - break;
|
| - case EXTERNAL_SHORT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ strh(r5, MemOperand(r3, key, LSL, 0));
|
| - break;
|
| - case EXTERNAL_INT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ str(r5, MemOperand(r3, key, LSL, 1));
|
| - 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;
|
| - }
|
| - }
|
|
|
| - // Entry registers are intact, r0 holds the value which is the return
|
| - // value.
|
| - __ Ret();
|
| + if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
| + // vldr requires offset to be a multiple of 4 so we can not
|
| + // include -kHeapObjectTag into it.
|
| + __ sub(r5, r0, Operand(kHeapObjectTag));
|
| + __ vldr(d0, r5, HeapNumber::kValueOffset);
|
| + __ add(r5, r3, Operand(key, LSL, 1));
|
| + __ vcvt_f32_f64(s0, d0);
|
| + __ vstr(s0, r5, 0);
|
| + } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
| + __ sub(r5, r0, Operand(kHeapObjectTag));
|
| + __ vldr(d0, r5, HeapNumber::kValueOffset);
|
| + __ add(r5, r3, Operand(key, LSL, 2));
|
| + __ vstr(d0, r5, 0);
|
| } else {
|
| - // VFP3 is not available do manual conversions.
|
| - __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
|
| - __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
|
| -
|
| - if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) {
|
| - Label done, nan_or_infinity_or_zero;
|
| - static const int kMantissaInHiWordShift =
|
| - kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
|
| -
|
| - static const int kMantissaInLoWordShift =
|
| - kBitsPerInt - kMantissaInHiWordShift;
|
| -
|
| - // Test for all special exponent values: zeros, subnormal numbers, NaNs
|
| - // and infinities. All these should be converted to 0.
|
| - __ mov(r7, Operand(HeapNumber::kExponentMask));
|
| - __ and_(r9, r5, Operand(r7), SetCC);
|
| - __ b(eq, &nan_or_infinity_or_zero);
|
| -
|
| - __ teq(r9, Operand(r7));
|
| - __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
|
| - __ b(eq, &nan_or_infinity_or_zero);
|
| -
|
| - // Rebias exponent.
|
| - __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
|
| - __ add(r9,
|
| - r9,
|
| - Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
|
| -
|
| - __ cmp(r9, Operand(kBinary32MaxExponent));
|
| - __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
|
| - __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
|
| - __ b(gt, &done);
|
| -
|
| - __ cmp(r9, Operand(kBinary32MinExponent));
|
| - __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
|
| - __ b(lt, &done);
|
| -
|
| - __ and_(r7, r5, Operand(HeapNumber::kSignMask));
|
| - __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
|
| - __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
|
| - __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
|
| - __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
|
| -
|
| - __ bind(&done);
|
| - __ str(r5, MemOperand(r3, key, LSL, 1));
|
| - // Entry registers are intact, r0 holds the value which is the return
|
| - // value.
|
| - __ Ret();
|
| -
|
| - __ bind(&nan_or_infinity_or_zero);
|
| - __ and_(r7, r5, Operand(HeapNumber::kSignMask));
|
| - __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
|
| - __ orr(r9, r9, r7);
|
| - __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
|
| - __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
|
| - __ b(&done);
|
| - } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) {
|
| - __ add(r7, r3, Operand(key, LSL, 2));
|
| - // r7: effective address of destination element.
|
| - __ str(r6, MemOperand(r7, 0));
|
| - __ str(r5, MemOperand(r7, Register::kSizeInBytes));
|
| - __ Ret();
|
| - } else {
|
| - bool is_signed_type = IsElementTypeSigned(elements_kind);
|
| - int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
|
| - int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
|
| -
|
| - Label done, sign;
|
| -
|
| - // Test for all special exponent values: zeros, subnormal numbers, NaNs
|
| - // and infinities. All these should be converted to 0.
|
| - __ mov(r7, Operand(HeapNumber::kExponentMask));
|
| - __ and_(r9, r5, Operand(r7), SetCC);
|
| - __ mov(r5, Operand::Zero(), LeaveCC, eq);
|
| - __ b(eq, &done);
|
| -
|
| - __ teq(r9, Operand(r7));
|
| - __ mov(r5, Operand::Zero(), LeaveCC, eq);
|
| - __ b(eq, &done);
|
| -
|
| - // Unbias exponent.
|
| - __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
|
| - __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
|
| - // If exponent is negative then result is 0.
|
| - __ mov(r5, Operand::Zero(), LeaveCC, mi);
|
| - __ b(mi, &done);
|
| -
|
| - // If exponent is too big then result is minimal value.
|
| - __ cmp(r9, Operand(meaningfull_bits - 1));
|
| - __ mov(r5, Operand(min_value), LeaveCC, ge);
|
| - __ b(ge, &done);
|
| -
|
| - __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
|
| - __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
|
| - __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
|
| -
|
| - __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
|
| - __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
|
| - __ b(pl, &sign);
|
| -
|
| - __ rsb(r9, r9, Operand::Zero());
|
| - __ mov(r5, Operand(r5, LSL, r9));
|
| - __ rsb(r9, r9, Operand(meaningfull_bits));
|
| - __ orr(r5, r5, Operand(r6, LSR, r9));
|
| -
|
| - __ bind(&sign);
|
| - __ teq(r7, Operand::Zero());
|
| - __ rsb(r5, r5, Operand::Zero(), LeaveCC, ne);
|
| -
|
| - __ bind(&done);
|
| - switch (elements_kind) {
|
| - case EXTERNAL_BYTE_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| - __ strb(r5, MemOperand(r3, key, LSR, 1));
|
| - break;
|
| - case EXTERNAL_SHORT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| - __ strh(r5, MemOperand(r3, key, LSL, 0));
|
| - break;
|
| - case EXTERNAL_INT_ELEMENTS:
|
| - case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| - __ str(r5, MemOperand(r3, key, LSL, 1));
|
| - 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;
|
| - }
|
| + // Hoisted load. vldr requires offset to be a multiple of 4 so we can
|
| + // not include -kHeapObjectTag into it.
|
| + __ sub(r5, value, Operand(kHeapObjectTag));
|
| + __ vldr(d0, r5, HeapNumber::kValueOffset);
|
| + __ ECMAToInt32(r5, d0, d1, r6, r7, r9);
|
| +
|
| + switch (elements_kind) {
|
| + case EXTERNAL_BYTE_ELEMENTS:
|
| + case EXTERNAL_UNSIGNED_BYTE_ELEMENTS:
|
| + __ strb(r5, MemOperand(r3, key, LSR, 1));
|
| + break;
|
| + case EXTERNAL_SHORT_ELEMENTS:
|
| + case EXTERNAL_UNSIGNED_SHORT_ELEMENTS:
|
| + __ strh(r5, MemOperand(r3, key, LSL, 0));
|
| + break;
|
| + case EXTERNAL_INT_ELEMENTS:
|
| + case EXTERNAL_UNSIGNED_INT_ELEMENTS:
|
| + __ str(r5, MemOperand(r3, key, LSL, 1));
|
| + 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;
|
| }
|
| }
|
| +
|
| + // Entry registers are intact, r0 holds the value which is the return
|
| + // value.
|
| + __ Ret();
|
| }
|
|
|
| // Slow case, key and receiver still in r0 and r1.
|
|
|