| 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 3474 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3485 return array_object; | 3485 return array_object; |
| 3486 } | 3486 } |
| 3487 | 3487 |
| 3488 | 3488 |
| 3489 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) { | 3489 HValue* HGraphBuilder::AddLoadJSBuiltin(int context_index) { |
| 3490 HValue* native_context = BuildGetNativeContext(); | 3490 HValue* native_context = BuildGetNativeContext(); |
| 3491 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index); | 3491 HObjectAccess function_access = HObjectAccess::ForContextSlot(context_index); |
| 3492 return Add<HLoadNamedField>(native_context, nullptr, function_access); | 3492 return Add<HLoadNamedField>(native_context, nullptr, function_access); |
| 3493 } | 3493 } |
| 3494 | 3494 |
| 3495 | |
| 3496 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) | 3495 HOptimizedGraphBuilder::HOptimizedGraphBuilder(CompilationInfo* info) |
| 3497 : HGraphBuilder(info, CallInterfaceDescriptor()), | 3496 : HGraphBuilder(info, CallInterfaceDescriptor()), |
| 3498 function_state_(NULL), | 3497 function_state_(NULL), |
| 3499 initial_function_state_(this, info, NORMAL_RETURN, 0), | 3498 initial_function_state_(this, info, NORMAL_RETURN, 0, |
| 3499 TailCallMode::kAllow), |
| 3500 ast_context_(NULL), | 3500 ast_context_(NULL), |
| 3501 break_scope_(NULL), | 3501 break_scope_(NULL), |
| 3502 inlined_count_(0), | 3502 inlined_count_(0), |
| 3503 globals_(10, info->zone()), | 3503 globals_(10, info->zone()), |
| 3504 osr_(new (info->zone()) HOsrBuilder(this)) { | 3504 osr_(new (info->zone()) HOsrBuilder(this)) { |
| 3505 // This is not initialized in the initializer list because the | 3505 // This is not initialized in the initializer list because the |
| 3506 // constructor for the initial state relies on function_state_ == NULL | 3506 // constructor for the initial state relies on function_state_ == NULL |
| 3507 // to know it's the initial state. | 3507 // to know it's the initial state. |
| 3508 function_state_ = &initial_function_state_; | 3508 function_state_ = &initial_function_state_; |
| 3509 InitializeAstVisitor(info->isolate()); | 3509 InitializeAstVisitor(info->isolate()); |
| (...skipping 515 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4025 phi_list_->Add(phi, zone()); | 4025 phi_list_->Add(phi, zone()); |
| 4026 } | 4026 } |
| 4027 } | 4027 } |
| 4028 } | 4028 } |
| 4029 | 4029 |
| 4030 | 4030 |
| 4031 // Implementation of utility class to encapsulate the translation state for | 4031 // Implementation of utility class to encapsulate the translation state for |
| 4032 // a (possibly inlined) function. | 4032 // a (possibly inlined) function. |
| 4033 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, | 4033 FunctionState::FunctionState(HOptimizedGraphBuilder* owner, |
| 4034 CompilationInfo* info, InliningKind inlining_kind, | 4034 CompilationInfo* info, InliningKind inlining_kind, |
| 4035 int inlining_id) | 4035 int inlining_id, TailCallMode tail_call_mode) |
| 4036 : owner_(owner), | 4036 : owner_(owner), |
| 4037 compilation_info_(info), | 4037 compilation_info_(info), |
| 4038 call_context_(NULL), | 4038 call_context_(NULL), |
| 4039 inlining_kind_(inlining_kind), | 4039 inlining_kind_(inlining_kind), |
| 4040 tail_call_mode_(tail_call_mode), |
| 4040 function_return_(NULL), | 4041 function_return_(NULL), |
| 4041 test_context_(NULL), | 4042 test_context_(NULL), |
| 4042 entry_(NULL), | 4043 entry_(NULL), |
| 4043 arguments_object_(NULL), | 4044 arguments_object_(NULL), |
| 4044 arguments_elements_(NULL), | 4045 arguments_elements_(NULL), |
| 4045 inlining_id_(inlining_id), | 4046 inlining_id_(inlining_id), |
| 4046 outer_source_position_(SourcePosition::Unknown()), | 4047 outer_source_position_(SourcePosition::Unknown()), |
| 4047 outer_(owner->function_state()) { | 4048 outer_(owner->function_state()) { |
| 4048 if (outer_ != NULL) { | 4049 if (outer_ != NULL) { |
| 4049 // State for an inline function. | 4050 // State for an inline function. |
| (...skipping 2516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6566 if (!info->IsLoad()) { | 6567 if (!info->IsLoad()) { |
| 6567 argument_count = 2; | 6568 argument_count = 2; |
| 6568 Push(value); | 6569 Push(value); |
| 6569 } | 6570 } |
| 6570 | 6571 |
| 6571 if (info->accessor()->IsJSFunction() && | 6572 if (info->accessor()->IsJSFunction() && |
| 6572 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { | 6573 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { |
| 6573 HValue* function = Add<HConstant>(info->accessor()); | 6574 HValue* function = Add<HConstant>(info->accessor()); |
| 6574 PushArgumentsFromEnvironment(argument_count); | 6575 PushArgumentsFromEnvironment(argument_count); |
| 6575 return NewCallFunction(function, argument_count, | 6576 return NewCallFunction(function, argument_count, |
| 6576 ConvertReceiverMode::kNotNullOrUndefined); | 6577 ConvertReceiverMode::kNotNullOrUndefined, |
| 6578 TailCallMode::kDisallow); |
| 6577 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6579 } else if (FLAG_inline_accessors && can_inline_accessor) { |
| 6578 bool success = info->IsLoad() | 6580 bool success = info->IsLoad() |
| 6579 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6581 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
| 6580 : TryInlineSetter( | 6582 : TryInlineSetter( |
| 6581 info->accessor(), info->map(), ast_id, return_id, value); | 6583 info->accessor(), info->map(), ast_id, return_id, value); |
| 6582 if (success || HasStackOverflow()) return NULL; | 6584 if (success || HasStackOverflow()) return NULL; |
| 6583 } | 6585 } |
| 6584 | 6586 |
| 6585 PushArgumentsFromEnvironment(argument_count); | 6587 PushArgumentsFromEnvironment(argument_count); |
| 6586 if (!info->accessor()->IsJSFunction()) { | 6588 if (!info->accessor()->IsJSFunction()) { |
| 6587 Bailout(kInliningBailedOut); | 6589 Bailout(kInliningBailedOut); |
| 6588 return nullptr; | 6590 return nullptr; |
| 6589 } | 6591 } |
| 6590 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), | 6592 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), |
| 6591 argument_count); | 6593 argument_count, TailCallMode::kDisallow); |
| 6592 } | 6594 } |
| 6593 | 6595 |
| 6594 DCHECK(info->IsDataConstant()); | 6596 DCHECK(info->IsDataConstant()); |
| 6595 if (info->IsLoad()) { | 6597 if (info->IsLoad()) { |
| 6596 return New<HConstant>(info->constant()); | 6598 return New<HConstant>(info->constant()); |
| 6597 } else { | 6599 } else { |
| 6598 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6600 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
| 6599 } | 6601 } |
| 6600 } | 6602 } |
| 6601 | 6603 |
| (...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7980 | 7982 |
| 7981 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7983 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
| 7982 Handle<Map> receiver_map) { | 7984 Handle<Map> receiver_map) { |
| 7983 if (!holder.is_null()) { | 7985 if (!holder.is_null()) { |
| 7984 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7986 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
| 7985 BuildCheckPrototypeMaps(prototype, holder); | 7987 BuildCheckPrototypeMaps(prototype, holder); |
| 7986 } | 7988 } |
| 7987 } | 7989 } |
| 7988 | 7990 |
| 7989 HInstruction* HOptimizedGraphBuilder::NewCallFunction( | 7991 HInstruction* HOptimizedGraphBuilder::NewCallFunction( |
| 7990 HValue* function, int argument_count, ConvertReceiverMode convert_mode) { | 7992 HValue* function, int argument_count, ConvertReceiverMode convert_mode, |
| 7993 TailCallMode tail_call_mode) { |
| 7991 HValue* arity = Add<HConstant>(argument_count - 1); | 7994 HValue* arity = Add<HConstant>(argument_count - 1); |
| 7992 | 7995 |
| 7993 HValue* op_vals[] = {context(), function, arity}; | 7996 HValue* op_vals[] = {context(), function, arity}; |
| 7994 | 7997 |
| 7998 // TODO(ishell): use tail_call_mode here. |
| 7995 Callable callable = CodeFactory::Call(isolate(), convert_mode); | 7999 Callable callable = CodeFactory::Call(isolate(), convert_mode); |
| 7996 HConstant* stub = Add<HConstant>(callable.code()); | 8000 HConstant* stub = Add<HConstant>(callable.code()); |
| 7997 | 8001 |
| 7998 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8002 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
| 7999 Vector<HValue*>(op_vals, arraysize(op_vals))); | 8003 Vector<HValue*>(op_vals, arraysize(op_vals))); |
| 8000 } | 8004 } |
| 8001 | 8005 |
| 8002 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC( | 8006 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC( |
| 8003 HValue* function, int argument_count, ConvertReceiverMode convert_mode, | 8007 HValue* function, int argument_count, ConvertReceiverMode convert_mode, |
| 8004 FeedbackVectorSlot slot) { | 8008 TailCallMode tail_call_mode, FeedbackVectorSlot slot) { |
| 8005 int arity = argument_count - 1; | 8009 int arity = argument_count - 1; |
| 8006 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 8010 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
| 8007 HValue* index_val = Add<HConstant>(vector->GetIndex(slot)); | 8011 HValue* index_val = Add<HConstant>(vector->GetIndex(slot)); |
| 8008 HValue* vector_val = Add<HConstant>(vector); | 8012 HValue* vector_val = Add<HConstant>(vector); |
| 8009 | 8013 |
| 8010 HValue* op_vals[] = {context(), function, index_val, vector_val}; | 8014 HValue* op_vals[] = {context(), function, index_val, vector_val}; |
| 8011 | 8015 |
| 8016 // TODO(ishell): use tail_call_mode here. |
| 8012 Callable callable = CodeFactory::CallICInOptimizedCode( | 8017 Callable callable = CodeFactory::CallICInOptimizedCode( |
| 8013 isolate(), arity, ConvertReceiverMode::kNullOrUndefined); | 8018 isolate(), arity, ConvertReceiverMode::kNullOrUndefined); |
| 8014 HConstant* stub = Add<HConstant>(callable.code()); | 8019 HConstant* stub = Add<HConstant>(callable.code()); |
| 8015 | 8020 |
| 8016 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8021 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
| 8017 Vector<HValue*>(op_vals, arraysize(op_vals))); | 8022 Vector<HValue*>(op_vals, arraysize(op_vals))); |
| 8018 } | 8023 } |
| 8019 | 8024 |
| 8020 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( | 8025 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( |
| 8021 Handle<JSFunction> function, int argument_count) { | 8026 Handle<JSFunction> function, int argument_count, |
| 8027 TailCallMode tail_call_mode) { |
| 8028 // TODO(ishell): use tail_call_mode here. |
| 8022 HValue* target = Add<HConstant>(function); | 8029 HValue* target = Add<HConstant>(function); |
| 8023 return New<HInvokeFunction>(target, function, argument_count); | 8030 return New<HInvokeFunction>(target, function, argument_count); |
| 8024 } | 8031 } |
| 8025 | 8032 |
| 8026 | 8033 |
| 8027 class FunctionSorter { | 8034 class FunctionSorter { |
| 8028 public: | 8035 public: |
| 8029 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) | 8036 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) |
| 8030 : index_(index), ticks_(ticks), size_(size) {} | 8037 : index_(index), ticks_(ticks), size_(size) {} |
| 8031 | 8038 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 8051 HValue* receiver, | 8058 HValue* receiver, |
| 8052 SmallMapList* maps, | 8059 SmallMapList* maps, |
| 8053 Handle<String> name) { | 8060 Handle<String> name) { |
| 8054 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 8061 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
| 8055 FunctionSorter order[kMaxCallPolymorphism]; | 8062 FunctionSorter order[kMaxCallPolymorphism]; |
| 8056 | 8063 |
| 8057 bool handle_smi = false; | 8064 bool handle_smi = false; |
| 8058 bool handled_string = false; | 8065 bool handled_string = false; |
| 8059 int ordered_functions = 0; | 8066 int ordered_functions = 0; |
| 8060 | 8067 |
| 8068 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
| 8069 TailCallMode tail_call_mode = |
| 8070 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
| 8071 |
| 8061 int i; | 8072 int i; |
| 8062 for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism; | 8073 for (i = 0; i < maps->length() && ordered_functions < kMaxCallPolymorphism; |
| 8063 ++i) { | 8074 ++i) { |
| 8064 PropertyAccessInfo info(this, LOAD, maps->at(i), name); | 8075 PropertyAccessInfo info(this, LOAD, maps->at(i), name); |
| 8065 if (info.CanAccessMonomorphic() && info.IsDataConstant() && | 8076 if (info.CanAccessMonomorphic() && info.IsDataConstant() && |
| 8066 info.constant()->IsJSFunction()) { | 8077 info.constant()->IsJSFunction()) { |
| 8067 if (info.IsStringType()) { | 8078 if (info.IsStringType()) { |
| 8068 if (handled_string) continue; | 8079 if (handled_string) continue; |
| 8069 handled_string = true; | 8080 handled_string = true; |
| 8070 } | 8081 } |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8161 // entire compilation by setting stack overflow on the visitor. | 8172 // entire compilation by setting stack overflow on the visitor. |
| 8162 if (HasStackOverflow()) return; | 8173 if (HasStackOverflow()) return; |
| 8163 } else { | 8174 } else { |
| 8164 // Since HWrapReceiver currently cannot actually wrap numbers and strings, | 8175 // Since HWrapReceiver currently cannot actually wrap numbers and strings, |
| 8165 // use the regular call builtin for method calls to wrap the receiver. | 8176 // use the regular call builtin for method calls to wrap the receiver. |
| 8166 // TODO(verwaest): Support creation of value wrappers directly in | 8177 // TODO(verwaest): Support creation of value wrappers directly in |
| 8167 // HWrapReceiver. | 8178 // HWrapReceiver. |
| 8168 HInstruction* call = | 8179 HInstruction* call = |
| 8169 needs_wrapping | 8180 needs_wrapping |
| 8170 ? NewCallFunction(function, argument_count, | 8181 ? NewCallFunction(function, argument_count, |
| 8171 ConvertReceiverMode::kNotNullOrUndefined) | 8182 ConvertReceiverMode::kNotNullOrUndefined, |
| 8172 : NewCallConstantFunction(target, argument_count); | 8183 tail_call_mode) |
| 8184 : NewCallConstantFunction(target, argument_count, tail_call_mode); |
| 8173 PushArgumentsFromEnvironment(argument_count); | 8185 PushArgumentsFromEnvironment(argument_count); |
| 8174 AddInstruction(call); | 8186 AddInstruction(call); |
| 8175 Drop(1); // Drop the function. | 8187 Drop(1); // Drop the function. |
| 8176 if (!ast_context()->IsEffect()) Push(call); | 8188 if (!ast_context()->IsEffect()) Push(call); |
| 8177 } | 8189 } |
| 8178 | 8190 |
| 8179 if (current_block() != NULL) Goto(join); | 8191 if (current_block() != NULL) Goto(join); |
| 8180 set_current_block(if_false); | 8192 set_current_block(if_false); |
| 8181 } | 8193 } |
| 8182 | 8194 |
| 8183 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 8195 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
| 8184 // know about and do not want to handle ones we've never seen. Otherwise | 8196 // know about and do not want to handle ones we've never seen. Otherwise |
| 8185 // use a generic IC. | 8197 // use a generic IC. |
| 8186 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { | 8198 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { |
| 8187 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); | 8199 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
| 8188 } else { | 8200 } else { |
| 8189 Property* prop = expr->expression()->AsProperty(); | 8201 Property* prop = expr->expression()->AsProperty(); |
| 8190 HInstruction* function = | 8202 HInstruction* function = |
| 8191 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, | 8203 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, |
| 8192 name, NULL, prop->IsUninitialized()); | 8204 name, NULL, prop->IsUninitialized()); |
| 8193 AddInstruction(function); | 8205 AddInstruction(function); |
| 8194 Push(function); | 8206 Push(function); |
| 8195 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 8207 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
| 8196 | 8208 |
| 8197 environment()->SetExpressionStackAt(1, function); | 8209 environment()->SetExpressionStackAt(1, function); |
| 8198 environment()->SetExpressionStackAt(0, receiver); | 8210 environment()->SetExpressionStackAt(0, receiver); |
| 8199 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8211 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
| 8200 | 8212 |
| 8201 HInstruction* call = NewCallFunction( | 8213 HInstruction* call = NewCallFunction( |
| 8202 function, argument_count, ConvertReceiverMode::kNotNullOrUndefined); | 8214 function, argument_count, ConvertReceiverMode::kNotNullOrUndefined, |
| 8215 tail_call_mode); |
| 8203 | 8216 |
| 8204 PushArgumentsFromEnvironment(argument_count); | 8217 PushArgumentsFromEnvironment(argument_count); |
| 8205 | 8218 |
| 8206 Drop(1); // Function. | 8219 Drop(1); // Function. |
| 8207 | 8220 |
| 8208 if (join != NULL) { | 8221 if (join != NULL) { |
| 8209 AddInstruction(call); | 8222 AddInstruction(call); |
| 8210 if (!ast_context()->IsEffect()) Push(call); | 8223 if (!ast_context()->IsEffect()) Push(call); |
| 8211 Goto(join); | 8224 Goto(join); |
| 8212 } else { | 8225 } else { |
| 8213 return ast_context()->ReturnInstruction(call, expr->id()); | 8226 return ast_context()->ReturnInstruction(call, expr->id()); |
| 8214 } | 8227 } |
| 8215 } | 8228 } |
| 8216 | 8229 |
| 8217 // We assume that control flow is always live after an expression. So | 8230 // We assume that control flow is always live after an expression. So |
| 8218 // even without predecessors to the join block, we set it as the exit | 8231 // even without predecessors to the join block, we set it as the exit |
| 8219 // block and continue by adding instructions there. | 8232 // block and continue by adding instructions there. |
| 8220 DCHECK(join != NULL); | 8233 DCHECK(join != NULL); |
| 8221 if (join->HasPredecessor()) { | 8234 if (join->HasPredecessor()) { |
| 8222 set_current_block(join); | 8235 set_current_block(join); |
| 8223 join->SetJoinId(expr->id()); | 8236 join->SetJoinId(expr->id()); |
| 8224 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); | 8237 if (!ast_context()->IsEffect()) return ast_context()->ReturnValue(Pop()); |
| 8225 } else { | 8238 } else { |
| 8226 set_current_block(NULL); | 8239 set_current_block(NULL); |
| 8227 } | 8240 } |
| 8228 } | 8241 } |
| 8229 | 8242 |
| 8230 | |
| 8231 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, | 8243 void HOptimizedGraphBuilder::TraceInline(Handle<JSFunction> target, |
| 8232 Handle<JSFunction> caller, | 8244 Handle<JSFunction> caller, |
| 8233 const char* reason) { | 8245 const char* reason, |
| 8246 TailCallMode tail_call_mode) { |
| 8234 if (FLAG_trace_inlining) { | 8247 if (FLAG_trace_inlining) { |
| 8235 base::SmartArrayPointer<char> target_name = | 8248 base::SmartArrayPointer<char> target_name = |
| 8236 target->shared()->DebugName()->ToCString(); | 8249 target->shared()->DebugName()->ToCString(); |
| 8237 base::SmartArrayPointer<char> caller_name = | 8250 base::SmartArrayPointer<char> caller_name = |
| 8238 caller->shared()->DebugName()->ToCString(); | 8251 caller->shared()->DebugName()->ToCString(); |
| 8239 if (reason == NULL) { | 8252 if (reason == NULL) { |
| 8240 PrintF("Inlined %s called from %s.\n", target_name.get(), | 8253 const char* call_mode = |
| 8254 tail_call_mode == TailCallMode::kAllow ? "tail called" : "called"; |
| 8255 PrintF("Inlined %s %s from %s.\n", target_name.get(), call_mode, |
| 8241 caller_name.get()); | 8256 caller_name.get()); |
| 8242 } else { | 8257 } else { |
| 8243 PrintF("Did not inline %s called from %s (%s).\n", | 8258 PrintF("Did not inline %s called from %s (%s).\n", |
| 8244 target_name.get(), caller_name.get(), reason); | 8259 target_name.get(), caller_name.get(), reason); |
| 8245 } | 8260 } |
| 8246 } | 8261 } |
| 8247 } | 8262 } |
| 8248 | 8263 |
| 8249 | 8264 |
| 8250 static const int kNotInlinable = 1000000000; | 8265 static const int kNotInlinable = 1000000000; |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8287 } | 8302 } |
| 8288 if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) { | 8303 if (noopt_reason != kNoReason && noopt_reason != kHydrogenFilter) { |
| 8289 TraceInline(target, caller, "target contains unsupported syntax [early]"); | 8304 TraceInline(target, caller, "target contains unsupported syntax [early]"); |
| 8290 return kNotInlinable; | 8305 return kNotInlinable; |
| 8291 } | 8306 } |
| 8292 | 8307 |
| 8293 int nodes_added = target_shared->ast_node_count(); | 8308 int nodes_added = target_shared->ast_node_count(); |
| 8294 return nodes_added; | 8309 return nodes_added; |
| 8295 } | 8310 } |
| 8296 | 8311 |
| 8297 | |
| 8298 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, | 8312 bool HOptimizedGraphBuilder::TryInline(Handle<JSFunction> target, |
| 8299 int arguments_count, | 8313 int arguments_count, |
| 8300 HValue* implicit_return_value, | 8314 HValue* implicit_return_value, |
| 8301 BailoutId ast_id, BailoutId return_id, | 8315 BailoutId ast_id, BailoutId return_id, |
| 8302 InliningKind inlining_kind) { | 8316 InliningKind inlining_kind, |
| 8317 TailCallMode syntactic_tail_call_mode) { |
| 8303 if (target->context()->native_context() != | 8318 if (target->context()->native_context() != |
| 8304 top_info()->closure()->context()->native_context()) { | 8319 top_info()->closure()->context()->native_context()) { |
| 8305 return false; | 8320 return false; |
| 8306 } | 8321 } |
| 8307 int nodes_added = InliningAstSize(target); | 8322 int nodes_added = InliningAstSize(target); |
| 8308 if (nodes_added == kNotInlinable) return false; | 8323 if (nodes_added == kNotInlinable) return false; |
| 8309 | 8324 |
| 8310 Handle<JSFunction> caller = current_info()->closure(); | 8325 Handle<JSFunction> caller = current_info()->closure(); |
| 8326 if (syntactic_tail_call_mode == TailCallMode::kAllow) { |
| 8327 TraceInline(target, caller, "call is at tail position"); |
| 8328 return false; |
| 8329 } |
| 8311 | 8330 |
| 8312 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { | 8331 if (nodes_added > Min(FLAG_max_inlined_nodes, kUnlimitedMaxInlinedNodes)) { |
| 8313 TraceInline(target, caller, "target AST is too large [early]"); | 8332 TraceInline(target, caller, "target AST is too large [early]"); |
| 8314 return false; | 8333 return false; |
| 8315 } | 8334 } |
| 8316 | 8335 |
| 8317 // Don't inline deeper than the maximum number of inlining levels. | 8336 // Don't inline deeper than the maximum number of inlining levels. |
| 8318 HEnvironment* env = environment(); | 8337 HEnvironment* env = environment(); |
| 8319 int current_level = 1; | 8338 int current_level = 1; |
| 8320 while (env->outer() != NULL) { | 8339 while (env->outer() != NULL) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8462 | 8481 |
| 8463 int inlining_id = 0; | 8482 int inlining_id = 0; |
| 8464 if (top_info()->is_tracking_positions()) { | 8483 if (top_info()->is_tracking_positions()) { |
| 8465 inlining_id = top_info()->TraceInlinedFunction( | 8484 inlining_id = top_info()->TraceInlinedFunction( |
| 8466 target_shared, source_position(), function_state()->inlining_id()); | 8485 target_shared, source_position(), function_state()->inlining_id()); |
| 8467 } | 8486 } |
| 8468 | 8487 |
| 8469 // Save the pending call context. Set up new one for the inlined function. | 8488 // Save the pending call context. Set up new one for the inlined function. |
| 8470 // The function state is new-allocated because we need to delete it | 8489 // The function state is new-allocated because we need to delete it |
| 8471 // in two different places. | 8490 // in two different places. |
| 8472 FunctionState* target_state = | 8491 FunctionState* target_state = new FunctionState( |
| 8473 new FunctionState(this, &target_info, inlining_kind, inlining_id); | 8492 this, &target_info, inlining_kind, inlining_id, |
| 8493 function_state()->ComputeTailCallMode(syntactic_tail_call_mode)); |
| 8474 | 8494 |
| 8475 HConstant* undefined = graph()->GetConstantUndefined(); | 8495 HConstant* undefined = graph()->GetConstantUndefined(); |
| 8476 | 8496 |
| 8477 HEnvironment* inner_env = | 8497 HEnvironment* inner_env = |
| 8478 environment()->CopyForInlining(target, | 8498 environment()->CopyForInlining(target, |
| 8479 arguments_count, | 8499 arguments_count, |
| 8480 function, | 8500 function, |
| 8481 undefined, | 8501 undefined, |
| 8482 function_state()->inlining_kind()); | 8502 function_state()->inlining_kind()); |
| 8483 | 8503 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8533 | 8553 |
| 8534 // Update inlined nodes count. | 8554 // Update inlined nodes count. |
| 8535 inlined_count_ += nodes_added; | 8555 inlined_count_ += nodes_added; |
| 8536 | 8556 |
| 8537 Handle<Code> unoptimized_code(target_shared->code()); | 8557 Handle<Code> unoptimized_code(target_shared->code()); |
| 8538 DCHECK(unoptimized_code->kind() == Code::FUNCTION); | 8558 DCHECK(unoptimized_code->kind() == Code::FUNCTION); |
| 8539 Handle<TypeFeedbackInfo> type_info( | 8559 Handle<TypeFeedbackInfo> type_info( |
| 8540 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); | 8560 TypeFeedbackInfo::cast(unoptimized_code->type_feedback_info())); |
| 8541 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); | 8561 graph()->update_type_change_checksum(type_info->own_type_change_checksum()); |
| 8542 | 8562 |
| 8543 TraceInline(target, caller, NULL); | 8563 TraceInline(target, caller, NULL, syntactic_tail_call_mode); |
| 8544 | 8564 |
| 8545 if (current_block() != NULL) { | 8565 if (current_block() != NULL) { |
| 8546 FunctionState* state = function_state(); | 8566 FunctionState* state = function_state(); |
| 8547 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { | 8567 if (state->inlining_kind() == CONSTRUCT_CALL_RETURN) { |
| 8548 // Falling off the end of an inlined construct call. In a test context the | 8568 // Falling off the end of an inlined construct call. In a test context the |
| 8549 // return value will always evaluate to true, in a value context the | 8569 // return value will always evaluate to true, in a value context the |
| 8550 // return value is the newly allocated receiver. | 8570 // return value is the newly allocated receiver. |
| 8551 if (call_context()->IsTest()) { | 8571 if (call_context()->IsTest()) { |
| 8552 Goto(inlined_test_context()->if_true(), state); | 8572 Goto(inlined_test_context()->if_true(), state); |
| 8553 } else if (call_context()->IsEffect()) { | 8573 } else if (call_context()->IsEffect()) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8617 } else { | 8637 } else { |
| 8618 set_current_block(NULL); | 8638 set_current_block(NULL); |
| 8619 } | 8639 } |
| 8620 delete target_state; | 8640 delete target_state; |
| 8621 return true; | 8641 return true; |
| 8622 } | 8642 } |
| 8623 | 8643 |
| 8624 | 8644 |
| 8625 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) { | 8645 bool HOptimizedGraphBuilder::TryInlineCall(Call* expr) { |
| 8626 return TryInline(expr->target(), expr->arguments()->length(), NULL, | 8646 return TryInline(expr->target(), expr->arguments()->length(), NULL, |
| 8627 expr->id(), expr->ReturnId(), NORMAL_RETURN); | 8647 expr->id(), expr->ReturnId(), NORMAL_RETURN, |
| 8648 expr->tail_call_mode()); |
| 8628 } | 8649 } |
| 8629 | 8650 |
| 8630 | 8651 |
| 8631 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, | 8652 bool HOptimizedGraphBuilder::TryInlineConstruct(CallNew* expr, |
| 8632 HValue* implicit_return_value) { | 8653 HValue* implicit_return_value) { |
| 8633 return TryInline(expr->target(), expr->arguments()->length(), | 8654 return TryInline(expr->target(), expr->arguments()->length(), |
| 8634 implicit_return_value, expr->id(), expr->ReturnId(), | 8655 implicit_return_value, expr->id(), expr->ReturnId(), |
| 8635 CONSTRUCT_CALL_RETURN); | 8656 CONSTRUCT_CALL_RETURN, TailCallMode::kDisallow); |
| 8636 } | 8657 } |
| 8637 | 8658 |
| 8638 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter, | 8659 bool HOptimizedGraphBuilder::TryInlineGetter(Handle<Object> getter, |
| 8639 Handle<Map> receiver_map, | 8660 Handle<Map> receiver_map, |
| 8640 BailoutId ast_id, | 8661 BailoutId ast_id, |
| 8641 BailoutId return_id) { | 8662 BailoutId return_id) { |
| 8642 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; | 8663 if (TryInlineApiGetter(getter, receiver_map, ast_id)) return true; |
| 8643 return getter->IsJSFunction() && | 8664 return getter->IsJSFunction() && |
| 8644 TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id, | 8665 TryInline(Handle<JSFunction>::cast(getter), 0, NULL, ast_id, return_id, |
| 8645 GETTER_CALL_RETURN); | 8666 GETTER_CALL_RETURN, TailCallMode::kDisallow); |
| 8646 } | 8667 } |
| 8647 | 8668 |
| 8648 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter, | 8669 bool HOptimizedGraphBuilder::TryInlineSetter(Handle<Object> setter, |
| 8649 Handle<Map> receiver_map, | 8670 Handle<Map> receiver_map, |
| 8650 BailoutId id, | 8671 BailoutId id, |
| 8651 BailoutId assignment_id, | 8672 BailoutId assignment_id, |
| 8652 HValue* implicit_return_value) { | 8673 HValue* implicit_return_value) { |
| 8653 if (TryInlineApiSetter(setter, receiver_map, id)) return true; | 8674 if (TryInlineApiSetter(setter, receiver_map, id)) return true; |
| 8654 return setter->IsJSFunction() && | 8675 return setter->IsJSFunction() && |
| 8655 TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value, | 8676 TryInline(Handle<JSFunction>::cast(setter), 1, implicit_return_value, |
| 8656 id, assignment_id, SETTER_CALL_RETURN); | 8677 id, assignment_id, SETTER_CALL_RETURN, |
| 8678 TailCallMode::kDisallow); |
| 8657 } | 8679 } |
| 8658 | 8680 |
| 8659 | 8681 |
| 8660 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, | 8682 bool HOptimizedGraphBuilder::TryInlineIndirectCall(Handle<JSFunction> function, |
| 8661 Call* expr, | 8683 Call* expr, |
| 8662 int arguments_count) { | 8684 int arguments_count) { |
| 8663 return TryInline(function, arguments_count, NULL, expr->id(), | 8685 return TryInline(function, arguments_count, NULL, expr->id(), |
| 8664 expr->ReturnId(), NORMAL_RETURN); | 8686 expr->ReturnId(), NORMAL_RETURN, expr->tail_call_mode()); |
| 8665 } | 8687 } |
| 8666 | 8688 |
| 8667 | 8689 |
| 8668 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) { | 8690 bool HOptimizedGraphBuilder::TryInlineBuiltinFunctionCall(Call* expr) { |
| 8669 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; | 8691 if (!expr->target()->shared()->HasBuiltinFunctionId()) return false; |
| 8670 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); | 8692 BuiltinFunctionId id = expr->target()->shared()->builtin_function_id(); |
| 8693 // We intentionally ignore expr->tail_call_mode() here because builtins |
| 8694 // we inline here do not observe if they were tail called or not. |
| 8671 switch (id) { | 8695 switch (id) { |
| 8672 case kMathExp: | 8696 case kMathExp: |
| 8673 if (!FLAG_fast_math) break; | 8697 if (!FLAG_fast_math) break; |
| 8674 // Fall through if FLAG_fast_math. | 8698 // Fall through if FLAG_fast_math. |
| 8675 case kMathRound: | 8699 case kMathRound: |
| 8676 case kMathFround: | 8700 case kMathFround: |
| 8677 case kMathFloor: | 8701 case kMathFloor: |
| 8678 case kMathAbs: | 8702 case kMathAbs: |
| 8679 case kMathSqrt: | 8703 case kMathSqrt: |
| 8680 case kMathLog: | 8704 case kMathLog: |
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9076 INITIALIZING_STORE); | 9100 INITIALIZING_STORE); |
| 9077 | 9101 |
| 9078 // Remember new length. | 9102 // Remember new length. |
| 9079 Add<HStoreNamedField>( | 9103 Add<HStoreNamedField>( |
| 9080 receiver, HObjectAccess::ForArrayLength(kind), | 9104 receiver, HObjectAccess::ForArrayLength(kind), |
| 9081 new_length, STORE_TO_INITIALIZED_ENTRY); | 9105 new_length, STORE_TO_INITIALIZED_ENTRY); |
| 9082 } | 9106 } |
| 9083 if_inline.Else(); | 9107 if_inline.Else(); |
| 9084 { | 9108 { |
| 9085 Add<HPushArguments>(receiver); | 9109 Add<HPushArguments>(receiver); |
| 9086 result = AddInstruction(NewCallConstantFunction(function, 1)); | 9110 result = AddInstruction( |
| 9111 NewCallConstantFunction(function, 1, TailCallMode::kDisallow)); |
| 9087 if (!ast_context()->IsEffect()) Push(result); | 9112 if (!ast_context()->IsEffect()) Push(result); |
| 9088 } | 9113 } |
| 9089 if_inline.End(); | 9114 if_inline.End(); |
| 9090 } | 9115 } |
| 9091 if_lengthiszero.End(); | 9116 if_lengthiszero.End(); |
| 9092 } | 9117 } |
| 9093 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 9118 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
| 9094 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 9119 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
| 9095 if (!ast_context()->IsEffect()) Drop(1); | 9120 if (!ast_context()->IsEffect()) Drop(1); |
| 9096 ast_context()->ReturnValue(result); | 9121 ast_context()->ReturnValue(result); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9140 } | 9165 } |
| 9141 return false; | 9166 return false; |
| 9142 } | 9167 } |
| 9143 | 9168 |
| 9144 | 9169 |
| 9145 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, | 9170 bool HOptimizedGraphBuilder::TryInlineApiFunctionCall(Call* expr, |
| 9146 HValue* receiver) { | 9171 HValue* receiver) { |
| 9147 Handle<JSFunction> function = expr->target(); | 9172 Handle<JSFunction> function = expr->target(); |
| 9148 int argc = expr->arguments()->length(); | 9173 int argc = expr->arguments()->length(); |
| 9149 SmallMapList receiver_maps; | 9174 SmallMapList receiver_maps; |
| 9150 return TryInlineApiCall(function, | 9175 return TryInlineApiCall(function, receiver, &receiver_maps, argc, expr->id(), |
| 9151 receiver, | 9176 kCallApiFunction, expr->tail_call_mode()); |
| 9152 &receiver_maps, | |
| 9153 argc, | |
| 9154 expr->id(), | |
| 9155 kCallApiFunction); | |
| 9156 } | 9177 } |
| 9157 | 9178 |
| 9158 | 9179 |
| 9159 bool HOptimizedGraphBuilder::TryInlineApiMethodCall( | 9180 bool HOptimizedGraphBuilder::TryInlineApiMethodCall( |
| 9160 Call* expr, | 9181 Call* expr, |
| 9161 HValue* receiver, | 9182 HValue* receiver, |
| 9162 SmallMapList* receiver_maps) { | 9183 SmallMapList* receiver_maps) { |
| 9163 Handle<JSFunction> function = expr->target(); | 9184 Handle<JSFunction> function = expr->target(); |
| 9164 int argc = expr->arguments()->length(); | 9185 int argc = expr->arguments()->length(); |
| 9165 return TryInlineApiCall(function, | 9186 return TryInlineApiCall(function, receiver, receiver_maps, argc, expr->id(), |
| 9166 receiver, | 9187 kCallApiMethod, expr->tail_call_mode()); |
| 9167 receiver_maps, | |
| 9168 argc, | |
| 9169 expr->id(), | |
| 9170 kCallApiMethod); | |
| 9171 } | 9188 } |
| 9172 | 9189 |
| 9173 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function, | 9190 bool HOptimizedGraphBuilder::TryInlineApiGetter(Handle<Object> function, |
| 9174 Handle<Map> receiver_map, | 9191 Handle<Map> receiver_map, |
| 9175 BailoutId ast_id) { | 9192 BailoutId ast_id) { |
| 9176 SmallMapList receiver_maps(1, zone()); | 9193 SmallMapList receiver_maps(1, zone()); |
| 9177 receiver_maps.Add(receiver_map, zone()); | 9194 receiver_maps.Add(receiver_map, zone()); |
| 9178 return TryInlineApiCall(function, | 9195 return TryInlineApiCall(function, |
| 9179 NULL, // Receiver is on expression stack. | 9196 NULL, // Receiver is on expression stack. |
| 9180 &receiver_maps, | 9197 &receiver_maps, 0, ast_id, kCallApiGetter, |
| 9181 0, | 9198 TailCallMode::kDisallow); |
| 9182 ast_id, | |
| 9183 kCallApiGetter); | |
| 9184 } | 9199 } |
| 9185 | 9200 |
| 9186 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function, | 9201 bool HOptimizedGraphBuilder::TryInlineApiSetter(Handle<Object> function, |
| 9187 Handle<Map> receiver_map, | 9202 Handle<Map> receiver_map, |
| 9188 BailoutId ast_id) { | 9203 BailoutId ast_id) { |
| 9189 SmallMapList receiver_maps(1, zone()); | 9204 SmallMapList receiver_maps(1, zone()); |
| 9190 receiver_maps.Add(receiver_map, zone()); | 9205 receiver_maps.Add(receiver_map, zone()); |
| 9191 return TryInlineApiCall(function, | 9206 return TryInlineApiCall(function, |
| 9192 NULL, // Receiver is on expression stack. | 9207 NULL, // Receiver is on expression stack. |
| 9193 &receiver_maps, | 9208 &receiver_maps, 1, ast_id, kCallApiSetter, |
| 9194 1, | 9209 TailCallMode::kDisallow); |
| 9195 ast_id, | |
| 9196 kCallApiSetter); | |
| 9197 } | 9210 } |
| 9198 | 9211 |
| 9199 bool HOptimizedGraphBuilder::TryInlineApiCall(Handle<Object> function, | 9212 bool HOptimizedGraphBuilder::TryInlineApiCall( |
| 9200 HValue* receiver, | 9213 Handle<Object> function, HValue* receiver, SmallMapList* receiver_maps, |
| 9201 SmallMapList* receiver_maps, | 9214 int argc, BailoutId ast_id, ApiCallType call_type, |
| 9202 int argc, BailoutId ast_id, | 9215 TailCallMode syntactic_tail_call_mode) { |
| 9203 ApiCallType call_type) { | |
| 9204 if (function->IsJSFunction() && | 9216 if (function->IsJSFunction() && |
| 9205 Handle<JSFunction>::cast(function)->context()->native_context() != | 9217 Handle<JSFunction>::cast(function)->context()->native_context() != |
| 9206 top_info()->closure()->context()->native_context()) { | 9218 top_info()->closure()->context()->native_context()) { |
| 9207 return false; | 9219 return false; |
| 9208 } | 9220 } |
| 9221 if (syntactic_tail_call_mode == TailCallMode::kAllow) { |
| 9222 return false; |
| 9223 } |
| 9209 CallOptimization optimization(function); | 9224 CallOptimization optimization(function); |
| 9210 if (!optimization.is_simple_api_call()) return false; | 9225 if (!optimization.is_simple_api_call()) return false; |
| 9211 Handle<Map> holder_map; | 9226 Handle<Map> holder_map; |
| 9212 for (int i = 0; i < receiver_maps->length(); ++i) { | 9227 for (int i = 0; i < receiver_maps->length(); ++i) { |
| 9213 auto map = receiver_maps->at(i); | 9228 auto map = receiver_maps->at(i); |
| 9214 // Don't inline calls to receivers requiring accesschecks. | 9229 // Don't inline calls to receivers requiring accesschecks. |
| 9215 if (map->is_access_check_needed()) return false; | 9230 if (map->is_access_check_needed()) return false; |
| 9216 } | 9231 } |
| 9217 if (call_type == kCallApiFunction) { | 9232 if (call_type == kCallApiFunction) { |
| 9218 // Cannot embed a direct reference to the global proxy map | 9233 // Cannot embed a direct reference to the global proxy map |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9352 PrintF("\n"); | 9367 PrintF("\n"); |
| 9353 } | 9368 } |
| 9354 return; | 9369 return; |
| 9355 } | 9370 } |
| 9356 | 9371 |
| 9357 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) { | 9372 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) { |
| 9358 return; | 9373 return; |
| 9359 } | 9374 } |
| 9360 } | 9375 } |
| 9361 | 9376 |
| 9377 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
| 9378 TailCallMode tail_call_mode = |
| 9379 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
| 9380 USE(tail_call_mode); |
| 9381 |
| 9382 // TODO(ishell): use tail_call_mode here. |
| 9362 PushArgumentsFromEnvironment(arguments_count); | 9383 PushArgumentsFromEnvironment(arguments_count); |
| 9363 HInvokeFunction* call = | 9384 HInvokeFunction* call = |
| 9364 New<HInvokeFunction>(function, known_function, arguments_count); | 9385 New<HInvokeFunction>(function, known_function, arguments_count); |
| 9365 Drop(1); // Function | 9386 Drop(1); // Function |
| 9366 ast_context()->ReturnInstruction(call, expr->id()); | 9387 ast_context()->ReturnInstruction(call, expr->id()); |
| 9367 } | 9388 } |
| 9368 | 9389 |
| 9369 | 9390 |
| 9370 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { | 9391 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { |
| 9371 DCHECK(expr->expression()->IsProperty()); | 9392 DCHECK(expr->expression()->IsProperty()); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9406 ZoneList<Expression*>* args = expr->arguments(); | 9427 ZoneList<Expression*>* args = expr->arguments(); |
| 9407 CHECK_ALIVE(VisitForValue(args->at(0))); | 9428 CHECK_ALIVE(VisitForValue(args->at(0))); |
| 9408 HValue* receiver = Pop(); // receiver | 9429 HValue* receiver = Pop(); // receiver |
| 9409 HValue* function = Pop(); // f | 9430 HValue* function = Pop(); // f |
| 9410 Drop(1); // apply | 9431 Drop(1); // apply |
| 9411 | 9432 |
| 9412 Handle<Map> function_map = expr->GetReceiverTypes()->first(); | 9433 Handle<Map> function_map = expr->GetReceiverTypes()->first(); |
| 9413 HValue* checked_function = AddCheckMap(function, function_map); | 9434 HValue* checked_function = AddCheckMap(function, function_map); |
| 9414 | 9435 |
| 9415 if (function_state()->outer() == NULL) { | 9436 if (function_state()->outer() == NULL) { |
| 9437 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
| 9438 TailCallMode tail_call_mode = |
| 9439 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
| 9440 USE(tail_call_mode); |
| 9441 |
| 9442 // TODO(ishell): use tail_call_mode here. |
| 9416 HInstruction* elements = Add<HArgumentsElements>(false); | 9443 HInstruction* elements = Add<HArgumentsElements>(false); |
| 9417 HInstruction* length = Add<HArgumentsLength>(elements); | 9444 HInstruction* length = Add<HArgumentsLength>(elements); |
| 9418 HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function); | 9445 HValue* wrapped_receiver = BuildWrapReceiver(receiver, checked_function); |
| 9419 HInstruction* result = New<HApplyArguments>(function, | 9446 HInstruction* result = New<HApplyArguments>(function, |
| 9420 wrapped_receiver, | 9447 wrapped_receiver, |
| 9421 length, | 9448 length, |
| 9422 elements); | 9449 elements); |
| 9423 ast_context()->ReturnInstruction(result, expr->id()); | 9450 ast_context()->ReturnInstruction(result, expr->id()); |
| 9424 } else { | 9451 } else { |
| 9425 // We are inside inlined function and we know exactly what is inside | 9452 // We are inside inlined function and we know exactly what is inside |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9691 return Bailout(kTailCall); | 9718 return Bailout(kTailCall); |
| 9692 } | 9719 } |
| 9693 DCHECK(!HasStackOverflow()); | 9720 DCHECK(!HasStackOverflow()); |
| 9694 DCHECK(current_block() != NULL); | 9721 DCHECK(current_block() != NULL); |
| 9695 DCHECK(current_block()->HasPredecessor()); | 9722 DCHECK(current_block()->HasPredecessor()); |
| 9696 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); | 9723 if (!top_info()->is_tracking_positions()) SetSourcePosition(expr->position()); |
| 9697 Expression* callee = expr->expression(); | 9724 Expression* callee = expr->expression(); |
| 9698 int argument_count = expr->arguments()->length() + 1; // Plus receiver. | 9725 int argument_count = expr->arguments()->length() + 1; // Plus receiver. |
| 9699 HInstruction* call = NULL; | 9726 HInstruction* call = NULL; |
| 9700 | 9727 |
| 9728 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
| 9729 TailCallMode tail_call_mode = |
| 9730 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
| 9731 |
| 9701 Property* prop = callee->AsProperty(); | 9732 Property* prop = callee->AsProperty(); |
| 9702 if (prop != NULL) { | 9733 if (prop != NULL) { |
| 9703 CHECK_ALIVE(VisitForValue(prop->obj())); | 9734 CHECK_ALIVE(VisitForValue(prop->obj())); |
| 9704 HValue* receiver = Top(); | 9735 HValue* receiver = Top(); |
| 9705 | 9736 |
| 9706 SmallMapList* maps; | 9737 SmallMapList* maps; |
| 9707 ComputeReceiverTypes(expr, receiver, &maps, this); | 9738 ComputeReceiverTypes(expr, receiver, &maps, this); |
| 9708 | 9739 |
| 9709 if (prop->key()->IsPropertyName() && maps->length() > 0) { | 9740 if (prop->key()->IsPropertyName() && maps->length() > 0) { |
| 9710 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); | 9741 Handle<String> name = prop->key()->AsLiteral()->AsPropertyName(); |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9749 if (TryInlineApiMethodCall(expr, receiver, maps)) return; | 9780 if (TryInlineApiMethodCall(expr, receiver, maps)) return; |
| 9750 | 9781 |
| 9751 // Wrap the receiver if necessary. | 9782 // Wrap the receiver if necessary. |
| 9752 if (NeedsWrapping(maps->first(), known_function)) { | 9783 if (NeedsWrapping(maps->first(), known_function)) { |
| 9753 // Since HWrapReceiver currently cannot actually wrap numbers and | 9784 // Since HWrapReceiver currently cannot actually wrap numbers and |
| 9754 // strings, use the regular call builtin for method calls to wrap | 9785 // strings, use the regular call builtin for method calls to wrap |
| 9755 // the receiver. | 9786 // the receiver. |
| 9756 // TODO(verwaest): Support creation of value wrappers directly in | 9787 // TODO(verwaest): Support creation of value wrappers directly in |
| 9757 // HWrapReceiver. | 9788 // HWrapReceiver. |
| 9758 call = NewCallFunction(function, argument_count, | 9789 call = NewCallFunction(function, argument_count, |
| 9759 ConvertReceiverMode::kNotNullOrUndefined); | 9790 ConvertReceiverMode::kNotNullOrUndefined, |
| 9791 tail_call_mode); |
| 9760 } else if (TryInlineCall(expr)) { | 9792 } else if (TryInlineCall(expr)) { |
| 9761 return; | 9793 return; |
| 9762 } else { | 9794 } else { |
| 9763 call = NewCallConstantFunction(known_function, argument_count); | 9795 call = NewCallConstantFunction(known_function, argument_count, |
| 9796 tail_call_mode); |
| 9764 } | 9797 } |
| 9765 | 9798 |
| 9766 } else { | 9799 } else { |
| 9767 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9800 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
| 9768 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9801 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
| 9769 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9802 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
| 9770 // gets ignored by the always-opt flag, which leads to incorrect code. | 9803 // gets ignored by the always-opt flag, which leads to incorrect code. |
| 9771 Add<HDeoptimize>( | 9804 Add<HDeoptimize>( |
| 9772 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, | 9805 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
| 9773 Deoptimizer::EAGER); | 9806 Deoptimizer::EAGER); |
| 9774 arguments_flag = ARGUMENTS_FAKED; | 9807 arguments_flag = ARGUMENTS_FAKED; |
| 9775 } | 9808 } |
| 9776 | 9809 |
| 9777 // Push the function under the receiver. | 9810 // Push the function under the receiver. |
| 9778 environment()->SetExpressionStackAt(0, function); | 9811 environment()->SetExpressionStackAt(0, function); |
| 9779 Push(receiver); | 9812 Push(receiver); |
| 9780 | 9813 |
| 9781 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9814 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
| 9782 call = NewCallFunction(function, argument_count, | 9815 call = NewCallFunction(function, argument_count, |
| 9783 ConvertReceiverMode::kNotNullOrUndefined); | 9816 ConvertReceiverMode::kNotNullOrUndefined, |
| 9817 tail_call_mode); |
| 9784 } | 9818 } |
| 9785 PushArgumentsFromEnvironment(argument_count); | 9819 PushArgumentsFromEnvironment(argument_count); |
| 9786 | 9820 |
| 9787 } else { | 9821 } else { |
| 9788 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9822 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
| 9789 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 9823 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
| 9790 return Bailout(kPossibleDirectCallToEval); | 9824 return Bailout(kPossibleDirectCallToEval); |
| 9791 } | 9825 } |
| 9792 | 9826 |
| 9793 // The function is on the stack in the unoptimized code during | 9827 // The function is on the stack in the unoptimized code during |
| (...skipping 26 matching lines...) Expand all Loading... |
| 9820 expr->target()->ShortPrint(); | 9854 expr->target()->ShortPrint(); |
| 9821 PrintF("\n"); | 9855 PrintF("\n"); |
| 9822 } | 9856 } |
| 9823 return; | 9857 return; |
| 9824 } | 9858 } |
| 9825 if (TryInlineApiFunctionCall(expr, receiver)) return; | 9859 if (TryInlineApiFunctionCall(expr, receiver)) return; |
| 9826 if (TryHandleArrayCall(expr, function)) return; | 9860 if (TryHandleArrayCall(expr, function)) return; |
| 9827 if (TryInlineCall(expr)) return; | 9861 if (TryInlineCall(expr)) return; |
| 9828 | 9862 |
| 9829 PushArgumentsFromEnvironment(argument_count); | 9863 PushArgumentsFromEnvironment(argument_count); |
| 9830 call = NewCallConstantFunction(expr->target(), argument_count); | 9864 call = NewCallConstantFunction(expr->target(), argument_count, |
| 9865 tail_call_mode); |
| 9831 } else { | 9866 } else { |
| 9832 PushArgumentsFromEnvironment(argument_count); | 9867 PushArgumentsFromEnvironment(argument_count); |
| 9833 if (expr->is_uninitialized() && | 9868 if (expr->is_uninitialized() && |
| 9834 expr->IsUsingCallFeedbackICSlot(isolate())) { | 9869 expr->IsUsingCallFeedbackICSlot(isolate())) { |
| 9835 // We've never seen this call before, so let's have Crankshaft learn | 9870 // We've never seen this call before, so let's have Crankshaft learn |
| 9836 // through the type vector. | 9871 // through the type vector. |
| 9837 call = NewCallFunctionViaIC(function, argument_count, | 9872 call = NewCallFunctionViaIC(function, argument_count, |
| 9838 ConvertReceiverMode::kNullOrUndefined, | 9873 ConvertReceiverMode::kNullOrUndefined, |
| 9839 expr->CallFeedbackICSlot()); | 9874 tail_call_mode, expr->CallFeedbackICSlot()); |
| 9840 } else { | 9875 } else { |
| 9841 call = NewCallFunction(function, argument_count, | 9876 call = NewCallFunction(function, argument_count, |
| 9842 ConvertReceiverMode::kNullOrUndefined); | 9877 ConvertReceiverMode::kNullOrUndefined, |
| 9878 tail_call_mode); |
| 9843 } | 9879 } |
| 9844 } | 9880 } |
| 9845 } | 9881 } |
| 9846 | 9882 |
| 9847 Drop(1); // Drop the function. | 9883 Drop(1); // Drop the function. |
| 9848 return ast_context()->ReturnInstruction(call, expr->id()); | 9884 return ast_context()->ReturnInstruction(call, expr->id()); |
| 9849 } | 9885 } |
| 9850 | 9886 |
| 9851 | 9887 |
| 9852 void HOptimizedGraphBuilder::BuildInlinedCallArray( | 9888 void HOptimizedGraphBuilder::BuildInlinedCallArray( |
| (...skipping 3617 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13470 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13506 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
| 13471 } | 13507 } |
| 13472 | 13508 |
| 13473 #ifdef DEBUG | 13509 #ifdef DEBUG |
| 13474 graph_->Verify(false); // No full verify. | 13510 graph_->Verify(false); // No full verify. |
| 13475 #endif | 13511 #endif |
| 13476 } | 13512 } |
| 13477 | 13513 |
| 13478 } // namespace internal | 13514 } // namespace internal |
| 13479 } // namespace v8 | 13515 } // namespace v8 |
| OLD | NEW |