OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |