Commit 1a4a904b authored by verwaest@chromium.org's avatar verwaest@chromium.org

Replace DeoptimizeOnUndefined with whitelisting AllowUndefinedAsNan

R=danno@chromium.org

Review URL: https://chromiumcodereview.appspot.com/15952007

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@14894 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 6c21d125
......@@ -4976,7 +4976,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
DwVfpRegister result_reg,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
......@@ -4996,7 +4996,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
__ ldr(scratch, FieldMemOperand(input_reg, HeapObject::kMapOffset));
__ LoadRoot(ip, Heap::kHeapNumberMapRootIndex);
__ cmp(scratch, Operand(ip));
if (deoptimize_on_undefined) {
if (!allow_undefined_as_nan) {
DeoptimizeIf(ne, env);
} else {
Label heap_number, convert;
......@@ -5166,7 +5166,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
}
EmitNumberUntagD(input_reg, result_reg,
instr->hydrogen()->deoptimize_on_undefined(),
instr->hydrogen()->allow_undefined_as_nan(),
instr->hydrogen()->deoptimize_on_minus_zero(),
instr->environment(),
mode);
......
......@@ -335,7 +335,7 @@ class LCodeGen BASE_EMBEDDED {
void EmitBranch(int left_block, int right_block, Condition cc);
void EmitNumberUntagD(Register input,
DwVfpRegister result,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode);
......
......@@ -1485,7 +1485,7 @@ void HChange::PrintDataTo(StringStream* stream) {
if (CanTruncateToInt32()) stream->Add(" truncating-int32");
if (CheckFlag(kBailoutOnMinusZero)) stream->Add(" -0?");
if (CheckFlag(kDeoptimizeOnUndefined)) stream->Add(" deopt-on-undefined");
if (CheckFlag(kAllowUndefinedAsNaN)) stream->Add(" allow-undefined-as-nan");
}
......@@ -2490,8 +2490,8 @@ void HCompareIDAndBranch::InferRepresentation(HInferRepresentation* h_infer) {
// (false). Therefore, any comparisons other than ordered relational
// comparisons must cause a deopt when one of their arguments is undefined.
// See also v8:1434
if (!Token::IsOrderedRelationalCompareOp(token_)) {
SetFlag(kDeoptimizeOnUndefined);
if (Token::IsOrderedRelationalCompareOp(token_)) {
SetFlag(kAllowUndefinedAsNaN);
}
}
ChangeRepresentation(rep);
......@@ -2754,7 +2754,7 @@ bool HLoadKeyed::AllUsesCanTreatHoleAsNaN() const {
for (HUseIterator it(uses()); !it.Done(); it.Advance()) {
HValue* use = it.value();
if (use->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
if (!use->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
return false;
}
}
......@@ -3749,7 +3749,6 @@ void HObjectAccess::SetGVNFlags(HValue *instr, bool is_store) {
// track dominating allocations in order to eliminate write barriers
instr->SetGVNFlag(kDependsOnNewSpacePromotion);
instr->SetFlag(HValue::kTrackSideEffectDominators);
instr->SetFlag(HValue::kDeoptimizeOnUndefined);
} else {
// try to GVN loads, but don't hoist above map changes
instr->SetFlag(HValue::kUseGVN);
......
......@@ -790,7 +790,7 @@ class HValue: public ZoneObject {
kCanOverflow,
kBailoutOnMinusZero,
kCanBeDivByZero,
kDeoptimizeOnUndefined,
kAllowUndefinedAsNaN,
kIsArguments,
kTruncatingToInt32,
// Set after an instruction is killed.
......@@ -1715,14 +1715,14 @@ class HChange: public HUnaryOperation {
HChange(HValue* value,
Representation to,
bool is_truncating,
bool deoptimize_on_undefined)
bool allow_undefined_as_nan)
: HUnaryOperation(value) {
ASSERT(!value->representation().IsNone());
ASSERT(!to.IsNone());
ASSERT(!value->representation().Equals(to));
set_representation(to);
SetFlag(kUseGVN);
if (deoptimize_on_undefined) SetFlag(kDeoptimizeOnUndefined);
if (allow_undefined_as_nan) SetFlag(kAllowUndefinedAsNaN);
if (is_truncating) SetFlag(kTruncatingToInt32);
if (value->representation().IsSmi() || value->type().IsSmi()) {
set_type(HType::Smi());
......@@ -1738,8 +1738,8 @@ class HChange: public HUnaryOperation {
Representation from() const { return value()->representation(); }
Representation to() const { return representation(); }
bool deoptimize_on_undefined() const {
return CheckFlag(kDeoptimizeOnUndefined);
bool allow_undefined_as_nan() const {
return CheckFlag(kAllowUndefinedAsNaN);
}
bool deoptimize_on_minus_zero() const {
return CheckFlag(kBailoutOnMinusZero);
......@@ -1769,6 +1769,7 @@ class HClampToUint8: public HUnaryOperation {
explicit HClampToUint8(HValue* value)
: HUnaryOperation(value) {
set_representation(Representation::Integer32());
SetFlag(kAllowUndefinedAsNaN);
SetFlag(kUseGVN);
}
......@@ -2495,6 +2496,7 @@ class HBitNot: public HUnaryOperation {
set_representation(Representation::Integer32());
SetFlag(kUseGVN);
SetFlag(kTruncatingToInt32);
SetFlag(kAllowUndefinedAsNaN);
}
virtual Representation RequiredInputRepresentation(int index) {
......@@ -2604,6 +2606,7 @@ class HUnaryMathOperation: public HTemplateInstruction<2> {
UNREACHABLE();
}
SetFlag(kUseGVN);
SetFlag(kAllowUndefinedAsNaN);
}
virtual bool IsDeletable() const { return true; }
......@@ -2945,6 +2948,7 @@ class HPhi: public HValue {
}
ASSERT(merged_index >= 0);
SetFlag(kFlexibleRepresentation);
SetFlag(kAllowUndefinedAsNaN);
}
virtual Representation RepresentationFromInputs();
......@@ -3668,6 +3672,7 @@ class HBitwiseBinaryOperation: public HBinaryOperation {
: HBinaryOperation(context, left, right) {
SetFlag(kFlexibleRepresentation);
SetFlag(kTruncatingToInt32);
SetFlag(kAllowUndefinedAsNaN);
SetAllSideEffects();
}
......@@ -3722,6 +3727,7 @@ class HMathFloorOfDiv: public HBinaryOperation {
if (!right->IsConstant()) {
SetFlag(kCanBeDivByZero);
}
SetFlag(kAllowUndefinedAsNaN);
}
virtual HValue* EnsureAndPropagateNotMinusZero(BitVector* visited);
......@@ -3746,6 +3752,7 @@ class HArithmeticBinaryOperation: public HBinaryOperation {
: HBinaryOperation(context, left, right) {
SetAllSideEffects();
SetFlag(kFlexibleRepresentation);
SetFlag(kAllowUndefinedAsNaN);
}
virtual void RepresentationChanged(Representation to) {
......@@ -5731,12 +5738,11 @@ class HStoreKeyed
}
if (is_external()) {
SetGVNFlag(kChangesSpecializedArrayElements);
SetFlag(kAllowUndefinedAsNaN);
} else if (IsFastDoubleElementsKind(elements_kind)) {
SetGVNFlag(kChangesDoubleArrayElements);
SetFlag(kDeoptimizeOnUndefined);
} else if (IsFastSmiElementsKind(elements_kind)) {
SetGVNFlag(kChangesArrayElements);
SetFlag(kDeoptimizeOnUndefined);
} else {
SetGVNFlag(kChangesArrayElements);
}
......
......@@ -1586,7 +1586,10 @@ void HGraphBuilder::BuildCopyElements(HValue* context,
? FAST_HOLEY_ELEMENTS : to_elements_kind;
HInstruction* holey_store = AddInstruction(
new(zone()) HStoreKeyed(to_elements, key, element, holey_kind));
holey_store->ClearFlag(HValue::kDeoptimizeOnUndefined);
// Allow NaN hole values to converted to their tagged counterparts.
if (IsFastHoleyElementsKind(to_elements_kind)) {
holey_store->SetFlag(HValue::kAllowUndefinedAsNaN);
}
builder.EndBody();
......@@ -3100,8 +3103,8 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
// change instructions for them.
HInstruction* new_value = NULL;
bool is_truncating = use_value->CheckFlag(HValue::kTruncatingToInt32);
bool deoptimize_on_undefined =
use_value->CheckFlag(HValue::kDeoptimizeOnUndefined);
bool allow_undefined_as_nan =
use_value->CheckFlag(HValue::kAllowUndefinedAsNaN);
if (value->IsConstant()) {
HConstant* constant = HConstant::cast(value);
// Try to create a new copy of the constant with the new representation.
......@@ -3112,7 +3115,7 @@ void HGraph::InsertRepresentationChangeForUse(HValue* value,
if (new_value == NULL) {
new_value = new(zone()) HChange(value, to,
is_truncating, deoptimize_on_undefined);
is_truncating, allow_undefined_as_nan);
}
new_value->InsertBefore(next);
......@@ -3219,8 +3222,8 @@ void HGraph::InsertRepresentationChanges() {
void HGraph::RecursivelyMarkPhiDeoptimizeOnUndefined(HPhi* phi) {
if (phi->CheckFlag(HValue::kDeoptimizeOnUndefined)) return;
phi->SetFlag(HValue::kDeoptimizeOnUndefined);
if (!phi->CheckFlag(HValue::kAllowUndefinedAsNaN)) return;
phi->ClearFlag(HValue::kAllowUndefinedAsNaN);
for (int i = 0; i < phi->OperandCount(); ++i) {
HValue* input = phi->OperandAt(i);
if (input->IsPhi()) {
......@@ -3240,16 +3243,11 @@ void HGraph::MarkDeoptimizeOnUndefined() {
// if one of its uses has this flag set.
for (int i = 0; i < phi_list()->length(); i++) {
HPhi* phi = phi_list()->at(i);
if (phi->representation().IsDouble()) {
for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
int use_index = it.index();
HValue* use_value = it.value();
Representation req = use_value->RequiredInputRepresentation(use_index);
if (!req.IsDouble() ||
use_value->CheckFlag(HValue::kDeoptimizeOnUndefined)) {
RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
break;
}
for (HUseIterator it(phi->uses()); !it.Done(); it.Advance()) {
HValue* use_value = it.value();
if (!use_value->CheckFlag(HValue::kAllowUndefinedAsNaN)) {
RecursivelyMarkPhiDeoptimizeOnUndefined(phi);
break;
}
}
}
......@@ -10109,7 +10107,7 @@ void HOptimizedGraphBuilder::BuildEmitFixedDoubleArray(
boilerplate_elements, key_constant, NULL, kind, ALLOW_RETURN_HOLE));
HInstruction* store = AddInstruction(new(zone) HStoreKeyed(
object_elements, key_constant, value_instruction, kind));
store->ClearFlag(HValue::kDeoptimizeOnUndefined);
store->SetFlag(HValue::kAllowUndefinedAsNaN);
}
}
......
......@@ -5095,7 +5095,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
Register temp_reg,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
......@@ -5110,7 +5110,7 @@ void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
// Heap number map check.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
if (deoptimize_on_undefined) {
if (!allow_undefined_as_nan) {
DeoptimizeIf(not_equal, env);
} else {
Label heap_number, convert;
......@@ -5167,7 +5167,7 @@ void LCodeGen::EmitNumberUntagDNoSSE2(Register input_reg,
void LCodeGen::EmitNumberUntagD(Register input_reg,
Register temp_reg,
XMMRegister result_reg,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
......@@ -5182,7 +5182,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Heap number map check.
__ cmp(FieldOperand(input_reg, HeapObject::kMapOffset),
factory()->heap_number_map());
if (deoptimize_on_undefined) {
if (!allow_undefined_as_nan) {
DeoptimizeIf(not_equal, env);
} else {
Label heap_number, convert;
......@@ -5530,14 +5530,14 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
EmitNumberUntagD(input_reg,
temp_reg,
result_reg,
instr->hydrogen()->deoptimize_on_undefined(),
instr->hydrogen()->allow_undefined_as_nan(),
deoptimize_on_minus_zero,
instr->environment(),
mode);
} else {
EmitNumberUntagDNoSSE2(input_reg,
temp_reg,
instr->hydrogen()->deoptimize_on_undefined(),
instr->hydrogen()->allow_undefined_as_nan(),
deoptimize_on_minus_zero,
instr->environment(),
mode);
......
......@@ -331,7 +331,7 @@ class LCodeGen BASE_EMBEDDED {
Register input,
Register temp,
XMMRegister result,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
......@@ -339,7 +339,7 @@ class LCodeGen BASE_EMBEDDED {
void EmitNumberUntagDNoSSE2(
Register input,
Register temp,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
......
......@@ -4688,7 +4688,7 @@ void LCodeGen::DoSmiUntag(LSmiUntag* instr) {
void LCodeGen::EmitNumberUntagD(Register input_reg,
XMMRegister result_reg,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode) {
......@@ -4703,7 +4703,7 @@ void LCodeGen::EmitNumberUntagD(Register input_reg,
// Heap number map check.
__ CompareRoot(FieldOperand(input_reg, HeapObject::kMapOffset),
Heap::kHeapNumberMapRootIndex);
if (deoptimize_on_undefined) {
if (!allow_undefined_as_nan) {
DeoptimizeIf(not_equal, env);
} else {
Label heap_number, convert;
......@@ -4839,7 +4839,7 @@ void LCodeGen::DoNumberUntagD(LNumberUntagD* instr) {
}
EmitNumberUntagD(input_reg, result_reg,
instr->hydrogen()->deoptimize_on_undefined(),
instr->hydrogen()->allow_undefined_as_nan(),
instr->hydrogen()->deoptimize_on_minus_zero(),
instr->environment(),
mode);
......
......@@ -295,7 +295,7 @@ class LCodeGen BASE_EMBEDDED {
void EmitNumberUntagD(
Register input,
XMMRegister result,
bool deoptimize_on_undefined,
bool allow_undefined_as_nan,
bool deoptimize_on_minus_zero,
LEnvironment* env,
NumberUntagDMode mode = NUMBER_CANDIDATE_IS_ANY_TAGGED);
......
......@@ -27,7 +27,7 @@
// Flags: --allow-natives-syntax
function f(test, test2, a, i) {
function f_store(test, test2, a, i) {
var o = [0.5,1,,3];
var d;
if (test) {
......@@ -42,11 +42,67 @@ function f(test, test2, a, i) {
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]);
var a1 = [0, 0, 0, {}];
f_store(true, false, a1, 0);
f_store(true, true, a1, 0);
f_store(false, false, a1, 1);
f_store(false, true, a1, 1);
%OptimizeFunctionOnNextCall(f_store);
f_store(false, false, a1, 2);
assertEquals(undefined, a1[2]);
function test_arg(expected) {
return function(v) {
assertEquals(expected, v);
}
}
function f_call(f, test, test2, i) {
var o = [0.5,1,,3];
var d;
if (test) {
d = 1.5;
} else {
d = o[i];
}
if (test2) {
d += 1;
}
f(d);
return d;
}
f_call(test_arg(1.5), true, false, 0);
f_call(test_arg(2.5), true, true, 0);
f_call(test_arg(1), false, false, 1);
f_call(test_arg(2), false, true, 1);
%OptimizeFunctionOnNextCall(f_call);
f_call(test_arg(undefined), false, false, 2);
function f_external(test, test2, test3, a, i) {
var o = [0.5,1,,3];
var d;
if (test) {
d = 1.5;
} else {
d = o[i];
}
if (test2) {
d += 1;
}
if (test3) {
d = d|0;
}
a[d] = 1;
return d;
}
var a2 = new Int32Array(10);
f_external(true, false, true, a2, 0);
f_external(true, true, true, a2, 0);
f_external(false, false, true, a2, 1);
f_external(false, true, true, a2, 1);
%OptimizeFunctionOnNextCall(f_external);
f_external(false, false, false, a2, 2);
assertEquals(1, a2[undefined]);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment