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

Side by Side Diff: src/arm/stub-cache-arm.cc

Issue 6697023: Merge 6800:7180 from the bleeding edge branch to the experimental/gc branch. (Closed) Base URL: http://v8.googlecode.com/svn/branches/experimental/gc/
Patch Set: Created 9 years, 9 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/simulator-arm.cc ('k') | src/arm/virtual-frame-arm.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 2006-2009 the V8 project authors. All rights reserved. 1 // Copyright 2006-2009 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 641 matching lines...) Expand 10 before | Expand all | Expand 10 after
652 __ mov(ip, Operand(argc)); 652 __ mov(ip, Operand(argc));
653 __ str(ip, MemOperand(r0, 2 * kPointerSize)); 653 __ str(ip, MemOperand(r0, 2 * kPointerSize));
654 // v8::Arguments::is_construct_call = 0 654 // v8::Arguments::is_construct_call = 0
655 __ mov(ip, Operand(0)); 655 __ mov(ip, Operand(0));
656 __ str(ip, MemOperand(r0, 3 * kPointerSize)); 656 __ str(ip, MemOperand(r0, 3 * kPointerSize));
657 657
658 // Emitting a stub call may try to allocate (if the code is not 658 // Emitting a stub call may try to allocate (if the code is not
659 // already generated). Do not allow the assembler to perform a 659 // already generated). Do not allow the assembler to perform a
660 // garbage collection but instead return the allocation failure 660 // garbage collection but instead return the allocation failure
661 // object. 661 // object.
662 MaybeObject* result = masm->TryCallApiFunctionAndReturn( 662 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1;
663 &fun, argc + kFastApiCallArguments + 1); 663 ExternalReference ref =
664 if (result->IsFailure()) { 664 ExternalReference(&fun, ExternalReference::DIRECT_API_CALL);
665 return result; 665 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
666 }
667 return Heap::undefined_value();
668 } 666 }
669 667
670 class CallInterceptorCompiler BASE_EMBEDDED { 668 class CallInterceptorCompiler BASE_EMBEDDED {
671 public: 669 public:
672 CallInterceptorCompiler(StubCompiler* stub_compiler, 670 CallInterceptorCompiler(StubCompiler* stub_compiler,
673 const ParameterCount& arguments, 671 const ParameterCount& arguments,
674 Register name) 672 Register name)
675 : stub_compiler_(stub_compiler), 673 : stub_compiler_(stub_compiler),
676 arguments_(arguments), 674 arguments_(arguments),
677 name_(name) {} 675 name_(name) {}
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after
1242 Label* miss) { 1240 Label* miss) {
1243 // Check that the receiver isn't a smi. 1241 // Check that the receiver isn't a smi.
1244 __ tst(receiver, Operand(kSmiTagMask)); 1242 __ tst(receiver, Operand(kSmiTagMask));
1245 __ b(eq, miss); 1243 __ b(eq, miss);
1246 1244
1247 // Check that the maps haven't changed. 1245 // Check that the maps haven't changed.
1248 Register reg = 1246 Register reg =
1249 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3, 1247 CheckPrototypes(object, receiver, holder, scratch1, scratch2, scratch3,
1250 name, miss); 1248 name, miss);
1251 1249
1252 // Push the arguments on the JS stack of the caller. 1250 // Build AccessorInfo::args_ list on the stack and push property name below
1253 __ push(receiver); // Receiver. 1251 // the exit frame to make GC aware of them and store pointers to them.
1254 __ mov(scratch3, Operand(Handle<AccessorInfo>(callback))); // callback data 1252 __ push(receiver);
1255 __ ldr(ip, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); 1253 __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_
1256 __ Push(reg, ip, scratch3, name_reg); 1254 Handle<AccessorInfo> callback_handle(callback);
1255 if (Heap::InNewSpace(callback_handle->data())) {
1256 __ Move(scratch3, callback_handle);
1257 __ ldr(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset));
1258 } else {
1259 __ Move(scratch3, Handle<Object>(callback_handle->data()));
1260 }
1261 __ Push(reg, scratch3, name_reg);
1262 __ mov(r0, sp); // r0 = Handle<String>
1257 1263
1258 // Do tail-call to the runtime system. 1264 Address getter_address = v8::ToCData<Address>(callback->getter());
1259 ExternalReference load_callback_property = 1265 ApiFunction fun(getter_address);
1260 ExternalReference(IC_Utility(IC::kLoadCallbackProperty));
1261 __ TailCallExternalReference(load_callback_property, 5, 1);
1262 1266
1263 return Heap::undefined_value(); // Success. 1267 const int kApiStackSpace = 1;
1268 __ EnterExitFrame(false, kApiStackSpace);
1269 // Create AccessorInfo instance on the stack above the exit frame with
1270 // scratch2 (internal::Object **args_) as the data.
1271 __ str(scratch2, MemOperand(sp, 1 * kPointerSize));
1272 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo&
1273
1274 // Emitting a stub call may try to allocate (if the code is not
1275 // already generated). Do not allow the assembler to perform a
1276 // garbage collection but instead return the allocation failure
1277 // object.
1278 const int kStackUnwindSpace = 4;
1279 ExternalReference ref =
1280 ExternalReference(&fun, ExternalReference::DIRECT_GETTER_CALL);
1281 return masm()->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace);
1264 } 1282 }
1265 1283
1266 1284
1267 void StubCompiler::GenerateLoadInterceptor(JSObject* object, 1285 void StubCompiler::GenerateLoadInterceptor(JSObject* object,
1268 JSObject* interceptor_holder, 1286 JSObject* interceptor_holder,
1269 LookupResult* lookup, 1287 LookupResult* lookup,
1270 Register receiver, 1288 Register receiver,
1271 Register name_reg, 1289 Register name_reg,
1272 Register scratch1, 1290 Register scratch1,
1273 Register scratch2, 1291 Register scratch2,
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after
2336 // Patch the receiver on the stack with the global proxy if 2354 // Patch the receiver on the stack with the global proxy if
2337 // necessary. 2355 // necessary.
2338 if (object->IsGlobalObject()) { 2356 if (object->IsGlobalObject()) {
2339 ASSERT(depth == kInvalidProtoDepth); 2357 ASSERT(depth == kInvalidProtoDepth);
2340 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset)); 2358 __ ldr(r3, FieldMemOperand(r1, GlobalObject::kGlobalReceiverOffset));
2341 __ str(r3, MemOperand(sp, argc * kPointerSize)); 2359 __ str(r3, MemOperand(sp, argc * kPointerSize));
2342 } 2360 }
2343 break; 2361 break;
2344 2362
2345 case STRING_CHECK: 2363 case STRING_CHECK:
2346 if (!function->IsBuiltin()) { 2364 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2347 // Calling non-builtins with a value as receiver requires boxing. 2365 // Calling non-strict non-builtins with a value as the receiver
2366 // requires boxing.
2348 __ jmp(&miss); 2367 __ jmp(&miss);
2349 } else { 2368 } else {
2350 // Check that the object is a two-byte string or a symbol. 2369 // Check that the object is a two-byte string or a symbol.
2351 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE); 2370 __ CompareObjectType(r1, r3, r3, FIRST_NONSTRING_TYPE);
2352 __ b(hs, &miss); 2371 __ b(hs, &miss);
2353 // Check that the maps starting from the prototype haven't changed. 2372 // Check that the maps starting from the prototype haven't changed.
2354 GenerateDirectLoadGlobalFunctionPrototype( 2373 GenerateDirectLoadGlobalFunctionPrototype(
2355 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss); 2374 masm(), Context::STRING_FUNCTION_INDEX, r0, &miss);
2356 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 2375 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
2357 r1, r4, name, &miss); 2376 r1, r4, name, &miss);
2358 } 2377 }
2359 break; 2378 break;
2360 2379
2361 case NUMBER_CHECK: { 2380 case NUMBER_CHECK: {
2362 if (!function->IsBuiltin()) { 2381 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2363 // Calling non-builtins with a value as receiver requires boxing. 2382 // Calling non-strict non-builtins with a value as the receiver
2383 // requires boxing.
2364 __ jmp(&miss); 2384 __ jmp(&miss);
2365 } else { 2385 } else {
2366 Label fast; 2386 Label fast;
2367 // Check that the object is a smi or a heap number. 2387 // Check that the object is a smi or a heap number.
2368 __ tst(r1, Operand(kSmiTagMask)); 2388 __ tst(r1, Operand(kSmiTagMask));
2369 __ b(eq, &fast); 2389 __ b(eq, &fast);
2370 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE); 2390 __ CompareObjectType(r1, r0, r0, HEAP_NUMBER_TYPE);
2371 __ b(ne, &miss); 2391 __ b(ne, &miss);
2372 __ bind(&fast); 2392 __ bind(&fast);
2373 // Check that the maps starting from the prototype haven't changed. 2393 // Check that the maps starting from the prototype haven't changed.
2374 GenerateDirectLoadGlobalFunctionPrototype( 2394 GenerateDirectLoadGlobalFunctionPrototype(
2375 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss); 2395 masm(), Context::NUMBER_FUNCTION_INDEX, r0, &miss);
2376 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3, 2396 CheckPrototypes(JSObject::cast(object->GetPrototype()), r0, holder, r3,
2377 r1, r4, name, &miss); 2397 r1, r4, name, &miss);
2378 } 2398 }
2379 break; 2399 break;
2380 } 2400 }
2381 2401
2382 case BOOLEAN_CHECK: { 2402 case BOOLEAN_CHECK: {
2383 if (!function->IsBuiltin()) { 2403 if (!function->IsBuiltin() && !function_info->strict_mode()) {
2384 // Calling non-builtins with a value as receiver requires boxing. 2404 // Calling non-strict non-builtins with a value as the receiver
2405 // requires boxing.
2385 __ jmp(&miss); 2406 __ jmp(&miss);
2386 } else { 2407 } else {
2387 Label fast; 2408 Label fast;
2388 // Check that the object is a boolean. 2409 // Check that the object is a boolean.
2389 __ LoadRoot(ip, Heap::kTrueValueRootIndex); 2410 __ LoadRoot(ip, Heap::kTrueValueRootIndex);
2390 __ cmp(r1, ip); 2411 __ cmp(r1, ip);
2391 __ b(eq, &fast); 2412 __ b(eq, &fast);
2392 __ LoadRoot(ip, Heap::kFalseValueRootIndex); 2413 __ LoadRoot(ip, Heap::kFalseValueRootIndex);
2393 __ cmp(r1, ip); 2414 __ cmp(r1, ip);
2394 __ b(ne, &miss); 2415 __ b(ne, &miss);
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
2654 if (receiver->IsJSGlobalProxy()) { 2675 if (receiver->IsJSGlobalProxy()) {
2655 __ CheckAccessGlobalProxy(r1, r3, &miss); 2676 __ CheckAccessGlobalProxy(r1, r3, &miss);
2656 } 2677 }
2657 2678
2658 // Stub is never generated for non-global objects that require access 2679 // Stub is never generated for non-global objects that require access
2659 // checks. 2680 // checks.
2660 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2681 ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded());
2661 2682
2662 __ Push(r1, r2, r0); // Receiver, name, value. 2683 __ Push(r1, r2, r0); // Receiver, name, value.
2663 2684
2685 __ mov(r0, Operand(Smi::FromInt(strict_mode_)));
2686 __ push(r0); // strict mode
2687
2664 // Do tail-call to the runtime system. 2688 // Do tail-call to the runtime system.
2665 ExternalReference store_ic_property = 2689 ExternalReference store_ic_property =
2666 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty)); 2690 ExternalReference(IC_Utility(IC::kStoreInterceptorProperty));
2667 __ TailCallExternalReference(store_ic_property, 3, 1); 2691 __ TailCallExternalReference(store_ic_property, 4, 1);
2668 2692
2669 // Handle store cache miss. 2693 // Handle store cache miss.
2670 __ bind(&miss); 2694 __ bind(&miss);
2671 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss)); 2695 Handle<Code> ic(Builtins::builtin(Builtins::StoreIC_Miss));
2672 __ Jump(ic, RelocInfo::CODE_TARGET); 2696 __ Jump(ic, RelocInfo::CODE_TARGET);
2673 2697
2674 // Return the generated code. 2698 // Return the generated code.
2675 return GetCode(INTERCEPTOR, name); 2699 return GetCode(INTERCEPTOR, name);
2676 } 2700 }
2677 2701
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after
3123 __ Ret(); 3147 __ Ret();
3124 3148
3125 __ bind(&miss); 3149 __ bind(&miss);
3126 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3150 GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC);
3127 3151
3128 // Return the generated code. 3152 // Return the generated code.
3129 return GetCode(NORMAL, NULL); 3153 return GetCode(NORMAL, NULL);
3130 } 3154 }
3131 3155
3132 3156
3133 MaybeObject* KeyedLoadStubCompiler::CompileLoadPixelArray(JSObject* receiver) {
3134 // ----------- S t a t e -------------
3135 // -- lr : return address
3136 // -- r0 : key
3137 // -- r1 : receiver
3138 // -----------------------------------
3139 Label miss;
3140
3141 // Check that the map matches.
3142 __ CheckMap(r1, r2, Handle<Map>(receiver->map()), &miss, false);
3143
3144 GenerateFastPixelArrayLoad(masm(),
3145 r1,
3146 r0,
3147 r2,
3148 r3,
3149 r4,
3150 r5,
3151 r0,
3152 &miss,
3153 &miss,
3154 &miss);
3155
3156 __ bind(&miss);
3157 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Miss));
3158 __ Jump(ic, RelocInfo::CODE_TARGET);
3159
3160 // Return the generated code.
3161 return GetCode(NORMAL, NULL);
3162 }
3163
3164
3165 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object, 3157 MaybeObject* KeyedStoreStubCompiler::CompileStoreField(JSObject* object,
3166 int index, 3158 int index,
3167 Map* transition, 3159 Map* transition,
3168 String* name) { 3160 String* name) {
3169 // ----------- S t a t e ------------- 3161 // ----------- S t a t e -------------
3170 // -- r0 : value 3162 // -- r0 : value
3171 // -- r1 : name 3163 // -- r1 : name
3172 // -- r2 : receiver 3164 // -- r2 : receiver
3173 // -- lr : return address 3165 // -- lr : return address
3174 // ----------------------------------- 3166 // -----------------------------------
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
3265 3257
3266 __ bind(&miss); 3258 __ bind(&miss);
3267 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss)); 3259 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
3268 __ Jump(ic, RelocInfo::CODE_TARGET); 3260 __ Jump(ic, RelocInfo::CODE_TARGET);
3269 3261
3270 // Return the generated code. 3262 // Return the generated code.
3271 return GetCode(NORMAL, NULL); 3263 return GetCode(NORMAL, NULL);
3272 } 3264 }
3273 3265
3274 3266
3275 MaybeObject* KeyedStoreStubCompiler::CompileStorePixelArray(
3276 JSObject* receiver) {
3277 // ----------- S t a t e -------------
3278 // -- r0 : value
3279 // -- r1 : key
3280 // -- r2 : receiver
3281 // -- r3 : scratch
3282 // -- r4 : scratch
3283 // -- r5 : scratch
3284 // -- r6 : scratch
3285 // -- lr : return address
3286 // -----------------------------------
3287 Label miss;
3288
3289 // Check that the map matches.
3290 __ CheckMap(r2, r6, Handle<Map>(receiver->map()), &miss, false);
3291
3292 GenerateFastPixelArrayStore(masm(),
3293 r2,
3294 r1,
3295 r0,
3296 r3,
3297 r4,
3298 r5,
3299 r6,
3300 true,
3301 true,
3302 &miss,
3303 &miss,
3304 NULL,
3305 &miss);
3306
3307 __ bind(&miss);
3308 Handle<Code> ic(Builtins::builtin(Builtins::KeyedStoreIC_Miss));
3309 __ Jump(ic, RelocInfo::CODE_TARGET);
3310
3311 // Return the generated code.
3312 return GetCode(NORMAL, NULL);
3313 }
3314
3315
3316 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) { 3267 MaybeObject* ConstructStubCompiler::CompileConstructStub(JSFunction* function) {
3317 // ----------- S t a t e ------------- 3268 // ----------- S t a t e -------------
3318 // -- r0 : argc 3269 // -- r0 : argc
3319 // -- r1 : constructor 3270 // -- r1 : constructor
3320 // -- lr : return address 3271 // -- lr : return address
3321 // -- [sp] : last argument 3272 // -- [sp] : last argument
3322 // ----------------------------------- 3273 // -----------------------------------
3323 Label generic_stub_call; 3274 Label generic_stub_call;
3324 3275
3325 // Use r7 for holding undefined which is used in several places below. 3276 // Use r7 for holding undefined which is used in several places below.
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
3470 return false; 3421 return false;
3471 3422
3472 default: 3423 default:
3473 UNREACHABLE(); 3424 UNREACHABLE();
3474 return false; 3425 return false;
3475 } 3426 }
3476 } 3427 }
3477 3428
3478 3429
3479 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub( 3430 MaybeObject* ExternalArrayStubCompiler::CompileKeyedLoadStub(
3480 ExternalArrayType array_type, Code::Flags flags) { 3431 JSObject* receiver_object,
3432 ExternalArrayType array_type,
3433 Code::Flags flags) {
3481 // ---------- S t a t e -------------- 3434 // ---------- S t a t e --------------
3482 // -- lr : return address 3435 // -- lr : return address
3483 // -- r0 : key 3436 // -- r0 : key
3484 // -- r1 : receiver 3437 // -- r1 : receiver
3485 // ----------------------------------- 3438 // -----------------------------------
3486 Label slow, failed_allocation; 3439 Label slow, failed_allocation;
3487 3440
3488 Register key = r0; 3441 Register key = r0;
3489 Register receiver = r1; 3442 Register receiver = r1;
3490 3443
3491 // Check that the object isn't a smi 3444 // Check that the object isn't a smi
3492 __ JumpIfSmi(receiver, &slow); 3445 __ JumpIfSmi(receiver, &slow);
3493 3446
3494 // Check that the key is a smi. 3447 // Check that the key is a smi.
3495 __ JumpIfNotSmi(key, &slow); 3448 __ JumpIfNotSmi(key, &slow);
3496 3449
3497 // Check that the object is a JS object. Load map into r2. 3450 // Make sure that we've got the right map.
3498 __ CompareObjectType(receiver, r2, r3, FIRST_JS_OBJECT_TYPE); 3451 __ ldr(r2, FieldMemOperand(receiver, HeapObject::kMapOffset));
3499 __ b(lt, &slow); 3452 __ cmp(r2, Operand(Handle<Map>(receiver_object->map())));
3500
3501 // Check that the receiver does not require access checks. We need
3502 // to check this explicitly since this generic stub does not perform
3503 // map checks.
3504 __ ldrb(r3, FieldMemOperand(r2, Map::kBitFieldOffset));
3505 __ tst(r3, Operand(1 << Map::kIsAccessCheckNeeded));
3506 __ b(ne, &slow); 3453 __ b(ne, &slow);
3507 3454
3508 // Check that the elements array is the appropriate type of
3509 // ExternalArray.
3510 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3455 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3511 __ ldr(r2, FieldMemOperand(r3, HeapObject::kMapOffset)); 3456 // r3: elements array
3512 __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
3513 __ cmp(r2, ip);
3514 __ b(ne, &slow);
3515 3457
3516 // Check that the index is in range. 3458 // Check that the index is in range.
3517 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3459 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3518 __ cmp(ip, Operand(key, ASR, kSmiTagSize)); 3460 __ cmp(ip, Operand(key, ASR, kSmiTagSize));
3519 // Unsigned comparison catches both negative and too-large values. 3461 // Unsigned comparison catches both negative and too-large values.
3520 __ b(lo, &slow); 3462 __ b(lo, &slow);
3521 3463
3522 // r3: elements array
3523 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3464 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3524 // r3: base pointer of external storage 3465 // r3: base pointer of external storage
3525 3466
3526 // We are not untagging smi key and instead work with it 3467 // We are not untagging smi key and instead work with it
3527 // as if it was premultiplied by 2. 3468 // as if it was premultiplied by 2.
3528 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 3469 ASSERT((kSmiTag == 0) && (kSmiTagSize == 1));
3529 3470
3530 Register value = r2; 3471 Register value = r2;
3531 switch (array_type) { 3472 switch (array_type) {
3532 case kExternalByteArray: 3473 case kExternalByteArray:
3533 __ ldrsb(value, MemOperand(r3, key, LSR, 1)); 3474 __ ldrsb(value, MemOperand(r3, key, LSR, 1));
3534 break; 3475 break;
3476 case kExternalPixelArray:
3535 case kExternalUnsignedByteArray: 3477 case kExternalUnsignedByteArray:
3536 __ ldrb(value, MemOperand(r3, key, LSR, 1)); 3478 __ ldrb(value, MemOperand(r3, key, LSR, 1));
3537 break; 3479 break;
3538 case kExternalShortArray: 3480 case kExternalShortArray:
3539 __ ldrsh(value, MemOperand(r3, key, LSL, 0)); 3481 __ ldrsh(value, MemOperand(r3, key, LSL, 0));
3540 break; 3482 break;
3541 case kExternalUnsignedShortArray: 3483 case kExternalUnsignedShortArray:
3542 __ ldrh(value, MemOperand(r3, key, LSL, 0)); 3484 __ ldrh(value, MemOperand(r3, key, LSL, 0));
3543 break; 3485 break;
3544 case kExternalIntArray: 3486 case kExternalIntArray:
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
3750 3692
3751 __ Push(r1, r0); 3693 __ Push(r1, r0);
3752 3694
3753 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3695 __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1);
3754 3696
3755 return GetCode(flags); 3697 return GetCode(flags);
3756 } 3698 }
3757 3699
3758 3700
3759 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub( 3701 MaybeObject* ExternalArrayStubCompiler::CompileKeyedStoreStub(
3760 ExternalArrayType array_type, Code::Flags flags) { 3702 JSObject* receiver_object,
3703 ExternalArrayType array_type,
3704 Code::Flags flags) {
3761 // ---------- S t a t e -------------- 3705 // ---------- S t a t e --------------
3762 // -- r0 : value 3706 // -- r0 : value
3763 // -- r1 : key 3707 // -- r1 : key
3764 // -- r2 : receiver 3708 // -- r2 : receiver
3765 // -- lr : return address 3709 // -- lr : return address
3766 // ----------------------------------- 3710 // -----------------------------------
3767 Label slow, check_heap_number; 3711 Label slow, check_heap_number;
3768 3712
3769 // Register usage. 3713 // Register usage.
3770 Register value = r0; 3714 Register value = r0;
3771 Register key = r1; 3715 Register key = r1;
3772 Register receiver = r2; 3716 Register receiver = r2;
3773 // r3 mostly holds the elements array or the destination external array. 3717 // r3 mostly holds the elements array or the destination external array.
3774 3718
3775 // Check that the object isn't a smi. 3719 // Check that the object isn't a smi.
3776 __ JumpIfSmi(receiver, &slow); 3720 __ JumpIfSmi(receiver, &slow);
3777 3721
3778 // Check that the object is a JS object. Load map into r3. 3722 // Make sure that we've got the right map.
3779 __ CompareObjectType(receiver, r3, r4, FIRST_JS_OBJECT_TYPE); 3723 __ ldr(r3, FieldMemOperand(receiver, HeapObject::kMapOffset));
3780 __ b(le, &slow); 3724 __ cmp(r3, Operand(Handle<Map>(receiver_object->map())));
3725 __ b(ne, &slow);
3781 3726
3782 // Check that the receiver does not require access checks. We need 3727 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset));
3783 // to do this because this generic stub does not perform map checks.
3784 __ ldrb(ip, FieldMemOperand(r3, Map::kBitFieldOffset));
3785 __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded));
3786 __ b(ne, &slow);
3787 3728
3788 // Check that the key is a smi. 3729 // Check that the key is a smi.
3789 __ JumpIfNotSmi(key, &slow); 3730 __ JumpIfNotSmi(key, &slow);
3790 3731
3791 // Check that the elements array is the appropriate type of ExternalArray. 3732 // Check that the index is in range
3792 __ ldr(r3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3733 __ SmiUntag(r4, key);
3793 __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset));
3794 __ LoadRoot(ip, Heap::RootIndexForExternalArrayType(array_type));
3795 __ cmp(r4, ip);
3796 __ b(ne, &slow);
3797
3798 // Check that the index is in range.
3799 __ mov(r4, Operand(key, ASR, kSmiTagSize)); // Untag the index.
3800 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset)); 3734 __ ldr(ip, FieldMemOperand(r3, ExternalArray::kLengthOffset));
3801 __ cmp(r4, ip); 3735 __ cmp(r4, ip);
3802 // Unsigned comparison catches both negative and too-large values. 3736 // Unsigned comparison catches both negative and too-large values.
3803 __ b(hs, &slow); 3737 __ b(hs, &slow);
3804 3738
3805 // Handle both smis and HeapNumbers in the fast path. Go to the 3739 // Handle both smis and HeapNumbers in the fast path. Go to the
3806 // runtime for all other kinds of values. 3740 // runtime for all other kinds of values.
3807 // r3: external array. 3741 // r3: external array.
3808 // r4: key (integer). 3742 // r4: key (integer).
3809 __ JumpIfNotSmi(value, &check_heap_number); 3743 if (array_type == kExternalPixelArray) {
3810 __ mov(r5, Operand(value, ASR, kSmiTagSize)); // Untag the value. 3744 // Double to pixel conversion is only implemented in the runtime for now.
3745 __ JumpIfNotSmi(value, &slow);
3746 } else {
3747 __ JumpIfNotSmi(value, &check_heap_number);
3748 }
3749 __ SmiUntag(r5, value);
3811 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3750 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3812 3751
3813 // r3: base pointer of external storage. 3752 // r3: base pointer of external storage.
3814 // r4: key (integer). 3753 // r4: key (integer).
3815 // r5: value (integer). 3754 // r5: value (integer).
3816 switch (array_type) { 3755 switch (array_type) {
3756 case kExternalPixelArray:
3757 // Clamp the value to [0..255].
3758 __ Usat(r5, 8, Operand(r5));
3759 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3760 break;
3817 case kExternalByteArray: 3761 case kExternalByteArray:
3818 case kExternalUnsignedByteArray: 3762 case kExternalUnsignedByteArray:
3819 __ strb(r5, MemOperand(r3, r4, LSL, 0)); 3763 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3820 break; 3764 break;
3821 case kExternalShortArray: 3765 case kExternalShortArray:
3822 case kExternalUnsignedShortArray: 3766 case kExternalUnsignedShortArray:
3823 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 3767 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3824 break; 3768 break;
3825 case kExternalIntArray: 3769 case kExternalIntArray:
3826 case kExternalUnsignedIntArray: 3770 case kExternalUnsignedIntArray:
3827 __ str(r5, MemOperand(r3, r4, LSL, 2)); 3771 __ str(r5, MemOperand(r3, r4, LSL, 2));
3828 break; 3772 break;
3829 case kExternalFloatArray: 3773 case kExternalFloatArray:
3830 // Perform int-to-float conversion and store to memory. 3774 // Perform int-to-float conversion and store to memory.
3831 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9); 3775 StoreIntAsFloat(masm(), r3, r4, r5, r6, r7, r9);
3832 break; 3776 break;
3833 default: 3777 default:
3834 UNREACHABLE(); 3778 UNREACHABLE();
3835 break; 3779 break;
3836 } 3780 }
3837 3781
3838 // Entry registers are intact, r0 holds the value which is the return value. 3782 // Entry registers are intact, r0 holds the value which is the return value.
3839 __ Ret(); 3783 __ Ret();
3840 3784
3841 3785 if (array_type != kExternalPixelArray) {
3842 // r3: external array. 3786 // r3: external array.
3843 // r4: index (integer). 3787 // r4: index (integer).
3844 __ bind(&check_heap_number); 3788 __ bind(&check_heap_number);
3845 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE); 3789 __ CompareObjectType(value, r5, r6, HEAP_NUMBER_TYPE);
3846 __ b(ne, &slow); 3790 __ b(ne, &slow);
3847 3791
3848 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset)); 3792 __ ldr(r3, FieldMemOperand(r3, ExternalArray::kExternalPointerOffset));
3849 3793
3850 // r3: base pointer of external storage. 3794 // r3: base pointer of external storage.
3851 // r4: key (integer). 3795 // r4: key (integer).
3852 3796
3853 // The WebGL specification leaves the behavior of storing NaN and 3797 // The WebGL specification leaves the behavior of storing NaN and
3854 // +/-Infinity into integer arrays basically undefined. For more 3798 // +/-Infinity into integer arrays basically undefined. For more
3855 // reproducible behavior, convert these to zero. 3799 // reproducible behavior, convert these to zero.
3856 if (CpuFeatures::IsSupported(VFP3)) { 3800 if (CpuFeatures::IsSupported(VFP3)) {
3857 CpuFeatures::Scope scope(VFP3); 3801 CpuFeatures::Scope scope(VFP3);
3858 3802
3859 3803
3860 if (array_type == kExternalFloatArray) { 3804 if (array_type == kExternalFloatArray) {
3861 // vldr requires offset to be a multiple of 4 so we can not 3805 // vldr requires offset to be a multiple of 4 so we can not
3862 // include -kHeapObjectTag into it. 3806 // include -kHeapObjectTag into it.
3863 __ sub(r5, r0, Operand(kHeapObjectTag)); 3807 __ sub(r5, r0, Operand(kHeapObjectTag));
3864 __ vldr(d0, r5, HeapNumber::kValueOffset); 3808 __ vldr(d0, r5, HeapNumber::kValueOffset);
3865 __ add(r5, r3, Operand(r4, LSL, 2)); 3809 __ add(r5, r3, Operand(r4, LSL, 2));
3866 __ vcvt_f32_f64(s0, d0); 3810 __ vcvt_f32_f64(s0, d0);
3867 __ vstr(s0, r5, 0); 3811 __ vstr(s0, r5, 0);
3868 } else {
3869 // Need to perform float-to-int conversion.
3870 // Test for NaN or infinity (both give zero).
3871 __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
3872
3873 // Hoisted load. vldr requires offset to be a multiple of 4 so we can not
3874 // include -kHeapObjectTag into it.
3875 __ sub(r5, value, Operand(kHeapObjectTag));
3876 __ vldr(d0, r5, HeapNumber::kValueOffset);
3877
3878 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
3879 // NaNs and Infinities have all-one exponents so they sign extend to -1.
3880 __ cmp(r6, Operand(-1));
3881 __ mov(r5, Operand(0), LeaveCC, eq);
3882
3883 // Not infinity or NaN simply convert to int.
3884 if (IsElementTypeSigned(array_type)) {
3885 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
3886 } else { 3812 } else {
3887 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne); 3813 // Need to perform float-to-int conversion.
3814 // Test for NaN or infinity (both give zero).
3815 __ ldr(r6, FieldMemOperand(value, HeapNumber::kExponentOffset));
3816
3817 // Hoisted load. vldr requires offset to be a multiple of 4 so we can
3818 // not include -kHeapObjectTag into it.
3819 __ sub(r5, value, Operand(kHeapObjectTag));
3820 __ vldr(d0, r5, HeapNumber::kValueOffset);
3821
3822 __ Sbfx(r6, r6, HeapNumber::kExponentShift, HeapNumber::kExponentBits);
3823 // NaNs and Infinities have all-one exponents so they sign extend to -1.
3824 __ cmp(r6, Operand(-1));
3825 __ mov(r5, Operand(0), LeaveCC, eq);
3826
3827 // Not infinity or NaN simply convert to int.
3828 if (IsElementTypeSigned(array_type)) {
3829 __ vcvt_s32_f64(s0, d0, kDefaultRoundToZero, ne);
3830 } else {
3831 __ vcvt_u32_f64(s0, d0, kDefaultRoundToZero, ne);
3832 }
3833 __ vmov(r5, s0, ne);
3834
3835 switch (array_type) {
3836 case kExternalByteArray:
3837 case kExternalUnsignedByteArray:
3838 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3839 break;
3840 case kExternalShortArray:
3841 case kExternalUnsignedShortArray:
3842 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3843 break;
3844 case kExternalIntArray:
3845 case kExternalUnsignedIntArray:
3846 __ str(r5, MemOperand(r3, r4, LSL, 2));
3847 break;
3848 default:
3849 UNREACHABLE();
3850 break;
3851 }
3888 } 3852 }
3889 __ vmov(r5, s0, ne); 3853
3890
3891 switch (array_type) {
3892 case kExternalByteArray:
3893 case kExternalUnsignedByteArray:
3894 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3895 break;
3896 case kExternalShortArray:
3897 case kExternalUnsignedShortArray:
3898 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3899 break;
3900 case kExternalIntArray:
3901 case kExternalUnsignedIntArray:
3902 __ str(r5, MemOperand(r3, r4, LSL, 2));
3903 break;
3904 default:
3905 UNREACHABLE();
3906 break;
3907 }
3908 }
3909
3910 // Entry registers are intact, r0 holds the value which is the return value.
3911 __ Ret();
3912 } else {
3913 // VFP3 is not available do manual conversions.
3914 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
3915 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
3916
3917 if (array_type == kExternalFloatArray) {
3918 Label done, nan_or_infinity_or_zero;
3919 static const int kMantissaInHiWordShift =
3920 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
3921
3922 static const int kMantissaInLoWordShift =
3923 kBitsPerInt - kMantissaInHiWordShift;
3924
3925 // Test for all special exponent values: zeros, subnormal numbers, NaNs
3926 // and infinities. All these should be converted to 0.
3927 __ mov(r7, Operand(HeapNumber::kExponentMask));
3928 __ and_(r9, r5, Operand(r7), SetCC);
3929 __ b(eq, &nan_or_infinity_or_zero);
3930
3931 __ teq(r9, Operand(r7));
3932 __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
3933 __ b(eq, &nan_or_infinity_or_zero);
3934
3935 // Rebias exponent.
3936 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
3937 __ add(r9,
3938 r9,
3939 Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
3940
3941 __ cmp(r9, Operand(kBinary32MaxExponent));
3942 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
3943 __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
3944 __ b(gt, &done);
3945
3946 __ cmp(r9, Operand(kBinary32MinExponent));
3947 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
3948 __ b(lt, &done);
3949
3950 __ and_(r7, r5, Operand(HeapNumber::kSignMask));
3951 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
3952 __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
3953 __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
3954 __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
3955
3956 __ bind(&done);
3957 __ str(r5, MemOperand(r3, r4, LSL, 2));
3958 // Entry registers are intact, r0 holds the value which is the return 3854 // Entry registers are intact, r0 holds the value which is the return
3959 // value. 3855 // value.
3960 __ Ret(); 3856 __ Ret();
3961
3962 __ bind(&nan_or_infinity_or_zero);
3963 __ and_(r7, r5, Operand(HeapNumber::kSignMask));
3964 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
3965 __ orr(r9, r9, r7);
3966 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
3967 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
3968 __ b(&done);
3969 } else { 3857 } else {
3970 bool is_signed_type = IsElementTypeSigned(array_type); 3858 // VFP3 is not available do manual conversions.
3971 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; 3859 __ ldr(r5, FieldMemOperand(value, HeapNumber::kExponentOffset));
3972 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; 3860 __ ldr(r6, FieldMemOperand(value, HeapNumber::kMantissaOffset));
3973 3861
3974 Label done, sign; 3862 if (array_type == kExternalFloatArray) {
3975 3863 Label done, nan_or_infinity_or_zero;
3976 // Test for all special exponent values: zeros, subnormal numbers, NaNs 3864 static const int kMantissaInHiWordShift =
3977 // and infinities. All these should be converted to 0. 3865 kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord;
3978 __ mov(r7, Operand(HeapNumber::kExponentMask)); 3866
3979 __ and_(r9, r5, Operand(r7), SetCC); 3867 static const int kMantissaInLoWordShift =
3980 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 3868 kBitsPerInt - kMantissaInHiWordShift;
3981 __ b(eq, &done); 3869
3982 3870 // Test for all special exponent values: zeros, subnormal numbers, NaNs
3983 __ teq(r9, Operand(r7)); 3871 // and infinities. All these should be converted to 0.
3984 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq); 3872 __ mov(r7, Operand(HeapNumber::kExponentMask));
3985 __ b(eq, &done); 3873 __ and_(r9, r5, Operand(r7), SetCC);
3986 3874 __ b(eq, &nan_or_infinity_or_zero);
3987 // Unbias exponent. 3875
3988 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift)); 3876 __ teq(r9, Operand(r7));
3989 __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC); 3877 __ mov(r9, Operand(kBinary32ExponentMask), LeaveCC, eq);
3990 // If exponent is negative then result is 0. 3878 __ b(eq, &nan_or_infinity_or_zero);
3991 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi); 3879
3992 __ b(mi, &done); 3880 // Rebias exponent.
3993 3881 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
3994 // If exponent is too big then result is minimal value. 3882 __ add(r9,
3995 __ cmp(r9, Operand(meaningfull_bits - 1)); 3883 r9,
3996 __ mov(r5, Operand(min_value), LeaveCC, ge); 3884 Operand(kBinary32ExponentBias - HeapNumber::kExponentBias));
3997 __ b(ge, &done); 3885
3998 3886 __ cmp(r9, Operand(kBinary32MaxExponent));
3999 __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC); 3887 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, gt);
4000 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask)); 3888 __ orr(r5, r5, Operand(kBinary32ExponentMask), LeaveCC, gt);
4001 __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); 3889 __ b(gt, &done);
4002 3890
4003 __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC); 3891 __ cmp(r9, Operand(kBinary32MinExponent));
4004 __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl); 3892 __ and_(r5, r5, Operand(HeapNumber::kSignMask), LeaveCC, lt);
4005 __ b(pl, &sign); 3893 __ b(lt, &done);
4006 3894
4007 __ rsb(r9, r9, Operand(0, RelocInfo::NONE)); 3895 __ and_(r7, r5, Operand(HeapNumber::kSignMask));
4008 __ mov(r5, Operand(r5, LSL, r9)); 3896 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
4009 __ rsb(r9, r9, Operand(meaningfull_bits)); 3897 __ orr(r7, r7, Operand(r5, LSL, kMantissaInHiWordShift));
4010 __ orr(r5, r5, Operand(r6, LSR, r9)); 3898 __ orr(r7, r7, Operand(r6, LSR, kMantissaInLoWordShift));
4011 3899 __ orr(r5, r7, Operand(r9, LSL, kBinary32ExponentShift));
4012 __ bind(&sign); 3900
4013 __ teq(r7, Operand(0, RelocInfo::NONE)); 3901 __ bind(&done);
4014 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne); 3902 __ str(r5, MemOperand(r3, r4, LSL, 2));
4015 3903 // Entry registers are intact, r0 holds the value which is the return
4016 __ bind(&done); 3904 // value.
4017 switch (array_type) { 3905 __ Ret();
4018 case kExternalByteArray: 3906
4019 case kExternalUnsignedByteArray: 3907 __ bind(&nan_or_infinity_or_zero);
4020 __ strb(r5, MemOperand(r3, r4, LSL, 0)); 3908 __ and_(r7, r5, Operand(HeapNumber::kSignMask));
4021 break; 3909 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
4022 case kExternalShortArray: 3910 __ orr(r9, r9, r7);
4023 case kExternalUnsignedShortArray: 3911 __ orr(r9, r9, Operand(r5, LSL, kMantissaInHiWordShift));
4024 __ strh(r5, MemOperand(r3, r4, LSL, 1)); 3912 __ orr(r5, r9, Operand(r6, LSR, kMantissaInLoWordShift));
4025 break; 3913 __ b(&done);
4026 case kExternalIntArray: 3914 } else {
4027 case kExternalUnsignedIntArray: 3915 bool is_signed_type = IsElementTypeSigned(array_type);
4028 __ str(r5, MemOperand(r3, r4, LSL, 2)); 3916 int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt;
4029 break; 3917 int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000;
4030 default: 3918
4031 UNREACHABLE(); 3919 Label done, sign;
4032 break; 3920
3921 // Test for all special exponent values: zeros, subnormal numbers, NaNs
3922 // and infinities. All these should be converted to 0.
3923 __ mov(r7, Operand(HeapNumber::kExponentMask));
3924 __ and_(r9, r5, Operand(r7), SetCC);
3925 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
3926 __ b(eq, &done);
3927
3928 __ teq(r9, Operand(r7));
3929 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, eq);
3930 __ b(eq, &done);
3931
3932 // Unbias exponent.
3933 __ mov(r9, Operand(r9, LSR, HeapNumber::kExponentShift));
3934 __ sub(r9, r9, Operand(HeapNumber::kExponentBias), SetCC);
3935 // If exponent is negative then result is 0.
3936 __ mov(r5, Operand(0, RelocInfo::NONE), LeaveCC, mi);
3937 __ b(mi, &done);
3938
3939 // If exponent is too big then result is minimal value.
3940 __ cmp(r9, Operand(meaningfull_bits - 1));
3941 __ mov(r5, Operand(min_value), LeaveCC, ge);
3942 __ b(ge, &done);
3943
3944 __ and_(r7, r5, Operand(HeapNumber::kSignMask), SetCC);
3945 __ and_(r5, r5, Operand(HeapNumber::kMantissaMask));
3946 __ orr(r5, r5, Operand(1u << HeapNumber::kMantissaBitsInTopWord));
3947
3948 __ rsb(r9, r9, Operand(HeapNumber::kMantissaBitsInTopWord), SetCC);
3949 __ mov(r5, Operand(r5, LSR, r9), LeaveCC, pl);
3950 __ b(pl, &sign);
3951
3952 __ rsb(r9, r9, Operand(0, RelocInfo::NONE));
3953 __ mov(r5, Operand(r5, LSL, r9));
3954 __ rsb(r9, r9, Operand(meaningfull_bits));
3955 __ orr(r5, r5, Operand(r6, LSR, r9));
3956
3957 __ bind(&sign);
3958 __ teq(r7, Operand(0, RelocInfo::NONE));
3959 __ rsb(r5, r5, Operand(0, RelocInfo::NONE), LeaveCC, ne);
3960
3961 __ bind(&done);
3962 switch (array_type) {
3963 case kExternalByteArray:
3964 case kExternalUnsignedByteArray:
3965 __ strb(r5, MemOperand(r3, r4, LSL, 0));
3966 break;
3967 case kExternalShortArray:
3968 case kExternalUnsignedShortArray:
3969 __ strh(r5, MemOperand(r3, r4, LSL, 1));
3970 break;
3971 case kExternalIntArray:
3972 case kExternalUnsignedIntArray:
3973 __ str(r5, MemOperand(r3, r4, LSL, 2));
3974 break;
3975 default:
3976 UNREACHABLE();
3977 break;
3978 }
4033 } 3979 }
4034 } 3980 }
4035 } 3981 }
4036 3982
4037 // Slow case: call runtime. 3983 // Slow case: call runtime.
4038 __ bind(&slow); 3984 __ bind(&slow);
4039 3985
4040 // Entry registers are intact. 3986 // Entry registers are intact.
4041 // ---------- S t a t e -------------- 3987 // ---------- S t a t e --------------
4042 // -- r0 : value 3988 // -- r0 : value
4043 // -- r1 : key 3989 // -- r1 : key
4044 // -- r2 : receiver 3990 // -- r2 : receiver
4045 // -- lr : return address 3991 // -- lr : return address
4046 // ----------------------------------- 3992 // -----------------------------------
4047 3993
4048 // Push receiver, key and value for runtime call. 3994 // Push receiver, key and value for runtime call.
4049 __ Push(r2, r1, r0); 3995 __ Push(r2, r1, r0);
4050 3996
4051 __ TailCallRuntime(Runtime::kSetProperty, 3, 1); 3997 __ mov(r1, Operand(Smi::FromInt(NONE))); // PropertyAttributes
3998 __ mov(r0, Operand(Smi::FromInt(
3999 Code::ExtractExtraICStateFromFlags(flags) & kStrictMode)));
4000 __ Push(r1, r0);
4001
4002 __ TailCallRuntime(Runtime::kSetProperty, 5, 1);
4052 4003
4053 return GetCode(flags); 4004 return GetCode(flags);
4054 } 4005 }
4055 4006
4056 4007
4057 #undef __ 4008 #undef __
4058 4009
4059 } } // namespace v8::internal 4010 } } // namespace v8::internal
4060 4011
4061 #endif // V8_TARGET_ARCH_ARM 4012 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/arm/simulator-arm.cc ('k') | src/arm/virtual-frame-arm.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698