Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: src/arm/codegen-arm.cc

Issue 2731007: Implement transcendental cache probing in generated code on ARM.... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 5069 matching lines...) Expand 10 before | Expand all | Expand 10 after
5080 Load(args->at(i + 1)); 5080 Load(args->at(i + 1));
5081 } 5081 }
5082 Load(args->at(n_args + 1)); // function 5082 Load(args->at(n_args + 1)); // function
5083 frame_->CallJSFunction(n_args); 5083 frame_->CallJSFunction(n_args);
5084 frame_->EmitPush(r0); 5084 frame_->EmitPush(r0);
5085 } 5085 }
5086 5086
5087 5087
5088 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) { 5088 void CodeGenerator::GenerateMathSin(ZoneList<Expression*>* args) {
5089 ASSERT_EQ(args->length(), 1); 5089 ASSERT_EQ(args->length(), 1);
5090 // Load the argument on the stack and jump to the runtime.
5091 Load(args->at(0)); 5090 Load(args->at(0));
5092 frame_->CallRuntime(Runtime::kMath_sin, 1); 5091 if (CpuFeatures::IsSupported(VFP3)) {
5092 TranscendentalCacheStub stub(TranscendentalCache::SIN);
5093 frame_->SpillAllButCopyTOSToR0();
5094 frame_->CallStub(&stub, 1);
5095 } else {
5096 frame_->CallRuntime(Runtime::kMath_sin, 1);
5097 }
5093 frame_->EmitPush(r0); 5098 frame_->EmitPush(r0);
5094 } 5099 }
5095 5100
5096 5101
5097 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) { 5102 void CodeGenerator::GenerateMathCos(ZoneList<Expression*>* args) {
5098 ASSERT_EQ(args->length(), 1); 5103 ASSERT_EQ(args->length(), 1);
5099 // Load the argument on the stack and jump to the runtime.
5100 Load(args->at(0)); 5104 Load(args->at(0));
5101 frame_->CallRuntime(Runtime::kMath_cos, 1); 5105 if (CpuFeatures::IsSupported(VFP3)) {
5106 TranscendentalCacheStub stub(TranscendentalCache::COS);
5107 frame_->SpillAllButCopyTOSToR0();
5108 frame_->CallStub(&stub, 1);
5109 } else {
5110 frame_->CallRuntime(Runtime::kMath_cos, 1);
5111 }
5102 frame_->EmitPush(r0); 5112 frame_->EmitPush(r0);
5103 } 5113 }
5104 5114
5105 5115
5106 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) { 5116 void CodeGenerator::GenerateObjectEquals(ZoneList<Expression*>* args) {
5107 ASSERT(args->length() == 2); 5117 ASSERT(args->length() == 2);
5108 5118
5109 // Load the two objects into registers and perform the comparison. 5119 // Load the two objects into registers and perform the comparison.
5110 Load(args->at(0)); 5120 Load(args->at(0));
5111 Load(args->at(1)); 5121 Load(args->at(1));
(...skipping 1971 matching lines...) Expand 10 before | Expand all | Expand 10 after
7083 // doubles is the xor of the upper and lower words. See 7093 // doubles is the xor of the upper and lower words. See
7084 // Heap::GetNumberStringCache. 7094 // Heap::GetNumberStringCache.
7085 Label is_smi; 7095 Label is_smi;
7086 Label load_result_from_cache; 7096 Label load_result_from_cache;
7087 if (!object_is_smi) { 7097 if (!object_is_smi) {
7088 __ BranchOnSmi(object, &is_smi); 7098 __ BranchOnSmi(object, &is_smi);
7089 if (CpuFeatures::IsSupported(VFP3)) { 7099 if (CpuFeatures::IsSupported(VFP3)) {
7090 CpuFeatures::Scope scope(VFP3); 7100 CpuFeatures::Scope scope(VFP3);
7091 __ CheckMap(object, 7101 __ CheckMap(object,
7092 scratch1, 7102 scratch1,
7093 Factory::heap_number_map(), 7103 Heap::kHeapNumberMapRootIndex,
7094 not_found, 7104 not_found,
7095 true); 7105 true);
7096 7106
7097 ASSERT_EQ(8, kDoubleSize); 7107 ASSERT_EQ(8, kDoubleSize);
7098 __ add(scratch1, 7108 __ add(scratch1,
7099 object, 7109 object,
7100 Operand(HeapNumber::kValueOffset - kHeapObjectTag)); 7110 Operand(HeapNumber::kValueOffset - kHeapObjectTag));
7101 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit()); 7111 __ ldm(ia, scratch1, scratch1.bit() | scratch2.bit());
7102 __ eor(scratch1, scratch1, Operand(scratch2)); 7112 __ eor(scratch1, scratch1, Operand(scratch2));
7103 __ and_(scratch1, scratch1, Operand(mask)); 7113 __ and_(scratch1, scratch1, Operand(mask));
(...skipping 1125 matching lines...) Expand 10 before | Expand all | Expand 10 after
8229 __ bind(&get_result); 8239 __ bind(&get_result);
8230 } 8240 }
8231 8241
8232 8242
8233 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) { 8243 Handle<Code> GetBinaryOpStub(int key, BinaryOpIC::TypeInfo type_info) {
8234 GenericBinaryOpStub stub(key, type_info); 8244 GenericBinaryOpStub stub(key, type_info);
8235 return stub.GetCode(); 8245 return stub.GetCode();
8236 } 8246 }
8237 8247
8238 8248
8249 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
8250 // Argument is a number and is on stack and in r0.
8251 Label runtime_call;
8252 Label input_not_smi;
8253 Label loaded;
8254
8255 if (CpuFeatures::IsSupported(VFP3)) {
8256 // Load argument and check if it is a smi.
8257 __ BranchOnNotSmi(r0, &input_not_smi);
8258
8259 CpuFeatures::Scope scope(VFP3);
8260 // Input is a smi. Convert to double and load the low and high words
8261 // of the double into r2, r3.
8262 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
8263 __ b(&loaded);
8264
8265 __ bind(&input_not_smi);
8266 // Check if input is a HeapNumber.
8267 __ CheckMap(r0,
8268 r1,
8269 Heap::kHeapNumberMapRootIndex,
8270 &runtime_call,
8271 true);
8272 // Input is a HeapNumber. Load it to a double register and store the
8273 // low and high words into r2, r3.
8274 __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset));
8275
8276 __ bind(&loaded);
8277 // r2 = low 32 bits of double value
8278 // r3 = high 32 bits of double value
8279 // Compute hash:
8280 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
8281 __ eor(r1, r2, Operand(r2));
8282 __ eor(r1, r1, Operand(r1, LSR, 16));
8283 __ eor(r1, r1, Operand(r1, LSR, 8));
8284 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
8285 if (CpuFeatures::IsSupported(ARMv7)) {
8286 const int kTranscendentalCacheSizeBits = 9;
8287 ASSERT_EQ(1 << kTranscendentalCacheSizeBits,
8288 TranscendentalCache::kCacheSize);
8289 __ ubfx(r1, r1, 0, kTranscendentalCacheSizeBits);
8290 } else {
8291 __ and_(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
8292 }
8293
8294 // r2 = low 32 bits of double value.
8295 // r3 = high 32 bits of double value.
8296 // r1 = TranscendentalCache::hash(double value).
8297 __ mov(r0,
8298 Operand(ExternalReference::transcendental_cache_array_address()));
8299 // r0 points to cache array.
8300 __ ldr(r0, MemOperand(r0, type_ * sizeof(TranscendentalCache::caches_[0])));
8301 // r0 points to the cache for the type type_.
8302 // If NULL, the cache hasn't been initialized yet, so go through runtime.
8303 __ cmp(r0, Operand(0));
8304 __ b(eq, &runtime_call);
8305
8306 #ifdef DEBUG
8307 // Check that the layout of cache elements match expectations.
8308 { TranscendentalCache::Element test_elem[2];
8309 char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
8310 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
8311 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
8312 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
8313 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
8314 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
8315 CHECK_EQ(0, elem_in0 - elem_start);
8316 CHECK_EQ(kIntSize, elem_in1 - elem_start);
8317 CHECK_EQ(2 * kIntSize, elem_out - elem_start);
8318 }
8319 #endif
8320
8321 // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12].
8322 __ add(r1, r1, Operand(r1, LSL, 1));
8323 __ add(r0, r0, Operand(r1, LSL, 2));
8324 // Check if cache matches: Double value is stored in uint32_t[2] array.
8325 __ ldm(ia, r0, r4.bit()| r5.bit() | r6.bit());
8326 __ cmp(r2, r4);
8327 __ b(ne, &runtime_call);
8328 __ cmp(r3, r5);
8329 __ b(ne, &runtime_call);
8330 // Cache hit. Load result, pop argument and return.
8331 __ mov(r0, Operand(r6));
8332 __ pop();
8333 __ Ret();
8334 }
8335
8336 __ bind(&runtime_call);
8337 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
8338 }
8339
8340
8341 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
8342 switch (type_) {
8343 // Add more cases when necessary.
8344 case TranscendentalCache::SIN: return Runtime::kMath_sin;
8345 case TranscendentalCache::COS: return Runtime::kMath_cos;
8346 default:
8347 UNIMPLEMENTED();
8348 return Runtime::kAbort;
8349 }
8350 }
8351
8352
8239 void StackCheckStub::Generate(MacroAssembler* masm) { 8353 void StackCheckStub::Generate(MacroAssembler* masm) {
8240 // Do tail-call to runtime routine. Runtime routines expect at least one 8354 // Do tail-call to runtime routine. Runtime routines expect at least one
8241 // argument, so give it a Smi. 8355 // argument, so give it a Smi.
8242 __ mov(r0, Operand(Smi::FromInt(0))); 8356 __ mov(r0, Operand(Smi::FromInt(0)));
8243 __ push(r0); 8357 __ push(r0);
8244 __ TailCallRuntime(Runtime::kStackGuard, 1, 1); 8358 __ TailCallRuntime(Runtime::kStackGuard, 1, 1);
8245 8359
8246 __ StubReturn(1); 8360 __ StubReturn(1);
8247 } 8361 }
8248 8362
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after
9543 } 9657 }
9544 9658
9545 9659
9546 void StringCharCodeAtGenerator::GenerateSlow( 9660 void StringCharCodeAtGenerator::GenerateSlow(
9547 MacroAssembler* masm, const RuntimeCallHelper& call_helper) { 9661 MacroAssembler* masm, const RuntimeCallHelper& call_helper) {
9548 __ Abort("Unexpected fallthrough to CharCodeAt slow case"); 9662 __ Abort("Unexpected fallthrough to CharCodeAt slow case");
9549 9663
9550 // Index is not a smi. 9664 // Index is not a smi.
9551 __ bind(&index_not_smi_); 9665 __ bind(&index_not_smi_);
9552 // If index is a heap number, try converting it to an integer. 9666 // If index is a heap number, try converting it to an integer.
9553 __ CheckMap(index_, scratch_, 9667 __ CheckMap(index_,
9554 Factory::heap_number_map(), index_not_number_, true); 9668 scratch_,
9669 Heap::kHeapNumberMapRootIndex,
9670 index_not_number_,
9671 true);
9555 call_helper.BeforeCall(masm); 9672 call_helper.BeforeCall(masm);
9556 __ Push(object_, index_); 9673 __ Push(object_, index_);
9557 __ push(index_); // Consumed by runtime conversion function. 9674 __ push(index_); // Consumed by runtime conversion function.
9558 if (index_flags_ == STRING_INDEX_IS_NUMBER) { 9675 if (index_flags_ == STRING_INDEX_IS_NUMBER) {
9559 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1); 9676 __ CallRuntime(Runtime::kNumberToIntegerMapMinusZero, 1);
9560 } else { 9677 } else {
9561 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX); 9678 ASSERT(index_flags_ == STRING_INDEX_IS_ARRAY_INDEX);
9562 // NumberToSmi discards numbers that are not exact integers. 9679 // NumberToSmi discards numbers that are not exact integers.
9563 __ CallRuntime(Runtime::kNumberToSmi, 1); 9680 __ CallRuntime(Runtime::kNumberToSmi, 1);
9564 } 9681 }
(...skipping 973 matching lines...) Expand 10 before | Expand all | Expand 10 after
10538 __ bind(&string_add_runtime); 10655 __ bind(&string_add_runtime);
10539 __ TailCallRuntime(Runtime::kStringAdd, 2, 1); 10656 __ TailCallRuntime(Runtime::kStringAdd, 2, 1);
10540 } 10657 }
10541 10658
10542 10659
10543 #undef __ 10660 #undef __
10544 10661
10545 } } // namespace v8::internal 10662 } } // namespace v8::internal
10546 10663
10547 #endif // V8_TARGET_ARCH_ARM 10664 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/codegen-arm.h ('k') | src/ia32/codegen-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698