| 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 8674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8685 } | 8685 } |
| 8686 return number; | 8686 return number; |
| 8687 } | 8687 } |
| 8688 | 8688 |
| 8689 | 8689 |
| 8690 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { | 8690 HValue* HGraphBuilder::TruncateToNumber(HValue* value, Handle<Type>* expected) { |
| 8691 if (value->IsConstant()) { | 8691 if (value->IsConstant()) { |
| 8692 HConstant* constant = HConstant::cast(value); | 8692 HConstant* constant = HConstant::cast(value); |
| 8693 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); | 8693 Maybe<HConstant*> number = constant->CopyToTruncatedNumber(zone()); |
| 8694 if (number.has_value) { | 8694 if (number.has_value) { |
| 8695 *expected = handle(Type::Number(), isolate()); | 8695 *expected = Type::Number(isolate()); |
| 8696 return AddInstruction(number.value); | 8696 return AddInstruction(number.value); |
| 8697 } | 8697 } |
| 8698 } | 8698 } |
| 8699 | 8699 |
| 8700 // We put temporary values on the stack, which don't correspond to anything | 8700 // We put temporary values on the stack, which don't correspond to anything |
| 8701 // in baseline code. Since nothing is observable we avoid recording those | 8701 // in baseline code. Since nothing is observable we avoid recording those |
| 8702 // pushes with a NoObservableSideEffectsScope. | 8702 // pushes with a NoObservableSideEffectsScope. |
| 8703 NoObservableSideEffectsScope no_effects(this); | 8703 NoObservableSideEffectsScope no_effects(this); |
| 8704 | 8704 |
| 8705 Handle<Type> expected_type = *expected; | 8705 Handle<Type> expected_type = *expected; |
| 8706 | 8706 |
| 8707 // Separate the number type from the rest. | 8707 // Separate the number type from the rest. |
| 8708 Handle<Type> expected_obj = handle(Type::Intersect( | 8708 Handle<Type> expected_obj = Type::Intersect( |
| 8709 expected_type, handle(Type::NonNumber(), isolate())), isolate()); | 8709 expected_type, Type::NonNumber(isolate()), isolate()); |
| 8710 Handle<Type> expected_number = handle(Type::Intersect( | 8710 Handle<Type> expected_number = Type::Intersect( |
| 8711 expected_type, handle(Type::Number(), isolate())), isolate()); | 8711 expected_type, Type::Number(isolate()), isolate()); |
| 8712 | 8712 |
| 8713 // We expect to get a number. | 8713 // We expect to get a number. |
| 8714 // (We need to check first, since Type::None->Is(Type::Any()) == true. | 8714 // (We need to check first, since Type::None->Is(Type::Any()) == true. |
| 8715 if (expected_obj->Is(Type::None())) { | 8715 if (expected_obj->Is(Type::None())) { |
| 8716 ASSERT(!expected_number->Is(Type::None())); | 8716 ASSERT(!expected_number->Is(Type::None())); |
| 8717 return value; | 8717 return value; |
| 8718 } | 8718 } |
| 8719 | 8719 |
| 8720 if (expected_obj->Is(Type::Undefined())) { | 8720 if (expected_obj->Is(Type::Undefined())) { |
| 8721 // This is already done by HChange. | 8721 // This is already done by HChange. |
| 8722 *expected = handle(Type::Union( | 8722 *expected = Type::Union( |
| 8723 expected_number, handle(Type::Double(), isolate())), isolate()); | 8723 expected_number, Type::Double(isolate()), isolate()); |
| 8724 return value; | 8724 return value; |
| 8725 } | 8725 } |
| 8726 | 8726 |
| 8727 return value; | 8727 return value; |
| 8728 } | 8728 } |
| 8729 | 8729 |
| 8730 | 8730 |
| 8731 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( | 8731 HValue* HOptimizedGraphBuilder::BuildBinaryOperation( |
| 8732 BinaryOperation* expr, | 8732 BinaryOperation* expr, |
| 8733 HValue* left, | 8733 HValue* left, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8766 | 8766 |
| 8767 bool maybe_string_add = op == Token::ADD && | 8767 bool maybe_string_add = op == Token::ADD && |
| 8768 (left_type->Maybe(Type::String()) || | 8768 (left_type->Maybe(Type::String()) || |
| 8769 right_type->Maybe(Type::String())); | 8769 right_type->Maybe(Type::String())); |
| 8770 | 8770 |
| 8771 if (left_type->Is(Type::None())) { | 8771 if (left_type->Is(Type::None())) { |
| 8772 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", | 8772 Add<HDeoptimize>("Insufficient type feedback for LHS of binary operation", |
| 8773 Deoptimizer::SOFT); | 8773 Deoptimizer::SOFT); |
| 8774 // TODO(rossberg): we should be able to get rid of non-continuous | 8774 // TODO(rossberg): we should be able to get rid of non-continuous |
| 8775 // defaults. | 8775 // defaults. |
| 8776 left_type = handle(Type::Any(), isolate()); | 8776 left_type = Type::Any(isolate()); |
| 8777 } else { | 8777 } else { |
| 8778 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); | 8778 if (!maybe_string_add) left = TruncateToNumber(left, &left_type); |
| 8779 left_rep = Representation::FromType(left_type); | 8779 left_rep = Representation::FromType(left_type); |
| 8780 } | 8780 } |
| 8781 | 8781 |
| 8782 if (right_type->Is(Type::None())) { | 8782 if (right_type->Is(Type::None())) { |
| 8783 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", | 8783 Add<HDeoptimize>("Insufficient type feedback for RHS of binary operation", |
| 8784 Deoptimizer::SOFT); | 8784 Deoptimizer::SOFT); |
| 8785 right_type = handle(Type::Any(), isolate()); | 8785 right_type = Type::Any(isolate()); |
| 8786 } else { | 8786 } else { |
| 8787 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); | 8787 if (!maybe_string_add) right = TruncateToNumber(right, &right_type); |
| 8788 right_rep = Representation::FromType(right_type); | 8788 right_rep = Representation::FromType(right_type); |
| 8789 } | 8789 } |
| 8790 | 8790 |
| 8791 // Special case for string addition here. | 8791 // Special case for string addition here. |
| 8792 if (op == Token::ADD && | 8792 if (op == Token::ADD && |
| 8793 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { | 8793 (left_type->Is(Type::String()) || right_type->Is(Type::String()))) { |
| 8794 // Validate type feedback for left argument. | 8794 // Validate type feedback for left argument. |
| 8795 if (left_type->Is(Type::String())) { | 8795 if (left_type->Is(Type::String())) { |
| (...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9217 HInstruction* result = New<HInvokeFunction>(function, 2); | 9217 HInstruction* result = New<HInvokeFunction>(function, 2); |
| 9218 return ast_context()->ReturnInstruction(result, expr->id()); | 9218 return ast_context()->ReturnInstruction(result, expr->id()); |
| 9219 } | 9219 } |
| 9220 | 9220 |
| 9221 // Cases handled below depend on collected type feedback. They should | 9221 // Cases handled below depend on collected type feedback. They should |
| 9222 // soft deoptimize when there is no type feedback. | 9222 // soft deoptimize when there is no type feedback. |
| 9223 if (combined_type->Is(Type::None())) { | 9223 if (combined_type->Is(Type::None())) { |
| 9224 Add<HDeoptimize>("Insufficient type feedback for combined type " | 9224 Add<HDeoptimize>("Insufficient type feedback for combined type " |
| 9225 "of binary operation", | 9225 "of binary operation", |
| 9226 Deoptimizer::SOFT); | 9226 Deoptimizer::SOFT); |
| 9227 combined_type = left_type = right_type = handle(Type::Any(), isolate()); | 9227 combined_type = left_type = right_type = Type::Any(isolate()); |
| 9228 } | 9228 } |
| 9229 | 9229 |
| 9230 if (combined_type->Is(Type::Receiver())) { | 9230 if (combined_type->Is(Type::Receiver())) { |
| 9231 switch (op) { | 9231 switch (op) { |
| 9232 case Token::EQ: | 9232 case Token::EQ: |
| 9233 case Token::EQ_STRICT: { | 9233 case Token::EQ_STRICT: { |
| 9234 // Can we get away with map check and not instance type check? | 9234 // Can we get away with map check and not instance type check? |
| 9235 if (combined_type->IsClass()) { | 9235 if (combined_type->IsClass()) { |
| 9236 Handle<Map> map = combined_type->AsClass(); | 9236 Handle<Map> map = combined_type->AsClass(); |
| 9237 AddCheckMap(left, map); | 9237 AddCheckMap(left, map); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9307 if (expr->op() == Token::EQ_STRICT) { | 9307 if (expr->op() == Token::EQ_STRICT) { |
| 9308 HConstant* nil_constant = nil == kNullValue | 9308 HConstant* nil_constant = nil == kNullValue |
| 9309 ? graph()->GetConstantNull() | 9309 ? graph()->GetConstantNull() |
| 9310 : graph()->GetConstantUndefined(); | 9310 : graph()->GetConstantUndefined(); |
| 9311 HCompareObjectEqAndBranch* instr = | 9311 HCompareObjectEqAndBranch* instr = |
| 9312 New<HCompareObjectEqAndBranch>(value, nil_constant); | 9312 New<HCompareObjectEqAndBranch>(value, nil_constant); |
| 9313 return ast_context()->ReturnControl(instr, expr->id()); | 9313 return ast_context()->ReturnControl(instr, expr->id()); |
| 9314 } else { | 9314 } else { |
| 9315 ASSERT_EQ(Token::EQ, expr->op()); | 9315 ASSERT_EQ(Token::EQ, expr->op()); |
| 9316 Handle<Type> type = expr->combined_type()->Is(Type::None()) | 9316 Handle<Type> type = expr->combined_type()->Is(Type::None()) |
| 9317 ? handle(Type::Any(), isolate_) | 9317 ? Type::Any(isolate_) : expr->combined_type(); |
| 9318 : expr->combined_type(); | |
| 9319 HIfContinuation continuation; | 9318 HIfContinuation continuation; |
| 9320 BuildCompareNil(value, type, &continuation); | 9319 BuildCompareNil(value, type, &continuation); |
| 9321 return ast_context()->ReturnContinuation(&continuation, expr->id()); | 9320 return ast_context()->ReturnContinuation(&continuation, expr->id()); |
| 9322 } | 9321 } |
| 9323 } | 9322 } |
| 9324 | 9323 |
| 9325 | 9324 |
| 9326 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { | 9325 HInstruction* HOptimizedGraphBuilder::BuildThisFunction() { |
| 9327 // If we share optimized code between different closures, the | 9326 // If we share optimized code between different closures, the |
| 9328 // this-function is not a constant, except inside an inlined body. | 9327 // this-function is not a constant, except inside an inlined body. |
| (...skipping 749 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10078 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { | 10077 void HOptimizedGraphBuilder::GenerateGetFromCache(CallRuntime* call) { |
| 10079 return Bailout(kInlinedRuntimeFunctionGetFromCache); | 10078 return Bailout(kInlinedRuntimeFunctionGetFromCache); |
| 10080 } | 10079 } |
| 10081 | 10080 |
| 10082 | 10081 |
| 10083 // Fast support for number to string. | 10082 // Fast support for number to string. |
| 10084 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { | 10083 void HOptimizedGraphBuilder::GenerateNumberToString(CallRuntime* call) { |
| 10085 ASSERT_EQ(1, call->arguments()->length()); | 10084 ASSERT_EQ(1, call->arguments()->length()); |
| 10086 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); | 10085 CHECK_ALIVE(VisitForValue(call->arguments()->at(0))); |
| 10087 HValue* number = Pop(); | 10086 HValue* number = Pop(); |
| 10088 HValue* result = BuildNumberToString( | 10087 HValue* result = BuildNumberToString(number, Type::Number(isolate())); |
| 10089 number, handle(Type::Number(), isolate())); | |
| 10090 return ast_context()->ReturnValue(result); | 10088 return ast_context()->ReturnValue(result); |
| 10091 } | 10089 } |
| 10092 | 10090 |
| 10093 | 10091 |
| 10094 // Fast call for custom callbacks. | 10092 // Fast call for custom callbacks. |
| 10095 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { | 10093 void HOptimizedGraphBuilder::GenerateCallFunction(CallRuntime* call) { |
| 10096 // 1 ~ The function to call is not itself an argument to the call. | 10094 // 1 ~ The function to call is not itself an argument to the call. |
| 10097 int arg_count = call->arguments()->length() - 1; | 10095 int arg_count = call->arguments()->length() - 1; |
| 10098 ASSERT(arg_count >= 1); // There's always at least a receiver. | 10096 ASSERT(arg_count >= 1); // There's always at least a receiver. |
| 10099 | 10097 |
| (...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10811 if (ShouldProduceTraceOutput()) { | 10809 if (ShouldProduceTraceOutput()) { |
| 10812 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 10810 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 10813 } | 10811 } |
| 10814 | 10812 |
| 10815 #ifdef DEBUG | 10813 #ifdef DEBUG |
| 10816 graph_->Verify(false); // No full verify. | 10814 graph_->Verify(false); // No full verify. |
| 10817 #endif | 10815 #endif |
| 10818 } | 10816 } |
| 10819 | 10817 |
| 10820 } } // namespace v8::internal | 10818 } } // namespace v8::internal |
| OLD | NEW |