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

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

Powered by Google App Engine
This is Rietveld 408576698