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

Side by Side Diff: src/x64/stub-cache-x64.cc

Issue 6315004: Truncate rather than round to nearest when performing float-to-integer... (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 11 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/x64/ic-x64.cc ('k') | no next file » | 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 3097 matching lines...) Expand 10 before | Expand all | Expand 10 after
3108 __ bind(&generic_stub_call); 3108 __ bind(&generic_stub_call);
3109 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 3109 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
3110 Handle<Code> generic_construct_stub(code); 3110 Handle<Code> generic_construct_stub(code);
3111 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3111 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3112 3112
3113 // Return the generated code. 3113 // Return the generated code.
3114 return GetCode(); 3114 return GetCode();
3115 } 3115 }
3116 3116
3117 3117
3118 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
3119 ExternalArrayType array_type, Code::Flags flags) {
3120 // ----------- S t a t e -------------
3121 // -- rax : key
3122 // -- rdx : receiver
3123 // -- rsp[0] : return address
3124 // -----------------------------------
3125 Label slow;
3126
3127 // Check that the object isn't a smi.
3128 __ JumpIfSmi(rdx, &slow);
3129
3130 // Check that the key is a smi.
3131 __ JumpIfNotSmi(rax, &slow);
3132
3133 // Check that the object is a JS object.
3134 __ CmpObjectType(rdx, JS_OBJECT_TYPE, rcx);
3135 __ j(not_equal, &slow);
3136 // Check that the receiver does not require access checks. We need
3137 // to check this explicitly since this generic stub does not perform
3138 // map checks. The map is already in rdx.
3139 __ testb(FieldOperand(rcx, Map::kBitFieldOffset),
3140 Immediate(1 << Map::kIsAccessCheckNeeded));
3141 __ j(not_zero, &slow);
3142
3143 // Check that the elements array is the appropriate type of
3144 // ExternalArray.
3145 // rax: index (as a smi)
3146 // rdx: JSObject
3147 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3148 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
3149 Heap::RootIndexForExternalArrayType(array_type));
3150 __ j(not_equal, &slow);
3151
3152 // Check that the index is in range.
3153 __ SmiToInteger32(rcx, rax);
3154 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3155 // Unsigned comparison catches both negative and too-large values.
3156 __ j(above_equal, &slow);
3157
3158 // rax: index (as a smi)
3159 // rdx: receiver (JSObject)
3160 // rcx: untagged index
3161 // rbx: elements array
3162 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3163 // rbx: base pointer of external storage
3164 switch (array_type) {
3165 case kExternalByteArray:
3166 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
3167 break;
3168 case kExternalUnsignedByteArray:
3169 __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0));
3170 break;
3171 case kExternalShortArray:
3172 __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0));
3173 break;
3174 case kExternalUnsignedShortArray:
3175 __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0));
3176 break;
3177 case kExternalIntArray:
3178 __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0));
3179 break;
3180 case kExternalUnsignedIntArray:
3181 __ movl(rcx, Operand(rbx, rcx, times_4, 0));
3182 break;
3183 case kExternalFloatArray:
3184 __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0));
3185 break;
3186 default:
3187 UNREACHABLE();
3188 break;
3189 }
3190
3191 // rax: index
3192 // rdx: receiver
3193 // For integer array types:
3194 // rcx: value
3195 // For floating-point array type:
3196 // xmm0: value as double.
3197
3198 ASSERT(kSmiValueSize == 32);
3199 if (array_type == kExternalUnsignedIntArray) {
3200 // For the UnsignedInt array type, we need to see whether
3201 // the value can be represented in a Smi. If not, we need to convert
3202 // it to a HeapNumber.
3203 NearLabel box_int;
3204
3205 __ JumpIfUIntNotValidSmiValue(rcx, &box_int);
3206
3207 __ Integer32ToSmi(rax, rcx);
3208 __ ret(0);
3209
3210 __ bind(&box_int);
3211
3212 // Allocate a HeapNumber for the int and perform int-to-double
3213 // conversion.
3214 // The value is zero-extended since we loaded the value from memory
3215 // with movl.
3216 __ cvtqsi2sd(xmm0, rcx);
3217
3218 __ AllocateHeapNumber(rcx, rbx, &slow);
3219 // Set the value.
3220 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3221 __ movq(rax, rcx);
3222 __ ret(0);
3223 } else if (array_type == kExternalFloatArray) {
3224 // For the floating-point array type, we need to always allocate a
3225 // HeapNumber.
3226 __ AllocateHeapNumber(rcx, rbx, &slow);
3227 // Set the value.
3228 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3229 __ movq(rax, rcx);
3230 __ ret(0);
3231 } else {
3232 __ Integer32ToSmi(rax, rcx);
3233 __ ret(0);
3234 }
3235
3236 // Slow case: Jump to runtime.
3237 __ bind(&slow);
3238 __ IncrementCounter(&Counters::keyed_load_external_array_slow, 1);
3239
3240 // ----------- S t a t e -------------
3241 // -- rax : key
3242 // -- rdx : receiver
3243 // -- rsp[0] : return address
3244 // -----------------------------------
3245
3246 __ pop(rbx);
3247 __ push(rdx); // receiver
3248 __ push(rax); // name
3249 __ push(rbx); // return address
3250
3251 // Perform tail call to the entry.
3252 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3253
3254 // Return the generated code.
3255 return GetCode(flags);
3256 }
3257
3258
3259 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
3260 ExternalArrayType array_type, Code::Flags flags) {
3261 // ----------- S t a t e -------------
3262 // -- rax : value
3263 // -- rcx : key
3264 // -- rdx : receiver
3265 // -- rsp[0] : return address
3266 // -----------------------------------
3267 Label slow;
3268
3269 // Check that the object isn't a smi.
3270 __ JumpIfSmi(rdx, &slow);
3271 // Get the map from the receiver.
3272 __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset));
3273 // Check that the receiver does not require access checks. We need
3274 // to do this because this generic stub does not perform map checks.
3275 __ testb(FieldOperand(rbx, Map::kBitFieldOffset),
3276 Immediate(1 << Map::kIsAccessCheckNeeded));
3277 __ j(not_zero, &slow);
3278 // Check that the key is a smi.
3279 __ JumpIfNotSmi(rcx, &slow);
3280
3281 // Check that the object is a JS object.
3282 __ CmpInstanceType(rbx, JS_OBJECT_TYPE);
3283 __ j(not_equal, &slow);
3284
3285 // Check that the elements array is the appropriate type of
3286 // ExternalArray.
3287 // rax: value
3288 // rcx: key (a smi)
3289 // rdx: receiver (a JSObject)
3290 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3291 __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset),
3292 Heap::RootIndexForExternalArrayType(array_type));
3293 __ j(not_equal, &slow);
3294
3295 // Check that the index is in range.
3296 __ SmiToInteger32(rdi, rcx); // Untag the index.
3297 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
3298 // Unsigned comparison catches both negative and too-large values.
3299 __ j(above_equal, &slow);
3300
3301 // Handle both smis and HeapNumbers in the fast path. Go to the
3302 // runtime for all other kinds of values.
3303 // rax: value
3304 // rcx: key (a smi)
3305 // rdx: receiver (a JSObject)
3306 // rbx: elements array
3307 // rdi: untagged key
3308 NearLabel check_heap_number;
3309 __ JumpIfNotSmi(rax, &check_heap_number);
3310 // No more branches to slow case on this path. Key and receiver not needed.
3311 __ SmiToInteger32(rdx, rax);
3312 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3313 // rbx: base pointer of external storage
3314 switch (array_type) {
3315 case kExternalByteArray:
3316 case kExternalUnsignedByteArray:
3317 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3318 break;
3319 case kExternalShortArray:
3320 case kExternalUnsignedShortArray:
3321 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
3322 break;
3323 case kExternalIntArray:
3324 case kExternalUnsignedIntArray:
3325 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3326 break;
3327 case kExternalFloatArray:
3328 // Need to perform int-to-float conversion.
3329 __ cvtlsi2ss(xmm0, rdx);
3330 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3331 break;
3332 default:
3333 UNREACHABLE();
3334 break;
3335 }
3336 __ ret(0);
3337
3338 __ bind(&check_heap_number);
3339 // rax: value
3340 // rcx: key (a smi)
3341 // rdx: receiver (a JSObject)
3342 // rbx: elements array
3343 // rdi: untagged key
3344 __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister);
3345 __ j(not_equal, &slow);
3346 // No more branches to slow case on this path.
3347
3348 // The WebGL specification leaves the behavior of storing NaN and
3349 // +/-Infinity into integer arrays basically undefined. For more
3350 // reproducible behavior, convert these to zero.
3351 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
3352 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3353 // rdi: untagged index
3354 // rbx: base pointer of external storage
3355 // top of FPU stack: value
3356 if (array_type == kExternalFloatArray) {
3357 __ cvtsd2ss(xmm0, xmm0);
3358 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3359 __ ret(0);
3360 } else {
3361 // Perform float-to-int conversion with truncation (round-to-zero)
3362 // behavior.
3363
3364 // Convert to int32 and store the low byte/word.
3365 // If the value is NaN or +/-infinity, the result is 0x80000000,
3366 // which is automatically zero when taken mod 2^n, n < 32.
3367 // rdx: value (converted to an untagged integer)
3368 // rdi: untagged index
3369 // rbx: base pointer of external storage
3370 switch (array_type) {
3371 case kExternalByteArray:
3372 case kExternalUnsignedByteArray:
3373 __ cvttsd2si(rdx, xmm0);
3374 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3375 break;
3376 case kExternalShortArray:
3377 case kExternalUnsignedShortArray:
3378 __ cvttsd2si(rdx, xmm0);
3379 __ movw(Operand(rbx, rdi, times_2, 0), rdx);
3380 break;
3381 case kExternalIntArray:
3382 case kExternalUnsignedIntArray: {
3383 // Convert to int64, so that NaN and infinities become
3384 // 0x8000000000000000, which is zero mod 2^32.
3385 __ cvttsd2siq(rdx, xmm0);
3386 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3387 break;
3388 }
3389 default:
3390 UNREACHABLE();
3391 break;
3392 }
3393 __ ret(0);
3394 }
3395
3396 // Slow case: call runtime.
3397 __ bind(&slow);
3398
3399 // ----------- S t a t e -------------
3400 // -- rax : value
3401 // -- rcx : key
3402 // -- rdx : receiver
3403 // -- rsp[0] : return address
3404 // -----------------------------------
3405
3406 __ pop(rbx);
3407 __ push(rdx); // receiver
3408 __ push(rcx); // key
3409 __ push(rax); // value
3410 __ push(rbx); // return address
3411
3412 // Do tail-call to runtime routine.
3413 __ TailCallRuntime(Runtime::kSetProperty, 3, 1);
3414
3415 return GetCode(flags);
3416 }
3417
3118 #undef __ 3418 #undef __
3119 3419
3120 } } // namespace v8::internal 3420 } } // namespace v8::internal
3121 3421
3122 #endif // V8_TARGET_ARCH_X64 3422 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/ic-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698