OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #if V8_TARGET_ARCH_X64 | 5 #if V8_TARGET_ARCH_X64 |
6 | 6 |
7 #include "src/base/bits.h" | 7 #include "src/base/bits.h" |
8 #include "src/base/division-by-constant.h" | 8 #include "src/base/division-by-constant.h" |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/codegen.h" | 10 #include "src/codegen.h" |
(...skipping 3645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3656 movp(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 3656 movp(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
3657 CmpInstanceType(map, type); | 3657 CmpInstanceType(map, type); |
3658 } | 3658 } |
3659 | 3659 |
3660 | 3660 |
3661 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { | 3661 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { |
3662 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), | 3662 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), |
3663 Immediate(static_cast<int8_t>(type))); | 3663 Immediate(static_cast<int8_t>(type))); |
3664 } | 3664 } |
3665 | 3665 |
3666 void MacroAssembler::CheckFastObjectElements(Register map, | |
3667 Label* fail, | |
3668 Label::Distance distance) { | |
3669 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
3670 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
3671 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
3672 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
3673 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
3674 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | |
3675 j(below_equal, fail, distance); | |
3676 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
3677 Immediate(Map::kMaximumBitField2FastHoleyElementValue)); | |
3678 j(above, fail, distance); | |
3679 } | |
3680 | |
3681 | |
3682 void MacroAssembler::CheckFastSmiElements(Register map, | |
3683 Label* fail, | |
3684 Label::Distance distance) { | |
3685 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
3686 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
3687 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
3688 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | |
3689 j(above, fail, distance); | |
3690 } | |
3691 | |
3692 | |
3693 void MacroAssembler::StoreNumberToDoubleElements( | |
3694 Register maybe_number, | |
3695 Register elements, | |
3696 Register index, | |
3697 XMMRegister xmm_scratch, | |
3698 Label* fail, | |
3699 int elements_offset) { | |
3700 Label smi_value, done; | |
3701 | |
3702 JumpIfSmi(maybe_number, &smi_value, Label::kNear); | |
3703 | |
3704 CheckMap(maybe_number, | |
3705 isolate()->factory()->heap_number_map(), | |
3706 fail, | |
3707 DONT_DO_SMI_CHECK); | |
3708 | |
3709 // Double value, turn potential sNaN into qNaN. | |
3710 Move(xmm_scratch, 1.0); | |
3711 mulsd(xmm_scratch, FieldOperand(maybe_number, HeapNumber::kValueOffset)); | |
3712 jmp(&done, Label::kNear); | |
3713 | |
3714 bind(&smi_value); | |
3715 // Value is a smi. convert to a double and store. | |
3716 // Preserve original value. | |
3717 SmiToInteger32(kScratchRegister, maybe_number); | |
3718 Cvtlsi2sd(xmm_scratch, kScratchRegister); | |
3719 bind(&done); | |
3720 Movsd(FieldOperand(elements, index, times_8, | |
3721 FixedDoubleArray::kHeaderSize - elements_offset), | |
3722 xmm_scratch); | |
3723 } | |
3724 | |
3725 | |
3726 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { | 3666 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { |
3727 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); | 3667 Cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
3728 } | 3668 } |
3729 | 3669 |
3730 | 3670 |
3731 void MacroAssembler::CheckMap(Register obj, | 3671 void MacroAssembler::CheckMap(Register obj, |
3732 Handle<Map> map, | 3672 Handle<Map> map, |
3733 Label* fail, | 3673 Label* fail, |
3734 SmiCheckType smi_check_type) { | 3674 SmiCheckType smi_check_type) { |
3735 if (smi_check_type == DO_SMI_CHECK) { | 3675 if (smi_check_type == DO_SMI_CHECK) { |
(...skipping 1394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5130 // chain (i.e., the static scope chain and runtime context chain do | 5070 // chain (i.e., the static scope chain and runtime context chain do |
5131 // not agree). A variable occurring in such a scope should have | 5071 // not agree). A variable occurring in such a scope should have |
5132 // slot type LOOKUP and not CONTEXT. | 5072 // slot type LOOKUP and not CONTEXT. |
5133 if (emit_debug_code()) { | 5073 if (emit_debug_code()) { |
5134 CompareRoot(FieldOperand(dst, HeapObject::kMapOffset), | 5074 CompareRoot(FieldOperand(dst, HeapObject::kMapOffset), |
5135 Heap::kWithContextMapRootIndex); | 5075 Heap::kWithContextMapRootIndex); |
5136 Check(not_equal, kVariableResolvedToWithContext); | 5076 Check(not_equal, kVariableResolvedToWithContext); |
5137 } | 5077 } |
5138 } | 5078 } |
5139 | 5079 |
5140 | |
5141 void MacroAssembler::LoadTransitionedArrayMapConditional( | |
5142 ElementsKind expected_kind, | |
5143 ElementsKind transitioned_kind, | |
5144 Register map_in_out, | |
5145 Register scratch, | |
5146 Label* no_map_match) { | |
5147 DCHECK(IsFastElementsKind(expected_kind)); | |
5148 DCHECK(IsFastElementsKind(transitioned_kind)); | |
5149 | |
5150 // Check that the function's map is the same as the expected cached map. | |
5151 movp(scratch, NativeContextOperand()); | |
5152 cmpp(map_in_out, | |
5153 ContextOperand(scratch, Context::ArrayMapIndex(expected_kind))); | |
5154 j(not_equal, no_map_match); | |
5155 | |
5156 // Use the transitioned cached map. | |
5157 movp(map_in_out, | |
5158 ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind))); | |
5159 } | |
5160 | |
5161 | |
5162 #ifdef _WIN64 | 5080 #ifdef _WIN64 |
5163 static const int kRegisterPassedArguments = 4; | 5081 static const int kRegisterPassedArguments = 4; |
5164 #else | 5082 #else |
5165 static const int kRegisterPassedArguments = 6; | 5083 static const int kRegisterPassedArguments = 6; |
5166 #endif | 5084 #endif |
5167 | 5085 |
5168 | 5086 |
5169 void MacroAssembler::LoadNativeContextSlot(int index, Register dst) { | 5087 void MacroAssembler::LoadNativeContextSlot(int index, Register dst) { |
5170 movp(dst, NativeContextOperand()); | 5088 movp(dst, NativeContextOperand()); |
5171 movp(dst, ContextOperand(dst, index)); | 5089 movp(dst, ContextOperand(dst, index)); |
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5494 bind(&top_check); | 5412 bind(&top_check); |
5495 leap(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset)); | 5413 leap(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset)); |
5496 cmpp(scratch_reg, ExternalOperand(new_space_allocation_top)); | 5414 cmpp(scratch_reg, ExternalOperand(new_space_allocation_top)); |
5497 j(greater_equal, no_memento_found); | 5415 j(greater_equal, no_memento_found); |
5498 // Memento map check. | 5416 // Memento map check. |
5499 bind(&map_check); | 5417 bind(&map_check); |
5500 CompareRoot(MemOperand(receiver_reg, kMementoMapOffset), | 5418 CompareRoot(MemOperand(receiver_reg, kMementoMapOffset), |
5501 Heap::kAllocationMementoMapRootIndex); | 5419 Heap::kAllocationMementoMapRootIndex); |
5502 } | 5420 } |
5503 | 5421 |
5504 | |
5505 void MacroAssembler::JumpIfDictionaryInPrototypeChain( | |
5506 Register object, | |
5507 Register scratch0, | |
5508 Register scratch1, | |
5509 Label* found) { | |
5510 DCHECK(!(scratch0.is(kScratchRegister) && scratch1.is(kScratchRegister))); | |
5511 DCHECK(!scratch1.is(scratch0)); | |
5512 Register current = scratch0; | |
5513 Label loop_again, end; | |
5514 | |
5515 movp(current, object); | |
5516 movp(current, FieldOperand(current, HeapObject::kMapOffset)); | |
5517 movp(current, FieldOperand(current, Map::kPrototypeOffset)); | |
5518 CompareRoot(current, Heap::kNullValueRootIndex); | |
5519 j(equal, &end); | |
5520 | |
5521 // Loop based on the map going up the prototype chain. | |
5522 bind(&loop_again); | |
5523 movp(current, FieldOperand(current, HeapObject::kMapOffset)); | |
5524 STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE); | |
5525 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); | |
5526 CmpInstanceType(current, JS_OBJECT_TYPE); | |
5527 j(below, found); | |
5528 movp(scratch1, FieldOperand(current, Map::kBitField2Offset)); | |
5529 DecodeField<Map::ElementsKindBits>(scratch1); | |
5530 cmpp(scratch1, Immediate(DICTIONARY_ELEMENTS)); | |
5531 j(equal, found); | |
5532 movp(current, FieldOperand(current, Map::kPrototypeOffset)); | |
5533 CompareRoot(current, Heap::kNullValueRootIndex); | |
5534 j(not_equal, &loop_again); | |
5535 | |
5536 bind(&end); | |
5537 } | |
5538 | |
5539 | |
5540 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { | 5422 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { |
5541 DCHECK(!dividend.is(rax)); | 5423 DCHECK(!dividend.is(rax)); |
5542 DCHECK(!dividend.is(rdx)); | 5424 DCHECK(!dividend.is(rdx)); |
5543 base::MagicNumbersForDivision<uint32_t> mag = | 5425 base::MagicNumbersForDivision<uint32_t> mag = |
5544 base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); | 5426 base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); |
5545 movl(rax, Immediate(mag.multiplier)); | 5427 movl(rax, Immediate(mag.multiplier)); |
5546 imull(dividend); | 5428 imull(dividend); |
5547 bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; | 5429 bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; |
5548 if (divisor > 0 && neg) addl(rdx, dividend); | 5430 if (divisor > 0 && neg) addl(rdx, dividend); |
5549 if (divisor < 0 && !neg && mag.multiplier > 0) subl(rdx, dividend); | 5431 if (divisor < 0 && !neg && mag.multiplier > 0) subl(rdx, dividend); |
5550 if (mag.shift > 0) sarl(rdx, Immediate(mag.shift)); | 5432 if (mag.shift > 0) sarl(rdx, Immediate(mag.shift)); |
5551 movl(rax, dividend); | 5433 movl(rax, dividend); |
5552 shrl(rax, Immediate(31)); | 5434 shrl(rax, Immediate(31)); |
5553 addl(rdx, rax); | 5435 addl(rdx, rax); |
5554 } | 5436 } |
5555 | 5437 |
5556 | 5438 |
5557 } // namespace internal | 5439 } // namespace internal |
5558 } // namespace v8 | 5440 } // namespace v8 |
5559 | 5441 |
5560 #endif // V8_TARGET_ARCH_X64 | 5442 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |