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

Side by Side Diff: src/arm/code-stubs-arm.cc

Issue 6591073: ARM: Implement untagged input for TranscendentalCacheStub. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 9 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/code-stubs-arm.h ('k') | src/arm/codegen-arm.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 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 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 3054 matching lines...) Expand 10 before | Expand all | Expand 10 after
3065 } 3065 }
3066 } 3066 }
3067 3067
3068 3068
3069 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) { 3069 void TypeRecordingBinaryOpStub::GenerateRegisterArgsPush(MacroAssembler* masm) {
3070 __ Push(r1, r0); 3070 __ Push(r1, r0);
3071 } 3071 }
3072 3072
3073 3073
3074 void TranscendentalCacheStub::Generate(MacroAssembler* masm) { 3074 void TranscendentalCacheStub::Generate(MacroAssembler* masm) {
3075 // Argument is a number and is on stack and in r0.
3076 Label runtime_call;
3077 Label input_not_smi; 3075 Label input_not_smi;
3078 Label loaded; 3076 Label loaded;
3077 Label runtime_call;
3078 Label invalid_cache;
3079 const Register scratch0 = r9;
3080 const Register scratch1 = r10;
Søren Thygesen Gjesse 2011/03/02 10:09:45 As discussed offline using r10 here is might be th
Karl Klose 2011/03/02 11:16:41 Yes, it is. Used different register.
3081 const Register tagged_input = r7;
3082 const bool tagged = (argument_type_ == TAGGED);
3079 3083
3080 if (CpuFeatures::IsSupported(VFP3)) { 3084 if (CpuFeatures::IsSupported(VFP3)) {
3081 // Load argument and check if it is a smi. 3085 CpuFeatures::Scope scope(VFP3);
3082 __ JumpIfNotSmi(r0, &input_not_smi); 3086 if (tagged) {
3087 // Argument is a number and is on stack and in r0.
3088 // Load argument and check if it is a smi.
3089 __ JumpIfNotSmi(r0, &input_not_smi);
3083 3090
3084 CpuFeatures::Scope scope(VFP3); 3091 CpuFeatures::Scope scope(VFP3);
Søren Thygesen Gjesse 2011/03/02 10:09:45 Duplicate CpuFeatures::Scope.
Karl Klose 2011/03/02 11:16:41 Done, removed.
3085 // Input is a smi. Convert to double and load the low and high words 3092 // Input is a smi. Convert to double and load the low and high words
3086 // of the double into r2, r3. 3093 // of the double into r2, r3.
3087 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2); 3094 __ IntegerToDoubleConversionWithVFP3(r0, r3, r2);
3088 __ b(&loaded); 3095 __ b(&loaded);
3089 3096
3090 __ bind(&input_not_smi); 3097 __ bind(&input_not_smi);
3091 // Check if input is a HeapNumber. 3098 // Check if input is a HeapNumber.
3092 __ CheckMap(r0, 3099 __ CheckMap(r0,
3093 r1, 3100 r1,
3094 Heap::kHeapNumberMapRootIndex, 3101 Heap::kHeapNumberMapRootIndex,
3095 &runtime_call, 3102 &runtime_call,
3096 true); 3103 true);
3097 // Input is a HeapNumber. Load it to a double register and store the 3104 // Input is a HeapNumber. Load it to a double register and store the
3098 // low and high words into r2, r3. 3105 // low and high words into r2, r3.
3099 __ Ldrd(r2, r3, FieldMemOperand(r0, HeapNumber::kValueOffset)); 3106 __ vldr(d0, FieldMemOperand(r0, HeapNumber::kValueOffset));
3100 3107 __ vmov(r2, r3, d0);
3108 } else {
3109 // Input is untagged double in d2. Output goes to d2.
3110 __ vmov(r2, r3, d2);
3111 }
3101 __ bind(&loaded); 3112 __ bind(&loaded);
3102 // r2 = low 32 bits of double value 3113 // r2 = low 32 bits of double value
3103 // r3 = high 32 bits of double value 3114 // r3 = high 32 bits of double value
3104 // Compute hash (the shifts are arithmetic): 3115 // Compute hash (the shifts are arithmetic):
3105 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1); 3116 // h = (low ^ high); h ^= h >> 16; h ^= h >> 8; h = h & (cacheSize - 1);
3106 __ eor(r1, r2, Operand(r3)); 3117 __ eor(r1, r2, Operand(r3));
3107 __ eor(r1, r1, Operand(r1, ASR, 16)); 3118 __ eor(r1, r1, Operand(r1, ASR, 16));
3108 __ eor(r1, r1, Operand(r1, ASR, 8)); 3119 __ eor(r1, r1, Operand(r1, ASR, 8));
3109 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize)); 3120 ASSERT(IsPowerOf2(TranscendentalCache::kCacheSize));
3110 __ And(r1, r1, Operand(TranscendentalCache::kCacheSize - 1)); 3121 __ And(r1, r1, Operand(TranscendentalCache::kCacheSize - 1));
3111 3122
3112 // r2 = low 32 bits of double value. 3123 // r2 = low 32 bits of double value.
3113 // r3 = high 32 bits of double value. 3124 // r3 = high 32 bits of double value.
3114 // r1 = TranscendentalCache::hash(double value). 3125 // r1 = TranscendentalCache::hash(double value).
3115 __ mov(r0, 3126 __ mov(r0,
3116 Operand(ExternalReference::transcendental_cache_array_address())); 3127 Operand(ExternalReference::transcendental_cache_array_address()));
3117 // r0 points to cache array. 3128 // r0 points to cache array.
3118 __ ldr(r0, MemOperand(r0, type_ * sizeof(TranscendentalCache::caches_[0]))); 3129 __ ldr(r0, MemOperand(r0, type_ * sizeof(TranscendentalCache::caches_[0])));
3119 // r0 points to the cache for the type type_. 3130 // r0 points to the cache for the type type_.
3120 // If NULL, the cache hasn't been initialized yet, so go through runtime. 3131 // If NULL, the cache hasn't been initialized yet, so go through runtime.
3121 __ cmp(r0, Operand(0, RelocInfo::NONE)); 3132 __ cmp(r0, Operand(0, RelocInfo::NONE));
3122 __ b(eq, &runtime_call); 3133 __ b(eq, &invalid_cache);
3123 3134
3124 #ifdef DEBUG 3135 #ifdef DEBUG
3125 // Check that the layout of cache elements match expectations. 3136 // Check that the layout of cache elements match expectations.
3126 { TranscendentalCache::Element test_elem[2]; 3137 { TranscendentalCache::Element test_elem[2];
3127 char* elem_start = reinterpret_cast<char*>(&test_elem[0]); 3138 char* elem_start = reinterpret_cast<char*>(&test_elem[0]);
3128 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]); 3139 char* elem2_start = reinterpret_cast<char*>(&test_elem[1]);
3129 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0])); 3140 char* elem_in0 = reinterpret_cast<char*>(&(test_elem[0].in[0]));
3130 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1])); 3141 char* elem_in1 = reinterpret_cast<char*>(&(test_elem[0].in[1]));
3131 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output)); 3142 char* elem_out = reinterpret_cast<char*>(&(test_elem[0].output));
3132 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer. 3143 CHECK_EQ(12, elem2_start - elem_start); // Two uint_32's and a pointer.
3133 CHECK_EQ(0, elem_in0 - elem_start); 3144 CHECK_EQ(0, elem_in0 - elem_start);
3134 CHECK_EQ(kIntSize, elem_in1 - elem_start); 3145 CHECK_EQ(kIntSize, elem_in1 - elem_start);
3135 CHECK_EQ(2 * kIntSize, elem_out - elem_start); 3146 CHECK_EQ(2 * kIntSize, elem_out - elem_start);
3136 } 3147 }
3137 #endif 3148 #endif
3138 3149
3139 // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12]. 3150 // Find the address of the r1'st entry in the cache, i.e., &r0[r1*12].
3140 __ add(r1, r1, Operand(r1, LSL, 1)); 3151 __ add(r1, r1, Operand(r1, LSL, 1));
3141 __ add(r0, r0, Operand(r1, LSL, 2)); 3152 __ add(r0, r0, Operand(r1, LSL, 2));
3142 // Check if cache matches: Double value is stored in uint32_t[2] array. 3153 // Check if cache matches: Double value is stored in uint32_t[2] array.
3143 __ ldm(ia, r0, r4.bit()| r5.bit() | r6.bit()); 3154 __ ldm(ia, r0, r4.bit() | r5.bit() | r6.bit());
3144 __ cmp(r2, r4); 3155 __ cmp(r2, r4);
3145 __ b(ne, &runtime_call); 3156 __ b(ne, &runtime_call);
3146 __ cmp(r3, r5); 3157 __ cmp(r3, r5);
3147 __ b(ne, &runtime_call); 3158 __ b(ne, &runtime_call);
3148 // Cache hit. Load result, pop argument and return. 3159 // Cache hit. Load result, cleanup and return.
3149 __ mov(r0, Operand(r6)); 3160 if (tagged) {
3150 __ pop(); 3161 // Pop input value from stack and load result into r0.
3162 __ pop();
3163 __ mov(r0, Operand(r6));
3164 } else {
3165 //__ stop("cache hit");
Søren Thygesen Gjesse 2011/03/02 10:09:45 Debug code.
Karl Klose 2011/03/02 11:16:41 Done.
3166 // Load result into d2.
3167 __ vldr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
3168 }
3169 __ Ret();
3170 } // if (CpuFeatures::IsSupported(VFP3))
Søren Thygesen Gjesse 2011/03/02 10:09:45 Two spaces before //.
Karl Klose 2011/03/02 11:16:41 Done.
3171
3172 __ bind(&runtime_call);
Søren Thygesen Gjesse 2011/03/02 10:09:45 Maybe the name of this label should be "calculate"
Karl Klose 2011/03/02 11:16:41 Done.
3173 if (tagged) {
3174 __ bind(&invalid_cache);
3175 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
3176 } else {
3177 if (!CpuFeatures::IsSupported(VFP3)) UNREACHABLE();
3178 CpuFeatures::Scope scope(VFP3);
3179
3180 Register cache_entry = r0;
3181 Register heap_number_map = r5;
3182 Label no_update;
3183 Label skip_cache;
3184
3185 // Call C function to calculate the result and update the cache.
3186 __ push(r0);
Søren Thygesen Gjesse 2011/03/02 10:09:45 r0 -> cache_entry
Karl Klose 2011/03/02 11:16:41 Done.
3187 __ push(lr);
Søren Thygesen Gjesse 2011/03/02 10:09:45 The code for calling the C functions are repeated.
Karl Klose 2011/03/02 11:16:41 Done.
3188 __ PrepareCallCFunction(2, scratch0);
3189 __ vmov(r0, r1, d2);
3190 switch(type_) {
3191 case TranscendentalCache::SIN:
3192 __ CallCFunction(ExternalReference::math_sin_double_function(), 2);
3193 break;
3194 case TranscendentalCache::COS:
3195 __ CallCFunction(ExternalReference::math_cos_double_function(), 2);
3196 break;
3197 case TranscendentalCache::LOG:
3198 __ CallCFunction(ExternalReference::math_log_double_function(), 2);
3199 break;
3200 default:
3201 UNIMPLEMENTED();
3202 break;
3203 }
3204 __ pop(lr);
3205 __ GetCFunctionDoubleResult(d2);
3206
3207 // Try to update the cache.
3208 __ pop(cache_entry);
3209
3210 // Check if the cache is valid.
3211 __ cmp(r0, Operand(0, RelocInfo::NONE));
3212 __ b(&no_update, eq);
3213 __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
3214 __ AllocateHeapNumber(r6, scratch0, scratch1, r5, &no_update);
3215 __ vstr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
3216 __ stm(ia, cache_entry, r2.bit() | r3.bit() | r6.bit());
3217 __ bind(&no_update);
3218 __ Ret();
3219
3220 __ bind(&skip_cache);
3221 // Call C function to calculate the result and answer directly
3222 // without updating the cache.
3223 __ push(lr);
3224 __ PrepareCallCFunction(2, scratch0);
3225 __ vmov(r0, r1, d2);
3226 switch(type_) {
3227 case TranscendentalCache::SIN:
3228 __ CallCFunction(ExternalReference::math_sin_double_function(), 2);
3229 break;
3230 case TranscendentalCache::COS:
3231 __ CallCFunction(ExternalReference::math_cos_double_function(), 2);
3232 break;
3233 case TranscendentalCache::LOG:
3234 __ CallCFunction(ExternalReference::math_log_double_function(), 2);
3235 break;
3236 default:
3237 UNIMPLEMENTED();
3238 break;
3239 }
3240 __ pop(lr);
3241 __ GetCFunctionDoubleResult(d2);
3242 // We return the value in d2 without adding it to the cache, but
3243 // we cause a scavenging GC so that future allocations will succeed.
3244 __ EnterInternalFrame();
3245 // Allocate an unused object bigger than a HeapNumber.
3246 __ mov(scratch0, Operand(Smi::FromInt(2 * kDoubleSize)));
Søren Thygesen Gjesse 2011/03/02 10:09:45 Shouldn't HeapNumber::kSize be enough? Allocating
Karl Klose 2011/03/02 11:16:41 Done.
3247 __ push(scratch0);
3248 __ CallRuntimeSaveDoubles(Runtime::kAllocateInNewSpace);
3249 __ LeaveInternalFrame();
3250 __ Ret();
3251
3252 __ bind(&invalid_cache);
3253 // The cache is invalid. Call runtime which will recreate the
3254 // cache.
3255 __ LoadRoot(r5, Heap::kHeapNumberMapRootIndex);
3256 __ AllocateHeapNumber(r6, scratch0, scratch1, r5, &skip_cache);
Søren Thygesen Gjesse 2011/03/02 10:09:45 Any reason for having the skip cache code before t
Karl Klose 2011/03/02 11:16:41 There is no reason. I changed the order.
3257 __ vstr(d2, FieldMemOperand(r6, HeapNumber::kValueOffset));
3258 __ EnterInternalFrame();
3259 __ push(r6);
3260 __ CallRuntime(RuntimeFunction(), 1);
3261 __ LeaveInternalFrame();
3262 __ vldr(d2, FieldMemOperand(r0, HeapNumber::kValueOffset));
3151 __ Ret(); 3263 __ Ret();
3152 } 3264 }
3153
3154 __ bind(&runtime_call);
3155 __ TailCallExternalReference(ExternalReference(RuntimeFunction()), 1, 1);
3156 } 3265 }
3157 3266
3158 3267
3159 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() { 3268 Runtime::FunctionId TranscendentalCacheStub::RuntimeFunction() {
3160 switch (type_) { 3269 switch (type_) {
3161 // Add more cases when necessary. 3270 // Add more cases when necessary.
3162 case TranscendentalCache::SIN: return Runtime::kMath_sin; 3271 case TranscendentalCache::SIN: return Runtime::kMath_sin;
3163 case TranscendentalCache::COS: return Runtime::kMath_cos; 3272 case TranscendentalCache::COS: return Runtime::kMath_cos;
3164 case TranscendentalCache::LOG: return Runtime::kMath_log; 3273 case TranscendentalCache::LOG: return Runtime::kMath_log;
3165 default: 3274 default:
(...skipping 2964 matching lines...) Expand 10 before | Expand all | Expand 10 after
6130 __ strb(untagged_value, MemOperand(external_pointer, untagged_key)); 6239 __ strb(untagged_value, MemOperand(external_pointer, untagged_key));
6131 __ Ret(); 6240 __ Ret();
6132 } 6241 }
6133 6242
6134 6243
6135 #undef __ 6244 #undef __
6136 6245
6137 } } // namespace v8::internal 6246 } } // namespace v8::internal
6138 6247
6139 #endif // V8_TARGET_ARCH_ARM 6248 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/code-stubs-arm.h ('k') | src/arm/codegen-arm.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698