| 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 |