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

Side by Side Diff: src/x87/lithium-codegen-x87.cc

Issue 895473002: x87: Use signaling NaN for holes in fixed double arrays. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « no previous file | src/x87/lithium-x87.h » ('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 // 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 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #if V8_TARGET_ARCH_X87 7 #if V8_TARGET_ARCH_X87
8 8
9 #include "src/base/bits.h" 9 #include "src/base/bits.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 1983 matching lines...) Expand 10 before | Expand all | Expand 10 after
1994 __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1994 __ Move(ToRegister(instr->result()), Immediate(instr->value()));
1995 } 1995 }
1996 1996
1997 1997
1998 void LCodeGen::DoConstantS(LConstantS* instr) { 1998 void LCodeGen::DoConstantS(LConstantS* instr) {
1999 __ Move(ToRegister(instr->result()), Immediate(instr->value())); 1999 __ Move(ToRegister(instr->result()), Immediate(instr->value()));
2000 } 2000 }
2001 2001
2002 2002
2003 void LCodeGen::DoConstantD(LConstantD* instr) { 2003 void LCodeGen::DoConstantD(LConstantD* instr) {
2004 double v = instr->value(); 2004 uint64_t const bits = instr->bits();
2005 uint64_t int_val = bit_cast<uint64_t, double>(v); 2005 uint32_t const lower = static_cast<uint32_t>(bits);
2006 int32_t lower = static_cast<int32_t>(int_val); 2006 uint32_t const upper = static_cast<uint32_t>(bits >> 32);
2007 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
2008 DCHECK(instr->result()->IsDoubleRegister()); 2007 DCHECK(instr->result()->IsDoubleRegister());
2009 2008
2010 __ push(Immediate(upper)); 2009 __ push(Immediate(upper));
2011 __ push(Immediate(lower)); 2010 __ push(Immediate(lower));
2012 X87Register reg = ToX87Register(instr->result()); 2011 X87Register reg = ToX87Register(instr->result());
2013 X87Mov(reg, Operand(esp, 0)); 2012 X87Mov(reg, Operand(esp, 0));
2014 __ add(Operand(esp), Immediate(kDoubleSize)); 2013 __ add(Operand(esp), Immediate(kDoubleSize));
2015 } 2014 }
2016 2015
2017 2016
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
2606 __ fstp(0); 2605 __ fstp(0);
2607 EmitFalseBranch(instr, no_condition); 2606 EmitFalseBranch(instr, no_condition);
2608 __ bind(&ok); 2607 __ bind(&ok);
2609 2608
2610 2609
2611 __ sub(esp, Immediate(kDoubleSize)); 2610 __ sub(esp, Immediate(kDoubleSize));
2612 __ fstp_d(MemOperand(esp, 0)); 2611 __ fstp_d(MemOperand(esp, 0));
2613 2612
2614 __ add(esp, Immediate(kDoubleSize)); 2613 __ add(esp, Immediate(kDoubleSize));
2615 int offset = sizeof(kHoleNanUpper32); 2614 int offset = sizeof(kHoleNanUpper32);
2616 __ cmp(MemOperand(esp, -offset), Immediate(kHoleNanUpper32)); 2615 // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
2616 // so we check the upper with 0xffffffff for hole as a temporary fix.
2617 __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
2617 EmitBranch(instr, equal); 2618 EmitBranch(instr, equal);
2618 } 2619 }
2619 2620
2620 2621
2621 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) { 2622 void LCodeGen::DoCompareMinusZeroAndBranch(LCompareMinusZeroAndBranch* instr) {
2622 Representation rep = instr->hydrogen()->value()->representation(); 2623 Representation rep = instr->hydrogen()->value()->representation();
2623 DCHECK(!rep.IsInteger32()); 2624 DCHECK(!rep.IsInteger32());
2624 2625
2625 if (rep.IsDouble()) { 2626 if (rep.IsDouble()) {
2626 X87Register input = ToX87Register(instr->value()); 2627 X87Register input = ToX87Register(instr->value());
(...skipping 1608 matching lines...) Expand 10 before | Expand all | Expand 10 after
4235 // Positive input. 4236 // Positive input.
4236 // {input, ln2}. 4237 // {input, ln2}.
4237 __ fldln2(); 4238 __ fldln2();
4238 // {ln2, input}. 4239 // {ln2, input}.
4239 __ fxch(); 4240 __ fxch();
4240 // {result}. 4241 // {result}.
4241 __ fyl2x(); 4242 __ fyl2x();
4242 __ jmp(&done, Label::kNear); 4243 __ jmp(&done, Label::kNear);
4243 4244
4244 __ bind(&nan_result); 4245 __ bind(&nan_result);
4245 ExternalReference nan =
4246 ExternalReference::address_of_canonical_non_hole_nan();
4247 X87PrepareToWrite(input_reg); 4246 X87PrepareToWrite(input_reg);
4248 __ fld_d(Operand::StaticVariable(nan)); 4247 __ push(Immediate(0xffffffff));
4248 __ push(Immediate(0x7fffffff));
4249 __ fld_d(MemOperand(esp, 0));
4250 __ lea(esp, Operand(esp, kDoubleSize));
4249 X87CommitWrite(input_reg); 4251 X87CommitWrite(input_reg);
4250 __ jmp(&done, Label::kNear); 4252 __ jmp(&done, Label::kNear);
4251 4253
4252 __ bind(&zero); 4254 __ bind(&zero);
4253 ExternalReference ninf = ExternalReference::address_of_negative_infinity(); 4255 ExternalReference ninf = ExternalReference::address_of_negative_infinity();
4254 X87PrepareToWrite(input_reg); 4256 X87PrepareToWrite(input_reg);
4255 __ fld_d(Operand::StaticVariable(ninf)); 4257 __ fld_d(Operand::StaticVariable(ninf));
4256 X87CommitWrite(input_reg); 4258 X87CommitWrite(input_reg);
4257 4259
4258 __ bind(&done); 4260 __ bind(&done);
(...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after
4633 case DICTIONARY_ELEMENTS: 4635 case DICTIONARY_ELEMENTS:
4634 case SLOPPY_ARGUMENTS_ELEMENTS: 4636 case SLOPPY_ARGUMENTS_ELEMENTS:
4635 UNREACHABLE(); 4637 UNREACHABLE();
4636 break; 4638 break;
4637 } 4639 }
4638 } 4640 }
4639 } 4641 }
4640 4642
4641 4643
4642 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) { 4644 void LCodeGen::DoStoreKeyedFixedDoubleArray(LStoreKeyed* instr) {
4643 ExternalReference canonical_nan_reference =
4644 ExternalReference::address_of_canonical_non_hole_nan();
4645 Operand double_store_operand = BuildFastArrayOperand( 4645 Operand double_store_operand = BuildFastArrayOperand(
4646 instr->elements(), 4646 instr->elements(),
4647 instr->key(), 4647 instr->key(),
4648 instr->hydrogen()->key()->representation(), 4648 instr->hydrogen()->key()->representation(),
4649 FAST_DOUBLE_ELEMENTS, 4649 FAST_DOUBLE_ELEMENTS,
4650 instr->base_offset()); 4650 instr->base_offset());
4651 4651
4652 // Can't use SSE2 in the serializer 4652 uint64_t int_val = kHoleNanInt64;
4653 int32_t lower = static_cast<int32_t>(int_val);
4654 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
4655 Operand double_store_operand2 = BuildFastArrayOperand(
4656 instr->elements(), instr->key(),
4657 instr->hydrogen()->key()->representation(), FAST_DOUBLE_ELEMENTS,
4658 instr->base_offset() + kPointerSize);
4659
4653 if (instr->hydrogen()->IsConstantHoleStore()) { 4660 if (instr->hydrogen()->IsConstantHoleStore()) {
4654 // This means we should store the (double) hole. No floating point 4661 // This means we should store the (double) hole. No floating point
4655 // registers required. 4662 // registers required.
4656 double nan_double = FixedDoubleArray::hole_nan_as_double();
4657 uint64_t int_val = bit_cast<uint64_t, double>(nan_double);
4658 int32_t lower = static_cast<int32_t>(int_val);
4659 int32_t upper = static_cast<int32_t>(int_val >> (kBitsPerInt));
4660
4661 __ mov(double_store_operand, Immediate(lower)); 4663 __ mov(double_store_operand, Immediate(lower));
4662 Operand double_store_operand2 = BuildFastArrayOperand(
4663 instr->elements(),
4664 instr->key(),
4665 instr->hydrogen()->key()->representation(),
4666 FAST_DOUBLE_ELEMENTS,
4667 instr->base_offset() + kPointerSize);
4668 __ mov(double_store_operand2, Immediate(upper)); 4664 __ mov(double_store_operand2, Immediate(upper));
4669 } else { 4665 } else {
4670 Label no_special_nan_handling; 4666 Label no_special_nan_handling, done;
4671 X87Register value = ToX87Register(instr->value()); 4667 X87Register value = ToX87Register(instr->value());
4672 X87Fxch(value); 4668 X87Fxch(value);
4673 4669
4674 if (instr->NeedsCanonicalization()) { 4670 if (instr->NeedsCanonicalization()) {
4675 __ fld(0); 4671 __ fld(0);
4676 __ fld(0); 4672 __ fld(0);
4677 __ FCmp(); 4673 __ FCmp();
4678
4679 __ j(parity_odd, &no_special_nan_handling, Label::kNear); 4674 __ j(parity_odd, &no_special_nan_handling, Label::kNear);
4680 __ sub(esp, Immediate(kDoubleSize)); 4675 // All NaNs are Canonicalized to 0x7fffffffffffffff
4676 __ mov(double_store_operand, Immediate(0xffffffff));
4677 __ mov(double_store_operand2, Immediate(0x7fffffff));
4678 __ jmp(&done, Label::kNear);
4679 } else {
4680 __ lea(esp, Operand(esp, -kDoubleSize));
4681 __ fst_d(MemOperand(esp, 0)); 4681 __ fst_d(MemOperand(esp, 0));
4682 __ cmp(MemOperand(esp, sizeof(kHoleNanLower32)), 4682 __ lea(esp, Operand(esp, kDoubleSize));
4683 Immediate(kHoleNanUpper32)); 4683 int offset = sizeof(kHoleNanUpper32);
4684 __ add(esp, Immediate(kDoubleSize)); 4684 // x87 converts sNaN(0xfff7fffffff7ffff) to QNaN(0xfffffffffff7ffff),
4685 Label canonicalize; 4685 // so we check the upper with 0xffffffff for hole as a temporary fix.
4686 __ j(not_equal, &canonicalize, Label::kNear); 4686 __ cmp(MemOperand(esp, -offset), Immediate(0xffffffff));
4687 __ jmp(&no_special_nan_handling, Label::kNear); 4687 __ j(not_equal, &no_special_nan_handling, Label::kNear);
4688 __ bind(&canonicalize); 4688 __ mov(double_store_operand, Immediate(lower));
4689 __ fstp(0); 4689 __ mov(double_store_operand2, Immediate(upper));
4690 __ fld_d(Operand::StaticVariable(canonical_nan_reference)); 4690 __ jmp(&done, Label::kNear);
4691 } 4691 }
4692
4693 __ bind(&no_special_nan_handling); 4692 __ bind(&no_special_nan_handling);
4694 __ fst_d(double_store_operand); 4693 __ fst_d(double_store_operand);
4694 __ bind(&done);
4695 } 4695 }
4696 } 4696 }
4697 4697
4698 4698
4699 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) { 4699 void LCodeGen::DoStoreKeyedFixedArray(LStoreKeyed* instr) {
4700 Register elements = ToRegister(instr->elements()); 4700 Register elements = ToRegister(instr->elements());
4701 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg; 4701 Register key = instr->key()->IsRegister() ? ToRegister(instr->key()) : no_reg;
4702 4702
4703 Operand operand = BuildFastArrayOperand( 4703 Operand operand = BuildFastArrayOperand(
4704 instr->elements(), 4704 instr->elements(),
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after
5182 DeoptimizeIf(not_equal, instr, "not a heap number"); 5182 DeoptimizeIf(not_equal, instr, "not a heap number");
5183 } else { 5183 } else {
5184 Label heap_number, convert; 5184 Label heap_number, convert;
5185 __ j(equal, &heap_number); 5185 __ j(equal, &heap_number);
5186 5186
5187 // Convert undefined (or hole) to NaN. 5187 // Convert undefined (or hole) to NaN.
5188 __ cmp(input_reg, factory()->undefined_value()); 5188 __ cmp(input_reg, factory()->undefined_value());
5189 DeoptimizeIf(not_equal, instr, "not a heap number/undefined"); 5189 DeoptimizeIf(not_equal, instr, "not a heap number/undefined");
5190 5190
5191 __ bind(&convert); 5191 __ bind(&convert);
5192 ExternalReference nan = 5192 __ push(Immediate(0xffffffff));
5193 ExternalReference::address_of_canonical_non_hole_nan(); 5193 __ push(Immediate(0x7fffffff));
5194 __ fld_d(Operand::StaticVariable(nan)); 5194 __ fld_d(MemOperand(esp, 0));
5195 __ lea(esp, Operand(esp, kDoubleSize));
5195 __ jmp(&done, Label::kNear); 5196 __ jmp(&done, Label::kNear);
5196 5197
5197 __ bind(&heap_number); 5198 __ bind(&heap_number);
5198 } 5199 }
5199 // Heap number to x87 conversion. 5200 // Heap number to x87 conversion.
5200 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5201 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
5201 if (deoptimize_on_minus_zero) { 5202 if (deoptimize_on_minus_zero) {
5202 __ fldz(); 5203 __ fldz();
5203 __ FCmp(); 5204 __ FCmp();
5204 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset)); 5205 __ fld_d(FieldOperand(input_reg, HeapNumber::kValueOffset));
(...skipping 1125 matching lines...) Expand 10 before | Expand all | Expand 10 after
6330 CallRuntime(Runtime::kPushBlockContext, 2, instr); 6331 CallRuntime(Runtime::kPushBlockContext, 2, instr);
6331 RecordSafepoint(Safepoint::kNoLazyDeopt); 6332 RecordSafepoint(Safepoint::kNoLazyDeopt);
6332 } 6333 }
6333 6334
6334 6335
6335 #undef __ 6336 #undef __
6336 6337
6337 } } // namespace v8::internal 6338 } } // namespace v8::internal
6338 6339
6339 #endif // V8_TARGET_ARCH_X87 6340 #endif // V8_TARGET_ARCH_X87
OLDNEW
« no previous file with comments | « no previous file | src/x87/lithium-x87.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698