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

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

Issue 3008017: Port inline in-object property stores from ia32 to x64. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 10 years, 5 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/ic-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 4822 matching lines...) Expand 10 before | Expand all | Expand 10 after
4833 break; 4833 break;
4834 case ObjectLiteral::Property::MATERIALIZED_LITERAL: 4834 case ObjectLiteral::Property::MATERIALIZED_LITERAL:
4835 if (CompileTimeValue::IsCompileTimeValue(property->value())) break; 4835 if (CompileTimeValue::IsCompileTimeValue(property->value())) break;
4836 // else fall through. 4836 // else fall through.
4837 case ObjectLiteral::Property::COMPUTED: { 4837 case ObjectLiteral::Property::COMPUTED: {
4838 Handle<Object> key(property->key()->handle()); 4838 Handle<Object> key(property->key()->handle());
4839 if (key->IsSymbol()) { 4839 if (key->IsSymbol()) {
4840 // Duplicate the object as the IC receiver. 4840 // Duplicate the object as the IC receiver.
4841 frame_->Dup(); 4841 frame_->Dup();
4842 Load(property->value()); 4842 Load(property->value());
4843 frame_->Push(key); 4843 Result ignored =
4844 Result ignored = frame_->CallStoreIC(); 4844 frame_->CallStoreIC(Handle<String>::cast(key), false);
4845 // A test rax instruction following the store IC call would
4846 // indicate the presence of an inlined version of the
4847 // store. Add a nop to indicate that there is no such
4848 // inlined version.
4849 __ nop();
4845 break; 4850 break;
4846 } 4851 }
4847 // Fall through 4852 // Fall through
4848 } 4853 }
4849 case ObjectLiteral::Property::PROTOTYPE: { 4854 case ObjectLiteral::Property::PROTOTYPE: {
4850 // Duplicate the object as an argument to the runtime call. 4855 // Duplicate the object as an argument to the runtime call.
4851 frame_->Dup(); 4856 frame_->Dup();
4852 Load(property->key()); 4857 Load(property->key());
4853 Load(property->value()); 4858 Load(property->value());
4854 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3); 4859 Result ignored = frame_->CallRuntime(Runtime::kSetProperty, 3);
(...skipping 3130 matching lines...) Expand 10 before | Expand all | Expand 10 after
7985 ASSERT(frame()->height() == original_height - 1); 7990 ASSERT(frame()->height() == original_height - 1);
7986 return result; 7991 return result;
7987 } 7992 }
7988 7993
7989 7994
7990 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) { 7995 Result CodeGenerator::EmitNamedStore(Handle<String> name, bool is_contextual) {
7991 #ifdef DEBUG 7996 #ifdef DEBUG
7992 int expected_height = frame()->height() - (is_contextual ? 1 : 2); 7997 int expected_height = frame()->height() - (is_contextual ? 1 : 2);
7993 #endif 7998 #endif
7994 7999
7995 Result result = frame()->CallStoreIC(name, is_contextual); 8000 Result result;
7996 // A test rax instruction following the call signals that the inobject 8001 if (is_contextual || scope()->is_global_scope() || loop_nesting() == 0) {
7997 // property case was inlined. Ensure that there is not a test rax 8002 result = frame()->CallStoreIC(name, is_contextual);
7998 // instruction here. 8003 // A test rax instruction following the call signals that the inobject
7999 __ nop(); 8004 // property case was inlined. Ensure that there is not a test rax
8005 // instruction here.
8006 __ nop();
8007 } else {
8008 // Inline the in-object property case.
8009 JumpTarget slow, done;
8010 Label patch_site;
8011
8012 // Get the value and receiver from the stack.
8013 Result value = frame()->Pop();
8014 value.ToRegister();
8015 Result receiver = frame()->Pop();
8016 receiver.ToRegister();
8017
8018 // Allocate result register.
8019 result = allocator()->Allocate();
8020 ASSERT(result.is_valid() && receiver.is_valid() && value.is_valid());
8021
8022 // Check that the receiver is a heap object.
8023 Condition is_smi = __ CheckSmi(receiver.reg());
8024 slow.Branch(is_smi, &value, &receiver);
8025
8026 // This is the map check instruction that will be patched.
8027 // Initially use an invalid map to force a failure. The exact
8028 // instruction sequence is important because we use the
8029 // kOffsetToStoreInstruction constant for patching. We avoid using
8030 // the __ macro for the following two instructions because it
8031 // might introduce extra instructions.
8032 __ bind(&patch_site);
8033 masm()->Move(kScratchRegister, Factory::null_value());
8034 masm()->cmpq(FieldOperand(receiver.reg(), HeapObject::kMapOffset),
8035 kScratchRegister);
8036 // This branch is always a forwards branch so it's always a fixed size
8037 // which allows the assert below to succeed and patching to work.
8038 slow.Branch(not_equal, &value, &receiver);
8039
8040 // The delta from the patch label to the store offset must be
8041 // statically known.
8042 ASSERT(masm()->SizeOfCodeGeneratedSince(&patch_site) ==
8043 StoreIC::kOffsetToStoreInstruction);
8044
8045 // The initial (invalid) offset has to be large enough to force a 32-bit
8046 // instruction encoding to allow patching with an arbitrary offset. Use
8047 // kMaxInt (minus kHeapObjectTag).
8048 int offset = kMaxInt;
8049 __ movq(FieldOperand(receiver.reg(), offset), value.reg());
8050 __ movq(result.reg(), value.reg());
8051
8052 // Allocate scratch register for write barrier.
8053 Result scratch = allocator()->Allocate();
8054 ASSERT(scratch.is_valid() &&
8055 result.is_valid() &&
8056 receiver.is_valid() &&
8057 value.is_valid());
8058
8059 // The write barrier clobbers all input registers, so spill the
8060 // receiver and the value.
8061 frame_->Spill(receiver.reg());
8062 frame_->Spill(value.reg());
8063
8064 // Update the write barrier. To save instructions in the inlined
8065 // version we do not filter smis.
8066 Label skip_write_barrier;
8067 __ InNewSpace(receiver.reg(), value.reg(), equal, &skip_write_barrier);
8068 int delta_to_record_write = masm_->SizeOfCodeGeneratedSince(&patch_site);
8069 __ lea(scratch.reg(), Operand(receiver.reg(), offset));
8070 __ RecordWriteHelper(receiver.reg(), scratch.reg(), value.reg());
8071 if (FLAG_debug_code) {
8072 __ movq(receiver.reg(), Immediate(BitCast<int64_t>(kZapValue)));
8073 __ movq(value.reg(), Immediate(BitCast<int64_t>(kZapValue)));
8074 __ movq(scratch.reg(), Immediate(BitCast<int64_t>(kZapValue)));
8075 }
8076 __ bind(&skip_write_barrier);
8077 value.Unuse();
8078 scratch.Unuse();
8079 receiver.Unuse();
8080 done.Jump(&result);
8081
8082 slow.Bind(&value, &receiver);
8083 frame()->Push(&receiver);
8084 frame()->Push(&value);
8085 result = frame()->CallStoreIC(name, is_contextual);
8086 // Encode the offset to the map check instruction and the offset
8087 // to the write barrier store address computation in a test rax
8088 // instruction.
8089 int delta_to_patch_site = masm_->SizeOfCodeGeneratedSince(&patch_site);
8090 __ testl(rax,
8091 Immediate((delta_to_record_write << 16) | delta_to_patch_site));
8092 done.Bind(&result);
8093 }
8000 8094
8001 ASSERT_EQ(expected_height, frame()->height()); 8095 ASSERT_EQ(expected_height, frame()->height());
8002 return result; 8096 return result;
8003 } 8097 }
8004 8098
8005 8099
8006 Result CodeGenerator::EmitKeyedLoad() { 8100 Result CodeGenerator::EmitKeyedLoad() {
8007 #ifdef DEBUG 8101 #ifdef DEBUG
8008 int original_height = frame()->height(); 8102 int original_height = frame()->height();
8009 #endif 8103 #endif
(...skipping 1581 matching lines...) Expand 10 before | Expand all | Expand 10 after
9591 // If the argument is undefined it converts to zero (ECMA-262, section 9.5). 9685 // If the argument is undefined it converts to zero (ECMA-262, section 9.5).
9592 __ bind(&check_undefined_arg2); 9686 __ bind(&check_undefined_arg2);
9593 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex); 9687 __ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
9594 __ j(not_equal, conversion_failure); 9688 __ j(not_equal, conversion_failure);
9595 __ movl(rcx, Immediate(0)); 9689 __ movl(rcx, Immediate(0));
9596 __ jmp(&done); 9690 __ jmp(&done);
9597 9691
9598 __ bind(&arg2_is_object); 9692 __ bind(&arg2_is_object);
9599 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map); 9693 __ cmpq(FieldOperand(rax, HeapObject::kMapOffset), heap_number_map);
9600 __ j(not_equal, &check_undefined_arg2); 9694 __ j(not_equal, &check_undefined_arg2);
9601 // Get the untagged integer version of the eax heap number in ecx. 9695 // Get the untagged integer version of the rax heap number in rcx.
9602 IntegerConvert(masm, rcx, rax); 9696 IntegerConvert(masm, rcx, rax);
9603 __ bind(&done); 9697 __ bind(&done);
9604 __ movl(rax, rdx); 9698 __ movl(rax, rdx);
9605 } 9699 }
9606 9700
9607 9701
9608 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) { 9702 void FloatingPointHelper::LoadSSE2SmiOperands(MacroAssembler* masm) {
9609 __ SmiToInteger32(kScratchRegister, rdx); 9703 __ SmiToInteger32(kScratchRegister, rdx);
9610 __ cvtlsi2sd(xmm0, kScratchRegister); 9704 __ cvtlsi2sd(xmm0, kScratchRegister);
9611 __ SmiToInteger32(kScratchRegister, rax); 9705 __ SmiToInteger32(kScratchRegister, rax);
(...skipping 435 matching lines...) Expand 10 before | Expand all | Expand 10 after
10047 ASSERT_EQ(0, kConsStringTag & kExternalStringTag); 10141 ASSERT_EQ(0, kConsStringTag & kExternalStringTag);
10048 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag)); 10142 __ testb(rbx, Immediate(kIsNotStringMask | kExternalStringTag));
10049 __ j(not_zero, &runtime); 10143 __ j(not_zero, &runtime);
10050 // String is a cons string. 10144 // String is a cons string.
10051 __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset)); 10145 __ movq(rdx, FieldOperand(rax, ConsString::kSecondOffset));
10052 __ Cmp(rdx, Factory::empty_string()); 10146 __ Cmp(rdx, Factory::empty_string());
10053 __ j(not_equal, &runtime); 10147 __ j(not_equal, &runtime);
10054 __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset)); 10148 __ movq(rax, FieldOperand(rax, ConsString::kFirstOffset));
10055 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset)); 10149 __ movq(rbx, FieldOperand(rax, HeapObject::kMapOffset));
10056 // String is a cons string with empty second part. 10150 // String is a cons string with empty second part.
10057 // eax: first part of cons string. 10151 // rax: first part of cons string.
10058 // ebx: map of first part of cons string. 10152 // rbx: map of first part of cons string.
10059 // Is first part a flat two byte string? 10153 // Is first part a flat two byte string?
10060 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 10154 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
10061 Immediate(kStringRepresentationMask | kStringEncodingMask)); 10155 Immediate(kStringRepresentationMask | kStringEncodingMask));
10062 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag); 10156 ASSERT_EQ(0, kSeqStringTag | kTwoByteStringTag);
10063 __ j(zero, &seq_two_byte_string); 10157 __ j(zero, &seq_two_byte_string);
10064 // Any other flat string must be ascii. 10158 // Any other flat string must be ascii.
10065 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset), 10159 __ testb(FieldOperand(rbx, Map::kInstanceTypeOffset),
10066 Immediate(kStringRepresentationMask)); 10160 Immediate(kStringRepresentationMask));
10067 __ j(not_zero, &runtime); 10161 __ j(not_zero, &runtime);
10068 10162
(...skipping 2262 matching lines...) Expand 10 before | Expand all | Expand 10 after
12331 #undef __ 12425 #undef __
12332 12426
12333 void RecordWriteStub::Generate(MacroAssembler* masm) { 12427 void RecordWriteStub::Generate(MacroAssembler* masm) {
12334 masm->RecordWriteHelper(object_, addr_, scratch_); 12428 masm->RecordWriteHelper(object_, addr_, scratch_);
12335 masm->ret(0); 12429 masm->ret(0);
12336 } 12430 }
12337 12431
12338 } } // namespace v8::internal 12432 } } // namespace v8::internal
12339 12433
12340 #endif // V8_TARGET_ARCH_X64 12434 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/x64/builtins-x64.cc ('k') | src/x64/ic-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698