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 5491 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5502 // Use the fast case closure allocation code that allocates in new | 5502 // Use the fast case closure allocation code that allocates in new |
5503 // space for nested functions that don't need literals cloning. | 5503 // space for nested functions that don't need literals cloning. |
5504 HConstant* shared_info_value = Add<HConstant>(shared_info); | 5504 HConstant* shared_info_value = Add<HConstant>(shared_info); |
5505 HInstruction* instr; | 5505 HInstruction* instr; |
5506 if (!expr->pretenure() && shared_info->num_literals() == 0) { | 5506 if (!expr->pretenure() && shared_info->num_literals() == 0) { |
5507 FastNewClosureStub stub(isolate(), shared_info->language_mode(), | 5507 FastNewClosureStub stub(isolate(), shared_info->language_mode(), |
5508 shared_info->kind()); | 5508 shared_info->kind()); |
5509 FastNewClosureDescriptor descriptor(isolate()); | 5509 FastNewClosureDescriptor descriptor(isolate()); |
5510 HValue* values[] = {context(), shared_info_value}; | 5510 HValue* values[] = {context(), shared_info_value}; |
5511 HConstant* stub_value = Add<HConstant>(stub.GetCode()); | 5511 HConstant* stub_value = Add<HConstant>(stub.GetCode()); |
5512 instr = New<HCallWithDescriptor>(stub_value, 0, descriptor, | 5512 instr = New<HCallWithDescriptor>( |
5513 Vector<HValue*>(values, arraysize(values)), | 5513 stub_value, 0, descriptor, Vector<HValue*>(values, arraysize(values))); |
5514 NORMAL_CALL); | |
5515 } else { | 5514 } else { |
5516 Add<HPushArguments>(shared_info_value); | 5515 Add<HPushArguments>(shared_info_value); |
5517 Runtime::FunctionId function_id = | 5516 Runtime::FunctionId function_id = |
5518 expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure; | 5517 expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure; |
5519 instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1); | 5518 instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1); |
5520 } | 5519 } |
5521 return ast_context()->ReturnInstruction(instr, expr->id()); | 5520 return ast_context()->ReturnInstruction(instr, expr->id()); |
5522 } | 5521 } |
5523 | 5522 |
5524 | 5523 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5785 | 5784 |
5786 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 5785 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
5787 DCHECK(!HasStackOverflow()); | 5786 DCHECK(!HasStackOverflow()); |
5788 DCHECK(current_block() != NULL); | 5787 DCHECK(current_block() != NULL); |
5789 DCHECK(current_block()->HasPredecessor()); | 5788 DCHECK(current_block()->HasPredecessor()); |
5790 Callable callable = CodeFactory::FastCloneRegExp(isolate()); | 5789 Callable callable = CodeFactory::FastCloneRegExp(isolate()); |
5791 HValue* values[] = { | 5790 HValue* values[] = { |
5792 context(), AddThisFunction(), Add<HConstant>(expr->literal_index()), | 5791 context(), AddThisFunction(), Add<HConstant>(expr->literal_index()), |
5793 Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())}; | 5792 Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())}; |
5794 HConstant* stub_value = Add<HConstant>(callable.code()); | 5793 HConstant* stub_value = Add<HConstant>(callable.code()); |
5795 HInstruction* instr = New<HCallWithDescriptor>( | 5794 HInstruction* instr = |
5796 stub_value, 0, callable.descriptor(), | 5795 New<HCallWithDescriptor>(stub_value, 0, callable.descriptor(), |
5797 Vector<HValue*>(values, arraysize(values)), NORMAL_CALL); | 5796 Vector<HValue*>(values, arraysize(values))); |
5798 return ast_context()->ReturnInstruction(instr, expr->id()); | 5797 return ast_context()->ReturnInstruction(instr, expr->id()); |
5799 } | 5798 } |
5800 | 5799 |
5801 | 5800 |
5802 static bool CanInlinePropertyAccess(Handle<Map> map) { | 5801 static bool CanInlinePropertyAccess(Handle<Map> map) { |
5803 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; | 5802 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; |
5804 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; | 5803 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
5805 return map->IsJSObjectMap() && !map->is_dictionary_map() && | 5804 return map->IsJSObjectMap() && !map->is_dictionary_map() && |
5806 !map->has_named_interceptor() && | 5805 !map->has_named_interceptor() && |
5807 // TODO(verwaest): Whitelist contexts to which we have access. | 5806 // TODO(verwaest): Whitelist contexts to which we have access. |
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6578 int argument_count = 1; | 6577 int argument_count = 1; |
6579 if (!info->IsLoad()) { | 6578 if (!info->IsLoad()) { |
6580 argument_count = 2; | 6579 argument_count = 2; |
6581 Push(value); | 6580 Push(value); |
6582 } | 6581 } |
6583 | 6582 |
6584 if (info->accessor()->IsJSFunction() && | 6583 if (info->accessor()->IsJSFunction() && |
6585 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { | 6584 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { |
6586 HValue* function = Add<HConstant>(info->accessor()); | 6585 HValue* function = Add<HConstant>(info->accessor()); |
6587 PushArgumentsFromEnvironment(argument_count); | 6586 PushArgumentsFromEnvironment(argument_count); |
6588 return NewCallFunction(function, argument_count, | 6587 return NewCallFunction(function, argument_count, TailCallMode::kDisallow, |
6589 ConvertReceiverMode::kNotNullOrUndefined, | 6588 ConvertReceiverMode::kNotNullOrUndefined, |
6590 TailCallMode::kDisallow); | 6589 TailCallMode::kDisallow); |
6591 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6590 } else if (FLAG_inline_accessors && can_inline_accessor) { |
6592 bool success = info->IsLoad() | 6591 bool success = info->IsLoad() |
6593 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6592 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
6594 : TryInlineSetter( | 6593 : TryInlineSetter( |
6595 info->accessor(), info->map(), ast_id, return_id, value); | 6594 info->accessor(), info->map(), ast_id, return_id, value); |
6596 if (success || HasStackOverflow()) return NULL; | 6595 if (success || HasStackOverflow()) return NULL; |
6597 } | 6596 } |
6598 | 6597 |
6599 PushArgumentsFromEnvironment(argument_count); | 6598 PushArgumentsFromEnvironment(argument_count); |
6600 if (!info->accessor()->IsJSFunction()) { | 6599 if (!info->accessor()->IsJSFunction()) { |
6601 Bailout(kInliningBailedOut); | 6600 Bailout(kInliningBailedOut); |
6602 return nullptr; | 6601 return nullptr; |
6603 } | 6602 } |
6604 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), | 6603 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), |
6605 argument_count, TailCallMode::kDisallow); | 6604 argument_count, TailCallMode::kDisallow, |
| 6605 TailCallMode::kDisallow); |
6606 } | 6606 } |
6607 | 6607 |
6608 DCHECK(info->IsDataConstant()); | 6608 DCHECK(info->IsDataConstant()); |
6609 if (info->IsLoad()) { | 6609 if (info->IsLoad()) { |
6610 return New<HConstant>(info->constant()); | 6610 return New<HConstant>(info->constant()); |
6611 } else { | 6611 } else { |
6612 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6612 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6613 } | 6613 } |
6614 } | 6614 } |
6615 | 6615 |
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7994 | 7994 |
7995 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7995 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
7996 Handle<Map> receiver_map) { | 7996 Handle<Map> receiver_map) { |
7997 if (!holder.is_null()) { | 7997 if (!holder.is_null()) { |
7998 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7998 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
7999 BuildCheckPrototypeMaps(prototype, holder); | 7999 BuildCheckPrototypeMaps(prototype, holder); |
8000 } | 8000 } |
8001 } | 8001 } |
8002 | 8002 |
8003 HInstruction* HOptimizedGraphBuilder::NewCallFunction( | 8003 HInstruction* HOptimizedGraphBuilder::NewCallFunction( |
8004 HValue* function, int argument_count, ConvertReceiverMode convert_mode, | 8004 HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode, |
8005 TailCallMode tail_call_mode) { | 8005 ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) { |
8006 HValue* arity = Add<HConstant>(argument_count - 1); | 8006 HValue* arity = Add<HConstant>(argument_count - 1); |
8007 | 8007 |
8008 HValue* op_vals[] = {context(), function, arity}; | 8008 HValue* op_vals[] = {context(), function, arity}; |
8009 | 8009 |
8010 Callable callable = | 8010 Callable callable = |
8011 CodeFactory::Call(isolate(), convert_mode, tail_call_mode); | 8011 CodeFactory::Call(isolate(), convert_mode, tail_call_mode); |
8012 HConstant* stub = Add<HConstant>(callable.code()); | 8012 HConstant* stub = Add<HConstant>(callable.code()); |
8013 | 8013 |
8014 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8014 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
8015 Vector<HValue*>(op_vals, arraysize(op_vals))); | 8015 Vector<HValue*>(op_vals, arraysize(op_vals)), |
| 8016 syntactic_tail_call_mode); |
8016 } | 8017 } |
8017 | 8018 |
8018 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC( | 8019 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC( |
8019 HValue* function, int argument_count, ConvertReceiverMode convert_mode, | 8020 HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode, |
8020 TailCallMode tail_call_mode, FeedbackVectorSlot slot) { | 8021 ConvertReceiverMode convert_mode, TailCallMode tail_call_mode, |
| 8022 FeedbackVectorSlot slot) { |
8021 int arity = argument_count - 1; | 8023 int arity = argument_count - 1; |
8022 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 8024 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
8023 HValue* index_val = Add<HConstant>(vector->GetIndex(slot)); | 8025 HValue* index_val = Add<HConstant>(vector->GetIndex(slot)); |
8024 HValue* vector_val = Add<HConstant>(vector); | 8026 HValue* vector_val = Add<HConstant>(vector); |
8025 | 8027 |
8026 HValue* op_vals[] = {context(), function, index_val, vector_val}; | 8028 HValue* op_vals[] = {context(), function, index_val, vector_val}; |
8027 | 8029 |
8028 Callable callable = CodeFactory::CallICInOptimizedCode( | 8030 Callable callable = CodeFactory::CallICInOptimizedCode( |
8029 isolate(), arity, ConvertReceiverMode::kNullOrUndefined, tail_call_mode); | 8031 isolate(), arity, ConvertReceiverMode::kNullOrUndefined, tail_call_mode); |
8030 HConstant* stub = Add<HConstant>(callable.code()); | 8032 HConstant* stub = Add<HConstant>(callable.code()); |
8031 | 8033 |
8032 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8034 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
8033 Vector<HValue*>(op_vals, arraysize(op_vals))); | 8035 Vector<HValue*>(op_vals, arraysize(op_vals)), |
| 8036 syntactic_tail_call_mode); |
8034 } | 8037 } |
8035 | 8038 |
8036 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( | 8039 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( |
8037 Handle<JSFunction> function, int argument_count, | 8040 Handle<JSFunction> function, int argument_count, |
8038 TailCallMode tail_call_mode) { | 8041 TailCallMode syntactic_tail_call_mode, TailCallMode tail_call_mode) { |
8039 HValue* target = Add<HConstant>(function); | 8042 HValue* target = Add<HConstant>(function); |
8040 return New<HInvokeFunction>(target, function, argument_count, tail_call_mode); | 8043 return New<HInvokeFunction>(target, function, argument_count, |
| 8044 syntactic_tail_call_mode, tail_call_mode); |
8041 } | 8045 } |
8042 | 8046 |
8043 | 8047 |
8044 class FunctionSorter { | 8048 class FunctionSorter { |
8045 public: | 8049 public: |
8046 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) | 8050 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) |
8047 : index_(index), ticks_(ticks), size_(size) {} | 8051 : index_(index), ticks_(ticks), size_(size) {} |
8048 | 8052 |
8049 int index() const { return index_; } | 8053 int index() const { return index_; } |
8050 int ticks() const { return ticks_; } | 8054 int ticks() const { return ticks_; } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8181 // Trying to inline will signal that we should bailout from the | 8185 // Trying to inline will signal that we should bailout from the |
8182 // entire compilation by setting stack overflow on the visitor. | 8186 // entire compilation by setting stack overflow on the visitor. |
8183 if (HasStackOverflow()) return; | 8187 if (HasStackOverflow()) return; |
8184 } else { | 8188 } else { |
8185 // Since HWrapReceiver currently cannot actually wrap numbers and strings, | 8189 // Since HWrapReceiver currently cannot actually wrap numbers and strings, |
8186 // use the regular call builtin for method calls to wrap the receiver. | 8190 // use the regular call builtin for method calls to wrap the receiver. |
8187 // TODO(verwaest): Support creation of value wrappers directly in | 8191 // TODO(verwaest): Support creation of value wrappers directly in |
8188 // HWrapReceiver. | 8192 // HWrapReceiver. |
8189 HInstruction* call = | 8193 HInstruction* call = |
8190 needs_wrapping | 8194 needs_wrapping |
8191 ? NewCallFunction(function, argument_count, | 8195 ? NewCallFunction( |
8192 ConvertReceiverMode::kNotNullOrUndefined, | 8196 function, argument_count, syntactic_tail_call_mode, |
8193 tail_call_mode) | 8197 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode) |
8194 : NewCallConstantFunction(target, argument_count, tail_call_mode); | 8198 : NewCallConstantFunction(target, argument_count, |
| 8199 syntactic_tail_call_mode, |
| 8200 tail_call_mode); |
8195 PushArgumentsFromEnvironment(argument_count); | 8201 PushArgumentsFromEnvironment(argument_count); |
8196 AddInstruction(call); | 8202 AddInstruction(call); |
8197 Drop(1); // Drop the function. | 8203 Drop(1); // Drop the function. |
8198 if (!ast_context()->IsEffect()) Push(call); | 8204 if (!ast_context()->IsEffect()) Push(call); |
8199 } | 8205 } |
8200 | 8206 |
8201 if (current_block() != NULL) Goto(join); | 8207 if (current_block() != NULL) Goto(join); |
8202 set_current_block(if_false); | 8208 set_current_block(if_false); |
8203 } | 8209 } |
8204 | 8210 |
8205 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 8211 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
8206 // know about and do not want to handle ones we've never seen. Otherwise | 8212 // know about and do not want to handle ones we've never seen. Otherwise |
8207 // use a generic IC. | 8213 // use a generic IC. |
8208 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { | 8214 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { |
8209 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); | 8215 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
8210 } else { | 8216 } else { |
8211 Property* prop = expr->expression()->AsProperty(); | 8217 Property* prop = expr->expression()->AsProperty(); |
8212 HInstruction* function = | 8218 HInstruction* function = |
8213 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, | 8219 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, |
8214 name, NULL, prop->IsUninitialized()); | 8220 name, NULL, prop->IsUninitialized()); |
8215 AddInstruction(function); | 8221 AddInstruction(function); |
8216 Push(function); | 8222 Push(function); |
8217 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 8223 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
8218 | 8224 |
8219 environment()->SetExpressionStackAt(1, function); | 8225 environment()->SetExpressionStackAt(1, function); |
8220 environment()->SetExpressionStackAt(0, receiver); | 8226 environment()->SetExpressionStackAt(0, receiver); |
8221 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8227 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
8222 | 8228 |
8223 HInstruction* call = NewCallFunction( | 8229 HInstruction* call = NewCallFunction( |
8224 function, argument_count, ConvertReceiverMode::kNotNullOrUndefined, | 8230 function, argument_count, syntactic_tail_call_mode, |
8225 tail_call_mode); | 8231 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode); |
8226 | 8232 |
8227 PushArgumentsFromEnvironment(argument_count); | 8233 PushArgumentsFromEnvironment(argument_count); |
8228 | 8234 |
8229 Drop(1); // Function. | 8235 Drop(1); // Function. |
8230 | 8236 |
8231 if (join != NULL) { | 8237 if (join != NULL) { |
8232 AddInstruction(call); | 8238 AddInstruction(call); |
8233 if (!ast_context()->IsEffect()) Push(call); | 8239 if (!ast_context()->IsEffect()) Push(call); |
8234 Goto(join); | 8240 Goto(join); |
8235 } else { | 8241 } else { |
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9110 INITIALIZING_STORE); | 9116 INITIALIZING_STORE); |
9111 | 9117 |
9112 // Remember new length. | 9118 // Remember new length. |
9113 Add<HStoreNamedField>( | 9119 Add<HStoreNamedField>( |
9114 receiver, HObjectAccess::ForArrayLength(kind), | 9120 receiver, HObjectAccess::ForArrayLength(kind), |
9115 new_length, STORE_TO_INITIALIZED_ENTRY); | 9121 new_length, STORE_TO_INITIALIZED_ENTRY); |
9116 } | 9122 } |
9117 if_inline.Else(); | 9123 if_inline.Else(); |
9118 { | 9124 { |
9119 Add<HPushArguments>(receiver); | 9125 Add<HPushArguments>(receiver); |
9120 result = AddInstruction( | 9126 result = AddInstruction(NewCallConstantFunction( |
9121 NewCallConstantFunction(function, 1, TailCallMode::kDisallow)); | 9127 function, 1, TailCallMode::kDisallow, TailCallMode::kDisallow)); |
9122 if (!ast_context()->IsEffect()) Push(result); | 9128 if (!ast_context()->IsEffect()) Push(result); |
9123 } | 9129 } |
9124 if_inline.End(); | 9130 if_inline.End(); |
9125 } | 9131 } |
9126 if_lengthiszero.End(); | 9132 if_lengthiszero.End(); |
9127 } | 9133 } |
9128 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 9134 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
9129 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 9135 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
9130 if (!ast_context()->IsEffect()) Drop(1); | 9136 if (!ast_context()->IsEffect()) Drop(1); |
9131 ast_context()->ReturnValue(result); | 9137 ast_context()->ReturnValue(result); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9375 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) { | 9381 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) { |
9376 return; | 9382 return; |
9377 } | 9383 } |
9378 } | 9384 } |
9379 | 9385 |
9380 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); | 9386 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
9381 TailCallMode tail_call_mode = | 9387 TailCallMode tail_call_mode = |
9382 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); | 9388 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
9383 | 9389 |
9384 PushArgumentsFromEnvironment(arguments_count); | 9390 PushArgumentsFromEnvironment(arguments_count); |
9385 HInvokeFunction* call = New<HInvokeFunction>(function, known_function, | 9391 HInvokeFunction* call = |
9386 arguments_count, tail_call_mode); | 9392 New<HInvokeFunction>(function, known_function, arguments_count, |
| 9393 syntactic_tail_call_mode, tail_call_mode); |
9387 Drop(1); // Function | 9394 Drop(1); // Function |
9388 ast_context()->ReturnInstruction(call, expr->id()); | 9395 ast_context()->ReturnInstruction(call, expr->id()); |
9389 } | 9396 } |
9390 | 9397 |
9391 | 9398 |
9392 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { | 9399 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { |
9393 DCHECK(expr->expression()->IsProperty()); | 9400 DCHECK(expr->expression()->IsProperty()); |
9394 | 9401 |
9395 if (!expr->IsMonomorphic()) { | 9402 if (!expr->IsMonomorphic()) { |
9396 return false; | 9403 return false; |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9773 } | 9780 } |
9774 if (TryInlineApiMethodCall(expr, receiver, maps)) return; | 9781 if (TryInlineApiMethodCall(expr, receiver, maps)) return; |
9775 | 9782 |
9776 // Wrap the receiver if necessary. | 9783 // Wrap the receiver if necessary. |
9777 if (NeedsWrapping(maps->first(), known_function)) { | 9784 if (NeedsWrapping(maps->first(), known_function)) { |
9778 // Since HWrapReceiver currently cannot actually wrap numbers and | 9785 // Since HWrapReceiver currently cannot actually wrap numbers and |
9779 // strings, use the regular call builtin for method calls to wrap | 9786 // strings, use the regular call builtin for method calls to wrap |
9780 // the receiver. | 9787 // the receiver. |
9781 // TODO(verwaest): Support creation of value wrappers directly in | 9788 // TODO(verwaest): Support creation of value wrappers directly in |
9782 // HWrapReceiver. | 9789 // HWrapReceiver. |
9783 call = NewCallFunction(function, argument_count, | 9790 call = NewCallFunction( |
9784 ConvertReceiverMode::kNotNullOrUndefined, | 9791 function, argument_count, syntactic_tail_call_mode, |
9785 tail_call_mode); | 9792 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode); |
9786 } else if (TryInlineCall(expr)) { | 9793 } else if (TryInlineCall(expr)) { |
9787 return; | 9794 return; |
9788 } else { | 9795 } else { |
9789 call = NewCallConstantFunction(known_function, argument_count, | 9796 call = |
9790 tail_call_mode); | 9797 NewCallConstantFunction(known_function, argument_count, |
| 9798 syntactic_tail_call_mode, tail_call_mode); |
9791 } | 9799 } |
9792 | 9800 |
9793 } else { | 9801 } else { |
9794 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9802 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9795 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9803 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9796 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9804 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9797 // gets ignored by the always-opt flag, which leads to incorrect code. | 9805 // gets ignored by the always-opt flag, which leads to incorrect code. |
9798 Add<HDeoptimize>( | 9806 Add<HDeoptimize>( |
9799 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, | 9807 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
9800 Deoptimizer::EAGER); | 9808 Deoptimizer::EAGER); |
9801 arguments_flag = ARGUMENTS_FAKED; | 9809 arguments_flag = ARGUMENTS_FAKED; |
9802 } | 9810 } |
9803 | 9811 |
9804 // Push the function under the receiver. | 9812 // Push the function under the receiver. |
9805 environment()->SetExpressionStackAt(0, function); | 9813 environment()->SetExpressionStackAt(0, function); |
9806 Push(receiver); | 9814 Push(receiver); |
9807 | 9815 |
9808 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9816 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9809 call = NewCallFunction(function, argument_count, | 9817 call = NewCallFunction(function, argument_count, syntactic_tail_call_mode, |
9810 ConvertReceiverMode::kNotNullOrUndefined, | 9818 ConvertReceiverMode::kNotNullOrUndefined, |
9811 tail_call_mode); | 9819 tail_call_mode); |
9812 } | 9820 } |
9813 PushArgumentsFromEnvironment(argument_count); | 9821 PushArgumentsFromEnvironment(argument_count); |
9814 | 9822 |
9815 } else { | 9823 } else { |
9816 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9824 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
9817 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 9825 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
9818 return Bailout(kPossibleDirectCallToEval); | 9826 return Bailout(kPossibleDirectCallToEval); |
9819 } | 9827 } |
(...skipping 29 matching lines...) Expand all Loading... |
9849 PrintF("\n"); | 9857 PrintF("\n"); |
9850 } | 9858 } |
9851 return; | 9859 return; |
9852 } | 9860 } |
9853 if (TryInlineApiFunctionCall(expr, receiver)) return; | 9861 if (TryInlineApiFunctionCall(expr, receiver)) return; |
9854 if (TryHandleArrayCall(expr, function)) return; | 9862 if (TryHandleArrayCall(expr, function)) return; |
9855 if (TryInlineCall(expr)) return; | 9863 if (TryInlineCall(expr)) return; |
9856 | 9864 |
9857 PushArgumentsFromEnvironment(argument_count); | 9865 PushArgumentsFromEnvironment(argument_count); |
9858 call = NewCallConstantFunction(expr->target(), argument_count, | 9866 call = NewCallConstantFunction(expr->target(), argument_count, |
9859 tail_call_mode); | 9867 syntactic_tail_call_mode, tail_call_mode); |
9860 } else { | 9868 } else { |
9861 PushArgumentsFromEnvironment(argument_count); | 9869 PushArgumentsFromEnvironment(argument_count); |
9862 if (expr->is_uninitialized() && | 9870 if (expr->is_uninitialized() && |
9863 expr->IsUsingCallFeedbackICSlot(isolate())) { | 9871 expr->IsUsingCallFeedbackICSlot(isolate())) { |
9864 // We've never seen this call before, so let's have Crankshaft learn | 9872 // We've never seen this call before, so let's have Crankshaft learn |
9865 // through the type vector. | 9873 // through the type vector. |
9866 call = NewCallFunctionViaIC(function, argument_count, | 9874 call = NewCallFunctionViaIC(function, argument_count, |
| 9875 syntactic_tail_call_mode, |
9867 ConvertReceiverMode::kNullOrUndefined, | 9876 ConvertReceiverMode::kNullOrUndefined, |
9868 tail_call_mode, expr->CallFeedbackICSlot()); | 9877 tail_call_mode, expr->CallFeedbackICSlot()); |
9869 } else { | 9878 } else { |
9870 call = NewCallFunction(function, argument_count, | 9879 call = NewCallFunction( |
9871 ConvertReceiverMode::kNullOrUndefined, | 9880 function, argument_count, syntactic_tail_call_mode, |
9872 tail_call_mode); | 9881 ConvertReceiverMode::kNullOrUndefined, tail_call_mode); |
9873 } | 9882 } |
9874 } | 9883 } |
9875 } | 9884 } |
9876 | 9885 |
9877 Drop(1); // Drop the function. | 9886 Drop(1); // Drop the function. |
9878 return ast_context()->ReturnInstruction(call, expr->id()); | 9887 return ast_context()->ReturnInstruction(call, expr->id()); |
9879 } | 9888 } |
9880 | 9889 |
9881 | 9890 |
9882 void HOptimizedGraphBuilder::BuildInlinedCallArray( | 9891 void HOptimizedGraphBuilder::BuildInlinedCallArray( |
(...skipping 3631 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13514 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13523 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13515 } | 13524 } |
13516 | 13525 |
13517 #ifdef DEBUG | 13526 #ifdef DEBUG |
13518 graph_->Verify(false); // No full verify. | 13527 graph_->Verify(false); // No full verify. |
13519 #endif | 13528 #endif |
13520 } | 13529 } |
13521 | 13530 |
13522 } // namespace internal | 13531 } // namespace internal |
13523 } // namespace v8 | 13532 } // namespace v8 |
OLD | NEW |