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

Side by Side Diff: src/ia32/codegen-ia32.cc

Issue 1709008: Introduce faster swapping primitives. (Closed)
Patch Set: Stub ports to x64 and ARM Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ic.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 2010 the V8 project authors. All rights reserved. 1 // Copyright 2010 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 6589 matching lines...) Expand 10 before | Expand all | Expand 10 after
6600 ASSERT_EQ(args->length(), 1); 6600 ASSERT_EQ(args->length(), 1);
6601 6601
6602 // Load the argument on the stack and call the stub. 6602 // Load the argument on the stack and call the stub.
6603 Load(args->at(0)); 6603 Load(args->at(0));
6604 NumberToStringStub stub; 6604 NumberToStringStub stub;
6605 Result result = frame_->CallStub(&stub, 1); 6605 Result result = frame_->CallStub(&stub, 1);
6606 frame_->Push(&result); 6606 frame_->Push(&result);
6607 } 6607 }
6608 6608
6609 6609
6610 class DeferredSwapElements: public DeferredCode {
6611 public:
6612 DeferredSwapElements(Register object, Register index1, Register index2)
6613 : object_(object), index1_(index1), index2_(index2) {
6614 set_comment("[ DeferredSwapElements");
6615 }
6616
6617 virtual void Generate();
6618
6619 private:
6620 Register object_, index1_, index2_;
6621 };
6622
6623
6624 void DeferredSwapElements::Generate() {
6625 __ push(object_);
6626 __ push(index1_);
6627 __ push(index2_);
6628 __ CallRuntime(Runtime::kSwapElements, 3);
6629 }
6630
6631
6632 void CodeGenerator::GenerateSwapElements(ZoneList<Expression*>* args) {
6633 // Note: this code assumes that indices are passed are within
6634 // elements' bounds and refer to valid (not holes) values.
6635 Comment cmnt(masm_, "[ GenerateSwapElements");
6636
6637 ASSERT_EQ(3, args->length());
6638
6639 Load(args->at(0));
6640 Load(args->at(1));
6641 Load(args->at(2));
6642
6643 Result index2 = frame_->Pop();
6644 index2.ToRegister();
6645
6646 Result index1 = frame_->Pop();
6647 index1.ToRegister();
6648
6649 Result object = frame_->Pop();
6650 object.ToRegister();
6651
6652 Result tmp1 = allocator()->Allocate();
6653 tmp1.ToRegister();
6654 Result tmp2 = allocator()->Allocate();
6655 tmp2.ToRegister();
6656
6657 frame_->Spill(object.reg());
6658 frame_->Spill(index1.reg());
6659 frame_->Spill(index2.reg());
6660
6661 DeferredSwapElements* deferred = new DeferredSwapElements(object.reg(),
6662 index1.reg(),
6663 index2.reg());
6664
6665 // Fetch the map and check if array is in fast case.
6666 // Check that object doesn't require security checks and
6667 // has no indexed interceptor.
6668 __ CmpObjectType(object.reg(), FIRST_JS_OBJECT_TYPE, tmp1.reg());
6669 deferred->Branch(less);
6670 __ movzx_b(tmp1.reg(), FieldOperand(tmp1.reg(), Map::kBitFieldOffset));
6671 __ test(tmp1.reg(), Immediate(KeyedLoadIC::kSlowCaseBitFieldMask));
6672 deferred->Branch(not_zero);
6673
6674 // Check the object's elements are in fast case.
6675 __ mov(tmp1.reg(), FieldOperand(object.reg(), JSObject::kElementsOffset));
6676 __ cmp(FieldOperand(tmp1.reg(), HeapObject::kMapOffset),
6677 Immediate(Factory::fixed_array_map()));
6678 deferred->Branch(not_equal);
6679
6680 // Smi-tagging is equivalent to multiplying by 2.
6681 STATIC_ASSERT(kSmiTag == 0);
6682 STATIC_ASSERT(kSmiTagSize == 1);
6683
6684 // Check that both indices are smis.
6685 __ mov(tmp2.reg(), index1.reg());
6686 __ or_(tmp2.reg(), Operand(index2.reg()));
6687 __ test(tmp2.reg(), Immediate(kSmiTagMask));
6688 deferred->Branch(not_zero);
6689
6690 // Bring addresses into index1 and index2.
6691 __ lea(index1.reg(), FieldOperand(tmp1.reg(),
6692 index1.reg(),
6693 times_half_pointer_size, // index1 is Smi
6694 FixedArray::kHeaderSize));
6695 __ lea(index2.reg(), FieldOperand(tmp1.reg(),
6696 index2.reg(),
6697 times_half_pointer_size, // index2 is Smi
6698 FixedArray::kHeaderSize));
6699
6700 // Swap elements.
6701 __ mov(object.reg(), Operand(index1.reg(), 0));
6702 __ mov(tmp2.reg(), Operand(index2.reg(), 0));
6703 __ mov(Operand(index2.reg(), 0), object.reg());
6704 __ mov(Operand(index1.reg(), 0), tmp2.reg());
6705
6706 Label done;
6707 __ InNewSpace(tmp1.reg(), tmp2.reg(), equal, &done);
6708 // Possible optimization: do a check that both values are Smis
6709 // (or them and test against Smi mask.)
6710
6711 __ mov(tmp2.reg(), tmp1.reg());
6712 RecordWriteStub recordWrite1(tmp2.reg(), index1.reg(), object.reg());
6713 __ CallStub(&recordWrite1);
6714
6715 RecordWriteStub recordWrite2(tmp1.reg(), index2.reg(), object.reg());
6716 __ CallStub(&recordWrite2);
6717
6718 __ bind(&done);
6719
6720 deferred->BindExit();
6721 frame_->Push(Factory::undefined_value());
6722 }
6723
6724
6610 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) { 6725 void CodeGenerator::GenerateCallFunction(ZoneList<Expression*>* args) {
6611 Comment cmnt(masm_, "[ GenerateCallFunction"); 6726 Comment cmnt(masm_, "[ GenerateCallFunction");
6612 6727
6613 ASSERT(args->length() >= 2); 6728 ASSERT(args->length() >= 2);
6614 6729
6615 int n_args = args->length() - 2; // for receiver and function. 6730 int n_args = args->length() - 2; // for receiver and function.
6616 Load(args->at(0)); // receiver 6731 Load(args->at(0)); // receiver
6617 for (int i = 0; i < n_args; i++) { 6732 for (int i = 0; i < n_args; i++) {
6618 Load(args->at(i + 1)); 6733 Load(args->at(i + 1));
6619 } 6734 }
(...skipping 6307 matching lines...) Expand 10 before | Expand all | Expand 10 after
12927 13042
12928 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater) 13043 // Call the runtime; it returns -1 (less), 0 (equal), or 1 (greater)
12929 // tagged as a small integer. 13044 // tagged as a small integer.
12930 __ bind(&runtime); 13045 __ bind(&runtime);
12931 __ TailCallRuntime(Runtime::kStringCompare, 2, 1); 13046 __ TailCallRuntime(Runtime::kStringCompare, 2, 1);
12932 } 13047 }
12933 13048
12934 #undef __ 13049 #undef __
12935 13050
12936 } } // namespace v8::internal 13051 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/ia32/codegen-ia32.h ('k') | src/ic.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698