Record ToBoolean's type information in Hydrogen's HBranch instruction, so we can...
authorsvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 25 Jul 2011 14:08:36 +0000 (14:08 +0000)
committersvenpanne@chromium.org <svenpanne@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 25 Jul 2011 14:08:36 +0000 (14:08 +0000)
Review URL: http://codereview.chromium.org/7491043

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8736 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/code-stubs.h
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/full-codegen-ia32.cc
src/type-info.cc
src/type-info.h

index cfc0ab0371250c79b929a09b2a2b41c982bac2ed..c5fd7cfef76e638e28c524b21f3b7ff345bcb9c4 100644 (file)
@@ -933,6 +933,8 @@ class ToBooleanStub: public CodeStub {
     EnumSet<Type, byte> set_;
   };
 
+  static Types no_types() { return Types(); }
+
   explicit ToBooleanStub(Register tos, Types types = Types())
       : tos_(tos), types_(types) { }
 
index bd6763f140ad15762dfe24e2fd32ae311bd52c72..fcf5b25588e088817721183368db94d8b87167ec 100644 (file)
@@ -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_;
 };
 
 
index d03aa5d2f657d7e1c58731a9faf8ed055a472afd..199eac8f10f38c37c221cb0eacbecb0f59f811b6 100644 (file)
@@ -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);
index c0d6323fc48f2f8c2efe6d50909636d99ec18abe..c8e3f0a9cce3def217d9c6c43d4da4e5d43ef58d 100644 (file)
@@ -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();
index f9f63a70edff7fa1b3516869e9e9a1212bc4f606..7d41d9524f3e3409e12c7494091349c66f58ccaf 100644 (file)
@@ -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);
index defb1ae9666a48da8f41cc83eb7f5e028354da01..e10c5f40e45e1769a58313f8a03adfda153e1d15 100644 (file)
@@ -439,6 +439,12 @@ void TypeFeedbackOracle::CollectKeyedReceiverTypes(
 }
 
 
+byte TypeFeedbackOracle::ToBooleanTypes(unsigned ast_id) {
+  Handle<Object> object = GetInfo(ast_id);
+  return object->IsCode() ? Handle<Code>::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;
 
index 0a8c935dfac3fb219999a9b350c3053cb46bf19a..dee4c34c929453e16d2f081927967ba171acf0fe 100644 (file)
@@ -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);