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_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
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 792 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
803 Register map) { | 803 Register map) { |
804 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); | 804 mov(map, FieldOperand(heap_object, HeapObject::kMapOffset)); |
805 CmpInstanceType(map, type); | 805 CmpInstanceType(map, type); |
806 } | 806 } |
807 | 807 |
808 | 808 |
809 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { | 809 void MacroAssembler::CmpInstanceType(Register map, InstanceType type) { |
810 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); | 810 cmpb(FieldOperand(map, Map::kInstanceTypeOffset), Immediate(type)); |
811 } | 811 } |
812 | 812 |
813 void MacroAssembler::CheckFastObjectElements(Register map, | |
814 Label* fail, | |
815 Label::Distance distance) { | |
816 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
817 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
818 STATIC_ASSERT(FAST_ELEMENTS == 2); | |
819 STATIC_ASSERT(FAST_HOLEY_ELEMENTS == 3); | |
820 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
821 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | |
822 j(below_equal, fail, distance); | |
823 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
824 Immediate(Map::kMaximumBitField2FastHoleyElementValue)); | |
825 j(above, fail, distance); | |
826 } | |
827 | |
828 | |
829 void MacroAssembler::CheckFastSmiElements(Register map, | |
830 Label* fail, | |
831 Label::Distance distance) { | |
832 STATIC_ASSERT(FAST_SMI_ELEMENTS == 0); | |
833 STATIC_ASSERT(FAST_HOLEY_SMI_ELEMENTS == 1); | |
834 cmpb(FieldOperand(map, Map::kBitField2Offset), | |
835 Immediate(Map::kMaximumBitField2FastHoleySmiElementValue)); | |
836 j(above, fail, distance); | |
837 } | |
838 | |
839 | |
840 void MacroAssembler::StoreNumberToDoubleElements( | |
841 Register maybe_number, | |
842 Register elements, | |
843 Register key, | |
844 Register scratch1, | |
845 XMMRegister scratch2, | |
846 Label* fail, | |
847 int elements_offset) { | |
848 Label smi_value, done; | |
849 JumpIfSmi(maybe_number, &smi_value, Label::kNear); | |
850 | |
851 CheckMap(maybe_number, | |
852 isolate()->factory()->heap_number_map(), | |
853 fail, | |
854 DONT_DO_SMI_CHECK); | |
855 | |
856 // Double value, turn potential sNaN into qNaN. | |
857 Move(scratch2, 1.0); | |
858 mulsd(scratch2, FieldOperand(maybe_number, HeapNumber::kValueOffset)); | |
859 jmp(&done, Label::kNear); | |
860 | |
861 bind(&smi_value); | |
862 // Value is a smi. Convert to a double and store. | |
863 // Preserve original value. | |
864 mov(scratch1, maybe_number); | |
865 SmiUntag(scratch1); | |
866 Cvtsi2sd(scratch2, scratch1); | |
867 bind(&done); | |
868 movsd(FieldOperand(elements, key, times_4, | |
869 FixedDoubleArray::kHeaderSize - elements_offset), | |
870 scratch2); | |
871 } | |
872 | |
873 | |
874 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { | 813 void MacroAssembler::CompareMap(Register obj, Handle<Map> map) { |
875 cmp(FieldOperand(obj, HeapObject::kMapOffset), map); | 814 cmp(FieldOperand(obj, HeapObject::kMapOffset), map); |
876 } | 815 } |
877 | 816 |
878 | 817 |
879 void MacroAssembler::CheckMap(Register obj, | 818 void MacroAssembler::CheckMap(Register obj, |
880 Handle<Map> map, | 819 Handle<Map> map, |
881 Label* fail, | 820 Label* fail, |
882 SmiCheckType smi_check_type) { | 821 SmiCheckType smi_check_type) { |
883 if (smi_check_type == DO_SMI_CHECK) { | 822 if (smi_check_type == DO_SMI_CHECK) { |
(...skipping 1400 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2284 Check(not_equal, kVariableResolvedToWithContext); | 2223 Check(not_equal, kVariableResolvedToWithContext); |
2285 } | 2224 } |
2286 } | 2225 } |
2287 | 2226 |
2288 | 2227 |
2289 void MacroAssembler::LoadGlobalProxy(Register dst) { | 2228 void MacroAssembler::LoadGlobalProxy(Register dst) { |
2290 mov(dst, NativeContextOperand()); | 2229 mov(dst, NativeContextOperand()); |
2291 mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX)); | 2230 mov(dst, ContextOperand(dst, Context::GLOBAL_PROXY_INDEX)); |
2292 } | 2231 } |
2293 | 2232 |
2294 | |
2295 void MacroAssembler::LoadTransitionedArrayMapConditional( | |
2296 ElementsKind expected_kind, | |
2297 ElementsKind transitioned_kind, | |
2298 Register map_in_out, | |
2299 Register scratch, | |
2300 Label* no_map_match) { | |
2301 DCHECK(IsFastElementsKind(expected_kind)); | |
2302 DCHECK(IsFastElementsKind(transitioned_kind)); | |
2303 | |
2304 // Check that the function's map is the same as the expected cached map. | |
2305 mov(scratch, NativeContextOperand()); | |
2306 cmp(map_in_out, | |
2307 ContextOperand(scratch, Context::ArrayMapIndex(expected_kind))); | |
2308 j(not_equal, no_map_match); | |
2309 | |
2310 // Use the transitioned cached map. | |
2311 mov(map_in_out, | |
2312 ContextOperand(scratch, Context::ArrayMapIndex(transitioned_kind))); | |
2313 } | |
2314 | |
2315 | |
2316 void MacroAssembler::LoadGlobalFunction(int index, Register function) { | 2233 void MacroAssembler::LoadGlobalFunction(int index, Register function) { |
2317 // Load the native context from the current context. | 2234 // Load the native context from the current context. |
2318 mov(function, NativeContextOperand()); | 2235 mov(function, NativeContextOperand()); |
2319 // Load the function from the native context. | 2236 // Load the function from the native context. |
2320 mov(function, ContextOperand(function, index)); | 2237 mov(function, ContextOperand(function, index)); |
2321 } | 2238 } |
2322 | 2239 |
2323 | 2240 |
2324 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, | 2241 void MacroAssembler::LoadGlobalFunctionInitialMap(Register function, |
2325 Register map) { | 2242 Register map) { |
(...skipping 829 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3155 bind(&top_check); | 3072 bind(&top_check); |
3156 lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset)); | 3073 lea(scratch_reg, Operand(receiver_reg, kMementoLastWordOffset)); |
3157 cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top)); | 3074 cmp(scratch_reg, Operand::StaticVariable(new_space_allocation_top)); |
3158 j(greater_equal, no_memento_found); | 3075 j(greater_equal, no_memento_found); |
3159 // Memento map check. | 3076 // Memento map check. |
3160 bind(&map_check); | 3077 bind(&map_check); |
3161 mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset)); | 3078 mov(scratch_reg, Operand(receiver_reg, kMementoMapOffset)); |
3162 cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map())); | 3079 cmp(scratch_reg, Immediate(isolate()->factory()->allocation_memento_map())); |
3163 } | 3080 } |
3164 | 3081 |
3165 | |
3166 void MacroAssembler::JumpIfDictionaryInPrototypeChain( | |
3167 Register object, | |
3168 Register scratch0, | |
3169 Register scratch1, | |
3170 Label* found) { | |
3171 DCHECK(!scratch1.is(scratch0)); | |
3172 Factory* factory = isolate()->factory(); | |
3173 Register current = scratch0; | |
3174 Label loop_again, end; | |
3175 | |
3176 // scratch contained elements pointer. | |
3177 mov(current, object); | |
3178 mov(current, FieldOperand(current, HeapObject::kMapOffset)); | |
3179 mov(current, FieldOperand(current, Map::kPrototypeOffset)); | |
3180 cmp(current, Immediate(factory->null_value())); | |
3181 j(equal, &end); | |
3182 | |
3183 // Loop based on the map going up the prototype chain. | |
3184 bind(&loop_again); | |
3185 mov(current, FieldOperand(current, HeapObject::kMapOffset)); | |
3186 STATIC_ASSERT(JS_PROXY_TYPE < JS_OBJECT_TYPE); | |
3187 STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); | |
3188 CmpInstanceType(current, JS_OBJECT_TYPE); | |
3189 j(below, found); | |
3190 mov(scratch1, FieldOperand(current, Map::kBitField2Offset)); | |
3191 DecodeField<Map::ElementsKindBits>(scratch1); | |
3192 cmp(scratch1, Immediate(DICTIONARY_ELEMENTS)); | |
3193 j(equal, found); | |
3194 mov(current, FieldOperand(current, Map::kPrototypeOffset)); | |
3195 cmp(current, Immediate(factory->null_value())); | |
3196 j(not_equal, &loop_again); | |
3197 | |
3198 bind(&end); | |
3199 } | |
3200 | |
3201 | |
3202 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { | 3082 void MacroAssembler::TruncatingDiv(Register dividend, int32_t divisor) { |
3203 DCHECK(!dividend.is(eax)); | 3083 DCHECK(!dividend.is(eax)); |
3204 DCHECK(!dividend.is(edx)); | 3084 DCHECK(!dividend.is(edx)); |
3205 base::MagicNumbersForDivision<uint32_t> mag = | 3085 base::MagicNumbersForDivision<uint32_t> mag = |
3206 base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); | 3086 base::SignedDivisionByConstant(static_cast<uint32_t>(divisor)); |
3207 mov(eax, Immediate(mag.multiplier)); | 3087 mov(eax, Immediate(mag.multiplier)); |
3208 imul(dividend); | 3088 imul(dividend); |
3209 bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; | 3089 bool neg = (mag.multiplier & (static_cast<uint32_t>(1) << 31)) != 0; |
3210 if (divisor > 0 && neg) add(edx, dividend); | 3090 if (divisor > 0 && neg) add(edx, dividend); |
3211 if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend); | 3091 if (divisor < 0 && !neg && mag.multiplier > 0) sub(edx, dividend); |
3212 if (mag.shift > 0) sar(edx, mag.shift); | 3092 if (mag.shift > 0) sar(edx, mag.shift); |
3213 mov(eax, dividend); | 3093 mov(eax, dividend); |
3214 shr(eax, 31); | 3094 shr(eax, 31); |
3215 add(edx, eax); | 3095 add(edx, eax); |
3216 } | 3096 } |
3217 | 3097 |
3218 | 3098 |
3219 } // namespace internal | 3099 } // namespace internal |
3220 } // namespace v8 | 3100 } // namespace v8 |
3221 | 3101 |
3222 #endif // V8_TARGET_ARCH_IA32 | 3102 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |