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

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

Issue 6894003: Better support for 'polymorphic' JS and external arrays (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: review feedback and merge 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 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss); 696 code = masm->isolate()->builtins()->builtin(Builtins::kLoadIC_Miss);
697 } else { 697 } else {
698 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss); 698 code = masm->isolate()->builtins()->builtin(Builtins::kKeyedLoadIC_Miss);
699 } 699 }
700 700
701 Handle<Code> ic(code); 701 Handle<Code> ic(code);
702 __ Jump(ic, RelocInfo::CODE_TARGET); 702 __ Jump(ic, RelocInfo::CODE_TARGET);
703 } 703 }
704 704
705 705
706 void StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) {
707 Code* code = masm->isolate()->builtins()->builtin(
708 Builtins::kKeyedLoadIC_MissForceGeneric);
709 Handle<Code> ic(code);
710 __ Jump(ic, RelocInfo::CODE_TARGET);
711 }
712
713
706 // Both name_reg and receiver_reg are preserved on jumps to miss_label, 714 // Both name_reg and receiver_reg are preserved on jumps to miss_label,
707 // but may be destroyed if store is successful. 715 // but may be destroyed if store is successful.
708 void StubCompiler::GenerateStoreField(MacroAssembler* masm, 716 void StubCompiler::GenerateStoreField(MacroAssembler* masm,
709 JSObject* object, 717 JSObject* object,
710 int index, 718 int index,
711 Map* transition, 719 Map* transition,
712 Register receiver_reg, 720 Register receiver_reg,
713 Register name_reg, 721 Register name_reg,
714 Register scratch, 722 Register scratch,
715 Label* miss_label) { 723 Label* miss_label) {
(...skipping 1761 matching lines...) Expand 10 before | Expand all | Expand 10 after
2477 __ bind(&miss); 2485 __ bind(&miss);
2478 __ DecrementCounter(counters->keyed_store_field(), 1); 2486 __ DecrementCounter(counters->keyed_store_field(), 1);
2479 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2487 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2480 __ Jump(ic, RelocInfo::CODE_TARGET); 2488 __ Jump(ic, RelocInfo::CODE_TARGET);
2481 2489
2482 // Return the generated code. 2490 // Return the generated code.
2483 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 2491 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
2484 } 2492 }
2485 2493
2486 2494
2487 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 2495 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
2488 JSObject* receiver) { 2496 Map* receiver_map) {
2489 // ----------- S t a t e ------------- 2497 // ----------- S t a t e -------------
2490 // -- rax : value 2498 // -- rax : value
2491 // -- rcx : key 2499 // -- rcx : key
2492 // -- rdx : receiver 2500 // -- rdx : receiver
2493 // -- rsp[0] : return address 2501 // -- rsp[0] : return address
2494 // ----------------------------------- 2502 // -----------------------------------
2495 Label miss; 2503 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2504 MaybeObject* maybe_stub =
2505 KeyedStoreFastElementStub(is_js_array).TryGetCode();
2506 Code* stub;
2507 if (!maybe_stub->To(&stub)) return maybe_stub;
2508 __ DispatchMap(rdx,
2509 Handle<Map>(receiver_map),
2510 Handle<Code>(stub),
2511 false);
2496 2512
2497 // Check that the receiver isn't a smi.
2498 __ JumpIfSmi(rdx, &miss);
2499
2500 // Check that the map matches.
2501 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2502 Handle<Map>(receiver->map()));
2503 __ j(not_equal, &miss);
2504
2505 // Check that the key is a smi.
2506 __ JumpIfNotSmi(rcx, &miss);
2507
2508 // Get the elements array and make sure it is a fast element array, not 'cow'.
2509 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
2510 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
2511 factory()->fixed_array_map());
2512 __ j(not_equal, &miss);
2513
2514 // Check that the key is within bounds.
2515 if (receiver->IsJSArray()) {
2516 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
2517 __ j(above_equal, &miss);
2518 } else {
2519 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
2520 __ j(above_equal, &miss);
2521 }
2522
2523 // Do the store and update the write barrier. Make sure to preserve
2524 // the value in register eax.
2525 __ movq(rdx, rax);
2526 __ SmiToInteger32(rcx, rcx);
2527 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
2528 rax);
2529 __ RecordWrite(rdi, 0, rdx, rcx);
2530
2531 // Done.
2532 __ ret(0);
2533
2534 // Handle store cache miss.
2535 __ bind(&miss);
2536 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2513 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2537 __ jmp(ic, RelocInfo::CODE_TARGET); 2514 __ jmp(ic, RelocInfo::CODE_TARGET);
2538 2515
2539 // Return the generated code. 2516 // Return the generated code.
2540 return GetCode(NORMAL, NULL); 2517 return GetCode(NORMAL, NULL);
2541 } 2518 }
2542 2519
2543 2520
2521 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2522 MapList* receiver_maps,
2523 CodeList* handler_ics) {
2524 // ----------- S t a t e -------------
2525 // -- rax : value
2526 // -- rcx : key
2527 // -- rdx : receiver
2528 // -- rsp[0] : return address
2529 // -----------------------------------
2530 Label miss;
2531 __ JumpIfSmi(rdx, &miss);
2532
2533 int receiver_count = receiver_maps->length();
2534 for (int current = 0; current < receiver_count; ++current) {
2535 // Check map and tail call if there's a match
2536 __ DispatchMap(rdx,
2537 Handle<Map>(receiver_maps->at(current)),
2538 Handle<Code>(handler_ics->at(current)),
Lasse Reichstein 2011/05/12 08:33:46 You repeatedly read the map out of the value. It'l
danno 2011/06/01 13:16:08 Done.
2539 true);
2540 }
2541
2542 __ bind(&miss);
2543 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2544 __ jmp(ic, RelocInfo::CODE_TARGET);
2545
2546 // Return the generated code.
2547 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2548 }
2549
2550
2544 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2551 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2545 JSObject* object, 2552 JSObject* object,
2546 JSObject* last) { 2553 JSObject* last) {
2547 // ----------- S t a t e ------------- 2554 // ----------- S t a t e -------------
2548 // -- rax : receiver 2555 // -- rax : receiver
2549 // -- rcx : name 2556 // -- rcx : name
2550 // -- rsp[0] : return address 2557 // -- rsp[0] : return address
2551 // ----------------------------------- 2558 // -----------------------------------
2552 Label miss; 2559 Label miss;
2553 2560
2554 // Chech that receiver is not a smi. 2561 // Check that receiver is not a smi.
2555 __ JumpIfSmi(rax, &miss); 2562 __ JumpIfSmi(rax, &miss);
2556 2563
2557 // Check the maps of the full prototype chain. Also check that 2564 // Check the maps of the full prototype chain. Also check that
2558 // global property cells up to (but not including) the last object 2565 // global property cells up to (but not including) the last object
2559 // in the prototype chain are empty. 2566 // in the prototype chain are empty.
2560 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); 2567 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
2561 2568
2562 // If the last object in the prototype chain is a global object, 2569 // If the last object in the prototype chain is a global object,
2563 // check that the global property cell is empty. 2570 // check that the global property cell is empty.
2564 if (last->IsGlobalObject()) { 2571 if (last->IsGlobalObject()) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2935 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); 2942 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
2936 __ bind(&miss); 2943 __ bind(&miss);
2937 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 2944 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
2938 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2945 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2939 2946
2940 // Return the generated code. 2947 // Return the generated code.
2941 return GetCode(CALLBACKS, name); 2948 return GetCode(CALLBACKS, name);
2942 } 2949 }
2943 2950
2944 2951
2945 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 2952 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
2953 // ----------- S t a t e -------------
2954 // -- rax : key
2955 // -- rdx : receiver
2956 // -- rsp[0] : return address
2957 // -----------------------------------
2958 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
2959 Code* stub;
2960 if (!maybe_stub->To(&stub)) return maybe_stub;
2961 __ DispatchMap(rdx, Handle<Map>(receiver_map), Handle<Code>(stub), false);
2962
2963 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2964 __ jmp(ic, RelocInfo::CODE_TARGET);
2965
2966 // Return the generated code.
2967 return GetCode(NORMAL, NULL);
2968 }
2969
2970
2971 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
2972 MapList* receiver_maps,
2973 CodeList* handler_ics) {
2946 // ----------- S t a t e ------------- 2974 // ----------- S t a t e -------------
2947 // -- rax : key 2975 // -- rax : key
2948 // -- rdx : receiver 2976 // -- rdx : receiver
2949 // -- rsp[0] : return address 2977 // -- rsp[0] : return address
2950 // ----------------------------------- 2978 // -----------------------------------
2951 Label miss; 2979 Label miss;
2952
2953 // Check that the receiver isn't a smi.
2954 __ JumpIfSmi(rdx, &miss); 2980 __ JumpIfSmi(rdx, &miss);
2955 2981
2956 // Check that the map matches. 2982 int receiver_count = receiver_maps->length();
2957 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2983 for (int current = 0; current < receiver_count; ++current) {
2958 Handle<Map>(receiver->map())); 2984 // Check map and tail call if there's a match
2959 __ j(not_equal, &miss); 2985 __ DispatchMap(rdx,
2960 2986 Handle<Map>(receiver_maps->at(current)),
2961 // Check that the key is a smi. 2987 Handle<Code>(handler_ics->at(current)),
2962 __ JumpIfNotSmi(rax, &miss); 2988 true);
2963 2989 }
2964 // Get the elements array. 2990 __ bind(&miss);
2965 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
2966 __ AssertFastElements(rcx);
2967
2968 // Check that the key is within bounds.
2969 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
2970 __ j(above_equal, &miss);
2971
2972 // Load the result and make sure it's not the hole.
2973 SmiIndex index = masm()->SmiToIndex(rbx, rax, kPointerSizeLog2);
2974 __ movq(rbx, FieldOperand(rcx,
2975 index.reg,
2976 index.scale,
2977 FixedArray::kHeaderSize));
2978 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
2979 __ j(equal, &miss);
2980 __ movq(rax, rbx);
2981 __ ret(0);
2982
2983 __ bind(&miss);
2984 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2991 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2985 2992
2986 // Return the generated code. 2993 // Return the generated code.
2987 return GetCode(NORMAL, NULL); 2994 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2988 } 2995 }
2989 2996
2990 2997
2991 // Specialized stub for constructing objects from functions which only have only 2998 // Specialized stub for constructing objects from functions which only have only
2992 // simple assignments of the form this.x = ...; in their body. 2999 // simple assignments of the form this.x = ...; in their body.
2993 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3000 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
2994 // ----------- S t a t e ------------- 3001 // ----------- S t a t e -------------
2995 // -- rax : argc 3002 // -- rax : argc
2996 // -- rdi : constructor 3003 // -- rdi : constructor
2997 // -- rsp[0] : return address 3004 // -- rsp[0] : return address
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3114 Code* code = 3121 Code* code =
3115 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric); 3122 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
3116 Handle<Code> generic_construct_stub(code); 3123 Handle<Code> generic_construct_stub(code);
3117 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3124 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3118 3125
3119 // Return the generated code. 3126 // Return the generated code.
3120 return GetCode(); 3127 return GetCode();
3121 } 3128 }
3122 3129
3123 3130
3124 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3131 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3125 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3132 JSObject*receiver, ExternalArrayType array_type) {
3126 // ----------- S t a t e ------------- 3133 // ----------- S t a t e -------------
3127 // -- rax : key 3134 // -- rax : key
3128 // -- rdx : receiver 3135 // -- rdx : receiver
3129 // -- rsp[0] : return address 3136 // -- rsp[0] : return address
3130 // ----------------------------------- 3137 // -----------------------------------
3131 Label slow; 3138 MaybeObject* maybe_stub =
3139 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3140 Code* stub;
3141 if (!maybe_stub->To(&stub)) return maybe_stub;
3142 __ DispatchMap(rdx, Handle<Map>(receiver->map()), Handle<Code>(stub), false);
3132 3143
3133 // Check that the object isn't a smi. 3144 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3134 __ JumpIfSmi(rdx, &slow); 3145 __ jmp(ic, RelocInfo::CODE_TARGET);
3146
3147 // Return the generated code.
3148 return GetCode();
3149 }
3150
3151
3152 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3153 JSObject* receiver, ExternalArrayType array_type) {
3154 // ----------- S t a t e -------------
3155 // -- rax : value
3156 // -- rcx : key
3157 // -- rdx : receiver
3158 // -- rsp[0] : return address
3159 // -----------------------------------
3160 MaybeObject* maybe_stub =
3161 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3162 Code* stub;
3163 if (!maybe_stub->To(&stub)) return maybe_stub;
3164 __ DispatchMap(rdx, Handle<Map>(receiver->map()), Handle<Code>(stub), false);
3165
3166 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3167 __ jmp(ic, RelocInfo::CODE_TARGET);
3168
3169 return GetCode();
3170 }
3171
3172
3173 #undef __
3174 #define __ ACCESS_MASM(masm)
3175
3176
3177 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3178 MacroAssembler* masm,
3179 ExternalArrayType array_type) {
3180 // ----------- S t a t e -------------
3181 // -- rax : key
3182 // -- rdx : receiver
3183 // -- rsp[0] : return address
3184 // -----------------------------------
3185 Label slow, miss_force_generic;
3186
3187 // This stub is meant to be tail-jumped to, the receiver must already
3188 // have been verified by the caller to not be a smi.
3135 3189
3136 // Check that the key is a smi. 3190 // Check that the key is a smi.
3137 __ JumpIfNotSmi(rax, &slow); 3191 __ JumpIfNotSmi(rax, &miss_force_generic);
3138
3139 // Check that the map matches.
3140 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
3141 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3142 3192
3143 // Check that the index is in range. 3193 // Check that the index is in range.
3194 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3144 __ SmiToInteger32(rcx, rax); 3195 __ SmiToInteger32(rcx, rax);
3145 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3196 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3146 // Unsigned comparison catches both negative and too-large values. 3197 // Unsigned comparison catches both negative and too-large values.
3147 __ j(above_equal, &slow); 3198 __ j(above_equal, &miss_force_generic);
3148 3199
3149 // rax: index (as a smi) 3200 // rax: index (as a smi)
3150 // rdx: receiver (JSObject) 3201 // rdx: receiver (JSObject)
3151 // rcx: untagged index 3202 // rcx: untagged index
3152 // rbx: elements array 3203 // rbx: elements array
3153 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 3204 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3154 // rbx: base pointer of external storage 3205 // rbx: base pointer of external storage
3155 switch (array_type) { 3206 switch (array_type) {
3156 case kExternalByteArray: 3207 case kExternalByteArray:
3157 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); 3208 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0));
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
3224 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 3275 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3225 __ movq(rax, rcx); 3276 __ movq(rax, rcx);
3226 __ ret(0); 3277 __ ret(0);
3227 } else { 3278 } else {
3228 __ Integer32ToSmi(rax, rcx); 3279 __ Integer32ToSmi(rax, rcx);
3229 __ ret(0); 3280 __ ret(0);
3230 } 3281 }
3231 3282
3232 // Slow case: Jump to runtime. 3283 // Slow case: Jump to runtime.
3233 __ bind(&slow); 3284 __ bind(&slow);
3234 Counters* counters = isolate()->counters(); 3285 Counters* counters = masm->isolate()->counters();
3235 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3286 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3236 3287
3237 // ----------- S t a t e ------------- 3288 // ----------- S t a t e -------------
3238 // -- rax : key 3289 // -- rax : key
3239 // -- rdx : receiver 3290 // -- rdx : receiver
3240 // -- rsp[0] : return address 3291 // -- rsp[0] : return address
3241 // ----------------------------------- 3292 // -----------------------------------
3242 3293
3243 __ pop(rbx); 3294 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3244 __ push(rdx); // receiver 3295 __ jmp(ic, RelocInfo::CODE_TARGET);
3245 __ push(rax); // name
3246 __ push(rbx); // return address
3247 3296
3248 // Perform tail call to the entry. 3297 // Miss case: Jump to runtime.
3249 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3298 __ bind(&miss_force_generic);
3250 3299
3251 // Return the generated code. 3300 // ----------- S t a t e -------------
3252 return GetCode(flags); 3301 // -- rax : key
3302 // -- rdx : receiver
3303 // -- rsp[0] : return address
3304 // -----------------------------------
3305 Handle<Code> miss_ic =
3306 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3307 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3253 } 3308 }
3254 3309
3255 3310
3256 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3311 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3257 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3312 MacroAssembler* masm,
3313 ExternalArrayType array_type) {
3258 // ----------- S t a t e ------------- 3314 // ----------- S t a t e -------------
3259 // -- rax : value 3315 // -- rax : value
3260 // -- rcx : key 3316 // -- rcx : key
3261 // -- rdx : receiver 3317 // -- rdx : receiver
3262 // -- rsp[0] : return address 3318 // -- rsp[0] : return address
3263 // ----------------------------------- 3319 // -----------------------------------
3264 Label slow; 3320 Label slow, miss_force_generic;
3265 3321
3266 // Check that the object isn't a smi. 3322 // This stub is meant to be tail-jumped to, the receiver must already
3267 __ JumpIfSmi(rdx, &slow); 3323 // have been verified by the caller to not be a smi.
3268
3269 // Check that the map matches.
3270 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, false);
3271 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3272 3324
3273 // Check that the key is a smi. 3325 // Check that the key is a smi.
3274 __ JumpIfNotSmi(rcx, &slow); 3326 __ JumpIfNotSmi(rcx, &miss_force_generic);
3275 3327
3276 // Check that the index is in range. 3328 // Check that the index is in range.
3329 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3277 __ SmiToInteger32(rdi, rcx); // Untag the index. 3330 __ SmiToInteger32(rdi, rcx); // Untag the index.
3278 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3331 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
3279 // Unsigned comparison catches both negative and too-large values. 3332 // Unsigned comparison catches both negative and too-large values.
3280 __ j(above_equal, &slow); 3333 __ j(above_equal, &miss_force_generic);
3281 3334
3282 // Handle both smis and HeapNumbers in the fast path. Go to the 3335 // Handle both smis and HeapNumbers in the fast path. Go to the
3283 // runtime for all other kinds of values. 3336 // runtime for all other kinds of values.
3284 // rax: value 3337 // rax: value
3285 // rcx: key (a smi) 3338 // rcx: key (a smi)
3286 // rdx: receiver (a JSObject) 3339 // rdx: receiver (a JSObject)
3287 // rbx: elements array 3340 // rbx: elements array
3288 // rdi: untagged key 3341 // rdi: untagged key
3289 Label check_heap_number; 3342 Label check_heap_number;
3290 if (array_type == kExternalPixelArray) { 3343 if (array_type == kExternalPixelArray) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3404 // Slow case: call runtime. 3457 // Slow case: call runtime.
3405 __ bind(&slow); 3458 __ bind(&slow);
3406 3459
3407 // ----------- S t a t e ------------- 3460 // ----------- S t a t e -------------
3408 // -- rax : value 3461 // -- rax : value
3409 // -- rcx : key 3462 // -- rcx : key
3410 // -- rdx : receiver 3463 // -- rdx : receiver
3411 // -- rsp[0] : return address 3464 // -- rsp[0] : return address
3412 // ----------------------------------- 3465 // -----------------------------------
3413 3466
3414 __ pop(rbx); 3467 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3415 __ push(rdx); // receiver 3468 __ jmp(ic, RelocInfo::CODE_TARGET);
3416 __ push(rcx); // key
3417 __ push(rax); // value
3418 __ Push(Smi::FromInt(NONE)); // PropertyAttributes
3419 __ Push(Smi::FromInt(
3420 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode));
3421 __ push(rbx); // return address
3422 3469
3423 // Do tail-call to runtime routine. 3470 // Miss case: call runtime.
3424 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 3471 __ bind(&miss_force_generic);
3425 3472
3426 return GetCode(flags); 3473 // ----------- S t a t e -------------
3474 // -- rax : value
3475 // -- rcx : key
3476 // -- rdx : receiver
3477 // -- rsp[0] : return address
3478 // -----------------------------------
3479
3480 Handle<Code> miss_ic =
3481 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3482 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3427 } 3483 }
3428 3484
3485
3486 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3487 // ----------- S t a t e -------------
3488 // -- rax : key
3489 // -- rdx : receiver
3490 // -- rsp[0] : return address
3491 // -----------------------------------
3492 Label miss_force_generic;
3493
3494 // This stub is meant to be tail-jumped to, the receiver must already
3495 // have been verified by the caller to not be a smi.
3496
3497 // Check that the key is a smi.
3498 __ JumpIfNotSmi(rax, &miss_force_generic);
3499
3500 // Get the elements array.
3501 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3502 __ AssertFastElements(rcx);
3503
3504 // Check that the key is within bounds.
3505 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3506 __ j(above_equal, &miss_force_generic);
3507
3508 // Load the result and make sure it's not the hole.
3509 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3510 __ movq(rbx, FieldOperand(rcx,
3511 index.reg,
3512 index.scale,
3513 FixedArray::kHeaderSize));
3514 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3515 __ j(equal, &miss_force_generic);
3516 __ movq(rax, rbx);
3517 __ ret(0);
3518
3519 __ bind(&miss_force_generic);
3520 Code* code = masm->isolate()->builtins()->builtin(
3521 Builtins::kKeyedLoadIC_MissForceGeneric);
3522 Handle<Code> ic(code);
3523 __ jmp(ic, RelocInfo::CODE_TARGET);
3524 }
3525
3526
3527 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3528 bool is_js_array) {
3529 // ----------- S t a t e -------------
3530 // -- rax : value
3531 // -- rcx : key
3532 // -- rdx : receiver
3533 // -- rsp[0] : return address
3534 // -----------------------------------
3535 Label miss_force_generic;
3536
3537 // This stub is meant to be tail-jumped to, the receiver must already
3538 // have been verified by the caller to not be a smi.
3539
3540 // Check that the key is a smi.
3541 __ JumpIfNotSmi(rcx, &miss_force_generic);
3542
3543 // Get the elements array and make sure it is a fast element array, not 'cow'.
3544 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3545 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
3546 masm->isolate()->factory()->fixed_array_map());
Mads Ager (chromium) 2011/05/12 09:42:47 You could load this from the root array into kScra
danno 2011/06/01 13:16:08 Done.
3547 __ j(not_equal, &miss_force_generic);
3548
3549 // Check that the key is within bounds.
3550 if (is_js_array) {
3551 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3552 __ j(above_equal, &miss_force_generic);
3553 } else {
3554 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3555 __ j(above_equal, &miss_force_generic);
3556 }
3557
3558 // Do the store and update the write barrier. Make sure to preserve
3559 // the value in register eax.
3560 __ movq(rdx, rax);
3561 __ SmiToInteger32(rcx, rcx);
3562 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
3563 rax);
3564 __ RecordWrite(rdi, 0, rdx, rcx);
3565
3566 // Done.
3567 __ ret(0);
3568
3569 // Handle store cache miss.
3570 __ bind(&miss_force_generic);
3571 Handle<Code> ic_force_generic =
3572 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3573 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3574 }
3575
3576
3429 #undef __ 3577 #undef __
3430 3578
3431 } } // namespace v8::internal 3579 } } // namespace v8::internal
3432 3580
3433 #endif // V8_TARGET_ARCH_X64 3581 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698