Index: src/crankshaft/hydrogen.cc |
diff --git a/src/crankshaft/hydrogen.cc b/src/crankshaft/hydrogen.cc |
index 33b0c27565d22ca57c4f05f32fa3c53858848e63..1eccd38789c68eaf99f2cd03251a3f58c767bbb0 100644 |
--- a/src/crankshaft/hydrogen.cc |
+++ b/src/crankshaft/hydrogen.cc |
@@ -3177,6 +3177,58 @@ |
BuildCopyElements(boilerplate_elements, kind, elements, |
kind, length, NULL); |
return result; |
+} |
+ |
+ |
+void HGraphBuilder::BuildCompareNil(HValue* value, Type* type, |
+ HIfContinuation* continuation, |
+ MapEmbedding map_embedding) { |
+ IfBuilder if_nil(this); |
+ |
+ if (type->Maybe(Type::Undetectable())) { |
+ if_nil.If<HIsUndetectableAndBranch>(value); |
+ } else { |
+ bool maybe_null = type->Maybe(Type::Null()); |
+ if (maybe_null) { |
+ if_nil.If<HCompareObjectEqAndBranch>(value, graph()->GetConstantNull()); |
+ } |
+ |
+ if (type->Maybe(Type::Undefined())) { |
+ if (maybe_null) if_nil.Or(); |
+ if_nil.If<HCompareObjectEqAndBranch>(value, |
+ graph()->GetConstantUndefined()); |
+ } |
+ |
+ if_nil.Then(); |
+ if_nil.Else(); |
+ |
+ if (type->NumClasses() == 1) { |
+ BuildCheckHeapObject(value); |
+ // For ICs, the map checked below is a sentinel map that gets replaced by |
+ // the monomorphic map when the code is used as a template to generate a |
+ // new IC. For optimized functions, there is no sentinel map, the map |
+ // emitted below is the actual monomorphic map. |
+ if (map_embedding == kEmbedMapsViaWeakCells) { |
+ HValue* cell = |
+ Add<HConstant>(Map::WeakCellForMap(type->Classes().Current())); |
+ HValue* expected_map = Add<HLoadNamedField>( |
+ cell, nullptr, HObjectAccess::ForWeakCellValue()); |
+ HValue* map = |
+ Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); |
+ IfBuilder map_check(this); |
+ map_check.IfNot<HCompareObjectEqAndBranch>(expected_map, map); |
+ map_check.ThenDeopt(Deoptimizer::kUnknownMap); |
+ map_check.End(); |
+ } else { |
+ DCHECK(map_embedding == kEmbedMapsDirectly); |
+ Add<HCheckMaps>(value, type->Classes().Current()); |
+ } |
+ } else { |
+ if_nil.Deopt(Deoptimizer::kTooManyUndetectableTypes); |
+ } |
+ } |
+ |
+ if_nil.CaptureContinuation(continuation); |
} |
@@ -11688,17 +11740,22 @@ |
if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); |
CHECK_ALIVE(VisitForValue(sub_expr)); |
HValue* value = Pop(); |
- HControlInstruction* instr; |
if (expr->op() == Token::EQ_STRICT) { |
HConstant* nil_constant = nil == kNullValue |
? graph()->GetConstantNull() |
: graph()->GetConstantUndefined(); |
- instr = New<HCompareObjectEqAndBranch>(value, nil_constant); |
+ HCompareObjectEqAndBranch* instr = |
+ New<HCompareObjectEqAndBranch>(value, nil_constant); |
+ return ast_context()->ReturnControl(instr, expr->id()); |
} else { |
DCHECK_EQ(Token::EQ, expr->op()); |
- instr = New<HIsUndetectableAndBranch>(value); |
- } |
- return ast_context()->ReturnControl(instr, expr->id()); |
+ Type* type = expr->combined_type()->Is(Type::None()) |
+ ? Type::Any() |
+ : expr->combined_type(); |
+ HIfContinuation continuation; |
+ BuildCompareNil(value, type, &continuation); |
+ return ast_context()->ReturnContinuation(&continuation, expr->id()); |
+ } |
} |