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

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: 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 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 KeyedStoreIC keyed_store_ic(isolate());
2504 MaybeObject* maybe_stub =
2505 keyed_store_ic.ComputeMonomorphicBuiltinFastElementStub(
2506 receiver_map->instance_type() == JS_ARRAY_TYPE);
2507 Code* stub;
2508 if (!maybe_stub->To(&stub)) return maybe_stub;
2509 __ DispatchMap(rdx,
2510 Handle<Map>(receiver_map),
2511 Handle<Code>(stub),
2512 false);
2496 2513
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(); 2514 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2537 __ jmp(ic, RelocInfo::CODE_TARGET); 2515 __ jmp(ic, RelocInfo::CODE_TARGET);
2538 2516
2539 // Return the generated code. 2517 // Return the generated code.
2540 return GetCode(NORMAL, NULL); 2518 return GetCode(NORMAL, NULL);
2541 } 2519 }
2542 2520
2543 2521
2522 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
2523 MapList* receiver_maps,
2524 CodeList* handler_ics) {
2525 // ----------- S t a t e -------------
2526 // -- rax : value
2527 // -- rcx : key
2528 // -- rdx : receiver
2529 // -- rsp[0] : return address
2530 // -----------------------------------
2531 Label miss;
2532 __ JumpIfSmi(rdx, &miss);
2533
2534 int receiver_count = receiver_maps->length();
2535 for (int current = 0; current < receiver_count; ++current) {
2536 // Check map and tail call if there's a match
2537 __ DispatchMap(rdx,
2538 Handle<Map>(receiver_maps->at(current)),
2539 Handle<Code>(handler_ics->at(current)),
2540 true);
2541 }
2542
2543 __ bind(&miss);
2544 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2545 __ jmp(ic, RelocInfo::CODE_TARGET);
2546
2547 // Return the generated code.
2548 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2549 }
2550
2551
2544 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2552 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2545 JSObject* object, 2553 JSObject* object,
2546 JSObject* last) { 2554 JSObject* last) {
2547 // ----------- S t a t e ------------- 2555 // ----------- S t a t e -------------
2548 // -- rax : receiver 2556 // -- rax : receiver
2549 // -- rcx : name 2557 // -- rcx : name
2550 // -- rsp[0] : return address 2558 // -- rsp[0] : return address
2551 // ----------------------------------- 2559 // -----------------------------------
2552 Label miss; 2560 Label miss;
2553 2561
2554 // Chech that receiver is not a smi. 2562 // Check that receiver is not a smi.
2555 __ JumpIfSmi(rax, &miss); 2563 __ JumpIfSmi(rax, &miss);
2556 2564
2557 // Check the maps of the full prototype chain. Also check that 2565 // Check the maps of the full prototype chain. Also check that
2558 // global property cells up to (but not including) the last object 2566 // global property cells up to (but not including) the last object
2559 // in the prototype chain are empty. 2567 // in the prototype chain are empty.
2560 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); 2568 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
2561 2569
2562 // If the last object in the prototype chain is a global object, 2570 // If the last object in the prototype chain is a global object,
2563 // check that the global property cell is empty. 2571 // check that the global property cell is empty.
2564 if (last->IsGlobalObject()) { 2572 if (last->IsGlobalObject()) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2935 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); 2943 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
2936 __ bind(&miss); 2944 __ bind(&miss);
2937 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 2945 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
2938 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2946 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2939 2947
2940 // Return the generated code. 2948 // Return the generated code.
2941 return GetCode(CALLBACKS, name); 2949 return GetCode(CALLBACKS, name);
2942 } 2950 }
2943 2951
2944 2952
2945 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 2953 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
2954 // ----------- S t a t e -------------
2955 // -- rax : key
2956 // -- rdx : receiver
2957 // -- rsp[0] : return address
2958 // -----------------------------------
2959 KeyedLoadIC load_ic(isolate());
2960 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
2961 MaybeObject* maybe_stub =
2962 load_ic.ComputeMonomorphicBuiltinFastElementStub(is_js_array);
2963 Code* stub;
2964 if (!maybe_stub->To(&stub)) return maybe_stub;
2965 __ DispatchMap(rdx, Handle<Map>(receiver_map), Handle<Code>(stub), false);
2966
2967 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2968 __ jmp(ic, RelocInfo::CODE_TARGET);
2969
2970 // Return the generated code.
2971 return GetCode(NORMAL, NULL);
2972 }
2973
2974
2975 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
2976 MapList* receiver_maps,
2977 CodeList* handler_ics) {
2946 // ----------- S t a t e ------------- 2978 // ----------- S t a t e -------------
2947 // -- rax : key 2979 // -- rax : key
2948 // -- rdx : receiver 2980 // -- rdx : receiver
2949 // -- rsp[0] : return address 2981 // -- rsp[0] : return address
2950 // ----------------------------------- 2982 // -----------------------------------
2951 Label miss; 2983 Label miss;
2952
2953 // Check that the receiver isn't a smi.
2954 __ JumpIfSmi(rdx, &miss); 2984 __ JumpIfSmi(rdx, &miss);
2955 2985
2956 // Check that the map matches. 2986 int receiver_count = receiver_maps->length();
2957 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2987 for (int current = 0; current < receiver_count; ++current) {
2958 Handle<Map>(receiver->map())); 2988 // Check map and tail call if there's a match
2959 __ j(not_equal, &miss); 2989 __ DispatchMap(rdx,
2960 2990 Handle<Map>(receiver_maps->at(current)),
2961 // Check that the key is a smi. 2991 Handle<Code>(handler_ics->at(current)),
2962 __ JumpIfNotSmi(rax, &miss); 2992 true);
2963 2993 }
2964 // Get the elements array. 2994 __ 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); 2995 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2985 2996
2986 // Return the generated code. 2997 // Return the generated code.
2987 return GetCode(NORMAL, NULL); 2998 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2988 } 2999 }
2989 3000
2990 3001
2991 // Specialized stub for constructing objects from functions which only have only 3002 // Specialized stub for constructing objects from functions which only have only
2992 // simple assignments of the form this.x = ...; in their body. 3003 // simple assignments of the form this.x = ...; in their body.
2993 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3004 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
2994 // ----------- S t a t e ------------- 3005 // ----------- S t a t e -------------
2995 // -- rax : argc 3006 // -- rax : argc
2996 // -- rdi : constructor 3007 // -- rdi : constructor
2997 // -- rsp[0] : return address 3008 // -- rsp[0] : return address
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3114 Code* code = 3125 Code* code =
3115 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric); 3126 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
3116 Handle<Code> generic_construct_stub(code); 3127 Handle<Code> generic_construct_stub(code);
3117 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3128 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3118 3129
3119 // Return the generated code. 3130 // Return the generated code.
3120 return GetCode(); 3131 return GetCode();
3121 } 3132 }
3122 3133
3123 3134
3124 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3135 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3125 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3136 JSObject*receiver, ExternalArrayType array_type) {
3126 // ----------- S t a t e ------------- 3137 // ----------- S t a t e -------------
3127 // -- rax : key 3138 // -- rax : key
3128 // -- rdx : receiver 3139 // -- rdx : receiver
3129 // -- rsp[0] : return address 3140 // -- rsp[0] : return address
3130 // ----------------------------------- 3141 // -----------------------------------
3131 Label slow; 3142 KeyedLoadIC load_ic(isolate());
3143 MaybeObject* maybe_stub =
3144 load_ic.ComputeMonomorphicBuiltinExternalArrayStub(array_type);
3145 Code* stub;
3146 if (!maybe_stub->To(&stub)) return maybe_stub;
3147 __ DispatchMap(rdx, Handle<Map>(receiver->map()), Handle<Code>(stub), false);
3132 3148
3133 // Check that the object isn't a smi. 3149 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3134 __ JumpIfSmi(rdx, &slow); 3150 __ jmp(ic, RelocInfo::CODE_TARGET);
3151
3152 // Return the generated code.
3153 return GetCode();
3154 }
3155
3156
3157 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3158 JSObject* receiver, ExternalArrayType array_type) {
3159 // ----------- S t a t e -------------
3160 // -- rax : value
3161 // -- rcx : key
3162 // -- rdx : receiver
3163 // -- rsp[0] : return address
3164 // -----------------------------------
3165 KeyedStoreIC store_ic(isolate());
3166 MaybeObject* maybe_stub =
3167 store_ic.ComputeMonomorphicBuiltinExternalArrayStub(array_type);
3168 Code* stub;
3169 if (!maybe_stub->To(&stub)) return maybe_stub;
3170 __ DispatchMap(rdx, Handle<Map>(receiver->map()), Handle<Code>(stub), false);
3171
3172 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3173 __ jmp(ic, RelocInfo::CODE_TARGET);
3174
3175 return GetCode();
3176 }
3177
3178
3179 #undef __
3180 #define __ ACCESS_MASM(masm)
3181
3182
3183 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3184 MacroAssembler* masm,
3185 ExternalArrayType array_type) {
3186 // ----------- S t a t e -------------
3187 // -- rax : key
3188 // -- rdx : receiver
3189 // -- rsp[0] : return address
3190 // -----------------------------------
3191 Label slow, miss_force_generic;
3135 3192
3136 // Check that the key is a smi. 3193 // Check that the key is a smi.
3137 __ JumpIfNotSmi(rax, &slow); 3194 __ 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 3195
3143 // Check that the index is in range. 3196 // Check that the index is in range.
3197 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3144 __ SmiToInteger32(rcx, rax); 3198 __ SmiToInteger32(rcx, rax);
3145 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3199 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3146 // Unsigned comparison catches both negative and too-large values. 3200 // Unsigned comparison catches both negative and too-large values.
3147 __ j(above_equal, &slow); 3201 __ j(above_equal, &miss_force_generic);
3148 3202
3149 // rax: index (as a smi) 3203 // rax: index (as a smi)
3150 // rdx: receiver (JSObject) 3204 // rdx: receiver (JSObject)
3151 // rcx: untagged index 3205 // rcx: untagged index
3152 // rbx: elements array 3206 // rbx: elements array
3153 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 3207 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3154 // rbx: base pointer of external storage 3208 // rbx: base pointer of external storage
3155 switch (array_type) { 3209 switch (array_type) {
3156 case kExternalByteArray: 3210 case kExternalByteArray:
3157 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); 3211 __ 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); 3278 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3225 __ movq(rax, rcx); 3279 __ movq(rax, rcx);
3226 __ ret(0); 3280 __ ret(0);
3227 } else { 3281 } else {
3228 __ Integer32ToSmi(rax, rcx); 3282 __ Integer32ToSmi(rax, rcx);
3229 __ ret(0); 3283 __ ret(0);
3230 } 3284 }
3231 3285
3232 // Slow case: Jump to runtime. 3286 // Slow case: Jump to runtime.
3233 __ bind(&slow); 3287 __ bind(&slow);
3234 Counters* counters = isolate()->counters(); 3288 Counters* counters = masm->isolate()->counters();
3235 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3289 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3236 3290
3237 // ----------- S t a t e ------------- 3291 // ----------- S t a t e -------------
3238 // -- rax : key 3292 // -- rax : key
3239 // -- rdx : receiver 3293 // -- rdx : receiver
3240 // -- rsp[0] : return address 3294 // -- rsp[0] : return address
3241 // ----------------------------------- 3295 // -----------------------------------
3242 3296
3243 __ pop(rbx); 3297 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3244 __ push(rdx); // receiver 3298 __ jmp(ic, RelocInfo::CODE_TARGET);
3245 __ push(rax); // name
3246 __ push(rbx); // return address
3247 3299
3248 // Perform tail call to the entry. 3300 // Miss case: Jump to runtime.
3249 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3301 __ bind(&miss_force_generic);
3250 3302
3251 // Return the generated code. 3303 // ----------- S t a t e -------------
3252 return GetCode(flags); 3304 // -- rax : key
3305 // -- rdx : receiver
3306 // -- rsp[0] : return address
3307 // -----------------------------------
3308 Handle<Code> miss_ic =
3309 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3310 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3253 } 3311 }
3254 3312
3255 3313
3256 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3314 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3257 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3315 MacroAssembler* masm,
3316 ExternalArrayType array_type) {
3258 // ----------- S t a t e ------------- 3317 // ----------- S t a t e -------------
3259 // -- rax : value 3318 // -- rax : value
3260 // -- rcx : key 3319 // -- rcx : key
3261 // -- rdx : receiver 3320 // -- rdx : receiver
3262 // -- rsp[0] : return address 3321 // -- rsp[0] : return address
3263 // ----------------------------------- 3322 // -----------------------------------
3264 Label slow; 3323 Label slow, miss_force_generic;
3265
3266 // Check that the object isn't a smi.
3267 __ JumpIfSmi(rdx, &slow);
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 NearLabel check_heap_number; 3342 NearLabel check_heap_number;
3290 if (array_type == kExternalPixelArray) { 3343 if (array_type == kExternalPixelArray) {
3291 // Float to pixel conversion is only implemented in the runtime for now. 3344 // Float to pixel conversion is only implemented in the runtime for now.
3292 __ JumpIfNotSmi(rax, &slow); 3345 __ JumpIfNotSmi(rax, &slow);
3293 } else { 3346 } else {
3294 __ JumpIfNotSmi(rax, &check_heap_number); 3347 __ JumpIfNotSmi(rax, &check_heap_number);
3295 } 3348 }
3296 // No more branches to slow case on this path. Key and receiver not needed. 3349 // No more branches to slow case on this path. Key and receiver not needed.
3297 __ SmiToInteger32(rdx, rax); 3350 __ SmiToInteger32(rdx, rax);
3298 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 3351 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3299 // rbx: base pointer of external storage 3352 // rbx: base pointer of external storage
3300 switch (array_type) { 3353 switch (array_type) {
3301 case kExternalPixelArray: 3354 case kExternalPixelArray:
3302 { // Clamp the value to [0..255]. 3355 { // Clamp the value to [0..255].
3303 Label done; 3356 NearLabel done;
3304 __ testl(rdx, Immediate(0xFFFFFF00)); 3357 __ testl(rdx, Immediate(0xFFFFFF00));
3305 __ j(zero, &done, Label::kNear); 3358 __ j(zero, &done);
3306 __ setcc(negative, rdx); // 1 if negative, 0 if positive. 3359 __ setcc(negative, rdx); // 1 if negative, 0 if positive.
3307 __ decb(rdx); // 0 if negative, 255 if positive. 3360 __ decb(rdx); // 0 if negative, 255 if positive.
3308 __ bind(&done); 3361 __ bind(&done);
3309 } 3362 }
3310 __ movb(Operand(rbx, rdi, times_1, 0), rdx); 3363 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3311 break; 3364 break;
3312 case kExternalByteArray: 3365 case kExternalByteArray:
3313 case kExternalUnsignedByteArray: 3366 case kExternalUnsignedByteArray:
3314 __ movb(Operand(rbx, rdi, times_1, 0), rdx); 3367 __ movb(Operand(rbx, rdi, times_1, 0), rdx);
3315 break; 3368 break;
(...skipping 88 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 // Check that the key is a smi.
3495 __ JumpIfNotSmi(rax, &miss_force_generic);
3496
3497 // Get the elements array.
3498 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3499 __ AssertFastElements(rcx);
3500
3501 // Check that the key is within bounds.
3502 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3503 __ j(above_equal, &miss_force_generic);
3504
3505 // Load the result and make sure it's not the hole.
3506 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3507 __ movq(rbx, FieldOperand(rcx,
3508 index.reg,
3509 index.scale,
3510 FixedArray::kHeaderSize));
3511 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3512 __ j(equal, &miss_force_generic);
3513 __ movq(rax, rbx);
3514 __ ret(0);
3515
3516 __ bind(&miss_force_generic);
3517 Code* code = masm->isolate()->builtins()->builtin(
3518 Builtins::kKeyedLoadIC_MissForceGeneric);
3519 Handle<Code> ic(code);
3520 __ jmp(ic, RelocInfo::CODE_TARGET);
3521 }
3522
3523
3524 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3525 bool is_js_array) {
3526 // ----------- S t a t e -------------
3527 // -- rax : value
3528 // -- rcx : key
3529 // -- rdx : receiver
3530 // -- rsp[0] : return address
3531 // -----------------------------------
3532 Label miss_force_generic;
3533
3534 // Check that the key is a smi.
3535 __ JumpIfNotSmi(rcx, &miss_force_generic);
3536
3537 // Get the elements array and make sure it is a fast element array, not 'cow'.
3538 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3539 __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset),
3540 masm->isolate()->factory()->fixed_array_map());
3541 __ j(not_equal, &miss_force_generic);
3542
3543 // Check that the key is within bounds.
3544 if (is_js_array) {
3545 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3546 __ j(above_equal, &miss_force_generic);
3547 } else {
3548 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3549 __ j(above_equal, &miss_force_generic);
3550 }
3551
3552 // Do the store and update the write barrier. Make sure to preserve
3553 // the value in register eax.
3554 __ movq(rdx, rax);
3555 __ SmiToInteger32(rcx, rcx);
3556 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
3557 rax);
3558 __ RecordWrite(rdi, 0, rdx, rcx);
3559
3560 // Done.
3561 __ ret(0);
3562
3563 // Handle store cache miss.
3564 __ bind(&miss_force_generic);
3565 Handle<Code> ic_force_generic =
3566 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3567 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3568 }
3569
3570
3429 #undef __ 3571 #undef __
3430 3572
3431 } } // namespace v8::internal 3573 } } // namespace v8::internal
3432 3574
3433 #endif // V8_TARGET_ARCH_X64 3575 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698