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

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

Issue 6894003: Better support for 'polymorphic' JS and external arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: merge with latest Created 9 years, 7 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 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 695 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); 706 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
707 } else { 707 } else {
708 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); 708 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
709 } 709 }
710 710
711 Handle<Code> ic(code); 711 Handle<Code> ic(code);
712 __ jmp(ic, RelocInfo::CODE_TARGET); 712 __ jmp(ic, RelocInfo::CODE_TARGET);
713 } 713 }
714 714
715 715
716 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
717 Code* code = masm->isolate()->builtins()->builtin(
718 Builtins::kKeyedLoadIC_MissForceGeneric);
Mads Ager (chromium) 2011/05/10 13:38:06 four-space indent?
danno 2011/05/11 14:20:19 Done.
719 Handle<Code> ic(code);
720 __ jmp(ic, RelocInfo::CODE_TARGET);
721 }
722
723
716 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 724 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
717 // but may be destroyed if store is successful. 725 // but may be destroyed if store is successful.
718 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 726 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
719 JSObject* object, 727 JSObject* object,
720 int index, 728 int index,
721 Map* transition, 729 Map* transition,
722 Register receiver_reg, 730 Register receiver_reg,
723 Register name_reg, 731 Register name_reg,
724 Register scratch, 732 Register scratch,
725 Label* miss_label) { 733 Label* miss_label) {
(...skipping 1921 matching lines...) Expand 10 before | Expand all | Expand 10 after
2647 __ bind(&miss); 2655 __ bind(&miss);
2648 __ DecrementCounter(counters->keyed_store_field(), 1); 2656 __ DecrementCounter(counters->keyed_store_field(), 1);
2649 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2657 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2650 __ jmp(ic, RelocInfo::CODE_TARGET); 2658 __ jmp(ic, RelocInfo::CODE_TARGET);
2651 2659
2652 // Return the generated code. 2660 // Return the generated code.
2653 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2661 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2654 } 2662 }
2655 2663
2656 2664
2657 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 2665 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
2658 JSObject* receiver) { 2666 Map* receiver_map) {
2659 // ----------- S t a t e ------------- 2667 // ----------- S t a t e -------------
2660 // -- eax : value 2668 // -- eax : value
2661 // -- ecx : key 2669 // -- ecx : key
2662 // -- edx : receiver 2670 // -- edx : receiver
2663 // -- esp[0] : return address 2671 // -- esp[0] : return address
2664 // ----------------------------------- 2672 // -----------------------------------
2665 Label miss; 2673 KeyedStoreIC keyed_store_ic(isolate());
2674 MaybeObject* maybe_stub =
2675 keyed_store_ic.ComputeMonomorphicBuiltinFastElementStub(
2676 receiver_map->instance_type() == JS_ARRAY_TYPE);
2677 Code* stub;
2678 if (!maybe_stub->To(&stub)) return maybe_stub;
2679 __ DispatchMap(edx,
2680 Handle<Map>(receiver_map),
2681 Handle<Code>(stub),
2682 false);
2666 2683
2667 // Check that the receiver isn't a smi.
2668 __ test(edx, Immediate(kSmiTagMask));
2669 __ j(zero, &miss, not_taken);
2670
2671 // Check that the map matches.
2672 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2673 Immediate(Handle<Map>(receiver->map())));
2674 __ j(not_equal, &miss, not_taken);
2675
2676 // Check that the key is a smi.
2677 __ test(ecx, Immediate(kSmiTagMask));
2678 __ j(not_zero, &miss, not_taken);
2679
2680 // Get the elements array and make sure it is a fast element array, not 'cow'.
2681 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
2682 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
2683 Immediate(factory()->fixed_array_map()));
2684 __ j(not_equal, &miss, not_taken);
2685
2686 // Check that the key is within bounds.
2687 if (receiver->IsJSArray()) {
2688 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // Compare smis.
2689 __ j(above_equal, &miss, not_taken);
2690 } else {
2691 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis.
2692 __ j(above_equal, &miss, not_taken);
2693 }
2694
2695 // Do the store and update the write barrier. Make sure to preserve
2696 // the value in register eax.
2697 __ mov(edx, Operand(eax));
2698 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
2699 __ RecordWrite(edi, 0, edx, ecx);
2700
2701 // Done.
2702 __ ret(0);
2703
2704 // Handle store cache miss.
2705 __ bind(&miss);
2706 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2684 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2707 __ jmp(ic, RelocInfo::CODE_TARGET); 2685 __ jmp(ic, RelocInfo::CODE_TARGET);
2708 2686
2709 // Return the generated code. 2687 // Return the generated code.
2710 return GetCode(NORMAL, NULL); 2688 return GetCode(NORMAL, NULL);
2711 } 2689 }
2712 2690
2713 2691
2692 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2693 MapList* receiver_maps,
2694 CodeList* handler_ics) {
2695 // ----------- S t a t e -------------
2696 // -- eax : value
2697 // -- ecx : key
2698 // -- edx : receiver
2699 // -- esp[0] : return address
2700 // -----------------------------------
2701 Label miss;
2702 __ JumpIfSmi(edx, &miss);
2703
2704 int receiver_count = receiver_maps->length();
2705 for (int current = 0; current < receiver_count; ++current) {
2706 Handle<Map> map(receiver_maps->at(current));
2707 __ DispatchMap(edx, map, Handle<Code>(handler_ics->at(current)), true);
2708 }
2709 __ bind(&miss);
2710 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2711 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2712
2713 // Return the generated code.
2714 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2715 }
2716
2717
2714 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2718 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2715 JSObject* object, 2719 JSObject* object,
2716 JSObject* last) { 2720 JSObject* last) {
2717 // ----------- S t a t e ------------- 2721 // ----------- S t a t e -------------
2718 // -- eax : receiver 2722 // -- eax : receiver
2719 // -- ecx : name 2723 // -- ecx : name
2720 // -- esp[0] : return address 2724 // -- esp[0] : return address
2721 // ----------------------------------- 2725 // -----------------------------------
2722 Label miss; 2726 Label miss;
2723 2727
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
3113 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3117 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3114 __ bind(&miss); 3118 __ bind(&miss);
3115 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3119 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3116 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3120 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3117 3121
3118 // Return the generated code. 3122 // Return the generated code.
3119 return GetCode(CALLBACKS, name); 3123 return GetCode(CALLBACKS, name);
3120 } 3124 }
3121 3125
3122 3126
3123 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 3127 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
3124 // ----------- S t a t e ------------- 3128 // ----------- S t a t e -------------
3125 // -- eax : key 3129 // -- eax : key
3126 // -- edx : receiver 3130 // -- edx : receiver
3127 // -- esp[0] : return address 3131 // -- esp[0] : return address
3128 // ----------------------------------- 3132 // -----------------------------------
3129 Label miss; 3133 KeyedLoadIC keyed_load_ic(isolate());
3134 MaybeObject* maybe_stub =
3135 keyed_load_ic.ComputeMonomorphicBuiltinFastElementStub(
3136 receiver_map->instance_type() == JS_ARRAY_TYPE);
3137 Code* stub;
3138 if (!maybe_stub->To(&stub)) return maybe_stub;
3139 __ DispatchMap(edx,
3140 Handle<Map>(receiver_map),
3141 Handle<Code>(stub),
3142 false);
3130 3143
3131 // Check that the receiver isn't a smi.
3132 __ test(edx, Immediate(kSmiTagMask));
3133 __ j(zero, &miss, not_taken);
3134
3135 // Check that the map matches.
3136 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3137 Immediate(Handle<Map>(receiver->map())));
3138 __ j(not_equal, &miss, not_taken);
3139
3140 // Check that the key is a smi.
3141 __ test(eax, Immediate(kSmiTagMask));
3142 __ j(not_zero, &miss, not_taken);
3143
3144 // Get the elements array.
3145 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3146 __ AssertFastElements(ecx);
3147
3148 // Check that the key is within bounds.
3149 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3150 __ j(above_equal, &miss, not_taken);
3151
3152 // Load the result and make sure it's not the hole.
3153 __ mov(ebx, Operand(ecx, eax, times_2,
3154 FixedArray::kHeaderSize - kHeapObjectTag));
3155 __ cmp(ebx, factory()->the_hole_value());
3156 __ j(equal, &miss, not_taken);
3157 __ mov(eax, ebx);
3158 __ ret(0);
3159
3160 __ bind(&miss);
3161 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3144 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3162 3145
3163 // Return the generated code. 3146 // Return the generated code.
3164 return GetCode(NORMAL, NULL); 3147 return GetCode(NORMAL, NULL);
3165 } 3148 }
3166 3149
3167 3150
3151 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
3152 MapList* receiver_maps,
3153 CodeList* handler_ics) {
3154 // ----------- S t a t e -------------
3155 // -- eax : key
3156 // -- edx : receiver
3157 // -- esp[0] : return address
3158 // -----------------------------------
3159 Label miss;
3160 __ JumpIfSmi(edx, &miss);
3161
3162 int receiver_count = receiver_maps->length();
3163 for (int current = 0; current < receiver_count; ++current) {
3164 Handle<Map> map(receiver_maps->at(current));
3165 __ DispatchMap(edx, map, Handle<Code>(handler_ics->at(current)), true);
3166 }
3167 __ bind(&miss);
3168 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3169
3170 // Return the generated code.
3171 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3172 }
3173
3174
3168 // Specialized stub for constructing objects from functions which only have only 3175 // Specialized stub for constructing objects from functions which only have only
3169 // simple assignments of the form this.x = ...; in their body. 3176 // simple assignments of the form this.x = ...; in their body.
3170 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3177 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3171 // ----------- S t a t e ------------- 3178 // ----------- S t a t e -------------
3172 // -- eax : argc 3179 // -- eax : argc
3173 // -- edi : constructor 3180 // -- edi : constructor
3174 // -- esp[0] : return address 3181 // -- esp[0] : return address
3175 // -- esp[4] : last argument 3182 // -- esp[4] : last argument
3176 // ----------------------------------- 3183 // -----------------------------------
3177 Label generic_stub_call; 3184 Label generic_stub_call;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3297 __ bind(&generic_stub_call); 3304 __ bind(&generic_stub_call);
3298 Handle<Code> generic_construct_stub = 3305 Handle<Code> generic_construct_stub =
3299 isolate()->builtins()->JSConstructStubGeneric(); 3306 isolate()->builtins()->JSConstructStubGeneric();
3300 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 3307 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
3301 3308
3302 // Return the generated code. 3309 // Return the generated code.
3303 return GetCode(); 3310 return GetCode();
3304 } 3311 }
3305 3312
3306 3313
3307 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3314 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3308 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { 3315 JSObject*receiver, ExternalArrayType array_type) {
3309 // ----------- S t a t e ------------- 3316 // ----------- S t a t e -------------
3310 // -- eax : key 3317 // -- eax : key
3311 // -- edx : receiver 3318 // -- edx : receiver
3312 // -- esp[0] : return address 3319 // -- esp[0] : return address
3313 // ----------------------------------- 3320 // -----------------------------------
3314 Label slow, failed_allocation; 3321 KeyedLoadIC load_ic(isolate());
3322 MaybeObject* maybe_stub =
3323 load_ic.ComputeMonomorphicBuiltinExternalArrayStub(array_type);
3324 Code* stub;
3325 if (!maybe_stub->To(&stub)) return maybe_stub;
3326 __ DispatchMap(edx, Handle<Map>(receiver->map()), Handle<Code>(stub), false);
3315 3327
3316 // Check that the object isn't a smi. 3328 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3317 __ test(edx, Immediate(kSmiTagMask)); 3329 __ jmp(ic, RelocInfo::CODE_TARGET);
3318 __ j(zero, &slow, not_taken); 3330
3331 // Return the generated code.
3332 return GetCode();
3333 }
3334
3335
3336 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3337 JSObject* receiver, ExternalArrayType array_type) {
3338 // ----------- S t a t e -------------
3339 // -- eax : value
3340 // -- ecx : key
3341 // -- edx : receiver
3342 // -- esp[0] : return address
3343 // -----------------------------------
3344 KeyedStoreIC store_ic(isolate());
3345 MaybeObject* maybe_stub =
3346 store_ic.ComputeMonomorphicBuiltinExternalArrayStub(array_type);
3347 Code* stub;
3348 if (!maybe_stub->To(&stub)) return maybe_stub;
3349 __ DispatchMap(edx, Handle<Map>(receiver->map()), Handle<Code>(stub), false);
3350
3351 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Slow();
3352 __ jmp(ic, RelocInfo::CODE_TARGET);
3353
3354 return GetCode();
3355 }
3356
3357
3358 #undef __
3359 #define __ ACCESS_MASM(masm)
3360
3361
3362 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3363 MacroAssembler* masm,
3364 ExternalArrayType array_type) {
3365 // ----------- S t a t e -------------
3366 // -- eax : key
3367 // -- edx : receiver
3368 // -- esp[0] : return address
3369 // -----------------------------------
3370 Label miss_force_generic, failed_allocation, slow;
3319 3371
3320 // Check that the key is a smi. 3372 // Check that the key is a smi.
3321 __ test(eax, Immediate(kSmiTagMask)); 3373 __ test(eax, Immediate(kSmiTagMask));
3322 __ j(not_zero, &slow, not_taken); 3374 __ j(not_zero, &miss_force_generic, not_taken);
3323 3375
3324 // Check that the map matches.
3325 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
3326 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3327
3328 // eax: key, known to be a smi.
3329 // edx: receiver, known to be a JSObject.
3330 // ebx: elements object, known to be an external array.
3331 // Check that the index is in range. 3376 // Check that the index is in range.
3332 __ mov(ecx, eax); 3377 __ mov(ecx, eax);
3333 __ SmiUntag(ecx); // Untag the index. 3378 __ SmiUntag(ecx); // Untag the index.
3379 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3334 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 3380 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
3335 // Unsigned comparison catches both negative and too-large values. 3381 // Unsigned comparison catches both negative and too-large values.
3336 __ j(above_equal, &slow); 3382 __ j(above_equal, &miss_force_generic);
3337 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 3383 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
3338 // ebx: base pointer of external storage 3384 // ebx: base pointer of external storage
3339 switch (array_type) { 3385 switch (array_type) {
3340 case kExternalByteArray: 3386 case kExternalByteArray:
3341 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); 3387 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
3342 break; 3388 break;
3343 case kExternalUnsignedByteArray: 3389 case kExternalUnsignedByteArray:
3344 case kExternalPixelArray: 3390 case kExternalPixelArray:
3345 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); 3391 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
3346 break; 3392 break;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3433 3479
3434 // If we fail allocation of the HeapNumber, we still have a value on 3480 // If we fail allocation of the HeapNumber, we still have a value on
3435 // top of the FPU stack. Remove it. 3481 // top of the FPU stack. Remove it.
3436 __ bind(&failed_allocation); 3482 __ bind(&failed_allocation);
3437 __ ffree(); 3483 __ ffree();
3438 __ fincstp(); 3484 __ fincstp();
3439 // Fall through to slow case. 3485 // Fall through to slow case.
3440 3486
3441 // Slow case: Jump to runtime. 3487 // Slow case: Jump to runtime.
3442 __ bind(&slow); 3488 __ bind(&slow);
3443 Counters* counters = isolate()->counters(); 3489 Counters* counters = masm->isolate()->counters();
3444 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3490 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3491
3445 // ----------- S t a t e ------------- 3492 // ----------- S t a t e -------------
3446 // -- eax : key 3493 // -- eax : key
3447 // -- edx : receiver 3494 // -- edx : receiver
3448 // -- esp[0] : return address 3495 // -- esp[0] : return address
3449 // ----------------------------------- 3496 // -----------------------------------
3450 3497
3451 __ pop(ebx); 3498 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3452 __ push(edx); // receiver 3499 __ jmp(ic, RelocInfo::CODE_TARGET);
3453 __ push(eax); // name
3454 __ push(ebx); // return address
3455 3500
3456 // Perform tail call to the entry. 3501 // ----------- S t a t e -------------
3457 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3502 // -- eax : key
3503 // -- edx : receiver
3504 // -- esp[0] : return address
3505 // -----------------------------------
3458 3506
3459 // Return the generated code. 3507 // Miss case: Jump to runtime.
3460 return GetCode(flags); 3508 __ bind(&miss_force_generic);
3509 Handle<Code> miss_ic =
3510 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3511 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3461 } 3512 }
3462 3513
3463 3514
3464 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3515 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3465 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3516 MacroAssembler* masm,
3517 ExternalArrayType array_type) {
3466 // ----------- S t a t e ------------- 3518 // ----------- S t a t e -------------
3467 // -- eax : value 3519 // -- eax : key
3468 // -- ecx : key
3469 // -- edx : receiver 3520 // -- edx : receiver
3470 // -- esp[0] : return address 3521 // -- esp[0] : return address
3471 // ----------------------------------- 3522 // -----------------------------------
3472 Label slow, check_heap_number; 3523 Label miss_force_generic, slow, check_heap_number;
3473
3474 // Check that the object isn't a smi.
3475 __ test(edx, Immediate(kSmiTagMask));
3476 __ j(zero, &slow);
3477
3478 // Check that the map matches.
3479 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, false);
3480 3524
3481 // Check that the key is a smi. 3525 // Check that the key is a smi.
3482 __ test(ecx, Immediate(kSmiTagMask)); 3526 __ test(ecx, Immediate(kSmiTagMask));
3483 __ j(not_zero, &slow); 3527 __ j(not_zero, &miss_force_generic);
3484 3528
3485 // Check that the index is in range. 3529 // Check that the index is in range.
3486 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3530 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3487 __ mov(ebx, ecx); 3531 __ mov(ebx, ecx);
3488 __ SmiUntag(ebx); 3532 __ SmiUntag(ebx);
3489 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 3533 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
3490 // Unsigned comparison catches both negative and too-large values. 3534 // Unsigned comparison catches both negative and too-large values.
3491 __ j(above_equal, &slow); 3535 __ j(above_equal, &slow);
3492 3536
3493 // Handle both smis and HeapNumbers in the fast path. Go to the 3537 // Handle both smis and HeapNumbers in the fast path. Go to the
(...skipping 10 matching lines...) Expand all
3504 __ j(not_equal, &check_heap_number); 3548 __ j(not_equal, &check_heap_number);
3505 3549
3506 // smi case 3550 // smi case
3507 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed. 3551 __ mov(ecx, eax); // Preserve the value in eax. Key is no longer needed.
3508 __ SmiUntag(ecx); 3552 __ SmiUntag(ecx);
3509 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3553 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3510 // ecx: base pointer of external storage 3554 // ecx: base pointer of external storage
3511 switch (array_type) { 3555 switch (array_type) {
3512 case kExternalPixelArray: 3556 case kExternalPixelArray:
3513 { // Clamp the value to [0..255]. 3557 { // Clamp the value to [0..255].
3514 Label done; 3558 NearLabel done;
3515 __ test(ecx, Immediate(0xFFFFFF00)); 3559 __ test(ecx, Immediate(0xFFFFFF00));
3516 __ j(zero, &done, Label::kNear); 3560 __ j(zero, &done);
3517 __ setcc(negative, ecx); // 1 if negative, 0 if positive. 3561 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3518 __ dec_b(ecx); // 0 if negative, 255 if positive. 3562 __ dec_b(ecx); // 0 if negative, 255 if positive.
3519 __ bind(&done); 3563 __ bind(&done);
3520 } 3564 }
3521 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3565 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3522 break; 3566 break;
3523 case kExternalByteArray: 3567 case kExternalByteArray:
3524 case kExternalUnsignedByteArray: 3568 case kExternalUnsignedByteArray:
3525 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3569 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3526 break; 3570 break;
(...skipping 25 matching lines...) Expand all
3552 3596
3553 // TODO(danno): handle heap number -> pixel array conversion 3597 // TODO(danno): handle heap number -> pixel array conversion
3554 if (array_type != kExternalPixelArray) { 3598 if (array_type != kExternalPixelArray) {
3555 __ bind(&check_heap_number); 3599 __ bind(&check_heap_number);
3556 // eax: value 3600 // eax: value
3557 // edx: receiver 3601 // edx: receiver
3558 // ecx: key 3602 // ecx: key
3559 // edi: elements array 3603 // edi: elements array
3560 // ebx: untagged index 3604 // ebx: untagged index
3561 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3605 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3562 Immediate(factory()->heap_number_map())); 3606 Immediate(masm->isolate()->factory()->heap_number_map()));
3563 __ j(not_equal, &slow); 3607 __ j(not_equal, &slow);
3564 3608
3565 // The WebGL specification leaves the behavior of storing NaN and 3609 // The WebGL specification leaves the behavior of storing NaN and
3566 // +/-Infinity into integer arrays basically undefined. For more 3610 // +/-Infinity into integer arrays basically undefined. For more
3567 // reproducible behavior, convert these to zero. 3611 // reproducible behavior, convert these to zero.
3568 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3612 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3569 // ebx: untagged index 3613 // ebx: untagged index
3570 // edi: base pointer of external storage 3614 // edi: base pointer of external storage
3571 if (array_type == kExternalFloatArray) { 3615 if (array_type == kExternalFloatArray) {
3572 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3616 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
(...skipping 14 matching lines...) Expand all
3587 if (CpuFeatures::IsSupported(SSE2)) { 3631 if (CpuFeatures::IsSupported(SSE2)) {
3588 if (array_type != kExternalIntArray && 3632 if (array_type != kExternalIntArray &&
3589 array_type != kExternalUnsignedIntArray) { 3633 array_type != kExternalUnsignedIntArray) {
3590 ASSERT(CpuFeatures::IsSupported(SSE2)); 3634 ASSERT(CpuFeatures::IsSupported(SSE2));
3591 CpuFeatures::Scope scope(SSE2); 3635 CpuFeatures::Scope scope(SSE2);
3592 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset)); 3636 __ cvttsd2si(ecx, FieldOperand(eax, HeapNumber::kValueOffset));
3593 // ecx: untagged integer value 3637 // ecx: untagged integer value
3594 switch (array_type) { 3638 switch (array_type) {
3595 case kExternalPixelArray: 3639 case kExternalPixelArray:
3596 { // Clamp the value to [0..255]. 3640 { // Clamp the value to [0..255].
3597 Label done; 3641 NearLabel done;
Mads Ager (chromium) 2011/05/10 13:38:06 Accidental edit? There are more than this one I th
danno 2011/05/11 14:20:19 Done.
3598 __ test(ecx, Immediate(0xFFFFFF00)); 3642 __ test(ecx, Immediate(0xFFFFFF00));
3599 __ j(zero, &done, Label::kNear); 3643 __ j(zero, &done);
3600 __ setcc(negative, ecx); // 1 if negative, 0 if positive. 3644 __ setcc(negative, ecx); // 1 if negative, 0 if positive.
3601 __ dec_b(ecx); // 0 if negative, 255 if positive. 3645 __ dec_b(ecx); // 0 if negative, 255 if positive.
3602 __ bind(&done); 3646 __ bind(&done);
3603 } 3647 }
3604 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3648 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3605 break; 3649 break;
3606 case kExternalByteArray: 3650 case kExternalByteArray:
3607 case kExternalUnsignedByteArray: 3651 case kExternalUnsignedByteArray:
3608 __ mov_b(Operand(edi, ebx, times_1, 0), ecx); 3652 __ mov_b(Operand(edi, ebx, times_1, 0), ecx);
3609 break; 3653 break;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
3647 // ecx: untagged integer value 3691 // ecx: untagged integer value
3648 __ mov(Operand(edi, ebx, times_4, 0), ecx); 3692 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3649 } 3693 }
3650 __ ret(0); // Return original value. 3694 __ ret(0); // Return original value.
3651 } 3695 }
3652 } 3696 }
3653 } 3697 }
3654 3698
3655 // Slow case: call runtime. 3699 // Slow case: call runtime.
3656 __ bind(&slow); 3700 __ bind(&slow);
3701 Counters* counters = masm->isolate()->counters();
3702 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3703
3657 // ----------- S t a t e ------------- 3704 // ----------- S t a t e -------------
3658 // -- eax : value 3705 // -- eax : value
3659 // -- ecx : key 3706 // -- ecx : key
3660 // -- edx : receiver 3707 // -- edx : receiver
3661 // -- esp[0] : return address 3708 // -- esp[0] : return address
3662 // ----------------------------------- 3709 // -----------------------------------
3663 3710
3664 __ pop(ebx); 3711 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3665 __ push(edx); 3712 __ jmp(ic, RelocInfo::CODE_TARGET);
3666 __ push(ecx);
3667 __ push(eax);
3668 __ push(Immediate(Smi::FromInt(NONE))); // PropertyAttributes
3669 __ push(Immediate(Smi::FromInt(
3670 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
3671 __ push(ebx); // return address
3672 3713
3673 // Do tail-call to runtime routine. 3714 // ----------- S t a t e -------------
3674 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 3715 // -- eax : value
3716 // -- ecx : key
3717 // -- edx : receiver
3718 // -- esp[0] : return address
3719 // -----------------------------------
3675 3720
3676 return GetCode(flags); 3721 __ bind(&miss_force_generic);
3722 Handle<Code> miss_ic =
3723 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3724 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3677 } 3725 }
3678 3726
3679 3727
3728
3729
3730 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3731 // ----------- S t a t e -------------
3732 // -- eax : key
3733 // -- edx : receiver
3734 // -- esp[0] : return address
3735 // -----------------------------------
3736 Label miss_force_generic;
3737
3738 // Check that the key is a smi.
3739 __ test(eax, Immediate(kSmiTagMask));
3740 __ j(not_zero, &miss_force_generic, not_taken);
3741
3742 // Get the elements array.
3743 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3744 __ AssertFastElements(ecx);
3745
3746 // Check that the key is within bounds.
3747 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3748 __ j(above_equal, &miss_force_generic, not_taken);
3749
3750 // Load the result and make sure it's not the hole.
3751 __ mov(ebx, Operand(ecx, eax, times_2,
3752 FixedArray::kHeaderSize - kHeapObjectTag));
3753 __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3754 __ j(equal, &miss_force_generic, not_taken);
3755 __ mov(eax, ebx);
3756 __ ret(0);
3757
3758 __ bind(&miss_force_generic);
3759 Handle<Code> miss_ic =
3760 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3761 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3762 }
3763
3764
3765 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3766 bool is_js_array) {
3767 // ----------- S t a t e -------------
3768 // -- eax : key
3769 // -- edx : receiver
3770 // -- esp[0] : return address
3771 // -----------------------------------
3772 Label miss_force_generic;
3773
3774 // Check that the key is a smi.
3775 __ test(ecx, Immediate(kSmiTagMask));
3776 __ j(not_zero, &miss_force_generic, not_taken);
3777
3778 // Get the elements array and make sure it is a fast element array, not 'cow'.
3779 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3780 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3781 Immediate(masm->isolate()->factory()->fixed_array_map()));
3782 __ j(not_equal, &miss_force_generic, not_taken);
3783
3784 if (is_js_array) {
3785 // Check that the key is within bounds.
3786 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3787 __ j(above_equal, &miss_force_generic, not_taken);
3788
3789 } else {
3790 // Check that the key is within bounds.
3791 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3792 __ j(above_equal, &miss_force_generic, not_taken);
3793 }
3794
3795 // Do the store and update the write barrier. Make sure to preserve
3796 // the value in register eax.
3797 __ mov(edx, Operand(eax));
3798 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
3799 __ RecordWrite(edi, 0, edx, ecx);
3800
3801 // Done.
3802 __ ret(0);
3803
3804 // Handle store cache miss, replacing the ic with the generic stub.
3805 __ bind(&miss_force_generic);
3806 Handle<Code> ic_force_generic =
3807 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3808 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3809 }
3810
3811
3680 #undef __ 3812 #undef __
3681 3813
3682 } } // namespace v8::internal 3814 } } // namespace v8::internal
3683 3815
3684 #endif // V8_TARGET_ARCH_IA32 3816 #endif // V8_TARGET_ARCH_IA32
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698