Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 void MacroAssembler::ClampUint8(Register reg) { | 154 void MacroAssembler::ClampUint8(Register reg) { |
| 155 Label done; | 155 Label done; |
| 156 test(reg, Immediate(0xFFFFFF00)); | 156 test(reg, Immediate(0xFFFFFF00)); |
| 157 j(zero, &done, Label::kNear); | 157 j(zero, &done, Label::kNear); |
| 158 setcc(negative, reg); // 1 if negative, 0 if positive. | 158 setcc(negative, reg); // 1 if negative, 0 if positive. |
| 159 dec_b(reg); // 0 if negative, 255 if positive. | 159 dec_b(reg); // 0 if negative, 255 if positive. |
| 160 bind(&done); | 160 bind(&done); |
| 161 } | 161 } |
| 162 | 162 |
| 163 | 163 |
| 164 void MacroAssembler::SlowTruncateToI(Register input_reg, Register result_reg, | |
| 165 int index) { | |
| 166 DoubleToIStub stub(input_reg, result_reg, index, true); | |
| 167 call(stub.GetCode(isolate()), RelocInfo::CODE_TARGET); | |
| 168 } | |
| 169 | |
| 170 | |
| 171 void MacroAssembler::TruncateDoubleToI( | |
| 172 XMMRegister input_reg, Register result_reg) { | |
| 173 Label done; | |
| 174 cvttsd2si(result_reg, Operand(input_reg)); | |
| 175 cmp(result_reg, 0x80000000u); | |
| 176 j(not_equal, &done, Label::kNear); | |
| 177 | |
| 178 sub(esp, Immediate(kDoubleSize)); | |
| 179 movdbl(MemOperand(esp, 0), input_reg); | |
| 180 SlowTruncateToI(esp, result_reg, 0); | |
| 181 add(esp, Immediate(kDoubleSize)); | |
| 182 bind(&done); | |
| 183 } | |
| 184 | |
| 185 | |
| 186 void MacroAssembler::DoubleToI(XMMRegister input_reg, Register result_reg, | |
| 187 XMMRegister scratch, bool bailout_on_minus_zero, | |
| 188 Label* conversion_failed, Label* done, Label::Distance dst) { | |
| 189 cvttsd2si(result_reg, Operand(input_reg)); | |
| 190 cvtsi2sd(scratch, Operand(result_reg)); | |
| 191 ucomisd(scratch, input_reg); | |
| 192 j(not_equal, conversion_failed, dst); | |
| 193 j(parity_even, conversion_failed, dst); // NaN. | |
| 194 if (bailout_on_minus_zero) { | |
| 195 test(result_reg, Operand(result_reg)); | |
| 196 j(not_zero, done, dst); | |
| 197 movmskpd(result_reg, input_reg); | |
| 198 and_(result_reg, 1); | |
| 199 j(not_zero, conversion_failed, dst); | |
| 200 } | |
| 201 jmp(done, dst); | |
| 202 } | |
| 203 | |
| 204 | |
| 205 void MacroAssembler::TruncateHeapNumberToI(Register input_reg, | |
| 206 Register result_reg) { | |
| 207 Label done, slow_case; | |
| 208 | |
| 209 if (CpuFeatures::IsSupported(SSE3)) { | |
| 210 CpuFeatureScope scope(this, SSE3); | |
| 211 Label convert; | |
| 212 // Use more powerful conversion when sse3 is available. | |
| 213 // Load x87 register with heap number. | |
| 214 fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 215 // Get exponent alone and check for too-big exponent. | |
| 216 mov(result_reg, FieldOperand(input_reg, HeapNumber::kExponentOffset)); | |
| 217 and_(result_reg, HeapNumber::kExponentMask); | |
| 218 const uint32_t kTooBigExponent = | |
| 219 (HeapNumber::kExponentBias + 63) << HeapNumber::kExponentShift; | |
| 220 cmp(Operand(result_reg), Immediate(kTooBigExponent)); | |
| 221 j(greater_equal, &slow_case, Label::kNear); | |
| 222 | |
| 223 // Reserve space for 64 bit answer. | |
| 224 sub(Operand(esp), Immediate(kDoubleSize)); | |
| 225 // Do conversion, which cannot fail because we checked the exponent. | |
| 226 fisttp_d(Operand(esp, 0)); | |
| 227 mov(result_reg, Operand(esp, 0)); // Low word of answer is the result. | |
| 228 add(Operand(esp), Immediate(kDoubleSize)); | |
| 229 jmp(&done, Label::kNear); | |
| 230 | |
| 231 // Slow case. | |
| 232 bind(&slow_case); | |
| 233 if (input_reg.is(result_reg)) { | |
| 234 // Input is clobbered. Restore number from fpu stack | |
| 235 sub(Operand(esp), Immediate(kDoubleSize)); | |
| 236 fstp_d(Operand(esp, 0)); | |
| 237 SlowTruncateToI(esp, result_reg, 0); | |
| 238 add(esp, Immediate(kDoubleSize)); | |
| 239 } else { | |
| 240 fstp(0); | |
| 241 SlowTruncateToI(input_reg, result_reg); | |
| 242 } | |
| 243 } else if (CpuFeatures::IsSupported(SSE2)) { | |
| 244 CpuFeatureScope scope(this, SSE2); | |
| 245 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 246 cvttsd2si(result_reg, Operand(xmm0)); | |
| 247 cmp(result_reg, 0x80000000u); | |
| 248 j(not_equal, &done, Label::kNear); | |
| 249 // Check if the input was 0x8000000 (kMinInt). | |
| 250 // If no, then we got an overflow and we deoptimize. | |
| 251 ExternalReference min_int = ExternalReference::address_of_min_int(); | |
| 252 ucomisd(xmm0, Operand::StaticVariable(min_int)); | |
| 253 j(not_equal, &slow_case, Label::kNear); | |
| 254 j(parity_even, &slow_case, Label::kNear); // NaN. | |
| 255 jmp(&done, Label::kNear); | |
| 256 | |
| 257 // Slow case. | |
| 258 bind(&slow_case); | |
| 259 if (input_reg.is(result_reg)) { | |
| 260 // Input is clobbered. Restore number from double scratch. | |
| 261 sub(esp, Immediate(kDoubleSize)); | |
| 262 movdbl(MemOperand(esp, 0), xmm0); | |
| 263 SlowTruncateToI(esp, result_reg, 0); | |
| 264 add(esp, Immediate(kDoubleSize)); | |
| 265 } else { | |
| 266 SlowTruncateToI(input_reg, result_reg); | |
| 267 } | |
| 268 } else { | |
| 269 ASSERT(Serializer::enabled()); | |
| 270 // TODO(olivf) If we ever hit this assert, it means that a DoubleToIStub is | |
| 271 // used in a snapshoted stub. In that case we should probably add a fast | |
| 272 // case here, which e.g. covers exponents < 31. | |
| 273 SlowTruncateToI(input_reg, result_reg); | |
| 274 } | |
| 275 bind(&done); | |
| 276 } | |
| 277 | |
| 278 | |
| 279 void MacroAssembler::TaggedToI(Register input_reg, Register result_reg, | |
|
danno
2013/08/09 13:27:25
Why not just pass is no_reg to temp (removing the
oliv
2013/08/12 12:18:47
Done.
| |
| 280 Maybe<XMMRegister> temp, bool bailout_on_minus_zero, | |
| 281 Label* bailout, Label* done) { | |
| 282 | |
| 283 cmp(FieldOperand(input_reg, HeapObject::kMapOffset), | |
| 284 isolate()->factory()->heap_number_map()); | |
| 285 j(not_equal, bailout, Label::kNear); | |
| 286 | |
| 287 if (CpuFeatures::IsSafeForSnapshot(SSE2) && temp.has_value) { | |
|
danno
2013/08/09 13:27:25
if temp == no_reg, then why not just just do:
tem
oliv
2013/08/12 12:18:47
not sure what you mean by existing code. but actua
| |
| 288 CpuFeatureScope scope(this, SSE2); | |
| 289 | |
| 290 XMMRegister xmm_temp = temp.value; | |
| 291 movdbl(xmm0, FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 292 cvttsd2si(result_reg, Operand(xmm0)); | |
| 293 cvtsi2sd(xmm_temp, Operand(result_reg)); | |
| 294 ucomisd(xmm0, xmm_temp); | |
| 295 RecordComment("Deferred TaggedToI: lost precision"); | |
| 296 j(not_equal, bailout, Label::kNear); | |
| 297 RecordComment("Deferred TaggedToI: NaN"); | |
| 298 j(parity_even, bailout, Label::kNear); | |
| 299 if (bailout_on_minus_zero) { | |
| 300 test(result_reg, Operand(result_reg)); | |
| 301 j(not_zero, done, Label::kNear); | |
| 302 movmskpd(result_reg, xmm0); | |
| 303 and_(result_reg, 1); | |
| 304 RecordComment("Deferred TaggedToI: minus zero"); | |
| 305 j(not_zero, bailout, Label::kNear); | |
| 306 } | |
| 307 jmp(done, Label::kNear); | |
| 308 } else { | |
| 309 // TODO(olivf) Converting a number on the fpu is actually quite slow. We | |
| 310 // should first try a fast conversion and then bailout to this slow case. | |
| 311 Label bailout_pop, zero_check; | |
| 312 sub(esp, Immediate(kPointerSize)); | |
| 313 fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 314 if (bailout_on_minus_zero) fld(0); | |
| 315 fild_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); | |
| 316 fist_s(MemOperand(esp, 0)); | |
| 317 FCmp(); | |
| 318 pop(result_reg); | |
| 319 j(not_equal, bailout_on_minus_zero ? &bailout_pop : bailout, | |
| 320 Label::kNear); | |
| 321 j(parity_even, bailout_on_minus_zero ? &bailout_pop : bailout, | |
| 322 Label::kNear); // NaN. | |
| 323 if (bailout_on_minus_zero) { | |
| 324 test(result_reg, Operand(result_reg)); | |
| 325 j(zero, &zero_check, Label::kNear); | |
| 326 fstp(0); | |
| 327 jmp(done, Label::kNear); | |
| 328 bind(&zero_check); | |
| 329 // To check for minus zero, we load the value again as float, and check | |
| 330 // if that is still 0. | |
| 331 sub(esp, Immediate(kPointerSize)); | |
| 332 fstp_s(Operand(esp, 0)); | |
| 333 pop(result_reg); | |
| 334 test(result_reg, Operand(result_reg)); | |
| 335 j(zero, done, Label::kNear); | |
| 336 jmp(bailout, Label::kNear); | |
| 337 | |
| 338 bind(&bailout_pop); | |
| 339 fstp(0); | |
| 340 jmp(bailout, Label::kNear); | |
| 341 } else { | |
| 342 jmp(done, Label::kNear); | |
| 343 } | |
| 344 } | |
|
danno
2013/08/09 13:27:25
Why do you need an explicit done label? Falling th
oliv
2013/08/12 12:18:47
Done.
| |
| 345 } | |
| 346 | |
| 347 | |
| 348 | |
| 164 static double kUint32Bias = | 349 static double kUint32Bias = |
| 165 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; | 350 static_cast<double>(static_cast<uint32_t>(0xFFFFFFFF)) + 1; |
| 166 | 351 |
| 167 | 352 |
| 168 void MacroAssembler::LoadUint32(XMMRegister dst, | 353 void MacroAssembler::LoadUint32(XMMRegister dst, |
| 169 Register src, | 354 Register src, |
| 170 XMMRegister scratch) { | 355 XMMRegister scratch) { |
| 171 Label done; | 356 Label done; |
| 172 cmp(src, Immediate(0)); | 357 cmp(src, Immediate(0)); |
| 173 movdbl(scratch, | 358 movdbl(scratch, |
| (...skipping 3013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3187 j(greater, &no_memento_available); | 3372 j(greater, &no_memento_available); |
| 3188 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), | 3373 cmp(MemOperand(scratch_reg, -AllocationMemento::kSize), |
| 3189 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); | 3374 Immediate(Handle<Map>(isolate()->heap()->allocation_memento_map()))); |
| 3190 bind(&no_memento_available); | 3375 bind(&no_memento_available); |
| 3191 } | 3376 } |
| 3192 | 3377 |
| 3193 | 3378 |
| 3194 } } // namespace v8::internal | 3379 } } // namespace v8::internal |
| 3195 | 3380 |
| 3196 #endif // V8_TARGET_ARCH_IA32 | 3381 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |