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

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

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
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/ia32/simulator-ia32.h ('k') | src/ia32/virtual-frame-ia32.h » ('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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 2195 matching lines...) Expand 10 before | Expand all | Expand 10 after
2206 // Patch the receiver on the stack with the global proxy if 2206 // Patch the receiver on the stack with the global proxy if
2207 // necessary. 2207 // necessary.
2208 if (object->IsGlobalObject()) { 2208 if (object->IsGlobalObject()) {
2209 ASSERT(depth == kInvalidProtoDepth); 2209 ASSERT(depth == kInvalidProtoDepth);
2210 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset)); 2210 __ mov(edx, FieldOperand(edx, GlobalObject::kGlobalReceiverOffset));
2211 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx); 2211 __ mov(Operand(esp, (argc + 1) * kPointerSize), edx);
2212 } 2212 }
2213 break; 2213 break;
2214 2214
2215 case STRING_CHECK: 2215 case STRING_CHECK:
2216 if (!function->IsBuiltin()) { 2216 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2217 // Calling non-builtins with a value as receiver requires boxing. 2217 // Calling non-strict non-builtins with a value as the receiver
2218 // requires boxing.
2218 __ jmp(&miss); 2219 __ jmp(&miss);
2219 } else { 2220 } else {
2220 // Check that the object is a string or a symbol. 2221 // Check that the object is a string or a symbol.
2221 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax); 2222 __ CmpObjectType(edx, FIRST_NONSTRING_TYPE, eax);
2222 __ j(above_equal, &miss, not_taken); 2223 __ j(above_equal, &miss, not_taken);
2223 // Check that the maps starting from the prototype haven't changed. 2224 // Check that the maps starting from the prototype haven't changed.
2224 GenerateDirectLoadGlobalFunctionPrototype( 2225 GenerateDirectLoadGlobalFunctionPrototype(
2225 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss); 2226 masm(), Context::STRING_FUNCTION_INDEX, eax, &miss);
2226 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2227 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2227 ebx, edx, edi, name, &miss); 2228 ebx, edx, edi, name, &miss);
2228 } 2229 }
2229 break; 2230 break;
2230 2231
2231 case NUMBER_CHECK: { 2232 case NUMBER_CHECK: {
2232 if (!function->IsBuiltin()) { 2233 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2233 // Calling non-builtins with a value as receiver requires boxing. 2234 // Calling non-strict non-builtins with a value as the receiver
2235 // requires boxing.
2234 __ jmp(&miss); 2236 __ jmp(&miss);
2235 } else { 2237 } else {
2236 Label fast; 2238 Label fast;
2237 // Check that the object is a smi or a heap number. 2239 // Check that the object is a smi or a heap number.
2238 __ test(edx, Immediate(kSmiTagMask)); 2240 __ test(edx, Immediate(kSmiTagMask));
2239 __ j(zero, &fast, taken); 2241 __ j(zero, &fast, taken);
2240 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax); 2242 __ CmpObjectType(edx, HEAP_NUMBER_TYPE, eax);
2241 __ j(not_equal, &miss, not_taken); 2243 __ j(not_equal, &miss, not_taken);
2242 __ bind(&fast); 2244 __ bind(&fast);
2243 // Check that the maps starting from the prototype haven't changed. 2245 // Check that the maps starting from the prototype haven't changed.
2244 GenerateDirectLoadGlobalFunctionPrototype( 2246 GenerateDirectLoadGlobalFunctionPrototype(
2245 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss); 2247 masm(), Context::NUMBER_FUNCTION_INDEX, eax, &miss);
2246 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder, 2248 CheckPrototypes(JSObject::cast(object->GetPrototype()), eax, holder,
2247 ebx, edx, edi, name, &miss); 2249 ebx, edx, edi, name, &miss);
2248 } 2250 }
2249 break; 2251 break;
2250 } 2252 }
2251 2253
2252 case BOOLEAN_CHECK: { 2254 case BOOLEAN_CHECK: {
2253 if (!function->IsBuiltin()) { 2255 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2254 // Calling non-builtins with a value as receiver requires boxing. 2256 // Calling non-strict non-builtins with a value as the receiver
2257 // requires boxing.
2255 __ jmp(&miss); 2258 __ jmp(&miss);
2256 } else { 2259 } else {
2257 Label fast; 2260 Label fast;
2258 // Check that the object is a boolean. 2261 // Check that the object is a boolean.
2259 __ cmp(edx, Factory::true_value()); 2262 __ cmp(edx, Factory::true_value());
2260 __ j(equal, &fast, taken); 2263 __ j(equal, &fast, taken);
2261 __ cmp(edx, Factory::false_value()); 2264 __ cmp(edx, Factory::false_value());
2262 __ j(not_equal, &miss, not_taken); 2265 __ j(not_equal, &miss, not_taken);
2263 __ bind(&fast); 2266 __ bind(&fast);
2264 // Check that the maps starting from the prototype haven't changed. 2267 // Check that the maps starting from the prototype haven't changed.
(...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after
2551 } 2554 }
2552 2555
2553 // Stub never generated for non-global objects that require access 2556 // Stub never generated for non-global objects that require access
2554 // checks. 2557 // checks.
2555 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2558 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2556 2559
2557 __ pop(ebx); // remove the return address 2560 __ pop(ebx); // remove the return address
2558 __ push(edx); // receiver 2561 __ push(edx); // receiver
2559 __ push(ecx); // name 2562 __ push(ecx); // name
2560 __ push(eax); // value 2563 __ push(eax); // value
2564 __ push(Immediate(Smi::FromInt(strict_mode_)));
2561 __ push(ebx); // restore return address 2565 __ push(ebx); // restore return address
2562 2566
2563 // Do tail-call to the runtime system. 2567 // Do tail-call to the runtime system.
2564 ExternalReference store_ic_property = 2568 ExternalReference store_ic_property =
2565 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); 2569 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
2566 __ TailCallExternalReference(store_ic_property, 3, 1); 2570 __ TailCallExternalReference(store_ic_property, 4, 1);
2567 2571
2568 // Handle store cache miss. 2572 // Handle store cache miss.
2569 __ bind(&miss); 2573 __ bind(&miss);
2570 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2574 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2571 __ jmp(ic, RelocInfo::CODE_TARGET); 2575 __ jmp(ic, RelocInfo::CODE_TARGET);
2572 2576
2573 // Return the generated code. 2577 // Return the generated code.
2574 return GetCode(INTERCEPTOR, name); 2578 return GetCode(INTERCEPTOR, name);
2575 } 2579 }
2576 2580
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
2722 // Handle store cache miss. 2726 // Handle store cache miss.
2723 __ bind(&miss); 2727 __ bind(&miss);
2724 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 2728 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2725 __ jmp(ic, RelocInfo::CODE_TARGET); 2729 __ jmp(ic, RelocInfo::CODE_TARGET);
2726 2730
2727 // Return the generated code. 2731 // Return the generated code.
2728 return GetCode(NORMAL, NULL); 2732 return GetCode(NORMAL, NULL);
2729 } 2733 }
2730 2734
2731 2735
2732 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
2733 JSObject* receiver) {
2734 // ----------- S t a t e -------------
2735 // -- eax : value
2736 // -- ecx : key
2737 // -- edx : receiver
2738 // -- esp[0] : return address
2739 // -----------------------------------
2740 Label miss;
2741
2742 // Check that the map matches.
2743 __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
2744
2745 // Do the load.
2746 GenerateFastPixelArrayStore(masm(),
2747 edx,
2748 ecx,
2749 eax,
2750 edi,
2751 ebx,
2752 true,
2753 &miss,
2754 &miss,
2755 NULL,
2756 &miss);
2757
2758 // Handle store cache miss.
2759 __ bind(&miss);
2760 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
2761 __ jmp(ic, RelocInfo::CODE_TARGET);
2762
2763 // Return the generated code.
2764 return GetCode(NORMAL, NULL);
2765 }
2766
2767
2768 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2736 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2769 JSObject* object, 2737 JSObject* object,
2770 JSObject* last) { 2738 JSObject* last) {
2771 // ----------- S t a t e ------------- 2739 // ----------- S t a t e -------------
2772 // -- eax : receiver 2740 // -- eax : receiver
2773 // -- ecx : name 2741 // -- ecx : name
2774 // -- esp[0] : return address 2742 // -- esp[0] : return address
2775 // ----------------------------------- 2743 // -----------------------------------
2776 Label miss; 2744 Label miss;
2777 2745
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after
3204 __ ret(0); 3172 __ ret(0);
3205 3173
3206 __ bind(&miss); 3174 __ bind(&miss);
3207 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3175 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3208 3176
3209 // Return the generated code. 3177 // Return the generated code.
3210 return GetCode(NORMAL, NULL); 3178 return GetCode(NORMAL, NULL);
3211 } 3179 }
3212 3180
3213 3181
3214 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
3215 // ----------- S t a t e -------------
3216 // -- eax : key
3217 // -- edx : receiver
3218 // -- esp[0] : return address
3219 // -----------------------------------
3220 Label miss;
3221
3222 // Check that the map matches.
3223 __ CheckMap(edx, Handle<Map>(receiver->map()), &miss, false);
3224
3225 GenerateFastPixelArrayLoad(masm(),
3226 edx,
3227 eax,
3228 ecx,
3229 ebx,
3230 eax,
3231 &miss,
3232 &miss,
3233 &miss);
3234
3235 // Handle load cache miss.
3236 __ bind(&miss);
3237 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
3238 __ jmp(ic, RelocInfo::CODE_TARGET);
3239
3240 // Return the generated code.
3241 return GetCode(NORMAL, NULL);
3242 }
3243
3244
3245 // Specialized stub for constructing objects from functions which only have only 3182 // Specialized stub for constructing objects from functions which only have only
3246 // simple assignments of the form this.x = ...; in their body. 3183 // simple assignments of the form this.x = ...; in their body.
3247 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3184 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3248 // ----------- S t a t e ------------- 3185 // ----------- S t a t e -------------
3249 // -- eax : argc 3186 // -- eax : argc
3250 // -- edi : constructor 3187 // -- edi : constructor
3251 // -- esp[0] : return address 3188 // -- esp[0] : return address
3252 // -- esp[4] : last argument 3189 // -- esp[4] : last argument
3253 // ----------------------------------- 3190 // -----------------------------------
3254 Label generic_stub_call; 3191 Label generic_stub_call;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3374 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric); 3311 Code* code = Builtins::builtin(Builtins::JSConstructStubGeneric);
3375 Handle<Code> generic_construct_stub(code); 3312 Handle<Code> generic_construct_stub(code);
3376 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 3313 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
3377 3314
3378 // Return the generated code. 3315 // Return the generated code.
3379 return GetCode(); 3316 return GetCode();
3380 } 3317 }
3381 3318
3382 3319
3383 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3320 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
3384 ExternalArrayType array_type, Code::Flags flags) { 3321 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) {
3385 // ----------- S t a t e ------------- 3322 // ----------- S t a t e -------------
3386 // -- eax : key 3323 // -- eax : key
3387 // -- edx : receiver 3324 // -- edx : receiver
3388 // -- esp[0] : return address 3325 // -- esp[0] : return address
3389 // ----------------------------------- 3326 // -----------------------------------
3390 Label slow, failed_allocation; 3327 Label slow, failed_allocation;
3391 3328
3392 // Check that the object isn't a smi. 3329 // Check that the object isn't a smi.
3393 __ test(edx, Immediate(kSmiTagMask)); 3330 __ test(edx, Immediate(kSmiTagMask));
3394 __ j(zero, &slow, not_taken); 3331 __ j(zero, &slow, not_taken);
3395 3332
3396 // Check that the key is a smi. 3333 // Check that the key is a smi.
3397 __ test(eax, Immediate(kSmiTagMask)); 3334 __ test(eax, Immediate(kSmiTagMask));
3398 __ j(not_zero, &slow, not_taken); 3335 __ j(not_zero, &slow, not_taken);
3399 3336
3400 // Get the map of the receiver. 3337 // Check that the map matches.
3401 __ mov(ecx, FieldOperand(edx, HeapObject::kMapOffset)); 3338 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
3402 // Check that the receiver does not require access checks. We need
3403 // to check this explicitly since this generic stub does not perform
3404 // map checks.
3405 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset),
3406 1 << Map::kIsAccessCheckNeeded);
3407 __ j(not_zero, &slow, not_taken);
3408
3409 __ CmpInstanceType(ecx, JS_OBJECT_TYPE);
3410 __ j(not_equal, &slow, not_taken);
3411
3412 // Check that the elements array is the appropriate type of
3413 // ExternalArray.
3414 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset)); 3339 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3415 Handle<Map> map(Heap::MapForExternalArrayType(array_type));
3416 __ cmp(FieldOperand(ebx, HeapObject::kMapOffset),
3417 Immediate(map));
3418 __ j(not_equal, &slow, not_taken);
3419 3340
3420 // eax: key, known to be a smi. 3341 // eax: key, known to be a smi.
3421 // edx: receiver, known to be a JSObject. 3342 // edx: receiver, known to be a JSObject.
3422 // ebx: elements object, known to be an external array. 3343 // ebx: elements object, known to be an external array.
3423 // Check that the index is in range. 3344 // Check that the index is in range.
3424 __ mov(ecx, eax); 3345 __ mov(ecx, eax);
3425 __ SmiUntag(ecx); // Untag the index. 3346 __ SmiUntag(ecx); // Untag the index.
3426 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 3347 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
3427 // Unsigned comparison catches both negative and too-large values. 3348 // Unsigned comparison catches both negative and too-large values.
3428 __ j(above_equal, &slow); 3349 __ j(above_equal, &slow);
3429
3430 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 3350 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
3431 // ebx: base pointer of external storage 3351 // ebx: base pointer of external storage
3432 switch (array_type) { 3352 switch (array_type) {
3433 case kExternalByteArray: 3353 case kExternalByteArray:
3434 __ movsx_b(ecx, Operand(ebx, ecx, times_1, 0)); 3354 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
3435 break; 3355 break;
3436 case kExternalUnsignedByteArray: 3356 case kExternalUnsignedByteArray:
3437 __ movzx_b(ecx, Operand(ebx, ecx, times_1, 0)); 3357 case kExternalPixelArray:
3358 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
3438 break; 3359 break;
3439 case kExternalShortArray: 3360 case kExternalShortArray:
3440 __ movsx_w(ecx, Operand(ebx, ecx, times_2, 0)); 3361 __ movsx_w(eax, Operand(ebx, ecx, times_2, 0));
3441 break; 3362 break;
3442 case kExternalUnsignedShortArray: 3363 case kExternalUnsignedShortArray:
3443 __ movzx_w(ecx, Operand(ebx, ecx, times_2, 0)); 3364 __ movzx_w(eax, Operand(ebx, ecx, times_2, 0));
3444 break; 3365 break;
3445 case kExternalIntArray: 3366 case kExternalIntArray:
3446 case kExternalUnsignedIntArray: 3367 case kExternalUnsignedIntArray:
3447 __ mov(ecx, Operand(ebx, ecx, times_4, 0)); 3368 __ mov(ecx, Operand(ebx, ecx, times_4, 0));
3448 break; 3369 break;
3449 case kExternalFloatArray: 3370 case kExternalFloatArray:
3450 __ fld_s(Operand(ebx, ecx, times_4, 0)); 3371 __ fld_s(Operand(ebx, ecx, times_4, 0));
3451 break; 3372 break;
3452 default: 3373 default:
3453 UNREACHABLE(); 3374 UNREACHABLE();
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
3508 __ ret(0); 3429 __ ret(0);
3509 } else if (array_type == kExternalFloatArray) { 3430 } else if (array_type == kExternalFloatArray) {
3510 // For the floating-point array type, we need to always allocate a 3431 // For the floating-point array type, we need to always allocate a
3511 // HeapNumber. 3432 // HeapNumber.
3512 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation); 3433 __ AllocateHeapNumber(ecx, ebx, edi, &failed_allocation);
3513 // Set the value. 3434 // Set the value.
3514 __ mov(eax, ecx); 3435 __ mov(eax, ecx);
3515 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3436 __ fstp_d(FieldOperand(eax, HeapNumber::kValueOffset));
3516 __ ret(0); 3437 __ ret(0);
3517 } else { 3438 } else {
3518 __ mov(eax, ecx);
3519 __ SmiTag(eax); 3439 __ SmiTag(eax);
3520 __ ret(0); 3440 __ ret(0);
3521 } 3441 }
3522 3442
3523 // If we fail allocation of the HeapNumber, we still have a value on 3443 // If we fail allocation of the HeapNumber, we still have a value on
3524 // top of the FPU stack. Remove it. 3444 // top of the FPU stack. Remove it.
3525 __ bind(&failed_allocation); 3445 __ bind(&failed_allocation);
3526 __ ffree(); 3446 __ ffree();
3527 __ fincstp(); 3447 __ fincstp();
3528 // Fall through to slow case. 3448 // Fall through to slow case.
(...skipping 14 matching lines...) Expand all
3543 3463
3544 // Perform tail call to the entry. 3464 // Perform tail call to the entry.
3545 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3465 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3546 3466
3547 // Return the generated code. 3467 // Return the generated code.
3548 return GetCode(flags); 3468 return GetCode(flags);
3549 } 3469 }
3550 3470
3551 3471
3552 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3472 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
3553 ExternalArrayType array_type, Code::Flags flags) { 3473 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) {
3554 // ----------- S t a t e ------------- 3474 // ----------- S t a t e -------------
3555 // -- eax : value 3475 // -- eax : value
3556 // -- ecx : key 3476 // -- ecx : key
3557 // -- edx : receiver 3477 // -- edx : receiver
3558 // -- esp[0] : return address 3478 // -- esp[0] : return address
3559 // ----------------------------------- 3479 // -----------------------------------
3560 Label slow, check_heap_number; 3480 Label slow, check_heap_number;
3561 3481
3562 // Check that the object isn't a smi. 3482 // Check that the object isn't a smi.
3563 __ test(edx, Immediate(kSmiTagMask)); 3483 __ test(edx, Immediate(kSmiTagMask));
3564 __ j(zero, &slow); 3484 __ j(zero, &slow);
3565 // Get the map from the receiver. 3485
3566 __ mov(edi, FieldOperand(edx, HeapObject::kMapOffset)); 3486 // Check that the map matches.
3567 // Check that the receiver does not require access checks. We need 3487 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
3568 // to do this because this generic stub does not perform map checks. 3488
3569 __ test_b(FieldOperand(edi, Map::kBitFieldOffset),
3570 1 << Map::kIsAccessCheckNeeded);
3571 __ j(not_zero, &slow);
3572 // Check that the key is a smi. 3489 // Check that the key is a smi.
3573 __ test(ecx, Immediate(kSmiTagMask)); 3490 __ test(ecx, Immediate(kSmiTagMask));
3574 __ j(not_zero, &slow); 3491 __ j(not_zero, &slow);
3575 // Get the instance type from the map of the receiver.
3576 __ CmpInstanceType(edi, JS_OBJECT_TYPE);
3577 __ j(not_equal, &slow);
3578
3579 // Check that the elements array is the appropriate type of
3580 // ExternalArray.
3581 // eax: value
3582 // edx: receiver, a JSObject
3583 // ecx: key, a smi
3584 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3585 __ CheckMap(edi, Handle<Map>(Heap::MapForExternalArrayType(array_type)),
3586 &slow, true);
3587 3492
3588 // Check that the index is in range. 3493 // Check that the index is in range.
3494 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3589 __ mov(ebx, ecx); 3495 __ mov(ebx, ecx);
3590 __ SmiUntag(ebx); 3496 __ SmiUntag(ebx);
3591 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 3497 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
3592 // Unsigned comparison catches both negative and too-large values. 3498 // Unsigned comparison catches both negative and too-large values.
3593 __ j(above_equal, &slow); 3499 __ j(above_equal, &slow);
3594 3500
3595 // Handle both smis and HeapNumbers in the fast path. Go to the 3501 // Handle both smis and HeapNumbers in the fast path. Go to the
3596 // runtime for all other kinds of values. 3502 // runtime for all other kinds of values.
3597 // eax: value 3503 // eax: value
3598 // edx: receiver 3504 // edx: receiver
3599 // ecx: key 3505 // ecx: key
3600 // edi: elements array 3506 // edi: elements array
3601 // ebx: untagged index 3507 // ebx: untagged index
3602 __ test(eax, Immediate(kSmiTagMask)); 3508 __ test(eax, Immediate(kSmiTagMask));
3603 __ j(not_equal, &check_heap_number); 3509 if (array_type == kExternalPixelArray)
3510 __ j(not_equal, &slow);
3511 else
3512 __ j(not_equal, &check_heap_number);
3513
3604 // smi case 3514 // smi case
3605 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 3515 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
3606 __ SmiUntag(ecx); 3516 __ SmiUntag(ecx);
3607 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3517 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3608 // ecx: base pointer of external storage 3518 // ecx: base pointer of external storage
3609 switch (array_type) { 3519 switch (array_type) {
3520 case kExternalPixelArray:
3521 { // Clamp the value to [0..255].
3522 NearLabel done;
3523 __ test(ecx, Immediate(0xFFFFFF00));
3524 __ j(zero, &done);
3525 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3526 __ dec_b(ecx); // 0 if negative, 255 if positive.
3527 __ bind(&done);
3528 }
3529 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3530 break;
3610 case kExternalByteArray: 3531 case kExternalByteArray:
3611 case kExternalUnsignedByteArray: 3532 case kExternalUnsignedByteArray:
3612 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3533 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3613 break; 3534 break;
3614 case kExternalShortArray: 3535 case kExternalShortArray:
3615 case kExternalUnsignedShortArray: 3536 case kExternalUnsignedShortArray:
3616 __ mov_w(Operand(edi, ebx, times_2, 0), ecx); 3537 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3617 break; 3538 break;
3618 case kExternalIntArray: 3539 case kExternalIntArray:
3619 case kExternalUnsignedIntArray: 3540 case kExternalUnsignedIntArray:
3620 __ mov(Operand(edi, ebx, times_4, 0), ecx); 3541 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3621 break; 3542 break;
3622 case kExternalFloatArray: 3543 case kExternalFloatArray:
3623 // Need to perform int-to-float conversion. 3544 // Need to perform int-to-float conversion.
3624 __ push(ecx); 3545 __ push(ecx);
3625 __ fild_s(Operand(esp, 0)); 3546 __ fild_s(Operand(esp, 0));
3626 __ pop(ecx); 3547 __ pop(ecx);
3627 __ fstp_s(Operand(edi, ebx, times_4, 0)); 3548 __ fstp_s(Operand(edi, ebx, times_4, 0));
3628 break; 3549 break;
3629 default: 3550 default:
3630 UNREACHABLE(); 3551 UNREACHABLE();
3631 break; 3552 break;
3632 } 3553 }
3633 __ ret(0); // Return the original value. 3554 __ ret(0); // Return the original value.
3634 3555
3635 __ bind(&check_heap_number); 3556 // TODO(danno): handle heap number -> pixel array conversion
3636 // eax: value 3557 if (array_type != kExternalPixelArray) {
3637 // edx: receiver 3558 __ bind(&check_heap_number);
3638 // ecx: key 3559 // eax: value
3639 // edi: elements array 3560 // edx: receiver
3640 // ebx: untagged index 3561 // ecx: key
3641 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3562 // edi: elements array
3642 Immediate(Factory::heap_number_map())); 3563 // ebx: untagged index
3643 __ j(not_equal, &slow); 3564 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3565 Immediate(Factory::heap_number_map()));
3566 __ j(not_equal, &slow);
3644 3567
3645 // The WebGL specification leaves the behavior of storing NaN and 3568 // The WebGL specification leaves the behavior of storing NaN and
3646 // +/-Infinity into integer arrays basically undefined. For more 3569 // +/-Infinity into integer arrays basically undefined. For more
3647 // reproducible behavior, convert these to zero. 3570 // reproducible behavior, convert these to zero.
3648 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3571 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3649 // ebx: untagged index 3572 // ebx: untagged index
3650 // edi: base pointer of external storage 3573 // edi: base pointer of external storage
3651 if (array_type == kExternalFloatArray) { 3574 if (array_type == kExternalFloatArray) {
3652 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3575 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3653 __ fstp_s(Operand(edi, ebx, times_4, 0)); 3576 __ fstp_s(Operand(edi, ebx, times_4, 0));
3654 __ ret(0); 3577 __ ret(0);
3655 } else { 3578 } else {
3656 // Perform float-to-int conversion with truncation (round-to-zero) 3579 // Perform float-to-int conversion with truncation (round-to-zero)
3657 // behavior. 3580 // behavior.
3658 3581
3659 // For the moment we make the slow call to the runtime on 3582 // For the moment we make the slow call to the runtime on
3660 // processors that don't support SSE2. The code in IntegerConvert 3583 // processors that don't support SSE2. The code in IntegerConvert
3661 // (code-stubs-ia32.cc) is roughly what is needed here though the 3584 // (code-stubs-ia32.cc) is roughly what is needed here though the
3662 // conversion failure case does not need to be handled. 3585 // conversion failure case does not need to be handled.
3663 if (CpuFeatures::IsSupported(SSE2)) { 3586 if (CpuFeatures::IsSupported(SSE2)) {
3664 if (array_type != kExternalIntArray && 3587 if (array_type != kExternalIntArray &&
3665 array_type != kExternalUnsignedIntArray) { 3588 array_type != kExternalUnsignedIntArray) {
3666 ASSERT(CpuFeatures::IsSupported(SSE2));
3667 CpuFeatures::Scope scope(SSE2);
3668 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
3669 // ecx: untagged integer value
3670 switch (array_type) {
3671 case kExternalByteArray:
3672 case kExternalUnsignedByteArray:
3673 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3674 break;
3675 case kExternalShortArray:
3676 case kExternalUnsignedShortArray:
3677 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3678 break;
3679 default:
3680 UNREACHABLE();
3681 break;
3682 }
3683 } else {
3684 if (CpuFeatures::IsSupported(SSE3)) {
3685 CpuFeatures::Scope scope(SSE3);
3686 // fisttp stores values as signed integers. To represent the
3687 // entire range of int and unsigned int arrays, store as a
3688 // 64-bit int and discard the high 32 bits.
3689 // If the value is NaN or +/-infinity, the result is 0x80000000,
3690 // which is automatically zero when taken mod 2^n, n < 32.
3691 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3692 __ sub(Operand(esp), Immediate(2 * kPointerSize));
3693 __ fisttp_d(Operand(esp, 0));
3694 __ pop(ecx);
3695 __ add(Operand(esp), Immediate(kPointerSize));
3696 } else {
3697 ASSERT(CpuFeatures::IsSupported(SSE2)); 3589 ASSERT(CpuFeatures::IsSupported(SSE2));
3698 CpuFeatures::Scope scope(SSE2); 3590 CpuFeatures::Scope scope(SSE2);
3699 // We can easily implement the correct rounding behavior for the 3591 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
3700 // range [0, 2^31-1]. For the time being, to keep this code simple, 3592 // ecx: untagged integer value
3701 // make the slow runtime call for values outside this range. 3593 switch (array_type) {
3702 // Note: we could do better for signed int arrays. 3594 case kExternalPixelArray:
3703 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset)); 3595 { // Clamp the value to [0..255].
3704 // We will need the key if we have to make the slow runtime call. 3596 NearLabel done;
3705 __ push(ecx); 3597 __ test(ecx, Immediate(0xFFFFFF00));
3706 __ LoadPowerOf2(xmm1, ecx, 31); 3598 __ j(zero, &done);
3707 __ pop(ecx); 3599 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3708 __ ucomisd(xmm1, xmm0); 3600 __ dec_b(ecx); // 0 if negative, 255 if positive.
3709 __ j(above_equal, &slow); 3601 __ bind(&done);
3710 __ cvttsd2si(ecx, Operand(xmm0)); 3602 }
3603 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3604 case kExternalByteArray:
3605 case kExternalUnsignedByteArray:
3606 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3607 break;
3608 case kExternalShortArray:
3609 case kExternalUnsignedShortArray:
3610 __ mov_w(Operand(edi, ebx, times_2, 0), ecx);
3611 break;
3612 default:
3613 UNREACHABLE();
3614 break;
3615 }
3616 } else {
3617 if (CpuFeatures::IsSupported(SSE3)) {
3618 CpuFeatures::Scope scope(SSE3);
3619 // fisttp stores values as signed integers. To represent the
3620 // entire range of int and unsigned int arrays, store as a
3621 // 64-bit int and discard the high 32 bits.
3622 // If the value is NaN or +/-infinity, the result is 0x80000000,
3623 // which is automatically zero when taken mod 2^n, n < 32.
3624 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
3625 __ sub(Operand(esp), Immediate(2 * kPointerSize));
3626 __ fisttp_d(Operand(esp, 0));
3627 __ pop(ecx);
3628 __ add(Operand(esp), Immediate(kPointerSize));
3629 } else {
3630 ASSERT(CpuFeatures::IsSupported(SSE2));
3631 CpuFeatures::Scope scope(SSE2);
3632 // We can easily implement the correct rounding behavior for the
3633 // range [0, 2^31-1]. For the time being, to keep this code simple,
3634 // make the slow runtime call for values outside this range.
3635 // Note: we could do better for signed int arrays.
3636 __ movd(xmm0, FieldOperand(eax, HeapNumber::kValueOffset));
3637 // We will need the key if we have to make the slow runtime call.
3638 __ push(ecx);
3639 __ LoadPowerOf2(xmm1, ecx, 31);
3640 __ pop(ecx);
3641 __ ucomisd(xmm1, xmm0);
3642 __ j(above_equal, &slow);
3643 __ cvttsd2si(ecx, Operand(xmm0));
3644 }
3645 // ecx: untagged integer value
3646 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3711 } 3647 }
3712 // ecx: untagged integer value 3648 __ ret(0); // Return original value.
3713 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3714 } 3649 }
3715 __ ret(0); // Return original value.
3716 } 3650 }
3717 } 3651 }
3718 3652
3719 // Slow case: call runtime. 3653 // Slow case: call runtime.
3720 __ bind(&slow); 3654 __ bind(&slow);
3721 // ----------- S t a t e ------------- 3655 // ----------- S t a t e -------------
3722 // -- eax : value 3656 // -- eax : value
3723 // -- ecx : key 3657 // -- ecx : key
3724 // -- edx : receiver 3658 // -- edx : receiver
3725 // -- esp[0] : return address 3659 // -- esp[0] : return address
3726 // ----------------------------------- 3660 // -----------------------------------
3727 3661
3728 __ pop(ebx); 3662 __ pop(ebx);
3729 __ push(edx); 3663 __ push(edx);
3730 __ push(ecx); 3664 __ push(ecx);
3731 __ push(eax); 3665 __ push(eax);
3732 __ push(ebx); 3666 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
3667 __ push(Immediate(Smi::FromInt(
3668 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
3669 __ push(ebx); // return address
3733 3670
3734 // Do tail-call to runtime routine. 3671 // Do tail-call to runtime routine.
3735 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); 3672 __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
3736 3673
3737 return GetCode(flags); 3674 return GetCode(flags);
3738 } 3675 }
3739 3676
3740 3677
3741 #undef __ 3678 #undef __
3742 3679
3743 } } // namespace v8::internal 3680 } } // namespace v8::internal
3744 3681
3745 #endif // V8_TARGET_ARCH_IA32 3682 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/simulator-ia32.h ('k') | src/ia32/virtual-frame-ia32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698