| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 9013 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9024 return ast_context()->ReturnInstruction(instr, expr->id()); | 9024 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9025 } | 9025 } |
| 9026 | 9026 |
| 9027 | 9027 |
| 9028 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { | 9028 void HOptimizedGraphBuilder::VisitSub(UnaryOperation* expr) { |
| 9029 CHECK_ALIVE(VisitForValue(expr->expression())); | 9029 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9030 HValue* value = Pop(); | 9030 HValue* value = Pop(); |
| 9031 HValue* context = environment()->LookupContext(); | 9031 HValue* context = environment()->LookupContext(); |
| 9032 HInstruction* instr = | 9032 HInstruction* instr = |
| 9033 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); | 9033 HMul::New(zone(), context, value, graph()->GetConstantMinus1()); |
| 9034 Handle<Type> type = expr->type(); | 9034 Handle<Type> operand_type = expr->expression()->lower_type(); |
| 9035 Representation rep = ToRepresentation(type); | 9035 Representation rep = ToRepresentation(operand_type); |
| 9036 if (type->Is(Type::None())) { | 9036 if (operand_type->Is(Type::None())) { |
| 9037 AddSoftDeoptimize(); | 9037 AddSoftDeoptimize(); |
| 9038 type = handle(Type::Any(), isolate()); | |
| 9039 } | 9038 } |
| 9040 if (instr->IsBinaryOperation()) { | 9039 if (instr->IsBinaryOperation()) { |
| 9041 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); | 9040 HBinaryOperation::cast(instr)->set_observed_input_representation(1, rep); |
| 9042 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); | 9041 HBinaryOperation::cast(instr)->set_observed_input_representation(2, rep); |
| 9043 } | 9042 } |
| 9044 return ast_context()->ReturnInstruction(instr, expr->id()); | 9043 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9045 } | 9044 } |
| 9046 | 9045 |
| 9047 | 9046 |
| 9048 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { | 9047 void HOptimizedGraphBuilder::VisitBitNot(UnaryOperation* expr) { |
| 9049 CHECK_ALIVE(VisitForValue(expr->expression())); | 9048 CHECK_ALIVE(VisitForValue(expr->expression())); |
| 9050 HValue* value = Pop(); | 9049 HValue* value = Pop(); |
| 9051 Handle<Type> info = expr->type(); | 9050 Handle<Type> operand_type = expr->expression()->lower_type(); |
| 9052 if (info->Is(Type::None())) { | 9051 if (operand_type->Is(Type::None())) { |
| 9053 AddSoftDeoptimize(); | 9052 AddSoftDeoptimize(); |
| 9054 } | 9053 } |
| 9055 HInstruction* instr = new(zone()) HBitNot(value); | 9054 HInstruction* instr = new(zone()) HBitNot(value); |
| 9056 return ast_context()->ReturnInstruction(instr, expr->id()); | 9055 return ast_context()->ReturnInstruction(instr, expr->id()); |
| 9057 } | 9056 } |
| 9058 | 9057 |
| 9059 | 9058 |
| 9060 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { | 9059 void HOptimizedGraphBuilder::VisitNot(UnaryOperation* expr) { |
| 9061 if (ast_context()->IsTest()) { | 9060 if (ast_context()->IsTest()) { |
| 9062 TestContext* context = TestContext::cast(ast_context()); | 9061 TestContext* context = TestContext::cast(ast_context()); |
| (...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9404 } | 9403 } |
| 9405 return true; | 9404 return true; |
| 9406 } | 9405 } |
| 9407 | 9406 |
| 9408 | 9407 |
| 9409 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( | 9408 HInstruction* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 9410 BinaryOperation* expr, | 9409 BinaryOperation* expr, |
| 9411 HValue* left, | 9410 HValue* left, |
| 9412 HValue* right) { | 9411 HValue* right) { |
| 9413 HValue* context = environment()->LookupContext(); | 9412 HValue* context = environment()->LookupContext(); |
| 9414 Handle<Type> left_type = expr->left_type(); | 9413 Handle<Type> left_type = expr->left()->lower_type(); |
| 9415 Handle<Type> right_type = expr->right_type(); | 9414 Handle<Type> right_type = expr->right()->lower_type(); |
| 9416 Handle<Type> result_type = expr->result_type(); | 9415 Handle<Type> result_type = expr->result_type(); |
| 9417 bool has_fixed_right_arg = expr->has_fixed_right_arg(); | 9416 Maybe<int> fixed_right_arg = expr->fixed_right_arg(); |
| 9418 int fixed_right_arg_value = expr->fixed_right_arg_value(); | |
| 9419 Representation left_rep = ToRepresentation(left_type); | 9417 Representation left_rep = ToRepresentation(left_type); |
| 9420 Representation right_rep = ToRepresentation(right_type); | 9418 Representation right_rep = ToRepresentation(right_type); |
| 9421 Representation result_rep = ToRepresentation(result_type); | 9419 Representation result_rep = ToRepresentation(result_type); |
| 9422 if (left_type->Is(Type::None())) { | 9420 if (left_type->Is(Type::None())) { |
| 9423 AddSoftDeoptimize(); | 9421 AddSoftDeoptimize(); |
| 9422 // TODO(rossberg): we should be able to get rid of non-continuous defaults. |
| 9424 left_type = handle(Type::Any(), isolate()); | 9423 left_type = handle(Type::Any(), isolate()); |
| 9425 } | 9424 } |
| 9426 if (right_type->Is(Type::None())) { | 9425 if (right_type->Is(Type::None())) { |
| 9427 AddSoftDeoptimize(); | 9426 AddSoftDeoptimize(); |
| 9428 right_type = handle(Type::Any(), isolate()); | 9427 right_type = handle(Type::Any(), isolate()); |
| 9429 } | 9428 } |
| 9430 HInstruction* instr = NULL; | 9429 HInstruction* instr = NULL; |
| 9431 switch (expr->op()) { | 9430 switch (expr->op()) { |
| 9432 case Token::ADD: | 9431 case Token::ADD: |
| 9433 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { | 9432 if (left_type->Is(Type::String()) && right_type->Is(Type::String())) { |
| 9434 BuildCheckNonSmi(left); | 9433 BuildCheckNonSmi(left); |
| 9435 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); | 9434 AddInstruction(HCheckInstanceType::NewIsString(left, zone())); |
| 9436 BuildCheckNonSmi(right); | 9435 BuildCheckNonSmi(right); |
| 9437 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); | 9436 AddInstruction(HCheckInstanceType::NewIsString(right, zone())); |
| 9438 instr = HStringAdd::New(zone(), context, left, right); | 9437 instr = HStringAdd::New(zone(), context, left, right); |
| 9439 } else { | 9438 } else { |
| 9440 instr = HAdd::New(zone(), context, left, right); | 9439 instr = HAdd::New(zone(), context, left, right); |
| 9441 } | 9440 } |
| 9442 break; | 9441 break; |
| 9443 case Token::SUB: | 9442 case Token::SUB: |
| 9444 instr = HSub::New(zone(), context, left, right); | 9443 instr = HSub::New(zone(), context, left, right); |
| 9445 break; | 9444 break; |
| 9446 case Token::MUL: | 9445 case Token::MUL: |
| 9447 instr = HMul::New(zone(), context, left, right); | 9446 instr = HMul::New(zone(), context, left, right); |
| 9448 break; | 9447 break; |
| 9449 case Token::MOD: | 9448 case Token::MOD: |
| 9450 instr = HMod::New(zone(), | 9449 instr = HMod::New(zone(), context, left, right, fixed_right_arg); |
| 9451 context, | |
| 9452 left, | |
| 9453 right, | |
| 9454 has_fixed_right_arg, | |
| 9455 fixed_right_arg_value); | |
| 9456 break; | 9450 break; |
| 9457 case Token::DIV: | 9451 case Token::DIV: |
| 9458 instr = HDiv::New(zone(), context, left, right); | 9452 instr = HDiv::New(zone(), context, left, right); |
| 9459 break; | 9453 break; |
| 9460 case Token::BIT_XOR: | 9454 case Token::BIT_XOR: |
| 9461 case Token::BIT_AND: | 9455 case Token::BIT_AND: |
| 9462 instr = HBitwise::New(zone(), expr->op(), context, left, right); | 9456 instr = HBitwise::New(zone(), expr->op(), context, left, right); |
| 9463 break; | 9457 break; |
| 9464 case Token::BIT_OR: { | 9458 case Token::BIT_OR: { |
| 9465 HValue* operand, *shift_amount; | 9459 HValue* operand, *shift_amount; |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9752 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 9746 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 9753 HValue* value = Pop(); | 9747 HValue* value = Pop(); |
| 9754 Literal* literal = expr->right()->AsLiteral(); | 9748 Literal* literal = expr->right()->AsLiteral(); |
| 9755 Handle<String> rhs = Handle<String>::cast(literal->handle()); | 9749 Handle<String> rhs = Handle<String>::cast(literal->handle()); |
| 9756 HClassOfTestAndBranch* instr = | 9750 HClassOfTestAndBranch* instr = |
| 9757 new(zone()) HClassOfTestAndBranch(value, rhs); | 9751 new(zone()) HClassOfTestAndBranch(value, rhs); |
| 9758 instr->set_position(expr->position()); | 9752 instr->set_position(expr->position()); |
| 9759 return ast_context()->ReturnControl(instr, expr->id()); | 9753 return ast_context()->ReturnControl(instr, expr->id()); |
| 9760 } | 9754 } |
| 9761 | 9755 |
| 9762 Handle<Type> left_type = expr->left_type(); | 9756 Handle<Type> left_type = expr->left()->lower_type(); |
| 9763 Handle<Type> right_type = expr->right_type(); | 9757 Handle<Type> right_type = expr->right()->lower_type(); |
| 9764 Handle<Type> overall_type = expr->overall_type(); | 9758 Handle<Type> combined_type = expr->combined_type(); |
| 9765 Representation combined_rep = ToRepresentation(overall_type); | 9759 Representation combined_rep = ToRepresentation(combined_type); |
| 9766 Representation left_rep = ToRepresentation(left_type); | 9760 Representation left_rep = ToRepresentation(left_type); |
| 9767 Representation right_rep = ToRepresentation(right_type); | 9761 Representation right_rep = ToRepresentation(right_type); |
| 9768 // Check if this expression was ever executed according to type feedback. | 9762 // Check if this expression was ever executed according to type feedback. |
| 9769 // Note that for the special typeof/null/undefined cases we get unknown here. | 9763 // Note that for the special typeof/null/undefined cases we get unknown here. |
| 9770 if (overall_type->Is(Type::None())) { | 9764 if (combined_type->Is(Type::None())) { |
| 9771 AddSoftDeoptimize(); | 9765 AddSoftDeoptimize(); |
| 9772 overall_type = left_type = right_type = handle(Type::Any(), isolate()); | 9766 combined_type = left_type = right_type = handle(Type::Any(), isolate()); |
| 9773 } | 9767 } |
| 9774 | 9768 |
| 9775 CHECK_ALIVE(VisitForValue(expr->left())); | 9769 CHECK_ALIVE(VisitForValue(expr->left())); |
| 9776 CHECK_ALIVE(VisitForValue(expr->right())); | 9770 CHECK_ALIVE(VisitForValue(expr->right())); |
| 9777 | 9771 |
| 9778 HValue* context = environment()->LookupContext(); | 9772 HValue* context = environment()->LookupContext(); |
| 9779 HValue* right = Pop(); | 9773 HValue* right = Pop(); |
| 9780 HValue* left = Pop(); | 9774 HValue* left = Pop(); |
| 9781 Token::Value op = expr->op(); | 9775 Token::Value op = expr->op(); |
| 9782 | 9776 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9834 AddInstruction(new(zone()) HCheckFunction(right, target)); | 9828 AddInstruction(new(zone()) HCheckFunction(right, target)); |
| 9835 HInstanceOfKnownGlobal* result = | 9829 HInstanceOfKnownGlobal* result = |
| 9836 new(zone()) HInstanceOfKnownGlobal(context, left, target); | 9830 new(zone()) HInstanceOfKnownGlobal(context, left, target); |
| 9837 result->set_position(expr->position()); | 9831 result->set_position(expr->position()); |
| 9838 return ast_context()->ReturnInstruction(result, expr->id()); | 9832 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9839 } | 9833 } |
| 9840 } else if (op == Token::IN) { | 9834 } else if (op == Token::IN) { |
| 9841 HIn* result = new(zone()) HIn(context, left, right); | 9835 HIn* result = new(zone()) HIn(context, left, right); |
| 9842 result->set_position(expr->position()); | 9836 result->set_position(expr->position()); |
| 9843 return ast_context()->ReturnInstruction(result, expr->id()); | 9837 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9844 } else if (overall_type->Is(Type::Receiver())) { | 9838 } else if (combined_type->Is(Type::Receiver())) { |
| 9845 switch (op) { | 9839 switch (op) { |
| 9846 case Token::EQ: | 9840 case Token::EQ: |
| 9847 case Token::EQ_STRICT: { | 9841 case Token::EQ_STRICT: { |
| 9848 // Can we get away with map check and not instance type check? | 9842 // Can we get away with map check and not instance type check? |
| 9849 if (overall_type->IsClass()) { | 9843 if (combined_type->IsClass()) { |
| 9850 Handle<Map> map = overall_type->AsClass(); | 9844 Handle<Map> map = combined_type->AsClass(); |
| 9851 AddCheckMapsWithTransitions(left, map); | 9845 AddCheckMapsWithTransitions(left, map); |
| 9852 AddCheckMapsWithTransitions(right, map); | 9846 AddCheckMapsWithTransitions(right, map); |
| 9853 HCompareObjectEqAndBranch* result = | 9847 HCompareObjectEqAndBranch* result = |
| 9854 new(zone()) HCompareObjectEqAndBranch(left, right); | 9848 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9855 result->set_position(expr->position()); | 9849 result->set_position(expr->position()); |
| 9856 return ast_context()->ReturnControl(result, expr->id()); | 9850 return ast_context()->ReturnControl(result, expr->id()); |
| 9857 } else { | 9851 } else { |
| 9858 BuildCheckNonSmi(left); | 9852 BuildCheckNonSmi(left); |
| 9859 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); | 9853 AddInstruction(HCheckInstanceType::NewIsSpecObject(left, zone())); |
| 9860 BuildCheckNonSmi(right); | 9854 BuildCheckNonSmi(right); |
| 9861 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); | 9855 AddInstruction(HCheckInstanceType::NewIsSpecObject(right, zone())); |
| 9862 HCompareObjectEqAndBranch* result = | 9856 HCompareObjectEqAndBranch* result = |
| 9863 new(zone()) HCompareObjectEqAndBranch(left, right); | 9857 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9864 result->set_position(expr->position()); | 9858 result->set_position(expr->position()); |
| 9865 return ast_context()->ReturnControl(result, expr->id()); | 9859 return ast_context()->ReturnControl(result, expr->id()); |
| 9866 } | 9860 } |
| 9867 } | 9861 } |
| 9868 default: | 9862 default: |
| 9869 return Bailout("Unsupported non-primitive compare"); | 9863 return Bailout("Unsupported non-primitive compare"); |
| 9870 } | 9864 } |
| 9871 } else if (overall_type->Is(Type::InternalizedString()) && | 9865 } else if (combined_type->Is(Type::InternalizedString()) && |
| 9872 Token::IsEqualityOp(op)) { | 9866 Token::IsEqualityOp(op)) { |
| 9873 BuildCheckNonSmi(left); | 9867 BuildCheckNonSmi(left); |
| 9874 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); | 9868 AddInstruction(HCheckInstanceType::NewIsInternalizedString(left, zone())); |
| 9875 BuildCheckNonSmi(right); | 9869 BuildCheckNonSmi(right); |
| 9876 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); | 9870 AddInstruction(HCheckInstanceType::NewIsInternalizedString(right, zone())); |
| 9877 HCompareObjectEqAndBranch* result = | 9871 HCompareObjectEqAndBranch* result = |
| 9878 new(zone()) HCompareObjectEqAndBranch(left, right); | 9872 new(zone()) HCompareObjectEqAndBranch(left, right); |
| 9879 result->set_position(expr->position()); | 9873 result->set_position(expr->position()); |
| 9880 return ast_context()->ReturnControl(result, expr->id()); | 9874 return ast_context()->ReturnControl(result, expr->id()); |
| 9881 } else { | 9875 } else { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 9912 if (expr->op() == Token::EQ_STRICT) { | 9906 if (expr->op() == Token::EQ_STRICT) { |
| 9913 IfBuilder if_nil(this); | 9907 IfBuilder if_nil(this); |
| 9914 if_nil.If<HCompareObjectEqAndBranch>( | 9908 if_nil.If<HCompareObjectEqAndBranch>( |
| 9915 value, (nil == kNullValue) ? graph()->GetConstantNull() | 9909 value, (nil == kNullValue) ? graph()->GetConstantNull() |
| 9916 : graph()->GetConstantUndefined()); | 9910 : graph()->GetConstantUndefined()); |
| 9917 if_nil.Then(); | 9911 if_nil.Then(); |
| 9918 if_nil.Else(); | 9912 if_nil.Else(); |
| 9919 if_nil.CaptureContinuation(&continuation); | 9913 if_nil.CaptureContinuation(&continuation); |
| 9920 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9914 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9921 } | 9915 } |
| 9922 Handle<Type> type = expr->compare_nil_type()->Is(Type::None()) | 9916 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
| 9923 ? handle(Type::Any(), isolate_) : expr->compare_nil_type(); | 9917 ? handle(Type::Any(), isolate_) : expr->combined_type(); |
| 9924 BuildCompareNil(value, type, expr->position(), &continuation); | 9918 BuildCompareNil(value, type, expr->position(), &continuation); |
| 9925 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9919 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9926 } | 9920 } |
| 9927 | 9921 |
| 9928 | 9922 |
| 9929 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9923 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 9930 // If we share optimized code between different closures, the | 9924 // If we share optimized code between different closures, the |
| 9931 // this-function is not a constant, except inside an inlined body. | 9925 // this-function is not a constant, except inside an inlined body. |
| 9932 if (function_state()->outer() != NULL) { | 9926 if (function_state()->outer() != NULL) { |
| 9933 return new(zone()) HConstant( | 9927 return new(zone()) HConstant( |
| (...skipping 1650 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11584 } | 11578 } |
| 11585 } | 11579 } |
| 11586 | 11580 |
| 11587 #ifdef DEBUG | 11581 #ifdef DEBUG |
| 11588 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 11582 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 11589 if (allocator_ != NULL) allocator_->Verify(); | 11583 if (allocator_ != NULL) allocator_->Verify(); |
| 11590 #endif | 11584 #endif |
| 11591 } | 11585 } |
| 11592 | 11586 |
| 11593 } } // namespace v8::internal | 11587 } } // namespace v8::internal |
| OLD | NEW |