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

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

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

Powered by Google App Engine
This is Rietveld 408576698