OLD | NEW |
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 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 if (index < 0) { | 424 if (index < 0) { |
425 // Set the property straight into the object. | 425 // Set the property straight into the object. |
426 int offset = object->map()->instance_size() + (index * kPointerSize); | 426 int offset = object->map()->instance_size() + (index * kPointerSize); |
427 __ str(r0, FieldMemOperand(receiver_reg, offset)); | 427 __ str(r0, FieldMemOperand(receiver_reg, offset)); |
428 | 428 |
429 // Skip updating write barrier if storing a smi. | 429 // Skip updating write barrier if storing a smi. |
430 __ JumpIfSmi(r0, &exit); | 430 __ JumpIfSmi(r0, &exit); |
431 | 431 |
432 // Update the write barrier for the array address. | 432 // Update the write barrier for the array address. |
433 // Pass the now unused name_reg as a scratch register. | 433 // Pass the now unused name_reg as a scratch register. |
434 __ RecordWrite(receiver_reg, Operand(offset), name_reg, scratch); | 434 __ mov(name_reg, r0); |
| 435 __ RecordWriteField(receiver_reg, |
| 436 offset, |
| 437 name_reg, |
| 438 scratch, |
| 439 kLRHasNotBeenSaved, |
| 440 kDontSaveFPRegs); |
435 } else { | 441 } else { |
436 // Write to the properties array. | 442 // Write to the properties array. |
437 int offset = index * kPointerSize + FixedArray::kHeaderSize; | 443 int offset = index * kPointerSize + FixedArray::kHeaderSize; |
438 // Get the properties array | 444 // Get the properties array |
439 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); | 445 __ ldr(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); |
440 __ str(r0, FieldMemOperand(scratch, offset)); | 446 __ str(r0, FieldMemOperand(scratch, offset)); |
441 | 447 |
442 // Skip updating write barrier if storing a smi. | 448 // Skip updating write barrier if storing a smi. |
443 __ JumpIfSmi(r0, &exit); | 449 __ JumpIfSmi(r0, &exit); |
444 | 450 |
445 // Update the write barrier for the array address. | 451 // Update the write barrier for the array address. |
446 // Ok to clobber receiver_reg and name_reg, since we return. | 452 // Ok to clobber receiver_reg and name_reg, since we return. |
447 __ RecordWrite(scratch, Operand(offset), name_reg, receiver_reg); | 453 __ mov(name_reg, r0); |
| 454 __ RecordWriteField(scratch, |
| 455 offset, |
| 456 name_reg, |
| 457 receiver_reg, |
| 458 kLRHasNotBeenSaved, |
| 459 kDontSaveFPRegs); |
448 } | 460 } |
449 | 461 |
450 // Return the value (register r0). | 462 // Return the value (register r0). |
451 __ bind(&exit); | 463 __ bind(&exit); |
452 __ Ret(); | 464 __ Ret(); |
453 } | 465 } |
454 | 466 |
455 | 467 |
456 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { | 468 void StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { |
457 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); | 469 ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
546 } | 558 } |
547 } | 559 } |
548 | 560 |
549 | 561 |
550 // Undoes the effects of ReserveSpaceForFastApiCall. | 562 // Undoes the effects of ReserveSpaceForFastApiCall. |
551 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { | 563 static void FreeSpaceForFastApiCall(MacroAssembler* masm) { |
552 __ Drop(kFastApiCallArguments); | 564 __ Drop(kFastApiCallArguments); |
553 } | 565 } |
554 | 566 |
555 | 567 |
556 static MaybeObject* GenerateFastApiDirectCall(MacroAssembler* masm, | 568 static MaybeObject* GenerateFastApiDirectCall( |
557 const CallOptimization& optimization, | 569 MacroAssembler* masm, |
558 int argc) { | 570 const CallOptimization& optimization, |
| 571 int argc) { |
559 // ----------- S t a t e ------------- | 572 // ----------- S t a t e ------------- |
560 // -- sp[0] : holder (set by CheckPrototypes) | 573 // -- sp[0] : holder (set by CheckPrototypes) |
561 // -- sp[4] : callee js function | 574 // -- sp[4] : callee js function |
562 // -- sp[8] : call data | 575 // -- sp[8] : call data |
563 // -- sp[12] : last js argument | 576 // -- sp[12] : last js argument |
564 // -- ... | 577 // -- ... |
565 // -- sp[(argc + 3) * 4] : first js argument | 578 // -- sp[(argc + 3) * 4] : first js argument |
566 // -- sp[(argc + 4) * 4] : receiver | 579 // -- sp[(argc + 4) * 4] : receiver |
567 // ----------------------------------- | 580 // ----------------------------------- |
568 // Get the function and setup the context. | 581 // Get the function and setup the context. |
(...skipping 15 matching lines...) Expand all Loading... |
584 | 597 |
585 // r2 points to call data as expected by Arguments | 598 // r2 points to call data as expected by Arguments |
586 // (refer to layout above). | 599 // (refer to layout above). |
587 __ add(r2, sp, Operand(2 * kPointerSize)); | 600 __ add(r2, sp, Operand(2 * kPointerSize)); |
588 | 601 |
589 Object* callback = optimization.api_call_info()->callback(); | 602 Object* callback = optimization.api_call_info()->callback(); |
590 Address api_function_address = v8::ToCData<Address>(callback); | 603 Address api_function_address = v8::ToCData<Address>(callback); |
591 ApiFunction fun(api_function_address); | 604 ApiFunction fun(api_function_address); |
592 | 605 |
593 const int kApiStackSpace = 4; | 606 const int kApiStackSpace = 4; |
| 607 |
| 608 FrameScope frame_scope(masm, StackFrame::MANUAL); |
594 __ EnterExitFrame(false, kApiStackSpace); | 609 __ EnterExitFrame(false, kApiStackSpace); |
595 | 610 |
596 // r0 = v8::Arguments& | 611 // r0 = v8::Arguments& |
597 // Arguments is after the return address. | 612 // Arguments is after the return address. |
598 __ add(r0, sp, Operand(1 * kPointerSize)); | 613 __ add(r0, sp, Operand(1 * kPointerSize)); |
599 // v8::Arguments::implicit_args = data | 614 // v8::Arguments::implicit_args = data |
600 __ str(r2, MemOperand(r0, 0 * kPointerSize)); | 615 __ str(r2, MemOperand(r0, 0 * kPointerSize)); |
601 // v8::Arguments::values = last argument | 616 // v8::Arguments::values = last argument |
602 __ add(ip, r2, Operand(argc * kPointerSize)); | 617 __ add(ip, r2, Operand(argc * kPointerSize)); |
603 __ str(ip, MemOperand(r0, 1 * kPointerSize)); | 618 __ str(ip, MemOperand(r0, 1 * kPointerSize)); |
604 // v8::Arguments::length_ = argc | 619 // v8::Arguments::length_ = argc |
605 __ mov(ip, Operand(argc)); | 620 __ mov(ip, Operand(argc)); |
606 __ str(ip, MemOperand(r0, 2 * kPointerSize)); | 621 __ str(ip, MemOperand(r0, 2 * kPointerSize)); |
607 // v8::Arguments::is_construct_call = 0 | 622 // v8::Arguments::is_construct_call = 0 |
608 __ mov(ip, Operand(0)); | 623 __ mov(ip, Operand(0)); |
609 __ str(ip, MemOperand(r0, 3 * kPointerSize)); | 624 __ str(ip, MemOperand(r0, 3 * kPointerSize)); |
610 | 625 |
611 // Emitting a stub call may try to allocate (if the code is not | 626 // Emitting a stub call may try to allocate (if the code is not |
612 // already generated). Do not allow the assembler to perform a | 627 // already generated). Do not allow the assembler to perform a |
613 // garbage collection but instead return the allocation failure | 628 // garbage collection but instead return the allocation failure |
614 // object. | 629 // object. |
615 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; | 630 const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; |
616 ExternalReference ref = ExternalReference(&fun, | 631 ExternalReference ref = ExternalReference(&fun, |
617 ExternalReference::DIRECT_API_CALL, | 632 ExternalReference::DIRECT_API_CALL, |
618 masm->isolate()); | 633 masm->isolate()); |
| 634 AllowExternalCallThatCantCauseGC scope(masm); |
619 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); | 635 return masm->TryCallApiFunctionAndReturn(ref, kStackUnwindSpace); |
620 } | 636 } |
621 | 637 |
| 638 |
622 class CallInterceptorCompiler BASE_EMBEDDED { | 639 class CallInterceptorCompiler BASE_EMBEDDED { |
623 public: | 640 public: |
624 CallInterceptorCompiler(StubCompiler* stub_compiler, | 641 CallInterceptorCompiler(StubCompiler* stub_compiler, |
625 const ParameterCount& arguments, | 642 const ParameterCount& arguments, |
626 Register name, | 643 Register name, |
627 Code::ExtraICState extra_ic_state) | 644 Code::ExtraICState extra_ic_state) |
628 : stub_compiler_(stub_compiler), | 645 : stub_compiler_(stub_compiler), |
629 arguments_(arguments), | 646 arguments_(arguments), |
630 name_(name), | 647 name_(name), |
631 extra_ic_state_(extra_ic_state) {} | 648 extra_ic_state_(extra_ic_state) {} |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
787 Register scratch3, | 804 Register scratch3, |
788 String* name, | 805 String* name, |
789 JSObject* interceptor_holder, | 806 JSObject* interceptor_holder, |
790 Label* miss_label) { | 807 Label* miss_label) { |
791 Register holder = | 808 Register holder = |
792 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, | 809 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, |
793 scratch1, scratch2, scratch3, name, | 810 scratch1, scratch2, scratch3, name, |
794 miss_label); | 811 miss_label); |
795 | 812 |
796 // Call a runtime function to load the interceptor property. | 813 // Call a runtime function to load the interceptor property. |
797 __ EnterInternalFrame(); | 814 FrameScope scope(masm, StackFrame::INTERNAL); |
798 // Save the name_ register across the call. | 815 // Save the name_ register across the call. |
799 __ push(name_); | 816 __ push(name_); |
800 | 817 |
801 PushInterceptorArguments(masm, | 818 PushInterceptorArguments(masm, |
802 receiver, | 819 receiver, |
803 holder, | 820 holder, |
804 name_, | 821 name_, |
805 interceptor_holder); | 822 interceptor_holder); |
806 | 823 |
807 __ CallExternalReference( | 824 __ CallExternalReference( |
808 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), | 825 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), |
809 masm->isolate()), | 826 masm->isolate()), |
810 5); | 827 5); |
811 | 828 |
812 // Restore the name_ register. | 829 // Restore the name_ register. |
813 __ pop(name_); | 830 __ pop(name_); |
814 __ LeaveInternalFrame(); | 831 |
| 832 // Leave the internal frame. |
815 } | 833 } |
816 | 834 |
817 void LoadWithInterceptor(MacroAssembler* masm, | 835 void LoadWithInterceptor(MacroAssembler* masm, |
818 Register receiver, | 836 Register receiver, |
819 Register holder, | 837 Register holder, |
820 JSObject* holder_obj, | 838 JSObject* holder_obj, |
821 Register scratch, | 839 Register scratch, |
822 Label* interceptor_succeeded) { | 840 Label* interceptor_succeeded) { |
823 __ EnterInternalFrame(); | 841 { |
824 __ Push(holder, name_); | 842 FrameScope scope(masm, StackFrame::INTERNAL); |
| 843 __ Push(holder, name_); |
825 | 844 |
826 CompileCallLoadPropertyWithInterceptor(masm, | 845 CompileCallLoadPropertyWithInterceptor(masm, |
827 receiver, | 846 receiver, |
828 holder, | 847 holder, |
829 name_, | 848 name_, |
830 holder_obj); | 849 holder_obj); |
831 | 850 |
832 __ pop(name_); // Restore the name. | 851 __ pop(name_); // Restore the name. |
833 __ pop(receiver); // Restore the holder. | 852 __ pop(receiver); // Restore the holder. |
834 __ LeaveInternalFrame(); | 853 } |
835 | 854 |
836 // If interceptor returns no-result sentinel, call the constant function. | 855 // If interceptor returns no-result sentinel, call the constant function. |
837 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); | 856 __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); |
838 __ cmp(r0, scratch); | 857 __ cmp(r0, scratch); |
839 __ b(ne, interceptor_succeeded); | 858 __ b(ne, interceptor_succeeded); |
840 } | 859 } |
841 | 860 |
842 StubCompiler* stub_compiler_; | 861 StubCompiler* stub_compiler_; |
843 const ParameterCount& arguments_; | 862 const ParameterCount& arguments_; |
844 Register name_; | 863 Register name_; |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1221 } else { | 1240 } else { |
1222 __ Move(scratch3, Handle<Object>(callback_handle->data())); | 1241 __ Move(scratch3, Handle<Object>(callback_handle->data())); |
1223 } | 1242 } |
1224 __ Push(reg, scratch3, name_reg); | 1243 __ Push(reg, scratch3, name_reg); |
1225 __ mov(r0, sp); // r0 = Handle<String> | 1244 __ mov(r0, sp); // r0 = Handle<String> |
1226 | 1245 |
1227 Address getter_address = v8::ToCData<Address>(callback->getter()); | 1246 Address getter_address = v8::ToCData<Address>(callback->getter()); |
1228 ApiFunction fun(getter_address); | 1247 ApiFunction fun(getter_address); |
1229 | 1248 |
1230 const int kApiStackSpace = 1; | 1249 const int kApiStackSpace = 1; |
| 1250 |
| 1251 FrameScope frame_scope(masm(), StackFrame::MANUAL); |
1231 __ EnterExitFrame(false, kApiStackSpace); | 1252 __ EnterExitFrame(false, kApiStackSpace); |
| 1253 |
1232 // Create AccessorInfo instance on the stack above the exit frame with | 1254 // Create AccessorInfo instance on the stack above the exit frame with |
1233 // scratch2 (internal::Object **args_) as the data. | 1255 // scratch2 (internal::Object **args_) as the data. |
1234 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); | 1256 __ str(scratch2, MemOperand(sp, 1 * kPointerSize)); |
1235 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& | 1257 __ add(r1, sp, Operand(1 * kPointerSize)); // r1 = AccessorInfo& |
1236 | 1258 |
1237 // Emitting a stub call may try to allocate (if the code is not | 1259 // Emitting a stub call may try to allocate (if the code is not |
1238 // already generated). Do not allow the assembler to perform a | 1260 // already generated). Do not allow the assembler to perform a |
1239 // garbage collection but instead return the allocation failure | 1261 // garbage collection but instead return the allocation failure |
1240 // object. | 1262 // object. |
1241 const int kStackUnwindSpace = 4; | 1263 const int kStackUnwindSpace = 4; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1281 // Compile the interceptor call, followed by inline code to load the | 1303 // Compile the interceptor call, followed by inline code to load the |
1282 // property from further up the prototype chain if the call fails. | 1304 // property from further up the prototype chain if the call fails. |
1283 // Check that the maps haven't changed. | 1305 // Check that the maps haven't changed. |
1284 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, | 1306 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, |
1285 scratch1, scratch2, scratch3, | 1307 scratch1, scratch2, scratch3, |
1286 name, miss); | 1308 name, miss); |
1287 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); | 1309 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); |
1288 | 1310 |
1289 // Save necessary data before invoking an interceptor. | 1311 // Save necessary data before invoking an interceptor. |
1290 // Requires a frame to make GC aware of pushed pointers. | 1312 // Requires a frame to make GC aware of pushed pointers. |
1291 __ EnterInternalFrame(); | 1313 { |
| 1314 FrameScope frame_scope(masm(), StackFrame::INTERNAL); |
1292 | 1315 |
1293 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | 1316 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
1294 // CALLBACKS case needs a receiver to be passed into C++ callback. | 1317 // CALLBACKS case needs a receiver to be passed into C++ callback. |
1295 __ Push(receiver, holder_reg, name_reg); | 1318 __ Push(receiver, holder_reg, name_reg); |
1296 } else { | 1319 } else { |
1297 __ Push(holder_reg, name_reg); | 1320 __ Push(holder_reg, name_reg); |
| 1321 } |
| 1322 |
| 1323 // Invoke an interceptor. Note: map checks from receiver to |
| 1324 // interceptor's holder has been compiled before (see a caller |
| 1325 // of this method.) |
| 1326 CompileCallLoadPropertyWithInterceptor(masm(), |
| 1327 receiver, |
| 1328 holder_reg, |
| 1329 name_reg, |
| 1330 interceptor_holder); |
| 1331 |
| 1332 // Check if interceptor provided a value for property. If it's |
| 1333 // the case, return immediately. |
| 1334 Label interceptor_failed; |
| 1335 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); |
| 1336 __ cmp(r0, scratch1); |
| 1337 __ b(eq, &interceptor_failed); |
| 1338 frame_scope.GenerateLeaveFrame(); |
| 1339 __ Ret(); |
| 1340 |
| 1341 __ bind(&interceptor_failed); |
| 1342 __ pop(name_reg); |
| 1343 __ pop(holder_reg); |
| 1344 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { |
| 1345 __ pop(receiver); |
| 1346 } |
| 1347 |
| 1348 // Leave the internal frame. |
1298 } | 1349 } |
1299 | 1350 |
1300 // Invoke an interceptor. Note: map checks from receiver to | |
1301 // interceptor's holder has been compiled before (see a caller | |
1302 // of this method.) | |
1303 CompileCallLoadPropertyWithInterceptor(masm(), | |
1304 receiver, | |
1305 holder_reg, | |
1306 name_reg, | |
1307 interceptor_holder); | |
1308 | |
1309 // Check if interceptor provided a value for property. If it's | |
1310 // the case, return immediately. | |
1311 Label interceptor_failed; | |
1312 __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); | |
1313 __ cmp(r0, scratch1); | |
1314 __ b(eq, &interceptor_failed); | |
1315 __ LeaveInternalFrame(); | |
1316 __ Ret(); | |
1317 | |
1318 __ bind(&interceptor_failed); | |
1319 __ pop(name_reg); | |
1320 __ pop(holder_reg); | |
1321 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { | |
1322 __ pop(receiver); | |
1323 } | |
1324 | |
1325 __ LeaveInternalFrame(); | |
1326 | |
1327 // Check that the maps from interceptor's holder to lookup's holder | 1351 // Check that the maps from interceptor's holder to lookup's holder |
1328 // haven't changed. And load lookup's holder into |holder| register. | 1352 // haven't changed. And load lookup's holder into |holder| register. |
1329 if (interceptor_holder != lookup->holder()) { | 1353 if (interceptor_holder != lookup->holder()) { |
1330 holder_reg = CheckPrototypes(interceptor_holder, | 1354 holder_reg = CheckPrototypes(interceptor_holder, |
1331 holder_reg, | 1355 holder_reg, |
1332 lookup->holder(), | 1356 lookup->holder(), |
1333 scratch1, | 1357 scratch1, |
1334 scratch2, | 1358 scratch2, |
1335 scratch3, | 1359 scratch3, |
1336 name, | 1360 name, |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1549 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); | 1573 __ ldr(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); |
1550 | 1574 |
1551 // Check that the elements are in fast mode and writable. | 1575 // Check that the elements are in fast mode and writable. |
1552 __ CheckMap(elements, | 1576 __ CheckMap(elements, |
1553 r0, | 1577 r0, |
1554 Heap::kFixedArrayMapRootIndex, | 1578 Heap::kFixedArrayMapRootIndex, |
1555 &call_builtin, | 1579 &call_builtin, |
1556 DONT_DO_SMI_CHECK); | 1580 DONT_DO_SMI_CHECK); |
1557 | 1581 |
1558 if (argc == 1) { // Otherwise fall through to call the builtin. | 1582 if (argc == 1) { // Otherwise fall through to call the builtin. |
1559 Label exit, with_write_barrier, attempt_to_grow_elements; | 1583 Label attempt_to_grow_elements; |
1560 | 1584 |
1561 // Get the array's length into r0 and calculate new length. | 1585 // Get the array's length into r0 and calculate new length. |
1562 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1586 __ ldr(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1563 STATIC_ASSERT(kSmiTagSize == 1); | 1587 STATIC_ASSERT(kSmiTagSize == 1); |
1564 STATIC_ASSERT(kSmiTag == 0); | 1588 STATIC_ASSERT(kSmiTag == 0); |
1565 __ add(r0, r0, Operand(Smi::FromInt(argc))); | 1589 __ add(r0, r0, Operand(Smi::FromInt(argc))); |
1566 | 1590 |
1567 // Get the element's length. | 1591 // Get the element's length. |
1568 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1592 __ ldr(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
1569 | 1593 |
1570 // Check if we could survive without allocation. | 1594 // Check if we could survive without allocation. |
1571 __ cmp(r0, r4); | 1595 __ cmp(r0, r4); |
1572 __ b(gt, &attempt_to_grow_elements); | 1596 __ b(gt, &attempt_to_grow_elements); |
1573 | 1597 |
| 1598 // Check if value is a smi. |
| 1599 Label with_write_barrier; |
| 1600 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1601 __ JumpIfNotSmi(r4, &with_write_barrier); |
| 1602 |
1574 // Save new length. | 1603 // Save new length. |
1575 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1604 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1576 | 1605 |
1577 // Push the element. | 1606 // Push the element. |
1578 __ ldr(r4, MemOperand(sp, (argc - 1) * kPointerSize)); | |
1579 // We may need a register containing the address end_elements below, | 1607 // We may need a register containing the address end_elements below, |
1580 // so write back the value in end_elements. | 1608 // so write back the value in end_elements. |
1581 __ add(end_elements, elements, | 1609 __ add(end_elements, elements, |
1582 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1610 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
1583 const int kEndElementsOffset = | 1611 const int kEndElementsOffset = |
1584 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; | 1612 FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; |
1585 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); | 1613 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); |
1586 | 1614 |
1587 // Check for a smi. | 1615 // Check for a smi. |
1588 __ JumpIfNotSmi(r4, &with_write_barrier); | |
1589 __ bind(&exit); | |
1590 __ Drop(argc + 1); | 1616 __ Drop(argc + 1); |
1591 __ Ret(); | 1617 __ Ret(); |
1592 | 1618 |
1593 __ bind(&with_write_barrier); | 1619 __ bind(&with_write_barrier); |
1594 __ InNewSpace(elements, r4, eq, &exit); | 1620 |
1595 __ RecordWriteHelper(elements, end_elements, r4); | 1621 if (FLAG_smi_only_arrays) { |
| 1622 __ ldr(r6, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1623 __ CheckFastSmiOnlyElements(r6, r6, &call_builtin); |
| 1624 } |
| 1625 |
| 1626 // Save new length. |
| 1627 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
| 1628 |
| 1629 // Push the element. |
| 1630 // We may need a register containing the address end_elements below, |
| 1631 // so write back the value in end_elements. |
| 1632 __ add(end_elements, elements, |
| 1633 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 1634 __ str(r4, MemOperand(end_elements, kEndElementsOffset, PreIndex)); |
| 1635 |
| 1636 __ RecordWrite(elements, |
| 1637 end_elements, |
| 1638 r4, |
| 1639 kLRHasNotBeenSaved, |
| 1640 kDontSaveFPRegs, |
| 1641 EMIT_REMEMBERED_SET, |
| 1642 OMIT_SMI_CHECK); |
1596 __ Drop(argc + 1); | 1643 __ Drop(argc + 1); |
1597 __ Ret(); | 1644 __ Ret(); |
1598 | 1645 |
1599 __ bind(&attempt_to_grow_elements); | 1646 __ bind(&attempt_to_grow_elements); |
1600 // r0: array's length + 1. | 1647 // r0: array's length + 1. |
1601 // r4: elements' length. | 1648 // r4: elements' length. |
1602 | 1649 |
1603 if (!FLAG_inline_new) { | 1650 if (!FLAG_inline_new) { |
1604 __ b(&call_builtin); | 1651 __ b(&call_builtin); |
1605 } | 1652 } |
1606 | 1653 |
| 1654 __ ldr(r2, MemOperand(sp, (argc - 1) * kPointerSize)); |
| 1655 if (FLAG_smi_only_arrays) { |
| 1656 // Growing elements that are SMI-only requires special handling in case |
| 1657 // the new element is non-Smi. For now, delegate to the builtin. |
| 1658 Label no_fast_elements_check; |
| 1659 __ JumpIfSmi(r2, &no_fast_elements_check); |
| 1660 __ ldr(r7, FieldMemOperand(receiver, HeapObject::kMapOffset)); |
| 1661 __ CheckFastObjectElements(r7, r7, &call_builtin); |
| 1662 __ bind(&no_fast_elements_check); |
| 1663 } |
| 1664 |
1607 Isolate* isolate = masm()->isolate(); | 1665 Isolate* isolate = masm()->isolate(); |
1608 ExternalReference new_space_allocation_top = | 1666 ExternalReference new_space_allocation_top = |
1609 ExternalReference::new_space_allocation_top_address(isolate); | 1667 ExternalReference::new_space_allocation_top_address(isolate); |
1610 ExternalReference new_space_allocation_limit = | 1668 ExternalReference new_space_allocation_limit = |
1611 ExternalReference::new_space_allocation_limit_address(isolate); | 1669 ExternalReference::new_space_allocation_limit_address(isolate); |
1612 | 1670 |
1613 const int kAllocationDelta = 4; | 1671 const int kAllocationDelta = 4; |
1614 // Load top and check if it is the end of elements. | 1672 // Load top and check if it is the end of elements. |
1615 __ add(end_elements, elements, | 1673 __ add(end_elements, elements, |
1616 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1674 Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
1617 __ add(end_elements, end_elements, Operand(kEndElementsOffset)); | 1675 __ add(end_elements, end_elements, Operand(kEndElementsOffset)); |
1618 __ mov(r7, Operand(new_space_allocation_top)); | 1676 __ mov(r7, Operand(new_space_allocation_top)); |
1619 __ ldr(r6, MemOperand(r7)); | 1677 __ ldr(r6, MemOperand(r7)); |
1620 __ cmp(end_elements, r6); | 1678 __ cmp(end_elements, r6); |
1621 __ b(ne, &call_builtin); | 1679 __ b(ne, &call_builtin); |
1622 | 1680 |
1623 __ mov(r9, Operand(new_space_allocation_limit)); | 1681 __ mov(r9, Operand(new_space_allocation_limit)); |
1624 __ ldr(r9, MemOperand(r9)); | 1682 __ ldr(r9, MemOperand(r9)); |
1625 __ add(r6, r6, Operand(kAllocationDelta * kPointerSize)); | 1683 __ add(r6, r6, Operand(kAllocationDelta * kPointerSize)); |
1626 __ cmp(r6, r9); | 1684 __ cmp(r6, r9); |
1627 __ b(hi, &call_builtin); | 1685 __ b(hi, &call_builtin); |
1628 | 1686 |
1629 // We fit and could grow elements. | 1687 // We fit and could grow elements. |
1630 // Update new_space_allocation_top. | 1688 // Update new_space_allocation_top. |
1631 __ str(r6, MemOperand(r7)); | 1689 __ str(r6, MemOperand(r7)); |
1632 // Push the argument. | 1690 // Push the argument. |
1633 __ ldr(r6, MemOperand(sp, (argc - 1) * kPointerSize)); | 1691 __ str(r2, MemOperand(end_elements)); |
1634 __ str(r6, MemOperand(end_elements)); | |
1635 // Fill the rest with holes. | 1692 // Fill the rest with holes. |
1636 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); | 1693 __ LoadRoot(r6, Heap::kTheHoleValueRootIndex); |
1637 for (int i = 1; i < kAllocationDelta; i++) { | 1694 for (int i = 1; i < kAllocationDelta; i++) { |
1638 __ str(r6, MemOperand(end_elements, i * kPointerSize)); | 1695 __ str(r6, MemOperand(end_elements, i * kPointerSize)); |
1639 } | 1696 } |
1640 | 1697 |
1641 // Update elements' and array's sizes. | 1698 // Update elements' and array's sizes. |
1642 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); | 1699 __ str(r0, FieldMemOperand(receiver, JSArray::kLengthOffset)); |
1643 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); | 1700 __ add(r4, r4, Operand(Smi::FromInt(kAllocationDelta))); |
1644 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); | 1701 __ str(r4, FieldMemOperand(elements, FixedArray::kLengthOffset)); |
(...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2706 // global object. We bail out to the runtime system to do that. | 2763 // global object. We bail out to the runtime system to do that. |
2707 __ mov(r4, Operand(Handle<JSGlobalPropertyCell>(cell))); | 2764 __ mov(r4, Operand(Handle<JSGlobalPropertyCell>(cell))); |
2708 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); | 2765 __ LoadRoot(r5, Heap::kTheHoleValueRootIndex); |
2709 __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); | 2766 __ ldr(r6, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); |
2710 __ cmp(r5, r6); | 2767 __ cmp(r5, r6); |
2711 __ b(eq, &miss); | 2768 __ b(eq, &miss); |
2712 | 2769 |
2713 // Store the value in the cell. | 2770 // Store the value in the cell. |
2714 __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); | 2771 __ str(r0, FieldMemOperand(r4, JSGlobalPropertyCell::kValueOffset)); |
2715 | 2772 |
| 2773 __ mov(r1, r0); |
| 2774 __ RecordWriteField(r4, |
| 2775 JSGlobalPropertyCell::kValueOffset, |
| 2776 r1, |
| 2777 r2, |
| 2778 kLRHasNotBeenSaved, |
| 2779 kDontSaveFPRegs, |
| 2780 OMIT_REMEMBERED_SET); |
| 2781 |
2716 Counters* counters = masm()->isolate()->counters(); | 2782 Counters* counters = masm()->isolate()->counters(); |
2717 __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3); | 2783 __ IncrementCounter(counters->named_store_global_inline(), 1, r4, r3); |
2718 __ Ret(); | 2784 __ Ret(); |
2719 | 2785 |
2720 // Handle store cache miss. | 2786 // Handle store cache miss. |
2721 __ bind(&miss); | 2787 __ bind(&miss); |
2722 __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3); | 2788 __ IncrementCounter(counters->named_store_global_inline_miss(), 1, r4, r3); |
2723 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); | 2789 Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); |
2724 __ Jump(ic, RelocInfo::CODE_TARGET); | 2790 __ Jump(ic, RelocInfo::CODE_TARGET); |
2725 | 2791 |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3447 | 3513 |
3448 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: | 3514 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: |
3449 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: | 3515 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: |
3450 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 3516 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3451 case EXTERNAL_PIXEL_ELEMENTS: | 3517 case EXTERNAL_PIXEL_ELEMENTS: |
3452 return false; | 3518 return false; |
3453 | 3519 |
3454 case EXTERNAL_FLOAT_ELEMENTS: | 3520 case EXTERNAL_FLOAT_ELEMENTS: |
3455 case EXTERNAL_DOUBLE_ELEMENTS: | 3521 case EXTERNAL_DOUBLE_ELEMENTS: |
3456 case FAST_ELEMENTS: | 3522 case FAST_ELEMENTS: |
| 3523 case FAST_SMI_ONLY_ELEMENTS: |
3457 case FAST_DOUBLE_ELEMENTS: | 3524 case FAST_DOUBLE_ELEMENTS: |
3458 case DICTIONARY_ELEMENTS: | 3525 case DICTIONARY_ELEMENTS: |
3459 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3526 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3460 UNREACHABLE(); | 3527 UNREACHABLE(); |
3461 return false; | 3528 return false; |
3462 } | 3529 } |
3463 return false; | 3530 return false; |
3464 } | 3531 } |
3465 | 3532 |
3466 | 3533 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3533 __ add(r2, r3, Operand(key, LSL, 2)); | 3600 __ add(r2, r3, Operand(key, LSL, 2)); |
3534 __ vldr(d0, r2, 0); | 3601 __ vldr(d0, r2, 0); |
3535 } else { | 3602 } else { |
3536 __ add(r4, r3, Operand(key, LSL, 2)); | 3603 __ add(r4, r3, Operand(key, LSL, 2)); |
3537 // r4: pointer to the beginning of the double we want to load. | 3604 // r4: pointer to the beginning of the double we want to load. |
3538 __ ldr(r2, MemOperand(r4, 0)); | 3605 __ ldr(r2, MemOperand(r4, 0)); |
3539 __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); | 3606 __ ldr(r3, MemOperand(r4, Register::kSizeInBytes)); |
3540 } | 3607 } |
3541 break; | 3608 break; |
3542 case FAST_ELEMENTS: | 3609 case FAST_ELEMENTS: |
| 3610 case FAST_SMI_ONLY_ELEMENTS: |
3543 case FAST_DOUBLE_ELEMENTS: | 3611 case FAST_DOUBLE_ELEMENTS: |
3544 case DICTIONARY_ELEMENTS: | 3612 case DICTIONARY_ELEMENTS: |
3545 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3613 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3546 UNREACHABLE(); | 3614 UNREACHABLE(); |
3547 break; | 3615 break; |
3548 } | 3616 } |
3549 | 3617 |
3550 // For integer array types: | 3618 // For integer array types: |
3551 // r2: value | 3619 // r2: value |
3552 // For float array type: | 3620 // For float array type: |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3873 r4, s2); // These are: scratch2, single_scratch. | 3941 r4, s2); // These are: scratch2, single_scratch. |
3874 if (destination == FloatingPointHelper::kVFPRegisters) { | 3942 if (destination == FloatingPointHelper::kVFPRegisters) { |
3875 CpuFeatures::Scope scope(VFP3); | 3943 CpuFeatures::Scope scope(VFP3); |
3876 __ vstr(d0, r3, 0); | 3944 __ vstr(d0, r3, 0); |
3877 } else { | 3945 } else { |
3878 __ str(r6, MemOperand(r3, 0)); | 3946 __ str(r6, MemOperand(r3, 0)); |
3879 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); | 3947 __ str(r7, MemOperand(r3, Register::kSizeInBytes)); |
3880 } | 3948 } |
3881 break; | 3949 break; |
3882 case FAST_ELEMENTS: | 3950 case FAST_ELEMENTS: |
| 3951 case FAST_SMI_ONLY_ELEMENTS: |
3883 case FAST_DOUBLE_ELEMENTS: | 3952 case FAST_DOUBLE_ELEMENTS: |
3884 case DICTIONARY_ELEMENTS: | 3953 case DICTIONARY_ELEMENTS: |
3885 case NON_STRICT_ARGUMENTS_ELEMENTS: | 3954 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3886 UNREACHABLE(); | 3955 UNREACHABLE(); |
3887 break; | 3956 break; |
3888 } | 3957 } |
3889 | 3958 |
3890 // Entry registers are intact, r0 holds the value which is the return value. | 3959 // Entry registers are intact, r0 holds the value which is the return value. |
3891 __ Ret(); | 3960 __ Ret(); |
3892 | 3961 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3936 __ strh(r5, MemOperand(r3, key, LSL, 0)); | 4005 __ strh(r5, MemOperand(r3, key, LSL, 0)); |
3937 break; | 4006 break; |
3938 case EXTERNAL_INT_ELEMENTS: | 4007 case EXTERNAL_INT_ELEMENTS: |
3939 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4008 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
3940 __ str(r5, MemOperand(r3, key, LSL, 1)); | 4009 __ str(r5, MemOperand(r3, key, LSL, 1)); |
3941 break; | 4010 break; |
3942 case EXTERNAL_PIXEL_ELEMENTS: | 4011 case EXTERNAL_PIXEL_ELEMENTS: |
3943 case EXTERNAL_FLOAT_ELEMENTS: | 4012 case EXTERNAL_FLOAT_ELEMENTS: |
3944 case EXTERNAL_DOUBLE_ELEMENTS: | 4013 case EXTERNAL_DOUBLE_ELEMENTS: |
3945 case FAST_ELEMENTS: | 4014 case FAST_ELEMENTS: |
| 4015 case FAST_SMI_ONLY_ELEMENTS: |
3946 case FAST_DOUBLE_ELEMENTS: | 4016 case FAST_DOUBLE_ELEMENTS: |
3947 case DICTIONARY_ELEMENTS: | 4017 case DICTIONARY_ELEMENTS: |
3948 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4018 case NON_STRICT_ARGUMENTS_ELEMENTS: |
3949 UNREACHABLE(); | 4019 UNREACHABLE(); |
3950 break; | 4020 break; |
3951 } | 4021 } |
3952 } | 4022 } |
3953 | 4023 |
3954 // Entry registers are intact, r0 holds the value which is the return | 4024 // Entry registers are intact, r0 holds the value which is the return |
3955 // value. | 4025 // value. |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4075 __ strh(r5, MemOperand(r3, key, LSL, 0)); | 4145 __ strh(r5, MemOperand(r3, key, LSL, 0)); |
4076 break; | 4146 break; |
4077 case EXTERNAL_INT_ELEMENTS: | 4147 case EXTERNAL_INT_ELEMENTS: |
4078 case EXTERNAL_UNSIGNED_INT_ELEMENTS: | 4148 case EXTERNAL_UNSIGNED_INT_ELEMENTS: |
4079 __ str(r5, MemOperand(r3, key, LSL, 1)); | 4149 __ str(r5, MemOperand(r3, key, LSL, 1)); |
4080 break; | 4150 break; |
4081 case EXTERNAL_PIXEL_ELEMENTS: | 4151 case EXTERNAL_PIXEL_ELEMENTS: |
4082 case EXTERNAL_FLOAT_ELEMENTS: | 4152 case EXTERNAL_FLOAT_ELEMENTS: |
4083 case EXTERNAL_DOUBLE_ELEMENTS: | 4153 case EXTERNAL_DOUBLE_ELEMENTS: |
4084 case FAST_ELEMENTS: | 4154 case FAST_ELEMENTS: |
| 4155 case FAST_SMI_ONLY_ELEMENTS: |
4085 case FAST_DOUBLE_ELEMENTS: | 4156 case FAST_DOUBLE_ELEMENTS: |
4086 case DICTIONARY_ELEMENTS: | 4157 case DICTIONARY_ELEMENTS: |
4087 case NON_STRICT_ARGUMENTS_ELEMENTS: | 4158 case NON_STRICT_ARGUMENTS_ELEMENTS: |
4088 UNREACHABLE(); | 4159 UNREACHABLE(); |
4089 break; | 4160 break; |
4090 } | 4161 } |
4091 } | 4162 } |
4092 } | 4163 } |
4093 } | 4164 } |
4094 | 4165 |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4227 masm->isolate()->builtins()->KeyedLoadIC_Slow(); | 4298 masm->isolate()->builtins()->KeyedLoadIC_Slow(); |
4228 __ Jump(slow_ic, RelocInfo::CODE_TARGET); | 4299 __ Jump(slow_ic, RelocInfo::CODE_TARGET); |
4229 | 4300 |
4230 __ bind(&miss_force_generic); | 4301 __ bind(&miss_force_generic); |
4231 Handle<Code> miss_ic = | 4302 Handle<Code> miss_ic = |
4232 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); | 4303 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); |
4233 __ Jump(miss_ic, RelocInfo::CODE_TARGET); | 4304 __ Jump(miss_ic, RelocInfo::CODE_TARGET); |
4234 } | 4305 } |
4235 | 4306 |
4236 | 4307 |
4237 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm, | 4308 void KeyedStoreStubCompiler::GenerateStoreFastElement( |
4238 bool is_js_array) { | 4309 MacroAssembler* masm, |
| 4310 bool is_js_array, |
| 4311 ElementsKind elements_kind) { |
4239 // ----------- S t a t e ------------- | 4312 // ----------- S t a t e ------------- |
4240 // -- r0 : value | 4313 // -- r0 : value |
4241 // -- r1 : key | 4314 // -- r1 : key |
4242 // -- r2 : receiver | 4315 // -- r2 : receiver |
4243 // -- lr : return address | 4316 // -- lr : return address |
4244 // -- r3 : scratch | 4317 // -- r3 : scratch |
4245 // -- r4 : scratch (elements) | 4318 // -- r4 : scratch (elements) |
4246 // ----------------------------------- | 4319 // ----------------------------------- |
4247 Label miss_force_generic; | 4320 Label miss_force_generic; |
4248 | 4321 |
(...skipping 21 matching lines...) Expand all Loading... |
4270 // Check that the key is within bounds. | 4343 // Check that the key is within bounds. |
4271 if (is_js_array) { | 4344 if (is_js_array) { |
4272 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); | 4345 __ ldr(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); |
4273 } else { | 4346 } else { |
4274 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); | 4347 __ ldr(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); |
4275 } | 4348 } |
4276 // Compare smis. | 4349 // Compare smis. |
4277 __ cmp(key_reg, scratch); | 4350 __ cmp(key_reg, scratch); |
4278 __ b(hs, &miss_force_generic); | 4351 __ b(hs, &miss_force_generic); |
4279 | 4352 |
4280 __ add(scratch, | 4353 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { |
4281 elements_reg, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); | 4354 __ JumpIfNotSmi(value_reg, &miss_force_generic); |
4282 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); | 4355 __ add(scratch, |
4283 __ str(value_reg, | 4356 elements_reg, |
4284 MemOperand(scratch, key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); | 4357 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
4285 __ RecordWrite(scratch, | 4358 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
4286 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize), | 4359 __ add(scratch, |
4287 receiver_reg , elements_reg); | 4360 scratch, |
4288 | 4361 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4362 __ str(value_reg, MemOperand(scratch)); |
| 4363 } else { |
| 4364 ASSERT(elements_kind == FAST_ELEMENTS); |
| 4365 __ add(scratch, |
| 4366 elements_reg, |
| 4367 Operand(FixedArray::kHeaderSize - kHeapObjectTag)); |
| 4368 STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); |
| 4369 __ add(scratch, |
| 4370 scratch, |
| 4371 Operand(key_reg, LSL, kPointerSizeLog2 - kSmiTagSize)); |
| 4372 __ str(value_reg, MemOperand(scratch)); |
| 4373 __ mov(receiver_reg, value_reg); |
| 4374 __ RecordWrite(elements_reg, // Object. |
| 4375 scratch, // Address. |
| 4376 receiver_reg, // Value. |
| 4377 kLRHasNotBeenSaved, |
| 4378 kDontSaveFPRegs); |
| 4379 } |
4289 // value_reg (r0) is preserved. | 4380 // value_reg (r0) is preserved. |
4290 // Done. | 4381 // Done. |
4291 __ Ret(); | 4382 __ Ret(); |
4292 | 4383 |
4293 __ bind(&miss_force_generic); | 4384 __ bind(&miss_force_generic); |
4294 Handle<Code> ic = | 4385 Handle<Code> ic = |
4295 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4386 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
4296 __ Jump(ic, RelocInfo::CODE_TARGET); | 4387 __ Jump(ic, RelocInfo::CODE_TARGET); |
4297 } | 4388 } |
4298 | 4389 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4421 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); | 4512 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); |
4422 __ Jump(ic, RelocInfo::CODE_TARGET); | 4513 __ Jump(ic, RelocInfo::CODE_TARGET); |
4423 } | 4514 } |
4424 | 4515 |
4425 | 4516 |
4426 #undef __ | 4517 #undef __ |
4427 | 4518 |
4428 } } // namespace v8::internal | 4519 } } // namespace v8::internal |
4429 | 4520 |
4430 #endif // V8_TARGET_ARCH_ARM | 4521 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |