OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 3932 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3943 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); | 3943 instruction->DeleteAndReplaceWith(instruction->RedefinedOperand()); |
3944 } else { | 3944 } else { |
3945 instruction->ReplaceAllUsesWith(instruction->ActualValue()); | 3945 instruction->ReplaceAllUsesWith(instruction->ActualValue()); |
3946 } | 3946 } |
3947 } | 3947 } |
3948 } | 3948 } |
3949 } | 3949 } |
3950 } | 3950 } |
3951 | 3951 |
3952 | 3952 |
3953 template <class Instruction> | 3953 void HOptimizedGraphBuilder::PushArgumentsFromEnvironment(int count) { |
3954 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { | |
3955 int count = call->argument_count(); | |
3956 ZoneList<HValue*> arguments(count, zone()); | 3954 ZoneList<HValue*> arguments(count, zone()); |
3957 for (int i = 0; i < count; ++i) { | 3955 for (int i = 0; i < count; ++i) { |
3958 arguments.Add(Pop(), zone()); | 3956 arguments.Add(Pop(), zone()); |
3959 } | 3957 } |
3960 | 3958 |
3961 while (!arguments.is_empty()) { | 3959 while (!arguments.is_empty()) { |
3962 Add<HPushArgument>(arguments.RemoveLast()); | 3960 Add<HPushArgument>(arguments.RemoveLast()); |
3963 } | 3961 } |
| 3962 } |
| 3963 |
| 3964 |
| 3965 template <class Instruction> |
| 3966 HInstruction* HOptimizedGraphBuilder::PreProcessCall(Instruction* call) { |
| 3967 PushArgumentsFromEnvironment(call->argument_count()); |
3964 return call; | 3968 return call; |
3965 } | 3969 } |
3966 | 3970 |
3967 | 3971 |
3968 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { | 3972 void HOptimizedGraphBuilder::SetUpScope(Scope* scope) { |
3969 // First special is HContext. | 3973 // First special is HContext. |
3970 HInstruction* context = Add<HContext>(); | 3974 HInstruction* context = Add<HContext>(); |
3971 environment()->BindContext(context); | 3975 environment()->BindContext(context); |
3972 | 3976 |
3973 // Create an arguments object containing the initial parameters. Set the | 3977 // Create an arguments object containing the initial parameters. Set the |
(...skipping 1551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5525 } | 5529 } |
5526 | 5530 |
5527 if (info->lookup()->IsPropertyCallbacks()) { | 5531 if (info->lookup()->IsPropertyCallbacks()) { |
5528 Push(checked_object); | 5532 Push(checked_object); |
5529 if (FLAG_inline_accessors && | 5533 if (FLAG_inline_accessors && |
5530 can_inline_accessor && | 5534 can_inline_accessor && |
5531 TryInlineGetter(info->accessor(), ast_id, return_id)) { | 5535 TryInlineGetter(info->accessor(), ast_id, return_id)) { |
5532 return NULL; | 5536 return NULL; |
5533 } | 5537 } |
5534 Add<HPushArgument>(Pop()); | 5538 Add<HPushArgument>(Pop()); |
5535 return New<HCallConstantFunction>(info->accessor(), 1); | 5539 return BuildCallConstantFunction(info->accessor(), 1); |
5536 } | 5540 } |
5537 | 5541 |
5538 ASSERT(info->lookup()->IsConstant()); | 5542 ASSERT(info->lookup()->IsConstant()); |
5539 return New<HConstant>(info->constant()); | 5543 return New<HConstant>(info->constant()); |
5540 } | 5544 } |
5541 | 5545 |
5542 | 5546 |
5543 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( | 5547 void HOptimizedGraphBuilder::HandlePolymorphicLoadNamedField( |
5544 BailoutId ast_id, | 5548 BailoutId ast_id, |
5545 BailoutId return_id, | 5549 BailoutId return_id, |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5810 Handle<JSObject> holder; | 5814 Handle<JSObject> holder; |
5811 if (LookupSetter(map, name, &setter, &holder)) { | 5815 if (LookupSetter(map, name, &setter, &holder)) { |
5812 AddCheckConstantFunction(holder, object, map); | 5816 AddCheckConstantFunction(holder, object, map); |
5813 if (FLAG_inline_accessors && | 5817 if (FLAG_inline_accessors && |
5814 TryInlineSetter(setter, ast_id, return_id, value)) { | 5818 TryInlineSetter(setter, ast_id, return_id, value)) { |
5815 return; | 5819 return; |
5816 } | 5820 } |
5817 Drop(2); | 5821 Drop(2); |
5818 Add<HPushArgument>(object); | 5822 Add<HPushArgument>(object); |
5819 Add<HPushArgument>(value); | 5823 Add<HPushArgument>(value); |
5820 instr = New<HCallConstantFunction>(setter, 2); | 5824 instr = BuildCallConstantFunction(setter, 2); |
5821 } else { | 5825 } else { |
5822 Drop(2); | 5826 Drop(2); |
5823 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, | 5827 CHECK_ALIVE(instr = BuildStoreNamedMonomorphic(object, |
5824 name, | 5828 name, |
5825 value, | 5829 value, |
5826 map)); | 5830 map)); |
5827 } | 5831 } |
5828 } else if (types != NULL && types->length() > 1) { | 5832 } else if (types != NULL && types->length() > 1) { |
5829 Drop(2); | 5833 Drop(2); |
5830 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); | 5834 return HandlePolymorphicStoreNamedField(ast_id, object, value, types, name); |
(...skipping 941 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6772 HValue* receiver, | 6776 HValue* receiver, |
6773 Handle<Map> receiver_map) { | 6777 Handle<Map> receiver_map) { |
6774 // Constant functions have the nice property that the map will change if they | 6778 // Constant functions have the nice property that the map will change if they |
6775 // are overwritten. Therefore it is enough to check the map of the holder and | 6779 // are overwritten. Therefore it is enough to check the map of the holder and |
6776 // its prototypes. | 6780 // its prototypes. |
6777 AddCheckMap(receiver, receiver_map); | 6781 AddCheckMap(receiver, receiver_map); |
6778 AddCheckPrototypeMaps(holder, receiver_map); | 6782 AddCheckPrototypeMaps(holder, receiver_map); |
6779 } | 6783 } |
6780 | 6784 |
6781 | 6785 |
| 6786 HInstruction* HOptimizedGraphBuilder::NewPlainFunctionCall( |
| 6787 HValue* fun, int argument_count, bool pass_argument_count) { |
| 6788 return New<HCallJSFunction>( |
| 6789 fun, argument_count, pass_argument_count); |
| 6790 } |
| 6791 |
| 6792 |
| 6793 HInstruction* HOptimizedGraphBuilder::NewArgumentAdaptorCall( |
| 6794 HValue* fun, HValue* context, |
| 6795 int argument_count, HValue* expected_param_count) { |
| 6796 CallInterfaceDescriptor* descriptor = |
| 6797 isolate()->call_descriptor(Isolate::ArgumentAdaptorCall); |
| 6798 |
| 6799 HValue* arity = Add<HConstant>(argument_count - 1); |
| 6800 |
| 6801 HValue* op_vals[] = { fun, context, arity, expected_param_count }; |
| 6802 |
| 6803 Handle<Code> adaptor = |
| 6804 isolate()->builtins()->ArgumentsAdaptorTrampoline(); |
| 6805 HConstant* adaptor_value = Add<HConstant>(adaptor); |
| 6806 |
| 6807 return New<HCallWithDescriptor>( |
| 6808 adaptor_value, argument_count, descriptor, |
| 6809 Vector<HValue*>(op_vals, descriptor->environment_length())); |
| 6810 } |
| 6811 |
| 6812 |
| 6813 HInstruction* HOptimizedGraphBuilder::BuildCallConstantFunction( |
| 6814 Handle<JSFunction> jsfun, int argument_count) { |
| 6815 HValue* target = Add<HConstant>(jsfun); |
| 6816 // For constant functions, we try to avoid calling the |
| 6817 // argument adaptor and instead call the function directly |
| 6818 int formal_parameter_count = jsfun->shared()->formal_parameter_count(); |
| 6819 bool dont_adapt_arguments = |
| 6820 (formal_parameter_count == |
| 6821 SharedFunctionInfo::kDontAdaptArgumentsSentinel); |
| 6822 int arity = argument_count - 1; |
| 6823 bool can_invoke_directly = |
| 6824 dont_adapt_arguments || formal_parameter_count == arity; |
| 6825 if (can_invoke_directly) { |
| 6826 return NewPlainFunctionCall(target, argument_count, dont_adapt_arguments); |
| 6827 } else { |
| 6828 HValue* param_count_value = Add<HConstant>(formal_parameter_count); |
| 6829 HValue* context = Add<HLoadNamedField>(target, |
| 6830 HObjectAccess::ForFunctionContextPointer()); |
| 6831 return NewArgumentAdaptorCall(target, context, |
| 6832 argument_count, param_count_value); |
| 6833 } |
| 6834 UNREACHABLE(); |
| 6835 return NULL; |
| 6836 } |
| 6837 |
| 6838 |
| 6839 HInstruction* HOptimizedGraphBuilder::NewCallNamed( |
| 6840 Handle<String> name, int argument_count) { |
| 6841 CallInterfaceDescriptor* descriptor = |
| 6842 isolate()->call_descriptor(Isolate::NamedCall); |
| 6843 HValue* op_vals[] = { context(), Add<HConstant>(name) }; |
| 6844 int arity = argument_count - 1; |
| 6845 Handle<Code> ic = isolate()->stub_cache()->ComputeCallInitialize(arity); |
| 6846 |
| 6847 return New<HCallWithDescriptor>( |
| 6848 Add<HConstant>(ic), argument_count, descriptor, |
| 6849 Vector<HValue*>(op_vals, descriptor->environment_length())); |
| 6850 } |
| 6851 |
| 6852 |
| 6853 HInstruction* HOptimizedGraphBuilder::NewCallKeyed( |
| 6854 HValue* key, int argument_count) { |
| 6855 CallInterfaceDescriptor* descriptor = |
| 6856 isolate()->call_descriptor(Isolate::KeyedCall); |
| 6857 HValue* op_vals[] = { context(), key }; |
| 6858 int arity = argument_count - 1; |
| 6859 Handle<Code> ic = isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
| 6860 |
| 6861 return New<HCallWithDescriptor>( |
| 6862 Add<HConstant>(ic), argument_count, descriptor, |
| 6863 Vector<HValue*>(op_vals, descriptor->environment_length())); |
| 6864 } |
| 6865 |
6782 class FunctionSorter { | 6866 class FunctionSorter { |
6783 public: | 6867 public: |
6784 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } | 6868 FunctionSorter() : index_(0), ticks_(0), ast_length_(0), src_length_(0) { } |
6785 FunctionSorter(int index, int ticks, int ast_length, int src_length) | 6869 FunctionSorter(int index, int ticks, int ast_length, int src_length) |
6786 : index_(index), | 6870 : index_(index), |
6787 ticks_(ticks), | 6871 ticks_(ticks), |
6788 ast_length_(ast_length), | 6872 ast_length_(ast_length), |
6789 src_length_(src_length) { } | 6873 src_length_(src_length) { } |
6790 | 6874 |
6791 int index() const { return index_; } | 6875 int index() const { return index_; } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6827 if (FLAG_trace_inlining) { | 6911 if (FLAG_trace_inlining) { |
6828 Handle<JSFunction> caller = current_info()->closure(); | 6912 Handle<JSFunction> caller = current_info()->closure(); |
6829 SmartArrayPointer<char> caller_name = | 6913 SmartArrayPointer<char> caller_name = |
6830 caller->shared()->DebugName()->ToCString(); | 6914 caller->shared()->DebugName()->ToCString(); |
6831 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 6915 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
6832 name->ToCString().get(), caller_name.get()); | 6916 name->ToCString().get(), caller_name.get()); |
6833 } | 6917 } |
6834 | 6918 |
6835 if (!TryInlineCall(expr)) { | 6919 if (!TryInlineCall(expr)) { |
6836 int argument_count = expr->arguments()->length() + 1; // Includes receiver. | 6920 int argument_count = expr->arguments()->length() + 1; // Includes receiver. |
6837 HCallConstantFunction* call = | 6921 HInstruction* call = BuildCallConstantFunction( |
6838 New<HCallConstantFunction>(expr->target(), argument_count); | 6922 expr->target(), argument_count); |
6839 PreProcessCall(call); | 6923 PushArgumentsFromEnvironment(argument_count); |
6840 AddInstruction(call); | 6924 AddInstruction(call); |
6841 if (!ast_context()->IsEffect()) Push(call); | 6925 if (!ast_context()->IsEffect()) Push(call); |
6842 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); | 6926 Add<HSimulate>(expr->id(), REMOVABLE_SIMULATE); |
6843 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); | 6927 if (!ast_context()->IsEffect()) ast_context()->ReturnValue(Pop()); |
6844 } | 6928 } |
6845 | 6929 |
6846 return true; | 6930 return true; |
6847 } | 6931 } |
6848 | 6932 |
6849 | 6933 |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6989 caller->shared()->DebugName()->ToCString(); | 7073 caller->shared()->DebugName()->ToCString(); |
6990 PrintF("Trying to inline the polymorphic call to %s from %s\n", | 7074 PrintF("Trying to inline the polymorphic call to %s from %s\n", |
6991 name->ToCString().get(), | 7075 name->ToCString().get(), |
6992 caller_name.get()); | 7076 caller_name.get()); |
6993 } | 7077 } |
6994 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { | 7078 if (FLAG_polymorphic_inlining && TryInlineCall(expr)) { |
6995 // Trying to inline will signal that we should bailout from the | 7079 // Trying to inline will signal that we should bailout from the |
6996 // entire compilation by setting stack overflow on the visitor. | 7080 // entire compilation by setting stack overflow on the visitor. |
6997 if (HasStackOverflow()) return; | 7081 if (HasStackOverflow()) return; |
6998 } else { | 7082 } else { |
6999 HCallConstantFunction* call = | 7083 HInstruction* call = BuildCallConstantFunction( |
7000 New<HCallConstantFunction>(expr->target(), argument_count); | 7084 expr->target(), argument_count); |
7001 PreProcessCall(call); | 7085 PushArgumentsFromEnvironment(argument_count); |
7002 AddInstruction(call); | 7086 AddInstruction(call); |
7003 if (!ast_context()->IsEffect()) Push(call); | 7087 if (!ast_context()->IsEffect()) Push(call); |
7004 } | 7088 } |
7005 if (current_block() != NULL) Goto(join); | 7089 if (current_block() != NULL) Goto(join); |
7006 | 7090 |
7007 set_current_block(if_false); | 7091 set_current_block(if_false); |
7008 } | 7092 } |
7009 | 7093 |
7010 // Finish up. Unconditionally deoptimize if we've handled all the maps we | 7094 // Finish up. Unconditionally deoptimize if we've handled all the maps we |
7011 // know about and do not want to handle ones we've never seen. Otherwise | 7095 // know about and do not want to handle ones we've never seen. Otherwise |
7012 // use a generic IC. | 7096 // use a generic IC. |
7013 if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) { | 7097 if (maps_count == types->length() && FLAG_deoptimize_uncommon_cases) { |
7014 // Because the deopt may be the only path in the polymorphic call, make sure | 7098 // Because the deopt may be the only path in the polymorphic call, make sure |
7015 // that the environment stack matches the depth on deopt that it otherwise | 7099 // that the environment stack matches the depth on deopt that it otherwise |
7016 // would have had after a successful call. | 7100 // would have had after a successful call. |
7017 Drop(argument_count); | 7101 Drop(argument_count); |
7018 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); | 7102 if (!ast_context()->IsEffect()) Push(graph()->GetConstant0()); |
7019 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); | 7103 FinishExitWithHardDeoptimization("Unknown map in polymorphic call", join); |
7020 } else { | 7104 } else { |
7021 HCallNamed* call = New<HCallNamed>(name, argument_count); | 7105 HInstruction* call = NewCallNamed(name, argument_count); |
7022 PreProcessCall(call); | 7106 PushArgumentsFromEnvironment(argument_count); |
7023 | 7107 |
7024 if (join != NULL) { | 7108 if (join != NULL) { |
7025 AddInstruction(call); | 7109 AddInstruction(call); |
7026 if (!ast_context()->IsEffect()) Push(call); | 7110 if (!ast_context()->IsEffect()) Push(call); |
7027 Goto(join); | 7111 Goto(join); |
7028 } else { | 7112 } else { |
7029 return ast_context()->ReturnInstruction(call, expr->id()); | 7113 return ast_context()->ReturnInstruction(call, expr->id()); |
7030 } | 7114 } |
7031 } | 7115 } |
7032 | 7116 |
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7736 ElementsKind kind = expr->KeyedArrayCallIsHoley() | 7820 ElementsKind kind = expr->KeyedArrayCallIsHoley() |
7737 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; | 7821 ? FAST_HOLEY_ELEMENTS : FAST_ELEMENTS; |
7738 | 7822 |
7739 Handle<Map> map(isolate()->get_initial_js_array_map(kind)); | 7823 Handle<Map> map(isolate()->get_initial_js_array_map(kind)); |
7740 | 7824 |
7741 HValue* function = BuildMonomorphicElementAccess( | 7825 HValue* function = BuildMonomorphicElementAccess( |
7742 receiver, key, NULL, NULL, map, false, STANDARD_STORE); | 7826 receiver, key, NULL, NULL, map, false, STANDARD_STORE); |
7743 | 7827 |
7744 call = New<HCallFunction>(function, argument_count); | 7828 call = New<HCallFunction>(function, argument_count); |
7745 } else { | 7829 } else { |
7746 call = New<HCallKeyed>(key, argument_count); | 7830 call = NewCallKeyed(key, argument_count); |
7747 } | 7831 } |
7748 Drop(argument_count + 1); // 1 is the key. | 7832 Drop(argument_count + 1); // 1 is the key. |
7749 return ast_context()->ReturnInstruction(call, expr->id()); | 7833 return ast_context()->ReturnInstruction(call, expr->id()); |
7750 } | 7834 } |
7751 | 7835 |
7752 // Named function call. | 7836 // Named function call. |
7753 if (TryCallApply(expr)) return; | 7837 if (TryCallApply(expr)) return; |
7754 | 7838 |
7755 CHECK_ALIVE(VisitForValue(prop->obj())); | 7839 CHECK_ALIVE(VisitForValue(prop->obj())); |
7756 CHECK_ALIVE(VisitExpressions(expr->arguments())); | 7840 CHECK_ALIVE(VisitExpressions(expr->arguments())); |
(...skipping 18 matching lines...) Expand all Loading... |
7775 PrintF("\n"); | 7859 PrintF("\n"); |
7776 } | 7860 } |
7777 return; | 7861 return; |
7778 } | 7862 } |
7779 | 7863 |
7780 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || | 7864 if (CallStubCompiler::HasCustomCallGenerator(expr->target()) || |
7781 expr->check_type() != RECEIVER_MAP_CHECK) { | 7865 expr->check_type() != RECEIVER_MAP_CHECK) { |
7782 // When the target has a custom call IC generator, use the IC, | 7866 // When the target has a custom call IC generator, use the IC, |
7783 // because it is likely to generate better code. Also use the IC | 7867 // because it is likely to generate better code. Also use the IC |
7784 // when a primitive receiver check is required. | 7868 // when a primitive receiver check is required. |
7785 call = PreProcessCall(New<HCallNamed>(name, argument_count)); | 7869 call = NewCallNamed(name, argument_count); |
| 7870 PushArgumentsFromEnvironment(argument_count); |
7786 } else { | 7871 } else { |
7787 AddCheckConstantFunction(expr->holder(), receiver, map); | 7872 AddCheckConstantFunction(expr->holder(), receiver, map); |
7788 | 7873 |
7789 if (TryInlineCall(expr)) return; | 7874 if (TryInlineCall(expr)) return; |
7790 call = PreProcessCall( | 7875 call = BuildCallConstantFunction(expr->target(), argument_count); |
7791 New<HCallConstantFunction>(expr->target(), argument_count)); | 7876 PushArgumentsFromEnvironment(argument_count); |
7792 } | 7877 } |
7793 } else if (types != NULL && types->length() > 1) { | 7878 } else if (types != NULL && types->length() > 1) { |
7794 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); | 7879 ASSERT(expr->check_type() == RECEIVER_MAP_CHECK); |
7795 HandlePolymorphicCallNamed(expr, receiver, types, name); | 7880 HandlePolymorphicCallNamed(expr, receiver, types, name); |
7796 return; | 7881 return; |
7797 | 7882 |
7798 } else { | 7883 } else { |
7799 call = PreProcessCall(New<HCallNamed>(name, argument_count)); | 7884 call = NewCallNamed(name, argument_count); |
| 7885 PushArgumentsFromEnvironment(argument_count); |
7800 } | 7886 } |
7801 } else { | 7887 } else { |
7802 VariableProxy* proxy = expr->expression()->AsVariableProxy(); | 7888 VariableProxy* proxy = expr->expression()->AsVariableProxy(); |
7803 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { | 7889 if (proxy != NULL && proxy->var()->is_possibly_eval(isolate())) { |
7804 return Bailout(kPossibleDirectCallToEval); | 7890 return Bailout(kPossibleDirectCallToEval); |
7805 } | 7891 } |
7806 | 7892 |
7807 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); | 7893 bool global_call = proxy != NULL && proxy->var()->IsUnallocated(); |
7808 if (global_call) { | 7894 if (global_call) { |
7809 Variable* var = proxy->var(); | 7895 Variable* var = proxy->var(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7850 } | 7936 } |
7851 | 7937 |
7852 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { | 7938 if (CallStubCompiler::HasCustomCallGenerator(expr->target())) { |
7853 // We're about to install a contextual IC, which expects the global | 7939 // We're about to install a contextual IC, which expects the global |
7854 // object as receiver rather than the global proxy. | 7940 // object as receiver rather than the global proxy. |
7855 HGlobalObject* global_object = Add<HGlobalObject>(); | 7941 HGlobalObject* global_object = Add<HGlobalObject>(); |
7856 const int receiver_index = argument_count - 1; | 7942 const int receiver_index = argument_count - 1; |
7857 environment()->SetExpressionStackAt(receiver_index, global_object); | 7943 environment()->SetExpressionStackAt(receiver_index, global_object); |
7858 // When the target has a custom call IC generator, use the IC, | 7944 // When the target has a custom call IC generator, use the IC, |
7859 // because it is likely to generate better code. | 7945 // because it is likely to generate better code. |
7860 call = PreProcessCall(New<HCallNamed>(var->name(), argument_count)); | 7946 call = NewCallNamed(var->name(), argument_count); |
| 7947 PushArgumentsFromEnvironment(argument_count); |
7861 } else { | 7948 } else { |
7862 call = PreProcessCall(New<HCallKnownGlobal>( | 7949 call = BuildCallConstantFunction(expr->target(), argument_count); |
7863 expr->target(), argument_count)); | 7950 PushArgumentsFromEnvironment(argument_count); |
7864 } | 7951 } |
7865 } else { | 7952 } else { |
7866 HGlobalObject* receiver = Add<HGlobalObject>(); | 7953 HGlobalObject* receiver = Add<HGlobalObject>(); |
7867 Push(Add<HPushArgument>(receiver)); | 7954 Push(Add<HPushArgument>(receiver)); |
7868 CHECK_ALIVE(VisitArgumentList(expr->arguments())); | 7955 CHECK_ALIVE(VisitArgumentList(expr->arguments())); |
7869 | 7956 |
7870 call = New<HCallNamed>(var->name(), argument_count); | 7957 call = NewCallNamed(var->name(), argument_count); |
7871 Drop(argument_count); | 7958 Drop(argument_count); |
7872 } | 7959 } |
7873 | 7960 |
7874 } else if (expr->IsMonomorphic()) { | 7961 } else if (expr->IsMonomorphic()) { |
7875 // The function is on the stack in the unoptimized code during | 7962 // The function is on the stack in the unoptimized code during |
7876 // evaluation of the arguments. | 7963 // evaluation of the arguments. |
7877 CHECK_ALIVE(VisitForValue(expr->expression())); | 7964 CHECK_ALIVE(VisitForValue(expr->expression())); |
7878 HValue* function = Top(); | 7965 HValue* function = Top(); |
7879 | 7966 |
7880 Add<HCheckValue>(function, expr->target()); | 7967 Add<HCheckValue>(function, expr->target()); |
(...skipping 3106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10987 if (ShouldProduceTraceOutput()) { | 11074 if (ShouldProduceTraceOutput()) { |
10988 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); | 11075 isolate()->GetHTracer()->TraceHydrogen(name(), graph_); |
10989 } | 11076 } |
10990 | 11077 |
10991 #ifdef DEBUG | 11078 #ifdef DEBUG |
10992 graph_->Verify(false); // No full verify. | 11079 graph_->Verify(false); // No full verify. |
10993 #endif | 11080 #endif |
10994 } | 11081 } |
10995 | 11082 |
10996 } } // namespace v8::internal | 11083 } } // namespace v8::internal |
OLD | NEW |