OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/crankshaft/hydrogen.h" | 5 #include "src/crankshaft/hydrogen.h" |
6 | 6 |
7 #include <sstream> | 7 #include <sstream> |
8 | 8 |
9 #include "src/allocation-site-scopes.h" | 9 #include "src/allocation-site-scopes.h" |
10 #include "src/ast/ast-numbering.h" | 10 #include "src/ast/ast-numbering.h" |
(...skipping 6571 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6582 : TryInlineSetter( | 6582 : TryInlineSetter( |
6583 info->accessor(), info->map(), ast_id, return_id, value); | 6583 info->accessor(), info->map(), ast_id, return_id, value); |
6584 if (success || HasStackOverflow()) return NULL; | 6584 if (success || HasStackOverflow()) return NULL; |
6585 } | 6585 } |
6586 | 6586 |
6587 PushArgumentsFromEnvironment(argument_count); | 6587 PushArgumentsFromEnvironment(argument_count); |
6588 if (!info->accessor()->IsJSFunction()) { | 6588 if (!info->accessor()->IsJSFunction()) { |
6589 Bailout(kInliningBailedOut); | 6589 Bailout(kInliningBailedOut); |
6590 return nullptr; | 6590 return nullptr; |
6591 } | 6591 } |
6592 return BuildCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), | 6592 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), |
6593 argument_count); | 6593 argument_count); |
6594 } | 6594 } |
6595 | 6595 |
6596 DCHECK(info->IsDataConstant()); | 6596 DCHECK(info->IsDataConstant()); |
6597 if (info->IsLoad()) { | 6597 if (info->IsLoad()) { |
6598 return New<HConstant>(info->constant()); | 6598 return New<HConstant>(info->constant()); |
6599 } else { | 6599 } else { |
6600 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6600 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6601 } | 6601 } |
6602 } | 6602 } |
6603 | 6603 |
(...skipping 1377 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7981 | 7981 |
7982 | 7982 |
7983 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7983 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
7984 Handle<Map> receiver_map) { | 7984 Handle<Map> receiver_map) { |
7985 if (!holder.is_null()) { | 7985 if (!holder.is_null()) { |
7986 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7986 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
7987 BuildCheckPrototypeMaps(prototype, holder); | 7987 BuildCheckPrototypeMaps(prototype, holder); |
7988 } | 7988 } |
7989 } | 7989 } |
7990 | 7990 |
7991 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall(HValue* function, | |
7992 int argument_count) { | |
7993 return New<HCallJSFunction>(function, argument_count); | |
7994 } | |
7995 | |
7996 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( | |
7997 HValue* function, int argument_count, HValue* expected_param_count) { | |
7998 HValue* context = Add<HLoadNamedField>( | |
7999 function, nullptr, HObjectAccess::ForFunctionContextPointer()); | |
8000 HValue* new_target = graph()->GetConstantUndefined(); | |
8001 HValue* arity = Add<HConstant>(argument_count - 1); | |
8002 | |
8003 HValue* op_vals[] = {context, function, new_target, arity, | |
8004 expected_param_count}; | |
8005 | |
8006 Callable callable = CodeFactory::ArgumentAdaptor(isolate()); | |
8007 HConstant* stub = Add<HConstant>(callable.code()); | |
8008 | |
8009 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | |
8010 Vector<HValue*>(op_vals, arraysize(op_vals))); | |
8011 } | |
8012 | |
8013 HInstruction* HOptimizedGraphBuilder::NewCallFunction( | 7991 HInstruction* HOptimizedGraphBuilder::NewCallFunction( |
8014 HValue* function, int argument_count, ConvertReceiverMode convert_mode) { | 7992 HValue* function, int argument_count, ConvertReceiverMode convert_mode) { |
8015 HValue* arity = Add<HConstant>(argument_count - 1); | 7993 HValue* arity = Add<HConstant>(argument_count - 1); |
8016 | 7994 |
8017 HValue* op_vals[] = {context(), function, arity}; | 7995 HValue* op_vals[] = {context(), function, arity}; |
8018 | 7996 |
8019 Callable callable = CodeFactory::Call(isolate(), convert_mode); | 7997 Callable callable = CodeFactory::Call(isolate(), convert_mode); |
8020 HConstant* stub = Add<HConstant>(callable.code()); | 7998 HConstant* stub = Add<HConstant>(callable.code()); |
8021 | 7999 |
8022 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8000 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
(...skipping 11 matching lines...) Expand all Loading... |
8034 HValue* op_vals[] = {context(), function, index_val, vector_val}; | 8012 HValue* op_vals[] = {context(), function, index_val, vector_val}; |
8035 | 8013 |
8036 Callable callable = CodeFactory::CallICInOptimizedCode( | 8014 Callable callable = CodeFactory::CallICInOptimizedCode( |
8037 isolate(), arity, ConvertReceiverMode::kNullOrUndefined); | 8015 isolate(), arity, ConvertReceiverMode::kNullOrUndefined); |
8038 HConstant* stub = Add<HConstant>(callable.code()); | 8016 HConstant* stub = Add<HConstant>(callable.code()); |
8039 | 8017 |
8040 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8018 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
8041 Vector<HValue*>(op_vals, arraysize(op_vals))); | 8019 Vector<HValue*>(op_vals, arraysize(op_vals))); |
8042 } | 8020 } |
8043 | 8021 |
8044 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction( | 8022 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( |
8045 Handle<JSFunction> jsfun, int argument_count) { | 8023 Handle<JSFunction> function, int argument_count) { |
8046 HValue* target = Add<HConstant>(jsfun); | 8024 HValue* target = Add<HConstant>(function); |
8047 // For constant functions, we try to avoid calling the | 8025 return New<HInvokeFunction>(target, function, argument_count); |
8048 // argument adaptor and instead call the function directly | |
8049 int formal_parameter_count = | |
8050 jsfun->shared()->internal_formal_parameter_count(); | |
8051 bool dont_adapt_arguments = | |
8052 (formal_parameter_count == | |
8053 SharedFunctionInfo::kDontAdaptArgumentsSentinel); | |
8054 int arity = argument_count - 1; | |
8055 bool can_invoke_directly = | |
8056 dont_adapt_arguments || formal_parameter_count == arity; | |
8057 if (can_invoke_directly) { | |
8058 return NewPlainFunctionCall(target, argument_count); | |
8059 } else { | |
8060 HValue* param_count_value = Add<HConstant>(formal_parameter_count); | |
8061 return NewArgumentAdaptorCall(target, argument_count, param_count_value); | |
8062 } | |
8063 UNREACHABLE(); | |
8064 return NULL; | |
8065 } | 8026 } |
8066 | 8027 |
8067 | 8028 |
8068 class FunctionSorter { | 8029 class FunctionSorter { |
8069 public: | 8030 public: |
8070 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) | 8031 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) |
8071 : index_(index), ticks_(ticks), size_(size) {} | 8032 : index_(index), ticks_(ticks), size_(size) {} |
8072 | 8033 |
8073 int index() const { return index_; } | 8034 int index() const { return index_; } |
8074 int ticks() const { return ticks_; } | 8035 int ticks() const { return ticks_; } |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8203 if (HasStackOverflow()) return; | 8164 if (HasStackOverflow()) return; |
8204 } else { | 8165 } else { |
8205 // Since HWrapReceiver currently cannot actually wrap numbers and strings, | 8166 // Since HWrapReceiver currently cannot actually wrap numbers and strings, |
8206 // use the regular call builtin for method calls to wrap the receiver. | 8167 // use the regular call builtin for method calls to wrap the receiver. |
8207 // TODO(verwaest): Support creation of value wrappers directly in | 8168 // TODO(verwaest): Support creation of value wrappers directly in |
8208 // HWrapReceiver. | 8169 // HWrapReceiver. |
8209 HInstruction* call = | 8170 HInstruction* call = |
8210 needs_wrapping | 8171 needs_wrapping |
8211 ? NewCallFunction(function, argument_count, | 8172 ? NewCallFunction(function, argument_count, |
8212 ConvertReceiverMode::kNotNullOrUndefined) | 8173 ConvertReceiverMode::kNotNullOrUndefined) |
8213 : BuildCallConstantFunction(target, argument_count); | 8174 : NewCallConstantFunction(target, argument_count); |
8214 PushArgumentsFromEnvironment(argument_count); | 8175 PushArgumentsFromEnvironment(argument_count); |
8215 AddInstruction(call); | 8176 AddInstruction(call); |
8216 Drop(1); // Drop the function. | 8177 Drop(1); // Drop the function. |
8217 if (!ast_context()->IsEffect()) Push(call); | 8178 if (!ast_context()->IsEffect()) Push(call); |
8218 } | 8179 } |
8219 | 8180 |
8220 if (current_block() != NULL) Goto(join); | 8181 if (current_block() != NULL) Goto(join); |
8221 set_current_block(if_false); | 8182 set_current_block(if_false); |
8222 } | 8183 } |
8223 | 8184 |
(...skipping 798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9022 // in a map change. | 8983 // in a map change. |
9023 BuildCheckPrototypeMaps( | 8984 BuildCheckPrototypeMaps( |
9024 handle(JSObject::cast(receiver_map->prototype()), isolate()), | 8985 handle(JSObject::cast(receiver_map->prototype()), isolate()), |
9025 Handle<JSObject>::null()); | 8986 Handle<JSObject>::null()); |
9026 | 8987 |
9027 // Threshold for fast inlined Array.shift(). | 8988 // Threshold for fast inlined Array.shift(). |
9028 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); | 8989 HConstant* inline_threshold = Add<HConstant>(static_cast<int32_t>(16)); |
9029 | 8990 |
9030 Drop(args_count_no_receiver); | 8991 Drop(args_count_no_receiver); |
9031 HValue* receiver = Pop(); | 8992 HValue* receiver = Pop(); |
9032 HValue* function = Pop(); | 8993 Drop(1); // Function. |
9033 HValue* result; | 8994 HValue* result; |
9034 | 8995 |
9035 { | 8996 { |
9036 NoObservableSideEffectsScope scope(this); | 8997 NoObservableSideEffectsScope scope(this); |
9037 | 8998 |
9038 HValue* length = Add<HLoadNamedField>( | 8999 HValue* length = Add<HLoadNamedField>( |
9039 receiver, nullptr, HObjectAccess::ForArrayLength(kind)); | 9000 receiver, nullptr, HObjectAccess::ForArrayLength(kind)); |
9040 | 9001 |
9041 IfBuilder if_lengthiszero(this); | 9002 IfBuilder if_lengthiszero(this); |
9042 HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>( | 9003 HValue* lengthiszero = if_lengthiszero.If<HCompareNumericAndBranch>( |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9098 INITIALIZING_STORE); | 9059 INITIALIZING_STORE); |
9099 | 9060 |
9100 // Remember new length. | 9061 // Remember new length. |
9101 Add<HStoreNamedField>( | 9062 Add<HStoreNamedField>( |
9102 receiver, HObjectAccess::ForArrayLength(kind), | 9063 receiver, HObjectAccess::ForArrayLength(kind), |
9103 new_length, STORE_TO_INITIALIZED_ENTRY); | 9064 new_length, STORE_TO_INITIALIZED_ENTRY); |
9104 } | 9065 } |
9105 if_inline.Else(); | 9066 if_inline.Else(); |
9106 { | 9067 { |
9107 Add<HPushArguments>(receiver); | 9068 Add<HPushArguments>(receiver); |
9108 result = Add<HCallJSFunction>(function, 1); | 9069 result = AddInstruction(NewCallConstantFunction(function, 1)); |
9109 if (!ast_context()->IsEffect()) Push(result); | 9070 if (!ast_context()->IsEffect()) Push(result); |
9110 } | 9071 } |
9111 if_inline.End(); | 9072 if_inline.End(); |
9112 } | 9073 } |
9113 if_lengthiszero.End(); | 9074 if_lengthiszero.End(); |
9114 } | 9075 } |
9115 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 9076 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
9116 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 9077 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
9117 if (!ast_context()->IsEffect()) Drop(1); | 9078 if (!ast_context()->IsEffect()) Drop(1); |
9118 ast_context()->ReturnValue(result); | 9079 ast_context()->ReturnValue(result); |
(...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9775 // Since HWrapReceiver currently cannot actually wrap numbers and | 9736 // Since HWrapReceiver currently cannot actually wrap numbers and |
9776 // strings, use the regular call builtin for method calls to wrap | 9737 // strings, use the regular call builtin for method calls to wrap |
9777 // the receiver. | 9738 // the receiver. |
9778 // TODO(verwaest): Support creation of value wrappers directly in | 9739 // TODO(verwaest): Support creation of value wrappers directly in |
9779 // HWrapReceiver. | 9740 // HWrapReceiver. |
9780 call = NewCallFunction(function, argument_count, | 9741 call = NewCallFunction(function, argument_count, |
9781 ConvertReceiverMode::kNotNullOrUndefined); | 9742 ConvertReceiverMode::kNotNullOrUndefined); |
9782 } else if (TryInlineCall(expr)) { | 9743 } else if (TryInlineCall(expr)) { |
9783 return; | 9744 return; |
9784 } else { | 9745 } else { |
9785 call = BuildCallConstantFunction(known_function, argument_count); | 9746 call = NewCallConstantFunction(known_function, argument_count); |
9786 } | 9747 } |
9787 | 9748 |
9788 } else { | 9749 } else { |
9789 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9750 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9790 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9751 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9791 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9752 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9792 // gets ignored by the always-opt flag, which leads to incorrect code. | 9753 // gets ignored by the always-opt flag, which leads to incorrect code. |
9793 Add<HDeoptimize>( | 9754 Add<HDeoptimize>( |
9794 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, | 9755 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
9795 Deoptimizer::EAGER); | 9756 Deoptimizer::EAGER); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9842 expr->target()->ShortPrint(); | 9803 expr->target()->ShortPrint(); |
9843 PrintF("\n"); | 9804 PrintF("\n"); |
9844 } | 9805 } |
9845 return; | 9806 return; |
9846 } | 9807 } |
9847 if (TryInlineApiFunctionCall(expr, receiver)) return; | 9808 if (TryInlineApiFunctionCall(expr, receiver)) return; |
9848 if (TryHandleArrayCall(expr, function)) return; | 9809 if (TryHandleArrayCall(expr, function)) return; |
9849 if (TryInlineCall(expr)) return; | 9810 if (TryInlineCall(expr)) return; |
9850 | 9811 |
9851 PushArgumentsFromEnvironment(argument_count); | 9812 PushArgumentsFromEnvironment(argument_count); |
9852 call = BuildCallConstantFunction(expr->target(), argument_count); | 9813 call = NewCallConstantFunction(expr->target(), argument_count); |
9853 } else { | 9814 } else { |
9854 PushArgumentsFromEnvironment(argument_count); | 9815 PushArgumentsFromEnvironment(argument_count); |
9855 if (expr->is_uninitialized() && | 9816 if (expr->is_uninitialized() && |
9856 expr->IsUsingCallFeedbackICSlot(isolate())) { | 9817 expr->IsUsingCallFeedbackICSlot(isolate())) { |
9857 // We've never seen this call before, so let's have Crankshaft learn | 9818 // We've never seen this call before, so let's have Crankshaft learn |
9858 // through the type vector. | 9819 // through the type vector. |
9859 call = NewCallFunctionViaIC(function, argument_count, | 9820 call = NewCallFunctionViaIC(function, argument_count, |
9860 ConvertReceiverMode::kNullOrUndefined, | 9821 ConvertReceiverMode::kNullOrUndefined, |
9861 expr->CallFeedbackICSlot()); | 9822 expr->CallFeedbackICSlot()); |
9862 } else { | 9823 } else { |
(...skipping 3630 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13493 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13454 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13494 } | 13455 } |
13495 | 13456 |
13496 #ifdef DEBUG | 13457 #ifdef DEBUG |
13497 graph_->Verify(false); // No full verify. | 13458 graph_->Verify(false); // No full verify. |
13498 #endif | 13459 #endif |
13499 } | 13460 } |
13500 | 13461 |
13501 } // namespace internal | 13462 } // namespace internal |
13502 } // namespace v8 | 13463 } // namespace v8 |
OLD | NEW |