diff --git a/src/code-stubs.h b/src/code-stubs.h index cfc0ab0371..c5fd7cfef7 100644 --- a/src/code-stubs.h +++ b/src/code-stubs.h @@ -933,6 +933,8 @@ class ToBooleanStub: public CodeStub { EnumSet set_; }; + static Types no_types() { return Types(); } + explicit ToBooleanStub(Register tos, Types types = Types()) : tos_(tos), types_(types) { } diff --git a/src/hydrogen-instructions.h b/src/hydrogen-instructions.h index bd6763f140..fcf5b25588 100644 --- a/src/hydrogen-instructions.h +++ b/src/hydrogen-instructions.h @@ -933,8 +933,12 @@ class HUnaryControlInstruction: public HTemplateControlInstruction<2, 1> { class HBranch: public HUnaryControlInstruction { public: - HBranch(HValue* value, HBasicBlock* true_target, HBasicBlock* false_target) - : HUnaryControlInstruction(value, true_target, false_target) { + HBranch(HValue* value, + HBasicBlock* true_target, + HBasicBlock* false_target, + ToBooleanStub::Types expected_input_types = ToBooleanStub::no_types()) + : HUnaryControlInstruction(value, true_target, false_target), + expected_input_types_(expected_input_types) { ASSERT(true_target != NULL && false_target != NULL); } explicit HBranch(HValue* value) @@ -945,7 +949,14 @@ class HBranch: public HUnaryControlInstruction { return Representation::None(); } + ToBooleanStub::Types expected_input_types() const { + return expected_input_types_; + } + DECLARE_CONCRETE_INSTRUCTION(Branch) + + private: + ToBooleanStub::Types expected_input_types_; }; diff --git a/src/hydrogen.cc b/src/hydrogen.cc index d03aa5d2f6..199eac8f10 100644 --- a/src/hydrogen.cc +++ b/src/hydrogen.cc @@ -2158,7 +2158,9 @@ void TestContext::BuildBranch(HValue* value) { } HBasicBlock* empty_true = builder->graph()->CreateBasicBlock(); HBasicBlock* empty_false = builder->graph()->CreateBasicBlock(); - HBranch* test = new(zone()) HBranch(value, empty_true, empty_false); + unsigned test_id = condition()->test_id(); + ToBooleanStub::Types expected(builder->oracle()->ToBooleanTypes(test_id)); + HBranch* test = new(zone()) HBranch(value, empty_true, empty_false, expected); builder->current_block()->Finish(test); empty_true->Goto(if_true()); @@ -5504,9 +5506,11 @@ void HGraphBuilder::VisitLogicalExpression(BinaryOperation* expr) { // We need an extra block to maintain edge-split form. HBasicBlock* empty_block = graph()->CreateBasicBlock(); HBasicBlock* eval_right = graph()->CreateBasicBlock(); + unsigned test_id = expr->left()->test_id(); + ToBooleanStub::Types expected(oracle()->ToBooleanTypes(test_id)); HBranch* test = is_logical_and - ? new(zone()) HBranch(Top(), eval_right, empty_block) - : new(zone()) HBranch(Top(), empty_block, eval_right); + ? new(zone()) HBranch(Top(), eval_right, empty_block, expected) + : new(zone()) HBranch(Top(), empty_block, eval_right, expected); current_block()->Finish(test); set_current_block(eval_right); diff --git a/src/hydrogen.h b/src/hydrogen.h index c0d6323fc4..c8e3f0a9cc 100644 --- a/src/hydrogen.h +++ b/src/hydrogen.h @@ -719,6 +719,8 @@ class HGraphBuilder: public AstVisitor { HBasicBlock* second, int join_id); + TypeFeedbackOracle* oracle() const { return function_state()->oracle(); } + private: // Type of a member function that generates inline code for a native function. typedef void (HGraphBuilder::*InlineFunctionGenerator)(CallRuntime* call); @@ -747,7 +749,6 @@ class HGraphBuilder: public AstVisitor { CompilationInfo* info() const { return function_state()->compilation_info(); } - TypeFeedbackOracle* oracle() const { return function_state()->oracle(); } AstContext* call_context() const { return function_state()->call_context(); diff --git a/src/ia32/full-codegen-ia32.cc b/src/ia32/full-codegen-ia32.cc index f9f63a70ed..7d41d9524f 100644 --- a/src/ia32/full-codegen-ia32.cc +++ b/src/ia32/full-codegen-ia32.cc @@ -572,7 +572,7 @@ void FullCodeGenerator::DoTest(Expression* condition, Label* fall_through) { ToBooleanStub stub(result_register()); __ push(result_register()); - __ CallStub(&stub); + __ CallStub(&stub, condition->test_id()); __ test(result_register(), Operand(result_register())); // The stub returns nonzero for true. Split(not_zero, if_true, if_false, fall_through); diff --git a/src/type-info.cc b/src/type-info.cc index defb1ae966..e10c5f40e4 100644 --- a/src/type-info.cc +++ b/src/type-info.cc @@ -439,6 +439,12 @@ void TypeFeedbackOracle::CollectKeyedReceiverTypes( } +byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) { + Handle object = GetInfo(ast_id); + return object->IsCode() ? Handle::cast(object)->to_boolean_state() : 0; +} + + // Things are a bit tricky here: The iterator for the RelocInfos and the infos // themselves are not GC-safe, so we first get all infos, then we create the // dictionary (possibly triggering GC), and finally we relocate the collected @@ -523,6 +529,7 @@ void TypeFeedbackOracle::ProcessTarget(unsigned ast_id, Code* target) { case Code::UNARY_OP_IC: case Code::BINARY_OP_IC: case Code::COMPARE_IC: + case Code::TO_BOOLEAN_IC: SetInfo(ast_id, target); break; diff --git a/src/type-info.h b/src/type-info.h index 0a8c935dfa..dee4c34c92 100644 --- a/src/type-info.h +++ b/src/type-info.h @@ -238,6 +238,11 @@ class TypeFeedbackOracle BASE_EMBEDDED { bool LoadIsBuiltin(Property* expr, Builtins::Name id); + // TODO(1571) We can't use ToBooleanStub::Types as the return value because + // of various cylces in our headers. Death to tons of implementations in + // headers!! :-P + byte ToBooleanTypes(unsigned ast_id); + // Get type information for arithmetic operations and compares. TypeInfo UnaryType(UnaryOperation* expr); TypeInfo BinaryType(BinaryOperation* expr);