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

Side by Side Diff: src/arm/stub-cache-arm.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 3066 matching lines...) Expand 10 before | Expand all | Expand 10 after
3077 3077
3078 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss); 3078 GenerateLoadFunctionPrototype(masm(), r1, r2, r3, &miss);
3079 __ bind(&miss); 3079 __ bind(&miss);
3080 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3); 3080 __ DecrementCounter(counters->keyed_load_function_prototype(), 1, r2, r3);
3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3081 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3082 3082
3083 return GetCode(CALLBACKS, name); 3083 return GetCode(CALLBACKS, name);
3084 } 3084 }
3085 3085
3086 3086
3087 MaybeObject* KeyedLoadStubCompiler::CompileLoadSpecialized(JSObject* receiver) { 3087 MaybeObject* KeyedLoadStubCompiler::CompileLoadFastElement(Map* receiver_map) {
3088 // ----------- S t a t e -------------
3089 // -- lr : return address
3090 // -- r0 : key
3091 // -- r1 : receiver
3092 // -----------------------------------
3093 MaybeObject* maybe_stub = KeyedLoadFastElementStub().TryGetCode();
3094 Code* stub;
3095 if (!maybe_stub->To(&stub)) return maybe_stub;
3096 __ DispatchMap(r1,
3097 r2,
3098 Handle<Map>(receiver_map),
3099 Handle<Code>(stub),
3100 false);
3101
3102 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3103 __ Jump(ic, RelocInfo::CODE_TARGET);
3104
3105 // Return the generated code.
3106 return GetCode(NORMAL, NULL);
3107 }
3108
3109
3110 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
3111 MapList* receiver_maps,
3112 CodeList* handler_ics) {
3088 // ----------- S t a t e ------------- 3113 // ----------- S t a t e -------------
3089 // -- lr : return address 3114 // -- lr : return address
3090 // -- r0 : key 3115 // -- r0 : key
3091 // -- r1 : receiver 3116 // -- r1 : receiver
3092 // ----------------------------------- 3117 // -----------------------------------
3093 Label miss; 3118 Label miss;
3119 __ JumpIfSmi(r1, &miss);
3094 3120
3095 // Check that the receiver isn't a smi. 3121 int receiver_count = receiver_maps->length();
3096 __ tst(r1, Operand(kSmiTagMask)); 3122 for (int current = 0; current < receiver_count; ++current) {
3097 __ b(eq, &miss); 3123 // Check map and tail call if there's a match
3098 3124 __ DispatchMap(r1,
3099 // Check that the map matches. 3125 r2,
3100 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3126 Handle<Map>(receiver_maps->at(current)),
3101 __ cmp(r2, Operand(Handle<Map>(receiver->map()))); 3127 Handle<Code>(handler_ics->at(current)),
3102 __ b(ne, &miss); 3128 true);
Mads Ager (chromium) 2011/05/12 09:42:47 I already forgot what this boolean is. Using an en
danno 2011/06/01 13:16:08 Done.
3103 3129 }
3104 // Check that the key is a smi.
3105 __ tst(r0, Operand(kSmiTagMask));
3106 __ b(ne, &miss);
3107
3108 // Get the elements array.
3109 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
3110 __ AssertFastElements(r2);
3111
3112 // Check that the key is within bounds.
3113 __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
3114 __ cmp(r0, Operand(r3));
3115 __ b(hs, &miss);
3116
3117 // Load the result and make sure it's not the hole.
3118 __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3119 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
3120 __ ldr(r4,
3121 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
3122 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
3123 __ cmp(r4, ip);
3124 __ b(eq, &miss);
3125 __ mov(r0, r4);
3126 __ Ret();
3127 3130
3128 __ bind(&miss); 3131 __ bind(&miss);
3129 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3132 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
3133 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3130 3134
3131 // Return the generated code. 3135 // Return the generated code.
3132 return GetCode(NORMAL, NULL); 3136 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3133 } 3137 }
3134 3138
3135 3139
3136 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 3140 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
3137 int index, 3141 int index,
3138 Map* transition, 3142 Map* transition,
3139 String* name) { 3143 String* name) {
3140 // ----------- S t a t e ------------- 3144 // ----------- S t a t e -------------
3141 // -- r0 : value 3145 // -- r0 : value
3142 // -- r1 : name 3146 // -- r1 : name
(...skipping 21 matching lines...) Expand all
3164 3168
3165 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); 3169 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
3166 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3170 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3167 __ Jump(ic, RelocInfo::CODE_TARGET); 3171 __ Jump(ic, RelocInfo::CODE_TARGET);
3168 3172
3169 // Return the generated code. 3173 // Return the generated code.
3170 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 3174 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
3171 } 3175 }
3172 3176
3173 3177
3174 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 3178 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
3175 JSObject* receiver) { 3179 Map* receiver_map) {
3176 // ----------- S t a t e ------------- 3180 // ----------- S t a t e -------------
3177 // -- r0 : value 3181 // -- r0 : value
3178 // -- r1 : key 3182 // -- r1 : key
3179 // -- r2 : receiver 3183 // -- r2 : receiver
3180 // -- lr : return address 3184 // -- lr : return address
3181 // -- r3 : scratch 3185 // -- r3 : scratch
3182 // -- r4 : scratch (elements)
3183 // ----------------------------------- 3186 // -----------------------------------
3184 Label miss; 3187 bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE;
3188 MaybeObject* maybe_stub =
3189 KeyedStoreFastElementStub(is_js_array).TryGetCode();
3190 Code* stub;
3191 if (!maybe_stub->To(&stub)) return maybe_stub;
3192 __ DispatchMap(r2,
3193 r3,
3194 Handle<Map>(receiver_map),
3195 Handle<Code>(stub),
3196 false);
3185 3197
3186 Register value_reg = r0; 3198 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3187 Register key_reg = r1;
3188 Register receiver_reg = r2;
3189 Register scratch = r3;
3190 Register elements_reg = r4;
3191
3192 // Check that the receiver isn't a smi.
3193 __ tst(receiver_reg, Operand(kSmiTagMask));
3194 __ b(eq, &miss);
3195
3196 // Check that the map matches.
3197 __ ldr(scratch, FieldMemOperand(receiver_reg, HeapObject::kMapOffset));
3198 __ cmp(scratch, Operand(Handle<Map>(receiver->map())));
3199 __ b(ne, &miss);
3200
3201 // Check that the key is a smi.
3202 __ tst(key_reg, Operand(kSmiTagMask));
3203 __ b(ne, &miss);
3204
3205 // Get the elements array and make sure it is a fast element array, not 'cow'.
3206 __ ldr(elements_reg,
3207 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
3208 __ ldr(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset));
3209 __ cmp(scratch, Operand(Handle<Map>(factory()->fixed_array_map())));
3210 __ b(ne, &miss);
3211
3212 // Check that the key is within bounds.
3213 if (receiver->IsJSArray()) {
3214 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
3215 } else {
3216 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
3217 }
3218 // Compare smis.
3219 __ cmp(key_reg, scratch);
3220 __ b(hs, &miss);
3221
3222 __ add(scratch,
3223 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
3224 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
3225 __ str(value_reg,
3226 MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
3227 __ RecordWrite(scratch,
3228 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
3229 receiver_reg , elements_reg);
3230
3231 // value_reg (r0) is preserved.
3232 // Done.
3233 __ Ret();
3234
3235 __ bind(&miss);
3236 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3237 __ Jump(ic, RelocInfo::CODE_TARGET); 3199 __ Jump(ic, RelocInfo::CODE_TARGET);
3238 3200
3239 // Return the generated code. 3201 // Return the generated code.
3240 return GetCode(NORMAL, NULL); 3202 return GetCode(NORMAL, NULL);
3241 } 3203 }
3242 3204
3243 3205
3206 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
3207 MapList* receiver_maps,
3208 CodeList* handler_ics) {
3209 // ----------- S t a t e -------------
3210 // -- r0 : value
3211 // -- r1 : key
3212 // -- r2 : receiver
3213 // -- lr : return address
3214 // -- r3 : scratch
3215 // -----------------------------------
3216 Label miss;
3217 __ JumpIfSmi(r2, &miss);
3218
3219 int receiver_count = receiver_maps->length();
3220 for (int current = 0; current < receiver_count; ++current) {
3221 // Check map and tail call if there's a match
3222 __ DispatchMap(r2,
3223 r3,
3224 Handle<Map>(receiver_maps->at(current)),
3225 Handle<Code>(handler_ics->at(current)),
3226 true);
3227 }
3228
3229 __ bind(&miss);
3230 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
3231 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3232
3233 // Return the generated code.
3234 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3235 }
3236
3237
3244 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3238 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3245 // ----------- S t a t e ------------- 3239 // ----------- S t a t e -------------
3246 // -- r0 : argc 3240 // -- r0 : argc
3247 // -- r1 : constructor 3241 // -- r1 : constructor
3248 // -- lr : return address 3242 // -- lr : return address
3249 // -- [sp] : last argument 3243 // -- [sp] : last argument
3250 // ----------------------------------- 3244 // -----------------------------------
3251 Label generic_stub_call; 3245 Label generic_stub_call;
3252 3246
3253 // Use r7 for holding undefined which is used in several places below. 3247 // Use r7 for holding undefined which is used in several places below.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
3378 // construction. 3372 // construction.
3379 __ bind(&generic_stub_call); 3373 __ bind(&generic_stub_call);
3380 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); 3374 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
3381 __ Jump(code, RelocInfo::CODE_TARGET); 3375 __ Jump(code, RelocInfo::CODE_TARGET);
3382 3376
3383 // Return the generated code. 3377 // Return the generated code.
3384 return GetCode(); 3378 return GetCode();
3385 } 3379 }
3386 3380
3387 3381
3382 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3383 JSObject*receiver, ExternalArrayType array_type) {
3384 // ----------- S t a t e -------------
3385 // -- lr : return address
3386 // -- r0 : key
3387 // -- r1 : receiver
3388 // -----------------------------------
3389 MaybeObject* maybe_stub =
3390 KeyedLoadExternalArrayStub(array_type).TryGetCode();
3391 Code* stub;
3392 if (!maybe_stub->To(&stub)) return maybe_stub;
3393 __ DispatchMap(r1,
3394 r2,
3395 Handle<Map>(receiver->map()),
3396 Handle<Code>(stub),
3397 false);
3398
3399 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3400 __ Jump(ic, RelocInfo::CODE_TARGET);
3401
3402 // Return the generated code.
3403 return GetCode();
3404 }
3405
3406
3407 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3408 JSObject* receiver, ExternalArrayType array_type) {
3409 // ----------- S t a t e -------------
3410 // -- r0 : value
3411 // -- r1 : name
3412 // -- r2 : receiver
3413 // -- lr : return address
3414 // -----------------------------------
3415 MaybeObject* maybe_stub =
3416 KeyedStoreExternalArrayStub(array_type).TryGetCode();
3417 Code* stub;
3418 if (!maybe_stub->To(&stub)) return maybe_stub;
3419 __ DispatchMap(r2,
3420 r3,
3421 Handle<Map>(receiver->map()),
3422 Handle<Code>(stub),
3423 false);
3424
3425 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3426 __ Jump(ic, RelocInfo::CODE_TARGET);
3427
3428 return GetCode();
3429 }
3430
3431
3432 #undef __
3433 #define __ ACCESS_MASM(masm)
3434
3435
3388 static bool IsElementTypeSigned(ExternalArrayType array_type) { 3436 static bool IsElementTypeSigned(ExternalArrayType array_type) {
3389 switch (array_type) { 3437 switch (array_type) {
3390 case kExternalByteArray: 3438 case kExternalByteArray:
3391 case kExternalShortArray: 3439 case kExternalShortArray:
3392 case kExternalIntArray: 3440 case kExternalIntArray:
3393 return true; 3441 return true;
3394 3442
3395 case kExternalUnsignedByteArray: 3443 case kExternalUnsignedByteArray:
3396 case kExternalUnsignedShortArray: 3444 case kExternalUnsignedShortArray:
3397 case kExternalUnsignedIntArray: 3445 case kExternalUnsignedIntArray:
3398 return false; 3446 return false;
3399 3447
3400 default: 3448 default:
3401 UNREACHABLE(); 3449 UNREACHABLE();
3402 return false; 3450 return false;
3403 } 3451 }
3404 } 3452 }
3405 3453
3406 3454
3407 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3455 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3408 JSObject* receiver_object, 3456 MacroAssembler* masm,
3409 ExternalArrayType array_type, 3457 ExternalArrayType array_type) {
3410 Code::Flags flags) {
3411 // ---------- S t a t e -------------- 3458 // ---------- S t a t e --------------
3412 // -- lr : return address 3459 // -- lr : return address
3413 // -- r0 : key 3460 // -- r0 : key
3414 // -- r1 : receiver 3461 // -- r1 : receiver
3415 // ----------------------------------- 3462 // -----------------------------------
3416 Label slow, failed_allocation; 3463 Label miss_force_generic, slow, failed_allocation;
3417 3464
3418 Register key = r0; 3465 Register key = r0;
3419 Register receiver = r1; 3466 Register receiver = r1;
3420 3467
3421 // Check that the object isn't a smi 3468 // This stub is meant to be tail-jumped to, the receiver must already
3422 __ JumpIfSmi(receiver, &slow); 3469 // have been verified by the caller to not be a smi.
3423 3470
3424 // Check that the key is a smi. 3471 // Check that the key is a smi.
3425 __ JumpIfNotSmi(key, &slow); 3472 __ JumpIfNotSmi(key, &miss_force_generic);
3426
3427 // Make sure that we've got the right map.
3428 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
3429 __ cmp(r2, Operand(Handle<Map>(receiver_object->map())));
3430 __ b(ne, &slow);
3431 3473
3432 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3474 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3433 // r3: elements array 3475 // r3: elements array
3434 3476
3435 // Check that the index is in range. 3477 // Check that the index is in range.
3436 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3478 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3437 __ cmp(ip, Operand(key, ASR, kSmiTagSize)); 3479 __ cmp(ip, Operand(key, ASR, kSmiTagSize));
3438 // Unsigned comparison catches both negative and too-large values. 3480 // Unsigned comparison catches both negative and too-large values.
3439 __ b(lo, &slow); 3481 __ b(lo, &miss_force_generic);
3440 3482
3441 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3483 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3442 // r3: base pointer of external storage 3484 // r3: base pointer of external storage
3443 3485
3444 // We are not untagging smi key and instead work with it 3486 // We are not untagging smi key and instead work with it
3445 // as if it was premultiplied by 2. 3487 // as if it was premultiplied by 2.
3446 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 3488 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
3447 3489
3448 Register value = r2; 3490 Register value = r2;
3449 switch (array_type) { 3491 switch (array_type) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3566 __ b(ne, &box_int_1); 3608 __ b(ne, &box_int_1);
3567 // Tag integer as smi and return it. 3609 // Tag integer as smi and return it.
3568 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3610 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3569 __ Ret(); 3611 __ Ret();
3570 3612
3571 Register hiword = value; // r2. 3613 Register hiword = value; // r2.
3572 Register loword = r3; 3614 Register loword = r3;
3573 3615
3574 __ bind(&box_int_0); 3616 __ bind(&box_int_0);
3575 // Integer does not have leading zeros. 3617 // Integer does not have leading zeros.
3576 GenerateUInt2Double(masm(), hiword, loword, r4, 0); 3618 GenerateUInt2Double(masm, hiword, loword, r4, 0);
3577 __ b(&done); 3619 __ b(&done);
3578 3620
3579 __ bind(&box_int_1); 3621 __ bind(&box_int_1);
3580 // Integer has one leading zero. 3622 // Integer has one leading zero.
3581 GenerateUInt2Double(masm(), hiword, loword, r4, 1); 3623 GenerateUInt2Double(masm, hiword, loword, r4, 1);
3582 3624
3583 3625
3584 __ bind(&done); 3626 __ bind(&done);
3585 // Integer was converted to double in registers hiword:loword. 3627 // Integer was converted to double in registers hiword:loword.
3586 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber 3628 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
3587 // clobbers all registers - also when jumping due to exhausted young 3629 // clobbers all registers - also when jumping due to exhausted young
3588 // space. 3630 // space.
3589 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3631 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3590 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); 3632 __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
3591 3633
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3693 3735
3694 } else { 3736 } else {
3695 // Tag integer as smi and return it. 3737 // Tag integer as smi and return it.
3696 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3738 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3697 __ Ret(); 3739 __ Ret();
3698 } 3740 }
3699 3741
3700 // Slow case, key and receiver still in r0 and r1. 3742 // Slow case, key and receiver still in r0 and r1.
3701 __ bind(&slow); 3743 __ bind(&slow);
3702 __ IncrementCounter( 3744 __ IncrementCounter(
3703 masm()->isolate()->counters()->keyed_load_external_array_slow(), 3745 masm->isolate()->counters()->keyed_load_external_array_slow(),
3704 1, r2, r3); 3746 1, r2, r3);
3705 3747
3706 // ---------- S t a t e -------------- 3748 // ---------- S t a t e --------------
3707 // -- lr : return address 3749 // -- lr : return address
3708 // -- r0 : key 3750 // -- r0 : key
3709 // -- r1 : receiver 3751 // -- r1 : receiver
3710 // ----------------------------------- 3752 // -----------------------------------
3711 3753
3712 __ Push(r1, r0); 3754 __ Push(r1, r0);
3713 3755
3714 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3756 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3715 3757
3716 return GetCode(flags); 3758 __ bind(&miss_force_generic);
3759 Code* stub = masm->isolate()->builtins()->builtin(
3760 Builtins::kKeyedLoadIC_MissForceGeneric);
3761 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
3717 } 3762 }
3718 3763
3719 3764
3720 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3765 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3721 JSObject* receiver_object, 3766 MacroAssembler* masm,
3722 ExternalArrayType array_type, 3767 ExternalArrayType array_type) {
3723 Code::Flags flags) {
3724 // ---------- S t a t e -------------- 3768 // ---------- S t a t e --------------
3725 // -- r0 : value 3769 // -- r0 : value
3726 // -- r1 : key 3770 // -- r1 : key
3727 // -- r2 : receiver 3771 // -- r2 : receiver
3728 // -- lr : return address 3772 // -- lr : return address
3729 // ----------------------------------- 3773 // -----------------------------------
3730 Label slow, check_heap_number; 3774 Label slow, check_heap_number, miss_force_generic;
3731 3775
3732 // Register usage. 3776 // Register usage.
3733 Register value = r0; 3777 Register value = r0;
3734 Register key = r1; 3778 Register key = r1;
3735 Register receiver = r2; 3779 Register receiver = r2;
3736 // r3 mostly holds the elements array or the destination external array. 3780 // r3 mostly holds the elements array or the destination external array.
3737 3781
3738 // Check that the object isn't a smi. 3782 // This stub is meant to be tail-jumped to, the receiver must already
3739 __ JumpIfSmi(receiver, &slow); 3783 // have been verified by the caller to not be a smi.
3740
3741 // Make sure that we've got the right map.
3742 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
3743 __ cmp(r3, Operand(Handle<Map>(receiver_object->map())));
3744 __ b(ne, &slow);
3745 3784
3746 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3785 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3747 3786
3748 // Check that the key is a smi. 3787 // Check that the key is a smi.
3749 __ JumpIfNotSmi(key, &slow); 3788 __ JumpIfNotSmi(key, &miss_force_generic);
3750 3789
3751 // Check that the index is in range 3790 // Check that the index is in range
3752 __ SmiUntag(r4, key); 3791 __ SmiUntag(r4, key);
3753 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3792 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3754 __ cmp(r4, ip); 3793 __ cmp(r4, ip);
3755 // Unsigned comparison catches both negative and too-large values. 3794 // Unsigned comparison catches both negative and too-large values.
3756 __ b(hs, &slow); 3795 __ b(hs, &miss_force_generic);
3757 3796
3758 // Handle both smis and HeapNumbers in the fast path. Go to the 3797 // Handle both smis and HeapNumbers in the fast path. Go to the
3759 // runtime for all other kinds of values. 3798 // runtime for all other kinds of values.
3760 // r3: external array. 3799 // r3: external array.
3761 // r4: key (integer). 3800 // r4: key (integer).
3762 if (array_type == kExternalPixelArray) { 3801 if (array_type == kExternalPixelArray) {
3763 // Double to pixel conversion is only implemented in the runtime for now. 3802 // Double to pixel conversion is only implemented in the runtime for now.
3764 __ JumpIfNotSmi(value, &slow); 3803 __ JumpIfNotSmi(value, &slow);
3765 } else { 3804 } else {
3766 __ JumpIfNotSmi(value, &check_heap_number); 3805 __ JumpIfNotSmi(value, &check_heap_number);
(...skipping 17 matching lines...) Expand all
3784 case kExternalShortArray: 3823 case kExternalShortArray:
3785 case kExternalUnsignedShortArray: 3824 case kExternalUnsignedShortArray:
3786 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 3825 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3787 break; 3826 break;
3788 case kExternalIntArray: 3827 case kExternalIntArray:
3789 case kExternalUnsignedIntArray: 3828 case kExternalUnsignedIntArray:
3790 __ str(r5, MemOperand(r3, r4, LSL, 2)); 3829 __ str(r5, MemOperand(r3, r4, LSL, 2));
3791 break; 3830 break;
3792 case kExternalFloatArray: 3831 case kExternalFloatArray:
3793 // Perform int-to-float conversion and store to memory. 3832 // Perform int-to-float conversion and store to memory.
3794 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9); 3833 StoreIntAsFloat(masm, r3, r4, r5, r6, r7, r9);
3795 break; 3834 break;
3796 case kExternalDoubleArray: 3835 case kExternalDoubleArray:
3797 __ add(r3, r3, Operand(r4, LSL, 3)); 3836 __ add(r3, r3, Operand(r4, LSL, 3));
3798 // r3: effective address of the double element 3837 // r3: effective address of the double element
3799 FloatingPointHelper::Destination destination; 3838 FloatingPointHelper::Destination destination;
3800 if (CpuFeatures::IsSupported(VFP3)) { 3839 if (CpuFeatures::IsSupported(VFP3)) {
3801 destination = FloatingPointHelper::kVFPRegisters; 3840 destination = FloatingPointHelper::kVFPRegisters;
3802 } else { 3841 } else {
3803 destination = FloatingPointHelper::kCoreRegisters; 3842 destination = FloatingPointHelper::kCoreRegisters;
3804 } 3843 }
3805 FloatingPointHelper::ConvertIntToDouble( 3844 FloatingPointHelper::ConvertIntToDouble(
3806 masm(), r5, destination, 3845 masm, r5, destination,
3807 d0, r6, r7, // These are: double_dst, dst1, dst2. 3846 d0, r6, r7, // These are: double_dst, dst1, dst2.
3808 r4, s2); // These are: scratch2, single_scratch. 3847 r4, s2); // These are: scratch2, single_scratch.
3809 if (destination == FloatingPointHelper::kVFPRegisters) { 3848 if (destination == FloatingPointHelper::kVFPRegisters) {
3810 CpuFeatures::Scope scope(VFP3); 3849 CpuFeatures::Scope scope(VFP3);
3811 __ vstr(d0, r3, 0); 3850 __ vstr(d0, r3, 0);
3812 } else { 3851 } else {
3813 __ str(r6, MemOperand(r3, 0)); 3852 __ str(r6, MemOperand(r3, 0));
3814 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); 3853 __ str(r7, MemOperand(r3, Register::kSizeInBytes));
3815 } 3854 }
3816 break; 3855 break;
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
4023 __ str(r5, MemOperand(r3, r4, LSL, 2)); 4062 __ str(r5, MemOperand(r3, r4, LSL, 2));
4024 break; 4063 break;
4025 default: 4064 default:
4026 UNREACHABLE(); 4065 UNREACHABLE();
4027 break; 4066 break;
4028 } 4067 }
4029 } 4068 }
4030 } 4069 }
4031 } 4070 }
4032 4071
4033 // Slow case: call runtime. 4072 // Slow case, key and receiver still in r0 and r1.
4034 __ bind(&slow); 4073 __ bind(&slow);
4074 __ IncrementCounter(
4075 masm->isolate()->counters()->keyed_load_external_array_slow(),
4076 1, r2, r3);
4035 4077
4036 // Entry registers are intact.
4037 // ---------- S t a t e -------------- 4078 // ---------- S t a t e --------------
4038 // -- r0 : value
4039 // -- r1 : key
4040 // -- r2 : receiver
4041 // -- lr : return address 4079 // -- lr : return address
4080 // -- r0 : key
4081 // -- r1 : receiver
4082 // -----------------------------------
4083 Handle<Code> slow_ic =
4084 masm->isolate()->builtins()->KeyedStoreIC_Slow();
4085 __ Jump(slow_ic, RelocInfo::CODE_TARGET);
4086
4087 // Miss case, call the runtime.
4088 __ bind(&miss_force_generic);
4089
4090 // ---------- S t a t e --------------
4091 // -- lr : return address
4092 // -- r0 : key
4093 // -- r1 : receiver
4042 // ----------------------------------- 4094 // -----------------------------------
4043 4095
4044 // Push receiver, key and value for runtime call. 4096 Handle<Code> miss_ic =
4045 __ Push(r2, r1, r0); 4097 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4046 4098 __ Jump(miss_ic, RelocInfo::CODE_TARGET);
4047 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes
4048 __ mov(r0, Operand(Smi::FromInt(
4049 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
4050 __ Push(r1, r0);
4051
4052 __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
4053
4054 return GetCode(flags);
4055 } 4099 }
4056 4100
4057 4101
4102 void KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) {
4103 // ----------- S t a t e -------------
4104 // -- lr : return address
4105 // -- r0 : key
4106 // -- r1 : receiver
4107 // -----------------------------------
4108 Label miss_force_generic;
4109
4110 // This stub is meant to be tail-jumped to, the receiver must already
4111 // have been verified by the caller to not be a smi.
4112
4113 // Check that the key is a smi.
4114 __ tst(r0, Operand(kSmiTagMask));
Mads Ager (chromium) 2011/05/12 09:42:47 Use JumpIfNotSmi?
danno 2011/06/01 13:16:08 Done.
4115 __ b(ne, &miss_force_generic);
4116
4117 // Get the elements array.
4118 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
4119 __ AssertFastElements(r2);
4120
4121 // Check that the key is within bounds.
4122 __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
4123 __ cmp(r0, Operand(r3));
4124 __ b(hs, &miss_force_generic);
4125
4126 // Load the result and make sure it's not the hole.
4127 __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4128 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4129 __ ldr(r4,
4130 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
4131 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
4132 __ cmp(r4, ip);
4133 __ b(eq, &miss_force_generic);
4134 __ mov(r0, r4);
4135 __ Ret();
4136
4137 __ bind(&miss_force_generic);
4138 Code* stub = masm->isolate()->builtins()->builtin(
4139 Builtins::kKeyedLoadIC_MissForceGeneric);
4140 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
4141 }
4142
4143
4144 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
4145 bool is_js_array) {
4146 // ----------- S t a t e -------------
4147 // -- r0 : value
4148 // -- r1 : key
4149 // -- r2 : receiver
4150 // -- lr : return address
4151 // -- r3 : scratch
4152 // -- r4 : scratch (elements)
4153 // -----------------------------------
4154 Label miss_force_generic;
4155
4156 Register value_reg = r0;
4157 Register key_reg = r1;
4158 Register receiver_reg = r2;
4159 Register scratch = r3;
4160 Register elements_reg = r4;
4161
4162 // This stub is meant to be tail-jumped to, the receiver must already
4163 // have been verified by the caller to not be a smi.
4164
4165 // Check that the key is a smi.
4166 __ tst(key_reg, Operand(kSmiTagMask));
Mads Ager (chromium) 2011/05/12 09:42:47 JumpIfNotSmi?
danno 2011/06/01 13:16:08 Done.
4167 __ b(ne, &miss_force_generic);
4168
4169 // Get the elements array and make sure it is a fast element array, not 'cow'.
4170 __ ldr(elements_reg,
4171 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4172 __ ldr(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset));
Mads Ager (chromium) 2011/05/12 09:42:47 Can you use CheckMap with kFixedArrayMapRootIndex
danno 2011/06/01 13:16:08 Done.
4173 Handle<Map> map =
4174 Handle<Map>(masm->isolate()->factory()->fixed_array_map());
4175 __ cmp(scratch, Operand(map));
4176 __ b(ne, &miss_force_generic);
4177
4178 // Check that the key is within bounds.
4179 if (is_js_array) {
4180 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4181 } else {
4182 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4183 }
4184 // Compare smis.
4185 __ cmp(key_reg, scratch);
4186 __ b(hs, &miss_force_generic);
4187
4188 __ add(scratch,
4189 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4190 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4191 __ str(value_reg,
4192 MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
4193 __ RecordWrite(scratch,
4194 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
4195 receiver_reg , elements_reg);
4196
4197 // value_reg (r0) is preserved.
4198 // Done.
4199 __ Ret();
4200
4201 __ bind(&miss_force_generic);
4202 Handle<Code> ic =
4203 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4204 __ Jump(ic, RelocInfo::CODE_TARGET);
4205 }
4206
4207
4058 #undef __ 4208 #undef __
4059 4209
4060 } } // namespace v8::internal 4210 } } // namespace v8::internal
4061 4211
4062 #endif // V8_TARGET_ARCH_ARM 4212 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/macro-assembler-arm.cc ('k') | src/builtins.h » ('j') | src/code-stubs.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698