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

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: 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 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 KeyedLoadIC keyed_load_ic(isolate());
Mads Ager (chromium) 2011/05/10 13:38:06 Isn't this called from a KeyedLoadIC instance? Can
danno 2011/05/11 14:20:19 Done.
3094 MaybeObject* maybe_stub =
3095 keyed_load_ic.ComputeMonomorphicBuiltinFastElementStub(
Mads Ager (chromium) 2011/05/10 13:38:06 Are any of these stubs actually builtin? This is t
danno 2011/05/11 14:20:19 Done.
3096 receiver_map->instance_type() == JS_ARRAY_TYPE);
3097 Code* stub;
3098 if (!maybe_stub->To(&stub)) return maybe_stub;
3099 __ DispatchMap(r1,
3100 r2,
3101 Handle<Map>(receiver_map),
3102 Handle<Code>(stub),
3103 false);
Mads Ager (chromium) 2011/05/10 13:38:06 Creating an enum for this would make this call sit
danno 2011/05/11 14:20:19 Really good idea. Mind if I do that in another CL?
3104
3105 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3106 __ Jump(ic, RelocInfo::CODE_TARGET);
3107
3108 // Return the generated code.
3109 return GetCode(NORMAL, NULL);
3110 }
3111
3112
3113 MaybeObject* KeyedLoadStubCompiler::CompileLoadMegamorphic(
3114 MapList* receiver_maps,
3115 CodeList* handler_ics) {
3088 // ----------- S t a t e ------------- 3116 // ----------- S t a t e -------------
3089 // -- lr : return address 3117 // -- lr : return address
3090 // -- r0 : key 3118 // -- r0 : key
3091 // -- r1 : receiver 3119 // -- r1 : receiver
3092 // ----------------------------------- 3120 // -----------------------------------
3093 Label miss; 3121 Label miss;
3122 __ JumpIfSmi(r1, &miss);
3094 3123
3095 // Check that the receiver isn't a smi. 3124 int receiver_count = receiver_maps->length();
3096 __ tst(r1, Operand(kSmiTagMask)); 3125 for (int current = 0; current < receiver_count; ++current) {
3097 __ b(eq, &miss); 3126 // Check map and tail call if there's a match
3098 3127 __ DispatchMap(r1,
3099 // Check that the map matches. 3128 r2,
3100 __ ldr(r2, FieldMemOperand(r1, HeapObject::kMapOffset)); 3129 Handle<Map>(receiver_maps->at(current)),
3101 __ cmp(r2, Operand(Handle<Map>(receiver->map()))); 3130 Handle<Code>(handler_ics->at(current)),
3102 __ b(ne, &miss); 3131 true);
3103 3132 }
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 3133
3128 __ bind(&miss); 3134 __ bind(&miss);
3129 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3135 Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss();
3136 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3130 3137
3131 // Return the generated code. 3138 // Return the generated code.
3132 return GetCode(NORMAL, NULL); 3139 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3133 } 3140 }
3134 3141
3135 3142
3136 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 3143 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
3137 int index, 3144 int index,
3138 Map* transition, 3145 Map* transition,
3139 String* name) { 3146 String* name) {
3140 // ----------- S t a t e ------------- 3147 // ----------- S t a t e -------------
3141 // -- r0 : value 3148 // -- r0 : value
3142 // -- r1 : name 3149 // -- r1 : name
(...skipping 21 matching lines...) Expand all
3164 3171
3165 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4); 3172 __ DecrementCounter(counters->keyed_store_field(), 1, r3, r4);
3166 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3173 Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss();
3167 __ Jump(ic, RelocInfo::CODE_TARGET); 3174 __ Jump(ic, RelocInfo::CODE_TARGET);
3168 3175
3169 // Return the generated code. 3176 // Return the generated code.
3170 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name); 3177 return GetCode(transition == NULL ? FIELD : MAP_TRANSITION, name);
3171 } 3178 }
3172 3179
3173 3180
3174 MaybeObject* KeyedStoreStubCompiler::CompileStoreSpecialized( 3181 MaybeObject* KeyedStoreStubCompiler::CompileStoreFastElement(
3175 JSObject* receiver) { 3182 Map* receiver_map) {
3176 // ----------- S t a t e ------------- 3183 // ----------- S t a t e -------------
3177 // -- r0 : value 3184 // -- r0 : value
3178 // -- r1 : key 3185 // -- r1 : key
3179 // -- r2 : receiver 3186 // -- r2 : receiver
3180 // -- lr : return address 3187 // -- lr : return address
3181 // -- r3 : scratch 3188 // -- r3 : scratch
3182 // -- r4 : scratch (elements)
3183 // ----------------------------------- 3189 // -----------------------------------
3184 Label miss; 3190 KeyedStoreIC keyed_store_ic(isolate());
Mads Ager (chromium) 2011/05/10 13:38:06 I would prefer passing in the actual stub here and
danno 2011/05/11 14:20:19 Done.
3191 MaybeObject* maybe_stub =
3192 keyed_store_ic.ComputeMonomorphicBuiltinFastElementStub(
3193 receiver_map->instance_type() == JS_ARRAY_TYPE);
3194 Code* stub;
3195 if (!maybe_stub->To(&stub)) return maybe_stub;
3196 __ DispatchMap(r2,
3197 r3,
3198 Handle<Map>(receiver_map),
3199 Handle<Code>(stub),
3200 false);
3185 3201
3186 Register value_reg = r0; 3202 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); 3203 __ Jump(ic, RelocInfo::CODE_TARGET);
3238 3204
3239 // Return the generated code. 3205 // Return the generated code.
3240 return GetCode(NORMAL, NULL); 3206 return GetCode(NORMAL, NULL);
3241 } 3207 }
3242 3208
3243 3209
3210 MaybeObject* KeyedStoreStubCompiler::CompileStoreMegamorphic(
3211 MapList* receiver_maps,
3212 CodeList* handler_ics) {
3213 // ----------- S t a t e -------------
3214 // -- r0 : value
3215 // -- r1 : key
3216 // -- r2 : receiver
3217 // -- lr : return address
3218 // -- r3 : scratch
3219 // -----------------------------------
3220 Label miss;
3221 __ JumpIfSmi(r2, &miss);
3222
3223 int receiver_count = receiver_maps->length();
3224 for (int current = 0; current < receiver_count; ++current) {
3225 // Check map and tail call if there's a match
3226 __ DispatchMap(r2,
3227 r3,
3228 Handle<Map>(receiver_maps->at(current)),
3229 Handle<Code>(handler_ics->at(current)),
3230 true);
3231 }
3232
3233 __ bind(&miss);
3234 Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss();
3235 __ Jump(miss_ic, RelocInfo::CODE_TARGET, al);
3236
3237 // Return the generated code.
3238 return GetCode(NORMAL, NULL, MEGAMORPHIC);
3239 }
3240
3241
3244 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3242 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3245 // ----------- S t a t e ------------- 3243 // ----------- S t a t e -------------
3246 // -- r0 : argc 3244 // -- r0 : argc
3247 // -- r1 : constructor 3245 // -- r1 : constructor
3248 // -- lr : return address 3246 // -- lr : return address
3249 // -- [sp] : last argument 3247 // -- [sp] : last argument
3250 // ----------------------------------- 3248 // -----------------------------------
3251 Label generic_stub_call; 3249 Label generic_stub_call;
3252 3250
3253 // Use r7 for holding undefined which is used in several places below. 3251 // 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. 3376 // construction.
3379 __ bind(&generic_stub_call); 3377 __ bind(&generic_stub_call);
3380 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric(); 3378 Handle<Code> code = masm()->isolate()->builtins()->JSConstructStubGeneric();
3381 __ Jump(code, RelocInfo::CODE_TARGET); 3379 __ Jump(code, RelocInfo::CODE_TARGET);
3382 3380
3383 // Return the generated code. 3381 // Return the generated code.
3384 return GetCode(); 3382 return GetCode();
3385 } 3383 }
3386 3384
3387 3385
3386 MaybeObject* ExternalArrayLoadStubCompiler::CompileLoad(
3387 JSObject*receiver, ExternalArrayType array_type) {
3388 // ----------- S t a t e -------------
3389 // -- lr : return address
3390 // -- r0 : key
3391 // -- r1 : receiver
3392 // -----------------------------------
3393 KeyedLoadIC load_ic(isolate());
3394 MaybeObject* maybe_stub =
3395 load_ic.ComputeMonomorphicBuiltinExternalArrayStub(array_type);
3396 Code* stub;
3397 if (!maybe_stub->To(&stub)) return maybe_stub;
3398 __ DispatchMap(r1,
3399 r2,
3400 Handle<Map>(receiver->map()),
3401 Handle<Code>(stub),
3402 false);
3403
3404 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss();
3405 __ Jump(ic, RelocInfo::CODE_TARGET);
3406
3407 // Return the generated code.
3408 return GetCode();
3409 }
3410
3411
3412 MaybeObject* ExternalArrayStoreStubCompiler::CompileStore(
3413 JSObject* receiver, ExternalArrayType array_type) {
3414 // ----------- S t a t e -------------
3415 // -- r0 : value
3416 // -- r1 : name
3417 // -- r2 : receiver
3418 // -- lr : return address
3419 // -----------------------------------
3420 KeyedStoreIC store_ic(isolate());
3421 MaybeObject* maybe_stub =
3422 store_ic.ComputeMonomorphicBuiltinExternalArrayStub(array_type);
3423 Code* stub;
3424 if (!maybe_stub->To(&stub)) return maybe_stub;
3425 __ DispatchMap(r2,
3426 r3,
3427 Handle<Map>(receiver->map()),
3428 Handle<Code>(stub),
3429 false);
3430
3431 Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss();
3432 __ Jump(ic, RelocInfo::CODE_TARGET);
3433
3434 return GetCode();
3435 }
3436
3437
3438 #undef __
3439 #define __ ACCESS_MASM(masm)
3440
3441
3388 static bool IsElementTypeSigned(ExternalArrayType array_type) { 3442 static bool IsElementTypeSigned(ExternalArrayType array_type) {
3389 switch (array_type) { 3443 switch (array_type) {
3390 case kExternalByteArray: 3444 case kExternalByteArray:
3391 case kExternalShortArray: 3445 case kExternalShortArray:
3392 case kExternalIntArray: 3446 case kExternalIntArray:
3393 return true; 3447 return true;
3394 3448
3395 case kExternalUnsignedByteArray: 3449 case kExternalUnsignedByteArray:
3396 case kExternalUnsignedShortArray: 3450 case kExternalUnsignedShortArray:
3397 case kExternalUnsignedIntArray: 3451 case kExternalUnsignedIntArray:
3398 return false; 3452 return false;
3399 3453
3400 default: 3454 default:
3401 UNREACHABLE(); 3455 UNREACHABLE();
3402 return false; 3456 return false;
3403 } 3457 }
3404 } 3458 }
3405 3459
3406 3460
3407 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3461 void KeyedLoadStubCompiler::GenerateLoadExternalArray(
3408 JSObject* receiver_object, 3462 MacroAssembler* masm,
3409 ExternalArrayType array_type, 3463 ExternalArrayType array_type) {
3410 Code::Flags flags) {
3411 // ---------- S t a t e -------------- 3464 // ---------- S t a t e --------------
3412 // -- lr : return address 3465 // -- lr : return address
3413 // -- r0 : key 3466 // -- r0 : key
3414 // -- r1 : receiver 3467 // -- r1 : receiver
3415 // ----------------------------------- 3468 // -----------------------------------
3416 Label slow, failed_allocation; 3469 Label miss_force_generic, slow, failed_allocation;
3417 3470
3418 Register key = r0; 3471 Register key = r0;
3419 Register receiver = r1; 3472 Register receiver = r1;
3420 3473
3421 // Check that the object isn't a smi
3422 __ JumpIfSmi(receiver, &slow);
3423
3424 // Check that the key is a smi. 3474 // Check that the key is a smi.
3425 __ JumpIfNotSmi(key, &slow); 3475 __ 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 3476
3432 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3477 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3433 // r3: elements array 3478 // r3: elements array
3434 3479
3435 // Check that the index is in range. 3480 // Check that the index is in range.
3436 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3481 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3437 __ cmp(ip, Operand(key, ASR, kSmiTagSize)); 3482 __ cmp(ip, Operand(key, ASR, kSmiTagSize));
3438 // Unsigned comparison catches both negative and too-large values. 3483 // Unsigned comparison catches both negative and too-large values.
3439 __ b(lo, &slow); 3484 __ b(lo, &miss_force_generic);
3440 3485
3441 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3486 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3442 // r3: base pointer of external storage 3487 // r3: base pointer of external storage
3443 3488
3444 // We are not untagging smi key and instead work with it 3489 // We are not untagging smi key and instead work with it
3445 // as if it was premultiplied by 2. 3490 // as if it was premultiplied by 2.
3446 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 3491 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
3447 3492
3448 Register value = r2; 3493 Register value = r2;
3449 switch (array_type) { 3494 switch (array_type) {
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
3566 __ b(ne, &box_int_1); 3611 __ b(ne, &box_int_1);
3567 // Tag integer as smi and return it. 3612 // Tag integer as smi and return it.
3568 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3613 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3569 __ Ret(); 3614 __ Ret();
3570 3615
3571 Register hiword = value; // r2. 3616 Register hiword = value; // r2.
3572 Register loword = r3; 3617 Register loword = r3;
3573 3618
3574 __ bind(&box_int_0); 3619 __ bind(&box_int_0);
3575 // Integer does not have leading zeros. 3620 // Integer does not have leading zeros.
3576 GenerateUInt2Double(masm(), hiword, loword, r4, 0); 3621 GenerateUInt2Double(masm, hiword, loword, r4, 0);
3577 __ b(&done); 3622 __ b(&done);
3578 3623
3579 __ bind(&box_int_1); 3624 __ bind(&box_int_1);
3580 // Integer has one leading zero. 3625 // Integer has one leading zero.
3581 GenerateUInt2Double(masm(), hiword, loword, r4, 1); 3626 GenerateUInt2Double(masm, hiword, loword, r4, 1);
3582 3627
3583 3628
3584 __ bind(&done); 3629 __ bind(&done);
3585 // Integer was converted to double in registers hiword:loword. 3630 // Integer was converted to double in registers hiword:loword.
3586 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber 3631 // Wrap it into a HeapNumber. Don't use r0 and r1 as AllocateHeapNumber
3587 // clobbers all registers - also when jumping due to exhausted young 3632 // clobbers all registers - also when jumping due to exhausted young
3588 // space. 3633 // space.
3589 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex); 3634 __ LoadRoot(r6, Heap::kHeapNumberMapRootIndex);
3590 __ AllocateHeapNumber(r4, r5, r7, r6, &slow); 3635 __ AllocateHeapNumber(r4, r5, r7, r6, &slow);
3591 3636
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
3693 3738
3694 } else { 3739 } else {
3695 // Tag integer as smi and return it. 3740 // Tag integer as smi and return it.
3696 __ mov(r0, Operand(value, LSL, kSmiTagSize)); 3741 __ mov(r0, Operand(value, LSL, kSmiTagSize));
3697 __ Ret(); 3742 __ Ret();
3698 } 3743 }
3699 3744
3700 // Slow case, key and receiver still in r0 and r1. 3745 // Slow case, key and receiver still in r0 and r1.
3701 __ bind(&slow); 3746 __ bind(&slow);
3702 __ IncrementCounter( 3747 __ IncrementCounter(
3703 masm()->isolate()->counters()->keyed_load_external_array_slow(), 3748 masm->isolate()->counters()->keyed_load_external_array_slow(),
3704 1, r2, r3); 3749 1, r2, r3);
3705 3750
3706 // ---------- S t a t e -------------- 3751 // ---------- S t a t e --------------
3707 // -- lr : return address 3752 // -- lr : return address
3708 // -- r0 : key 3753 // -- r0 : key
3709 // -- r1 : receiver 3754 // -- r1 : receiver
3710 // ----------------------------------- 3755 // -----------------------------------
3711 3756
3712 __ Push(r1, r0); 3757 __ Push(r1, r0);
3713 3758
3714 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3759 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3715 3760
3716 return GetCode(flags); 3761 __ bind(&miss_force_generic);
3762 Code* stub = masm->isolate()->builtins()->builtin(
3763 Builtins::kKeyedLoadIC_MissForceGeneric);
3764 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
3717 } 3765 }
3718 3766
3719 3767
3720 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3768 void KeyedStoreStubCompiler::GenerateStoreExternalArray(
3721 JSObject* receiver_object, 3769 MacroAssembler* masm,
3722 ExternalArrayType array_type, 3770 ExternalArrayType array_type) {
3723 Code::Flags flags) {
3724 // ---------- S t a t e -------------- 3771 // ---------- S t a t e --------------
3725 // -- r0 : value 3772 // -- r0 : value
3726 // -- r1 : key 3773 // -- r1 : key
3727 // -- r2 : receiver 3774 // -- r2 : receiver
3728 // -- lr : return address 3775 // -- lr : return address
3729 // ----------------------------------- 3776 // -----------------------------------
3730 Label slow, check_heap_number; 3777 Label slow, check_heap_number, miss_force_generic;
3731 3778
3732 // Register usage. 3779 // Register usage.
3733 Register value = r0; 3780 Register value = r0;
3734 Register key = r1; 3781 Register key = r1;
3735 Register receiver = r2; 3782 Register receiver = r2;
3736 // r3 mostly holds the elements array or the destination external array. 3783 // r3 mostly holds the elements array or the destination external array.
3737 3784
3738 // Check that the object isn't a smi.
3739 __ JumpIfSmi(receiver, &slow);
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
3746 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3785 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
Mads Ager (chromium) 2011/05/10 13:38:06 Have you always checked that the receiver is not a
danno 2011/05/11 14:20:19 Yes, this stub is always tail-called by other stub
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 // Check that the key is a smi.
4111 __ tst(r0, Operand(kSmiTagMask));
4112 __ b(ne, &miss_force_generic);
4113
4114 // Get the elements array.
4115 __ ldr(r2, FieldMemOperand(r1, JSObject::kElementsOffset));
4116 __ AssertFastElements(r2);
4117
4118 // Check that the key is within bounds.
4119 __ ldr(r3, FieldMemOperand(r2, FixedArray::kLengthOffset));
4120 __ cmp(r0, Operand(r3));
4121 __ b(hs, &miss_force_generic);
4122
4123 // Load the result and make sure it's not the hole.
4124 __ add(r3, r2, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4125 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4126 __ ldr(r4,
4127 MemOperand(r3, r0, LSL, kPointerSizeLog2 - kSmiTagSize));
4128 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
4129 __ cmp(r4, ip);
4130 __ b(eq, &miss_force_generic);
4131 __ mov(r0, r4);
4132 __ Ret();
4133
4134 __ bind(&miss_force_generic);
4135 Code* stub = masm->isolate()->builtins()->builtin(
4136 Builtins::kKeyedLoadIC_MissForceGeneric);
4137 __ Jump(Handle<Code>(stub), RelocInfo::CODE_TARGET);
4138 }
4139
4140
4141 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm,
4142 bool is_js_array) {
4143 // ----------- S t a t e -------------
4144 // -- r0 : value
4145 // -- r1 : key
4146 // -- r2 : receiver
4147 // -- lr : return address
4148 // -- r3 : scratch
4149 // -- r4 : scratch (elements)
4150 // -----------------------------------
4151 Label miss_force_generic;
4152
4153 Register value_reg = r0;
4154 Register key_reg = r1;
4155 Register receiver_reg = r2;
4156 Register scratch = r3;
4157 Register elements_reg = r4;
4158
4159 // Check that the key is a smi.
4160 __ tst(key_reg, Operand(kSmiTagMask));
4161 __ b(ne, &miss_force_generic);
4162
4163 // Get the elements array and make sure it is a fast element array, not 'cow'.
4164 __ ldr(elements_reg,
4165 FieldMemOperand(receiver_reg, JSObject::kElementsOffset));
4166 __ ldr(scratch, FieldMemOperand(elements_reg, HeapObject::kMapOffset));
4167 Handle<Map> map =
4168 Handle<Map>(masm->isolate()->factory()->fixed_array_map());
4169 __ cmp(scratch, Operand(map));
4170 __ b(ne, &miss_force_generic);
4171
4172 // Check that the key is within bounds.
4173 if (is_js_array) {
4174 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset));
4175 } else {
4176 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset));
4177 }
4178 // Compare smis.
4179 __ cmp(key_reg, scratch);
4180 __ b(hs, &miss_force_generic);
4181
4182 __ add(scratch,
4183 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag));
4184 ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2);
4185 __ str(value_reg,
4186 MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize));
4187 __ RecordWrite(scratch,
4188 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize),
4189 receiver_reg , elements_reg);
4190
4191 // value_reg (r0) is preserved.
4192 // Done.
4193 __ Ret();
4194
4195 __ bind(&miss_force_generic);
4196 Handle<Code> ic =
4197 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
4198 __ Jump(ic, RelocInfo::CODE_TARGET);
4199 }
4200
4201
4058 #undef __ 4202 #undef __
4059 4203
4060 } } // namespace v8::internal 4204 } } // namespace v8::internal
4061 4205
4062 #endif // V8_TARGET_ARCH_ARM 4206 #endif // V8_TARGET_ARCH_ARM
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698