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 |