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

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

Issue 8139027: Version 3.6.5 (Closed) Base URL: http://v8.googlecode.com/svn/trunk/
Patch Set: '' Created 9 years, 2 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/x64/regexp-macro-assembler-x64.cc ('k') | test/cctest/cctest.gyp » ('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 627 matching lines...) Expand 10 before | Expand all | Expand 10 after
638 Register scratch2, 638 Register scratch2,
639 Register scratch3, 639 Register scratch3,
640 String* name, 640 String* name,
641 JSObject* interceptor_holder, 641 JSObject* interceptor_holder,
642 Label* miss_label) { 642 Label* miss_label) {
643 Register holder = 643 Register holder =
644 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 644 stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder,
645 scratch1, scratch2, scratch3, name, 645 scratch1, scratch2, scratch3, name,
646 miss_label); 646 miss_label);
647 647
648 __ EnterInternalFrame(); 648 FrameScope scope(masm, StackFrame::INTERNAL);
649 // Save the name_ register across the call. 649 // Save the name_ register across the call.
650 __ push(name_); 650 __ push(name_);
651 651
652 PushInterceptorArguments(masm, 652 PushInterceptorArguments(masm,
653 receiver, 653 receiver,
654 holder, 654 holder,
655 name_, 655 name_,
656 interceptor_holder); 656 interceptor_holder);
657 657
658 __ CallExternalReference( 658 __ CallExternalReference(
659 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), 659 ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall),
660 masm->isolate()), 660 masm->isolate()),
661 5); 661 5);
662 662
663 // Restore the name_ register. 663 // Restore the name_ register.
664 __ pop(name_); 664 __ pop(name_);
665 __ LeaveInternalFrame(); 665
666 // Leave the internal frame.
666 } 667 }
667 668
668 void LoadWithInterceptor(MacroAssembler* masm, 669 void LoadWithInterceptor(MacroAssembler* masm,
669 Register receiver, 670 Register receiver,
670 Register holder, 671 Register holder,
671 JSObject* holder_obj, 672 JSObject* holder_obj,
672 Label* interceptor_succeeded) { 673 Label* interceptor_succeeded) {
673 __ EnterInternalFrame(); 674 {
674 __ push(holder); // Save the holder. 675 FrameScope scope(masm, StackFrame::INTERNAL);
675 __ push(name_); // Save the name. 676 __ push(holder); // Save the holder.
677 __ push(name_); // Save the name.
676 678
677 CompileCallLoadPropertyWithInterceptor(masm, 679 CompileCallLoadPropertyWithInterceptor(masm,
678 receiver, 680 receiver,
679 holder, 681 holder,
680 name_, 682 name_,
681 holder_obj); 683 holder_obj);
682 684
683 __ pop(name_); // Restore the name. 685 __ pop(name_); // Restore the name.
684 __ pop(receiver); // Restore the holder. 686 __ pop(receiver); // Restore the holder.
685 __ LeaveInternalFrame(); 687 // Leave the internal frame.
688 }
686 689
687 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); 690 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
688 __ j(not_equal, interceptor_succeeded); 691 __ j(not_equal, interceptor_succeeded);
689 } 692 }
690 693
691 StubCompiler* stub_compiler_; 694 StubCompiler* stub_compiler_;
692 const ParameterCount& arguments_; 695 const ParameterCount& arguments_;
693 Register name_; 696 Register name_;
694 Code::ExtraICState extra_ic_state_; 697 Code::ExtraICState extra_ic_state_;
695 }; 698 };
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
774 index -= object->map()->inobject_properties(); 777 index -= object->map()->inobject_properties();
775 778
776 if (index < 0) { 779 if (index < 0) {
777 // Set the property straight into the object. 780 // Set the property straight into the object.
778 int offset = object->map()->instance_size() + (index * kPointerSize); 781 int offset = object->map()->instance_size() + (index * kPointerSize);
779 __ movq(FieldOperand(receiver_reg, offset), rax); 782 __ movq(FieldOperand(receiver_reg, offset), rax);
780 783
781 // Update the write barrier for the array address. 784 // Update the write barrier for the array address.
782 // Pass the value being stored in the now unused name_reg. 785 // Pass the value being stored in the now unused name_reg.
783 __ movq(name_reg, rax); 786 __ movq(name_reg, rax);
784 __ RecordWrite(receiver_reg, offset, name_reg, scratch); 787 __ RecordWriteField(
788 receiver_reg, offset, name_reg, scratch, kDontSaveFPRegs);
785 } else { 789 } else {
786 // Write to the properties array. 790 // Write to the properties array.
787 int offset = index * kPointerSize + FixedArray::kHeaderSize; 791 int offset = index * kPointerSize + FixedArray::kHeaderSize;
788 // Get the properties array (optimistically). 792 // Get the properties array (optimistically).
789 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 793 __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset));
790 __ movq(FieldOperand(scratch, offset), rax); 794 __ movq(FieldOperand(scratch, offset), rax);
791 795
792 // Update the write barrier for the array address. 796 // Update the write barrier for the array address.
793 // Pass the value being stored in the now unused name_reg. 797 // Pass the value being stored in the now unused name_reg.
794 __ movq(name_reg, rax); 798 __ movq(name_reg, rax);
795 __ RecordWrite(scratch, offset, name_reg, receiver_reg); 799 __ RecordWriteField(
800 scratch, offset, name_reg, receiver_reg, kDontSaveFPRegs);
796 } 801 }
797 802
798 // Return the value (register rax). 803 // Return the value (register rax).
799 __ ret(0); 804 __ ret(0);
800 } 805 }
801 806
802 807
803 // Generate code to check that a global property cell is empty. Create 808 // Generate code to check that a global property cell is empty. Create
804 // the property cell at compilation time if no cell exists for the 809 // the property cell at compilation time if no cell exists for the
805 // property. 810 // property.
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 // Compile the interceptor call, followed by inline code to load the 1137 // Compile the interceptor call, followed by inline code to load the
1133 // property from further up the prototype chain if the call fails. 1138 // property from further up the prototype chain if the call fails.
1134 // Check that the maps haven't changed. 1139 // Check that the maps haven't changed.
1135 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1140 Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder,
1136 scratch1, scratch2, scratch3, 1141 scratch1, scratch2, scratch3,
1137 name, miss); 1142 name, miss);
1138 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 1143 ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1));
1139 1144
1140 // Save necessary data before invoking an interceptor. 1145 // Save necessary data before invoking an interceptor.
1141 // Requires a frame to make GC aware of pushed pointers. 1146 // Requires a frame to make GC aware of pushed pointers.
1142 __ EnterInternalFrame(); 1147 {
1148 FrameScope frame_scope(masm(), StackFrame::INTERNAL);
1143 1149
1144 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 1150 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1145 // CALLBACKS case needs a receiver to be passed into C++ callback. 1151 // CALLBACKS case needs a receiver to be passed into C++ callback.
1146 __ push(receiver); 1152 __ push(receiver);
1153 }
1154 __ push(holder_reg);
1155 __ push(name_reg);
1156
1157 // Invoke an interceptor. Note: map checks from receiver to
1158 // interceptor's holder has been compiled before (see a caller
1159 // of this method.)
1160 CompileCallLoadPropertyWithInterceptor(masm(),
1161 receiver,
1162 holder_reg,
1163 name_reg,
1164 interceptor_holder);
1165
1166 // Check if interceptor provided a value for property. If it's
1167 // the case, return immediately.
1168 Label interceptor_failed;
1169 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
1170 __ j(equal, &interceptor_failed);
1171 frame_scope.GenerateLeaveFrame();
1172 __ ret(0);
1173
1174 __ bind(&interceptor_failed);
1175 __ pop(name_reg);
1176 __ pop(holder_reg);
1177 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1178 __ pop(receiver);
1179 }
1180
1181 // Leave the internal frame.
1147 } 1182 }
1148 __ push(holder_reg);
1149 __ push(name_reg);
1150
1151 // Invoke an interceptor. Note: map checks from receiver to
1152 // interceptor's holder has been compiled before (see a caller
1153 // of this method.)
1154 CompileCallLoadPropertyWithInterceptor(masm(),
1155 receiver,
1156 holder_reg,
1157 name_reg,
1158 interceptor_holder);
1159
1160 // Check if interceptor provided a value for property. If it's
1161 // the case, return immediately.
1162 Label interceptor_failed;
1163 __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex);
1164 __ j(equal, &interceptor_failed);
1165 __ LeaveInternalFrame();
1166 __ ret(0);
1167
1168 __ bind(&interceptor_failed);
1169 __ pop(name_reg);
1170 __ pop(holder_reg);
1171 if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) {
1172 __ pop(receiver);
1173 }
1174
1175 __ LeaveInternalFrame();
1176 1183
1177 // Check that the maps from interceptor's holder to lookup's holder 1184 // Check that the maps from interceptor's holder to lookup's holder
1178 // haven't changed. And load lookup's holder into |holder| register. 1185 // haven't changed. And load lookup's holder into |holder| register.
1179 if (interceptor_holder != lookup->holder()) { 1186 if (interceptor_holder != lookup->holder()) {
1180 holder_reg = CheckPrototypes(interceptor_holder, 1187 holder_reg = CheckPrototypes(interceptor_holder,
1181 holder_reg, 1188 holder_reg,
1182 lookup->holder(), 1189 lookup->holder(),
1183 scratch1, 1190 scratch1,
1184 scratch2, 1191 scratch2,
1185 scratch3, 1192 scratch3,
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
1414 1421
1415 // Get the elements array of the object. 1422 // Get the elements array of the object.
1416 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1423 __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset));
1417 1424
1418 // Check that the elements are in fast mode and writable. 1425 // Check that the elements are in fast mode and writable.
1419 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset), 1426 __ Cmp(FieldOperand(rbx, HeapObject::kMapOffset),
1420 factory()->fixed_array_map()); 1427 factory()->fixed_array_map());
1421 __ j(not_equal, &call_builtin); 1428 __ j(not_equal, &call_builtin);
1422 1429
1423 if (argc == 1) { // Otherwise fall through to call builtin. 1430 if (argc == 1) { // Otherwise fall through to call builtin.
1424 Label exit, with_write_barrier, attempt_to_grow_elements; 1431 Label attempt_to_grow_elements, with_write_barrier;
1425 1432
1426 // Get the array's length into rax and calculate new length. 1433 // Get the array's length into rax and calculate new length.
1427 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 1434 __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset));
1428 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); 1435 STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue);
1429 __ addl(rax, Immediate(argc)); 1436 __ addl(rax, Immediate(argc));
1430 1437
1431 // Get the element's length into rcx. 1438 // Get the element's length into rcx.
1432 __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset)); 1439 __ SmiToInteger32(rcx, FieldOperand(rbx, FixedArray::kLengthOffset));
1433 1440
1434 // Check if we could survive without allocation. 1441 // Check if we could survive without allocation.
1435 __ cmpl(rax, rcx); 1442 __ cmpl(rax, rcx);
1436 __ j(greater, &attempt_to_grow_elements); 1443 __ j(greater, &attempt_to_grow_elements);
1437 1444
1445 // Check if value is a smi.
1446 __ movq(rcx, Operand(rsp, argc * kPointerSize));
1447 __ JumpIfNotSmi(rcx, &with_write_barrier);
1448
1438 // Save new length. 1449 // Save new length.
1439 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1450 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1440 1451
1441 // Push the element. 1452 // Push the element.
1442 __ movq(rcx, Operand(rsp, argc * kPointerSize));
1443 __ lea(rdx, FieldOperand(rbx, 1453 __ lea(rdx, FieldOperand(rbx,
1444 rax, times_pointer_size, 1454 rax, times_pointer_size,
1445 FixedArray::kHeaderSize - argc * kPointerSize)); 1455 FixedArray::kHeaderSize - argc * kPointerSize));
1446 __ movq(Operand(rdx, 0), rcx); 1456 __ movq(Operand(rdx, 0), rcx);
1447 1457
1448 // Check if value is a smi.
1449 __ Integer32ToSmi(rax, rax); // Return new length as smi. 1458 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1450
1451 __ JumpIfNotSmi(rcx, &with_write_barrier);
1452
1453 __ bind(&exit);
1454 __ ret((argc + 1) * kPointerSize); 1459 __ ret((argc + 1) * kPointerSize);
1455 1460
1456 __ bind(&with_write_barrier); 1461 __ bind(&with_write_barrier);
1457 1462
1458 __ InNewSpace(rbx, rcx, equal, &exit); 1463 if (FLAG_smi_only_arrays) {
1464 __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset));
1465 __ CheckFastObjectElements(rdi, &call_builtin);
1466 }
1459 1467
1460 __ RecordWriteHelper(rbx, rdx, rcx); 1468 // Save new length.
1469 __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1461 1470
1471 // Push the element.
1472 __ lea(rdx, FieldOperand(rbx,
1473 rax, times_pointer_size,
1474 FixedArray::kHeaderSize - argc * kPointerSize));
1475 __ movq(Operand(rdx, 0), rcx);
1476
1477 __ RecordWrite(
1478 rbx, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK);
1479
1480 __ Integer32ToSmi(rax, rax); // Return new length as smi.
1462 __ ret((argc + 1) * kPointerSize); 1481 __ ret((argc + 1) * kPointerSize);
1463 1482
1464 __ bind(&attempt_to_grow_elements); 1483 __ bind(&attempt_to_grow_elements);
1465 if (!FLAG_inline_new) { 1484 if (!FLAG_inline_new) {
1466 __ jmp(&call_builtin); 1485 __ jmp(&call_builtin);
1467 } 1486 }
1468 1487
1488 __ movq(rdi, Operand(rsp, argc * kPointerSize));
1489 if (FLAG_smi_only_arrays) {
1490 // Growing elements that are SMI-only requires special handling in case
1491 // the new element is non-Smi. For now, delegate to the builtin.
1492 Label no_fast_elements_check;
1493 __ JumpIfSmi(rdi, &no_fast_elements_check);
1494 __ movq(rsi, FieldOperand(rdx, HeapObject::kMapOffset));
1495 __ CheckFastObjectElements(rsi, &call_builtin, Label::kFar);
1496 __ bind(&no_fast_elements_check);
1497 }
1498
1469 ExternalReference new_space_allocation_top = 1499 ExternalReference new_space_allocation_top =
1470 ExternalReference::new_space_allocation_top_address(isolate()); 1500 ExternalReference::new_space_allocation_top_address(isolate());
1471 ExternalReference new_space_allocation_limit = 1501 ExternalReference new_space_allocation_limit =
1472 ExternalReference::new_space_allocation_limit_address(isolate()); 1502 ExternalReference::new_space_allocation_limit_address(isolate());
1473 1503
1474 const int kAllocationDelta = 4; 1504 const int kAllocationDelta = 4;
1475 // Load top. 1505 // Load top.
1476 __ Load(rcx, new_space_allocation_top); 1506 __ Load(rcx, new_space_allocation_top);
1477 1507
1478 // Check if it's the end of elements. 1508 // Check if it's the end of elements.
1479 __ lea(rdx, FieldOperand(rbx, 1509 __ lea(rdx, FieldOperand(rbx,
1480 rax, times_pointer_size, 1510 rax, times_pointer_size,
1481 FixedArray::kHeaderSize - argc * kPointerSize)); 1511 FixedArray::kHeaderSize - argc * kPointerSize));
1482 __ cmpq(rdx, rcx); 1512 __ cmpq(rdx, rcx);
1483 __ j(not_equal, &call_builtin); 1513 __ j(not_equal, &call_builtin);
1484 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); 1514 __ addq(rcx, Immediate(kAllocationDelta * kPointerSize));
1485 Operand limit_operand = 1515 Operand limit_operand =
1486 masm()->ExternalOperand(new_space_allocation_limit); 1516 masm()->ExternalOperand(new_space_allocation_limit);
1487 __ cmpq(rcx, limit_operand); 1517 __ cmpq(rcx, limit_operand);
1488 __ j(above, &call_builtin); 1518 __ j(above, &call_builtin);
1489 1519
1490 // We fit and could grow elements. 1520 // We fit and could grow elements.
1491 __ Store(new_space_allocation_top, rcx); 1521 __ Store(new_space_allocation_top, rcx);
1492 __ movq(rcx, Operand(rsp, argc * kPointerSize));
1493 1522
1494 // Push the argument... 1523 // Push the argument...
1495 __ movq(Operand(rdx, 0), rcx); 1524 __ movq(Operand(rdx, 0), rdi);
1496 // ... and fill the rest with holes. 1525 // ... and fill the rest with holes.
1497 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 1526 __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
1498 for (int i = 1; i < kAllocationDelta; i++) { 1527 for (int i = 1; i < kAllocationDelta; i++) {
1499 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); 1528 __ movq(Operand(rdx, i * kPointerSize), kScratchRegister);
1500 } 1529 }
1501 1530
1531 // We know the elements array is in new space so we don't need the
1532 // remembered set, but we just pushed a value onto it so we may have to
1533 // tell the incremental marker to rescan the object that we just grew. We
1534 // don't need to worry about the holes because they are in old space and
1535 // already marked black.
1536 __ RecordWrite(rbx, rdx, rdi, kDontSaveFPRegs, OMIT_REMEMBERED_SET);
1537
1502 // Restore receiver to rdx as finish sequence assumes it's here. 1538 // Restore receiver to rdx as finish sequence assumes it's here.
1503 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1539 __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize));
1504 1540
1505 // Increment element's and array's sizes. 1541 // Increment element's and array's sizes.
1506 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset), 1542 __ SmiAddConstant(FieldOperand(rbx, FixedArray::kLengthOffset),
1507 Smi::FromInt(kAllocationDelta)); 1543 Smi::FromInt(kAllocationDelta));
1508 1544
1509 // Make new length a smi before returning it. 1545 // Make new length a smi before returning it.
1510 __ Integer32ToSmi(rax, rax); 1546 __ Integer32ToSmi(rax, rax);
1511 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); 1547 __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax);
1512 1548
1513 // Elements are in new space, so write barrier is not required.
1514 __ ret((argc + 1) * kPointerSize); 1549 __ ret((argc + 1) * kPointerSize);
1515 } 1550 }
1516 1551
1517 __ bind(&call_builtin); 1552 __ bind(&call_builtin);
1518 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, 1553 __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush,
1519 isolate()), 1554 isolate()),
1520 argc + 1, 1555 argc + 1,
1521 1); 1556 1);
1522 } 1557 }
1523 1558
(...skipping 932 matching lines...) Expand 10 before | Expand all | Expand 10 after
2456 // -- rdx : receiver 2491 // -- rdx : receiver
2457 // -- rsp[0] : return address 2492 // -- rsp[0] : return address
2458 // ----------------------------------- 2493 // -----------------------------------
2459 Label miss; 2494 Label miss;
2460 2495
2461 // Check that the map of the global has not changed. 2496 // Check that the map of the global has not changed.
2462 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2497 __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset),
2463 Handle<Map>(object->map())); 2498 Handle<Map>(object->map()));
2464 __ j(not_equal, &miss); 2499 __ j(not_equal, &miss);
2465 2500
2501 // Compute the cell operand to use.
2502 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell));
2503 Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset);
2504
2466 // Check that the value in the cell is not the hole. If it is, this 2505 // Check that the value in the cell is not the hole. If it is, this
2467 // cell could have been deleted and reintroducing the global needs 2506 // cell could have been deleted and reintroducing the global needs
2468 // to update the property details in the property dictionary of the 2507 // to update the property details in the property dictionary of the
2469 // global object. We bail out to the runtime system to do that. 2508 // global object. We bail out to the runtime system to do that.
2470 __ Move(rbx, Handle<JSGlobalPropertyCell>(cell)); 2509 __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex);
2471 __ CompareRoot(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset),
2472 Heap::kTheHoleValueRootIndex);
2473 __ j(equal, &miss); 2510 __ j(equal, &miss);
2474 2511
2475 // Store the value in the cell. 2512 // Store the value in the cell.
2476 __ movq(FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset), rax); 2513 __ movq(cell_operand, rax);
2514 Label done;
2515 __ JumpIfSmi(rax, &done);
2516
2517 __ movq(rcx, rax);
2518 __ lea(rdx, cell_operand);
2519 // Cells are always in the remembered set.
2520 __ RecordWrite(rbx, // Object.
2521 rdx, // Address.
2522 rcx, // Value.
2523 kDontSaveFPRegs,
2524 OMIT_REMEMBERED_SET,
2525 OMIT_SMI_CHECK);
2526
2477 2527
2478 // Return the value (register rax). 2528 // Return the value (register rax).
2529 __ bind(&done);
2530
2479 Counters* counters = isolate()->counters(); 2531 Counters* counters = isolate()->counters();
2480 __ IncrementCounter(counters->named_store_global_inline(), 1); 2532 __ IncrementCounter(counters->named_store_global_inline(), 1);
2481 __ ret(0); 2533 __ ret(0);
2482 2534
2483 // Handle store cache miss. 2535 // Handle store cache miss.
2484 __ bind(&miss); 2536 __ bind(&miss);
2485 __ IncrementCounter(counters->named_store_global_inline_miss(), 1); 2537 __ IncrementCounter(counters->named_store_global_inline_miss(), 1);
2486 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2538 Handle<Code> ic = isolate()->builtins()->StoreIC_Miss();
2487 __ Jump(ic, RelocInfo::CODE_TARGET); 2539 __ Jump(ic, RelocInfo::CODE_TARGET);
2488 2540
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after
3429 // Need to perform int-to-float conversion. 3481 // Need to perform int-to-float conversion.
3430 __ cvtlsi2ss(xmm0, rdx); 3482 __ cvtlsi2ss(xmm0, rdx);
3431 __ movss(Operand(rbx, rdi, times_4, 0), xmm0); 3483 __ movss(Operand(rbx, rdi, times_4, 0), xmm0);
3432 break; 3484 break;
3433 case EXTERNAL_DOUBLE_ELEMENTS: 3485 case EXTERNAL_DOUBLE_ELEMENTS:
3434 // Need to perform int-to-float conversion. 3486 // Need to perform int-to-float conversion.
3435 __ cvtlsi2sd(xmm0, rdx); 3487 __ cvtlsi2sd(xmm0, rdx);
3436 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); 3488 __ movsd(Operand(rbx, rdi, times_8, 0), xmm0);
3437 break; 3489 break;
3438 case FAST_ELEMENTS: 3490 case FAST_ELEMENTS:
3491 case FAST_SMI_ONLY_ELEMENTS:
3439 case FAST_DOUBLE_ELEMENTS: 3492 case FAST_DOUBLE_ELEMENTS:
3440 case DICTIONARY_ELEMENTS: 3493 case DICTIONARY_ELEMENTS:
3441 case NON_STRICT_ARGUMENTS_ELEMENTS: 3494 case NON_STRICT_ARGUMENTS_ELEMENTS:
3442 UNREACHABLE(); 3495 UNREACHABLE();
3443 break; 3496 break;
3444 } 3497 }
3445 __ ret(0); 3498 __ ret(0);
3446 3499
3447 // TODO(danno): handle heap number -> pixel array conversion 3500 // TODO(danno): handle heap number -> pixel array conversion
3448 if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 3501 if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
3496 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3549 case EXTERNAL_UNSIGNED_INT_ELEMENTS:
3497 // Convert to int64, so that NaN and infinities become 3550 // Convert to int64, so that NaN and infinities become
3498 // 0x8000000000000000, which is zero mod 2^32. 3551 // 0x8000000000000000, which is zero mod 2^32.
3499 __ cvttsd2siq(rdx, xmm0); 3552 __ cvttsd2siq(rdx, xmm0);
3500 __ movl(Operand(rbx, rdi, times_4, 0), rdx); 3553 __ movl(Operand(rbx, rdi, times_4, 0), rdx);
3501 break; 3554 break;
3502 case EXTERNAL_PIXEL_ELEMENTS: 3555 case EXTERNAL_PIXEL_ELEMENTS:
3503 case EXTERNAL_FLOAT_ELEMENTS: 3556 case EXTERNAL_FLOAT_ELEMENTS:
3504 case EXTERNAL_DOUBLE_ELEMENTS: 3557 case EXTERNAL_DOUBLE_ELEMENTS:
3505 case FAST_ELEMENTS: 3558 case FAST_ELEMENTS:
3559 case FAST_SMI_ONLY_ELEMENTS:
3506 case FAST_DOUBLE_ELEMENTS: 3560 case FAST_DOUBLE_ELEMENTS:
3507 case DICTIONARY_ELEMENTS: 3561 case DICTIONARY_ELEMENTS:
3508 case NON_STRICT_ARGUMENTS_ELEMENTS: 3562 case NON_STRICT_ARGUMENTS_ELEMENTS:
3509 UNREACHABLE(); 3563 UNREACHABLE();
3510 break; 3564 break;
3511 } 3565 }
3512 __ ret(0); 3566 __ ret(0);
3513 } 3567 }
3514 } 3568 }
3515 3569
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
3627 masm->isolate()->builtins()->KeyedLoadIC_Slow(); 3681 masm->isolate()->builtins()->KeyedLoadIC_Slow();
3628 __ jmp(slow_ic, RelocInfo::CODE_TARGET); 3682 __ jmp(slow_ic, RelocInfo::CODE_TARGET);
3629 3683
3630 __ bind(&miss_force_generic); 3684 __ bind(&miss_force_generic);
3631 Handle<Code> miss_ic = 3685 Handle<Code> miss_ic =
3632 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3686 masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric();
3633 __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3687 __ jmp(miss_ic, RelocInfo::CODE_TARGET);
3634 } 3688 }
3635 3689
3636 3690
3637 void KeyedStoreStubCompiler::GenerateStoreFastElement(MacroAssembler* masm, 3691 void KeyedStoreStubCompiler::GenerateStoreFastElement(
3638 bool is_js_array) { 3692 MacroAssembler* masm,
3693 bool is_js_array,
3694 ElementsKind elements_kind) {
3639 // ----------- S t a t e ------------- 3695 // ----------- S t a t e -------------
3640 // -- rax : value 3696 // -- rax : value
3641 // -- rcx : key 3697 // -- rcx : key
3642 // -- rdx : receiver 3698 // -- rdx : receiver
3643 // -- rsp[0] : return address 3699 // -- rsp[0] : return address
3644 // ----------------------------------- 3700 // -----------------------------------
3645 Label miss_force_generic; 3701 Label miss_force_generic;
3646 3702
3647 // This stub is meant to be tail-jumped to, the receiver must already 3703 // This stub is meant to be tail-jumped to, the receiver must already
3648 // have been verified by the caller to not be a smi. 3704 // have been verified by the caller to not be a smi.
3649 3705
3650 // Check that the key is a smi. 3706 // Check that the key is a smi.
3651 __ JumpIfNotSmi(rcx, &miss_force_generic); 3707 __ JumpIfNotSmi(rcx, &miss_force_generic);
3652 3708
3653 // Get the elements array and make sure it is a fast element array, not 'cow'. 3709 // Get the elements array and make sure it is a fast element array, not 'cow'.
3654 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 3710 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3655 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), 3711 __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset),
3656 Heap::kFixedArrayMapRootIndex); 3712 Heap::kFixedArrayMapRootIndex);
3657 __ j(not_equal, &miss_force_generic); 3713 __ j(not_equal, &miss_force_generic);
3658 3714
3659 // Check that the key is within bounds. 3715 // Check that the key is within bounds.
3660 if (is_js_array) { 3716 if (is_js_array) {
3661 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 3717 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3662 __ j(above_equal, &miss_force_generic); 3718 __ j(above_equal, &miss_force_generic);
3663 } else { 3719 } else {
3664 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 3720 __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset));
3665 __ j(above_equal, &miss_force_generic); 3721 __ j(above_equal, &miss_force_generic);
3666 } 3722 }
3667 3723
3668 // Do the store and update the write barrier. Make sure to preserve 3724 // Do the store and update the write barrier.
3669 // the value in register eax. 3725 if (elements_kind == FAST_SMI_ONLY_ELEMENTS) {
3670 __ movq(rdx, rax); 3726 __ JumpIfNotSmi(rax, &miss_force_generic);
3671 __ SmiToInteger32(rcx, rcx); 3727 __ SmiToInteger32(rcx, rcx);
3672 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), 3728 __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize),
3673 rax); 3729 rax);
3674 __ RecordWrite(rdi, 0, rdx, rcx); 3730 } else {
3731 ASSERT(elements_kind == FAST_ELEMENTS);
3732 __ SmiToInteger32(rcx, rcx);
3733 __ lea(rcx,
3734 FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize));
3735 __ movq(Operand(rcx, 0), rax);
3736 // Make sure to preserve the value in register rax.
3737 __ movq(rdx, rax);
3738 __ RecordWrite(rdi, rcx, rdx, kDontSaveFPRegs);
3739 }
3675 3740
3676 // Done. 3741 // Done.
3677 __ ret(0); 3742 __ ret(0);
3678 3743
3679 // Handle store cache miss. 3744 // Handle store cache miss.
3680 __ bind(&miss_force_generic); 3745 __ bind(&miss_force_generic);
3681 Handle<Code> ic_force_generic = 3746 Handle<Code> ic_force_generic =
3682 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3747 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3683 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3748 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3684 } 3749 }
3685 3750
3686 3751
3687 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 3752 void KeyedStoreStubCompiler::GenerateStoreFastDoubleElement(
3688 MacroAssembler* masm, 3753 MacroAssembler* masm,
3689 bool is_js_array) { 3754 bool is_js_array) {
3690 // ----------- S t a t e ------------- 3755 // ----------- S t a t e -------------
3691 // -- rax : value 3756 // -- rax : value
3692 // -- rcx : key 3757 // -- rcx : key
3693 // -- rdx : receiver 3758 // -- rdx : receiver
3694 // -- rsp[0] : return address 3759 // -- rsp[0] : return address
3695 // ----------------------------------- 3760 // -----------------------------------
3696 Label miss_force_generic, smi_value, is_nan, maybe_nan; 3761 Label miss_force_generic;
3697 Label have_double_value, not_nan;
3698 3762
3699 // This stub is meant to be tail-jumped to, the receiver must already 3763 // This stub is meant to be tail-jumped to, the receiver must already
3700 // have been verified by the caller to not be a smi. 3764 // have been verified by the caller to not be a smi.
3701 3765
3702 // Check that the key is a smi. 3766 // Check that the key is a smi.
3703 __ JumpIfNotSmi(rcx, &miss_force_generic); 3767 __ JumpIfNotSmi(rcx, &miss_force_generic);
3704 3768
3705 // Get the elements array. 3769 // Get the elements array.
3706 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 3770 __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset));
3707 __ AssertFastElements(rdi); 3771 __ AssertFastElements(rdi);
3708 3772
3709 // Check that the key is within bounds. 3773 // Check that the key is within bounds.
3710 if (is_js_array) { 3774 if (is_js_array) {
3711 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 3775 __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset));
3712 } else { 3776 } else {
3713 __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); 3777 __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset));
3714 } 3778 }
3715 __ j(above_equal, &miss_force_generic); 3779 __ j(above_equal, &miss_force_generic);
3716 3780
3717 // Handle smi values specially 3781 // Handle smi values specially
3718 __ JumpIfSmi(rax, &smi_value, Label::kNear);
3719
3720 __ CheckMap(rax,
3721 masm->isolate()->factory()->heap_number_map(),
3722 &miss_force_generic,
3723 DONT_DO_SMI_CHECK);
3724
3725 // Double value, canonicalize NaN.
3726 uint32_t offset = HeapNumber::kValueOffset + sizeof(kHoleNanLower32);
3727 __ cmpl(FieldOperand(rax, offset),
3728 Immediate(kNaNOrInfinityLowerBoundUpper32));
3729 __ j(greater_equal, &maybe_nan, Label::kNear);
3730
3731 __ bind(&not_nan);
3732 __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset));
3733 __ bind(&have_double_value);
3734 __ SmiToInteger32(rcx, rcx); 3782 __ SmiToInteger32(rcx, rcx);
3735 __ movsd(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize), 3783 __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, &miss_force_generic);
3736 xmm0);
3737 __ ret(0);
3738
3739 __ bind(&maybe_nan);
3740 // Could be NaN or Infinity. If fraction is not zero, it's NaN, otherwise
3741 // it's an Infinity, and the non-NaN code path applies.
3742 __ j(greater, &is_nan, Label::kNear);
3743 __ cmpl(FieldOperand(rax, HeapNumber::kValueOffset), Immediate(0));
3744 __ j(zero, &not_nan);
3745 __ bind(&is_nan);
3746 // Convert all NaNs to the same canonical NaN value when they are stored in
3747 // the double array.
3748 __ Set(kScratchRegister, BitCast<uint64_t>(
3749 FixedDoubleArray::canonical_not_the_hole_nan_as_double()));
3750 __ movq(xmm0, kScratchRegister);
3751 __ jmp(&have_double_value, Label::kNear);
3752
3753 __ bind(&smi_value);
3754 // Value is a smi. convert to a double and store.
3755 // Preserve original value.
3756 __ SmiToInteger32(rdx, rax);
3757 __ push(rdx);
3758 __ fild_s(Operand(rsp, 0));
3759 __ pop(rdx);
3760 __ SmiToInteger32(rcx, rcx);
3761 __ fstp_d(FieldOperand(rdi, rcx, times_8, FixedDoubleArray::kHeaderSize));
3762 __ ret(0); 3784 __ ret(0);
3763 3785
3764 // Handle store cache miss, replacing the ic with the generic stub. 3786 // Handle store cache miss, replacing the ic with the generic stub.
3765 __ bind(&miss_force_generic); 3787 __ bind(&miss_force_generic);
3766 Handle<Code> ic_force_generic = 3788 Handle<Code> ic_force_generic =
3767 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3789 masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric();
3768 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 3790 __ jmp(ic_force_generic, RelocInfo::CODE_TARGET);
3769 } 3791 }
3770 3792
3771 3793
3772 #undef __ 3794 #undef __
3773 3795
3774 } } // namespace v8::internal 3796 } } // namespace v8::internal
3775 3797
3776 #endif // V8_TARGET_ARCH_X64 3798 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/regexp-macro-assembler-x64.cc ('k') | test/cctest/cctest.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698