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

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: 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/x64/macro-assembler-x64.cc ('k') | no next file » | 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 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 DO_SMI_CHECK);
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 Register map_reg = rbx;
2534 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2535 int receiver_count = receiver_maps->length();
2536 for (int current = 0; current < receiver_count; ++current) {
2537 // Check map and tail call if there's a match
2538 Handle<Map> map(receiver_maps->at(current));
2539 __ Cmp(map_reg, map);
2540 __ j(equal,
2541 Handle<Code>(handler_ics->at(current)),
2542 RelocInfo::CODE_TARGET);
2543 }
2544
2545 __ bind(&miss);
2546 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
2547 __ jmp(ic, RelocInfo::CODE_TARGET);
2548
2549 // Return the generated code.
2550 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2551 }
2552
2553
2544 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name, 2554 MaybeObject* LoadStubCompiler::CompileLoadNonexistent(String* name,
2545 JSObject* object, 2555 JSObject* object,
2546 JSObject* last) { 2556 JSObject* last) {
2547 // ----------- S t a t e ------------- 2557 // ----------- S t a t e -------------
2548 // -- rax : receiver 2558 // -- rax : receiver
2549 // -- rcx : name 2559 // -- rcx : name
2550 // -- rsp[0] : return address 2560 // -- rsp[0] : return address
2551 // ----------------------------------- 2561 // -----------------------------------
2552 Label miss; 2562 Label miss;
2553 2563
2554 // Chech that receiver is not a smi. 2564 // Check that receiver is not a smi.
2555 __ JumpIfSmi(rax, &miss); 2565 __ JumpIfSmi(rax, &miss);
2556 2566
2557 // Check the maps of the full prototype chain. Also check that 2567 // Check the maps of the full prototype chain. Also check that
2558 // global property cells up to (but not including) the last object 2568 // global property cells up to (but not including) the last object
2559 // in the prototype chain are empty. 2569 // in the prototype chain are empty.
2560 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); 2570 CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss);
2561 2571
2562 // If the last object in the prototype chain is a global object, 2572 // If the last object in the prototype chain is a global object,
2563 // check that the global property cell is empty. 2573 // check that the global property cell is empty.
2564 if (last->IsGlobalObject()) { 2574 if (last->IsGlobalObject()) {
(...skipping 370 matching lines...) Expand 10 before | Expand all | Expand 10 after
2935 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); 2945 GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss);
2936 __ bind(&miss); 2946 __ bind(&miss);
2937 __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 2947 __ DecrementCounter(counters->keyed_load_function_prototype(), 1);
2938 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2948 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2939 2949
2940 // Return the generated code. 2950 // Return the generated code.
2941 return GetCode(CALLBACKS, name); 2951 return GetCode(CALLBACKS, name);
2942 } 2952 }
2943 2953
2944 2954
2945 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 2955 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
2956 // ----------- S t a t e -------------
2957 // -- rax : key
2958 // -- rdx : receiver
2959 // -- rsp[0] : return address
2960 // -----------------------------------
2961 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
2962 Code* stub;
2963 if (!maybe_stub->To(&stub)) return maybe_stub;
2964 __ DispatchMap(rdx,
2965 Handle<Map>(receiver_map),
2966 Handle<Code>(stub),
2967 DO_SMI_CHECK);
2968
2969 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
2970 __ jmp(ic, RelocInfo::CODE_TARGET);
2971
2972 // Return the generated code.
2973 return GetCode(NORMAL, NULL);
2974 }
2975
2976
2977 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
2978 MapList* receiver_maps,
2979 CodeList* handler_ics) {
2946 // ----------- S t a t e ------------- 2980 // ----------- S t a t e -------------
2947 // -- rax : key 2981 // -- rax : key
2948 // -- rdx : receiver 2982 // -- rdx : receiver
2949 // -- rsp[0] : return address 2983 // -- rsp[0] : return address
2950 // ----------------------------------- 2984 // -----------------------------------
2951 Label miss; 2985 Label miss;
2952
2953 // Check that the receiver isn't a smi.
2954 __ JumpIfSmi(rdx, &miss); 2986 __ JumpIfSmi(rdx, &miss);
2955 2987
2956 // Check that the map matches. 2988 Register map_reg = rbx;
2957 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2989 __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset));
2958 Handle<Map>(receiver->map())); 2990 int receiver_count = receiver_maps->length();
2959 __ j(not_equal, &miss); 2991 for (int current = 0; current < receiver_count; ++current) {
2992 // Check map and tail call if there's a match
2993 Handle<Map> map(receiver_maps->at(current));
2994 __ Cmp(map_reg, map);
2995 __ j(equal,
2996 Handle<Code>(handler_ics->at(current)),
2997 RelocInfo::CODE_TARGET);
2998 }
2960 2999
2961 // Check that the key is a smi. 3000 __ bind(&miss);
2962 __ JumpIfNotSmi(rax, &miss);
2963
2964 // Get the elements array.
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); 3001 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
2985 3002
2986 // Return the generated code. 3003 // Return the generated code.
2987 return GetCode(NORMAL, NULL); 3004 return GetCode(NORMAL, NULL, MEGAMORPHIC);
2988 } 3005 }
2989 3006
2990 3007
2991 // Specialized stub for constructing objects from functions which only have only 3008 // Specialized stub for constructing objects from functions which only have only
2992 // simple assignments of the form this.x = ...; in their body. 3009 // simple assignments of the form this.x = ...; in their body.
2993 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3010 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
2994 // ----------- S t a t e ------------- 3011 // ----------- S t a t e -------------
2995 // -- rax : argc 3012 // -- rax : argc
2996 // -- rdi : constructor 3013 // -- rdi : constructor
2997 // -- rsp[0] : return address 3014 // -- rsp[0] : return address
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3114 Code* code = 3131 Code* code =
3115 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric); 3132 isolate()->builtins()->builtin(Builtins::kJSConstructStubGeneric);
3116 Handle<Code> generic_construct_stub(code); 3133 Handle<Code> generic_construct_stub(code);
3117 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3134 __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET);
3118 3135
3119 // Return the generated code. 3136 // Return the generated code.
3120 return GetCode(); 3137 return GetCode();
3121 } 3138 }
3122 3139
3123 3140
3124 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3141 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3125 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3142 JSObject*receiver, ExternalArrayType array_type) {
3126 // ----------- S t a t e ------------- 3143 // ----------- S t a t e -------------
3127 // -- rax : key 3144 // -- rax : key
3128 // -- rdx : receiver 3145 // -- rdx : receiver
3129 // -- rsp[0] : return address 3146 // -- rsp[0] : return address
3130 // ----------------------------------- 3147 // -----------------------------------
3131 Label slow; 3148 MaybeObject* maybe_stub =
3149 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3150 Code* stub;
3151 if (!maybe_stub->To(&stub)) return maybe_stub;
3152 __ DispatchMap(rdx,
3153 Handle<Map>(receiver->map()),
3154 Handle<Code>(stub),
3155 DO_SMI_CHECK);
3132 3156
3133 // Check that the object isn't a smi. 3157 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3134 __ JumpIfSmi(rdx, &slow); 3158 __ jmp(ic, RelocInfo::CODE_TARGET);
3159
3160 // Return the generated code.
3161 return GetCode();
3162 }
3163
3164 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3165 JSObject* receiver, ExternalArrayType array_type) {
3166 // ----------- S t a t e -------------
3167 // -- rax : value
3168 // -- rcx : key
3169 // -- rdx : receiver
3170 // -- rsp[0] : return address
3171 // -----------------------------------
3172 MaybeObject* maybe_stub =
3173 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3174 Code* stub;
3175 if (!maybe_stub->To(&stub)) return maybe_stub;
3176 __ DispatchMap(rdx,
3177 Handle<Map>(receiver->map()),
3178 Handle<Code>(stub),
3179 DO_SMI_CHECK);
3180
3181 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3182 __ jmp(ic, RelocInfo::CODE_TARGET);
3183
3184 return GetCode();
3185 }
3186
3187
3188 #undef __
3189 #define __ ACCESS_MASM(masm)
3190
3191
3192 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3193 MacroAssembler* masm,
3194 ExternalArrayType array_type) {
3195 // ----------- S t a t e -------------
3196 // -- rax : key
3197 // -- rdx : receiver
3198 // -- rsp[0] : return address
3199 // -----------------------------------
3200 Label slow, miss_force_generic;
3201
3202 // This stub is meant to be tail-jumped to, the receiver must already
3203 // have been verified by the caller to not be a smi.
3135 3204
3136 // Check that the key is a smi. 3205 // Check that the key is a smi.
3137 __ JumpIfNotSmi(rax, &slow); 3206 __ JumpIfNotSmi(rax, &miss_force_generic);
3138
3139 // Check that the map matches.
3140 __ CheckMap(rdx, Handle<Map>(receiver->map()), &slow, DO_SMI_CHECK);
3141 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3142 3207
3143 // Check that the index is in range. 3208 // Check that the index is in range.
3209 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3144 __ SmiToInteger32(rcx, rax); 3210 __ SmiToInteger32(rcx, rax);
3145 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3211 __ cmpl(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset));
3146 // Unsigned comparison catches both negative and too-large values. 3212 // Unsigned comparison catches both negative and too-large values.
3147 __ j(above_equal, &slow); 3213 __ j(above_equal, &miss_force_generic);
3148 3214
3149 // rax: index (as a smi) 3215 // rax: index (as a smi)
3150 // rdx: receiver (JSObject) 3216 // rdx: receiver (JSObject)
3151 // rcx: untagged index 3217 // rcx: untagged index
3152 // rbx: elements array 3218 // rbx: elements array
3153 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 3219 __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset));
3154 // rbx: base pointer of external storage 3220 // rbx: base pointer of external storage
3155 switch (array_type) { 3221 switch (array_type) {
3156 case kExternalByteArray: 3222 case kExternalByteArray:
3157 __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); 3223 __ 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); 3290 __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0);
3225 __ movq(rax, rcx); 3291 __ movq(rax, rcx);
3226 __ ret(0); 3292 __ ret(0);
3227 } else { 3293 } else {
3228 __ Integer32ToSmi(rax, rcx); 3294 __ Integer32ToSmi(rax, rcx);
3229 __ ret(0); 3295 __ ret(0);
3230 } 3296 }
3231 3297
3232 // Slow case: Jump to runtime. 3298 // Slow case: Jump to runtime.
3233 __ bind(&slow); 3299 __ bind(&slow);
3234 Counters* counters = isolate()->counters(); 3300 Counters* counters = masm->isolate()->counters();
3235 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 3301 __ IncrementCounter(counters->keyed_load_external_array_slow(), 1);
3236 3302
3237 // ----------- S t a t e ------------- 3303 // ----------- S t a t e -------------
3238 // -- rax : key 3304 // -- rax : key
3239 // -- rdx : receiver 3305 // -- rdx : receiver
3240 // -- rsp[0] : return address 3306 // -- rsp[0] : return address
3241 // ----------------------------------- 3307 // -----------------------------------
3242 3308
3243 __ pop(rbx); 3309 Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow();
3244 __ push(rdx); // receiver 3310 __ jmp(ic, RelocInfo::CODE_TARGET);
3245 __ push(rax); // name
3246 __ push(rbx); // return address
3247 3311
3248 // Perform tail call to the entry. 3312 // Miss case: Jump to runtime.
3249 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3313 __ bind(&miss_force_generic);
3250 3314
3251 // Return the generated code. 3315 // ----------- S t a t e -------------
3252 return GetCode(flags); 3316 // -- rax : key
3317 // -- rdx : receiver
3318 // -- rsp[0] : return address
3319 // -----------------------------------
3320 Handle<Code> miss_ic =
3321 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3322 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3253 } 3323 }
3254 3324
3255 3325
3256 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3326 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3257 JSObject* receiver, ExternalArrayType array_type, Code::Flags flags) { 3327 MacroAssembler* masm,
3328 ExternalArrayType array_type) {
3258 // ----------- S t a t e ------------- 3329 // ----------- S t a t e -------------
3259 // -- rax : value 3330 // -- rax : value
3260 // -- rcx : key 3331 // -- rcx : key
3261 // -- rdx : receiver 3332 // -- rdx : receiver
3262 // -- rsp[0] : return address 3333 // -- rsp[0] : return address
3263 // ----------------------------------- 3334 // -----------------------------------
3264 Label slow; 3335 Label slow, miss_force_generic;
3265 3336
3266 // Check that the object isn't a smi. 3337 // This stub is meant to be tail-jumped to, the receiver must already
3267 __ JumpIfSmi(rdx, &slow); 3338 // 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, DO_SMI_CHECK);
3271 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3272 3339
3273 // Check that the key is a smi. 3340 // Check that the key is a smi.
3274 __ JumpIfNotSmi(rcx, &slow); 3341 __ JumpIfNotSmi(rcx, &miss_force_generic);
3275 3342
3276 // Check that the index is in range. 3343 // Check that the index is in range.
3344 __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset));
3277 __ SmiToInteger32(rdi, rcx); // Untag the index. 3345 __ SmiToInteger32(rdi, rcx); // Untag the index.
3278 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset)); 3346 __ cmpl(rdi, FieldOperand(rbx, ExternalArray::kLengthOffset));
3279 // Unsigned comparison catches both negative and too-large values. 3347 // Unsigned comparison catches both negative and too-large values.
3280 __ j(above_equal, &slow); 3348 __ j(above_equal, &miss_force_generic);
3281 3349
3282 // Handle both smis and HeapNumbers in the fast path. Go to the 3350 // Handle both smis and HeapNumbers in the fast path. Go to the
3283 // runtime for all other kinds of values. 3351 // runtime for all other kinds of values.
3284 // rax: value 3352 // rax: value
3285 // rcx: key (a smi) 3353 // rcx: key (a smi)
3286 // rdx: receiver (a JSObject) 3354 // rdx: receiver (a JSObject)
3287 // rbx: elements array 3355 // rbx: elements array
3288 // rdi: untagged key 3356 // rdi: untagged key
3289 Label check_heap_number; 3357 Label check_heap_number;
3290 if (array_type == kExternalPixelArray) { 3358 if (array_type == kExternalPixelArray) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3404 // Slow case: call runtime. 3472 // Slow case: call runtime.
3405 __ bind(&slow); 3473 __ bind(&slow);
3406 3474
3407 // ----------- S t a t e ------------- 3475 // ----------- S t a t e -------------
3408 // -- rax : value 3476 // -- rax : value
3409 // -- rcx : key 3477 // -- rcx : key
3410 // -- rdx : receiver 3478 // -- rdx : receiver
3411 // -- rsp[0] : return address 3479 // -- rsp[0] : return address
3412 // ----------------------------------- 3480 // -----------------------------------
3413 3481
3414 __ pop(rbx); 3482 Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow();
3415 __ push(rdx); // receiver 3483 __ 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 3484
3423 // Do tail-call to runtime routine. 3485 // Miss case: call runtime.
3424 __ TailCallRuntime(Runtime::kSetProperty, 5, 1); 3486 __ bind(&miss_force_generic);
3425 3487
3426 return GetCode(flags); 3488 // ----------- S t a t e -------------
3489 // -- rax : value
3490 // -- rcx : key
3491 // -- rdx : receiver
3492 // -- rsp[0] : return address
3493 // -----------------------------------
3494
3495 Handle<Code> miss_ic =
3496 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3497 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3427 } 3498 }
3428 3499
3500
3501 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
3502 // ----------- S t a t e -------------
3503 // -- rax : key
3504 // -- rdx : receiver
3505 // -- rsp[0] : return address
3506 // -----------------------------------
3507 Label miss_force_generic;
3508
3509 // This stub is meant to be tail-jumped to, the receiver must already
3510 // have been verified by the caller to not be a smi.
3511
3512 // Check that the key is a smi.
3513 __ JumpIfNotSmi(rax, &miss_force_generic);
3514
3515 // Get the elements array.
3516 __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset));
3517 __ AssertFastElements(rcx);
3518
3519 // Check that the key is within bounds.
3520 __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset));
3521 __ j(above_equal, &miss_force_generic);
3522
3523 // Load the result and make sure it's not the hole.
3524 SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2);
3525 __ movq(rbx, FieldOperand(rcx,
3526 index.reg,
3527 index.scale,
3528 FixedArray::kHeaderSize));
3529 __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex);
3530 __ j(equal, &miss_force_generic);
3531 __ movq(rax, rbx);
3532 __ ret(0);
3533
3534 __ bind(&miss_force_generic);
3535 Code* code = masm->isolate()->builtins()->builtin(
3536 Builtins::kKeyedLoadIC_MissForceGeneric);
3537 Handle<Code> ic(code);
3538 __ jmp(ic, RelocInfo::CODE_TARGET);
3539 }
3540
3541
3542 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
3543 bool is_js_array) {
3544 // ----------- S t a t e -------------
3545 // -- rax : value
3546 // -- rcx : key
3547 // -- rdx : receiver
3548 // -- rsp[0] : return address
3549 // -----------------------------------
3550 Label miss_force_generic;
3551
3552 // This stub is meant to be tail-jumped to, the receiver must already
3553 // have been verified by the caller to not be a smi.
3554
3555 // Check that the key is a smi.
3556 __ JumpIfNotSmi(rcx, &miss_force_generic);
3557
3558 // Get the elements array and make sure it is a fast element array, not 'cow'.
3559 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3560 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3561 Heap::kFixedArrayMapRootIndex);
3562 __ j(not_equal, &miss_force_generic);
3563
3564 // Check that the key is within bounds.
3565 if (is_js_array) {
3566 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3567 __ j(above_equal, &miss_force_generic);
3568 } else {
3569 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3570 __ j(above_equal, &miss_force_generic);
3571 }
3572
3573 // Do the store and update the write barrier. Make sure to preserve
3574 // the value in register eax.
3575 __ movq(rdx, rax);
3576 __ SmiToInteger32(rcx, rcx);
3577 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
3578 rax);
3579 __ RecordWrite(rdi, 0, rdx, rcx);
3580
3581 // Done.
3582 __ ret(0);
3583
3584 // Handle store cache miss.
3585 __ bind(&miss_force_generic);
3586 Handle<Code> ic_force_generic =
3587 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3588 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3589 }
3590
3591
3429 #undef __ 3592 #undef __
3430 3593
3431 } } // namespace v8::internal 3594 } } // namespace v8::internal
3432 3595
3433 #endif // V8_TARGET_ARCH_X64 3596 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/macro-assembler-x64.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698