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

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

Issue 2470001: Change keyed load IC interface on x64 to pass arguments in registers. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 6 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/builtins-x64.cc ('k') | src/x64/debug-x64.cc » ('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 642 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 653
654 private: 654 private:
655 Label patch_site_; 655 Label patch_site_;
656 Register dst_; 656 Register dst_;
657 Register receiver_; 657 Register receiver_;
658 Register key_; 658 Register key_;
659 }; 659 };
660 660
661 661
662 void DeferredReferenceGetKeyedValue::Generate() { 662 void DeferredReferenceGetKeyedValue::Generate() {
663 __ push(receiver_); // First IC argument. 663 if (receiver_.is(rdx)) {
664 __ push(key_); // Second IC argument. 664 if (!key_.is(rax)) {
665 665 __ movq(rax, key_);
666 } // else do nothing.
667 } else if (receiver_.is(rax)) {
668 if (key_.is(rdx)) {
669 __ xchg(rax, rdx);
670 } else if (key_.is(rax)) {
671 __ movq(rdx, receiver_);
672 } else {
673 __ movq(rdx, receiver_);
674 __ movq(rax, key_);
675 }
676 } else if (key_.is(rax)) {
677 __ movq(rdx, receiver_);
678 } else {
679 __ movq(rax, key_);
680 __ movq(rdx, receiver_);
681 }
666 // Calculate the delta from the IC call instruction to the map check 682 // Calculate the delta from the IC call instruction to the map check
667 // movq instruction in the inlined version. This delta is stored in 683 // movq instruction in the inlined version. This delta is stored in
668 // a test(rax, delta) instruction after the call so that we can find 684 // a test(rax, delta) instruction after the call so that we can find
669 // it in the IC initialization code and patch the movq instruction. 685 // it in the IC initialization code and patch the movq instruction.
670 // This means that we cannot allow test instructions after calls to 686 // This means that we cannot allow test instructions after calls to
671 // KeyedLoadIC stubs in other places. 687 // KeyedLoadIC stubs in other places.
672 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize)); 688 Handle<Code> ic(Builtins::builtin(Builtins::KeyedLoadIC_Initialize));
673 __ Call(ic, RelocInfo::CODE_TARGET); 689 __ Call(ic, RelocInfo::CODE_TARGET);
674 // The delta from the start of the map-compare instruction to the 690 // The delta from the start of the map-compare instruction to the
675 // test instruction. We use masm_-> directly here instead of the __ 691 // test instruction. We use masm_-> directly here instead of the __
676 // macro because the macro sometimes uses macro expansion to turn 692 // macro because the macro sometimes uses macro expansion to turn
677 // into something that can't return a value. This is encountered 693 // into something that can't return a value. This is encountered
678 // when doing generated code coverage tests. 694 // when doing generated code coverage tests.
679 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site()); 695 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(patch_site());
680 // Here we use masm_-> instead of the __ macro because this is the 696 // Here we use masm_-> instead of the __ macro because this is the
681 // instruction that gets patched and coverage code gets in the way. 697 // instruction that gets patched and coverage code gets in the way.
682 // TODO(X64): Consider whether it's worth switching the test to a 698 // TODO(X64): Consider whether it's worth switching the test to a
683 // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't 699 // 7-byte NOP with non-zero immediate (0f 1f 80 xxxxxxxx) which won't
684 // be generated normally. 700 // be generated normally.
685 masm_->testl(rax, Immediate(-delta_to_patch_site)); 701 masm_->testl(rax, Immediate(-delta_to_patch_site));
686 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1); 702 __ IncrementCounter(&Counters::keyed_load_inline_miss, 1);
687 703
688 if (!dst_.is(rax)) __ movq(dst_, rax); 704 if (!dst_.is(rax)) __ movq(dst_, rax);
689 __ pop(key_);
690 __ pop(receiver_);
691 } 705 }
692 706
693 707
694 class DeferredReferenceSetKeyedValue: public DeferredCode { 708 class DeferredReferenceSetKeyedValue: public DeferredCode {
695 public: 709 public:
696 DeferredReferenceSetKeyedValue(Register value, 710 DeferredReferenceSetKeyedValue(Register value,
697 Register key, 711 Register key,
698 Register receiver) 712 Register receiver)
699 : value_(value), key_(key), receiver_(receiver) { 713 : value_(value), key_(key), receiver_(receiver) {
700 set_comment("[ DeferredReferenceSetKeyedValue"); 714 set_comment("[ DeferredReferenceSetKeyedValue");
(...skipping 5144 matching lines...) Expand 10 before | Expand all | Expand 10 after
5845 // object using keyed load. 5859 // object using keyed load.
5846 Result arguments = allocator()->Allocate(); 5860 Result arguments = allocator()->Allocate();
5847 ASSERT(arguments.is_valid()); 5861 ASSERT(arguments.is_valid());
5848 __ movq(arguments.reg(), 5862 __ movq(arguments.reg(),
5849 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(), 5863 ContextSlotOperandCheckExtensions(obj_proxy->var()->slot(),
5850 arguments, 5864 arguments,
5851 slow)); 5865 slow));
5852 frame_->Push(&arguments); 5866 frame_->Push(&arguments);
5853 frame_->Push(key_literal->handle()); 5867 frame_->Push(key_literal->handle());
5854 *result = EmitKeyedLoad(); 5868 *result = EmitKeyedLoad();
5855 frame_->Drop(2); // Drop key and receiver.
5856 done->Jump(result); 5869 done->Jump(result);
5857 } 5870 }
5858 } 5871 }
5859 } 5872 }
5860 } 5873 }
5861 } 5874 }
5862 5875
5863 5876
5864 void CodeGenerator::LoadGlobal() { 5877 void CodeGenerator::LoadGlobal() {
5865 if (in_spilled_code()) { 5878 if (in_spilled_code()) {
(...skipping 1574 matching lines...) Expand 10 before | Expand all | Expand 10 after
7440 // the receiver which is needed for the deferred slow case. 7453 // the receiver which is needed for the deferred slow case.
7441 // Allocate the temporary early so that we use rax if it is free. 7454 // Allocate the temporary early so that we use rax if it is free.
7442 Result elements = allocator()->Allocate(); 7455 Result elements = allocator()->Allocate();
7443 ASSERT(elements.is_valid()); 7456 ASSERT(elements.is_valid());
7444 7457
7445 Result key = frame_->Pop(); 7458 Result key = frame_->Pop();
7446 Result receiver = frame_->Pop(); 7459 Result receiver = frame_->Pop();
7447 key.ToRegister(); 7460 key.ToRegister();
7448 receiver.ToRegister(); 7461 receiver.ToRegister();
7449 7462
7463 // If key and receiver are shared registers on the frame, their values will
7464 // be automatically saved and restored when going to deferred code.
7465 // The result is returned in elements, which is not shared.
7450 DeferredReferenceGetKeyedValue* deferred = 7466 DeferredReferenceGetKeyedValue* deferred =
7451 new DeferredReferenceGetKeyedValue(elements.reg(), 7467 new DeferredReferenceGetKeyedValue(elements.reg(),
7452 receiver.reg(), 7468 receiver.reg(),
7453 key.reg()); 7469 key.reg());
7454 7470
7455 __ JumpIfSmi(receiver.reg(), deferred->entry_label()); 7471 __ JumpIfSmi(receiver.reg(), deferred->entry_label());
7456 7472
7457 // Check that the receiver has the expected map. 7473 // Check that the receiver has the expected map.
7458 // Initially, use an invalid map. The map is patched in the IC 7474 // Initially, use an invalid map. The map is patched in the IC
7459 // initialization code. 7475 // initialization code.
7460 __ bind(deferred->patch_site()); 7476 __ bind(deferred->patch_site());
7461 // Use masm-> here instead of the double underscore macro since extra 7477 // Use masm-> here instead of the double underscore macro since extra
7462 // coverage code can interfere with the patching. Do not use 7478 // coverage code can interfere with the patching. Do not use a load
7463 // root array to load null_value, since it must be patched with 7479 // from the root away to load null_value, since the load must be patched
7464 // the expected receiver map. 7480 // with the expected receiver map, which is not in the root array.
7465 masm_->movq(kScratchRegister, Factory::null_value(), 7481 masm_->movq(kScratchRegister, Factory::null_value(),
7466 RelocInfo::EMBEDDED_OBJECT); 7482 RelocInfo::EMBEDDED_OBJECT);
7467 masm_->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset), 7483 masm_->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
7468 kScratchRegister); 7484 kScratchRegister);
7469 deferred->Branch(not_equal); 7485 deferred->Branch(not_equal);
7470 7486
7471 // Check that the key is a non-negative smi. 7487 // Check that the key is a non-negative smi.
7472 __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label()); 7488 __ JumpIfNotPositiveSmi(key.reg(), deferred->entry_label());
7473 7489
7474 // Get the elements array from the receiver and check that it 7490 // Get the elements array from the receiver and check that it
(...skipping 22 matching lines...) Expand all
7497 FieldOperand(elements.reg(), 7513 FieldOperand(elements.reg(),
7498 index.reg, 7514 index.reg,
7499 index.scale, 7515 index.scale,
7500 FixedArray::kHeaderSize)); 7516 FixedArray::kHeaderSize));
7501 result = elements; 7517 result = elements;
7502 __ CompareRoot(result.reg(), Heap::kTheHoleValueRootIndex); 7518 __ CompareRoot(result.reg(), Heap::kTheHoleValueRootIndex);
7503 deferred->Branch(equal); 7519 deferred->Branch(equal);
7504 __ IncrementCounter(&Counters::keyed_load_inline, 1); 7520 __ IncrementCounter(&Counters::keyed_load_inline, 1);
7505 7521
7506 deferred->BindExit(); 7522 deferred->BindExit();
7507 frame_->Push(&receiver);
7508 frame_->Push(&key);
7509 } else { 7523 } else {
7510 Comment cmnt(masm_, "[ Load from keyed Property"); 7524 Comment cmnt(masm_, "[ Load from keyed Property");
7511 result = frame_->CallKeyedLoadIC(RelocInfo::CODE_TARGET); 7525 result = frame_->CallKeyedLoadIC(RelocInfo::CODE_TARGET);
7512 // Make sure that we do not have a test instruction after the 7526 // Make sure that we do not have a test instruction after the
7513 // call. A test instruction after the call is used to 7527 // call. A test instruction after the call is used to
7514 // indicate that we have generated an inline version of the 7528 // indicate that we have generated an inline version of the
7515 // keyed load. The explicit nop instruction is here because 7529 // keyed load. The explicit nop instruction is here because
7516 // the push that follows might be peep-hole optimized away. 7530 // the push that follows might be peep-hole optimized away.
7517 __ nop(); 7531 __ nop();
7518 } 7532 }
7519 ASSERT(frame()->height() == original_height); 7533 ASSERT(frame()->height() == original_height - 2);
7520 return result; 7534 return result;
7521 } 7535 }
7522 7536
7523 7537
7524 #undef __ 7538 #undef __
7525 #define __ ACCESS_MASM(masm) 7539 #define __ ACCESS_MASM(masm)
7526 7540
7527 7541
7528 Handle<String> Reference::GetName() { 7542 Handle<String> Reference::GetName() {
7529 ASSERT(type_ == NAMED); 7543 ASSERT(type_ == NAMED);
(...skipping 23 matching lines...) Expand all
7553 if (property != NULL) { 7567 if (property != NULL) {
7554 cgen_->CodeForSourcePosition(property->position()); 7568 cgen_->CodeForSourcePosition(property->position());
7555 } 7569 }
7556 7570
7557 switch (type_) { 7571 switch (type_) {
7558 case SLOT: { 7572 case SLOT: {
7559 Comment cmnt(masm, "[ Load from Slot"); 7573 Comment cmnt(masm, "[ Load from Slot");
7560 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot(); 7574 Slot* slot = expression_->AsVariableProxy()->AsVariable()->slot();
7561 ASSERT(slot != NULL); 7575 ASSERT(slot != NULL);
7562 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF); 7576 cgen_->LoadFromSlotCheckForArguments(slot, NOT_INSIDE_TYPEOF);
7563 if (!persist_after_get_) set_unloaded();
7564 break; 7577 break;
7565 } 7578 }
7566 7579
7567 case NAMED: { 7580 case NAMED: {
7568 Variable* var = expression_->AsVariableProxy()->AsVariable(); 7581 Variable* var = expression_->AsVariableProxy()->AsVariable();
7569 bool is_global = var != NULL; 7582 bool is_global = var != NULL;
7570 ASSERT(!is_global || var->is_global()); 7583 ASSERT(!is_global || var->is_global());
7571 if (persist_after_get_) { 7584 if (persist_after_get_) {
7572 cgen_->frame()->Dup(); 7585 cgen_->frame()->Dup();
7573 } 7586 }
7574 Result result = cgen_->EmitNamedLoad(GetName(), is_global); 7587 Result result = cgen_->EmitNamedLoad(GetName(), is_global);
7575 cgen_->frame()->Push(&result); 7588 cgen_->frame()->Push(&result);
7576 if (!persist_after_get_) {
7577 set_unloaded();
7578 }
7579 break; 7589 break;
7580 } 7590 }
7581 7591
7582 case KEYED: { 7592 case KEYED: {
7583 // A load of a bare identifier (load from global) cannot be keyed. 7593 // A load of a bare identifier (load from global) cannot be keyed.
7584 ASSERT(expression_->AsVariableProxy()->AsVariable() == NULL); 7594 ASSERT(expression_->AsVariableProxy()->AsVariable() == NULL);
7585 7595 if (persist_after_get_) {
7596 cgen_->frame()->PushElementAt(1);
7597 cgen_->frame()->PushElementAt(1);
7598 }
7586 Result value = cgen_->EmitKeyedLoad(); 7599 Result value = cgen_->EmitKeyedLoad();
7587 cgen_->frame()->Push(&value); 7600 cgen_->frame()->Push(&value);
7588 if (!persist_after_get_) {
7589 cgen_->UnloadReference(this);
7590 }
7591 break; 7601 break;
7592 } 7602 }
7593 7603
7594 default: 7604 default:
7595 UNREACHABLE(); 7605 UNREACHABLE();
7596 } 7606 }
7607
7608 if (!persist_after_get_) {
7609 set_unloaded();
7610 }
7597 } 7611 }
7598 7612
7599 7613
7600 void Reference::TakeValue() { 7614 void Reference::TakeValue() {
7601 // TODO(X64): This function is completely architecture independent. Move 7615 // TODO(X64): This function is completely architecture independent. Move
7602 // it somewhere shared. 7616 // it somewhere shared.
7603 7617
7604 // For non-constant frame-allocated slots, we invalidate the value in the 7618 // For non-constant frame-allocated slots, we invalidate the value in the
7605 // slot. For all others, we fall back on GetValue. 7619 // slot. For all others, we fall back on GetValue.
7606 ASSERT(!cgen_->in_spilled_code()); 7620 ASSERT(!cgen_->in_spilled_code());
(...skipping 4250 matching lines...) Expand 10 before | Expand all | Expand 10 after
11857 } 11871 }
11858 11872
11859 #endif 11873 #endif
11860 11874
11861 11875
11862 #undef __ 11876 #undef __
11863 11877
11864 } } // namespace v8::internal 11878 } } // namespace v8::internal
11865 11879
11866 #endif // V8_TARGET_ARCH_X64 11880 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/debug-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698