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

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: final review feedback 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
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.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 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);
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 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2674 MaybeObject* maybe_stub =
2675 KeyedStoreFastElementStub(is_js_array).TryGetCode();
2676 Code* stub;
2677 if (!maybe_stub->To(&stub)) return maybe_stub;
2678 __ DispatchMap(edx,
2679 Handle<Map>(receiver_map),
2680 Handle<Code>(stub),
2681 DO_SMI_CHECK);
2666 2682
2667 // Check that the receiver isn't a smi.
2668 __ test(edx, Immediate(kSmiTagMask));
2669 __ j(zero, &miss);
2670
2671 // Check that the map matches.
2672 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
2673 Immediate(Handle<Map>(receiver->map())));
2674 __ j(not_equal, &miss);
2675
2676 // Check that the key is a smi.
2677 __ test(ecx, Immediate(kSmiTagMask));
2678 __ j(not_zero, &miss);
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);
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);
2690 } else {
2691 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // Compare smis.
2692 __ j(above_equal, &miss);
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(); 2683 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2707 __ jmp(ic, RelocInfo::CODE_TARGET); 2684 __ jmp(ic, RelocInfo::CODE_TARGET);
2708 2685
2709 // Return the generated code. 2686 // Return the generated code.
2710 return GetCode(NORMAL, NULL); 2687 return GetCode(NORMAL, NULL);
2711 } 2688 }
2712 2689
2713 2690
2691 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2692 MapList* receiver_maps,
2693 CodeList* handler_ics) {
2694 // ----------- S t a t e -------------
2695 // -- eax : value
2696 // -- ecx : key
2697 // -- edx : receiver
2698 // -- esp[0] : return address
2699 // -----------------------------------
2700 Label miss;
2701 __ JumpIfSmi(edx, &miss);
2702
2703 Register map_reg = ebx;
2704 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
2705 int receiver_count = receiver_maps->length();
2706 for (int current = 0; current < receiver_count; ++current) {
2707 Handle<Map> map(receiver_maps->at(current));
2708 __ cmp(map_reg, map);
2709 __ j(equal, Handle<Code>(handler_ics->at(current)));
2710 }
2711 __ bind(&miss);
2712 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
2713 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
2714
2715 // Return the generated code.
2716 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2717 }
2718
2719
2714 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2720 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2715 JSObject* object, 2721 JSObject* object,
2716 JSObject* last) { 2722 JSObject* last) {
2717 // ----------- S t a t e ------------- 2723 // ----------- S t a t e -------------
2718 // -- eax : receiver 2724 // -- eax : receiver
2719 // -- ecx : name 2725 // -- ecx : name
2720 // -- esp[0] : return address 2726 // -- esp[0] : return address
2721 // ----------------------------------- 2727 // -----------------------------------
2722 Label miss; 2728 Label miss;
2723 2729
(...skipping 389 matching lines...) Expand 10 before | Expand all | Expand 10 after
3113 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss); 3119 GenerateLoadFunctionPrototype(masm(), edx, ecx, ebx, &miss);
3114 __ bind(&miss); 3120 __ bind(&miss);
3115 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 3121 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
3116 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3122 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3117 3123
3118 // Return the generated code. 3124 // Return the generated code.
3119 return GetCode(CALLBACKS, name); 3125 return GetCode(CALLBACKS, name);
3120 } 3126 }
3121 3127
3122 3128
3123 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 3129 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
3124 // ----------- S t a t e ------------- 3130 // ----------- S t a t e -------------
3125 // -- eax : key 3131 // -- eax : key
3126 // -- edx : receiver 3132 // -- edx : receiver
3127 // -- esp[0] : return address 3133 // -- esp[0] : return address
3128 // ----------------------------------- 3134 // -----------------------------------
3129 Label miss; 3135 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
3136 Code* stub;
3137 if (!maybe_stub->To(&stub)) return maybe_stub;
3138 __ DispatchMap(edx,
3139 Handle<Map>(receiver_map),
3140 Handle<Code>(stub),
3141 DO_SMI_CHECK);
3130 3142
3131 // Check that the receiver isn't a smi.
3132 __ test(edx, Immediate(kSmiTagMask));
3133 __ j(zero, &miss);
3134
3135 // Check that the map matches.
3136 __ cmp(FieldOperand(edx, HeapObject::kMapOffset),
3137 Immediate(Handle<Map>(receiver->map())));
3138 __ j(not_equal, &miss);
3139
3140 // Check that the key is a smi.
3141 __ test(eax, Immediate(kSmiTagMask));
3142 __ j(not_zero, &miss);
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);
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);
3157 __ mov(eax, ebx);
3158 __ ret(0);
3159
3160 __ bind(&miss);
3161 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3143 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3162 3144
3163 // Return the generated code. 3145 // Return the generated code.
3164 return GetCode(NORMAL, NULL); 3146 return GetCode(NORMAL, NULL);
3165 } 3147 }
3166 3148
3167 3149
3150 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
3151 MapList* receiver_maps,
3152 CodeList* handler_ics) {
3153 // ----------- S t a t e -------------
3154 // -- eax : key
3155 // -- edx : receiver
3156 // -- esp[0] : return address
3157 // -----------------------------------
3158 Label miss;
3159 __ JumpIfSmi(edx, &miss);
3160
3161 Register map_reg = ebx;
3162 __ mov(map_reg, FieldOperand(edx, HeapObject::kMapOffset));
3163 int receiver_count = receiver_maps->length();
3164 for (int current = 0; current < receiver_count; ++current) {
3165 Handle<Map> map(receiver_maps->at(current));
3166 __ cmp(map_reg, map);
3167 __ j(equal, Handle<Code>(handler_ics->at(current)));
3168 }
3169
3170 __ bind(&miss);
3171 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3172
3173 // Return the generated code.
3174 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3175 }
3176
3177
3168 // Specialized stub for constructing objects from functions which only have only 3178 // Specialized stub for constructing objects from functions which only have only
3169 // simple assignments of the form this.x = ...; in their body. 3179 // simple assignments of the form this.x = ...; in their body.
3170 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3180 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3171 // ----------- S t a t e ------------- 3181 // ----------- S t a t e -------------
3172 // -- eax : argc 3182 // -- eax : argc
3173 // -- edi : constructor 3183 // -- edi : constructor
3174 // -- esp[0] : return address 3184 // -- esp[0] : return address
3175 // -- esp[4] : last argument 3185 // -- esp[4] : last argument
3176 // ----------------------------------- 3186 // -----------------------------------
3177 Label generic_stub_call; 3187 Label generic_stub_call;
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
3297 __ bind(&generic_stub_call); 3307 __ bind(&generic_stub_call);
3298 Handle<Code> generic_construct_stub = 3308 Handle<Code> generic_construct_stub =
3299 isolate()->builtins()->JSConstructStubGeneric(); 3309 isolate()->builtins()->JSConstructStubGeneric();
3300 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET); 3310 __ jmp(generic_construct_stub, RelocInfo::CODE_TARGET);
3301 3311
3302 // Return the generated code. 3312 // Return the generated code.
3303 return GetCode(); 3313 return GetCode();
3304 } 3314 }
3305 3315
3306 3316
3307 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3317 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3308 JSObject*receiver, ExternalArrayType array_type, Code::Flags flags) { 3318 JSObject*receiver, ExternalArrayType array_type) {
3309 // ----------- S t a t e ------------- 3319 // ----------- S t a t e -------------
3310 // -- eax : key 3320 // -- eax : key
3311 // -- edx : receiver 3321 // -- edx : receiver
3312 // -- esp[0] : return address 3322 // -- esp[0] : return address
3313 // ----------------------------------- 3323 // -----------------------------------
3314 Label slow, failed_allocation; 3324 MaybeObject* maybe_stub =
3325 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3326 Code* stub;
3327 if (!maybe_stub->To(&stub)) return maybe_stub;
3328 __ DispatchMap(edx,
3329 Handle<Map>(receiver->map()),
3330 Handle<Code>(stub),
3331 DO_SMI_CHECK);
3315 3332
3316 // Check that the object isn't a smi. 3333 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3317 __ test(edx, Immediate(kSmiTagMask)); 3334 __ jmp(ic, RelocInfo::CODE_TARGET);
3318 __ j(zero, &slow); 3335
3336 // Return the generated code.
3337 return GetCode();
3338 }
3339
3340
3341 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3342 JSObject* receiver, ExternalArrayType array_type) {
3343 // ----------- S t a t e -------------
3344 // -- eax : value
3345 // -- ecx : key
3346 // -- edx : receiver
3347 // -- esp[0] : return address
3348 // -----------------------------------
3349 MaybeObject* maybe_stub =
3350 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3351 Code* stub;
3352 if (!maybe_stub->To(&stub)) return maybe_stub;
3353 __ DispatchMap(edx,
3354 Handle<Map>(receiver->map()),
3355 Handle<Code>(stub),
3356 DO_SMI_CHECK);
3357
3358 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3359 __ jmp(ic, RelocInfo::CODE_TARGET);
3360
3361 return GetCode();
3362 }
3363
3364
3365 #undef __
3366 #define __ ACCESS_MASM(masm)
3367
3368
3369 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3370 MacroAssembler* masm,
3371 ExternalArrayType array_type) {
3372 // ----------- S t a t e -------------
3373 // -- eax : key
3374 // -- edx : receiver
3375 // -- esp[0] : return address
3376 // -----------------------------------
3377 Label miss_force_generic, failed_allocation, slow;
3378
3379 // This stub is meant to be tail-jumped to, the receiver must already
3380 // have been verified by the caller to not be a smi.
3319 3381
3320 // Check that the key is a smi. 3382 // Check that the key is a smi.
3321 __ test(eax, Immediate(kSmiTagMask)); 3383 __ test(eax, Immediate(kSmiTagMask));
3322 __ j(not_zero, &slow); 3384 __ j(not_zero, &miss_force_generic);
3323 3385
3324 // Check that the map matches.
3325 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, DO_SMI_CHECK);
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. 3386 // Check that the index is in range.
3332 __ mov(ecx, eax); 3387 __ mov(ecx, eax);
3333 __ SmiUntag(ecx); // Untag the index. 3388 __ SmiUntag(ecx); // Untag the index.
3389 __ mov(ebx, FieldOperand(edx, JSObject::kElementsOffset));
3334 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset)); 3390 __ cmp(ecx, FieldOperand(ebx, ExternalArray::kLengthOffset));
3335 // Unsigned comparison catches both negative and too-large values. 3391 // Unsigned comparison catches both negative and too-large values.
3336 __ j(above_equal, &slow); 3392 __ j(above_equal, &miss_force_generic);
3337 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset)); 3393 __ mov(ebx, FieldOperand(ebx, ExternalArray::kExternalPointerOffset));
3338 // ebx: base pointer of external storage 3394 // ebx: base pointer of external storage
3339 switch (array_type) { 3395 switch (array_type) {
3340 case kExternalByteArray: 3396 case kExternalByteArray:
3341 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0)); 3397 __ movsx_b(eax, Operand(ebx, ecx, times_1, 0));
3342 break; 3398 break;
3343 case kExternalUnsignedByteArray: 3399 case kExternalUnsignedByteArray:
3344 case kExternalPixelArray: 3400 case kExternalPixelArray:
3345 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0)); 3401 __ movzx_b(eax, Operand(ebx, ecx, times_1, 0));
3346 break; 3402 break;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
3433 3489
3434 // If we fail allocation of the HeapNumber, we still have a value on 3490 // If we fail allocation of the HeapNumber, we still have a value on
3435 // top of the FPU stack. Remove it. 3491 // top of the FPU stack. Remove it.
3436 __ bind(&failed_allocation); 3492 __ bind(&failed_allocation);
3437 __ ffree(); 3493 __ ffree();
3438 __ fincstp(); 3494 __ fincstp();
3439 // Fall through to slow case. 3495 // Fall through to slow case.
3440 3496
3441 // Slow case: Jump to runtime. 3497 // Slow case: Jump to runtime.
3442 __ bind(&slow); 3498 __ bind(&slow);
3443 Counters* counters = isolate()->counters(); 3499 Counters* counters = masm->isolate()->counters();
3444 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3500 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3501
3445 // ----------- S t a t e ------------- 3502 // ----------- S t a t e -------------
3446 // -- eax : key 3503 // -- eax : key
3447 // -- edx : receiver 3504 // -- edx : receiver
3448 // -- esp[0] : return address 3505 // -- esp[0] : return address
3449 // ----------------------------------- 3506 // -----------------------------------
3450 3507
3451 __ pop(ebx); 3508 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3452 __ push(edx); // receiver 3509 __ jmp(ic, RelocInfo::CODE_TARGET);
3453 __ push(eax); // name
3454 __ push(ebx); // return address
3455 3510
3456 // Perform tail call to the entry. 3511 // ----------- S t a t e -------------
3457 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3512 // -- eax : key
3513 // -- edx : receiver
3514 // -- esp[0] : return address
3515 // -----------------------------------
3458 3516
3459 // Return the generated code. 3517 // Miss case: Jump to runtime.
3460 return GetCode(flags); 3518 __ bind(&miss_force_generic);
3519 Handle<Code> miss_ic =
3520 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3521 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3461 } 3522 }
3462 3523
3463 3524
3464 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3525 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3465 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3526 MacroAssembler* masm,
3527 ExternalArrayType array_type) {
3466 // ----------- S t a t e ------------- 3528 // ----------- S t a t e -------------
3467 // -- eax : value 3529 // -- eax : key
3468 // -- ecx : key
3469 // -- edx : receiver 3530 // -- edx : receiver
3470 // -- esp[0] : return address 3531 // -- esp[0] : return address
3471 // ----------------------------------- 3532 // -----------------------------------
3472 Label slow, check_heap_number; 3533 Label miss_force_generic, slow, check_heap_number;
3473 3534
3474 // Check that the object isn't a smi. 3535 // This stub is meant to be tail-jumped to, the receiver must already
3475 __ test(edx, Immediate(kSmiTagMask)); 3536 // have been verified by the caller to not be a smi.
3476 __ j(zero, &slow);
3477
3478 // Check that the map matches.
3479 __ CheckMap(edx, Handle<Map>(receiver->map()), &slow, DO_SMI_CHECK);
3480 3537
3481 // Check that the key is a smi. 3538 // Check that the key is a smi.
3482 __ test(ecx, Immediate(kSmiTagMask)); 3539 __ test(ecx, Immediate(kSmiTagMask));
3483 __ j(not_zero, &slow); 3540 __ j(not_zero, &miss_force_generic);
3484 3541
3485 // Check that the index is in range. 3542 // Check that the index is in range.
3486 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset)); 3543 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3487 __ mov(ebx, ecx); 3544 __ mov(ebx, ecx);
3488 __ SmiUntag(ebx); 3545 __ SmiUntag(ebx);
3489 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset)); 3546 __ cmp(ebx, FieldOperand(edi, ExternalArray::kLengthOffset));
3490 // Unsigned comparison catches both negative and too-large values. 3547 // Unsigned comparison catches both negative and too-large values.
3491 __ j(above_equal, &slow); 3548 __ j(above_equal, &slow);
3492 3549
3493 // Handle both smis and HeapNumbers in the fast path. Go to the 3550 // Handle both smis and HeapNumbers in the fast path. Go to the
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
3552 3609
3553 // TODO(danno): handle heap number -> pixel array conversion 3610 // TODO(danno): handle heap number -> pixel array conversion
3554 if (array_type != kExternalPixelArray) { 3611 if (array_type != kExternalPixelArray) {
3555 __ bind(&check_heap_number); 3612 __ bind(&check_heap_number);
3556 // eax: value 3613 // eax: value
3557 // edx: receiver 3614 // edx: receiver
3558 // ecx: key 3615 // ecx: key
3559 // edi: elements array 3616 // edi: elements array
3560 // ebx: untagged index 3617 // ebx: untagged index
3561 __ cmp(FieldOperand(eax, HeapObject::kMapOffset), 3618 __ cmp(FieldOperand(eax, HeapObject::kMapOffset),
3562 Immediate(factory()->heap_number_map())); 3619 Immediate(masm->isolate()->factory()->heap_number_map()));
3563 __ j(not_equal, &slow); 3620 __ j(not_equal, &slow);
3564 3621
3565 // The WebGL specification leaves the behavior of storing NaN and 3622 // The WebGL specification leaves the behavior of storing NaN and
3566 // +/-Infinity into integer arrays basically undefined. For more 3623 // +/-Infinity into integer arrays basically undefined. For more
3567 // reproducible behavior, convert these to zero. 3624 // reproducible behavior, convert these to zero.
3568 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset)); 3625 __ mov(edi, FieldOperand(edi, ExternalArray::kExternalPointerOffset));
3569 // ebx: untagged index 3626 // ebx: untagged index
3570 // edi: base pointer of external storage 3627 // edi: base pointer of external storage
3571 if (array_type == kExternalFloatArray) { 3628 if (array_type == kExternalFloatArray) {
3572 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset)); 3629 __ fld_d(FieldOperand(eax, HeapNumber::kValueOffset));
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
3647 // ecx: untagged integer value 3704 // ecx: untagged integer value
3648 __ mov(Operand(edi, ebx, times_4, 0), ecx); 3705 __ mov(Operand(edi, ebx, times_4, 0), ecx);
3649 } 3706 }
3650 __ ret(0); // Return original value. 3707 __ ret(0); // Return original value.
3651 } 3708 }
3652 } 3709 }
3653 } 3710 }
3654 3711
3655 // Slow case: call runtime. 3712 // Slow case: call runtime.
3656 __ bind(&slow); 3713 __ bind(&slow);
3714 Counters* counters = masm->isolate()->counters();
3715 __ IncrementCounter(counters->keyed_store_external_array_slow(), 1);
3716
3657 // ----------- S t a t e ------------- 3717 // ----------- S t a t e -------------
3658 // -- eax : value 3718 // -- eax : value
3659 // -- ecx : key 3719 // -- ecx : key
3660 // -- edx : receiver 3720 // -- edx : receiver
3661 // -- esp[0] : return address 3721 // -- esp[0] : return address
3662 // ----------------------------------- 3722 // -----------------------------------
3663 3723
3664 __ pop(ebx); 3724 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3665 __ push(edx); 3725 __ 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 3726
3673 // Do tail-call to runtime routine. 3727 // ----------- S t a t e -------------
3674 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 3728 // -- eax : value
3729 // -- ecx : key
3730 // -- edx : receiver
3731 // -- esp[0] : return address
3732 // -----------------------------------
3675 3733
3676 return GetCode(flags); 3734 __ bind(&miss_force_generic);
3735 Handle<Code> miss_ic =
3736 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3737 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3677 } 3738 }
3678 3739
3679 3740
3741
3742
3743 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3744 // ----------- S t a t e -------------
3745 // -- eax : key
3746 // -- edx : receiver
3747 // -- esp[0] : return address
3748 // -----------------------------------
3749 Label miss_force_generic;
3750
3751 // This stub is meant to be tail-jumped to, the receiver must already
3752 // have been verified by the caller to not be a smi.
3753
3754 // Check that the key is a smi.
3755 __ test(eax, Immediate(kSmiTagMask));
3756 __ j(not_zero, &miss_force_generic);
3757
3758 // Get the elements array.
3759 __ mov(ecx, FieldOperand(edx, JSObject::kElementsOffset));
3760 __ AssertFastElements(ecx);
3761
3762 // Check that the key is within bounds.
3763 __ cmp(eax, FieldOperand(ecx, FixedArray::kLengthOffset));
3764 __ j(above_equal, &miss_force_generic);
3765
3766 // Load the result and make sure it's not the hole.
3767 __ mov(ebx, Operand(ecx, eax, times_2,
3768 FixedArray::kHeaderSize - kHeapObjectTag));
3769 __ cmp(ebx, masm->isolate()->factory()->the_hole_value());
3770 __ j(equal, &miss_force_generic);
3771 __ mov(eax, ebx);
3772 __ ret(0);
3773
3774 __ bind(&miss_force_generic);
3775 Handle<Code> miss_ic =
3776 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3777 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3778 }
3779
3780
3781 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3782 bool is_js_array) {
3783 // ----------- S t a t e -------------
3784 // -- eax : key
3785 // -- edx : receiver
3786 // -- esp[0] : return address
3787 // -----------------------------------
3788 Label miss_force_generic;
3789
3790 // This stub is meant to be tail-jumped to, the receiver must already
3791 // have been verified by the caller to not be a smi.
3792
3793 // Check that the key is a smi.
3794 __ test(ecx, Immediate(kSmiTagMask));
3795 __ j(not_zero, &miss_force_generic);
3796
3797 // Get the elements array and make sure it is a fast element array, not 'cow'.
3798 __ mov(edi, FieldOperand(edx, JSObject::kElementsOffset));
3799 __ cmp(FieldOperand(edi, HeapObject::kMapOffset),
3800 Immediate(masm->isolate()->factory()->fixed_array_map()));
3801 __ j(not_equal, &miss_force_generic);
3802
3803 if (is_js_array) {
3804 // Check that the key is within bounds.
3805 __ cmp(ecx, FieldOperand(edx, JSArray::kLengthOffset)); // smis.
3806 __ j(above_equal, &miss_force_generic);
3807 } else {
3808 // Check that the key is within bounds.
3809 __ cmp(ecx, FieldOperand(edi, FixedArray::kLengthOffset)); // smis.
3810 __ j(above_equal, &miss_force_generic);
3811 }
3812
3813 // Do the store and update the write barrier. Make sure to preserve
3814 // the value in register eax.
3815 __ mov(edx, Operand(eax));
3816 __ mov(FieldOperand(edi, ecx, times_2, FixedArray::kHeaderSize), eax);
3817 __ RecordWrite(edi, 0, edx, ecx);
3818
3819 // Done.
3820 __ ret(0);
3821
3822 // Handle store cache miss, replacing the ic with the generic stub.
3823 __ bind(&miss_force_generic);
3824 Handle<Code> ic_force_generic =
3825 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3826 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3827 }
3828
3829
3680 #undef __ 3830 #undef __
3681 3831
3682 } } // namespace v8::internal 3832 } } // namespace v8::internal
3683 3833
3684 #endif // V8_TARGET_ARCH_IA32 3834 #endif // V8_TARGET_ARCH_IA32
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.cc ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698