Chromium Code Reviews| Index: src/arm/stub-cache-arm.cc |
| diff --git a/src/arm/stub-cache-arm.cc b/src/arm/stub-cache-arm.cc |
| index 675fdf49b23957adf20d95a26273c85345a55de0..7ea32cc9a714f1c887f065ae62359d8591680573 100644 |
| --- a/src/arm/stub-cache-arm.cc |
| +++ b/src/arm/stub-cache-arm.cc |
| @@ -3119,38 +3119,6 @@ MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { |
| } |
| -MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) { |
| - // ----------- S t a t e ------------- |
| - // -- lr : return address |
| - // -- r0 : key |
| - // -- r1 : receiver |
| - // ----------------------------------- |
| - Label miss; |
| - |
| - // Check that the map matches. |
| - __ CheckMap(r1, r2, Handle<Map>(receiver->map()), &miss, false); |
| - |
| - GenerateFastPixelArrayLoad(masm(), |
| - r1, |
| - r0, |
| - r2, |
| - r3, |
| - r4, |
| - r5, |
| - r0, |
| - &miss, |
| - &miss, |
| - &miss); |
| - |
| - __ bind(&miss); |
| - Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss)); |
| - __ Jump(ic, RelocInfo::CODE_TARGET); |
| - |
| - // Return the generated code. |
| - return GetCode(NORMAL, NULL); |
| -} |
| - |
| - |
| MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, |
| int index, |
| Map* transition, |
| @@ -3259,47 +3227,6 @@ MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( |
| } |
| -MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray( |
| - JSObject* receiver) { |
| - // ----------- S t a t e ------------- |
| - // -- r0 : value |
| - // -- r1 : key |
| - // -- r2 : receiver |
| - // -- r3 : scratch |
| - // -- r4 : scratch |
| - // -- r5 : scratch |
| - // -- r6 : scratch |
| - // -- lr : return address |
| - // ----------------------------------- |
| - Label miss; |
| - |
| - // Check that the map matches. |
| - __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false); |
| - |
| - GenerateFastPixelArrayStore(masm(), |
| - r2, |
| - r1, |
| - r0, |
| - r3, |
| - r4, |
| - r5, |
| - r6, |
| - true, |
| - true, |
| - &miss, |
| - &miss, |
| - NULL, |
| - &miss); |
| - |
| - __ bind(&miss); |
| - Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); |
| - __ Jump(ic, RelocInfo::CODE_TARGET); |
| - |
| - // Return the generated code. |
| - return GetCode(NORMAL, NULL); |
| -} |
| - |
| - |
| MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
| // ----------- S t a t e ------------- |
| // -- r0 : argc |
| @@ -3464,7 +3391,9 @@ static bool IsElementTypeSigned(ExternalArrayType array_type) { |
| MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| - ExternalArrayType array_type, Code::Flags flags) { |
| + JSObject* receiver_object, |
| + ExternalArrayType array_type, |
| + Code::Flags flags) { |
| // ---------- S t a t e -------------- |
| // -- lr : return address |
| // -- r0 : key |
| @@ -3481,24 +3410,13 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| // Check that the key is a smi. |
| __ JumpIfNotSmi(key, &slow); |
| - // Check that the object is a JS object. Load map into r2. |
| - __ CompareObjectType(receiver, r2, r3, FIRST_JS_OBJECT_TYPE); |
| - __ b(lt, &slow); |
| - |
| - // Check that the receiver does not require access checks. We need |
| - // to check this explicitly since this generic stub does not perform |
| - // map checks. |
| - __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset)); |
| - __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded)); |
| + // Make sure that we've got the right map. |
| + __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| + __ cmp(r2, Operand(Handle<Map>(receiver_object->map()))); |
| __ b(ne, &slow); |
| - // Check that the elements array is the appropriate type of |
| - // ExternalArray. |
| __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| - __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| - __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type)); |
| - __ cmp(r2, ip); |
| - __ b(ne, &slow); |
| + // r3: elements array |
| // Check that the index is in range. |
| __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); |
| @@ -3506,7 +3424,6 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| // Unsigned comparison catches both negative and too-large values. |
| __ b(lo, &slow); |
| - // r3: elements array |
| __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| // r3: base pointer of external storage |
| @@ -3519,6 +3436,7 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| case kExternalByteArray: |
| __ ldrsb(value, MemOperand(r3, key, LSR, 1)); |
| break; |
| + case kExternalPixelArray: |
| case kExternalUnsignedByteArray: |
| __ ldrb(value, MemOperand(r3, key, LSR, 1)); |
| break; |
| @@ -3744,7 +3662,9 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
| MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| - ExternalArrayType array_type, Code::Flags flags) { |
| + JSObject* receiver_object, |
| + ExternalArrayType array_type, |
| + Code::Flags flags) { |
| // ---------- S t a t e -------------- |
| // -- r0 : value |
| // -- r1 : key |
| @@ -3762,28 +3682,18 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| // Check that the object isn't a smi. |
| __ JumpIfSmi(receiver, &slow); |
| - // Check that the object is a JS object. Load map into r3. |
| - __ CompareObjectType(receiver, r3, r4, FIRST_JS_OBJECT_TYPE); |
| - __ b(le, &slow); |
| - |
| - // Check that the receiver does not require access checks. We need |
| - // to do this because this generic stub does not perform map checks. |
| - __ ldrb(ip, FieldMemOperand(r3, Map::kBitFieldOffset)); |
| - __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded)); |
| + // Make sure that we've got the right map. |
| + __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| + __ cmp(r3, Operand(Handle<Map>(receiver_object->map()))); |
| __ b(ne, &slow); |
| + __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| + |
| // Check that the key is a smi. |
| __ JumpIfNotSmi(key, &slow); |
| - // Check that the elements array is the appropriate type of ExternalArray. |
| - __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); |
| - __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); |
| - __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type)); |
| - __ cmp(r4, ip); |
| - __ b(ne, &slow); |
| - |
| - // Check that the index is in range. |
| - __ mov(r4, Operand(key, ASR, kSmiTagSize)); // Untag the index. |
| + // Check that the index is in range |
| + __ SmiUntag(r4, key); |
| __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); |
| __ cmp(r4, ip); |
| // Unsigned comparison catches both negative and too-large values. |
| @@ -3793,14 +3703,24 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| // runtime for all other kinds of values. |
| // r3: external array. |
| // r4: key (integer). |
| - __ JumpIfNotSmi(value, &check_heap_number); |
| - __ mov(r5, Operand(value, ASR, kSmiTagSize)); // Untag the value. |
| + if (array_type == kExternalPixelArray) { |
| + // Float to pixel conversion is only implemented in the runtime for now. |
|
Mads Ager (chromium)
2011/02/21 13:32:27
Float -> Double?
|
| + __ JumpIfNotSmi(value, &slow); |
| + } else { |
| + __ JumpIfNotSmi(value, &check_heap_number); |
| + } |
| + __ SmiUntag(r5, value); |
| __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| // r3: base pointer of external storage. |
| // r4: key (integer). |
| // r5: value (integer). |
| switch (array_type) { |
| + case kExternalPixelArray: |
| + // Clamp the value to [0..255]. |
| + __ Usat(r5, 8, Operand(r5)); |
| + __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| + break; |
| case kExternalByteArray: |
| case kExternalUnsignedByteArray: |
| __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| @@ -3825,198 +3745,200 @@ MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
| // Entry registers are intact, r0 holds the value which is the return value. |
| __ Ret(); |
| + if (array_type != kExternalPixelArray) { |
| + // r3: external array. |
| + // r4: index (integer). |
| + __ bind(&check_heap_number); |
| + __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); |
| + __ b(ne, &slow); |
| - // r3: external array. |
| - // r4: index (integer). |
| - __ bind(&check_heap_number); |
| - __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); |
| - __ b(ne, &slow); |
| + __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| - __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); |
| - |
| - // r3: base pointer of external storage. |
| - // r4: key (integer). |
| + // r3: base pointer of external storage. |
| + // r4: key (integer). |
| - // 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(VFP3)) { |
| - CpuFeatures::Scope scope(VFP3); |
| + // 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(VFP3)) { |
| + CpuFeatures::Scope scope(VFP3); |
| - if (array_type == kExternalFloatArray) { |
| - // 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(r4, LSL, 2)); |
| - __ vcvt_f32_f64(s0, d0); |
| - __ vstr(s0, r5, 0); |
| - } else { |
| - // Need to perform float-to-int conversion. |
| - // Test for NaN or infinity (both give zero). |
| - __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| - |
| - // 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); |
| - |
| - __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| - // NaNs and Infinities have all-one exponents so they sign extend to -1. |
| - __ cmp(r6, Operand(-1)); |
| - __ mov(r5, Operand(0), LeaveCC, eq); |
| - |
| - // Not infinity or NaN simply convert to int. |
| - if (IsElementTypeSigned(array_type)) { |
| - __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne); |
| + if (array_type == kExternalFloatArray) { |
| + // 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(r4, LSL, 2)); |
| + __ vcvt_f32_f64(s0, d0); |
| + __ vstr(s0, r5, 0); |
| } else { |
| - __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); |
| - } |
| - __ vmov(r5, s0, ne); |
| - |
| - switch (array_type) { |
| - case kExternalByteArray: |
| - case kExternalUnsignedByteArray: |
| - __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| - break; |
| - case kExternalShortArray: |
| - case kExternalUnsignedShortArray: |
| - __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| - break; |
| - case kExternalIntArray: |
| - case kExternalUnsignedIntArray: |
| - __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| - break; |
| - default: |
| - UNREACHABLE(); |
| - break; |
| + // Need to perform float-to-int conversion. |
| + // Test for NaN or infinity (both give zero). |
| + __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| + |
| + // 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); |
| + |
| + __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits); |
| + // NaNs and Infinities have all-one exponents so they sign extend to -1. |
| + __ cmp(r6, Operand(-1)); |
| + __ mov(r5, Operand(0), LeaveCC, eq); |
| + |
| + // Not infinity or NaN simply convert to int. |
| + if (IsElementTypeSigned(array_type)) { |
| + __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne); |
| + } else { |
| + __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); |
| + } |
| + __ vmov(r5, s0, ne); |
| + |
| + switch (array_type) { |
| + case kExternalByteArray: |
| + case kExternalUnsignedByteArray: |
| + __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| + break; |
| + case kExternalShortArray: |
| + case kExternalUnsignedShortArray: |
| + __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| + break; |
| + case kExternalIntArray: |
| + case kExternalUnsignedIntArray: |
| + __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| } |
| - } |
| - |
| - // Entry registers are intact, r0 holds the value which is the return value. |
| - __ Ret(); |
| - } else { |
| - // VFP3 is not available do manual conversions. |
| - __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| - __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
| - |
| - if (array_type == kExternalFloatArray) { |
| - 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, r4, LSL, 2)); |
| // 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 { |
| - bool is_signed_type = IsElementTypeSigned(array_type); |
| - 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(0, RelocInfo::NONE), LeaveCC, eq); |
| - __ b(eq, &done); |
| - |
| - __ teq(r9, Operand(r7)); |
| - __ mov(r5, Operand(0, RelocInfo::NONE), 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(0, RelocInfo::NONE), 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(0, RelocInfo::NONE)); |
| - __ mov(r5, Operand(r5, LSL, r9)); |
| - __ rsb(r9, r9, Operand(meaningfull_bits)); |
| - __ orr(r5, r5, Operand(r6, LSR, r9)); |
| - |
| - __ bind(&sign); |
| - __ teq(r7, Operand(0, RelocInfo::NONE)); |
| - __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| - |
| - __ bind(&done); |
| - switch (array_type) { |
| - case kExternalByteArray: |
| - case kExternalUnsignedByteArray: |
| - __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| - break; |
| - case kExternalShortArray: |
| - case kExternalUnsignedShortArray: |
| - __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| - break; |
| - case kExternalIntArray: |
| - case kExternalUnsignedIntArray: |
| - __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| - break; |
| - default: |
| - UNREACHABLE(); |
| - break; |
| + // VFP3 is not available do manual conversions. |
| + __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset)); |
| + __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset)); |
| + |
| + if (array_type == kExternalFloatArray) { |
| + 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, r4, LSL, 2)); |
| + // 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 { |
| + bool is_signed_type = IsElementTypeSigned(array_type); |
| + 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(0, RelocInfo::NONE), LeaveCC, eq); |
| + __ b(eq, &done); |
| + |
| + __ teq(r9, Operand(r7)); |
| + __ mov(r5, Operand(0, RelocInfo::NONE), 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(0, RelocInfo::NONE), 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(0, RelocInfo::NONE)); |
| + __ mov(r5, Operand(r5, LSL, r9)); |
| + __ rsb(r9, r9, Operand(meaningfull_bits)); |
| + __ orr(r5, r5, Operand(r6, LSR, r9)); |
| + |
| + __ bind(&sign); |
| + __ teq(r7, Operand(0, RelocInfo::NONE)); |
| + __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); |
| + |
| + __ bind(&done); |
| + switch (array_type) { |
| + case kExternalByteArray: |
| + case kExternalUnsignedByteArray: |
| + __ strb(r5, MemOperand(r3, r4, LSL, 0)); |
| + break; |
| + case kExternalShortArray: |
| + case kExternalUnsignedShortArray: |
| + __ strh(r5, MemOperand(r3, r4, LSL, 1)); |
| + break; |
| + case kExternalIntArray: |
| + case kExternalUnsignedIntArray: |
| + __ str(r5, MemOperand(r3, r4, LSL, 2)); |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + break; |
| + } |
| } |
| } |
| } |