OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 8754 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8765 } | 8765 } |
8766 return number; | 8766 return number; |
8767 } | 8767 } |
8768 | 8768 |
8769 | 8769 |
8770 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 8770 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
8771 if (value->IsConstant()) { | 8771 if (value->IsConstant()) { |
8772 HConstant* constant = HConstant::cast(value); | 8772 HConstant* constant = HConstant::cast(value); |
8773 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 8773 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
8774 if (number.has_value) { | 8774 if (number.has_value) { |
8775 *expected = handle(Type::Number(), isolate()); | 8775 *expected = Type::Number(isolate()); |
8776 return AddInstruction(number.value); | 8776 return AddInstruction(number.value); |
8777 } | 8777 } |
8778 } | 8778 } |
8779 | 8779 |
8780 // We put temporary values on the stack, which don't correspond to anything | 8780 // We put temporary values on the stack, which don't correspond to anything |
8781 // in baseline code. Since nothing is observable we avoid recording those | 8781 // in baseline code. Since nothing is observable we avoid recording those |
8782 // pushes with a NoObservableSideEffectsScope. | 8782 // pushes with a NoObservableSideEffectsScope. |
8783 NoObservableSideEffectsScope no_effects(this); | 8783 NoObservableSideEffectsScope no_effects(this); |
8784 | 8784 |
8785 Handle<Type> expected_type = *expected; | 8785 Handle<Type> expected_type = *expected; |
8786 | 8786 |
8787 // Separate the number type from the rest. | 8787 // Separate the number type from the rest. |
8788 Handle<Type> expected_obj = handle(Type::Intersect( | 8788 Handle<Type> expected_obj = Type::Intersect( |
8789 expected_type, handle(Type::NonNumber(), isolate())), isolate()); | 8789 expected_type, Type::NonNumber(isolate()), isolate()); |
8790 Handle<Type> expected_number = handle(Type::Intersect( | 8790 Handle<Type> expected_number = Type::Intersect( |
8791 expected_type, handle(Type::Number(), isolate())), isolate()); | 8791 expected_type, Type::Number(isolate()), isolate()); |
8792 | 8792 |
8793 // We expect to get a number. | 8793 // We expect to get a number. |
8794 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 8794 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
8795 if (expected_obj->Is(Type::None())) { | 8795 if (expected_obj->Is(Type::None())) { |
8796 ASSERT(!expected_number->Is(Type::None())); | 8796 ASSERT(!expected_number->Is(Type::None())); |
8797 return value; | 8797 return value; |
8798 } | 8798 } |
8799 | 8799 |
8800 if (expected_obj->Is(Type::Undefined())) { | 8800 if (expected_obj->Is(Type::Undefined())) { |
8801 // This is already done by HChange. | 8801 // This is already done by HChange. |
8802 *expected = handle(Type::Union( | 8802 *expected = Type::Union( |
8803 expected_number, handle(Type::Double(), isolate())), isolate()); | 8803 expected_number, Type::Double(isolate()), isolate()); |
8804 return value; | 8804 return value; |
8805 } | 8805 } |
8806 | 8806 |
8807 return value; | 8807 return value; |
8808 } | 8808 } |
8809 | 8809 |
8810 | 8810 |
8811 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 8811 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
8812 BinaryOperation* expr, | 8812 BinaryOperation* expr, |
8813 HValue* left, | 8813 HValue* left, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8855 | 8855 |
8856 bool maybe_string_add = op == Token::ADD && | 8856 bool maybe_string_add = op == Token::ADD && |
8857 (left_type->Maybe(Type::String()) || | 8857 (left_type->Maybe(Type::String()) || |
8858 right_type->Maybe(Type::String())); | 8858 right_type->Maybe(Type::String())); |
8859 | 8859 |
8860 if (left_type->Is(Type::None())) { | 8860 if (left_type->Is(Type::None())) { |
8861 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8861 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
8862 Deoptimizer::SOFT); | 8862 Deoptimizer::SOFT); |
8863 // TODO(rossberg): we should be able to get rid of non-continuous | 8863 // TODO(rossberg): we should be able to get rid of non-continuous |
8864 // defaults. | 8864 // defaults. |
8865 left_type = handle(Type::Any(), isolate()); | 8865 left_type = Type::Any(isolate()); |
8866 } else { | 8866 } else { |
8867 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 8867 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
8868 left_rep = Representation::FromType(left_type); | 8868 left_rep = Representation::FromType(left_type); |
8869 } | 8869 } |
8870 | 8870 |
8871 if (right_type->Is(Type::None())) { | 8871 if (right_type->Is(Type::None())) { |
8872 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 8872 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
8873 Deoptimizer::SOFT); | 8873 Deoptimizer::SOFT); |
8874 right_type = handle(Type::Any(), isolate()); | 8874 right_type = Type::Any(isolate()); |
8875 } else { | 8875 } else { |
8876 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 8876 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
8877 right_rep = Representation::FromType(right_type); | 8877 right_rep = Representation::FromType(right_type); |
8878 } | 8878 } |
8879 | 8879 |
8880 // Special case for string addition here. | 8880 // Special case for string addition here. |
8881 if (op == Token::ADD && | 8881 if (op == Token::ADD && |
8882 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 8882 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
8883 // Validate type feedback for left argument. | 8883 // Validate type feedback for left argument. |
8884 if (left_type->Is(Type::String())) { | 8884 if (left_type->Is(Type::String())) { |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9362 Handle<Type> combined_type, | 9362 Handle<Type> combined_type, |
9363 int left_position, | 9363 int left_position, |
9364 int right_position, | 9364 int right_position, |
9365 BailoutId bailout_id) { | 9365 BailoutId bailout_id) { |
9366 // Cases handled below depend on collected type feedback. They should | 9366 // Cases handled below depend on collected type feedback. They should |
9367 // soft deoptimize when there is no type feedback. | 9367 // soft deoptimize when there is no type feedback. |
9368 if (combined_type->Is(Type::None())) { | 9368 if (combined_type->Is(Type::None())) { |
9369 Add<HDeoptimize>("Insufficient type feedback for combined type " | 9369 Add<HDeoptimize>("Insufficient type feedback for combined type " |
9370 "of binary operation", | 9370 "of binary operation", |
9371 Deoptimizer::SOFT); | 9371 Deoptimizer::SOFT); |
9372 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 9372 combined_type = left_type = right_type = Type::Any(isolate()); |
9373 } | 9373 } |
9374 | 9374 |
9375 Representation left_rep = Representation::FromType(left_type); | 9375 Representation left_rep = Representation::FromType(left_type); |
9376 Representation right_rep = Representation::FromType(right_type); | 9376 Representation right_rep = Representation::FromType(right_type); |
9377 Representation combined_rep = Representation::FromType(combined_type); | 9377 Representation combined_rep = Representation::FromType(combined_type); |
9378 | 9378 |
9379 if (combined_type->Is(Type::Receiver())) { | 9379 if (combined_type->Is(Type::Receiver())) { |
9380 if (Token::IsEqualityOp(op)) { | 9380 if (Token::IsEqualityOp(op)) { |
9381 // Can we get away with map check and not instance type check? | 9381 // Can we get away with map check and not instance type check? |
9382 HValue* operand_to_check = | 9382 HValue* operand_to_check = |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9459 if (expr->op() == Token::EQ_STRICT) { | 9459 if (expr->op() == Token::EQ_STRICT) { |
9460 HConstant* nil_constant = nil == kNullValue | 9460 HConstant* nil_constant = nil == kNullValue |
9461 ? graph()->GetConstantNull() | 9461 ? graph()->GetConstantNull() |
9462 : graph()->GetConstantUndefined(); | 9462 : graph()->GetConstantUndefined(); |
9463 HCompareObjectEqAndBranch* instr = | 9463 HCompareObjectEqAndBranch* instr = |
9464 New<HCompareObjectEqAndBranch>(value, nil_constant); | 9464 New<HCompareObjectEqAndBranch>(value, nil_constant); |
9465 return ast_context()->ReturnControl(instr, expr->id()); | 9465 return ast_context()->ReturnControl(instr, expr->id()); |
9466 } else { | 9466 } else { |
9467 ASSERT_EQ(Token::EQ, expr->op()); | 9467 ASSERT_EQ(Token::EQ, expr->op()); |
9468 Handle<Type> type = expr->combined_type()->Is(Type::None()) | 9468 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
9469 ? handle(Type::Any(), isolate_) | 9469 ? Type::Any(isolate_) : expr->combined_type(); |
9470 : expr->combined_type(); | |
9471 HIfContinuation continuation; | 9470 HIfContinuation continuation; |
9472 BuildCompareNil(value, type, &continuation); | 9471 BuildCompareNil(value, type, &continuation); |
9473 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9472 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
9474 } | 9473 } |
9475 } | 9474 } |
9476 | 9475 |
9477 | 9476 |
9478 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9477 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
9479 // If we share optimized code between different closures, the | 9478 // If we share optimized code between different closures, the |
9480 // this-function is not a constant, except inside an inlined body. | 9479 // this-function is not a constant, except inside an inlined body. |
(...skipping 752 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10233 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 10232 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
10234 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 10233 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
10235 } | 10234 } |
10236 | 10235 |
10237 | 10236 |
10238 // Fast support for number to string. | 10237 // Fast support for number to string. |
10239 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 10238 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
10240 ASSERT_EQ(1, call->arguments()->length()); | 10239 ASSERT_EQ(1, call->arguments()->length()); |
10241 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10240 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
10242 HValue* number = Pop(); | 10241 HValue* number = Pop(); |
10243 HValue* result = BuildNumberToString( | 10242 HValue* result = BuildNumberToString(number, Type::Number(isolate())); |
10244 number, handle(Type::Number(), isolate())); | |
10245 return ast_context()->ReturnValue(result); | 10243 return ast_context()->ReturnValue(result); |
10246 } | 10244 } |
10247 | 10245 |
10248 | 10246 |
10249 // Fast call for custom callbacks. | 10247 // Fast call for custom callbacks. |
10250 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 10248 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
10251 // 1 ~ The function to call is not itself an argument to the call. | 10249 // 1 ~ The function to call is not itself an argument to the call. |
10252 int arg_count = call->arguments()->length() - 1; | 10250 int arg_count = call->arguments()->length() - 1; |
10253 ASSERT(arg_count >= 1); // There's always at least a receiver. | 10251 ASSERT(arg_count >= 1); // There's always at least a receiver. |
10254 | 10252 |
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10966 if (ShouldProduceTraceOutput()) { | 10964 if (ShouldProduceTraceOutput()) { |
10967 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10965 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10968 } | 10966 } |
10969 | 10967 |
10970 #ifdef DEBUG | 10968 #ifdef DEBUG |
10971 graph_->Verify(false); // No full verify. | 10969 graph_->Verify(false); // No full verify. |
10972 #endif | 10970 #endif |
10973 } | 10971 } |
10974 | 10972 |
10975 } } // namespace v8::internal | 10973 } } // namespace v8::internal |
OLD | NEW |