Label load_smi, heap_number, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
if (deoptimize_on_undefined) {
DeoptimizeIf(ne, env);
} else {
- Label heap_number;
+ Label heap_number, convert;
__ b(eq, &heap_number);
+ // Convert undefined (and hole) to NaN.
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(input_reg, Operand(ip));
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ b(eq, &convert);
+ __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
+ __ cmp(input_reg, Operand(ip));
+ }
DeoptimizeIf(ne, env);
- // Convert undefined to NaN.
+ __ bind(&convert);
__ LoadRoot(ip, Heap::kNanValueRootIndex);
__ sub(ip, ip, Operand(kHeapObjectTag));
__ vldr(result_reg, ip, HeapNumber::kValueOffset);
DeoptimizeIf(eq, env);
}
__ jmp(&done);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_OR_HOLE) {
- __ SmiUntag(scratch, input_reg, SetCC);
- DeoptimizeIf(cs, env);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE) {
- __ UntagAndJumpIfSmi(scratch, input_reg, &load_smi);
- __ Vmov(result_reg,
- FixedDoubleArray::hole_nan_as_double(),
- no_reg);
- __ b(&done);
} else {
__ SmiUntag(scratch, input_reg);
ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
if (value->type().IsSmi()) {
- if (value->IsLoadKeyed()) {
- HLoadKeyed* load = HLoadKeyed::cast(value);
- if (load->UsesMustHandleHole()) {
- if (load->hole_mode() == ALLOW_RETURN_HOLE) {
- mode = NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE;
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI_OR_HOLE;
- }
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ if (load->hole_mode() == ALLOW_RETURN_HOLE) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
}
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
}
}
return false;
}
+ // Holes are only returned as tagged values.
+ if (!representation().IsTagged()) {
+ return false;
+ }
+
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
- if (!use->IsChange() || !HChange::cast(use)->to().IsDouble()) {
- return false;
- }
+ if (!use->IsChange()) return false;
}
return true;
ASSERT(!value->representation().Equals(to));
set_representation(to);
SetFlag(kUseGVN);
- if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
+ if (deoptimize_on_undefined || to.IsTagged()) {
+ SetFlag(kDeoptimizeOnUndefined);
+ }
if (is_truncating) SetFlag(kTruncatingToInt32);
if (value->representation().IsSmi() || value->type().IsSmi()) {
set_type(HType::Smi());
// This must happen after inferring representations.
MergeRemovableSimulates();
- MarkDeoptimizeOnUndefined();
InsertRepresentationChanges();
+ MarkDeoptimizeOnUndefined();
InitializeInferredTypes();
NumberUntagDMode mode) {
Label load_smi, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
if (deoptimize_on_undefined) {
DeoptimizeIf(not_equal, env);
} else {
- Label heap_number;
+ Label heap_number, convert;
__ j(equal, &heap_number, Label::kNear);
+ // Convert undefined (or hole) to NaN.
__ cmp(input_reg, factory()->undefined_value());
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ j(equal, &convert, Label::kNear);
+ __ cmp(input_reg, factory()->the_hole_value());
+ }
DeoptimizeIf(not_equal, env);
- // Convert undefined to NaN.
+ __ bind(&convert);
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
__ fld_d(Operand::StaticVariable(nan));
__ jmp(&done, Label::kNear);
+
__ bind(&heap_number);
}
// Heap number to x87 conversion.
DeoptimizeIf(not_zero, env);
}
__ jmp(&done, Label::kNear);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_OR_HOLE) {
- __ test(input_reg, Immediate(kSmiTagMask));
- DeoptimizeIf(not_equal, env);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE) {
- __ test(input_reg, Immediate(kSmiTagMask));
- __ j(zero, &load_smi);
- ExternalReference hole_nan_reference =
- ExternalReference::address_of_the_hole_nan();
- __ fld_d(Operand::StaticVariable(hole_nan_reference));
- __ jmp(&done, Label::kNear);
} else {
ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
}
NumberUntagDMode mode) {
Label load_smi, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
if (deoptimize_on_undefined) {
DeoptimizeIf(not_equal, env);
} else {
- Label heap_number;
+ Label heap_number, convert;
__ j(equal, &heap_number, Label::kNear);
+ // Convert undefined (and hole) to NaN.
__ cmp(input_reg, factory()->undefined_value());
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ j(equal, &convert, Label::kNear);
+ __ cmp(input_reg, factory()->the_hole_value());
+ }
DeoptimizeIf(not_equal, env);
- // Convert undefined to NaN.
+ __ bind(&convert);
ExternalReference nan =
ExternalReference::address_of_canonical_non_hole_nan();
__ movdbl(result_reg, Operand::StaticVariable(nan));
DeoptimizeIf(not_zero, env);
}
__ jmp(&done, Label::kNear);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_OR_HOLE) {
- __ test(input_reg, Immediate(kSmiTagMask));
- DeoptimizeIf(not_equal, env);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE) {
- __ test(input_reg, Immediate(kSmiTagMask));
- __ j(zero, &load_smi);
- ExternalReference hole_nan_reference =
- ExternalReference::address_of_the_hole_nan();
- __ movdbl(result_reg, Operand::StaticVariable(hole_nan_reference));
- __ jmp(&done, Label::kNear);
} else {
ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
}
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
- if (value->type().IsSmi()) {
- if (value->IsLoadKeyed()) {
- HLoadKeyed* load = HLoadKeyed::cast(value);
- if (load->UsesMustHandleHole()) {
- if (load->hole_mode() == ALLOW_RETURN_HOLE) {
- mode = NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE;
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI_OR_HOLE;
- }
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
- }
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
+ if (value->representation().IsSmi()) {
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
}
}
enum NumberUntagDMode {
NUMBER_CANDIDATE_IS_SMI,
- NUMBER_CANDIDATE_IS_SMI_OR_HOLE,
- NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE,
- NUMBER_CANDIDATE_IS_ANY_TAGGED
+ NUMBER_CANDIDATE_IS_ANY_TAGGED,
+ NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE
};
NumberUntagDMode mode) {
Label load_smi, done;
- if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED) {
+ STATIC_ASSERT(NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE >
+ NUMBER_CANDIDATE_IS_ANY_TAGGED);
+ if (mode >= NUMBER_CANDIDATE_IS_ANY_TAGGED) {
// Smi check.
__ JumpIfSmi(input_reg, &load_smi, Label::kNear);
if (deoptimize_on_undefined) {
DeoptimizeIf(not_equal, env);
} else {
- Label heap_number;
+ Label heap_number, convert;
__ j(equal, &heap_number, Label::kNear);
+ // Convert undefined (and hole) to NaN. Compute NaN as 0/0.
__ CompareRoot(input_reg, Heap::kUndefinedValueRootIndex);
+ if (mode == NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE) {
+ __ j(equal, &convert, Label::kNear);
+ __ CompareRoot(input_reg, Heap::kTheHoleValueRootIndex);
+ }
DeoptimizeIf(not_equal, env);
- // Convert undefined to NaN. Compute NaN as 0/0.
+ __ bind(&convert);
__ xorps(result_reg, result_reg);
__ divsd(result_reg, result_reg);
__ jmp(&done, Label::kNear);
DeoptimizeIf(not_zero, env);
}
__ jmp(&done, Label::kNear);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_OR_HOLE) {
- __ testq(input_reg, Immediate(kSmiTagMask));
- DeoptimizeIf(not_equal, env);
- } else if (mode == NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE) {
- __ testq(input_reg, Immediate(kSmiTagMask));
- __ j(zero, &load_smi);
- __ Set(kScratchRegister, BitCast<uint64_t>(
- FixedDoubleArray::hole_nan_as_double()));
- __ movq(result_reg, kScratchRegister);
- __ jmp(&done, Label::kNear);
} else {
ASSERT(mode == NUMBER_CANDIDATE_IS_SMI);
}
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED;
HValue* value = instr->hydrogen()->value();
if (value->type().IsSmi()) {
- if (value->IsLoadKeyed()) {
- HLoadKeyed* load = HLoadKeyed::cast(value);
- if (load->UsesMustHandleHole()) {
- if (load->hole_mode() == ALLOW_RETURN_HOLE) {
- mode = NUMBER_CANDIDATE_IS_SMI_CONVERT_HOLE;
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI_OR_HOLE;
- }
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
- }
- } else {
- mode = NUMBER_CANDIDATE_IS_SMI;
+ mode = NUMBER_CANDIDATE_IS_SMI;
+ } else if (value->IsLoadKeyed()) {
+ HLoadKeyed* load = HLoadKeyed::cast(value);
+ if (load->UsesMustHandleHole()) {
+ mode = NUMBER_CANDIDATE_IS_ANY_TAGGED_CONVERT_HOLE;
}
}
--- /dev/null
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+// Flags: --allow-natives-syntax
+
+function f(test, test2, a, i) {
+ var o = [0.5,1,,3];
+ var d;
+ if (test) {
+ d = 1.5;
+ } else {
+ d = o[i];
+ }
+ if (test2) {
+ d += 1;
+ }
+ a[i] = d;
+ return d;
+}
+
+var a = [0, 0, 0, {}];
+f(true, false, a, 0);
+f(true, true, a, 0);
+f(false, false, a, 1);
+f(false, true, a, 1);
+%OptimizeFunctionOnNextCall(f);
+f(false, false, a, 2);
+assertEquals(undefined, a[2]);