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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 683 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 Register map) { | 694 Register map) { |
695 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 695 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
696 CmpInstanceType(map, type); | 696 CmpInstanceType(map, type); |
697 } | 697 } |
698 | 698 |
699 | 699 |
700 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { | 700 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { |
701 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); | 701 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); |
702 } | 702 } |
703 | 703 |
704 void MacroAssembler::CheckFastObjectElements(Register map, | |
705 Label* fail, | |
706 Label::Distance distance) { | |
707 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
708 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
709 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
710 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
711 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
712 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | |
713 j(below_equal, fail, distance); | |
714 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
715 Immediate(Map::kMaximumBitField2FastHoleyElementValue)); | |
716 j(above, fail, distance); | |
717 } | |
718 | |
719 | |
720 void MacroAssembler::CheckFastSmiElements(Register map, | |
721 Label* fail, | |
722 Label::Distance distance) { | |
723 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
724 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
725 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
726 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | |
727 j(above, fail, distance); | |
728 } | |
729 | |
730 | |
731 void MacroAssembler::StoreNumberToDoubleElements( | |
732 Register maybe_number, | |
733 Register elements, | |
734 Register key, | |
735 Register scratch, | |
736 Label* fail, | |
737 int elements_offset) { | |
738 Label smi_value, done, maybe_nan, not_nan, is_nan, have_double_value; | |
739 JumpIfSmi(maybe_number, &smi_value, Label::kNear); | |
740 | |
741 CheckMap(maybe_number, | |
742 isolate()->factory()->heap_number_map(), | |
743 fail, | |
744 DONT_DO_SMI_CHECK); | |
745 | |
746 fld_d(FieldOperand(maybe_number, HeapNumber::kValueOffset)); | |
747 jmp(&done, Label::kNear); | |
748 | |
749 bind(&smi_value); | |
750 // Value is a smi. Convert to a double and store. | |
751 // Preserve original value. | |
752 mov(scratch, maybe_number); | |
753 SmiUntag(scratch); | |
754 push(scratch); | |
755 fild_s(Operand(esp, 0)); | |
756 pop(scratch); | |
757 bind(&done); | |
758 fstp_d(FieldOperand(elements, key, times_4, | |
759 FixedDoubleArray::kHeaderSize - elements_offset)); | |
760 } | |
761 | |
762 | |
763 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { | 704 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { |
764 cmp(FieldOperand(obj, HeapObject::kMapOffset), map); | 705 cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
765 } | 706 } |
766 | 707 |
767 | 708 |
768 void MacroAssembler::CheckMap(Register obj, | 709 void MacroAssembler::CheckMap(Register obj, |
769 Handle<Map> map, | 710 Handle<Map> map, |
770 Label* fail, | 711 Label* fail, |
771 SmiCheckType smi_check_type) { | 712 SmiCheckType smi_check_type) { |
772 if (smi_check_type == DO_SMI_CHECK) { | 713 if (smi_check_type == DO_SMI_CHECK) { |
(...skipping 1450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2223 Check(not_equal, kVariableResolvedToWithContext); | 2164 Check(not_equal, kVariableResolvedToWithContext); |
2224 } | 2165 } |
2225 } | 2166 } |
2226 | 2167 |
2227 | 2168 |
2228 void MacroAssembler::LoadGlobalProxy(Register dst) { | 2169 void MacroAssembler::LoadGlobalProxy(Register dst) { |
2229 mov(dst, NativeContextOperand()); | 2170 mov(dst, NativeContextOperand()); |
2230 mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX)); | 2171 mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX)); |
2231 } | 2172 } |
2232 | 2173 |
2233 | |
2234 void MacroAssembler::LoadTransitionedArrayMapConditional( | |
2235 ElementsKind expected_kind, | |
2236 ElementsKind transitioned_kind, | |
2237 Register map_in_out, | |
2238 Register scratch, | |
2239 Label* no_map_match) { | |
2240 DCHECK(IsFastElementsKind(expected_kind)); | |
2241 DCHECK(IsFastElementsKind(transitioned_kind)); | |
2242 | |
2243 // Check that the function's map is the same as the expected cached map. | |
2244 mov(scratch, NativeContextOperand()); | |
2245 cmp(map_in_out, | |
2246 ContextOperand(scratch, Context::ArrayMapIndex(expected_kind))); | |
2247 j(not_equal, no_map_match); | |
2248 | |
2249 // Use the transitioned cached map. | |
2250 mov(map_in_out, | |
2251 ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind))); | |
2252 } | |
2253 | |
2254 | |
2255 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2174 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
2256 // Load the native context from the current context. | 2175 // Load the native context from the current context. |
2257 mov(function, NativeContextOperand()); | 2176 mov(function, NativeContextOperand()); |
2258 // Load the function from the native context. | 2177 // Load the function from the native context. |
2259 mov(function, ContextOperand(function, index)); | 2178 mov(function, ContextOperand(function, index)); |
2260 } | 2179 } |
2261 | 2180 |
2262 | 2181 |
2263 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 2182 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
2264 Register map) { | 2183 Register map) { |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3002 bind(&top_check); | 2921 bind(&top_check); |
3003 lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset)); | 2922 lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset)); |
3004 cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top)); | 2923 cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top)); |
3005 j(greater_equal, no_memento_found); | 2924 j(greater_equal, no_memento_found); |
3006 // Memento map check. | 2925 // Memento map check. |
3007 bind(&map_check); | 2926 bind(&map_check); |
3008 mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset)); | 2927 mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset)); |
3009 cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map())); | 2928 cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map())); |
3010 } | 2929 } |
3011 | 2930 |
3012 | |
3013 void MacroAssembler::JumpIfDictionaryInPrototypeChain( | |
3014 Register object, | |
3015 Register scratch0, | |
3016 Register scratch1, | |
3017 Label* found) { | |
3018 DCHECK(!scratch1.is(scratch0)); | |
3019 Factory* factory = isolate()->factory(); | |
3020 Register current = scratch0; | |
3021 Label loop_again, end; | |
3022 | |
3023 // scratch contained elements pointer. | |
3024 mov(current, object); | |
3025 mov(current, FieldOperand(current, HeapObject::kMapOffset)); | |
3026 mov(current, FieldOperand(current, Map::kPrototypeOffset)); | |
3027 cmp(current, Immediate(factory->null_value())); | |
3028 j(equal, &end); | |
3029 | |
3030 // Loop based on the map going up the prototype chain. | |
3031 bind(&loop_again); | |
3032 mov(current, FieldOperand(current, HeapObject::kMapOffset)); | |
3033 STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE); | |
3034 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); | |
3035 CmpInstanceType(current, JS_OBJECT_TYPE); | |
3036 j(below, found); | |
3037 mov(scratch1, FieldOperand(current, Map::kBitField2Offset)); | |
3038 DecodeField<Map::ElementsKindBits>(scratch1); | |
3039 cmp(scratch1, Immediate(DICTIONARY_ELEMENTS)); | |
3040 j(equal, found); | |
3041 mov(current, FieldOperand(current, Map::kPrototypeOffset)); | |
3042 cmp(current, Immediate(factory->null_value())); | |
3043 j(not_equal, &loop_again); | |
3044 | |
3045 bind(&end); | |
3046 } | |
3047 | |
3048 | |
3049 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { | 2931 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { |
3050 DCHECK(!dividend.is(eax)); | 2932 DCHECK(!dividend.is(eax)); |
3051 DCHECK(!dividend.is(edx)); | 2933 DCHECK(!dividend.is(edx)); |
3052 base::MagicNumbersForDivision<uint32_t> mag = | 2934 base::MagicNumbersForDivision<uint32_t> mag = |
3053 base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); | 2935 base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); |
3054 mov(eax, Immediate(mag.multiplier)); | 2936 mov(eax, Immediate(mag.multiplier)); |
3055 imul(dividend); | 2937 imul(dividend); |
3056 bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; | 2938 bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; |
3057 if (divisor > 0 && neg) add(edx, dividend); | 2939 if (divisor > 0 && neg) add(edx, dividend); |
3058 if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend); | 2940 if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend); |
3059 if (mag.shift > 0) sar(edx, mag.shift); | 2941 if (mag.shift > 0) sar(edx, mag.shift); |
3060 mov(eax, dividend); | 2942 mov(eax, dividend); |
3061 shr(eax, 31); | 2943 shr(eax, 31); |
3062 add(edx, eax); | 2944 add(edx, eax); |
3063 } | 2945 } |
3064 | 2946 |
3065 | 2947 |
3066 } // namespace internal | 2948 } // namespace internal |
3067 } // namespace v8 | 2949 } // namespace v8 |
3068 | 2950 |
3069 #endif // V8_TARGET_ARCH_X87 | 2951 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |