| 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 |