Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(40)

Side by Side Diff: src/hydrogen.cc

Issue 6963008: A few "extract method" refactorings, trying to get individual method definitions (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: '' Created 9 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 4550 matching lines...) Expand 10 before | Expand all | Expand 10 after
4561 Drop(argument_count); 4561 Drop(argument_count);
4562 ast_context()->ReturnInstruction(call, expr->id()); 4562 ast_context()->ReturnInstruction(call, expr->id());
4563 } 4563 }
4564 } 4564 }
4565 4565
4566 4566
4567 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) { 4567 void HGraphBuilder::VisitUnaryOperation(UnaryOperation* expr) {
4568 ASSERT(!HasStackOverflow()); 4568 ASSERT(!HasStackOverflow());
4569 ASSERT(current_block() != NULL); 4569 ASSERT(current_block() != NULL);
4570 ASSERT(current_block()->HasPredecessor()); 4570 ASSERT(current_block()->HasPredecessor());
4571 Token::Value op = expr->op(); 4571 switch (expr->op()) {
4572 if (op == Token::VOID) { 4572 case Token::DELETE: return VisitDelete(expr);
4573 case Token::VOID: return VisitVoid(expr);
4574 case Token::TYPEOF: return VisitTypeof(expr);
4575 case Token::ADD: return VisitAdd(expr);
4576 case Token::SUB: return VisitSub(expr);
4577 case Token::BIT_NOT: return VisitBitNot(expr);
4578 case Token::NOT: return VisitNot(expr);
4579 default: UNREACHABLE();
4580 }
4581 }
4582
4583 void HGraphBuilder::VisitDelete(UnaryOperation* expr) {
4584 Property* prop = expr->expression()->AsProperty();
4585 Variable* var = expr->expression()->AsVariableProxy()->AsVariable();
4586 if (prop == NULL && var == NULL) {
4587 // Result of deleting non-property, non-variable reference is true.
4588 // Evaluate the subexpression for side effects.
4573 CHECK_ALIVE(VisitForEffect(expr->expression())); 4589 CHECK_ALIVE(VisitForEffect(expr->expression()));
4574 ast_context()->ReturnValue(graph()->GetConstantUndefined()); 4590 ast_context()->ReturnValue(graph()->GetConstantTrue());
4575 } else if (op == Token::DELETE) { 4591 } else if (var != NULL &&
4576 Property* prop = expr->expression()->AsProperty(); 4592 !var->is_global() &&
4577 Variable* var = expr->expression()->AsVariableProxy()->AsVariable(); 4593 var->AsSlot() != NULL &&
4578 if (prop == NULL && var == NULL) { 4594 var->AsSlot()->type() != Slot::LOOKUP) {
4579 // Result of deleting non-property, non-variable reference is true. 4595 // Result of deleting non-global, non-dynamic variables is false.
4580 // Evaluate the subexpression for side effects. 4596 // The subexpression does not have side effects.
4581 CHECK_ALIVE(VisitForEffect(expr->expression())); 4597 ast_context()->ReturnValue(graph()->GetConstantFalse());
4582 ast_context()->ReturnValue(graph()->GetConstantTrue()); 4598 } else if (prop != NULL) {
4583 } else if (var != NULL && 4599 if (prop->is_synthetic()) {
4584 !var->is_global() && 4600 // Result of deleting parameters is false, even when they rewrite
4585 var->AsSlot() != NULL && 4601 // to accesses on the arguments object.
4586 var->AsSlot()->type() != Slot::LOOKUP) {
4587 // Result of deleting non-global, non-dynamic variables is false.
4588 // The subexpression does not have side effects.
4589 ast_context()->ReturnValue(graph()->GetConstantFalse()); 4602 ast_context()->ReturnValue(graph()->GetConstantFalse());
4590 } else if (prop != NULL) {
4591 if (prop->is_synthetic()) {
4592 // Result of deleting parameters is false, even when they rewrite
4593 // to accesses on the arguments object.
4594 ast_context()->ReturnValue(graph()->GetConstantFalse());
4595 } else {
4596 CHECK_ALIVE(VisitForValue(prop->obj()));
4597 CHECK_ALIVE(VisitForValue(prop->key()));
4598 HValue* key = Pop();
4599 HValue* obj = Pop();
4600 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key);
4601 ast_context()->ReturnInstruction(instr, expr->id());
4602 }
4603 } else if (var->is_global()) {
4604 return Bailout("delete with global variable");
4605 } else { 4603 } else {
4606 return Bailout("delete with non-global variable"); 4604 CHECK_ALIVE(VisitForValue(prop->obj()));
4605 CHECK_ALIVE(VisitForValue(prop->key()));
4606 HValue* key = Pop();
4607 HValue* obj = Pop();
4608 HDeleteProperty* instr = new(zone()) HDeleteProperty(obj, key);
4609 ast_context()->ReturnInstruction(instr, expr->id());
4607 } 4610 }
4608 } else if (op == Token::NOT) { 4611 } else if (var->is_global()) {
4609 if (ast_context()->IsTest()) { 4612 Bailout("delete with global variable");
4610 TestContext* context = TestContext::cast(ast_context());
4611 VisitForControl(expr->expression(),
4612 context->if_false(),
4613 context->if_true());
4614 } else if (ast_context()->IsValue()) {
4615 HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4616 HBasicBlock* materialize_true = graph()->CreateBasicBlock();
4617 CHECK_BAILOUT(VisitForControl(expr->expression(),
4618 materialize_false,
4619 materialize_true));
4620
4621 if (materialize_false->HasPredecessor()) {
4622 materialize_false->SetJoinId(expr->expression()->id());
4623 set_current_block(materialize_false);
4624 Push(graph()->GetConstantFalse());
4625 } else {
4626 materialize_false = NULL;
4627 }
4628
4629 if (materialize_true->HasPredecessor()) {
4630 materialize_true->SetJoinId(expr->expression()->id());
4631 set_current_block(materialize_true);
4632 Push(graph()->GetConstantTrue());
4633 } else {
4634 materialize_true = NULL;
4635 }
4636
4637 HBasicBlock* join =
4638 CreateJoin(materialize_false, materialize_true, expr->id());
4639 set_current_block(join);
4640 if (join != NULL) ast_context()->ReturnValue(Pop());
4641 } else {
4642 ASSERT(ast_context()->IsEffect());
4643 VisitForEffect(expr->expression());
4644 }
4645
4646 } else if (op == Token::TYPEOF) {
4647 CHECK_ALIVE(VisitForTypeOf(expr->expression()));
4648 HValue* value = Pop();
4649 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id());
4650
4651 } else { 4613 } else {
4652 CHECK_ALIVE(VisitForValue(expr->expression())); 4614 Bailout("delete with non-global variable");
4653 HValue* value = Pop();
4654 HInstruction* instr = NULL;
4655 switch (op) {
4656 case Token::BIT_NOT:
4657 instr = new(zone()) HBitNot(value);
4658 break;
4659 case Token::SUB:
4660 instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
4661 break;
4662 case Token::ADD:
4663 instr = new(zone()) HMul(value, graph_->GetConstant1());
4664 break;
4665 default:
4666 return Bailout("Value: unsupported unary operation");
4667 break;
4668 }
4669 ast_context()->ReturnInstruction(instr, expr->id());
4670 } 4615 }
4671 } 4616 }
4672 4617
4673 4618
4619 void HGraphBuilder::VisitVoid(UnaryOperation* expr) {
4620 CHECK_ALIVE(VisitForEffect(expr->expression()));
4621 ast_context()->ReturnValue(graph()->GetConstantUndefined());
4622 }
4623
4624
4625 void HGraphBuilder::VisitTypeof(UnaryOperation* expr) {
4626 CHECK_ALIVE(VisitForTypeOf(expr->expression()));
4627 HValue* value = Pop();
4628 ast_context()->ReturnInstruction(new(zone()) HTypeof(value), expr->id());
4629 }
4630
4631
4632 void HGraphBuilder::VisitAdd(UnaryOperation* expr) {
4633 CHECK_ALIVE(VisitForValue(expr->expression()));
4634 HValue* value = Pop();
4635 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstant1());
4636 ast_context()->ReturnInstruction(instr, expr->id());
4637 }
4638
4639
4640 void HGraphBuilder::VisitSub(UnaryOperation* expr) {
4641 CHECK_ALIVE(VisitForValue(expr->expression()));
4642 HValue* value = Pop();
4643 HInstruction* instr = new(zone()) HMul(value, graph_->GetConstantMinus1());
4644 ast_context()->ReturnInstruction(instr, expr->id());
4645 }
4646
4647
4648 void HGraphBuilder::VisitBitNot(UnaryOperation* expr) {
4649 CHECK_ALIVE(VisitForValue(expr->expression()));
4650 HValue* value = Pop();
4651 HInstruction* instr = new(zone()) HBitNot(value);
4652 ast_context()->ReturnInstruction(instr, expr->id());
4653 }
4654
4655
4656 void HGraphBuilder::VisitNot(UnaryOperation* expr) {
4657 // TODO(svenpanne) Perhaps a switch/virtual function is nicer here.
4658 if (ast_context()->IsTest()) {
4659 TestContext* context = TestContext::cast(ast_context());
4660 VisitForControl(expr->expression(),
4661 context->if_false(),
4662 context->if_true());
4663 return;
4664 }
4665
4666 if (ast_context()->IsEffect()) {
4667 VisitForEffect(expr->expression());
4668 return;
4669 }
4670
4671 ASSERT(ast_context()->IsValue());
4672 HBasicBlock* materialize_false = graph()->CreateBasicBlock();
4673 HBasicBlock* materialize_true = graph()->CreateBasicBlock();
4674 CHECK_BAILOUT(VisitForControl(expr->expression(),
4675 materialize_false,
4676 materialize_true));
4677
4678 if (materialize_false->HasPredecessor()) {
4679 materialize_false->SetJoinId(expr->expression()->id());
4680 set_current_block(materialize_false);
4681 Push(graph()->GetConstantFalse());
4682 } else {
4683 materialize_false = NULL;
4684 }
4685
4686 if (materialize_true->HasPredecessor()) {
4687 materialize_true->SetJoinId(expr->expression()->id());
4688 set_current_block(materialize_true);
4689 Push(graph()->GetConstantTrue());
4690 } else {
4691 materialize_true = NULL;
4692 }
4693
4694 HBasicBlock* join =
4695 CreateJoin(materialize_false, materialize_true, expr->id());
4696 set_current_block(join);
4697 if (join != NULL) ast_context()->ReturnValue(Pop());
4698 }
4699
4700
4674 HInstruction* HGraphBuilder::BuildIncrement(HValue* value, 4701 HInstruction* HGraphBuilder::BuildIncrement(HValue* value,
4675 bool increment, 4702 bool increment,
4676 CountOperation* expr) { 4703 CountOperation* expr) {
4677 HConstant* delta = increment 4704 HConstant* delta = increment
4678 ? graph_->GetConstant1() 4705 ? graph_->GetConstant1()
4679 : graph_->GetConstantMinus1(); 4706 : graph_->GetConstantMinus1();
4680 HInstruction* instr = new(zone()) HAdd(value, delta); 4707 HInstruction* instr = new(zone()) HAdd(value, delta);
4681 Representation rep = ToRepresentation(oracle()->IncrementType(expr)); 4708 Representation rep = ToRepresentation(oracle()->IncrementType(expr));
4682 if (rep.IsTagged()) { 4709 if (rep.IsTagged()) {
4683 rep = Representation::Integer32(); 4710 rep = Representation::Integer32();
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
4827 AddInstruction(length); 4854 AddInstruction(length);
4828 AddInstruction(new(zone()) HBoundsCheck(index, length)); 4855 AddInstruction(new(zone()) HBoundsCheck(index, length));
4829 return new(zone()) HStringCharCodeAt(string, index); 4856 return new(zone()) HStringCharCodeAt(string, index);
4830 } 4857 }
4831 4858
4832 4859
4833 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr, 4860 HInstruction* HGraphBuilder::BuildBinaryOperation(BinaryOperation* expr,
4834 HValue* left, 4861 HValue* left,
4835 HValue* right) { 4862 HValue* right) {
4836 TypeInfo info = oracle()->BinaryType(expr); 4863 TypeInfo info = oracle()->BinaryType(expr);
4837 HInstruction* instr = NULL; 4864 HInstruction* instr = BuildBinaryOperation(expr->op(), left, right, info);
fschneider 2011/05/10 13:34:20 I agree with Kevin to a degree. Having two functi
4838 switch (expr->op()) {
4839 case Token::ADD:
4840 if (info.IsString()) {
4841 AddInstruction(new(zone()) HCheckNonSmi(left));
4842 AddInstruction(new(zone()) HCheckInstanceType(
4843 left, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4844 AddInstruction(new(zone()) HCheckNonSmi(right));
4845 AddInstruction(new(zone()) HCheckInstanceType(
4846 right, FIRST_STRING_TYPE, LAST_STRING_TYPE));
4847 instr = new(zone()) HStringAdd(left, right);
4848 } else {
4849 instr = new(zone()) HAdd(left, right);
4850 }
4851 break;
4852 case Token::SUB:
4853 instr = new(zone()) HSub(left, right);
4854 break;
4855 case Token::MUL:
4856 instr = new(zone()) HMul(left, right);
4857 break;
4858 case Token::MOD:
4859 instr = new(zone()) HMod(left, right);
4860 break;
4861 case Token::DIV:
4862 instr = new(zone()) HDiv(left, right);
4863 break;
4864 case Token::BIT_XOR:
4865 instr = new(zone()) HBitXor(left, right);
4866 break;
4867 case Token::BIT_AND:
4868 instr = new(zone()) HBitAnd(left, right);
4869 break;
4870 case Token::BIT_OR:
4871 instr = new(zone()) HBitOr(left, right);
4872 break;
4873 case Token::SAR:
4874 instr = new(zone()) HSar(left, right);
4875 break;
4876 case Token::SHR:
4877 instr = new(zone()) HShr(left, right);
4878 break;
4879 case Token::SHL:
4880 instr = new(zone()) HShl(left, right);
4881 break;
4882 default:
4883 UNREACHABLE();
4884 }
4885 // If we hit an uninitialized binary op stub we will get type info 4865 // If we hit an uninitialized binary op stub we will get type info
4886 // for a smi operation. If one of the operands is a constant string 4866 // for a smi operation. If one of the operands is a constant string
4887 // do not generate code assuming it is a smi operation. 4867 // do not generate code assuming it is a smi operation.
4888 if (info.IsSmi() && 4868 if (info.IsSmi() &&
4889 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) || 4869 ((left->IsConstant() && HConstant::cast(left)->HasStringValue()) ||
4890 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) { 4870 (right->IsConstant() && HConstant::cast(right)->HasStringValue()))) {
4891 return instr; 4871 return instr;
4892 } 4872 }
4893 if (FLAG_trace_representation) { 4873 if (FLAG_trace_representation) {
4894 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic()); 4874 PrintF("Info: %s/%s\n", info.ToString(), ToRepresentation(info).Mnemonic());
4895 } 4875 }
4896 Representation rep = ToRepresentation(info); 4876 Representation rep = ToRepresentation(info);
4897 // We only generate either int32 or generic tagged bitwise operations. 4877 // We only generate either int32 or generic tagged bitwise operations.
4898 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) { 4878 if (instr->IsBitwiseBinaryOperation() && rep.IsDouble()) {
4899 rep = Representation::Integer32(); 4879 rep = Representation::Integer32();
4900 } 4880 }
4901 AssumeRepresentation(instr, rep); 4881 AssumeRepresentation(instr, rep);
4902 return instr; 4882 return instr;
4903 } 4883 }
4904 4884
4905 4885
4886 HInstruction* HGraphBuilder::BuildBinaryOperation(
4887 Token::Value op, HValue* left, HValue* right, TypeInfo info) {
4888 switch (op) {
4889 case Token::ADD:
4890 if (info.IsString()) {
4891 AddInstruction(new(zone()) HCheckNonSmi(left));
4892 AddInstruction(new(zone()) HCheckInstanceType(left, FIRST_STRING_TYPE,
4893 LAST_STRING_TYPE));
4894 AddInstruction(new(zone()) HCheckNonSmi(right));
4895 AddInstruction(new(zone()) HCheckInstanceType(right, FIRST_STRING_TYPE,
4896 LAST_STRING_TYPE));
4897 return new(zone()) HStringAdd(left, right);
4898 } else {
4899 return new(zone()) HAdd(left, right);
4900 }
4901 case Token::SUB: return new(zone()) HSub(left, right);
4902 case Token::MUL: return new(zone()) HMul(left, right);
4903 case Token::MOD: return new(zone()) HMod(left, right);
4904 case Token::DIV: return new(zone()) HDiv(left, right);
4905 case Token::BIT_XOR: return new(zone()) HBitXor(left, right);
4906 case Token::BIT_AND: return new(zone()) HBitAnd(left, right);
4907 case Token::BIT_OR: return new(zone()) HBitOr(left, right);
4908 case Token::SAR: return new(zone()) HSar(left, right);
4909 case Token::SHR: return new(zone()) HShr(left, right);
4910 case Token::SHL: return new(zone()) HShl(left, right);
4911 default:
4912 UNREACHABLE();
4913 return NULL;
4914 }
4915 }
4916
4917
4906 // Check for the form (%_ClassOf(foo) === 'BarClass'). 4918 // Check for the form (%_ClassOf(foo) === 'BarClass').
4907 static bool IsClassOfTest(CompareOperation* expr) { 4919 static bool IsClassOfTest(CompareOperation* expr) {
4908 if (expr->op() != Token::EQ_STRICT) return false; 4920 if (expr->op() != Token::EQ_STRICT) return false;
4909 CallRuntime* call = expr->left()->AsCallRuntime(); 4921 CallRuntime* call = expr->left()->AsCallRuntime();
4910 if (call == NULL) return false; 4922 if (call == NULL) return false;
4911 Literal* literal = expr->right()->AsLiteral(); 4923 Literal* literal = expr->right()->AsLiteral();
4912 if (literal == NULL) return false; 4924 if (literal == NULL) return false;
4913 if (!literal->handle()->IsString()) return false; 4925 if (!literal->handle()->IsString()) return false;
4914 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false; 4926 if (!call->name()->IsEqualTo(CStrVector("_ClassOf"))) return false;
4915 ASSERT(call->arguments()->length() == 1); 4927 ASSERT(call->arguments()->length() == 1);
4916 return true; 4928 return true;
4917 } 4929 }
4918 4930
4919 4931
4920 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) { 4932 void HGraphBuilder::VisitBinaryOperation(BinaryOperation* expr) {
4921 ASSERT(!HasStackOverflow()); 4933 ASSERT(!HasStackOverflow());
4922 ASSERT(current_block() != NULL); 4934 ASSERT(current_block() != NULL);
4923 ASSERT(current_block()->HasPredecessor()); 4935 ASSERT(current_block()->HasPredecessor());
4924 if (expr->op() == Token::COMMA) { 4936 switch (expr->op()) {
4925 CHECK_ALIVE(VisitForEffect(expr->left())); 4937 case Token::COMMA: return VisitComma(expr);
4926 // Visit the right subexpression in the same AST context as the entire 4938 case Token::OR: return VisitAndOr(expr, false);
4927 // expression. 4939 case Token::AND: return VisitAndOr(expr, true);
4928 Visit(expr->right()); 4940 default: return VisitCommon(expr);
4941 }
4942 }
4929 4943
4930 } else if (expr->op() == Token::AND || expr->op() == Token::OR) {
4931 bool is_logical_and = (expr->op() == Token::AND);
4932 if (ast_context()->IsTest()) {
4933 TestContext* context = TestContext::cast(ast_context());
4934 // Translate left subexpression.
4935 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4936 if (is_logical_and) {
4937 CHECK_BAILOUT(VisitForControl(expr->left(),
4938 eval_right,
4939 context->if_false()));
4940 } else {
4941 CHECK_BAILOUT(VisitForControl(expr->left(),
4942 context->if_true(),
4943 eval_right));
4944 }
4945 4944
4946 // Translate right subexpression by visiting it in the same AST 4945 void HGraphBuilder::VisitComma(BinaryOperation* expr) {
4947 // context as the entire expression. 4946 CHECK_ALIVE(VisitForEffect(expr->left()));
4948 if (eval_right->HasPredecessor()) { 4947 // Visit the right subexpression in the same AST context as the entire
4949 eval_right->SetJoinId(expr->RightId()); 4948 // expression.
4950 set_current_block(eval_right); 4949 Visit(expr->right());
4951 Visit(expr->right()); 4950 }
4952 }
4953 4951
4954 } else if (ast_context()->IsValue()) {
4955 CHECK_ALIVE(VisitForValue(expr->left()));
4956 ASSERT(current_block() != NULL);
4957 4952
4958 // We need an extra block to maintain edge-split form. 4953 void HGraphBuilder::VisitAndOr(BinaryOperation* expr, bool is_logical_and) {
4959 HBasicBlock* empty_block = graph()->CreateBasicBlock(); 4954 if (ast_context()->IsTest()) {
4960 HBasicBlock* eval_right = graph()->CreateBasicBlock(); 4955 TestContext* context = TestContext::cast(ast_context());
4961 HTest* test = is_logical_and 4956 // Translate left subexpression.
4962 ? new(zone()) HTest(Top(), eval_right, empty_block) 4957 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4963 : new(zone()) HTest(Top(), empty_block, eval_right); 4958 if (is_logical_and) {
4964 current_block()->Finish(test); 4959 CHECK_BAILOUT(VisitForControl(expr->left(),
4965 4960 eval_right,
4966 set_current_block(eval_right); 4961 context->if_false()));
4967 Drop(1); // Value of the left subexpression.
4968 CHECK_BAILOUT(VisitForValue(expr->right()));
4969
4970 HBasicBlock* join_block =
4971 CreateJoin(empty_block, current_block(), expr->id());
4972 set_current_block(join_block);
4973 ast_context()->ReturnValue(Pop());
4974
4975 } else { 4962 } else {
4976 ASSERT(ast_context()->IsEffect()); 4963 CHECK_BAILOUT(VisitForControl(expr->left(),
4977 // In an effect context, we don't need the value of the left 4964 context->if_true(),
4978 // subexpression, only its control flow and side effects. We need an 4965 eval_right));
4979 // extra block to maintain edge-split form.
4980 HBasicBlock* empty_block = graph()->CreateBasicBlock();
4981 HBasicBlock* right_block = graph()->CreateBasicBlock();
4982 if (is_logical_and) {
4983 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
4984 } else {
4985 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
4986 }
4987
4988 // TODO(kmillikin): Find a way to fix this. It's ugly that there are
4989 // actually two empty blocks (one here and one inserted by
4990 // TestContext::BuildBranch, and that they both have an HSimulate
4991 // though the second one is not a merge node, and that we really have
4992 // no good AST ID to put on that first HSimulate.
4993 if (empty_block->HasPredecessor()) {
4994 empty_block->SetJoinId(expr->id());
4995 } else {
4996 empty_block = NULL;
4997 }
4998
4999 if (right_block->HasPredecessor()) {
5000 right_block->SetJoinId(expr->RightId());
5001 set_current_block(right_block);
5002 CHECK_BAILOUT(VisitForEffect(expr->right()));
5003 right_block = current_block();
5004 } else {
5005 right_block = NULL;
5006 }
5007
5008 HBasicBlock* join_block =
5009 CreateJoin(empty_block, right_block, expr->id());
5010 set_current_block(join_block);
5011 // We did not materialize any value in the predecessor environments,
5012 // so there is no need to handle it here.
5013 } 4966 }
5014 4967
4968 // Translate right subexpression by visiting it in the same AST
4969 // context as the entire expression.
4970 if (eval_right->HasPredecessor()) {
4971 eval_right->SetJoinId(expr->RightId());
4972 set_current_block(eval_right);
4973 Visit(expr->right());
4974 }
4975
4976 } else if (ast_context()->IsValue()) {
4977 CHECK_ALIVE(VisitForValue(expr->left()));
4978 ASSERT(current_block() != NULL);
4979
4980 // We need an extra block to maintain edge-split form.
4981 HBasicBlock* empty_block = graph()->CreateBasicBlock();
4982 HBasicBlock* eval_right = graph()->CreateBasicBlock();
4983 HTest* test = is_logical_and
4984 ? new(zone()) HTest(Top(), eval_right, empty_block)
4985 : new(zone()) HTest(Top(), empty_block, eval_right);
4986 current_block()->Finish(test);
4987
4988 set_current_block(eval_right);
4989 Drop(1); // Value of the left subexpression.
4990 CHECK_BAILOUT(VisitForValue(expr->right()));
4991
4992 HBasicBlock* join_block =
4993 CreateJoin(empty_block, current_block(), expr->id());
4994 set_current_block(join_block);
4995 ast_context()->ReturnValue(Pop());
4996
5015 } else { 4997 } else {
5016 CHECK_ALIVE(VisitForValue(expr->left())); 4998 ASSERT(ast_context()->IsEffect());
5017 CHECK_ALIVE(VisitForValue(expr->right())); 4999 // In an effect context, we don't need the value of the left subexpression,
5000 // only its control flow and side effects. We need an extra block to
5001 // maintain edge-split form.
5002 HBasicBlock* empty_block = graph()->CreateBasicBlock();
5003 HBasicBlock* right_block = graph()->CreateBasicBlock();
5004 if (is_logical_and) {
5005 CHECK_BAILOUT(VisitForControl(expr->left(), right_block, empty_block));
5006 } else {
5007 CHECK_BAILOUT(VisitForControl(expr->left(), empty_block, right_block));
5008 }
5018 5009
5019 HValue* right = Pop(); 5010 // TODO(kmillikin): Find a way to fix this. It's ugly that there are
5020 HValue* left = Pop(); 5011 // actually two empty blocks (one here and one inserted by
5021 HInstruction* instr = BuildBinaryOperation(expr, left, right); 5012 // TestContext::BuildBranch, and that they both have an HSimulate though the
5022 instr->set_position(expr->position()); 5013 // second one is not a merge node, and that we really have no good AST ID to
5023 ast_context()->ReturnInstruction(instr, expr->id()); 5014 // put on that first HSimulate.
5015
5016 if (empty_block->HasPredecessor()) {
5017 empty_block->SetJoinId(expr->id());
5018 } else {
5019 empty_block = NULL;
5020 }
5021
5022 if (right_block->HasPredecessor()) {
5023 right_block->SetJoinId(expr->RightId());
5024 set_current_block(right_block);
5025 CHECK_BAILOUT(VisitForEffect(expr->right()));
5026 right_block = current_block();
5027 } else {
5028 right_block = NULL;
5029 }
5030
5031 HBasicBlock* join_block =
5032 CreateJoin(empty_block, right_block, expr->id());
5033 set_current_block(join_block);
5034 // We did not materialize any value in the predecessor environments,
5035 // so there is no need to handle it here.
5024 } 5036 }
5025 } 5037 }
5026 5038
5027 5039
5040 void HGraphBuilder::VisitCommon(BinaryOperation* expr) {
5041 CHECK_ALIVE(VisitForValue(expr->left()));
5042 CHECK_ALIVE(VisitForValue(expr->right()));
5043 HValue* right = Pop();
5044 HValue* left = Pop();
5045 HInstruction* instr = BuildBinaryOperation(expr, left, right);
5046 instr->set_position(expr->position());
5047 ast_context()->ReturnInstruction(instr, expr->id());
5048 }
5049
5050
5028 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) { 5051 void HGraphBuilder::AssumeRepresentation(HValue* value, Representation r) {
5029 if (value->CheckFlag(HValue::kFlexibleRepresentation)) { 5052 if (value->CheckFlag(HValue::kFlexibleRepresentation)) {
5030 if (FLAG_trace_representation) { 5053 if (FLAG_trace_representation) {
5031 PrintF("Assume representation for %s to be %s (%d)\n", 5054 PrintF("Assume representation for %s to be %s (%d)\n",
5032 value->Mnemonic(), 5055 value->Mnemonic(),
5033 r.Mnemonic(), 5056 r.Mnemonic(),
5034 graph_->GetMaximumValueID()); 5057 graph_->GetMaximumValueID());
5035 } 5058 }
5036 value->ChangeRepresentation(r); 5059 value->ChangeRepresentation(r);
5037 // The representation of the value is dictated by type feedback and 5060 // The representation of the value is dictated by type feedback and
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
6097 } 6120 }
6098 } 6121 }
6099 6122
6100 #ifdef DEBUG 6123 #ifdef DEBUG
6101 if (graph_ != NULL) graph_->Verify(); 6124 if (graph_ != NULL) graph_->Verify();
6102 if (allocator_ != NULL) allocator_->Verify(); 6125 if (allocator_ != NULL) allocator_->Verify();
6103 #endif 6126 #endif
6104 } 6127 }
6105 6128
6106 } } // namespace v8::internal 6129 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698