Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(207)

Side by Side Diff: src/crankshaft/hydrogen.cc

Issue 1761023003: [crankshaft] Correctly propagate TailCallMode in case of inlining. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/crankshaft/hydrogen.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698