OLD | NEW |
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 729 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
740 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); | 740 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); |
741 } else { | 741 } else { |
742 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); | 742 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); |
743 } | 743 } |
744 | 744 |
745 Handle<Code> ic(code); | 745 Handle<Code> ic(code); |
746 __ Jump(ic, RelocInfo::CODE_TARGET); | 746 __ Jump(ic, RelocInfo::CODE_TARGET); |
747 } | 747 } |
748 | 748 |
749 | 749 |
| 750 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { |
| 751 Code* code = masm->isolate()->builtins()->builtin( |
| 752 Builtins::kKeyedLoadIC_MissForceGeneric); |
| 753 Handle<Code> ic(code); |
| 754 __ Jump(ic, RelocInfo::CODE_TARGET); |
| 755 } |
| 756 |
| 757 |
750 // Both name_reg and receiver_reg are preserved on jumps to miss_label, | 758 // Both name_reg and receiver_reg are preserved on jumps to miss_label, |
751 // but may be destroyed if store is successful. | 759 // but may be destroyed if store is successful. |
752 void StubCompiler::GenerateStoreField(MacroAssembler* masm, | 760 void StubCompiler::GenerateStoreField(MacroAssembler* masm, |
753 JSObject* object, | 761 JSObject* object, |
754 int index, | 762 int index, |
755 Map* transition, | 763 Map* transition, |
756 Register receiver_reg, | 764 Register receiver_reg, |
757 Register name_reg, | 765 Register name_reg, |
758 Register scratch, | 766 Register scratch, |
759 Label* miss_label) { | 767 Label* miss_label) { |
(...skipping 1756 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2516 __ bind(&miss); | 2524 __ bind(&miss); |
2517 __ DecrementCounter(counters->keyed_store_field(), 1); | 2525 __ DecrementCounter(counters->keyed_store_field(), 1); |
2518 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2526 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2519 __ Jump(ic, RelocInfo::CODE_TARGET); | 2527 __ Jump(ic, RelocInfo::CODE_TARGET); |
2520 | 2528 |
2521 // Return the generated code. | 2529 // Return the generated code. |
2522 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); | 2530 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); |
2523 } | 2531 } |
2524 | 2532 |
2525 | 2533 |
2526 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( | 2534 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized(Handle<Map> receive
r_map) { |
2527 JSObject* receiver) { | |
2528 // ----------- S t a t e ------------- | 2535 // ----------- S t a t e ------------- |
2529 // -- rax : value | 2536 // -- rax : value |
2530 // -- rcx : key | 2537 // -- rcx : key |
2531 // -- rdx : receiver | 2538 // -- rdx : receiver |
2532 // -- rsp[0] : return address | 2539 // -- rsp[0] : return address |
2533 // ----------------------------------- | 2540 // ----------------------------------- |
2534 Label miss; | 2541 Label miss, miss_force_generic; |
2535 | 2542 |
2536 // Check that the receiver isn't a smi. | 2543 __ CheckMap(rdx, receiver_map, &miss, false); |
2537 __ JumpIfSmi(rdx, &miss); | |
2538 | |
2539 // Check that the map matches. | |
2540 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | |
2541 Handle<Map>(receiver->map())); | |
2542 __ j(not_equal, &miss); | |
2543 | 2544 |
2544 // Check that the key is a smi. | 2545 // Check that the key is a smi. |
2545 __ JumpIfNotSmi(rcx, &miss); | 2546 __ JumpIfNotSmi(rcx, &miss_force_generic); |
2546 | 2547 |
2547 // Get the elements array and make sure it is a fast element array, not 'cow'. | 2548 // Get the elements array and make sure it is a fast element array, not 'cow'. |
2548 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); | 2549 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); |
2549 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), | 2550 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), |
2550 factory()->fixed_array_map()); | 2551 factory()->fixed_array_map()); |
2551 __ j(not_equal, &miss); | 2552 __ j(not_equal, &miss_force_generic); |
2552 | 2553 |
2553 // Check that the key is within bounds. | 2554 // Check that the key is within bounds. |
2554 if (receiver->IsJSArray()) { | 2555 if (receiver_map->instance_type() == JS_ARRAY_TYPE) { |
2555 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); | 2556 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); |
2556 __ j(above_equal, &miss); | 2557 __ j(above_equal, &miss_force_generic); |
2557 } else { | 2558 } else { |
2558 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); | 2559 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); |
2559 __ j(above_equal, &miss); | 2560 __ j(above_equal, &miss_force_generic); |
2560 } | 2561 } |
2561 | 2562 |
2562 // Do the store and update the write barrier. Make sure to preserve | 2563 // Do the store and update the write barrier. Make sure to preserve |
2563 // the value in register eax. | 2564 // the value in register eax. |
2564 __ movq(rdx, rax); | 2565 __ movq(rdx, rax); |
2565 __ SmiToInteger32(rcx, rcx); | 2566 __ SmiToInteger32(rcx, rcx); |
2566 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), | 2567 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), |
2567 rax); | 2568 rax); |
2568 __ RecordWrite(rdi, 0, rdx, rcx); | 2569 __ RecordWrite(rdi, 0, rdx, rcx); |
2569 | 2570 |
2570 // Done. | 2571 // Done. |
2571 __ ret(0); | 2572 __ ret(0); |
2572 | 2573 |
2573 // Handle store cache miss. | 2574 // Handle store cache miss. |
2574 __ bind(&miss); | 2575 __ bind(&miss); |
2575 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); | 2576 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
2576 __ jmp(ic, RelocInfo::CODE_TARGET); | 2577 __ jmp(ic, RelocInfo::CODE_TARGET); |
2577 | 2578 |
| 2579 // Handle store cache miss. |
| 2580 __ bind(&miss_force_generic); |
| 2581 Handle<Code> ic_force_generic = |
| 2582 isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
| 2583 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); |
| 2584 |
2578 // Return the generated code. | 2585 // Return the generated code. |
2579 return GetCode(NORMAL, NULL); | 2586 return GetCode(NORMAL, NULL); |
2580 } | 2587 } |
2581 | 2588 |
2582 | 2589 |
| 2590 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic( |
| 2591 ZoneMapList* receiver_maps, |
| 2592 ZoneCodeList* handler_ics) { |
| 2593 // ----------- S t a t e ------------- |
| 2594 // -- rax : receiver |
| 2595 // -- rcx : name |
| 2596 // -- rsp[0] : return address |
| 2597 // ----------------------------------- |
| 2598 Label miss; |
| 2599 __ JumpIfSmi(rax, &miss); |
| 2600 |
| 2601 int receiver_count = receiver_maps->length(); |
| 2602 for (int current = 0; current < receiver_count; ++current) { |
| 2603 // Check map and tail call if there's a match |
| 2604 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), receiver_maps->at(current)
); |
| 2605 __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET); |
| 2606 } |
| 2607 __ bind(&miss); |
| 2608 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 2609 __ jmp(ic, RelocInfo::CODE_TARGET); |
| 2610 |
| 2611 // Return the generated code. |
| 2612 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| 2613 } |
| 2614 |
| 2615 |
2583 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, | 2616 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, |
2584 JSObject* object, | 2617 JSObject* object, |
2585 JSObject* last) { | 2618 JSObject* last) { |
2586 // ----------- S t a t e ------------- | 2619 // ----------- S t a t e ------------- |
2587 // -- rax : receiver | 2620 // -- rax : receiver |
2588 // -- rcx : name | 2621 // -- rcx : name |
2589 // -- rsp[0] : return address | 2622 // -- rsp[0] : return address |
2590 // ----------------------------------- | 2623 // ----------------------------------- |
2591 Label miss; | 2624 Label miss; |
2592 | 2625 |
2593 // Chech that receiver is not a smi. | 2626 // Check that receiver is not a smi. |
2594 __ JumpIfSmi(rax, &miss); | 2627 __ JumpIfSmi(rax, &miss); |
2595 | 2628 |
2596 // Check the maps of the full prototype chain. Also check that | 2629 // Check the maps of the full prototype chain. Also check that |
2597 // global property cells up to (but not including) the last object | 2630 // global property cells up to (but not including) the last object |
2598 // in the prototype chain are empty. | 2631 // in the prototype chain are empty. |
2599 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); | 2632 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); |
2600 | 2633 |
2601 // If the last object in the prototype chain is a global object, | 2634 // If the last object in the prototype chain is a global object, |
2602 // check that the global property cell is empty. | 2635 // check that the global property cell is empty. |
2603 if (last->IsGlobalObject()) { | 2636 if (last->IsGlobalObject()) { |
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2974 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); | 3007 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); |
2975 __ bind(&miss); | 3008 __ bind(&miss); |
2976 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); | 3009 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); |
2977 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3010 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
2978 | 3011 |
2979 // Return the generated code. | 3012 // Return the generated code. |
2980 return GetCode(CALLBACKS, name); | 3013 return GetCode(CALLBACKS, name); |
2981 } | 3014 } |
2982 | 3015 |
2983 | 3016 |
2984 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { | 3017 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(Handle<Map> receiver_
map) { |
2985 // ----------- S t a t e ------------- | 3018 // ----------- S t a t e ------------- |
2986 // -- rax : key | 3019 // -- rax : key |
2987 // -- rdx : receiver | 3020 // -- rdx : receiver |
2988 // -- rsp[0] : return address | 3021 // -- rsp[0] : return address |
2989 // ----------------------------------- | 3022 // ----------------------------------- |
2990 Label miss; | 3023 Label miss, miss_force_generic; |
2991 | 3024 |
2992 // Check that the receiver isn't a smi. | 3025 __ CheckMap(rdx, receiver_map, &miss, false); |
2993 __ JumpIfSmi(rdx, &miss); | |
2994 | |
2995 // Check that the map matches. | |
2996 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), | |
2997 Handle<Map>(receiver->map())); | |
2998 __ j(not_equal, &miss); | |
2999 | 3026 |
3000 // Check that the key is a smi. | 3027 // Check that the key is a smi. |
3001 __ JumpIfNotSmi(rax, &miss); | 3028 __ JumpIfNotSmi(rax, &miss_force_generic); |
3002 | 3029 |
3003 // Get the elements array. | 3030 // Get the elements array. |
3004 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); | 3031 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); |
3005 __ AssertFastElements(rcx); | 3032 __ AssertFastElements(rcx); |
3006 | 3033 |
3007 // Check that the key is within bounds. | 3034 // Check that the key is within bounds. |
3008 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); | 3035 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); |
3009 __ j(above_equal, &miss); | 3036 __ j(above_equal, &miss_force_generic); |
3010 | 3037 |
3011 // Load the result and make sure it's not the hole. | 3038 // Load the result and make sure it's not the hole. |
3012 SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2); | 3039 SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2); |
3013 __ movq(rbx, FieldOperand(rcx, | 3040 __ movq(rbx, FieldOperand(rcx, |
3014 index.reg, | 3041 index.reg, |
3015 index.scale, | 3042 index.scale, |
3016 FixedArray::kHeaderSize)); | 3043 FixedArray::kHeaderSize)); |
3017 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); | 3044 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); |
3018 __ j(equal, &miss); | 3045 __ j(equal, &miss_force_generic); |
3019 __ movq(rax, rbx); | 3046 __ movq(rax, rbx); |
3020 __ ret(0); | 3047 __ ret(0); |
3021 | 3048 |
3022 __ bind(&miss); | 3049 __ bind(&miss); |
3023 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); | 3050 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
3024 | 3051 |
| 3052 __ bind(&miss_force_generic); |
| 3053 GenerateKeyedLoadMissForceGeneric(masm()); |
| 3054 |
3025 // Return the generated code. | 3055 // Return the generated code. |
3026 return GetCode(NORMAL, NULL); | 3056 return GetCode(NORMAL, NULL); |
3027 } | 3057 } |
3028 | 3058 |
3029 | 3059 |
| 3060 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic( |
| 3061 ZoneMapList* receiver_maps, |
| 3062 ZoneCodeList* handler_ics) { |
| 3063 // ----------- S t a t e ------------- |
| 3064 // -- rax : key |
| 3065 // -- rdx : receiver |
| 3066 // -- rsp[0] : return address |
| 3067 // ----------------------------------- |
| 3068 Label miss; |
| 3069 |
| 3070 __ JumpIfSmi(rax, &miss); |
| 3071 |
| 3072 int receiver_count = receiver_maps->length(); |
| 3073 for (int current = 0; current < receiver_count; ++current) { |
| 3074 // Check map and tail call if there's a match |
| 3075 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), receiver_maps->at(current)
); |
| 3076 __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET); |
| 3077 } |
| 3078 __ bind(&miss); |
| 3079 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); |
| 3080 |
| 3081 // Return the generated code. |
| 3082 return GetCode(NORMAL, NULL, MEGAMORPHIC); |
| 3083 } |
| 3084 |
| 3085 |
3030 // Specialized stub for constructing objects from functions which only have only | 3086 // Specialized stub for constructing objects from functions which only have only |
3031 // simple assignments of the form this.x = ...; in their body. | 3087 // simple assignments of the form this.x = ...; in their body. |
3032 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { | 3088 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { |
3033 // ----------- S t a t e ------------- | 3089 // ----------- S t a t e ------------- |
3034 // -- rax : argc | 3090 // -- rax : argc |
3035 // -- rdi : constructor | 3091 // -- rdi : constructor |
3036 // -- rsp[0] : return address | 3092 // -- rsp[0] : return address |
3037 // -- rsp[4] : last argument | 3093 // -- rsp[4] : last argument |
3038 // ----------------------------------- | 3094 // ----------------------------------- |
3039 Label generic_stub_call; | 3095 Label generic_stub_call; |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3160 } | 3216 } |
3161 | 3217 |
3162 | 3218 |
3163 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( | 3219 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( |
3164 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { | 3220 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { |
3165 // ----------- S t a t e ------------- | 3221 // ----------- S t a t e ------------- |
3166 // -- rax : key | 3222 // -- rax : key |
3167 // -- rdx : receiver | 3223 // -- rdx : receiver |
3168 // -- rsp[0] : return address | 3224 // -- rsp[0] : return address |
3169 // ----------------------------------- | 3225 // ----------------------------------- |
3170 Label slow; | 3226 Label slow, miss; |
3171 | 3227 |
3172 // Check that the object isn't a smi. | 3228 // Check that the object isn't a smi. |
3173 __ JumpIfSmi(rdx, &slow); | 3229 __ JumpIfSmi(rdx, &miss); |
3174 | 3230 |
3175 // Check that the key is a smi. | 3231 // Check that the key is a smi. |
3176 __ JumpIfNotSmi(rax, &slow); | 3232 __ JumpIfNotSmi(rax, &miss); |
3177 | 3233 |
3178 // Check that the map matches. | 3234 // Check that the map matches. |
3179 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false); | 3235 __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false); |
3180 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 3236 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
3181 | 3237 |
3182 // Check that the index is in range. | 3238 // Check that the index is in range. |
3183 __ SmiToInteger32(rcx, rax); | 3239 __ SmiToInteger32(rcx, rax); |
3184 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); | 3240 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
3185 // Unsigned comparison catches both negative and too-large values. | 3241 // Unsigned comparison catches both negative and too-large values. |
3186 __ j(above_equal, &slow); | 3242 __ j(above_equal, &miss); |
3187 | 3243 |
3188 // rax: index (as a smi) | 3244 // rax: index (as a smi) |
3189 // rdx: receiver (JSObject) | 3245 // rdx: receiver (JSObject) |
3190 // rcx: untagged index | 3246 // rcx: untagged index |
3191 // rbx: elements array | 3247 // rbx: elements array |
3192 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); | 3248 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); |
3193 // rbx: base pointer of external storage | 3249 // rbx: base pointer of external storage |
3194 switch (array_type) { | 3250 switch (array_type) { |
3195 case kExternalByteArray: | 3251 case kExternalByteArray: |
3196 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); | 3252 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3272 __ bind(&slow); | 3328 __ bind(&slow); |
3273 Counters* counters = isolate()->counters(); | 3329 Counters* counters = isolate()->counters(); |
3274 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); | 3330 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); |
3275 | 3331 |
3276 // ----------- S t a t e ------------- | 3332 // ----------- S t a t e ------------- |
3277 // -- rax : key | 3333 // -- rax : key |
3278 // -- rdx : receiver | 3334 // -- rdx : receiver |
3279 // -- rsp[0] : return address | 3335 // -- rsp[0] : return address |
3280 // ----------------------------------- | 3336 // ----------------------------------- |
3281 | 3337 |
3282 __ pop(rbx); | 3338 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Slow(); |
3283 __ push(rdx); // receiver | 3339 __ jmp(ic, RelocInfo::CODE_TARGET); |
3284 __ push(rax); // name | |
3285 __ push(rbx); // return address | |
3286 | 3340 |
3287 // Perform tail call to the entry. | 3341 // Slow case: Jump to runtime. |
3288 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); | 3342 __ bind(&miss); |
| 3343 // ----------- S t a t e ------------- |
| 3344 // -- rax : key |
| 3345 // -- rdx : receiver |
| 3346 // -- rsp[0] : return address |
| 3347 // ----------------------------------- |
| 3348 |
| 3349 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); |
| 3350 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3289 | 3351 |
3290 // Return the generated code. | 3352 // Return the generated code. |
3291 return GetCode(flags); | 3353 return GetCode(flags); |
3292 } | 3354 } |
3293 | 3355 |
3294 | 3356 |
3295 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( | 3357 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( |
3296 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { | 3358 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { |
3297 // ----------- S t a t e ------------- | 3359 // ----------- S t a t e ------------- |
3298 // -- rax : value | 3360 // -- rax : value |
3299 // -- rcx : key | 3361 // -- rcx : key |
3300 // -- rdx : receiver | 3362 // -- rdx : receiver |
3301 // -- rsp[0] : return address | 3363 // -- rsp[0] : return address |
3302 // ----------------------------------- | 3364 // ----------------------------------- |
3303 Label slow; | 3365 Label slow, miss; |
| 3366 |
| 3367 // Check that the key is a smi. |
| 3368 __ JumpIfNotSmi(rcx, &miss); |
3304 | 3369 |
3305 // Check that the object isn't a smi. | 3370 // Check that the object isn't a smi. |
3306 __ JumpIfSmi(rdx, &slow); | 3371 __ JumpIfSmi(rdx, &miss); |
3307 | 3372 |
3308 // Check that the map matches. | 3373 // Check that the map matches. |
3309 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false); | 3374 __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, false); |
3310 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); | 3375 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); |
3311 | 3376 |
3312 // Check that the key is a smi. | 3377 // Check that the key is a smi. |
3313 __ JumpIfNotSmi(rcx, &slow); | 3378 __ JumpIfNotSmi(rcx, &miss); |
3314 | 3379 |
3315 // Check that the index is in range. | 3380 // Check that the index is in range. |
3316 __ SmiToInteger32(rdi, rcx); // Untag the index. | 3381 __ SmiToInteger32(rdi, rcx); // Untag the index. |
3317 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); | 3382 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); |
3318 // Unsigned comparison catches both negative and too-large values. | 3383 // Unsigned comparison catches both negative and too-large values. |
3319 __ j(above_equal, &slow); | 3384 __ j(above_equal, &miss); |
3320 | 3385 |
3321 // Handle both smis and HeapNumbers in the fast path. Go to the | 3386 // Handle both smis and HeapNumbers in the fast path. Go to the |
3322 // runtime for all other kinds of values. | 3387 // runtime for all other kinds of values. |
3323 // rax: value | 3388 // rax: value |
3324 // rcx: key (a smi) | 3389 // rcx: key (a smi) |
3325 // rdx: receiver (a JSObject) | 3390 // rdx: receiver (a JSObject) |
3326 // rbx: elements array | 3391 // rbx: elements array |
3327 // rdi: untagged key | 3392 // rdi: untagged key |
3328 NearLabel check_heap_number; | 3393 NearLabel check_heap_number; |
3329 if (array_type == kExternalPixelArray) { | 3394 if (array_type == kExternalPixelArray) { |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3443 // Slow case: call runtime. | 3508 // Slow case: call runtime. |
3444 __ bind(&slow); | 3509 __ bind(&slow); |
3445 | 3510 |
3446 // ----------- S t a t e ------------- | 3511 // ----------- S t a t e ------------- |
3447 // -- rax : value | 3512 // -- rax : value |
3448 // -- rcx : key | 3513 // -- rcx : key |
3449 // -- rdx : receiver | 3514 // -- rdx : receiver |
3450 // -- rsp[0] : return address | 3515 // -- rsp[0] : return address |
3451 // ----------------------------------- | 3516 // ----------------------------------- |
3452 | 3517 |
3453 __ pop(rbx); | 3518 bool strict = (Code::ExtractExtraICStateFromFlags(flags) & kStrictMode) != 0; |
3454 __ push(rdx); // receiver | 3519 Handle<Code> ic = strict |
3455 __ push(rcx); // key | 3520 ? isolate()->builtins()->KeyedStoreIC_Slow_Strict() |
3456 __ push(rax); // value | 3521 : isolate()->builtins()->KeyedStoreIC_Slow_NonStrict(); |
3457 __ Push(Smi::FromInt(NONE)); // PropertyAttributes | 3522 __ jmp(ic, RelocInfo::CODE_TARGET); |
3458 __ Push(Smi::FromInt( | |
3459 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)); | |
3460 __ push(rbx); // return address | |
3461 | 3523 |
3462 // Do tail-call to runtime routine. | 3524 // Miss case: call runtime. |
3463 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); | 3525 __ bind(&miss); |
| 3526 |
| 3527 // ----------- S t a t e ------------- |
| 3528 // -- rax : value |
| 3529 // -- rcx : key |
| 3530 // -- rdx : receiver |
| 3531 // -- rsp[0] : return address |
| 3532 // ----------------------------------- |
| 3533 |
| 3534 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); |
| 3535 __ jmp(miss_ic, RelocInfo::CODE_TARGET); |
3464 | 3536 |
3465 return GetCode(flags); | 3537 return GetCode(flags); |
3466 } | 3538 } |
3467 | 3539 |
3468 #undef __ | 3540 #undef __ |
3469 | 3541 |
3470 } } // namespace v8::internal | 3542 } } // namespace v8::internal |
3471 | 3543 |
3472 #endif // V8_TARGET_ARCH_X64 | 3544 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |