Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(94)

Side by Side Diff: src/ia32/macro-assembler-ia32.cc

Issue 22290005: Move ToI conversions to the MacroAssembler (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/ia32/macro-assembler-ia32.h ('k') | src/ia32/stub-cache-ia32.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698