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 5495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5506 // Use the fast case closure allocation code that allocates in new | 5506 // Use the fast case closure allocation code that allocates in new |
5507 // space for nested functions that don't need literals cloning. | 5507 // space for nested functions that don't need literals cloning. |
5508 HConstant* shared_info_value = Add<HConstant>(shared_info); | 5508 HConstant* shared_info_value = Add<HConstant>(shared_info); |
5509 HInstruction* instr; | 5509 HInstruction* instr; |
5510 if (!expr->pretenure() && shared_info->num_literals() == 0) { | 5510 if (!expr->pretenure() && shared_info->num_literals() == 0) { |
5511 FastNewClosureStub stub(isolate(), shared_info->language_mode(), | 5511 FastNewClosureStub stub(isolate(), shared_info->language_mode(), |
5512 shared_info->kind()); | 5512 shared_info->kind()); |
5513 FastNewClosureDescriptor descriptor(isolate()); | 5513 FastNewClosureDescriptor descriptor(isolate()); |
5514 HValue* values[] = {context(), shared_info_value}; | 5514 HValue* values[] = {context(), shared_info_value}; |
5515 HConstant* stub_value = Add<HConstant>(stub.GetCode()); | 5515 HConstant* stub_value = Add<HConstant>(stub.GetCode()); |
5516 instr = New<HCallWithDescriptor>( | 5516 instr = New<HCallWithDescriptor>(stub_value, 0, descriptor, |
5517 stub_value, 0, descriptor, Vector<HValue*>(values, arraysize(values))); | 5517 Vector<HValue*>(values, arraysize(values)), |
| 5518 NORMAL_CALL); |
5518 } else { | 5519 } else { |
5519 Add<HPushArguments>(shared_info_value); | 5520 Add<HPushArguments>(shared_info_value); |
5520 Runtime::FunctionId function_id = | 5521 Runtime::FunctionId function_id = |
5521 expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure; | 5522 expr->pretenure() ? Runtime::kNewClosure_Tenured : Runtime::kNewClosure; |
5522 instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1); | 5523 instr = New<HCallRuntime>(Runtime::FunctionForId(function_id), 1); |
5523 } | 5524 } |
5524 return ast_context()->ReturnInstruction(instr, expr->id()); | 5525 return ast_context()->ReturnInstruction(instr, expr->id()); |
5525 } | 5526 } |
5526 | 5527 |
5527 | 5528 |
(...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5788 | 5789 |
5789 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { | 5790 void HOptimizedGraphBuilder::VisitRegExpLiteral(RegExpLiteral* expr) { |
5790 DCHECK(!HasStackOverflow()); | 5791 DCHECK(!HasStackOverflow()); |
5791 DCHECK(current_block() != NULL); | 5792 DCHECK(current_block() != NULL); |
5792 DCHECK(current_block()->HasPredecessor()); | 5793 DCHECK(current_block()->HasPredecessor()); |
5793 Callable callable = CodeFactory::FastCloneRegExp(isolate()); | 5794 Callable callable = CodeFactory::FastCloneRegExp(isolate()); |
5794 HValue* values[] = { | 5795 HValue* values[] = { |
5795 context(), AddThisFunction(), Add<HConstant>(expr->literal_index()), | 5796 context(), AddThisFunction(), Add<HConstant>(expr->literal_index()), |
5796 Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())}; | 5797 Add<HConstant>(expr->pattern()), Add<HConstant>(expr->flags())}; |
5797 HConstant* stub_value = Add<HConstant>(callable.code()); | 5798 HConstant* stub_value = Add<HConstant>(callable.code()); |
5798 HInstruction* instr = | 5799 HInstruction* instr = New<HCallWithDescriptor>( |
5799 New<HCallWithDescriptor>(stub_value, 0, callable.descriptor(), | 5800 stub_value, 0, callable.descriptor(), |
5800 Vector<HValue*>(values, arraysize(values))); | 5801 Vector<HValue*>(values, arraysize(values)), NORMAL_CALL); |
5801 return ast_context()->ReturnInstruction(instr, expr->id()); | 5802 return ast_context()->ReturnInstruction(instr, expr->id()); |
5802 } | 5803 } |
5803 | 5804 |
5804 | 5805 |
5805 static bool CanInlinePropertyAccess(Handle<Map> map) { | 5806 static bool CanInlinePropertyAccess(Handle<Map> map) { |
5806 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; | 5807 if (map->instance_type() == HEAP_NUMBER_TYPE) return true; |
5807 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; | 5808 if (map->instance_type() < FIRST_NONSTRING_TYPE) return true; |
5808 return map->IsJSObjectMap() && !map->is_dictionary_map() && | 5809 return map->IsJSObjectMap() && !map->is_dictionary_map() && |
5809 !map->has_named_interceptor() && | 5810 !map->has_named_interceptor() && |
5810 // TODO(verwaest): Whitelist contexts to which we have access. | 5811 // TODO(verwaest): Whitelist contexts to which we have access. |
(...skipping 764 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6575 int argument_count = 1; | 6576 int argument_count = 1; |
6576 if (!info->IsLoad()) { | 6577 if (!info->IsLoad()) { |
6577 argument_count = 2; | 6578 argument_count = 2; |
6578 Push(value); | 6579 Push(value); |
6579 } | 6580 } |
6580 | 6581 |
6581 if (info->accessor()->IsJSFunction() && | 6582 if (info->accessor()->IsJSFunction() && |
6582 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { | 6583 info->NeedsWrappingFor(Handle<JSFunction>::cast(info->accessor()))) { |
6583 HValue* function = Add<HConstant>(info->accessor()); | 6584 HValue* function = Add<HConstant>(info->accessor()); |
6584 PushArgumentsFromEnvironment(argument_count); | 6585 PushArgumentsFromEnvironment(argument_count); |
6585 return NewCallFunction(function, argument_count, TailCallMode::kDisallow, | 6586 return NewCallFunction(function, argument_count, |
6586 ConvertReceiverMode::kNotNullOrUndefined, | 6587 ConvertReceiverMode::kNotNullOrUndefined, |
6587 TailCallMode::kDisallow); | 6588 TailCallMode::kDisallow); |
6588 } else if (FLAG_inline_accessors && can_inline_accessor) { | 6589 } else if (FLAG_inline_accessors && can_inline_accessor) { |
6589 bool success = info->IsLoad() | 6590 bool success = info->IsLoad() |
6590 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) | 6591 ? TryInlineGetter(info->accessor(), info->map(), ast_id, return_id) |
6591 : TryInlineSetter( | 6592 : TryInlineSetter( |
6592 info->accessor(), info->map(), ast_id, return_id, value); | 6593 info->accessor(), info->map(), ast_id, return_id, value); |
6593 if (success || HasStackOverflow()) return NULL; | 6594 if (success || HasStackOverflow()) return NULL; |
6594 } | 6595 } |
6595 | 6596 |
6596 PushArgumentsFromEnvironment(argument_count); | 6597 PushArgumentsFromEnvironment(argument_count); |
6597 if (!info->accessor()->IsJSFunction()) { | 6598 if (!info->accessor()->IsJSFunction()) { |
6598 Bailout(kInliningBailedOut); | 6599 Bailout(kInliningBailedOut); |
6599 return nullptr; | 6600 return nullptr; |
6600 } | 6601 } |
6601 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), | 6602 return NewCallConstantFunction(Handle<JSFunction>::cast(info->accessor()), |
6602 argument_count, TailCallMode::kDisallow, | 6603 argument_count, TailCallMode::kDisallow); |
6603 TailCallMode::kDisallow); | |
6604 } | 6604 } |
6605 | 6605 |
6606 DCHECK(info->IsDataConstant()); | 6606 DCHECK(info->IsDataConstant()); |
6607 if (info->IsLoad()) { | 6607 if (info->IsLoad()) { |
6608 return New<HConstant>(info->constant()); | 6608 return New<HConstant>(info->constant()); |
6609 } else { | 6609 } else { |
6610 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); | 6610 return New<HCheckValue>(value, Handle<JSFunction>::cast(info->constant())); |
6611 } | 6611 } |
6612 } | 6612 } |
6613 | 6613 |
(...skipping 1378 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7992 | 7992 |
7993 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, | 7993 void HOptimizedGraphBuilder::AddCheckPrototypeMaps(Handle<JSObject> holder, |
7994 Handle<Map> receiver_map) { | 7994 Handle<Map> receiver_map) { |
7995 if (!holder.is_null()) { | 7995 if (!holder.is_null()) { |
7996 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); | 7996 Handle<JSObject> prototype(JSObject::cast(receiver_map->prototype())); |
7997 BuildCheckPrototypeMaps(prototype, holder); | 7997 BuildCheckPrototypeMaps(prototype, holder); |
7998 } | 7998 } |
7999 } | 7999 } |
8000 | 8000 |
8001 HInstruction* HOptimizedGraphBuilder::NewCallFunction( | 8001 HInstruction* HOptimizedGraphBuilder::NewCallFunction( |
8002 HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode, | 8002 HValue* function, int argument_count, ConvertReceiverMode convert_mode, |
8003 ConvertReceiverMode convert_mode, TailCallMode tail_call_mode) { | 8003 TailCallMode tail_call_mode) { |
8004 HValue* arity = Add<HConstant>(argument_count - 1); | 8004 HValue* arity = Add<HConstant>(argument_count - 1); |
8005 | 8005 |
8006 HValue* op_vals[] = {context(), function, arity}; | 8006 HValue* op_vals[] = {context(), function, arity}; |
8007 | 8007 |
8008 Callable callable = | 8008 Callable callable = |
8009 CodeFactory::Call(isolate(), convert_mode, tail_call_mode); | 8009 CodeFactory::Call(isolate(), convert_mode, tail_call_mode); |
8010 HConstant* stub = Add<HConstant>(callable.code()); | 8010 HConstant* stub = Add<HConstant>(callable.code()); |
8011 | 8011 |
8012 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8012 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
8013 Vector<HValue*>(op_vals, arraysize(op_vals)), | 8013 Vector<HValue*>(op_vals, arraysize(op_vals))); |
8014 syntactic_tail_call_mode); | |
8015 } | 8014 } |
8016 | 8015 |
8017 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC( | 8016 HInstruction* HOptimizedGraphBuilder::NewCallFunctionViaIC( |
8018 HValue* function, int argument_count, TailCallMode syntactic_tail_call_mode, | 8017 HValue* function, int argument_count, ConvertReceiverMode convert_mode, |
8019 ConvertReceiverMode convert_mode, TailCallMode tail_call_mode, | 8018 TailCallMode tail_call_mode, FeedbackVectorSlot slot) { |
8020 FeedbackVectorSlot slot) { | |
8021 int arity = argument_count - 1; | 8019 int arity = argument_count - 1; |
8022 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); | 8020 Handle<TypeFeedbackVector> vector(current_feedback_vector(), isolate()); |
8023 HValue* index_val = Add<HConstant>(vector->GetIndex(slot)); | 8021 HValue* index_val = Add<HConstant>(vector->GetIndex(slot)); |
8024 HValue* vector_val = Add<HConstant>(vector); | 8022 HValue* vector_val = Add<HConstant>(vector); |
8025 | 8023 |
8026 HValue* op_vals[] = {context(), function, index_val, vector_val}; | 8024 HValue* op_vals[] = {context(), function, index_val, vector_val}; |
8027 | 8025 |
8028 Callable callable = CodeFactory::CallICInOptimizedCode( | 8026 Callable callable = CodeFactory::CallICInOptimizedCode( |
8029 isolate(), arity, ConvertReceiverMode::kNullOrUndefined, tail_call_mode); | 8027 isolate(), arity, ConvertReceiverMode::kNullOrUndefined, tail_call_mode); |
8030 HConstant* stub = Add<HConstant>(callable.code()); | 8028 HConstant* stub = Add<HConstant>(callable.code()); |
8031 | 8029 |
8032 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), | 8030 return New<HCallWithDescriptor>(stub, argument_count, callable.descriptor(), |
8033 Vector<HValue*>(op_vals, arraysize(op_vals)), | 8031 Vector<HValue*>(op_vals, arraysize(op_vals))); |
8034 syntactic_tail_call_mode); | |
8035 } | 8032 } |
8036 | 8033 |
8037 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( | 8034 HInstruction* HOptimizedGraphBuilder::NewCallConstantFunction( |
8038 Handle<JSFunction> function, int argument_count, | 8035 Handle<JSFunction> function, int argument_count, |
8039 TailCallMode syntactic_tail_call_mode, TailCallMode tail_call_mode) { | 8036 TailCallMode tail_call_mode) { |
8040 HValue* target = Add<HConstant>(function); | 8037 HValue* target = Add<HConstant>(function); |
8041 return New<HInvokeFunction>(target, function, argument_count, | 8038 return New<HInvokeFunction>(target, function, argument_count, tail_call_mode); |
8042 syntactic_tail_call_mode, tail_call_mode); | |
8043 } | 8039 } |
8044 | 8040 |
8045 | 8041 |
8046 class FunctionSorter { | 8042 class FunctionSorter { |
8047 public: | 8043 public: |
8048 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) | 8044 explicit FunctionSorter(int index = 0, int ticks = 0, int size = 0) |
8049 : index_(index), ticks_(ticks), size_(size) {} | 8045 : index_(index), ticks_(ticks), size_(size) {} |
8050 | 8046 |
8051 int index() const { return index_; } | 8047 int index() const { return index_; } |
8052 int ticks() const { return ticks_; } | 8048 int ticks() const { return ticks_; } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8183 // Trying to inline will signal that we should bailout from the | 8179 // Trying to inline will signal that we should bailout from the |
8184 // entire compilation by setting stack overflow on the visitor. | 8180 // entire compilation by setting stack overflow on the visitor. |
8185 if (HasStackOverflow()) return; | 8181 if (HasStackOverflow()) return; |
8186 } else { | 8182 } else { |
8187 // Since HWrapReceiver currently cannot actually wrap numbers and strings, | 8183 // Since HWrapReceiver currently cannot actually wrap numbers and strings, |
8188 // use the regular call builtin for method calls to wrap the receiver. | 8184 // use the regular call builtin for method calls to wrap the receiver. |
8189 // TODO(verwaest): Support creation of value wrappers directly in | 8185 // TODO(verwaest): Support creation of value wrappers directly in |
8190 // HWrapReceiver. | 8186 // HWrapReceiver. |
8191 HInstruction* call = | 8187 HInstruction* call = |
8192 needs_wrapping | 8188 needs_wrapping |
8193 ? NewCallFunction( | 8189 ? NewCallFunction(function, argument_count, |
8194 function, argument_count, syntactic_tail_call_mode, | 8190 ConvertReceiverMode::kNotNullOrUndefined, |
8195 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode) | 8191 tail_call_mode) |
8196 : NewCallConstantFunction(target, argument_count, | 8192 : NewCallConstantFunction(target, argument_count, tail_call_mode); |
8197 syntactic_tail_call_mode, | |
8198 tail_call_mode); | |
8199 PushArgumentsFromEnvironment(argument_count); | 8193 PushArgumentsFromEnvironment(argument_count); |
8200 AddInstruction(call); | 8194 AddInstruction(call); |
8201 Drop(1); // Drop the function. | 8195 Drop(1); // Drop the function. |
8202 if (!ast_context()->IsEffect()) Push(call); | 8196 if (!ast_context()->IsEffect()) Push(call); |
8203 } | 8197 } |
8204 | 8198 |
8205 if (current_block() != NULL) Goto(join); | 8199 if (current_block() != NULL) Goto(join); |
8206 set_current_block(if_false); | 8200 set_current_block(if_false); |
8207 } | 8201 } |
8208 | 8202 |
8209 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 8203 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
8210 // know about and do not want to handle ones we've never seen. Otherwise | 8204 // know about and do not want to handle ones we've never seen. Otherwise |
8211 // use a generic IC. | 8205 // use a generic IC. |
8212 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { | 8206 if (ordered_functions == maps->length() && FLAG_deoptimize_uncommon_cases) { |
8213 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); | 8207 FinishExitWithHardDeoptimization(Deoptimizer::kUnknownMapInPolymorphicCall); |
8214 } else { | 8208 } else { |
8215 Property* prop = expr->expression()->AsProperty(); | 8209 Property* prop = expr->expression()->AsProperty(); |
8216 HInstruction* function = | 8210 HInstruction* function = |
8217 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, | 8211 BuildNamedGeneric(LOAD, prop, prop->PropertyFeedbackSlot(), receiver, |
8218 name, NULL, prop->IsUninitialized()); | 8212 name, NULL, prop->IsUninitialized()); |
8219 AddInstruction(function); | 8213 AddInstruction(function); |
8220 Push(function); | 8214 Push(function); |
8221 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); | 8215 AddSimulate(prop->LoadId(), REMOVABLE_SIMULATE); |
8222 | 8216 |
8223 environment()->SetExpressionStackAt(1, function); | 8217 environment()->SetExpressionStackAt(1, function); |
8224 environment()->SetExpressionStackAt(0, receiver); | 8218 environment()->SetExpressionStackAt(0, receiver); |
8225 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 8219 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
8226 | 8220 |
8227 HInstruction* call = NewCallFunction( | 8221 HInstruction* call = NewCallFunction( |
8228 function, argument_count, syntactic_tail_call_mode, | 8222 function, argument_count, ConvertReceiverMode::kNotNullOrUndefined, |
8229 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode); | 8223 tail_call_mode); |
8230 | 8224 |
8231 PushArgumentsFromEnvironment(argument_count); | 8225 PushArgumentsFromEnvironment(argument_count); |
8232 | 8226 |
8233 Drop(1); // Function. | 8227 Drop(1); // Function. |
8234 | 8228 |
8235 if (join != NULL) { | 8229 if (join != NULL) { |
8236 AddInstruction(call); | 8230 AddInstruction(call); |
8237 if (!ast_context()->IsEffect()) Push(call); | 8231 if (!ast_context()->IsEffect()) Push(call); |
8238 Goto(join); | 8232 Goto(join); |
8239 } else { | 8233 } else { |
(...skipping 865 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9105 INITIALIZING_STORE); | 9099 INITIALIZING_STORE); |
9106 | 9100 |
9107 // Remember new length. | 9101 // Remember new length. |
9108 Add<HStoreNamedField>( | 9102 Add<HStoreNamedField>( |
9109 receiver, HObjectAccess::ForArrayLength(kind), | 9103 receiver, HObjectAccess::ForArrayLength(kind), |
9110 new_length, STORE_TO_INITIALIZED_ENTRY); | 9104 new_length, STORE_TO_INITIALIZED_ENTRY); |
9111 } | 9105 } |
9112 if_inline.Else(); | 9106 if_inline.Else(); |
9113 { | 9107 { |
9114 Add<HPushArguments>(receiver); | 9108 Add<HPushArguments>(receiver); |
9115 result = AddInstruction(NewCallConstantFunction( | 9109 result = AddInstruction( |
9116 function, 1, TailCallMode::kDisallow, TailCallMode::kDisallow)); | 9110 NewCallConstantFunction(function, 1, TailCallMode::kDisallow)); |
9117 if (!ast_context()->IsEffect()) Push(result); | 9111 if (!ast_context()->IsEffect()) Push(result); |
9118 } | 9112 } |
9119 if_inline.End(); | 9113 if_inline.End(); |
9120 } | 9114 } |
9121 if_lengthiszero.End(); | 9115 if_lengthiszero.End(); |
9122 } | 9116 } |
9123 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); | 9117 result = ast_context()->IsEffect() ? graph()->GetConstant0() : Top(); |
9124 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 9118 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
9125 if (!ast_context()->IsEffect()) Drop(1); | 9119 if (!ast_context()->IsEffect()) Drop(1); |
9126 ast_context()->ReturnValue(result); | 9120 ast_context()->ReturnValue(result); |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9370 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) { | 9364 if (TryInlineIndirectCall(known_function, expr, args_count_no_receiver)) { |
9371 return; | 9365 return; |
9372 } | 9366 } |
9373 } | 9367 } |
9374 | 9368 |
9375 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); | 9369 TailCallMode syntactic_tail_call_mode = expr->tail_call_mode(); |
9376 TailCallMode tail_call_mode = | 9370 TailCallMode tail_call_mode = |
9377 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); | 9371 function_state()->ComputeTailCallMode(syntactic_tail_call_mode); |
9378 | 9372 |
9379 PushArgumentsFromEnvironment(arguments_count); | 9373 PushArgumentsFromEnvironment(arguments_count); |
9380 HInvokeFunction* call = | 9374 HInvokeFunction* call = New<HInvokeFunction>(function, known_function, |
9381 New<HInvokeFunction>(function, known_function, arguments_count, | 9375 arguments_count, tail_call_mode); |
9382 syntactic_tail_call_mode, tail_call_mode); | |
9383 Drop(1); // Function | 9376 Drop(1); // Function |
9384 ast_context()->ReturnInstruction(call, expr->id()); | 9377 ast_context()->ReturnInstruction(call, expr->id()); |
9385 } | 9378 } |
9386 | 9379 |
9387 | 9380 |
9388 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { | 9381 bool HOptimizedGraphBuilder::TryIndirectCall(Call* expr) { |
9389 DCHECK(expr->expression()->IsProperty()); | 9382 DCHECK(expr->expression()->IsProperty()); |
9390 | 9383 |
9391 if (!expr->IsMonomorphic()) { | 9384 if (!expr->IsMonomorphic()) { |
9392 return false; | 9385 return false; |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
9769 } | 9762 } |
9770 if (TryInlineApiMethodCall(expr, receiver, maps)) return; | 9763 if (TryInlineApiMethodCall(expr, receiver, maps)) return; |
9771 | 9764 |
9772 // Wrap the receiver if necessary. | 9765 // Wrap the receiver if necessary. |
9773 if (NeedsWrapping(maps->first(), known_function)) { | 9766 if (NeedsWrapping(maps->first(), known_function)) { |
9774 // Since HWrapReceiver currently cannot actually wrap numbers and | 9767 // Since HWrapReceiver currently cannot actually wrap numbers and |
9775 // strings, use the regular call builtin for method calls to wrap | 9768 // strings, use the regular call builtin for method calls to wrap |
9776 // the receiver. | 9769 // the receiver. |
9777 // TODO(verwaest): Support creation of value wrappers directly in | 9770 // TODO(verwaest): Support creation of value wrappers directly in |
9778 // HWrapReceiver. | 9771 // HWrapReceiver. |
9779 call = NewCallFunction( | 9772 call = NewCallFunction(function, argument_count, |
9780 function, argument_count, syntactic_tail_call_mode, | 9773 ConvertReceiverMode::kNotNullOrUndefined, |
9781 ConvertReceiverMode::kNotNullOrUndefined, tail_call_mode); | 9774 tail_call_mode); |
9782 } else if (TryInlineCall(expr)) { | 9775 } else if (TryInlineCall(expr)) { |
9783 return; | 9776 return; |
9784 } else { | 9777 } else { |
9785 call = | 9778 call = NewCallConstantFunction(known_function, argument_count, |
9786 NewCallConstantFunction(known_function, argument_count, | 9779 tail_call_mode); |
9787 syntactic_tail_call_mode, tail_call_mode); | |
9788 } | 9780 } |
9789 | 9781 |
9790 } else { | 9782 } else { |
9791 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; | 9783 ArgumentsAllowedFlag arguments_flag = ARGUMENTS_NOT_ALLOWED; |
9792 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { | 9784 if (CanBeFunctionApplyArguments(expr) && expr->is_uninitialized()) { |
9793 // We have to use EAGER deoptimization here because Deoptimizer::SOFT | 9785 // We have to use EAGER deoptimization here because Deoptimizer::SOFT |
9794 // gets ignored by the always-opt flag, which leads to incorrect code. | 9786 // gets ignored by the always-opt flag, which leads to incorrect code. |
9795 Add<HDeoptimize>( | 9787 Add<HDeoptimize>( |
9796 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, | 9788 Deoptimizer::kInsufficientTypeFeedbackForCallWithArguments, |
9797 Deoptimizer::EAGER); | 9789 Deoptimizer::EAGER); |
9798 arguments_flag = ARGUMENTS_FAKED; | 9790 arguments_flag = ARGUMENTS_FAKED; |
9799 } | 9791 } |
9800 | 9792 |
9801 // Push the function under the receiver. | 9793 // Push the function under the receiver. |
9802 environment()->SetExpressionStackAt(0, function); | 9794 environment()->SetExpressionStackAt(0, function); |
9803 Push(receiver); | 9795 Push(receiver); |
9804 | 9796 |
9805 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); | 9797 CHECK_ALIVE(VisitExpressions(expr->arguments(), arguments_flag)); |
9806 call = NewCallFunction(function, argument_count, syntactic_tail_call_mode, | 9798 call = NewCallFunction(function, argument_count, |
9807 ConvertReceiverMode::kNotNullOrUndefined, | 9799 ConvertReceiverMode::kNotNullOrUndefined, |
9808 tail_call_mode); | 9800 tail_call_mode); |
9809 } | 9801 } |
9810 PushArgumentsFromEnvironment(argument_count); | 9802 PushArgumentsFromEnvironment(argument_count); |
9811 | 9803 |
9812 } else { | 9804 } else { |
9813 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 9805 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
9814 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 9806 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
9815 return Bailout(kPossibleDirectCallToEval); | 9807 return Bailout(kPossibleDirectCallToEval); |
9816 } | 9808 } |
(...skipping 29 matching lines...) Expand all Loading... |
9846 PrintF("\n"); | 9838 PrintF("\n"); |
9847 } | 9839 } |
9848 return; | 9840 return; |
9849 } | 9841 } |
9850 if (TryInlineApiFunctionCall(expr, receiver)) return; | 9842 if (TryInlineApiFunctionCall(expr, receiver)) return; |
9851 if (TryHandleArrayCall(expr, function)) return; | 9843 if (TryHandleArrayCall(expr, function)) return; |
9852 if (TryInlineCall(expr)) return; | 9844 if (TryInlineCall(expr)) return; |
9853 | 9845 |
9854 PushArgumentsFromEnvironment(argument_count); | 9846 PushArgumentsFromEnvironment(argument_count); |
9855 call = NewCallConstantFunction(expr->target(), argument_count, | 9847 call = NewCallConstantFunction(expr->target(), argument_count, |
9856 syntactic_tail_call_mode, tail_call_mode); | 9848 tail_call_mode); |
9857 } else { | 9849 } else { |
9858 PushArgumentsFromEnvironment(argument_count); | 9850 PushArgumentsFromEnvironment(argument_count); |
9859 if (expr->is_uninitialized() && | 9851 if (expr->is_uninitialized() && |
9860 expr->IsUsingCallFeedbackICSlot(isolate())) { | 9852 expr->IsUsingCallFeedbackICSlot(isolate())) { |
9861 // We've never seen this call before, so let's have Crankshaft learn | 9853 // We've never seen this call before, so let's have Crankshaft learn |
9862 // through the type vector. | 9854 // through the type vector. |
9863 call = NewCallFunctionViaIC(function, argument_count, | 9855 call = NewCallFunctionViaIC(function, argument_count, |
9864 syntactic_tail_call_mode, | |
9865 ConvertReceiverMode::kNullOrUndefined, | 9856 ConvertReceiverMode::kNullOrUndefined, |
9866 tail_call_mode, expr->CallFeedbackICSlot()); | 9857 tail_call_mode, expr->CallFeedbackICSlot()); |
9867 } else { | 9858 } else { |
9868 call = NewCallFunction( | 9859 call = NewCallFunction(function, argument_count, |
9869 function, argument_count, syntactic_tail_call_mode, | 9860 ConvertReceiverMode::kNullOrUndefined, |
9870 ConvertReceiverMode::kNullOrUndefined, tail_call_mode); | 9861 tail_call_mode); |
9871 } | 9862 } |
9872 } | 9863 } |
9873 } | 9864 } |
9874 | 9865 |
9875 Drop(1); // Drop the function. | 9866 Drop(1); // Drop the function. |
9876 return ast_context()->ReturnInstruction(call, expr->id()); | 9867 return ast_context()->ReturnInstruction(call, expr->id()); |
9877 } | 9868 } |
9878 | 9869 |
9879 | 9870 |
9880 void HOptimizedGraphBuilder::BuildInlinedCallArray( | 9871 void HOptimizedGraphBuilder::BuildInlinedCallArray( |
(...skipping 612 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10493 // The callee and the receiver both have to be pushed onto the operand stack | 10484 // The callee and the receiver both have to be pushed onto the operand stack |
10494 // before arguments are being evaluated. | 10485 // before arguments are being evaluated. |
10495 HValue* function = AddLoadJSBuiltin(expr->context_index()); | 10486 HValue* function = AddLoadJSBuiltin(expr->context_index()); |
10496 HValue* receiver = graph()->GetConstantUndefined(); | 10487 HValue* receiver = graph()->GetConstantUndefined(); |
10497 Push(function); | 10488 Push(function); |
10498 Push(receiver); | 10489 Push(receiver); |
10499 | 10490 |
10500 int argument_count = expr->arguments()->length() + 1; // Count receiver. | 10491 int argument_count = expr->arguments()->length() + 1; // Count receiver. |
10501 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 10492 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
10502 PushArgumentsFromEnvironment(argument_count); | 10493 PushArgumentsFromEnvironment(argument_count); |
10503 HInstruction* call = NewCallFunction( | 10494 HInstruction* call = NewCallFunction(function, argument_count, |
10504 function, argument_count, TailCallMode::kDisallow, | 10495 ConvertReceiverMode::kNullOrUndefined, |
10505 ConvertReceiverMode::kNullOrUndefined, TailCallMode::kDisallow); | 10496 TailCallMode::kDisallow); |
10506 Drop(1); // Function | 10497 Drop(1); // Function |
10507 return ast_context()->ReturnInstruction(call, expr->id()); | 10498 return ast_context()->ReturnInstruction(call, expr->id()); |
10508 } | 10499 } |
10509 | 10500 |
10510 const Runtime::Function* function = expr->function(); | 10501 const Runtime::Function* function = expr->function(); |
10511 DCHECK(function != NULL); | 10502 DCHECK(function != NULL); |
10512 switch (function->function_id) { | 10503 switch (function->function_id) { |
10513 #define CALL_INTRINSIC_GENERATOR(Name) \ | 10504 #define CALL_INTRINSIC_GENERATOR(Name) \ |
10514 case Runtime::kInline##Name: \ | 10505 case Runtime::kInline##Name: \ |
10515 return Generate##Name(expr); | 10506 return Generate##Name(expr); |
(...skipping 3006 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
13522 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 13513 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
13523 } | 13514 } |
13524 | 13515 |
13525 #ifdef DEBUG | 13516 #ifdef DEBUG |
13526 graph_->Verify(false); // No full verify. | 13517 graph_->Verify(false); // No full verify. |
13527 #endif | 13518 #endif |
13528 } | 13519 } |
13529 | 13520 |
13530 } // namespace internal | 13521 } // namespace internal |
13531 } // namespace v8 | 13522 } // namespace v8 |
OLD | NEW |