| Index: src/arm/codegen-arm.cc
|
| ===================================================================
|
| --- src/arm/codegen-arm.cc (revision 4842)
|
| +++ src/arm/codegen-arm.cc (working copy)
|
| @@ -5087,18 +5087,28 @@
|
|
|
| void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
|
| ASSERT_EQ(args->length(), 1);
|
| - // Load the argument on the stack and jump to the runtime.
|
| Load(args->at(0));
|
| - frame_->CallRuntime(Runtime::kMath_sin, 1);
|
| + if (CpuFeatures::IsSupported(VFP3)) {
|
| + TranscendentalCacheStub stub(TranscendentalCache::SIN);
|
| + frame_->SpillAllButCopyTOSToR0();
|
| + frame_->CallStub(&stub, 1);
|
| + } else {
|
| + frame_->CallRuntime(Runtime::kMath_sin, 1);
|
| + }
|
| frame_->EmitPush(r0);
|
| }
|
|
|
|
|
| void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
|
| ASSERT_EQ(args->length(), 1);
|
| - // Load the argument on the stack and jump to the runtime.
|
| Load(args->at(0));
|
| - frame_->CallRuntime(Runtime::kMath_cos, 1);
|
| + if (CpuFeatures::IsSupported(VFP3)) {
|
| + TranscendentalCacheStub stub(TranscendentalCache::COS);
|
| + frame_->SpillAllButCopyTOSToR0();
|
| + frame_->CallStub(&stub, 1);
|
| + } else {
|
| + frame_->CallRuntime(Runtime::kMath_cos, 1);
|
| + }
|
| frame_->EmitPush(r0);
|
| }
|
|
|
| @@ -7090,7 +7100,7 @@
|
| CpuFeatures::Scope scope(VFP3);
|
| __ CheckMap(object,
|
| scratch1,
|
| - Factory::heap_number_map(),
|
| + Heap::kHeapNumberMapRootIndex,
|
| not_found,
|
| true);
|
|
|
| @@ -8236,6 +8246,110 @@
|
| }
|
|
|
|
|
| +void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
|
| + // Argument is a number and is on stack and in r0.
|
| + Label runtime_call;
|
| + Label input_not_smi;
|
| + Label loaded;
|
| +
|
| + if (CpuFeatures::IsSupported(VFP3)) {
|
| + // Load argument and check if it is a smi.
|
| + __ BranchOnNotSmi(r0, &input_not_smi);
|
| +
|
| + CpuFeatures::Scope scope(VFP3);
|
| + // Input is a smi. Convert to double and load the low and high words
|
| + // of the double into r2, r3.
|
| + __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
|
| + __ b(&loaded);
|
| +
|
| + __ bind(&input_not_smi);
|
| + // Check if input is a HeapNumber.
|
| + __ CheckMap(r0,
|
| + r1,
|
| + Heap::kHeapNumberMapRootIndex,
|
| + &runtime_call,
|
| + true);
|
| + // Input is a HeapNumber. Load it to a double register and store the
|
| + // low and high words into r2, r3.
|
| + __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset));
|
| +
|
| + __ bind(&loaded);
|
| + // r2 = low 32 bits of double value
|
| + // r3 = high 32 bits of double value
|
| + // Compute hash:
|
| + // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
|
| + __ eor(r1, r2, Operand(r2));
|
| + __ eor(r1, r1, Operand(r1, LSR, 16));
|
| + __ eor(r1, r1, Operand(r1, LSR, 8));
|
| + ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
|
| + if (CpuFeatures::IsSupported(ARMv7)) {
|
| + const int kTranscendentalCacheSizeBits = 9;
|
| + ASSERT_EQ(1 << kTranscendentalCacheSizeBits,
|
| + TranscendentalCache::kCacheSize);
|
| + __ ubfx(r1, r1, 0, kTranscendentalCacheSizeBits);
|
| + } else {
|
| + __ and_(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
|
| + }
|
| +
|
| + // r2 = low 32 bits of double value.
|
| + // r3 = high 32 bits of double value.
|
| + // r1 = TranscendentalCache::hash(double value).
|
| + __ mov(r0,
|
| + Operand(ExternalReference::transcendental_cache_array_address()));
|
| + // r0 points to cache array.
|
| + __ ldr(r0, MemOperand(r0, type_ * sizeof(TranscendentalCache::caches_[0])));
|
| + // r0 points to the cache for the type type_.
|
| + // If NULL, the cache hasn't been initialized yet, so go through runtime.
|
| + __ cmp(r0, Operand(0));
|
| + __ b(eq, &runtime_call);
|
| +
|
| +#ifdef DEBUG
|
| + // Check that the layout of cache elements match expectations.
|
| + { TranscendentalCache::Element test_elem[2];
|
| + char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
|
| + char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
|
| + char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
|
| + char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
|
| + char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
|
| + CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
|
| + CHECK_EQ(0, elem_in0 - elem_start);
|
| + CHECK_EQ(kIntSize, elem_in1 - elem_start);
|
| + CHECK_EQ(2 * kIntSize, elem_out - elem_start);
|
| + }
|
| +#endif
|
| +
|
| + // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12].
|
| + __ add(r1, r1, Operand(r1, LSL, 1));
|
| + __ add(r0, r0, Operand(r1, LSL, 2));
|
| + // Check if cache matches: Double value is stored in uint32_t[2] array.
|
| + __ ldm(ia, r0, r4.bit()| r5.bit() | r6.bit());
|
| + __ cmp(r2, r4);
|
| + __ b(ne, &runtime_call);
|
| + __ cmp(r3, r5);
|
| + __ b(ne, &runtime_call);
|
| + // Cache hit. Load result, pop argument and return.
|
| + __ mov(r0, Operand(r6));
|
| + __ pop();
|
| + __ Ret();
|
| + }
|
| +
|
| + __ bind(&runtime_call);
|
| + __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
|
| +}
|
| +
|
| +
|
| +Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
|
| + switch (type_) {
|
| + // Add more cases when necessary.
|
| + case TranscendentalCache::SIN: return Runtime::kMath_sin;
|
| + case TranscendentalCache::COS: return Runtime::kMath_cos;
|
| + default:
|
| + UNIMPLEMENTED();
|
| + return Runtime::kAbort;
|
| + }
|
| +}
|
| +
|
| +
|
| void StackCheckStub::Generate(MacroAssembler* masm) {
|
| // Do tail-call to runtime routine. Runtime routines expect at least one
|
| // argument, so give it a Smi.
|
| @@ -9550,8 +9664,11 @@
|
| // Index is not a smi.
|
| __ bind(&index_not_smi_);
|
| // If index is a heap number, try converting it to an integer.
|
| - __ CheckMap(index_, scratch_,
|
| - Factory::heap_number_map(), index_not_number_, true);
|
| + __ CheckMap(index_,
|
| + scratch_,
|
| + Heap::kHeapNumberMapRootIndex,
|
| + index_not_number_,
|
| + true);
|
| call_helper.BeforeCall(masm);
|
| __ Push(object_, index_);
|
| __ push(index_); // Consumed by runtime conversion function.
|
|
|